Bug 1198078 - Add support for TYPE_INTERNAL_SERVICE_WORKER; r=ckerschb,tanvi

This commit is contained in:
Ehsan Akhgari 2015-09-11 18:48:43 -04:00
parent da8bcafc3f
commit 3cf853e5af
13 changed files with 104 additions and 25 deletions

View File

@ -23,6 +23,7 @@
#include "nsILoadContext.h"
#include "nsCOMArray.h"
#include "nsContentUtils.h"
#include "mozilla/dom/nsMixedContentBlocker.h"
using mozilla::LogLevel;
@ -119,6 +120,12 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod,
nsContentPolicyType externalType =
nsContentUtils::InternalContentPolicyTypeToExternal(contentType);
nsContentPolicyType externalTypeOrScript =
nsContentUtils::InternalContentPolicyTypeToExternalOrScript(contentType);
nsCOMPtr<nsIContentPolicy> mixedContentBlocker =
do_GetService(NS_MIXEDCONTENTBLOCKER_CONTRACTID);
/*
* Enumerate mPolicies and ask each of them, taking the logical AND of
* their permissions.
@ -129,7 +136,15 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod,
int32_t count = entries.Count();
for (int32_t i = 0; i < count; i++) {
/* check the appropriate policy */
rv = (entries[i]->*policyMethod)(externalType, contentLocation,
// Send the internal content policy type to the mixed content blocker
// which needs to know about TYPE_INTERNAL_WORKER,
// TYPE_INTERNAL_SHARED_WORKER and TYPE_INTERNAL_SERVICE_WORKER.
bool isMixedContentBlocker = mixedContentBlocker == entries[i];
nsContentPolicyType type = externalType;
if (isMixedContentBlocker) {
type = externalTypeOrScript;
}
rv = (entries[i]->*policyMethod)(type, contentLocation,
requestingLocation, requestingContext,
mimeType, extra, requestPrincipal,
decision);

View File

@ -126,6 +126,7 @@ NS_CP_ContentTypeName(uint32_t contentType)
CASE_RETURN( TYPE_INTERNAL_TRACK );
CASE_RETURN( TYPE_INTERNAL_XMLHTTPREQUEST );
CASE_RETURN( TYPE_INTERNAL_EVENTSOURCE );
CASE_RETURN( TYPE_INTERNAL_SERVICE_WORKER );
default:
return "<Unknown Type>";
}

View File

@ -7928,6 +7928,7 @@ nsContentUtils::InternalContentPolicyTypeToExternal(nsContentPolicyType aType)
case nsIContentPolicy::TYPE_INTERNAL_SCRIPT:
case nsIContentPolicy::TYPE_INTERNAL_WORKER:
case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER:
case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER:
return nsIContentPolicy::TYPE_SCRIPT;
case nsIContentPolicy::TYPE_INTERNAL_EMBED:
@ -7952,6 +7953,22 @@ nsContentUtils::InternalContentPolicyTypeToExternal(nsContentPolicyType aType)
}
}
/* static */
nsContentPolicyType
nsContentUtils::InternalContentPolicyTypeToExternalOrScript(nsContentPolicyType aType)
{
switch (aType) {
case nsIContentPolicy::TYPE_INTERNAL_SCRIPT:
case nsIContentPolicy::TYPE_INTERNAL_WORKER:
case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER:
case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER:
return aType;
default:
return InternalContentPolicyTypeToExternal(aType);
}
}
nsresult
nsContentUtils::SetFetchReferrerURIWithPolicy(nsIPrincipal* aPrincipal,

View File

@ -953,6 +953,18 @@ public:
*/
static nsContentPolicyType InternalContentPolicyTypeToExternal(nsContentPolicyType aType);
/**
* Map internal content policy types to external ones or script types:
* * TYPE_INTERNAL_SCRIPT
* * TYPE_INTERNAL_WORKER
* * TYPE_INTERNAL_SHARED_WORKER
* * TYPE_INTERNAL_SERVICE_WORKER
*
*
* Note: DO NOT call this function unless you know what you're doing!
*/
static nsContentPolicyType InternalContentPolicyTypeToExternalOrScript(nsContentPolicyType aType);
/**
* Quick helper to determine whether there are any mutation listeners
* of a given type that apply to this content or any of its ancestors.

View File

@ -20,7 +20,7 @@ interface nsIPrincipal;
* by launching a dialog to prompt the user for something).
*/
[scriptable,uuid(3663021e-5670-496f-887b-b408d6526b5b)]
[scriptable,uuid(ce321216-c404-40a7-a711-d80454ec6b76)]
interface nsIContentPolicy : nsIContentPolicyBase
{
/**

View File

@ -24,7 +24,7 @@ typedef unsigned long nsContentPolicyType;
* by launching a dialog to prompt the user for something).
*/
[scriptable,uuid(20f7b9bf-d7d5-4987-ade8-b7dc0398d44a)]
[scriptable,uuid(8527ae0d-0c43-4413-bc46-85c0bcb66876)]
interface nsIContentPolicyBase : nsISupports
{
/**
@ -271,6 +271,15 @@ interface nsIContentPolicyBase : nsISupports
*/
const nsContentPolicyType TYPE_INTERNAL_EVENTSOURCE = 34;
/**
* Indicates an internal constant for scripts loaded through a service
* worker.
*
* This will be mapped to TYPE_SCRIPT before being passed to content policy
* implementations.
*/
const nsContentPolicyType TYPE_INTERNAL_SERVICE_WORKER = 35;
/* When adding new content types, please update nsContentBlocker,
* NS_CP_ContentTypeName, nsCSPContext, all nsIContentPolicy
* implementations, the static_assert in dom/cache/DBSchema.cpp,

View File

@ -28,7 +28,7 @@ interface nsIDOMElement;
* by launching a dialog to prompt the user for something).
*/
[scriptable,uuid(b181c97c-9d67-4da1-95a0-e0a202e1807c)]
[scriptable,uuid(b9df71e3-a9b3-4706-b2d5-e6c0d3d68ec7)]
interface nsISimpleContentPolicy : nsIContentPolicyBase
{
/**

View File

@ -274,8 +274,9 @@ static_assert(nsIContentPolicy::TYPE_INVALID == 0 &&
nsIContentPolicy::TYPE_INTERNAL_VIDEO == 31 &&
nsIContentPolicy::TYPE_INTERNAL_TRACK == 32 &&
nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST == 33 &&
nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE == 34,
"nsContentPolicytType values are as expected");
nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE == 34 &&
nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER == 35,
"nsContentPolicyType values are as expected");
namespace {

View File

@ -116,6 +116,7 @@ InternalRequest::MapContentPolicyTypeToRequestContext(nsContentPolicyType aConte
context = RequestContext::Internal;
break;
case nsIContentPolicy::TYPE_INTERNAL_SCRIPT:
case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER:
context = RequestContext::Script;
break;
case nsIContentPolicy::TYPE_INTERNAL_WORKER:

View File

@ -291,7 +291,7 @@ nsMixedContentBlocker::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
return NS_OK;
}
uint32_t contentPolicyType = loadInfo->GetContentPolicyType();
nsContentPolicyType contentPolicyType = loadInfo->InternalContentPolicyType();
nsCOMPtr<nsIPrincipal> requestingPrincipal = loadInfo->LoadingPrincipal();
// Since we are calling shouldLoad() directly on redirects, we don't go through the code
@ -310,7 +310,7 @@ nsMixedContentBlocker::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
}
int16_t decision = REJECT_REQUEST;
rv = ShouldLoad(nsContentUtils::InternalContentPolicyTypeToExternal(contentPolicyType),
rv = ShouldLoad(nsContentUtils::InternalContentPolicyTypeToExternalOrScript(contentPolicyType),
newUri,
requestingLocation,
loadInfo->LoadingNode(),
@ -378,9 +378,17 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
// to them.
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType),
MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternalOrScript(aContentType),
"We should only see external content policy types here.");
// The content policy type that we receive may be an internal type for
// scripts. Let's remember if we have seen a worker type, and reset it to the
// external type in all cases right now.
bool isWorkerType = aContentType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
aContentType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER ||
aContentType == nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER;
aContentType = nsContentUtils::InternalContentPolicyTypeToExternal(aContentType);
// Assume active (high risk) content and blocked by default
MixedContentTypes classification = eMixedScript;
// Make decision to block/reject by default
@ -625,6 +633,23 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
return NS_OK;
}
// Disallow mixed content loads for workers, shared workers and service
// workers.
if (isWorkerType) {
// For workers, we can assume that we're mixed content at this point, since
// the parent is https, and the protocol associated with aContentLocation
// doesn't map to the secure URI flags checked above. Assert this for
// sanity's sake
#ifdef DEBUG
bool isHttpsScheme = false;
rv = aContentLocation->SchemeIs("https", &isHttpsScheme);
NS_ENSURE_SUCCESS(rv, rv);
MOZ_ASSERT(!isHttpsScheme);
#endif
*aDecision = REJECT_REQUEST;
return NS_OK;
}
// Determine if the rootDoc is https and if the user decided to allow Mixed Content
nsCOMPtr<nsIDocShell> docShell = NS_CP_GetDocShellFromContext(aRequestingContext);
NS_ENSURE_TRUE(docShell, NS_OK);

View File

@ -120,21 +120,18 @@ ChannelFromScriptURL(nsIPrincipal* principal,
return NS_ERROR_DOM_SYNTAX_ERR;
}
// If we're part of a document then check the content load policy.
if (parentDoc) {
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(aContentPolicyType, uri,
principal, parentDoc,
NS_LITERAL_CSTRING("text/javascript"),
nullptr, &shouldLoad,
nsContentUtils::GetContentPolicy(),
secMan);
if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
if (NS_FAILED(rv) || shouldLoad != nsIContentPolicy::REJECT_TYPE) {
return rv = NS_ERROR_CONTENT_BLOCKED;
}
return rv = NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(aContentPolicyType, uri,
principal, parentDoc,
NS_LITERAL_CSTRING("text/javascript"),
nullptr, &shouldLoad,
nsContentUtils::GetContentPolicy(),
secMan);
if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
if (NS_FAILED(rv) || shouldLoad != nsIContentPolicy::REJECT_TYPE) {
return rv = NS_ERROR_CONTENT_BLOCKED;
}
return rv = NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
}
if (aWorkerScriptType == DebuggerScript) {

View File

@ -732,7 +732,7 @@ public:
case WorkerTypeShared:
return nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER;
case WorkerTypeService:
return nsIContentPolicy::TYPE_SCRIPT;
return nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER;
default:
MOZ_ASSERT_UNREACHABLE("Invalid worker type");
return nsIContentPolicy::TYPE_INVALID;

View File

@ -57,7 +57,8 @@ static const char *kTypeString[] = {
"", // TYPE_INTERNAL_VIDEO
"", // TYPE_INTERNAL_TRACK
"", // TYPE_INTERNAL_XMLHTTPREQUEST
"" // TYPE_INTERNAL_EVENTSOURCE
"", // TYPE_INTERNAL_EVENTSOURCE
"", // TYPE_INTERNAL_SERVICE_WORKER
};
#define NUMBER_OF_TYPES MOZ_ARRAY_LENGTH(kTypeString)