Bug 1536411 - StoragePrincipal - part 2 - Worker and StoragePrincipal, r=Ehsan

Differential Revision: https://phabricator.services.mozilla.com/D24026

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Andrea Marchesini 2019-04-11 16:27:30 +00:00
Родитель 5cfeeda19e
Коммит dfe371cba0
9 изменённых файлов: 120 добавлений и 34 удалений

Просмотреть файл

@ -1751,7 +1751,8 @@ nsresult ServiceWorkerPrivate::SpawnWorkerIfNeeded(WakeUpReason aWhy,
WorkerPrivate::OverrideLoadInfoLoadGroup(info, info.mPrincipal);
rv = info.SetPrincipalOnMainThread(info.mPrincipal, info.mLoadGroup);
rv = info.SetPrincipalsOnMainThread(info.mPrincipal, info.mStoragePrincipal,
info.mLoadGroup);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}

Просмотреть файл

@ -1188,7 +1188,7 @@ class ScriptLoaderRunnable final : public nsIRunnable, public nsINamed {
// URL must exactly match the final worker script URL in order to
// properly set the referrer header on fetch/xhr requests. If bug 1340694
// is ever fixed this can be removed.
rv = mWorkerPrivate->SetPrincipalFromChannel(channel);
rv = mWorkerPrivate->SetPrincipalsFromChannel(channel);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIContentSecurityPolicy> csp = mWorkerPrivate->GetCSP();
@ -1296,8 +1296,9 @@ class ScriptLoaderRunnable final : public nsIRunnable, public nsINamed {
// referrer logic depends on the WorkerPrivate principal having a URL
// that matches the worker script URL. If bug 1340694 is ever fixed
// this can be removed.
rv = mWorkerPrivate->SetPrincipalOnMainThread(responsePrincipal,
loadGroup);
// TODO: storagePrincipal here?
rv = mWorkerPrivate->SetPrincipalsOnMainThread(
responsePrincipal, responsePrincipal, loadGroup);
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
rv = mWorkerPrivate->SetCSPFromHeaderValues(aCSPHeaderValue,
@ -1841,7 +1842,7 @@ class ChannelGetterRunnable final : public WorkerMainThreadRunnable {
getter_AddRefs(channel));
NS_ENSURE_SUCCESS(mResult, true);
mResult = mLoadInfo.SetPrincipalFromChannel(channel);
mResult = mLoadInfo.SetPrincipalsFromChannel(channel);
NS_ENSURE_SUCCESS(mResult, true);
mLoadInfo.mChannel = channel.forget();

Просмотреть файл

@ -92,12 +92,14 @@ WorkerLoadInfoData::WorkerLoadInfoData()
mServiceWorkersTestingInWindow(false),
mSecureContext(eNotSet) {}
nsresult WorkerLoadInfo::SetPrincipalOnMainThread(nsIPrincipal* aPrincipal,
nsILoadGroup* aLoadGroup) {
nsresult WorkerLoadInfo::SetPrincipalsOnMainThread(
nsIPrincipal* aPrincipal, nsIPrincipal* aStoragePrincipal,
nsILoadGroup* aLoadGroup) {
AssertIsOnMainThread();
MOZ_ASSERT(NS_LoadGroupMatchesPrincipal(aLoadGroup, aPrincipal));
mPrincipal = aPrincipal;
mStoragePrincipal = aStoragePrincipal;
mPrincipalIsSystem = nsContentUtils::IsSystemPrincipal(aPrincipal);
nsresult rv = aPrincipal->GetCsp(getter_AddRefs(mCSP));
@ -113,23 +115,33 @@ nsresult WorkerLoadInfo::SetPrincipalOnMainThread(nsIPrincipal* aPrincipal,
mLoadGroup = aLoadGroup;
mPrincipalInfo = new PrincipalInfo();
mStoragePrincipalInfo = new PrincipalInfo();
mOriginAttributes = nsContentUtils::GetOriginAttributes(aLoadGroup);
rv = PrincipalToPrincipalInfo(aPrincipal, mPrincipalInfo);
NS_ENSURE_SUCCESS(rv, rv);
if (aPrincipal->Equals(aStoragePrincipal)) {
*mStoragePrincipalInfo = *mPrincipalInfo;
} else {
mStoragePrincipalInfo = new PrincipalInfo();
rv = PrincipalToPrincipalInfo(aStoragePrincipal, mStoragePrincipalInfo);
NS_ENSURE_SUCCESS(rv, rv);
}
rv = nsContentUtils::GetUTFOrigin(aPrincipal, mOrigin);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsresult WorkerLoadInfo::GetPrincipalAndLoadGroupFromChannel(
nsresult WorkerLoadInfo::GetPrincipalsAndLoadGroupFromChannel(
nsIChannel* aChannel, nsIPrincipal** aPrincipalOut,
nsILoadGroup** aLoadGroupOut) {
nsIPrincipal** aStoragePrincipalOut, nsILoadGroup** aLoadGroupOut) {
AssertIsOnMainThread();
MOZ_DIAGNOSTIC_ASSERT(aChannel);
MOZ_DIAGNOSTIC_ASSERT(aPrincipalOut);
MOZ_DIAGNOSTIC_ASSERT(aStoragePrincipalOut);
MOZ_DIAGNOSTIC_ASSERT(aLoadGroupOut);
// Initial triggering principal should be set
@ -143,6 +155,11 @@ nsresult WorkerLoadInfo::GetPrincipalAndLoadGroupFromChannel(
aChannel, getter_AddRefs(channelPrincipal));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> channelStoragePrincipal;
rv = ssm->GetChannelResultStoragePrincipal(
aChannel, getter_AddRefs(channelStoragePrincipal));
NS_ENSURE_SUCCESS(rv, rv);
// Every time we call GetChannelResultPrincipal() it will return a different
// null principal for a data URL. We don't want to change the worker's
// principal again, though. Instead just keep the original null principal we
@ -154,6 +171,7 @@ nsresult WorkerLoadInfo::GetPrincipalAndLoadGroupFromChannel(
if (mPrincipal && mPrincipal->GetIsNullPrincipal() &&
channelPrincipal->GetIsNullPrincipal()) {
channelPrincipal = mPrincipal;
channelStoragePrincipal = mPrincipal;
}
nsCOMPtr<nsILoadGroup> channelLoadGroup;
@ -186,6 +204,7 @@ nsresult WorkerLoadInfo::GetPrincipalAndLoadGroupFromChannel(
// Assign the system principal to the resource:// worker only if it
// was loaded from code using the system principal.
channelPrincipal = mLoadingPrincipal;
channelStoragePrincipal = mLoadingPrincipal;
} else {
return NS_ERROR_DOM_BAD_URI;
}
@ -197,30 +216,35 @@ nsresult WorkerLoadInfo::GetPrincipalAndLoadGroupFromChannel(
MOZ_ASSERT(NS_LoadGroupMatchesPrincipal(channelLoadGroup, channelPrincipal));
channelPrincipal.forget(aPrincipalOut);
channelStoragePrincipal.forget(aStoragePrincipalOut);
channelLoadGroup.forget(aLoadGroupOut);
return NS_OK;
}
nsresult WorkerLoadInfo::SetPrincipalFromChannel(nsIChannel* aChannel) {
nsresult WorkerLoadInfo::SetPrincipalsFromChannel(nsIChannel* aChannel) {
AssertIsOnMainThread();
nsCOMPtr<nsIPrincipal> principal;
nsCOMPtr<nsIPrincipal> storagePrincipal;
nsCOMPtr<nsILoadGroup> loadGroup;
nsresult rv = GetPrincipalAndLoadGroupFromChannel(
aChannel, getter_AddRefs(principal), getter_AddRefs(loadGroup));
nsresult rv = GetPrincipalsAndLoadGroupFromChannel(
aChannel, getter_AddRefs(principal), getter_AddRefs(storagePrincipal),
getter_AddRefs(loadGroup));
NS_ENSURE_SUCCESS(rv, rv);
return SetPrincipalOnMainThread(principal, loadGroup);
return SetPrincipalsOnMainThread(principal, storagePrincipal, loadGroup);
}
bool WorkerLoadInfo::FinalChannelPrincipalIsValid(nsIChannel* aChannel) {
AssertIsOnMainThread();
nsCOMPtr<nsIPrincipal> principal;
nsCOMPtr<nsIPrincipal> storagePrincipal;
nsCOMPtr<nsILoadGroup> loadGroup;
nsresult rv = GetPrincipalAndLoadGroupFromChannel(
aChannel, getter_AddRefs(principal), getter_AddRefs(loadGroup));
nsresult rv = GetPrincipalsAndLoadGroupFromChannel(
aChannel, getter_AddRefs(principal), getter_AddRefs(storagePrincipal),
getter_AddRefs(loadGroup));
NS_ENSURE_SUCCESS(rv, false);
// Verify that the channel is still a null principal. We don't care
@ -243,7 +267,10 @@ bool WorkerLoadInfo::FinalChannelPrincipalIsValid(nsIChannel* aChannel) {
bool WorkerLoadInfo::PrincipalIsValid() const {
return mPrincipal && mPrincipalInfo &&
mPrincipalInfo->type() != PrincipalInfo::T__None &&
mPrincipalInfo->type() <= PrincipalInfo::T__Last;
mPrincipalInfo->type() <= PrincipalInfo::T__Last &&
mStoragePrincipal && mStoragePrincipalInfo &&
mStoragePrincipalInfo->type() != PrincipalInfo::T__None &&
mStoragePrincipalInfo->type() <= PrincipalInfo::T__Last;
}
bool WorkerLoadInfo::PrincipalURIMatchesScriptURL() {
@ -312,7 +339,7 @@ bool WorkerLoadInfo::ProxyReleaseMainThreadObjects(
bool WorkerLoadInfo::ProxyReleaseMainThreadObjects(
WorkerPrivate* aWorkerPrivate, nsCOMPtr<nsILoadGroup>& aLoadGroupToCancel) {
static const uint32_t kDoomedCount = 10;
static const uint32_t kDoomedCount = 11;
nsTArray<nsCOMPtr<nsISupports>> doomed(kDoomedCount);
SwapToISupportsArray(mWindow, doomed);
@ -320,6 +347,7 @@ bool WorkerLoadInfo::ProxyReleaseMainThreadObjects(
SwapToISupportsArray(mBaseURI, doomed);
SwapToISupportsArray(mResolvedScriptURI, doomed);
SwapToISupportsArray(mPrincipal, doomed);
SwapToISupportsArray(mStoragePrincipal, doomed);
SwapToISupportsArray(mLoadingPrincipal, doomed);
SwapToISupportsArray(mChannel, doomed);
SwapToISupportsArray(mCSP, doomed);

Просмотреть файл

@ -50,6 +50,7 @@ struct WorkerLoadInfoData {
// If we load a data: URL, mPrincipal will be a null principal.
nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCOMPtr<nsIPrincipal> mStoragePrincipal;
// Taken from the parent context.
nsCOMPtr<nsICookieSettings> mCookieSettings;
@ -91,6 +92,7 @@ struct WorkerLoadInfoData {
RefPtr<InterfaceRequestor> mInterfaceRequestor;
nsAutoPtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
nsAutoPtr<mozilla::ipc::PrincipalInfo> mStoragePrincipalInfo;
nsCString mDomain;
nsString mOrigin; // Derived from mPrincipal; can be used on worker thread.
@ -136,14 +138,15 @@ struct WorkerLoadInfo : WorkerLoadInfoData {
WorkerLoadInfo& operator=(WorkerLoadInfo&& aOther) = default;
nsresult SetPrincipalOnMainThread(nsIPrincipal* aPrincipal,
nsILoadGroup* aLoadGroup);
nsresult SetPrincipalsOnMainThread(nsIPrincipal* aPrincipal,
nsIPrincipal* aStoragePrincipal,
nsILoadGroup* aLoadGroup);
nsresult GetPrincipalAndLoadGroupFromChannel(nsIChannel* aChannel,
nsIPrincipal** aPrincipalOut,
nsILoadGroup** aLoadGroupOut);
nsresult GetPrincipalsAndLoadGroupFromChannel(
nsIChannel* aChannel, nsIPrincipal** aPrincipalOut,
nsIPrincipal** aStoragePrincipalOut, nsILoadGroup** aLoadGroupOut);
nsresult SetPrincipalFromChannel(nsIChannel* aChannel);
nsresult SetPrincipalsFromChannel(nsIChannel* aChannel);
bool FinalChannelPrincipalIsValid(nsIChannel* aChannel);

Просмотреть файл

@ -1932,13 +1932,15 @@ void WorkerPrivate::SetBaseURI(nsIURI* aBaseURI) {
nsContentUtils::GetUTFOrigin(aBaseURI, mLocationInfo.mOrigin);
}
nsresult WorkerPrivate::SetPrincipalOnMainThread(nsIPrincipal* aPrincipal,
nsILoadGroup* aLoadGroup) {
return mLoadInfo.SetPrincipalOnMainThread(aPrincipal, aLoadGroup);
nsresult WorkerPrivate::SetPrincipalsOnMainThread(
nsIPrincipal* aPrincipal, nsIPrincipal* aStoragePrincipal,
nsILoadGroup* aLoadGroup) {
return mLoadInfo.SetPrincipalsOnMainThread(aPrincipal, aStoragePrincipal,
aLoadGroup);
}
nsresult WorkerPrivate::SetPrincipalFromChannel(nsIChannel* aChannel) {
return mLoadInfo.SetPrincipalFromChannel(aChannel);
nsresult WorkerPrivate::SetPrincipalsFromChannel(nsIChannel* aChannel) {
return mLoadInfo.SetPrincipalsFromChannel(aChannel);
}
bool WorkerPrivate::FinalChannelPrincipalIsValid(nsIChannel* aChannel) {
@ -2562,7 +2564,7 @@ nsresult WorkerPrivate::GetLoadInfo(JSContext* aCx, nsPIDOMWindowInner* aWindow,
getter_AddRefs(loadInfo.mResolvedScriptURI));
NS_ENSURE_SUCCESS(rv, rv);
rv = loadInfo.SetPrincipalFromChannel(loadInfo.mChannel);
rv = loadInfo.SetPrincipalsFromChannel(loadInfo.mChannel);
NS_ENSURE_SUCCESS(rv, rv);
}

Просмотреть файл

@ -662,6 +662,11 @@ class WorkerPrivate : public RelativeTimeline {
return mLoadInfo.mPrincipal;
}
nsIPrincipal* GetEffectiveStoragePrincipal() const {
AssertIsOnMainThread();
return mLoadInfo.mStoragePrincipal;
}
nsIPrincipal* GetLoadingPrincipal() const {
AssertIsOnMainThread();
return mLoadInfo.mLoadingPrincipal;
@ -680,6 +685,10 @@ class WorkerPrivate : public RelativeTimeline {
return *mLoadInfo.mPrincipalInfo;
}
const mozilla::ipc::PrincipalInfo& GetEffectiveStoragePrincipalInfo() const {
return *mLoadInfo.mStoragePrincipalInfo;
}
already_AddRefed<nsIChannel> ForgetWorkerChannel() {
AssertIsOnMainThread();
return mLoadInfo.mChannel.forget();
@ -788,10 +797,11 @@ class WorkerPrivate : public RelativeTimeline {
void CycleCollect(bool aDummy);
nsresult SetPrincipalOnMainThread(nsIPrincipal* aPrincipal,
nsILoadGroup* aLoadGroup);
nsresult SetPrincipalsOnMainThread(nsIPrincipal* aPrincipal,
nsIPrincipal* aStoragePrincipal,
nsILoadGroup* aLoadGroup);
nsresult SetPrincipalFromChannel(nsIChannel* aChannel);
nsresult SetPrincipalsFromChannel(nsIChannel* aChannel);
bool FinalChannelPrincipalIsValid(nsIChannel* aChannel);

Просмотреть файл

@ -262,14 +262,29 @@ nsresult RemoteWorkerChild::ExecWorkerOnMainThread(
return rv;
}
nsCOMPtr<nsIPrincipal> storagePrincipal =
PrincipalInfoToPrincipal(aData.storagePrincipalInfo(), &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = PopulatePrincipalContentSecurityPolicy(
storagePrincipal, aData.storagePrincipalCsp(),
aData.storagePrincipalPreloadCsp());
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
WorkerLoadInfo info;
info.mBaseURI = DeserializeURI(aData.baseScriptURL());
info.mResolvedScriptURI = DeserializeURI(aData.resolvedScriptURL());
info.mPrincipalInfo = new PrincipalInfo(aData.principalInfo());
info.mStoragePrincipalInfo = new PrincipalInfo(aData.storagePrincipalInfo());
info.mDomain = aData.domain();
info.mPrincipal = principal;
info.mStoragePrincipal = storagePrincipal;
info.mLoadingPrincipal = loadingPrincipal;
info.mStorageAccess = aData.storageAccess();
info.mOriginAttributes =
@ -290,7 +305,8 @@ nsresult RemoteWorkerChild::ExecWorkerOnMainThread(
new SharedWorkerInterfaceRequestor();
info.mInterfaceRequestor->SetOuterRequestor(requestor);
rv = info.SetPrincipalOnMainThread(info.mPrincipal, info.mLoadGroup);
rv = info.SetPrincipalsOnMainThread(info.mPrincipal, info.mStoragePrincipal,
info.mLoadGroup);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}

Просмотреть файл

@ -38,6 +38,10 @@ struct RemoteWorkerData
ContentSecurityPolicy[] principalCsp;
ContentSecurityPolicy[] principalPreloadCsp;
PrincipalInfo storagePrincipalInfo;
ContentSecurityPolicy[] storagePrincipalCsp;
ContentSecurityPolicy[] storagePrincipalPreloadCsp;
nsCString domain;
bool isSecureContext;

Просмотреть файл

@ -176,6 +176,26 @@ already_AddRefed<SharedWorker> SharedWorker::Constructor(
return nullptr;
}
PrincipalInfo storagePrincipalInfo;
if (loadInfo.mPrincipal->Equals(loadInfo.mStoragePrincipal)) {
storagePrincipalInfo = principalInfo;
} else {
aRv = PrincipalToPrincipalInfo(loadInfo.mStoragePrincipal,
&storagePrincipalInfo);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
}
nsTArray<ContentSecurityPolicy> storagePrincipalCSP;
nsTArray<ContentSecurityPolicy> storagePrincipalPreloadCSP;
aRv = PopulateContentSecurityPolicyArray(loadInfo.mStoragePrincipal,
storagePrincipalCSP,
storagePrincipalPreloadCSP);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
// We don't actually care about this MessageChannel, but we use it to 'steal'
// its 2 connected ports.
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(window);
@ -207,7 +227,8 @@ already_AddRefed<SharedWorker> SharedWorker::Constructor(
RemoteWorkerData remoteWorkerData(
nsString(aScriptURL), baseURL, resolvedScriptURL, name,
loadingPrincipalInfo, loadingPrincipalCSP, loadingPrincipalPreloadCSP,
principalInfo, principalCSP, principalPreloadCSP, loadInfo.mDomain,
principalInfo, principalCSP, principalPreloadCSP, storagePrincipalInfo,
storagePrincipalCSP, storagePrincipalPreloadCSP, loadInfo.mDomain,
isSecureContext, ipcClientInfo, storageAllowed, true /* sharedWorker */);
PSharedWorkerChild* pActor = actorChild->SendPSharedWorkerConstructor(