/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ /* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */ /* This Source Code Form is subject to the terms of the Mozilla Public * 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/. */ /** * Provides functions to handle status and messages in the user interface. */ "use strict"; this.EXPORTED_SYMBOLS = [ "DownloadUIHelper", ]; // Globals const Cc = Components.classes; const Ci = Components.interfaces; const Cu = Components.utils; const Cr = Components.results; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Promise", "resource://gre/modules/Promise.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm"); const kStringBundleUrl = "chrome://mozapps/locale/downloads/downloads.properties"; const kStringsRequiringFormatting = { fileExecutableSecurityWarning: true, cancelDownloadsOKTextMultiple: true, quitCancelDownloadsAlertMsgMultiple: true, quitCancelDownloadsAlertMsgMacMultiple: true, offlineCancelDownloadsAlertMsgMultiple: true, leavePrivateBrowsingWindowsCancelDownloadsAlertMsgMultiple2: true }; // DownloadUIHelper /** * Provides functions to handle status and messages in the user interface. */ this.DownloadUIHelper = { /** * Returns an object that can be used to display prompts related to downloads. * * The prompts may be either anchored to a specified window, or anchored to * the most recently active window, for example if the prompt is displayed in * response to global notifications that are not associated with any window. * * @param aParent * If specified, should reference the nsIDOMWindow to which the prompts * should be attached. If omitted, the prompts will be attached to the * most recently active window. * * @return A DownloadPrompter object. */ getPrompter: function (aParent) { return new DownloadPrompter(aParent || null); }, }; /** * Returns an object whose keys are the string names from the downloads string * bundle, and whose values are either the translated strings or functions * returning formatted strings. */ XPCOMUtils.defineLazyGetter(DownloadUIHelper, "strings", function () { let strings = {}; let sb = Services.strings.createBundle(kStringBundleUrl); let enumerator = sb.getSimpleEnumeration(); while (enumerator.hasMoreElements()) { let string = enumerator.getNext().QueryInterface(Ci.nsIPropertyElement); let stringName = string.key; if (stringName in kStringsRequiringFormatting) { strings[stringName] = function () { // Convert "arguments" to a real array before calling into XPCOM. return sb.formatStringFromName(stringName, Array.slice(arguments, 0), arguments.length); }; } else { strings[stringName] = string.value; } } return strings; }); // DownloadPrompter /** * Allows displaying prompts related to downloads. * * @param aParent * The nsIDOMWindow to which prompts should be attached, or null to * attach prompts to the most recently active window. */ this.DownloadPrompter = function (aParent) { this._prompter = Services.ww.getNewPrompter(aParent); } this.DownloadPrompter.prototype = { /** * Constants with the different type of prompts. */ ON_QUIT: "prompt-on-quit", ON_OFFLINE: "prompt-on-offline", ON_LEAVE_PRIVATE_BROWSING: "prompt-on-leave-private-browsing", /** * nsIPrompt instance for displaying messages. */ _prompter: null, /** * Displays a warning message box that informs that the specified file is * executable, and asks whether the user wants to launch it. * * @param aPath * String containing the full path to the file to be opened. * * @resolves Boolean indicating whether the launch operation can continue. */ async confirmLaunchExecutable: function (aPath) { const kPrefConfirmOpenExe = "browser.download.confirmOpenExecutable"; // Always launch in case we have no prompter implementation. if (!this._prompter) { return true; } try { if (!Services.prefs.getBoolPref(kPrefConfirmOpenExe)) { return true; } } catch (ex) { // If the preference does not exist, continue with the prompt. } let leafName = OS.Path.basename(aPath); let s = DownloadUIHelper.strings; return this._prompter.confirm(s.fileExecutableSecurityWarningTitle, s.fileExecutableSecurityWarning(leafName, leafName)); }, /** * Displays a warning message box that informs that there are active * downloads, and asks whether the user wants to cancel them or not. * * @param aDownloadsCount * The current downloads count. * @param aPromptType * The type of prompt notification depending on the observer. * * @return False to cancel the downloads and continue, true to abort the * operation. */ confirmCancelDownloads: function DP_confirmCancelDownload(aDownloadsCount, aPromptType) { // Always continue in case we have no prompter implementation, or if there // are no active downloads. if (!this._prompter || aDownloadsCount <= 0) { return false; } let s = DownloadUIHelper.strings; let buttonFlags = (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_0) + (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_1); let okButton = aDownloadsCount > 1 ? s.cancelDownloadsOKTextMultiple(aDownloadsCount) : s.cancelDownloadsOKText; let title, message, cancelButton; switch (aPromptType) { case this.ON_QUIT: title = s.quitCancelDownloadsAlertTitle; #ifdef XP_MACOSX message = aDownloadsCount > 1 ? s.quitCancelDownloadsAlertMsgMacMultiple(aDownloadsCount) : s.quitCancelDownloadsAlertMsgMac; cancelButton = s.dontQuitButtonMac; #else message = aDownloadsCount > 1 ? s.quitCancelDownloadsAlertMsgMultiple(aDownloadsCount) : s.quitCancelDownloadsAlertMsg; cancelButton = s.dontQuitButtonWin; #endif break; case this.ON_OFFLINE: title = s.offlineCancelDownloadsAlertTitle; message = aDownloadsCount > 1 ? s.offlineCancelDownloadsAlertMsgMultiple(aDownloadsCount) : s.offlineCancelDownloadsAlertMsg; cancelButton = s.dontGoOfflineButton; break; case this.ON_LEAVE_PRIVATE_BROWSING: title = s.leavePrivateBrowsingCancelDownloadsAlertTitle; message = aDownloadsCount > 1 ? s.leavePrivateBrowsingWindowsCancelDownloadsAlertMsgMultiple2(aDownloadsCount) : s.leavePrivateBrowsingWindowsCancelDownloadsAlertMsg2; cancelButton = s.dontLeavePrivateBrowsingButton2; break; } let rv = this._prompter.confirmEx(title, message, buttonFlags, okButton, cancelButton, null, null, {}); return (rv == 1); } };