Bug 1461140: Part 3 - Cleanup some cruft. r?aswan draft
authorKris Maglione <maglione.k@gmail.com>
Sat, 12 May 2018 14:14:56 -0700
changeset 794545 484aa8a070e67963f16f66a498803213ae919631
parent 794544 7d1c3f87c51533e385f1e9f5cba77a4b45320c62
child 794546 96f3eb38726edd38106474a76ded55962bce51bc
push id109708
push usermaglione.k@gmail.com
push dateSat, 12 May 2018 21:30:53 +0000
reviewersaswan
bugs1461140
milestone62.0a1
Bug 1461140: Part 3 - Cleanup some cruft. r?aswan Some of this is directly related to the code in question. Some of it is only tangentially related, but follows the same patterns. MozReview-Commit-ID: 768QMXYpLFK
toolkit/mozapps/extensions/AddonManager.jsm
toolkit/mozapps/extensions/internal/XPIDatabase.jsm
toolkit/mozapps/extensions/internal/XPIInstall.jsm
toolkit/mozapps/extensions/internal/XPIProvider.jsm
--- a/toolkit/mozapps/extensions/AddonManager.jsm
+++ b/toolkit/mozapps/extensions/AddonManager.jsm
@@ -3004,16 +3004,25 @@ var AddonManagerPrivate = {
   // timer.done() is called
   simpleTimer(aName) {
     let startTime = Cu.now();
     return {
       done: () => this.recordSimpleMeasure(aName, Math.round(Cu.now() - startTime))
     };
   },
 
+  recordTiming(aName, task) {
+    let timer = this.simpleTimer(aName);
+    try {
+      return task();
+    } finally {
+      timer.done();
+    }
+  },
+
   /**
    * Helper to call update listeners when no update is available.
    *
    * This can be used as an implementation for Addon.findUpdates() when
    * no update mechanism is available.
    */
   callNoUpdateListeners(addon, listener, reason, appVersion, platformVersion) {
     if ("onNoCompatibilityUpdateAvailable" in listener) {
--- a/toolkit/mozapps/extensions/internal/XPIDatabase.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIDatabase.jsm
@@ -68,27 +68,33 @@ for (let sym of [
 }
 
 ChromeUtils.import("resource://gre/modules/Log.jsm");
 const LOGGER_ID = "addons.xpi-utils";
 
 const nsIFile = Components.Constructor("@mozilla.org/file/local;1", "nsIFile",
                                        "initWithPath");
 
+const FileInputStream = Components.Constructor("@mozilla.org/network/file-input-stream;1",
+                                               "nsIFileInputStream", "init");
+const ConverterInputStream = Components.Constructor("@mozilla.org/intl/converter-input-stream;1",
+                                                    "nsIConverterInputStream", "init");
+const ZipReader = Components.Constructor("@mozilla.org/libjar/zip-reader;1",
+                                         "nsIZipReader", "open");
+
 // Create a new logger for use by the Addons XPI Provider Utils
 // (Requires AddonManager.jsm)
 var logger = Log.repository.getLogger(LOGGER_ID);
 
 const KEY_PROFILEDIR                  = "ProfD";
 const FILE_JSON_DB                    = "extensions.json";
 
 // The last version of DB_SCHEMA implemented in SQLITE
 const LAST_SQLITE_DB_SCHEMA           = 14;
 
-const PREF_BLOCKLIST_ITEM_URL         = "extensions.blocklist.itemURL";
 const PREF_DB_SCHEMA                  = "extensions.databaseSchema";
 const PREF_EM_AUTO_DISABLED_SCOPES    = "extensions.autoDisableScopes";
 const PREF_EM_EXTENSION_FORMAT        = "extensions.";
 const PREF_PENDING_OPERATIONS         = "extensions.pendingOperations";
 const PREF_XPI_SIGNATURES_DEV_ROOT    = "xpinstall.signatures.dev-root";
 
 const TOOLKIT_ID                      = "toolkit@mozilla.org";
 
@@ -135,39 +141,16 @@ const PROP_JSON_FIELDS = ["id", "syncGUI
 
 const LEGACY_TYPES = new Set([
   "extension",
 ]);
 
 // Time to wait before async save of XPI JSON database, in milliseconds
 const ASYNC_SAVE_DELAY_MS = 20;
 
-// Note: When adding/changing/removing items here, remember to change the
-// DB schema version to ensure changes are picked up ASAP.
-const STATIC_BLOCKLIST_PATTERNS = [
-  { creator: "Mozilla Corp.",
-    level: nsIBlocklistService.STATE_BLOCKED,
-    blockID: "i162" },
-  { creator: "Mozilla.org",
-    level: nsIBlocklistService.STATE_BLOCKED,
-    blockID: "i162" }
-];
-
-function findMatchingStaticBlocklistItem(aAddon) {
-  for (let item of STATIC_BLOCKLIST_PATTERNS) {
-    if ("creator" in item && typeof item.creator == "string") {
-      if ((aAddon.defaultLocale && aAddon.defaultLocale.creator == item.creator) ||
-          (aAddon.selectedLocale && aAddon.selectedLocale.creator == item.creator)) {
-        return item;
-      }
-    }
-  }
-  return null;
-}
-
 function promiseIdleDispatch(task) {
   return new Promise((resolve, reject) => {
     ChromeUtils.idleDispatch(deadline => {
       try {
         resolve(task(deadline));
       } catch (e) {
         reject(e);
       }
@@ -452,25 +435,16 @@ class AddonInternal {
         return targetApp;
       if (targetApp.id == TOOLKIT_ID)
         app = targetApp;
     }
     return app;
   }
 
   async findBlocklistEntry() {
-    let staticItem = findMatchingStaticBlocklistItem(this);
-    if (staticItem) {
-      let url = Services.urlFormatter.formatURLPref(PREF_BLOCKLIST_ITEM_URL);
-      return {
-        state: staticItem.level,
-        url: url.replace(/%blockID%/g, staticItem.blockID)
-      };
-    }
-
     return Blocklist.getAddonBlocklistEntry(this.wrapper);
   }
 
   async updateBlocklistState(options = {}) {
     let {applySoftBlock = true, oldAddon = null, updateDatabase = true} = options;
 
     if (oldAddon) {
       this.userDisabled = oldAddon.userDisabled;
@@ -1025,28 +999,28 @@ AddonWrapper = class {
     if (isDir) {
       if (aPath)
         aPath.split("/").forEach(part => bundle.append(part));
       let result = bundle.exists();
       addon._hasResourceCache.set(aPath, result);
       return result;
     }
 
-    let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"].
-                    createInstance(Ci.nsIZipReader);
+    let zipReader;
     try {
-      zipReader.open(bundle);
+      zipReader = new ZipReader(bundle);
       let result = zipReader.hasEntry(aPath);
       addon._hasResourceCache.set(aPath, result);
       return result;
     } catch (e) {
       addon._hasResourceCache.set(aPath, false);
       return false;
     } finally {
-      zipReader.close();
+      if (zipReader)
+        zipReader.close();
     }
   }
 
   /**
    * Reloads the add-on.
    *
    * For temporarily installed add-ons, this uninstalls and re-installs the
    * add-on. Otherwise, the addon is disabled and then re-enabled, and the cache
@@ -1158,31 +1132,36 @@ function defineAddonWrapperProperty(name
     if (!target)
       return null;
     if (fromRepo)
       return target;
     return Services.io.newURI(target);
   });
 });
 
+function getLocalizedPref(pref) {
+  if (Services.prefs.getPrefType(pref) != Ci.nsIPrefBranch.PREF_INVALID)
+    return Services.prefs.getComplexValue(pref, Ci.nsIPrefLocalizedString).data;
+  return null;
+}
+
 PROP_LOCALE_SINGLE.forEach(function(aProp) {
   defineAddonWrapperProperty(aProp, function() {
     let addon = addonFor(this);
     // Override XPI creator if repository creator is defined
     if (aProp == "creator" &&
         addon._repositoryAddon && addon._repositoryAddon.creator) {
       return addon._repositoryAddon.creator;
     }
 
     let result = null;
 
     if (addon.active) {
       try {
-        let pref = PREF_EM_EXTENSION_FORMAT + addon.id + "." + aProp;
-        let value = Services.prefs.getPrefType(pref) != Ci.nsIPrefBranch.PREF_INVALID ? Services.prefs.getComplexValue(pref, Ci.nsIPrefLocalizedString).data : null;
+        let value = getLocalizedPref(`${PREF_EM_EXTENSION_FORMAT}${addon.id}.${aProp}`);
         if (value)
           result = value;
       } catch (e) {
       }
     }
 
     if (result == null)
       [result] = chooseValue(addon, addon.selectedLocale, aProp);
@@ -1196,24 +1175,23 @@ PROP_LOCALE_SINGLE.forEach(function(aPro
 
 PROP_LOCALE_MULTI.forEach(function(aProp) {
   defineAddonWrapperProperty(aProp, function() {
     let addon = addonFor(this);
     let results = null;
     let usedRepository = false;
 
     if (addon.active) {
-      let pref = PREF_EM_EXTENSION_FORMAT + addon.id + "." +
-                 aProp.substring(0, aProp.length - 1);
+      let pref = `${PREF_EM_EXTENSION_FORMAT}${addon.id}.${aProp.slice(0, -1)}`;
       let list = Services.prefs.getChildList(pref, {});
       if (list.length > 0) {
         list.sort();
         results = [];
         for (let childPref of list) {
-          let value = Services.prefs.getPrefType(childPref) != Ci.nsIPrefBranch.PREF_INVALID ? Services.prefs.getComplexValue(childPref, Ci.nsIPrefLocalizedString).data : null;
+          let value = getLocalizedPref(childPref);
           if (value)
             results.push(value);
         }
       }
     }
 
     if (results == null)
       [results, usedRepository] = chooseValue(addon, addon.selectedLocale, aProp);
@@ -1456,24 +1434,20 @@ this.XPIDatabase = {
    *        (if false, caller is XPIProvider.checkForChanges() which will rebuild)
    */
   syncLoadDB(aRebuildOnError) {
     let fstream = null;
     let data = "";
     try {
       let readTimer = AddonManagerPrivate.simpleTimer("XPIDB_syncRead_MS");
       logger.debug("Opening XPI database " + this.jsonFile.path);
-      fstream = Cc["@mozilla.org/network/file-input-stream;1"].
-              createInstance(Ci.nsIFileInputStream);
-      fstream.init(this.jsonFile, -1, 0, 0);
+      fstream = new FileInputStream(this.jsonFile, -1, 0, 0);
       let cstream = null;
       try {
-        cstream = Cc["@mozilla.org/intl/converter-input-stream;1"].
-                createInstance(Ci.nsIConverterInputStream);
-        cstream.init(fstream, "UTF-8", 0, 0);
+        cstream = new ConverterInputStream(fstream, "UTF-8", 0, 0);
 
         let str = {};
         let read = 0;
         do {
           read = cstream.readString(0xffffffff, str); // read as much as we can and put it in str.value
           data += str.value;
         } while (read != 0);
 
@@ -1513,38 +1487,35 @@ this.XPIDatabase = {
    *        The stringified add-on JSON to parse.
    * @param {boolean} aRebuildOnError
    *        If true, synchronously reconstruct the database from installed add-ons
    */
   parseDB(aData, aRebuildOnError) {
     let parseTimer = AddonManagerPrivate.simpleTimer("XPIDB_parseDB_MS");
     try {
       let inputAddons = JSON.parse(aData);
-      // Now do some sanity checks on our JSON db
+
       if (!("schemaVersion" in inputAddons) || !("addons" in inputAddons)) {
         parseTimer.done();
+
         // Content of JSON file is bad, need to rebuild from scratch
         logger.error("bad JSON file contents");
         AddonManagerPrivate.recordSimpleMeasure("XPIDB_startupError", "badJSON");
-        let rebuildTimer = AddonManagerPrivate.simpleTimer("XPIDB_rebuildBadJSON_MS");
-        this.rebuildDatabase(aRebuildOnError);
-        rebuildTimer.done();
+
+        this.timeRebuildDatabase("XPIDB_rebuildBadJSON_MS", aRebuildOnError);
         return;
       }
+
       if (inputAddons.schemaVersion != DB_SCHEMA) {
-        // Handle mismatched JSON schema version. For now, we assume
-        // compatibility for JSON data, though we throw away any fields we
+        // For now, we assume compatibility for JSON data with a
+        // mismatched schema version, though we throw away any fields we
         // don't know about (bug 902956)
         AddonManagerPrivate.recordSimpleMeasure("XPIDB_startupError",
-                                                "schemaMismatch-" + inputAddons.schemaVersion);
-        logger.debug("JSON schema mismatch: expected " + DB_SCHEMA +
-            ", actual " + inputAddons.schemaVersion);
-        // When we rev the schema of the JSON database, we need to make sure we
-        // force the DB to save so that the DB_SCHEMA value in the JSON file and
-        // the preference are updated.
+                                                `schemaMismatch-${inputAddons.schemaVersion}`);
+        logger.debug(`JSON schema mismatch: expected ${DB_SCHEMA}, actual ${inputAddons.schemaVersion}`);
       }
       // If we got here, we probably have good data
       // Make AddonInternal instances from the loaded data and save them
       let addonDB = new Map();
       for (let loadedAddon of inputAddons.addons) {
         try {
           if (!loadedAddon.path) {
             loadedAddon.path = descriptorToPath(loadedAddon.descriptor);
@@ -1562,68 +1533,68 @@ this.XPIDatabase = {
       parseTimer.done();
       this.addonDB = addonDB;
       logger.debug("Successfully read XPI database");
       this.initialized = true;
     } catch (e) {
       // If we catch and log a SyntaxError from the JSON
       // parser, the xpcshell test harness fails the test for us: bug 870828
       parseTimer.done();
+
       if (e.name == "SyntaxError") {
         logger.error("Syntax error parsing saved XPI JSON data");
         AddonManagerPrivate.recordSimpleMeasure("XPIDB_startupError", "syntax");
       } else {
         logger.error("Failed to load XPI JSON data from profile", e);
         AddonManagerPrivate.recordSimpleMeasure("XPIDB_startupError", "other");
       }
-      let rebuildTimer = AddonManagerPrivate.simpleTimer("XPIDB_rebuildReadFailed_MS");
-      this.rebuildDatabase(aRebuildOnError);
-      rebuildTimer.done();
+
+      this.timeRebuildDatabase("XPIDB_rebuildReadFailed_MS", aRebuildOnError);
     }
   },
 
+  timeRebuildDatabase(timerName, rebuildOnError) {
+    AddonManagerPrivate.recordTiming(timerName, () => {
+      this.rebuildDatabase(rebuildOnError);
+    });
+  },
+
   /**
    * Upgrade database from earlier (sqlite or RDF) version if available
    *
    * @param {boolean} aRebuildOnError
    *        If true, synchronously reconstruct the database from installed add-ons
    */
   upgradeDB(aRebuildOnError) {
-    let upgradeTimer = AddonManagerPrivate.simpleTimer("XPIDB_upgradeDB_MS");
-
     let schemaVersion = Services.prefs.getIntPref(PREF_DB_SCHEMA, 0);
     if (schemaVersion > LAST_SQLITE_DB_SCHEMA) {
       // we've upgraded before but the JSON file is gone, fall through
       // and rebuild from scratch
       AddonManagerPrivate.recordSimpleMeasure("XPIDB_startupError", "dbMissing");
     }
 
-    this.rebuildDatabase(aRebuildOnError);
-    upgradeTimer.done();
+    this.timeRebuildDatabase("XPIDB_upgradeDB_MS", aRebuildOnError);
   },
 
   /**
    * Reconstruct when the DB file exists but is unreadable
    * (for example because read permission is denied)
    *
    * @param {Error} aError
    *        The error that triggered the rebuild.
    * @param {boolean} aRebuildOnError
    *        If true, synchronously reconstruct the database from installed add-ons
    */
   rebuildUnreadableDB(aError, aRebuildOnError) {
-    let rebuildTimer = AddonManagerPrivate.simpleTimer("XPIDB_rebuildUnreadableDB_MS");
-    logger.warn("Extensions database " + this.jsonFile.path +
-        " exists but is not readable; rebuilding", aError);
+    logger.warn(`Extensions database ${this.jsonFile.path} exists but is not readable; rebuilding`, aError);
     // Remember the error message until we try and write at least once, so
     // we know at shutdown time that there was a problem
     this._loadError = aError;
-    AddonManagerPrivate.recordSimpleMeasure("XPIDB_startupError", "unreadable");
-    this.rebuildDatabase(aRebuildOnError);
-    rebuildTimer.done();
+
+    this.timeRebuildDatabase("XPIDB_rebuildUnreadableDB_MS", aRebuildOnError);
   },
 
   /**
    * Open and read the XPI database asynchronously, upgrading if
    * necessary. If any DB load operation fails, we need to
    * synchronously rebuild the DB from the installed extensions.
    *
    * @returns {Promise<AddonDB>}
@@ -1640,24 +1611,24 @@ this.XPIDatabase = {
     AddonManagerPrivate.recordSimpleMeasure("XPIDB_async_load", XPIProvider.runPhase);
     let readOptions = {
       outExecutionDuration: 0
     };
     this._dbPromise = (async () => {
       try {
         let byteArray = await OS.File.read(this.jsonFile.path, null, readOptions);
 
-        logger.debug("Async JSON file read took " + readOptions.outExecutionDuration + " MS");
+        logger.debug(`Async JSON file read took ${readOptions.outExecutionDuration} MS`);
         AddonManagerPrivate.recordSimpleMeasure("XPIDB_asyncRead_MS",
-          readOptions.outExecutionDuration);
 
         if (this.addonDB) {
           logger.debug("Synchronous load completed while waiting for async load");
           return this.addonDB;
         }
+                                                readOptions.outExecutionDuration);
 
         logger.debug("Finished async read of XPI database, parsing...");
         let text = await promiseIdleDispatch(() => {
           let decodeTimer = AddonManagerPrivate.simpleTimer("XPIDB_decode_MS");
           try {
             return new TextDecoder().decode(byteArray);
           } finally {
             decodeTimer.done();
--- a/toolkit/mozapps/extensions/internal/XPIInstall.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIInstall.jsm
@@ -45,29 +45,34 @@ XPCOMUtils.defineLazyModuleGetters(this,
 
   AddonInternal: "resource://gre/modules/addons/XPIDatabase.jsm",
   InstallRDF: "resource://gre/modules/addons/RDFManifestConverter.jsm",
   XPIDatabase: "resource://gre/modules/addons/XPIDatabase.jsm",
   XPIInternal: "resource://gre/modules/addons/XPIProvider.jsm",
   XPIProvider: "resource://gre/modules/addons/XPIProvider.jsm",
 });
 
+XPCOMUtils.defineLazyServiceGetter(this, "uuidGen",
+                                   "@mozilla.org/uuid-generator;1", "nsIUUIDGenerator");
+
 XPCOMUtils.defineLazyGetter(this, "IconDetails", () => {
   return ChromeUtils.import("resource://gre/modules/ExtensionParent.jsm", {}).ExtensionParent.IconDetails;
 });
 
 const {nsIBlocklistService} = Ci;
 
 const nsIFile = Components.Constructor("@mozilla.org/file/local;1", "nsIFile",
                                        "initWithPath");
 
 const BinaryOutputStream = Components.Constructor("@mozilla.org/binaryoutputstream;1",
                                                   "nsIBinaryOutputStream", "setOutputStream");
 const CryptoHash = Components.Constructor("@mozilla.org/security/hash;1",
                                           "nsICryptoHash", "initWithString");
+const FileInputStream = Components.Constructor("@mozilla.org/network/file-input-stream;1",
+                                               "nsIFileInputStream", "init");
 const FileOutputStream = Components.Constructor("@mozilla.org/network/file-output-stream;1",
                                                 "nsIFileOutputStream", "init");
 const ZipReader = Components.Constructor("@mozilla.org/libjar/zip-reader;1",
                                          "nsIZipReader", "open");
 
 XPCOMUtils.defineLazyServiceGetters(this, {
   gCertDB: ["@mozilla.org/security/x509certdb;1", "nsIX509CertDB"],
 });
@@ -748,24 +753,18 @@ async function loadManifestFromRDF(aUri,
 
   return addon;
 }
 
 function defineSyncGUID(aAddon) {
   // Define .syncGUID as a lazy property which is also settable
   Object.defineProperty(aAddon, "syncGUID", {
     get: () => {
-      // Generate random GUID used for Sync.
-      let guid = Cc["@mozilla.org/uuid-generator;1"]
-          .getService(Ci.nsIUUIDGenerator)
-          .generateUUID().toString();
-
-      delete aAddon.syncGUID;
-      aAddon.syncGUID = guid;
-      return guid;
+      aAddon.syncGUID = uuidGen.generateUUID().toString();
+      return aAddon.syncGUID;
     },
     set: (val) => {
       delete aAddon.syncGUID;
       aAddon.syncGUID = val;
     },
     configurable: true,
     enumerable: true,
   });
@@ -1980,19 +1979,17 @@ var LocalAddonInstall = class extends Ad
       } catch (e) {
         logger.warn("Unknown hash algorithm '" + this.hash.algorithm + "' for addon " + this.sourceURI.spec, e);
         this.state = AddonManager.STATE_DOWNLOAD_FAILED;
         this.error = AddonManager.ERROR_INCORRECT_HASH;
         XPIInstall.installs.delete(this);
         return;
       }
 
-      let fis = Cc["@mozilla.org/network/file-input-stream;1"].
-          createInstance(Ci.nsIFileInputStream);
-      fis.init(this.file, -1, -1, false);
+      let fis = new FileInputStream(this.file, -1, -1, false);
       crypto.updateFromStream(fis, this.file.fileSize);
       let calculatedHash = getHashStringForCrypto(crypto);
       if (calculatedHash != this.hash.data) {
         logger.warn("File hash (" + calculatedHash + ") did not match provided hash (" +
                     this.hash.data + ")");
         this.state = AddonManager.STATE_DOWNLOAD_FAILED;
         this.error = AddonManager.ERROR_INCORRECT_HASH;
         XPIInstall.installs.delete(this);
@@ -2161,31 +2158,30 @@ var DownloadAddonInstall = class extends
   }
 
   openChannel() {
     this.restartDownload = false;
 
     try {
       this.file = getTemporaryFile();
       this.ownsTempFile = true;
-      this.stream = Cc["@mozilla.org/network/file-output-stream;1"].
-                    createInstance(Ci.nsIFileOutputStream);
-      this.stream.init(this.file, FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE |
-                       FileUtils.MODE_TRUNCATE, FileUtils.PERMS_FILE, 0);
+      this.stream = new FileOutputStream(this.file,
+                                         (FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE |
+                                          FileUtils.MODE_TRUNCATE),
+                                         FileUtils.PERMS_FILE, 0);
     } catch (e) {
       logger.warn("Failed to start download for addon " + this.sourceURI.spec, e);
       this.state = AddonManager.STATE_DOWNLOAD_FAILED;
       this.error = AddonManager.ERROR_FILE_ACCESS;
       XPIInstall.installs.delete(this);
       this._callInstallListeners("onDownloadFailed");
       return;
     }
 
-    let listener = Cc["@mozilla.org/network/stream-listener-tee;1"].
-                   createInstance(Ci.nsIStreamListenerTee);
+    let listener = Cc["@mozilla.org/network/stream-listener-tee;1"].createInstance(Ci.nsIStreamListenerTee);
     listener.init(this, this.stream);
     try {
       let requireBuiltIn = Services.prefs.getBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, true);
       this.badCertHandler = new CertUtils.BadCertHandler(!requireBuiltIn);
 
       this.channel = NetUtil.newChannel({
         uri: this.sourceURI,
         loadUsingSystemPrincipal: true
@@ -2422,18 +2418,17 @@ var DownloadAddonInstall = class extends
 
   getInterface(iid) {
     if (iid.equals(Ci.nsIAuthPrompt2)) {
       let win = null;
       if (this.browser) {
         win = this.browser.contentWindow || this.browser.ownerGlobal;
       }
 
-      let factory = Cc["@mozilla.org/prompter;1"].
-                    getService(Ci.nsIPromptFactory);
+      let factory = Cc["@mozilla.org/prompter;1"].getService(Ci.nsIPromptFactory);
       let prompt = factory.getPrompt(win, Ci.nsIAuthPrompt2);
 
       if (this.browser && prompt instanceof Ci.nsILoginManagerPrompter)
         prompt.browser = this.browser;
 
       return prompt;
     } else if (iid.equals(Ci.nsIChannelEventSink)) {
       return this;
@@ -3234,24 +3229,20 @@ class SystemAddonInstallLocation extends
     // Remove any add-ons that are no longer part of the set.
     for (let addonID of Object.keys(addonSet.addons)) {
       if (!aAddons.includes(addonID)) {
         AddonManager.getAddonByID(addonID).then(a => a.uninstall());
       }
     }
 
     let newDir = this._baseDir.clone();
-
-    let uuidGen = Cc["@mozilla.org/uuid-generator;1"].
-                  getService(Ci.nsIUUIDGenerator);
     newDir.append("blank");
 
     while (true) {
       newDir.leafName = uuidGen.generateUUID().toString();
-
       try {
         await OS.File.makeDir(newDir.path, { ignoreExisting: false });
         break;
       } catch (e) {
         logger.debug("Could not create new system add-on updates dir, retrying", e);
       }
     }
 
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -46,16 +46,18 @@ XPCOMUtils.defineLazyModuleGetters(this,
 
 XPCOMUtils.defineLazyServiceGetters(this, {
   aomStartup: ["@mozilla.org/addons/addon-manager-startup;1", "amIAddonManagerStartup"],
   timerManager: ["@mozilla.org/updates/timer-manager;1", "nsIUpdateTimerManager"],
 });
 
 const nsIFile = Components.Constructor("@mozilla.org/file/local;1", "nsIFile",
                                        "initWithPath");
+const FileInputStream = Components.Constructor("@mozilla.org/network/file-input-stream;1",
+                                               "nsIFileInputStream", "init");
 
 const PREF_DB_SCHEMA                  = "extensions.databaseSchema";
 const PREF_XPI_STATE                  = "extensions.xpiState";
 const PREF_BOOTSTRAP_ADDONS           = "extensions.bootstrappedAddons";
 const PREF_PENDING_OPERATIONS         = "extensions.pendingOperations";
 const PREF_EM_ENABLED_SCOPES          = "extensions.enabledScopes";
 const PREF_EM_STARTUP_SCAN_SCOPES     = "extensions.startupScanScopes";
 // xpinstall.signatures.required only supported in dev builds
@@ -2775,27 +2777,22 @@ class DirectoryInstallLocation {
       try {
         linkedDirectory.normalize();
       } catch (e) {
         logger.warn("Symbolic link " + aFile.path + " points to a path" +
              " which does not exist");
         return null;
       }
     } else {
-      let fis = Cc["@mozilla.org/network/file-input-stream;1"].
-                createInstance(Ci.nsIFileInputStream);
-      fis.init(aFile, -1, -1, false);
+      let fis = new FileInputStream(aFile, -1, -1, false);
       let line = { value: "" };
-      if (fis instanceof Ci.nsILineInputStream)
-        fis.readLine(line);
+      fis.QueryInterface(Ci.nsILineInputStream).readLine(line);
       fis.close();
       if (line.value) {
-        linkedDirectory = Cc["@mozilla.org/file/local;1"].
-                              createInstance(Ci.nsIFile);
-
+        linkedDirectory = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
         try {
           linkedDirectory.initWithPath(line.value);
         } catch (e) {
           linkedDirectory.setRelativeDescriptor(aFile.parent, line.value);
         }
       }
     }
 
@@ -3138,18 +3135,17 @@ class WinRegInstallLocation extends Dire
 
     this.locked = true;
     this._name = aName;
     this._rootKey = aRootKey;
     this._scope = aScope;
     this._IDToFileMap = {};
 
     let path = this._appKeyPath + "\\Extensions";
-    let key = Cc["@mozilla.org/windows-registry-key;1"].
-              createInstance(Ci.nsIWindowsRegKey);
+    let key = Cc["@mozilla.org/windows-registry-key;1"].createInstance(Ci.nsIWindowsRegKey);
 
     // Reading the registry may throw an exception, and that's ok.  In error
     // cases, we just leave ourselves in the empty state.
     try {
       key.open(this._rootKey, path, Ci.nsIWindowsRegKey.ACCESS_READ);
     } catch (e) {
       return;
     }