tor-browser

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

commit c32abaee2e8896ecd62dd065ac6c485520d76d1f
parent d779c5e8ed412e3423c7077ec86b81d90fdd6279
Author: Adam Vandolder <avandolder@mozilla.com>
Date:   Wed, 15 Oct 2025 15:21:31 +0000

Bug 1994342 - Sync navigation API state updates in the child to the parent process. r=dom-core,farre

Differential Revision: https://phabricator.services.mozilla.com/D268641

Diffstat:
Mdocshell/base/BrowsingContext.cpp | 19+++++++++++++++++++
Mdocshell/base/BrowsingContext.h | 1+
Mdocshell/base/CanonicalBrowsingContext.cpp | 7+++++++
Mdocshell/base/CanonicalBrowsingContext.h | 2++
Mdocshell/shistory/SessionHistoryEntry.h | 4++++
Mdom/ipc/ContentParent.cpp | 14++++++++++++++
Mdom/ipc/ContentParent.h | 4++++
Mdom/ipc/PContent.ipdl | 3+++
Mdom/navigation/Navigation.cpp | 15+++++++++++++++
Dtesting/web-platform/meta/navigation-api/navigate-event/navigate-destination-getState-reload.html.ini | 6------
Dtesting/web-platform/meta/navigation-api/state/cross-document-away-and-back.html.ini | 3---
Dtesting/web-platform/meta/navigation-api/state/cross-document-getState.html.ini | 3---
Dtesting/web-platform/meta/navigation-api/state/location-reload.html.ini | 3---
Dtesting/web-platform/meta/navigation-api/updateCurrentEntry-method/same-document-away-and-back-location-api.html.ini | 4----
14 files changed, 69 insertions(+), 19 deletions(-)

diff --git a/docshell/base/BrowsingContext.cpp b/docshell/base/BrowsingContext.cpp @@ -4485,6 +4485,25 @@ void BrowsingContext::ConsumeHistoryActivation() { }); } +void BrowsingContext::SynchronizeNavigationAPIState( + nsIStructuredCloneContainer* aState) { + if (!aState) { + return; + } + + if (XRE_IsContentProcess()) { + ClonedMessageData data; + DebugOnly<bool> result = static_cast<nsStructuredCloneContainer*>(aState) + ->BuildClonedMessageData(data); + MOZ_ASSERT(result); + + MOZ_ASSERT(ContentChild::GetSingleton()); + ContentChild::GetSingleton()->SendSynchronizeNavigationAPIState(this, data); + } else { + Canonical()->SynchronizeNavigationAPIState(aState); + } +} + } // namespace dom namespace ipc { diff --git a/docshell/base/BrowsingContext.h b/docshell/base/BrowsingContext.h @@ -1070,6 +1070,7 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache { void ClearCachedValuesOfLocations(); void ConsumeHistoryActivation(); + void SynchronizeNavigationAPIState(nsIStructuredCloneContainer* aState); protected: virtual ~BrowsingContext(); diff --git a/docshell/base/CanonicalBrowsingContext.cpp b/docshell/base/CanonicalBrowsingContext.cpp @@ -2864,6 +2864,13 @@ void CanonicalBrowsingContext::SynchronizeLayoutHistoryState() { } } +void CanonicalBrowsingContext::SynchronizeNavigationAPIState( + nsIStructuredCloneContainer* aState) { + if (mActiveEntry) { + mActiveEntry->SetNavigationAPIState(aState); + } +} + void CanonicalBrowsingContext::ResetScalingZoom() { // This currently only ever gets called in the parent process, and we // pass the message on to the WindowGlobalChild for the rootmost browsing diff --git a/docshell/base/CanonicalBrowsingContext.h b/docshell/base/CanonicalBrowsingContext.h @@ -337,6 +337,8 @@ class CanonicalBrowsingContext final : public BrowsingContext { void SynchronizeLayoutHistoryState(); + void SynchronizeNavigationAPIState(nsIStructuredCloneContainer* aState); + void ResetScalingZoom(); void SetContainerFeaturePolicy( diff --git a/docshell/shistory/SessionHistoryEntry.h b/docshell/shistory/SessionHistoryEntry.h @@ -465,6 +465,10 @@ class SessionHistoryEntry : public nsISHEntry, already_AddRefed<nsIURI> GetURIOrInheritedForAboutBlank() const; + void SetNavigationAPIState(nsIStructuredCloneContainer* aState) { + mInfo->SetNavigationAPIState(aState); + } + private: friend struct LoadingSessionHistoryInfo; virtual ~SessionHistoryEntry(); diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp @@ -7741,6 +7741,20 @@ ContentParent::RecvGetLoadingSessionHistoryInfoFromParent( return IPC_OK(); } +mozilla::ipc::IPCResult ContentParent::RecvSynchronizeNavigationAPIState( + const MaybeDiscarded<BrowsingContext>& aContext, + const ClonedMessageData& aState) { + if (aContext.IsNullOrDiscarded()) { + return IPC_OK(); + } + + RefPtr state = MakeRefPtr<nsStructuredCloneContainer>(); + state->CopyFromClonedMessageData(aState); + + aContext.get_canonical()->SynchronizeNavigationAPIState(state); + return IPC_OK(); +} + mozilla::ipc::IPCResult ContentParent::RecvRemoveFromBFCache( const MaybeDiscarded<BrowsingContext>& aContext) { if (aContext.IsNullOrDiscarded()) { diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h @@ -1356,6 +1356,10 @@ class ContentParent final : public PContentParent, const MaybeDiscarded<BrowsingContext>& aContext, GetLoadingSessionHistoryInfoFromParentResolver&& aResolver); + mozilla::ipc::IPCResult RecvSynchronizeNavigationAPIState( + const MaybeDiscarded<BrowsingContext>& aContext, + const ClonedMessageData& aState); + mozilla::ipc::IPCResult RecvRemoveFromBFCache( const MaybeDiscarded<BrowsingContext>& aContext); diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl @@ -1103,6 +1103,9 @@ parent: async GetLoadingSessionHistoryInfoFromParent(MaybeDiscardedBrowsingContext aContext) returns (LoadingSessionHistoryInfo? aLoadingInfo); + async SynchronizeNavigationAPIState(MaybeDiscardedBrowsingContext aContext, + ClonedMessageData aState); + async RemoveFromBFCache(MaybeDiscardedBrowsingContext aContext); async InitBackground(Endpoint<PBackgroundStarterParent> aEndpoint); diff --git a/dom/navigation/Navigation.cpp b/dom/navigation/Navigation.cpp @@ -245,6 +245,21 @@ void Navigation::UpdateCurrentEntry( currentEntry->SetNavigationAPIState(serializedState); + ToMaybeRef(GetOwnerWindow()) + .andThen([](auto& aWindow) { + return ToMaybeRef(aWindow.GetBrowsingContext()); + }) + .apply([serializedState](auto& navigable) { + navigable.SynchronizeNavigationAPIState(serializedState); + ToMaybeRef(nsDocShell::Cast(navigable.GetDocShell())) + .andThen([](auto& docshell) { + return ToMaybeRef(docshell.GetActiveSessionHistoryInfo()); + }) + .apply([serializedState](auto& activeInfo) { + activeInfo.SetNavigationAPIState(serializedState); + }); + }); + NavigationCurrentEntryChangeEventInit init; init.mFrom = currentEntry; // Leaving the navigation type unspecified means it will be initialized to diff --git a/testing/web-platform/meta/navigation-api/navigate-event/navigate-destination-getState-reload.html.ini b/testing/web-platform/meta/navigation-api/navigate-event/navigate-destination-getState-reload.html.ini @@ -1,6 +0,0 @@ -[navigate-destination-getState-reload.html] - expected: - if not tsan and asan and fission: [OK, ERROR] - if tsan: [OK, ERROR] - [navigate event destination.getState() on location.reload()] - expected: FAIL diff --git a/testing/web-platform/meta/navigation-api/state/cross-document-away-and-back.html.ini b/testing/web-platform/meta/navigation-api/state/cross-document-away-and-back.html.ini @@ -1,3 +0,0 @@ -[cross-document-away-and-back.html?method=updateCurrentEntry] - [entry.getState() behavior after navigating away and back] - expected: FAIL diff --git a/testing/web-platform/meta/navigation-api/state/cross-document-getState.html.ini b/testing/web-platform/meta/navigation-api/state/cross-document-getState.html.ini @@ -1,3 +0,0 @@ -[cross-document-getState.html] - [entry.getState() still works for a non-current cross-document entry] - expected: FAIL diff --git a/testing/web-platform/meta/navigation-api/state/location-reload.html.ini b/testing/web-platform/meta/navigation-api/state/location-reload.html.ini @@ -1,3 +0,0 @@ -[location-reload.html?method=updateCurrentEntry] - [entry.getState() after location.reload()] - expected: FAIL diff --git a/testing/web-platform/meta/navigation-api/updateCurrentEntry-method/same-document-away-and-back-location-api.html.ini b/testing/web-platform/meta/navigation-api/updateCurrentEntry-method/same-document-away-and-back-location-api.html.ini @@ -1,4 +0,0 @@ -[same-document-away-and-back-location-api.html] - expected: ERROR - [entry.getState() behavior after navigating away using the location API, then back] - expected: TIMEOUT