tor-browser

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

commit 782b1abb8a3509e51371aef10867e60501420ce9
parent 1f74f55b43b518287525819030f372d6efbe695d
Author: Rob Wu <rob@robwu.nl>
Date:   Mon, 29 Dec 2025 22:17:05 +0000

Bug 2002643 - Preserve custom tab value when tab is adopted r=sessionstore-reviewers,sthompson

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

Diffstat:
Mbrowser/components/extensions/test/browser/browser_ext_sessions_window_tab_value.js | 41+++++++++++++++++++++++++++++++++++++++++
Mbrowser/components/sessionstore/SessionStore.sys.mjs | 15+++++++++++++++
2 files changed, 56 insertions(+), 0 deletions(-)

diff --git a/browser/components/extensions/test/browser/browser_ext_sessions_window_tab_value.js b/browser/components/extensions/test/browser/browser_ext_sessions_window_tab_value.js @@ -226,6 +226,47 @@ add_task(async function test_sessions_tab_value_persistence() { await extension.unload(); }); +// Regression test for https://bugzilla.mozilla.org/show_bug.cgi?id=2002643 +add_task(async function test_sessions_tab_value_persists_across_adoption() { + async function background() { + const tab = await browser.tabs.create({ url: "about:blank" }); + + await browser.sessions.setTabValue(tab.id, "my key", "tab value"); + + await browser.windows.create({ tabId: tab.id }); + + browser.test.assertEq( + await browser.sessions.getTabValue(tab.id, "my key"), + "tab value", + "setTabValue sticks to tab when tab is adopted in new window" + ); + + const win = await browser.windows.create({}); + await browser.tabs.group({ + createProperties: { windowId: win.id }, + tabIds: [tab.id], + }); + + browser.test.assertEq( + await browser.sessions.getTabValue(tab.id, "my key"), + "tab value", + "setTabValue sticks to tab when tab is adopted in group in other window" + ); + + await browser.windows.remove(win.id); + browser.test.sendMessage("testComplete"); + } + + let extension = ExtensionTestUtils.loadExtension({ + manifest: { permissions: ["sessions"] }, + background, + }); + + await extension.startup(); + await extension.awaitMessage("testComplete"); + await extension.unload(); +}); + add_task(async function test_sessions_window_value() { info("Testing set/get/deleteWindowValue."); diff --git a/browser/components/sessionstore/SessionStore.sys.mjs b/browser/components/sessionstore/SessionStore.sys.mjs @@ -1904,6 +1904,9 @@ var SessionStoreInternal = { switch (aEvent.type) { case "TabOpen": this.onTabAdd(win); + if (aEvent.detail.adoptedTab) { + this.moveCustomTabValue(aEvent.detail.adoptedTab, target); + } break; case "TabBrowserInserted": this.onTabBrowserInserted(win, target); @@ -1912,6 +1915,7 @@ var SessionStoreInternal = { // `adoptedBy` will be set if the tab was closed because it is being // moved to a new window. if (aEvent.detail.adoptedBy) { + this.moveCustomTabValue(target, aEvent.detail.adoptedBy); this.onMoveToNewWindow( target.linkedBrowser, aEvent.detail.adoptedBy.linkedBrowser @@ -4962,6 +4966,17 @@ var SessionStoreInternal = { } }, + moveCustomTabValue(aFromTab, aToTab) { + let state = TAB_CUSTOM_VALUES.get(aFromTab); + if (state) { + TAB_CUSTOM_VALUES.set(aToTab, state); + TAB_CUSTOM_VALUES.delete(aFromTab); + // No saveStateDelayed calls for either window here, because the callers + // of moveCustomTabValue already call saveStateDelayed for both windows + // as needed, from onTabAdd and onTabRemove. + } + }, + /** * Retrieves data specific to lazy-browser tabs. If tab is not lazy, * will return undefined.