tor-browser

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

commit dcbcf6b14a80ee09dd7a313bfba1fa43b59007dc
parent 3c38e096408e850731b1647597cd422031ee8bcb
Author: unifolia <jlewis@mozilla.com>
Date:   Thu, 18 Dec 2025 19:25:07 +0000

Bug 2000881 - Persist AI-Window session and restore r=Gijs,sessionstore-reviewers,ai-frontend-reviewers,sthompson

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

Diffstat:
Mbrowser/base/content/utilityOverlay.js | 4++--
Mbrowser/components/aiwindow/ui/modules/AIWindow.sys.mjs | 23+++++++++++++----------
Mbrowser/components/sessionstore/SessionStore.sys.mjs | 28+++++++++++++++++++++++-----
Mbrowser/components/sessionstore/session.schema.json | 3+++
4 files changed, 41 insertions(+), 17 deletions(-)

diff --git a/browser/base/content/utilityOverlay.js b/browser/base/content/utilityOverlay.js @@ -13,6 +13,8 @@ var { XPCOMUtils } = ChromeUtils.importESModule( ChromeUtils.defineESModuleGetters(this, { AboutNewTab: "resource:///modules/AboutNewTab.sys.mjs", + AIWindow: + "moz-src:///browser/components/aiwindow/ui/modules/AIWindow.sys.mjs", BrowserUtils: "resource://gre/modules/BrowserUtils.sys.mjs", BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.sys.mjs", ContextualIdentityService: @@ -23,8 +25,6 @@ ChromeUtils.defineESModuleGetters(this, { PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs", ShellService: "moz-src:///browser/components/shell/ShellService.sys.mjs", URILoadingHelper: "resource:///modules/URILoadingHelper.sys.mjs", - AIWindow: - "moz-src:///browser/components/aiwindow/ui/modules/AIWindow.sys.mjs", }); ChromeUtils.defineLazyGetter(this, "ReferrerInfo", () => diff --git a/browser/components/aiwindow/ui/modules/AIWindow.sys.mjs b/browser/components/aiwindow/ui/modules/AIWindow.sys.mjs @@ -41,23 +41,24 @@ export const AIWindow = { * @param {object} options Used in BrowserWindowTracker.openWindow * @param {object} options.openerWindow Window making the BrowserWindowTracker.openWindow call * @param {object} options.args Array of arguments to pass to new window - * @param {boolean} options.aiWindow Should new window be AI Window - * @param {boolean} options.private Should new window be Private Window + * @param {boolean} [options.aiWindow] Should new window be AI Window (true), Classic Window (false), or inherited from opener (undefined, default) + * @param {boolean} [options.private] Should new window be Private Window + * @param {boolean} [options.restoreSession] Should previous AI Window session be restored * * @returns {object} Modified arguments appended to the options object */ handleAIWindowOptions({ openerWindow, args, - aiWindow, - private: isPrivate, + aiWindow = undefined, + private: isPrivate = false, + restoreSession = false, } = {}) { // Indicates whether the new window should inherit AI Window state from opener window const canInheritAIWindow = - this.isAIWindowEnabled() && - this.isAIWindowActive(openerWindow) && + this.isAIWindowActiveAndEnabled(openerWindow) && !isPrivate && - !aiWindow; + typeof aiWindow === "undefined"; const willOpenAIWindow = (aiWindow && this.isAIWindowEnabled()) || canInheritAIWindow; @@ -72,7 +73,7 @@ export const AIWindow = { const aiWindowURI = Cc["@mozilla.org/supports-string;1"].createInstance( Ci.nsISupportsString ); - aiWindowURI.data = AIWINDOW_URL; + aiWindowURI.data = restoreSession ? "" : AIWINDOW_URL; args.appendElement(aiWindowURI); const aiOption = Cc["@mozilla.org/hash-property-bag;1"].createInstance( @@ -91,7 +92,6 @@ export const AIWindow = { * @param {object} win current Window * @returns {boolean} whether current Window is an AI Window */ - isAIWindowActive(win) { return !!win && win.document.documentElement.hasAttribute("ai-window"); }, @@ -101,11 +101,14 @@ export const AIWindow = { * * @returns {boolean} whether AI Window is enabled */ - isAIWindowEnabled() { return this.AIWindowEnabled; }, + isAIWindowActiveAndEnabled(win) { + return this.isAIWindowActive(win) && this.AIWindowEnabled; + }, + get newTabURL() { return AIWINDOW_URL; }, diff --git a/browser/components/sessionstore/SessionStore.sys.mjs b/browser/components/sessionstore/SessionStore.sys.mjs @@ -173,6 +173,8 @@ XPCOMUtils.defineLazyServiceGetters(lazy, { }); ChromeUtils.defineESModuleGetters(lazy, { + AIWindow: + "moz-src:///browser/components/aiwindow/ui/modules/AIWindow.sys.mjs", AsyncShutdown: "resource://gre/modules/AsyncShutdown.sys.mjs", BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.sys.mjs", DevToolsShim: "chrome://devtools-startup/content/DevToolsShim.sys.mjs", @@ -2044,6 +2046,10 @@ var SessionStoreInternal = { this._windows[aWindow.__SSi].isTaskbarTab = true; } + if (lazy.AIWindow.isAIWindowActiveAndEnabled(aWindow)) { + this._windows[aWindow.__SSi].isAIWindow = true; + } + let tabbrowser = aWindow.gBrowser; // add tab change listeners to all already existing tabs @@ -6977,11 +6983,8 @@ var SessionStoreInternal = { * Object containing session data */ _openWindowWithState: function ssi_openWindowWithState(aState) { - var argString = Cc["@mozilla.org/supports-string;1"].createInstance( - Ci.nsISupportsString - ); - argString.data = ""; - + // Build arguments string + let argString; // Build feature string let features; let winState = aState.windows[0]; @@ -7024,8 +7027,23 @@ var SessionStoreInternal = { } }); + // A window CANNOT be both a Private Window and an AI Window if (winState.isPrivate) { features.push("private"); + } else if (winState.isAIWindow) { + argString = lazy.AIWindow.handleAIWindowOptions({ + openerWindow: null, + args: argString, + aiWindow: winState.isAIWindow, + restoreSession: true, + }); + } + + if (!argString) { + argString = Cc["@mozilla.org/supports-string;1"].createInstance( + Ci.nsISupportsString + ); + argString.data = ""; } this._log.debug( diff --git a/browser/components/sessionstore/session.schema.json b/browser/components/sessionstore/session.schema.json @@ -174,6 +174,9 @@ "hidden": { "type": "string" }, + "isAIWindow": { + "type": "boolean" + }, "isPopup": { "type": "boolean" },