Bug 1649606 - Migrate XPIDatabase.jsm from OSFile to IOUtils r=emalysz,mixedpuppy
☠☠ backed out by e06c2941cdfc ☠ ☠
authorBarret Rennie <barret@brennie.ca>
Wed, 07 Apr 2021 00:16:04 +0000
changeset 574667 6c93b2419ee50246d8f81ad30419d35289491cd9
parent 574666 5574f84255953f4cbb1616e51fb9efa1f846c108
child 574668 09acdcb865bb1189274500b876b20af53506fada
push id140296
push userbrennie@mozilla.com
push dateWed, 07 Apr 2021 00:18:31 +0000
treeherderautoland@6c93b2419ee5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemalysz, mixedpuppy
bugs1649606
milestone89.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 1649606 - Migrate XPIDatabase.jsm from OSFile to IOUtils r=emalysz,mixedpuppy Differential Revision: https://phabricator.services.mozilla.com/D110506
toolkit/mozapps/extensions/internal/XPIDatabase.jsm
--- a/toolkit/mozapps/extensions/internal/XPIDatabase.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIDatabase.jsm
@@ -23,17 +23,16 @@ const { XPCOMUtils } = ChromeUtils.impor
 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",
   ExtensionUtils: "resource://gre/modules/ExtensionUtils.jsm",
   FileUtils: "resource://gre/modules/FileUtils.jsm",
-  OS: "resource://gre/modules/osfile.jsm",
   PermissionsUtils: "resource://gre/modules/PermissionsUtils.jsm",
   Services: "resource://gre/modules/Services.jsm",
 
   Blocklist: "resource://gre/modules/Blocklist.jsm",
   UpdateChecker: "resource://gre/modules/addons/XPIInstall.jsm",
   XPIInstall: "resource://gre/modules/addons/XPIInstall.jsm",
   XPIInternal: "resource://gre/modules/addons/XPIProvider.jsm",
   XPIProvider: "resource://gre/modules/addons/XPIProvider.jsm",
@@ -1546,19 +1545,18 @@ this.XPIDatabase = {
     if (this._saveError) {
       return this._saveError;
     }
     return null;
   },
 
   async _saveNow() {
     try {
-      let json = JSON.stringify(this);
       let path = this.jsonFile.path;
-      await OS.File.writeAtomic(path, json, { tmpPath: `${path}.tmp` });
+      await IOUtils.writeJSON(path, this, { tmpPath: `${path}.tmp` });
 
       if (!this._schemaVersionSet) {
         // Update the XPIDB schema version preference the first time we
         // successfully save the database.
         logger.debug(
           "XPI Database saved, setting schema version preference to " +
             DB_SCHEMA
         );
@@ -1566,17 +1564,20 @@ this.XPIDatabase = {
         this._schemaVersionSet = true;
 
         // Reading the DB worked once, so we don't need the load error
         this._loadError = null;
       }
     } catch (error) {
       logger.warn("Failed to save XPI database", error);
       this._saveError = error;
-      throw error;
+
+      if (!(error instanceof DOMException) || error.name !== "AbortError") {
+        throw error;
+      }
     }
   },
 
   /**
    * Mark the current stored data dirty, and schedule a flush to disk
    */
   saveChanges() {
     if (!this.initialized) {
@@ -1660,53 +1661,54 @@ this.XPIDatabase = {
 
   _recordStartupError(reason) {
     AddonManagerPrivate.recordSimpleMeasure("XPIDB_startupError", reason);
   },
 
   /**
    * Parse loaded data, reconstructing the database if the loaded data is not valid
    *
-   * @param {string} aData
-   *        The stringified add-on JSON to parse.
+   * @param {object} aInputAddons
+   *        The add-on JSON to parse.
    * @param {boolean} aRebuildOnError
    *        If true, synchronously reconstruct the database from installed add-ons
    */
-  async parseDB(aData, aRebuildOnError) {
+  async parseDB(aInputAddons, aRebuildOnError) {
     try {
       let parseTimer = AddonManagerPrivate.simpleTimer("XPIDB_parseDB_MS");
-      let inputAddons = JSON.parse(aData);
-
-      if (!("schemaVersion" in inputAddons) || !("addons" in inputAddons)) {
+
+      if (!("schemaVersion" in aInputAddons) || !("addons" in aInputAddons)) {
         let error = new Error("Bad JSON file contents");
         error.rebuildReason = "XPIDB_rebuildBadJSON_MS";
         throw error;
       }
 
-      if (inputAddons.schemaVersion <= 27) {
+      if (aInputAddons.schemaVersion <= 27) {
         // Types were translated in bug 857456.
-        for (let addon of inputAddons.addons) {
+        for (let addon of aInputAddons.addons) {
           migrateAddonLoader(addon);
         }
-      } else if (inputAddons.schemaVersion != DB_SCHEMA) {
+      } else if (aInputAddons.schemaVersion != DB_SCHEMA) {
         // 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)
-        this._recordStartupError(`schemaMismatch-${inputAddons.schemaVersion}`);
+        this._recordStartupError(
+          `schemaMismatch-${aInputAddons.schemaVersion}`
+        );
         logger.debug(
-          `JSON schema mismatch: expected ${DB_SCHEMA}, actual ${inputAddons.schemaVersion}`
+          `JSON schema mismatch: expected ${DB_SCHEMA}, actual ${aInputAddons.schemaVersion}`
         );
       }
 
       let forEach = this.syncLoadingDB ? arrayForEach : idleForEach;
 
       // If we got here, we probably have good data
       // Make AddonInternal instances from the loaded data and save them
       let addonDB = new Map();
-      await forEach(inputAddons.addons, loadedAddon => {
+      await forEach(aInputAddons.addons, loadedAddon => {
         if (loadedAddon.path) {
           try {
             loadedAddon._sourceBundle = new nsIFile(loadedAddon.path);
           } catch (e) {
             // We can fail here when the path is invalid, usually from the
             // wrong OS
             logger.warn(
               "Could not find source bundle for add-on " + loadedAddon.id,
@@ -1767,26 +1769,23 @@ this.XPIDatabase = {
     // Already started (and possibly finished) loading
     if (this._dbPromise) {
       return this._dbPromise;
     }
 
     logger.debug(`Starting async load of XPI database ${this.jsonFile.path}`);
     this._dbPromise = (async () => {
       try {
-        let byteArray = await OS.File.read(this.jsonFile.path, null);
+        let json = await IOUtils.readJSON(this.jsonFile.path);
 
         logger.debug("Finished async read of XPI database, parsing...");
         await this.maybeIdleDispatch();
-        let text = new TextDecoder().decode(byteArray);
-
-        await this.maybeIdleDispatch();
-        await this.parseDB(text, true);
+        await this.parseDB(json, true);
       } catch (error) {
-        if (error.becauseNoSuchFile) {
+        if (error instanceof DOMException && error.name === "NotFoundError") {
           if (Services.prefs.getIntPref(PREF_DB_SCHEMA, 0)) {
             this._recordStartupError("dbMissing");
           }
         } else {
           logger.warn(
             `Extensions database ${this.jsonFile.path} exists but is not readable; rebuilding`,
             error
           );