tor-browser

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

commit f058bb0a22b2ef7382c72412bedb4a2e3de9c18d
parent f64838ecf242272eafa9e4713b9fba5362ecdcfd
Author: Stephanie Cunnane <scunnane@mozilla.com>
Date:   Thu,  4 Dec 2025 22:19:10 +0000

Bug 1972068 - Convert default search engine section of search settings to config-based prefs. r=Standard8,fluent-reviewers,desktop-theme-reviewers,hjones,bolsson

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

Diffstat:
Mbrowser/components/preferences/main.js | 26++++++++++++++++++++++++++
Mbrowser/components/preferences/search.inc.xhtml | 28+++++-----------------------
Mbrowser/components/preferences/search.js | 343+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Mbrowser/components/preferences/tests/browser_searchDefaultEngine.js | 89++++++++++++++++++++++++++++++++++++++-----------------------------------------
Mbrowser/components/preferences/tests/browser_search_searchTerms.js | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Mbrowser/locales/en-US/browser/preferences/preferences.ftl | 27+++++++++++++++------------
Mbrowser/themes/shared/preferences/search.css | 14++------------
Apython/l10n/fluent_migrations/bug_1972068_default_search_engine.py | 24++++++++++++++++++++++++
Mtoolkit/themes/shared/global-shared.css | 2+-
9 files changed, 355 insertions(+), 273 deletions(-)

diff --git a/browser/components/preferences/main.js b/browser/components/preferences/main.js @@ -2779,6 +2779,32 @@ SettingGroupManager.registerGroups({ }, ], }, + defaultEngine: { + l10nId: "search-engine-group", + headingLevel: 2, + items: [ + { + id: "defaultEngineNormal", + l10nId: "search-default-engine", + control: "moz-select", + }, + { + id: "searchShowSearchTermCheckbox", + l10nId: "search-show-search-term-option-2", + }, + { + id: "browserSeparateDefaultEngine", + l10nId: "search-separate-default-engine-2", + items: [ + { + id: "defaultPrivateEngine", + l10nId: "search-separate-default-engine-dropdown", + control: "moz-select", + }, + ], + }, + ], + }, dnsOverHttpsAdvanced: { inProgress: true, l10nId: "preferences-doh-advanced-section", diff --git a/browser/components/preferences/search.inc.xhtml b/browser/components/preferences/search.inc.xhtml @@ -13,30 +13,11 @@ <!-- Default Search Engine --> <groupbox id="defaultEngineGroup" data-category="paneSearch" hidden="true"> - <label><html:h2 data-l10n-id="search-engine-default-header" id="search-engine-default-header" /></label> - <description class="description-deemphasized" data-l10n-id="search-engine-default-desc-2" id="search-engine-default-desc-2" /> - <hbox> - <menulist id="defaultEngine" aria-labelledby="search-engine-default-header" aria-describedby="search-engine-default-desc-2"> - <menupopup/> - </menulist> - </hbox> - <checkbox id="searchShowSearchTermCheckbox" - data-l10n-id="search-show-search-term-option-2" - preference="browser.urlbar.showSearchTerms.enabled" - hidden="true" /> - <checkbox id="browserSeparateDefaultEngine" - data-l10n-id="search-separate-default-engine" - hidden="true"/> - <vbox id="browserPrivateEngineSelection" class="indent" hidden="true"> - <description data-l10n-id="search-engine-default-private-desc-2" id="search-engine-default-private-desc-2" /> - <hbox> - <menulist id="defaultPrivateEngine" aria-labelledby="search-engine-default-private-desc-2"> - <menupopup/> - </menulist> - </hbox> - </vbox> - </groupbox> + <html:setting-group groupid="defaultEngine" /> + </groupbox> + + <!-- Search Suggestions --> <groupbox id="searchSuggestionsGroup" data-category="paneSearch" hidden="true"> <label><html:h2 data-l10n-id="search-suggestions-header" /></label> <description id="searchSuggestionsDesc" @@ -153,6 +134,7 @@ </vbox> </groupbox> + <!-- Search Shortcuts --> <groupbox id="oneClickSearchProvidersGroup" data-category="paneSearch" hidden="true"> <label><html:h2 data-l10n-id="search-one-click-header2" /></label> <description class="description-deemphasized" data-l10n-id="search-one-click-desc" /> diff --git a/browser/components/preferences/search.js b/browser/components/preferences/search.js @@ -24,6 +24,7 @@ Preferences.addAll([ { id: "browser.search.suggest.enabled.private", type: "bool" }, { id: "browser.urlbar.showSearchSuggestionsFirst", type: "bool" }, { id: "browser.urlbar.showSearchTerms.enabled", type: "bool" }, + { id: "browser.urlbar.showSearchTerms.featureGate", type: "bool" }, { id: "browser.search.separatePrivateDefault", type: "bool" }, { id: "browser.search.separatePrivateDefault.ui.enabled", type: "bool" }, { id: "browser.urlbar.suggest.trending", type: "bool" }, @@ -44,6 +45,181 @@ Preferences.addAll([ { id: "browser.urlbar.quicksuggest.online.enabled", type: "bool" }, ]); +/** + * Generates the config needed to populate the dropdowns for the user's + * default search engine and separate private default search engine. + * + * @param {object} options + * Options for creating the config. + * @param {string} options.settingId + * The id for the particular setting. + * @param {() => Promise<nsISearchEngine>} options.getEngine + * The method used to get the engine from the Search Service. + * @param {(id: string) => Promise<void>} options.setEngine + * The method used to set a new engine. + * @returns {PreferencesSettingsConfig} + */ +function createSearchEngineConfig({ settingId, getEngine, setEngine }) { + return class extends Preferences.AsyncSetting { + static id = settingId; + ENGINE_MODIFIED = "browser-search-engine-modified"; + iconMap = new Map(); + + /** @type {{options: PreferencesSettingsConfig[]}} */ + defaultGetControlConfig = { options: [] }; + + async get() { + let engine = await getEngine(); + return engine.id; + } + + async set(id) { + await setEngine(id); + } + + async getControlConfig() { + let engines = await Services.search.getEngines(); + await Promise.allSettled(engines.map(e => this.loadEngineIcon(e))); + return { + options: engines.map(engine => ({ + value: engine.id, + iconSrc: this.getEngineIcon(engine), + controlAttrs: { + label: engine.name, + }, + })), + }; + } + + getEngineIcon(engine) { + return this.iconMap.get(engine.id); + } + + getPlaceholderIcon() { + return window.devicePixelRatio > 1 + ? "chrome://browser/skin/search-engine-placeholder@2x.png" + : "chrome://browser/skin/search-engine-placeholder.png"; + } + + async loadEngineIcon(engine) { + try { + let iconURL = await engine.getIconURL(); + let url = iconURL ?? this.getPlaceholderIcon(); + this.iconMap.set(engine.id, url); + return url; + } catch (error) { + console.warn(`Failed to load icon for engine ${engine.name}:`, error); + let placeholderIcon = this.getPlaceholderIcon(); + this.iconMap.set(engine.id, placeholderIcon); + return placeholderIcon; + } + } + + setup() { + Services.obs.addObserver(this, this.ENGINE_MODIFIED); + return () => Services.obs.removeObserver(this, this.ENGINE_MODIFIED); + } + + observe(subject, topic, data) { + if (topic == this.ENGINE_MODIFIED) { + let engine = subject.QueryInterface(Ci.nsISearchEngine); + + // Clean up cache for removed engines. + if (data == "engine-removed") { + this.iconMap.delete(engine.id); + } + + // Always emit change for any change that could affect the engine list + // or default. + this.emitChange(); + } + } + }; +} + +Preferences.addSetting( + createSearchEngineConfig({ + settingId: "defaultEngineNormal", + getEngine: () => Services.search.getDefault(), + setEngine: id => + Services.search.setDefault( + Services.search.getEngineById(id), + Ci.nsISearchService.CHANGE_REASON_USER + ), + }) +); + +Preferences.addSetting({ + id: "scotchBonnetEnabled", + pref: "browser.urlbar.scotchBonnet.enableOverride", +}); + +Preferences.addSetting({ + id: "showSearchTermsFeatureGate", + pref: "browser.urlbar.showSearchTerms.featureGate", +}); + +Preferences.addSetting({ + id: "searchShowSearchTermCheckbox", + pref: "browser.urlbar.showSearchTerms.enabled", + deps: ["scotchBonnetEnabled", "showSearchTermsFeatureGate"], + visible: ({ scotchBonnetEnabled, showSearchTermsFeatureGate }) => { + if (lazy.CustomizableUI.getPlacementOfWidget("search-container")) { + return false; + } + return showSearchTermsFeatureGate.value || scotchBonnetEnabled.value; + }, + setup: onChange => { + // Add observer of CustomizableUI as showSearchTerms checkbox should be + // hidden while searchbar is enabled. + let customizableUIListener = { + onWidgetAfterDOMChange: node => { + if (node.id == "search-container") { + onChange(); + } + }, + }; + + lazy.CustomizableUI.addListener(customizableUIListener); + + window.addEventListener("unload", () => { + lazy.CustomizableUI.removeListener(customizableUIListener); + }); + }, +}); + +Preferences.addSetting({ + id: "separatePrivateDefaultUI", + pref: "browser.search.separatePrivateDefault.ui.enabled", + onUserChange: () => { + gSearchPane._engineStore.notifyRebuildViews(); + }, +}); + +Preferences.addSetting({ + id: "browserSeparateDefaultEngine", + pref: "browser.search.separatePrivateDefault", + deps: ["separatePrivateDefaultUI"], + visible: ({ separatePrivateDefaultUI }) => { + return separatePrivateDefaultUI.value; + }, + onUserChange: () => { + gSearchPane._engineStore.notifyRebuildViews(); + }, +}); + +Preferences.addSetting( + createSearchEngineConfig({ + settingId: "defaultPrivateEngine", + getEngine: () => Services.search.getDefaultPrivate(), + setEngine: id => + Services.search.setDefaultPrivate( + Services.search.getEngineById(id), + Ci.nsISearchService.CHANGE_REASON_USER + ), + }) +); + const ENGINE_FLAVOR = "text/x-moz-search-engine"; const SEARCH_TYPE = "default_search"; const SEARCH_KEY = "defaultSearch"; @@ -52,22 +228,13 @@ var gEngineView = null; var gSearchPane = { _engineStore: null, - _engineDropDown: null, - _engineDropDownPrivate: null, init() { + initSettingGroup("defaultEngine"); + this._engineStore = new EngineStore(); gEngineView = new EngineView(this._engineStore); - this._engineDropDown = new DefaultEngineDropDown( - "normal", - this._engineStore - ); - this._engineDropDownPrivate = new DefaultEngineDropDown( - "private", - this._engineStore - ); - this._engineStore.init().catch(console.error); if ( @@ -143,84 +310,11 @@ var gSearchPane = { this._onFirefoxSuggestAllChange.bind(this) ); - setEventListener( - "browserSeparateDefaultEngine", - "command", - this._onBrowserSeparateDefaultEngineChange.bind(this) - ); - - this._initDefaultEngines(); - this._initShowSearchTermsCheckbox(); this._updateSuggestionCheckboxes(); this._initRecentSeachesCheckbox(); this._initAddressBar(); }, - /** - * Initialize the default engine handling. This will hide the private default - * options if they are not enabled yet. - */ - _initDefaultEngines() { - this._separatePrivateDefaultEnabledPref = Preferences.get( - "browser.search.separatePrivateDefault.ui.enabled" - ); - - this._separatePrivateDefaultPref = Preferences.get( - "browser.search.separatePrivateDefault" - ); - - const checkbox = document.getElementById("browserSeparateDefaultEngine"); - checkbox.checked = !this._separatePrivateDefaultPref.value; - - this._updatePrivateEngineDisplayBoxes(); - - const listener = () => { - this._updatePrivateEngineDisplayBoxes(); - this._engineStore.notifyRebuildViews(); - }; - - this._separatePrivateDefaultEnabledPref.on("change", listener); - this._separatePrivateDefaultPref.on("change", listener); - }, - - _initShowSearchTermsCheckbox() { - let checkbox = document.getElementById("searchShowSearchTermCheckbox"); - let updateCheckboxHidden = () => { - checkbox.hidden = - !UrlbarPrefs.getScotchBonnetPref("showSearchTerms.featureGate") || - !!lazy.CustomizableUI.getPlacementOfWidget("search-container"); - }; - - // Add observer of CustomizableUI as showSearchTerms checkbox - // should be hidden while Search Bar is enabled. - let customizableUIListener = { - onWidgetAfterDOMChange: node => { - if (node.id == "search-container") { - updateCheckboxHidden(); - } - }, - }; - lazy.CustomizableUI.addListener(customizableUIListener); - - // Fire once to initialize. - updateCheckboxHidden(); - - window.addEventListener("unload", () => { - lazy.CustomizableUI.removeListener(customizableUIListener); - }); - }, - - _updatePrivateEngineDisplayBoxes() { - const separateEnabled = this._separatePrivateDefaultEnabledPref.value; - document.getElementById("browserSeparateDefaultEngine").hidden = - !separateEnabled; - - const separateDefault = this._separatePrivateDefaultPref.value; - - const vbox = document.getElementById("browserPrivateEngineSelection"); - vbox.hidden = !separateEnabled || !separateDefault; - }, - _onFirefoxSuggestAllChange() { var prefValue = Preferences.get( "browser.urlbar.suggest.quicksuggest.all" @@ -232,10 +326,6 @@ var gSearchPane = { return undefined; }, - _onBrowserSeparateDefaultEngineChange(event) { - this._separatePrivateDefaultPref.value = !event.target.checked; - }, - _updateSuggestionCheckboxes() { if (this._skipUpdateSuggestionCheckboxesFromPrefChanges) { return; @@ -1496,80 +1586,3 @@ class EngineView { return true; } } - -/** - * Manages the default engine dropdown buttons in the search pane of preferences. - */ -class DefaultEngineDropDown { - #element = null; - #type = null; - - constructor(type, engineStore) { - this.#type = type; - this.#element = document.getElementById( - type == "private" ? "defaultPrivateEngine" : "defaultEngine" - ); - - engineStore.addListener(this); - } - - rowCountChanged(index, count, enginesList) { - // Simply rebuild the menulist, rather than trying to update the changed row. - this.rebuild(enginesList); - } - - defaultEngineChanged(type, engine, enginesList) { - if (type != this.#type) { - return; - } - // If the user is going through the drop down using up/down keys, the - // dropdown may still be open (eg. on Windows) when engine-default is - // fired, so rebuilding the list unconditionally would get in the way. - let selectedEngineName = this.#element.selectedItem?.engine?.name; - if (selectedEngineName != engine.name) { - this.rebuild(enginesList); - } - } - - engineIconUpdated(index, enginesList) { - let item = this.#element.getItemAtIndex(index); - // Check this is the right item. - if (item?.label == enginesList[index].name) { - item.setAttribute("image", enginesList[index].iconURL); - } - } - - async rebuild(enginesList) { - if ( - this.#type == "private" && - !gSearchPane._separatePrivateDefaultPref.value - ) { - return; - } - let defaultEngine = - await Services.search[ - this.#type == "normal" ? "getDefault" : "getDefaultPrivate" - ](); - - this.#element.removeAllItems(); - for (let engine of enginesList) { - let item = this.#element.appendItem(engine.name); - item.setAttribute( - "class", - "menuitem-iconic searchengine-menuitem menuitem-with-favicon" - ); - if (engine.iconURL) { - item.setAttribute("image", engine.iconURL); - } - item.engine = engine; - if (engine.name == defaultEngine.name) { - this.#element.selectedItem = item; - } - } - // This should never happen, but try and make sure we have at least one - // selected item. - if (!this.#element.selectedItem) { - this.#element.selectedIndex = 0; - } - } -} diff --git a/browser/components/preferences/tests/browser_searchDefaultEngine.js b/browser/components/preferences/tests/browser_searchDefaultEngine.js @@ -47,17 +47,16 @@ add_task(async function test_openWithPrivateDefaultNotEnabledFirst() { const doc = gBrowser.selectedBrowser.contentDocument; const separateEngineCheckbox = doc.getElementById( "browserSeparateDefaultEngine" - ); - const privateDefaultVbox = doc.getElementById( - "browserPrivateEngineSelection" - ); + ).parentElement; + const privateDefaultDropdown = doc.getElementById("defaultPrivateEngine"); Assert.ok( separateEngineCheckbox.hidden, "Should have hidden the separate search engine checkbox" ); Assert.ok( - privateDefaultVbox.hidden, + separateEngineCheckbox.hidden && + separateEngineCheckbox.contains(privateDefaultDropdown), "Should have hidden the private engine selection box" ); @@ -70,8 +69,8 @@ add_task(async function test_openWithPrivateDefaultNotEnabledFirst() { "Should have displayed the separate search engine checkbox" ); Assert.ok( - privateDefaultVbox.hidden, - "Should not have displayed the private engine selection box" + BrowserTestUtils.isVisible(privateDefaultDropdown), + "Private engine selection box should be visible" ); await SpecialPowers.pushPrefEnv({ @@ -83,8 +82,8 @@ add_task(async function test_openWithPrivateDefaultNotEnabledFirst() { "Should still be displaying the separate search engine checkbox" ); Assert.ok( - !privateDefaultVbox.hidden, - "Should have displayed the private engine selection box" + !privateDefaultDropdown.disabled, + "Private engine selection box should be enabled" ); gBrowser.removeCurrentTab(); @@ -103,18 +102,16 @@ add_task(async function test_openWithPrivateDefaultEnabledFirst() { const doc = gBrowser.selectedBrowser.contentDocument; const separateEngineCheckbox = doc.getElementById( "browserSeparateDefaultEngine" - ); - const privateDefaultVbox = doc.getElementById( - "browserPrivateEngineSelection" - ); + ).parentElement; + const privateDefaultDropdown = doc.getElementById("defaultPrivateEngine"); Assert.ok( !separateEngineCheckbox.hidden, "Should not have hidden the separate search engine checkbox" ); Assert.ok( - !privateDefaultVbox.hidden, - "Should not have hidden the private engine selection box" + !privateDefaultDropdown.shadowRoot.getElementById("input").disabled, + "Private engine selection box should be enabled" ); await SpecialPowers.pushPrefEnv({ @@ -126,8 +123,8 @@ add_task(async function test_openWithPrivateDefaultEnabledFirst() { "Should not have hidden the separate search engine checkbox" ); Assert.ok( - privateDefaultVbox.hidden, - "Should have hidden the private engine selection box" + BrowserTestUtils.isVisible(privateDefaultDropdown), + "Private engine selection box should be visible" ); await SpecialPowers.pushPrefEnv({ @@ -139,8 +136,9 @@ add_task(async function test_openWithPrivateDefaultEnabledFirst() { "Should have hidden the separate private engine checkbox" ); Assert.ok( - privateDefaultVbox.hidden, - "Should still be hiding the private engine selection box" + separateEngineCheckbox.hidden && + separateEngineCheckbox.contains(privateDefaultDropdown), + "Should have hidden the private engine selection box" ); gBrowser.removeCurrentTab(); @@ -160,39 +158,35 @@ add_task(async function test_separatePrivateDefault() { const separateEngineCheckbox = doc.getElementById( "browserSeparateDefaultEngine" ); - const privateDefaultVbox = doc.getElementById( - "browserPrivateEngineSelection" - ); + const privateDefaultDropdown = doc.getElementById("defaultPrivateEngine"); Assert.ok( - privateDefaultVbox.hidden, - "Should not be displaying the private engine selection box" + BrowserTestUtils.isVisible(privateDefaultDropdown), + "Private engine selection box should be visible" ); - separateEngineCheckbox.checked = false; - separateEngineCheckbox.doCommand(); + separateEngineCheckbox.click(); + await separateEngineCheckbox.parentElement.updateComplete; Assert.ok( Services.prefs.getBoolPref("browser.search.separatePrivateDefault"), "Should have correctly set the pref" ); - Assert.ok( - !privateDefaultVbox.hidden, - "Should be displaying the private engine selection box" + !privateDefaultDropdown.shadowRoot.getElementById("input").disabled, + "Private engine selection box should be enabled" ); - separateEngineCheckbox.checked = true; - separateEngineCheckbox.doCommand(); + separateEngineCheckbox.click(); + await separateEngineCheckbox.parentElement.updateComplete; Assert.ok( !Services.prefs.getBoolPref("browser.search.separatePrivateDefault"), "Should have correctly turned the pref off" ); - Assert.ok( - privateDefaultVbox.hidden, - "Should have hidden the private engine selection box" + BrowserTestUtils.isVisible(privateDefaultDropdown), + "Private engine selection box should be visible" ); gBrowser.removeCurrentTab(); @@ -206,28 +200,31 @@ async function setDefaultEngine( await openPreferencesViaOpenPreferencesAPI("search", { leaveOpen: true }); const doc = gBrowser.selectedBrowser.contentDocument; - const defaultEngineSelector = doc.getElementById( - testPrivate ? "defaultPrivateEngine" : "defaultEngine" + const input = doc.getElementById( + testPrivate ? "defaultPrivateEngine" : "defaultEngineNormal" ); + const defaultEngineSelector = input.inputEl; + const defaultEngineTrigger = input.shadowRoot.querySelector(".panel-trigger"); - Assert.equal( - defaultEngineSelector.selectedItem.engine.name, - currentEngineName, + Assert.ok( + defaultEngineSelector.value.startsWith(currentEngineName), "Should have the correct engine as default on first open" ); - const popup = defaultEngineSelector.menupopup; - const popupShown = BrowserTestUtils.waitForEvent(popup, "popupshown"); - EventUtils.synthesizeMouseAtCenter( + const popupShown = BrowserTestUtils.waitForEvent( defaultEngineSelector, + "shown" + ); + EventUtils.synthesizeMouseAtCenter( + defaultEngineTrigger, {}, - defaultEngineSelector.ownerGlobal + defaultEngineTrigger.ownerGlobal ); await popupShown; - const items = Array.from(popup.children); - const engine2Item = items.find( - item => item.engine.name == expectedEngineName + const items = Array.from(defaultEngineSelector.children); + const engine2Item = items.find(item => + item.textContent.includes(expectedEngineName) ); const defaultChanged = SearchTestUtils.promiseSearchNotification( diff --git a/browser/components/preferences/tests/browser_search_searchTerms.js b/browser/components/preferences/tests/browser_search_searchTerms.js @@ -64,9 +64,11 @@ add_task(async function showSearchTermsVisibility_scotchBonnet() { // enabled by default. add_task(async function showSearchTermsVisibility_featureGate() { await SpecialPowers.pushPrefEnv({ - set: [[PREF_FEATUREGATE, false]], + set: [ + [PREF_SCOTCH_BONNET, false], + [PREF_FEATUREGATE, false], + ], }); - await BrowserTestUtils.withNewTab( "about:preferences#search", async browser => { @@ -77,11 +79,14 @@ add_task(async function showSearchTermsVisibility_featureGate() { ); } ); + await SpecialPowers.popPrefEnv(); await SpecialPowers.pushPrefEnv({ - set: [[PREF_FEATUREGATE, true]], + set: [ + [PREF_SCOTCH_BONNET, false], + [PREF_FEATUREGATE, true], + ], }); - await BrowserTestUtils.withNewTab( "about:preferences#search", async browser => { @@ -92,8 +97,42 @@ add_task(async function showSearchTermsVisibility_featureGate() { ); } ); + await SpecialPowers.popPrefEnv(); + await SpecialPowers.pushPrefEnv({ + set: [ + [PREF_SCOTCH_BONNET, true], + [PREF_FEATUREGATE, false], + ], + }); + await BrowserTestUtils.withNewTab( + "about:preferences#search", + async browser => { + let container = browser.contentDocument.getElementById(CHECKBOX_ID); + Assert.ok( + BrowserTestUtils.isVisible(container), + "The option box is visible" + ); + } + ); await SpecialPowers.popPrefEnv(); + + await SpecialPowers.pushPrefEnv({ + set: [ + [PREF_SCOTCH_BONNET, true], + [PREF_FEATUREGATE, true], + ], + }); + await BrowserTestUtils.withNewTab( + "about:preferences#search", + async browser => { + let container = browser.contentDocument.getElementById(CHECKBOX_ID); + Assert.ok( + BrowserTestUtils.isVisible(container), + "The option box is visible" + ); + } + ); await SpecialPowers.popPrefEnv(); }); @@ -151,21 +190,23 @@ add_task(async function showSearchTerms_checkbox() { }); /* - When loading the search preferences panel, the - showSearchTerms checkbox should be hidden if - the search bar is enabled. + When loading the search preferences panel, the showSearchTerms checkbox + should be hidden if the search bar is enabled. */ add_task(async function showSearchTerms_and_searchBar_preference_load() { // Enable the feature. await SpecialPowers.pushPrefEnv({ - set: [[PREF_FEATUREGATE, true]], + set: [ + [PREF_SCOTCH_BONNET, true], + [PREF_FEATUREGATE, true], + ], }); await gCUITestUtils.addSearchBar(); await openPreferencesViaOpenPreferencesAPI("search", { leaveOpen: true }); let doc = gBrowser.selectedBrowser.contentDocument; - let checkbox = doc.getElementById(CHECKBOX_ID); + let checkbox = doc.getElementById(CHECKBOX_ID).parentElement; Assert.ok( checkbox.hidden, "showSearchTerms checkbox should be hidden when search bar is enabled." @@ -178,20 +219,22 @@ add_task(async function showSearchTerms_and_searchBar_preference_load() { }); /* - If the search bar is enabled while the search - preferences panel is open, the showSearchTerms - checkbox should not be clickable. + If the search bar is enabled while the search preferences panel is open, the + showSearchTerms checkbox should not be clickable. */ add_task(async function showSearchTerms_and_searchBar_preference_change() { // Enable the feature. await SpecialPowers.pushPrefEnv({ - set: [[PREF_FEATUREGATE, true]], + set: [ + [PREF_SCOTCH_BONNET, true], + [PREF_FEATUREGATE, true], + ], }); await openPreferencesViaOpenPreferencesAPI("search", { leaveOpen: true }); let doc = gBrowser.selectedBrowser.contentDocument; - let checkbox = doc.getElementById(CHECKBOX_ID); + let checkbox = doc.getElementById(CHECKBOX_ID).parentElement; Assert.ok(!checkbox.hidden, "showSearchTerms checkbox should be shown."); await gCUITestUtils.addSearchBar(); @@ -202,6 +245,10 @@ add_task(async function showSearchTerms_and_searchBar_preference_change() { // Clean-up. gCUITestUtils.removeSearchBar(); + await TestUtils.waitForCondition( + () => !checkbox.hidden, + "Wait for preferences to know search bar has been removed." + ); Assert.ok(!checkbox.hidden, "showSearchTerms checkbox should be shown."); gBrowser.removeCurrentTab(); diff --git a/browser/locales/en-US/browser/preferences/preferences.ftl b/browser/locales/en-US/browser/preferences/preferences.ftl @@ -865,13 +865,23 @@ home-prefs-sections-rows-option = ## Search Section -search-engine-default-header = Default Search Engine -search-engine-default-desc-2 = This is your default search engine in the address bar and search bar. You can switch it at any time. -search-engine-default-private-desc-2 = Choose a different default search engine for Private Windows only -search-separate-default-engine = - .label = Use this search engine in Private Windows +search-engine-group = + .label = Default search engine +search-default-engine = + .aria-label = Default search engine + +# With this option enabled, while on a SERP, the URL normally displayed in the +# address bar will be replaced with the search term used to generate that SERP. +search-show-search-term-option-2 = + .label = Show search terms in the address bar on results pages + +search-separate-default-engine-2 = + .label = Use a different default search engine in private windows .accesskey = U +search-separate-default-engine-dropdown = + .aria-label = Default search engine in private windows + search-suggestions-header = Search Suggestions search-suggestions-desc = Choose how suggestions from search engines appear. @@ -883,13 +893,6 @@ search-show-suggestions-url-bar-option = .label = Show search suggestions in address bar results .accesskey = l - -# With this option enabled, on the search results page -# the URL will be replaced by the search terms in the address bar. -search-show-search-term-option-2 = - .label = Show search terms in the address bar on results pages - - # This string describes what the user will observe when the system # prioritizes search suggestions over browsing history in the results # that extend down from the address bar. In the original English string, diff --git a/browser/themes/shared/preferences/search.css b/browser/themes/shared/preferences/search.css @@ -2,19 +2,9 @@ * 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/. */ -#defaultEngine, +#defaultEngineNormal, #defaultPrivateEngine { - margin-inline-start: 0; - &, - & menupopup { - max-width: var(--search-engine-name-max-width); - } -} - -#defaultEngine::part(icon), -#defaultPrivateEngine::part(icon) { - height: 16px; - width: 16px; + max-width: var(--search-engine-name-max-width); } #engineList { diff --git a/python/l10n/fluent_migrations/bug_1972068_default_search_engine.py b/python/l10n/fluent_migrations/bug_1972068_default_search_engine.py @@ -0,0 +1,24 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migrate.helpers import transforms_from + + +def migrate(ctx): + """Bug 1972068 - Convert default search engine section of search settings to config-based prefs, part {index}.""" + + target = "browser/browser/preferences/preferences.ftl" + + ctx.add_transforms( + target, + target, + transforms_from( + """ +search-engine-group = + .label = {COPY_PATTERN(from_path, "search-engine-default-header")} +search-default-engine = + .aria-label = {COPY_PATTERN(from_path, "search-engine-default-header")} +""", + from_path=target, + ), + ) diff --git a/toolkit/themes/shared/global-shared.css b/toolkit/themes/shared/global-shared.css @@ -36,7 +36,7 @@ --arrowpanel-menuitem-padding-inline: 8px; --arrowpanel-menuitem-padding: var(--arrowpanel-menuitem-padding-block) var(--arrowpanel-menuitem-padding-inline); - --search-engine-name-max-width: 25em; + --search-engine-name-max-width: 15em; @media (-moz-platform: macos) { /* On macOS we use native shadows via -moz-window-shadow */