Bug 1107516 - Part 3: Make sure all workers have an nsILoadGroup when loading scripts. r=sicking, r=bent

This commit is contained in:
Ben Kelly 2014-12-12 11:06:00 -05:00
parent 2900870db1
commit 0422e2eb55
5 changed files with 78 additions and 26 deletions

View File

@ -29,6 +29,8 @@
#include "nsXPCOM.h"
#include "xpcpublic.h"
#include "mozilla/Assertions.h"
#include "mozilla/LoadContext.h"
#include "mozilla/dom/Exceptions.h"
#include "Principal.h"
#include "WorkerFeature.h"
@ -117,15 +119,14 @@ ChannelFromScriptURL(nsIPrincipal* principal,
flags,
ios);
} else {
// we should use 'principal' here; needs to be fixed before
// we move security checks to AsyncOpen. We use nullPrincipal
// for now, because the loadGroup is null and hence causes
// GetChannelUriPrincipal to return the wrong principal.
nsCOMPtr<nsIPrincipal> nullPrincipal =
do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
// We must have a loadGroup with a load context for the principal to
// traverse the channel correctly.
MOZ_ASSERT(loadGroup);
MOZ_ASSERT(NS_LoadGroupMatchesPrincipal(loadGroup, principal));
rv = NS_NewChannel(getter_AddRefs(channel),
uri,
nullPrincipal,
principal,
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_SCRIPT,
loadGroup,
@ -334,13 +335,16 @@ private:
// Figure out which principal to use.
nsIPrincipal* principal = mWorkerPrivate->GetPrincipal();
nsCOMPtr<nsILoadGroup> loadGroup = mWorkerPrivate->GetLoadGroup();
if (!principal) {
NS_ASSERTION(parentWorker, "Must have a principal!");
NS_ASSERTION(mIsWorkerScript, "Must have a principal for importScripts!");
principal = parentWorker->GetPrincipal();
loadGroup = parentWorker->GetLoadGroup();
}
NS_ASSERTION(principal, "This should never be null here!");
MOZ_ASSERT(NS_LoadGroupMatchesPrincipal(loadGroup, principal));
// Figure out our base URI.
nsCOMPtr<nsIURI> baseURI;
@ -368,13 +372,6 @@ private:
channel = mWorkerPrivate->ForgetWorkerChannel();
}
// All of these can potentially be null, but that should be ok. We'll either
// succeed without them or fail below.
nsCOMPtr<nsILoadGroup> loadGroup;
if (parentDoc) {
loadGroup = parentDoc->GetDocumentLoadGroup();
}
nsCOMPtr<nsIIOService> ios(do_GetIOService());
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
@ -513,6 +510,11 @@ private:
rv = ssm->GetChannelResultPrincipal(channel, getter_AddRefs(channelPrincipal));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsILoadGroup> channelLoadGroup;
rv = channel->GetLoadGroup(getter_AddRefs(channelLoadGroup));
NS_ENSURE_SUCCESS(rv, rv);
MOZ_ASSERT(channelLoadGroup);
// See if this is a resource URI. Since JSMs usually come from resource://
// URIs we're currently considering all URIs with the URI_IS_UI_RESOURCE
// flag as valid for creating privileged workers.
@ -551,7 +553,11 @@ private:
}
}
mWorkerPrivate->SetPrincipal(channelPrincipal);
// The principal can change, but it should still match the original
// load group's appId and browser element flag.
MOZ_ASSERT(NS_LoadGroupMatchesPrincipal(channelLoadGroup, channelPrincipal));
mWorkerPrivate->SetPrincipal(channelPrincipal, channelLoadGroup);
if (parent) {
// XHR Params Allowed
@ -633,6 +639,7 @@ public:
: mParentWorker(aParentWorker), mSyncLoopTarget(aSyncLoopTarget),
mScriptURL(aScriptURL), mChannel(aChannel), mResult(NS_ERROR_FAILURE)
{
MOZ_ASSERT(mParentWorker);
aParentWorker->AssertIsOnWorkerThread();
MOZ_ASSERT(aSyncLoopTarget);
}
@ -652,10 +659,13 @@ public:
// May be null.
nsCOMPtr<nsIDocument> parentDoc = mParentWorker->GetDocument();
nsCOMPtr<nsILoadGroup> loadGroup = mParentWorker->GetLoadGroup();
nsCOMPtr<nsIChannel> channel;
mResult =
scriptloader::ChannelFromScriptURLMainThread(principal, baseURI,
parentDoc, mScriptURL,
parentDoc, loadGroup,
mScriptURL,
getter_AddRefs(channel));
if (NS_SUCCEEDED(mResult)) {
channel.forget(mChannel);
@ -846,22 +856,18 @@ nsresult
ChannelFromScriptURLMainThread(nsIPrincipal* aPrincipal,
nsIURI* aBaseURI,
nsIDocument* aParentDoc,
nsILoadGroup* aLoadGroup,
const nsAString& aScriptURL,
nsIChannel** aChannel)
{
AssertIsOnMainThread();
nsCOMPtr<nsILoadGroup> loadGroup;
if (aParentDoc) {
loadGroup = aParentDoc->GetDocumentLoadGroup();
}
nsCOMPtr<nsIIOService> ios(do_GetIOService());
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
NS_ASSERTION(secMan, "This should never be null!");
return ChannelFromScriptURL(aPrincipal, aBaseURI, aParentDoc, loadGroup,
return ChannelFromScriptURL(aPrincipal, aBaseURI, aParentDoc, aLoadGroup,
ios, secMan, aScriptURL, true, aChannel);
}

View File

@ -11,6 +11,7 @@
class nsIPrincipal;
class nsIURI;
class nsIDocument;
class nsILoadGroup;
class nsString;
class nsIChannel;
@ -34,6 +35,7 @@ nsresult
ChannelFromScriptURLMainThread(nsIPrincipal* aPrincipal,
nsIURI* aBaseURI,
nsIDocument* aParentDoc,
nsILoadGroup* aLoadGroup,
const nsAString& aScriptURL,
nsIChannel** aChannel);

View File

@ -11,6 +11,7 @@
#include "jsapi.h"
#include "mozilla/LoadContext.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/DOMError.h"
#include "mozilla/dom/ErrorEvent.h"
@ -32,6 +33,10 @@
#include "WorkerRunnable.h"
#include "WorkerScope.h"
#ifdef PostMessage
#undef PostMessage
#endif
using namespace mozilla;
using namespace mozilla::dom;
@ -2098,6 +2103,17 @@ ServiceWorkerManager::CreateServiceWorker(const nsACString& aScriptSpec,
return rv;
}
// NOTE: this defaults the SW load context to:
// - private browsing = false
// - content = true
// - use remote tabs = false
// Alternatively we could persist the original load group values and use
// them here.
rv = NS_NewLoadGroup(getter_AddRefs(info.mLoadGroup), info.mPrincipal);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
AutoSafeJSContext cx;
nsRefPtr<ServiceWorker> serviceWorker;

View File

@ -38,6 +38,7 @@
#include "mozilla/ContentEvents.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/Likely.h"
#include "mozilla/LoadContext.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/BlobBinding.h"
#include "mozilla/dom/ErrorEvent.h"
@ -2624,7 +2625,7 @@ WorkerPrivateParent<Derived>::ForgetMainThreadObjects(
AssertIsOnParentThread();
MOZ_ASSERT(!mMainThreadObjectsForgotten);
static const uint32_t kDoomedCount = 7;
static const uint32_t kDoomedCount = 8;
aDoomed.SetCapacity(kDoomedCount);
@ -2635,6 +2636,7 @@ WorkerPrivateParent<Derived>::ForgetMainThreadObjects(
SwapToISupportsArray(mLoadInfo.mPrincipal, aDoomed);
SwapToISupportsArray(mLoadInfo.mChannel, aDoomed);
SwapToISupportsArray(mLoadInfo.mCSP, aDoomed);
SwapToISupportsArray(mLoadInfo.mLoadGroup, aDoomed);
// Before adding anything here update kDoomedCount above!
MOZ_ASSERT(aDoomed.Length() == kDoomedCount);
@ -3360,9 +3362,11 @@ WorkerPrivateParent<Derived>::SetBaseURI(nsIURI* aBaseURI)
template <class Derived>
void
WorkerPrivateParent<Derived>::SetPrincipal(nsIPrincipal* aPrincipal)
WorkerPrivateParent<Derived>::SetPrincipal(nsIPrincipal* aPrincipal,
nsILoadGroup* aLoadGroup)
{
AssertIsOnMainThread();
MOZ_ASSERT(NS_LoadGroupMatchesPrincipal(aLoadGroup, aPrincipal));
mLoadInfo.mPrincipal = aPrincipal;
mLoadInfo.mPrincipalIsSystem = nsContentUtils::IsSystemPrincipal(aPrincipal);
@ -3371,6 +3375,8 @@ WorkerPrivateParent<Derived>::SetPrincipal(nsIPrincipal* aPrincipal)
(appStatus == nsIPrincipal::APP_STATUS_CERTIFIED ||
appStatus == nsIPrincipal::APP_STATUS_PRIVILEGED);
mLoadInfo.mIsInCertifiedApp = (appStatus == nsIPrincipal::APP_STATUS_CERTIFIED);
mLoadInfo.mLoadGroup = aLoadGroup;
}
template <class Derived>
@ -4013,6 +4019,7 @@ WorkerPrivate::GetLoadInfo(JSContext* aCx, nsPIDOMWindow* aWindow,
NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
loadInfo.mBaseURI = document->GetDocBaseURI();
loadInfo.mLoadGroup = document->GetDocumentLoadGroup();
// Use the document's NodePrincipal as our principal if we're not being
// called from chrome.
@ -4121,8 +4128,17 @@ WorkerPrivate::GetLoadInfo(JSContext* aCx, nsPIDOMWindow* aWindow,
loadInfo.mReportCSPViolations = false;
}
if (!loadInfo.mLoadGroup) {
rv = NS_NewLoadGroup(getter_AddRefs(loadInfo.mLoadGroup),
loadInfo.mPrincipal);
NS_ENSURE_SUCCESS(rv, rv);
}
MOZ_ASSERT(NS_LoadGroupMatchesPrincipal(loadInfo.mLoadGroup,
loadInfo.mPrincipal));
rv = ChannelFromScriptURLMainThread(loadInfo.mPrincipal, loadInfo.mBaseURI,
document, aScriptURL,
document, loadInfo.mLoadGroup,
aScriptURL,
getter_AddRefs(loadInfo.mChannel));
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -9,6 +9,7 @@
#include "Workers.h"
#include "nsIContentSecurityPolicy.h"
#include "nsILoadGroup.h"
#include "nsIWorkerDebugger.h"
#include "nsPIDOMWindow.h"
@ -154,6 +155,7 @@ public:
nsCOMPtr<nsPIDOMWindow> mWindow;
nsCOMPtr<nsIContentSecurityPolicy> mCSP;
nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsCString mDomain;
@ -194,6 +196,9 @@ public:
MOZ_ASSERT(!mChannel);
aOther.mChannel.swap(mChannel);
MOZ_ASSERT(!mLoadGroup);
aOther.mLoadGroup.swap(mLoadGroup);
mDomain = aOther.mDomain;
mEvalAllowed = aOther.mEvalAllowed;
mReportCSPViolations = aOther.mReportCSPViolations;
@ -540,6 +545,13 @@ public:
return mLoadInfo.mPrincipal;
}
nsILoadGroup*
GetLoadGroup() const
{
AssertIsOnMainThread();
return mLoadInfo.mLoadGroup;
}
// This method allows the principal to be retrieved off the main thread.
// Principals are main-thread objects so the caller must ensure that all
// access occurs on the main thread.
@ -550,7 +562,7 @@ public:
}
void
SetPrincipal(nsIPrincipal* aPrincipal);
SetPrincipal(nsIPrincipal* aPrincipal, nsILoadGroup* aLoadGroup);
bool
UsesSystemPrincipal() const