Bug 717070 - Profile reset - Part 1 - Backend to initiate profile reset. r=mano
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Thu, 23 Feb 2012 19:34:18 -0800
changeset 88609 5b6fc1230141c725d6d67478c0c043fc1aa14836
parent 88608 9059fb810f28f82bfeba318d6b9533c008f760d7
child 88610 f3b97dc917cfd8cd0c5fc01e03dc605376ae7c19
push id6919
push usermozilla@noorenberghe.ca
push dateFri, 09 Mar 2012 05:51:54 +0000
treeherdermozilla-inbound@750307029faa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmano
bugs717070
milestone13.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 717070 - Profile reset - Part 1 - Backend to initiate profile reset. r=mano
browser/components/migration/src/ProfileMigrator.js
toolkit/profile/nsIProfileMigrator.idl
toolkit/xre/nsAppRunner.cpp
--- a/browser/components/migration/src/ProfileMigrator.js
+++ b/browser/components/migration/src/ProfileMigrator.js
@@ -11,47 +11,67 @@ const Cu = Components.utils;
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/FileUtils.jsm");
 
 function ProfileMigrator() {
 }
 
 ProfileMigrator.prototype = {
-  migrate: function PM_migrate(aStartup) {
+  migrate: function PM_migrate(aStartup, aKey) {
     // By opening the wizard with a supplied migrator, it will automatically
     // migrate from it.
-    let [key, migrator] = this._getDefaultMigrator();
+    let key = null, migrator = null;
+    let skipImportSourcePage = Cc["@mozilla.org/supports-PRBool;1"]
+                                 .createInstance(Ci.nsISupportsPRBool);
+    if (aKey) {
+      key = aKey;
+      migrator = this._getMigratorIfSourceExists(key);
+      if (!migrator) {
+        Cu.reportError("Invalid migrator key specified or source does not exist.");
+        return;
+      }
+      // If the migrator was passed to us from the caller, use that migrator
+      // and skip the import source page.
+      skipImportSourcePage.data = true;
+    } else {
+      [key, migrator] = this._getDefaultMigrator();
+    }
     if (!key)
         return;
 
     let params = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
     params.appendElement(this._toCString(key), false);
     params.appendElement(migrator, false);
     params.appendElement(aStartup, false);
+    params.appendElement(skipImportSourcePage, false);
 
     Services.ww.openWindow(null,
                            "chrome://browser/content/migration/migration.xul",
                            "_blank",
                            "chrome,dialog,modal,centerscreen,titlebar",
                            params);
   },
 
   _toCString: function PM__toCString(aStr) {
     let cstr = Cc["@mozilla.org/supports-cstring;1"].
                createInstance(Ci.nsISupportsCString);
     cstr.data = aStr;
     return cstr;
   },
 
   _getMigratorIfSourceExists: function PM__getMigratorIfSourceExists(aKey) {
-    let cid = "@mozilla.org/profile/migrator;1?app=browser&type=" + aKey;
-    let migrator = Cc[cid].createInstance(Ci.nsIBrowserProfileMigrator);
-    if (migrator.sourceExists)
-      return migrator;
+    try {
+      let cid = "@mozilla.org/profile/migrator;1?app=browser&type=" + aKey;
+      let migrator = Cc[cid].createInstance(Ci.nsIBrowserProfileMigrator);
+      if (migrator.sourceExists)
+        return migrator;
+    } catch (ex) {
+      Cu.reportError("Could not get migrator: " + ex);
+    }
     return null;
   },
 
   // We don't yet support checking for the default browser on all platforms,
   // needless to say we don't have migrators for all browsers.  Thus, for each
   // platform, there's a fallback list of migrators used in these cases.
   _PLATFORM_FALLBACK_LIST:
 #ifdef XP_WIN
--- a/toolkit/profile/nsIProfileMigrator.idl
+++ b/toolkit/profile/nsIProfileMigrator.idl
@@ -64,33 +64,36 @@ interface nsIProfileStartup : nsISupport
 
 /**
  * Migrate application settings from an outside source.
  *
  * @provider Application (Profile-migration code)
  * @client   Toolkit (Startup code)
  * @obtainable service, contractid("@mozilla.org/toolkit/profile-migrator;1")
  */
-[scriptable, uuid(24ce8b9d-b7ff-4279-aef4-26e158f03e34)]
+[scriptable, uuid(3df284a5-2258-4d46-a664-761ecdc04c22)]
 interface nsIProfileMigrator : nsISupports 
 {
   /**
    * Migrate data from an outside source, if possible.  Does nothing
    * otherwise.
    *
    * When this method is called, a default profile has been created;
    * XPCOM has been initialized such that compreg.dat is in the
    * profile; the directory service does *not* return a key for
    * NS_APP_USER_PROFILE_50_DIR or any of the keys depending on an active
    * profile. To figure out the directory of the "current" profile, use
    * aStartup.directory.
    *
    * If your migrator needs to access services that use the profile (to
    * set profile prefs or bookmarks, for example), use aStartup.doStartup.
    *
+   * @param  aStartup nsIProfileStartup object to use during migration.
+   * @param  aKey     optional key of a migrator to use to skip source selection.
+   *
    * @note The startup code ignores COM exceptions thrown from this method.
    */
-  void migrate(in nsIProfileStartup aStartup);
-};  
+  void migrate(in nsIProfileStartup aStartup, in ACString aKey);
+};
 
 %{C++
 #define NS_PROFILEMIGRATOR_CONTRACTID "@mozilla.org/toolkit/profile-migrator;1"
 %}
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -145,16 +145,17 @@ using mozilla::unused;
 #include "nsDirectoryServiceUtils.h"
 #include "nsEmbedCID.h"
 #include "nsNetUtil.h"
 #include "nsReadableUtils.h"
 #include "nsStaticComponents.h"
 #include "nsXPCOM.h"
 #include "nsXPCOMCIDInternal.h"
 #include "nsXPIDLString.h"
+#include "nsPrintfCString.h"
 #include "nsVersionComparator.h"
 
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsXULAppAPI.h"
 #include "nsXREDirProvider.h"
 #include "nsToolkitCompsCID.h"
 
 #include "nsINIParser.h"
@@ -1906,19 +1907,82 @@ ShowProfileManager(nsIToolkitProfileServ
 // 1) check for -profile <path>
 // 2) check for -P <name>
 // 3) check for -ProfileManager
 // 4) use the default profile, if there is one
 // 5) if there are *no* profiles, set up profile-migration
 // 6) display the profile-manager UI
 
 static bool gDoMigration = false;
+static bool gDoProfileReset = false;
+
+/**
+ * Creates a new profile with a timestamp in the name to use for profile reset.
+ */
+static nsresult
+ResetProfile(nsIToolkitProfileService* aProfileSvc, nsIToolkitProfile* *aNewProfile)
+{
+  NS_ENSURE_ARG_POINTER(aProfileSvc);
+
+  nsCOMPtr<nsIToolkitProfile> newProfile;
+  // Make the new profile "default-" + the time in seconds since epoch for uniqueness.
+  nsCAutoString newProfileName("default-");
+  newProfileName.Append(nsPrintfCString("%lld", PR_Now() / 1000));
+  nsresult rv = aProfileSvc->CreateProfile(nsnull, // choose a default dir for us
+                                           nsnull, // choose a default dir for us
+                                           newProfileName,
+                                           getter_AddRefs(newProfile));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aProfileSvc->Flush();
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  NS_IF_ADDREF(*aNewProfile = newProfile);
+
+  return NS_OK;
+}
+
+/**
+ * Set the currently running profile as the default/selected one.
+ *
+ * @param aCurrentProfileRoot The root directory of the current profile.
+ * @return an error if aCurrentProfileRoot is not found or the profile could not
+ * be set as the default.
+ */
+static nsresult
+SetCurrentProfileAsDefault(nsIToolkitProfileService* aProfileSvc,
+                           nsILocalFile* aCurrentProfileRoot)
+{
+  NS_ENSURE_ARG_POINTER(aProfileSvc);
+
+  nsCOMPtr<nsISimpleEnumerator> profiles;
+  nsresult rv = aProfileSvc->GetProfiles(getter_AddRefs(profiles));
+  if (NS_FAILED(rv))
+    return rv;
+
+  bool foundMatchingProfile = false;
+  nsCOMPtr<nsIToolkitProfile> profile;
+  rv = profiles->GetNext(getter_AddRefs(profile));
+  while (NS_SUCCEEDED(rv)) {
+    nsCOMPtr<nsILocalFile> profileRoot;
+    profile->GetRootDir(getter_AddRefs(profileRoot));
+    profileRoot->Equals(aCurrentProfileRoot, &foundMatchingProfile);
+    if (foundMatchingProfile && profile) {
+      rv = aProfileSvc->SetSelectedProfile(profile);
+      if (NS_SUCCEEDED(rv))
+        rv = aProfileSvc->Flush();
+      return rv;
+    }
+    rv = profiles->GetNext(getter_AddRefs(profile));
+  }
+  return rv;
+}
 
 static nsresult
-SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
+SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, nsINativeAppSupport* aNative,
               bool* aStartOffline, nsACString* aProfileName)
 {
   nsresult rv;
   ArgResult ar;
   const char* arg;
   *aResult = nsnull;
   *aStartOffline = false;
 
@@ -1926,16 +1990,38 @@ SelectProfile(nsIProfileLock* *aResult, 
   if (ar == ARG_BAD) {
     PR_fprintf(PR_STDERR, "Error: argument -offline is invalid when argument -osint is specified\n");
     return NS_ERROR_FAILURE;
   }
 
   if (ar || EnvHasValue("XRE_START_OFFLINE"))
     *aStartOffline = true;
 
+  if (EnvHasValue("MOZ_RESET_PROFILE_RESTART")) {
+    gDoProfileReset = true;
+    gDoMigration = true;
+    SaveToEnv("MOZ_RESET_PROFILE_RESTART=");
+  }
+
+  // reset-profile and migration args need to be checked before any profiles are chosen below.
+  ar = CheckArg("reset-profile", true);
+  if (ar == ARG_BAD) {
+    PR_fprintf(PR_STDERR, "Error: argument -reset-profile is invalid when argument -osint is specified\n");
+    return NS_ERROR_FAILURE;
+  } else if (ar == ARG_FOUND) {
+    gDoProfileReset = true;
+  }
+
+  ar = CheckArg("migration", true);
+  if (ar == ARG_BAD) {
+    PR_fprintf(PR_STDERR, "Error: argument -migration is invalid when argument -osint is specified\n");
+    return NS_ERROR_FAILURE;
+  } else if (ar == ARG_FOUND) {
+    gDoMigration = true;
+  }
 
   nsCOMPtr<nsILocalFile> lf = GetFileFromEnv("XRE_PROFILE_PATH");
   if (lf) {
     nsCOMPtr<nsILocalFile> localDir =
       GetFileFromEnv("XRE_PROFILE_LOCAL_PATH");
     if (!localDir) {
       localDir = lf;
     }
@@ -1945,33 +2031,53 @@ SelectProfile(nsIProfileLock* *aResult, 
       aProfileName->Assign(nsDependentCString(arg));
 
     // Clear out flags that we handled (or should have handled!) last startup.
     const char *dummy;
     CheckArg("p", false, &dummy);
     CheckArg("profile", false, &dummy);
     CheckArg("profilemanager");
 
+    if (gDoProfileReset) {
+      // If we're resetting a profile, create a new one and use it to startup.
+      nsCOMPtr<nsIToolkitProfile> newProfile;
+      rv = ResetProfile(aProfileSvc, getter_AddRefs(newProfile));
+      if (NS_SUCCEEDED(rv)) {
+        rv = newProfile->GetRootDir(getter_AddRefs(lf));
+        NS_ENSURE_SUCCESS(rv, rv);
+        SaveFileToEnv("XRE_PROFILE_PATH", lf);
+
+        rv = newProfile->GetLocalDir(getter_AddRefs(localDir));
+        NS_ENSURE_SUCCESS(rv, rv);
+        SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", localDir);
+
+        rv = newProfile->GetName(*aProfileName);
+        if (NS_FAILED(rv))
+          aProfileName->Truncate(0);
+        SaveWordToEnv("XRE_PROFILE_NAME", *aProfileName);
+      } else {
+        NS_WARNING("Profile reset failed.");
+        gDoProfileReset = false;
+      }
+    }
+
     return NS_LockProfilePath(lf, localDir, nsnull, aResult);
   }
 
-  ar = CheckArg("migration", true);
-  if (ar == ARG_BAD) {
-    PR_fprintf(PR_STDERR, "Error: argument -migration is invalid when argument -osint is specified\n");
-    return NS_ERROR_FAILURE;
-  } else if (ar == ARG_FOUND) {
-    gDoMigration = true;
-  }
-
   ar = CheckArg("profile", true, &arg);
   if (ar == ARG_BAD) {
     PR_fprintf(PR_STDERR, "Error: argument -profile requires a path\n");
     return NS_ERROR_FAILURE;
   }
   if (ar) {
+    if (gDoProfileReset) {
+      NS_WARNING("Profile reset is only supported for the default profile.");
+      gDoProfileReset = false;
+    }
+
     nsCOMPtr<nsILocalFile> lf;
     rv = XRE_GetFileFromPath(arg, getter_AddRefs(lf));
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIProfileUnlocker> unlocker;
 
     // Check if the profile path exists and it's a directory.
     bool exists;
@@ -1985,23 +2091,16 @@ SelectProfile(nsIProfileLock* *aResult, 
     // assume that the temp directory is the same as the given directory.
     rv = NS_LockProfilePath(lf, lf, getter_AddRefs(unlocker), aResult);
     if (NS_SUCCEEDED(rv))
       return rv;
 
     return ProfileLockedDialog(lf, lf, unlocker, aNative, aResult);
   }
 
-  nsCOMPtr<nsIToolkitProfileService> profileSvc;
-  rv = NS_NewToolkitProfileService(getter_AddRefs(profileSvc));
-  if (rv == NS_ERROR_FILE_ACCESS_DENIED)
-    PR_fprintf(PR_STDERR, "Error: Access was denied while trying to open files in " \
-                "your profile directory.\n"); 
-  NS_ENSURE_SUCCESS(rv, rv);
-
   ar = CheckArg("createprofile", true, &arg);
   if (ar == ARG_BAD) {
     PR_fprintf(PR_STDERR, "Error: argument -createprofile requires a profile name\n");
     return NS_ERROR_FAILURE;
   }
   if (ar) {
     nsCOMPtr<nsIToolkitProfile> profile;
 
@@ -2012,29 +2111,29 @@ SelectProfile(nsIProfileLock* *aResult, 
                                    true, getter_AddRefs(lf));
       if (NS_FAILED(rv)) {
         PR_fprintf(PR_STDERR, "Error: profile path not valid.\n");
         return rv;
       }
       
       // As with -profile, assume that the given path will be used for both the
       // main profile directory and the temp profile directory.
-      rv = profileSvc->CreateProfile(lf, lf, nsDependentCSubstring(arg, delim),
+      rv = aProfileSvc->CreateProfile(lf, lf, nsDependentCSubstring(arg, delim),
                                      getter_AddRefs(profile));
     } else {
-      rv = profileSvc->CreateProfile(nsnull, nsnull, nsDependentCString(arg),
+      rv = aProfileSvc->CreateProfile(nsnull, nsnull, nsDependentCString(arg),
                                      getter_AddRefs(profile));
     }
     // Some pathological arguments can make it this far
     if (NS_FAILED(rv)) {
       PR_fprintf(PR_STDERR, "Error creating profile.\n");
       return rv; 
     }
     rv = NS_ERROR_ABORT;  
-    profileSvc->Flush();
+    aProfileSvc->Flush();
 
     // XXXben need to ensure prefs.js exists here so the tinderboxes will
     //        not go orange.
     nsCOMPtr<nsILocalFile> prefsJSFile;
     profile->GetRootDir(getter_AddRefs(prefsJSFile));
     prefsJSFile->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
     nsCAutoString pathStr;
     prefsJSFile->GetNativePath(pathStr);
@@ -2044,38 +2143,44 @@ SelectProfile(nsIProfileLock* *aResult, 
     if (!exists)
       prefsJSFile->Create(nsIFile::NORMAL_FILE_TYPE, 0644);
     // XXXdarin perhaps 0600 would be better?
 
     return rv;
   }
 
   PRUint32 count;
-  rv = profileSvc->GetProfileCount(&count);
+  rv = aProfileSvc->GetProfileCount(&count);
   NS_ENSURE_SUCCESS(rv, rv);
 
   ar = CheckArg("p", false, &arg);
   if (ar == ARG_BAD) {
     ar = CheckArg("osint");
     if (ar == ARG_FOUND) {
       PR_fprintf(PR_STDERR, "Error: argument -p is invalid when argument -osint is specified\n");
       return NS_ERROR_FAILURE;
     }
-    return ShowProfileManager(profileSvc, aNative);
+    return ShowProfileManager(aProfileSvc, aNative);
   }
   if (ar) {
     ar = CheckArg("osint");
     if (ar == ARG_FOUND) {
       PR_fprintf(PR_STDERR, "Error: argument -p is invalid when argument -osint is specified\n");
       return NS_ERROR_FAILURE;
     }
     nsCOMPtr<nsIToolkitProfile> profile;
-    rv = profileSvc->GetProfileByName(nsDependentCString(arg),
+    rv = aProfileSvc->GetProfileByName(nsDependentCString(arg),
                                       getter_AddRefs(profile));
     if (NS_SUCCEEDED(rv)) {
+      // If we're resetting a profile, create a new one and use it to startup.
+      if (gDoProfileReset) {
+        NS_WARNING("Profile reset is only supported for the default profile.");
+        gDoProfileReset = false;
+      }
+
       nsCOMPtr<nsIProfileUnlocker> unlocker;
       rv = profile->Lock(nsnull, aResult);
       if (NS_SUCCEEDED(rv)) {
         if (aProfileName)
           aProfileName->Assign(nsDependentCString(arg));
         return NS_OK;
       }
 
@@ -2086,56 +2191,66 @@ SelectProfile(nsIProfileLock* *aResult, 
       nsCOMPtr<nsILocalFile> profileLocalDir;
       rv = profile->GetLocalDir(getter_AddRefs(profileLocalDir));
       NS_ENSURE_SUCCESS(rv, rv);
 
       return ProfileLockedDialog(profileDir, profileLocalDir, unlocker,
                                  aNative, aResult);
     }
 
-    return ShowProfileManager(profileSvc, aNative);
+    return ShowProfileManager(aProfileSvc, aNative);
   }
 
   ar = CheckArg("profilemanager", true);
   if (ar == ARG_BAD) {
     PR_fprintf(PR_STDERR, "Error: argument -profilemanager is invalid when argument -osint is specified\n");
     return NS_ERROR_FAILURE;
   } else if (ar == ARG_FOUND) {
-    return ShowProfileManager(profileSvc, aNative);
+    return ShowProfileManager(aProfileSvc, aNative);
   }
 
   if (!count) {
     gDoMigration = true;
+    gDoProfileReset = false;
 
     // create a default profile
     nsCOMPtr<nsIToolkitProfile> profile;
-    nsresult rv = profileSvc->CreateProfile(nsnull, // choose a default dir for us
-                                            nsnull, // choose a default dir for us
-                                            NS_LITERAL_CSTRING("default"),
-                                            getter_AddRefs(profile));
+    nsresult rv = aProfileSvc->CreateProfile(nsnull, // choose a default dir for us
+                                             nsnull, // choose a default dir for us
+                                             NS_LITERAL_CSTRING("default"),
+                                             getter_AddRefs(profile));
     if (NS_SUCCEEDED(rv)) {
-      profileSvc->Flush();
+      aProfileSvc->Flush();
       rv = profile->Lock(nsnull, aResult);
       if (NS_SUCCEEDED(rv)) {
         if (aProfileName)
           aProfileName->Assign(NS_LITERAL_CSTRING("default"));
         return NS_OK;
       }
     }
   }
 
   bool useDefault = true;
   if (count > 1)
-    profileSvc->GetStartWithLastProfile(&useDefault);
+    aProfileSvc->GetStartWithLastProfile(&useDefault);
 
   if (useDefault) {
     nsCOMPtr<nsIToolkitProfile> profile;
     // GetSelectedProfile will auto-select the only profile if there's just one
-    profileSvc->GetSelectedProfile(getter_AddRefs(profile));
+    aProfileSvc->GetSelectedProfile(getter_AddRefs(profile));
     if (profile) {
+      // If we're resetting a profile, create a new one and use it to startup.
+      if (gDoProfileReset) {
+        nsCOMPtr<nsIToolkitProfile> newProfile;
+        rv = ResetProfile(aProfileSvc, getter_AddRefs(newProfile));
+        if (NS_SUCCEEDED(rv))
+          profile = newProfile;
+        else
+          gDoProfileReset = false;
+      }
       nsCOMPtr<nsIProfileUnlocker> unlocker;
       rv = profile->Lock(getter_AddRefs(unlocker), aResult);
       if (NS_SUCCEEDED(rv)) {
         // Try to grab the profile name.
         if (aProfileName) {
           rv = profile->GetName(*aProfileName);
           if (NS_FAILED(rv))
             aProfileName->Truncate(0);
@@ -2151,17 +2266,17 @@ SelectProfile(nsIProfileLock* *aResult, 
       rv = profile->GetRootDir(getter_AddRefs(profileLocalDir));
       NS_ENSURE_SUCCESS(rv, rv);
 
       return ProfileLockedDialog(profileDir, profileLocalDir, unlocker,
                                  aNative, aResult);
     }
   }
 
-  return ShowProfileManager(profileSvc, aNative);
+  return ShowProfileManager(aProfileSvc, aNative);
 }
 
 /** 
  * Checks the compatibility.ini file to see if we have updated our application
  * or otherwise invalidated our caches. If the application has been updated, 
  * we return false; otherwise, we return true. We also write the status 
  * of the caches (valid/invalid) into the return param aCachesOK. The aCachesOK
  * is always invalid if the application has been updated. 
@@ -3195,17 +3310,29 @@ XRE_main(int argc, char* argv[], const n
       return 0;
     }
 #endif
 
     nsCOMPtr<nsIProfileLock> profileLock;
     bool startOffline = false;
     nsCAutoString profileName;
 
-    rv = SelectProfile(getter_AddRefs(profileLock), nativeApp, &startOffline,
+    nsCOMPtr<nsIToolkitProfileService> profileSvc;
+    rv = NS_NewToolkitProfileService(getter_AddRefs(profileSvc));
+    if (rv == NS_ERROR_FILE_ACCESS_DENIED) {
+      PR_fprintf(PR_STDERR, "Error: Access was denied while trying to open files in " \
+                 "your profile directory.\n");
+    }
+    if (NS_FAILED(rv)) {
+      // We failed to choose or create profile - notify user and quit
+      ProfileMissingDialog(nativeApp);
+      return 1;
+    }
+
+    rv = SelectProfile(getter_AddRefs(profileLock), profileSvc, nativeApp, &startOffline,
                        &profileName);
     if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ||
         rv == NS_ERROR_ABORT) return 0;
 
     if (NS_FAILED(rv)) {
       // We failed to choose or create profile - notify user and quit
       ProfileMissingDialog(nativeApp);
       return 1;
@@ -3424,18 +3551,30 @@ XRE_main(int argc, char* argv[], const n
           }
         }
 
         // Profile Migration
         if (gAppData->flags & NS_XRE_ENABLE_PROFILE_MIGRATOR && gDoMigration) {
           gDoMigration = false;
           nsCOMPtr<nsIProfileMigrator> pm
             (do_CreateInstance(NS_PROFILEMIGRATOR_CONTRACTID));
-          if (pm)
-            pm->Migrate(&dirProvider);
+          if (pm) {
+            nsCAutoString aKey;
+            if (gDoProfileReset) {
+              // Automatically migrate from the current application if we just
+              // reset the profile.
+              aKey = MOZ_APP_NAME;
+              pm->Migrate(&dirProvider, aKey);
+              // Set the new profile as the default after migration.
+              rv = SetCurrentProfileAsDefault(profileSvc, profD);
+              if (NS_FAILED(rv)) NS_WARNING("Could not set current profile as the default");
+            } else {
+              pm->Migrate(&dirProvider, aKey);
+            }
+          }
         }
 
         NS_TIME_FUNCTION_MARK("Profile migration");
 
         dirProvider.DoStartup();
 
         NS_TIME_FUNCTION_MARK("dirProvider.DoStartup() (profile-after-change)");