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:
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 */