Bug 1363925: Part 8a - Migrate XPIProviderUtils.js to XPIDatabase.jsm. r?aswan draft
authorKris Maglione <maglione.k@gmail.com>
Sun, 22 Apr 2018 14:22:59 -0700
changeset 786320 6c8467fbf0928b7d7f7b01c609c0edc52aedf3ad
parent 786319 0838d09243ba2362be2902c81f5c45419261af36
child 786321 295c3fc3ee8c153d358cc1e7c8b6f85925a03bd7
push id107433
push usermaglione.k@gmail.com
push dateSun, 22 Apr 2018 22:24:27 +0000
reviewersaswan
bugs1363925
milestone61.0a1
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");
 
 ChromeUtils.defineModuleGetter(this, "clearTimeout", "resource://gre/modules/Timer.jsm");
 ChromeUtils.defineModuleGetter(this, "setTimeout", "resource://gre/modules/Timer.jsm");
 
 const {nsIBlocklistService} = Ci;
 
@@ -83,30 +85,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
@@ -24,16 +24,18 @@ XPCOMUtils.defineLazyModuleGetters(this,
   FileUtils: "resource://gre/modules/FileUtils.jsm",
   PermissionsUtils: "resource://gre/modules/PermissionsUtils.jsm",
   OS: "resource://gre/modules/osfile.jsm",
   ConsoleAPI: "resource://gre/modules/Console.jsm",
   JSONFile: "resource://gre/modules/JSONFile.jsm",
   LegacyExtensionsUtils: "resource://gre/modules/LegacyExtensionsUtils.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",
@@ -233,73 +235,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.
@@ -802,17 +759,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;
   }
 
 
@@ -1494,17 +1451,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.
@@ -3107,17 +3067,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);
   });
@@ -4617,38 +4577,39 @@ 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,
   isDisabledLegacy,
   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':