Bug 1586830 - Part 1: Ensure IsInitialDocument is set earlier and consistently on WindowGlobalParent, r=smaug

This makes sure to clear and set the value more consistently when replacing
documents within a WindowGlobal, and makes sure to include the relevant flag in
the initializer.

In addition, the place where the flag is set is moved ahead to happen before
the call to `Embed` so that the information is ready before the window is
created.

Differential Revision: https://phabricator.services.mozilla.com/D119815
This commit is contained in:
Nika Layzell 2021-07-14 15:51:20 +00:00
parent 0bf5838230
commit fdaf413fa3
10 changed files with 53 additions and 31 deletions

View File

@ -6428,17 +6428,17 @@ nsresult nsDocShell::EnsureContentViewer() {
}
nsresult rv = CreateAboutBlankContentViewer(
principal, partitionedPrincipal, cspToInheritForAboutBlank, baseURI);
principal, partitionedPrincipal, cspToInheritForAboutBlank, baseURI,
/* aIsInitialDocument */ true);
NS_ENSURE_STATE(mContentViewer);
if (NS_SUCCEEDED(rv)) {
RefPtr<Document> doc(GetDocument());
NS_ASSERTION(doc,
"Should have doc if CreateAboutBlankContentViewer "
"succeeded!");
doc->SetIsInitialDocument(true);
MOZ_ASSERT(doc,
"Should have doc if CreateAboutBlankContentViewer "
"succeeded!");
MOZ_ASSERT(doc->IsInitialDocument(), "Document should be initial document");
// Documents created using EnsureContentViewer may be transient
// placeholders created by framescripts before content has a
@ -6455,7 +6455,7 @@ nsresult nsDocShell::EnsureContentViewer() {
nsresult nsDocShell::CreateAboutBlankContentViewer(
nsIPrincipal* aPrincipal, nsIPrincipal* aPartitionedPrincipal,
nsIContentSecurityPolicy* aCSP, nsIURI* aBaseURI,
nsIContentSecurityPolicy* aCSP, nsIURI* aBaseURI, bool aIsInitialDocument,
const Maybe<nsILoadInfo::CrossOriginEmbedderPolicy>& aCOEP,
bool aTryToSaveOldPresentation, bool aCheckPermitUnload,
WindowGlobalChild* aActor) {
@ -6593,6 +6593,8 @@ nsresult nsDocShell::CreateAboutBlankContentViewer(
blankDoc->SetCsp(cspToInherit);
}
blankDoc->SetIsInitialDocument(aIsInitialDocument);
blankDoc->SetEmbedderPolicy(aCOEP);
// Hack: set the base URI manually, since this document never
@ -6640,7 +6642,7 @@ nsDocShell::CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal,
nsIPrincipal* aPartitionedPrincipal,
nsIContentSecurityPolicy* aCSP) {
return CreateAboutBlankContentViewer(aPrincipal, aPartitionedPrincipal, aCSP,
nullptr);
nullptr, /* aIsInitialDocument */ false);
}
nsresult nsDocShell::CreateContentViewerForActor(
@ -6648,13 +6650,16 @@ nsresult nsDocShell::CreateContentViewerForActor(
MOZ_ASSERT(aWindowActor);
// FIXME: WindowGlobalChild should provide the PartitionedPrincipal.
// FIXME: We may want to support non-initial documents here.
nsresult rv = CreateAboutBlankContentViewer(
aWindowActor->DocumentPrincipal(), aWindowActor->DocumentPrincipal(),
/* aCsp */ nullptr,
/* aBaseURI */ nullptr,
/* aIsInitialDocument */ true,
/* aCOEP */ Nothing(),
/* aTryToSaveOldPresentation */ true,
/* aCheckPermitUnload */ true, aWindowActor);
#ifdef DEBUG
if (NS_SUCCEEDED(rv)) {
RefPtr<Document> doc(GetDocument());
MOZ_ASSERT(
@ -6662,10 +6667,10 @@ nsresult nsDocShell::CreateContentViewerForActor(
"Should have a document if CreateAboutBlankContentViewer succeeded");
MOZ_ASSERT(doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal(),
"New document should be in the same global as our actor");
// FIXME: We may want to support non-initial documents here.
doc->SetIsInitialDocument(true);
MOZ_ASSERT(doc->IsInitialDocument(),
"New document should be an initial document");
}
#endif
return rv;
}
@ -9186,7 +9191,8 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
}
// clear the decks to prevent context bleed-through (bug 298255)
rv = CreateAboutBlankContentViewer(nullptr, nullptr, nullptr, nullptr);
rv = CreateAboutBlankContentViewer(nullptr, nullptr, nullptr, nullptr,
/* aIsInitialDocument */ false);
if (NS_FAILED(rv)) {
return NS_ERROR_FAILURE;
}
@ -11719,7 +11725,7 @@ nsresult nsDocShell::LoadHistoryEntry(nsDocShellLoadState* aLoadState,
rv = CreateAboutBlankContentViewer(
aLoadState->PrincipalToInherit(),
aLoadState->PartitionedPrincipalToInherit(), nullptr, nullptr,
Nothing(), !aReloadingActiveEntry);
/* aIsInitialDocument */ false, Nothing(), !aReloadingActiveEntry);
if (NS_FAILED(rv)) {
// The creation of the intermittent about:blank content

View File

@ -522,6 +522,7 @@ class nsDocShell final : public nsDocLoader,
nsresult aStatusCode) override;
private: // member functions
friend class nsAppShellService;
friend class nsDSURIContentListener;
friend class FramingChecker;
friend class OnLinkClickEvent;
@ -588,7 +589,7 @@ class nsDocShell final : public nsDocLoader,
// aCSP, if any, will be used for the new about:blank load.
nsresult CreateAboutBlankContentViewer(
nsIPrincipal* aPrincipal, nsIPrincipal* aPartitionedPrincipal,
nsIContentSecurityPolicy* aCSP, nsIURI* aBaseURI,
nsIContentSecurityPolicy* aCSP, nsIURI* aBaseURI, bool aIsInitialDocument,
const mozilla::Maybe<nsILoadInfo::CrossOriginEmbedderPolicy>& aCOEP =
mozilla::Nothing(),
bool aTryToSaveOldPresentation = true, bool aCheckPermitUnload = true,

View File

@ -1791,10 +1791,12 @@ void nsGlobalWindowOuter::SetInitialPrincipalToSubject(
// the new window finishes navigating and gets a real storage principal.
nsDocShell::Cast(GetDocShell())
->CreateAboutBlankContentViewer(newWindowPrincipal, newWindowPrincipal,
aCSP, nullptr, aCOEP);
aCSP, nullptr,
/* aIsInitialDocument */ true, aCOEP);
if (mDoc) {
mDoc->SetIsInitialDocument(true);
MOZ_ASSERT(mDoc->IsInitialDocument(),
"document should be initial document");
}
RefPtr<PresShell> presShell = GetDocShell()->GetPresShell();

View File

@ -1742,6 +1742,13 @@ mozilla::ipc::IPCResult ContentChild::RecvConstructBrowser(
return IPC_FAIL(this, "Null or discarded initial BrowsingContext");
}
if (!aWindowInit.isInitialDocument() ||
!NS_IsAboutBlank(aWindowInit.documentURI())) {
return IPC_FAIL(this,
"Logic in CreateContentViewerForActor currently requires "
"actors to be initial about:blank documents");
}
// We'll happily accept any kind of IPCTabContext here; we don't need to
// check that it's of a certain type for security purposes, because we
// believe whatever the parent process tells us.

View File

@ -69,6 +69,7 @@ WindowGlobalInit WindowGlobalActor::AboutBlankInitializer(
init.principal() = aPrincipal;
init.storagePrincipal() = aPrincipal;
Unused << NS_NewURI(getter_AddRefs(init.documentURI()), "about:blank");
init.isInitialDocument() = true;
return init;
}
@ -85,6 +86,7 @@ WindowGlobalInit WindowGlobalActor::WindowInitializer(
Document* doc = aWindow->GetDocument();
init.isInitialDocument() = doc->IsInitialDocument();
init.blockAllMixedContent() = doc->GetBlockAllMixedContent(false);
init.upgradeInsecureRequests() = doc->GetUpgradeInsecureRequests(false);
init.sandboxFlags() = doc->GetSandboxFlags();

View File

@ -182,6 +182,7 @@ void WindowGlobalChild::OnNewDocument(Document* aDocument) {
// added here should also be added to WindowGlobalActor::WindowInitializer.
// FIXME: Perhaps these should be combined into a smaller number of messages?
SendSetIsInitialDocument(aDocument->IsInitialDocument());
SetDocumentURI(aDocument->GetDocumentURI());
SetDocumentPrincipal(aDocument->NodePrincipal(),
aDocument->EffectiveStoragePrincipal());

View File

@ -108,6 +108,7 @@ already_AddRefed<WindowGlobalParent> WindowGlobalParent::CreateDisconnected(
aInit.context().mOuterWindowId, std::move(fields));
wgp->mDocumentPrincipal = aInit.principal();
wgp->mDocumentURI = aInit.documentURI();
wgp->mIsInitialDocument = aInit.isInitialDocument();
wgp->mBlockAllMixedContent = aInit.blockAllMixedContent();
wgp->mUpgradeInsecureRequests = aInit.upgradeInsecureRequests();
wgp->mSandboxFlags = aInit.sandboxFlags();

View File

@ -27,6 +27,7 @@ struct WindowGlobalInit
nsIPrincipal storagePrincipal;
nsIURI documentURI;
bool isInitialDocument;
bool blockAllMixedContent;
bool upgradeInsecureRequests;
uint32_t sandboxFlags;

View File

@ -1025,22 +1025,21 @@ nsresult nsWindowWatcher::OpenWindowInternal(
RefPtr<nsGlobalWindowOuter> win(
nsGlobalWindowOuter::Cast(newBC->GetDOMWindow()));
if (win) {
if (windowIsNew) {
#ifdef DEBUG
// Assert that we're not loading things right now. If we are, when
// that load completes it will clobber whatever principals we set up
// on this new window!
nsCOMPtr<nsIChannel> chan;
newDocShell->GetDocumentChannel(getter_AddRefs(chan));
MOZ_ASSERT(!chan, "Why is there a document channel?");
#endif
if (win && windowIsNew) {
// Assert that we're not loading things right now. If we are, when
// that load completes it will clobber whatever principals we set up
// on this new window!
nsCOMPtr<nsIChannel> chan;
newDocShell->GetDocumentChannel(getter_AddRefs(chan));
MOZ_ASSERT(!chan, "Why is there a document channel?");
if (RefPtr<Document> doc = win->GetExtantDoc()) {
doc->SetIsInitialDocument(true);
}
if (RefPtr<Document> doc = win->GetExtantDoc()) {
MOZ_ASSERT(doc->IsInitialDocument(),
"New window's document should be an initial document");
}
}
#endif
MOZ_ASSERT(win || !windowIsNew, "New windows are always created in-process");

View File

@ -754,12 +754,14 @@ nsresult nsAppShellService::JustCreateTopWindow(
// Use the subject (or system) principal as the storage principal too
// until the new window finishes navigating and gets a real storage
// principal.
rv = docShell->CreateAboutBlankContentViewer(principal, principal,
/* aCsp = */ nullptr);
rv = docShell->CreateAboutBlankContentViewer(
principal, principal, /* aCsp = */ nullptr, /* aBaseURI = */ nullptr,
/* aIsInitialDocument = */ true);
NS_ENSURE_SUCCESS(rv, rv);
RefPtr<Document> doc = docShell->GetDocument();
NS_ENSURE_TRUE(!!doc, NS_ERROR_FAILURE);
doc->SetIsInitialDocument(true);
MOZ_ASSERT(doc->IsInitialDocument(),
"Document should be an initial document");
}
// Begin loading the URL provided.