Part 1: Bug 1700623 - Add storagePrincipal to WindowGlobalParent. r=nika,timhuang

We use the storage principal to look up origin records in the
background session storage manager.

Differential Revision: https://phabricator.services.mozilla.com/D111428
This commit is contained in:
Andreas Farre 2021-05-26 07:14:03 +00:00
parent 9e6185bf59
commit 1f6b2e377e
9 changed files with 88 additions and 9 deletions

View File

@ -80,6 +80,12 @@ class OriginAttributes : public dom::OriginAttributesDictionary {
mGeckoViewSessionContextId == aOther.mGeckoViewSessionContextId;
}
[[nodiscard]] bool EqualsIgnoringPartitionKey(
const OriginAttributes& aOther) const {
return EqualsIgnoringFPD(aOther) &&
mFirstPartyDomain == aOther.mFirstPartyDomain;
}
// Serializes/Deserializes non-default values into the suffix format, i.e.
// |!key1=value1&key2=value2|. If there are no non-default attributes, this
// returns an empty string.

View File

@ -7570,6 +7570,14 @@ void nsGlobalWindowInner::StorageAccessPermissionGranted() {
// Reset the active storage principal
if (mDoc) {
mDoc->ClearActiveStoragePrincipal();
if (mWindowGlobalChild) {
// XXX(farre): This is a bit backwards, but clearing the storage
// principal might make us end up with a new effective storage
// principal on the child side than on the parent side, which
// means that we need to sync it. See bug 1705359.
mWindowGlobalChild->SetDocumentPrincipal(
mDoc->NodePrincipal(), mDoc->EffectiveStoragePrincipal());
}
}
}

View File

@ -118,7 +118,8 @@ parent:
// principals collected. In order to be compatible with that API, we need to
// update the document's principal. This is only allowed if the principals are
// `equals` to each other.
async UpdateDocumentPrincipal(nsIPrincipal aPrincipal);
async UpdateDocumentPrincipal(nsIPrincipal aPrincipal,
nsIPrincipal aStoragePrincipal);
// Update document's `documentHasLoaded` bit in this WindowGlobal.
async UpdateDocumentHasLoaded(bool aDocumentHasLoaded);

View File

@ -66,6 +66,7 @@ WindowGlobalInit WindowGlobalActor::AboutBlankInitializer(
nsContentUtils::GenerateWindowId());
init.principal() = aPrincipal;
init.storagePrincipal() = aPrincipal;
Unused << NS_NewURI(getter_AddRefs(init.documentURI()), "about:blank");
return init;
@ -78,6 +79,7 @@ WindowGlobalInit WindowGlobalActor::WindowInitializer(
aWindow->GetOuterWindow()->WindowID());
init.principal() = aWindow->GetPrincipal();
init.storagePrincipal() = aWindow->GetEffectiveStoragePrincipal();
init.documentURI() = aWindow->GetDocumentURI();
Document* doc = aWindow->GetDocument();

View File

@ -183,7 +183,8 @@ void WindowGlobalChild::OnNewDocument(Document* aDocument) {
// FIXME: Perhaps these should be combined into a smaller number of messages?
SetDocumentURI(aDocument->GetDocumentURI());
SetDocumentPrincipal(aDocument->NodePrincipal());
SetDocumentPrincipal(aDocument->NodePrincipal(),
aDocument->EffectiveStoragePrincipal());
nsCOMPtr<nsITransportSecurityInfo> securityInfo;
if (nsCOMPtr<nsIChannel> channel = aDocument->GetChannel()) {
@ -611,10 +612,12 @@ void WindowGlobalChild::SetDocumentURI(nsIURI* aDocumentURI) {
}
void WindowGlobalChild::SetDocumentPrincipal(
nsIPrincipal* aNewDocumentPrincipal) {
nsIPrincipal* aNewDocumentPrincipal,
nsIPrincipal* aNewDocumentStoragePrincipal) {
MOZ_ASSERT(mDocumentPrincipal->Equals(aNewDocumentPrincipal));
mDocumentPrincipal = aNewDocumentPrincipal;
SendUpdateDocumentPrincipal(aNewDocumentPrincipal);
SendUpdateDocumentPrincipal(aNewDocumentPrincipal,
aNewDocumentStoragePrincipal);
}
const nsACString& WindowGlobalChild::GetRemoteType() {

View File

@ -68,7 +68,8 @@ class WindowGlobalChild final : public WindowGlobalActor,
void SetDocumentURI(nsIURI* aDocumentURI);
// See the corresponding comment for `UpdateDocumentPrincipal` in
// PWindowGlobal on why and when this is allowed
void SetDocumentPrincipal(nsIPrincipal* aNewDocumentPrincipal);
void SetDocumentPrincipal(nsIPrincipal* aNewDocumentPrincipal,
nsIPrincipal* aNewDocumentStoragePrincipal);
nsIPrincipal* DocumentPrincipal() { return mDocumentPrincipal; }

View File

@ -116,6 +116,10 @@ already_AddRefed<WindowGlobalParent> WindowGlobalParent::CreateDisconnected(
getter_AddRefs(wgp->mCookieJarSettings));
MOZ_RELEASE_ASSERT(wgp->mDocumentPrincipal, "Must have a valid principal");
nsresult rv = wgp->SetDocumentStoragePrincipal(aInit.storagePrincipal());
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv),
"Must succeed in setting storage principal");
return wgp.forget();
}
@ -370,14 +374,55 @@ IPCResult WindowGlobalParent::RecvUpdateDocumentURI(nsIURI* aURI) {
return IPC_OK();
}
nsresult WindowGlobalParent::SetDocumentStoragePrincipal(
nsIPrincipal* aNewDocumentStoragePrincipal) {
if (mDocumentPrincipal->Equals(aNewDocumentStoragePrincipal)) {
mDocumentStoragePrincipal = mDocumentPrincipal;
return NS_OK;
}
// Compare originNoSuffix to ensure it's equal.
nsCString noSuffix;
nsresult rv = mDocumentPrincipal->GetOriginNoSuffix(noSuffix);
if (NS_FAILED(rv)) {
return rv;
}
nsCString storageNoSuffix;
rv = aNewDocumentStoragePrincipal->GetOriginNoSuffix(storageNoSuffix);
if (NS_FAILED(rv)) {
return rv;
}
if (noSuffix != storageNoSuffix) {
return NS_ERROR_FAILURE;
}
if (!mDocumentPrincipal->OriginAttributesRef().EqualsIgnoringPartitionKey(
aNewDocumentStoragePrincipal->OriginAttributesRef())) {
return NS_ERROR_FAILURE;
}
mDocumentStoragePrincipal = aNewDocumentStoragePrincipal;
return NS_OK;
}
IPCResult WindowGlobalParent::RecvUpdateDocumentPrincipal(
nsIPrincipal* aNewDocumentPrincipal) {
nsIPrincipal* aNewDocumentPrincipal,
nsIPrincipal* aNewDocumentStoragePrincipal) {
if (!mDocumentPrincipal->Equals(aNewDocumentPrincipal)) {
return IPC_FAIL(this,
"Trying to reuse WindowGlobalParent but the principal of "
"the new document does not match the old one");
}
mDocumentPrincipal = aNewDocumentPrincipal;
if (NS_FAILED(SetDocumentStoragePrincipal(aNewDocumentStoragePrincipal))) {
return IPC_FAIL(this,
"Trying to reuse WindowGlobalParent but the principal of "
"the new document does not match the storage principal");
}
return IPC_OK();
}
mozilla::ipc::IPCResult WindowGlobalParent::RecvUpdateDocumentTitle(

View File

@ -110,6 +110,8 @@ class WindowGlobalParent final : public WindowContext,
// |document.domain|.
nsIPrincipal* DocumentPrincipal() { return mDocumentPrincipal; }
nsIPrincipal* DocumentStoragePrincipal() { return mDocumentStoragePrincipal; }
// The BrowsingContext which this WindowGlobal has been loaded into.
// FIXME: It's quite awkward that this method has a slightly different name
// than the one on WindowContext.
@ -232,7 +234,8 @@ class WindowGlobalParent final : public WindowContext,
mozilla::ipc::IPCResult RecvInternalLoad(nsDocShellLoadState* aLoadState);
mozilla::ipc::IPCResult RecvUpdateDocumentURI(nsIURI* aURI);
mozilla::ipc::IPCResult RecvUpdateDocumentPrincipal(
nsIPrincipal* aNewDocumentPrincipal);
nsIPrincipal* aNewDocumentPrincipal,
nsIPrincipal* aNewDocumentStoragePrincipal);
mozilla::ipc::IPCResult RecvUpdateDocumentHasLoaded(bool aDocumentHasLoaded);
mozilla::ipc::IPCResult RecvUpdateDocumentHasUserInteracted(
bool aDocumentHasUserInteracted);
@ -305,11 +308,20 @@ class WindowGlobalParent final : public WindowContext,
nsresult ResetSessionStore(uint32_t aEpoch);
// NOTE: This document principal doesn't reflect possible |document.domain|
// mutations which may have been made in the actual document.
// Returns failure if the new storage principal cannot be validated
// against the current document principle.
nsresult SetDocumentStoragePrincipal(
nsIPrincipal* aNewDocumentStoragePrincipal);
// NOTE: Neither this document principal nor the document storage
// principal doesn't reflect possible |document.domain| mutations
// which may have been made in the actual document.
nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
nsCOMPtr<nsIPrincipal> mDocumentStoragePrincipal;
// The principal to use for the content blocking allow list.
nsCOMPtr<nsIPrincipal> mDocContentBlockingAllowListPrincipal;
nsCOMPtr<nsIURI> mDocumentURI;
Maybe<nsString> mDocumentTitle;

View File

@ -24,6 +24,7 @@ struct WindowGlobalInit
// Private fields only shared with the parent process.
nsIPrincipal principal;
nsIPrincipal storagePrincipal;
nsIURI documentURI;
bool blockAllMixedContent;