Bug 1363925: Part 8a - Migrate XPIProviderUtils.js to XPIDatabase.jsm. r=aswan
authorKris Maglione <maglione.k@gmail.com>
Sun, 22 Apr 2018 14:22:59 -0700
changeset 468748 20d1663e4a8cd7c1aa2bdef66c6b0e92bf8b81f5
parent 468747 fde77a548f547094e5c06a30f927175c03ad23ae
child 468749 8adbe703aeba227b6ec186c306a42b291b0b627f
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaswan
bugs1363925
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1363925: Part 8a - Migrate XPIProviderUtils.js to XPIDatabase.jsm. r=aswan MozReview-Commit-ID: CNfHgCYCkNd
toolkit/mozapps/extensions/internal/AddonRepository.jsm
toolkit/mozapps/extensions/internal/AddonTestUtils.jsm
toolkit/mozapps/extensions/internal/XPIDatabase.jsm
toolkit/mozapps/extensions/internal/XPIInstall.jsm
toolkit/mozapps/extensions/internal/XPIProvider.jsm
toolkit/mozapps/extensions/internal/XPIProviderUtils.js
toolkit/mozapps/extensions/internal/moz.build
--- a/toolkit/mozapps/extensions/internal/AddonRepository.jsm
+++ b/toolkit/mozapps/extensions/internal/AddonRepository.jsm
@@ -366,17 +366,17 @@ var AddonRepository = {
   },
 
   /**
    * Asynchronously get a cached add-on by id. The add-on (or null if the
    * add-on is not found) is passed to the specified callback. If caching is
    * disabled, null is passed to the specified callback.
    *
    * The callback variant exists only for existing code in XPIProvider.jsm
-   * and XPIProviderUtils.jsm that requires a synchronous callback, yuck.
+   * and XPIDatabase.jsm that requires a synchronous callback, yuck.
    *
    * @param  aId
    *         The id of the add-on to get
    */
   async getCachedAddonByID(aId, aCallback) {
     if (!aId || !this.cacheEnabled) {
       if (aCallback) {
         aCallback(null);
--- a/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm
+++ b/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm
@@ -782,16 +782,17 @@ var AddonTestUtils = {
         // simulate real-world usage.
         let XPIscope = ChromeUtils.import("resource://gre/modules/addons/XPIProvider.jsm", {});
         // This would be cleaner if I could get it as the rejection reason from
         // the AddonManagerInternal.shutdown() promise
         let shutdownError = XPIscope.XPIDatabase._saveError;
 
         AddonManagerPrivate.unregisterProvider(XPIscope.XPIProvider);
         Cu.unload("resource://gre/modules/addons/XPIProvider.jsm");
+        Cu.unload("resource://gre/modules/addons/XPIDatabase.jsm");
         Cu.unload("resource://gre/modules/addons/XPIInstall.jsm");
 
         if (shutdownError)
           throw shutdownError;
 
         return true;
       });
   },
rename from toolkit/mozapps/extensions/internal/XPIProviderUtils.js
rename to toolkit/mozapps/extensions/internal/XPIDatabase.jsm
--- a/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
+++ b/toolkit/mozapps/extensions/internal/XPIDatabase.jsm
@@ -1,35 +1,53 @@
 /* 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/. */
 
 "use strict";
 
 /* eslint "valid-jsdoc": [2, {requireReturn: false, requireReturnDescription: false, prefer: {return: "returns"}}] */
 
-// These are injected from XPIProvider.jsm
-/* globals ADDON_SIGNING, SIGNED_TYPES, BOOTSTRAP_REASONS, DB_SCHEMA,
-          AddonInternal, XPIProvider, XPIStates,
-          isUsableAddon, recordAddonTelemetry,
-          descriptorToPath */
+var EXPORTED_SYMBOLS = ["XPIDatabase", "XPIDatabaseReconcile"];
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetters(this, {
   AddonManager: "resource://gre/modules/AddonManager.jsm",
   AddonManagerPrivate: "resource://gre/modules/AddonManager.jsm",
   AddonRepository: "resource://gre/modules/addons/AddonRepository.jsm",
+  AddonSettings: "resource://gre/modules/addons/AddonSettings.jsm",
   DeferredTask: "resource://gre/modules/DeferredTask.jsm",
   FileUtils: "resource://gre/modules/FileUtils.jsm",
   OS: "resource://gre/modules/osfile.jsm",
   Services: "resource://gre/modules/Services.jsm",
   XPIInstall: "resource://gre/modules/addons/XPIInstall.jsm",
+  XPIInternal: "resource://gre/modules/addons/XPIProvider.jsm",
 });
 
+// These are injected from XPIProvider.jsm
+/* globals SIGNED_TYPES, BOOTSTRAP_REASONS, DB_SCHEMA,
+          AddonInternal, XPIProvider, XPIStates,
+          isUsableAddon, recordAddonTelemetry,
+          descriptorToPath */
+
+for (let sym of [
+  "AddonInternal",
+  "BOOTSTRAP_REASONS",
+  "DB_SCHEMA",
+  "SIGNED_TYPES",
+  "XPIProvider",
+  "XPIStates",
+  "descriptorToPath",
+  "isUsableAddon",
+  "recordAddonTelemetry",
+]) {
+  XPCOMUtils.defineLazyGetter(this, sym, () => XPIInternal[sym]);
+}
+
 ChromeUtils.import("resource://gre/modules/Log.jsm");
 const LOGGER_ID = "addons.xpi-utils";
 
 const nsIFile = Components.Constructor("@mozilla.org/file/local;1", "nsIFile",
                                        "initWithPath");
 
 // Create a new logger for use by the Addons XPI Provider Utils
 // (Requires AddonManager.jsm)
@@ -1261,18 +1279,19 @@ this.XPIDatabaseReconcile = {
    *        A boolean which indicates whether metadata should be reloaded from
    *        the addon manifests. Default to false.
    * @returns {DBAddonInternal}
    *        The new addon.
    */
   updateCompatibility(aInstallLocation, aOldAddon, aAddonState, aReloadMetadata) {
     logger.debug("Updating compatibility for add-on " + aOldAddon.id + " in " + aInstallLocation.name);
 
-    let checkSigning = aOldAddon.signedState === undefined && ADDON_SIGNING &&
-                       SIGNED_TYPES.has(aOldAddon.type);
+    let checkSigning = (aOldAddon.signedState === undefined &&
+                        AddonSettings.ADDON_SIGNING &&
+                        SIGNED_TYPES.has(aOldAddon.type));
 
     let manifest = null;
     if (checkSigning || aReloadMetadata) {
       try {
         let file = new nsIFile(aAddonState.path);
         manifest = XPIInstall.syncLoadManifestFromFile(file, aInstallLocation);
       } catch (err) {
         // If we can no longer read the manifest, it is no longer compatible.
@@ -1307,17 +1326,17 @@ this.XPIDatabaseReconcile = {
     return aOldAddon;
   },
 
   /**
    * Compares the add-ons that are currently installed to those that were
    * known to be installed when the application last ran and applies any
    * changes found to the database. Also sends "startupcache-invalidate" signal to
    * observerservice if it detects that data may have changed.
-   * Always called after XPIProviderUtils.js and extensions.json have been loaded.
+   * Always called after XPIDatabase.jsm and extensions.json have been loaded.
    *
    * @param {Object} aManifests
    *        A dictionary of cached AddonInstalls for add-ons that have been
    *        installed
    * @param {boolean} aUpdateCompatibility
    *        true to update add-ons appDisabled property when the application
    *        version has changed
    * @param {string?} [aOldAppVersion]
--- a/toolkit/mozapps/extensions/internal/XPIInstall.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIInstall.jsm
@@ -38,16 +38,18 @@ XPCOMUtils.defineLazyGetter(this, "IconD
 ChromeUtils.defineModuleGetter(this, "NetUtil",
                                "resource://gre/modules/NetUtil.jsm");
 ChromeUtils.defineModuleGetter(this, "OS",
                                "resource://gre/modules/osfile.jsm");
 ChromeUtils.defineModuleGetter(this, "ProductAddonChecker",
                                "resource://gre/modules/addons/ProductAddonChecker.jsm");
 ChromeUtils.defineModuleGetter(this, "UpdateUtils",
                                "resource://gre/modules/UpdateUtils.jsm");
+ChromeUtils.defineModuleGetter(this, "XPIDatabase",
+                               "resource://gre/modules/addons/XPIDatabase.jsm");
 ChromeUtils.defineModuleGetter(this, "ZipUtils",
                                "resource://gre/modules/ZipUtils.jsm");
 
 const {nsIBlocklistService} = Ci;
 
 const nsIFile = Components.Constructor("@mozilla.org/file/local;1", "nsIFile",
                                        "initWithPath");
 
@@ -80,30 +82,29 @@ const PREF_DISTRO_ADDONS_PERMS        = 
 const PREF_INSTALL_REQUIRESECUREORIGIN = "extensions.install.requireSecureOrigin";
 const PREF_PENDING_OPERATIONS         = "extensions.pendingOperations";
 const PREF_SYSTEM_ADDON_UPDATE_URL    = "extensions.systemAddon.update.url";
 const PREF_XPI_ENABLED                = "xpinstall.enabled";
 const PREF_XPI_DIRECT_WHITELISTED     = "xpinstall.whitelist.directRequest";
 const PREF_XPI_FILE_WHITELISTED       = "xpinstall.whitelist.fileRequest";
 const PREF_XPI_WHITELIST_REQUIRED     = "xpinstall.whitelist.required";
 
-/* globals AddonInternal, BOOTSTRAP_REASONS, KEY_APP_SYSTEM_ADDONS, KEY_APP_SYSTEM_DEFAULTS, KEY_APP_TEMPORARY, PREF_BRANCH_INSTALLED_ADDON, PREF_SYSTEM_ADDON_SET, TEMPORARY_ADDON_SUFFIX, SIGNED_TYPES, TOOLKIT_ID, XPIDatabase, XPI_PERMISSION, XPIStates, getExternalType, isTheme, isUsableAddon, isWebExtension, mustSign, recordAddonTelemetry */
+/* globals AddonInternal, BOOTSTRAP_REASONS, KEY_APP_SYSTEM_ADDONS, KEY_APP_SYSTEM_DEFAULTS, KEY_APP_TEMPORARY, PREF_BRANCH_INSTALLED_ADDON, PREF_SYSTEM_ADDON_SET, TEMPORARY_ADDON_SUFFIX, SIGNED_TYPES, TOOLKIT_ID, XPI_PERMISSION, XPIStates, getExternalType, isTheme, isUsableAddon, isWebExtension, mustSign, recordAddonTelemetry */
 const XPI_INTERNAL_SYMBOLS = [
   "AddonInternal",
   "BOOTSTRAP_REASONS",
   "KEY_APP_SYSTEM_ADDONS",
   "KEY_APP_SYSTEM_DEFAULTS",
   "KEY_APP_TEMPORARY",
   "PREF_BRANCH_INSTALLED_ADDON",
   "PREF_SYSTEM_ADDON_SET",
   "SIGNED_TYPES",
   "TEMPORARY_ADDON_SUFFIX",
   "TOOLKIT_ID",
   "XPI_PERMISSION",
-  "XPIDatabase",
   "XPIStates",
   "getExternalType",
   "isTheme",
   "isUsableAddon",
   "isWebExtension",
   "mustSign",
   "recordAddonTelemetry",
 ];
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -26,16 +26,18 @@ XPCOMUtils.defineLazyModuleGetters(this,
   OS: "resource://gre/modules/osfile.jsm",
   ConsoleAPI: "resource://gre/modules/Console.jsm",
   JSONFile: "resource://gre/modules/JSONFile.jsm",
   LegacyExtensionsUtils: "resource://gre/modules/LegacyExtensionsUtils.jsm",
   setTimeout: "resource://gre/modules/Timer.jsm",
   clearTimeout: "resource://gre/modules/Timer.jsm",
 
   UpdateChecker: "resource://gre/modules/addons/XPIInstall.jsm",
+  XPIDatabase: "resource://gre/modules/addons/XPIDatabase.jsm",
+  XPIDatabaseReconcile: "resource://gre/modules/addons/XPIDatabase.jsm",
   XPIInstall: "resource://gre/modules/addons/XPIInstall.jsm",
   verifyBundleSignedState: "resource://gre/modules/addons/XPIInstall.jsm",
 });
 
 const {nsIBlocklistService} = Ci;
 
 XPCOMUtils.defineLazyServiceGetter(this, "aomStartup",
                                    "@mozilla.org/addons/addon-manager-startup;1",
@@ -235,73 +237,28 @@ var gIDTest = /^(\{[0-9a-f]{8}-[0-9a-f]{
 
 ChromeUtils.import("resource://gre/modules/Log.jsm");
 const LOGGER_ID = "addons.xpi";
 
 // Create a new logger for use by all objects in this Addons XPI Provider module
 // (Requires AddonManager.jsm)
 var logger = Log.repository.getLogger(LOGGER_ID);
 
-const LAZY_OBJECTS = ["XPIDatabase", "XPIDatabaseReconcile"];
-/* globals XPIDatabase, XPIDatabaseReconcile*/
-
-var gLazyObjectsLoaded = false;
-
 XPCOMUtils.defineLazyGetter(this, "gStartupScanScopes", () => {
   let appBuildID = Services.appinfo.appBuildID;
   let oldAppBuildID = Services.prefs.getCharPref(PREF_EM_LAST_APP_BUILD_ID, "");
   Services.prefs.setCharPref(PREF_EM_LAST_APP_BUILD_ID, appBuildID);
   if (appBuildID !== oldAppBuildID) {
     // If the build id changed, scan all scopes
     return AddonManager.SCOPE_ALL;
   }
 
   return Services.prefs.getIntPref(PREF_EM_STARTUP_SCAN_SCOPES, 0);
 });
 
-function loadLazyObjects() {
-  let uri = "resource://gre/modules/addons/XPIProviderUtils.js";
-  let scope = Cu.Sandbox(Services.scriptSecurityManager.getSystemPrincipal(), {
-    sandboxName: uri,
-    wantGlobalProperties: ["ChromeUtils", "TextDecoder"],
-  });
-
-  Object.assign(scope, {
-    ADDON_SIGNING: AddonSettings.ADDON_SIGNING,
-    SIGNED_TYPES,
-    BOOTSTRAP_REASONS,
-    DB_SCHEMA,
-    AddonInternal,
-    XPIProvider,
-    XPIStates,
-    isUsableAddon,
-    recordAddonTelemetry,
-    descriptorToPath,
-  });
-
-  Services.scriptloader.loadSubScript(uri, scope);
-
-  for (let name of LAZY_OBJECTS) {
-    delete gGlobalScope[name];
-    gGlobalScope[name] = scope[name];
-  }
-  gLazyObjectsLoaded = true;
-  return scope;
-}
-
-LAZY_OBJECTS.forEach(name => {
-  Object.defineProperty(gGlobalScope, name, {
-    get() {
-      let objs = loadLazyObjects();
-      return objs[name];
-    },
-    configurable: true
-  });
-});
-
 /**
  * Spins the event loop until the given promise resolves, and then eiter returns
  * its success value or throws its rejection value.
  *
  * @param {Promise} promise
  *        The promise to await.
  * @returns {any}
  *        The promise's resolution value, if any.
@@ -804,17 +761,17 @@ class XPIState {
           data[field] = bootstrapped[field];
         }
       }
     }
 
     return new XPIState(location, id, data);
   }
 
-  // Compatibility shim getters for legacy callers in XPIProviderUtils:
+  // Compatibility shim getters for legacy callers in XPIDatabase.jsm.
   get mtime() {
     return this.lastModifiedTime;
   }
   get active() {
     return this.enabled;
   }
 
 
@@ -1496,17 +1453,20 @@ var XPIProvider = {
   // Per-addon telemetry information
   _telemetryDetails: {},
   // Have we started shutting down bootstrap add-ons?
   _closing: false,
 
   // Check if the XPIDatabase has been loaded (without actually
   // triggering unwanted imports or I/O)
   get isDBLoaded() {
-    return gLazyObjectsLoaded && XPIDatabase.initialized;
+    // Make sure we don't touch the XPIDatabase getter before it's
+    // actually loaded, and force an early load.
+    return (Object.getOwnPropertyDescriptor(gGlobalScope, "XPIDatabase").value &&
+            XPIDatabase.initialized);
   },
 
   /**
    * Returns true if the add-on with the given ID is currently active,
    * without forcing the add-ons database to load.
    *
    * @param {string} addonId
    *        The ID of the add-on to check.
@@ -3258,17 +3218,17 @@ for (let meth of ["cancelUninstallAddon"
 }
 
 // Maps instances of AddonInternal to AddonWrapper
 const wrapperMap = new WeakMap();
 let addonFor = wrapper => wrapperMap.get(wrapper);
 
 /**
  * The AddonInternal is an internal only representation of add-ons. It may
- * have come from the database (see DBAddonInternal in XPIProviderUtils.jsm)
+ * have come from the database (see DBAddonInternal in XPIDatabase.jsm)
  * or an install manifest.
  */
 function AddonInternal() {
   this._hasResourceCache = new Map();
 
   XPCOMUtils.defineLazyGetter(this, "wrapper", () => {
     return new AddonWrapper(this);
   });
@@ -4768,37 +4728,38 @@ class WinRegInstallLocation extends Dire
   isLinkedAddon(aId) {
     return true;
   }
 }
 
 var XPIInternal = {
   AddonInternal,
   BOOTSTRAP_REASONS,
+  DB_SCHEMA,
   KEY_APP_SYSTEM_ADDONS,
   KEY_APP_SYSTEM_DEFAULTS,
   KEY_APP_TEMPORARY,
   PREF_BRANCH_INSTALLED_ADDON,
   PREF_SYSTEM_ADDON_SET,
   SIGNED_TYPES,
   SystemAddonInstallLocation,
-  TemporaryInstallLocation,
   TEMPORARY_ADDON_SUFFIX,
   TOOLKIT_ID,
-  XPI_PERMISSION,
+  TemporaryInstallLocation,
+  XPIProvider,
   XPIStates,
+  XPI_PERMISSION,
   awaitPromise,
+  descriptorToPath,
   getExternalType,
   isTheme,
   isUsableAddon,
   isWebExtension,
   mustSign,
   recordAddonTelemetry,
-
-  get XPIDatabase() { return gGlobalScope.XPIDatabase; },
 };
 
 var addonTypes = [
   new AddonManagerPrivate.AddonType("extension", URI_EXTENSION_STRINGS,
                                     "type.extension.name",
                                     AddonManager.VIEW_TYPE_LIST, 4000,
                                     AddonManager.TYPE_SUPPORTS_UNDO_RESTARTLESS_UNINSTALL),
   new AddonManagerPrivate.AddonType("theme", URI_EXTENSION_STRINGS,
--- a/toolkit/mozapps/extensions/internal/moz.build
+++ b/toolkit/mozapps/extensions/internal/moz.build
@@ -9,19 +9,19 @@ EXTRA_JS_MODULES.addons += [
     'AddonSettings.jsm',
     'AddonUpdateChecker.jsm',
     'Content.js',
     'GMPProvider.jsm',
     'LightweightThemeImageOptimizer.jsm',
     'ProductAddonChecker.jsm',
     'SpellCheckDictionaryBootstrap.js',
     'UpdateRDFConverter.jsm',
+    'XPIDatabase.jsm',
     'XPIInstall.jsm',
     'XPIProvider.jsm',
-    'XPIProviderUtils.js',
 ]
 
 TESTING_JS_MODULES += [
     'AddonTestUtils.jsm',
 ]
 
 # Don't ship unused providers on Android
 if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android':