
morgan pushed to branch mullvad-browser-140.2.0esr-15.0-1 at The Tor Project / Applications / Mullvad Browser Commits: 3bd4ddd5 by Henry Wilkes at 2025-08-14T16:11:39+00:00 BB 44040: Modify prompt service for Base Browser. - - - - - 887c6e2e by Henry Wilkes at 2025-08-14T16:11:39+00:00 fixup! BB 40925: Implemented the Security Level component TB 44030: Show a warning before restarting the browser when applying a new security level. Also adapt the existing warning to use a destructive button and the button "Restart Tor Browser" rather than just "Restart". - - - - - b95639fd by Henry Wilkes at 2025-08-14T16:11:40+00:00 fixup! Base Browser strings TB 44030: Add strings for the new security level warning dialog. - - - - - 8 changed files: - browser/components/securitylevel/content/securityLevelDialog.js - browser/modules/SecurityLevelRestartNotification.sys.mjs - netwerk/base/nsIPrompt.idl - toolkit/components/prompts/content/commonDialog.js - toolkit/components/prompts/src/Prompter.sys.mjs - toolkit/components/windowwatcher/nsIPromptService.idl - toolkit/content/widgets/dialog.js - toolkit/locales/en-US/toolkit/global/base-browser.ftl Changes: ===================================== browser/components/securitylevel/content/securityLevelDialog.js ===================================== @@ -39,8 +39,8 @@ const gSecurityLevelDialog = { async init() { const dialog = document.getElementById("security-level-dialog"); dialog.addEventListener("dialogaccept", event => { + event.preventDefault(); if (this._acceptButton.disabled) { - event.preventDefault(); return; } this._commitChange(); @@ -158,7 +158,41 @@ const gSecurityLevelDialog = { /** * Commit the change in security level and restart the browser. */ - _commitChange() { + async _commitChange() { + const doNotWarnPref = "browser.security_level.disable_warn_before_restart"; + if (!Services.prefs.getBoolPref(doNotWarnPref, false)) { + const [titleString, bodyString, checkboxString, restartString] = + await document.l10n.formatValues([ + { id: "security-level-restart-warning-dialog-title" }, + { id: "security-level-restart-warning-dialog-body" }, + { id: "restart-warning-dialog-do-not-warn-checkbox" }, + { id: "restart-warning-dialog-restart-button" }, + ]); + const flags = + Services.prompt.BUTTON_POS_0 * Services.prompt.BUTTON_TITLE_IS_STRING + + Services.prompt.BUTTON_POS_0_DEFAULT + + Services.prompt.BUTTON_DEFAULT_IS_DESTRUCTIVE + + Services.prompt.BUTTON_POS_1 * Services.prompt.BUTTON_TITLE_CANCEL; + const propBag = await Services.prompt.asyncConfirmEx( + window.browsingContext.top, + Services.prompt.MODAL_TYPE_CONTENT, + titleString, + bodyString, + flags, + restartString, + null, + null, + checkboxString, + false, + { useTitle: true, noIcon: true } + ); + if (propBag.get("buttonNumClicked") !== 0) { + return; + } + if (propBag.get("checked")) { + Services.prefs.setBoolPref(doNotWarnPref, true); + } + } SecurityLevelPrefs.setSecurityLevelBeforeRestart(this._selectedLevel); Services.startup.quit( Services.startup.eAttemptQuit | Services.startup.eRestart ===================================== browser/modules/SecurityLevelRestartNotification.sys.mjs ===================================== @@ -42,11 +42,13 @@ export const SecurityLevelRestartNotification = { await lazy.NotificationStrings.formatValues([ { id: "security-level-restart-prompt-title" }, { id: "security-level-restart-prompt-body" }, - { id: "security-level-restart-prompt-button-restart" }, + { id: "restart-warning-dialog-restart-button" }, { id: "security-level-restart-prompt-button-ignore" }, ]); const buttonFlags = Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_0 + + Services.prompt.BUTTON_POS_0_DEFAULT + + Services.prompt.BUTTON_DEFAULT_IS_DESTRUCTIVE + Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_1; const propBag = await Services.prompt.asyncConfirmEx( ===================================== netwerk/base/nsIPrompt.idl ===================================== @@ -67,6 +67,8 @@ interface nsIPrompt : nsISupports const unsigned long BUTTON_POS_1_IS_SECONDARY = 1 << 29; + const unsigned long BUTTON_DEFAULT_IS_DESTRUCTIVE = 1 << 30; + const unsigned long STD_OK_CANCEL_BUTTONS = (BUTTON_TITLE_OK * BUTTON_POS_0) + (BUTTON_TITLE_CANCEL * BUTTON_POS_1); const unsigned long STD_YES_NO_BUTTONS = (BUTTON_TITLE_YES * BUTTON_POS_0) + ===================================== toolkit/components/prompts/content/commonDialog.js ===================================== @@ -39,7 +39,7 @@ function commonDialogOnLoad() { ["promptUserAndPass", "promptPassword"].includes(args.promptType) || args.headerIconCSSValue; let root = document.documentElement; - if (needIconifiedHeader) { + if (needIconifiedHeader && !args.noIcon) { root.setAttribute("neediconheader", "true"); } let title = { raw: args.title }; @@ -107,6 +107,10 @@ function commonDialogOnLoad() { dialog.setAttribute("extra1-is-secondary", true); } + if (args.isDefaultDestructive) { + dialog.setAttribute("default-is-destructive", true); + } + Dialog = new CommonDialog(args, ui); window.addEventListener("dialogclosing", function (aEvent) { if (aEvent.detail?.abort) { ===================================== toolkit/components/prompts/src/Prompter.sys.mjs ===================================== @@ -1507,6 +1507,10 @@ class ModalPrompter { args.isExtra1Secondary = true; } + if (flags & Ci.nsIPrompt.BUTTON_DEFAULT_IS_DESTRUCTIVE) { + args.isDefaultDestructive = true; + } + if (flags & Ci.nsIPrompt.SHOW_SPINNER) { args.headerIconCSSValue = "url('chrome://global/skin/icons/loading.svg')"; } ===================================== toolkit/components/windowwatcher/nsIPromptService.idl ===================================== @@ -287,6 +287,8 @@ interface nsIPromptService : nsISupports */ const unsigned long BUTTON_POS_1_IS_SECONDARY = 1 << 29; + const unsigned long BUTTON_DEFAULT_IS_DESTRUCTIVE = 1 << 30; + /** * Selects the standard set of OK/Cancel buttons. */ ===================================== toolkit/content/widgets/dialog.js ===================================== @@ -21,7 +21,8 @@ static get observedAttributes() { return super.observedAttributes.concat( "subdialog", - "extra1-is-secondary" + "extra1-is-secondary", + "default-is-destructive" ); } @@ -40,6 +41,12 @@ if (name === "extra1-is-secondary" && AppConstants.XP_UNIX) { this.getButton("cancel").after(this.getButton("extra1")); } + if (name === "default-is-destructive") { + this.#setButtonIsDestructive( + this.getButton(this.defaultButton), + this.hasAttribute("default-is-destructive") + ); + } super.attributeChangedCallback(name, oldValue, newValue); } @@ -491,12 +498,17 @@ var oldDefaultButton = this.getButton(this.defaultButton); if (oldDefaultButton) { oldDefaultButton.removeAttribute("default"); + this.#setButtonIsDestructive(oldDefaultButton, false); } var newDefaultButton = this.getButton(aNewDefault); if (newDefaultButton) { this.setAttribute("defaultButton", aNewDefault); newDefaultButton.setAttribute("default", "true"); + this.#setButtonIsDestructive( + newDefaultButton, + this.hasAttribute("default-is-destructive") + ); } else { this.setAttribute("defaultButton", "none"); if (aNewDefault != "none") { @@ -507,6 +519,16 @@ } } + /** + * Mark or un-mark a button as a destructive action. + * + * @param {?Element} button - The button to mark. + * @param {boolean} isDestructive - Whether the button is destructive. + */ + #setButtonIsDestructive(button, isDestructive) { + button?.classList.toggle("danger-button", isDestructive); + } + _handleButtonCommand(aEvent) { return this._doButtonCommand(aEvent.target.getAttribute("dlgtype")); } ===================================== toolkit/locales/en-US/toolkit/global/base-browser.ftl ===================================== @@ -177,6 +177,13 @@ security-level-preferences-bullet-limit-media = Audio and video (HTML5 media), a security-level-preferences-bullet-disabled-javascript = JavaScript is disabled by default on all sites. security-level-preferences-bullet-limit-font-and-symbols-and-images = Some fonts, icons, math symbols, and images are disabled. +## Security level dialog warning the user about a restart. + +# '-brand-short-name' is the localized browser name, like "Tor Browser". +security-level-restart-warning-dialog-title = Restart { -brand-short-name } to apply changes? +# '-brand-short-name' is the localized browser name, like "Tor Browser". +security-level-restart-warning-dialog-body = { -brand-short-name } needs to restart to apply your changes. This will close all your windows and tabs. + ## Custom security level. ## Some custom preferences configuration has placed the user outside one of the standard three levels. @@ -188,5 +195,12 @@ security-level-summary-custom = Your custom browser preferences have resulted in security-level-restart-prompt-title = Your security level settings require a restart security-level-restart-prompt-body = You must restart { -brand-short-name } for your security level settings to be applied. This will close all your windows and tabs. -security-level-restart-prompt-button-restart = Restart security-level-restart-prompt-button-ignore = Ignore + +## Part of the restart dialogs for security level and new identity. + +# Checkbox to never show the restart warning dialog again. +restart-warning-dialog-do-not-warn-checkbox = Don’t show this warning again +# Button to restart the browser. +# '-brand-short-name' is the localized browser name, like "Tor Browser". +restart-warning-dialog-restart-button = Restart { -brand-short-name } View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/compare/8c3... -- View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/compare/8c3... You're receiving this email because of your account on gitlab.torproject.org.
participants (1)
-
morgan (@morgan)