tor-browser

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

commit 954449162966ffb0853b159c8bf5f1b5410b3344
parent d2894a5af8a8a56011b5740bab1e99a4aa84235d
Author: Atila Butkovits <abutkovits@mozilla.com>
Date:   Mon,  5 Jan 2026 19:44:18 +0200

Revert "Bug 2007135 - Create Sidebar service to control sidebar state from other location in the window r=ai-frontend-reviewers,Gijs" for causing build bustages.

This reverts commit 39cd7bea2aea4afcef9b6a53b0aaad5853cb5fe9.

Diffstat:
Dbrowser/components/aiwindow/ui/modules/AIWIndowUI.sys.mjs | 145-------------------------------------------------------------------------------
Mbrowser/components/aiwindow/ui/moz.build | 1-
Mbrowser/components/aiwindow/ui/test/browser/browser.toml | 2--
Dbrowser/components/aiwindow/ui/test/browser/browser_aiwindowui.js | 138-------------------------------------------------------------------------------
Mbrowser/components/genai/content/smart-assist.mjs | 103++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
5 files changed, 100 insertions(+), 289 deletions(-)

diff --git a/browser/components/aiwindow/ui/modules/AIWIndowUI.sys.mjs b/browser/components/aiwindow/ui/modules/AIWIndowUI.sys.mjs @@ -1,145 +0,0 @@ -/** - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -const AIWINDOW_SIDEBAR_URL = - "chrome://browser/content/aiwindow/aiWindow.html#mode=sidebar"; - -export const AIWindowUI = { - BOX_ID: "ai-window-box", - SPLITTER_ID: "ai-window-splitter", - BROWSER_ID: "ai-window-browser", - STACK_CLASS: "ai-window-browser-stack", - - /** - * @param {Window} win - * @returns {{ chromeDoc: Document, box: Element, splitter: Element } | null} - */ - _getSidebarElements(win) { - if (!win) { - return null; - } - const chromeDoc = win.document; - const box = chromeDoc.getElementById(this.BOX_ID); - const splitter = chromeDoc.getElementById(this.SPLITTER_ID); - - if (!box || !splitter) { - return null; - } - return { chromeDoc, box, splitter }; - }, - - /** - * Ensure the aiwindow <browser> exists under the sidebar box. - * - * @param {Document} chromeDoc - * @param {Element} box - * @returns {XULElement} browser - */ - ensureBrowserIsAppended(chromeDoc, box) { - const existingBrowser = chromeDoc.getElementById(this.BROWSER_ID); - if (existingBrowser) { - // Already exists - return existingBrowser; - } - - const stack = box.querySelector(`.${this.STACK_CLASS}`); - - if (!stack.isConnected) { - stack.className = this.STACK_CLASS; - stack.setAttribute("flex", "1"); - box.appendChild(stack); - } - - const browser = chromeDoc.createXULElement("browser"); - browser.id = this.BROWSER_ID; - browser.setAttribute("transparent", "true"); - browser.setAttribute("flex", "1"); - browser.setAttribute("disablehistory", "true"); - browser.setAttribute("disablefullscreen", "true"); - browser.setAttribute("tooltip", "aHTMLTooltip"); - browser.setAttribute("src", AIWINDOW_SIDEBAR_URL); - stack.appendChild(browser); - return browser; - }, - - /** - * @param {Window} win - * @returns {boolean} whether the sidebar is open (visible) - */ - isSidebarOpen(win) { - const nodes = this._getSidebarElements(win); - if (!nodes) { - return false; - } - // The sidebar is considered open if the box is visible - return !nodes.box.hidden; - }, - - /** - * Open the AI Window sidebar - * - * @param {Window} win - */ - openSidebar(win) { - const nodes = this._getSidebarElements(win); - - if (!nodes) { - return; - } - - const { chromeDoc, box, splitter } = nodes; - - this.ensureBrowserIsAppended(chromeDoc, box); - - box.hidden = false; - splitter.hidden = false; - box.parentElement.hidden = false; - }, - - /** - * Close the AI Window sidebar. - * - * @param {Window} win - */ - closeSidebar(win) { - const nodes = this._getSidebarElements(win); - if (!nodes) { - return; - } - const { box, splitter } = nodes; - - box.hidden = true; - splitter.hidden = true; - }, - - /** - * Toggle the AI Window sidebar - * - * @param {Window} win - * @returns {boolean} true if now open, false if now closed - */ - toggleSidebar(win) { - const nodes = this._getSidebarElements(win); - if (!nodes) { - return false; - } - const { chromeDoc, box, splitter } = nodes; - - const opening = box.hidden; - if (opening) { - this.ensureBrowserIsAppended(chromeDoc, box); - } - - box.hidden = !opening; - splitter.hidden = !opening; - - if (opening && box.parentElement?.hidden) { - box.parentElement.hidden = false; - } - - return opening; - }, -}; diff --git a/browser/components/aiwindow/ui/moz.build b/browser/components/aiwindow/ui/moz.build @@ -14,7 +14,6 @@ MOZ_SRC_FILES += [ "modules/AIWindow.sys.mjs", "modules/AIWindowAccountAuth.sys.mjs", "modules/AIWindowMenu.sys.mjs", - "modules/AIWindowUI.sys.mjs", "modules/ChatConstants.sys.mjs", "modules/ChatConversation.sys.mjs", "modules/ChatEnums.sys.mjs", diff --git a/browser/components/aiwindow/ui/test/browser/browser.toml b/browser/components/aiwindow/ui/test/browser/browser.toml @@ -15,8 +15,6 @@ support-files = [ ["browser_aiwindow_transparency.js"] -["browser_aiwindowui.js"] - ["browser_open_aiwindow.js"] ["browser_sidebar_aiwindow.js"] diff --git a/browser/components/aiwindow/ui/test/browser/browser_aiwindowui.js b/browser/components/aiwindow/ui/test/browser/browser_aiwindowui.js @@ -1,138 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -const { AIWindowUI } = ChromeUtils.importESModule( - "moz-src:///browser/components/aiwindow/ui/modules/AIWindowUI.sys.mjs" -); - -add_task(async function test_aiwindowui_constants() { - is(AIWindowUI.BOX_ID, "ai-window-box", "BOX_ID constant is correct"); - is( - AIWindowUI.SPLITTER_ID, - "ai-window-splitter", - "SPLITTER_ID constant is correct" - ); - is( - AIWindowUI.BROWSER_ID, - "ai-window-browser", - "BROWSER_ID constant is correct" - ); - is( - AIWindowUI.STACK_CLASS, - "ai-window-browser-stack", - "STACK_CLASS constant is correct" - ); -}); - -add_task(async function test_aiwindowui_sidebar_operations() { - const box = document.getElementById(AIWindowUI.BOX_ID); - const splitter = document.getElementById(AIWindowUI.SPLITTER_ID); - - if (!box || !splitter) { - todo( - false, - "AI Window elements not present in this window - skipping DOM tests" - ); - return; - } - - const initialBoxHidden = box.hidden; - const initialSplitterHidden = splitter.hidden; - - try { - // Test opening - AIWindowUI.openSidebar(window); - is(box.hidden, false, "Box should be visible after opening"); - is(splitter.hidden, false, "Splitter should be visible after opening"); - is( - AIWindowUI.isSidebarOpen(window), - true, - "isSidebarOpen should return true after opening" - ); - - // Test closing - AIWindowUI.closeSidebar(window); - is(box.hidden, true, "Box should be hidden after closing"); - is(splitter.hidden, true, "Splitter should be hidden after closing"); - is( - AIWindowUI.isSidebarOpen(window), - false, - "isSidebarOpen should return false after closing" - ); - - // Test toggling from closed to open - const toggleResult1 = AIWindowUI.toggleSidebar(window); - is(toggleResult1, true, "Toggle should return true when opening"); - is(box.hidden, false, "Box should be visible after toggling open"); - is( - splitter.hidden, - false, - "Splitter should be visible after toggling open" - ); - is( - AIWindowUI.isSidebarOpen(window), - true, - "isSidebarOpen should return true after toggling open" - ); - - // Test toggling from open to closed - const toggleResult2 = AIWindowUI.toggleSidebar(window); - is(toggleResult2, false, "Toggle should return false when closing"); - is(box.hidden, true, "Box should be hidden after toggling closed"); - is( - splitter.hidden, - true, - "Splitter should be hidden after toggling closed" - ); - is( - AIWindowUI.isSidebarOpen(window), - false, - "isSidebarOpen should return false after toggling closed" - ); - } finally { - // Restore initial state - box.hidden = initialBoxHidden; - splitter.hidden = initialSplitterHidden; - } -}); - -add_task(async function test_aiwindowui_ensureBrowserIsAppended() { - const box = document.getElementById(AIWindowUI.BOX_ID); - - if (!box) { - todo( - false, - "AI Window box element not present - skipping browser creation test" - ); - return; - } - - // Remove any existing browser to start clean - let existingBrowser = document.getElementById(AIWindowUI.BROWSER_ID); - if (existingBrowser) { - existingBrowser.remove(); - } - - try { - const browser1 = AIWindowUI.ensureBrowserIsAppended(document, box); - ok(browser1, "Should create and return a browser element"); - is(browser1.id, AIWindowUI.BROWSER_ID, "Browser should have correct ID"); - ok(browser1.isConnected, "Browser should be connected to DOM"); - - // Call again - should return the same browser - const browser2 = AIWindowUI.ensureBrowserIsAppended(document, box); - is( - browser1, - browser2, - "Should return the same browser instance when called again" - ); - } finally { - // Clean up the created browser - let createdBrowser = document.getElementById(AIWindowUI.BROWSER_ID); - if (createdBrowser) { - createdBrowser.remove(); - } - } -}); diff --git a/browser/components/genai/content/smart-assist.mjs b/browser/components/genai/content/smart-assist.mjs @@ -16,8 +16,6 @@ ChromeUtils.defineESModuleGetters(lazy, { PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs", SpecialMessageActions: "resource://messaging-system/lib/SpecialMessageActions.sys.mjs", - AIWindowUI: - "moz-src:///browser/components/aiwindow/ui/modules/AIWindowUI.sys.mjs", }); const FULL_PAGE_URL = "chrome://browser/content/genai/smartAssistPage.html"; @@ -249,8 +247,107 @@ export class SmartAssist extends MozLitElement { ); } + /** + * Helper method to get the chrome document + * + * @returns {Document} The top-level chrome window's document + */ + + _getChromeDocument() { + return window.browsingContext.topChromeWindow.document; + } + + /** + * Helper method to find an element in the chrome document + * + * @param {string} id - The element ID to find + * @returns {Element|null} The found element or null + */ + + _getChromeElement(id) { + return this._getChromeDocument().getElementById(id); + } + + /** + * Helper method to get or create the AI window browser element + * + * @param {Document} chromeDoc - The chrome document + * @param {Element} box - The AI window box element + * @returns {Element} The AI window browser element + */ + + _getOrCreateBrowser(chromeDoc, box) { + let stack = box.querySelector(".ai-window-browser-stack"); + if (!stack) { + stack = chromeDoc.createXULElement("stack"); + stack.className = "ai-window-browser-stack"; + stack.setAttribute("flex", "1"); + box.appendChild(stack); + } + + let browser = stack.querySelector("#ai-window-browser"); + if (!browser) { + browser = chromeDoc.createXULElement("browser"); + browser.setAttribute("id", "ai-window-browser"); + browser.setAttribute("flex", "1"); + browser.setAttribute("disablehistory", "true"); + browser.setAttribute("disablefullscreen", "true"); + browser.setAttribute("tooltip", "aHTMLTooltip"); + + browser.setAttribute( + "src", + "chrome://browser/content/aiwindow/aiWindow.html" + ); + + stack.appendChild(browser); + } + return stack; + } + + /** + * Helper method to get or create the smartbar element + * + * @param {Document} chromeDoc - The chrome document + * @param {Element} container - The container element + */ + _getOrCreateSmartbar(chromeDoc, container) { + // Find existing Smartbar, or create it the first time we open the sidebar. + let smartbar = chromeDoc.getElementById("ai-window-smartbar"); + + if (!smartbar) { + smartbar = chromeDoc.createElement("moz-smartbar"); + smartbar.id = "ai-window-smartbar"; + smartbar.setAttribute("sap-name", "smartbar"); + smartbar.setAttribute("pageproxystate", "invalid"); + smartbar.setAttribute("popover", "manual"); + smartbar.classList.add("smartbar", "urlbar"); + container.append(smartbar); + } + return smartbar; + } + _toggleAIWindowSidebar() { - lazy.AIWindowUI.toggleSidebar(window.browsingContext.topChromeWindow); + const chromeDoc = this._getChromeDocument(); + const box = chromeDoc.getElementById("ai-window-box"); + const splitter = chromeDoc.getElementById("ai-window-splitter"); + + if (!box || !splitter) { + return; + } + + const stack = this._getOrCreateBrowser(chromeDoc, box); + this._getOrCreateSmartbar(chromeDoc, stack); + + // Toggle visibility + const opening = box.hidden; + + box.hidden = !opening; + splitter.hidden = !opening; + + // Make sure parent container is also visible + if (box.parentElement && box.parentElement.hidden) { + box.parentElement.hidden = false; + } } render() {