block document loads for URIs tagged as malware by the url-classifier service. b=384941, r=bzbarsky, r=tony, sr=biesi, ui-r=johnath, a=bzbarsky

git-svn-id: svn://10.0.0.236/trunk@233523 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
dcamp%mozilla.com
2007-08-31 23:18:48 +00:00
parent 1a2a6df23f
commit 1a066ed8a8
14 changed files with 470 additions and 21 deletions

View File

@@ -59,3 +59,4 @@ externalProtocolPrompt=An external application must be launched to handle %1$S:
externalProtocolUnknown=<Unknown>
externalProtocolChkMsg=Remember my choice for all links of this type.
externalProtocolLaunchBtn=Launch application
malwareBlocked=The site at %S has been reported as an attack site and has been blocked based on your security preferences.

View File

@@ -113,6 +113,7 @@ XPIDLSRCS = \
nsIURIFixup.idl \
nsIEditorDocShell.idl \
nsIWebPageDescriptor.idl \
nsIURIClassifier.idl \
$(NULL)
EXPORTS = nsDocShellLoadTypes.h

View File

@@ -58,6 +58,7 @@
#include "nsIDocumentViewer.h"
#include "nsIDocumentLoaderFactory.h"
#include "nsCURILoader.h"
#include "nsURILoader.h"
#include "nsDocShellCID.h"
#include "nsLayoutCID.h"
#include "nsDOMCID.h"
@@ -105,6 +106,7 @@
#include "nsIViewManager.h"
#include "nsIScrollableView.h"
#include "nsIScriptChannel.h"
#include "nsIURIClassifier.h"
// we want to explore making the document own the load group
// so we can associate the document URI with the load group.
@@ -2840,6 +2842,7 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI *aURI,
PRUint32 formatStrCount = 0;
nsresult rv = NS_OK;
nsAutoString messageStr;
nsCAutoString cssClass;
// Turn the error code into a human readable error message.
if (NS_ERROR_UNKNOWN_PROTOCOL == aError) {
@@ -2980,6 +2983,15 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI *aURI,
// Bad Content Encoding.
error.AssignLiteral("contentEncodingError");
break;
case NS_ERROR_MALWARE_URI:
nsCAutoString host;
aURI->GetHost(host);
CopyUTF8toUTF16(host, formatStrs[0]);
formatStrCount = 1;
error.AssignLiteral("malwareBlocked");
cssClass.AssignLiteral("blacklist");
break;
}
}
@@ -3021,7 +3033,7 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI *aURI,
if (mUseErrorPages && aURI && aFailedChannel) {
// Display an error page
LoadErrorPage(aURI, aURL, error.get(), messageStr.get(),
aFailedChannel);
cssClass.get(), aFailedChannel);
}
else
{
@@ -3046,6 +3058,7 @@ NS_IMETHODIMP
nsDocShell::LoadErrorPage(nsIURI *aURI, const PRUnichar *aURL,
const PRUnichar *aErrorType,
const PRUnichar *aDescription,
const char *aCSSClass,
nsIChannel* aFailedChannel)
{
#if defined(PR_LOGGING) && defined(DEBUG)
@@ -3110,12 +3123,17 @@ nsDocShell::LoadErrorPage(nsIURI *aURI, const PRUnichar *aURL,
char *escapedCharset = nsEscape(charset.get(), url_Path);
char *escapedError = nsEscape(NS_ConvertUTF16toUTF8(aErrorType).get(), url_Path);
char *escapedDescription = nsEscape(NS_ConvertUTF16toUTF8(aDescription).get(), url_Path);
char *escapedCSSClass = nsEscape(aCSSClass, url_Path);
nsCString errorPageUrl("about:neterror?e=");
errorPageUrl.AppendASCII(escapedError);
errorPageUrl.AppendLiteral("&u=");
errorPageUrl.AppendASCII(escapedUrl);
if (escapedCSSClass && escapedCSSClass[0]) {
errorPageUrl.AppendASCII("&s=");
errorPageUrl.AppendASCII(escapedCSSClass);
}
errorPageUrl.AppendLiteral("&c=");
errorPageUrl.AppendASCII(escapedCharset);
errorPageUrl.AppendLiteral("&d=");
@@ -3125,6 +3143,7 @@ nsDocShell::LoadErrorPage(nsIURI *aURI, const PRUnichar *aURL,
nsMemory::Free(escapedError);
nsMemory::Free(escapedUrl);
nsMemory::Free(escapedCharset);
nsMemory::Free(escapedCSSClass);
nsCOMPtr<nsIURI> errorPageURI;
nsresult rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl);
@@ -3222,6 +3241,11 @@ 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!
@@ -4831,6 +4855,17 @@ 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->SetChannel(aNewChannel);
// we call the nsClassifierCallback:Run() from the main loop to
// give the channel a chance to AsyncOpen() the channel before
// we suspend it.
NS_DispatchToCurrentThread(mClassifier);
}
nsCOMPtr<nsIGlobalHistory3> history3(do_QueryInterface(mGlobalHistory));
nsresult result = NS_ERROR_NOT_IMPLEMENTED;
if (history3) {
@@ -4880,6 +4915,10 @@ nsDocShell::EndPageLoad(nsIWebProgress * aProgress,
// during this load handler.
//
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...
//
@@ -7244,8 +7283,34 @@ nsresult nsDocShell::DoChannelLoad(nsIChannel * aChannel,
rv = aURILoader->OpenURI(aChannel,
(mLoadType == LOAD_LINK),
this);
return rv;
NS_ENSURE_SUCCESS(rv, rv);
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;
classifier->SetChannel(aChannel);
nsresult rv = classifier->Run();
if (rv == NS_ERROR_FACTORY_NOT_REGISTERED) {
// no URI classifier, ignore this
return NS_OK;
}
NS_ENSURE_SUCCESS(rv, rv);
mClassifier = classifier;
return NS_OK;
}
NS_IMETHODIMP
@@ -8992,4 +9057,126 @@ nsDocShell::IsAboutBlank(nsIURI* aURI)
aURI->GetSpec(str);
return str.EqualsLiteral("about:blank");
}
//*****************************************************************************
// nsClassifierCallback
//*****************************************************************************
NS_IMPL_THREADSAFE_ISUPPORTS2(nsClassifierCallback,
nsIURIClassifierCallback,
nsIRunnable)
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 load that's coming from the
// cache and doesn't need validaton.
nsCOMPtr<nsICachingChannel> cachingChannel = do_QueryInterface(channel);
if (cachingChannel) {
PRBool fromCache;
if (NS_SUCCEEDED(cachingChannel->IsFromCache(&fromCache)) &&
fromCache) {
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;
nsCOMPtr<nsIURIClassifier> uriClassifier =
do_GetService(NS_URICLASSIFIERSERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv)) return 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();
NS_ENSURE_SUCCESS(rv, rv);
mSuspendedChannel = channel;
PR_LOG(gDocShellLog, PR_LOG_DEBUG,
("nsClassifierCallback[%p]: suspended channel %p",
this, mSuspendedChannel.get()));
}
return NS_OK;
}
NS_IMETHODIMP
nsClassifierCallback::OnClassifyComplete(nsresult aErrorCode)
{
if (mSuspendedChannel) {
if (NS_FAILED(aErrorCode)) {
PR_LOG(gDocShellLog, PR_LOG_DEBUG,
("nsClassifierCallback[%p]: cancelling channel %p with error code: %d",
this, mSuspendedChannel.get(), aErrorCode));
mSuspendedChannel->Cancel(aErrorCode);
}
PR_LOG(gDocShellLog, PR_LOG_DEBUG,
("nsClassifierCallback[%p]: resuming channel %p from OnClassifyComplete",
this, mSuspendedChannel.get()));
mSuspendedChannel->Resume();
mSuspendedChannel = nsnull;
}
return NS_OK;
}
void
nsClassifierCallback::Cancel()
{
if (mSuspendedChannel) {
PR_LOG(gDocShellLog, PR_LOG_DEBUG,
("nsClassifierCallback[%p]: resuming channel %p from Cancel()",
this, mSuspendedChannel.get()));
mSuspendedChannel->Resume();
mSuspendedChannel = nsnull;
}
if (mChannel) {
mChannel = nsnull;
}
}

View File

@@ -105,6 +105,7 @@
#include "nsIObserver.h"
#include "nsDocShellLoadTypes.h"
#include "nsPIDOMEventTarget.h"
#include "nsIURIClassifier.h"
class nsIScrollableView;
@@ -141,6 +142,26 @@ protected:
virtual ~nsRefreshTimer();
};
class nsClassifierCallback : public nsIURIClassifierCallback
, public nsIRunnable
{
public:
nsClassifierCallback() {}
~nsClassifierCallback() {}
NS_DECL_ISUPPORTS
NS_DECL_NSIURICLASSIFIERCALLBACK
NS_DECL_NSIRUNNABLE
void SetChannel(nsIChannel * aChannel)
{ mChannel = aChannel; }
void Cancel();
private:
nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsIChannel> mSuspendedChannel;
};
//*****************************************************************************
//*** nsDocShell
//*****************************************************************************
@@ -260,6 +281,12 @@ protected:
nsIChannel * aChannel);
virtual nsresult DoChannelLoad(nsIChannel * aChannel,
nsIURILoader * aURILoader);
// 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);
NS_IMETHOD ScrollIfAnchor(nsIURI * aURI, PRBool * aWasAnchor,
PRUint32 aLoadType, nscoord *cx, nscoord *cy);
@@ -379,6 +406,7 @@ protected:
NS_IMETHOD LoadErrorPage(nsIURI *aURI, const PRUnichar *aURL,
const PRUnichar *aPage,
const PRUnichar *aDescription,
const char *aCSSClass,
nsIChannel* aFailedChannel);
PRBool IsNavigationAllowed(PRBool aDisplayPrintErrorDialog = PR_TRUE);
PRBool IsPrintingOrPP(PRBool aDisplayErrorDialog = PR_TRUE);
@@ -612,6 +640,9 @@ protected:
// Secure browser UI object
nsCOMPtr<nsISecureBrowserUI> mSecurityUI;
// Suspends/resumes channels based on the URI classifier.
nsRefPtr<nsClassifierCallback> mClassifier;
// WEAK REFERENCES BELOW HERE.
// Note these are intentionally not addrefd. Doing so will create a cycle.
// For that reasons don't use nsCOMPtr.

View File

@@ -0,0 +1,85 @@
/* ***** 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 nsIURI;
interface nsIChannel;
/**
* Callback function for nsIURIClassifier lookups.
*/
[scriptable, function, uuid(8face46e-0c96-470f-af40-0037dcd797bd)]
interface nsIURIClassifierCallback : nsISupports
{
/**
* Called by the URI classifier service when it is done checking a URI.
*
* Clients are responsible for associating callback objects with classify()
* calls.
*
* @param aErrorCode
* The error code with which the channel should be cancelled, or
* NS_OK if the load should continue normally.
*/
void onClassifyComplete(in nsresult aErrorCode);
};
/**
* The URI classifier service checks a URI against lists of phishing
* and malware sites.
*/
[scriptable, uuid(2de5c563-1203-43dd-a212-f5d56d530b6f)]
interface nsIURIClassifier : nsISupports
{
/**
* Classify a URI.
*
* @param aURI
* The URI that should be checked by the URI classifier.
* @param aCallback
* The URI classifier will call this callback when the URI has been
* classified.
*
* @return <code>false</code> if classification is not necessary. The
* callback will not be called.
* <code>true</code> if classification will be performed. The
* callback will be called.
*/
boolean classify(in nsIURI aURI,
in nsIURIClassifierCallback aCallback);
};

View File

@@ -85,6 +85,7 @@
#include "nsIDocShellTreeNode.h"
#include "nsIDocShellTreeOwner.h"
#include "nsCURILoader.h"
#include "nsURILoader.h"
#include "nsIDOMWindowInternal.h"
#include "nsEscape.h"
#include "nsIPlatformCharset.h"
@@ -124,6 +125,8 @@
#include "nsIScriptSecurityManager.h"
#include "nsContentPolicyUtils.h"
#include "nsIURIClassifier.h"
#ifdef NS_DEBUG
/**
* Note: the log module is created during initialization which
@@ -1191,6 +1194,7 @@ nsresult nsWebShell::EndPageLoad(nsIWebProgress *aProgress,
aStatus == NS_ERROR_UNKNOWN_SOCKET_TYPE ||
aStatus == NS_ERROR_NET_INTERRUPT ||
aStatus == NS_ERROR_NET_RESET ||
aStatus == NS_ERROR_MALWARE_URI ||
NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY) {
DisplayLoadError(aStatus, url, nsnull, channel);
}

View File

@@ -49,6 +49,12 @@
#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"
/**
* An observer service topic that can be listened to to catch creation
* of content browsing areas (both toplevel ones and subframes). The

View File

@@ -67,7 +67,7 @@
// or optionally, to specify an alternate CSS class to allow for
// custom styling and favicon:
//
// moz-neterror:page?c=classname&e=error&u=url&d=desc
// moz-neterror:page?e=error&u=url&s=classname&d=desc
// Note that this file uses document.documentURI to get
// the URL (with the format from above). This is because
@@ -86,14 +86,13 @@
function getCSSClass()
{
var url = document.documentURI;
var classParam = url.search(/c\=/);
// c is optional, if classParam == -1 just return nothing
if (classParam == -1)
var matches = url.match(/s\=([^&]+)\&/);
// s is optional, if no match just return nothing
if (!matches || matches.length < 2)
return "";
var rest = url.search(/\&/);
return decodeURIComponent(url.slice(classParam + 2, rest));
// parenthetical match is the second entry
return decodeURIComponent(matches[1]);
}
function getDescription()

View File

@@ -59,3 +59,4 @@ externalProtocolPrompt=An external application must be launched to handle %1$S:
externalProtocolUnknown=<Unknown>
externalProtocolChkMsg=Remember my choice for all links of this type.
externalProtocolLaunchBtn=Launch application
malwareBlocked=The site at %S has been reported as an attack site and has been blocked based on your security preferences.

View File

@@ -58,6 +58,7 @@
#include "nsUrlClassifierDBService.h"
#include "nsUrlClassifierStreamUpdater.h"
#include "nsUrlClassifierUtils.h"
#include "nsDocShellCID.h"
#endif
#ifdef MOZ_FEEDS
@@ -137,6 +138,10 @@ static const nsModuleComponentInfo components[] =
NS_URLCLASSIFIERDBSERVICE_CID,
NS_URLCLASSIFIERDBSERVICE_CONTRACTID,
nsUrlClassifierDBServiceConstructor },
{ "Url Classifier DB Service",
NS_URLCLASSIFIERDBSERVICE_CID,
NS_URICLASSIFIERSERVICE_CONTRACTID,
nsUrlClassifierDBServiceConstructor },
{ "Url Classifier Stream Updater",
NS_URLCLASSIFIERSTREAMUPDATER_CID,
NS_URLCLASSIFIERSTREAMUPDATER_CONTRACTID,

View File

@@ -12,9 +12,11 @@ LIBXUL_LIBRARY = 1
FORCE_STATIC_LIB = 1
REQUIRES = necko \
REQUIRES = docshell \
necko \
storage \
string \
uriloader \
xpcom \
$(ZLIB_REQUIRES) \
$(NULL)

View File

@@ -38,6 +38,7 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "mozIStorageService.h"
#include "mozIStorageConnection.h"
@@ -50,11 +51,15 @@
#include "nsICryptoHash.h"
#include "nsIDirectoryService.h"
#include "nsIObserverService.h"
#include "nsIPrefBranch.h"
#include "nsIPrefBranch2.h"
#include "nsIPrefService.h"
#include "nsIProperties.h"
#include "nsIProxyObjectManager.h"
#include "nsToolkitCompsCID.h"
#include "nsIUrlClassifierUtils.h"
#include "nsUrlClassifierDBService.h"
#include "nsURILoader.h"
#include "nsString.h"
#include "nsTArray.h"
#include "nsVoidArray.h"
@@ -119,6 +124,10 @@ static const PRLogModuleInfo *gUrlClassifierDbServiceLog = nsnull;
#define KEY_LENGTH 16
// Prefs for implementing nsIURIClassifier to block page loads
#define CHECK_MALWARE_PREF "browser.safebrowsing.malware.enabled"
#define CHECK_MALWARE_DEFAULT PR_FALSE
// Singleton instance.
static nsUrlClassifierDBService* sUrlClassifierDBService;
@@ -2028,11 +2037,55 @@ nsUrlClassifierDBServiceWorker::MaybeCreateTables(mozIStorageConnection* connect
return rv;
}
// -------------------------------------------------------------------------
// Helper class for nsIURIClassifier implementation, translates table names
// to nsIURIClassifier enums.
class nsUrlClassifierClassifyCallback : public nsIUrlClassifierCallback
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIURLCLASSIFIERCALLBACK
nsUrlClassifierClassifyCallback(nsIURIClassifierCallback *c)
: mCallback(c)
{}
private:
nsCOMPtr<nsIURIClassifierCallback> mCallback;
};
NS_IMPL_THREADSAFE_ISUPPORTS1(nsUrlClassifierClassifyCallback,
nsIUrlClassifierCallback);
NS_IMETHODIMP
nsUrlClassifierClassifyCallback::HandleEvent(const nsACString& tables)
{
// XXX: we should probably have the wardens tell the service which table
// names match with which classification. For now the table names give
// enough information.
nsresult response = NS_OK;
nsACString::const_iterator begin, end;
tables.BeginReading(begin);
tables.EndReading(end);
if (FindInReadable(NS_LITERAL_CSTRING("-malware-"), begin, end)) {
response = NS_ERROR_MALWARE_URI;
}
mCallback->OnClassifyComplete(response);
return NS_OK;
}
// -------------------------------------------------------------------------
// Proxy class implementation
NS_IMPL_THREADSAFE_ISUPPORTS2(nsUrlClassifierDBService,
NS_IMPL_THREADSAFE_ISUPPORTS3(nsUrlClassifierDBService,
nsIUrlClassifierDBService,
nsIURIClassifier,
nsIObserver)
/* static */ nsUrlClassifierDBService*
@@ -2058,6 +2111,7 @@ nsUrlClassifierDBService::GetInstance()
nsUrlClassifierDBService::nsUrlClassifierDBService()
: mCheckMalware(CHECK_MALWARE_DEFAULT)
{
}
@@ -2088,6 +2142,17 @@ nsUrlClassifierDBService::Init()
do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
// Should we check document loads for malware URIs?
nsCOMPtr<nsIPrefBranch2> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (prefs) {
PRBool tmpbool;
rv = prefs->GetBoolPref(CHECK_MALWARE_PREF, &tmpbool);
mCheckMalware = NS_SUCCEEDED(rv) ? tmpbool : CHECK_MALWARE_DEFAULT;
prefs->AddObserver(CHECK_MALWARE_PREF, this, PR_FALSE);
}
// Start the background thread.
rv = NS_NewThread(&gDbBackgroundThread);
if (NS_FAILED(rv))
@@ -2115,7 +2180,27 @@ nsUrlClassifierDBService::Init()
return NS_OK;
}
nsresult
NS_IMETHODIMP
nsUrlClassifierDBService::Classify(nsIURI *uri,
nsIURIClassifierCallback* c,
PRBool* result)
{
NS_ENSURE_TRUE(gDbBackgroundThread, NS_ERROR_NOT_INITIALIZED);
if (!mCheckMalware) {
*result = PR_FALSE;
return NS_OK;
}
nsRefPtr<nsUrlClassifierClassifyCallback> callback =
new nsUrlClassifierClassifyCallback(c);
if (!callback) return NS_ERROR_OUT_OF_MEMORY;
*result = PR_TRUE;
return LookupURI(uri, callback, PR_TRUE);
}
NS_IMETHODIMP
nsUrlClassifierDBService::Lookup(const nsACString& spec,
nsIUrlClassifierCallback* c,
PRBool needsProxy)
@@ -2132,11 +2217,21 @@ nsUrlClassifierDBService::Lookup(const nsACString& spec,
return NS_ERROR_FAILURE;
}
return LookupURI(uri, c, needsProxy);
}
nsresult
nsUrlClassifierDBService::LookupURI(nsIURI* uri,
nsIUrlClassifierCallback* c,
PRBool needsProxy)
{
NS_ENSURE_TRUE(gDbBackgroundThread, NS_ERROR_NOT_INITIALIZED);
nsCAutoString key;
// Canonicalize the url
nsCOMPtr<nsIUrlClassifierUtils> utilsService =
do_GetService(NS_URLCLASSIFIERUTILS_CONTRACTID);
rv = utilsService->GetKeyForURI(uri, key);
nsresult rv = utilsService->GetKeyForURI(uri, key);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIUrlClassifierCallback> proxyCallback;
@@ -2278,11 +2373,21 @@ NS_IMETHODIMP
nsUrlClassifierDBService::Observe(nsISupports *aSubject, const char *aTopic,
const PRUnichar *aData)
{
NS_ASSERTION(strcmp(aTopic, "profile-before-change") == 0 ||
strcmp(aTopic, "xpcom-shutdown-threads") == 0,
"Unexpected observer topic");
Shutdown();
if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
nsresult rv;
nsCOMPtr<nsIPrefBranch> prefs(do_QueryInterface(aSubject, &rv));
NS_ENSURE_SUCCESS(rv, rv);
if (NS_LITERAL_STRING(CHECK_MALWARE_PREF).Equals(aData)) {
PRBool tmpbool;
rv = prefs->GetBoolPref(CHECK_MALWARE_PREF, &tmpbool);
mCheckMalware = NS_SUCCEEDED(rv) ? tmpbool : CHECK_MALWARE_DEFAULT;
}
} else if (!strcmp(aTopic, "profile-before-change") ||
!strcmp(aTopic, "xpcom-shutdown-threads")) {
Shutdown();
} else {
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
}
@@ -2296,6 +2401,11 @@ nsUrlClassifierDBService::Shutdown()
if (!gDbBackgroundThread)
return NS_OK;
nsCOMPtr<nsIPrefBranch2> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (prefs) {
prefs->RemoveObserver(CHECK_MALWARE_PREF, this);
}
nsresult rv;
// First close the db connection.
if (mWorker) {

View File

@@ -45,12 +45,14 @@
#include "nsID.h"
#include "nsIObserver.h"
#include "nsIUrlClassifierDBService.h"
#include "nsIURIClassifier.h"
class nsUrlClassifierDBServiceWorker;
// This is a proxy class that just creates a background thread and delagates
// calls to the background thread.
class nsUrlClassifierDBService : public nsIUrlClassifierDBService,
public nsIURIClassifier,
public nsIObserver
{
public:
@@ -69,12 +71,17 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIURLCLASSIFIERDBSERVICE
NS_DECL_NSIURICLASSIFIER
NS_DECL_NSIOBSERVER
private:
// No subclassing
~nsUrlClassifierDBService();
nsresult LookupURI(nsIURI* uri,
nsIUrlClassifierCallback* c,
PRBool needsProxy);
// Disallow copy constructor
nsUrlClassifierDBService(nsUrlClassifierDBService&);
@@ -85,6 +92,10 @@ private:
nsresult Shutdown();
nsCOMPtr<nsUrlClassifierDBServiceWorker> mWorker;
// TRUE if the nsURIClassifier implementation should check for malware
// uris on document loads.
PRBool mCheckMalware;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsUrlClassifierDBService, NS_URLCLASSIFIERDBSERVICE_CID)

View File

@@ -92,4 +92,10 @@ protected:
friend class nsDocumentOpenInfo;
};
/**
* The load has been cancelled because it was found on a malware blacklist.
* XXX: this belongs in an nsDocShellErrors.h file of some sort.
*/
#define NS_ERROR_MALWARE_URI NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_URILOADER, 30)
#endif /* nsURILoader_h__ */