# User Michal Novotny <michal.novotny@gmail.com>

# Date 1272456176 -7200
Bug 549241 - Channel classifier should run in chrome process. r=biesi, sr=jst
This commit is contained in:
Jason Duell 2010-05-21 14:03:02 -07:00
Родитель d1441baf4a
Коммит 86c0119176
22 изменённых файлов: 368 добавлений и 557 удалений

Просмотреть файл

@ -500,9 +500,6 @@ nsObjectLoadingContent::OnStartRequest(nsIRequest *aRequest,
return NS_BINDING_ABORTED;
}
// We're done with the classifier
mClassifier = nsnull;
AutoNotifier notifier(this, PR_TRUE);
if (!IsSuccessfulRequest(aRequest)) {
@ -1033,10 +1030,6 @@ nsObjectLoadingContent::OnChannelRedirect(nsIChannel *aOldChannel,
return NS_BINDING_ABORTED;
}
if (mClassifier) {
mClassifier->OnRedirect(aOldChannel, aNewChannel);
}
mChannel = aNewChannel;
return NS_OK;
}
@ -1204,11 +1197,6 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
if (mChannel) {
LOG(("OBJLC [%p]: Cancelling existing load\n", this));
if (mClassifier) {
mClassifier->Cancel();
mClassifier = nsnull;
}
// These three statements are carefully ordered:
// - onStopRequest should get a channel whose status is the same as the
// status argument
@ -1436,7 +1424,8 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
channelPolicy->SetLoadType(nsIContentPolicy::TYPE_OBJECT);
}
rv = NS_NewChannel(getter_AddRefs(chan), aURI, nsnull, group, this,
nsIChannel::LOAD_CALL_CONTENT_SNIFFERS,
nsIChannel::LOAD_CALL_CONTENT_SNIFFERS |
nsIChannel::LOAD_CLASSIFY_URI,
channelPolicy);
NS_ENSURE_SUCCESS(rv, rv);
@ -1477,12 +1466,6 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
if (NS_SUCCEEDED(rv)) {
LOG(("OBJLC [%p]: Channel opened.\n", this));
rv = CheckClassifier(chan);
if (NS_FAILED(rv)) {
chan->Cancel(rv);
return rv;
}
mChannel = chan;
mType = eType_Loading;
}
@ -1924,22 +1907,6 @@ nsObjectLoadingContent::Instantiate(nsIObjectFrame* aFrame,
return rv;
}
nsresult
nsObjectLoadingContent::CheckClassifier(nsIChannel *aChannel)
{
nsresult rv;
nsCOMPtr<nsIChannelClassifier> classifier =
do_CreateInstance(NS_CHANNELCLASSIFIER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = classifier->Start(aChannel, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
mClassifier = classifier;
return NS_OK;
}
/* static */ PluginSupportState
nsObjectLoadingContent::GetPluginSupportState(nsIContent* aContent,
const nsCString& aContentType)

Просмотреть файл

@ -52,7 +52,6 @@
#include "nsIChannelEventSink.h"
#include "nsIObjectLoadingContent.h"
#include "nsIRunnable.h"
#include "nsIChannelClassifier.h"
#include "nsIFrame.h"
class nsAsyncInstantiateEvent;
@ -328,13 +327,6 @@ class nsObjectLoadingContent : public nsImageLoadingContent
*/
nsresult Instantiate(nsIObjectFrame* aFrame, const nsACString& aMIMEType, nsIURI* aURI);
/**
* Check the channel load against the URI classifier service (if it
* exists). The channel will be suspended until the classification is
* complete.
*/
nsresult CheckClassifier(nsIChannel *aChannel);
/**
* Get the plugin support state for the given content node and MIME type.
* This is used for purposes of determining whether to fire PluginNotFound
@ -394,11 +386,6 @@ class nsObjectLoadingContent : public nsImageLoadingContent
// The data we were last asked to load
nsCOMPtr<nsIURI> mURI;
/**
* Suspends/resumes channels based on the URI classifier.
*/
nsCOMPtr<nsIChannelClassifier> mClassifier;
/**
* Type of the currently-loaded content.
*/

Просмотреть файл

@ -69,7 +69,6 @@
#include "nsContentErrors.h"
#include "nsIParser.h"
#include "nsThreadUtils.h"
#include "nsIChannelClassifier.h"
#include "nsDocShellCID.h"
#include "nsIContentSecurityPolicy.h"
#include "prlog.h"
@ -305,8 +304,8 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType)
nsCOMPtr<nsIChannel> channel;
rv = NS_NewChannel(getter_AddRefs(channel),
aRequest->mURI, nsnull, loadGroup,
prompter, nsIRequest::LOAD_NORMAL,
aRequest->mURI, nsnull, loadGroup, prompter,
nsIRequest::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI,
channelPolicy);
NS_ENSURE_SUCCESS(rv, rv);
@ -325,17 +324,6 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType)
rv = channel->AsyncOpen(loader, aRequest);
NS_ENSURE_SUCCESS(rv, rv);
// Check the load against the URI classifier
nsCOMPtr<nsIChannelClassifier> classifier =
do_CreateInstance(NS_CHANNELCLASSIFIER_CONTRACTID);
if (classifier) {
rv = classifier->Start(channel, PR_TRUE);
if (NS_FAILED(rv)) {
channel->Cancel(rv);
return rv;
}
}
return NS_OK;
}

Просмотреть файл

@ -74,8 +74,6 @@ XPIDLSRCS = \
nsIURIFixup.idl \
nsIEditorDocShell.idl \
nsIWebPageDescriptor.idl \
nsIURIClassifier.idl \
nsIChannelClassifier.idl \
nsIDownloadHistory.idl \
nsILoadContext.idl \
$(NULL)

Просмотреть файл

@ -108,7 +108,6 @@
#include "nsIView.h"
#include "nsIViewManager.h"
#include "nsIScriptChannel.h"
#include "nsIURIClassifier.h"
#include "nsIOfflineCacheUpdate.h"
#include "nsCPrefetchService.h"
#include "nsJSON.h"
@ -4043,11 +4042,6 @@ nsDocShell::Stop(PRUint32 aStopFlags)
mRefreshURIList = nsnull;
}
if (mClassifier) {
mClassifier->Cancel();
mClassifier = nsnull;
}
// XXXbz We could also pass |this| to nsIURILoader::Stop. That will
// just call Stop() on us as an nsIDocumentLoader... We need fewer
// redundant apis!
@ -5667,12 +5661,6 @@ nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
if (!(aStateFlags & STATE_IS_DOCUMENT))
return; // not a toplevel document
// If this load is being checked by the URI classifier, we need to
// query the classifier again for the new URI.
if (mClassifier) {
mClassifier->OnRedirect(aOldChannel, aNewChannel);
}
nsCOMPtr<nsIGlobalHistory3> history3(do_QueryInterface(mGlobalHistory));
nsresult result = NS_ERROR_NOT_IMPLEMENTED;
if (history3) {
@ -5756,9 +5744,6 @@ nsDocShell::EndPageLoad(nsIWebProgress * aProgress,
//
nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
// We're done with the URI classifier for this channel
mClassifier = nsnull;
// Notify the ContentViewer that the Document has finished loading. This
// will cause any OnLoad(...) and PopState(...) handlers to fire.
if (!mEODForCurrentDocument && mContentViewer) {
@ -8681,6 +8666,10 @@ nsresult nsDocShell::DoChannelLoad(nsIChannel * aChannel,
break;
}
if (!aBypassClassifier) {
loadFlags |= nsIChannel::LOAD_CLASSIFY_URI;
}
(void) aChannel->SetLoadFlags(loadFlags);
rv = aURILoader->OpenURI(aChannel,
@ -8688,28 +8677,6 @@ nsresult nsDocShell::DoChannelLoad(nsIChannel * aChannel,
this);
NS_ENSURE_SUCCESS(rv, rv);
if (!aBypassClassifier) {
rv = CheckClassifier(aChannel);
if (NS_FAILED(rv)) {
aChannel->Cancel(rv);
return rv;
}
}
return NS_OK;
}
nsresult
nsDocShell::CheckClassifier(nsIChannel *aChannel)
{
nsRefPtr<nsClassifierCallback> classifier = new nsClassifierCallback();
if (!classifier) return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = classifier->Start(aChannel, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
mClassifier = classifier;
return NS_OK;
}
@ -10747,279 +10714,6 @@ nsDocShell::IsOKToLoadURI(nsIURI* aURI)
NS_SUCCEEDED(secMan->CheckSameOriginURI(aURI, mLoadingURI, PR_FALSE));
}
//*****************************************************************************
// nsClassifierCallback
//*****************************************************************************
NS_IMPL_ISUPPORTS5(nsClassifierCallback,
nsIChannelClassifier,
nsIURIClassifierCallback,
nsIRunnable,
nsIChannelEventSink,
nsIInterfaceRequestor)
NS_IMETHODIMP
nsClassifierCallback::Run()
{
if (!mChannel) {
return NS_OK;
}
NS_ASSERTION(!mSuspendedChannel,
"nsClassifierCallback::Run() called while a "
"channel is still suspended.");
nsCOMPtr<nsIChannel> channel;
channel.swap(mChannel);
// Don't bother to run the classifier on a load that has already failed.
// (this might happen after a redirect)
PRUint32 status;
channel->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(channel)) {
return NS_OK;
}
nsCOMPtr<nsIURI> uri;
nsresult rv = channel->GetURI(getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
// Don't bother checking certain types of URIs.
PRBool 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);
PRBool 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 = channel->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 = channel;
#ifdef DEBUG
PR_LOG(gDocShellLog, PR_LOG_DEBUG,
("nsClassifierCallback[%p]: suspended channel %p",
this, mSuspendedChannel.get()));
#endif
}
return NS_OK;
}
// Note in the cache entry that this URL was classified, so that future
// cached loads don't need to be checked.
void
nsClassifierCallback::MarkEntryClassified(nsresult status)
{
nsCOMPtr<nsICachingChannel> cachingChannel =
do_QueryInterface(mSuspendedChannel);
if (!cachingChannel) {
return;
}
nsCOMPtr<nsISupports> cacheToken;
cachingChannel->GetCacheToken(getter_AddRefs(cacheToken));
if (!cacheToken) {
return;
}
nsCOMPtr<nsICacheEntryDescriptor> cacheEntry =
do_QueryInterface(cacheToken);
if (!cacheEntry) {
return;
}
cacheEntry->SetMetaDataElement("docshell:classified",
NS_SUCCEEDED(status) ? "1" : nsnull);
}
PRBool
nsClassifierCallback::HasBeenClassified(nsIChannel *aChannel)
{
nsCOMPtr<nsICachingChannel> cachingChannel =
do_QueryInterface(aChannel);
if (!cachingChannel) {
return PR_FALSE;
}
// Only check the tag if we are loading from the cache without
// validation.
PRBool fromCache;
if (NS_FAILED(cachingChannel->IsFromCache(&fromCache)) || !fromCache) {
return PR_FALSE;
}
nsCOMPtr<nsISupports> cacheToken;
cachingChannel->GetCacheToken(getter_AddRefs(cacheToken));
if (!cacheToken) {
return PR_FALSE;
}
nsCOMPtr<nsICacheEntryDescriptor> cacheEntry =
do_QueryInterface(cacheToken);
if (!cacheEntry) {
return PR_FALSE;
}
nsXPIDLCString tag;
cacheEntry->GetMetaDataElement("docshell:classified", getter_Copies(tag));
return tag.EqualsLiteral("1");
}
NS_IMETHODIMP
nsClassifierCallback::OnClassifyComplete(nsresult aErrorCode)
{
if (mSuspendedChannel) {
MarkEntryClassified(aErrorCode);
if (NS_FAILED(aErrorCode)) {
#ifdef DEBUG
PR_LOG(gDocShellLog, PR_LOG_DEBUG,
("nsClassifierCallback[%p]: cancelling channel %p with error code: %d",
this, mSuspendedChannel.get(), aErrorCode));
#endif
mSuspendedChannel->Cancel(aErrorCode);
}
#ifdef DEBUG
PR_LOG(gDocShellLog, PR_LOG_DEBUG,
("nsClassifierCallback[%p]: resuming channel %p from OnClassifyComplete",
this, mSuspendedChannel.get()));
#endif
mSuspendedChannel->Resume();
mSuspendedChannel = nsnull;
}
return NS_OK;
}
NS_IMETHODIMP
nsClassifierCallback::Start(nsIChannel *aChannel, PRBool aInstallListener)
{
mChannel = aChannel;
if (aInstallListener) {
nsresult rv = aChannel->GetNotificationCallbacks
(getter_AddRefs(mNotificationCallbacks));
NS_ENSURE_SUCCESS(rv, rv);
rv = aChannel->SetNotificationCallbacks
(static_cast<nsIInterfaceRequestor*>(this));
NS_ENSURE_SUCCESS(rv, rv);
}
return Run();
}
NS_IMETHODIMP
nsClassifierCallback::OnRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel)
{
mChannel = aNewChannel;
// we call the Run() from the main loop to give the channel a
// chance to AsyncOpen() before we suspend it.
NS_DispatchToCurrentThread(this);
return NS_OK;
}
NS_IMETHODIMP
nsClassifierCallback::Cancel()
{
if (mSuspendedChannel) {
#ifdef DEBUG
PR_LOG(gDocShellLog, PR_LOG_DEBUG,
("nsClassifierCallback[%p]: resuming channel %p from Cancel()",
this, mSuspendedChannel.get()));
#endif
mSuspendedChannel->Resume();
mSuspendedChannel = nsnull;
}
if (mChannel) {
mChannel = nsnull;
}
return NS_OK;
}
NS_IMETHODIMP
nsClassifierCallback::OnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags)
{
nsresult rv = OnRedirect(aOldChannel, aNewChannel);
NS_ENSURE_SUCCESS(rv, rv);
if (mNotificationCallbacks) {
nsCOMPtr<nsIChannelEventSink> sink =
do_GetInterface(mNotificationCallbacks);
if (sink) {
return sink->OnChannelRedirect(aOldChannel, aNewChannel, aFlags);
}
}
return NS_OK;
}
NS_IMETHODIMP
nsClassifierCallback::GetInterface(const nsIID &aIID, void **aResult)
{
if (aIID.Equals(NS_GET_IID(nsIChannelEventSink))) {
NS_ADDREF_THIS();
*aResult = static_cast<nsIChannelEventSink *>(this);
return NS_OK;
} else if (mNotificationCallbacks) {
return mNotificationCallbacks->GetInterface(aIID, aResult);
} else {
return NS_ERROR_NO_INTERFACE;
}
}
//
// Routines for selection and clipboard
//

Просмотреть файл

@ -108,8 +108,6 @@
#include "nsIObserver.h"
#include "nsDocShellLoadTypes.h"
#include "nsPIDOMEventTarget.h"
#include "nsIURIClassifier.h"
#include "nsIChannelClassifier.h"
#include "nsILoadContext.h"
#include "nsIWidget.h"
#include "nsIWebShellServices.h"
@ -156,32 +154,6 @@ protected:
virtual ~nsRefreshTimer();
};
class nsClassifierCallback : public nsIChannelClassifier
, public nsIURIClassifierCallback
, public nsIRunnable
, public nsIChannelEventSink
, public nsIInterfaceRequestor
{
public:
nsClassifierCallback() {}
~nsClassifierCallback() {}
NS_DECL_ISUPPORTS
NS_DECL_NSICHANNELCLASSIFIER
NS_DECL_NSIURICLASSIFIERCALLBACK
NS_DECL_NSIRUNNABLE
NS_DECL_NSICHANNELEVENTSINK
NS_DECL_NSIINTERFACEREQUESTOR
private:
nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsIChannel> mSuspendedChannel;
nsCOMPtr<nsIInterfaceRequestor> mNotificationCallbacks;
void MarkEntryClassified(nsresult status);
PRBool HasBeenClassified(nsIChannel *aChannel);
};
#define NS_ERROR_DOCSHELL_REQUEST_REJECTED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_GENERAL,1001)
typedef enum {
@ -353,11 +325,6 @@ protected:
nsIURILoader * aURILoader,
PRBool aBypassClassifier);
// Check the channel load against the URI classifier service (if it
// exists). The channel will be suspended until the classification is
// complete.
nsresult CheckClassifier(nsIChannel *aChannel);
nsresult ScrollIfAnchor(nsIURI * aURI, PRBool * aWasAnchor,
PRUint32 aLoadType, nscoord *cx, nscoord *cy,
PRBool * aDoHashchange);
@ -693,9 +660,6 @@ protected:
// Secure browser UI object
nsCOMPtr<nsISecureBrowserUI> mSecurityUI;
// Suspends/resumes channels based on the URI classifier.
nsRefPtr<nsClassifierCallback> mClassifier;
// The URI we're currently loading. This is only relevant during the
// firing of a pagehide/unload. The caller of FirePageHideNotification()
// is responsible for setting it and unsetting it. It may be null if the

Просмотреть файл

@ -1,91 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: ft=cpp tw=78 sw=4 et ts=4 sts=4 cin
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dave Camp <dcamp@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface nsIChannel;
/**
* An nsIChannelClassifier object checks a channel's URI against the
* URI classifier service, and cancels the channel before OnStartRequest
* if it is found on a blacklist.
*/
[scriptable, uuid(1481c5b5-9f6e-4995-8fe3-2aad5c06440d)]
interface nsIChannelClassifier : nsISupports
{
/**
* Checks a channel against the URI classifier service (if it exists).
*
* The channel will be suspended while the classifier is checked. The
* channel may be cancelled with an error code determined by the classifier
* before it is resumed.
*
* If there is no URI classifier service, NS_ERROR_FACTORY_NOT_REGISTERED
* will be returned.
*
* This method must be called immediately after AsyncOpen() has been called
* on the channel.
*
* @param aChannel
* The channel to suspend.
* @param aInstallListener
* If true, the classifier will install notification
* callbacks to listen for redirects. The classifier will
* pass all notifications on to the channel's existing
* notification callbacks.
*/
void start(in nsIChannel aChannel, in boolean aInstallListener);
/**
* Notify the classifier that the channel was redirected. The new channel
* will be suspended pending a new classifier lookup.
*
* @param aOldChannel
* The channel that's being redirected.
* @param aNewChannel
* The new channel. This channel is not opened yet.
*/
void onRedirect(in nsIChannel aOldChannel, in nsIChannel aNewChannel);
/**
* Cancel an existing query. If a channel has been suspended, it will
* be resumed.
*/
void cancel();
};

Просмотреть файл

@ -60,21 +60,6 @@
#define NS_WEBNAVIGATION_INFO_CONTRACTID \
"@mozilla.org/webnavigation-info;1"
/**
* Contract ID for a service implementing nsIURIClassifier that identifies
* phishing and malware sites.
*/
#define NS_URICLASSIFIERSERVICE_CONTRACTID "@mozilla.org/uriclassifierservice"
/**
* Class and contract ID for an nsIChannelClassifier implementation for
* checking a channel load against the URI classifier service.
*/
#define NS_CHANNELCLASSIFIER_CID \
{ 0xce02d538, 0x0217, 0x47a3,{0xa5, 0x89, 0xb5, 0x17, 0x90, 0xfd, 0xd8, 0xce}}
#define NS_CHANNELCLASSIFIER_CONTRACTID "@mozilla.org/channelclassifier"
/**
* Class and contract ID for the docshell. This is the container for a web
* navigation context. It implements too many interfaces to count, and the

Просмотреть файл

@ -103,7 +103,6 @@ Shutdown(nsIModule* aSelf)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsDocShell, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDefaultURIFixup)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsWebNavigationInfo, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsClassifierCallback)
// uriloader
NS_GENERIC_FACTORY_CONSTRUCTOR(nsURILoader)
@ -144,12 +143,6 @@ static const nsModuleComponentInfo gDocShellModuleInfo[] = {
NS_WEBNAVIGATION_INFO_CONTRACTID,
nsWebNavigationInfoConstructor
},
{
"Channel classifier",
NS_CHANNELCLASSIFIER_CID,
NS_CHANNELCLASSIFIER_CONTRACTID,
nsClassifierCallbackConstructor
},
// about redirector
{ "about:about",

Просмотреть файл

@ -46,7 +46,6 @@
#include "nsIRequest.h"
#include "nsIScriptSecurityManager.h"
#include "nsIStreamLoader.h"
#include "nsIChannelClassifier.h"
// Other includes
#include "nsAutoLock.h"
@ -526,7 +525,8 @@ nsDOMWorkerScriptLoader::RunInternal()
ios,
loadGroup,
nsnull, // callbacks
nsIRequest::LOAD_NORMAL, // loadFlags
nsIRequest::LOAD_NORMAL |
nsIChannel::LOAD_CLASSIFY_URI, // loadFlags
channelPolicy); // CSP info
NS_ENSURE_SUCCESS(rv, rv);
@ -536,18 +536,6 @@ nsDOMWorkerScriptLoader::RunInternal()
loadInfo.channel = nsnull;
return rv;
}
// Check the load against the URI classifier
nsCOMPtr<nsIChannelClassifier> classifier =
do_CreateInstance(NS_CHANNELCLASSIFIER_CONTRACTID);
if (classifier) {
rv = classifier->Start(loadInfo.channel, PR_TRUE);
if (NS_FAILED(rv)) {
loadInfo.channel->Cancel(rv);
loadInfo.channel = nsnull;
return rv;
}
}
}
return NS_OK;

Просмотреть файл

@ -85,7 +85,6 @@
#include "nsThreadUtils.h"
#include "nsGkAtoms.h"
#include "nsDocShellCID.h"
#include "nsIChannelClassifier.h"
#ifdef MOZ_XUL
#include "nsXULPrototypeCache.h"
@ -1537,8 +1536,9 @@ Loader::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState)
nsCOMPtr<nsIChannel> channel;
rv = NS_NewChannel(getter_AddRefs(channel),
aLoadData->mURI, nsnull, loadGroup,
nsnull, nsIChannel::LOAD_NORMAL, channelPolicy);
aLoadData->mURI, nsnull, loadGroup, nsnull,
nsIChannel::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI,
channelPolicy);
if (NS_FAILED(rv)) {
#ifdef DEBUG
@ -1596,20 +1596,6 @@ Loader::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState)
return rv;
}
// Check the load against the URI classifier
nsCOMPtr<nsIChannelClassifier> classifier =
do_CreateInstance(NS_CHANNELCLASSIFIER_CONTRACTID);
if (classifier) {
rv = classifier->Start(channel, PR_TRUE);
if (NS_FAILED(rv)) {
LOG_ERROR((" Failed to classify URI"));
aLoadData->mIsCancelled = PR_TRUE;
channel->Cancel(rv);
SheetComplete(aLoadData, rv);
return rv;
}
}
if (!mLoadingDatas.Put(&key, aLoadData)) {
LOG_ERROR((" Failed to put data in loading table"));
aLoadData->mIsCancelled = PR_TRUE;

Просмотреть файл

@ -135,6 +135,7 @@ XPIDLSRCS = \
nsIProxiedChannel.idl \
nsIRandomGenerator.idl \
nsIURIWithPrincipal.idl \
nsIURIClassifier.idl \
$(NULL)
EXPORTS = \

Просмотреть файл

@ -213,7 +213,7 @@ interface nsIChannel : nsIRequest
/**************************************************************************
* Channel specific load flags:
*
* Bits 22-31 are reserved for future use by this interface or one of its
* Bits 23-31 are reserved for future use by this interface or one of its
* derivatives (e.g., see nsICachingChannel).
*/
@ -268,4 +268,10 @@ interface nsIChannel : nsIRequest
* should only do so with good reason.
*/
const unsigned long LOAD_CALL_CONTENT_SNIFFERS = 1 << 21;
/**
* This flag tells the channel to use URI classifier service to check
* the URI when opening the channel.
*/
const unsigned long LOAD_CLASSIFY_URI = 1 << 22;
};

Просмотреть файл

@ -55,6 +55,7 @@ CPPSRCS = \
nsBaseChannel.cpp \
nsBaseContentStream.cpp \
nsBufferedStreams.cpp \
nsChannelClassifier.cpp \
nsDirectoryIndexStream.cpp \
nsDownloader.cpp \
nsFileStreams.cpp \

Просмотреть файл

@ -46,6 +46,7 @@
#include "nsIChannelEventSink.h"
#include "nsIStreamConverterService.h"
#include "nsIContentSniffer.h"
#include "nsChannelClassifier.h"
static PLDHashOperator
CopyProperties(const nsAString &key, nsIVariant *data, void *closure)
@ -284,6 +285,24 @@ nsBaseChannel::HandleAsyncRedirect(nsIChannel* newChannel)
CallbacksChanged();
}
void
nsBaseChannel::ClassifyURI()
{
nsresult rv;
if (mLoadFlags & LOAD_CLASSIFY_URI) {
nsRefPtr<nsChannelClassifier> classifier = new nsChannelClassifier();
if (classifier) {
rv = classifier->Start(this);
if (NS_FAILED(rv)) {
Cancel(rv);
}
} else {
Cancel(NS_ERROR_OUT_OF_MEMORY);
}
}
}
//-----------------------------------------------------------------------------
// nsBaseChannel::nsISupports
@ -513,7 +532,10 @@ nsBaseChannel::Open(nsIInputStream **result)
} else if (rv == NS_ERROR_NOT_IMPLEMENTED)
return NS_ImplementChannelOpen(this, result);
mWasOpened = NS_SUCCEEDED(rv);
if (NS_SUCCEEDED(rv)) {
mWasOpened = PR_TRUE;
ClassifyURI();
}
return rv;
}
@ -561,6 +583,8 @@ nsBaseChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt)
if (mLoadGroup)
mLoadGroup->AddRequest(this, nsnull);
ClassifyURI();
return NS_OK;
}

Просмотреть файл

@ -247,6 +247,9 @@ private:
// returned success from AsyncOpen while posting a redirect runnable.
void HandleAsyncRedirect(nsIChannel* newChannel);
// start URI classifier if requested
void ClassifyURI();
class RedirectRunnable : public nsRunnable
{
public:

Просмотреть файл

@ -0,0 +1,229 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dave Camp <dcamp@mozilla.com>
* Michal Novotny <michal.novotny@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsChannelClassifier.h"
#include "nsNetUtil.h"
#include "nsIChannel.h"
#include "nsIProtocolHandler.h"
#include "nsICachingChannel.h"
#include "nsICacheEntryDescriptor.h"
#include "prlog.h"
#if defined(PR_LOGGING)
//
// NSPR_LOG_MODULES=nsChannelClassifier:5
//
static PRLogModuleInfo *gChannelClassifierLog;
#endif
#define LOG(args) PR_LOG(gChannelClassifierLog, PR_LOG_DEBUG, args)
NS_IMPL_ISUPPORTS1(nsChannelClassifier,
nsIURIClassifierCallback)
nsChannelClassifier::nsChannelClassifier()
{
#if defined(PR_LOGGING)
if (!gChannelClassifierLog)
gChannelClassifierLog = PR_NewLogModule("nsChannelClassifier");
#endif
}
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.
PRBool 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);
PRBool 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;
}
// Note in the cache entry that this URL was classified, so that future
// cached loads don't need to be checked.
void
nsChannelClassifier::MarkEntryClassified(nsresult status)
{
nsCOMPtr<nsICachingChannel> cachingChannel =
do_QueryInterface(mSuspendedChannel);
if (!cachingChannel) {
return;
}
nsCOMPtr<nsISupports> cacheToken;
cachingChannel->GetCacheToken(getter_AddRefs(cacheToken));
if (!cacheToken) {
return;
}
nsCOMPtr<nsICacheEntryDescriptor> cacheEntry =
do_QueryInterface(cacheToken);
if (!cacheEntry) {
return;
}
cacheEntry->SetMetaDataElement("necko:classified",
NS_SUCCEEDED(status) ? "1" : nsnull);
}
PRBool
nsChannelClassifier::HasBeenClassified(nsIChannel *aChannel)
{
nsCOMPtr<nsICachingChannel> cachingChannel =
do_QueryInterface(aChannel);
if (!cachingChannel) {
return PR_FALSE;
}
// Only check the tag if we are loading from the cache without
// validation.
PRBool fromCache;
if (NS_FAILED(cachingChannel->IsFromCache(&fromCache)) || !fromCache) {
return PR_FALSE;
}
nsCOMPtr<nsISupports> cacheToken;
cachingChannel->GetCacheToken(getter_AddRefs(cacheToken));
if (!cacheToken) {
return PR_FALSE;
}
nsCOMPtr<nsICacheEntryDescriptor> cacheEntry =
do_QueryInterface(cacheToken);
if (!cacheEntry) {
return PR_FALSE;
}
nsXPIDLCString tag;
cacheEntry->GetMetaDataElement("necko:classified", getter_Copies(tag));
return tag.EqualsLiteral("1");
}
NS_IMETHODIMP
nsChannelClassifier::OnClassifyComplete(nsresult aErrorCode)
{
if (mSuspendedChannel) {
MarkEntryClassified(aErrorCode);
if (NS_FAILED(aErrorCode)) {
#ifdef DEBUG
LOG(("nsChannelClassifier[%p]: cancelling channel %p with error "
"code: %x", this, mSuspendedChannel.get(), aErrorCode));
#endif
mSuspendedChannel->Cancel(aErrorCode);
}
#ifdef DEBUG
LOG(("nsChannelClassifier[%p]: resuming channel %p from "
"OnClassifyComplete", this, mSuspendedChannel.get()));
#endif
mSuspendedChannel->Resume();
mSuspendedChannel = nsnull;
}
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,67 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dave Camp <dcamp@mozilla.com>
* Michal Novotny <michal.novotny@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsChannelClassifier_h__
#define nsChannelClassifier_h__
#include "nsIURIClassifier.h"
#include "nsIRunnable.h"
#include "nsCOMPtr.h"
class nsIChannel;
class nsChannelClassifier : public nsIURIClassifierCallback
{
public:
nsChannelClassifier();
NS_DECL_ISUPPORTS
NS_DECL_NSIURICLASSIFIERCALLBACK
nsresult Start(nsIChannel *aChannel);
private:
nsCOMPtr<nsIChannel> mSuspendedChannel;
~nsChannelClassifier() {}
void MarkEntryClassified(nsresult status);
PRBool HasBeenClassified(nsIChannel *aChannel);
};
#endif

Просмотреть файл

@ -469,6 +469,13 @@
#define NS_DEFAULTAUTHPROMPT_CONTRACTID \
"@mozilla.org/network/default-auth-prompt;1"
/**
* Contract ID for a service implementing nsIURIClassifier that identifies
* phishing and malware sites.
*/
#define NS_URICLASSIFIERSERVICE_CONTRACTID \
"@mozilla.org/uriclassifierservice"
/******************************************************************************
* netwerk/cache/ classes
*/

Просмотреть файл

@ -83,6 +83,7 @@
#include "nsAuthInformationHolder.h"
#include "nsICacheService.h"
#include "nsDNSPrefetch.h"
#include "nsChannelClassifier.h"
// True if the local cache should be bypassed when processing a request.
#define BYPASS_LOCAL_CACHE(loadFlags) \
@ -4496,6 +4497,20 @@ nsHttpChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *context)
CloseCacheEntry(PR_TRUE);
AsyncAbort(rv);
}
if (mLoadFlags & LOAD_CLASSIFY_URI) {
nsRefPtr<nsChannelClassifier> classifier = new nsChannelClassifier();
if (!classifier) {
Cancel(NS_ERROR_OUT_OF_MEMORY);
return NS_OK;
}
rv = classifier->Start(this);
if (NS_FAILED(rv)) {
Cancel(rv);
}
}
return NS_OK;
}
//-----------------------------------------------------------------------------

Просмотреть файл

@ -63,7 +63,6 @@
#include "nsUrlClassifierStreamUpdater.h"
#include "nsUrlClassifierUtils.h"
#include "nsUrlClassifierHashCompleter.h"
#include "nsDocShellCID.h"
#endif
#ifdef MOZ_FEEDS