Bug 1535021: Check if there is an existing instance of Firefox using the default selected profile before showing the profile manager. r=froydnj
authorDave Townsend <dtownsend@oxymoronical.com>
Thu, 14 Mar 2019 19:55:31 +0000
changeset 521945 af5b991568da
parent 521944 be4af23f4c1a
child 521946 db4a1fa6c07c
push id10870
push usernbeleuzu@mozilla.com
push dateFri, 15 Mar 2019 20:00:07 +0000
treeherdermozilla-beta@c594aee5b7a4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1535021
milestone67.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 1535021: Check if there is an existing instance of Firefox using the default selected profile before showing the profile manager. r=froydnj If configured to show the profile manager on startup we want to defer doing that until after attempting to remote to an existing Firefox. So in the default startup case (not first run, not when a profile is selected on the command line and not when the profile manager is requested on the command line) let default profile selection complete, check for an existing Firefox and only then check that we're configure to show the profile manager on startup and show it then. Differential Revision: https://phabricator.services.mozilla.com/D23410
toolkit/profile/nsToolkitProfileService.cpp
toolkit/profile/nsToolkitProfileService.h
toolkit/xre/nsAppRunner.cpp
--- a/toolkit/profile/nsToolkitProfileService.cpp
+++ b/toolkit/profile/nsToolkitProfileService.cpp
@@ -836,18 +836,20 @@ nsToolkitProfileService::SelectStartupPr
   auto allocated = MakeUnique<UniqueFreePtr<char>[]>(argc);
 
   for (int i = 0; i < argc; i++) {
     allocated[i].reset(ToNewCString(aArgv[i]));
     argv[i] = allocated[i].get();
   }
   argv[argc] = nullptr;
 
+  bool wasDefault;
   nsresult rv = SelectStartupProfile(&argc, argv.get(), aIsResetting, aRootDir,
-                                     aLocalDir, aProfile, aDidCreate);
+                                     aLocalDir, aProfile, aDidCreate,
+                                     &wasDefault);
 
   // Since we were called outside of the normal startup path complete any
   // startup tasks.
   if (NS_SUCCEEDED(rv)) {
     CompleteStartup();
   }
 
   return rv;
@@ -869,23 +871,25 @@ nsToolkitProfileService::SelectStartupPr
  * returned in aProfile.
  * aDidCreate will be set to true if a new profile was created.
  * This function should be called once at startup and will fail if called again.
  * aArgv should be an array of aArgc + 1 strings, the last element being null.
  * Both aArgv and aArgc will be mutated.
  */
 nsresult nsToolkitProfileService::SelectStartupProfile(
     int* aArgc, char* aArgv[], bool aIsResetting, nsIFile** aRootDir,
-    nsIFile** aLocalDir, nsIToolkitProfile** aProfile, bool* aDidCreate) {
+    nsIFile** aLocalDir, nsIToolkitProfile** aProfile, bool* aDidCreate,
+    bool* aWasDefaultSelection) {
   if (mStartupProfileSelected) {
     return NS_ERROR_ALREADY_INITIALIZED;
   }
 
   mStartupProfileSelected = true;
   *aDidCreate = false;
+  *aWasDefaultSelection = false;
 
   nsresult rv;
   const char* arg;
 
   // Use the profile specified in the environment variables (generally from an
   // app initiated restart).
   nsCOMPtr<nsIFile> lf = GetFileFromEnv("XRE_PROFILE_PATH");
   if (lf) {
@@ -1087,30 +1091,31 @@ nsresult nsToolkitProfileService::Select
                "Error: argument --profilemanager is invalid when argument "
                "--osint is specified\n");
     return NS_ERROR_FAILURE;
   }
   if (ar == ARG_FOUND) {
     return NS_ERROR_SHOW_PROFILE_MANAGER;
   }
 
-  // We've been told not to use the selected profile automatically.
-  if (!mStartWithLast) {
-    return NS_ERROR_SHOW_PROFILE_MANAGER;
-  }
-
   // If this is a first run then create a new profile.
   if (mIsFirstRun) {
     if (aIsResetting) {
       // We don't want to create a fresh profile when we're attempting a
       // profile reset so just bail out here, the calling code will handle it.
       *aProfile = nullptr;
       return NS_OK;
     }
 
+    // If we're configured to always show the profile manager then don't create
+    // a new profile to use.
+    if (!mStartWithLast) {
+      return NS_ERROR_SHOW_PROFILE_MANAGER;
+    }
+
     if (mUseDedicatedProfile) {
       // This is the first run of a dedicated profile install. We have to decide
       // whether to use the default profile used by non-dedicated-profile
       // installs or to create a new profile.
 
       // Find what would have been the default profile for old installs.
       nsCOMPtr<nsIToolkitProfile> profile = mNormalDefault;
       if (mUseDevEditionProfile) {
@@ -1185,16 +1190,18 @@ nsresult nsToolkitProfileService::Select
   GetDefaultProfile(getter_AddRefs(mCurrent));
 
   // None of the profiles was marked as default (generally only happens if the
   // user modifies profiles.ini manually). Let the user choose.
   if (!mCurrent) {
     return NS_ERROR_SHOW_PROFILE_MANAGER;
   }
 
+  // Let the caller know that the profile was selected by default.
+  *aWasDefaultSelection = true;
   mStartupReason = NS_LITERAL_STRING("default");
 
   // Use the selected profile.
   mCurrent->GetRootDir(aRootDir);
   mCurrent->GetLocalDir(aLocalDir);
   NS_ADDREF(*aProfile = mCurrent);
 
   return NS_OK;
--- a/toolkit/profile/nsToolkitProfileService.h
+++ b/toolkit/profile/nsToolkitProfileService.h
@@ -71,17 +71,18 @@ class nsToolkitProfileFactory final : pu
 
 class nsToolkitProfileService final : public nsIToolkitProfileService {
  public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSITOOLKITPROFILESERVICE
 
   nsresult SelectStartupProfile(int* aArgc, char* aArgv[], bool aIsResetting,
                                 nsIFile** aRootDir, nsIFile** aLocalDir,
-                                nsIToolkitProfile** aProfile, bool* aDidCreate);
+                                nsIToolkitProfile** aProfile, bool* aDidCreate,
+                                bool* aWasDefaultSelection);
   nsresult CreateResetProfile(nsIToolkitProfile** aNewProfile);
   nsresult ApplyResetProfile(nsIToolkitProfile* aOldProfile);
   void CompleteStartup();
 
  private:
   friend class nsToolkitProfile;
   friend class nsToolkitProfileFactory;
   friend nsresult NS_NewToolkitProfileService(nsToolkitProfileService**);
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -1978,17 +1978,18 @@ static nsresult LockProfile(nsINativeApp
 // 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 nsresult SelectProfile(nsToolkitProfileService* aProfileSvc,
                               nsINativeAppSupport* aNative, nsIFile** aRootDir,
                               nsIFile** aLocalDir,
-                              nsIToolkitProfile** aProfile) {
+                              nsIToolkitProfile** aProfile,
+                              bool* aWasDefaultSelection) {
   StartupTimeline::Record(StartupTimeline::SELECT_PROFILE);
 
   nsresult rv;
 
   if (EnvHasValue("MOZ_RESET_PROFILE_RESTART")) {
     gDoProfileReset = true;
     gDoMigration = true;
     SaveToEnv("MOZ_RESET_PROFILE_RESTART=");
@@ -2026,17 +2027,17 @@ static nsresult SelectProfile(nsToolkitP
   if (ar == ARG_FOUND) {
     gDoMigration = true;
   }
 
   // Ask the profile manager to select the profile directories to use.
   bool didCreate = false;
   rv = aProfileSvc->SelectStartupProfile(&gArgc, gArgv, gDoProfileReset,
                                          aRootDir, aLocalDir, aProfile,
-                                         &didCreate);
+                                         &didCreate, aWasDefaultSelection);
 
   if (rv == NS_ERROR_SHOW_PROFILE_MANAGER) {
     return ShowProfileManager(aProfileSvc, aNative);
   }
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (didCreate) {
@@ -3910,19 +3911,21 @@ int XREMain::XRE_mainStartup(bool* aExit
                "your profile directory.\n");
   }
   if (NS_FAILED(rv)) {
     // We failed to choose or create profile - notify user and quit
     ProfileMissingDialog(mNativeApp);
     return 1;
   }
 
+  bool wasDefaultSelection;
   nsCOMPtr<nsIToolkitProfile> profile;
   rv = SelectProfile(mProfileSvc, mNativeApp, getter_AddRefs(mProfD),
-                     getter_AddRefs(mProfLD), getter_AddRefs(profile));
+                     getter_AddRefs(mProfLD), getter_AddRefs(profile),
+                     &wasDefaultSelection);
   if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS || rv == NS_ERROR_ABORT) {
     *aExitFlag = true;
     return 0;
   }
 
   if (NS_FAILED(rv)) {
     // We failed to choose or create profile - notify user and quit
     ProfileMissingDialog(mNativeApp);
@@ -4014,16 +4017,36 @@ int XREMain::XRE_mainStartup(bool* aExit
                  gRestartArgv, mAppData->version);
   if (EnvHasValue("MOZ_TEST_PROCESS_UPDATES")) {
     SaveToEnv("MOZ_TEST_PROCESS_UPDATES=");
     *aExitFlag = true;
     return 0;
   }
 #endif
 
+  // We now know there is no existing instance using the selected profile. If
+  // the profile wasn't selected by specific command line arguments and the
+  // user has chosen to show the profile manager on startup then do that.
+  if (wasDefaultSelection) {
+    bool useSelectedProfile;
+    rv = mProfileSvc->GetStartWithLastProfile(&useSelectedProfile);
+    NS_ENSURE_SUCCESS(rv, 1);
+
+    if (!useSelectedProfile) {
+      rv = ShowProfileManager(mProfileSvc, mNativeApp);
+      if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS || rv == NS_ERROR_ABORT) {
+        *aExitFlag = true;
+        return 0;
+      }
+      if (NS_FAILED(rv)) {
+        return 1;
+      }
+    }
+  }
+
   // We always want to lock the profile even if we're actually going to reset
   // it later.
   rv = LockProfile(mNativeApp, mProfD, mProfLD, profile,
                    getter_AddRefs(mProfileLock));
   if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS || rv == NS_ERROR_ABORT) {
     *aExitFlag = true;
     return 0;
   } else if (NS_FAILED(rv)) {