Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / profiles / profile_manager.cc
blobc4ce8f7dfc26b0051dd200356538d459b2eb7eb5
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
3 // found in the LICENSE file.
5 #include "chrome/browser/profiles/profile_manager.h"
7 #include <set>
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/debug/trace_event.h"
12 #include "base/deferred_sequenced_task_runner.h"
13 #include "base/file_util.h"
14 #include "base/files/file_enumerator.h"
15 #include "base/files/file_path.h"
16 #include "base/metrics/histogram.h"
17 #include "base/prefs/pref_service.h"
18 #include "base/prefs/scoped_user_pref_update.h"
19 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "chrome/browser/bookmarks/bookmark_model.h"
23 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
24 #include "chrome/browser/browser_process.h"
25 #include "chrome/browser/chrome_notification_types.h"
26 #include "chrome/browser/content_settings/host_content_settings_map.h"
27 #include "chrome/browser/prefs/incognito_mode_prefs.h"
28 #include "chrome/browser/profiles/bookmark_model_loaded_observer.h"
29 #include "chrome/browser/profiles/profile_destroyer.h"
30 #include "chrome/browser/profiles/profile_info_cache.h"
31 #include "chrome/browser/profiles/profile_metrics.h"
32 #include "chrome/browser/profiles/profiles_state.h"
33 #include "chrome/browser/profiles/startup_task_runner_service.h"
34 #include "chrome/browser/profiles/startup_task_runner_service_factory.h"
35 #include "chrome/browser/signin/account_reconcilor_factory.h"
36 #include "chrome/browser/sync/profile_sync_service.h"
37 #include "chrome/browser/sync/profile_sync_service_factory.h"
38 #include "chrome/browser/ui/browser.h"
39 #include "chrome/browser/ui/browser_iterator.h"
40 #include "chrome/browser/ui/sync/sync_promo_ui.h"
41 #include "chrome/common/chrome_constants.h"
42 #include "chrome/common/chrome_paths_internal.h"
43 #include "chrome/common/chrome_switches.h"
44 #include "chrome/common/logging_chrome.h"
45 #include "chrome/common/pref_names.h"
46 #include "chrome/common/profile_management_switches.h"
47 #include "chrome/common/url_constants.h"
48 #include "content/public/browser/browser_thread.h"
49 #include "content/public/browser/notification_service.h"
50 #include "content/public/browser/user_metrics.h"
51 #include "grit/generated_resources.h"
52 #include "net/http/http_transaction_factory.h"
53 #include "net/url_request/url_request_context.h"
54 #include "net/url_request/url_request_context_getter.h"
55 #include "net/url_request/url_request_job.h"
56 #include "ui/base/l10n/l10n_util.h"
58 #if defined(ENABLE_MANAGED_USERS)
59 #include "chrome/browser/managed_mode/managed_user_service.h"
60 #include "chrome/browser/managed_mode/managed_user_service_factory.h"
61 #endif
63 #if !defined(OS_IOS)
64 #include "chrome/browser/extensions/extension_service.h"
65 #include "chrome/browser/extensions/extension_system.h"
66 #include "chrome/browser/sessions/session_service_factory.h"
67 #include "chrome/browser/ui/browser_list.h"
68 #endif // !defined (OS_IOS)
70 #if defined(OS_WIN)
71 #include "base/win/metro.h"
72 #include "chrome/installer/util/browser_distribution.h"
73 #endif
75 #if defined(OS_CHROMEOS)
76 #include "chrome/browser/browser_process_platform_part_chromeos.h"
77 #include "chrome/browser/chromeos/login/user.h"
78 #include "chrome/browser/chromeos/login/user_manager.h"
79 #include "chrome/browser/chromeos/profiles/profile_helper.h"
80 #include "chromeos/chromeos_switches.h"
81 #include "chromeos/dbus/cryptohome_client.h"
82 #include "chromeos/dbus/dbus_thread_manager.h"
83 #endif
85 using base::UserMetricsAction;
86 using content::BrowserThread;
88 namespace {
90 // Profiles that should be deleted on shutdown.
91 std::vector<base::FilePath>& ProfilesToDelete() {
92 CR_DEFINE_STATIC_LOCAL(std::vector<base::FilePath>, profiles_to_delete, ());
93 return profiles_to_delete;
96 int64 ComputeFilesSize(const base::FilePath& directory,
97 const base::FilePath::StringType& pattern) {
98 int64 running_size = 0;
99 base::FileEnumerator iter(directory, false, base::FileEnumerator::FILES,
100 pattern);
101 while (!iter.Next().empty())
102 running_size += iter.GetInfo().GetSize();
103 return running_size;
106 // Simple task to log the size of the current profile.
107 void ProfileSizeTask(const base::FilePath& path, int extension_count) {
108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
109 const int64 kBytesInOneMB = 1024 * 1024;
111 int64 size = ComputeFilesSize(path, FILE_PATH_LITERAL("*"));
112 int size_MB = static_cast<int>(size / kBytesInOneMB);
113 UMA_HISTOGRAM_COUNTS_10000("Profile.TotalSize", size_MB);
115 size = ComputeFilesSize(path, FILE_PATH_LITERAL("History"));
116 size_MB = static_cast<int>(size / kBytesInOneMB);
117 UMA_HISTOGRAM_COUNTS_10000("Profile.HistorySize", size_MB);
119 size = ComputeFilesSize(path, FILE_PATH_LITERAL("History*"));
120 size_MB = static_cast<int>(size / kBytesInOneMB);
121 UMA_HISTOGRAM_COUNTS_10000("Profile.TotalHistorySize", size_MB);
123 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Cookies"));
124 size_MB = static_cast<int>(size / kBytesInOneMB);
125 UMA_HISTOGRAM_COUNTS_10000("Profile.CookiesSize", size_MB);
127 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Bookmarks"));
128 size_MB = static_cast<int>(size / kBytesInOneMB);
129 UMA_HISTOGRAM_COUNTS_10000("Profile.BookmarksSize", size_MB);
131 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Favicons"));
132 size_MB = static_cast<int>(size / kBytesInOneMB);
133 UMA_HISTOGRAM_COUNTS_10000("Profile.FaviconsSize", size_MB);
135 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Top Sites"));
136 size_MB = static_cast<int>(size / kBytesInOneMB);
137 UMA_HISTOGRAM_COUNTS_10000("Profile.TopSitesSize", size_MB);
139 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Visited Links"));
140 size_MB = static_cast<int>(size / kBytesInOneMB);
141 UMA_HISTOGRAM_COUNTS_10000("Profile.VisitedLinksSize", size_MB);
143 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Web Data"));
144 size_MB = static_cast<int>(size / kBytesInOneMB);
145 UMA_HISTOGRAM_COUNTS_10000("Profile.WebDataSize", size_MB);
147 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Extension*"));
148 size_MB = static_cast<int>(size / kBytesInOneMB);
149 UMA_HISTOGRAM_COUNTS_10000("Profile.ExtensionSize", size_MB);
151 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Policy"));
152 size_MB = static_cast<int>(size / kBytesInOneMB);
153 UMA_HISTOGRAM_COUNTS_10000("Profile.PolicySize", size_MB);
155 // Count number of extensions in this profile, if we know.
156 if (extension_count != -1)
157 UMA_HISTOGRAM_COUNTS_10000("Profile.AppCount", extension_count);
160 void QueueProfileDirectoryForDeletion(const base::FilePath& path) {
161 ProfilesToDelete().push_back(path);
164 bool IsProfileMarkedForDeletion(const base::FilePath& profile_path) {
165 return std::find(ProfilesToDelete().begin(), ProfilesToDelete().end(),
166 profile_path) != ProfilesToDelete().end();
169 // Physically remove deleted profile directories from disk.
170 void NukeProfileFromDisk(const base::FilePath& profile_path) {
171 // Delete both the profile directory and its corresponding cache.
172 base::FilePath cache_path;
173 chrome::GetUserCacheDirectory(profile_path, &cache_path);
174 base::DeleteFile(profile_path, true);
175 base::DeleteFile(cache_path, true);
178 #if defined(OS_CHROMEOS)
179 void CheckCryptohomeIsMounted(chromeos::DBusMethodCallStatus call_status,
180 bool is_mounted) {
181 if (call_status != chromeos::DBUS_METHOD_CALL_SUCCESS) {
182 LOG(ERROR) << "IsMounted call failed.";
183 return;
185 if (!is_mounted)
186 LOG(ERROR) << "Cryptohome is not mounted.";
189 #endif
191 } // namespace
193 ProfileManager::ProfileManager(const base::FilePath& user_data_dir)
194 : user_data_dir_(user_data_dir),
195 logged_in_(false),
196 #if !defined(OS_ANDROID) && !defined(OS_IOS)
197 browser_list_observer_(this),
198 #endif
199 closing_all_browsers_(false) {
200 #if defined(OS_CHROMEOS)
201 registrar_.Add(
202 this,
203 chrome::NOTIFICATION_LOGIN_USER_CHANGED,
204 content::NotificationService::AllSources());
205 #endif
206 registrar_.Add(
207 this,
208 chrome::NOTIFICATION_BROWSER_OPENED,
209 content::NotificationService::AllSources());
210 registrar_.Add(
211 this,
212 chrome::NOTIFICATION_BROWSER_CLOSED,
213 content::NotificationService::AllSources());
214 registrar_.Add(
215 this,
216 chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST,
217 content::NotificationService::AllSources());
218 registrar_.Add(
219 this,
220 chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED,
221 content::NotificationService::AllSources());
222 registrar_.Add(
223 this,
224 chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
225 content::NotificationService::AllSources());
227 if (ProfileShortcutManager::IsFeatureEnabled() && !user_data_dir_.empty())
228 profile_shortcut_manager_.reset(ProfileShortcutManager::Create(
229 this));
232 ProfileManager::~ProfileManager() {
235 #if defined(ENABLE_SESSION_SERVICE)
236 // static
237 void ProfileManager::ShutdownSessionServices() {
238 ProfileManager* pm = g_browser_process->profile_manager();
239 if (!pm) // Is NULL when running unit tests.
240 return;
241 std::vector<Profile*> profiles(pm->GetLoadedProfiles());
242 for (size_t i = 0; i < profiles.size(); ++i)
243 SessionServiceFactory::ShutdownForProfile(profiles[i]);
245 #endif
247 // static
248 void ProfileManager::NukeDeletedProfilesFromDisk() {
249 for (std::vector<base::FilePath>::iterator it =
250 ProfilesToDelete().begin();
251 it != ProfilesToDelete().end();
252 ++it) {
253 NukeProfileFromDisk(*it);
255 ProfilesToDelete().clear();
258 // static
259 Profile* ProfileManager::GetLastUsedProfile() {
260 ProfileManager* profile_manager = g_browser_process->profile_manager();
261 return profile_manager->GetLastUsedProfile(profile_manager->user_data_dir_);
264 // static
265 Profile* ProfileManager::GetLastUsedProfileAllowedByPolicy() {
266 Profile* profile = GetLastUsedProfile();
267 if (IncognitoModePrefs::GetAvailability(profile->GetPrefs()) ==
268 IncognitoModePrefs::FORCED) {
269 return profile->GetOffTheRecordProfile();
271 return profile;
274 // static
275 std::vector<Profile*> ProfileManager::GetLastOpenedProfiles() {
276 ProfileManager* profile_manager = g_browser_process->profile_manager();
277 return profile_manager->GetLastOpenedProfiles(
278 profile_manager->user_data_dir_);
281 // static
282 Profile* ProfileManager::GetPrimaryUserProfile() {
283 ProfileManager* profile_manager = g_browser_process->profile_manager();
284 #if defined(OS_CHROMEOS)
285 if (!profile_manager->IsLoggedIn() || !chromeos::UserManager::IsInitialized())
286 return profile_manager->GetActiveUserOrOffTheRecordProfileFromPath(
287 profile_manager->user_data_dir());
288 chromeos::UserManager* manager = chromeos::UserManager::Get();
289 // Note: The user manager will take care of guest profiles.
290 return manager->GetProfileByUser(manager->GetPrimaryUser());
291 #else
292 return profile_manager->GetActiveUserOrOffTheRecordProfileFromPath(
293 profile_manager->user_data_dir());
294 #endif
297 // static
298 Profile* ProfileManager::GetActiveUserProfile() {
299 ProfileManager* profile_manager = g_browser_process->profile_manager();
300 #if defined(OS_CHROMEOS)
301 if (!chromeos::UserManager::IsMultipleProfilesAllowed() ||
302 !profile_manager->IsLoggedIn() ||
303 !chromeos::UserManager::IsInitialized())
304 return profile_manager->GetActiveUserOrOffTheRecordProfileFromPath(
305 profile_manager->user_data_dir());
306 chromeos::UserManager* manager = chromeos::UserManager::Get();
307 const chromeos::User* user = manager->GetActiveUser();
308 // To avoid an endless loop (crbug.com/334098) we have to additionally check
309 // if the profile of the user was already created. If the profile was not yet
310 // created we load the profile using the profile directly.
311 // TODO: This should be cleaned up with the new profile manager.
312 if (user && user->is_profile_created())
313 return manager->GetProfileByUser(user);
314 #endif
315 return profile_manager->GetActiveUserOrOffTheRecordProfileFromPath(
316 profile_manager->user_data_dir());
319 Profile* ProfileManager::GetProfile(const base::FilePath& profile_dir) {
320 TRACE_EVENT0("browser", "ProfileManager::GetProfile")
321 // If the profile is already loaded (e.g., chrome.exe launched twice), just
322 // return it.
323 Profile* profile = GetProfileByPath(profile_dir);
324 if (NULL != profile)
325 return profile;
327 profile = CreateProfileHelper(profile_dir);
328 DCHECK(profile);
329 if (profile) {
330 bool result = AddProfile(profile);
331 DCHECK(result);
333 return profile;
336 size_t ProfileManager::GetNumberOfProfiles() {
337 return GetProfileInfoCache().GetNumberOfProfiles();
340 void ProfileManager::CreateProfileAsync(
341 const base::FilePath& profile_path,
342 const CreateCallback& callback,
343 const base::string16& name,
344 const base::string16& icon_url,
345 const std::string& managed_user_id) {
346 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
348 // Make sure that this profile is not pending deletion.
349 if (IsProfileMarkedForDeletion(profile_path)) {
350 if (!callback.is_null())
351 callback.Run(NULL, Profile::CREATE_STATUS_LOCAL_FAIL);
352 return;
355 // Create the profile if needed and collect its ProfileInfo.
356 ProfilesInfoMap::iterator iter = profiles_info_.find(profile_path);
357 ProfileInfo* info = NULL;
359 if (iter != profiles_info_.end()) {
360 info = iter->second.get();
361 } else {
362 // Initiate asynchronous creation process.
363 info = RegisterProfile(CreateProfileAsyncHelper(profile_path, this), false);
364 ProfileInfoCache& cache = GetProfileInfoCache();
365 // Get the icon index from the user's icon url
366 size_t icon_index;
367 std::string icon_url_std = UTF16ToASCII(icon_url);
368 if (cache.IsDefaultAvatarIconUrl(icon_url_std, &icon_index)) {
369 // add profile to cache with user selected name and avatar
370 cache.AddProfileToCache(profile_path, name, base::string16(), icon_index,
371 managed_user_id);
374 if (!managed_user_id.empty()) {
375 content::RecordAction(
376 UserMetricsAction("ManagedMode_LocallyManagedUserCreated"));
379 ProfileMetrics::UpdateReportedProfilesStatistics(this);
382 // Call or enqueue the callback.
383 if (!callback.is_null()) {
384 if (iter != profiles_info_.end() && info->created) {
385 Profile* profile = info->profile.get();
386 // If this was the guest profile, apply settings.
387 if (profile->GetPath() == ProfileManager::GetGuestProfilePath())
388 SetGuestProfilePrefs(profile);
389 // Profile has already been created. Run callback immediately.
390 callback.Run(profile, Profile::CREATE_STATUS_INITIALIZED);
391 } else {
392 // Profile is either already in the process of being created, or new.
393 // Add callback to the list.
394 info->callbacks.push_back(callback);
399 bool ProfileManager::IsValidProfile(Profile* profile) {
400 for (ProfilesInfoMap::iterator iter = profiles_info_.begin();
401 iter != profiles_info_.end(); ++iter) {
402 if (iter->second->created) {
403 Profile* candidate = iter->second->profile.get();
404 if (candidate == profile ||
405 (candidate->HasOffTheRecordProfile() &&
406 candidate->GetOffTheRecordProfile() == profile)) {
407 return true;
411 return false;
414 base::FilePath ProfileManager::GetInitialProfileDir() {
415 base::FilePath relative_profile_dir;
416 #if defined(OS_CHROMEOS)
417 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
418 if (logged_in_) {
419 base::FilePath profile_dir;
420 // If the user has logged in, pick up the new profile.
421 if (command_line.HasSwitch(chromeos::switches::kLoginProfile)) {
422 // TODO(nkostylev): Remove this code completely once we eliminate
423 // legacy --login-profile=user switch and enable multi-profiles on CrOS
424 // by default. http://crbug.com/294628
425 profile_dir = chromeos::ProfileHelper::
426 GetProfileDirByLegacyLoginProfileSwitch();
427 } else if (!command_line.HasSwitch(switches::kMultiProfiles)) {
428 // We should never be logged in with no profile dir unless
429 // multi-profiles are enabled.
430 // In that case profile dir will be defined by user_id hash.
431 NOTREACHED();
432 return base::FilePath("");
434 // In case of multi-profiles ignore --login-profile switch.
435 // TODO(nkostylev): Some cases like Guest mode will have empty username_hash
436 // so default kLoginProfile dir will be used.
437 std::string user_id_hash = g_browser_process->platform_part()->
438 profile_helper()->active_user_id_hash();
439 if (command_line.HasSwitch(switches::kMultiProfiles) &&
440 !user_id_hash.empty()) {
441 profile_dir = g_browser_process->platform_part()->
442 profile_helper()->GetActiveUserProfileDir();
444 relative_profile_dir = relative_profile_dir.Append(profile_dir);
445 return relative_profile_dir;
447 #endif
448 // TODO(mirandac): should not automatically be default profile.
449 relative_profile_dir =
450 relative_profile_dir.AppendASCII(chrome::kInitialProfile);
451 return relative_profile_dir;
454 Profile* ProfileManager::GetLastUsedProfile(
455 const base::FilePath& user_data_dir) {
456 #if defined(OS_CHROMEOS)
457 // Use default login profile if user has not logged in yet.
458 if (!logged_in_) {
459 return GetActiveUserOrOffTheRecordProfileFromPath(user_data_dir);
460 } else {
461 // CrOS multi-profiles implementation is different so GetLastUsedProfile
462 // has custom implementation too.
463 base::FilePath profile_dir;
464 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
465 if (command_line.HasSwitch(switches::kMultiProfiles)) {
466 // In case of multi-profiles we ignore "last used profile" preference
467 // since it may refer to profile that has been in use in previous session.
468 // That profile dir may not be mounted in this session so instead return
469 // active profile from current session.
470 profile_dir = g_browser_process->platform_part()->
471 profile_helper()->GetActiveUserProfileDir();
472 } else {
473 // For legacy (not multi-profiles) implementation always default to
474 // --login-profile value.
475 profile_dir =
476 chromeos::ProfileHelper::GetProfileDirByLegacyLoginProfileSwitch();
478 base::FilePath profile_path(user_data_dir);
479 return GetProfile(profile_path.Append(profile_dir));
481 #endif
483 return GetProfile(GetLastUsedProfileDir(user_data_dir));
486 base::FilePath ProfileManager::GetLastUsedProfileDir(
487 const base::FilePath& user_data_dir) {
488 base::FilePath last_used_profile_dir(user_data_dir);
489 PrefService* local_state = g_browser_process->local_state();
490 DCHECK(local_state);
492 if (local_state->HasPrefPath(prefs::kProfileLastUsed)) {
493 return last_used_profile_dir.AppendASCII(
494 local_state->GetString(prefs::kProfileLastUsed));
497 return last_used_profile_dir.AppendASCII(chrome::kInitialProfile);
500 std::vector<Profile*> ProfileManager::GetLastOpenedProfiles(
501 const base::FilePath& user_data_dir) {
502 PrefService* local_state = g_browser_process->local_state();
503 DCHECK(local_state);
505 std::vector<Profile*> to_return;
506 if (local_state->HasPrefPath(prefs::kProfilesLastActive) &&
507 local_state->GetList(prefs::kProfilesLastActive)) {
508 // Make a copy because the list might change in the calls to GetProfile.
509 scoped_ptr<base::ListValue> profile_list(
510 local_state->GetList(prefs::kProfilesLastActive)->DeepCopy());
511 base::ListValue::const_iterator it;
512 std::string profile;
513 for (it = profile_list->begin(); it != profile_list->end(); ++it) {
514 if (!(*it)->GetAsString(&profile) || profile.empty()) {
515 LOG(WARNING) << "Invalid entry in " << prefs::kProfilesLastActive;
516 continue;
518 to_return.push_back(GetProfile(user_data_dir.AppendASCII(profile)));
521 return to_return;
524 std::vector<Profile*> ProfileManager::GetLoadedProfiles() const {
525 std::vector<Profile*> profiles;
526 for (ProfilesInfoMap::const_iterator iter = profiles_info_.begin();
527 iter != profiles_info_.end(); ++iter) {
528 if (iter->second->created)
529 profiles.push_back(iter->second->profile.get());
531 return profiles;
534 Profile* ProfileManager::GetProfileByPath(const base::FilePath& path) const {
535 ProfileInfo* profile_info = GetProfileInfoByPath(path);
536 return profile_info ? profile_info->profile.get() : NULL;
539 // static
540 base::FilePath ProfileManager::CreateMultiProfileAsync(
541 const base::string16& name,
542 const base::string16& icon_url,
543 const CreateCallback& callback,
544 const std::string& managed_user_id) {
545 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
547 ProfileManager* profile_manager = g_browser_process->profile_manager();
549 base::FilePath new_path = profile_manager->GenerateNextProfileDirectoryPath();
551 profile_manager->CreateProfileAsync(new_path,
552 callback,
553 name,
554 icon_url,
555 managed_user_id);
556 return new_path;
559 // static
560 base::FilePath ProfileManager::GetGuestProfilePath() {
561 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
563 ProfileManager* profile_manager = g_browser_process->profile_manager();
565 base::FilePath guest_path = profile_manager->user_data_dir();
566 return guest_path.Append(chrome::kGuestProfileDir);
569 base::FilePath ProfileManager::GenerateNextProfileDirectoryPath() {
570 PrefService* local_state = g_browser_process->local_state();
571 DCHECK(local_state);
573 DCHECK(profiles::IsMultipleProfilesEnabled());
575 // Create the next profile in the next available directory slot.
576 int next_directory = local_state->GetInteger(prefs::kProfilesNumCreated);
577 std::string profile_name = chrome::kMultiProfileDirPrefix;
578 profile_name.append(base::IntToString(next_directory));
579 base::FilePath new_path = user_data_dir_;
580 #if defined(OS_WIN)
581 new_path = new_path.Append(base::ASCIIToUTF16(profile_name));
582 #else
583 new_path = new_path.Append(profile_name);
584 #endif
585 local_state->SetInteger(prefs::kProfilesNumCreated, ++next_directory);
586 return new_path;
589 ProfileInfoCache& ProfileManager::GetProfileInfoCache() {
590 if (!profile_info_cache_) {
591 profile_info_cache_.reset(new ProfileInfoCache(
592 g_browser_process->local_state(), user_data_dir_));
594 return *profile_info_cache_.get();
597 ProfileShortcutManager* ProfileManager::profile_shortcut_manager() {
598 return profile_shortcut_manager_.get();
601 void ProfileManager::ScheduleProfileForDeletion(
602 const base::FilePath& profile_dir,
603 const CreateCallback& callback) {
604 DCHECK(profiles::IsMultipleProfilesEnabled());
605 PrefService* local_state = g_browser_process->local_state();
606 ProfileInfoCache& cache = GetProfileInfoCache();
608 if (profile_dir.BaseName().MaybeAsASCII() ==
609 local_state->GetString(prefs::kProfileLastUsed)) {
610 // Update the last used profile pref before closing browser windows. This
611 // way the correct last used profile is set for any notification observers.
612 base::FilePath last_non_managed_profile_path;
613 for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) {
614 base::FilePath cur_path = cache.GetPathOfProfileAtIndex(i);
615 // Make sure that this profile is not pending deletion.
616 if (cur_path != profile_dir && !cache.ProfileIsManagedAtIndex(i) &&
617 !IsProfileMarkedForDeletion(cur_path)) {
618 last_non_managed_profile_path = cur_path;
619 break;
623 // If we're deleting the last (non-managed) profile, then create a new
624 // profile in its place.
625 const std::string last_non_managed_profile =
626 last_non_managed_profile_path.BaseName().MaybeAsASCII();
627 if (last_non_managed_profile.empty()) {
628 base::FilePath new_path = GenerateNextProfileDirectoryPath();
629 // Make sure the last used profile path is pointing at it. This way the
630 // correct last used profile is set for any notification observers.
631 local_state->SetString(prefs::kProfileLastUsed,
632 new_path.BaseName().MaybeAsASCII());
633 CreateProfileAsync(new_path,
634 callback,
635 base::string16(),
636 base::string16(),
637 std::string());
638 } else {
639 // On the Mac, the browser process is not killed when all browser windows
640 // are closed, so just in case we are deleting the active profile, and no
641 // other profile has been loaded, we must pre-load a next one.
642 #if defined(OS_MACOSX)
643 CreateProfileAsync(last_non_managed_profile_path,
644 base::Bind(&ProfileManager::OnNewActiveProfileLoaded,
645 base::Unretained(this),
646 profile_dir,
647 last_non_managed_profile_path,
648 callback),
649 base::string16(),
650 base::string16(),
651 std::string());
652 return;
653 #else
654 // For OS_MACOSX the pref is updated in the callback to make sure that
655 // it isn't used before the profile is actually loaded.
656 local_state->SetString(prefs::kProfileLastUsed, last_non_managed_profile);
657 #endif
660 FinishDeletingProfile(profile_dir);
663 // static
664 void ProfileManager::CleanUpStaleProfiles(
665 const std::vector<base::FilePath>& profile_paths) {
666 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
668 for (std::vector<base::FilePath>::const_iterator it = profile_paths.begin();
669 it != profile_paths.end(); ++it) {
670 NukeProfileFromDisk(*it);
674 void ProfileManager::AutoloadProfiles() {
675 // If running in the background is disabled for the browser, do not autoload
676 // any profiles.
677 PrefService* local_state = g_browser_process->local_state();
678 if (!local_state->HasPrefPath(prefs::kBackgroundModeEnabled) ||
679 !local_state->GetBoolean(prefs::kBackgroundModeEnabled)) {
680 return;
683 ProfileInfoCache& cache = GetProfileInfoCache();
684 size_t number_of_profiles = cache.GetNumberOfProfiles();
685 for (size_t p = 0; p < number_of_profiles; ++p) {
686 if (cache.GetBackgroundStatusOfProfileAtIndex(p)) {
687 // If status is true, that profile is running background apps. By calling
688 // GetProfile, we automatically cause the profile to be loaded which will
689 // register it with the BackgroundModeManager.
690 GetProfile(cache.GetPathOfProfileAtIndex(p));
695 void ProfileManager::InitProfileUserPrefs(Profile* profile) {
696 ProfileInfoCache& cache = GetProfileInfoCache();
698 if (profile->GetPath().DirName() != cache.GetUserDataDir())
699 return;
701 size_t avatar_index;
702 std::string profile_name;
703 std::string managed_user_id;
704 if (profile->IsGuestSession()) {
705 profile_name = l10n_util::GetStringUTF8(IDS_PROFILES_GUEST_PROFILE_NAME);
706 avatar_index = 0;
707 } else {
708 size_t profile_cache_index =
709 cache.GetIndexOfProfileWithPath(profile->GetPath());
710 // If the cache has an entry for this profile, use the cache data.
711 if (profile_cache_index != std::string::npos) {
712 avatar_index =
713 cache.GetAvatarIconIndexOfProfileAtIndex(profile_cache_index);
714 profile_name =
715 base::UTF16ToUTF8(cache.GetNameOfProfileAtIndex(profile_cache_index));
716 managed_user_id =
717 cache.GetManagedUserIdOfProfileAtIndex(profile_cache_index);
718 } else if (profile->GetPath() ==
719 profiles::GetDefaultProfileDir(cache.GetUserDataDir())) {
720 avatar_index = 0;
721 profile_name = l10n_util::GetStringUTF8(IDS_DEFAULT_PROFILE_NAME);
722 } else {
723 avatar_index = cache.ChooseAvatarIconIndexForNewProfile();
724 profile_name =
725 base::UTF16ToUTF8(cache.ChooseNameForNewProfile(avatar_index));
729 if (!profile->GetPrefs()->HasPrefPath(prefs::kProfileAvatarIndex))
730 profile->GetPrefs()->SetInteger(prefs::kProfileAvatarIndex, avatar_index);
732 if (!profile->GetPrefs()->HasPrefPath(prefs::kProfileName))
733 profile->GetPrefs()->SetString(prefs::kProfileName, profile_name);
735 CommandLine* command_line = CommandLine::ForCurrentProcess();
736 bool force_managed_user_id =
737 command_line->HasSwitch(switches::kManagedUserId);
738 if (force_managed_user_id) {
739 managed_user_id =
740 command_line->GetSwitchValueASCII(switches::kManagedUserId);
742 if (force_managed_user_id ||
743 !profile->GetPrefs()->HasPrefPath(prefs::kManagedUserId)) {
744 profile->GetPrefs()->SetString(prefs::kManagedUserId, managed_user_id);
748 void ProfileManager::RegisterTestingProfile(Profile* profile,
749 bool add_to_cache,
750 bool start_deferred_task_runners) {
751 RegisterProfile(profile, true);
752 if (add_to_cache) {
753 InitProfileUserPrefs(profile);
754 AddProfileToCache(profile);
756 if (start_deferred_task_runners) {
757 StartupTaskRunnerServiceFactory::GetForProfile(profile)->
758 StartDeferredTaskRunners();
762 void ProfileManager::Observe(
763 int type,
764 const content::NotificationSource& source,
765 const content::NotificationDetails& details) {
766 #if defined(OS_CHROMEOS)
767 if (type == chrome::NOTIFICATION_LOGIN_USER_CHANGED) {
768 logged_in_ = true;
770 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
771 if (!command_line.HasSwitch(switches::kTestType)) {
772 // If we don't have a mounted profile directory we're in trouble.
773 // TODO(davemoore) Once we have better api this check should ensure that
774 // our profile directory is the one that's mounted, and that it's mounted
775 // as the current user.
776 chromeos::DBusThreadManager::Get()->GetCryptohomeClient()->IsMounted(
777 base::Bind(&CheckCryptohomeIsMounted));
779 // Confirm that we hadn't loaded the new profile previously.
780 base::FilePath default_profile_dir = user_data_dir_.Append(
781 GetInitialProfileDir());
782 CHECK(!GetProfileByPath(default_profile_dir))
783 << "The default profile was loaded before we mounted the cryptohome.";
785 return;
787 #endif
788 bool save_active_profiles = false;
789 switch (type) {
790 case chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST: {
791 // Ignore any browsers closing from now on.
792 closing_all_browsers_ = true;
793 save_active_profiles = true;
794 break;
796 case chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED: {
797 // This will cancel the shutdown process, so the active profiles are
798 // tracked again. Also, as the active profiles may have changed (i.e. if
799 // some windows were closed) we save the current list of active profiles
800 // again.
801 closing_all_browsers_ = false;
802 save_active_profiles = true;
803 break;
805 case chrome::NOTIFICATION_BROWSER_OPENED: {
806 Browser* browser = content::Source<Browser>(source).ptr();
807 DCHECK(browser);
808 Profile* profile = browser->profile();
809 DCHECK(profile);
810 bool is_ephemeral =
811 profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles);
812 if (!profile->IsOffTheRecord() && !is_ephemeral &&
813 ++browser_counts_[profile] == 1) {
814 active_profiles_.push_back(profile);
815 save_active_profiles = true;
817 // If browsers are opening, we can't be closing all the browsers. This
818 // can happen if the application was exited, but background mode or
819 // packaged apps prevented the process from shutting down, and then
820 // a new browser window was opened.
821 closing_all_browsers_ = false;
822 break;
824 case chrome::NOTIFICATION_BROWSER_CLOSED: {
825 Browser* browser = content::Source<Browser>(source).ptr();
826 DCHECK(browser);
827 Profile* profile = browser->profile();
828 DCHECK(profile);
829 if (!profile->IsOffTheRecord() && --browser_counts_[profile] == 0) {
830 active_profiles_.erase(std::find(active_profiles_.begin(),
831 active_profiles_.end(), profile));
832 save_active_profiles = !closing_all_browsers_;
834 break;
836 case chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED: {
837 save_active_profiles = !closing_all_browsers_;
838 break;
840 default: {
841 NOTREACHED();
842 break;
846 if (save_active_profiles) {
847 PrefService* local_state = g_browser_process->local_state();
848 DCHECK(local_state);
849 ListPrefUpdate update(local_state, prefs::kProfilesLastActive);
850 base::ListValue* profile_list = update.Get();
852 profile_list->Clear();
854 // crbug.com/120112 -> several non-incognito profiles might have the same
855 // GetPath().BaseName(). In that case, we cannot restore both
856 // profiles. Include each base name only once in the last active profile
857 // list.
858 std::set<std::string> profile_paths;
859 std::vector<Profile*>::const_iterator it;
860 for (it = active_profiles_.begin(); it != active_profiles_.end(); ++it) {
861 std::string profile_path = (*it)->GetPath().BaseName().MaybeAsASCII();
862 // Some profiles might become ephemeral after they are created.
863 if (!(*it)->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles) &&
864 profile_paths.find(profile_path) == profile_paths.end()) {
865 profile_paths.insert(profile_path);
866 profile_list->Append(new base::StringValue(profile_path));
872 void ProfileManager::OnProfileCreated(Profile* profile,
873 bool success,
874 bool is_new_profile) {
875 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
877 ProfilesInfoMap::iterator iter = profiles_info_.find(profile->GetPath());
878 DCHECK(iter != profiles_info_.end());
879 ProfileInfo* info = iter->second.get();
881 std::vector<CreateCallback> callbacks;
882 info->callbacks.swap(callbacks);
884 // Invoke CREATED callback for normal profiles.
885 bool go_off_the_record = ShouldGoOffTheRecord(profile);
886 if (success && !go_off_the_record)
887 RunCallbacks(callbacks, profile, Profile::CREATE_STATUS_CREATED);
889 // Perform initialization.
890 if (success) {
891 DoFinalInit(profile, go_off_the_record);
892 if (go_off_the_record)
893 profile = profile->GetOffTheRecordProfile();
894 info->created = true;
895 } else {
896 profile = NULL;
897 profiles_info_.erase(iter);
900 if (profile) {
901 // If this was the guest profile, finish setting its incognito status.
902 if (profile->GetPath() == ProfileManager::GetGuestProfilePath())
903 SetGuestProfilePrefs(profile);
905 // Invoke CREATED callback for incognito profiles.
906 if (go_off_the_record)
907 RunCallbacks(callbacks, profile, Profile::CREATE_STATUS_CREATED);
910 // Invoke INITIALIZED or FAIL for all profiles.
911 RunCallbacks(callbacks, profile,
912 profile ? Profile::CREATE_STATUS_INITIALIZED :
913 Profile::CREATE_STATUS_LOCAL_FAIL);
916 void ProfileManager::DoFinalInit(Profile* profile, bool go_off_the_record) {
917 DoFinalInitForServices(profile, go_off_the_record);
918 AddProfileToCache(profile);
919 DoFinalInitLogging(profile);
921 ProfileMetrics::LogNumberOfProfiles(this);
922 content::NotificationService::current()->Notify(
923 chrome::NOTIFICATION_PROFILE_ADDED,
924 content::Source<Profile>(profile),
925 content::NotificationService::NoDetails());
928 void ProfileManager::DoFinalInitForServices(Profile* profile,
929 bool go_off_the_record) {
930 #if defined(ENABLE_EXTENSIONS)
931 extensions::ExtensionSystem::Get(profile)->InitForRegularProfile(
932 !go_off_the_record);
933 // During tests, when |profile| is an instance of TestingProfile,
934 // ExtensionSystem might not create an ExtensionService.
935 if (extensions::ExtensionSystem::Get(profile)->extension_service()) {
936 profile->GetHostContentSettingsMap()->RegisterExtensionService(
937 extensions::ExtensionSystem::Get(profile)->extension_service());
939 #endif
940 #if defined(ENABLE_MANAGED_USERS)
941 // Initialization needs to happen after extension system initialization (for
942 // extension::ManagementPolicy) and InitProfileUserPrefs (for setting the
943 // initializing the managed flag if necessary).
944 ManagedUserServiceFactory::GetForProfile(profile)->Init();
945 #endif
946 // Start the deferred task runners once the profile is loaded.
947 StartupTaskRunnerServiceFactory::GetForProfile(profile)->
948 StartDeferredTaskRunners();
950 if (switches::IsNewProfileManagement())
951 AccountReconcilorFactory::GetForProfile(profile);
954 void ProfileManager::DoFinalInitLogging(Profile* profile) {
955 // Count number of extensions in this profile.
956 int extension_count = -1;
957 #if defined(ENABLE_EXTENSIONS)
958 ExtensionService* extension_service = profile->GetExtensionService();
959 if (extension_service)
960 extension_count = extension_service->GetAppIds().size();
961 #endif
963 // Log the profile size after a reasonable startup delay.
964 BrowserThread::PostDelayedTask(
965 BrowserThread::FILE, FROM_HERE,
966 base::Bind(&ProfileSizeTask, profile->GetPath(), extension_count),
967 base::TimeDelta::FromSeconds(112));
970 Profile* ProfileManager::CreateProfileHelper(const base::FilePath& path) {
971 return Profile::CreateProfile(path, NULL, Profile::CREATE_MODE_SYNCHRONOUS);
974 Profile* ProfileManager::CreateProfileAsyncHelper(const base::FilePath& path,
975 Delegate* delegate) {
976 return Profile::CreateProfile(path,
977 delegate,
978 Profile::CREATE_MODE_ASYNCHRONOUS);
981 Profile* ProfileManager::GetActiveUserOrOffTheRecordProfileFromPath(
982 const base::FilePath& user_data_dir) {
983 #if defined(OS_CHROMEOS)
984 base::FilePath default_profile_dir(user_data_dir);
985 if (!logged_in_) {
986 default_profile_dir = profiles::GetDefaultProfileDir(user_data_dir);
987 Profile* profile = GetProfile(default_profile_dir);
988 // For cros, return the OTR profile so we never accidentally keep
989 // user data in an unencrypted profile. But doing this makes
990 // many of the browser and ui tests fail. We do return the OTR profile
991 // if the login-profile switch is passed so that we can test this.
992 if (ShouldGoOffTheRecord(profile))
993 return profile->GetOffTheRecordProfile();
994 DCHECK(!chromeos::UserManager::Get()->IsLoggedInAsGuest());
995 return profile;
998 default_profile_dir = default_profile_dir.Append(GetInitialProfileDir());
999 ProfileInfo* profile_info = GetProfileInfoByPath(default_profile_dir);
1000 // Fallback to default off-the-record profile, if user profile has not fully
1001 // loaded yet.
1002 if (profile_info && !profile_info->created)
1003 default_profile_dir = profiles::GetDefaultProfileDir(user_data_dir);
1005 Profile* profile = GetProfile(default_profile_dir);
1006 // Some unit tests didn't initialize the UserManager.
1007 if (chromeos::UserManager::IsInitialized() &&
1008 chromeos::UserManager::Get()->IsLoggedInAsGuest())
1009 return profile->GetOffTheRecordProfile();
1010 return profile;
1011 #else
1012 base::FilePath default_profile_dir(user_data_dir);
1013 default_profile_dir = default_profile_dir.Append(GetInitialProfileDir());
1014 return GetProfile(default_profile_dir);
1015 #endif
1018 bool ProfileManager::AddProfile(Profile* profile) {
1019 DCHECK(profile);
1021 // Make sure that we're not loading a profile with the same ID as a profile
1022 // that's already loaded.
1023 if (GetProfileByPath(profile->GetPath())) {
1024 NOTREACHED() << "Attempted to add profile with the same path (" <<
1025 profile->GetPath().value() <<
1026 ") as an already-loaded profile.";
1027 return false;
1030 RegisterProfile(profile, true);
1031 InitProfileUserPrefs(profile);
1032 DoFinalInit(profile, ShouldGoOffTheRecord(profile));
1033 return true;
1036 void ProfileManager::FinishDeletingProfile(const base::FilePath& profile_dir) {
1037 ProfileInfoCache& cache = GetProfileInfoCache();
1038 // TODO(sail): Due to bug 88586 we don't delete the profile instance. Once we
1039 // start deleting the profile instance we need to close background apps too.
1040 Profile* profile = GetProfileByPath(profile_dir);
1042 if (profile) {
1043 BrowserList::CloseAllBrowsersWithProfile(profile);
1045 // Disable sync for doomed profile.
1046 if (ProfileSyncServiceFactory::GetInstance()->HasProfileSyncService(
1047 profile)) {
1048 ProfileSyncServiceFactory::GetInstance()->GetForProfile(
1049 profile)->DisableForUser();
1053 QueueProfileDirectoryForDeletion(profile_dir);
1054 cache.DeleteProfileFromCache(profile_dir);
1055 ProfileMetrics::UpdateReportedProfilesStatistics(this);
1058 ProfileManager::ProfileInfo* ProfileManager::RegisterProfile(
1059 Profile* profile,
1060 bool created) {
1061 ProfileInfo* info = new ProfileInfo(profile, created);
1062 profiles_info_.insert(
1063 std::make_pair(profile->GetPath(), linked_ptr<ProfileInfo>(info)));
1064 return info;
1067 ProfileManager::ProfileInfo* ProfileManager::GetProfileInfoByPath(
1068 const base::FilePath& path) const {
1069 ProfilesInfoMap::const_iterator iter = profiles_info_.find(path);
1070 return (iter == profiles_info_.end()) ? NULL : iter->second.get();
1073 void ProfileManager::AddProfileToCache(Profile* profile) {
1074 if (profile->IsGuestSession())
1075 return;
1076 ProfileInfoCache& cache = GetProfileInfoCache();
1077 if (profile->GetPath().DirName() != cache.GetUserDataDir())
1078 return;
1080 if (cache.GetIndexOfProfileWithPath(profile->GetPath()) != std::string::npos)
1081 return;
1083 base::string16 username = base::UTF8ToUTF16(profile->GetPrefs()->GetString(
1084 prefs::kGoogleServicesUsername));
1086 // Profile name and avatar are set by InitProfileUserPrefs and stored in the
1087 // profile. Use those values to setup the cache entry.
1088 base::string16 profile_name =
1089 base::UTF8ToUTF16(profile->GetPrefs()->GetString(prefs::kProfileName));
1091 size_t icon_index = profile->GetPrefs()->GetInteger(
1092 prefs::kProfileAvatarIndex);
1094 std::string managed_user_id =
1095 profile->GetPrefs()->GetString(prefs::kManagedUserId);
1097 cache.AddProfileToCache(profile->GetPath(),
1098 profile_name,
1099 username,
1100 icon_index,
1101 managed_user_id);
1103 if (profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles)) {
1104 cache.SetProfileIsEphemeralAtIndex(
1105 cache.GetIndexOfProfileWithPath(profile->GetPath()), true);
1109 void ProfileManager::SetGuestProfilePrefs(Profile* profile) {
1110 IncognitoModePrefs::SetAvailability(profile->GetPrefs(),
1111 IncognitoModePrefs::FORCED);
1112 profile->GetPrefs()->SetBoolean(prefs::kShowBookmarkBar, false);
1115 bool ProfileManager::ShouldGoOffTheRecord(Profile* profile) {
1116 bool go_off_the_record = false;
1117 #if defined(OS_CHROMEOS)
1118 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1119 if (command_line.HasSwitch(chromeos::switches::kGuestSession) ||
1120 (profile->GetPath().BaseName().value() == chrome::kInitialProfile &&
1121 (!command_line.HasSwitch(switches::kTestType) ||
1122 command_line.HasSwitch(chromeos::switches::kLoginProfile)))) {
1123 go_off_the_record = true;
1125 #endif
1126 return go_off_the_record;
1129 void ProfileManager::RunCallbacks(const std::vector<CreateCallback>& callbacks,
1130 Profile* profile,
1131 Profile::CreateStatus status) {
1132 for (size_t i = 0; i < callbacks.size(); ++i)
1133 callbacks[i].Run(profile, status);
1136 ProfileManager::ProfileInfo::ProfileInfo(
1137 Profile* profile,
1138 bool created)
1139 : profile(profile),
1140 created(created) {
1143 ProfileManager::ProfileInfo::~ProfileInfo() {
1144 ProfileDestroyer::DestroyProfileWhenAppropriate(profile.release());
1147 #if !defined(OS_ANDROID) && !defined(OS_IOS)
1148 ProfileManager::BrowserListObserver::BrowserListObserver(
1149 ProfileManager* manager)
1150 : profile_manager_(manager) {
1151 BrowserList::AddObserver(this);
1154 ProfileManager::BrowserListObserver::~BrowserListObserver() {
1155 BrowserList::RemoveObserver(this);
1158 void ProfileManager::BrowserListObserver::OnBrowserAdded(
1159 Browser* browser) {}
1161 void ProfileManager::BrowserListObserver::OnBrowserRemoved(
1162 Browser* browser) {
1163 Profile* profile = browser->profile();
1164 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
1165 if (it->profile()->GetOriginalProfile() == profile->GetOriginalProfile())
1166 // Not the last window for this profile.
1167 return;
1170 // If the last browser of a profile that is scheduled for deletion is closed
1171 // do that now.
1172 base::FilePath path = profile->GetPath();
1173 if (profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles) &&
1174 !IsProfileMarkedForDeletion(path)) {
1175 g_browser_process->profile_manager()->ScheduleProfileForDeletion(
1176 path, ProfileManager::CreateCallback());
1180 void ProfileManager::BrowserListObserver::OnBrowserSetLastActive(
1181 Browser* browser) {
1182 // If all browsers are being closed (e.g. the user is in the process of
1183 // shutting down), this event will be fired after each browser is
1184 // closed. This does not represent a user intention to change the active
1185 // browser so is not handled here.
1186 if (profile_manager_->closing_all_browsers_)
1187 return;
1189 Profile* last_active = browser->profile();
1191 // Don't remember ephemeral profiles as last because they are not going to
1192 // persist after restart.
1193 if (last_active->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles))
1194 return;
1196 PrefService* local_state = g_browser_process->local_state();
1197 DCHECK(local_state);
1198 // Only keep track of profiles that we are managing; tests may create others.
1199 if (profile_manager_->profiles_info_.find(
1200 last_active->GetPath()) != profile_manager_->profiles_info_.end()) {
1201 local_state->SetString(prefs::kProfileLastUsed,
1202 last_active->GetPath().BaseName().MaybeAsASCII());
1204 ProfileInfoCache& cache = profile_manager_->GetProfileInfoCache();
1205 size_t profile_index =
1206 cache.GetIndexOfProfileWithPath(last_active->GetPath());
1207 if (profile_index != std::string::npos)
1208 cache.SetProfileActiveTimeAtIndex(profile_index);
1211 #endif // !defined(OS_ANDROID) && !defined(OS_IOS)
1213 #if defined(OS_MACOSX)
1214 void ProfileManager::OnNewActiveProfileLoaded(
1215 const base::FilePath& profile_to_delete_path,
1216 const base::FilePath& last_non_managed_profile_path,
1217 const CreateCallback& original_callback,
1218 Profile* loaded_profile,
1219 Profile::CreateStatus status) {
1220 DCHECK(status != Profile::CREATE_STATUS_LOCAL_FAIL &&
1221 status != Profile::CREATE_STATUS_REMOTE_FAIL);
1223 // Only run the code if the profile initialization has finished completely.
1224 if (status == Profile::CREATE_STATUS_INITIALIZED) {
1225 if (IsProfileMarkedForDeletion(last_non_managed_profile_path)) {
1226 // If the profile we tried to load as the next active profile has been
1227 // deleted, then retry deleting this profile to redo the logic to load
1228 // the next available profile.
1229 ScheduleProfileForDeletion(profile_to_delete_path, original_callback);
1230 } else {
1231 // Update the local state as promised in the ScheduleProfileForDeletion.
1232 g_browser_process->local_state()->SetString(
1233 prefs::kProfileLastUsed,
1234 last_non_managed_profile_path.BaseName().MaybeAsASCII());
1235 FinishDeletingProfile(profile_to_delete_path);
1239 #endif
1241 ProfileManagerWithoutInit::ProfileManagerWithoutInit(
1242 const base::FilePath& user_data_dir) : ProfileManager(user_data_dir) {