summaryrefslogtreecommitdiffstats
path: root/toolkit/components/jsdownloads/src/DownloadUIHelper.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/jsdownloads/src/DownloadUIHelper.jsm')
-rw-r--r--toolkit/components/jsdownloads/src/DownloadUIHelper.jsm243
1 files changed, 243 insertions, 0 deletions
diff --git a/toolkit/components/jsdownloads/src/DownloadUIHelper.jsm b/toolkit/components/jsdownloads/src/DownloadUIHelper.jsm
new file mode 100644
index 000000000..f5102b4a8
--- /dev/null
+++ b/toolkit/components/jsdownloads/src/DownloadUIHelper.jsm
@@ -0,0 +1,243 @@
+/* -*- 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");
+Cu.import("resource://gre/modules/AppConstants.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)
+{
+ if (AppConstants.MOZ_B2G) {
+ // On B2G there is no prompter implementation.
+ this._prompter = null;
+ } else {
+ 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. The user is
+ * given the option of disabling future instances of this warning.
+ *
+ * @param aPath
+ * String containing the full path to the file to be opened.
+ *
+ * @return {Promise}
+ * @resolves Boolean indicating whether the launch operation can continue.
+ * @rejects JavaScript exception.
+ */
+ confirmLaunchExecutable: function (aPath)
+ {
+ const kPrefAlertOnEXEOpen = "browser.download.manager.alertOnEXEOpen";
+
+ try {
+ // Always launch in case we have no prompter implementation.
+ if (!this._prompter) {
+ return Promise.resolve(true);
+ }
+
+ try {
+ if (!Services.prefs.getBoolPref(kPrefAlertOnEXEOpen)) {
+ return Promise.resolve(true);
+ }
+ } catch (ex) {
+ // If the preference does not exist, continue with the prompt.
+ }
+
+ let leafName = OS.Path.basename(aPath);
+
+ let s = DownloadUIHelper.strings;
+ let checkState = { value: false };
+ let shouldLaunch = this._prompter.confirmCheck(
+ s.fileExecutableSecurityWarningTitle,
+ s.fileExecutableSecurityWarning(leafName, leafName),
+ s.fileExecutableSecurityWarningDontAsk,
+ checkState);
+
+ if (shouldLaunch) {
+ Services.prefs.setBoolPref(kPrefAlertOnEXEOpen, !checkState.value);
+ }
+
+ return Promise.resolve(shouldLaunch);
+ } catch (ex) {
+ return Promise.reject(ex);
+ }
+ },
+
+ /**
+ * 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;
+ if (AppConstants.platform != "macosx") {
+ message = aDownloadsCount > 1
+ ? s.quitCancelDownloadsAlertMsgMultiple(aDownloadsCount)
+ : s.quitCancelDownloadsAlertMsg;
+ cancelButton = s.dontQuitButtonWin;
+ } else {
+ message = aDownloadsCount > 1
+ ? s.quitCancelDownloadsAlertMsgMacMultiple(aDownloadsCount)
+ : s.quitCancelDownloadsAlertMsgMac;
+ cancelButton = s.dontQuitButtonMac;
+ }
+ 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);
+ }
+};