OLD | NEW |
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 Loading... |
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 Loading... |
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(); |
653 ProfileInfoCache& cache = GetProfileInfoCache(); | 654 ProfileInfoCache& cache = GetProfileInfoCache(); |
654 | 655 |
655 // If we're deleting the last (non-legacy-supervised) profile, then create a | 656 // If we're deleting the last (non-legacy-supervised) profile, then create a |
656 // new profile in its place. | 657 // new profile in its place. |
657 base::FilePath last_non_supervised_profile_path; | 658 base::FilePath last_non_supervised_profile_path; |
658 for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) { | 659 for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) { |
659 base::FilePath cur_path = cache.GetPathOfProfileAtIndex(i); | 660 base::FilePath cur_path = cache.GetPathOfProfileAtIndex(i); |
660 // Make sure that this profile is not pending deletion, and is not | 661 // Make sure that this profile is not pending deletion, and is not |
661 // legacy-supervised. | 662 // legacy-supervised. |
662 if (cur_path != profile_dir && | 663 if (cur_path != profile_dir && |
(...skipping 11 matching lines...) Expand all Loading... |
674 bool is_new_avatar_menu = switches::IsNewAvatarMenu(); | 675 bool is_new_avatar_menu = switches::IsNewAvatarMenu(); |
675 int avatar_index = profiles::GetPlaceholderAvatarIndex(); | 676 int avatar_index = profiles::GetPlaceholderAvatarIndex(); |
676 base::string16 new_avatar_url = is_new_avatar_menu ? | 677 base::string16 new_avatar_url = is_new_avatar_menu ? |
677 base::UTF8ToUTF16(profiles::GetDefaultAvatarIconUrl(avatar_index)) : | 678 base::UTF8ToUTF16(profiles::GetDefaultAvatarIconUrl(avatar_index)) : |
678 base::string16(); | 679 base::string16(); |
679 base::string16 new_profile_name = is_new_avatar_menu ? | 680 base::string16 new_profile_name = is_new_avatar_menu ? |
680 cache.ChooseNameForNewProfile(avatar_index) : base::string16(); | 681 cache.ChooseNameForNewProfile(avatar_index) : base::string16(); |
681 | 682 |
682 new_path = GenerateNextProfileDirectoryPath(); | 683 new_path = GenerateNextProfileDirectoryPath(); |
683 CreateProfileAsync(new_path, | 684 CreateProfileAsync(new_path, |
684 base::Bind(&ProfileManager::OnNewActiveProfileLoaded, | 685 callback, |
685 base::Unretained(this), | |
686 profile_dir, | |
687 new_path, | |
688 callback), | |
689 new_profile_name, | 686 new_profile_name, |
690 new_avatar_url, | 687 new_avatar_url, |
691 std::string()); | 688 std::string()); |
692 | 689 |
693 ProfileMetrics::LogProfileAddNewUser( | 690 ProfileMetrics::LogProfileAddNewUser( |
694 ProfileMetrics::ADD_NEW_USER_LAST_DELETED); | 691 ProfileMetrics::ADD_NEW_USER_LAST_DELETED); |
695 return; | |
696 } | 692 } |
697 | 693 |
698 #if defined(OS_MACOSX) | 694 // Update the last used profile pref before closing browser windows. This |
699 // On the Mac, the browser process is not killed when all browser windows are | 695 // way the correct last used profile is set for any notification observers. |
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. | |
702 const std::string last_used_profile = | 696 const std::string last_used_profile = |
703 g_browser_process->local_state()->GetString(prefs::kProfileLastUsed); | 697 local_state->GetString(prefs::kProfileLastUsed); |
704 if (last_used_profile == profile_dir.BaseName().MaybeAsASCII() || | 698 if (last_used_profile == profile_dir.BaseName().MaybeAsASCII() || |
705 last_used_profile == GetGuestProfilePath().BaseName().MaybeAsASCII()) { | 699 last_used_profile == GetGuestProfilePath().BaseName().MaybeAsASCII()) { |
706 CreateProfileAsync(last_non_supervised_profile_path, | 700 const std::string last_non_supervised_profile = |
707 base::Bind(&ProfileManager::OnNewActiveProfileLoaded, | 701 last_non_supervised_profile_path.BaseName().MaybeAsASCII(); |
708 base::Unretained(this), | 702 if (last_non_supervised_profile.empty()) { |
709 profile_dir, | 703 DCHECK(!new_path.empty()); |
710 last_non_supervised_profile_path, | 704 local_state->SetString(prefs::kProfileLastUsed, |
711 callback), | 705 new_path.BaseName().MaybeAsASCII()); |
712 base::string16(), | 706 } else { |
713 base::string16(), | 707 // On the Mac, the browser process is not killed when all browser windows |
714 std::string()); | 708 // are closed, so just in case we are deleting the active profile, and no |
715 return; | 709 // other profile has been loaded, we must pre-load a next one. |
| 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 } |
716 } | 728 } |
717 #endif // defined(OS_MACOSX) | 729 FinishDeletingProfile(profile_dir); |
718 | |
719 FinishDeletingProfile(profile_dir, last_non_supervised_profile_path); | |
720 } | 730 } |
721 | 731 |
722 // static | 732 // static |
723 void ProfileManager::CleanUpStaleProfiles( | 733 void ProfileManager::CleanUpStaleProfiles( |
724 const std::vector<base::FilePath>& profile_paths) { | 734 const std::vector<base::FilePath>& profile_paths) { |
725 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 735 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
726 | 736 |
727 for (std::vector<base::FilePath>::const_iterator it = profile_paths.begin(); | 737 for (std::vector<base::FilePath>::const_iterator it = profile_paths.begin(); |
728 it != profile_paths.end(); ++it) { | 738 it != profile_paths.end(); ++it) { |
729 NukeProfileFromDisk(*it); | 739 NukeProfileFromDisk(*it); |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1143 CHECK(!GetProfileByPathInternal(profile_dir)); | 1153 CHECK(!GetProfileByPathInternal(profile_dir)); |
1144 Profile* profile = CreateProfileHelper(profile_dir); | 1154 Profile* profile = CreateProfileHelper(profile_dir); |
1145 DCHECK(profile); | 1155 DCHECK(profile); |
1146 if (profile) { | 1156 if (profile) { |
1147 bool result = AddProfile(profile); | 1157 bool result = AddProfile(profile); |
1148 DCHECK(result); | 1158 DCHECK(result); |
1149 } | 1159 } |
1150 return profile; | 1160 return profile; |
1151 } | 1161 } |
1152 | 1162 |
1153 void ProfileManager::FinishDeletingProfile( | 1163 void ProfileManager::FinishDeletingProfile(const base::FilePath& profile_dir) { |
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 | |
1162 ProfileInfoCache& cache = GetProfileInfoCache(); | 1164 ProfileInfoCache& cache = GetProfileInfoCache(); |
1163 // TODO(sail): Due to bug 88586 we don't delete the profile instance. Once we | 1165 // TODO(sail): Due to bug 88586 we don't delete the profile instance. Once we |
1164 // start deleting the profile instance we need to close background apps too. | 1166 // start deleting the profile instance we need to close background apps too. |
1165 Profile* profile = GetProfileByPath(profile_dir); | 1167 Profile* profile = GetProfileByPath(profile_dir); |
1166 | 1168 |
1167 if (profile) { | 1169 if (profile) { |
1168 // TODO: Migrate additional code in this block to observe this notification | 1170 // TODO: Migrate additional code in this block to observe this notification |
1169 // instead of being implemented here. | 1171 // instead of being implemented here. |
1170 content::NotificationService::current()->Notify( | 1172 content::NotificationService::current()->Notify( |
1171 chrome::NOTIFICATION_PROFILE_DESTRUCTION_STARTED, | 1173 chrome::NOTIFICATION_PROFILE_DESTRUCTION_STARTED, |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1363 | 1365 |
1364 // Don't remember ephemeral profiles as last because they are not going to | 1366 // Don't remember ephemeral profiles as last because they are not going to |
1365 // persist after restart. | 1367 // persist after restart. |
1366 if (last_active->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles)) | 1368 if (last_active->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles)) |
1367 return; | 1369 return; |
1368 | 1370 |
1369 profile_manager_->UpdateLastUser(last_active); | 1371 profile_manager_->UpdateLastUser(last_active); |
1370 } | 1372 } |
1371 #endif // !defined(OS_ANDROID) && !defined(OS_IOS) | 1373 #endif // !defined(OS_ANDROID) && !defined(OS_IOS) |
1372 | 1374 |
| 1375 #if defined(OS_MACOSX) |
1373 void ProfileManager::OnNewActiveProfileLoaded( | 1376 void ProfileManager::OnNewActiveProfileLoaded( |
1374 const base::FilePath& profile_to_delete_path, | 1377 const base::FilePath& profile_to_delete_path, |
1375 const base::FilePath& new_active_profile_path, | 1378 const base::FilePath& last_non_supervised_profile_path, |
1376 const CreateCallback& original_callback, | 1379 const CreateCallback& original_callback, |
1377 Profile* loaded_profile, | 1380 Profile* loaded_profile, |
1378 Profile::CreateStatus status) { | 1381 Profile::CreateStatus status) { |
1379 DCHECK(status != Profile::CREATE_STATUS_LOCAL_FAIL && | 1382 DCHECK(status != Profile::CREATE_STATUS_LOCAL_FAIL && |
1380 status != Profile::CREATE_STATUS_REMOTE_FAIL); | 1383 status != Profile::CREATE_STATUS_REMOTE_FAIL); |
1381 | 1384 |
1382 // Only run the code if the profile initialization has finished completely. | 1385 // Only run the code if the profile initialization has finished completely. |
1383 if (status != Profile::CREATE_STATUS_INITIALIZED) | 1386 if (status == Profile::CREATE_STATUS_INITIALIZED) { |
1384 return; | 1387 if (IsProfileMarkedForDeletion(last_non_supervised_profile_path)) { |
1385 | 1388 // If the profile we tried to load as the next active profile has been |
1386 if (IsProfileMarkedForDeletion(new_active_profile_path)) { | 1389 // deleted, then retry deleting this profile to redo the logic to load |
1387 // If the profile we tried to load as the next active profile has been | 1390 // the next available profile. |
1388 // deleted, then retry deleting this profile to redo the logic to load | 1391 ScheduleProfileForDeletion(profile_to_delete_path, original_callback); |
1389 // the next available profile. | 1392 } else { |
1390 ScheduleProfileForDeletion(profile_to_delete_path, original_callback); | 1393 // Update the local state as promised in the ScheduleProfileForDeletion. |
1391 return; | 1394 g_browser_process->local_state()->SetString( |
| 1395 prefs::kProfileLastUsed, |
| 1396 last_non_supervised_profile_path.BaseName().MaybeAsASCII()); |
| 1397 FinishDeletingProfile(profile_to_delete_path); |
| 1398 } |
1392 } | 1399 } |
1393 | |
1394 FinishDeletingProfile(profile_to_delete_path, new_active_profile_path); | |
1395 if (!original_callback.is_null()) | |
1396 original_callback.Run(loaded_profile, status); | |
1397 } | 1400 } |
| 1401 #endif |
1398 | 1402 |
1399 ProfileManagerWithoutInit::ProfileManagerWithoutInit( | 1403 ProfileManagerWithoutInit::ProfileManagerWithoutInit( |
1400 const base::FilePath& user_data_dir) : ProfileManager(user_data_dir) { | 1404 const base::FilePath& user_data_dir) : ProfileManager(user_data_dir) { |
1401 } | 1405 } |
OLD | NEW |