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

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

Powered by Google App Engine
This is Rietveld 408576698