Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(366)

Unified Diff: chrome/browser/profiles/profile_manager.cc

Issue 2201793002: Fixed sole profile double deletion. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: ABANDONED -> MARKED Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/profiles/profile_manager.cc
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc
index 1c992d410357ccbe7f9db73fac8bc686aedbb1fa..becbbe83f74e625e94b16b4d14f564f08908a07e 100644
--- a/chrome/browser/profiles/profile_manager.cc
+++ b/chrome/browser/profiles/profile_manager.cc
@@ -6,6 +6,7 @@
#include <stdint.h>
+#include <map>
#include <set>
#include <string>
@@ -130,9 +131,18 @@ using content::BrowserThread;
namespace {
-// Profiles that should be deleted on shutdown.
-std::vector<base::FilePath>& ProfilesToDelete() {
- CR_DEFINE_STATIC_LOCAL(std::vector<base::FilePath>, profiles_to_delete, ());
+// Profile deletion can pass through two stages:
+enum class ProfileDeletionStage {
+ // At SCHEDULED stage will be performed necessary activity prior to
+ // profile deletion. Such as new profile creation, if none is left, or load
+ // fallback profile for Macs, if it not loaded yet.
+ SCHEDULED,
+ // At MARKED stage profile can be safely removed from disk.
+ MARKED
+};
+using ProfileDeletionMap = std::map<base::FilePath, ProfileDeletionStage>;
+ProfileDeletionMap& ProfilesToDelete() {
+ CR_DEFINE_STATIC_LOCAL(ProfileDeletionMap, profiles_to_delete, ());
return profiles_to_delete;
}
@@ -201,14 +211,26 @@ void ProfileSizeTask(const base::FilePath& path, int enabled_app_count) {
}
#if !defined(OS_ANDROID)
-void QueueProfileDirectoryForDeletion(const base::FilePath& path) {
- ProfilesToDelete().push_back(path);
+// Schedule a profile for deletion if it isn't already scheduled.
+// Returns whether the profile has been newly scheduled.
+bool ScheduleProfileDirectoryForDeletion(const base::FilePath& path) {
+ if (ContainsKey(ProfilesToDelete(), path))
+ return false;
+ ProfilesToDelete()[path] = ProfileDeletionStage::SCHEDULED;
+ return true;
+}
+
+void MarkProfileDirectoryForDeletion(const base::FilePath& path) {
+ DCHECK(!ContainsKey(ProfilesToDelete(), path) ||
+ ProfilesToDelete()[path] == ProfileDeletionStage::SCHEDULED);
+ ProfilesToDelete()[path] = ProfileDeletionStage::MARKED;
}
#endif
-bool IsProfileMarkedForDeletion(const base::FilePath& profile_path) {
- return std::find(ProfilesToDelete().begin(), ProfilesToDelete().end(),
- profile_path) != ProfilesToDelete().end();
+bool IsProfileDirectoryMarkedForDeletion(const base::FilePath& profile_path) {
+ auto it = ProfilesToDelete().find(profile_path);
+ return it != ProfilesToDelete().end() &&
+ it->second == ProfileDeletionStage::MARKED;
}
// Physically remove deleted profile directories from disk.
@@ -333,11 +355,9 @@ void ProfileManager::ShutdownSessionServices() {
// static
void ProfileManager::NukeDeletedProfilesFromDisk() {
- for (std::vector<base::FilePath>::iterator it =
- ProfilesToDelete().begin();
- it != ProfilesToDelete().end();
- ++it) {
- NukeProfileFromDisk(*it);
+ for (const auto& item : ProfilesToDelete()) {
+ if (item.second == ProfileDeletionStage::MARKED)
+ NukeProfileFromDisk(item.first);
}
ProfilesToDelete().clear();
}
@@ -467,7 +487,7 @@ void ProfileManager::CreateProfileAsync(
profile_path.AsUTF8Unsafe());
// Make sure that this profile is not pending deletion.
- if (IsProfileMarkedForDeletion(profile_path)) {
+ if (IsProfileDirectoryMarkedForDeletion(profile_path)) {
if (!callback.is_null())
callback.Run(NULL, Profile::CREATE_STATUS_LOCAL_FAIL);
return;
@@ -735,7 +755,7 @@ bool ProfileManager::MaybeScheduleProfileForDeletion(
const base::FilePath& profile_dir,
const CreateCallback& callback,
ProfileMetrics::ProfileDelete deletion_source) {
- if (IsProfileMarkedForDeletion(profile_dir))
+ if (!ScheduleProfileDirectoryForDeletion(profile_dir))
return false;
ScheduleProfileForDeletion(profile_dir, callback);
ProfileMetrics::LogProfileDeleteUser(deletion_source);
@@ -746,7 +766,7 @@ void ProfileManager::ScheduleProfileForDeletion(
const base::FilePath& profile_dir,
const CreateCallback& callback) {
DCHECK(profiles::IsMultipleProfilesEnabled());
- DCHECK(!IsProfileMarkedForDeletion(profile_dir));
+ DCHECK(!IsProfileDirectoryMarkedForDeletion(profile_dir));
// Cancel all in-progress downloads before deleting the profile to prevent a
// "Do you want to exit Google Chrome and cancel the downloads?" prompt
@@ -770,7 +790,7 @@ void ProfileManager::ScheduleProfileForDeletion(
// legacy-supervised.
if (cur_path != profile_dir &&
!entry->IsLegacySupervised() &&
- !IsProfileMarkedForDeletion(cur_path)) {
+ !IsProfileDirectoryMarkedForDeletion(cur_path)) {
last_non_supervised_profile_path = cur_path;
break;
}
@@ -1403,7 +1423,7 @@ void ProfileManager::FinishDeletingProfile(
// Queue even a profile that was nuked so it will be MarkedForDeletion and so
// CreateProfileAsync can't create it.
- QueueProfileDirectoryForDeletion(profile_dir);
+ MarkProfileDirectoryForDeletion(profile_dir);
storage.RemoveProfile(profile_dir);
ProfileMetrics::UpdateReportedProfilesStatistics(this);
}
@@ -1566,7 +1586,7 @@ void ProfileManager::BrowserListObserver::OnBrowserRemoved(
}
base::FilePath path = profile->GetPath();
- if (IsProfileMarkedForDeletion(path)) {
+ if (IsProfileDirectoryMarkedForDeletion(path)) {
// Do nothing if the profile is already being deleted.
} else if (profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles)) {
// Delete if the profile is an ephemeral profile.
@@ -1617,7 +1637,7 @@ void ProfileManager::OnNewActiveProfileLoaded(
if (status != Profile::CREATE_STATUS_INITIALIZED)
return;
- if (IsProfileMarkedForDeletion(new_active_profile_path)) {
+ if (IsProfileDirectoryMarkedForDeletion(new_active_profile_path)) {
// If the profile we tried to load as the next active profile has been
// deleted, then retry deleting this profile to redo the logic to load
// the next available profile.
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698