commit 8c5176b7fb40d47b1c4026c7f3ee0e10fe1b2299
parent d914cf1a8532d6295c262afc790e7b35570964a8
Author: Simon Farre <sfarre@mozilla.com>
Date: Thu, 27 Nov 2025 14:34:34 +0000
Bug 2002750 - Serve Navigate algorithm with sourceDoc r=farre
The algorithm https://html.spec.whatwg.org/#beginning-navigation takes
an optional Document-or-null, that we are currently not passing to our
implementation of this algorithm.
Navigation::Navigate is supposed to provide the document that is
navigating away as the source document, which would differ from the old
LocationBase::Navigate behavior, which always takes the incumbent global
document as the source document (just like spec says for Location).
This change makes it possible to provide the aSourceDocument.
Differential Revision: https://phabricator.services.mozilla.com/D274272
Diffstat:
4 files changed, 43 insertions(+), 39 deletions(-)
diff --git a/docshell/base/BrowsingContext.cpp b/docshell/base/BrowsingContext.cpp
@@ -2351,6 +2351,7 @@ nsresult BrowsingContext::InternalLoad(nsDocShellLoadState* aLoadState) {
already_AddRefed<nsDocShellLoadState>
BrowsingContext::CheckURLAndCreateLoadState(nsIURI* aURI,
nsIPrincipal& aSubjectPrincipal,
+ Document* aSourceDocument,
ErrorResult& aRv) {
nsCOMPtr<nsIPrincipal> triggeringPrincipal;
nsCOMPtr<nsIURI> sourceURI;
@@ -2377,41 +2378,22 @@ BrowsingContext::CheckURLAndCreateLoadState(nsIURI* aURI,
return nullptr;
}
- // Make the load's referrer reflect changes to the document's URI caused by
- // push/replaceState, if possible. First, get the document corresponding to
- // fp. If the document's original URI (i.e. its URI before
- // push/replaceState) matches the principal's URI, use the document's
- // current URI as the referrer. If they don't match, use the principal's
- // URI.
- //
- // The triggering principal for this load should be the principal of the
- // incumbent document (which matches where the referrer information is
- // coming from) when there is an incumbent document, and the subject
- // principal otherwise. Note that the URI in the triggering principal
- // may not match the referrer URI in various cases, notably including
- // the cases when the incumbent document's document URI was modified
- // after the document was loaded.
-
- nsCOMPtr<nsPIDOMWindowInner> incumbent =
- do_QueryInterface(mozilla::dom::GetIncumbentGlobal());
- nsCOMPtr<Document> doc = incumbent ? incumbent->GetDoc() : nullptr;
-
// Create load info
RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI);
- if (!doc) {
+ if (!aSourceDocument) {
// No document; just use our subject principal as the triggering principal.
loadState->SetTriggeringPrincipal(&aSubjectPrincipal);
return loadState.forget();
}
nsCOMPtr<nsIURI> docOriginalURI, docCurrentURI, principalURI;
- docOriginalURI = doc->GetOriginalURI();
- docCurrentURI = doc->GetDocumentURI();
- nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
+ docOriginalURI = aSourceDocument->GetOriginalURI();
+ docCurrentURI = aSourceDocument->GetDocumentURI();
+ nsCOMPtr<nsIPrincipal> principal = aSourceDocument->NodePrincipal();
- triggeringPrincipal = doc->NodePrincipal();
- referrerPolicy = doc->GetReferrerPolicy();
+ triggeringPrincipal = aSourceDocument->NodePrincipal();
+ referrerPolicy = aSourceDocument->GetReferrerPolicy();
bool urisEqual = false;
if (docOriginalURI && docCurrentURI && principal) {
@@ -2423,20 +2405,21 @@ BrowsingContext::CheckURLAndCreateLoadState(nsIURI* aURI,
principal->CreateReferrerInfo(referrerPolicy, getter_AddRefs(referrerInfo));
}
loadState->SetTriggeringPrincipal(triggeringPrincipal);
- loadState->SetTriggeringSandboxFlags(doc->GetSandboxFlags());
- loadState->SetPolicyContainer(doc->GetPolicyContainer());
+ loadState->SetTriggeringSandboxFlags(aSourceDocument->GetSandboxFlags());
+ loadState->SetPolicyContainer(aSourceDocument->GetPolicyContainer());
if (referrerInfo) {
loadState->SetReferrerInfo(referrerInfo);
}
loadState->SetHasValidUserGestureActivation(
- doc->HasValidTransientUserGestureActivation());
+ aSourceDocument->HasValidTransientUserGestureActivation());
loadState->SetTextDirectiveUserActivation(
- doc->ConsumeTextDirectiveUserActivation() ||
+ aSourceDocument->ConsumeTextDirectiveUserActivation() ||
loadState->HasValidUserGestureActivation());
- loadState->SetTriggeringWindowId(doc->InnerWindowID());
- loadState->SetTriggeringStorageAccess(doc->UsingStorageAccess());
- loadState->SetTriggeringClassificationFlags(doc->GetScriptTrackingFlags());
+ loadState->SetTriggeringWindowId(aSourceDocument->InnerWindowID());
+ loadState->SetTriggeringStorageAccess(aSourceDocument->UsingStorageAccess());
+ loadState->SetTriggeringClassificationFlags(
+ aSourceDocument->GetScriptTrackingFlags());
return loadState.forget();
}
@@ -2445,8 +2428,8 @@ BrowsingContext::CheckURLAndCreateLoadState(nsIURI* aURI,
// In its current state, this method is not closely following the spec.
// https://bugzil.la/1974717 tracks the work to align this method with the spec.
void BrowsingContext::Navigate(
- nsIURI* aURI, nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv,
- NavigationHistoryBehavior aHistoryHandling,
+ nsIURI* aURI, Document* aSourceDocument, nsIPrincipal& aSubjectPrincipal,
+ ErrorResult& aRv, NavigationHistoryBehavior aHistoryHandling,
bool aNeedsCompletelyLoadedDocument,
nsIStructuredCloneContainer* aNavigationAPIState,
dom::NavigationAPIMethodTracker* aNavigationAPIMethodTracker) {
@@ -2463,7 +2446,7 @@ void BrowsingContext::Navigate(
}
RefPtr<nsDocShellLoadState> loadState =
- CheckURLAndCreateLoadState(aURI, aSubjectPrincipal, aRv);
+ CheckURLAndCreateLoadState(aURI, aSubjectPrincipal, aSourceDocument, aRv);
if (aRv.Failed()) {
return;
}
diff --git a/docshell/base/BrowsingContext.h b/docshell/base/BrowsingContext.h
@@ -463,7 +463,8 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
nsresult InternalLoad(nsDocShellLoadState* aLoadState);
void Navigate(
- nsIURI* aURI, nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv,
+ nsIURI* aURI, Document* aSourceDocument, nsIPrincipal& aSubjectPrincipal,
+ ErrorResult& aRv,
NavigationHistoryBehavior aHistoryHandling =
NavigationHistoryBehavior::Auto,
bool aNeedsCompletelyLoadedDocument = false,
@@ -1101,7 +1102,8 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
// principal, and if so construct the right nsDocShellLoadInfo for the load
// and return it.
already_AddRefed<nsDocShellLoadState> CheckURLAndCreateLoadState(
- nsIURI* aURI, nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv);
+ nsIURI* aURI, nsIPrincipal& aSubjectPrincipal, Document* aSourceDocument,
+ ErrorResult& aRv);
bool AddSHEntryWouldIncreaseLength(SessionHistoryInfo* aCurrentEntry) const;
diff --git a/dom/base/LocationBase.cpp b/dom/base/LocationBase.cpp
@@ -43,8 +43,27 @@ void LocationBase::Navigate(nsIURI* aURI, nsIPrincipal& aSubjectPrincipal,
// Step 2-3, except the check for if document is completely loaded.
bool needsCompletelyLoadedDocument = !IncumbentGlobalHasTransientActivation();
+ // Make the load's referrer reflect changes to the document's URI caused by
+ // push/replaceState, if possible. First, get the document corresponding to
+ // fp. If the document's original URI (i.e. its URI before
+ // push/replaceState) matches the principal's URI, use the document's
+ // current URI as the referrer. If they don't match, use the principal's
+ // URI.
+ //
+ // The triggering principal for this load should be the principal of the
+ // incumbent document (which matches where the referrer information is
+ // coming from) when there is an incumbent document, and the subject
+ // principal otherwise. Note that the URI in the triggering principal
+ // may not match the referrer URI in various cases, notably including
+ // the cases when the incumbent document's document URI was modified
+ // after the document was loaded.
+
+ nsCOMPtr<nsPIDOMWindowInner> incumbent =
+ do_QueryInterface(mozilla::dom::GetIncumbentGlobal());
+ nsCOMPtr<Document> doc = incumbent ? incumbent->GetDoc() : nullptr;
+
// Step 4
- navigable->Navigate(aURI, aSubjectPrincipal, aRv, aHistoryHandling,
+ navigable->Navigate(aURI, doc, aSubjectPrincipal, aRv, aHistoryHandling,
needsCompletelyLoadedDocument);
}
diff --git a/dom/navigation/Navigation.cpp b/dom/navigation/Navigation.cpp
@@ -600,7 +600,7 @@ void Navigation::Navigate(JSContext* aCx, const nsAString& aUrl,
RefPtr bc = document->GetBrowsingContext();
MOZ_DIAGNOSTIC_ASSERT(bc);
- bc->Navigate(urlRecord, *document->NodePrincipal(),
+ bc->Navigate(urlRecord, document, *document->NodePrincipal(),
/* per spec, error handling defaults to false */ IgnoreErrors(),
aOptions.mHistory, /* aNeedsCompletelyLoadedDocument */ false,
serializedState, apiMethodTracker);