Bug 862127 - Convert migration.js to use async migration interfaces r?Gijs draft
authorDoug Thayer <dothayer@mozilla.com>
Fri, 12 Jan 2018 09:11:38 -0800
changeset 723848 883d79bef8f643006d53bfe44a71dca191380a9b
parent 723847 78f760f09356b9409cf63fadfe5708d22ecdbae8
child 723849 909545b0096eb6b5092ab279bd1d4967b559f90f
push id96559
push userbmo:dothayer@mozilla.com
push dateTue, 23 Jan 2018 23:30:16 +0000
reviewersGijs
bugs862127
milestone60.0a1
Bug 862127 - Convert migration.js to use async migration interfaces r?Gijs migration.js is a special case where we generally need blocking calls in order for the wizard to work correctly. Accordingly we block waiting for the new async interfaces. With automigration and potential new UIs that are in the works for migration, the asynchronicity of these interfaces will be more relevant, but here it's not really important enough to make big changes to the way the UI is implemented. MozReview-Commit-ID: LkfwBVfpCJO
browser/components/migration/content/migration.js
--- a/browser/components/migration/content/migration.js
+++ b/browser/components/migration/content/migration.js
@@ -38,17 +38,17 @@ var MigrationWizard = { /* exported Migr
     this.isInitialMigration = entryPointId == MigrationUtils.MIGRATION_ENTRYPOINT_FIRSTRUN;
 
     if (args.length > 1) {
       this._source = args[1];
       this._migrator = args[2] instanceof kIMig ? args[2] : null;
       this._autoMigrate = args[3].QueryInterface(kIPStartup);
       this._skipImportSourcePage = args[4];
       if (this._migrator && args[5]) {
-        let sourceProfiles = this._migrator.sourceProfiles;
+        let sourceProfiles = this.spinResolve(this._migrator.getSourceProfiles());
         this._selectedProfile = sourceProfiles.find(profile => profile.id == args[5]);
       }
 
       if (this._autoMigrate) {
         // Show the "nothing" option in the automigrate case to provide an
         // easily identifiable way to avoid migration and create a new profile.
         document.getElementById("nothing").hidden = false;
       }
@@ -62,38 +62,56 @@ var MigrationWizard = { /* exported Migr
     os.removeObserver(this, "Migration:Started");
     os.removeObserver(this, "Migration:ItemBeforeMigrate");
     os.removeObserver(this, "Migration:ItemAfterMigrate");
     os.removeObserver(this, "Migration:ItemError");
     os.removeObserver(this, "Migration:Ended");
     MigrationUtils.finishMigration();
   },
 
+  spinResolve(promise) {
+    let canAdvance = this._wiz.canAdvance;
+    let canRewind = this._wiz.canRewind;
+    let canCancel = this._canCancel;
+    this._wiz.canAdvance = false;
+    this._wiz.canRewind = false;
+    this._canCancel = false;
+    let result = MigrationUtils.spinResolve(promise);
+    this._wiz.canAdvance = canAdvance;
+    this._wiz.canRewind = canRewind;
+    this._canCancel = canCancel;
+    return result;
+  },
+
+  onWizardCancel() {
+    return this._canCancel;
+  },
+
   // 1 - Import Source
   onImportSourcePageShow() {
     // Show warning message to close the selected browser when needed
-    function toggleCloseBrowserWarning() {
+    let toggleCloseBrowserWarning = () => {
       let visibility = "hidden";
       if (group.selectedItem.id != "nothing") {
-        let migrator = MigrationUtils.getMigrator(group.selectedItem.id);
+        let migrator = this.spinResolve(MigrationUtils.getMigrator(group.selectedItem.id));
         visibility = migrator.sourceLocked ? "visible" : "hidden";
       }
       document.getElementById("closeSourceBrowser").style.visibility = visibility;
-    }
+    };
     this._wiz.canRewind = false;
 
     var selectedMigrator = null;
     this._availableMigrators = [];
 
     // Figure out what source apps are are available to import from:
     var group = document.getElementById("importSourceGroup");
     for (var i = 0; i < group.childNodes.length; ++i) {
       var migratorKey = group.childNodes[i].id;
       if (migratorKey != "nothing") {
-        var migrator = MigrationUtils.getMigrator(migratorKey);
+        var migrator = this.spinResolve(MigrationUtils.getMigrator(migratorKey));
         if (migrator) {
           // Save this as the first selectable item, if we don't already have
           // one, or if it is the migrator that was passed to us.
           if (!selectedMigrator || this._source == migratorKey)
             selectedMigrator = group.childNodes[i];
           this._availableMigrators.push([migratorKey, migrator]);
         } else {
           // Hide this option
@@ -143,25 +161,25 @@ var MigrationWizard = { /* exported Migr
       Services.telemetry.getHistogramById("FX_MIGRATION_SOURCE_BROWSER")
                         .add(MigrationUtils.getSourceIdForTelemetry("nothing"));
       document.documentElement.cancel();
       return false;
     }
 
     if (!this._migrator || (newSource != this._source)) {
       // Create the migrator for the selected source.
-      this._migrator = MigrationUtils.getMigrator(newSource);
+      this._migrator = this.spinResolve(MigrationUtils.getMigrator(newSource));
 
       this._itemsFlags = kIMig.ALL;
       this._selectedProfile = null;
     }
     this._source = newSource;
 
     // check for more than one source profile
-    var sourceProfiles = this._migrator.sourceProfiles;
+    var sourceProfiles = this.spinResolve(this._migrator.getSourceProfiles());
     if (this._skipImportSourcePage) {
       this._wiz.currentPage.next = "homePageImport";
     } else if (sourceProfiles && sourceProfiles.length > 1) {
       this._wiz.currentPage.next = "selectProfile";
     } else {
       if (this._autoMigrate)
         this._wiz.currentPage.next = "homePageImport";
       else
@@ -184,54 +202,57 @@ var MigrationWizard = { /* exported Migr
 
     var profiles = document.getElementById("profiles");
     while (profiles.hasChildNodes())
       profiles.firstChild.remove();
 
     // Note that this block is still reached even if the user chose 'From File'
     // and we canceled the dialog.  When that happens, _migrator will be null.
     if (this._migrator) {
-      var sourceProfiles = this._migrator.sourceProfiles;
+      var sourceProfiles = this.spinResolve(this._migrator.getSourceProfiles());
 
       for (let profile of sourceProfiles) {
         var item = document.createElement("radio");
         item.id = profile.id;
         item.setAttribute("label", profile.name);
         profiles.appendChild(item);
       }
     }
 
     profiles.selectedItem = this._selectedProfile ? document.getElementById(this._selectedProfile.id) : profiles.firstChild;
   },
 
   onSelectProfilePageRewound() {
     var profiles = document.getElementById("profiles");
-    this._selectedProfile = this._migrator.sourceProfiles.find(
+    let sourceProfiles = this.spinResolve(this._migrator.getSourceProfiles());
+    this._selectedProfile = sourceProfiles.find(
       profile => profile.id == profiles.selectedItem.id
     ) || null;
   },
 
   onSelectProfilePageAdvanced() {
     var profiles = document.getElementById("profiles");
-    this._selectedProfile = this._migrator.sourceProfiles.find(
+    let sourceProfiles = this.spinResolve(this._migrator.getSourceProfiles());
+    this._selectedProfile = sourceProfiles.find(
       profile => profile.id == profiles.selectedItem.id
     ) || null;
 
     // If we're automigrating or just doing bookmarks don't show the item selection page
     if (this._autoMigrate)
       this._wiz.currentPage.next = "homePageImport";
   },
 
   // 3 - ImportItems
   onImportItemsPageShow() {
     var dataSources = document.getElementById("dataSources");
     while (dataSources.hasChildNodes())
       dataSources.firstChild.remove();
 
-    var items = this._migrator.getMigrateData(this._selectedProfile, this._autoMigrate);
+    var items = this.spinResolve(this._migrator.getMigrateData(this._selectedProfile,
+                                                               this._autoMigrate));
     for (var i = 0; i < 16; ++i) {
       var itemID = (items >> i) & 0x1 ? Math.pow(2, i) : 0;
       if (itemID > 0) {
         var checkbox = document.createElement("checkbox");
         checkbox.id = itemID;
         checkbox.setAttribute("label",
           MigrationUtils.getLocalizedString(itemID + "_" + this._source));
         dataSources.appendChild(checkbox);
@@ -299,19 +320,19 @@ var MigrationWizard = { /* exported Migr
 
     var singleStart = document.getElementById("homePageSingleStart");
     singleStart.setAttribute("label", mainStr);
     singleStart.setAttribute("value", "DEFAULT");
 
     var appName = MigrationUtils.getBrowserName(this._source);
 
     // semi-wallpaper for crash when multiple profiles exist, since we haven't initialized mSourceProfile in places
-    this._migrator.getMigrateData(this._selectedProfile, this._autoMigrate);
+    this.spinResolve(this._migrator.getMigrateData(this._selectedProfile, this._autoMigrate));
 
-    var oldHomePageURL = this._migrator.sourceHomePageURL;
+    var oldHomePageURL = this.spinResolve(this._migrator.getSourceHomePageURL());
 
     if (oldHomePageURL && appName) {
       var oldHomePageLabel =
         brandBundle.getFormattedString("homePageImport", [appName]);
       var oldHomePage = document.getElementById("oldHomePage");
       oldHomePage.setAttribute("label", oldHomePageLabel);
       oldHomePage.setAttribute("value", oldHomePageURL);
       oldHomePage.removeAttribute("hidden");
@@ -332,25 +353,28 @@ var MigrationWizard = { /* exported Migr
 
   // 5 - Migrating
   onMigratingPageShow() {
     this._wiz.getButton("cancel").disabled = true;
     this._wiz.canRewind = false;
     this._wiz.canAdvance = false;
 
     // When automigrating, show all of the data that can be received from this source.
-    if (this._autoMigrate)
-      this._itemsFlags = this._migrator.getMigrateData(this._selectedProfile, this._autoMigrate);
+    if (this._autoMigrate) {
+      this._itemsFlags =
+        this.spinResolve(this._migrator.getMigrateData(this._selectedProfile,
+                                                       this._autoMigrate));
+    }
 
     this._listItems("migratingItems");
     setTimeout(() => this.onMigratingMigrate(), 0);
   },
 
-  onMigratingMigrate() {
-    this._migrator.migrate(this._itemsFlags, this._autoMigrate, this._selectedProfile);
+  async onMigratingMigrate() {
+    await this._migrator.migrate(this._itemsFlags, this._autoMigrate, this._selectedProfile);
 
     Services.telemetry.getHistogramById("FX_MIGRATION_SOURCE_BROWSER")
                       .add(MigrationUtils.getSourceIdForTelemetry(this._source));
     if (!this._autoMigrate) {
       let hist = Services.telemetry.getKeyedHistogramById("FX_MIGRATION_USAGE");
       let exp = 0;
       let items = this._itemsFlags;
       while (items) {