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

Side by Side Diff: chrome/browser/profiles/profile_manager.cc

Issue 953453002: Wait until a new profile has been created before deleting the active profile. (Closed) Base URL: https://chromium.googlesource.com/chromium/src@master
Patch Set: fix!!!!11111oneoneoneoneargh Created 5 years, 9 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 | « chrome/browser/profiles/profile_manager.h ('k') | 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 <set> 7 #include <set>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 Profile* ProfileManager::GetProfileByPathInternal( 551 Profile* ProfileManager::GetProfileByPathInternal(
552 const base::FilePath& path) const { 552 const base::FilePath& path) const {
553 TRACE_EVENT0("browser", "ProfileManager::GetProfileByPathInternal"); 553 TRACE_EVENT0("browser", "ProfileManager::GetProfileByPathInternal");
554 ProfileInfo* profile_info = GetProfileInfoByPath(path); 554 ProfileInfo* profile_info = GetProfileInfoByPath(path);
555 return profile_info ? profile_info->profile.get() : nullptr; 555 return profile_info ? profile_info->profile.get() : nullptr;
556 } 556 }
557 557
558 Profile* ProfileManager::GetProfileByPath(const base::FilePath& path) const { 558 Profile* ProfileManager::GetProfileByPath(const base::FilePath& path) const {
559 TRACE_EVENT0("browser", "ProfileManager::GetProfileByPath"); 559 TRACE_EVENT0("browser", "ProfileManager::GetProfileByPath");
560 ProfileInfo* profile_info = GetProfileInfoByPath(path); 560 ProfileInfo* profile_info = GetProfileInfoByPath(path);
561 return profile_info && profile_info->created ? profile_info->profile.get() 561 return (profile_info && profile_info->created) ? profile_info->profile.get()
562 : nullptr; 562 : nullptr;
563 } 563 }
564 564
565 // static 565 // static
566 base::FilePath ProfileManager::CreateMultiProfileAsync( 566 base::FilePath ProfileManager::CreateMultiProfileAsync(
567 const base::string16& name, 567 const base::string16& name,
568 const base::string16& icon_url, 568 const base::string16& icon_url,
569 const CreateCallback& callback, 569 const CreateCallback& callback,
570 const std::string& supervised_user_id) { 570 const std::string& supervised_user_id) {
571 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 571 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
572 572
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
643 // Cancel all in-progress downloads before deleting the profile to prevent a 643 // Cancel all in-progress downloads before deleting the profile to prevent a
644 // "Do you want to exit Google Chrome and cancel the downloads?" prompt 644 // "Do you want to exit Google Chrome and cancel the downloads?" prompt
645 // (crbug.com/336725). 645 // (crbug.com/336725).
646 Profile* profile = GetProfileByPath(profile_dir); 646 Profile* profile = GetProfileByPath(profile_dir);
647 if (profile) { 647 if (profile) {
648 DownloadService* service = 648 DownloadService* service =
649 DownloadServiceFactory::GetForBrowserContext(profile); 649 DownloadServiceFactory::GetForBrowserContext(profile);
650 service->CancelDownloads(); 650 service->CancelDownloads();
651 } 651 }
652 652
653 PrefService* local_state = g_browser_process->local_state();
654 ProfileInfoCache& cache = GetProfileInfoCache(); 653 ProfileInfoCache& cache = GetProfileInfoCache();
655 654
656 // If we're deleting the last (non-legacy-supervised) profile, then create a 655 // If we're deleting the last (non-legacy-supervised) profile, then create a
657 // new profile in its place. 656 // new profile in its place.
658 base::FilePath last_non_supervised_profile_path; 657 base::FilePath last_non_supervised_profile_path;
659 for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) { 658 for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) {
660 base::FilePath cur_path = cache.GetPathOfProfileAtIndex(i); 659 base::FilePath cur_path = cache.GetPathOfProfileAtIndex(i);
661 // Make sure that this profile is not pending deletion, and is not 660 // Make sure that this profile is not pending deletion, and is not
662 // legacy-supervised. 661 // legacy-supervised.
663 if (cur_path != profile_dir && 662 if (cur_path != profile_dir &&
(...skipping 11 matching lines...) Expand all
675 bool is_new_avatar_menu = switches::IsNewAvatarMenu(); 674 bool is_new_avatar_menu = switches::IsNewAvatarMenu();
676 int avatar_index = profiles::GetPlaceholderAvatarIndex(); 675 int avatar_index = profiles::GetPlaceholderAvatarIndex();
677 base::string16 new_avatar_url = is_new_avatar_menu ? 676 base::string16 new_avatar_url = is_new_avatar_menu ?
678 base::UTF8ToUTF16(profiles::GetDefaultAvatarIconUrl(avatar_index)) : 677 base::UTF8ToUTF16(profiles::GetDefaultAvatarIconUrl(avatar_index)) :
679 base::string16(); 678 base::string16();
680 base::string16 new_profile_name = is_new_avatar_menu ? 679 base::string16 new_profile_name = is_new_avatar_menu ?
681 cache.ChooseNameForNewProfile(avatar_index) : base::string16(); 680 cache.ChooseNameForNewProfile(avatar_index) : base::string16();
682 681
683 new_path = GenerateNextProfileDirectoryPath(); 682 new_path = GenerateNextProfileDirectoryPath();
684 CreateProfileAsync(new_path, 683 CreateProfileAsync(new_path,
685 callback, 684 base::Bind(&ProfileManager::OnNewActiveProfileLoaded,
685 base::Unretained(this),
686 profile_dir,
687 new_path,
688 callback),
686 new_profile_name, 689 new_profile_name,
687 new_avatar_url, 690 new_avatar_url,
688 std::string()); 691 std::string());
689 692
690 ProfileMetrics::LogProfileAddNewUser( 693 ProfileMetrics::LogProfileAddNewUser(
691 ProfileMetrics::ADD_NEW_USER_LAST_DELETED); 694 ProfileMetrics::ADD_NEW_USER_LAST_DELETED);
695 return;
692 } 696 }
693 697
694 // Update the last used profile pref before closing browser windows. This 698 #if defined(OS_MACOSX)
695 // way the correct last used profile is set for any notification observers. 699 // On the Mac, the browser process is not killed when all browser windows are
700 // closed, so just in case we are deleting the active profile, and no other
701 // profile has been loaded, we must pre-load a next one.
696 const std::string last_used_profile = 702 const std::string last_used_profile =
697 local_state->GetString(prefs::kProfileLastUsed); 703 g_browser_process->local_state()->GetString(prefs::kProfileLastUsed);
698 if (last_used_profile == profile_dir.BaseName().MaybeAsASCII() || 704 if (last_used_profile == profile_dir.BaseName().MaybeAsASCII() ||
699 last_used_profile == GetGuestProfilePath().BaseName().MaybeAsASCII()) { 705 last_used_profile == GetGuestProfilePath().BaseName().MaybeAsASCII()) {
700 const std::string last_non_supervised_profile = 706 CreateProfileAsync(last_non_supervised_profile_path,
701 last_non_supervised_profile_path.BaseName().MaybeAsASCII(); 707 base::Bind(&ProfileManager::OnNewActiveProfileLoaded,
702 if (last_non_supervised_profile.empty()) { 708 base::Unretained(this),
703 DCHECK(!new_path.empty()); 709 profile_dir,
704 local_state->SetString(prefs::kProfileLastUsed, 710 last_non_supervised_profile_path,
705 new_path.BaseName().MaybeAsASCII()); 711 callback),
706 } else { 712 base::string16(),
707 // On the Mac, the browser process is not killed when all browser windows 713 base::string16(),
708 // are closed, so just in case we are deleting the active profile, and no 714 std::string());
709 // other profile has been loaded, we must pre-load a next one. 715 return;
710 #if defined(OS_MACOSX)
711 CreateProfileAsync(last_non_supervised_profile_path,
712 base::Bind(&ProfileManager::OnNewActiveProfileLoaded,
713 base::Unretained(this),
714 profile_dir,
715 last_non_supervised_profile_path,
716 callback),
717 base::string16(),
718 base::string16(),
719 std::string());
720 return;
721 #else
722 // For OS_MACOSX the pref is updated in the callback to make sure that
723 // it isn't used before the profile is actually loaded.
724 local_state->SetString(prefs::kProfileLastUsed,
725 last_non_supervised_profile);
726 #endif
727 }
728 } 716 }
729 FinishDeletingProfile(profile_dir); 717 #endif // defined(OS_MACOSX)
718
719 FinishDeletingProfile(profile_dir, last_non_supervised_profile_path);
730 } 720 }
731 721
732 // static 722 // static
733 void ProfileManager::CleanUpStaleProfiles( 723 void ProfileManager::CleanUpStaleProfiles(
734 const std::vector<base::FilePath>& profile_paths) { 724 const std::vector<base::FilePath>& profile_paths) {
735 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 725 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
736 726
737 for (std::vector<base::FilePath>::const_iterator it = profile_paths.begin(); 727 for (std::vector<base::FilePath>::const_iterator it = profile_paths.begin();
738 it != profile_paths.end(); ++it) { 728 it != profile_paths.end(); ++it) {
739 NukeProfileFromDisk(*it); 729 NukeProfileFromDisk(*it);
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after
1153 CHECK(!GetProfileByPathInternal(profile_dir)); 1143 CHECK(!GetProfileByPathInternal(profile_dir));
1154 Profile* profile = CreateProfileHelper(profile_dir); 1144 Profile* profile = CreateProfileHelper(profile_dir);
1155 DCHECK(profile); 1145 DCHECK(profile);
1156 if (profile) { 1146 if (profile) {
1157 bool result = AddProfile(profile); 1147 bool result = AddProfile(profile);
1158 DCHECK(result); 1148 DCHECK(result);
1159 } 1149 }
1160 return profile; 1150 return profile;
1161 } 1151 }
1162 1152
1163 void ProfileManager::FinishDeletingProfile(const base::FilePath& profile_dir) { 1153 void ProfileManager::FinishDeletingProfile(
1154 const base::FilePath& profile_dir,
1155 const base::FilePath& new_active_profile_dir) {
1156 // Update the last used profile pref before closing browser windows. This
1157 // way the correct last used profile is set for any notification observers.
1158 g_browser_process->local_state()->SetString(
1159 prefs::kProfileLastUsed,
1160 new_active_profile_dir.BaseName().MaybeAsASCII());
1161
1164 ProfileInfoCache& cache = GetProfileInfoCache(); 1162 ProfileInfoCache& cache = GetProfileInfoCache();
1165 // TODO(sail): Due to bug 88586 we don't delete the profile instance. Once we 1163 // TODO(sail): Due to bug 88586 we don't delete the profile instance. Once we
1166 // start deleting the profile instance we need to close background apps too. 1164 // start deleting the profile instance we need to close background apps too.
1167 Profile* profile = GetProfileByPath(profile_dir); 1165 Profile* profile = GetProfileByPath(profile_dir);
1168 1166
1169 if (profile) { 1167 if (profile) {
1170 // TODO: Migrate additional code in this block to observe this notification 1168 // TODO: Migrate additional code in this block to observe this notification
1171 // instead of being implemented here. 1169 // instead of being implemented here.
1172 content::NotificationService::current()->Notify( 1170 content::NotificationService::current()->Notify(
1173 chrome::NOTIFICATION_PROFILE_DESTRUCTION_STARTED, 1171 chrome::NOTIFICATION_PROFILE_DESTRUCTION_STARTED,
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
1365 1363
1366 // Don't remember ephemeral profiles as last because they are not going to 1364 // Don't remember ephemeral profiles as last because they are not going to
1367 // persist after restart. 1365 // persist after restart.
1368 if (last_active->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles)) 1366 if (last_active->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles))
1369 return; 1367 return;
1370 1368
1371 profile_manager_->UpdateLastUser(last_active); 1369 profile_manager_->UpdateLastUser(last_active);
1372 } 1370 }
1373 #endif // !defined(OS_ANDROID) && !defined(OS_IOS) 1371 #endif // !defined(OS_ANDROID) && !defined(OS_IOS)
1374 1372
1375 #if defined(OS_MACOSX)
1376 void ProfileManager::OnNewActiveProfileLoaded( 1373 void ProfileManager::OnNewActiveProfileLoaded(
1377 const base::FilePath& profile_to_delete_path, 1374 const base::FilePath& profile_to_delete_path,
1378 const base::FilePath& last_non_supervised_profile_path, 1375 const base::FilePath& new_active_profile_path,
1379 const CreateCallback& original_callback, 1376 const CreateCallback& original_callback,
1380 Profile* loaded_profile, 1377 Profile* loaded_profile,
1381 Profile::CreateStatus status) { 1378 Profile::CreateStatus status) {
1382 DCHECK(status != Profile::CREATE_STATUS_LOCAL_FAIL && 1379 DCHECK(status != Profile::CREATE_STATUS_LOCAL_FAIL &&
1383 status != Profile::CREATE_STATUS_REMOTE_FAIL); 1380 status != Profile::CREATE_STATUS_REMOTE_FAIL);
1384 1381
1385 // Only run the code if the profile initialization has finished completely. 1382 // Only run the code if the profile initialization has finished completely.
1386 if (status == Profile::CREATE_STATUS_INITIALIZED) { 1383 if (status != Profile::CREATE_STATUS_INITIALIZED)
1387 if (IsProfileMarkedForDeletion(last_non_supervised_profile_path)) { 1384 return;
1388 // If the profile we tried to load as the next active profile has been 1385
1389 // deleted, then retry deleting this profile to redo the logic to load 1386 if (IsProfileMarkedForDeletion(new_active_profile_path)) {
1390 // the next available profile. 1387 // If the profile we tried to load as the next active profile has been
1391 ScheduleProfileForDeletion(profile_to_delete_path, original_callback); 1388 // deleted, then retry deleting this profile to redo the logic to load
1392 } else { 1389 // the next available profile.
1393 // Update the local state as promised in the ScheduleProfileForDeletion. 1390 ScheduleProfileForDeletion(profile_to_delete_path, original_callback);
1394 g_browser_process->local_state()->SetString( 1391 return;
1395 prefs::kProfileLastUsed,
1396 last_non_supervised_profile_path.BaseName().MaybeAsASCII());
1397 FinishDeletingProfile(profile_to_delete_path);
1398 }
1399 } 1392 }
1393
1394 FinishDeletingProfile(profile_to_delete_path, new_active_profile_path);
1395 if (!original_callback.is_null())
1396 original_callback.Run(loaded_profile, status);
1400 } 1397 }
1401 #endif
1402 1398
1403 ProfileManagerWithoutInit::ProfileManagerWithoutInit( 1399 ProfileManagerWithoutInit::ProfileManagerWithoutInit(
1404 const base::FilePath& user_data_dir) : ProfileManager(user_data_dir) { 1400 const base::FilePath& user_data_dir) : ProfileManager(user_data_dir) {
1405 } 1401 }
OLDNEW
« no previous file with comments | « chrome/browser/profiles/profile_manager.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698