tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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:
Mdocshell/base/BrowsingContext.cpp | 53++++++++++++++++++-----------------------------------
Mdocshell/base/BrowsingContext.h | 6++++--
Mdom/base/LocationBase.cpp | 21++++++++++++++++++++-
Mdom/navigation/Navigation.cpp | 2+-
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);