Bug 705927 - Support friendly names for profile selection during migration. r=Mano
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Wed, 04 Jun 2014 00:56:18 -0700
changeset 205711 875df781fa8bf83c4f6b056706269ec75daf258a
parent 205710 e7f2825aed544e4eeae78ddbcec10f089f5762c3
child 205712 49b4b6cf5de8bc582925b8aaa0a12b6beb75f906
child 205790 035c1df29690b37ecd5baaf8bf24138bbf0fb491
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersMano
bugs705927
milestone32.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 705927 - Support friendly names for profile selection during migration. r=Mano
browser/components/migration/content/migration.js
browser/components/migration/public/nsIBrowserProfileMigrator.idl
browser/components/migration/src/ChromeProfileMigrator.js
browser/components/migration/src/MigrationUtils.jsm
browser/components/migration/tests/unit/test_IE_bookmarks.js
--- a/browser/components/migration/content/migration.js
+++ b/browser/components/migration/content/migration.js
@@ -132,17 +132,17 @@ var MigrationWizard = {
       if (this._autoMigrate)
         this._wiz.currentPage.next = "homePageImport";
       else
         this._wiz.currentPage.next = "importItems";
 
       if (sourceProfiles && sourceProfiles.length == 1)
         this._selectedProfile = sourceProfiles[0];
       else
-        this._selectedProfile = "";
+        this._selectedProfile = null;
     }
   },
   
   // 2 - [Profile Selection]
   onSelectProfilePageShow: function ()
   {
     // Disabling this for now, since we ask about import sources in automigration
     // too and don't want to disable the back button
@@ -152,38 +152,43 @@ var MigrationWizard = {
     var profiles = document.getElementById("profiles");
     while (profiles.hasChildNodes()) 
       profiles.removeChild(profiles.firstChild);
     
     // 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;
-      for (var i = 0; i < sourceProfiles.length; ++i) {
+
+      for (let profile of sourceProfiles) {
         var item = document.createElement("radio");
-        item.id = sourceProfiles[i];
-        item.setAttribute("label", sourceProfiles[i]);
+        item.id = profile.id;
+        item.setAttribute("label", profile.name);
         profiles.appendChild(item);
       }
     }
     
-    profiles.selectedItem = this._selectedProfile ? document.getElementById(this._selectedProfile) : profiles.firstChild;
+    profiles.selectedItem = this._selectedProfile ? document.getElementById(this._selectedProfile.id) : profiles.firstChild;
   },
   
   onSelectProfilePageRewound: function ()
   {
     var profiles = document.getElementById("profiles");
-    this._selectedProfile = profiles.selectedItem.id;
+    this._selectedProfile = this._migrator.sourceProfiles.find(
+      profile => profile.id == profiles.selectedItem.id
+    ) || null;
   },
   
   onSelectProfilePageAdvanced: function ()
   {
     var profiles = document.getElementById("profiles");
-    this._selectedProfile = profiles.selectedItem.id;
-    
+    this._selectedProfile = this._migrator.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: function ()
   {
--- a/browser/components/migration/public/nsIBrowserProfileMigrator.idl
+++ b/browser/components/migration/public/nsIBrowserProfileMigrator.idl
@@ -3,17 +3,17 @@
  * 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/. */
 
 #include "nsISupports.idl"
 
 interface nsIArray;
 interface nsIProfileStartup;
 
-[scriptable, uuid(44993E0E-74E8-4BEC-9D66-AD8156E0A274)]
+[scriptable, uuid(30e5a7ec-f71e-4f41-9dbd-7429c02132ec)]
 interface nsIBrowserProfileMigrator : nsISupports
 {
   /**
    * profile items to migrate. use with migrate().
    */
   const unsigned short ALL         = 0x0000;
   const unsigned short SETTINGS    = 0x0001;
   const unsigned short COOKIES     = 0x0002;
@@ -25,28 +25,28 @@ interface nsIBrowserProfileMigrator : ns
   const unsigned short SESSION     = 0x0080;
 
   /**
    * Copy user profile information to the current active profile.
    * @param aItems   list of data items to migrate. see above for values.
    * @param aStartup helper interface which is non-null if called during startup. 
    * @param aProfile profile to migrate from, if there is more than one.
    */
-  void migrate(in unsigned short aItems, in nsIProfileStartup aStartup, in wstring aProfile);
+  void migrate(in unsigned short aItems, in nsIProfileStartup aStartup, in jsval aProfile);
 
   /**
    * A bit field containing profile items that this migrator
    * offers for import. 
    * @param   aProfile the profile that we are looking for available data
    *          to import
    * @param   aDoingStartup "true" if the profile is not currently being used.
    * @return  bit field containing profile items (see above)
    * @note    a return value of 0 represents no items rather than ALL.
    */
-  unsigned short getMigrateData(in wstring aProfile, in boolean aDoingStartup);
+  unsigned short getMigrateData(in jsval aProfile, in boolean aDoingStartup);
 
   /** 
    * Whether or not there is any data that can be imported from this 
    * browser (i.e. whether or not it is installed, and there exists
    * a user profile)
    */
   readonly attribute boolean          sourceExists;
 
--- a/browser/components/migration/src/ChromeProfileMigrator.js
+++ b/browser/components/migration/src/ChromeProfileMigrator.js
@@ -88,17 +88,17 @@ function ChromeProfileMigrator() {
 }
 
 ChromeProfileMigrator.prototype = Object.create(MigratorPrototype);
 
 ChromeProfileMigrator.prototype.getResources =
   function Chrome_getResources(aProfile) {
     if (this._chromeUserDataFolder) {
       let profileFolder = this._chromeUserDataFolder.clone();
-      profileFolder.append(aProfile);
+      profileFolder.append(aProfile.id);
       if (profileFolder.exists()) {
         let possibleResources = [GetBookmarksResource(profileFolder),
                                  GetHistoryResource(profileFolder),
                                  GetCookiesResource(profileFolder)];
         return [r for each (r in possibleResources) if (r != null)];
       }
     }
     return [];
@@ -107,45 +107,55 @@ ChromeProfileMigrator.prototype.getResou
 Object.defineProperty(ChromeProfileMigrator.prototype, "sourceProfiles", {
   get: function Chrome_sourceProfiles() {
     if ("__sourceProfiles" in this)
       return this.__sourceProfiles;
 
     if (!this._chromeUserDataFolder)
       return [];
 
-    let profiles;
+    let profiles = [];
     try {
       // Local State is a JSON file that contains profile info.
       let localState = this._chromeUserDataFolder.clone();
       localState.append("Local State");
       if (!localState.exists())
         throw new Error("Chrome's 'Local State' file does not exist.");
       if (!localState.isReadable())
         throw new Error("Chrome's 'Local State' file could not be read.");
 
       let fstream = Cc[FILE_INPUT_STREAM_CID].createInstance(Ci.nsIFileInputStream);
       fstream.init(localState, -1, 0, 0);
       let inputStream = NetUtil.readInputStreamToString(fstream, fstream.available(),
                                                         { charset: "UTF-8" });
       let info_cache = JSON.parse(inputStream).profile.info_cache;
-      if (info_cache)
-        profiles = Object.keys(info_cache);
+      for (let profileFolderName in info_cache) {
+        let profileFolder = this._chromeUserDataFolder.clone();
+        profileFolder.append(profileFolderName);
+        profiles.push({
+          id: profileFolderName,
+          name: info_cache[profileFolderName].name || profileFolderName,
+        });
+      }
     } catch (e) {
       Cu.reportError("Error detecting Chrome profiles: " + e);
       // If we weren't able to detect any profiles above, fallback to the Default profile.
       let defaultProfileFolder = this._chromeUserDataFolder.clone();
       defaultProfileFolder.append("Default");
-      if (defaultProfileFolder.exists())
-        profiles = ["Default"];
+      if (defaultProfileFolder.exists()) {
+        profiles = [{
+          id: "Default",
+          name: "Default",
+        }];
+      }
     }
 
     // Only list profiles from which any data can be imported
-    return this.__sourceProfiles = profiles.filter(function(profileName) {
-      let resources = this.getResources(profileName);
+    return this.__sourceProfiles = profiles.filter(function(profile) {
+      let resources = this.getResources(profile);
       return resources && resources.length > 0;
     }, this);
   }
 });
 
 Object.defineProperty(ChromeProfileMigrator.prototype, "sourceHomePageURL", {
   get: function Chrome_sourceHomePageURL() {
     let prefsFile = this._chromeUserDataFolder.clone();
--- a/browser/components/migration/src/MigrationUtils.jsm
+++ b/browser/components/migration/src/MigrationUtils.jsm
@@ -87,17 +87,20 @@ function getMigratorKeyForDefaultBrowser
  * 7. For startup-only migrators, override |startupOnlyMigrator|.
  */
 this.MigratorPrototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIBrowserProfileMigrator]),
 
   /**
    * OVERRIDE IF AND ONLY IF the source supports multiple profiles.
    *
-   * Returns array of profiles (by names) from which data may be imported.
+   * Returns array of profile objects from which data may be imported. The object
+   * should have the following keys:
+   *   id - a unique string identifier for the profile
+   *   name - a pretty name to display to the user in the UI
    *
    * Only profiles from which data can be imported should be listed.  Otherwise
    * the behavior of the migration wizard isn't well-defined.
    *
    * For a single-profile source (e.g. safari, ie), this returns null,
    * and not an empty array.  That is the default implementation.
    */
   get sourceProfiles() null,
@@ -308,24 +311,25 @@ this.MigratorPrototype = {
     catch(ex) {
       Cu.reportError(ex);
     }
     return exists;
   },
 
   /*** PRIVATE STUFF - DO NOT OVERRIDE ***/
   _getMaybeCachedResources: function PMB__getMaybeCachedResources(aProfile) {
+    let profileKey = aProfile ? aProfile.id : "";
     if (this._resourcesByProfile) {
-      if (aProfile in this._resourcesByProfile)
-        return this._resourcesByProfile[aProfile];
+      if (profileKey in this._resourcesByProfile)
+        return this._resourcesByProfile[profileKey];
     }
     else {
       this._resourcesByProfile = { };
     }
-    return this._resourcesByProfile[aProfile] = this.getResources(aProfile);
+    return this._resourcesByProfile[profileKey] = this.getResources(aProfile);
   }
 };
 
 this.MigrationUtils = Object.freeze({
   resourceTypes: {
     SETTINGS:   Ci.nsIBrowserProfileMigrator.SETTINGS,
     COOKIES:    Ci.nsIBrowserProfileMigrator.COOKIES,
     HISTORY:    Ci.nsIBrowserProfileMigrator.HISTORY,
--- a/browser/components/migration/tests/unit/test_IE_bookmarks.js
+++ b/browser/components/migration/tests/unit/test_IE_bookmarks.js
@@ -6,17 +6,17 @@ function run_test() {
   do_test_pending();
 
   let migrator = MigrationUtils.getMigrator("ie");
 
   // Sanity check for the source.
   do_check_true(migrator.sourceExists);
 
   // Ensure bookmarks migration is available.
-  let availableSources = migrator.getMigrateData("FieldOfFlowers", false);
+  let availableSources = migrator.getMigrateData(null, false);
   do_check_true((availableSources & MigrationUtils.resourceTypes.BOOKMARKS) > 0);
 
   // Wait for the imported bookmarks.  Check that "From Internet Explorer"
   // folders are created in the menu and on the toolbar.
   let source = MigrationUtils.getLocalizedString("sourceNameIE");
   let label = MigrationUtils.getLocalizedString("importedBookmarksFolder", [source]);
 
   let expectedParents = [ PlacesUtils.bookmarksMenuFolderId,
@@ -47,10 +47,10 @@ function run_test() {
 
     // Check the bookmarks have been imported to all the expected parents.
     do_check_eq(expectedParents.length, 0);
 
     do_test_finished();
   }, "Migration:Ended", false);
 
   migrator.migrate(MigrationUtils.resourceTypes.BOOKMARKS, null,
-                   "FieldOfFlowers");
+                   null);
 }