tor-browser

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

commit 967fc6d445e4e7bfc2d8df824b2e47c59b47e8f8
parent 39a8a4171bb2248c50f158f0d144474e21924db9
Author: Vincent Hilla <vhilla@mozilla.com>
Date:   Mon, 24 Nov 2025 05:32:05 +0000

Bug 543435 - Ensure the initial about:blank SH entry is replaced. r=smaug

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

Diffstat:
Mbrowser/components/sessionstore/test/browser_705597.js | 93++++++++++++++++++++++++++++++++++++-------------------------------------------
Mbrowser/components/sessionstore/test/browser_707862.js | 95++++++++++++++++++++++++++++++++++---------------------------------------------
Mdocshell/base/nsDocShell.cpp | 1+
Mdom/base/nsFrameLoader.cpp | 7+++++--
Dtesting/web-platform/meta/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-nosrc.html.ini | 17-----------------
Dtesting/web-platform/meta/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-src-aboutblank-navigate-immediately.html.ini | 17-----------------
Dtesting/web-platform/meta/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-src-aboutblank-wait-for-load.html.ini | 20--------------------
Dtesting/web-platform/meta/html/browsers/history/the-location-interface/location_assign_about_blank.html.ini | 5-----
Mtesting/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name-0.html | 31+++++++++++++++++++++++++++----
Mtesting/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-remove-iframe.html | 7+++----
Mtesting/web-platform/tests/html/browsers/history/the-location-interface/assign_after_load.html | 2+-
Mtesting/web-platform/tests/html/browsers/history/the-location-interface/assign_before_load.html | 2+-
Mtesting/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_1-1.html | 4++--
Mtesting/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_2-1.html | 2+-
14 files changed, 124 insertions(+), 179 deletions(-)

diff --git a/browser/components/sessionstore/test/browser_705597.js b/browser/components/sessionstore/test/browser_705597.js @@ -2,7 +2,7 @@ http://creativecommons.org/publicdomain/zero/1.0/ */ /* eslint-disable mozilla/no-arbitrary-setTimeout */ -var tabState = { +const tabState = { entries: [ { url: "about:robots", @@ -12,68 +12,59 @@ var tabState = { ], }; -function test() { - waitForExplicitFinish(); - requestLongerTimeout(2); +const blankState = { + windows: [ + { + tabs: [ + { + entries: [{ url: "about:blank", triggeringPrincipal_base64 }], + }, + ], + }, + ], +}; +add_task(async function test() { Services.prefs.setIntPref("browser.sessionstore.interval", 4000); registerCleanupFunction(function () { Services.prefs.clearUserPref("browser.sessionstore.interval"); }); let tab = BrowserTestUtils.addTab(gBrowser, "about:blank"); - let browser = tab.linkedBrowser; + await BrowserTestUtils.browserLoaded(browser, false, "about:blank"); - promiseTabState(tab, tabState).then(() => { - let sessionHistory = browser.browsingContext.sessionHistory; - let entry = sessionHistory.getEntryAtIndex(0); + await promiseTabState(tab, tabState); + let sessionHistory = browser.browsingContext.sessionHistory; + let entry = sessionHistory.getEntryAtIndex(0); - whenChildCount(entry, 1, function () { - whenChildCount(entry, 2, function () { - promiseBrowserLoaded(browser) - .then(() => { - return TabStateFlusher.flush(browser); - }) - .then(() => { - let { entries } = JSON.parse(ss.getTabState(tab)); - is(entries.length, 1, "tab has one history entry"); - ok(!entries[0].children, "history entry has no subframes"); + await whenChildCount(entry, 1); - // Make sure that we reset the state. - let blankState = { - windows: [ - { - tabs: [ - { - entries: [ - { url: "about:blank", triggeringPrincipal_base64 }, - ], - }, - ], - }, - ], - }; - waitForBrowserState(blankState, finish); - }); + // Create a dynamic subframe. + let doc = browser.contentDocument; + let iframe = doc.createElement("iframe"); + iframe.setAttribute("src", "about:mozilla"); + doc.body.appendChild(iframe); - // Force reload the browser to deprecate the subframes. - browser.reloadWithFlags(Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE); - }); + await whenChildCount(entry, 2); - // Create a dynamic subframe. - let doc = browser.contentDocument; - let iframe = doc.createElement("iframe"); - doc.body.appendChild(iframe); - iframe.setAttribute("src", "about:mozilla"); - }); - }); -} + // Force reload the browser to discard the subframes. + browser.reloadWithFlags(Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE); + + await BrowserTestUtils.browserLoaded(browser, false, "about:robots"); + await TabStateFlusher.flush(browser); + + let { entries } = JSON.parse(ss.getTabState(tab)); + is(entries.length, 1, "tab has one history entry"); + ok(!entries[0].children, "history entry has no subframes"); + + // Make sure that we reset the state. + waitForBrowserState(blankState, finish); +}); -function whenChildCount(aEntry, aChildCount, aCallback) { - if (aEntry.childCount == aChildCount) { - aCallback(); - } else { - setTimeout(() => whenChildCount(aEntry, aChildCount, aCallback), 100); - } +function whenChildCount(aEntry, aChildCount) { + return TestUtils.waitForCondition( + () => aEntry.childCount == aChildCount, + "wait for child count" + ); } diff --git a/browser/components/sessionstore/test/browser_707862.js b/browser/components/sessionstore/test/browser_707862.js @@ -2,7 +2,7 @@ http://creativecommons.org/publicdomain/zero/1.0/ */ /* eslint-disable mozilla/no-arbitrary-setTimeout */ -var tabState = { +const tabState = { entries: [ { url: "about:robots", @@ -12,72 +12,59 @@ var tabState = { ], }; -function test() { - waitForExplicitFinish(); - requestLongerTimeout(2); +const blankState = { + windows: [ + { + tabs: [ + { + entries: [{ url: "about:blank", triggeringPrincipal_base64 }], + }, + ], + }, + ], +}; +add_task(async function test() { Services.prefs.setIntPref("browser.sessionstore.interval", 4000); registerCleanupFunction(function () { Services.prefs.clearUserPref("browser.sessionstore.interval"); }); let tab = BrowserTestUtils.addTab(gBrowser, "about:blank"); - let browser = tab.linkedBrowser; + await BrowserTestUtils.browserLoaded(browser, false, "about:blank"); - promiseTabState(tab, tabState).then(() => { - let sessionHistory = browser.browsingContext.sessionHistory; - let entry = sessionHistory.getEntryAtIndex(0); + await promiseTabState(tab, tabState); + let sessionHistory = browser.browsingContext.sessionHistory; + let entry = sessionHistory.getEntryAtIndex(0); - whenChildCount(entry, 1, function () { - whenChildCount(entry, 2, function () { - promiseBrowserLoaded(browser).then(() => { - let newSessionHistory = browser.browsingContext.sessionHistory; - let newEntry = newSessionHistory.getEntryAtIndex(0); + await whenChildCount(entry, 1); - whenChildCount(newEntry, 0, function () { - // Make sure that we reset the state. - let blankState = { - windows: [ - { - tabs: [ - { - entries: [ - { url: "about:blank", triggeringPrincipal_base64 }, - ], - }, - ], - }, - ], - }; - waitForBrowserState(blankState, finish); - }); - }); + // Create a dynamic subframe. + let doc = browser.contentDocument; + let iframe = doc.createElement("iframe"); + iframe.setAttribute("src", "about:mozilla"); + doc.body.appendChild(iframe); - // Force reload the browser to deprecate the subframes. - browser.reloadWithFlags(Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE); - }); + await whenChildCount(entry, 2); - // Create a dynamic subframe. - let doc = browser.contentDocument; - let iframe = doc.createElement("iframe"); - doc.body.appendChild(iframe); - iframe.setAttribute("src", "about:mozilla"); - }); - }); + // Force reload the browser to deprecate the subframes. + browser.reloadWithFlags(Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE); - // This test relies on the test timing out in order to indicate failure so - // let's add a dummy pass. - ok( - true, - "Each test requires at least one pass, fail or todo so here is a pass." - ); -} + await BrowserTestUtils.browserLoaded(browser, false, "about:robots"); + let newSessionHistory = browser.browsingContext.sessionHistory; + let newEntry = newSessionHistory.getEntryAtIndex(0); + + await whenChildCount(newEntry, 0); + // Make sure that we reset the state. + waitForBrowserState(blankState, finish); -function whenChildCount(aEntry, aChildCount, aCallback) { - if (aEntry.childCount == aChildCount) { - aCallback(); - } else { - setTimeout(() => whenChildCount(aEntry, aChildCount, aCallback), 100); - } + ok(true, "test passed"); +}); + +function whenChildCount(aEntry, aChildCount) { + return TestUtils.waitForCondition( + () => aEntry.childCount == aChildCount, + "wait for child count" + ); } diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp @@ -10855,6 +10855,7 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState, aLoadState->PrincipalToInherit(), aLoadState->PartitionedPrincipalToInherit(), aLoadState->PolicyContainer(), mContentTypeHint); + entry->SetTransient(); mozilla::dom::LoadingSessionHistoryInfo info(*entry); info.mContiguousEntries.AppendElement(*entry); SetLoadingSessionHistoryInfo(info, true); diff --git a/dom/base/nsFrameLoader.cpp b/dom/base/nsFrameLoader.cpp @@ -1879,8 +1879,11 @@ void nsFrameLoader::StartDestroy(bool aForProcessSwitch) { if (mozilla::SessionHistoryInParent()) { uint32_t addedEntries = 0; browsingContext->PreOrderWalk([&addedEntries](BrowsingContext* aBC) { - // The initial load doesn't increase history length. - addedEntries += aBC->GetHistoryEntryCount() - 1; + const uint32_t len = aBC->GetHistoryEntryCount(); + // There might not be a SH entry yet, which is fine. + // The first entry doesn't increase history length, as it's added to + // it's parent entry + addedEntries += len > 0 ? len - 1 : 0; }); nsID changeID = {}; diff --git a/testing/web-platform/meta/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-nosrc.html.ini b/testing/web-platform/meta/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-nosrc.html.ini @@ -1,17 +0,0 @@ -[iframe-nosrc.html] - expected: - if (os == "android") and fission: [OK, TIMEOUT] - [link click] - expected: FAIL - - [location.href] - expected: FAIL - - [location.assign] - expected: FAIL - - [window.open] - expected: FAIL - - [form submission] - expected: FAIL # these failures are fixed in the SH patch of the stack diff --git a/testing/web-platform/meta/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-src-aboutblank-navigate-immediately.html.ini b/testing/web-platform/meta/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-src-aboutblank-navigate-immediately.html.ini @@ -1,17 +0,0 @@ -[iframe-src-aboutblank-navigate-immediately.html] - expected: - if (os == "android") and fission: [OK, TIMEOUT] - [Navigating to a different document with link click] - expected: FAIL - - [Navigating to a different document with location.href] - expected: FAIL - - [Navigating to a different document with location.assign] - expected: FAIL - - [Navigating to a different document with window.open] - expected: FAIL - - [Navigating to a different document with form submission] - expected: FAIL # these failures are fixed in the SH patch of the stack diff --git a/testing/web-platform/meta/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-src-aboutblank-wait-for-load.html.ini b/testing/web-platform/meta/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-src-aboutblank-wait-for-load.html.ini @@ -1,20 +0,0 @@ -[iframe-src-aboutblank-wait-for-load.html] - expected: - if (os == "android") and fission: [OK, TIMEOUT] - [Navigating to a different document with src] - expected: FAIL - - [Navigating to a different document with location.href] - expected: FAIL - - [Navigating to a different document with location.assign] - expected: FAIL - - [Navigating to a different document with window.open] - expected: FAIL - - [Navigating to a different document with link click] - expected: FAIL - - [Navigating to a different document with form submission] - expected: FAIL diff --git a/testing/web-platform/meta/html/browsers/history/the-location-interface/location_assign_about_blank.html.ini b/testing/web-platform/meta/html/browsers/history/the-location-interface/location_assign_about_blank.html.ini @@ -1,5 +0,0 @@ -[location_assign_about_blank.html] - expected: - if (os == "android") and fission: [OK, TIMEOUT] - [location.assign with initial about:blank browsing context] - expected: FAIL diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name-0.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name-0.html @@ -8,18 +8,38 @@ var l = opener.document.getElementById("step_log"); log = function(t) {l.textContent += ("\n" + t)} var navigated = false; var steps = [ - () => f.src = "browsing_context_name-1.html", + () => { + opener.assert_equals(history.length, 1, "first history.length"); + f.src = "browsing_context_name-1.html"; + }, () => { navigated = true; opener.assert_equals(f.contentWindow.name, "test", "Initial load"); + opener.assert_equals(history.length, 1, "second history.length"); + setTimeout(next, 0); + }, + () => { + opener.assert_equals(f.contentWindow.name, "test", "Initial load"); + opener.assert_equals(history.length, 1, "third history.length"); f.src = "browsing_context_name-2.html" }, () => { opener.assert_equals(f.contentWindow.name, "test1"); - opener.assert_equals(history.length, 2); - history.back() + opener.assert_equals(history.length, 2, "fourth history.length"); + setTimeout(next, 0); + }, + () => { + opener.assert_equals(f.contentWindow.name, "test1"); + opener.assert_equals(history.length, 2, "fifth history.length"); + history.back(); + }, + () => { + opener.assert_equals(history.length, 2, "sixth history.length"); + opener.assert_equals(f.contentWindow.name, "test1", "After navigation"); + setTimeout(next, 0); }, () => { + opener.assert_equals(history.length, 2, "seventh history.length"); opener.assert_equals(f.contentWindow.name, "test1", "After navigation"); t.done(); } @@ -29,7 +49,10 @@ next = () => steps.shift()(); onload = () => { log("page load"); - f.onload = () => {log("iframe onload"); next()}; + f.onload = () => { + log("iframe onload"); + next(); + }; setTimeout(next, 0); }; </script> diff --git a/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-remove-iframe.html b/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-remove-iframe.html @@ -11,12 +11,11 @@ async_test(function(t) { t.step_timeout(() => { var child = document.getElementById("frame"); var old_history_len = history.length; - child.onload = () => { - assert_equals(old_history_len + 1, history.length); + child.onload = t.step_func_done(() => { + assert_equals(old_history_len, history.length); document.body.removeChild(document.getElementById("frame")); assert_equals(old_history_len, history.length); - t.done(); - } + }) child.src = "joint-session-history-filler.html"; }, 1000); }); diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/assign_after_load.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/assign_after_load.html @@ -16,7 +16,7 @@ onload = t.step_func(function() { }); do_test = t.step_func(function() { - assert_equals(history.length, history_length + 2); + assert_equals(history.length, history_length + 1); t.done(); }); diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/assign_before_load.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/assign_before_load.html @@ -16,7 +16,7 @@ onload = t.step_func(function() { }); do_test = t.step_func(function() { - assert_equals(history.length, history_length + 1); + assert_equals(history.length, history_length); t.done(); }); diff --git a/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_1-1.html b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_1-1.html @@ -8,9 +8,9 @@ onload = t.step_func(function() { var history_length = history.length; var iframe = document.getElementsByTagName("iframe")[0]; iframe.onload = t.step_func(function() { - opener.assert_equals(history.length, history_length + 1); + opener.assert_equals(history.length, history_length, "History length before iframe removal"); iframe.parentNode.removeChild(iframe); - opener.assert_equals(history.length, history_length); + opener.assert_equals(history.length, history_length, "History length after iframe removal"); t.done(); window.close(); }); diff --git a/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_2-1.html b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_2-1.html @@ -9,7 +9,7 @@ onload = t.step_func(function() { var iframe = document.getElementsByTagName("iframe")[0]; iframe.onload = t.step_func(function() { setTimeout(t.step_func(function() { - opener.assert_equals(history.length, history_length + 1, "History length before iframe removal"); + opener.assert_equals(history.length, history_length, "History length before iframe removal"); document.body.innerHTML = ""; opener.assert_equals(history.length, history_length, "History length after iframe removal"); t.done();