Bug 413938: Add an nsIWebNavigation flag to let clients bypass malware/phishing detection. r=bz, sr=biesi, a1.9=damons

This commit is contained in:
dcamp@mozilla.com 2008-01-29 15:49:20 -08:00
parent 95ef32d978
commit fd14ef4029
5 changed files with 102 additions and 21 deletions

View File

@ -149,6 +149,7 @@
#include "nsIDOMDocument.h"
#include "nsICachingChannel.h"
#include "nsICacheVisitor.h"
#include "nsICacheEntryDescriptor.h"
#include "nsIMultiPartChannel.h"
#include "nsIWyciwygChannel.h"
@ -883,6 +884,9 @@ nsDocShell::LoadURI(nsIURI * aURI,
if (aLoadFlags & LOAD_FLAGS_FIRST_LOAD)
flags |= INTERNAL_LOAD_FLAGS_FIRST_LOAD;
if (aLoadFlags & LOAD_FLAGS_BYPASS_CLASSIFIER)
flags |= INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER;
rv = InternalLoad(aURI,
referrer,
owner,
@ -951,7 +955,8 @@ nsDocShell::LoadStream(nsIInputStream *aStream, nsIURI * aURI,
uriLoader(do_GetService(NS_URI_LOADER_CONTRACTID));
NS_ENSURE_TRUE(uriLoader, NS_ERROR_FAILURE);
NS_ENSURE_SUCCESS(DoChannelLoad(channel, uriLoader), NS_ERROR_FAILURE);
NS_ENSURE_SUCCESS(DoChannelLoad(channel, uriLoader, PR_FALSE),
NS_ERROR_FAILURE);
return NS_OK;
}
@ -7051,7 +7056,8 @@ nsDocShell::InternalLoad(nsIURI * aURI,
!(aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER),
owner, aTypeHint, aPostData, aHeadersData, aFirstParty,
aDocShell, getter_AddRefs(req),
(aFlags & INTERNAL_LOAD_FLAGS_FIRST_LOAD) != 0);
(aFlags & INTERNAL_LOAD_FLAGS_FIRST_LOAD) != 0,
(aFlags & INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER) != 0);
if (req && aRequest)
NS_ADDREF(*aRequest = req);
@ -7121,7 +7127,8 @@ nsDocShell::DoURILoad(nsIURI * aURI,
PRBool aFirstParty,
nsIDocShell ** aDocShell,
nsIRequest ** aRequest,
PRBool aIsNewWindowTarget)
PRBool aIsNewWindowTarget,
PRBool aBypassClassifier)
{
nsresult rv;
nsCOMPtr<nsIURILoader> uriLoader;
@ -7311,7 +7318,7 @@ nsDocShell::DoURILoad(nsIURI * aURI,
}
}
rv = DoChannelLoad(channel, uriLoader);
rv = DoChannelLoad(channel, uriLoader, aBypassClassifier);
//
// If the channel load failed, we failed and nsIWebProgress just ain't
@ -7404,7 +7411,8 @@ nsDocShell::AddHeadersToChannel(nsIInputStream *aHeadersData,
}
nsresult nsDocShell::DoChannelLoad(nsIChannel * aChannel,
nsIURILoader * aURILoader)
nsIURILoader * aURILoader,
PRBool aBypassClassifier)
{
nsresult rv;
// Mark the channel as being a document URI and allow content sniffing...
@ -7467,10 +7475,12 @@ nsresult nsDocShell::DoChannelLoad(nsIChannel * aChannel,
this);
NS_ENSURE_SUCCESS(rv, rv);
rv = CheckClassifier(aChannel);
if (NS_FAILED(rv)) {
aChannel->Cancel(rv);
return rv;
if (!aBypassClassifier) {
rv = CheckClassifier(aChannel);
if (NS_FAILED(rv)) {
aChannel->Cancel(rv);
return rv;
}
}
return NS_OK;
@ -9305,15 +9315,10 @@ nsClassifierCallback::Run()
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;
}
// Don't bother to run the classifier on a cached load that was
// previously classified.
if (HasBeenClassified()) {
return NS_OK;
}
nsCOMPtr<nsIURI> uri;
@ -9370,10 +9375,72 @@ nsClassifierCallback::Run()
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()
{
nsCOMPtr<nsICachingChannel> cachingChannel =
do_QueryInterface(mSuspendedChannel);
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,

View File

@ -160,6 +160,9 @@ public:
private:
nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsIChannel> mSuspendedChannel;
void MarkEntryClassified(nsresult status);
PRBool HasBeenClassified();
};
//*****************************************************************************
@ -275,11 +278,13 @@ protected:
PRBool firstParty,
nsIDocShell ** aDocShell,
nsIRequest ** aRequest,
PRBool aIsNewWindowTarget);
PRBool aIsNewWindowTarget,
PRBool aBypassClassifier);
NS_IMETHOD AddHeadersToChannel(nsIInputStream * aHeadersData,
nsIChannel * aChannel);
virtual nsresult DoChannelLoad(nsIChannel * aChannel,
nsIURILoader * aURILoader);
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

View File

@ -60,7 +60,8 @@
* be passed to MAKE_LOAD_TYPE.
*/
#define EXTRA_LOAD_FLAGS (LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP | \
LOAD_FLAGS_FIRST_LOAD)
LOAD_FLAGS_FIRST_LOAD | \
LOAD_FLAGS_BYPASS_CLASSIFIER)
/* load types are legal combinations of load commands and flags
*

View File

@ -126,6 +126,8 @@ interface nsIDocShell : nsISupports
// @see nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD
const long INTERNAL_LOAD_FLAGS_FIRST_LOAD = 0x8;
const long INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER = 0x10;
/**
* Loads the given URI. This method is identical to loadURI(...) except
* that its parameter list is broken out instead of being packaged inside

View File

@ -197,6 +197,12 @@ interface nsIWebNavigation : nsISupports
*/
const unsigned long LOAD_FLAGS_ALLOW_POPUPS = 0x8000;
/**
* This flag specifies that the URI classifier should not be checked for
* this load.
*/
const unsigned long LOAD_FLAGS_BYPASS_CLASSIFIER = 0x10000;
/**
* Loads a given URI. This will give priority to loading the requested URI
* in the object implementing this interface. If it can't be loaded here