tor-browser

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

commit 8e7e26472b2441bd235c6c4bff463f9e43cb5866
parent 91433997c262acd9e848fe87ab47d96ee767a41b
Author: Florian Zia <fzia@mozilla.com>
Date:   Fri,  2 Jan 2026 21:57:26 +0000

Bug 2003063 - Part 2: Add a new mode to SmartBar r=mak,frontend-codestyle-reviewers,urlbar-reviewers,ai-frontend-reviewers,Standard8

Adds a smartbar mode with the initial multiline editor support. The flag #isSmarbarMode and early returns serve as safety guards for addressbar specific behaviour until we get to merge back together with UrlbarInput.

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

Diffstat:
Mbrowser/base/content/browser-main.js | 3+++
Mbrowser/components/aiwindow/ui/modules/AIWindow.sys.mjs | 17++++++++++++++++-
Mbrowser/components/genai/content/smart-assist.mjs | 23+++++++++++++++++++++++
Mbrowser/components/urlbar/content/SmartbarInput.mjs | 188+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Abrowser/components/urlbar/content/SmartbarInputController.mjs | 34++++++++++++++++++++++++++++++++++
Abrowser/components/urlbar/content/SmartbarInputUtils.mjs | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mbrowser/components/urlbar/jar.mn | 6++++--
Mbrowser/themes/shared/browser-shared.css | 1+
Mbrowser/themes/shared/jar.inc.mn | 1+
Abrowser/themes/shared/smartbar.css | 25+++++++++++++++++++++++++
Mstylelint-rollouts.config.js | 1+
11 files changed, 341 insertions(+), 45 deletions(-)

diff --git a/browser/base/content/browser-main.js b/browser/base/content/browser-main.js @@ -32,6 +32,9 @@ Services.scriptloader.loadSubScript("chrome://browser/content/places/places-menupopup.js", this); Services.scriptloader.loadSubScript("chrome://browser/content/search/autocomplete-popup.js", this); Services.scriptloader.loadSubScript("chrome://browser/content/search/searchbar.js", this); + if (AIWindow.isOpeningAIWindow(window)) { + ChromeUtils.importESModule("chrome://browser/content/urlbar/SmartbarInput.mjs", { global: "current" }); + } ChromeUtils.importESModule("chrome://browser/content/urlbar/UrlbarInput.mjs", { global: "current" }); } diff --git a/browser/components/aiwindow/ui/modules/AIWindow.sys.mjs b/browser/components/aiwindow/ui/modules/AIWindow.sys.mjs @@ -102,7 +102,7 @@ export const AIWindow = { /** * Is current window an AI Window * - * @param {object} win current Window + * @param {Window} win current Window * @returns {boolean} whether current Window is an AI Window */ isAIWindowActive(win) { @@ -123,6 +123,21 @@ export const AIWindow = { }, /** + * Check if window is being opened as an AI Window. + * + * @param {Window} win - The window to check + * @returns {boolean} whether the window is being opened as an AI Window + */ + isOpeningAIWindow(win) { + const windowArgs = win?.arguments?.[1]; + if (!(windowArgs instanceof Ci.nsIPropertyBag2)) { + return false; + } + + return windowArgs.hasKey("ai-window"); + }, + + /** * Is AI Window content page active * * @param {nsIURI} uri current URI diff --git a/browser/components/genai/content/smart-assist.mjs b/browser/components/genai/content/smart-assist.mjs @@ -305,6 +305,28 @@ export class SmartAssist extends MozLitElement { } } + /** + * Helper method to get or create the smartbar element + * + * @param {Document} chromeDoc - The chrome document + * @param {Element} box - The container element + */ + _getOrCreateSmartbar(chromeDoc, box) { + // 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"); + box.append(smartbar); + } + return smartbar; + } + _toggleAIWindowSidebar() { const chromeDoc = this._getChromeDocument(); const box = chromeDoc.getElementById("ai-window-box"); @@ -315,6 +337,7 @@ export class SmartAssist extends MozLitElement { } this._getOrCreateBrowser(chromeDoc, box); + this._getOrCreateSmartbar(chromeDoc, box); // Toggle visibility const opening = box.hidden; diff --git a/browser/components/urlbar/content/SmartbarInput.mjs b/browser/components/urlbar/content/SmartbarInput.mjs @@ -12,6 +12,7 @@ const { AppConstants } = ChromeUtils.importESModule( /** * @import {UrlbarSearchOneOffs} from "moz-src:///browser/components/urlbar/UrlbarSearchOneOffs.sys.mjs" + * @import {SmartbarInputController} from "chrome://browser/content/urlbar/SmartbarInputController.mjs" */ const lazy = XPCOMUtils.declareLazy({ @@ -31,6 +32,8 @@ const lazy = XPCOMUtils.declareLazy({ "moz-src:///browser/components/urlbar/SearchModeSwitcher.sys.mjs", SearchUIUtils: "moz-src:///browser/components/search/SearchUIUtils.sys.mjs", SearchUtils: "moz-src:///toolkit/components/search/SearchUtils.sys.mjs", + SmartbarInputController: + "chrome://browser/content/urlbar/SmartbarInputController.mjs", UrlbarController: "moz-src:///browser/components/urlbar/UrlbarController.sys.mjs", UrlbarEventBufferer: @@ -65,7 +68,11 @@ const lazy = XPCOMUtils.declareLazy({ pref: "privacy.query_stripping.strip_on_share.enabled", default: false, }, - logger: () => lazy.UrlbarUtils.getLogger({ prefix: "Input" }), + createEditor: () => + ChromeUtils.importESModule( + "chrome://browser/content/urlbar/SmartbarInputUtils.mjs" + ).createEditor, + logger: () => lazy.UrlbarUtils.getLogger({ prefix: "SmartbarInput" }), }); const UNLIMITED_MAX_RESULTS = 99; @@ -77,7 +84,7 @@ let px = number => number.toFixed(2) + "px"; /** * Implements the text input part of the address bar UI. */ -export class UrlbarInput extends HTMLElement { +export class SmartbarInput extends HTMLElement { static get #markup() { return ` <hbox class="urlbar-background"/> @@ -156,17 +163,6 @@ export class UrlbarInput extends HTMLElement { </vbox>`; } - /** @type {DocumentFragment} */ - static get fragment() { - if (!UrlbarInput.#fragment) { - UrlbarInput.#fragment = window.MozXULElement.parseXULToFragment( - UrlbarInput.#markup - ); - } - // @ts-ignore - return document.importNode(UrlbarInput.#fragment, true); - } - /** * @type {DocumentFragment=} * @@ -174,6 +170,15 @@ export class UrlbarInput extends HTMLElement { */ static #fragment; + /** @type {DocumentFragment} */ + static get fragment() { + if (!this.#fragment) { + this.#fragment = window.MozXULElement.parseXULToFragment(this.#markup); + } + // @ts-ignore + return document.importNode(this.#fragment, true); + } + static #inputFieldEvents = [ "compositionstart", "compositionend", @@ -200,7 +205,19 @@ export class UrlbarInput extends HTMLElement { #gBrowserListenersAdded = false; #breakoutBlockerCount = 0; #isAddressbar = false; + /** + * `True` if this instance is in `smartbar` mode. + * + * Smartbar mode is enabled by adding the attribute `sap-name="smartbar"`. + * Both `#isSmartbarMode` and `#isAddressbar` are `false` if `sap-name` is neither + * `smartbar` nor `urlbar`. + */ + #isSmartbarMode = false; #sapName = ""; + /** @type {object | null} */ + #smartbarEditor = null; + /** @type {SmartbarEditorController | null} */ + #smartbarEditorController = null; _userTypedValue = ""; _actionOverrideKeyCount = 0; _lastValidURLStr = ""; @@ -277,6 +294,7 @@ export class UrlbarInput extends HTMLElement { #initOnce() { this.#sapName = this.getAttribute("sap-name"); this.#isAddressbar = this.#sapName == "urlbar"; + this.#isSmartbarMode = this.#sapName == "smartbar"; // This listener must be added before connecting the fragment // because the event could fire while or after connecting it. @@ -285,7 +303,7 @@ export class UrlbarInput extends HTMLElement { this.#onContextMenuRebuilt.bind(this) ); - this.appendChild(UrlbarInput.fragment); + this.appendChild(SmartbarInput.fragment); // Make sure all children have been parsed before calling #populateSlots. if (document.readyState === "loading") { @@ -302,6 +320,9 @@ export class UrlbarInput extends HTMLElement { this.inputField = /** @type {HTMLInputElement} */ ( this.querySelector(".urlbar-input") ); + if (this.#isSmartbarMode) { + this.#ensureSmartbarEditor(); + } this._inputContainer = this.querySelector(".urlbar-input-container"); this.controller = new lazy.UrlbarController({ input: this }); @@ -373,7 +394,7 @@ export class UrlbarInput extends HTMLElement { this._initCopyCutController(); - for (let event of UrlbarInput.#inputFieldEvents) { + for (let event of SmartbarInput.#inputFieldEvents) { this.inputField.addEventListener(event, this); } @@ -460,7 +481,7 @@ export class UrlbarInput extends HTMLElement { delete this._copyCutController; } - for (let event of UrlbarInput.#inputFieldEvents) { + for (let event of SmartbarInput.#inputFieldEvents) { this.inputField.removeEventListener(event, this); } @@ -515,6 +536,10 @@ export class UrlbarInput extends HTMLElement { } addGBrowserListeners() { + // The following listeners are only used for the address bar. + if (!this.#isAddressbar) { + return; + } if (this.window.gBrowser && !this.#gBrowserListenersAdded) { this.window.gBrowser.tabContainer.addEventListener("TabSelect", this); this.window.gBrowser.tabContainer.addEventListener("TabClose", this); @@ -523,6 +548,23 @@ export class UrlbarInput extends HTMLElement { } } + #initSmartbarEditor() { + const adapter = lazy.createEditor(this.inputField); + if (!adapter) { + return; + } + this.#smartbarEditorController = new lazy.SmartbarInputController(adapter); + this.inputField = adapter.input; + this.#smartbarEditor = adapter.editor; + } + + #ensureSmartbarEditor() { + if (!this.#smartbarEditorController) { + this.#initSmartbarEditor(); + } + return this.#smartbarEditor; + } + #lazy = XPCOMUtils.declareLazy({ valueFormatter: () => new lazy.UrlbarValueFormatter(this), addSearchEngineHelper: () => new AddSearchEngineHelper(this), @@ -536,7 +578,7 @@ export class UrlbarInput extends HTMLElement { } /** - * The search access point name of the UrlbarInput for use with telemetry or + * The search access point name of the SmartbarInput for use with telemetry or * logging, e.g. `urlbar`, `searchbar`. */ get sapName() { @@ -707,7 +749,7 @@ export class UrlbarInput extends HTMLElement { } = {}) { if (!this.#isAddressbar) { throw new Error( - "Cannot set URI for UrlbarInput that is not an address bar" + "Cannot set URI for SmartbarInput that is not an address bar" ); } // We only need to update the searchModeUI on tab switch conditionally @@ -950,10 +992,10 @@ export class UrlbarInput extends HTMLElement { try { this[methodName](event); } catch (e) { - console.error(`Error calling UrlbarInput::${methodName}:`, e); + console.error(`Error calling SmartbarInput::${methodName}:`, e); } } else { - throw new Error("Unrecognized UrlbarInput event: " + event.type); + throw new Error("Unrecognized SmartbarInput event: " + event.type); } } @@ -1017,6 +1059,20 @@ export class UrlbarInput extends HTMLElement { * The principal that the action was triggered from. */ handleNavigation({ event, oneOffParams, triggeringPrincipal }) { + if (this.#isSmartbarMode) { + const committedValue = this.untrimmedValue; + lazy.logger.debug(`commit: ${committedValue}`); + this.#clearSmartbarInput(); + this.dispatchEvent( + new CustomEvent("smartbar-commit", { + detail: { value: committedValue, event }, + }) + ); + if (!this.window.gBrowser) { + return; + } + // Fall through to default navigation behaviour. + } let element = this.view.selectedElement; let result = this.view.getResultFromElement(element); let openParams = oneOffParams?.openParams || { triggeringPrincipal }; @@ -1259,6 +1315,9 @@ export class UrlbarInput extends HTMLElement { } maybeHandleRevertFromPopup(anchorElement) { + if (!this.#isAddressbar) { + return; + } let state = this.getBrowserState(this.window.gBrowser.selectedBrowser); if (anchorElement?.closest("#urlbar") && state.persist?.shouldPersist) { this.handleRevert(); @@ -1768,6 +1827,15 @@ export class UrlbarInput extends HTMLElement { ); } + #clearSmartbarInput() { + this.value = ""; + this.userTypedValue = ""; + this._lastSearchString = ""; + this._autofillPlaceholder = null; + this._resultForCurrentValue = null; + this.setSelectionRange(0, 0); + } + /** * Called by the view when moving through results with the keyboard, and when * picking a result. This sets the input value to the value of the result and @@ -2262,7 +2330,6 @@ export class UrlbarInput extends HTMLElement { * * @param {MozBrowser} browser * The search mode for this browser will be returned. - * Pass the selected browser for the searchbar. * @param {boolean} [confirmedOnly] * Normally, if the browser has both preview and confirmed modes, preview * mode will be returned since it takes precedence. If this argument is @@ -2310,6 +2377,9 @@ export class UrlbarInput extends HTMLElement { * Pass the selected browser for the searchbar. */ async setSearchMode(searchMode, browser) { + if (this.#isSmartbarMode) { + return; + } let currentSearchMode = this.getSearchMode(browser); let areSearchModesSame = (!currentSearchMode && !searchMode) || @@ -2447,9 +2517,11 @@ export class UrlbarInput extends HTMLElement { * Restores the current browser search mode from a previously stored state. */ restoreSearchModeState() { - this.searchMode = this.#getSearchModesObject( - this.window.gBrowser.selectedBrowser - ).confirmed; + if (this.#isSmartbarMode) { + return; + } + let state = this.getBrowserState(this.window.gBrowser.selectedBrowser); + this.searchMode = state.searchModes?.confirmed; } /** @@ -2489,6 +2561,9 @@ export class UrlbarInput extends HTMLElement { // Getters and Setters below. get editor() { + if (this.#isSmartbarMode) { + return this.#ensureSmartbarEditor(); + } return this.inputField.editor; } @@ -2531,6 +2606,9 @@ export class UrlbarInput extends HTMLElement { } get searchMode() { + if (this.#isSmartbarMode) { + return null; + } if (!this.window.gBrowser) { // This only happens before DOMContentLoaded. return null; @@ -2539,6 +2617,9 @@ export class UrlbarInput extends HTMLElement { } set searchMode(searchMode) { + if (this.#isSmartbarMode) { + return; + } this.setSearchMode(searchMode, this.window.gBrowser.selectedBrowser); this.searchModeSwitcher?.onSearchModeChanged(); lazy.UrlbarSearchTermsPersistence.onSearchModeChanged(this.window); @@ -2634,6 +2715,9 @@ export class UrlbarInput extends HTMLElement { updatePopupNotifications, forceUnifiedSearchButtonAvailable = false ) { + if (!this.#isAddressbar) { + return; + } let prevState = this.getAttribute("pageproxystate"); this.setAttribute("pageproxystate", state); @@ -3607,6 +3691,10 @@ export class UrlbarInput extends HTMLElement { // beginning. Do not allow it to be trimmed. this._setValue(value, { untrimmedValue }); this.inputField.setSelectionRange(selectionStart, selectionEnd); + // Ensure selection state is cached for contenteditable and events fire. + this.inputField.dispatchEvent( + new Event("selectionchange", { bubbles: true, cancelable: false }) + ); this._autofillPlaceholder = { value, type, @@ -3916,6 +4004,10 @@ export class UrlbarInput extends HTMLElement { } _initCopyCutController() { + // Clipboard handling is managed by the multiline editor in smartbar mode. + if (this.#isSmartbarMode) { + return; + } if (this._copyCutController) { return; } @@ -4366,6 +4458,9 @@ export class UrlbarInput extends HTMLElement { isSameDocument, uri, }) { + if (!this.#isAddressbar) { + return false; + } if (!lazy.UrlbarPrefs.isPersistedSearchTermsEnabled()) { if (state.persist) { this.removeAttribute("persistsearchterms"); @@ -4516,6 +4611,9 @@ export class UrlbarInput extends HTMLElement { * @param {boolean} available If true Unified Search Button will be available. */ setUnifiedSearchButtonAvailability(available) { + if (this.#isSmartbarMode) { + return; + } this.toggleAttribute("unifiedsearchbutton-available", available); this.getBrowserState( this.window.gBrowser.selectedBrowser @@ -4940,19 +5038,21 @@ export class UrlbarInput extends HTMLElement { this.setPageProxyState("invalid", true); } - let state = this.getBrowserState(this.window.gBrowser.selectedBrowser); - if ( - state.persist?.shouldPersist && - this.value !== state.persist.searchTerms - ) { - state.persist.shouldPersist = false; - this.removeAttribute("persistsearchterms"); + if (this.#isAddressbar) { + let state = this.getBrowserState(this.window.gBrowser.selectedBrowser); + if ( + state.persist?.shouldPersist && + this.value !== state.persist.searchTerms + ) { + state.persist.shouldPersist = false; + this.removeAttribute("persistsearchterms"); + } } if (this.view.isOpen) { if (lazy.UrlbarPrefs.get("closeOtherPanelsOnOpen")) { - // UrlbarView rolls up all popups when it opens, but we should - // do the same for UrlbarInput when it's already open in case + // SmartbarView rolls up all popups when it opens, but we should + // do the same for SmartbarInput when it's already open in case // a tab preview was opened this.window.docShell.treeOwner .QueryInterface(Ci.nsIInterfaceRequestor) @@ -5208,11 +5308,6 @@ export class UrlbarInput extends HTMLElement { sapName: this.sapName, maxResults, searchString, - userContextId: parseInt( - this.window.gBrowser.selectedBrowser.getAttribute("usercontextid") || 0 - ), - tabGroup: this.window.gBrowser.selectedTab.group?.id ?? null, - currentPage: this.window.gBrowser.currentURI.spec, prohibitRemoteResults: event && lazy.UrlbarUtils.isPasteEvent(event) && @@ -5220,6 +5315,15 @@ export class UrlbarInput extends HTMLElement { event.data?.length, }; + // Only add gBrowser-dependent properties if gBrowser exists. + if (this.window.gBrowser) { + options.userContextId = parseInt( + this.window.gBrowser.selectedBrowser?.getAttribute("usercontextid") ?? 0 + ); + options.tabGroup = this.window.gBrowser.selectedTab.group?.id ?? null; + options.currentPage = this.window.gBrowser.currentURI?.spec ?? ""; + } + if (this.searchMode) { options.searchMode = this.searchMode; if (this.searchMode.source) { @@ -5784,8 +5888,8 @@ function losslessDecodeURI(aURI) { */ class CopyCutController { /** - * @param {UrlbarInput} urlbar - * The UrlbarInput instance to use this controller for. + * @param {SmartbarInput} urlbar + * The SmartbarInput instance to use this controller for. */ constructor(urlbar) { this.urlbar = urlbar; @@ -5868,7 +5972,7 @@ class AddSearchEngineHelper { shortcutButtons; /** - * @param {UrlbarInput} input The parent UrlbarInput. + * @param {SmartbarInput} input The parent SmartbarInput. */ constructor(input) { this.input = input; @@ -6007,4 +6111,4 @@ class AddSearchEngineHelper { } } -customElements.define("moz-urlbar", UrlbarInput); +customElements.define("moz-smartbar", SmartbarInput); diff --git a/browser/components/urlbar/content/SmartbarInputController.mjs b/browser/components/urlbar/content/SmartbarInputController.mjs @@ -0,0 +1,34 @@ +/* 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/. */ + +/** + * Controller for the Smartbar editor. + * + * The controller abstracts the underlying editor implementation allowing + * the Smartbar to also work with a standard HTML input. + * + * @property {Element} input - The input element or object. + * @property {object} editor - The editor object. + * @property {object} adapter - The adapter providing input and editor references. + * @property {boolean} readOnly - Whether the input is read-only. + * @property {string} placeholder - The placeholder text. + * @property {string} value - The current value of the input. + * @property {number} selectionStart - The start offset of the selection. + * @property {number} selectionEnd - The end offset of the selection. + * @property {boolean} composing - Whether the editor is in composition mode. + * @property {number} selectionRangeCount - The number of selection ranges. + */ +class SmartbarInputController { + constructor(adapter) { + this.adapter = adapter; + this.input = adapter?.input ?? null; + this.editor = adapter?.editor ?? null; + } + + focus() { + this.input?.focus(); + } +} + +export { SmartbarInputController }; diff --git a/browser/components/urlbar/content/SmartbarInputUtils.mjs b/browser/components/urlbar/content/SmartbarInputUtils.mjs @@ -0,0 +1,87 @@ +/* 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/. */ + +import { MozLitElement } from "chrome://global/content/lit-utils.mjs"; + +/** + * Minimal multiline editor placeholder for SmartBarInput. + */ +class SmartbarEditor extends MozLitElement { + createRenderRoot() { + return this; + } + + get value() { + return this.textContent ?? ""; + } + + set value(val) { + this.textContent = val ?? ""; + } + + initializeFromInput(inputElement) { + if (!inputElement) { + return null; + } + + // Copy existing input attributes. + for (const inputAttribute of inputElement.attributes) { + this.setAttribute(inputAttribute.name, inputAttribute.value); + } + + this.setAttribute("contenteditable", "true"); + this.setAttribute("aria-multiline", "true"); + this.removeAttribute("type"); + this.removeAttribute("value"); + this.className = inputElement.className; + this.textContent = inputElement.value ?? ""; + + inputElement.replaceWith(this); + return { input: this, editor: createEditorAdapter(this) }; + } +} + +function createEditor(inputElement) { + if (!inputElement) { + return null; + } + if (inputElement.localName == "moz-smartbar-editor") { + return { + input: inputElement, + editor: createEditorAdapter(inputElement), + }; + } + const host = inputElement.ownerDocument.createElement("moz-smartbar-editor"); + return host.initializeFromInput(inputElement); +} + +// Adapter for Smartbar editor element. +function createEditorAdapter(editorElement) { + return { + get composing() { + return false; + }, + selection: { + get rangeCount() { + const selection = editorElement.ownerGlobal.getSelection(); + return selection?.rangeCount ?? 0; + }, + toStringWithFormat() { + const selection = editorElement.ownerGlobal.getSelection(); + if ( + !selection || + !selection.rangeCount || + !editorElement.contains(selection.anchorNode) + ) { + return ""; + } + return selection.toString(); + }, + }, + }; +} + +customElements.define("moz-smartbar-editor", SmartbarEditor); + +export { createEditor, createEditorAdapter }; diff --git a/browser/components/urlbar/jar.mn b/browser/components/urlbar/jar.mn @@ -3,5 +3,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. browser.jar: - content/browser/urlbar/SmartbarInput.mjs (content/SmartbarInput.mjs) - content/browser/urlbar/UrlbarInput.mjs (content/UrlbarInput.mjs) + content/browser/urlbar/SmartbarInput.mjs (content/SmartbarInput.mjs) + content/browser/urlbar/SmartbarInputController.mjs (content/SmartbarInputController.mjs) + content/browser/urlbar/SmartbarInputUtils.mjs (content/SmartbarInputUtils.mjs) + content/browser/urlbar/UrlbarInput.mjs (content/UrlbarInput.mjs) diff --git a/browser/themes/shared/browser-shared.css b/browser/themes/shared/browser-shared.css @@ -24,6 +24,7 @@ @import url("chrome://browser/skin/places/editBookmarkPanel.css"); @import url("chrome://browser/skin/searchbar.css"); @import url("chrome://browser/skin/sidebar.css"); +@import url("chrome://browser/skin/smartbar.css"); @import url("chrome://browser/skin/aiWindowSidebar.css"); @import url("chrome://browser/skin/customizableui/customizeMode.css"); @import url("chrome://browser/skin/UITour.css"); diff --git a/browser/themes/shared/jar.inc.mn b/browser/themes/shared/jar.inc.mn @@ -27,6 +27,7 @@ skin/classic/browser/sanitizeDialog_v2.css (../shared/sanitizeDialog_v2.css) skin/classic/browser/setDesktopBackground.css (../shared/setDesktopBackground.css) skin/classic/browser/sidebar.css (../shared/sidebar.css) + skin/classic/browser/smartbar.css (../shared/smartbar.css) skin/classic/browser/toolbarbuttons.css (../shared/toolbarbuttons.css) skin/classic/browser/toolbarbutton-icons.css (../shared/toolbarbutton-icons.css) skin/classic/browser/urlbar/flight-airline.svg (../shared/urlbar/flight-airline.svg) diff --git a/browser/themes/shared/smartbar.css b/browser/themes/shared/smartbar.css @@ -0,0 +1,25 @@ +/* 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/. */ + +.smartbar { + --smartbar-min-height: var(--urlbar-min-height); + bottom: 0; + display: block; + height: auto; + min-height: var(--smartbar-min-height); + position: absolute; + width: 100%; +} + +.smartbar .urlbar-input-box { + align-items: stretch; +} + +.smartbar .urlbar-input { + box-sizing: border-box; + height: auto; + min-height: var(--smartbar-min-height); + white-space: pre-wrap; + width: 100%; +} diff --git a/stylelint-rollouts.config.js b/stylelint-rollouts.config.js @@ -171,6 +171,7 @@ module.exports = [ "browser/themes/shared/privatebrowsing/aboutPrivateBrowsing.css", "browser/themes/shared/search/searchbar.css", "browser/themes/shared/sidebar.css", + "browser/themes/shared/smartbar.css", "browser/themes/shared/syncedtabs/sidebar.css", "browser/themes/shared/tab-list-tree.css", "browser/themes/shared/tabbrowser/content-area.css",