Bug 1417944 - Enable ESLint rule mozilla/use-services for toolkit/. r?Mossop draft
authorMark Banner <standard8@mozilla.com>
Wed, 22 Nov 2017 13:36:34 +0000
changeset 703638 8d7504ff1184c089afd3fa6d578de9161bee3626
parent 703637 f490d1b054d24e029771de77ca34af8e7295cabd
child 741847 34ab310a9105c630f70ebbe3413d6051943dba4d
push id90900
push userbmo:standard8@mozilla.com
push dateMon, 27 Nov 2017 09:56:56 +0000
reviewersMossop
bugs1417944
milestone59.0a1
Bug 1417944 - Enable ESLint rule mozilla/use-services for toolkit/. r?Mossop MozReview-Commit-ID: JhHXYma5Adp
toolkit/.eslintrc.js
toolkit/components/.eslintrc.js
toolkit/modules/LoadContextInfo.jsm
toolkit/modules/Promise.jsm
toolkit/mozapps/downloads/DownloadLastDir.jsm
toolkit/mozapps/downloads/DownloadUtils.jsm
toolkit/mozapps/handling/content/dialog.js
toolkit/mozapps/handling/nsContentDispatchChooser.js
toolkit/mozapps/preferences/changemp.js
toolkit/mozapps/preferences/removemp.js
toolkit/mozapps/update/content/updates.js
toolkit/mozapps/update/tests/chrome/utils.js
tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-services.js
--- a/toolkit/.eslintrc.js
+++ b/toolkit/.eslintrc.js
@@ -2,10 +2,21 @@
 
 module.exports = {
   rules: {
     // XXX Bug 1326071 - This should be reduced down - probably to 20 or to
     // be removed & synced with the mozilla/recommended value.
     "complexity": ["error", 41],
 
     "mozilla/no-task": "error",
-  }
+
+    "mozilla/use-services": "error",
+  },
+
+  "overrides": [{
+    // Turn off use-services for xml files. XBL bindings are going away, and
+    // working out the valid globals for those is difficult.
+    "files": "**/*.xml",
+    "rules": {
+      "mozilla/use-services": "off",
+    }
+  }]
 };
deleted file mode 100644
--- a/toolkit/components/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  rules: {
-    "mozilla/use-services": "error",
-  }
-};
--- a/toolkit/modules/LoadContextInfo.jsm
+++ b/toolkit/modules/LoadContextInfo.jsm
@@ -6,10 +6,12 @@
  * This jsm is here only for compatibility.  Extension developers may use it
  * to build nsILoadContextInfo to pass down to HTTP cache APIs.  Originally
  * it was possible to implement nsILoadContextInfo in JS.  But now it turned
  * out to be a built-in class only, so we need a component (service) as
  * a factory to build nsILoadContextInfo in a JS code.
  */
 
 this.EXPORTED_SYMBOLS = ["LoadContextInfo"];
+// XXX Bug 1417937 will remove this file.
+// eslint-disable-next-line mozilla/use-services
 this.LoadContextInfo = Components.classes["@mozilla.org/load-context-info-factory;1"]
                                  .getService(Components.interfaces.nsILoadContextInfoFactory);
--- a/toolkit/modules/Promise.jsm
+++ b/toolkit/modules/Promise.jsm
@@ -91,11 +91,12 @@ this.EXPORTED_SYMBOLS = [
 
 // These constants must be defined on the "this" object for them to be visible
 // by subscripts in B2G, since "this" does not match the global scope.
 this.Cc = Components.classes;
 this.Ci = Components.interfaces;
 this.Cu = Components.utils;
 this.Cr = Components.results;
 
+// eslint-disable-next-line mozilla/use-services
 this.Cc["@mozilla.org/moz/jssubscript-loader;1"]
     .getService(this.Ci.mozIJSSubScriptLoader)
     .loadSubScript("resource://gre/modules/Promise-backend.js", this);
--- a/toolkit/mozapps/downloads/DownloadLastDir.jsm
+++ b/toolkit/mozapps/downloads/DownloadLastDir.jsm
@@ -63,20 +63,18 @@ var observer = {
 
         cps2.removeByName(LAST_DIR_PREF, nonPrivateLoadContext);
         cps2.removeByName(LAST_DIR_PREF, privateLoadContext);
         break;
     }
   }
 };
 
-var os = Components.classes["@mozilla.org/observer-service;1"]
-                   .getService(Components.interfaces.nsIObserverService);
-os.addObserver(observer, "last-pb-context-exited", true);
-os.addObserver(observer, "browser:purge-session-history", true);
+Services.obs.addObserver(observer, "last-pb-context-exited", true);
+Services.obs.addObserver(observer, "browser:purge-session-history", true);
 
 function readLastDirPref() {
   try {
     return Services.prefs.getComplexValue(LAST_DIR_PREF, nsIFile);
   } catch (e) {
     return null;
   }
 }
--- a/toolkit/mozapps/downloads/DownloadUtils.jsm
+++ b/toolkit/mozapps/downloads/DownloadUtils.jsm
@@ -89,19 +89,17 @@ var gStr = {
 };
 
 // This lazily initializes the string bundle upon first use.
 Object.defineProperty(this, "gBundle", {
   configurable: true,
   enumerable: true,
   get() {
     delete this.gBundle;
-    return this.gBundle = Cc["@mozilla.org/intl/stringbundle;1"].
-                          getService(Ci.nsIStringBundleService).
-                          createBundle(kDownloadProperties);
+    return this.gBundle = Services.strings.createBundle(kDownloadProperties);
   },
 });
 
 // Keep track of at most this many second/lastSec pairs so that multiple calls
 // to getTimeLeft produce the same time left
 const kCachedLastMaxSize = 10;
 var gCachedLast = [];
 
@@ -380,27 +378,23 @@ this.DownloadUtils = {
    * Get the appropriate display host string for a URI string depending on if
    * the URI has an eTLD + 1, is an IP address, a local file, or other protocol
    *
    * @param aURIString
    *        The URI string to try getting an eTLD + 1, etc.
    * @return A pair: [display host for the URI string, full host name]
    */
   getURIHost: function DU_getURIHost(aURIString) {
-    let ioService = Cc["@mozilla.org/network/io-service;1"].
-                    getService(Ci.nsIIOService);
-    let eTLDService = Cc["@mozilla.org/network/effective-tld-service;1"].
-                      getService(Ci.nsIEffectiveTLDService);
     let idnService = Cc["@mozilla.org/network/idn-service;1"].
                      getService(Ci.nsIIDNService);
 
     // Get a URI that knows about its components
     let uri;
     try {
-      uri = ioService.newURI(aURIString);
+      uri = Services.io.newURI(aURIString);
     } catch (ex) {
       return ["", ""];
     }
 
     // Get the inner-most uri for schemes like jar:
     if (uri instanceof Ci.nsINestedURI)
       uri = uri.innermostURI;
 
@@ -410,17 +404,17 @@ this.DownloadUtils = {
       fullHost = uri.host;
     } catch (e) {
       fullHost = "";
     }
 
     let displayHost;
     try {
       // This might fail if it's an IP address or doesn't have more than 1 part
-      let baseDomain = eTLDService.getBaseDomain(uri);
+      let baseDomain = Services.eTLD.getBaseDomain(uri);
 
       // Convert base domain for display; ignore the isAscii out param
       displayHost = idnService.convertToDisplayIDN(baseDomain, {});
     } catch (e) {
       // Default to the host name
       displayHost = fullHost;
     }
 
@@ -550,12 +544,11 @@ function convertTimeUnitsUnits(aTime, aI
 /**
  * Private helper function to log errors to the error console and command line
  *
  * @param aMsg
  *        Error message to log or an array of strings to concat
  */
 function log(aMsg) {
   let msg = "DownloadUtils.jsm: " + (aMsg.join ? aMsg.join("") : aMsg);
-  Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService).
-    logStringMessage(msg);
+  Services.console.logStringMessage(msg);
   dump(msg + "\n");
 }
--- a/toolkit/mozapps/handling/content/dialog.js
+++ b/toolkit/mozapps/handling/content/dialog.js
@@ -29,16 +29,17 @@
  */
 
 var Cc = Components.classes;
 var Ci = Components.interfaces;
 var Cr = Components.results;
 var Cu = Components.utils;
 
 Cu.import("resource://gre/modules/SharedPromptUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
 
 
 var dialog = {
   // Member Variables
 
   _handlerInfo: null,
   _URI: null,
   _itemChoose: null,
@@ -101,31 +102,29 @@ var dialog = {
 
  /**
   * Populates the list that a user can choose from.
   */
   populateList: function populateList() {
     var items = document.getElementById("items");
     var possibleHandlers = this._handlerInfo.possibleApplicationHandlers;
     var preferredHandler = this._handlerInfo.preferredApplicationHandler;
-    var ios = Cc["@mozilla.org/network/io-service;1"].
-              getService(Ci.nsIIOService);
     for (let i = possibleHandlers.length - 1; i >= 0; --i) {
       let app = possibleHandlers.queryElementAt(i, Ci.nsIHandlerApp);
       let elm = document.createElement("richlistitem");
       elm.setAttribute("type", "handler");
       elm.setAttribute("name", app.name);
       elm.obj = app;
 
       if (app instanceof Ci.nsILocalHandlerApp) {
         // See if we have an nsILocalHandlerApp and set the icon
-        let uri = ios.newFileURI(app.executable);
+        let uri = Services.io.newFileURI(app.executable);
         elm.setAttribute("image", "moz-icon://" + uri.spec + "?size=32");
       } else if (app instanceof Ci.nsIWebHandlerApp) {
-        let uri = ios.newURI(app.uriTemplate);
+        let uri = Services.io.newURI(app.uriTemplate);
         if (/^https?$/.test(uri.scheme)) {
           // Unfortunately we can't use the favicon service to get the favicon,
           // because the service looks for a record with the exact URL we give
           // it, and users won't have such records for URLs they don't visit,
           // and users won't visit the handler's URL template, they'll only
           // visit URLs derived from that template (i.e. with %s in the template
           // replaced by the URL of the content being handled).
           elm.setAttribute("image", uri.prePath + "/favicon.ico");
@@ -163,19 +162,17 @@ var dialog = {
     var title = bundle.getString("choose.application.title");
 
     var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
     fp.init(window, title, Ci.nsIFilePicker.modeOpen);
     fp.appendFilters(Ci.nsIFilePicker.filterApps);
 
     fp.open(rv => {
       if (rv == Ci.nsIFilePicker.returnOK && fp.file) {
-        let uri = Cc["@mozilla.org/network/util;1"].
-                  getService(Ci.nsIIOService).
-                  newFileURI(fp.file);
+        let uri = Services.io.newFileURI(fp.file);
 
         let handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
                          createInstance(Ci.nsILocalHandlerApp);
         handlerApp.executable = fp.file;
 
         // if this application is already in the list, select it and don't add it again
         let parent = document.getElementById("items");
         for (let i = 0; i < parent.childNodes.length; ++i) {
--- a/toolkit/mozapps/handling/nsContentDispatchChooser.js
+++ b/toolkit/mozapps/handling/nsContentDispatchChooser.js
@@ -1,19 +1,21 @@
 /* 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/. */
 
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-
 // Constants
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
 
 const CONTENT_HANDLING_URL = "chrome://mozapps/content/handling/dialog.xul";
 const STRINGBUNDLE_URL = "chrome://mozapps/locale/handling/handling.properties";
 
 // nsContentDispatchChooser class
 
 function nsContentDispatchChooser() {
 }
@@ -26,54 +28,48 @@ nsContentDispatchChooser.prototype =
 
   ask: function ask(aHandler, aWindowContext, aURI, aReason) {
     var window = null;
     try {
       if (aWindowContext)
         window = aWindowContext.getInterface(Ci.nsIDOMWindow);
     } catch (e) { /* it's OK to not have a window */ }
 
-    var sbs = Cc["@mozilla.org/intl/stringbundle;1"].
-              getService(Ci.nsIStringBundleService);
-    var bundle = sbs.createBundle(STRINGBUNDLE_URL);
+    var bundle = Services.strings.createBundle(STRINGBUNDLE_URL);
 
-    var xai = Cc["@mozilla.org/xre/app-info;1"].
-              getService(Ci.nsIXULAppInfo);
     // TODO when this is hooked up for content, we will need different strings
     //      for most of these
     var arr = [bundle.GetStringFromName("protocol.title"),
                "",
                bundle.GetStringFromName("protocol.description"),
                bundle.GetStringFromName("protocol.choices.label"),
                bundle.formatStringFromName("protocol.checkbox.label",
                                            [aURI.scheme], 1),
                bundle.GetStringFromName("protocol.checkbox.accesskey"),
                bundle.formatStringFromName("protocol.checkbox.extra",
-                                           [xai.name], 1)];
+                                           [Services.appinfo.name], 1)];
 
     var params = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
     let SupportsString = Components.Constructor(
                            "@mozilla.org/supports-string;1",
                            "nsISupportsString");
     for (let text of arr) {
       let string = new SupportsString;
       string.data = text;
       params.appendElement(string);
     }
     params.appendElement(aHandler);
     params.appendElement(aURI);
     params.appendElement(aWindowContext);
 
-    var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
-             getService(Ci.nsIWindowWatcher);
-    ww.openWindow(window,
-                  CONTENT_HANDLING_URL,
-                  null,
-                  "chrome,dialog=yes,resizable,centerscreen",
-                  params);
+    Services.ww.openWindow(window,
+                           CONTENT_HANDLING_URL,
+                           null,
+                           "chrome,dialog=yes,resizable,centerscreen",
+                           params);
   },
 
   // nsISupports
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentDispatchChooser])
 };
 
 // Module
--- a/toolkit/mozapps/preferences/changemp.js
+++ b/toolkit/mozapps/preferences/changemp.js
@@ -1,16 +1,18 @@
 // -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*-
 
 /* 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/. */
 
 const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
+Cu.import("resource://gre/modules/Services.jsm");
+
 const nsPK11TokenDB = "@mozilla.org/security/pk11tokendb;1";
 const nsIPK11TokenDB = Components.interfaces.nsIPK11TokenDB;
 const nsIDialogParamBlock = Components.interfaces.nsIDialogParamBlock;
 const nsPKCS11ModuleDB = "@mozilla.org/security/pkcs11moduledb;1";
 const nsIPKCS11ModuleDB = Components.interfaces.nsIPKCS11ModuleDB;
 const nsIPKCS11Slot = Components.interfaces.nsIPKCS11Slot;
 const nsIPK11Token = Components.interfaces.nsIPK11Token;
 
@@ -64,18 +66,16 @@ function process() {
     params.SetInt(1, 0);
   }
 
   checkPasswords();
 }
 
 function setPassword() {
   var pk11db = Components.classes[nsPK11TokenDB].getService(nsIPK11TokenDB);
-  var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
-                                .getService(Components.interfaces.nsIPromptService);
   var token = pk11db.getInternalKeyToken();
 
   var oldpwbox = document.getElementById("oldpw");
   var initpw = oldpwbox.getAttribute("inited");
   var bundle = document.getElementById("bundlePreferences");
 
   var success = false;
 
@@ -95,56 +95,56 @@ function setPassword() {
         if (initpw == "empty" && pw1.value == "") {
           // This makes no sense that we arrive here,
           // we reached a case that should have been prevented by checkPasswords.
         } else {
           if (pw1.value == "") {
             var secmoddb = Components.classes[nsPKCS11ModuleDB].getService(nsIPKCS11ModuleDB);
             if (secmoddb.isFIPSEnabled) {
               // empty passwords are not allowed in FIPS mode
-              promptService.alert(window,
-                                  bundle.getString("pw_change_failed_title"),
-                                  bundle.getString("pw_change2empty_in_fips_mode"));
+              Services.prompt.alert(window,
+                                    bundle.getString("pw_change_failed_title"),
+                                    bundle.getString("pw_change2empty_in_fips_mode"));
               passok = 0;
             }
           }
           if (passok) {
             token.changePassword(oldpw, pw1.value);
             if (pw1.value == "") {
-              promptService.alert(window,
-                                  bundle.getString("pw_change_success_title"),
-                                  bundle.getString("pw_erased_ok")
-                                  + " " + bundle.getString("pw_empty_warning"));
+              Services.prompt.alert(window,
+                                    bundle.getString("pw_change_success_title"),
+                                    bundle.getString("pw_erased_ok")
+                                    + " " + bundle.getString("pw_empty_warning"));
             } else {
-              promptService.alert(window,
-                                  bundle.getString("pw_change_success_title"),
-                                  bundle.getString("pw_change_ok"));
+              Services.prompt.alert(window,
+                                    bundle.getString("pw_change_success_title"),
+                                    bundle.getString("pw_change_ok"));
             }
             success = true;
           }
         }
       } else {
         oldpwbox.focus();
         oldpwbox.setAttribute("value", "");
-        promptService.alert(window,
-                            bundle.getString("pw_change_failed_title"),
-                            bundle.getString("incorrect_pw"));
+        Services.prompt.alert(window,
+                              bundle.getString("pw_change_failed_title"),
+                              bundle.getString("incorrect_pw"));
       }
     } catch (e) {
-      promptService.alert(window,
-                          bundle.getString("pw_change_failed_title"),
-                          bundle.getString("failed_pw_change"));
+      Services.prompt.alert(window,
+                            bundle.getString("pw_change_failed_title"),
+                            bundle.getString("failed_pw_change"));
     }
   } else {
     token.initPassword(pw1.value);
     if (pw1.value == "") {
-      promptService.alert(window,
-                          bundle.getString("pw_change_success_title"),
-                          bundle.getString("pw_not_wanted")
-                          + " " + bundle.getString("pw_empty_warning"));
+      Services.prompt.alert(window,
+                            bundle.getString("pw_change_success_title"),
+                            bundle.getString("pw_not_wanted")
+                            + " " + bundle.getString("pw_empty_warning"));
     }
     success = true;
   }
 
   // Terminate dialog
   if (success)
     window.close();
 }
--- a/toolkit/mozapps/preferences/removemp.js
+++ b/toolkit/mozapps/preferences/removemp.js
@@ -1,23 +1,22 @@
 // -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
 
 /* 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/. */
 
+Components.utils.import("resource://gre/modules/Services.jsm");
+
 var gRemovePasswordDialog = {
   _token: null,
   _bundle: null,
-  _prompt: null,
   _okButton: null,
   _password: null,
   init() {
-    this._prompt = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
-                             .getService(Components.interfaces.nsIPromptService);
     this._bundle = document.getElementById("bundlePreferences");
 
     this._okButton = document.documentElement.getButton("accept");
     this._okButton.label = this._bundle.getString("pw_remove_button");
 
     this._password = document.getElementById("password");
 
     var pk11db = Components.classes["@mozilla.org/security/pk11tokendb;1"]
@@ -31,22 +30,21 @@ var gRemovePasswordDialog = {
 
   validateInput() {
     this._okButton.disabled = !this._token.checkPassword(this._password.value);
   },
 
   removePassword() {
     if (this._token.checkPassword(this._password.value)) {
       this._token.changePassword(this._password.value, "");
-      this._prompt.alert(window,
-                         this._bundle.getString("pw_change_success_title"),
-                         this._bundle.getString("pw_erased_ok")
-                         + " " + this._bundle.getString("pw_empty_warning"));
+      Services.prompt.alert(window,
+                            this._bundle.getString("pw_change_success_title"),
+                            this._bundle.getString("pw_erased_ok")
+                            + " " + this._bundle.getString("pw_empty_warning"));
     } else {
       this._password.value = "";
       this._password.focus();
-      this._prompt.alert(window,
-                         this._bundle.getString("pw_change_failed_title"),
-                         this._bundle.getString("incorrect_pw"));
+      Services.prompt.alert(window,
+                            this._bundle.getString("pw_change_failed_title"),
+                            this._bundle.getString("incorrect_pw"));
     }
   },
 };
-
--- a/toolkit/mozapps/update/content/updates.js
+++ b/toolkit/mozapps/update/content/updates.js
@@ -1344,18 +1344,17 @@ var gFinishedPage = {
     // If already in safe mode restart in safe mode (bug 327119)
     if (Services.appinfo.inSafeMode) {
       let env = CoC["@mozilla.org/process/environment;1"].
                 getService(CoI.nsIEnvironment);
       env.set("MOZ_SAFE_MODE_RESTART", "1");
     }
 
     // Restart the application
-    CoC["@mozilla.org/toolkit/app-startup;1"].getService(CoI.nsIAppStartup).
-    quit(CoI.nsIAppStartup.eAttemptQuit | CoI.nsIAppStartup.eRestart);
+    Services.startup.quit(CoI.nsIAppStartup.eAttemptQuit | CoI.nsIAppStartup.eRestart);
   },
 
   /**
    * When the user clicks the "Restart Later" instead of the Restart Now" button
    * in the wizard after an update has been downloaded.
    */
   onExtra1() {
     gUpdates.wiz.cancel();
--- a/toolkit/mozapps/update/tests/chrome/utils.js
+++ b/toolkit/mozapps/update/tests/chrome/utils.js
@@ -475,19 +475,17 @@ function delayedDefaultCallback() {
 
 /**
  * Gets the continue file used to signal the mock http server to continue
  * downloading for slow download mar file tests without creating it.
  *
  * @return nsIFile for the continue file.
  */
 function getContinueFile() {
-  let continueFile = Cc["@mozilla.org/file/directory_service;1"].
-                     getService(Ci.nsIProperties).
-                     get("CurWorkD", Ci.nsIFile);
+  let continueFile = Services.dirsvc.get("CurWorkD", Ci.nsIFile);
   let continuePath = REL_PATH_DATA + "continue";
   let continuePathParts = continuePath.split("/");
   for (let i = 0; i < continuePathParts.length; ++i) {
     continueFile.append(continuePathParts[i]);
   }
   return continueFile;
 }
 
--- a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-services.js
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-services.js
@@ -104,16 +104,20 @@ function getInterfacesFromServicesFile()
   let ast = helpers.getAST(content);
 
   helpers.walkAST(ast, (type, node, parents) => {
     if (type in servicesASTParser) {
       servicesASTParser[type](node, parents);
     }
   });
 
+  // nsIPropertyBag2 is used for system-info, but it is also used for other
+  // services and items as well, so we can't really warn for it.
+  delete servicesASTParser.result.nsIPropertyBag2;
+
   return servicesASTParser.result;
 }
 
 let getServicesInterfaceMap = helpers.isMozillaCentralBased() ?
   getInterfacesFromServicesFile() :
   helpers.getSavedRuleData("use-services.js");
 
 // -----------------------------------------------------------------------------