nsresult nsChannelClassifier::Start(nsIChannel *aChannel) { // Don't bother to run the classifier on a load that has already failed. // (this might happen after a redirect) PRUint32 status; aChannel->GetStatus(&status); if (NS_FAILED(status)) return NS_OK; // Don't bother to run the classifier on a cached load that was // previously classified. if (HasBeenClassified(aChannel)) { return NS_OK; } nsCOMPtr<nsIURI> uri; nsresult rv = aChannel->GetURI(getter_AddRefs(uri)); NS_ENSURE_SUCCESS(rv, rv); // Don't bother checking certain types of URIs. bool hasFlags; rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_DANGEROUS_TO_LOAD, &hasFlags); NS_ENSURE_SUCCESS(rv, rv); if (hasFlags) return NS_OK; rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_LOCAL_FILE, &hasFlags); NS_ENSURE_SUCCESS(rv, rv); if (hasFlags) return NS_OK; rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &hasFlags); NS_ENSURE_SUCCESS(rv, rv); if (hasFlags) return NS_OK; rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_LOCAL_RESOURCE, &hasFlags); NS_ENSURE_SUCCESS(rv, rv); if (hasFlags) return NS_OK; nsCOMPtr<nsIURIClassifier> uriClassifier = do_GetService(NS_URICLASSIFIERSERVICE_CONTRACTID, &rv); if (rv == NS_ERROR_FACTORY_NOT_REGISTERED || rv == NS_ERROR_NOT_AVAILABLE) { // no URI classifier, ignore this failure. return NS_OK; } NS_ENSURE_SUCCESS(rv, rv); bool expectCallback; rv = uriClassifier->Classify(uri, this, &expectCallback); if (NS_FAILED(rv)) return rv; if (expectCallback) { // Suspend the channel, it will be resumed when we get the classifier // callback. rv = aChannel->Suspend(); if (NS_FAILED(rv)) { // Some channels (including nsJSChannel) fail on Suspend. This // shouldn't be fatal, but will prevent malware from being // blocked on these channels. return NS_OK; } mSuspendedChannel = aChannel; #ifdef DEBUG LOG(("nsChannelClassifier[%p]: suspended channel %p", this, mSuspendedChannel.get())); #endif } return NS_OK; }
nsresult nsChannelClassifier::StartInternal() { // Should only be called in the parent process. MOZ_ASSERT(XRE_IsParentProcess()); // Don't bother to run the classifier on a load that has already failed. // (this might happen after a redirect) nsresult status; mChannel->GetStatus(&status); if (NS_FAILED(status)) return status; // Don't bother to run the classifier on a cached load that was // previously classified as good. if (HasBeenClassified(mChannel)) { return NS_ERROR_UNEXPECTED; } nsCOMPtr<nsIURI> uri; nsresult rv = mChannel->GetURI(getter_AddRefs(uri)); NS_ENSURE_SUCCESS(rv, rv); // Don't bother checking certain types of URIs. bool hasFlags; rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_DANGEROUS_TO_LOAD, &hasFlags); NS_ENSURE_SUCCESS(rv, rv); if (hasFlags) return NS_ERROR_UNEXPECTED; rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_LOCAL_FILE, &hasFlags); NS_ENSURE_SUCCESS(rv, rv); if (hasFlags) return NS_ERROR_UNEXPECTED; rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &hasFlags); NS_ENSURE_SUCCESS(rv, rv); if (hasFlags) return NS_ERROR_UNEXPECTED; rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_LOCAL_RESOURCE, &hasFlags); NS_ENSURE_SUCCESS(rv, rv); if (hasFlags) return NS_ERROR_UNEXPECTED; // Skip whitelisted hostnames. nsAutoCString whitelisted; Preferences::GetCString("urlclassifier.skipHostnames", &whitelisted); if (!whitelisted.IsEmpty()) { ToLowerCase(whitelisted); LOG(("nsChannelClassifier[%p]:StartInternal whitelisted hostnames = %s", this, whitelisted.get())); if (IsHostnameWhitelisted(uri, whitelisted)) { return NS_ERROR_UNEXPECTED; } } nsCOMPtr<nsIURIClassifier> uriClassifier = do_GetService(NS_URICLASSIFIERSERVICE_CONTRACTID, &rv); if (rv == NS_ERROR_FACTORY_NOT_REGISTERED || rv == NS_ERROR_NOT_AVAILABLE) { // no URI classifier, ignore this failure. return NS_ERROR_NOT_AVAILABLE; } NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIScriptSecurityManager> securityManager = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIPrincipal> principal; rv = securityManager->GetChannelURIPrincipal(mChannel, getter_AddRefs(principal)); NS_ENSURE_SUCCESS(rv, rv); bool expectCallback; bool trackingProtectionEnabled = false; (void)ShouldEnableTrackingProtection(mChannel, &trackingProtectionEnabled); if (LOG_ENABLED()) { nsCOMPtr<nsIURI> principalURI; principal->GetURI(getter_AddRefs(principalURI)); LOG(("nsChannelClassifier[%p]: Classifying principal %s on channel with " "uri %s", this, principalURI->GetSpecOrDefault().get(), uri->GetSpecOrDefault().get())); } rv = uriClassifier->Classify(principal, trackingProtectionEnabled, this, &expectCallback); if (NS_FAILED(rv)) { return rv; } if (expectCallback) { // Suspend the channel, it will be resumed when we get the classifier // callback. rv = mChannel->Suspend(); if (NS_FAILED(rv)) { // Some channels (including nsJSChannel) fail on Suspend. This // shouldn't be fatal, but will prevent malware from being // blocked on these channels. LOG(("nsChannelClassifier[%p]: Couldn't suspend channel", this)); return rv; } mSuspendedChannel = true; LOG(("nsChannelClassifier[%p]: suspended channel %p", this, mChannel.get())); } else { LOG(("nsChannelClassifier[%p]: not expecting callback", this)); return NS_ERROR_FAILURE; } return NS_OK; }