From 4f9a932e771dfce1b9521f9d98c374b079a389dc Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Mon, 9 Feb 2026 11:37:10 +0100 Subject: [PATCH] fix: Fixed unpinned tabs not being cleared when the pref is off, b=closes #12307, c=no-component --- .../sessionstore/SessionStore-sys-mjs.patch | 54 +++++++++++-------- .../sessionstore/ZenSessionManager.sys.mjs | 26 +++++++-- 2 files changed, 54 insertions(+), 26 deletions(-) diff --git a/src/browser/components/sessionstore/SessionStore-sys-mjs.patch b/src/browser/components/sessionstore/SessionStore-sys-mjs.patch index 152104712..6284b2dc1 100644 --- a/src/browser/components/sessionstore/SessionStore-sys-mjs.patch +++ b/src/browser/components/sessionstore/SessionStore-sys-mjs.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/sessionstore/SessionStore.sys.mjs b/browser/components/sessionstore/SessionStore.sys.mjs -index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96faedf6f0b 100644 +index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2061ef7ac60371a563b4e4cd77ceab586f767a5e 100644 --- a/browser/components/sessionstore/SessionStore.sys.mjs +++ b/browser/components/sessionstore/SessionStore.sys.mjs @@ -127,6 +127,9 @@ const TAB_EVENTS = [ @@ -79,7 +79,15 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f !lazy.SessionStartup.willRestore() ) { // We want to split the window up into pinned tabs and unpinned tabs. -@@ -2239,6 +2248,15 @@ var SessionStoreInternal = { +@@ -2211,6 +2220,7 @@ var SessionStoreInternal = { + } + + if (newWindowState) { ++ lazy.ZenSessionStore.onRestoringClosedWindow(newWindowState); + // Ensure that the window state isn't hidden + this._restoreCount = 1; + let state = { windows: [newWindowState] }; +@@ -2239,6 +2249,15 @@ var SessionStoreInternal = { }); this._shouldRestoreLastSession = false; } @@ -95,7 +103,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f if (this._restoreLastWindow && aWindow.toolbar.visible) { // always reset (if not a popup window) -@@ -2383,7 +2401,7 @@ var SessionStoreInternal = { +@@ -2383,7 +2402,7 @@ var SessionStoreInternal = { var tabbrowser = aWindow.gBrowser; @@ -104,7 +112,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f TAB_EVENTS.forEach(function (aEvent) { tabbrowser.tabContainer.removeEventListener(aEvent, this, true); -@@ -2434,7 +2452,7 @@ var SessionStoreInternal = { +@@ -2434,7 +2453,7 @@ var SessionStoreInternal = { let isLastRegularWindow = Object.values(this._windows).filter( @@ -113,7 +121,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f ).length == 1; this._log.debug( `onClose, closing window isLastRegularWindow? ${isLastRegularWindow}` -@@ -2491,8 +2509,8 @@ var SessionStoreInternal = { +@@ -2491,8 +2510,8 @@ var SessionStoreInternal = { // 2) Flush the window. // 3) When the flush is complete, revisit our decision to store the window // in _closedWindows, and add/remove as necessary. @@ -124,7 +132,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f } completionPromise = lazy.TabStateFlusher.flushWindow(aWindow).then(() => { -@@ -2512,8 +2530,9 @@ var SessionStoreInternal = { +@@ -2512,8 +2531,9 @@ var SessionStoreInternal = { // Save non-private windows if they have at // least one saveable tab or are the last window. @@ -136,7 +144,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f if (!isLastWindow && winData.closedId > -1) { this._addClosedAction( -@@ -2589,7 +2608,7 @@ var SessionStoreInternal = { +@@ -2589,7 +2609,7 @@ var SessionStoreInternal = { * to call this method again asynchronously (for example, after * a window flush). */ @@ -145,7 +153,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f // Make sure SessionStore is still running, and make sure that we // haven't chosen to forget this window. if ( -@@ -2606,6 +2625,7 @@ var SessionStoreInternal = { +@@ -2606,6 +2626,7 @@ var SessionStoreInternal = { // _closedWindows from a previous call to this function. let winIndex = this._closedWindows.indexOf(winData); let alreadyStored = winIndex != -1; @@ -153,7 +161,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f // If sidebar command is truthy, i.e. sidebar is open, store sidebar settings let shouldStore = hasSaveableTabs || isLastWindow; -@@ -3408,7 +3428,7 @@ var SessionStoreInternal = { +@@ -3408,7 +3429,7 @@ var SessionStoreInternal = { if (!isPrivateWindow && tabState.isPrivate) { return; } @@ -162,7 +170,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f return; } -@@ -4129,6 +4149,12 @@ var SessionStoreInternal = { +@@ -4129,6 +4150,12 @@ var SessionStoreInternal = { Math.min(tabState.index, tabState.entries.length) ); tabState.pinned = false; @@ -175,7 +183,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f if (inBackground === false) { aWindow.gBrowser.selectedTab = newTab; -@@ -4565,6 +4591,8 @@ var SessionStoreInternal = { +@@ -4565,6 +4592,8 @@ var SessionStoreInternal = { // Append the tab if we're opening into a different window, tabIndex: aSource == aTargetWindow ? pos : Infinity, pinned: state.pinned, @@ -184,7 +192,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f userContextId: state.userContextId, skipLoad: true, preferredRemoteType, -@@ -5414,7 +5442,7 @@ var SessionStoreInternal = { +@@ -5414,7 +5443,7 @@ var SessionStoreInternal = { for (let i = tabbrowser.pinnedTabCount; i < tabbrowser.tabs.length; i++) { let tab = tabbrowser.tabs[i]; @@ -193,7 +201,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f removableTabs.push(tab); } } -@@ -5525,7 +5553,7 @@ var SessionStoreInternal = { +@@ -5525,7 +5554,7 @@ var SessionStoreInternal = { // collect the data for all windows for (ix in this._windows) { @@ -202,7 +210,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f // window data is still in _statesToRestore continue; } -@@ -5668,11 +5696,12 @@ var SessionStoreInternal = { +@@ -5668,11 +5697,12 @@ var SessionStoreInternal = { } let tabbrowser = aWindow.gBrowser; @@ -216,7 +224,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f // update the internal state data for this window for (let tab of tabs) { if (tab == aWindow.FirefoxViewHandler.tab) { -@@ -5683,6 +5712,9 @@ var SessionStoreInternal = { +@@ -5683,6 +5713,9 @@ var SessionStoreInternal = { tabsData.push(tabData); } @@ -226,7 +234,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f // update tab group state for this window winData.groups = []; for (let tabGroup of aWindow.gBrowser.tabGroups) { -@@ -5695,7 +5727,7 @@ var SessionStoreInternal = { +@@ -5695,7 +5728,7 @@ var SessionStoreInternal = { // a window is closed, point to the first item in the tab strip instead (it will never be the Firefox View tab, // since it's only inserted into the tab strip after it's selected). if (aWindow.FirefoxViewHandler.tab?.selected) { @@ -235,7 +243,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f winData.title = tabbrowser.tabs[0].label; } winData.selected = selectedIndex; -@@ -5810,8 +5842,8 @@ var SessionStoreInternal = { +@@ -5810,8 +5843,8 @@ var SessionStoreInternal = { // selectTab represents. let selectTab = 0; if (overwriteTabs) { @@ -246,7 +254,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f selectTab = Math.min(selectTab, winData.tabs.length); } -@@ -5833,6 +5865,7 @@ var SessionStoreInternal = { +@@ -5833,6 +5866,7 @@ var SessionStoreInternal = { if (overwriteTabs) { for (let i = tabbrowser.browsers.length - 1; i >= 0; i--) { if (!tabbrowser.tabs[i].selected) { @@ -254,7 +262,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f tabbrowser.removeTab(tabbrowser.tabs[i]); } } -@@ -5866,6 +5899,12 @@ var SessionStoreInternal = { +@@ -5866,6 +5900,12 @@ var SessionStoreInternal = { savedTabGroup => !openTabGroupIdsInWindow.has(savedTabGroup.id) ); } @@ -267,7 +275,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f // Move the originally open tabs to the end. if (initialTabs) { -@@ -6419,6 +6458,25 @@ var SessionStoreInternal = { +@@ -6419,6 +6459,25 @@ var SessionStoreInternal = { // Most of tabData has been restored, now continue with restoring // attributes that may trigger external events. @@ -293,7 +301,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f if (tabData.pinned) { tabbrowser.pinTab(tab); -@@ -6567,6 +6625,9 @@ var SessionStoreInternal = { +@@ -6567,6 +6626,9 @@ var SessionStoreInternal = { aWindow.gURLBar.readOnly = false; } } @@ -303,7 +311,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f let promiseParts = Promise.withResolvers(); aWindow.setTimeout(() => { -@@ -7343,7 +7404,7 @@ var SessionStoreInternal = { +@@ -7343,7 +7405,7 @@ var SessionStoreInternal = { let groupsToSave = new Map(); for (let tIndex = 0; tIndex < window.tabs.length; ) { @@ -312,7 +320,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f // Adjust window.selected if (tIndex + 1 < window.selected) { window.selected -= 1; -@@ -7358,7 +7419,7 @@ var SessionStoreInternal = { +@@ -7358,7 +7420,7 @@ var SessionStoreInternal = { ); // We don't want to increment tIndex here. continue; diff --git a/src/zen/sessionstore/ZenSessionManager.sys.mjs b/src/zen/sessionstore/ZenSessionManager.sys.mjs index e8fb15186..8e5eaa3df 100644 --- a/src/zen/sessionstore/ZenSessionManager.sys.mjs +++ b/src/zen/sessionstore/ZenSessionManager.sys.mjs @@ -387,6 +387,25 @@ export class nsZenSessionManager { return initialState; } + onRestoringClosedWindow(aWinData) { + // We only want to save all pinned tabs if the user preference allows it. + // See https://github.com/zen-browser/desktop/issues/12307 + if (this.#shouldRestoreOnlyPinned && aWinData?.tabs?.length) { + this.log("Restoring only pinned tabs for closed window"); + this.#filterUnpinnedTabs(aWinData); + } + } + + /** + * Filters out all unpinned tabs and groups from the given window data object. + * + * @param {object} aWindow - The window data object to filter. + */ + #filterUnpinnedTabs(aWindow) { + aWindow.tabs = aWindow.tabs.filter((tab) => tab.pinned); + aWindow.groups = aWindow.groups?.filter((group) => group.pinned); + } + /** * Determines if a given window data object is saveable. * @@ -627,18 +646,19 @@ export class nsZenSessionManager { ); let windowToClone = windows[0] || {}; let newWindow = Cu.cloneInto(windowToClone, {}); + let shouldRestoreOnlyPinned = !lazy.gWindowSyncEnabled || lazy.gSyncOnlyPinnedTabs; if (windows.length < 2) { // We only want to restore the sidebar object if we found // only one normal window to clone from (which is the one // we are opening). this.log("Restoring sidebar data into new window"); this.#restoreWindowData(newWindow); + shouldRestoreOnlyPinned ||= this.#shouldRestoreOnlyPinned; } newWindow.tabs = this.#filterUnusedTabs(newWindow.tabs || []); - if (!lazy.gWindowSyncEnabled || lazy.gSyncOnlyPinnedTabs) { + if (shouldRestoreOnlyPinned) { // Don't bring over any unpinned tabs if window sync is disabled or if syncing only pinned tabs. - newWindow.tabs = newWindow.tabs.filter((tab) => tab.pinned); - newWindow.groups = newWindow.groups?.filter((group) => group.pinned); + this.#filterUnpinnedTabs(newWindow); } // These are window-specific from the previous window state that