tor-browser

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

commit a64cd98732976e29500ccd076d697865c6a93810
parent a946c644949e65faf10d6589b8b863e99356bd4f
Author: Hiroyuki Ikezoe <hikezoe.birchill@mozilla.com>
Date:   Sat,  8 Nov 2025 21:41:18 +0000

Bug 1997214 - Explicitely set `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 | 84++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
2 files changed, 75 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,62 @@ 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. + let stoppedLoadingPromise = BrowserTestUtils.browserStopped( + tab.linkedBrowser, + TEST_PATH2 + ); + await loadURI(TEST_PATH2); + await stoppedLoadingPromise; + const secondBC = tab.linkedBrowser.browsingContext; + await TestUtils.waitForCondition(() => secondBC.isActive); + + 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. + 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); +});