commit 9d7faf035e9590310b3f6c86171a06aa30c29132
parent 5b8fe027b47780542708a8b89a9c0f795235b04d
Author: mark <mkennedy@mozilla.com>
Date: Fri, 3 Oct 2025 15:58:02 +0000
Bug 1969949 - Convert 'Default browser' Startup controls to config-based setting r=fluent-reviewers,desktop-theme-reviewers,akulyk,bolsson,mstriemer,hjones
Differential Revision: https://phabricator.services.mozilla.com/D262951
Diffstat:
9 files changed, 413 insertions(+), 252 deletions(-)
diff --git a/browser/components/preferences/main.inc.xhtml b/browser/components/preferences/main.inc.xhtml
@@ -30,27 +30,6 @@
<html:setting-group groupid="startup"/>
</vbox>
-#ifdef HAVE_SHELL_SERVICE
- <vbox id="defaultBrowserBox">
- <checkbox id="alwaysCheckDefault" preference="browser.shell.checkDefaultBrowser"
- disabled="true"
- data-l10n-id="always-check-default"/>
- <stack id="setDefaultPane">
- <hbox id="isNotDefaultPane" align="center" class="indent">
- <label class="face-sad" id="isNotDefaultLabel" flex="1" data-l10n-id="is-not-default"/>
- <button id="setDefaultButton"
- is="highlightable-button"
- class="accessory-button"
- data-l10n-id="set-as-my-default-browser"
- preference="pref.general.disable_button.default_browser"/>
- </hbox>
- <hbox id="isDefaultPane" align="center" class="indent">
- <label class="face-smile" id="isDefaultLabel" flex="1" data-l10n-id="is-default"/>
- </hbox>
- </stack>
- </vbox>
-#endif
-
</groupbox>
<!-- Data migration -->
diff --git a/browser/components/preferences/main.js b/browser/components/preferences/main.js
@@ -2,7 +2,8 @@
* 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 { SettingGroup } from "./widgets/setting-group/setting-group.mjs" */
+/** @import MozButton from "chrome://global/content/elements/moz-button.mjs"; */
+/** @import { SettingGroup } from "./widgets/setting-group/setting-group.mjs" */
/** @import { PreferencesSettingsConfig } from "chrome://global/content/preferences/Preferences.mjs" */
/* import-globals-from extensionControlled.js */
@@ -849,6 +850,198 @@ Preferences.addSetting({
Services.prefs.setBoolPref("browser.download.deletePrivate.chosen", true);
},
});
+/**
+ * A helper object containing all logic related to
+ * setting the browser as the user's default.
+ */
+const DefaultBrowserHelper = {
+ /**
+ * @type {number}
+ */
+ _backoffIndex: 0,
+
+ /**
+ * @type {number | undefined}
+ */
+ _pollingTimer: undefined,
+
+ /**
+ * Keeps track of the last known browser
+ * default value set to compare while polling.
+ *
+ * @type {boolean | undefined}
+ */
+ _lastPolledIsDefault: undefined,
+
+ /**
+ * @type {typeof import('../shell/ShellService.sys.mjs').ShellService | undefined}
+ */
+ get shellSvc() {
+ return AppConstants.HAVE_SHELL_SERVICE && getShellService();
+ },
+
+ /**
+ * Sets up polling of whether the browser is set to default,
+ * and calls provided hasChanged function when the state changes.
+ *
+ * @param {Function} hasChanged
+ */
+ pollForDefaultChanges(hasChanged) {
+ if (this._pollingTimer) {
+ return;
+ }
+ this._lastPolledIsDefault = this.isBrowserDefault;
+
+ // Exponential backoff mechanism will delay the polling times if user doesn't
+ // trigger SetDefaultBrowser for a long time.
+ const backoffTimes = [
+ 1000, 1000, 1000, 1000, 2000, 2000, 2000, 5000, 5000, 10000,
+ ];
+
+ const pollForDefaultBrowser = () => {
+ if (
+ (location.hash == "" || location.hash == "#general") &&
+ document.visibilityState == "visible"
+ ) {
+ const { isBrowserDefault } = this;
+ if (isBrowserDefault !== this._lastPolledIsDefault) {
+ this._lastPolledIsDefault = isBrowserDefault;
+ hasChanged();
+ }
+ }
+
+ if (!this._pollingTimer) {
+ return;
+ }
+
+ // approximately a "requestIdleInterval"
+ this._pollingTimer = window.setTimeout(
+ () => {
+ window.requestIdleCallback(pollForDefaultBrowser);
+ },
+ backoffTimes[
+ this._backoffIndex + 1 < backoffTimes.length
+ ? this._backoffIndex++
+ : backoffTimes.length - 1
+ ]
+ );
+ };
+
+ this._pollingTimer = window.setTimeout(() => {
+ window.requestIdleCallback(pollForDefaultBrowser);
+ }, backoffTimes[this._backoffIndex]);
+ },
+
+ /**
+ * Stops timer for polling changes.
+ */
+ clearPollingForDefaultChanges() {
+ if (this._pollingTimer) {
+ clearTimeout(this._pollingTimer);
+ this._pollingTimer = undefined;
+ }
+ },
+
+ /**
+ * Checks if the browser is default through the shell service.
+ */
+ get isBrowserDefault() {
+ if (!this.canCheck) {
+ return false;
+ }
+ return this.shellSvc?.isDefaultBrowser(false, true);
+ },
+
+ /**
+ * Attempts to set the browser as the user's
+ * default through the shell service.
+ *
+ * @returns {Promise<void>}
+ */
+ async setDefaultBrowser() {
+ // Reset exponential backoff delay time in order to do visual update in pollForDefaultBrowser.
+ this._backoffIndex = 0;
+
+ try {
+ await this.shellSvc?.setDefaultBrowser(false);
+ } catch (e) {
+ console.error(e);
+ }
+ },
+
+ /**
+ * Checks whether the browser is capable of being made default.
+ * @type {boolean}
+ */
+ get canCheck() {
+ return (
+ this.shellSvc &&
+ /**
+ * Flatpak does not support setting nor detection of default browser
+ */
+ !gGIOService?.isRunningUnderFlatpak
+ );
+ },
+};
+
+Preferences.addSetting({
+ id: "alwaysCheckDefault",
+ pref: "browser.shell.checkDefaultBrowser",
+ setup: emitChange => {
+ if (!DefaultBrowserHelper.canCheck) {
+ return;
+ }
+ DefaultBrowserHelper.pollForDefaultChanges(emitChange);
+ // eslint-disable-next-line consistent-return
+ return () => DefaultBrowserHelper.clearPollingForDefaultChanges();
+ },
+ /**
+ * Show button for setting browser as default browser or information that
+ * browser is already the default browser.
+ */
+ visible: () => DefaultBrowserHelper.canCheck,
+ disabled: (deps, setting) =>
+ !DefaultBrowserHelper.canCheck ||
+ setting.locked ||
+ DefaultBrowserHelper.isBrowserDefault,
+});
+
+Preferences.addSetting({
+ id: "isDefaultPane",
+ deps: ["alwaysCheckDefault"],
+ visible: () =>
+ DefaultBrowserHelper.canCheck && DefaultBrowserHelper.isBrowserDefault,
+});
+
+Preferences.addSetting({
+ id: "isNotDefaultPane",
+ deps: ["alwaysCheckDefault"],
+ visible: () =>
+ DefaultBrowserHelper.canCheck && !DefaultBrowserHelper.isBrowserDefault,
+ onUserClick: (e, { alwaysCheckDefault }) => {
+ if (!DefaultBrowserHelper.canCheck) {
+ return;
+ }
+ const setDefaultButton = /** @type {MozButton} */ (e.target);
+
+ if (!setDefaultButton) {
+ return;
+ }
+ if (setDefaultButton.disabled) {
+ return;
+ }
+
+ /**
+ * Disable the set default button, so that the user
+ * doesn't try to hit it again while browser is being set to default.
+ */
+ setDefaultButton.disabled = true;
+ alwaysCheckDefault.value = true;
+ DefaultBrowserHelper.setDefaultBrowser().finally(() => {
+ setDefaultButton.disabled = false;
+ });
+ },
+});
// Performance settings
Preferences.addSetting({
@@ -934,6 +1127,31 @@ let SETTINGS_CONFIG = {
l10nId: "startup-windows-launch-on-login-profile-disabled",
},
},
+ {
+ id: "alwaysCheckDefault",
+ l10nId: "always-check-default",
+ },
+ {
+ id: "isDefaultPane",
+ l10nId: "is-default-browser",
+ control: "moz-promo",
+ },
+ {
+ id: "isNotDefaultPane",
+ l10nId: "is-not-default-browser",
+ control: "moz-promo",
+ options: [
+ {
+ control: "moz-button",
+ l10nId: "set-as-my-default-browser",
+ id: "setDefaultButton",
+ controlAttrs: {
+ slot: "actions",
+ type: "primary",
+ },
+ },
+ ],
+ },
],
},
zoom: {
@@ -1365,8 +1583,6 @@ var gMainPane = {
return (this._filter = document.getElementById("filter"));
},
- _backoffIndex: 0,
-
/**
* Initialization of gMainPane.
*/
@@ -1377,47 +1593,6 @@ var gMainPane = {
.addEventListener(aEventType, aCallback.bind(gMainPane));
}
- if (AppConstants.HAVE_SHELL_SERVICE) {
- this.updateSetDefaultBrowser();
- let win = Services.wm.getMostRecentWindow("navigator:browser");
-
- // Exponential backoff mechanism will delay the polling times if user doesn't
- // trigger SetDefaultBrowser for a long time.
- let backoffTimes = [
- 1000, 1000, 1000, 1000, 2000, 2000, 2000, 5000, 5000, 10000,
- ];
-
- let pollForDefaultBrowser = () => {
- let uri = win.gBrowser.currentURI.spec;
-
- if (
- (uri == "about:preferences" ||
- uri == "about:preferences#general" ||
- uri == "about:settings" ||
- uri == "about:settings#general") &&
- document.visibilityState == "visible"
- ) {
- this.updateSetDefaultBrowser();
- }
-
- // approximately a "requestIdleInterval"
- window.setTimeout(
- () => {
- window.requestIdleCallback(pollForDefaultBrowser);
- },
- backoffTimes[
- this._backoffIndex + 1 < backoffTimes.length
- ? this._backoffIndex++
- : backoffTimes.length - 1
- ]
- );
- };
-
- window.setTimeout(() => {
- window.requestIdleCallback(pollForDefaultBrowser);
- }, backoffTimes[this._backoffIndex]);
- }
-
this.initBrowserContainers();
this.displayUseSystemLocale();
this.updateProxySettingsUI();
@@ -1522,13 +1697,6 @@ var gMainPane = {
});
}
- if (AppConstants.HAVE_SHELL_SERVICE) {
- setEventListener(
- "setDefaultButton",
- "command",
- gMainPane.setDefaultBrowser
- );
- }
setEventListener(
"disableContainersExtension",
"command",
@@ -2707,77 +2875,6 @@ var gMainPane = {
var linkTargeting = document.getElementById("linkTargeting");
return linkTargeting.checked ? 3 : 2;
},
- /*
- * Preferences:
- *
- * browser.shell.checkDefault
- * - true if a default-browser check (and prompt to make it so if necessary)
- * occurs at startup, false otherwise
- */
-
- /**
- * Show button for setting browser as default browser or information that
- * browser is already the default browser.
- */
- updateSetDefaultBrowser() {
- if (AppConstants.HAVE_SHELL_SERVICE) {
- let shellSvc = getShellService();
- let defaultBrowserBox = document.getElementById("defaultBrowserBox");
- let isInFlatpak = gGIOService?.isRunningUnderFlatpak;
- // Flatpak does not support setting nor detection of default browser
- if (!shellSvc || isInFlatpak) {
- defaultBrowserBox.hidden = true;
- return;
- }
- let isDefault = shellSvc.isDefaultBrowser(false, true);
- let setDefaultPane = document.getElementById("setDefaultPane");
- setDefaultPane.classList.toggle("is-default", isDefault);
- let alwaysCheck = document.getElementById("alwaysCheckDefault");
- let alwaysCheckPref = Preferences.get(
- "browser.shell.checkDefaultBrowser"
- );
- alwaysCheck.disabled = alwaysCheckPref.locked || isDefault;
- }
- },
-
- /**
- * Set browser as the operating system default browser.
- */
- async setDefaultBrowser() {
- if (AppConstants.HAVE_SHELL_SERVICE) {
- let alwaysCheckPref = Preferences.get(
- "browser.shell.checkDefaultBrowser"
- );
- alwaysCheckPref.value = true;
-
- // Reset exponential backoff delay time in order to do visual update in pollForDefaultBrowser.
- this._backoffIndex = 0;
-
- let shellSvc = getShellService();
- if (!shellSvc) {
- return;
- }
-
- // Disable the set default button, so that the user doesn't try to hit it again
- // while awaiting on setDefaultBrowser
- let setDefaultButton = document.getElementById("setDefaultButton");
- setDefaultButton.disabled = true;
-
- try {
- await shellSvc.setDefaultBrowser(false);
- } catch (ex) {
- console.error(ex);
- return;
- } finally {
- // Make sure to re-enable the default button when we're finished, regardless of the outcome
- setDefaultButton.disabled = false;
- }
-
- let isDefault = shellSvc.isDefaultBrowser(false, true);
- let setDefaultPane = document.getElementById("setDefaultPane");
- setDefaultPane.classList.toggle("is-default", isDefault);
- }
- },
/**
* Shows a subdialog containing the profile selector page.
diff --git a/browser/components/preferences/tests/browser_defaultbrowser_alwayscheck.js b/browser/components/preferences/tests/browser_defaultbrowser_alwayscheck.js
@@ -1,24 +1,73 @@
"use strict";
-const CHECK_DEFAULT_INITIAL = Services.prefs.getBoolPref(
- "browser.shell.checkDefaultBrowser"
-);
-
-add_task(async function clicking_make_default_checks_alwaysCheck_checkbox() {
+/**
+ * Sets up initial prefs and opens about:preferences page.
+ * @returns {Promise<void>}
+ */
+async function setup() {
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.shell.checkDefaultBrowser", false]],
+ });
await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:preferences");
+}
+
+/**
+ * Closes out the about:preferences tab and clears out
+ * any prefs that could have potentially been manipulated.
+ *
+ * @returns {void}
+ */
+function teardown() {
+ Services.prefs.unlockPref("browser.shell.checkDefaultBrowser");
+ gBrowser.removeCurrentTab();
+}
+
+/**
+ * Sets up the 'Make default' mock service to mimic
+ * whether the user has set the browser as default already or not.
+ *
+ * @param {{isDefault: boolean}} options
+ */
+async function setupInitialBrowserDefaultSetting(options) {
+ const win = gBrowser.selectedBrowser.contentWindow;
+ win.oldShellService = win.getShellService();
+ const { isDefault } = options;
+
+ const mockShellService = {
+ _isDefault: isDefault,
+ isDefaultBrowser() {
+ return this._isDefault;
+ },
+ async setDefaultBrowser() {
+ this._isDefault = true;
+ },
+ };
+ win.getShellService = function () {
+ return mockShellService;
+ };
+}
+
+add_task(
+ /**
+ * Tests when clicking 'Make default' button, setting browser
+ * to default, and the side effects of the 'Always check' checkbox.
+ */
+ async function clicking_make_default_checks_alwaysCheck_checkbox() {
+ await setup();
+ await setupInitialBrowserDefaultSetting({ isDefault: false });
- await test_with_mock_shellservice({ isDefault: false }, async function () {
let checkDefaultBrowserState = isDefault => {
let isDefaultPane = content.document.getElementById("isDefaultPane");
let isNotDefaultPane =
content.document.getElementById("isNotDefaultPane");
+
Assert.equal(
- ContentTaskUtils.isHidden(isDefaultPane),
+ BrowserTestUtils.isHidden(isDefaultPane.control),
!isDefault,
"The 'browser is default' pane should be hidden when browser is not default"
);
Assert.equal(
- ContentTaskUtils.isHidden(isNotDefaultPane),
+ BrowserTestUtils.isHidden(isNotDefaultPane.control),
isDefault,
"The 'make default' pane should be hidden when browser is default"
);
@@ -26,18 +75,25 @@ add_task(async function clicking_make_default_checks_alwaysCheck_checkbox() {
checkDefaultBrowserState(false);
- let alwaysCheck = content.document.getElementById("alwaysCheckDefault");
+ const alwaysCheck = content.document.getElementById("alwaysCheckDefault");
+
Assert.ok(!alwaysCheck.checked, "Always Check is unchecked by default");
+
Assert.ok(
!Services.prefs.getBoolPref("browser.shell.checkDefaultBrowser"),
"alwaysCheck pref should be false by default in test runs"
);
- let setDefaultButton = content.document.getElementById("setDefaultButton");
+ const setDefaultButton =
+ content.document.getElementById("setDefaultButton");
+ /**
+ * Click 'Make default' button to trigger shell service that sets the browser to default.
+ */
setDefaultButton.click();
- content.window.gMainPane.updateSetDefaultBrowser();
-
- await ContentTaskUtils.waitForCondition(
+ /**
+ * Deem complete when 'Always Check' checkbox is checked.
+ */
+ await TestUtils.waitForCondition(
() => alwaysCheck.checked,
"'Always Check' checkbox should get checked after clicking the 'Set Default' button"
);
@@ -59,30 +115,43 @@ add_task(async function clicking_make_default_checks_alwaysCheck_checkbox() {
Services.prefs.getBoolPref("browser.shell.checkDefaultBrowser"),
"checkDefaultBrowser pref is now enabled"
);
- });
+ teardown();
+ }
+);
- gBrowser.removeCurrentTab();
- Services.prefs.clearUserPref("browser.shell.checkDefaultBrowser");
-});
+add_task(
+ /**
+ * Tests when clicking 'Make default' button, setting browser
+ * to default, and the side effects of the 'Always check' checkbox
+ * when browser.shell.checkDefaultBrowser pref is locked
+ */
+ async function clicking_make_default_checks_alwaysCheck_checkbox_when_locked() {
+ await setup();
-add_task(async function clicking_make_default_checks_alwaysCheck_checkbox() {
- Services.prefs.lockPref("browser.shell.checkDefaultBrowser");
- await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:preferences");
+ Services.prefs.lockPref("browser.shell.checkDefaultBrowser");
+
+ const isDefault = false;
+ await setupInitialBrowserDefaultSetting({ isDefault });
- await test_with_mock_shellservice({ isDefault: false }, async function () {
let isDefaultPane = content.document.getElementById("isDefaultPane");
let isNotDefaultPane = content.document.getElementById("isNotDefaultPane");
+
+ is(isDefaultPane.localName, "moz-promo", "Pane is a moz-promo");
+
Assert.ok(
- ContentTaskUtils.isHidden(isDefaultPane),
+ BrowserTestUtils.isHidden(isDefaultPane.control),
"The 'browser is default' pane should be hidden when not default"
);
+
Assert.ok(
- ContentTaskUtils.isVisible(isNotDefaultPane),
- "The 'make default' pane should be visible when not default"
+ !BrowserTestUtils.isHidden(isNotDefaultPane.control),
+ "The 'is not default' pane should be visible when not default"
);
let alwaysCheck = content.document.getElementById("alwaysCheckDefault");
+
Assert.ok(alwaysCheck.disabled, "Always Check is disabled when locked");
+
Assert.ok(
alwaysCheck.checked,
"Always Check is checked because defaultPref is true and pref is locked"
@@ -91,14 +160,32 @@ add_task(async function clicking_make_default_checks_alwaysCheck_checkbox() {
Services.prefs.getBoolPref("browser.shell.checkDefaultBrowser"),
"alwaysCheck pref should ship with 'true' by default"
);
-
- let setDefaultButton = content.document.getElementById("setDefaultButton");
+ const setDefaultButton =
+ content.document.getElementById("setDefaultButton");
+ /**
+ * Click 'Make default' button to trigger shell service that sets the browser to default.
+ */
setDefaultButton.click();
- content.window.gMainPane.updateSetDefaultBrowser();
- await ContentTaskUtils.waitForCondition(
- () => ContentTaskUtils.isVisible(isDefaultPane),
- "Browser is now default"
+ const { TelemetryTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/TelemetryTestUtils.sys.mjs"
+ );
+ let snapshot = TelemetryTestUtils.getProcessScalars("parent", true, true);
+ TelemetryTestUtils.assertKeyedScalar(
+ snapshot,
+ "browser.ui.interaction.preferences_paneGeneral",
+ "setDefaultButton",
+ 2 // button clicked
+ );
+
+ Assert.ok(
+ !BrowserTestUtils.isHidden(isNotDefaultPane.control),
+ "Browser default pane still shows after click because pref is locked"
+ );
+
+ Assert.ok(
+ BrowserTestUtils.isHidden(isDefaultPane.control),
+ "Browser is not default pane is NOT showing"
);
Assert.ok(
@@ -113,73 +200,37 @@ add_task(async function clicking_make_default_checks_alwaysCheck_checkbox() {
Services.prefs.getBoolPref("browser.shell.checkDefaultBrowser"),
"The pref is locked and so doesn't get changed"
);
- });
+ teardown();
+ }
+);
- Services.prefs.unlockPref("browser.shell.checkDefaultBrowser");
- gBrowser.removeCurrentTab();
-});
+add_task(
+ /**
+ * Testcase with Firefox initially set as the default browser
+ */
+ async function make_default_after_browser_set_as_default() {
+ await setup();
-add_task(async function make_default_disabled_until_prefs_are_loaded() {
- // Testcase with Firefox not set as the default browser
- await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:preferences");
- await test_with_mock_shellservice({ isDefault: false }, async function () {
- let alwaysCheck = content.document.getElementById("alwaysCheckDefault");
- Assert.ok(
- !alwaysCheck.disabled,
- "'Always Check' is enabled after default browser updated"
- );
- });
- gBrowser.removeCurrentTab();
+ await setupInitialBrowserDefaultSetting({ isDefault: true });
+
+ const alwaysCheck = content.document.getElementById("alwaysCheckDefault");
+
+ is(alwaysCheck.localName, "moz-checkbox", "Checkbox is a moz-checkbox.");
- // Testcase with Firefox set as the default browser
- await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:preferences");
- await test_with_mock_shellservice({ isDefault: true }, async function () {
- let alwaysCheck = content.document.getElementById("alwaysCheckDefault");
Assert.ok(
- alwaysCheck.disabled,
- "'Always Check' is still disabled after default browser updated"
+ !BrowserTestUtils.isHidden(alwaysCheck.control),
+ "Control element is visible by default"
);
- });
- gBrowser.removeCurrentTab();
-});
-registerCleanupFunction(function () {
- Services.prefs.unlockPref("browser.shell.checkDefaultBrowser");
- Services.prefs.setBoolPref(
- "browser.shell.checkDefaultBrowser",
- CHECK_DEFAULT_INITIAL
- );
-});
-
-async function test_with_mock_shellservice(options, testFn) {
- await SpecialPowers.spawn(
- gBrowser.selectedBrowser,
- [options],
- async function (contentOptions) {
- let doc = content.document;
- let win = doc.defaultView;
- win.oldShellService = win.getShellService();
- let mockShellService = {
- _isDefault: false,
- isDefaultBrowser() {
- return this._isDefault;
- },
- async setDefaultBrowser() {
- this._isDefault = true;
- },
- };
- win.getShellService = function () {
- return mockShellService;
- };
- mockShellService._isDefault = contentOptions.isDefault;
- win.gMainPane.updateSetDefaultBrowser();
- }
- );
-
- await SpecialPowers.spawn(gBrowser.selectedBrowser, [], testFn);
-
- Services.prefs.setBoolPref(
- "browser.shell.checkDefaultBrowser",
- CHECK_DEFAULT_INITIAL
- );
-}
+ Assert.ok(!alwaysCheck.disabled, "'Always Check' is NOT disabled");
+
+ Assert.ok(!alwaysCheck.checked, "Checkbox is NOT checked initially");
+
+ is(
+ content.document.l10n.getAttributes(alwaysCheck).id,
+ "always-check-default",
+ `Checkbox has the correct data-l10n-id attribute`
+ );
+ teardown();
+ }
+);
diff --git a/browser/components/preferences/widgets/setting-control/setting-control.mjs b/browser/components/preferences/widgets/setting-control/setting-control.mjs
@@ -261,7 +261,6 @@ export class SettingControl extends MozLitElement {
getControlPropertyMapping(config) {
const props = this.getCommonPropertyMapping(config);
props[".parentDisabled"] = this.parentDisabled;
- props[".control"] = this;
props["?disabled"] =
this.setting.disabled ||
this.setting.locked ||
diff --git a/browser/locales/en-US/browser/preferences/preferences.ftl b/browser/locales/en-US/browser/preferences/preferences.ftl
@@ -142,8 +142,11 @@ always-check-default =
.label = Always check if { -brand-short-name } is your default browser
.accesskey = y
-is-default = { -brand-short-name } is currently your default browser
-is-not-default = { -brand-short-name } is not your default browser
+is-default-browser =
+ .message = { -brand-short-name } is currently your default browser
+
+is-not-default-browser =
+ .message = { -brand-short-name } is not your default browser
set-as-my-default-browser =
.label = Make Default…
diff --git a/browser/themes/shared/preferences/preferences.css b/browser/themes/shared/preferences/preferences.css
@@ -250,16 +250,6 @@ radio {
/* General Pane */
-.is-default > #isNotDefaultPane,
-:not(.is-default) > #isDefaultPane {
- visibility: hidden;
-}
-
-#isDefaultLabel,
-#isNotDefaultLabel {
- font-weight: var(--font-weight-bold);
-}
-
/* stylelint-disable-next-line media-query-no-invalid */
@media not -moz-pref("browser.migrate.preferences-entrypoint.enabled") {
#dataMigrationGroup {
diff --git a/python/l10n/fluent_migrations/bug_1969949_convert_startup_config_controls.py b/python/l10n/fluent_migrations/bug_1969949_convert_startup_config_controls.py
@@ -0,0 +1,36 @@
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+import re
+import fluent.syntax.ast as FTL
+from fluent.migrate import COPY_PATTERN
+from fluent.migrate.transforms import TransformPattern
+
+
+def migrate(ctx):
+ """Bug 1969949 - Migrate startup controls to config-based, part {index}."""
+ path = "browser/browser/preferences/preferences.ftl"
+ ctx.add_transforms(
+ path,
+ path,
+ [
+ FTL.Message(
+ id=FTL.Identifier("is-default-browser"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("message"),
+ value=COPY_PATTERN(path, "is-default"),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("is-not-default-browser"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("message"),
+ value=COPY_PATTERN(path, "is-not-default"),
+ ),
+ ],
+ ),
+ ],
+ )
diff --git a/toolkit/content/preferences/Preferences.mjs b/toolkit/content/preferences/Preferences.mjs
@@ -75,6 +75,8 @@ import { Setting } from "chrome://global/content/preferences/Setting.mjs";
/**
* @callback PreferencesSettingConfigOnUserClickFunction
* @param {Event} event
+ * @param {PreferenceSettingDepsMap} deps
+ * @param {Setting} setting
* @returns {void}
*/
diff --git a/toolkit/content/preferences/Setting.mjs b/toolkit/content/preferences/Setting.mjs
@@ -31,6 +31,10 @@ ChromeUtils.defineESModuleGetters(lazy, {
* @typedef {Record<string, Setting | undefined>} PreferenceSettingDepsMap
*/
+/**
+ * @typedef {string | boolean | number} SettingValue
+ */
+
export class Setting extends EventEmitter {
/**
* @type {Preference | undefined | null}
@@ -122,7 +126,7 @@ export class Setting extends EventEmitter {
}
/**
- * @type {string | undefined}
+ * @type {SettingValue}
*/
get value() {
let prefVal = this.pref?.value;
@@ -133,7 +137,7 @@ export class Setting extends EventEmitter {
}
/**
- * @param {string} val
+ * @param {SettingValue} val
*/
set value(val) {
let newVal = this.config.set ? this.config.set(val, this.deps, this) : val;