NS_IMETHODIMP
nsMsgContentPolicy::ShouldLoad(PRUint32          aContentType,
                               nsIURI           *aContentLocation,
                               nsIURI           *aRequestingLocation,
                               nsISupports      *aRequestingContext,
                               const nsACString &aMimeGuess,
                               nsISupports      *aExtra,
                               PRInt16          *aDecision)
{
    nsresult rv = NS_OK;
    *aDecision = nsIContentPolicy::ACCEPT;

    NS_ENSURE_ARG_POINTER(aContentLocation);

    // NOTE: Not using NS_ENSURE_ARG_POINTER because this is a legitimate case
    // that can happen.
    if (!aRequestingLocation)
        return NS_ERROR_INVALID_POINTER;

#ifndef MOZ_THUNDERBIRD
    // Go find out if we are dealing with mailnews. Anything else
    // isn't our concern and we accept content.
    nsCOMPtr<nsIDocShell> docshell;
    rv = GetRootDocShellForContext(aRequestingContext, getter_AddRefs(docshell));
    NS_ENSURE_SUCCESS(rv, rv);

    PRUint32 appType;
    rv = docshell->GetAppType(&appType);
    // We only want to deal with mailnews
    if (NS_FAILED(rv) || appType != nsIDocShell::APP_TYPE_MAIL)
        return NS_OK;
#endif

    if (aContentType == nsIContentPolicy::TYPE_OBJECT)
    {
        // only allow the plugin to load if the allow plugins pref has been set
        if (!mAllowPlugins)
            *aDecision = nsIContentPolicy::REJECT_TYPE;
        return NS_OK;
    }

    // if aRequestingLocation is chrome, resource or about,  allow
    // aContentLocation to load
    PRBool isChrome;
    PRBool isRes;
    PRBool isAbout;

    rv = aRequestingLocation->SchemeIs("chrome", &isChrome);
    rv |= aRequestingLocation->SchemeIs("resource", &isRes);
    rv |= aRequestingLocation->SchemeIs("about", &isAbout);

    if (NS_SUCCEEDED(rv) && (isChrome || isRes || isAbout))
        return rv;

    // Now default to reject so early returns via NS_ENSURE_SUCCESS
    // cause content to be rejected.
    *aDecision = nsIContentPolicy::REJECT_REQUEST;
    // From here on out, be very careful about returning error codes.
    // An error code will cause the content policy manager to ignore our
    // decision. In most cases, if we get an error code, it's something
    // we didn't expect which means we should be rejecting the request anyway...

    // if aContentLocation is a protocol we handle (imap, pop3, mailbox, etc)
    // or is a chrome url, then allow the load
    nsCAutoString contentScheme;
    PRBool isExposedProtocol = PR_FALSE;
    rv = aContentLocation->GetScheme(contentScheme);
    NS_ENSURE_SUCCESS(rv, NS_OK);

#ifdef MOZ_THUNDERBIRD
    nsCOMPtr<nsIExternalProtocolService> extProtService = do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID);
    rv = extProtService->IsExposedProtocol(contentScheme.get(), &isExposedProtocol);
    NS_ENSURE_SUCCESS(rv, NS_OK);
#else
    if (contentScheme.LowerCaseEqualsLiteral("mailto") ||
            contentScheme.LowerCaseEqualsLiteral("news") ||
            contentScheme.LowerCaseEqualsLiteral("snews") ||
            contentScheme.LowerCaseEqualsLiteral("nntp") ||
            contentScheme.LowerCaseEqualsLiteral("imap") ||
            contentScheme.LowerCaseEqualsLiteral("addbook") ||
            contentScheme.LowerCaseEqualsLiteral("pop") ||
            contentScheme.LowerCaseEqualsLiteral("mailbox") ||
            contentScheme.LowerCaseEqualsLiteral("about"))
        isExposedProtocol = PR_TRUE;
#endif

    rv = aContentLocation->SchemeIs("chrome", &isChrome);
    rv |= aContentLocation->SchemeIs("resource", &isRes);

    if (isExposedProtocol || (NS_SUCCEEDED(rv) && (isChrome || isRes)))
    {
        *aDecision = nsIContentPolicy::ACCEPT;
        return NS_OK;
    }

    // never load unexposed protocols except for http, https and file.
    // Protocols like ftp, gopher are always blocked.
    PRBool isHttp;
    PRBool isHttps;
    PRBool isFile;
    rv = aContentLocation->SchemeIs("http", &isHttp);
    rv |= aContentLocation->SchemeIs("https", &isHttps);
    rv |= aContentLocation->SchemeIs("file", &isFile);
    if (NS_FAILED(rv) || (!isHttp && !isHttps && !isFile))
        return NS_OK;

    // If we are allowing all remote content...
    if (!mBlockRemoteImages)
    {
        *aDecision = nsIContentPolicy::ACCEPT;
        return NS_OK;
    }

    // Extract the windowtype to handle compose windows separately from mail
    nsCOMPtr<nsIDocShell> rootDocShell;
    rv = GetRootDocShellForContext(aRequestingContext, getter_AddRefs(rootDocShell));
    NS_ENSURE_SUCCESS(rv, NS_OK);

    // get the dom document element
    nsCOMPtr<nsIDOMDocument> domDocument = do_GetInterface(rootDocShell, &rv);
    NS_ENSURE_SUCCESS(rv, NS_OK);

    nsCOMPtr<nsIDOMElement> windowEl;
    rv = domDocument->GetDocumentElement(getter_AddRefs(windowEl));
    NS_ENSURE_SUCCESS(rv, NS_OK);

    nsAutoString windowType;
    // GetDocumentElement may succeed but return nsnull, if it does, we'll
    // treat the window as a non-msgcompose window.
    if (windowEl)
    {
        rv = windowEl->GetAttribute(NS_LITERAL_STRING("windowtype"), windowType);
        NS_ENSURE_SUCCESS(rv, NS_OK);
    }

    if (windowType.Equals(NS_LITERAL_STRING("msgcompose")))
        ComposeShouldLoad(rootDocShell, aRequestingContext, aContentLocation, aDecision);
    else
    {
        // the remote image could be nested in any number of iframes. For those cases, we don't really
        // care about the value of aRequestingLocation. We care about the parent message pane nsIURI so
        // use that if we can find it. For the non nesting case, mailRequestingLocation and aRequestingLocation
        // should end up being the same object.
        nsCOMPtr<nsIURI> mailRequestingLocation;
        GetMessagePaneURI(rootDocShell, getter_AddRefs(mailRequestingLocation));

        MailShouldLoad(mailRequestingLocation ? mailRequestingLocation.get() : aRequestingLocation,
                       aContentLocation, aDecision);
    }

    return NS_OK;
}
Beispiel #2
0
NS_IMETHODIMP
nsMsgContentPolicy::ShouldLoad(PRUint32          aContentType,
                               nsIURI           *aContentLocation,
                               nsIURI           *aRequestingLocation,
                               nsISupports      *aRequestingContext,
                               const nsACString &aMimeGuess,
                               nsISupports      *aExtra,
                               nsIPrincipal     *aRequestPrincipal,
                               PRInt16          *aDecision)
{
  nsresult rv = NS_OK;
  // The default decision at the start of the function is to accept the load.
  // Once we have checked the content type and the requesting location, then
  // we switch it to reject.
  //
  // Be very careful about returning error codes - if this method returns an
  // NS_ERROR_*, any decision made here will be ignored, and the document could
  // be accepted when we don't want it to be.
  //
  // In most cases if an error occurs, its something we didn't expect so we
  // should be rejecting the document anyway.
  *aDecision = nsIContentPolicy::ACCEPT;

  NS_ENSURE_ARG_POINTER(aContentLocation);

#ifdef DEBUG_MsgContentPolicy
  nsCString spec;
  (void)aContentLocation->GetSpec(spec);
  fprintf(stderr, "aContentType: %d\naContentLocation = %s\n",
          aContentType,
          spec.get());
#endif

#ifndef MOZ_THUNDERBIRD
  // Go find out if we are dealing with mailnews. Anything else
  // isn't our concern and we accept content.
  nsCOMPtr<nsIDocShell> rootDocShell;
  rv = GetRootDocShellForContext(aRequestingContext,
                                 getter_AddRefs(rootDocShell));
  NS_ENSURE_SUCCESS(rv, rv);

  PRUint32 appType;
  rv = rootDocShell->GetAppType(&appType);
  // We only want to deal with mailnews
  if (NS_FAILED(rv) || appType != nsIDocShell::APP_TYPE_MAIL)
    return NS_OK;
#endif

  switch(aContentType) {
    // Plugins (nsIContentPolicy::TYPE_OBJECT) are blocked on document load.
  case nsIContentPolicy::TYPE_DOCUMENT:
    // At this point, we have no intention of supporting a different JS
    // setting on a subdocument, so we don't worry about TYPE_SUBDOCUMENT here.
   
    // If the timing were right, we'd enable JavaScript on the docshell
    // for non mailnews URIs here.  However, at this point, the
    // old document may still be around, so we can't do any enabling just yet.  
    // Instead, we apply the policy in nsIWebProgressListener::OnLocationChange. 
    // For now, we explicitly disable JavaScript in order to be safe rather than
    // sorry, because OnLocationChange isn't guaranteed to necessarily be called
    // soon enough to disable it in time (though bz says it _should_ be called 
    // soon enough "in all sane cases").
    rv = SetDisableItemsOnMailNewsUrlDocshells(aContentLocation,
                                               aRequestingContext);
    // if something went wrong during the tweaking, reject this content
    if (NS_FAILED(rv)) {
      NS_WARNING("Failed to set disable items on docShells");
      *aDecision = nsIContentPolicy::REJECT_TYPE;
      return NS_OK;
    }
    break;

  default:
    break;
  }
  
  // NOTE: Not using NS_ENSURE_ARG_POINTER because this is a legitimate case
  // that can happen.  Also keep in mind that the default policy used for a
  // failure code is ACCEPT.
  if (!aRequestingLocation)
    return NS_ERROR_INVALID_POINTER;

#ifdef DEBUG_MsgContentPolicy
  (void)aRequestingLocation->GetSpec(spec);
  fprintf(stderr, "aRequestingLocation = %s\n", spec.get());
#endif

  // If the requesting location is safe, accept the content location request.
  if (IsSafeRequestingLocation(aRequestingLocation))
    return rv;

  // Now default to reject so early returns via NS_ENSURE_SUCCESS 
  // cause content to be rejected.
  *aDecision = nsIContentPolicy::REJECT_REQUEST;

  // if aContentLocation is a protocol we handle (imap, pop3, mailbox, etc)
  // or is a chrome url, then allow the load

  if (IsExposedProtocol(aContentLocation))
  {
    *aDecision = nsIContentPolicy::ACCEPT;
    return NS_OK;
  }

  // never load unexposed protocols except for http, https and file. 
  // Protocols like ftp are always blocked.
  if (ShouldBlockUnexposedProtocol(aContentLocation))
    return NS_OK;

  // If we are allowing all remote content...
  if (!mBlockRemoteImages)
  {
    *aDecision = nsIContentPolicy::ACCEPT;
    return NS_OK;
  }

  // Extract the windowtype to handle compose windows separately from mail
  nsCOMPtr<nsIMsgCompose> msgCompose = GetMsgComposeForContext(aRequestingContext);
  // Work out if we're in a compose window or not.
  if (msgCompose)
  {
    ComposeShouldLoad(msgCompose, aRequestingContext, aContentLocation,
                      aDecision);
    return NS_OK;
  }

  // Find out the URI that originally initiated the set of requests for this
  // context.
  nsCOMPtr<nsIURI> originatorLocation;
  rv = GetOriginatingURIForContext(aRequestingContext,
                                   getter_AddRefs(originatorLocation));
  NS_ENSURE_SUCCESS(rv, NS_OK);

#ifdef DEBUG_MsgContentPolicy
  (void)originatorLocation->GetSpec(spec);
  fprintf(stderr, "originatorLocation = %s\n", spec.get());
#endif

  // Allow content when using a remote page.
  bool isHttp;
  bool isHttps;
  rv = originatorLocation->SchemeIs("http", &isHttp);
  rv |= originatorLocation->SchemeIs("https", &isHttps);
  if (NS_SUCCEEDED(rv) && (isHttp || isHttps))
  {
    *aDecision = nsIContentPolicy::ACCEPT;
    return NS_OK;
  }

  // The default decision is still to reject.
  ShouldAcceptContentForPotentialMsg(originatorLocation, aContentLocation,
                                     aDecision);
  return NS_OK;
}