Backed out changeset 081a659775d3 (bug 1529879) for xpcshell perma failures. CLOSED TREE
authorRazvan Maries <rmaries@mozilla.com>
Thu, 18 Apr 2019 20:59:54 +0300
changeset 470044 313aab6b8a05c0cfd63bc11e4c514ff39f92ad13
parent 470043 5982eef0c2cb7ca74ab2461b5601cad68caf49c4
child 470045 e95b995fc086ba80fb30791901e634374d33eacf
push id112839
push userapavel@mozilla.com
push dateThu, 18 Apr 2019 21:50:57 +0000
treeherdermozilla-inbound@e0a826fcd85b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1529879
milestone68.0a1
backs out081a659775d32b167cb0e74b7fb0e7ab1aee7a62
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
Backed out changeset 081a659775d3 (bug 1529879) for xpcshell perma failures. CLOSED TREE
js/xpconnect/src/xpc.msg
toolkit/content/aboutProfiles.js
toolkit/content/aboutProfiles.xhtml
toolkit/locales/en-US/chrome/mozapps/profile/profileSelection.properties
toolkit/locales/en-US/toolkit/about/aboutProfiles.ftl
toolkit/profile/content/profileSelection.js
toolkit/profile/nsIToolkitProfileService.idl
toolkit/profile/nsToolkitProfileService.cpp
toolkit/profile/nsToolkitProfileService.h
toolkit/profile/xpcshell/head.js
toolkit/profile/xpcshell/test_check_backup.js
toolkit/profile/xpcshell/test_claim_locked.js
toolkit/profile/xpcshell/test_clean.js
toolkit/profile/xpcshell/test_conflict_installs.js
toolkit/profile/xpcshell/test_conflict_profiles.js
toolkit/profile/xpcshell/test_create_default.js
toolkit/profile/xpcshell/test_lock.js
toolkit/profile/xpcshell/test_missing_profilesini.js
toolkit/profile/xpcshell/test_new_default.js
toolkit/profile/xpcshell/test_previous_dedicated.js
toolkit/profile/xpcshell/test_profile_reset.js
toolkit/profile/xpcshell/test_remove.js
toolkit/profile/xpcshell/test_remove_default.js
toolkit/profile/xpcshell/test_select_default.js
toolkit/profile/xpcshell/test_select_environment.js
toolkit/profile/xpcshell/test_select_environment_named.js
toolkit/profile/xpcshell/test_select_missing.js
toolkit/profile/xpcshell/test_select_named.js
toolkit/profile/xpcshell/test_select_noname.js
toolkit/profile/xpcshell/test_select_profilemanager.js
toolkit/profile/xpcshell/test_single_profile_selected.js
toolkit/profile/xpcshell/test_single_profile_unselected.js
toolkit/profile/xpcshell/test_skip_locked_environment.js
toolkit/profile/xpcshell/test_snap.js
toolkit/profile/xpcshell/test_snap_empty.js
toolkit/profile/xpcshell/test_snatch_environment.js
toolkit/profile/xpcshell/test_snatch_environment_default.js
toolkit/profile/xpcshell/test_startswithlast.js
toolkit/profile/xpcshell/test_steal_inuse.js
toolkit/profile/xpcshell/test_update_selected_dedicated.js
toolkit/profile/xpcshell/test_update_unknown_dedicated.js
toolkit/profile/xpcshell/test_update_unselected_dedicated.js
toolkit/profile/xpcshell/test_use_dedicated.js
toolkit/profile/xpcshell/xpcshell.ini
toolkit/xre/ProfileReset.h
toolkit/xre/nsAppRunner.cpp
xpcom/base/ErrorList.py
--- a/js/xpconnect/src/xpc.msg
+++ b/js/xpconnect/src/xpc.msg
@@ -235,11 +235,8 @@ XPC_MSG_DEF(NS_ERROR_DOM_NOT_ALLOWED_ERR
 XPC_MSG_DEF(NS_ERROR_MALWARE_URI                      , "The URI is malware")
 XPC_MSG_DEF(NS_ERROR_PHISHING_URI                     , "The URI is phishing")
 XPC_MSG_DEF(NS_ERROR_TRACKING_URI                     , "The URI is tracking")
 XPC_MSG_DEF(NS_ERROR_UNWANTED_URI                     , "The URI is unwanted")
 XPC_MSG_DEF(NS_ERROR_BLOCKED_URI                      , "The URI is blocked")
 XPC_MSG_DEF(NS_ERROR_HARMFUL_URI                      , "The URI is harmful")
 XPC_MSG_DEF(NS_ERROR_FINGERPRINTING_URI               , "The URI is fingerprinting")
 XPC_MSG_DEF(NS_ERROR_CRYPTOMINING_URI                 , "The URI is cryptomining")
-
-/* Profile manager error codes */
-XPC_MSG_DEF(NS_ERROR_DATABASE_CHANGED                 , "Flushing the profiles to disk would have overwritten changes made elsewhere.")
--- a/toolkit/content/aboutProfiles.js
+++ b/toolkit/content/aboutProfiles.js
@@ -9,40 +9,16 @@ const {XPCOMUtils} = ChromeUtils.import(
 
 XPCOMUtils.defineLazyServiceGetter(
   this,
   "ProfileService",
   "@mozilla.org/toolkit/profile-service;1",
   "nsIToolkitProfileService"
 );
 
-async function flush() {
-  try {
-    ProfileService.flush();
-    refreshUI();
-  } catch (e) {
-    let [title, msg, button] = await document.l10n.formatValues([
-      { id: "profiles-flush-fail-title" },
-      { id: e.result == Cr.NS_ERROR_DATABASE_CHANGED ?
-                        "profiles-flush-conflict" :
-                        "profiles-flush-failed" },
-      { id: "profiles-flush-restart-button" },
-    ]);
-
-    const PS = Ci.nsIPromptService;
-    let result = Services.prompt.confirmEx(window, title, msg,
-                                          (PS.BUTTON_POS_0 * PS.BUTTON_TITLE_CANCEL) +
-                                          (PS.BUTTON_POS_1 * PS.BUTTON_TITLE_IS_STRING),
-                                          null, button, null, null, {});
-    if (result == 1) {
-      restart(false);
-    }
-  }
-}
-
 function refreshUI() {
   let parent = document.getElementById("profiles");
   while (parent.firstChild) {
     parent.firstChild.remove();
   }
 
   let defaultProfile;
   try {
@@ -229,17 +205,18 @@ async function renameProfile(profile) {
         { id: "profiles-invalid-profile-name-title" },
         { id: "profiles-invalid-profile-name", args: { name: newName } },
       ]);
 
       Services.prompt.alert(window, title, msg);
       return;
     }
 
-    flush();
+    ProfileService.flush();
+    refreshUI();
   }
 }
 
 async function removeProfile(profile) {
   let deleteFiles = false;
 
   if (profile.rootDir.exists()) {
     let [title, msg, dontDeleteStr, deleteStr] = await document.l10n.formatValues([
@@ -298,32 +275,34 @@ async function removeProfile(profile) {
         { id: "profiles-delete-profile-failed-title" },
         { id: "profiles-delete-profile-failed-message" },
     ]);
 
     Services.prompt.alert(window, title, msg);
     return;
   }
 
-  flush();
+  ProfileService.flush();
+  refreshUI();
 }
 
 async function defaultProfile(profile) {
   try {
     ProfileService.defaultProfile = profile;
-    flush();
+    ProfileService.flush();
   } catch (e) {
     // This can happen on dev-edition.
     let [title, msg] = await document.l10n.formatValues([
         { id: "profiles-cannot-set-as-default-title" },
         { id: "profiles-cannot-set-as-default-message" },
     ]);
 
     Services.prompt.alert(window, title, msg);
   }
+  refreshUI();
 }
 
 function openProfile(profile) {
   let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]
                      .createInstance(Ci.nsISupportsPRBool);
   Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart");
 
   if (cancelQuit.data) {
@@ -347,15 +326,10 @@ function restart(safeMode) {
   if (safeMode) {
     Services.startup.restartInSafeMode(flags);
   } else {
     Services.startup.quit(flags);
   }
 }
 
 window.addEventListener("DOMContentLoaded", function() {
-  if (ProfileService.isListOutdated) {
-    document.getElementById("owned").hidden = true;
-  } else {
-    document.getElementById("conflict").hidden = true;
-    refreshUI();
-  }
+  refreshUI();
 }, {once: true});
--- a/toolkit/content/aboutProfiles.xhtml
+++ b/toolkit/content/aboutProfiles.xhtml
@@ -18,23 +18,17 @@
   <body id="body" class="wide-container">
     <div id="action-box" class="notice-box">
       <h3 data-l10n-id="profiles-restart-title"></h3>
       <button id="restart-in-safe-mode-button" data-l10n-id="profiles-restart-in-safe-mode"></button>
       <button id="restart-button" data-l10n-id="profiles-restart-normal"></button>
     </div>
 
     <h1 data-l10n-id="profiles-title"></h1>
-
-    <div id="conflict">
-      <p data-l10n-id="profiles-conflict" />
-    </div>
-    <div id="owned">
-      <div data-l10n-id="profiles-subtitle"></div>
+    <div data-l10n-id="profiles-subtitle"></div>
 
-      <div>
-        <button id="create-button" data-l10n-id="profiles-create"></button>
-      </div>
+    <div>
+      <button id="create-button" data-l10n-id="profiles-create"></button>
+    </div>
 
-      <div id="profiles" class="tab"></div>
-    </div>
+    <div id="profiles" class="tab"></div>
   </body>
 </html>
--- a/toolkit/locales/en-US/chrome/mozapps/profile/profileSelection.properties
+++ b/toolkit/locales/en-US/chrome/mozapps/profile/profileSelection.properties
@@ -46,16 +46,8 @@ profileFinishTextMac=Click Done to creat
 profileMissing=Your %S profile cannot be loaded. It may be missing or inaccessible.
 profileMissingTitle=Profile Missing
 profileDeletionFailed=Profile couldn’t be deleted as it may be in use.
 profileDeletionFailedTitle=Deletion Failed
 
 # Profile reset
 # LOCALIZATION NOTE (resetBackupDirectory): Directory name for the profile directory backup created during reset. This directory is placed in a location users will see it (ie. their desktop). %S is the application name.
 resetBackupDirectory=Old %S Data
-
-flushFailTitle=Changes not saved
-# LOCALIZATION NOTE (conflictMessage): %1$S is brandProductName, %2$S is brandShortName.
-conflictMessage=Another copy of %1$S has made changes to profiles. You must restart %2$S before making more changes.
-flushFailMessage=An unexpected error has prevented your changes from being saved.
-# LOCALIZATION NOTE (flushFailButton): $S is brandShortName.
-flushFailRestartButton=Restart %S
-flushFailExitButton=Exit
--- a/toolkit/locales/en-US/toolkit/about/aboutProfiles.ftl
+++ b/toolkit/locales/en-US/toolkit/about/aboutProfiles.ftl
@@ -4,21 +4,16 @@
 
 
 profiles-title = About Profiles
 profiles-subtitle = This page helps you to manage your profiles. Each profile is a separate world which contains separate history, bookmarks, settings and add-ons.
 profiles-create = Create a New Profile
 profiles-restart-title = Restart
 profiles-restart-in-safe-mode = Restart with Add-ons Disabled…
 profiles-restart-normal = Restart normally…
-profiles-conflict = Another copy of { -brand-product-name } has made changes to profiles. You must restart { -brand-short-name } before making more changes.
-profiles-flush-fail-title = Changes not saved
-profiles-flush-conflict = { profiles-conflict }
-profiles-flush-failed = An unexpected error has prevented your changes from being saved.
-profiles-flush-restart-button = Restart { -brand-short-name }
 
 # Variables:
 #   $name (String) - Name of the profile
 profiles-name = Profile: { $name }
 profiles-is-default = Default Profile
 profiles-rootdir = Root Directory
 
 # localDir is used to show the directory corresponding to
--- a/toolkit/profile/content/profileSelection.js
+++ b/toolkit/profile/content/profileSelection.js
@@ -11,17 +11,16 @@ const C = Cc;
 const I = Ci;
 
 const ToolkitProfileService = "@mozilla.org/toolkit/profile-service;1";
 
 var gDialogParams;
 var gProfileManagerBundle;
 var gBrandBundle;
 var gProfileService;
-var gNeedsFlush = false;
 
 function startup() {
   try {
     gDialogParams = window.arguments[0].
       QueryInterface(I.nsIDialogParamBlock);
 
     gProfileService = C[ToolkitProfileService].getService(I.nsIToolkitProfileService);
 
@@ -55,58 +54,16 @@ function startup() {
   } catch (e) {
     window.close();
     throw (e);
   }
   document.addEventListener("dialogaccept", acceptDialog);
   document.addEventListener("dialogcancel", exitDialog);
 }
 
-function flush(cancelled) {
-  updateStartupPrefs();
-
-  gDialogParams.SetInt(1, document.getElementById("offlineState").checked ? 1 : 0);
-
-  if (gNeedsFlush) {
-    try {
-      gProfileService.flush();
-    } catch (e) {
-      let productName = gBrandBundle.getString("brandProductName");
-      let appName = gBrandBundle.getString("brandShortName");
-
-      let title = gProfileManagerBundle.getString("flushFailTitle");
-      let restartButton = gProfileManagerBundle.getFormattedString("flushFailRestartButton",
-                                                                  [appName]);
-      let exitButton = gProfileManagerBundle.getString("flushFailExitButton");
-
-      let message;
-      if (e.result == undefined) {
-        message = gProfileManagerBundle.getFormattedString("conflictMessage",
-                                                          [productName, appName]);
-      } else {
-        message = gProfileManagerBundle.getString("flushFailMessage");
-      }
-
-      const PS = Ci.nsIPromptService;
-      let result = Services.prompt.confirmEx(window, title, message,
-                                            (PS.BUTTON_POS_0 * PS.BUTTON_TITLE_IS_STRING) +
-                                            (PS.BUTTON_POS_1 * PS.BUTTON_TITLE_IS_STRING),
-                                            restartButton, exitButton, null, null, {});
-
-      gDialogParams.SetInt(0, result == 0 ? Ci.nsIToolkitProfileService.restart
-                                          : Ci.nsIToolkitProfileService.exit);
-      return;
-    }
-    gNeedsFlush = false;
-  }
-
-  gDialogParams.SetInt(0, cancelled ? Ci.nsIToolkitProfileService.exit
-                                    : Ci.nsIToolkitProfileService.launchWithProfile);
-}
-
 function acceptDialog(event) {
   var appName = gBrandBundle.getString("brandShortName");
 
   var profilesElement = document.getElementById("profiles");
   var selectedProfile = profilesElement.selectedItem;
   if (!selectedProfile) {
     var pleaseSelectTitle = gProfileManagerBundle.getString("pleaseSelectTitle");
     var pleaseSelect =
@@ -114,38 +71,36 @@ function acceptDialog(event) {
     Services.prompt.alert(window, pleaseSelectTitle, pleaseSelect);
     event.preventDefault();
     return;
   }
 
   gDialogParams.objects.insertElementAt(selectedProfile.profile.rootDir, 0);
   gDialogParams.objects.insertElementAt(selectedProfile.profile.localDir, 1);
 
-  if (gProfileService.defaultProfile != selectedProfile.profile) {
-    try {
-      gProfileService.defaultProfile = selectedProfile.profile;
-      gNeedsFlush = true;
-    } catch (e) {
-      // This can happen on dev-edition. We'll still restart with the selected
-      // profile based on the lock's directories.
-    }
+  try {
+    gProfileService.defaultProfile = selectedProfile.profile;
+  } catch (e) {
+    // This can happen on dev-edition. We'll still restart with the selected
+    // profile based on the lock's directories.
   }
-  flush(false);
+  updateStartupPrefs();
+
+  gDialogParams.SetInt(0, 1);
+  /* Bug 257777 */
+  gDialogParams.SetInt(1, document.getElementById("offlineState").checked ? 1 : 0);
 }
 
 function exitDialog() {
-  flush(true);
+  updateStartupPrefs();
 }
 
 function updateStartupPrefs() {
   var autoSelectLastProfile = document.getElementById("autoSelectLastProfile");
-  if (gProfileService.startWithLastProfile != autoSelectLastProfile.checked) {
-    gProfileService.startWithLastProfile = autoSelectLastProfile.checked;
-    gNeedsFlush = true;
-  }
+  gProfileService.startWithLastProfile = autoSelectLastProfile.checked;
 }
 
 // handle key event on listboxes
 function onProfilesKey(aEvent) {
   switch ( aEvent.keyCode ) {
   case KeyEvent.DOM_VK_BACK_SPACE:
     if (AppConstants.platform != "macosx")
       break;
@@ -179,18 +134,16 @@ function CreateProfile(aProfile) {
 
   var tooltiptext =
     gProfileManagerBundle.getFormattedString("profileTooltip", [aProfile.name, aProfile.rootDir.path]);
   listitem.setAttribute("tooltiptext", tooltiptext);
   listitem.profile = aProfile;
 
   profilesElement.ensureElementIsVisible(listitem);
   profilesElement.selectItem(listitem);
-
-  gNeedsFlush = true;
 }
 
 // rename the selected profile
 function RenameProfile() {
   var profilesElement = document.getElementById("profiles");
   var selectedItem = profilesElement.selectedItem;
   if (!selectedItem) {
     return false;
@@ -209,17 +162,16 @@ function RenameProfile() {
     newName = newName.value;
 
     // User hasn't changed the profile name. Treat as if cancel was pressed.
     if (newName == oldName)
       return false;
 
     try {
       selectedProfile.name = newName;
-      gNeedsFlush = true;
     } catch (e) {
       var alTitle = gProfileManagerBundle.getString("profileNameInvalidTitle");
       var alMsg = gProfileManagerBundle.getFormattedString("profileNameInvalid", [newName]);
       Services.prompt.alert(window, alTitle, alMsg);
       return false;
     }
 
     selectedItem.firstChild.setAttribute("value", newName);
@@ -263,17 +215,16 @@ function ConfirmDelete() {
       return false;
 
     if (buttonPressed == 2)
       deleteFiles = true;
   }
 
   try {
     selectedProfile.remove(deleteFiles);
-    gNeedsFlush = true;
   } catch (e) {
     let title = gProfileManagerBundle.getString("profileDeletionFailedTitle");
     let msg = gProfileManagerBundle.getString("profileDeletionFailed");
     Services.prompt.alert(window, title, msg);
 
     return true;
   }
 
--- a/toolkit/profile/nsIToolkitProfileService.idl
+++ b/toolkit/profile/nsIToolkitProfileService.idl
@@ -9,44 +9,32 @@ interface nsISimpleEnumerator;
 interface nsIFile;
 interface nsIToolkitProfile;
 interface nsIProfileLock;
 
 [scriptable, builtinclass, uuid(1947899b-f369-48fa-89da-f7c37bb1e6bc)]
 interface nsIToolkitProfileService : nsISupports
 {
     /**
-     * Tests whether the profile lists on disk have changed since they were
-     * loaded. When this is true attempts to flush changes to disk will fail.
-     */
-    [infallible] readonly attribute boolean isListOutdated;
-
-    /**
      * When a downgrade is detected UI is presented to the user to ask how to
      * proceed. These flags are used to pass some information to the UI.
      */
     cenum downgradeUIFlags: 8 {
         hasSync = 1,
     };
 
     /**
      * When a downgrade is detected UI is presented to the user to ask how to
      * proceed. These are the possible options the user can choose.
      */
     cenum downgradeUIChoice: 8 {
         quit = 0,
         createNewProfile = 1,
     };
 
-    cenum profileManagerResult: 8 {
-        exit = 0,
-        launchWithProfile = 1,
-        restart = 2,
-    };
-
     attribute boolean startWithLastProfile;
 
     readonly attribute nsISimpleEnumerator /*nsIToolkitProfile*/ profiles;
 
     /**
      * The profile currently in use if it is a named profile. This will return
      * null if the current profile path doesn't match a profile in the database.
      */
@@ -135,18 +123,16 @@ interface nsIToolkitProfileService : nsI
 
     /**
      * Returns the number of profiles.
      * @return the number of profiles.
      */
     readonly attribute unsigned long profileCount;
 
     /**
-     * Flush the profiles list file. This will fail with
-     * NS_ERROR_DATABASE_CHANGED if the files on disk have changed since the
-     * profiles were loaded.
+     * Flush the profiles list file.
      */
     void flush();
 };
 
 %{C++
 #define NS_PROFILESERVICE_CONTRACTID "@mozilla.org/toolkit/profile-service;1"
 %}
--- a/toolkit/profile/nsToolkitProfileService.cpp
+++ b/toolkit/profile/nsToolkitProfileService.cpp
@@ -41,17 +41,16 @@
 #include "nsReadableUtils.h"
 #include "nsNativeCharsetUtils.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Sprintf.h"
 #include "nsPrintfCString.h"
 #include "mozilla/UniquePtr.h"
 #include "nsIToolkitShellService.h"
 #include "mozilla/Telemetry.h"
-#include "nsProxyRelease.h"
 
 using namespace mozilla;
 
 #define DEV_EDITION_NAME "dev-edition-default"
 #define DEFAULT_NAME "default"
 #define COMPAT_FILE NS_LITERAL_STRING("compatibility.ini")
 #define PROFILE_DB_VERSION "2"
 #define INSTALL_PREFIX "Install"
@@ -78,62 +77,16 @@ static bool GetStrings(const char* aStri
  */
 nsTArray<UniquePtr<KeyValue>> GetSectionStrings(nsINIParser* aParser,
                                                 const char* aSection) {
   nsTArray<UniquePtr<KeyValue>> result;
   aParser->GetStrings(aSection, &GetStrings, &result);
   return result;
 }
 
-void RemoveProfileFiles(nsIToolkitProfile* aProfile, bool aInBackground) {
-  nsCOMPtr<nsIFile> rootDir;
-  aProfile->GetRootDir(getter_AddRefs(rootDir));
-  nsCOMPtr<nsIFile> localDir;
-  aProfile->GetLocalDir(getter_AddRefs(localDir));
-
-  // Just lock the directories, don't mark the profile as locked or the lock
-  // will attempt to release its reference to the profile on the background
-  // thread which will assert.
-  nsCOMPtr<nsIProfileLock> lock;
-  nsresult rv =
-      NS_LockProfilePath(rootDir, localDir, nullptr, getter_AddRefs(lock));
-  NS_ENSURE_SUCCESS_VOID(rv);
-
-  nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction(
-      "nsToolkitProfile::RemoveProfileFiles",
-      [rootDir, localDir, lock]() mutable {
-        bool equals;
-        nsresult rv = rootDir->Equals(localDir, &equals);
-        // The root dir might contain the temp dir, so remove
-        // the temp dir first.
-        if (NS_SUCCEEDED(rv) && !equals) {
-          localDir->Remove(true);
-        }
-
-        // Ideally we'd unlock after deleting but since the lock is a file
-        // in the profile we must unlock before removing.
-        lock->Unlock();
-        // nsIProfileLock is not threadsafe so release our reference to it on
-        // the main thread.
-        NS_ReleaseOnMainThreadSystemGroup(
-            "nsToolkitProfile::RemoveProfileFiles::Unlock", lock.forget());
-
-        rv = rootDir->Remove(true);
-        NS_ENSURE_SUCCESS_VOID(rv);
-      });
-
-  if (aInBackground) {
-    nsCOMPtr<nsIEventTarget> target =
-        do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
-    target->Dispatch(runnable, NS_DISPATCH_NORMAL);
-  } else {
-    runnable->Run();
-  }
-}
-
 nsToolkitProfile::nsToolkitProfile(const nsACString& aName, nsIFile* aRootDir,
                                    nsIFile* aLocalDir, bool aFromDB)
     : mName(aName),
       mRootDir(aRootDir),
       mLocalDir(aLocalDir),
       mLock(nullptr),
       mIndex(0),
       mSection("Profile") {
@@ -220,17 +173,48 @@ nsresult nsToolkitProfile::RemoveInterna
 
   if (mLock) return NS_ERROR_FILE_IS_LOCKED;
 
   if (!isInList()) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   if (aRemoveFiles) {
-    RemoveProfileFiles(this, aInBackground);
+    // Check if another instance is using this profile.
+    nsCOMPtr<nsIProfileLock> lock;
+    nsresult rv = Lock(nullptr, getter_AddRefs(lock));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    nsCOMPtr<nsIFile> rootDir(mRootDir);
+    nsCOMPtr<nsIFile> localDir(mLocalDir);
+
+    nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction(
+        "nsToolkitProfile::RemoveInternal", [rootDir, localDir, lock]() {
+          bool equals;
+          nsresult rv = rootDir->Equals(localDir, &equals);
+          // The root dir might contain the temp dir, so remove
+          // the temp dir first.
+          if (NS_SUCCEEDED(rv) && !equals) {
+            localDir->Remove(true);
+          }
+
+          // Ideally we'd unlock after deleting but since the lock is a file
+          // in the profile we must unlock before removing.
+          lock->Unlock();
+
+          rootDir->Remove(true);
+        });
+
+    if (aInBackground) {
+      nsCOMPtr<nsIEventTarget> target =
+          do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
+      target->Dispatch(runnable, NS_DISPATCH_NORMAL);
+    } else {
+      runnable->Run();
+    }
   }
 
   nsINIParser* db = &nsToolkitProfileService::gService->mProfileDB;
   db->DeleteSection(mSection.get());
 
   // We make some assumptions that the profile's index in the database is based
   // on its position in the linked list. Removing a profile means we have to fix
   // the index of later profiles in the list. The easiest way to do that is just
@@ -384,23 +368,17 @@ nsToolkitProfileService::nsToolkitProfil
 #ifdef MOZ_DEDICATED_PROFILES
       mUseDedicatedProfile(!IsSnapEnvironment()),
 #else
       mUseDedicatedProfile(false),
 #endif
       mCreatedAlternateProfile(false),
       mStartupReason(NS_LITERAL_STRING("unknown")),
       mMaybeLockProfile(false),
-      mUpdateChannel(NS_STRINGIFY(MOZ_UPDATE_CHANNEL)),
-      mProfileDBExists(false),
-      mProfileDBFileSize(0),
-      mProfileDBModifiedTime(0),
-      mInstallDBExists(false),
-      mInstallDBFileSize(0),
-      mInstallDBModifiedTime(0) {
+      mUpdateChannel(NS_STRINGIFY(MOZ_UPDATE_CHANNEL)) {
 #ifdef MOZ_DEV_EDITION
   mUseDevEditionProfile = true;
 #endif
   gService = this;
 }
 
 nsToolkitProfileService::~nsToolkitProfileService() {
   gService = nullptr;
@@ -423,22 +401,16 @@ void nsToolkitProfileService::CompleteSt
     }
 
     bool isDefaultApp;
     nsresult rv = shell->IsDefaultApplication(&isDefaultApp);
     NS_ENSURE_SUCCESS_VOID(rv);
 
     if (isDefaultApp) {
       mProfileDB.SetString(mInstallSection.get(), "Locked", "1");
-
-      // There is a very small chance that this could fail if something else
-      // overwrote the profiles database since we started up, probably less than
-      // a second ago. There isn't really a sane response here, all the other
-      // profile changes are already flushed so whether we fail to flush here or
-      // force quit the app makes no difference.
       Flush();
     }
   }
 }
 
 // Tests whether the passed profile was last used by this install.
 bool nsToolkitProfileService::IsProfileForCurrentInstall(
     nsIToolkitProfile* aProfile) {
@@ -507,32 +479,30 @@ bool nsToolkitProfileService::IsProfileF
  *
  * We won't attempt to use the profile if it was last used by a different
  * install.
  *
  * If the profile is currently in use by an install that was either the OS
  * default install or the profile has been explicitely chosen by some other
  * means then we won't use it.
  *
- * aResult will be set to true if we chose to make the profile the new dedicated
- * default.
+ * Returns true if we chose to make the profile the new dedicated default.
  */
-nsresult nsToolkitProfileService::MaybeMakeDefaultDedicatedProfile(
-    nsIToolkitProfile* aProfile, bool* aResult) {
+bool nsToolkitProfileService::MaybeMakeDefaultDedicatedProfile(
+    nsIToolkitProfile* aProfile) {
   nsresult rv;
-  *aResult = false;
 
   // If the profile was last used by a different install then we won't use it.
   if (!IsProfileForCurrentInstall(aProfile)) {
-    return NS_OK;
+    return false;
   }
 
   nsCString descriptor;
   rv = GetProfileDescriptor(aProfile, descriptor, nullptr);
-  NS_ENSURE_SUCCESS(rv, rv);
+  NS_ENSURE_SUCCESS(rv, false);
 
   // Get a list of all the installs.
   nsTArray<nsCString> installs = GetKnownInstalls();
 
   // Cache the installs that use the profile.
   nsTArray<nsCString> inUseInstalls;
 
   // See if the profile is already in use by an install that hasn't locked it.
@@ -549,17 +519,17 @@ nsresult nsToolkitProfileService::MaybeM
     if (!descriptor.Equals(path)) {
       continue;
     }
 
     // Is this profile locked to this other install?
     nsCString isLocked;
     rv = mProfileDB.GetString(install.get(), "Locked", isLocked);
     if (NS_SUCCEEDED(rv) && isLocked.Equals("1")) {
-      return NS_OK;
+      return false;
     }
 
     inUseInstalls.AppendElement(install);
   }
 
   // At this point we've decided to take the profile. Strip it from other
   // installs.
   for (uint32_t i = 0; i < inUseInstalls.Length(); i++) {
@@ -572,71 +542,23 @@ nsresult nsToolkitProfileService::MaybeM
   SetDefaultProfile(aProfile);
 
   // SetDefaultProfile will have locked this profile to this install so no
   // other installs will steal it, but this was auto-selected so we want to
   // unlock it so that other installs can potentially take it.
   mProfileDB.DeleteString(mInstallSection.get(), "Locked");
 
   // Persist the changes.
-  rv = Flush();
-  NS_ENSURE_SUCCESS(rv, rv);
+  Flush();
 
   // Once XPCOM is available check if this is the default application and if so
   // lock the profile again.
   mMaybeLockProfile = true;
-  *aResult = true;
 
-  return NS_OK;
-}
-
-bool
-IsFileOutdated(nsIFile* aFile, bool aExists, PRTime aLastModified,
-               int64_t aLastSize) {
-  bool exists;
-  nsresult rv = aFile->Exists(&exists);
-  if (NS_FAILED(rv) || exists != aExists) {
-    return true;
-  }
-
-  if (!exists) {
-    return false;
-  }
-
-  int64_t size;
-  rv = aFile->GetFileSize(&size);
-  if (NS_FAILED(rv) || size != aLastSize) {
-    return true;
-  }
-
-  PRTime time;
-  rv = aFile->GetLastModifiedTime(&time);
-  if (NS_FAILED(rv) || time != aLastModified) {
-    return true;
-  }
-
-  return false;
-}
-
-NS_IMETHODIMP
-nsToolkitProfileService::GetIsListOutdated(bool *aResult) {
-  if (IsFileOutdated(mProfileDBFile, mProfileDBExists, mProfileDBModifiedTime,
-                     mProfileDBFileSize)) {
-    *aResult = true;
-    return NS_OK;
-  }
-
-  if (IsFileOutdated(mInstallDBFile, mInstallDBExists, mInstallDBModifiedTime,
-                     mInstallDBFileSize)) {
-    *aResult = true;
-    return NS_OK;
-  }
-
-  *aResult = false;
-  return NS_OK;
+  return true;
 }
 
 struct ImportInstallsClosure {
   nsINIParser* backupData;
   nsINIParser* profileDB;
 };
 
 static bool ImportInstalls(const char* aSection, void* aClosure) {
@@ -678,29 +600,21 @@ nsresult nsToolkitProfileService::Init()
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = mAppData->Clone(getter_AddRefs(mInstallDBFile));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = mInstallDBFile->AppendNative(NS_LITERAL_CSTRING("installs.ini"));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  rv = mInstallDBFile->IsFile(&mInstallDBExists);
-  if (NS_SUCCEEDED(rv) && mInstallDBExists) {
-    mInstallDBFile->GetFileSize(&mInstallDBFileSize);
-    mInstallDBFile->GetLastModifiedTime(&mInstallDBModifiedTime);
-  }
-
   nsAutoCString buffer;
 
-  rv = mProfileDBFile->IsFile(&mProfileDBExists);
-  if (NS_SUCCEEDED(rv) && mProfileDBExists) {
-    mProfileDBFile->GetFileSize(&mProfileDBFileSize);
-    mProfileDBFile->GetLastModifiedTime(&mProfileDBModifiedTime);
-
+  bool exists;
+  rv = mProfileDBFile->IsFile(&exists);
+  if (NS_SUCCEEDED(rv) && exists) {
     rv = mProfileDB.Init(mProfileDBFile);
     // Init does not fail on parsing errors, only on OOM/really unexpected
     // conditions.
     if (NS_FAILED(rv)) {
       return rv;
     }
 
     rv = mProfileDB.GetString("General", "StartWithLastProfile", buffer);
@@ -709,17 +623,19 @@ nsresult nsToolkitProfileService::Init()
     }
 
     rv = mProfileDB.GetString("General", "Version", buffer);
     if (NS_FAILED(rv)) {
       // This is a profiles.ini written by an older version. We must restore
       // any install data from the backup.
       nsINIParser installDB;
 
-      if (mInstallDBExists && NS_SUCCEEDED(installDB.Init(mInstallDBFile))) {
+      rv = mInstallDBFile->IsFile(&exists);
+      if (NS_SUCCEEDED(rv) && exists &&
+          NS_SUCCEEDED(installDB.Init(mInstallDBFile))) {
         // There is install data to import.
         ImportInstallsClosure closure = {&installDB, &mProfileDB};
         installDB.GetSections(&ImportInstalls, &closure);
       }
 
       rv = mProfileDB.SetString("General", "Version", PROFILE_DB_VERSION);
       NS_ENSURE_SUCCESS(rv, rv);
     }
@@ -1138,20 +1054,17 @@ nsresult nsToolkitProfileService::Select
 
     if (profile && mIsFirstRun && mUseDedicatedProfile) {
       if (profile ==
           (mUseDevEditionProfile ? mDevEditionDefault : mNormalDefault)) {
         // This is the first run of a dedicated profile build where the selected
         // profile is the previous default so we should either make it the
         // default profile for this install or push the user to a new profile.
 
-        bool result;
-        rv = MaybeMakeDefaultDedicatedProfile(profile, &result);
-        NS_ENSURE_SUCCESS(rv, rv);
-        if (result) {
+        if (MaybeMakeDefaultDedicatedProfile(profile)) {
           mStartupReason = NS_LITERAL_STRING("restart-claimed-default");
 
           mCurrent = profile;
         } else {
           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.
@@ -1160,18 +1073,17 @@ nsresult nsToolkitProfileService::Select
           }
 
           rv = CreateDefaultProfile(getter_AddRefs(mCurrent));
           if (NS_FAILED(rv)) {
             *aProfile = nullptr;
             return rv;
           }
 
-          rv = Flush();
-          NS_ENSURE_SUCCESS(rv, rv);
+          Flush();
 
           mStartupReason = NS_LITERAL_STRING("restart-skipped-default");
           *aDidCreate = true;
           mCreatedAlternateProfile = true;
         }
 
         NS_IF_ADDREF(*aProfile = mCurrent);
         mCurrent->GetRootDir(aRootDir);
@@ -1265,20 +1177,24 @@ nsresult nsToolkitProfileService::Select
       // main profile directory.
       rv = CreateProfile(lf, nsDependentCSubstring(arg, delim),
                          getter_AddRefs(profile));
     } else {
       rv = CreateProfile(nullptr, nsDependentCString(arg),
                          getter_AddRefs(profile));
     }
     // Some pathological arguments can make it this far
-    if (NS_FAILED(rv) || NS_FAILED(Flush())) {
+    if (NS_FAILED(rv)) {
       PR_fprintf(PR_STDERR, "Error creating profile.\n");
+      return rv;
     }
-    return NS_ERROR_ABORT;
+    rv = NS_ERROR_ABORT;
+    Flush();
+
+    return rv;
   }
 
   // Check the -p command line argument. It either accepts a profile name and
   // uses that named profile or without a name it opens the profile manager.
   ar = CheckArg(*aArgc, aArgv, "p", &arg);
   if (ar == ARG_BAD) {
     ar = CheckArg(*aArgc, aArgv, "osint");
     if (ar == ARG_FOUND) {
@@ -1362,20 +1278,17 @@ nsresult nsToolkitProfileService::Select
         bool exists;
         rv = compat->Exists(&exists);
         NS_ENSURE_SUCCESS(rv, rv);
 
         // If the file is missing then either this is an empty profile (likely
         // generated by bug 1518591) or it is from an ancient version. We'll opt
         // to leave it for older versions in this case.
         if (exists) {
-          bool result;
-          rv = MaybeMakeDefaultDedicatedProfile(profile, &result);
-          NS_ENSURE_SUCCESS(rv, rv);
-          if (result) {
+          if (MaybeMakeDefaultDedicatedProfile(profile)) {
             mStartupReason = NS_LITERAL_STRING("firstrun-claimed-default");
 
             mCurrent = profile;
             rootDir.forget(aRootDir);
             profile->GetLocalDir(aLocalDir);
             profile.forget(aProfile);
             return NS_OK;
           }
@@ -1398,18 +1311,17 @@ nsresult nsToolkitProfileService::Select
       if ((mUseDedicatedProfile || mUseDevEditionProfile) &&
           mProfiles.getFirst() == mProfiles.getLast()) {
         nsCOMPtr<nsIToolkitProfile> newProfile;
         CreateProfile(nullptr, NS_LITERAL_CSTRING(DEFAULT_NAME),
                       getter_AddRefs(newProfile));
         SetNormalDefault(newProfile);
       }
 
-      rv = Flush();
-      NS_ENSURE_SUCCESS(rv, rv);
+      Flush();
 
       if (mCreatedAlternateProfile) {
         mStartupReason = NS_LITERAL_STRING("firstrun-skipped-default");
       } else {
         mStartupReason = NS_LITERAL_STRING("firstrun-created-default");
       }
 
       // Use the new profile.
@@ -1460,21 +1372,22 @@ nsresult nsToolkitProfileService::Create
   } else {
     newProfileName.AssignLiteral("default-");
   }
   newProfileName.AppendPrintf("%" PRId64, PR_Now() / 1000);
   nsresult rv = CreateProfile(nullptr,  // choose a default dir for us
                               newProfileName, getter_AddRefs(newProfile));
   if (NS_FAILED(rv)) return rv;
 
+  rv = Flush();
+  if (NS_FAILED(rv)) return rv;
+
   mCurrent = newProfile;
   newProfile.forget(aNewProfile);
 
-  // Don't flush the changes yet. That will happen once the migration
-  // successfully completes.
   return NS_OK;
 }
 
 /**
  * This is responsible for deleting the old profile, copying its name to the
  * current profile and if the old profile was default making the new profile
  * default as well.
  */
@@ -1501,35 +1414,25 @@ nsresult nsToolkitProfileService::ApplyR
       mProfileDB.DeleteString(mInstallSection.get(), "Locked");
     }
   }
 
   nsCString name;
   nsresult rv = aOldProfile->GetName(name);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // Don't remove the old profile's files until after we've successfully flushed
-  // the profile changes to disk.
   rv = aOldProfile->Remove(false);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Switching the name will make this the default for dev-edition if
   // appropriate.
   rv = mCurrent->SetName(name);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  rv = Flush();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Now that the profile changes are flushed, try to remove the old profile's
-  // files. If we fail the worst that will happen is that an orphan directory is
-  // left. Let this run in the background while we start up.
-  RemoveProfileFiles(aOldProfile, true);
-
-  return NS_OK;
+  return Flush();
 }
 
 NS_IMETHODIMP
 nsToolkitProfileService::GetProfileByName(const nsACString& aName,
                                           nsIToolkitProfile** aResult) {
   for (RefPtr<nsToolkitProfile> profile : mProfiles) {
     if (profile->mName.Equals(aName)) {
       NS_ADDREF(*aResult = profile);
@@ -1788,20 +1691,16 @@ nsToolkitProfileService::GetProfileCount
     (*aResult)++;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsToolkitProfileService::Flush() {
-  if (GetIsListOutdated()) {
-    return NS_ERROR_DATABASE_CHANGED;
-  }
-
   nsresult rv;
 
   // If we aren't using dedicated profiles then nothing about the list of
   // installs can have changed, so no need to update the backup.
   if (mUseDedicatedProfile) {
     // Export the installs to the backup.
     nsTArray<nsCString> installs = GetKnownInstalls();
 
@@ -1835,37 +1734,28 @@ nsToolkitProfileService::Flush() {
 
       uint32_t length = data.Length();
       if (fwrite(data.get(), sizeof(char), length, writeFile) != length) {
         fclose(writeFile);
         return NS_ERROR_UNEXPECTED;
       }
 
       fclose(writeFile);
-
-      mInstallDBExists = true;
-      mInstallDBFile->GetFileSize(&mInstallDBFileSize);
-      mInstallDBFile->GetLastModifiedTime(&mInstallDBModifiedTime);
     } else {
       rv = mInstallDBFile->Remove(false);
       if (NS_FAILED(rv) && rv != NS_ERROR_FILE_TARGET_DOES_NOT_EXIST &&
           rv != NS_ERROR_FILE_NOT_FOUND) {
         return rv;
       }
-      mInstallDBExists = false;
     }
   }
 
   rv = mProfileDB.WriteToFile(mProfileDBFile);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  mProfileDBExists = true;
-  mProfileDBFile->GetFileSize(&mProfileDBFileSize);
-  mProfileDBFile->GetLastModifiedTime(&mProfileDBModifiedTime);
-
   return NS_OK;
 }
 
 NS_IMPL_ISUPPORTS(nsToolkitProfileFactory, nsIFactory)
 
 NS_IMETHODIMP
 nsToolkitProfileFactory::CreateInstance(nsISupports* aOuter, const nsID& aIID,
                                         void** aResult) {
--- a/toolkit/profile/nsToolkitProfileService.h
+++ b/toolkit/profile/nsToolkitProfileService.h
@@ -97,18 +97,17 @@ class nsToolkitProfileService final : pu
   nsresult CreateTimesInternal(nsIFile* profileDir);
   void GetProfileByDir(nsIFile* aRootDir, nsIFile* aLocalDir,
                        nsIToolkitProfile** aResult);
 
   nsresult GetProfileDescriptor(nsIToolkitProfile* aProfile,
                                 nsACString& aDescriptor, bool* aIsRelative);
   bool IsProfileForCurrentInstall(nsIToolkitProfile* aProfile);
   void ClearProfileFromOtherInstalls(nsIToolkitProfile* aProfile);
-  nsresult MaybeMakeDefaultDedicatedProfile(nsIToolkitProfile* aProfile,
-                                            bool* aResult);
+  bool MaybeMakeDefaultDedicatedProfile(nsIToolkitProfile* aProfile);
   bool IsSnapEnvironment();
   nsresult CreateDefaultProfile(nsIToolkitProfile** aResult);
   void SetNormalDefault(nsIToolkitProfile* aProfile);
 
   // Returns the known install hashes from the installs database. Modifying the
   // installs database is safe while iterating the returned array.
   nsTArray<nsCString> GetKnownInstalls();
 
@@ -145,27 +144,20 @@ class nsToolkitProfileService final : pu
   bool mUseDevEditionProfile;
   // True if this install should use a dedicated default profile.
   const bool mUseDedicatedProfile;
   // True if during startup no dedicated profile was already selected, an old
   // default profile existed but was rejected so a new profile was created.
   bool mCreatedAlternateProfile;
   nsString mStartupReason;
   bool mMaybeLockProfile;
+
   // Holds the current application update channel. This is only really held
   // so it can be overriden in tests.
   nsCString mUpdateChannel;
-  // Keep track of some attributes of the databases so we can tell if another
-  // process has changed them.
-  bool mProfileDBExists;
-  int64_t mProfileDBFileSize;
-  PRTime mProfileDBModifiedTime;
-  bool mInstallDBExists;
-  int64_t mInstallDBFileSize;
-  PRTime mInstallDBModifiedTime;
 
   static nsToolkitProfileService* gService;
 
   class ProfileEnumerator final : public nsSimpleEnumerator {
    public:
     NS_DECL_NSISIMPLEENUMERATOR
 
     const nsID& DefaultInterface() override {
--- a/toolkit/profile/xpcshell/head.js
+++ b/toolkit/profile/xpcshell/head.js
@@ -1,10 +1,11 @@
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
 
 const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 const { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
 const { FileUtils } = ChromeUtils.import("resource://gre/modules/FileUtils.jsm");
 const { OS } = ChromeUtils.import("resource://gre/modules/osfile.jsm");
 const { AppConstants } = ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 const { TelemetryTestUtils } = ChromeUtils.import("resource://testing-common/TelemetryTestUtils.jsm");
 
--- a/toolkit/profile/xpcshell/test_check_backup.js
+++ b/toolkit/profile/xpcshell/test_check_backup.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests that when the profiles DB is missing the install data we reload it.
  */
 
 add_task(async () => {
   let hash = xreDirProvider.getInstallHash();
 
   let profileData = {
--- a/toolkit/profile/xpcshell/test_claim_locked.js
+++ b/toolkit/profile/xpcshell/test_claim_locked.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests that an old-style default profile already locked to a different install
  * isn't claimed by this install.
  */
 
 add_task(async () => {
   let defaultProfile = makeRandomProfileDir("default");
 
--- a/toolkit/profile/xpcshell/test_clean.js
+++ b/toolkit/profile/xpcshell/test_clean.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests from a clean state.
  * Then does some testing that creating new profiles and marking them as
  * selected works.
  */
 
 add_task(async () => {
   let service = getProfileService();
deleted file mode 100644
--- a/toolkit/profile/xpcshell/test_conflict_installs.js
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/*
- * Tests that the profile service refuses to flush when the install.ini file
- * has been modified.
- */
-
-function check_unchanged(service) {
-  Assert.ok(!service.isListOutdated, "Should not have detected a modification.");
-  try {
-    service.flush();
-    Assert.ok(true, "Should have flushed.");
-  } catch (e) {
-    Assert.ok(false, "Should have succeeded flushing.");
-  }
-}
-
-function check_outdated(service) {
-  Assert.ok(service.isListOutdated, "Should have detected a modification.");
-  try {
-    service.flush();
-    Assert.ok(false, "Should have failed to flush.");
-  } catch (e) {
-    Assert.equal(e.result, Cr.NS_ERROR_DATABASE_CHANGED, "Should have refused to flush.");
-  }
-}
-
-add_task(async () => {
-  let service = getProfileService();
-
-  Assert.ok(!service.isListOutdated, "Should not be modified yet.");
-
-  let installsini = gDataHome.clone();
-  installsini.append("installs.ini");
-
-  Assert.ok(!installsini.exists(), "File should not exist yet.");
-  installsini.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644);
-  check_outdated(service);
-
-  installsini.remove(false);
-  // We have to do profile selection to actually have any install data.
-  selectStartupProfile();
-  check_unchanged(service);
-
-  let oldTime = installsini.lastModifiedTime;
-  installsini.lastModifiedTime = oldTime - 10000;
-  check_outdated(service);
-
-  // We can't reset the modification time back to exactly what it was, so I
-  // guess we can't do much more here :(
-});
deleted file mode 100644
--- a/toolkit/profile/xpcshell/test_conflict_profiles.js
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/*
- * Tests that the profile service refuses to flush when the profiles.ini file
- * has been modified.
- */
-
-function check_unchanged(service) {
-  Assert.ok(!service.isListOutdated, "Should not have detected a modification.");
-  try {
-    service.flush();
-    Assert.ok(true, "Should have flushed.");
-  } catch (e) {
-    Assert.ok(false, "Should have succeeded flushing.");
-  }
-}
-
-function check_outdated(service) {
-  Assert.ok(service.isListOutdated, "Should have detected a modification.");
-  try {
-    service.flush();
-    Assert.ok(false, "Should have failed to flush.");
-  } catch (e) {
-    Assert.equal(e.result, Cr.NS_ERROR_DATABASE_CHANGED, "Should have refused to flush.");
-  }
-}
-
-add_task(async () => {
-  let service = getProfileService();
-
-  Assert.ok(!service.isListOutdated, "Should not be modified yet.");
-
-  let profilesini = gDataHome.clone();
-  profilesini.append("profiles.ini");
-
-  Assert.ok(!profilesini.exists(), "File should not exist yet.");
-  profilesini.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644);
-  check_outdated(service);
-
-  profilesini.remove(false);
-  check_unchanged(service);
-
-  let oldTime = profilesini.lastModifiedTime;
-  profilesini.lastModifiedTime = oldTime - 10000;
-  check_outdated(service);
-
-  // We can't reset the modification time back to exactly what it was, so I
-  // guess we can't do much more here :(
-});
--- a/toolkit/profile/xpcshell/test_create_default.js
+++ b/toolkit/profile/xpcshell/test_create_default.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests that from an empty database a default profile is created.
  */
 
 add_task(async () => {
   let service = getProfileService();
   let { profile, didCreate } = selectStartupProfile();
 
--- a/toolkit/profile/xpcshell/test_lock.js
+++ b/toolkit/profile/xpcshell/test_lock.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests that when the default application claims the old-style default profile
  * it locks it to itself.
  */
 
 add_task(async () => {
   gIsDefaultApp = true;
   let defaultProfile = makeRandomProfileDir("default");
--- a/toolkit/profile/xpcshell/test_missing_profilesini.js
+++ b/toolkit/profile/xpcshell/test_missing_profilesini.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /**
  * When profiles.ini is missing there isn't any point in restoring from any
  * installs.ini, the profiles it refers to are gone anyway.
  */
 
 add_task(async () => {
   let hash = xreDirProvider.getInstallHash();
 
--- a/toolkit/profile/xpcshell/test_new_default.js
+++ b/toolkit/profile/xpcshell/test_new_default.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests that an old-style default profile previously used by this build gets
  * updated to a dedicated profile for this build.
  */
 
 add_task(async () => {
   let mydefaultProfile = makeRandomProfileDir("mydefault");
   let defaultProfile = makeRandomProfileDir("default");
--- a/toolkit/profile/xpcshell/test_previous_dedicated.js
+++ b/toolkit/profile/xpcshell/test_previous_dedicated.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /**
  * If install.ini lists a default profile for this build but that profile no
  * longer exists don't try to steal the old-style default even if it was used
  * by this build. It means this install has previously used dedicated profiles.
  */
 
 add_task(async () => {
   let hash = xreDirProvider.getInstallHash();
--- a/toolkit/profile/xpcshell/test_profile_reset.js
+++ b/toolkit/profile/xpcshell/test_profile_reset.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests that from an empty database profile reset doesn't create a new profile.
  */
 
 add_task(async () => {
   let service = getProfileService();
 
   let { profile, didCreate } = selectStartupProfile([], true);
--- a/toolkit/profile/xpcshell/test_remove.js
+++ b/toolkit/profile/xpcshell/test_remove.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests adding and removing functions correctly.
  */
 
 function compareLists(service, knownProfiles) {
   Assert.equal(service.profileCount, knownProfiles.length, "profileCount should be correct.");
   let serviceProfiles = Array.from(service.profiles);
   Assert.equal(serviceProfiles.length, knownProfiles.length, "Enumerator length should be correct.");
--- a/toolkit/profile/xpcshell/test_remove_default.js
+++ b/toolkit/profile/xpcshell/test_remove_default.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /**
  * Tests that calling nsIToolkitProfile.remove on the default profile correctly
  * removes the profile.
  */
 
 add_task(async () => {
   let hash = xreDirProvider.getInstallHash();
   let defaultProfile = makeRandomProfileDir("default");
--- a/toolkit/profile/xpcshell/test_select_default.js
+++ b/toolkit/profile/xpcshell/test_select_default.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests that from a database of profiles the default profile is selected.
  */
 
 add_task(async () => {
   let hash = xreDirProvider.getInstallHash();
 
   let profileData = {
--- a/toolkit/profile/xpcshell/test_select_environment.js
+++ b/toolkit/profile/xpcshell/test_select_environment.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests that the environment variables are used to select a profile.
  */
 
 add_task(async () => {
   let dir = makeRandomProfileDir("foo");
 
   let profileData = {
--- a/toolkit/profile/xpcshell/test_select_environment_named.js
+++ b/toolkit/profile/xpcshell/test_select_environment_named.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests that the environment variables are used to select a profile.
  */
 
 add_task(async () => {
   let root = makeRandomProfileDir("foo");
   let local = gDataHomeLocal.clone();
   local.append("foo");
--- a/toolkit/profile/xpcshell/test_select_missing.js
+++ b/toolkit/profile/xpcshell/test_select_missing.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests that when choosing an unknown profile the profile manager is shown.
  */
 
 add_task(async () => {
   let profileData = {
     options: {
       startWithLastProfile: true,
--- a/toolkit/profile/xpcshell/test_select_named.js
+++ b/toolkit/profile/xpcshell/test_select_named.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests that from a database of profiles the correct profile is selected.
  */
 
 add_task(async () => {
   let profileData = {
     options: {
       startWithLastProfile: true,
--- a/toolkit/profile/xpcshell/test_select_noname.js
+++ b/toolkit/profile/xpcshell/test_select_noname.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests that when passing the -P command line argument and not passing a
  * profile name the profile manager is opened.
  */
 
 add_task(async () => {
   let profileData = {
     options: {
--- a/toolkit/profile/xpcshell/test_select_profilemanager.js
+++ b/toolkit/profile/xpcshell/test_select_profilemanager.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests that when requested the profile manager is shown.
  */
 
 add_task(async () => {
   let profileData = {
     options: {
       startWithLastProfile: true,
--- a/toolkit/profile/xpcshell/test_single_profile_selected.js
+++ b/toolkit/profile/xpcshell/test_single_profile_selected.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Previous versions of Firefox automatically used a single profile even if it
  * wasn't marked as the default. So we should try to upgrade that one if it was
  * last used by this build. This test checks the case where it was.
  */
 
 add_task(async () => {
   let defaultProfile = makeRandomProfileDir("default");
--- a/toolkit/profile/xpcshell/test_single_profile_unselected.js
+++ b/toolkit/profile/xpcshell/test_single_profile_unselected.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Previous versions of Firefox automatically used a single profile even if it
  * wasn't marked as the default. So we should try to upgrade that one if it was
  * last used by this build. This test checks the case where it wasn't.
  */
 
 add_task(async () => {
   let defaultProfile = makeRandomProfileDir("default");
--- a/toolkit/profile/xpcshell/test_skip_locked_environment.js
+++ b/toolkit/profile/xpcshell/test_skip_locked_environment.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests that the environment variables are used to select a profile and that
  * on the first run of a dedicated profile build we don't snatch it if it is
  * locked by another install.
  */
 
 add_task(async () => {
   let root = makeRandomProfileDir("foo");
--- a/toolkit/profile/xpcshell/test_snap.js
+++ b/toolkit/profile/xpcshell/test_snap.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests that an old-style default profile not previously used by this build gets
  * used in a snap environment.
  */
 
 add_task(async () => {
   let defaultProfile = makeRandomProfileDir("default");
 
--- a/toolkit/profile/xpcshell/test_snap_empty.js
+++ b/toolkit/profile/xpcshell/test_snap_empty.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests that from a clean slate snap builds create an appropriate profile.
  */
 
 add_task(async () => {
   simulateSnapEnvironment();
 
   let service = getProfileService();
--- a/toolkit/profile/xpcshell/test_snatch_environment.js
+++ b/toolkit/profile/xpcshell/test_snatch_environment.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests that the environment variables are used to select a profile and that
  * on the first run of a dedicated profile build we snatch it if it was the
  * default profile.
  */
 
 add_task(async () => {
   let root = makeRandomProfileDir("foo");
--- a/toolkit/profile/xpcshell/test_snatch_environment_default.js
+++ b/toolkit/profile/xpcshell/test_snatch_environment_default.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests that the environment variables are used to select a profile and that
  * on the first run of a dedicated profile build we snatch it if it was the
  * default profile and lock it when we're the default app.
  */
 
 add_task(async () => {
   gIsDefaultApp = true;
--- a/toolkit/profile/xpcshell/test_startswithlast.js
+++ b/toolkit/profile/xpcshell/test_startswithlast.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests that if profiles.ini is set to not start with the last profile then
  * we show the profile manager in preference to assigning the old default.
  */
 
 add_task(async () => {
   let defaultProfile = makeRandomProfileDir("default");
 
--- a/toolkit/profile/xpcshell/test_steal_inuse.js
+++ b/toolkit/profile/xpcshell/test_steal_inuse.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests that an old-style default profile previously used by this build but
  * that has already been claimed by a different build gets stolen by this build.
  */
 
 add_task(async () => {
   let defaultProfile = makeRandomProfileDir("default");
 
--- a/toolkit/profile/xpcshell/test_update_selected_dedicated.js
+++ b/toolkit/profile/xpcshell/test_update_selected_dedicated.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests that an old-style default profile previously used by this build gets
  * updated to a dedicated profile for this build.
  */
 
 add_task(async () => {
   let defaultProfile = makeRandomProfileDir("default");
 
--- a/toolkit/profile/xpcshell/test_update_unknown_dedicated.js
+++ b/toolkit/profile/xpcshell/test_update_unknown_dedicated.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests that an old-style default profile not previously used by any build
  * doesn't get updated to a dedicated profile for this build and we don't set
  * the flag to show the user info about dedicated profiles.
  */
 
 add_task(async () => {
   let hash = xreDirProvider.getInstallHash();
--- a/toolkit/profile/xpcshell/test_update_unselected_dedicated.js
+++ b/toolkit/profile/xpcshell/test_update_unselected_dedicated.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /*
  * Tests that an old-style default profile not previously used by this build gets
  * ignored.
  */
 
 add_task(async () => {
   let hash = xreDirProvider.getInstallHash();
   let defaultProfile = makeRandomProfileDir("default");
--- a/toolkit/profile/xpcshell/test_use_dedicated.js
+++ b/toolkit/profile/xpcshell/test_use_dedicated.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
 /**
  * Tests that if installs.ini lists a profile we use it as the default.
  */
 
 add_task(async () => {
   let hash = xreDirProvider.getInstallHash();
   let defaultProfile = makeRandomProfileDir("default");
   let dedicatedProfile = makeRandomProfileDir("dedicated");
--- a/toolkit/profile/xpcshell/xpcshell.ini
+++ b/toolkit/profile/xpcshell/xpcshell.ini
@@ -30,10 +30,8 @@ skip-if = devedition
 [test_lock.js]
 [test_startswithlast.js]
 [test_snatch_environment.js]
 [test_skip_locked_environment.js]
 [test_snatch_environment_default.js]
 [test_check_backup.js]
 [test_missing_profilesini.js]
 [test_remove.js]
-[test_conflict_profiles.js]
-[test_conflict_installs.js]
--- a/toolkit/xre/ProfileReset.h
+++ b/toolkit/xre/ProfileReset.h
@@ -42,36 +42,33 @@ class ProfileResetCleanupAsyncTask : pub
         mTargetDir(aTargetDir),
         mLeafName(aLeafName) {}
 
   /**
    * Copy a root profile to a backup folder before deleting it.  Then delete the
    * local profile dir.
    */
   NS_IMETHOD Run() override {
-    // Copy profile's files to the destination. The profile folder will be
-    // removed after the changes to the known profiles have been flushed to disk
-    // in nsToolkitProfileService::ApplyResetProfile which isn't called until
-    // after this thread finishes copying the files.
+    // Copy to the destination then delete the profile. A move doesn't follow
+    // links.
     nsresult rv = mProfileDir->CopyToFollowingLinks(mTargetDir, mLeafName);
-    // I guess we just warn if we fail to make the backup?
+    if (NS_SUCCEEDED(rv)) rv = mProfileDir->Remove(true);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       NS_WARNING("Could not backup the root profile directory");
     }
 
     // If we have a separate local cache profile directory, just delete it.
     // Don't return an error if this fails so that reset can proceed if it can't
     // be deleted.
     bool sameDir;
     nsresult rvLocal = mProfileDir->Equals(mProfileLocalDir, &sameDir);
     if (NS_SUCCEEDED(rvLocal) && !sameDir) {
       rvLocal = mProfileLocalDir->Remove(true);
-      if (NS_FAILED(rvLocal)) {
+      if (NS_FAILED(rvLocal))
         NS_WARNING("Could not remove the old local profile directory (cache)");
-      }
     }
     gProfileResetCleanupCompleted = true;
 
     nsCOMPtr<nsIRunnable> resultRunnable = new ProfileResetCleanupResultTask();
     NS_DispatchToMainThread(resultRunnable);
     return NS_OK;
   }
 
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -1833,17 +1833,16 @@ static const char kProfileManagerURL[] =
     "chrome://mozapps/content/profile/profileSelection.xul";
 
 static ReturnAbortOnError ShowProfileManager(
     nsIToolkitProfileService* aProfileSvc, nsINativeAppSupport* aNative) {
   nsresult rv;
 
   nsCOMPtr<nsIFile> profD, profLD;
   bool offline = false;
-  int32_t dialogReturn;
 
   {
     ScopedXPCOMStartup xpcom;
     rv = xpcom.Initialize();
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Initialize the graphics prefs, some of the paths need them before
     // any other graphics is initialized (e.g., showing the profile chooser.)
@@ -1875,50 +1874,43 @@ static ReturnAbortOnError ShowProfileMan
 
       nsCOMPtr<mozIDOMWindowProxy> newWindow;
       rv = windowWatcher->OpenWindow(nullptr, kProfileManagerURL, "_blank",
                                      "centerscreen,chrome,modal,titlebar",
                                      ioParamBlock, getter_AddRefs(newWindow));
 
       NS_ENSURE_SUCCESS_LOG(rv, rv);
 
-      rv = ioParamBlock->GetInt(0, &dialogReturn);
-      if (NS_FAILED(rv) || dialogReturn == nsIToolkitProfileService::exit) {
-        return NS_ERROR_ABORT;
-      }
+      aProfileSvc->Flush();
+
+      int32_t dialogConfirmed;
+      rv = ioParamBlock->GetInt(0, &dialogConfirmed);
+      if (NS_FAILED(rv) || dialogConfirmed == 0) return NS_ERROR_ABORT;
 
       int32_t startOffline;
       rv = ioParamBlock->GetInt(1, &startOffline);
       offline = NS_SUCCEEDED(rv) && startOffline == 1;
 
       rv = dlgArray->QueryElementAt(0, NS_GET_IID(nsIFile),
                                     getter_AddRefs(profD));
       NS_ENSURE_SUCCESS_LOG(rv, rv);
 
       rv = dlgArray->QueryElementAt(1, NS_GET_IID(nsIFile),
                                     getter_AddRefs(profLD));
       NS_ENSURE_SUCCESS_LOG(rv, rv);
     }
   }
 
+  SaveFileToEnv("XRE_PROFILE_PATH", profD);
+  SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", profLD);
+  SaveToEnv("XRE_RESTARTED_BY_PROFILE_MANAGER=1");
+
   if (offline) {
     SaveToEnv("XRE_START_OFFLINE=1");
   }
-
-  // User requested that we restart back into the profile manager.
-  if (dialogReturn == nsIToolkitProfileService::restart) {
-    SaveToEnv("XRE_RESTART_TO_PROFILE_MANAGER=1");
-    SaveToEnv("XRE_RESTARTED_BY_PROFILE_MANAGER=1");
-  } else {
-    MOZ_ASSERT(dialogReturn == nsIToolkitProfileService::launchWithProfile);
-    SaveFileToEnv("XRE_PROFILE_PATH", profD);
-    SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", profLD);
-    SaveToEnv("XRE_RESTARTED_BY_PROFILE_MANAGER=1");
-  }
-
   if (gRestartedByOS) {
     // Re-add this argument when actually starting the application.
     char** newArgv =
         (char**)realloc(gRestartArgv, sizeof(char*) * (gRestartArgc + 2));
     NS_ENSURE_TRUE(newArgv, NS_ERROR_OUT_OF_MEMORY);
     gRestartArgv = newArgv;
     gRestartArgv[gRestartArgc++] = const_cast<char*>("-os-restarted");
     gRestartArgv[gRestartArgc] = nullptr;
@@ -2014,20 +2006,16 @@ static nsresult SelectProfile(nsToolkitP
                "Error: argument --migration is invalid when argument --osint "
                "is specified\n");
     return NS_ERROR_FAILURE;
   }
   if (ar == ARG_FOUND) {
     gDoMigration = true;
   }
 
-  if (EnvHasValue("XRE_RESTART_TO_PROFILE_MANAGER")) {
-    return ShowProfileManager(aProfileSvc, aNative);
-  }
-
   // Ask the profile manager to select the profile directories to use.
   bool didCreate = false;
   rv = aProfileSvc->SelectStartupProfile(&gArgc, gArgv, gDoProfileReset,
                                          aRootDir, aLocalDir, aProfile,
                                          &didCreate, aWasDefaultSelection);
 
   if (rv == NS_ERROR_SHOW_PROFILE_MANAGER) {
     return ShowProfileManager(aProfileSvc, aNative);
@@ -4368,19 +4356,18 @@ nsresult XREMain::XRE_mainRun() {
         }
         pm->Migrate(&mDirProvider, aKey, aName);
       }
     }
 
     if (gDoProfileReset) {
       nsresult backupCreated =
           ProfileResetCleanup(mProfileSvc, gResetOldProfile);
-      if (NS_FAILED(backupCreated)) {
+      if (NS_FAILED(backupCreated))
         NS_WARNING("Could not cleanup the profile that was reset");
-      }
     }
   }
 
 #ifndef XP_WIN
   nsCOMPtr<nsIFile> profileDir;
   nsAutoCString path;
   rv = mDirProvider.GetProfileStartupDir(getter_AddRefs(profileDir));
   if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(profileDir->GetNativePath(path)) &&
--- a/xpcom/base/ErrorList.py
+++ b/xpcom/base/ErrorList.py
@@ -751,17 +751,16 @@ with modules["XPCONNECT"]:
 
 
 # =======================================================================
 # 19: NS_ERROR_MODULE_PROFILE
 # =======================================================================
 with modules["PROFILE"]:
     errors["NS_ERROR_LAUNCHED_CHILD_PROCESS"] = FAILURE(200)
     errors["NS_ERROR_SHOW_PROFILE_MANAGER"] = FAILURE(201)
-    errors["NS_ERROR_DATABASE_CHANGED"] = FAILURE(202)
 
 
 # =======================================================================
 # 21: NS_ERROR_MODULE_SECURITY
 # =======================================================================
 with modules["SECURITY"]:
     # Error code for CSP
     errors["NS_ERROR_CSP_FORM_ACTION_VIOLATION"] = FAILURE(98)