tor-browser

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

commit e4338fcdcb24e288142eab0703bed60243d9ed1a
parent a10da7a0320d634a50e797a4b6b1330709d8fde6
Author: Hiroyuki Ikezoe <hikezoe.birchill@mozilla.com>
Date:   Tue,  4 Nov 2025 20:19:04 +0000

Bug 1997214 - Explicitely `InActive` for the replacing browsing context in CanonicalBrowsingContext::ReplacedBy. r=dom-core,smaug

The change in CanonicalBrowsingContext.cpp was provided by Nika.

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

Diffstat:
Mdocshell/base/CanonicalBrowsingContext.cpp | 5++++-
Mdocshell/test/browser/browser_browsing_context_active_change.js | 80++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
2 files changed, 71 insertions(+), 14 deletions(-)

diff --git a/docshell/base/CanonicalBrowsingContext.cpp b/docshell/base/CanonicalBrowsingContext.cpp @@ -323,7 +323,10 @@ void CanonicalBrowsingContext::ReplacedBy( } aNewContext->mRestoreState = mRestoreState.forget(); - MOZ_ALWAYS_SUCCEEDS(SetHasRestoreData(false)); + Transaction selfTxn; + selfTxn.SetHasRestoreData(false); + selfTxn.SetExplicitActive(ExplicitActiveStatus::Inactive); + MOZ_ALWAYS_SUCCEEDS(selfTxn.Commit(this)); // XXXBFCache name handling is still a bit broken in Fission in general, // at least in case name should be cleared. diff --git a/docshell/test/browser/browser_browsing_context_active_change.js b/docshell/test/browser/browser_browsing_context_active_change.js @@ -3,31 +3,30 @@ // Test browsing-context-active-change notification which is fired on the parent process // to know when a BrowsingContext becomes visible/hidden. -const TEST_PATH = - getRootDirectory(gTestPath).replace( - "chrome://mochitests/content", - // eslint-disable-next-line @microsoft/sdl/no-insecure-url - "http://example.com" - ) + "dummy_page.html"; - -const TOPIC = "browsing-context-active-change"; - -async function waitForActiveChange() { +function observeTopic(aTopic) { return new Promise(resolve => { function observer(subject, topic) { - is(topic, TOPIC, "observing correct topic"); + is(topic, aTopic, "observing correct topic"); ok( BrowsingContext.isInstance(subject), "subject to be a BrowsingContext" ); - Services.obs.removeObserver(observer, TOPIC); + Services.obs.removeObserver(observer, aTopic); resolve(); } - Services.obs.addObserver(observer, TOPIC); + Services.obs.addObserver(observer, aTopic); }); } +function waitForActiveChange() { + return observeTopic("browsing-context-active-change"); +} + +function waitForAttached() { + return observeTopic("browsing-context-attached"); +} + add_task(async function () { const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); const browser = tab.linkedBrowser; @@ -52,3 +51,58 @@ add_task(async function () { BrowserTestUtils.removeTab(tab); }); + +// Tests that BrowsingContext.isActive becomes false in BF cache. +add_task(async function () { + const TEST_PATH1 = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://example.com" + ) + "dummy_page.html"; + const TEST_PATH2 = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://example.com" + ) + "dummy_iframe_page.html"; + + let attached = waitForActiveChange(); + const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PATH1); + await attached; + + const firstBC = tab.linkedBrowser.browsingContext; + is(firstBC.isActive, true, "The first browsing context is now active"); + is(firstBC.currentURI.spec, TEST_PATH1); + + // Load a new page now. + attached = waitForActiveChange(); + await loadURI(TEST_PATH2); + await attached; + + const secondBC = tab.linkedBrowser.browsingContext; + isnot(firstBC, secondBC); + + is(secondBC.isActive, true, "The second browsing context is now active"); + is(secondBC.currentURI.spec, TEST_PATH2); + is(firstBC.isActive, false, "The first browsing context is no longer active"); + is(firstBC.currentURI.spec, TEST_PATH1); + + // Now try to back to the previous page, unlike above cases we don't wait + // "browsing-context-active-change" since it's not notified on this history back. + const stoppedLoadingPromise = BrowserTestUtils.browserStopped( + tab.linkedBrowser, + TEST_PATH1 + ); + gBrowser.goBack(); + await stoppedLoadingPromise; + + is( + secondBC.isActive, + false, + "The second browsing context is no longer active" + ); + is(firstBC.isActive, true, "The first browsing context is active again"); + + BrowserTestUtils.removeTab(tab); +});