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; }
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; }