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:
@@ -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.
|
||||
|
||||
@@ -113,6 +113,7 @@ XPIDLSRCS = \
|
||||
nsIURIFixup.idl \
|
||||
nsIEditorDocShell.idl \
|
||||
nsIWebPageDescriptor.idl \
|
||||
nsIURIClassifier.idl \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = nsDocShellLoadTypes.h
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
85
mozilla/docshell/base/nsIURIClassifier.idl
Normal file
85
mozilla/docshell/base/nsIURIClassifier.idl
Normal 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);
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -12,9 +12,11 @@ LIBXUL_LIBRARY = 1
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
|
||||
REQUIRES = necko \
|
||||
REQUIRES = docshell \
|
||||
necko \
|
||||
storage \
|
||||
string \
|
||||
uriloader \
|
||||
xpcom \
|
||||
$(ZLIB_REQUIRES) \
|
||||
$(NULL)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
Reference in New Issue
Block a user