commit b388347c051b0140a2526dc95a1e066617126823
parent 8a1b1970b7bd4743b2a5c4f5f2333a4d31b7c4e9
Author: Adam Vandolder <avandolder@mozilla.com>
Date: Tue, 21 Oct 2025 15:54:56 +0000
Bug 1995397 - Treat document.open'd documents as still initial about:blank for Navigation::HasEntriesAndEventsDisabled. r=jjaschke,smaug,dom-core
Differential Revision: https://phabricator.services.mozilla.com/D269286
Diffstat:
3 files changed, 45 insertions(+), 22 deletions(-)
diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp
@@ -1371,6 +1371,7 @@ Document::Document(const char* aContentType,
#ifdef DEBUG
mStyledLinksCleared(false),
#endif
+ mInitialStatus(Document::InitialStatus::NeverInitial),
mCachedStateObjectValid(false),
mBlockAllMixedContent(false),
mBlockAllMixedContentPreloads(false),
@@ -1381,8 +1382,6 @@ Document::Document(const char* aContentType,
mRenderingSuppressedForViewTransitions(false),
mBidiEnabled(false),
mMayNeedFontPrefsUpdate(true),
- mIsInitialDocumentInWindow(false),
- mIsEverInitialDocumentInWindow(false),
mIgnoreDocGroupMismatches(false),
mAddedToMemoryReportingAsDataDocument(false),
mMayStartLayout(true),
@@ -10479,7 +10478,9 @@ Document* Document::Open(const Optional<nsAString>& /* unused */,
// URL may be changing away from about:blank here, we really want to unset
// this flag no matter what, since only about:blank can be an initial
// document.
- SetIsInitialDocument(false);
+ if (IsInitialDocument()) {
+ SetInitialStatus(Document::InitialStatus::IsInitialButExplicitlyOpened);
+ }
// And let our docloader know that it will need to track our load event.
nsDocShell::Cast(shell)->SetDocumentOpenedButNotLoaded();
@@ -20383,10 +20384,10 @@ nsIPrincipal* Document::GetPrincipalForPrefBasedHacks() const {
}
void Document::SetIsInitialDocument(bool aIsInitialDocument) {
- mIsInitialDocumentInWindow = aIsInitialDocument;
-
- if (aIsInitialDocument && !mIsEverInitialDocumentInWindow) {
- mIsEverInitialDocumentInWindow = aIsInitialDocument;
+ if (aIsInitialDocument) {
+ mInitialStatus = InitialStatus::IsInitial;
+ } else if (mInitialStatus != InitialStatus::NeverInitial) {
+ mInitialStatus = InitialStatus::WasInitial;
}
// Asynchronously tell the parent process that we are, or are no longer, the
@@ -20396,6 +20397,16 @@ void Document::SetIsInitialDocument(bool aIsInitialDocument) {
}
}
+void Document::SetInitialStatus(InitialStatus aStatus) {
+ mInitialStatus = aStatus;
+
+ // Asynchronously tell the parent process that we are, or are no longer, the
+ // initial document. This happens async.
+ if (auto* wgc = GetWindowGlobalChild()) {
+ wgc->SendSetIsInitialDocument(aStatus == InitialStatus::IsInitial);
+ }
+}
+
// static
void Document::AddToplevelLoadingDocument(Document* aDoc) {
MOZ_ASSERT(aDoc && aDoc->IsTopLevelContentDocument());
diff --git a/dom/base/Document.h b/dom/base/Document.h
@@ -1016,16 +1016,27 @@ class Document : public nsINode,
*/
void SetBidiEnabled() { mBidiEnabled = true; }
+ enum class InitialStatus : uint8_t {
+ IsInitial,
+ IsInitialButExplicitlyOpened,
+ WasInitial,
+ NeverInitial,
+ };
+
/**
* Ask this document whether it's the initial document in its window.
*/
- bool IsInitialDocument() const { return mIsInitialDocumentInWindow; }
+ bool IsInitialDocument() const {
+ return mInitialStatus == InitialStatus::IsInitial;
+ }
/**
* Ask this document whether it has ever been a initial document in its
* window.
*/
- bool IsEverInitialDocument() const { return mIsEverInitialDocumentInWindow; }
+ bool IsEverInitialDocument() const {
+ return mInitialStatus != InitialStatus::NeverInitial;
+ }
/**
* Tell this document that it's the initial document in its window. See
@@ -1033,6 +1044,10 @@ class Document : public nsINode,
*/
void SetIsInitialDocument(bool aIsInitialDocument);
+ InitialStatus GetInitialStatus() const { return mInitialStatus; }
+
+ void SetInitialStatus(Document::InitialStatus aStatus);
+
void SetLoadedAsData(bool aLoadedAsData, bool aConsiderForMemoryReporting);
TimeStamp GetLoadingOrRestoredFromBFCacheTimeStamp() const {
@@ -4835,6 +4850,13 @@ class Document : public nsINode,
// GetPermissionDelegateHandler
RefPtr<PermissionDelegateHandler> mPermissionDelegateHandler;
+ // https://html.spec.whatwg.org/#is-initial-about:blank
+ // Track the initial about:blank status of this document.
+ // We track both whether the document was previously initial,
+ // and whether it is an initial about:blank which has had document.open called
+ // on it (see bug 1995397).
+ InitialStatus mInitialStatus;
+
bool mCachedStateObjectValid : 1;
bool mBlockAllMixedContent : 1;
bool mBlockAllMixedContentPreloads : 1;
@@ -4854,17 +4876,6 @@ class Document : public nsINode,
// True if we may need to recompute the language prefs for this document.
bool mMayNeedFontPrefsUpdate : 1;
- // True if this document is the initial document for a window. This should
- // basically be true only for documents that exist in newly-opened windows or
- // documents created to satisfy a GetDocument() on a window when there's no
- // document in it.
- bool mIsInitialDocumentInWindow : 1;
-
- // True if this document has ever been the initial document for a window. This
- // is useful to determine if a document that was the initial document at one
- // point, and became non-initial later.
- bool mIsEverInitialDocumentInWindow : 1;
-
bool mIgnoreDocGroupMismatches : 1;
// True if the document is considered for memory reporting as a
diff --git a/dom/navigation/Navigation.cpp b/dom/navigation/Navigation.cpp
@@ -288,8 +288,9 @@ NavigationActivation* Navigation::GetActivation() const { return mActivation; }
bool Navigation::HasEntriesAndEventsDisabled() const {
Document* doc = GetAssociatedDocument();
return !doc || !doc->IsCurrentActiveDocument() ||
- (NS_IsAboutBlankAllowQueryAndFragment(doc->GetDocumentURI()) &&
- doc->IsInitialDocument()) ||
+ doc->GetInitialStatus() == Document::InitialStatus::IsInitial ||
+ doc->GetInitialStatus() ==
+ Document::InitialStatus::IsInitialButExplicitlyOpened ||
doc->GetPrincipal()->GetIsNullPrincipal();
}