Temporarily re-enabling SizeAfterPrefChange test with traces (this time for Linux...
[chromium-blink-merge.git] / chrome / browser / profiles / profile_manager.cc
blob3634ad4bb03f270a7b370813de0f5e77ab6fc39e
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_factory.h"
23 #include "chrome/browser/browser_process.h"
24 #include "chrome/browser/chrome_notification_types.h"
25 #include "chrome/browser/content_settings/host_content_settings_map.h"
26 #include "chrome/browser/download/download_service.h"
27 #include "chrome/browser/download/download_service_factory.h"
28 #include "chrome/browser/prefs/incognito_mode_prefs.h"
29 #include "chrome/browser/profiles/bookmark_model_loaded_observer.h"
30 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
31 #include "chrome/browser/profiles/profile_destroyer.h"
32 #include "chrome/browser/profiles/profile_info_cache.h"
33 #include "chrome/browser/profiles/profile_metrics.h"
34 #include "chrome/browser/profiles/profiles_state.h"
35 #include "chrome/browser/profiles/startup_task_runner_service.h"
36 #include "chrome/browser/profiles/startup_task_runner_service_factory.h"
37 #include "chrome/browser/signin/account_reconcilor_factory.h"
38 #include "chrome/browser/sync/profile_sync_service.h"
39 #include "chrome/browser/sync/profile_sync_service_factory.h"
40 #include "chrome/browser/ui/browser.h"
41 #include "chrome/browser/ui/browser_iterator.h"
42 #include "chrome/browser/ui/sync/sync_promo_ui.h"
43 #include "chrome/common/chrome_constants.h"
44 #include "chrome/common/chrome_paths_internal.h"
45 #include "chrome/common/chrome_switches.h"
46 #include "chrome/common/logging_chrome.h"
47 #include "chrome/common/pref_names.h"
48 #include "chrome/common/url_constants.h"
49 #include "components/bookmarks/browser/bookmark_model.h"
50 #include "components/signin/core/common/profile_management_switches.h"
51 #include "content/public/browser/browser_thread.h"
52 #include "content/public/browser/notification_service.h"
53 #include "content/public/browser/user_metrics.h"
54 #include "extensions/browser/extension_registry.h"
55 #include "extensions/common/extension_set.h"
56 #include "extensions/common/manifest.h"
57 #include "grit/generated_resources.h"
58 #include "net/http/http_transaction_factory.h"
59 #include "net/url_request/url_request_context.h"
60 #include "net/url_request/url_request_context_getter.h"
61 #include "net/url_request/url_request_job.h"
62 #include "ui/base/l10n/l10n_util.h"
64 #if defined(ENABLE_MANAGED_USERS)
65 #include "chrome/browser/managed_mode/managed_user_service.h"
66 #include "chrome/browser/managed_mode/managed_user_service_factory.h"
67 #endif
69 #if !defined(OS_IOS)
70 #include "chrome/browser/extensions/extension_service.h"
71 #include "chrome/browser/sessions/session_service_factory.h"
72 #include "chrome/browser/ui/browser_list.h"
73 #include "extensions/browser/extension_system.h"
74 #endif // !defined (OS_IOS)
76 #if defined(OS_WIN)
77 #include "base/win/metro.h"
78 #include "chrome/installer/util/browser_distribution.h"
79 #endif
81 #if defined(OS_CHROMEOS)
82 #include "chrome/browser/browser_process_platform_part_chromeos.h"
83 #include "chrome/browser/chromeos/login/users/user.h"
84 #include "chrome/browser/chromeos/login/users/user_manager.h"
85 #include "chrome/browser/chromeos/profiles/profile_helper.h"
86 #include "chrome/browser/profiles/profiles_state.h"
87 #include "chromeos/chromeos_switches.h"
88 #include "chromeos/dbus/cryptohome_client.h"
89 #include "chromeos/dbus/dbus_thread_manager.h"
90 #endif
92 using base::UserMetricsAction;
93 using content::BrowserThread;
95 namespace {
97 // Profiles that should be deleted on shutdown.
98 std::vector<base::FilePath>& ProfilesToDelete() {
99 CR_DEFINE_STATIC_LOCAL(std::vector<base::FilePath>, profiles_to_delete, ());
100 return profiles_to_delete;
103 int64 ComputeFilesSize(const base::FilePath& directory,
104 const base::FilePath::StringType& pattern) {
105 int64 running_size = 0;
106 base::FileEnumerator iter(directory, false, base::FileEnumerator::FILES,
107 pattern);
108 while (!iter.Next().empty())
109 running_size += iter.GetInfo().GetSize();
110 return running_size;
113 // Simple task to log the size of the current profile.
114 void ProfileSizeTask(const base::FilePath& path, int enabled_app_count) {
115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
116 const int64 kBytesInOneMB = 1024 * 1024;
118 int64 size = ComputeFilesSize(path, FILE_PATH_LITERAL("*"));
119 int size_MB = static_cast<int>(size / kBytesInOneMB);
120 UMA_HISTOGRAM_COUNTS_10000("Profile.TotalSize", size_MB);
122 size = ComputeFilesSize(path, FILE_PATH_LITERAL("History"));
123 size_MB = static_cast<int>(size / kBytesInOneMB);
124 UMA_HISTOGRAM_COUNTS_10000("Profile.HistorySize", size_MB);
126 size = ComputeFilesSize(path, FILE_PATH_LITERAL("History*"));
127 size_MB = static_cast<int>(size / kBytesInOneMB);
128 UMA_HISTOGRAM_COUNTS_10000("Profile.TotalHistorySize", size_MB);
130 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Cookies"));
131 size_MB = static_cast<int>(size / kBytesInOneMB);
132 UMA_HISTOGRAM_COUNTS_10000("Profile.CookiesSize", size_MB);
134 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Bookmarks"));
135 size_MB = static_cast<int>(size / kBytesInOneMB);
136 UMA_HISTOGRAM_COUNTS_10000("Profile.BookmarksSize", size_MB);
138 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Favicons"));
139 size_MB = static_cast<int>(size / kBytesInOneMB);
140 UMA_HISTOGRAM_COUNTS_10000("Profile.FaviconsSize", size_MB);
142 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Top Sites"));
143 size_MB = static_cast<int>(size / kBytesInOneMB);
144 UMA_HISTOGRAM_COUNTS_10000("Profile.TopSitesSize", size_MB);
146 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Visited Links"));
147 size_MB = static_cast<int>(size / kBytesInOneMB);
148 UMA_HISTOGRAM_COUNTS_10000("Profile.VisitedLinksSize", size_MB);
150 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Web Data"));
151 size_MB = static_cast<int>(size / kBytesInOneMB);
152 UMA_HISTOGRAM_COUNTS_10000("Profile.WebDataSize", size_MB);
154 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Extension*"));
155 size_MB = static_cast<int>(size / kBytesInOneMB);
156 UMA_HISTOGRAM_COUNTS_10000("Profile.ExtensionSize", size_MB);
158 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Policy"));
159 size_MB = static_cast<int>(size / kBytesInOneMB);
160 UMA_HISTOGRAM_COUNTS_10000("Profile.PolicySize", size_MB);
162 // Count number of enabled apps in this profile, if we know.
163 if (enabled_app_count != -1)
164 UMA_HISTOGRAM_COUNTS_10000("Profile.AppCount", enabled_app_count);
167 void QueueProfileDirectoryForDeletion(const base::FilePath& path) {
168 ProfilesToDelete().push_back(path);
171 bool IsProfileMarkedForDeletion(const base::FilePath& profile_path) {
172 return std::find(ProfilesToDelete().begin(), ProfilesToDelete().end(),
173 profile_path) != ProfilesToDelete().end();
176 // Physically remove deleted profile directories from disk.
177 void NukeProfileFromDisk(const base::FilePath& profile_path) {
178 // Delete both the profile directory and its corresponding cache.
179 base::FilePath cache_path;
180 chrome::GetUserCacheDirectory(profile_path, &cache_path);
181 base::DeleteFile(profile_path, true);
182 base::DeleteFile(cache_path, true);
185 #if defined(OS_CHROMEOS)
186 void CheckCryptohomeIsMounted(chromeos::DBusMethodCallStatus call_status,
187 bool is_mounted) {
188 if (call_status != chromeos::DBUS_METHOD_CALL_SUCCESS) {
189 LOG(ERROR) << "IsMounted call failed.";
190 return;
192 if (!is_mounted)
193 LOG(ERROR) << "Cryptohome is not mounted.";
196 #endif
198 #if defined(ENABLE_EXTENSIONS)
200 // Returns the number of installed (and enabled) apps, excluding any component
201 // apps.
202 size_t GetEnabledAppCount(Profile* profile) {
203 size_t installed_apps = 0u;
204 const extensions::ExtensionSet& extensions =
205 extensions::ExtensionRegistry::Get(profile)->enabled_extensions();
206 for (extensions::ExtensionSet::const_iterator iter = extensions.begin();
207 iter != extensions.end();
208 ++iter) {
209 if ((*iter)->is_app() &&
210 (*iter)->location() != extensions::Manifest::COMPONENT) {
211 ++installed_apps;
214 return installed_apps;
217 #endif // ENABLE_EXTENSIONS
219 } // namespace
221 ProfileManager::ProfileManager(const base::FilePath& user_data_dir)
222 : user_data_dir_(user_data_dir),
223 logged_in_(false),
224 #if !defined(OS_ANDROID) && !defined(OS_IOS)
225 browser_list_observer_(this),
226 #endif
227 closing_all_browsers_(false) {
228 #if defined(OS_CHROMEOS)
229 registrar_.Add(
230 this,
231 chrome::NOTIFICATION_LOGIN_USER_CHANGED,
232 content::NotificationService::AllSources());
233 #endif
234 registrar_.Add(
235 this,
236 chrome::NOTIFICATION_BROWSER_OPENED,
237 content::NotificationService::AllSources());
238 registrar_.Add(
239 this,
240 chrome::NOTIFICATION_BROWSER_CLOSED,
241 content::NotificationService::AllSources());
242 registrar_.Add(
243 this,
244 chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST,
245 content::NotificationService::AllSources());
246 registrar_.Add(
247 this,
248 chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED,
249 content::NotificationService::AllSources());
250 registrar_.Add(
251 this,
252 chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
253 content::NotificationService::AllSources());
255 if (ProfileShortcutManager::IsFeatureEnabled() && !user_data_dir_.empty())
256 profile_shortcut_manager_.reset(ProfileShortcutManager::Create(
257 this));
260 ProfileManager::~ProfileManager() {
263 #if defined(ENABLE_SESSION_SERVICE)
264 // static
265 void ProfileManager::ShutdownSessionServices() {
266 ProfileManager* pm = g_browser_process->profile_manager();
267 if (!pm) // Is NULL when running unit tests.
268 return;
269 std::vector<Profile*> profiles(pm->GetLoadedProfiles());
270 for (size_t i = 0; i < profiles.size(); ++i)
271 SessionServiceFactory::ShutdownForProfile(profiles[i]);
273 #endif
275 // static
276 void ProfileManager::NukeDeletedProfilesFromDisk() {
277 for (std::vector<base::FilePath>::iterator it =
278 ProfilesToDelete().begin();
279 it != ProfilesToDelete().end();
280 ++it) {
281 NukeProfileFromDisk(*it);
283 ProfilesToDelete().clear();
286 // static
287 Profile* ProfileManager::GetLastUsedProfile() {
288 ProfileManager* profile_manager = g_browser_process->profile_manager();
289 return profile_manager->GetLastUsedProfile(profile_manager->user_data_dir_);
292 // static
293 Profile* ProfileManager::GetLastUsedProfileAllowedByPolicy() {
294 Profile* profile = GetLastUsedProfile();
295 if (profile->IsGuestSession() ||
296 IncognitoModePrefs::GetAvailability(profile->GetPrefs()) ==
297 IncognitoModePrefs::FORCED) {
298 return profile->GetOffTheRecordProfile();
300 return profile;
303 // static
304 std::vector<Profile*> ProfileManager::GetLastOpenedProfiles() {
305 ProfileManager* profile_manager = g_browser_process->profile_manager();
306 return profile_manager->GetLastOpenedProfiles(
307 profile_manager->user_data_dir_);
310 // static
311 Profile* ProfileManager::GetPrimaryUserProfile() {
312 ProfileManager* profile_manager = g_browser_process->profile_manager();
313 #if defined(OS_CHROMEOS)
314 if (!profile_manager->IsLoggedIn() || !chromeos::UserManager::IsInitialized())
315 return profile_manager->GetActiveUserOrOffTheRecordProfileFromPath(
316 profile_manager->user_data_dir());
317 chromeos::UserManager* manager = chromeos::UserManager::Get();
318 // Note: The user manager will take care of guest profiles.
319 return manager->GetProfileByUser(manager->GetPrimaryUser());
320 #else
321 return profile_manager->GetActiveUserOrOffTheRecordProfileFromPath(
322 profile_manager->user_data_dir());
323 #endif
326 // static
327 Profile* ProfileManager::GetActiveUserProfile() {
328 ProfileManager* profile_manager = g_browser_process->profile_manager();
329 #if defined(OS_CHROMEOS)
330 if (!profile_manager->IsLoggedIn() ||
331 !chromeos::UserManager::IsInitialized()) {
332 return profile_manager->GetActiveUserOrOffTheRecordProfileFromPath(
333 profile_manager->user_data_dir());
336 chromeos::UserManager* manager = chromeos::UserManager::Get();
337 const chromeos::User* user = manager->GetActiveUser();
338 // To avoid an endless loop (crbug.com/334098) we have to additionally check
339 // if the profile of the user was already created. If the profile was not yet
340 // created we load the profile using the profile directly.
341 // TODO: This should be cleaned up with the new profile manager.
342 if (user && user->is_profile_created())
343 return manager->GetProfileByUser(user);
344 #endif
345 return profile_manager->GetActiveUserOrOffTheRecordProfileFromPath(
346 profile_manager->user_data_dir());
349 Profile* ProfileManager::GetProfile(const base::FilePath& profile_dir) {
350 TRACE_EVENT0("browser", "ProfileManager::GetProfile")
351 // If the profile is already loaded (e.g., chrome.exe launched twice), just
352 // return it.
353 Profile* profile = GetProfileByPath(profile_dir);
354 if (NULL != profile)
355 return profile;
357 profile = CreateProfileHelper(profile_dir);
358 DCHECK(profile);
359 if (profile) {
360 bool result = AddProfile(profile);
361 DCHECK(result);
363 return profile;
366 size_t ProfileManager::GetNumberOfProfiles() {
367 return GetProfileInfoCache().GetNumberOfProfiles();
370 void ProfileManager::CreateProfileAsync(
371 const base::FilePath& profile_path,
372 const CreateCallback& callback,
373 const base::string16& name,
374 const base::string16& icon_url,
375 const std::string& managed_user_id) {
376 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
378 // Make sure that this profile is not pending deletion.
379 if (IsProfileMarkedForDeletion(profile_path)) {
380 if (!callback.is_null())
381 callback.Run(NULL, Profile::CREATE_STATUS_LOCAL_FAIL);
382 return;
385 // Create the profile if needed and collect its ProfileInfo.
386 ProfilesInfoMap::iterator iter = profiles_info_.find(profile_path);
387 ProfileInfo* info = NULL;
389 if (iter != profiles_info_.end()) {
390 info = iter->second.get();
391 } else {
392 // Initiate asynchronous creation process.
393 info = RegisterProfile(CreateProfileAsyncHelper(profile_path, this), false);
394 ProfileInfoCache& cache = GetProfileInfoCache();
395 // Get the icon index from the user's icon url
396 size_t icon_index;
397 std::string icon_url_std = base::UTF16ToASCII(icon_url);
398 if (profiles::IsDefaultAvatarIconUrl(icon_url_std, &icon_index)) {
399 // add profile to cache with user selected name and avatar
400 cache.AddProfileToCache(profile_path, name, base::string16(), icon_index,
401 managed_user_id);
404 if (!managed_user_id.empty()) {
405 content::RecordAction(
406 UserMetricsAction("ManagedMode_LocallyManagedUserCreated"));
409 ProfileMetrics::UpdateReportedProfilesStatistics(this);
412 // Call or enqueue the callback.
413 if (!callback.is_null()) {
414 if (iter != profiles_info_.end() && info->created) {
415 Profile* profile = info->profile.get();
416 // If this was the guest profile, apply settings and go OffTheRecord.
417 if (profile->GetPath() == ProfileManager::GetGuestProfilePath()) {
418 SetGuestProfilePrefs(profile);
419 profile = profile->GetOffTheRecordProfile();
421 // Profile has already been created. Run callback immediately.
422 callback.Run(profile, Profile::CREATE_STATUS_INITIALIZED);
423 } else {
424 // Profile is either already in the process of being created, or new.
425 // Add callback to the list.
426 info->callbacks.push_back(callback);
431 bool ProfileManager::IsValidProfile(Profile* profile) {
432 for (ProfilesInfoMap::iterator iter = profiles_info_.begin();
433 iter != profiles_info_.end(); ++iter) {
434 if (iter->second->created) {
435 Profile* candidate = iter->second->profile.get();
436 if (candidate == profile ||
437 (candidate->HasOffTheRecordProfile() &&
438 candidate->GetOffTheRecordProfile() == profile)) {
439 return true;
443 return false;
446 base::FilePath ProfileManager::GetInitialProfileDir() {
447 base::FilePath relative_profile_dir;
448 #if defined(OS_CHROMEOS)
449 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
450 if (logged_in_) {
451 base::FilePath profile_dir;
452 // If the user has logged in, pick up the new profile.
453 if (command_line.HasSwitch(chromeos::switches::kLoginProfile)) {
454 // TODO(nkostylev): Remove this code completely once we eliminate
455 // legacy --login-profile=user switch and enable multi-profiles on CrOS
456 // by default. http://crbug.com/294628
457 profile_dir = chromeos::ProfileHelper::
458 GetProfileDirByLegacyLoginProfileSwitch();
460 // In case of multi-profiles ignore --login-profile switch.
461 // TODO(nkostylev): Some cases like Guest mode will have empty username_hash
462 // so default kLoginProfile dir will be used.
463 std::string user_id_hash = g_browser_process->platform_part()->
464 profile_helper()->active_user_id_hash();
465 if (!user_id_hash.empty()) {
466 profile_dir = g_browser_process->platform_part()->
467 profile_helper()->GetActiveUserProfileDir();
469 relative_profile_dir = relative_profile_dir.Append(profile_dir);
470 return relative_profile_dir;
472 #endif
473 // TODO(mirandac): should not automatically be default profile.
474 relative_profile_dir =
475 relative_profile_dir.AppendASCII(chrome::kInitialProfile);
476 return relative_profile_dir;
479 Profile* ProfileManager::GetLastUsedProfile(
480 const base::FilePath& user_data_dir) {
481 #if defined(OS_CHROMEOS)
482 // Use default login profile if user has not logged in yet.
483 if (!logged_in_) {
484 return GetActiveUserOrOffTheRecordProfileFromPath(user_data_dir);
485 } else {
486 // CrOS multi-profiles implementation is different so GetLastUsedProfile
487 // has custom implementation too.
488 base::FilePath profile_dir;
489 // In case of multi-profiles we ignore "last used profile" preference
490 // since it may refer to profile that has been in use in previous session.
491 // That profile dir may not be mounted in this session so instead return
492 // active profile from current session.
493 profile_dir = g_browser_process->platform_part()->
494 profile_helper()->GetActiveUserProfileDir();
496 base::FilePath profile_path(user_data_dir);
497 Profile* profile = GetProfile(profile_path.Append(profile_dir));
498 return profile->IsGuestSession() ? profile->GetOffTheRecordProfile() :
499 profile;
501 #endif
503 return GetProfile(GetLastUsedProfileDir(user_data_dir));
506 base::FilePath ProfileManager::GetLastUsedProfileDir(
507 const base::FilePath& user_data_dir) {
508 base::FilePath last_used_profile_dir(user_data_dir);
509 PrefService* local_state = g_browser_process->local_state();
510 DCHECK(local_state);
512 if (local_state->HasPrefPath(prefs::kProfileLastUsed)) {
513 return last_used_profile_dir.AppendASCII(
514 local_state->GetString(prefs::kProfileLastUsed));
517 return last_used_profile_dir.AppendASCII(chrome::kInitialProfile);
520 std::vector<Profile*> ProfileManager::GetLastOpenedProfiles(
521 const base::FilePath& user_data_dir) {
522 PrefService* local_state = g_browser_process->local_state();
523 DCHECK(local_state);
525 std::vector<Profile*> to_return;
526 if (local_state->HasPrefPath(prefs::kProfilesLastActive) &&
527 local_state->GetList(prefs::kProfilesLastActive)) {
528 // Make a copy because the list might change in the calls to GetProfile.
529 scoped_ptr<base::ListValue> profile_list(
530 local_state->GetList(prefs::kProfilesLastActive)->DeepCopy());
531 base::ListValue::const_iterator it;
532 std::string profile;
533 for (it = profile_list->begin(); it != profile_list->end(); ++it) {
534 if (!(*it)->GetAsString(&profile) || profile.empty()) {
535 LOG(WARNING) << "Invalid entry in " << prefs::kProfilesLastActive;
536 continue;
538 to_return.push_back(GetProfile(user_data_dir.AppendASCII(profile)));
541 return to_return;
544 std::vector<Profile*> ProfileManager::GetLoadedProfiles() const {
545 std::vector<Profile*> profiles;
546 for (ProfilesInfoMap::const_iterator iter = profiles_info_.begin();
547 iter != profiles_info_.end(); ++iter) {
548 if (iter->second->created)
549 profiles.push_back(iter->second->profile.get());
551 return profiles;
554 Profile* ProfileManager::GetProfileByPath(const base::FilePath& path) const {
555 ProfileInfo* profile_info = GetProfileInfoByPath(path);
556 return profile_info ? profile_info->profile.get() : NULL;
559 // static
560 base::FilePath ProfileManager::CreateMultiProfileAsync(
561 const base::string16& name,
562 const base::string16& icon_url,
563 const CreateCallback& callback,
564 const std::string& managed_user_id) {
565 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
567 ProfileManager* profile_manager = g_browser_process->profile_manager();
569 base::FilePath new_path = profile_manager->GenerateNextProfileDirectoryPath();
571 profile_manager->CreateProfileAsync(new_path,
572 callback,
573 name,
574 icon_url,
575 managed_user_id);
576 return new_path;
579 // static
580 base::FilePath ProfileManager::GetGuestProfilePath() {
581 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
583 ProfileManager* profile_manager = g_browser_process->profile_manager();
585 base::FilePath guest_path = profile_manager->user_data_dir();
586 return guest_path.Append(chrome::kGuestProfileDir);
589 base::FilePath ProfileManager::GenerateNextProfileDirectoryPath() {
590 PrefService* local_state = g_browser_process->local_state();
591 DCHECK(local_state);
593 DCHECK(profiles::IsMultipleProfilesEnabled());
595 // Create the next profile in the next available directory slot.
596 int next_directory = local_state->GetInteger(prefs::kProfilesNumCreated);
597 std::string profile_name = chrome::kMultiProfileDirPrefix;
598 profile_name.append(base::IntToString(next_directory));
599 base::FilePath new_path = user_data_dir_;
600 #if defined(OS_WIN)
601 new_path = new_path.Append(base::ASCIIToUTF16(profile_name));
602 #else
603 new_path = new_path.Append(profile_name);
604 #endif
605 local_state->SetInteger(prefs::kProfilesNumCreated, ++next_directory);
606 return new_path;
609 ProfileInfoCache& ProfileManager::GetProfileInfoCache() {
610 if (!profile_info_cache_) {
611 profile_info_cache_.reset(new ProfileInfoCache(
612 g_browser_process->local_state(), user_data_dir_));
614 return *profile_info_cache_.get();
617 ProfileShortcutManager* ProfileManager::profile_shortcut_manager() {
618 return profile_shortcut_manager_.get();
621 void ProfileManager::ScheduleProfileForDeletion(
622 const base::FilePath& profile_dir,
623 const CreateCallback& callback) {
624 DCHECK(profiles::IsMultipleProfilesEnabled());
626 // Cancel all in-progress downloads before deleting the profile to prevent a
627 // "Do you want to exit Google Chrome and cancel the downloads?" prompt
628 // (crbug.com/336725).
629 Profile* profile = GetProfileByPath(profile_dir);
630 if (profile) {
631 DownloadService* service =
632 DownloadServiceFactory::GetForBrowserContext(profile);
633 service->CancelDownloads();
636 PrefService* local_state = g_browser_process->local_state();
637 ProfileInfoCache& cache = GetProfileInfoCache();
639 if (profile_dir.BaseName().MaybeAsASCII() ==
640 local_state->GetString(prefs::kProfileLastUsed)) {
641 // Update the last used profile pref before closing browser windows. This
642 // way the correct last used profile is set for any notification observers.
643 base::FilePath last_non_managed_profile_path;
644 for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) {
645 base::FilePath cur_path = cache.GetPathOfProfileAtIndex(i);
646 // Make sure that this profile is not pending deletion.
647 if (cur_path != profile_dir && !cache.ProfileIsManagedAtIndex(i) &&
648 !IsProfileMarkedForDeletion(cur_path)) {
649 last_non_managed_profile_path = cur_path;
650 break;
654 // If we're deleting the last (non-managed) profile, then create a new
655 // profile in its place.
656 const std::string last_non_managed_profile =
657 last_non_managed_profile_path.BaseName().MaybeAsASCII();
658 if (last_non_managed_profile.empty()) {
659 base::FilePath new_path = GenerateNextProfileDirectoryPath();
660 // Make sure the last used profile path is pointing at it. This way the
661 // correct last used profile is set for any notification observers.
662 local_state->SetString(prefs::kProfileLastUsed,
663 new_path.BaseName().MaybeAsASCII());
664 CreateProfileAsync(new_path,
665 callback,
666 base::string16(),
667 base::string16(),
668 std::string());
669 } else {
670 // On the Mac, the browser process is not killed when all browser windows
671 // are closed, so just in case we are deleting the active profile, and no
672 // other profile has been loaded, we must pre-load a next one.
673 #if defined(OS_MACOSX)
674 CreateProfileAsync(last_non_managed_profile_path,
675 base::Bind(&ProfileManager::OnNewActiveProfileLoaded,
676 base::Unretained(this),
677 profile_dir,
678 last_non_managed_profile_path,
679 callback),
680 base::string16(),
681 base::string16(),
682 std::string());
683 return;
684 #else
685 // For OS_MACOSX the pref is updated in the callback to make sure that
686 // it isn't used before the profile is actually loaded.
687 local_state->SetString(prefs::kProfileLastUsed, last_non_managed_profile);
688 #endif
691 FinishDeletingProfile(profile_dir);
694 // static
695 void ProfileManager::CleanUpStaleProfiles(
696 const std::vector<base::FilePath>& profile_paths) {
697 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
699 for (std::vector<base::FilePath>::const_iterator it = profile_paths.begin();
700 it != profile_paths.end(); ++it) {
701 NukeProfileFromDisk(*it);
705 void ProfileManager::AutoloadProfiles() {
706 // If running in the background is disabled for the browser, do not autoload
707 // any profiles.
708 PrefService* local_state = g_browser_process->local_state();
709 if (!local_state->HasPrefPath(prefs::kBackgroundModeEnabled) ||
710 !local_state->GetBoolean(prefs::kBackgroundModeEnabled)) {
711 return;
714 ProfileInfoCache& cache = GetProfileInfoCache();
715 size_t number_of_profiles = cache.GetNumberOfProfiles();
716 for (size_t p = 0; p < number_of_profiles; ++p) {
717 if (cache.GetBackgroundStatusOfProfileAtIndex(p)) {
718 // If status is true, that profile is running background apps. By calling
719 // GetProfile, we automatically cause the profile to be loaded which will
720 // register it with the BackgroundModeManager.
721 GetProfile(cache.GetPathOfProfileAtIndex(p));
726 void ProfileManager::InitProfileUserPrefs(Profile* profile) {
727 ProfileInfoCache& cache = GetProfileInfoCache();
729 if (profile->GetPath().DirName() != cache.GetUserDataDir())
730 return;
732 size_t avatar_index;
733 std::string profile_name;
734 std::string managed_user_id;
735 if (profile->IsGuestSession()) {
736 profile_name = l10n_util::GetStringUTF8(IDS_PROFILES_GUEST_PROFILE_NAME);
737 avatar_index = 0;
738 } else {
739 size_t profile_cache_index =
740 cache.GetIndexOfProfileWithPath(profile->GetPath());
741 // If the cache has an entry for this profile, use the cache data.
742 if (profile_cache_index != std::string::npos) {
743 avatar_index =
744 cache.GetAvatarIconIndexOfProfileAtIndex(profile_cache_index);
745 profile_name =
746 base::UTF16ToUTF8(cache.GetNameOfProfileAtIndex(profile_cache_index));
747 managed_user_id =
748 cache.GetManagedUserIdOfProfileAtIndex(profile_cache_index);
749 } else if (profile->GetPath() ==
750 profiles::GetDefaultProfileDir(cache.GetUserDataDir())) {
751 avatar_index = 0;
752 // The --new-profile-management flag no longer uses the "First User" name.
753 profile_name = switches::IsNewProfileManagement() ?
754 base::UTF16ToUTF8(cache.ChooseNameForNewProfile(avatar_index)) :
755 l10n_util::GetStringUTF8(IDS_DEFAULT_PROFILE_NAME);
756 } else {
757 avatar_index = cache.ChooseAvatarIconIndexForNewProfile();
758 profile_name =
759 base::UTF16ToUTF8(cache.ChooseNameForNewProfile(avatar_index));
763 if (!profile->GetPrefs()->HasPrefPath(prefs::kProfileAvatarIndex))
764 profile->GetPrefs()->SetInteger(prefs::kProfileAvatarIndex, avatar_index);
766 if (!profile->GetPrefs()->HasPrefPath(prefs::kProfileName))
767 profile->GetPrefs()->SetString(prefs::kProfileName, profile_name);
769 CommandLine* command_line = CommandLine::ForCurrentProcess();
770 bool force_managed_user_id =
771 command_line->HasSwitch(switches::kManagedUserId);
772 if (force_managed_user_id) {
773 managed_user_id =
774 command_line->GetSwitchValueASCII(switches::kManagedUserId);
776 if (force_managed_user_id ||
777 !profile->GetPrefs()->HasPrefPath(prefs::kManagedUserId)) {
778 profile->GetPrefs()->SetString(prefs::kManagedUserId, managed_user_id);
782 void ProfileManager::RegisterTestingProfile(Profile* profile,
783 bool add_to_cache,
784 bool start_deferred_task_runners) {
785 RegisterProfile(profile, true);
786 if (add_to_cache) {
787 InitProfileUserPrefs(profile);
788 AddProfileToCache(profile);
790 if (start_deferred_task_runners) {
791 StartupTaskRunnerServiceFactory::GetForProfile(profile)->
792 StartDeferredTaskRunners();
796 void ProfileManager::Observe(
797 int type,
798 const content::NotificationSource& source,
799 const content::NotificationDetails& details) {
800 #if defined(OS_CHROMEOS)
801 if (type == chrome::NOTIFICATION_LOGIN_USER_CHANGED) {
802 logged_in_ = true;
804 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
805 if (!command_line.HasSwitch(switches::kTestType)) {
806 // If we don't have a mounted profile directory we're in trouble.
807 // TODO(davemoore) Once we have better api this check should ensure that
808 // our profile directory is the one that's mounted, and that it's mounted
809 // as the current user.
810 chromeos::DBusThreadManager::Get()->GetCryptohomeClient()->IsMounted(
811 base::Bind(&CheckCryptohomeIsMounted));
813 // Confirm that we hadn't loaded the new profile previously.
814 base::FilePath default_profile_dir = user_data_dir_.Append(
815 GetInitialProfileDir());
816 CHECK(!GetProfileByPath(default_profile_dir))
817 << "The default profile was loaded before we mounted the cryptohome.";
819 return;
821 #endif
822 bool save_active_profiles = false;
823 switch (type) {
824 case chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST: {
825 // Ignore any browsers closing from now on.
826 closing_all_browsers_ = true;
827 save_active_profiles = true;
828 break;
830 case chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED: {
831 // This will cancel the shutdown process, so the active profiles are
832 // tracked again. Also, as the active profiles may have changed (i.e. if
833 // some windows were closed) we save the current list of active profiles
834 // again.
835 closing_all_browsers_ = false;
836 save_active_profiles = true;
837 break;
839 case chrome::NOTIFICATION_BROWSER_OPENED: {
840 Browser* browser = content::Source<Browser>(source).ptr();
841 DCHECK(browser);
842 Profile* profile = browser->profile();
843 DCHECK(profile);
844 bool is_ephemeral =
845 profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles);
846 if (!profile->IsOffTheRecord() && !is_ephemeral &&
847 ++browser_counts_[profile] == 1) {
848 active_profiles_.push_back(profile);
849 save_active_profiles = true;
851 // If browsers are opening, we can't be closing all the browsers. This
852 // can happen if the application was exited, but background mode or
853 // packaged apps prevented the process from shutting down, and then
854 // a new browser window was opened.
855 closing_all_browsers_ = false;
856 break;
858 case chrome::NOTIFICATION_BROWSER_CLOSED: {
859 Browser* browser = content::Source<Browser>(source).ptr();
860 DCHECK(browser);
861 Profile* profile = browser->profile();
862 DCHECK(profile);
863 if (!profile->IsOffTheRecord() && --browser_counts_[profile] == 0) {
864 active_profiles_.erase(std::find(active_profiles_.begin(),
865 active_profiles_.end(), profile));
866 save_active_profiles = !closing_all_browsers_;
868 break;
870 case chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED: {
871 save_active_profiles = !closing_all_browsers_;
872 break;
874 default: {
875 NOTREACHED();
876 break;
880 if (save_active_profiles) {
881 PrefService* local_state = g_browser_process->local_state();
882 DCHECK(local_state);
883 ListPrefUpdate update(local_state, prefs::kProfilesLastActive);
884 base::ListValue* profile_list = update.Get();
886 profile_list->Clear();
888 // crbug.com/120112 -> several non-incognito profiles might have the same
889 // GetPath().BaseName(). In that case, we cannot restore both
890 // profiles. Include each base name only once in the last active profile
891 // list.
892 std::set<std::string> profile_paths;
893 std::vector<Profile*>::const_iterator it;
894 for (it = active_profiles_.begin(); it != active_profiles_.end(); ++it) {
895 std::string profile_path = (*it)->GetPath().BaseName().MaybeAsASCII();
896 // Some profiles might become ephemeral after they are created.
897 if (!(*it)->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles) &&
898 profile_paths.find(profile_path) == profile_paths.end()) {
899 profile_paths.insert(profile_path);
900 profile_list->Append(new base::StringValue(profile_path));
906 void ProfileManager::OnProfileCreated(Profile* profile,
907 bool success,
908 bool is_new_profile) {
909 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
911 ProfilesInfoMap::iterator iter = profiles_info_.find(profile->GetPath());
912 DCHECK(iter != profiles_info_.end());
913 ProfileInfo* info = iter->second.get();
915 std::vector<CreateCallback> callbacks;
916 info->callbacks.swap(callbacks);
918 // Invoke CREATED callback for normal profiles.
919 bool go_off_the_record = ShouldGoOffTheRecord(profile);
920 if (success && !go_off_the_record)
921 RunCallbacks(callbacks, profile, Profile::CREATE_STATUS_CREATED);
923 // Perform initialization.
924 if (success) {
925 DoFinalInit(profile, go_off_the_record);
926 if (go_off_the_record)
927 profile = profile->GetOffTheRecordProfile();
928 info->created = true;
929 } else {
930 profile = NULL;
931 profiles_info_.erase(iter);
934 if (profile) {
935 // If this was the guest profile, finish setting its special status.
936 if (profile->GetPath() == ProfileManager::GetGuestProfilePath())
937 SetGuestProfilePrefs(profile);
939 // Invoke CREATED callback for incognito profiles.
940 if (go_off_the_record)
941 RunCallbacks(callbacks, profile, Profile::CREATE_STATUS_CREATED);
944 // Invoke INITIALIZED or FAIL for all profiles.
945 RunCallbacks(callbacks, profile,
946 profile ? Profile::CREATE_STATUS_INITIALIZED :
947 Profile::CREATE_STATUS_LOCAL_FAIL);
950 void ProfileManager::DoFinalInit(Profile* profile, bool go_off_the_record) {
951 DoFinalInitForServices(profile, go_off_the_record);
952 AddProfileToCache(profile);
953 DoFinalInitLogging(profile);
955 ProfileMetrics::LogNumberOfProfiles(this);
956 content::NotificationService::current()->Notify(
957 chrome::NOTIFICATION_PROFILE_ADDED,
958 content::Source<Profile>(profile),
959 content::NotificationService::NoDetails());
962 void ProfileManager::DoFinalInitForServices(Profile* profile,
963 bool go_off_the_record) {
964 #if defined(ENABLE_EXTENSIONS)
965 extensions::ExtensionSystem::Get(profile)->InitForRegularProfile(
966 !go_off_the_record);
967 // During tests, when |profile| is an instance of TestingProfile,
968 // ExtensionSystem might not create an ExtensionService.
969 if (extensions::ExtensionSystem::Get(profile)->extension_service()) {
970 profile->GetHostContentSettingsMap()->RegisterExtensionService(
971 extensions::ExtensionSystem::Get(profile)->extension_service());
973 #endif
974 #if defined(ENABLE_MANAGED_USERS)
975 // Initialization needs to happen after extension system initialization (for
976 // extension::ManagementPolicy) and InitProfileUserPrefs (for setting the
977 // initializing the managed flag if necessary).
978 ManagedUserServiceFactory::GetForProfile(profile)->Init();
979 #endif
980 // Start the deferred task runners once the profile is loaded.
981 StartupTaskRunnerServiceFactory::GetForProfile(profile)->
982 StartDeferredTaskRunners();
984 AccountReconcilorFactory::GetForProfile(profile);
987 void ProfileManager::DoFinalInitLogging(Profile* profile) {
988 // Count number of extensions in this profile.
989 int enabled_app_count = -1;
990 #if defined(ENABLE_EXTENSIONS)
991 enabled_app_count = GetEnabledAppCount(profile);
992 #endif
994 // Log the profile size after a reasonable startup delay.
995 BrowserThread::PostDelayedTask(
996 BrowserThread::FILE, FROM_HERE,
997 base::Bind(&ProfileSizeTask, profile->GetPath(), enabled_app_count),
998 base::TimeDelta::FromSeconds(112));
1001 Profile* ProfileManager::CreateProfileHelper(const base::FilePath& path) {
1002 return Profile::CreateProfile(path, NULL, Profile::CREATE_MODE_SYNCHRONOUS);
1005 Profile* ProfileManager::CreateProfileAsyncHelper(const base::FilePath& path,
1006 Delegate* delegate) {
1007 return Profile::CreateProfile(path,
1008 delegate,
1009 Profile::CREATE_MODE_ASYNCHRONOUS);
1012 Profile* ProfileManager::GetActiveUserOrOffTheRecordProfileFromPath(
1013 const base::FilePath& user_data_dir) {
1014 #if defined(OS_CHROMEOS)
1015 base::FilePath default_profile_dir(user_data_dir);
1016 if (!logged_in_) {
1017 default_profile_dir = profiles::GetDefaultProfileDir(user_data_dir);
1018 Profile* profile = GetProfile(default_profile_dir);
1019 // For cros, return the OTR profile so we never accidentally keep
1020 // user data in an unencrypted profile. But doing this makes
1021 // many of the browser and ui tests fail. We do return the OTR profile
1022 // if the login-profile switch is passed so that we can test this.
1023 if (ShouldGoOffTheRecord(profile))
1024 return profile->GetOffTheRecordProfile();
1025 DCHECK(!chromeos::UserManager::Get()->IsLoggedInAsGuest());
1026 return profile;
1029 default_profile_dir = default_profile_dir.Append(GetInitialProfileDir());
1030 ProfileInfo* profile_info = GetProfileInfoByPath(default_profile_dir);
1031 // Fallback to default off-the-record profile, if user profile has not fully
1032 // loaded yet.
1033 if (profile_info && !profile_info->created)
1034 default_profile_dir = profiles::GetDefaultProfileDir(user_data_dir);
1036 Profile* profile = GetProfile(default_profile_dir);
1037 // Some unit tests didn't initialize the UserManager.
1038 if (chromeos::UserManager::IsInitialized() &&
1039 chromeos::UserManager::Get()->IsLoggedInAsGuest())
1040 return profile->GetOffTheRecordProfile();
1041 return profile;
1042 #else
1043 base::FilePath default_profile_dir(user_data_dir);
1044 default_profile_dir = default_profile_dir.Append(GetInitialProfileDir());
1045 return GetProfile(default_profile_dir);
1046 #endif
1049 bool ProfileManager::AddProfile(Profile* profile) {
1050 DCHECK(profile);
1052 // Make sure that we're not loading a profile with the same ID as a profile
1053 // that's already loaded.
1054 if (GetProfileByPath(profile->GetPath())) {
1055 NOTREACHED() << "Attempted to add profile with the same path (" <<
1056 profile->GetPath().value() <<
1057 ") as an already-loaded profile.";
1058 return false;
1061 RegisterProfile(profile, true);
1062 InitProfileUserPrefs(profile);
1063 DoFinalInit(profile, ShouldGoOffTheRecord(profile));
1064 return true;
1067 void ProfileManager::FinishDeletingProfile(const base::FilePath& profile_dir) {
1068 ProfileInfoCache& cache = GetProfileInfoCache();
1069 // TODO(sail): Due to bug 88586 we don't delete the profile instance. Once we
1070 // start deleting the profile instance we need to close background apps too.
1071 Profile* profile = GetProfileByPath(profile_dir);
1073 if (profile) {
1074 // TODO: Migrate additional code in this block to observe this notification
1075 // instead of being implemented here.
1076 content::NotificationService::current()->Notify(
1077 chrome::NOTIFICATION_PROFILE_DESTRUCTION_STARTED,
1078 content::Source<Profile>(profile),
1079 content::NotificationService::NoDetails());
1081 // By this point, all in-progress downloads for the profile being deleted
1082 // must have been canceled (crbug.com/336725).
1083 DCHECK(DownloadServiceFactory::GetForBrowserContext(profile)->
1084 NonMaliciousDownloadCount() == 0);
1085 BrowserList::CloseAllBrowsersWithProfile(profile);
1087 // Disable sync for doomed profile.
1088 if (ProfileSyncServiceFactory::GetInstance()->HasProfileSyncService(
1089 profile)) {
1090 ProfileSyncServiceFactory::GetInstance()->GetForProfile(
1091 profile)->DisableForUser();
1095 QueueProfileDirectoryForDeletion(profile_dir);
1096 cache.DeleteProfileFromCache(profile_dir);
1097 ProfileMetrics::UpdateReportedProfilesStatistics(this);
1100 ProfileManager::ProfileInfo* ProfileManager::RegisterProfile(
1101 Profile* profile,
1102 bool created) {
1103 ProfileInfo* info = new ProfileInfo(profile, created);
1104 profiles_info_.insert(
1105 std::make_pair(profile->GetPath(), linked_ptr<ProfileInfo>(info)));
1106 return info;
1109 ProfileManager::ProfileInfo* ProfileManager::GetProfileInfoByPath(
1110 const base::FilePath& path) const {
1111 ProfilesInfoMap::const_iterator iter = profiles_info_.find(path);
1112 return (iter == profiles_info_.end()) ? NULL : iter->second.get();
1115 void ProfileManager::AddProfileToCache(Profile* profile) {
1116 if (profile->IsGuestSession())
1117 return;
1118 ProfileInfoCache& cache = GetProfileInfoCache();
1119 if (profile->GetPath().DirName() != cache.GetUserDataDir())
1120 return;
1122 if (cache.GetIndexOfProfileWithPath(profile->GetPath()) != std::string::npos)
1123 return;
1125 base::string16 username = base::UTF8ToUTF16(profile->GetPrefs()->GetString(
1126 prefs::kGoogleServicesUsername));
1128 // Profile name and avatar are set by InitProfileUserPrefs and stored in the
1129 // profile. Use those values to setup the cache entry.
1130 base::string16 profile_name =
1131 base::UTF8ToUTF16(profile->GetPrefs()->GetString(prefs::kProfileName));
1133 size_t icon_index = profile->GetPrefs()->GetInteger(
1134 prefs::kProfileAvatarIndex);
1136 std::string managed_user_id =
1137 profile->GetPrefs()->GetString(prefs::kManagedUserId);
1139 cache.AddProfileToCache(profile->GetPath(),
1140 profile_name,
1141 username,
1142 icon_index,
1143 managed_user_id);
1145 if (profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles)) {
1146 cache.SetProfileIsEphemeralAtIndex(
1147 cache.GetIndexOfProfileWithPath(profile->GetPath()), true);
1151 void ProfileManager::SetGuestProfilePrefs(Profile* profile) {
1152 PrefService* prefs = profile->GetPrefs();
1153 prefs->SetBoolean(prefs::kSigninAllowed, false);
1154 prefs->SetBoolean(prefs::kEditBookmarksEnabled, false);
1155 prefs->SetBoolean(prefs::kShowBookmarkBar, false);
1156 // This can be removed in the future but needs to be present through
1157 // a release (or two) so that any existing installs get switched to
1158 // the new state and away from the previous "forced" state.
1159 IncognitoModePrefs::SetAvailability(prefs, IncognitoModePrefs::ENABLED);
1162 bool ProfileManager::ShouldGoOffTheRecord(Profile* profile) {
1163 #if defined(OS_CHROMEOS)
1164 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1165 if (profile->GetPath().BaseName().value() == chrome::kInitialProfile &&
1166 (!command_line.HasSwitch(switches::kTestType) ||
1167 command_line.HasSwitch(chromeos::switches::kLoginProfile))) {
1168 return true;
1170 #endif
1171 return profile->IsGuestSession();
1174 void ProfileManager::RunCallbacks(const std::vector<CreateCallback>& callbacks,
1175 Profile* profile,
1176 Profile::CreateStatus status) {
1177 for (size_t i = 0; i < callbacks.size(); ++i)
1178 callbacks[i].Run(profile, status);
1181 ProfileManager::ProfileInfo::ProfileInfo(
1182 Profile* profile,
1183 bool created)
1184 : profile(profile),
1185 created(created) {
1188 ProfileManager::ProfileInfo::~ProfileInfo() {
1189 ProfileDestroyer::DestroyProfileWhenAppropriate(profile.release());
1192 #if !defined(OS_ANDROID) && !defined(OS_IOS)
1193 ProfileManager::BrowserListObserver::BrowserListObserver(
1194 ProfileManager* manager)
1195 : profile_manager_(manager) {
1196 BrowserList::AddObserver(this);
1199 ProfileManager::BrowserListObserver::~BrowserListObserver() {
1200 BrowserList::RemoveObserver(this);
1203 void ProfileManager::BrowserListObserver::OnBrowserAdded(
1204 Browser* browser) {}
1206 void ProfileManager::BrowserListObserver::OnBrowserRemoved(
1207 Browser* browser) {
1208 Profile* profile = browser->profile();
1209 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
1210 if (it->profile()->GetOriginalProfile() == profile->GetOriginalProfile())
1211 // Not the last window for this profile.
1212 return;
1215 // If the last browser of a profile that is scheduled for deletion is closed
1216 // do that now.
1217 base::FilePath path = profile->GetPath();
1218 if (profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles) &&
1219 !IsProfileMarkedForDeletion(path)) {
1220 g_browser_process->profile_manager()->ScheduleProfileForDeletion(
1221 path, ProfileManager::CreateCallback());
1225 void ProfileManager::BrowserListObserver::OnBrowserSetLastActive(
1226 Browser* browser) {
1227 // If all browsers are being closed (e.g. the user is in the process of
1228 // shutting down), this event will be fired after each browser is
1229 // closed. This does not represent a user intention to change the active
1230 // browser so is not handled here.
1231 if (profile_manager_->closing_all_browsers_)
1232 return;
1234 Profile* last_active = browser->profile();
1236 // Don't remember ephemeral profiles as last because they are not going to
1237 // persist after restart.
1238 if (last_active->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles))
1239 return;
1241 PrefService* local_state = g_browser_process->local_state();
1242 DCHECK(local_state);
1243 // Only keep track of profiles that we are managing; tests may create others.
1244 if (profile_manager_->profiles_info_.find(
1245 last_active->GetPath()) != profile_manager_->profiles_info_.end()) {
1246 local_state->SetString(prefs::kProfileLastUsed,
1247 last_active->GetPath().BaseName().MaybeAsASCII());
1249 ProfileInfoCache& cache = profile_manager_->GetProfileInfoCache();
1250 size_t profile_index =
1251 cache.GetIndexOfProfileWithPath(last_active->GetPath());
1252 if (profile_index != std::string::npos)
1253 cache.SetProfileActiveTimeAtIndex(profile_index);
1256 #endif // !defined(OS_ANDROID) && !defined(OS_IOS)
1258 #if defined(OS_MACOSX)
1259 void ProfileManager::OnNewActiveProfileLoaded(
1260 const base::FilePath& profile_to_delete_path,
1261 const base::FilePath& last_non_managed_profile_path,
1262 const CreateCallback& original_callback,
1263 Profile* loaded_profile,
1264 Profile::CreateStatus status) {
1265 DCHECK(status != Profile::CREATE_STATUS_LOCAL_FAIL &&
1266 status != Profile::CREATE_STATUS_REMOTE_FAIL);
1268 // Only run the code if the profile initialization has finished completely.
1269 if (status == Profile::CREATE_STATUS_INITIALIZED) {
1270 if (IsProfileMarkedForDeletion(last_non_managed_profile_path)) {
1271 // If the profile we tried to load as the next active profile has been
1272 // deleted, then retry deleting this profile to redo the logic to load
1273 // the next available profile.
1274 ScheduleProfileForDeletion(profile_to_delete_path, original_callback);
1275 } else {
1276 // Update the local state as promised in the ScheduleProfileForDeletion.
1277 g_browser_process->local_state()->SetString(
1278 prefs::kProfileLastUsed,
1279 last_non_managed_profile_path.BaseName().MaybeAsASCII());
1280 FinishDeletingProfile(profile_to_delete_path);
1284 #endif
1286 ProfileManagerWithoutInit::ProfileManagerWithoutInit(
1287 const base::FilePath& user_data_dir) : ProfileManager(user_data_dir) {