Bug 1547041 - Update and tidy SeaMonkey application preferences - Part 2: general fixes up to esr60 level. r=frg
authorIan Neal <iann_cvs@blueyonder.co.uk>
Sat, 22 Jun 2019 11:04:33 +0200
changeset 35922 60e3e0e72160bfd8bf8c183428ab38eb11ac4a9b
parent 35921 bcf0c2684ace6bca63d1fa08f35c8016e1d8bb54
child 35923 aedfbb684ce8128dff40ab4619599393a3e44edd
push id392
push userclokep@gmail.com
push dateMon, 02 Sep 2019 20:17:19 +0000
reviewersfrg
bugs1547041
Bug 1547041 - Update and tidy SeaMonkey application preferences - Part 2: general fixes up to esr60 level. r=frg
suite/components/pref/content/pref-applicationManager.js
suite/components/pref/content/pref-applications.js
suite/components/pref/jar.mn
--- a/suite/components/pref/content/pref-applicationManager.js
+++ b/suite/components/pref/content/pref-applicationManager.js
@@ -1,17 +1,12 @@
 /* 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/. */
 
-// As pref-applications.js is always loaded, we can (and should!) reuse
-// the nsI* constants from there, if needed also any services we need.
-
-var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
-
 var gAppManagerDialog = {
   _removed: [],
 
   init: function appManager_init() {
     this.handlerInfo = window.arguments[0];
 
     var bundle = document.getElementById("appManagerBundle");
     var contentText;
@@ -25,16 +20,19 @@ var gAppManagerDialog = {
       contentText = bundle.getFormattedString(key, [description]);
     }
     document.getElementById("appDescription").textContent = contentText;
 
     var list = document.getElementById("appList");
     var apps = this.handlerInfo.possibleApplicationHandlers.enumerate();
     while (apps.hasMoreElements()) {
       let app = apps.getNext();
+      if (!gApplicationsPane.isValidHandlerApp(app))
+        continue;
+
       app.QueryInterface(Ci.nsIHandlerApp);
       var item = list.appendItem(app.name);
       item.className = "listitem-iconic";
       item.setAttribute("image", gApplicationsPane._getIconURLForHandlerApp(app));
       item.app = app;
     }
 
     list.selectedIndex = 0;
--- a/suite/components/pref/content/pref-applications.js
+++ b/suite/components/pref/content/pref-applications.js
@@ -178,18 +178,18 @@ HandlerInfoWrapper.prototype = {
   type: null,
 
   get description() {
     if (this.wrappedHandlerInfo.description)
       return this.wrappedHandlerInfo.description;
 
     if (this.primaryExtension) {
       var extension = this.primaryExtension.toUpperCase();
-      return document.getElementById("bundlePrefApplications")
-                     .getFormattedString("fileEnding", [extension]);
+      return gApplicationsPane._prefsBundle.getFormattedString("fileEnding",
+                                                               [extension]);
     }
 
     return this.type;
   },
 
   get preferredApplicationHandler() {
     return this.wrappedHandlerInfo.preferredApplicationHandler;
   },
@@ -202,37 +202,40 @@ HandlerInfoWrapper.prototype = {
       this.addPossibleApplicationHandler(aNewValue);
   },
 
   get possibleApplicationHandlers() {
     return this.wrappedHandlerInfo.possibleApplicationHandlers;
   },
 
   addPossibleApplicationHandler(aNewHandler) {
-    try {
-      if (this.possibleApplicationHandlers.indexOf(0, aNewHandler) != -1)
+    var possibleApps = this.possibleApplicationHandlers.enumerate();
+    while (possibleApps.hasMoreElements()) {
+      if (possibleApps.getNext().equals(aNewHandler))
         return;
-    } catch (e) {
     }
     this.possibleApplicationHandlers.appendElement(aNewHandler);
   },
 
   removePossibleApplicationHandler(aHandler) {
     var defaultApp = this.preferredApplicationHandler;
     if (defaultApp && aHandler.equals(defaultApp)) {
       // If the app we remove was the default app, we must make sure
       // it won't be used anymore
       this.alwaysAskBeforeHandling = true;
       this.preferredApplicationHandler = null;
     }
 
-    try {
-      var handlerIdx = this.possibleApplicationHandlers.indexOf(0, aHandler);
-      this.possibleApplicationHandlers.removeElementAt(handlerIdx);
-    } catch (e) {
+    var handlers = this.possibleApplicationHandlers;
+    for (var i = 0; i < handlers.length; ++i) {
+      var handler = handlers.queryElementAt(i, Ci.nsIHandlerApp);
+      if (handler.equals(aHandler)) {
+        handlers.removeElementAt(i);
+        break;
+      }
     }
   },
 
   get hasDefaultHandler() {
     return this.wrappedHandlerInfo.hasDefaultHandler;
   },
 
   get defaultDescription() {
@@ -257,16 +260,24 @@ HandlerInfoWrapper.prototype = {
              Ci.nsIHandlerInfo.useSystemDefault :
              Ci.nsIHandlerInfo.saveToDisk;
     }
 
     return this.wrappedHandlerInfo.preferredAction;
   },
 
   set preferredAction(aNewValue) {
+    // If the action is to use the plugin,
+    // we must set the preferred action to "save to disk".
+    // But only if it's not currently the preferred action.
+    if ((aNewValue == kActionUsePlugin) &&
+        (this.preferredAction != Ci.nsIHandlerInfo.saveToDisk)) {
+      aNewValue = Ci.nsIHandlerInfo.saveToDisk;
+    }
+
     // We don't modify the preferred action if the new action is to use a plugin
     // because handler info objects don't understand our custom "use plugin"
     // value.  Also, leaving it untouched means that we can automatically revert
     // to the old setting if the user ever removes the plugin.
 
     if (aNewValue != kActionUsePlugin)
       this.wrappedHandlerInfo.preferredAction = aNewValue;
   },
@@ -337,34 +348,34 @@ HandlerInfoWrapper.prototype = {
   //
   // FIXME: once handler info records are broken up into OS-provided records
   // and user-configured records, stop using this boolean flag and simply
   // check for the presence of a user-configured record to determine whether
   // or not this type is only handled by a plugin.  Filed as bug 395142.
   handledOnlyByPlugin: undefined,
 
   get isDisabledPluginType() {
-    return this._getDisabledPluginTypes().indexOf(this.type) != -1;
+    return this._getDisabledPluginTypes().includes(this.type);
   },
 
   _getDisabledPluginTypes() {
     var types = "";
 
     if (Services.prefs.prefHasUserValue(PREF_DISABLED_PLUGIN_TYPES))
       types = Services.prefs.getCharPref(PREF_DISABLED_PLUGIN_TYPES);
 
     // Only split if the string isn't empty so we don't end up with an array
     // containing a single empty string.
     return types ? types.split(",") : [];
   },
 
   disablePluginType() {
     var disabledPluginTypes = this._getDisabledPluginTypes();
 
-    if (disabledPluginTypes.indexOf(this.type) == -1)
+    if (!disabledPluginTypes.includes(this.type))
       disabledPluginTypes.push(this.type);
 
     Services.prefs.setCharPref(PREF_DISABLED_PLUGIN_TYPES,
                                disabledPluginTypes.join(","));
 
     // Update the category manager so existing browser windows update.
     categoryMgr.deleteCategoryEntry("Gecko-Content-Viewers",
                                           this.type,
@@ -451,18 +462,17 @@ function FeedHandlerInfo(aMIMEType) {
 
 FeedHandlerInfo.prototype = {
   __proto__: HandlerInfoWrapper.prototype,
 
   //**************************************************************************//
   // nsIHandlerInfo
 
   get description() {
-    return document.getElementById("bundlePrefApplications")
-                   .getString(this.typeClass);
+    return gApplicationsPane._prefsBundle.getString(this.typeClass);
   },
 
   get preferredApplicationHandler() {
     switch (document.getElementById(this._prefSelectedReader).value) {
       case "client":
         var file = document.getElementById(this._prefSelectedApp).value;
         if (file)
           return getLocalHandlerApp(file);
@@ -510,24 +520,17 @@ FeedHandlerInfo.prototype = {
 
     // A minimal implementation of nsIMutableArray.  It only supports the two
     // methods its callers invoke, namely appendElement, nsIArray::enumerate
     // and nsIArray::indexOf.
     this._possibleApplicationHandlers = {
       _inner: [],
       _removed: [],
 
-      QueryInterface: function(aIID) {
-        if (aIID.equals(Ci.nsIMutableArray) ||
-            aIID.equals(Ci.nsIArray) ||
-            aIID.equals(Ci.nsISupports))
-          return this;
-
-        throw Cr.NS_ERROR_NO_INTERFACE;
-      },
+      QueryInterface: XPCOMUtils.generateQI([Ci.nsIMutableArray, Ci.nsIArray]),
 
       get length() {
         return this._inner.length;
       },
 
       enumerate: function() {
         return new ArrayEnumerator(this._inner);
       },
@@ -559,22 +562,20 @@ FeedHandlerInfo.prototype = {
     var preferredAppFile = document.getElementById(this._prefSelectedApp).value;
     if (preferredAppFile) {
       let preferredApp = getLocalHandlerApp(preferredAppFile);
       let defaultApp = this._defaultApplicationHandler;
       if (!defaultApp || !defaultApp.equals(preferredApp))
         this._possibleApplicationHandlers.appendElement(preferredApp);
     }
 
-    if (converterSvc) {
-      // Add the registered web handlers.  There can be any number of these.
-      var webHandlers = converterSvc.getContentHandlers(this.type, {});
-      for (let webHandler of webHandlers)
-        this._possibleApplicationHandlers.appendElement(webHandler);
-    }
+    // Add the registered web handlers.  There can be any number of these.
+    var webHandlers = converterSvc.getContentHandlers(this.type);
+    for (let webHandler of webHandlers)
+      this._possibleApplicationHandlers.appendElement(webHandler);
 
     return this._possibleApplicationHandlers;
   },
 
   __defaultApplicationHandler: undefined,
   get _defaultApplicationHandler() {
     if (this.__defaultApplicationHandler !== undefined)
       return this.__defaultApplicationHandler;
@@ -677,17 +678,17 @@ FeedHandlerInfo.prototype = {
     }
   },
 
   get alwaysAskBeforeHandling() {
     return document.getElementById(this._prefSelectedAction).value == "ask";
   },
 
   set alwaysAskBeforeHandling(aNewValue) {
-    if (aNewValue == true)
+    if (aNewValue)
       document.getElementById(this._prefSelectedAction).value = "ask";
     else
       document.getElementById(this._prefSelectedAction).value = "reader";
   },
 
   // Whether or not we are currently storing the action selected by the user.
   // We use this to suppress notification-triggered updates to the list when
   // we make changes that may spawn such updates, specifically when we change
@@ -879,25 +880,18 @@ var gApplicationsPane = {
     Services.prefs.removeObserver(PREF_AUDIO_FEED_SELECTED_WEB, this);
     Services.prefs.removeObserver(PREF_AUDIO_FEED_SELECTED_ACTION, this);
   },
 
 
   //**************************************************************************//
   // nsISupports
 
-  QueryInterface: function(aIID) {
-    if (aIID.equals(Ci.nsIObserver) ||
-        aIID.equals(Ci.nsIDOMEventListener ||
-        aIID.equals(Ci.nsISupports)))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
+                                         Ci.nsIDOMEventListener]),
 
   //**************************************************************************//
   // nsIObserver
 
   observe(aSubject, aTopic, aData) {
     // Rebuild the list when there are changes to preferences that influence
     // whether or not to show certain entries in the list.
     if (aTopic == "nsPref:changed" && !this._storingAction) {
@@ -1117,18 +1111,18 @@ var gApplicationsPane = {
       }
 
       this._list.appendChild(item);
     }
   },
 
   _matchesFilter(aType) {
     var filterValue = this._filter.value.toLowerCase();
-    return this._describeType(aType).toLowerCase().indexOf(filterValue) != -1 ||
-           this._describePreferredAction(aType).toLowerCase().indexOf(filterValue) != -1;
+    return this._describeType(aType).toLowerCase().includes(filterValue) ||
+      this._describePreferredAction(aType).toLowerCase().includes(filterValue);
   },
 
   /**
    * Describe, in a human-readable fashion, the type represented by the given
    * handler info object.  Normally this is just the description provided by
    * the info object, but if more than one object presents the same description,
    * then we annotate the duplicate descriptions with the type itself to help
    * users distinguish between those types.
@@ -1160,18 +1154,17 @@ var gApplicationsPane = {
   _describePreferredAction(aHandlerInfo) {
     // alwaysAskBeforeHandling overrides the preferred action, so if that flag
     // is set, then describe that behavior instead.  For most types, this is
     // the "alwaysAsk" string, but for the feed type we show something special.
     if (aHandlerInfo.alwaysAskBeforeHandling) {
       if (isFeedType(aHandlerInfo.type))
         return this._prefsBundle.getFormattedString("previewInApp",
                                                     [this._brandShortName]);
-      else
-        return this._prefsBundle.getString("alwaysAsk");
+      return this._prefsBundle.getString("alwaysAsk");
     }
 
     switch (aHandlerInfo.preferredAction) {
       case Ci.nsIHandlerInfo.saveToDisk:
         return this._prefsBundle.getString("saveFile");
 
       case Ci.nsIHandlerInfo.useHelperApp:
         var preferredApp = aHandlerInfo.preferredApplicationHandler;
@@ -1418,22 +1411,24 @@ var gApplicationsPane = {
                                                         this._brandShortName]);
       pluginMenuItem.setAttribute("label", label);
       pluginMenuItem.setAttribute("tooltiptext", label);
       pluginMenuItem.setAttribute("appHandlerIcon", "plugin");
       menuPopup.appendChild(pluginMenuItem);
     }
 
     // Create a menu item for selecting a local application.
-#ifdef XP_WIN
-    // On Windows, selecting an application to open another application
-    // would be meaningless so we special case executables.
-    var executableType = mimeSvc.getTypeFromExtension("exe");
-    if (handlerInfo.type != executableType)
-#endif
+    let canOpenWithOtherApp = true;
+    if (AppConstants.platform == "win") {
+      // On Windows, selecting an application to open another application
+      // would be meaningless so we special case executables.
+      let executableType = mimeSvc.getTypeFromExtension("exe");
+      canOpenWithOtherApp = handlerInfo.type != executableType;
+    }
+    if (canOpenWithOtherApp)
     {
       let menuItem = document.createElement("menuitem");
       menuItem.setAttribute("class", "handler-action");
       menuItem.setAttribute("value", kActionChooseApp);
       let label = this._prefsBundle.getString("useOtherApp");
       menuItem.setAttribute("label", label);
       menuItem.setAttribute("tooltiptext", label);
       menuPopup.appendChild(menuItem);
@@ -1492,16 +1487,19 @@ var gApplicationsPane = {
     this._sortVisibleTypes();
     this._rebuildView();
   },
 
   /**
    * Sort the list of visible types by the current sort column/direction.
    */
   _sortVisibleTypes() {
+    if (!this._sortColumn)
+      return;
+
     var t = this;
 
     function sortByType(a, b) {
       return t._describeType(a).toLowerCase()
               .localeCompare(t._describeType(b).toLowerCase());
     }
 
     function sortByAction(a, b) {
--- a/suite/components/pref/jar.mn
+++ b/suite/components/pref/jar.mn
@@ -7,17 +7,17 @@ comm.jar:
    content/communicator/pref/preferences.js                         (content/preferences.js)
    content/communicator/pref/prefpanels.css                         (content/prefpanels.css)
    content/communicator/pref/prefpanels.xml                         (content/prefpanels.xml)
    content/communicator/pref/pref-advanced.js                       (content/pref-advanced.js)
    content/communicator/pref/pref-advanced.xul                      (content/pref-advanced.xul)
    content/communicator/pref/pref-appearance.js                     (content/pref-appearance.js)
    content/communicator/pref/pref-appearance.xul                    (content/pref-appearance.xul)
    content/communicator/pref/pref-applications.xul                  (content/pref-applications.xul)
-*  content/communicator/pref/pref-applications.js                   (content/pref-applications.js)
+   content/communicator/pref/pref-applications.js                   (content/pref-applications.js)
    content/communicator/pref/pref-applicationManager.js             (content/pref-applicationManager.js)
    content/communicator/pref/pref-applicationManager.xul            (content/pref-applicationManager.xul)
    content/communicator/pref/pref-cache.js                          (content/pref-cache.js)
    content/communicator/pref/pref-cache.xul                         (content/pref-cache.xul)
    content/communicator/pref/pref-colors.js                         (content/pref-colors.js)
    content/communicator/pref/pref-colors.xul                        (content/pref-colors.xul)
    content/communicator/pref/pref-content.js                        (content/pref-content.js)
    content/communicator/pref/pref-content.xul                       (content/pref-content.xul)