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"
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/core/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"
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)
77 #include "base/win/metro.h"
78 #include "chrome/installer/util/browser_distribution.h"
81 #if defined(OS_CHROMEOS)
82 #include "chrome/browser/browser_process_platform_part_chromeos.h"
83 #include "chrome/browser/chromeos/login/user.h"
84 #include "chrome/browser/chromeos/login/user_manager.h"
85 #include "chrome/browser/chromeos/profiles/profile_helper.h"
86 #include "chromeos/chromeos_switches.h"
87 #include "chromeos/dbus/cryptohome_client.h"
88 #include "chromeos/dbus/dbus_thread_manager.h"
91 using base::UserMetricsAction;
92 using content::BrowserThread;
96 // Profiles that should be deleted on shutdown.
97 std::vector<base::FilePath>& ProfilesToDelete() {
98 CR_DEFINE_STATIC_LOCAL(std::vector<base::FilePath>, profiles_to_delete, ());
99 return profiles_to_delete;
102 int64 ComputeFilesSize(const base::FilePath& directory,
103 const base::FilePath::StringType& pattern) {
104 int64 running_size = 0;
105 base::FileEnumerator iter(directory, false, base::FileEnumerator::FILES,
107 while (!iter.Next().empty())
108 running_size += iter.GetInfo().GetSize();
112 // Simple task to log the size of the current profile.
113 void ProfileSizeTask(const base::FilePath& path, int enabled_app_count) {
114 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
115 const int64 kBytesInOneMB = 1024 * 1024;
117 int64 size = ComputeFilesSize(path, FILE_PATH_LITERAL("*"));
118 int size_MB = static_cast<int>(size / kBytesInOneMB);
119 UMA_HISTOGRAM_COUNTS_10000("Profile.TotalSize", size_MB);
121 size = ComputeFilesSize(path, FILE_PATH_LITERAL("History"));
122 size_MB = static_cast<int>(size / kBytesInOneMB);
123 UMA_HISTOGRAM_COUNTS_10000("Profile.HistorySize", size_MB);
125 size = ComputeFilesSize(path, FILE_PATH_LITERAL("History*"));
126 size_MB = static_cast<int>(size / kBytesInOneMB);
127 UMA_HISTOGRAM_COUNTS_10000("Profile.TotalHistorySize", size_MB);
129 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Cookies"));
130 size_MB = static_cast<int>(size / kBytesInOneMB);
131 UMA_HISTOGRAM_COUNTS_10000("Profile.CookiesSize", size_MB);
133 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Bookmarks"));
134 size_MB = static_cast<int>(size / kBytesInOneMB);
135 UMA_HISTOGRAM_COUNTS_10000("Profile.BookmarksSize", size_MB);
137 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Favicons"));
138 size_MB = static_cast<int>(size / kBytesInOneMB);
139 UMA_HISTOGRAM_COUNTS_10000("Profile.FaviconsSize", size_MB);
141 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Top Sites"));
142 size_MB = static_cast<int>(size / kBytesInOneMB);
143 UMA_HISTOGRAM_COUNTS_10000("Profile.TopSitesSize", size_MB);
145 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Visited Links"));
146 size_MB = static_cast<int>(size / kBytesInOneMB);
147 UMA_HISTOGRAM_COUNTS_10000("Profile.VisitedLinksSize", size_MB);
149 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Web Data"));
150 size_MB = static_cast<int>(size / kBytesInOneMB);
151 UMA_HISTOGRAM_COUNTS_10000("Profile.WebDataSize", size_MB);
153 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Extension*"));
154 size_MB = static_cast<int>(size / kBytesInOneMB);
155 UMA_HISTOGRAM_COUNTS_10000("Profile.ExtensionSize", size_MB);
157 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Policy"));
158 size_MB = static_cast<int>(size / kBytesInOneMB);
159 UMA_HISTOGRAM_COUNTS_10000("Profile.PolicySize", size_MB);
161 // Count number of enabled apps in this profile, if we know.
162 if (enabled_app_count != -1)
163 UMA_HISTOGRAM_COUNTS_10000("Profile.AppCount", enabled_app_count);
166 void QueueProfileDirectoryForDeletion(const base::FilePath& path) {
167 ProfilesToDelete().push_back(path);
170 bool IsProfileMarkedForDeletion(const base::FilePath& profile_path) {
171 return std::find(ProfilesToDelete().begin(), ProfilesToDelete().end(),
172 profile_path) != ProfilesToDelete().end();
175 // Physically remove deleted profile directories from disk.
176 void NukeProfileFromDisk(const base::FilePath& profile_path) {
177 // Delete both the profile directory and its corresponding cache.
178 base::FilePath cache_path;
179 chrome::GetUserCacheDirectory(profile_path, &cache_path);
180 base::DeleteFile(profile_path, true);
181 base::DeleteFile(cache_path, true);
184 #if defined(OS_CHROMEOS)
185 void CheckCryptohomeIsMounted(chromeos::DBusMethodCallStatus call_status,
187 if (call_status != chromeos::DBUS_METHOD_CALL_SUCCESS) {
188 LOG(ERROR) << "IsMounted call failed.";
192 LOG(ERROR) << "Cryptohome is not mounted.";
197 #if defined(ENABLE_EXTENSIONS)
199 // Returns the number of installed (and enabled) apps, excluding any component
201 size_t GetEnabledAppCount(Profile* profile) {
202 size_t installed_apps = 0u;
203 const extensions::ExtensionSet& extensions =
204 extensions::ExtensionRegistry::Get(profile)->enabled_extensions();
205 for (extensions::ExtensionSet::const_iterator iter = extensions.begin();
206 iter != extensions.end();
208 if ((*iter)->is_app() &&
209 (*iter)->location() != extensions::Manifest::COMPONENT) {
213 return installed_apps;
216 #endif // ENABLE_EXTENSIONS
220 ProfileManager::ProfileManager(const base::FilePath& user_data_dir)
221 : user_data_dir_(user_data_dir),
223 #if !defined(OS_ANDROID) && !defined(OS_IOS)
224 browser_list_observer_(this),
226 closing_all_browsers_(false) {
227 #if defined(OS_CHROMEOS)
230 chrome::NOTIFICATION_LOGIN_USER_CHANGED,
231 content::NotificationService::AllSources());
235 chrome::NOTIFICATION_BROWSER_OPENED,
236 content::NotificationService::AllSources());
239 chrome::NOTIFICATION_BROWSER_CLOSED,
240 content::NotificationService::AllSources());
243 chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST,
244 content::NotificationService::AllSources());
247 chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED,
248 content::NotificationService::AllSources());
251 chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
252 content::NotificationService::AllSources());
254 if (ProfileShortcutManager::IsFeatureEnabled() && !user_data_dir_.empty())
255 profile_shortcut_manager_.reset(ProfileShortcutManager::Create(
259 ProfileManager::~ProfileManager() {
262 #if defined(ENABLE_SESSION_SERVICE)
264 void ProfileManager::ShutdownSessionServices() {
265 ProfileManager* pm = g_browser_process->profile_manager();
266 if (!pm) // Is NULL when running unit tests.
268 std::vector<Profile*> profiles(pm->GetLoadedProfiles());
269 for (size_t i = 0; i < profiles.size(); ++i)
270 SessionServiceFactory::ShutdownForProfile(profiles[i]);
275 void ProfileManager::NukeDeletedProfilesFromDisk() {
276 for (std::vector<base::FilePath>::iterator it =
277 ProfilesToDelete().begin();
278 it != ProfilesToDelete().end();
280 NukeProfileFromDisk(*it);
282 ProfilesToDelete().clear();
286 Profile* ProfileManager::GetLastUsedProfile() {
287 ProfileManager* profile_manager = g_browser_process->profile_manager();
288 return profile_manager->GetLastUsedProfile(profile_manager->user_data_dir_);
292 Profile* ProfileManager::GetLastUsedProfileAllowedByPolicy() {
293 Profile* profile = GetLastUsedProfile();
294 if (profile->IsGuestSession() ||
295 IncognitoModePrefs::GetAvailability(profile->GetPrefs()) ==
296 IncognitoModePrefs::FORCED) {
297 return profile->GetOffTheRecordProfile();
303 std::vector<Profile*> ProfileManager::GetLastOpenedProfiles() {
304 ProfileManager* profile_manager = g_browser_process->profile_manager();
305 return profile_manager->GetLastOpenedProfiles(
306 profile_manager->user_data_dir_);
310 Profile* ProfileManager::GetPrimaryUserProfile() {
311 ProfileManager* profile_manager = g_browser_process->profile_manager();
312 #if defined(OS_CHROMEOS)
313 if (!profile_manager->IsLoggedIn() || !chromeos::UserManager::IsInitialized())
314 return profile_manager->GetActiveUserOrOffTheRecordProfileFromPath(
315 profile_manager->user_data_dir());
316 chromeos::UserManager* manager = chromeos::UserManager::Get();
317 // Note: The user manager will take care of guest profiles.
318 return manager->GetProfileByUser(manager->GetPrimaryUser());
320 return profile_manager->GetActiveUserOrOffTheRecordProfileFromPath(
321 profile_manager->user_data_dir());
326 Profile* ProfileManager::GetActiveUserProfile() {
327 ProfileManager* profile_manager = g_browser_process->profile_manager();
328 #if defined(OS_CHROMEOS)
329 if (!chromeos::UserManager::IsMultipleProfilesAllowed() ||
330 !profile_manager->IsLoggedIn() ||
331 !chromeos::UserManager::IsInitialized())
332 return profile_manager->GetActiveUserOrOffTheRecordProfileFromPath(
333 profile_manager->user_data_dir());
334 chromeos::UserManager* manager = chromeos::UserManager::Get();
335 const chromeos::User* user = manager->GetActiveUser();
336 // To avoid an endless loop (crbug.com/334098) we have to additionally check
337 // if the profile of the user was already created. If the profile was not yet
338 // created we load the profile using the profile directly.
339 // TODO: This should be cleaned up with the new profile manager.
340 if (user && user->is_profile_created())
341 return manager->GetProfileByUser(user);
343 return profile_manager->GetActiveUserOrOffTheRecordProfileFromPath(
344 profile_manager->user_data_dir());
347 Profile* ProfileManager::GetProfile(const base::FilePath& profile_dir) {
348 TRACE_EVENT0("browser", "ProfileManager::GetProfile")
349 // If the profile is already loaded (e.g., chrome.exe launched twice), just
351 Profile* profile = GetProfileByPath(profile_dir);
355 profile = CreateProfileHelper(profile_dir);
358 bool result = AddProfile(profile);
364 size_t ProfileManager::GetNumberOfProfiles() {
365 return GetProfileInfoCache().GetNumberOfProfiles();
368 void ProfileManager::CreateProfileAsync(
369 const base::FilePath& profile_path,
370 const CreateCallback& callback,
371 const base::string16& name,
372 const base::string16& icon_url,
373 const std::string& managed_user_id) {
374 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
376 // Make sure that this profile is not pending deletion.
377 if (IsProfileMarkedForDeletion(profile_path)) {
378 if (!callback.is_null())
379 callback.Run(NULL, Profile::CREATE_STATUS_LOCAL_FAIL);
383 // Create the profile if needed and collect its ProfileInfo.
384 ProfilesInfoMap::iterator iter = profiles_info_.find(profile_path);
385 ProfileInfo* info = NULL;
387 if (iter != profiles_info_.end()) {
388 info = iter->second.get();
390 // Initiate asynchronous creation process.
391 info = RegisterProfile(CreateProfileAsyncHelper(profile_path, this), false);
392 ProfileInfoCache& cache = GetProfileInfoCache();
393 // Get the icon index from the user's icon url
395 std::string icon_url_std = base::UTF16ToASCII(icon_url);
396 if (profiles::IsDefaultAvatarIconUrl(icon_url_std, &icon_index)) {
397 // add profile to cache with user selected name and avatar
398 cache.AddProfileToCache(profile_path, name, base::string16(), icon_index,
402 if (!managed_user_id.empty()) {
403 content::RecordAction(
404 UserMetricsAction("ManagedMode_LocallyManagedUserCreated"));
407 ProfileMetrics::UpdateReportedProfilesStatistics(this);
410 // Call or enqueue the callback.
411 if (!callback.is_null()) {
412 if (iter != profiles_info_.end() && info->created) {
413 Profile* profile = info->profile.get();
414 // If this was the guest profile, apply settings and go OffTheRecord.
415 if (profile->GetPath() == ProfileManager::GetGuestProfilePath()) {
416 SetGuestProfilePrefs(profile);
417 profile = profile->GetOffTheRecordProfile();
419 // Profile has already been created. Run callback immediately.
420 callback.Run(profile, Profile::CREATE_STATUS_INITIALIZED);
422 // Profile is either already in the process of being created, or new.
423 // Add callback to the list.
424 info->callbacks.push_back(callback);
429 bool ProfileManager::IsValidProfile(Profile* profile) {
430 for (ProfilesInfoMap::iterator iter = profiles_info_.begin();
431 iter != profiles_info_.end(); ++iter) {
432 if (iter->second->created) {
433 Profile* candidate = iter->second->profile.get();
434 if (candidate == profile ||
435 (candidate->HasOffTheRecordProfile() &&
436 candidate->GetOffTheRecordProfile() == profile)) {
444 base::FilePath ProfileManager::GetInitialProfileDir() {
445 base::FilePath relative_profile_dir;
446 #if defined(OS_CHROMEOS)
447 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
449 base::FilePath profile_dir;
450 // If the user has logged in, pick up the new profile.
451 if (command_line.HasSwitch(chromeos::switches::kLoginProfile)) {
452 // TODO(nkostylev): Remove this code completely once we eliminate
453 // legacy --login-profile=user switch and enable multi-profiles on CrOS
454 // by default. http://crbug.com/294628
455 profile_dir = chromeos::ProfileHelper::
456 GetProfileDirByLegacyLoginProfileSwitch();
457 } else if (!command_line.HasSwitch(switches::kMultiProfiles)) {
458 // We should never be logged in with no profile dir unless
459 // multi-profiles are enabled.
460 // In that case profile dir will be defined by user_id hash.
462 return base::FilePath("");
464 // In case of multi-profiles ignore --login-profile switch.
465 // TODO(nkostylev): Some cases like Guest mode will have empty username_hash
466 // so default kLoginProfile dir will be used.
467 std::string user_id_hash = g_browser_process->platform_part()->
468 profile_helper()->active_user_id_hash();
469 if (command_line.HasSwitch(switches::kMultiProfiles) &&
470 !user_id_hash.empty()) {
471 profile_dir = g_browser_process->platform_part()->
472 profile_helper()->GetActiveUserProfileDir();
474 relative_profile_dir = relative_profile_dir.Append(profile_dir);
475 return relative_profile_dir;
478 // TODO(mirandac): should not automatically be default profile.
479 relative_profile_dir =
480 relative_profile_dir.AppendASCII(chrome::kInitialProfile);
481 return relative_profile_dir;
484 Profile* ProfileManager::GetLastUsedProfile(
485 const base::FilePath& user_data_dir) {
486 #if defined(OS_CHROMEOS)
487 // Use default login profile if user has not logged in yet.
489 return GetActiveUserOrOffTheRecordProfileFromPath(user_data_dir);
491 // CrOS multi-profiles implementation is different so GetLastUsedProfile
492 // has custom implementation too.
493 base::FilePath profile_dir;
494 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
495 if (command_line.HasSwitch(switches::kMultiProfiles)) {
496 // In case of multi-profiles we ignore "last used profile" preference
497 // since it may refer to profile that has been in use in previous session.
498 // That profile dir may not be mounted in this session so instead return
499 // active profile from current session.
500 profile_dir = g_browser_process->platform_part()->
501 profile_helper()->GetActiveUserProfileDir();
503 // For legacy (not multi-profiles) implementation always default to
504 // --login-profile value.
506 chromeos::ProfileHelper::GetProfileDirByLegacyLoginProfileSwitch();
509 base::FilePath profile_path(user_data_dir);
510 Profile* profile = GetProfile(profile_path.Append(profile_dir));
511 return profile->IsGuestSession() ? profile->GetOffTheRecordProfile() :
516 return GetProfile(GetLastUsedProfileDir(user_data_dir));
519 base::FilePath ProfileManager::GetLastUsedProfileDir(
520 const base::FilePath& user_data_dir) {
521 base::FilePath last_used_profile_dir(user_data_dir);
522 PrefService* local_state = g_browser_process->local_state();
525 if (local_state->HasPrefPath(prefs::kProfileLastUsed)) {
526 return last_used_profile_dir.AppendASCII(
527 local_state->GetString(prefs::kProfileLastUsed));
530 return last_used_profile_dir.AppendASCII(chrome::kInitialProfile);
533 std::vector<Profile*> ProfileManager::GetLastOpenedProfiles(
534 const base::FilePath& user_data_dir) {
535 PrefService* local_state = g_browser_process->local_state();
538 std::vector<Profile*> to_return;
539 if (local_state->HasPrefPath(prefs::kProfilesLastActive) &&
540 local_state->GetList(prefs::kProfilesLastActive)) {
541 // Make a copy because the list might change in the calls to GetProfile.
542 scoped_ptr<base::ListValue> profile_list(
543 local_state->GetList(prefs::kProfilesLastActive)->DeepCopy());
544 base::ListValue::const_iterator it;
546 for (it = profile_list->begin(); it != profile_list->end(); ++it) {
547 if (!(*it)->GetAsString(&profile) || profile.empty()) {
548 LOG(WARNING) << "Invalid entry in " << prefs::kProfilesLastActive;
551 to_return.push_back(GetProfile(user_data_dir.AppendASCII(profile)));
557 std::vector<Profile*> ProfileManager::GetLoadedProfiles() const {
558 std::vector<Profile*> profiles;
559 for (ProfilesInfoMap::const_iterator iter = profiles_info_.begin();
560 iter != profiles_info_.end(); ++iter) {
561 if (iter->second->created)
562 profiles.push_back(iter->second->profile.get());
567 Profile* ProfileManager::GetProfileByPath(const base::FilePath& path) const {
568 ProfileInfo* profile_info = GetProfileInfoByPath(path);
569 return profile_info ? profile_info->profile.get() : NULL;
573 base::FilePath ProfileManager::CreateMultiProfileAsync(
574 const base::string16& name,
575 const base::string16& icon_url,
576 const CreateCallback& callback,
577 const std::string& managed_user_id) {
578 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
580 ProfileManager* profile_manager = g_browser_process->profile_manager();
582 base::FilePath new_path = profile_manager->GenerateNextProfileDirectoryPath();
584 profile_manager->CreateProfileAsync(new_path,
593 base::FilePath ProfileManager::GetGuestProfilePath() {
594 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
596 ProfileManager* profile_manager = g_browser_process->profile_manager();
598 base::FilePath guest_path = profile_manager->user_data_dir();
599 return guest_path.Append(chrome::kGuestProfileDir);
602 base::FilePath ProfileManager::GenerateNextProfileDirectoryPath() {
603 PrefService* local_state = g_browser_process->local_state();
606 DCHECK(profiles::IsMultipleProfilesEnabled());
608 // Create the next profile in the next available directory slot.
609 int next_directory = local_state->GetInteger(prefs::kProfilesNumCreated);
610 std::string profile_name = chrome::kMultiProfileDirPrefix;
611 profile_name.append(base::IntToString(next_directory));
612 base::FilePath new_path = user_data_dir_;
614 new_path = new_path.Append(base::ASCIIToUTF16(profile_name));
616 new_path = new_path.Append(profile_name);
618 local_state->SetInteger(prefs::kProfilesNumCreated, ++next_directory);
622 ProfileInfoCache& ProfileManager::GetProfileInfoCache() {
623 if (!profile_info_cache_) {
624 profile_info_cache_.reset(new ProfileInfoCache(
625 g_browser_process->local_state(), user_data_dir_));
627 return *profile_info_cache_.get();
630 ProfileShortcutManager* ProfileManager::profile_shortcut_manager() {
631 return profile_shortcut_manager_.get();
634 void ProfileManager::ScheduleProfileForDeletion(
635 const base::FilePath& profile_dir,
636 const CreateCallback& callback) {
637 DCHECK(profiles::IsMultipleProfilesEnabled());
639 // Cancel all in-progress downloads before deleting the profile to prevent a
640 // "Do you want to exit Google Chrome and cancel the downloads?" prompt
641 // (crbug.com/336725).
642 Profile* profile = GetProfileByPath(profile_dir);
644 DownloadService* service =
645 DownloadServiceFactory::GetForBrowserContext(profile);
646 service->CancelDownloads();
649 PrefService* local_state = g_browser_process->local_state();
650 ProfileInfoCache& cache = GetProfileInfoCache();
652 if (profile_dir.BaseName().MaybeAsASCII() ==
653 local_state->GetString(prefs::kProfileLastUsed)) {
654 // Update the last used profile pref before closing browser windows. This
655 // way the correct last used profile is set for any notification observers.
656 base::FilePath last_non_managed_profile_path;
657 for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) {
658 base::FilePath cur_path = cache.GetPathOfProfileAtIndex(i);
659 // Make sure that this profile is not pending deletion.
660 if (cur_path != profile_dir && !cache.ProfileIsManagedAtIndex(i) &&
661 !IsProfileMarkedForDeletion(cur_path)) {
662 last_non_managed_profile_path = cur_path;
667 // If we're deleting the last (non-managed) profile, then create a new
668 // profile in its place.
669 const std::string last_non_managed_profile =
670 last_non_managed_profile_path.BaseName().MaybeAsASCII();
671 if (last_non_managed_profile.empty()) {
672 base::FilePath new_path = GenerateNextProfileDirectoryPath();
673 // Make sure the last used profile path is pointing at it. This way the
674 // correct last used profile is set for any notification observers.
675 local_state->SetString(prefs::kProfileLastUsed,
676 new_path.BaseName().MaybeAsASCII());
677 CreateProfileAsync(new_path,
683 // On the Mac, the browser process is not killed when all browser windows
684 // are closed, so just in case we are deleting the active profile, and no
685 // other profile has been loaded, we must pre-load a next one.
686 #if defined(OS_MACOSX)
687 CreateProfileAsync(last_non_managed_profile_path,
688 base::Bind(&ProfileManager::OnNewActiveProfileLoaded,
689 base::Unretained(this),
691 last_non_managed_profile_path,
698 // For OS_MACOSX the pref is updated in the callback to make sure that
699 // it isn't used before the profile is actually loaded.
700 local_state->SetString(prefs::kProfileLastUsed, last_non_managed_profile);
704 FinishDeletingProfile(profile_dir);
708 void ProfileManager::CleanUpStaleProfiles(
709 const std::vector<base::FilePath>& profile_paths) {
710 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
712 for (std::vector<base::FilePath>::const_iterator it = profile_paths.begin();
713 it != profile_paths.end(); ++it) {
714 NukeProfileFromDisk(*it);
718 void ProfileManager::AutoloadProfiles() {
719 // If running in the background is disabled for the browser, do not autoload
721 PrefService* local_state = g_browser_process->local_state();
722 if (!local_state->HasPrefPath(prefs::kBackgroundModeEnabled) ||
723 !local_state->GetBoolean(prefs::kBackgroundModeEnabled)) {
727 ProfileInfoCache& cache = GetProfileInfoCache();
728 size_t number_of_profiles = cache.GetNumberOfProfiles();
729 for (size_t p = 0; p < number_of_profiles; ++p) {
730 if (cache.GetBackgroundStatusOfProfileAtIndex(p)) {
731 // If status is true, that profile is running background apps. By calling
732 // GetProfile, we automatically cause the profile to be loaded which will
733 // register it with the BackgroundModeManager.
734 GetProfile(cache.GetPathOfProfileAtIndex(p));
739 void ProfileManager::InitProfileUserPrefs(Profile* profile) {
740 ProfileInfoCache& cache = GetProfileInfoCache();
742 if (profile->GetPath().DirName() != cache.GetUserDataDir())
746 std::string profile_name;
747 std::string managed_user_id;
748 if (profile->IsGuestSession()) {
749 profile_name = l10n_util::GetStringUTF8(IDS_PROFILES_GUEST_PROFILE_NAME);
752 size_t profile_cache_index =
753 cache.GetIndexOfProfileWithPath(profile->GetPath());
754 // If the cache has an entry for this profile, use the cache data.
755 if (profile_cache_index != std::string::npos) {
757 cache.GetAvatarIconIndexOfProfileAtIndex(profile_cache_index);
759 base::UTF16ToUTF8(cache.GetNameOfProfileAtIndex(profile_cache_index));
761 cache.GetManagedUserIdOfProfileAtIndex(profile_cache_index);
762 } else if (profile->GetPath() ==
763 profiles::GetDefaultProfileDir(cache.GetUserDataDir())) {
765 // The --new-profile-management flag no longer uses the "First User" name.
766 profile_name = switches::IsNewProfileManagement() ?
767 base::UTF16ToUTF8(cache.ChooseNameForNewProfile(avatar_index)) :
768 l10n_util::GetStringUTF8(IDS_DEFAULT_PROFILE_NAME);
770 avatar_index = cache.ChooseAvatarIconIndexForNewProfile();
772 base::UTF16ToUTF8(cache.ChooseNameForNewProfile(avatar_index));
776 if (!profile->GetPrefs()->HasPrefPath(prefs::kProfileAvatarIndex))
777 profile->GetPrefs()->SetInteger(prefs::kProfileAvatarIndex, avatar_index);
779 if (!profile->GetPrefs()->HasPrefPath(prefs::kProfileName))
780 profile->GetPrefs()->SetString(prefs::kProfileName, profile_name);
782 CommandLine* command_line = CommandLine::ForCurrentProcess();
783 bool force_managed_user_id =
784 command_line->HasSwitch(switches::kManagedUserId);
785 if (force_managed_user_id) {
787 command_line->GetSwitchValueASCII(switches::kManagedUserId);
789 if (force_managed_user_id ||
790 !profile->GetPrefs()->HasPrefPath(prefs::kManagedUserId)) {
791 profile->GetPrefs()->SetString(prefs::kManagedUserId, managed_user_id);
795 void ProfileManager::RegisterTestingProfile(Profile* profile,
797 bool start_deferred_task_runners) {
798 RegisterProfile(profile, true);
800 InitProfileUserPrefs(profile);
801 AddProfileToCache(profile);
803 if (start_deferred_task_runners) {
804 StartupTaskRunnerServiceFactory::GetForProfile(profile)->
805 StartDeferredTaskRunners();
809 void ProfileManager::Observe(
811 const content::NotificationSource& source,
812 const content::NotificationDetails& details) {
813 #if defined(OS_CHROMEOS)
814 if (type == chrome::NOTIFICATION_LOGIN_USER_CHANGED) {
817 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
818 if (!command_line.HasSwitch(switches::kTestType)) {
819 // If we don't have a mounted profile directory we're in trouble.
820 // TODO(davemoore) Once we have better api this check should ensure that
821 // our profile directory is the one that's mounted, and that it's mounted
822 // as the current user.
823 chromeos::DBusThreadManager::Get()->GetCryptohomeClient()->IsMounted(
824 base::Bind(&CheckCryptohomeIsMounted));
826 // Confirm that we hadn't loaded the new profile previously.
827 base::FilePath default_profile_dir = user_data_dir_.Append(
828 GetInitialProfileDir());
829 CHECK(!GetProfileByPath(default_profile_dir))
830 << "The default profile was loaded before we mounted the cryptohome.";
835 bool save_active_profiles = false;
837 case chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST: {
838 // Ignore any browsers closing from now on.
839 closing_all_browsers_ = true;
840 save_active_profiles = true;
843 case chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED: {
844 // This will cancel the shutdown process, so the active profiles are
845 // tracked again. Also, as the active profiles may have changed (i.e. if
846 // some windows were closed) we save the current list of active profiles
848 closing_all_browsers_ = false;
849 save_active_profiles = true;
852 case chrome::NOTIFICATION_BROWSER_OPENED: {
853 Browser* browser = content::Source<Browser>(source).ptr();
855 Profile* profile = browser->profile();
858 profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles);
859 if (!profile->IsOffTheRecord() && !is_ephemeral &&
860 ++browser_counts_[profile] == 1) {
861 active_profiles_.push_back(profile);
862 save_active_profiles = true;
864 // If browsers are opening, we can't be closing all the browsers. This
865 // can happen if the application was exited, but background mode or
866 // packaged apps prevented the process from shutting down, and then
867 // a new browser window was opened.
868 closing_all_browsers_ = false;
871 case chrome::NOTIFICATION_BROWSER_CLOSED: {
872 Browser* browser = content::Source<Browser>(source).ptr();
874 Profile* profile = browser->profile();
876 if (!profile->IsOffTheRecord() && --browser_counts_[profile] == 0) {
877 active_profiles_.erase(std::find(active_profiles_.begin(),
878 active_profiles_.end(), profile));
879 save_active_profiles = !closing_all_browsers_;
883 case chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED: {
884 save_active_profiles = !closing_all_browsers_;
893 if (save_active_profiles) {
894 PrefService* local_state = g_browser_process->local_state();
896 ListPrefUpdate update(local_state, prefs::kProfilesLastActive);
897 base::ListValue* profile_list = update.Get();
899 profile_list->Clear();
901 // crbug.com/120112 -> several non-incognito profiles might have the same
902 // GetPath().BaseName(). In that case, we cannot restore both
903 // profiles. Include each base name only once in the last active profile
905 std::set<std::string> profile_paths;
906 std::vector<Profile*>::const_iterator it;
907 for (it = active_profiles_.begin(); it != active_profiles_.end(); ++it) {
908 std::string profile_path = (*it)->GetPath().BaseName().MaybeAsASCII();
909 // Some profiles might become ephemeral after they are created.
910 if (!(*it)->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles) &&
911 profile_paths.find(profile_path) == profile_paths.end()) {
912 profile_paths.insert(profile_path);
913 profile_list->Append(new base::StringValue(profile_path));
919 void ProfileManager::OnProfileCreated(Profile* profile,
921 bool is_new_profile) {
922 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
924 ProfilesInfoMap::iterator iter = profiles_info_.find(profile->GetPath());
925 DCHECK(iter != profiles_info_.end());
926 ProfileInfo* info = iter->second.get();
928 std::vector<CreateCallback> callbacks;
929 info->callbacks.swap(callbacks);
931 // Invoke CREATED callback for normal profiles.
932 bool go_off_the_record = ShouldGoOffTheRecord(profile);
933 if (success && !go_off_the_record)
934 RunCallbacks(callbacks, profile, Profile::CREATE_STATUS_CREATED);
936 // Perform initialization.
938 DoFinalInit(profile, go_off_the_record);
939 if (go_off_the_record)
940 profile = profile->GetOffTheRecordProfile();
941 info->created = true;
944 profiles_info_.erase(iter);
948 // If this was the guest profile, finish setting its special status.
949 if (profile->GetPath() == ProfileManager::GetGuestProfilePath())
950 SetGuestProfilePrefs(profile);
952 // Invoke CREATED callback for incognito profiles.
953 if (go_off_the_record)
954 RunCallbacks(callbacks, profile, Profile::CREATE_STATUS_CREATED);
957 // Invoke INITIALIZED or FAIL for all profiles.
958 RunCallbacks(callbacks, profile,
959 profile ? Profile::CREATE_STATUS_INITIALIZED :
960 Profile::CREATE_STATUS_LOCAL_FAIL);
963 void ProfileManager::DoFinalInit(Profile* profile, bool go_off_the_record) {
964 DoFinalInitForServices(profile, go_off_the_record);
965 AddProfileToCache(profile);
966 DoFinalInitLogging(profile);
968 ProfileMetrics::LogNumberOfProfiles(this);
969 content::NotificationService::current()->Notify(
970 chrome::NOTIFICATION_PROFILE_ADDED,
971 content::Source<Profile>(profile),
972 content::NotificationService::NoDetails());
975 void ProfileManager::DoFinalInitForServices(Profile* profile,
976 bool go_off_the_record) {
977 #if defined(ENABLE_EXTENSIONS)
978 extensions::ExtensionSystem::Get(profile)->InitForRegularProfile(
980 // During tests, when |profile| is an instance of TestingProfile,
981 // ExtensionSystem might not create an ExtensionService.
982 if (extensions::ExtensionSystem::Get(profile)->extension_service()) {
983 profile->GetHostContentSettingsMap()->RegisterExtensionService(
984 extensions::ExtensionSystem::Get(profile)->extension_service());
987 #if defined(ENABLE_MANAGED_USERS)
988 // Initialization needs to happen after extension system initialization (for
989 // extension::ManagementPolicy) and InitProfileUserPrefs (for setting the
990 // initializing the managed flag if necessary).
991 ManagedUserServiceFactory::GetForProfile(profile)->Init();
993 // Start the deferred task runners once the profile is loaded.
994 StartupTaskRunnerServiceFactory::GetForProfile(profile)->
995 StartDeferredTaskRunners();
997 if (switches::IsNewProfileManagement())
998 AccountReconcilorFactory::GetForProfile(profile);
1001 void ProfileManager::DoFinalInitLogging(Profile* profile) {
1002 // Count number of extensions in this profile.
1003 int enabled_app_count = -1;
1004 #if defined(ENABLE_EXTENSIONS)
1005 enabled_app_count = GetEnabledAppCount(profile);
1008 // Log the profile size after a reasonable startup delay.
1009 BrowserThread::PostDelayedTask(
1010 BrowserThread::FILE, FROM_HERE,
1011 base::Bind(&ProfileSizeTask, profile->GetPath(), enabled_app_count),
1012 base::TimeDelta::FromSeconds(112));
1015 Profile* ProfileManager::CreateProfileHelper(const base::FilePath& path) {
1016 return Profile::CreateProfile(path, NULL, Profile::CREATE_MODE_SYNCHRONOUS);
1019 Profile* ProfileManager::CreateProfileAsyncHelper(const base::FilePath& path,
1020 Delegate* delegate) {
1021 return Profile::CreateProfile(path,
1023 Profile::CREATE_MODE_ASYNCHRONOUS);
1026 Profile* ProfileManager::GetActiveUserOrOffTheRecordProfileFromPath(
1027 const base::FilePath& user_data_dir) {
1028 #if defined(OS_CHROMEOS)
1029 base::FilePath default_profile_dir(user_data_dir);
1031 default_profile_dir = profiles::GetDefaultProfileDir(user_data_dir);
1032 Profile* profile = GetProfile(default_profile_dir);
1033 // For cros, return the OTR profile so we never accidentally keep
1034 // user data in an unencrypted profile. But doing this makes
1035 // many of the browser and ui tests fail. We do return the OTR profile
1036 // if the login-profile switch is passed so that we can test this.
1037 if (ShouldGoOffTheRecord(profile))
1038 return profile->GetOffTheRecordProfile();
1039 DCHECK(!chromeos::UserManager::Get()->IsLoggedInAsGuest());
1043 default_profile_dir = default_profile_dir.Append(GetInitialProfileDir());
1044 ProfileInfo* profile_info = GetProfileInfoByPath(default_profile_dir);
1045 // Fallback to default off-the-record profile, if user profile has not fully
1047 if (profile_info && !profile_info->created)
1048 default_profile_dir = profiles::GetDefaultProfileDir(user_data_dir);
1050 Profile* profile = GetProfile(default_profile_dir);
1051 // Some unit tests didn't initialize the UserManager.
1052 if (chromeos::UserManager::IsInitialized() &&
1053 chromeos::UserManager::Get()->IsLoggedInAsGuest())
1054 return profile->GetOffTheRecordProfile();
1057 base::FilePath default_profile_dir(user_data_dir);
1058 default_profile_dir = default_profile_dir.Append(GetInitialProfileDir());
1059 return GetProfile(default_profile_dir);
1063 bool ProfileManager::AddProfile(Profile* profile) {
1066 // Make sure that we're not loading a profile with the same ID as a profile
1067 // that's already loaded.
1068 if (GetProfileByPath(profile->GetPath())) {
1069 NOTREACHED() << "Attempted to add profile with the same path (" <<
1070 profile->GetPath().value() <<
1071 ") as an already-loaded profile.";
1075 RegisterProfile(profile, true);
1076 InitProfileUserPrefs(profile);
1077 DoFinalInit(profile, ShouldGoOffTheRecord(profile));
1081 void ProfileManager::FinishDeletingProfile(const base::FilePath& profile_dir) {
1082 ProfileInfoCache& cache = GetProfileInfoCache();
1083 // TODO(sail): Due to bug 88586 we don't delete the profile instance. Once we
1084 // start deleting the profile instance we need to close background apps too.
1085 Profile* profile = GetProfileByPath(profile_dir);
1088 // By this point, all in-progress downloads for the profile being deleted
1089 // must have been canceled (crbug.com/336725).
1090 DCHECK(DownloadServiceFactory::GetForBrowserContext(profile)->
1091 NonMaliciousDownloadCount() == 0);
1092 BrowserList::CloseAllBrowsersWithProfile(profile);
1094 // Disable sync for doomed profile.
1095 if (ProfileSyncServiceFactory::GetInstance()->HasProfileSyncService(
1097 ProfileSyncServiceFactory::GetInstance()->GetForProfile(
1098 profile)->DisableForUser();
1102 QueueProfileDirectoryForDeletion(profile_dir);
1103 cache.DeleteProfileFromCache(profile_dir);
1104 ProfileMetrics::UpdateReportedProfilesStatistics(this);
1107 ProfileManager::ProfileInfo* ProfileManager::RegisterProfile(
1110 ProfileInfo* info = new ProfileInfo(profile, created);
1111 profiles_info_.insert(
1112 std::make_pair(profile->GetPath(), linked_ptr<ProfileInfo>(info)));
1116 ProfileManager::ProfileInfo* ProfileManager::GetProfileInfoByPath(
1117 const base::FilePath& path) const {
1118 ProfilesInfoMap::const_iterator iter = profiles_info_.find(path);
1119 return (iter == profiles_info_.end()) ? NULL : iter->second.get();
1122 void ProfileManager::AddProfileToCache(Profile* profile) {
1123 if (profile->IsGuestSession())
1125 ProfileInfoCache& cache = GetProfileInfoCache();
1126 if (profile->GetPath().DirName() != cache.GetUserDataDir())
1129 if (cache.GetIndexOfProfileWithPath(profile->GetPath()) != std::string::npos)
1132 base::string16 username = base::UTF8ToUTF16(profile->GetPrefs()->GetString(
1133 prefs::kGoogleServicesUsername));
1135 // Profile name and avatar are set by InitProfileUserPrefs and stored in the
1136 // profile. Use those values to setup the cache entry.
1137 base::string16 profile_name =
1138 base::UTF8ToUTF16(profile->GetPrefs()->GetString(prefs::kProfileName));
1140 size_t icon_index = profile->GetPrefs()->GetInteger(
1141 prefs::kProfileAvatarIndex);
1143 std::string managed_user_id =
1144 profile->GetPrefs()->GetString(prefs::kManagedUserId);
1146 cache.AddProfileToCache(profile->GetPath(),
1152 if (profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles)) {
1153 cache.SetProfileIsEphemeralAtIndex(
1154 cache.GetIndexOfProfileWithPath(profile->GetPath()), true);
1158 void ProfileManager::SetGuestProfilePrefs(Profile* profile) {
1159 PrefService* prefs = profile->GetPrefs();
1160 prefs->SetBoolean(prefs::kSigninAllowed, false);
1161 prefs->SetBoolean(prefs::kEditBookmarksEnabled, false);
1162 prefs->SetBoolean(prefs::kShowBookmarkBar, false);
1163 // This can be removed in the future but needs to be present through
1164 // a release (or two) so that any existing installs get switched to
1165 // the new state and away from the previous "forced" state.
1166 IncognitoModePrefs::SetAvailability(prefs, IncognitoModePrefs::ENABLED);
1169 bool ProfileManager::ShouldGoOffTheRecord(Profile* profile) {
1170 #if defined(OS_CHROMEOS)
1171 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1172 if (profile->GetPath().BaseName().value() == chrome::kInitialProfile &&
1173 (!command_line.HasSwitch(switches::kTestType) ||
1174 command_line.HasSwitch(chromeos::switches::kLoginProfile))) {
1178 return profile->IsGuestSession();
1181 void ProfileManager::RunCallbacks(const std::vector<CreateCallback>& callbacks,
1183 Profile::CreateStatus status) {
1184 for (size_t i = 0; i < callbacks.size(); ++i)
1185 callbacks[i].Run(profile, status);
1188 ProfileManager::ProfileInfo::ProfileInfo(
1195 ProfileManager::ProfileInfo::~ProfileInfo() {
1196 ProfileDestroyer::DestroyProfileWhenAppropriate(profile.release());
1199 #if !defined(OS_ANDROID) && !defined(OS_IOS)
1200 ProfileManager::BrowserListObserver::BrowserListObserver(
1201 ProfileManager* manager)
1202 : profile_manager_(manager) {
1203 BrowserList::AddObserver(this);
1206 ProfileManager::BrowserListObserver::~BrowserListObserver() {
1207 BrowserList::RemoveObserver(this);
1210 void ProfileManager::BrowserListObserver::OnBrowserAdded(
1211 Browser* browser) {}
1213 void ProfileManager::BrowserListObserver::OnBrowserRemoved(
1215 Profile* profile = browser->profile();
1216 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
1217 if (it->profile()->GetOriginalProfile() == profile->GetOriginalProfile())
1218 // Not the last window for this profile.
1222 // If the last browser of a profile that is scheduled for deletion is closed
1224 base::FilePath path = profile->GetPath();
1225 if (profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles) &&
1226 !IsProfileMarkedForDeletion(path)) {
1227 g_browser_process->profile_manager()->ScheduleProfileForDeletion(
1228 path, ProfileManager::CreateCallback());
1232 void ProfileManager::BrowserListObserver::OnBrowserSetLastActive(
1234 // If all browsers are being closed (e.g. the user is in the process of
1235 // shutting down), this event will be fired after each browser is
1236 // closed. This does not represent a user intention to change the active
1237 // browser so is not handled here.
1238 if (profile_manager_->closing_all_browsers_)
1241 Profile* last_active = browser->profile();
1243 // Don't remember ephemeral profiles as last because they are not going to
1244 // persist after restart.
1245 if (last_active->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles))
1248 PrefService* local_state = g_browser_process->local_state();
1249 DCHECK(local_state);
1250 // Only keep track of profiles that we are managing; tests may create others.
1251 if (profile_manager_->profiles_info_.find(
1252 last_active->GetPath()) != profile_manager_->profiles_info_.end()) {
1253 local_state->SetString(prefs::kProfileLastUsed,
1254 last_active->GetPath().BaseName().MaybeAsASCII());
1256 ProfileInfoCache& cache = profile_manager_->GetProfileInfoCache();
1257 size_t profile_index =
1258 cache.GetIndexOfProfileWithPath(last_active->GetPath());
1259 if (profile_index != std::string::npos)
1260 cache.SetProfileActiveTimeAtIndex(profile_index);
1263 #endif // !defined(OS_ANDROID) && !defined(OS_IOS)
1265 #if defined(OS_MACOSX)
1266 void ProfileManager::OnNewActiveProfileLoaded(
1267 const base::FilePath& profile_to_delete_path,
1268 const base::FilePath& last_non_managed_profile_path,
1269 const CreateCallback& original_callback,
1270 Profile* loaded_profile,
1271 Profile::CreateStatus status) {
1272 DCHECK(status != Profile::CREATE_STATUS_LOCAL_FAIL &&
1273 status != Profile::CREATE_STATUS_REMOTE_FAIL);
1275 // Only run the code if the profile initialization has finished completely.
1276 if (status == Profile::CREATE_STATUS_INITIALIZED) {
1277 if (IsProfileMarkedForDeletion(last_non_managed_profile_path)) {
1278 // If the profile we tried to load as the next active profile has been
1279 // deleted, then retry deleting this profile to redo the logic to load
1280 // the next available profile.
1281 ScheduleProfileForDeletion(profile_to_delete_path, original_callback);
1283 // Update the local state as promised in the ScheduleProfileForDeletion.
1284 g_browser_process->local_state()->SetString(
1285 prefs::kProfileLastUsed,
1286 last_non_managed_profile_path.BaseName().MaybeAsASCII());
1287 FinishDeletingProfile(profile_to_delete_path);
1293 ProfileManagerWithoutInit::ProfileManagerWithoutInit(
1294 const base::FilePath& user_data_dir) : ProfileManager(user_data_dir) {