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

Side by Side 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: review fixes 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 unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/profiles/profile_manager.h" 5 #include "chrome/browser/profiles/profile_manager.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <map>
9 #include <set> 10 #include <set>
10 #include <string> 11 #include <string>
11 12
12 #include "base/bind.h" 13 #include "base/bind.h"
13 #include "base/command_line.h" 14 #include "base/command_line.h"
14 #include "base/deferred_sequenced_task_runner.h" 15 #include "base/deferred_sequenced_task_runner.h"
15 #include "base/feature_list.h" 16 #include "base/feature_list.h"
16 #include "base/files/file_enumerator.h" 17 #include "base/files/file_enumerator.h"
17 #include "base/files/file_path.h" 18 #include "base/files/file_path.h"
18 #include "base/files/file_util.h" 19 #include "base/files/file_util.h"
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS) 124 #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
124 #include "chrome/browser/profiles/profile_statistics.h" 125 #include "chrome/browser/profiles/profile_statistics.h"
125 #include "chrome/browser/profiles/profile_statistics_factory.h" 126 #include "chrome/browser/profiles/profile_statistics_factory.h"
126 #endif 127 #endif
127 128
128 using base::UserMetricsAction; 129 using base::UserMetricsAction;
129 using content::BrowserThread; 130 using content::BrowserThread;
130 131
131 namespace { 132 namespace {
132 133
133 // Profiles that should be deleted on shutdown. 134 // Profile deletion can pass through two stages:
134 std::vector<base::FilePath>& ProfilesToDelete() { 135 enum class ProfileDeletionStage {
135 CR_DEFINE_STATIC_LOCAL(std::vector<base::FilePath>, profiles_to_delete, ()); 136 // At SCHEDULED stage will be performed necessary activity prior to
137 // profile deletion. Such as new profile creation, if none is left, or load
138 // fallback profile for Macs, if it not loaded yet.
139 SCHEDULED,
140 // At ABANDONED stage profile can be safely removed from disk.
141 ABANDONED
Bernhard Bauer 2016/08/04 16:28:36 MARKED maybe?
142 };
143 using ProfileDeletionMap = std::map<base::FilePath, ProfileDeletionStage>;
144 ProfileDeletionMap& ProfilesToDelete() {
145 CR_DEFINE_STATIC_LOCAL(ProfileDeletionMap, profiles_to_delete, ());
136 return profiles_to_delete; 146 return profiles_to_delete;
137 } 147 }
138 148
139 int64_t ComputeFilesSize(const base::FilePath& directory, 149 int64_t ComputeFilesSize(const base::FilePath& directory,
140 const base::FilePath::StringType& pattern) { 150 const base::FilePath::StringType& pattern) {
141 int64_t running_size = 0; 151 int64_t running_size = 0;
142 base::FileEnumerator iter(directory, false, base::FileEnumerator::FILES, 152 base::FileEnumerator iter(directory, false, base::FileEnumerator::FILES,
143 pattern); 153 pattern);
144 while (!iter.Next().empty()) 154 while (!iter.Next().empty())
145 running_size += iter.GetInfo().GetSize(); 155 running_size += iter.GetInfo().GetSize();
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Policy")); 204 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Policy"));
195 size_MB = static_cast<int>(size / kBytesInOneMB); 205 size_MB = static_cast<int>(size / kBytesInOneMB);
196 UMA_HISTOGRAM_COUNTS_10000("Profile.PolicySize", size_MB); 206 UMA_HISTOGRAM_COUNTS_10000("Profile.PolicySize", size_MB);
197 207
198 // Count number of enabled apps in this profile, if we know. 208 // Count number of enabled apps in this profile, if we know.
199 if (enabled_app_count != -1) 209 if (enabled_app_count != -1)
200 UMA_HISTOGRAM_COUNTS_10000("Profile.AppCount", enabled_app_count); 210 UMA_HISTOGRAM_COUNTS_10000("Profile.AppCount", enabled_app_count);
201 } 211 }
202 212
203 #if !defined(OS_ANDROID) 213 #if !defined(OS_ANDROID)
204 void QueueProfileDirectoryForDeletion(const base::FilePath& path) { 214 // Schedule a profile for deletion if it isn't already scheduled.
205 ProfilesToDelete().push_back(path); 215 // Returns whether the profile has been newly scheduled.
216 bool ScheduleProfileDirectoryForDeletion(const base::FilePath& path) {
217 if (ContainsKey(ProfilesToDelete(), path))
218 return false;
219 ProfilesToDelete()[path] = ProfileDeletionStage::SCHEDULED;
220 return true;
221 }
222
223 void MarkProfileDirectoryForDeletion(const base::FilePath& path) {
224 DCHECK(!ContainsKey(ProfilesToDelete(), path) ||
225 ProfilesToDelete()[path] == ProfileDeletionStage::SCHEDULED);
226 ProfilesToDelete()[path] = ProfileDeletionStage::ABANDONED;
206 } 227 }
207 #endif 228 #endif
208 229
209 bool IsProfileMarkedForDeletion(const base::FilePath& profile_path) { 230 bool IsProfileDirectoryMarkedForDeletion(const base::FilePath& profile_path) {
210 return std::find(ProfilesToDelete().begin(), ProfilesToDelete().end(), 231 auto it = ProfilesToDelete().find(profile_path);
211 profile_path) != ProfilesToDelete().end(); 232 return it != ProfilesToDelete().end() &&
233 it->second == ProfileDeletionStage::ABANDONED;
212 } 234 }
213 235
214 // Physically remove deleted profile directories from disk. 236 // Physically remove deleted profile directories from disk.
215 void NukeProfileFromDisk(const base::FilePath& profile_path) { 237 void NukeProfileFromDisk(const base::FilePath& profile_path) {
216 // Delete both the profile directory and its corresponding cache. 238 // Delete both the profile directory and its corresponding cache.
217 base::FilePath cache_path; 239 base::FilePath cache_path;
218 chrome::GetUserCacheDirectory(profile_path, &cache_path); 240 chrome::GetUserCacheDirectory(profile_path, &cache_path);
219 base::DeleteFile(profile_path, true); 241 base::DeleteFile(profile_path, true);
220 base::DeleteFile(cache_path, true); 242 base::DeleteFile(cache_path, true);
221 } 243 }
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 if (!pm) // Is NULL when running unit tests. 348 if (!pm) // Is NULL when running unit tests.
327 return; 349 return;
328 std::vector<Profile*> profiles(pm->GetLoadedProfiles()); 350 std::vector<Profile*> profiles(pm->GetLoadedProfiles());
329 for (size_t i = 0; i < profiles.size(); ++i) 351 for (size_t i = 0; i < profiles.size(); ++i)
330 SessionServiceFactory::ShutdownForProfile(profiles[i]); 352 SessionServiceFactory::ShutdownForProfile(profiles[i]);
331 } 353 }
332 #endif 354 #endif
333 355
334 // static 356 // static
335 void ProfileManager::NukeDeletedProfilesFromDisk() { 357 void ProfileManager::NukeDeletedProfilesFromDisk() {
336 for (std::vector<base::FilePath>::iterator it = 358 for (const auto& item : ProfilesToDelete()) {
337 ProfilesToDelete().begin(); 359 if (item.second == ProfileDeletionStage::ABANDONED)
338 it != ProfilesToDelete().end(); 360 NukeProfileFromDisk(item.first);
339 ++it) {
340 NukeProfileFromDisk(*it);
341 } 361 }
342 ProfilesToDelete().clear(); 362 ProfilesToDelete().clear();
343 } 363 }
344 364
345 // static 365 // static
346 Profile* ProfileManager::GetLastUsedProfile() { 366 Profile* ProfileManager::GetLastUsedProfile() {
347 ProfileManager* profile_manager = g_browser_process->profile_manager(); 367 ProfileManager* profile_manager = g_browser_process->profile_manager();
348 return profile_manager->GetLastUsedProfile(profile_manager->user_data_dir_); 368 return profile_manager->GetLastUsedProfile(profile_manager->user_data_dir_);
349 } 369 }
350 370
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 const base::string16& name, 480 const base::string16& name,
461 const std::string& icon_url, 481 const std::string& icon_url,
462 const std::string& supervised_user_id) { 482 const std::string& supervised_user_id) {
463 DCHECK_CURRENTLY_ON(BrowserThread::UI); 483 DCHECK_CURRENTLY_ON(BrowserThread::UI);
464 TRACE_EVENT1("browser,startup", 484 TRACE_EVENT1("browser,startup",
465 "ProfileManager::CreateProfileAsync", 485 "ProfileManager::CreateProfileAsync",
466 "profile_path", 486 "profile_path",
467 profile_path.AsUTF8Unsafe()); 487 profile_path.AsUTF8Unsafe());
468 488
469 // Make sure that this profile is not pending deletion. 489 // Make sure that this profile is not pending deletion.
470 if (IsProfileMarkedForDeletion(profile_path)) { 490 if (IsProfileDirectoryMarkedForDeletion(profile_path)) {
471 if (!callback.is_null()) 491 if (!callback.is_null())
472 callback.Run(NULL, Profile::CREATE_STATUS_LOCAL_FAIL); 492 callback.Run(NULL, Profile::CREATE_STATUS_LOCAL_FAIL);
473 return; 493 return;
474 } 494 }
475 495
476 // Create the profile if needed and collect its ProfileInfo. 496 // Create the profile if needed and collect its ProfileInfo.
477 ProfilesInfoMap::iterator iter = profiles_info_.find(profile_path); 497 ProfilesInfoMap::iterator iter = profiles_info_.find(profile_path);
478 ProfileInfo* info = NULL; 498 ProfileInfo* info = NULL;
479 499
480 if (iter != profiles_info_.end()) { 500 if (iter != profiles_info_.end()) {
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
728 748
729 ProfileShortcutManager* ProfileManager::profile_shortcut_manager() { 749 ProfileShortcutManager* ProfileManager::profile_shortcut_manager() {
730 return profile_shortcut_manager_.get(); 750 return profile_shortcut_manager_.get();
731 } 751 }
732 752
733 #if !defined(OS_ANDROID) 753 #if !defined(OS_ANDROID)
734 bool ProfileManager::MaybeScheduleProfileForDeletion( 754 bool ProfileManager::MaybeScheduleProfileForDeletion(
735 const base::FilePath& profile_dir, 755 const base::FilePath& profile_dir,
736 const CreateCallback& callback, 756 const CreateCallback& callback,
737 ProfileMetrics::ProfileDelete deletion_source) { 757 ProfileMetrics::ProfileDelete deletion_source) {
738 if (IsProfileMarkedForDeletion(profile_dir)) 758 if (!ScheduleProfileDirectoryForDeletion(profile_dir))
739 return false; 759 return false;
740 ScheduleProfileForDeletion(profile_dir, callback); 760 ScheduleProfileForDeletion(profile_dir, callback);
741 ProfileMetrics::LogProfileDeleteUser(deletion_source); 761 ProfileMetrics::LogProfileDeleteUser(deletion_source);
742 return true; 762 return true;
743 } 763 }
744 764
745 void ProfileManager::ScheduleProfileForDeletion( 765 void ProfileManager::ScheduleProfileForDeletion(
746 const base::FilePath& profile_dir, 766 const base::FilePath& profile_dir,
747 const CreateCallback& callback) { 767 const CreateCallback& callback) {
748 DCHECK(profiles::IsMultipleProfilesEnabled()); 768 DCHECK(profiles::IsMultipleProfilesEnabled());
749 DCHECK(!IsProfileMarkedForDeletion(profile_dir)); 769 DCHECK(!IsProfileDirectoryMarkedForDeletion(profile_dir));
750 770
751 // Cancel all in-progress downloads before deleting the profile to prevent a 771 // Cancel all in-progress downloads before deleting the profile to prevent a
752 // "Do you want to exit Google Chrome and cancel the downloads?" prompt 772 // "Do you want to exit Google Chrome and cancel the downloads?" prompt
753 // (crbug.com/336725). 773 // (crbug.com/336725).
754 Profile* profile = GetProfileByPath(profile_dir); 774 Profile* profile = GetProfileByPath(profile_dir);
755 if (profile) { 775 if (profile) {
756 DownloadService* service = 776 DownloadService* service =
757 DownloadServiceFactory::GetForBrowserContext(profile); 777 DownloadServiceFactory::GetForBrowserContext(profile);
758 service->CancelDownloads(); 778 service->CancelDownloads();
759 } 779 }
760 780
761 ProfileAttributesStorage& storage = GetProfileAttributesStorage(); 781 ProfileAttributesStorage& storage = GetProfileAttributesStorage();
762 // If we're deleting the last (non-legacy-supervised) profile, then create a 782 // If we're deleting the last (non-legacy-supervised) profile, then create a
763 // new profile in its place. 783 // new profile in its place.
764 base::FilePath last_non_supervised_profile_path; 784 base::FilePath last_non_supervised_profile_path;
765 std::vector<ProfileAttributesEntry*> entries = 785 std::vector<ProfileAttributesEntry*> entries =
766 storage.GetAllProfilesAttributes(); 786 storage.GetAllProfilesAttributes();
767 for (ProfileAttributesEntry* entry : entries) { 787 for (ProfileAttributesEntry* entry : entries) {
768 base::FilePath cur_path = entry->GetPath(); 788 base::FilePath cur_path = entry->GetPath();
769 // Make sure that this profile is not pending deletion, and is not 789 // Make sure that this profile is not pending deletion, and is not
770 // legacy-supervised. 790 // legacy-supervised.
771 if (cur_path != profile_dir && 791 if (cur_path != profile_dir &&
772 !entry->IsLegacySupervised() && 792 !entry->IsLegacySupervised() &&
773 !IsProfileMarkedForDeletion(cur_path)) { 793 !IsProfileDirectoryMarkedForDeletion(cur_path)) {
774 last_non_supervised_profile_path = cur_path; 794 last_non_supervised_profile_path = cur_path;
775 break; 795 break;
776 } 796 }
777 } 797 }
778 798
779 if (last_non_supervised_profile_path.empty()) { 799 if (last_non_supervised_profile_path.empty()) {
780 std::string new_avatar_url; 800 std::string new_avatar_url;
781 base::string16 new_profile_name; 801 base::string16 new_profile_name;
782 802
783 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) 803 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
(...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after
1396 profiles::RemoveBrowsingDataForProfile(profile_dir); 1416 profiles::RemoveBrowsingDataForProfile(profile_dir);
1397 } else { 1417 } else {
1398 // It is safe to delete a not yet loaded Profile from disk. 1418 // It is safe to delete a not yet loaded Profile from disk.
1399 BrowserThread::PostTask( 1419 BrowserThread::PostTask(
1400 BrowserThread::FILE, FROM_HERE, 1420 BrowserThread::FILE, FROM_HERE,
1401 base::Bind(&NukeProfileFromDisk, profile_dir)); 1421 base::Bind(&NukeProfileFromDisk, profile_dir));
1402 } 1422 }
1403 1423
1404 // Queue even a profile that was nuked so it will be MarkedForDeletion and so 1424 // Queue even a profile that was nuked so it will be MarkedForDeletion and so
1405 // CreateProfileAsync can't create it. 1425 // CreateProfileAsync can't create it.
1406 QueueProfileDirectoryForDeletion(profile_dir); 1426 MarkProfileDirectoryForDeletion(profile_dir);
1407 storage.RemoveProfile(profile_dir); 1427 storage.RemoveProfile(profile_dir);
1408 ProfileMetrics::UpdateReportedProfilesStatistics(this); 1428 ProfileMetrics::UpdateReportedProfilesStatistics(this);
1409 } 1429 }
1410 #endif // !defined(OS_ANDROID) 1430 #endif // !defined(OS_ANDROID)
1411 1431
1412 ProfileManager::ProfileInfo* ProfileManager::RegisterProfile( 1432 ProfileManager::ProfileInfo* ProfileManager::RegisterProfile(
1413 Profile* profile, 1433 Profile* profile,
1414 bool created) { 1434 bool created) {
1415 TRACE_EVENT0("browser", "ProfileManager::RegisterProfile"); 1435 TRACE_EVENT0("browser", "ProfileManager::RegisterProfile");
1416 ProfileInfo* info = new ProfileInfo(profile, created); 1436 ProfileInfo* info = new ProfileInfo(profile, created);
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
1559 Browser* browser) { 1579 Browser* browser) {
1560 Profile* profile = browser->profile(); 1580 Profile* profile = browser->profile();
1561 Profile* original_profile = profile->GetOriginalProfile(); 1581 Profile* original_profile = profile->GetOriginalProfile();
1562 // Do nothing if the closed window is not the last window of the same profile. 1582 // Do nothing if the closed window is not the last window of the same profile.
1563 for (auto* browser : *BrowserList::GetInstance()) { 1583 for (auto* browser : *BrowserList::GetInstance()) {
1564 if (browser->profile()->GetOriginalProfile() == original_profile) 1584 if (browser->profile()->GetOriginalProfile() == original_profile)
1565 return; 1585 return;
1566 } 1586 }
1567 1587
1568 base::FilePath path = profile->GetPath(); 1588 base::FilePath path = profile->GetPath();
1569 if (IsProfileMarkedForDeletion(path)) { 1589 if (IsProfileDirectoryMarkedForDeletion(path)) {
1570 // Do nothing if the profile is already being deleted. 1590 // Do nothing if the profile is already being deleted.
1571 } else if (profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles)) { 1591 } else if (profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles)) {
1572 // Delete if the profile is an ephemeral profile. 1592 // Delete if the profile is an ephemeral profile.
1573 g_browser_process->profile_manager()->ScheduleProfileForDeletion( 1593 g_browser_process->profile_manager()->ScheduleProfileForDeletion(
1574 path, ProfileManager::CreateCallback()); 1594 path, ProfileManager::CreateCallback());
1575 } else { 1595 } else {
1576 #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS) 1596 #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
1577 // Gather statistics and store into ProfileInfoCache. For incognito profile 1597 // Gather statistics and store into ProfileInfoCache. For incognito profile
1578 // we gather the statistics of its parent profile instead, because a window 1598 // we gather the statistics of its parent profile instead, because a window
1579 // of the parent profile was open. 1599 // of the parent profile was open.
(...skipping 30 matching lines...) Expand all
1610 const CreateCallback& original_callback, 1630 const CreateCallback& original_callback,
1611 Profile* loaded_profile, 1631 Profile* loaded_profile,
1612 Profile::CreateStatus status) { 1632 Profile::CreateStatus status) {
1613 DCHECK(status != Profile::CREATE_STATUS_LOCAL_FAIL && 1633 DCHECK(status != Profile::CREATE_STATUS_LOCAL_FAIL &&
1614 status != Profile::CREATE_STATUS_REMOTE_FAIL); 1634 status != Profile::CREATE_STATUS_REMOTE_FAIL);
1615 1635
1616 // Only run the code if the profile initialization has finished completely. 1636 // Only run the code if the profile initialization has finished completely.
1617 if (status != Profile::CREATE_STATUS_INITIALIZED) 1637 if (status != Profile::CREATE_STATUS_INITIALIZED)
1618 return; 1638 return;
1619 1639
1620 if (IsProfileMarkedForDeletion(new_active_profile_path)) { 1640 if (IsProfileDirectoryMarkedForDeletion(new_active_profile_path)) {
1621 // If the profile we tried to load as the next active profile has been 1641 // If the profile we tried to load as the next active profile has been
1622 // deleted, then retry deleting this profile to redo the logic to load 1642 // deleted, then retry deleting this profile to redo the logic to load
1623 // the next available profile. 1643 // the next available profile.
1624 ScheduleProfileForDeletion(profile_to_delete_path, original_callback); 1644 ScheduleProfileForDeletion(profile_to_delete_path, original_callback);
1625 return; 1645 return;
1626 } 1646 }
1627 1647
1628 FinishDeletingProfile(profile_to_delete_path, new_active_profile_path); 1648 FinishDeletingProfile(profile_to_delete_path, new_active_profile_path);
1629 if (!original_callback.is_null()) 1649 if (!original_callback.is_null())
1630 original_callback.Run(loaded_profile, status); 1650 original_callback.Run(loaded_profile, status);
1631 } 1651 }
1632 #endif // !defined(OS_ANDROID) 1652 #endif // !defined(OS_ANDROID)
1633 1653
1634 ProfileManagerWithoutInit::ProfileManagerWithoutInit( 1654 ProfileManagerWithoutInit::ProfileManagerWithoutInit(
1635 const base::FilePath& user_data_dir) : ProfileManager(user_data_dir) { 1655 const base::FilePath& user_data_dir) : ProfileManager(user_data_dir) {
1636 } 1656 }
OLDNEW
« 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