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 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 | 154 |
155 // Count number of extensions in this profile, if we know. | 155 // Count number of extensions in this profile, if we know. |
156 if (extension_count != -1) | 156 if (extension_count != -1) |
157 UMA_HISTOGRAM_COUNTS_10000("Profile.AppCount", extension_count); | 157 UMA_HISTOGRAM_COUNTS_10000("Profile.AppCount", extension_count); |
158 } | 158 } |
159 | 159 |
160 void QueueProfileDirectoryForDeletion(const base::FilePath& path) { | 160 void QueueProfileDirectoryForDeletion(const base::FilePath& path) { |
161 ProfilesToDelete().push_back(path); | 161 ProfilesToDelete().push_back(path); |
162 } | 162 } |
163 | 163 |
| 164 bool IsProfileMarkedForDeletion(const base::FilePath& profile_path) { |
| 165 return std::find(ProfilesToDelete().begin(), ProfilesToDelete().end(), |
| 166 profile_path) != ProfilesToDelete().end(); |
| 167 } |
| 168 |
164 #if defined(OS_CHROMEOS) | 169 #if defined(OS_CHROMEOS) |
165 void CheckCryptohomeIsMounted(chromeos::DBusMethodCallStatus call_status, | 170 void CheckCryptohomeIsMounted(chromeos::DBusMethodCallStatus call_status, |
166 bool is_mounted) { | 171 bool is_mounted) { |
167 if (call_status != chromeos::DBUS_METHOD_CALL_SUCCESS) { | 172 if (call_status != chromeos::DBUS_METHOD_CALL_SUCCESS) { |
168 LOG(ERROR) << "IsMounted call failed."; | 173 LOG(ERROR) << "IsMounted call failed."; |
169 return; | 174 return; |
170 } | 175 } |
171 if (!is_mounted) | 176 if (!is_mounted) |
172 LOG(ERROR) << "Cryptohome is not mounted."; | 177 LOG(ERROR) << "Cryptohome is not mounted."; |
173 } | 178 } |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
487 | 492 |
488 void ProfileManager::CreateProfileAsync( | 493 void ProfileManager::CreateProfileAsync( |
489 const base::FilePath& profile_path, | 494 const base::FilePath& profile_path, |
490 const CreateCallback& callback, | 495 const CreateCallback& callback, |
491 const string16& name, | 496 const string16& name, |
492 const string16& icon_url, | 497 const string16& icon_url, |
493 bool is_managed) { | 498 bool is_managed) { |
494 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 499 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
495 | 500 |
496 // Make sure that this profile is not pending deletion. | 501 // Make sure that this profile is not pending deletion. |
497 if (std::find(ProfilesToDelete().begin(), ProfilesToDelete().end(), | 502 if (IsProfileMarkedForDeletion(profile_path)) { |
498 profile_path) != ProfilesToDelete().end()) { | |
499 if (!callback.is_null()) | 503 if (!callback.is_null()) |
500 callback.Run(NULL, Profile::CREATE_STATUS_LOCAL_FAIL); | 504 callback.Run(NULL, Profile::CREATE_STATUS_LOCAL_FAIL); |
501 return; | 505 return; |
502 } | 506 } |
503 | 507 |
504 // Create the profile if needed and collect its ProfileInfo. | 508 // Create the profile if needed and collect its ProfileInfo. |
505 ProfilesInfoMap::iterator iter = profiles_info_.find(profile_path); | 509 ProfilesInfoMap::iterator iter = profiles_info_.find(profile_path); |
506 ProfileInfo* info = NULL; | 510 ProfileInfo* info = NULL; |
507 | 511 |
508 if (iter != profiles_info_.end()) { | 512 if (iter != profiles_info_.end()) { |
(...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1035 go_off_the_record = true; | 1039 go_off_the_record = true; |
1036 } | 1040 } |
1037 #endif | 1041 #endif |
1038 return go_off_the_record; | 1042 return go_off_the_record; |
1039 } | 1043 } |
1040 | 1044 |
1041 void ProfileManager::ScheduleProfileForDeletion( | 1045 void ProfileManager::ScheduleProfileForDeletion( |
1042 const base::FilePath& profile_dir, | 1046 const base::FilePath& profile_dir, |
1043 const CreateCallback& callback) { | 1047 const CreateCallback& callback) { |
1044 DCHECK(IsMultipleProfilesEnabled()); | 1048 DCHECK(IsMultipleProfilesEnabled()); |
1045 | |
1046 PrefService* local_state = g_browser_process->local_state(); | 1049 PrefService* local_state = g_browser_process->local_state(); |
1047 ProfileInfoCache& cache = GetProfileInfoCache(); | 1050 ProfileInfoCache& cache = GetProfileInfoCache(); |
| 1051 |
1048 if (profile_dir.BaseName().MaybeAsASCII() == | 1052 if (profile_dir.BaseName().MaybeAsASCII() == |
1049 local_state->GetString(prefs::kProfileLastUsed)) { | 1053 local_state->GetString(prefs::kProfileLastUsed)) { |
1050 // Update the last used profile pref before closing browser windows. This | 1054 // Update the last used profile pref before closing browser windows. This |
1051 // way the correct last used profile is set for any notification observers. | 1055 // way the correct last used profile is set for any notification observers. |
1052 std::string last_non_managed_profile; | 1056 base::FilePath last_non_managed_profile_path; |
1053 for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) { | 1057 for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) { |
1054 base::FilePath cur_path = cache.GetPathOfProfileAtIndex(i); | 1058 base::FilePath cur_path = cache.GetPathOfProfileAtIndex(i); |
1055 if (cur_path != profile_dir && !cache.ProfileIsManagedAtIndex(i)) { | 1059 // Make sure that this profile is not pending deletion. |
1056 last_non_managed_profile = cur_path.BaseName().MaybeAsASCII(); | 1060 if (cur_path != profile_dir && !cache.ProfileIsManagedAtIndex(i) && |
| 1061 !IsProfileMarkedForDeletion(cur_path)) { |
| 1062 last_non_managed_profile_path = cur_path; |
1057 break; | 1063 break; |
1058 } | 1064 } |
1059 } | 1065 } |
| 1066 |
1060 // If we're deleting the last (non-managed) profile, then create a new | 1067 // If we're deleting the last (non-managed) profile, then create a new |
1061 // profile in its place. | 1068 // profile in its place. |
| 1069 const std::string last_non_managed_profile = |
| 1070 last_non_managed_profile_path.BaseName().MaybeAsASCII(); |
1062 if (last_non_managed_profile.empty()) { | 1071 if (last_non_managed_profile.empty()) { |
1063 base::FilePath new_path = GenerateNextProfileDirectoryPath(); | 1072 base::FilePath new_path = GenerateNextProfileDirectoryPath(); |
1064 // Make sure the last used profile path is pointing at it. This way the | 1073 // Make sure the last used profile path is pointing at it. This way the |
1065 // correct last used profile is set for any notification observers. | 1074 // correct last used profile is set for any notification observers. |
1066 local_state->SetString(prefs::kProfileLastUsed, | 1075 local_state->SetString(prefs::kProfileLastUsed, |
1067 new_path.BaseName().MaybeAsASCII()); | 1076 new_path.BaseName().MaybeAsASCII()); |
1068 CreateProfileAsync(new_path, | 1077 CreateProfileAsync(new_path, |
1069 callback, | 1078 callback, |
1070 string16(), | 1079 string16(), |
1071 string16(), | 1080 string16(), |
1072 false); | 1081 false); |
1073 } else { | 1082 } else { |
| 1083 // On the Mac, the browser process is not killed when all browser windows |
| 1084 // are closed, so just in case we are deleting the active profile, and no |
| 1085 // other profile has been loaded, we must pre-load a next one. |
| 1086 #if defined(OS_MACOSX) |
| 1087 CreateProfileAsync(last_non_managed_profile_path, |
| 1088 base::Bind(&ProfileManager::OnNewActiveProfileLoaded, |
| 1089 base::Unretained(this), |
| 1090 profile_dir, |
| 1091 last_non_managed_profile_path, |
| 1092 callback), |
| 1093 string16(), |
| 1094 string16(), |
| 1095 false); |
| 1096 return; |
| 1097 #else |
| 1098 // For OS_MACOSX the pref is updated in the callback to make sure that |
| 1099 // it isn't used before the profile is actually loaded. |
1074 local_state->SetString(prefs::kProfileLastUsed, last_non_managed_profile); | 1100 local_state->SetString(prefs::kProfileLastUsed, last_non_managed_profile); |
| 1101 #endif |
1075 } | 1102 } |
1076 } | 1103 } |
| 1104 FinishDeletingProfile(profile_dir); |
| 1105 } |
1077 | 1106 |
| 1107 void ProfileManager::OnNewActiveProfileLoaded( |
| 1108 const base::FilePath& profile_to_delete_path, |
| 1109 const base::FilePath& last_non_managed_profile_path, |
| 1110 const CreateCallback& original_callback, |
| 1111 Profile* loaded_profile, |
| 1112 Profile::CreateStatus status) { |
| 1113 DCHECK(status != Profile::CREATE_STATUS_LOCAL_FAIL && |
| 1114 status != Profile::CREATE_STATUS_REMOTE_FAIL); |
| 1115 |
| 1116 // Only run the code if the profile initialization has finished completely. |
| 1117 if (status == Profile::CREATE_STATUS_INITIALIZED) { |
| 1118 if (IsProfileMarkedForDeletion(last_non_managed_profile_path)) { |
| 1119 // If the profile we tried to load as the next active profile has been |
| 1120 // deleted, then retry deleting this profile to redo the logic to load |
| 1121 // the next available profile. |
| 1122 ScheduleProfileForDeletion(profile_to_delete_path, original_callback); |
| 1123 } else { |
| 1124 // Update the local state as promised in the ScheduleProfileForDeletion. |
| 1125 g_browser_process->local_state()->SetString( |
| 1126 prefs::kProfileLastUsed, |
| 1127 last_non_managed_profile_path.BaseName().MaybeAsASCII()); |
| 1128 FinishDeletingProfile(profile_to_delete_path); |
| 1129 } |
| 1130 } |
| 1131 } |
| 1132 |
| 1133 void ProfileManager::FinishDeletingProfile(const base::FilePath& profile_dir) { |
| 1134 ProfileInfoCache& cache = GetProfileInfoCache(); |
1078 // TODO(sail): Due to bug 88586 we don't delete the profile instance. Once we | 1135 // TODO(sail): Due to bug 88586 we don't delete the profile instance. Once we |
1079 // start deleting the profile instance we need to close background apps too. | 1136 // start deleting the profile instance we need to close background apps too. |
1080 Profile* profile = GetProfileByPath(profile_dir); | 1137 Profile* profile = GetProfileByPath(profile_dir); |
| 1138 |
1081 if (profile) { | 1139 if (profile) { |
1082 BrowserList::CloseAllBrowsersWithProfile(profile); | 1140 BrowserList::CloseAllBrowsersWithProfile(profile); |
1083 | 1141 |
1084 // Disable sync for doomed profile. | 1142 // Disable sync for doomed profile. |
1085 if (ProfileSyncServiceFactory::GetInstance()->HasProfileSyncService( | 1143 if (ProfileSyncServiceFactory::GetInstance()->HasProfileSyncService( |
1086 profile)) { | 1144 profile)) { |
1087 ProfileSyncServiceFactory::GetInstance()->GetForProfile( | 1145 ProfileSyncServiceFactory::GetInstance()->GetForProfile( |
1088 profile)->DisableForUser(); | 1146 profile)->DisableForUser(); |
1089 } | 1147 } |
1090 } | 1148 } |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1155 ProfileManager::ProfileInfo::ProfileInfo( | 1213 ProfileManager::ProfileInfo::ProfileInfo( |
1156 Profile* profile, | 1214 Profile* profile, |
1157 bool created) | 1215 bool created) |
1158 : profile(profile), | 1216 : profile(profile), |
1159 created(created) { | 1217 created(created) { |
1160 } | 1218 } |
1161 | 1219 |
1162 ProfileManager::ProfileInfo::~ProfileInfo() { | 1220 ProfileManager::ProfileInfo::~ProfileInfo() { |
1163 ProfileDestroyer::DestroyProfileWhenAppropriate(profile.release()); | 1221 ProfileDestroyer::DestroyProfileWhenAppropriate(profile.release()); |
1164 } | 1222 } |
OLD | NEW |