diff --git a/browser/actors/PromptParent.sys.mjs b/browser/actors/PromptParent.sys.mjs index fe8c5db522a1..d190dbfbc69f 100644 --- a/browser/actors/PromptParent.sys.mjs +++ b/browser/actors/PromptParent.sys.mjs @@ -11,7 +11,7 @@ ChromeUtils.defineESModuleGetters(lazy, { }); ChromeUtils.defineLazyGetter(lazy, "gTabBrowserLocalization", function () { - return new Localization(["browser/tabbrowser.ftl"], true); + return new Localization(["browser/tabbrowser.ftl", "browser/waterfox.ftl"], true); }); /** diff --git a/browser/components/BrowserGlue.sys.mjs b/browser/components/BrowserGlue.sys.mjs index f8198001eef5..cd47b70e1a55 100644 --- a/browser/components/BrowserGlue.sys.mjs +++ b/browser/components/BrowserGlue.sys.mjs @@ -1532,6 +1532,18 @@ BrowserGlue.prototype = { aQuitType = "quit"; } + let restoreSession; + let startupPref = Services.prefs.getIntPref("browser.startup.page"); + + // If we are set to anything other than restore session, + if (startupPref != 3) { + console.log("Value of: " + startupPref); + restoreSession = { value: false }; + } else { + console.log("Value of: " + startupPref); + restoreSession = { value: true }; + } + let win = lazy.BrowserWindowTracker.getTopWindow(); // Our prompt for quitting is most important, so replace others. @@ -1585,11 +1597,14 @@ BrowserGlue.prototype = { checkboxLabelId = "tabbrowser-ask-close-tabs-checkbox"; } - const [title, quitButtonLabel, checkboxLabel] = + let checkboxLabelId2 = "tabbrowser-confirm-session-restore-checkbox"; + + const [title, quitButtonLabel, checkboxLabel, checkboxLabel2] = win.gBrowser.tabLocalization.formatMessagesSync([ titleId, quitButtonLabelId, checkboxLabelId, + checkboxLabelId2, ]); // Only format the "close current tab" message if needed @@ -1621,7 +1636,7 @@ BrowserGlue.prototype = { } // buttonPressed will be 0 for close all, 1 for cancel (don't close/quit), 2 for close current tab - let buttonPressed = Services.prompt.confirmEx( + let buttonPressed = Services.prompt.confirmEx2( win, title.value, null, @@ -1630,7 +1645,9 @@ BrowserGlue.prototype = { null, showCloseCurrentTabOption ? closeTabButtonLabel.value : null, checkboxLabel.value, - warnOnClose + warnOnClose, + checkboxLabel2.value, + restoreSession ); // If the user has unticked the box, and has confirmed closing, stop showing @@ -1648,6 +1665,18 @@ BrowserGlue.prototype = { win.gBrowser.removeTab(win.gBrowser.selectedTab); } + // If we are set to anything other than restore session, + // leave its value. + if (buttonPressed == 0) { + if (!restoreSession.value) { + if (startupPref === 3) { + Services.prefs.setIntPref("browser.startup.page", 1); + } + } else if (restoreSession.value) { + Services.prefs.setIntPref("browser.startup.page", 3); + } + } + this._quitSource = "unknown"; aCancelQuit.data = buttonPressed != 0; diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js index 37570c54b06f..f5ee4ce63dcd 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js @@ -117,7 +117,7 @@ }); ChromeUtils.defineLazyGetter(this, "tabLocalization", () => { return new Localization( - ["browser/tabbrowser.ftl", "branding/brand.ftl"], + ["browser/tabbrowser.ftl", "branding/brand.ftl", "browser/waterfox.ftl"], true ); }); @@ -3806,36 +3806,65 @@ // default to true: if it were false, we wouldn't get this far var warnOnClose = { value: true }; + let restoreSession; + let startupPref = Services.prefs.getIntPref("browser.startup.page"); + + // If we are set to anything other than restore session, + // leave its value. + if (startupPref != 3) { + restoreSession = { value: false }; + } else { + restoreSession = { value: true }; + } + // focus the window before prompting. // this will raise any minimized window, which will // make it obvious which window the prompt is for and will // solve the problem of windows "obscuring" the prompt. // see bug #350299 for more details window.focus(); - const [title, button, checkbox] = this.tabLocalization.formatValuesSync([ + const [title, button, checkbox, checkboxLabel2] = this.tabLocalization.formatValuesSync([ { id: "tabbrowser-confirm-close-tabs-title", args: { tabCount: tabsToClose }, }, { id: "tabbrowser-confirm-close-tabs-button" }, { id: "tabbrowser-ask-close-tabs-checkbox" }, + { id: "tabbrowser-confirm-session-restore-checkbox" } ]); let flags = ps.BUTTON_TITLE_IS_STRING * ps.BUTTON_POS_0 + ps.BUTTON_TITLE_CANCEL * ps.BUTTON_POS_1; let checkboxLabel = aCloseTabs == this.closingTabsEnum.ALL ? checkbox : null; - var buttonPressed = ps.confirmEx( - window, - title, - null, - flags, - button, - null, - null, - checkboxLabel, - warnOnClose - ); + var buttonPressed; + if (Services.prefs.getBoolPref("browser.tabs.warnOnCloseOtherTabs")) { + buttonPressed = ps.confirmEx( + window, + title, + null, + flags, + button, + null, + null, + checkboxLabel, + warnOnClose + ); + } else if (Services.prefs.getBoolPref("browser.tabs.warnOnClose")) { + buttonPressed = ps.confirmEx2( + window, + title, + null, + flags, + button, + null, + null, + checkboxLabel, + warnOnClose, + checkboxLabel2, + restoreSession + ); + } var reallyClose = buttonPressed == 0; @@ -3848,6 +3877,16 @@ Services.prefs.setBoolPref(pref, false); } + if (buttonPressed == 0) { + if (!restoreSession.value) { + if (startupPref === 3) { + Services.prefs.setIntPref("browser.startup.page", 1); + } + } else if (restoreSession.value) { + Services.prefs.setIntPref("browser.startup.page", 3); + } + } + return reallyClose; } diff --git a/netwerk/base/nsIPrompt.idl b/netwerk/base/nsIPrompt.idl index 46f23ee7c5a9..6455f474a4c8 100644 --- a/netwerk/base/nsIPrompt.idl +++ b/netwerk/base/nsIPrompt.idl @@ -90,6 +90,17 @@ interface nsIPrompt : nsISupports in wstring checkMsg, inout boolean checkValue); + int32_t confirmEx2(in wstring dialogTitle, + in wstring text, + in unsigned long buttonFlags, + in wstring button0Title, + in wstring button1Title, + in wstring button2Title, + in wstring checkMsg, + inout boolean checkValue, + in wstring checkMsg2, + inout boolean checkValue2); + boolean prompt(in wstring dialogTitle, in wstring text, inout wstring value, diff --git a/toolkit/components/prompts/content/commonDialog.js b/toolkit/components/prompts/content/commonDialog.js index 71108e6d3595..6c11782cca38 100644 --- a/toolkit/components/prompts/content/commonDialog.js +++ b/toolkit/components/prompts/content/commonDialog.js @@ -95,6 +95,7 @@ function commonDialogOnLoad() { infoTitle: document.getElementById("infoTitle"), infoIcon: document.getElementById("infoIcon"), checkbox: document.getElementById("checkbox"), + checkbox2: document.getElementById("checkbox2"), checkboxContainer: document.getElementById("checkboxContainer"), button3: dialog.getButton("extra2"), button2: dialog.getButton("extra1"), @@ -140,6 +141,9 @@ function commonDialogOnLoad() { case "checkbox": Dialog.onCheckbox(); break; + case "checkbox2": + Dialog.onCheckbox2(); + break; } }); diff --git a/toolkit/components/prompts/content/commonDialog.xhtml b/toolkit/components/prompts/content/commonDialog.xhtml index c47761ec958a..5ce85d73978e 100644 --- a/toolkit/components/prompts/content/commonDialog.xhtml +++ b/toolkit/components/prompts/content/commonDialog.xhtml @@ -92,6 +92,7 @@
+
diff --git a/toolkit/components/prompts/src/CommonDialog.sys.mjs b/toolkit/components/prompts/src/CommonDialog.sys.mjs index fbe3ac253a51..37cde1f5a680 100644 --- a/toolkit/components/prompts/src/CommonDialog.sys.mjs +++ b/toolkit/components/prompts/src/CommonDialog.sys.mjs @@ -78,6 +78,28 @@ export class CommonDialog { this.iconClass = ["question-icon"]; this.soundID = Ci.nsISound.EVENT_CONFIRM_DIALOG_OPEN; break; + case "confirmEx2": + var numButtons2 = 0; + if (this.args.button0Label) { + numButtons2++; + } + if (this.args.button1Label) { + numButtons2++; + } + if (this.args.button2Label) { + numButtons2++; + } + if (this.args.button3Label) { + numButtons2++; + } + if (numButtons2 == 0) { + throw new Error("A dialog with no buttons? Can not haz."); + } + this.numButtons = numButtons2; + this.hasInputField = false; + this.iconClass = ["question-icon"]; + this.soundID = Ci.nsISound.EVENT_CONFIRM_DIALOG_OPEN; + break; case "prompt": this.numButtons = 2; this.iconClass = ["question-icon"]; @@ -171,13 +193,35 @@ export class CommonDialog { let infoBody = this.ui.infoBody; infoBody.appendChild(infoBody.ownerDocument.createTextNode(croppedMessage)); + // WATERFOX: Check if both labels are undefined before deciding to hide the container. + // This first checks if both labels are undefined before hiding the container. + // If not, it shows the container and then proceeds to render each checkbox if its corresponding label is defined. let label = this.args.checkLabel; - if (label) { - // Only show the checkbox if label has a value. + let label2 = this.args.checkLabel2; + + if (!label && !label2) { + // Hide everything if both labels undefined + this.ui.checkboxContainer.hidden = true; + } else { + // Show container this.ui.checkboxContainer.hidden = false; - this.ui.checkboxContainer.clientTop; // style flush to assure binding is attached - this.setLabelForNode(this.ui.checkbox, label); - this.ui.checkbox.checked = this.args.checked; + this.ui.checkboxContainer.clientTop; + + if (label) { + this.setLabelForNode(this.ui.checkbox, label); + this.ui.checkbox.hidden = false; + this.ui.checkbox.checked = this.args.checked; + } else { + this.ui.checkbox.hidden = true; + } + + if (label2) { + this.setLabelForNode(this.ui.checkbox2, label2); + this.ui.checkbox2.hidden = false; + this.ui.checkbox2.checked = this.args.checked2; + } else { + this.ui.checkbox2.hidden = true; + } } // set the icon @@ -310,6 +354,10 @@ export class CommonDialog { this.args.checked = this.ui.checkbox.checked; } + onCheckbox2() { + this.args.checked2 = this.ui.checkbox2.checked; + } + onButton0() { this.args.promptActive = false; this.args.ok = true; diff --git a/toolkit/components/prompts/src/Prompter.sys.mjs b/toolkit/components/prompts/src/Prompter.sys.mjs index 0977c1e7bbe9..19723f441c93 100644 --- a/toolkit/components/prompts/src/Prompter.sys.mjs +++ b/toolkit/components/prompts/src/Prompter.sys.mjs @@ -312,6 +312,34 @@ Prompter.prototype = { ); }, + confirmEx2( + domWin, + title, + text, + flags, + button0, + button1, + button2, + checkLabel, + checkValue, + checkLabel2, + checkValue2 + ) { + let p = this.pickPrompter({ domWin }); + return p.confirmEx2( + title, + text, + flags, + button0, + button1, + button2, + checkLabel, + checkValue, + checkLabel2, + checkValue2 + ); + }, + /** * Puts up a dialog with up to 3 buttons and an optional, labeled checkbox. * @param {BrowsingContext} browsingContext - The browsing context the @@ -1524,6 +1552,66 @@ class ModalPrompter { return args.buttonNumClicked; } + confirmEx2( + title, + text, + flags, + button0, + button1, + button2, + checkLabel, + checkValue, + checkLabel2, + checkValue2, + extraArgs = {} + ) { + if (!title) { + title = InternalPromptUtils.getLocalizedString("Confirm"); + } + + let args = { + promptType: "confirmEx2", + title, + text, + checkLabel, + checked: this.async ? checkValue : checkValue.value, + checkLabel2, + checked2: this.async ? checkValue2 : checkValue2.value, + ok: false, + buttonNumClicked: 1, + ...extraArgs, + }; + + let [label0, label1, label2, defaultButtonNum, isDelayEnabled] = + InternalPromptUtils.confirmExHelper(flags, button0, button1, button2); + + args.defaultButtonNum = defaultButtonNum; + args.enableDelay = isDelayEnabled; + + if (label0) { + args.button0Label = label0; + if (label1) { + args.button1Label = label1; + if (label2) { + args.button2Label = label2; + } + } + } + + if (this.async) { + return this.openPromptAsync(args, result => ({ + checked: !!result.checked, + checked2: !!result.checked2, + buttonNumClicked: result.buttonNumClicked, + })); + } + + this.openPromptSync(args); + checkValue.value = args.checked; + checkValue2.value = args.checked2; + return args.buttonNumClicked; + } + nsIPrompt_prompt(title, text, value, checkLabel, checkValue) { if (!title) { title = InternalPromptUtils.getLocalizedString("Prompt"); diff --git a/toolkit/components/windowwatcher/nsIPromptService.idl b/toolkit/components/windowwatcher/nsIPromptService.idl index a675d4ababc9..e1fd43944ffc 100644 --- a/toolkit/components/windowwatcher/nsIPromptService.idl +++ b/toolkit/components/windowwatcher/nsIPromptService.idl @@ -363,6 +363,67 @@ interface nsIPromptService : nsISupports in wstring aButton2Title, in wstring aCheckMsg, inout boolean aCheckState); + + /** + * Puts up a dialog with up to 3 buttons and an optional, labeled checkbox. + * + * @param aParent + * The parent window or null. + * @param aDialogTitle + * Text to appear in the title of the dialog. + * @param aText + * Text to appear in the body of the dialog. + * @param aButtonFlags + * A combination of Button Flags. + * @param aButton0Title + * Used when button 0 uses TITLE_IS_STRING + * @param aButton1Title + * Used when button 1 uses TITLE_IS_STRING + * @param aButton2Title + * Used when button 2 uses TITLE_IS_STRING + * @param aCheckMsg + * Text to appear with the checkbox. Null if no checkbox. + * @param aCheckState + * Contains the initial checked state of the checkbox when this method + * is called and the final checked state after this method returns. + * @param aCheckMsg2 + * A second text to appear with the checkbox. Null if no checkbox. + * @param aCheckState2 + * Contains the initial checked state of the checkbox when this method + * is called and the final checked state after this method returns. + * + * @return index of the button pressed. + * + * Buttons are numbered 0 - 2. The implementation can decide whether the + * sequence goes from right to left or left to right. Button 0 is the + * default button unless one of the Button Default Flags is specified. + * + * A button may use a predefined title, specified by one of the Button Title + * Flags values. Each title value can be multiplied by a position value to + * assign the title to a particular button. If BUTTON_TITLE_IS_STRING is + * used for a button, the string parameter for that button will be used. If + * the value for a button position is zero, the button will not be shown. + * + * In general, aButtonFlags is constructed per the following example: + * + * aButtonFlags = (BUTTON_POS_0) * (BUTTON_TITLE_AAA) + + * (BUTTON_POS_1) * (BUTTON_TITLE_BBB) + + * BUTTON_POS_1_DEFAULT; + * + * where "AAA" and "BBB" correspond to one of the button titles. + */ + int32_t confirmEx2(in mozIDOMWindowProxy aParent, + in wstring aDialogTitle, + in wstring aText, + in unsigned long aButtonFlags, + in wstring aButton0Title, + in wstring aButton1Title, + in wstring aButton2Title, + in wstring aCheckMsg, + inout boolean aCheckState, + in wstring aCheckMsg2, + inout boolean aCheckState2); + /** * Like confirmEx, but with a BrowsingContext as parent. *