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.
7 #include "chrome/browser/profiles/profile_manager.h"
10 #include "base/command_line.h"
11 #include "base/file_path.h"
12 #include "base/file_util.h"
13 #include "base/metrics/histogram.h"
14 #include "base/string_number_conversions.h"
15 #include "base/string_util.h"
16 #include "base/utf_string_conversions.h"
17 #include "chrome/browser/browser_process.h"
18 #include "chrome/browser/content_settings/host_content_settings_map.h"
19 #include "chrome/browser/managed_mode/managed_mode.h"
20 #include "chrome/browser/prefs/pref_service.h"
21 #include "chrome/browser/prefs/scoped_user_pref_update.h"
22 #include "chrome/browser/profiles/profile_destroyer.h"
23 #include "chrome/browser/profiles/profile_info_cache.h"
24 #include "chrome/browser/profiles/profile_metrics.h"
25 #include "chrome/browser/sync/profile_sync_service.h"
26 #include "chrome/browser/sync/profile_sync_service_factory.h"
27 #include "chrome/browser/ui/browser.h"
28 #include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
29 #include "chrome/common/chrome_constants.h"
30 #include "chrome/common/chrome_notification_types.h"
31 #include "chrome/common/chrome_paths_internal.h"
32 #include "chrome/common/chrome_switches.h"
33 #include "chrome/common/logging_chrome.h"
34 #include "chrome/common/pref_names.h"
35 #include "chrome/common/url_constants.h"
36 #include "content/public/browser/browser_thread.h"
37 #include "content/public/browser/notification_service.h"
38 #include "content/public/browser/user_metrics.h"
39 #include "grit/generated_resources.h"
40 #include "net/http/http_transaction_factory.h"
41 #include "net/url_request/url_request_context.h"
42 #include "net/url_request/url_request_context_getter.h"
43 #include "net/url_request/url_request_job.h"
44 #include "ui/base/l10n/l10n_util.h"
47 #include "chrome/browser/extensions/extension_service.h"
48 #include "chrome/browser/extensions/extension_system.h"
49 #include "chrome/browser/sessions/session_service_factory.h"
50 #include "chrome/browser/ui/browser_finder.h"
51 #include "chrome/browser/ui/browser_list.h"
52 #include "chrome/browser/ui/browser_window.h"
53 #include "chrome/browser/ui/startup/startup_browser_creator.h"
54 #endif // !defined (OS_IOS)
57 #include "base/win/metro.h"
58 #include "chrome/installer/util/browser_distribution.h"
61 #if defined(OS_CHROMEOS)
62 #include "chromeos/dbus/cryptohome_client.h"
63 #include "chromeos/dbus/dbus_thread_manager.h"
64 #include "chrome/browser/chromeos/login/user_manager.h"
67 using content::BrowserThread
;
68 using content::UserMetricsAction
;
72 // Profiles that should be deleted on shutdown.
73 std::vector
<FilePath
>& ProfilesToDelete() {
74 CR_DEFINE_STATIC_LOCAL(std::vector
<FilePath
>, profiles_to_delete
, ());
75 return profiles_to_delete
;
78 // Checks if any user prefs for |profile| have default values.
79 bool HasAnyDefaultUserPrefs(Profile
* profile
) {
80 const PrefService::Preference
* avatar_index
=
81 profile
->GetPrefs()->FindPreference(prefs::kProfileAvatarIndex
);
83 const PrefService::Preference
* profile_name
=
84 profile
->GetPrefs()->FindPreference(prefs::kProfileName
);
86 return avatar_index
->IsDefaultValue() ||
87 profile_name
->IsDefaultValue();
90 // Simple task to log the size of the current profile.
91 void ProfileSizeTask(const FilePath
& path
, int extension_count
) {
92 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
94 int64 size
= file_util::ComputeFilesSize(path
, FILE_PATH_LITERAL("*"));
95 int size_MB
= static_cast<int>(size
/ (1024 * 1024));
96 UMA_HISTOGRAM_COUNTS_10000("Profile.TotalSize", size_MB
);
98 size
= file_util::ComputeFilesSize(path
, FILE_PATH_LITERAL("History"));
99 size_MB
= static_cast<int>(size
/ (1024 * 1024));
100 UMA_HISTOGRAM_COUNTS_10000("Profile.HistorySize", size_MB
);
102 size
= file_util::ComputeFilesSize(path
, FILE_PATH_LITERAL("History*"));
103 size_MB
= static_cast<int>(size
/ (1024 * 1024));
104 UMA_HISTOGRAM_COUNTS_10000("Profile.TotalHistorySize", size_MB
);
106 size
= file_util::ComputeFilesSize(path
, FILE_PATH_LITERAL("Cookies"));
107 size_MB
= static_cast<int>(size
/ (1024 * 1024));
108 UMA_HISTOGRAM_COUNTS_10000("Profile.CookiesSize", size_MB
);
110 size
= file_util::ComputeFilesSize(path
, FILE_PATH_LITERAL("Bookmarks"));
111 size_MB
= static_cast<int>(size
/ (1024 * 1024));
112 UMA_HISTOGRAM_COUNTS_10000("Profile.BookmarksSize", size_MB
);
114 size
= file_util::ComputeFilesSize(path
, FILE_PATH_LITERAL("Favicons"));
115 size_MB
= static_cast<int>(size
/ (1024 * 1024));
116 UMA_HISTOGRAM_COUNTS_10000("Profile.FaviconsSize", size_MB
);
118 size
= file_util::ComputeFilesSize(path
, FILE_PATH_LITERAL("Top Sites"));
119 size_MB
= static_cast<int>(size
/ (1024 * 1024));
120 UMA_HISTOGRAM_COUNTS_10000("Profile.TopSitesSize", size_MB
);
122 size
= file_util::ComputeFilesSize(path
, FILE_PATH_LITERAL("Visited Links"));
123 size_MB
= static_cast<int>(size
/ (1024 * 1024));
124 UMA_HISTOGRAM_COUNTS_10000("Profile.VisitedLinksSize", size_MB
);
126 size
= file_util::ComputeFilesSize(path
, FILE_PATH_LITERAL("Web Data"));
127 size_MB
= static_cast<int>(size
/ (1024 * 1024));
128 UMA_HISTOGRAM_COUNTS_10000("Profile.WebDataSize", size_MB
);
130 size
= file_util::ComputeFilesSize(path
, FILE_PATH_LITERAL("Extension*"));
131 size_MB
= static_cast<int>(size
/ (1024 * 1024));
132 UMA_HISTOGRAM_COUNTS_10000("Profile.ExtensionSize", size_MB
);
134 // Count number of extensions in this profile, if we know.
135 if (extension_count
!= -1)
136 UMA_HISTOGRAM_COUNTS_10000("Profile.AppCount", extension_count
);
139 void QueueProfileDirectoryForDeletion(const FilePath
& path
) {
140 ProfilesToDelete().push_back(path
);
143 // Called upon completion of profile creation. This function takes care of
144 // launching a new browser window and signing the user in to their Google
146 void OnOpenWindowForNewProfile(
147 chrome::HostDesktopType desktop_type
,
148 const ProfileManager::CreateCallback
& callback
,
150 Profile::CreateStatus status
) {
151 if (status
== Profile::CREATE_STATUS_INITIALIZED
) {
153 ProfileManager::FindOrCreateNewWindowForProfile(
155 chrome::startup::IS_PROCESS_STARTUP
,
156 chrome::startup::IS_FIRST_RUN
,
160 if (!callback
.is_null())
161 callback
.Run(profile
, status
);
164 #if defined(OS_CHROMEOS)
165 void CheckCryptohomeIsMounted(chromeos::DBusMethodCallStatus call_status
,
167 if (call_status
!= chromeos::DBUS_METHOD_CALL_SUCCESS
) {
168 LOG(ERROR
) << "IsMounted call failed.";
172 LOG(ERROR
) << "Cryptohome is not mounted.";
178 #if defined(ENABLE_SESSION_SERVICE)
180 void ProfileManager::ShutdownSessionServices() {
181 ProfileManager
* pm
= g_browser_process
->profile_manager();
182 if (!pm
) // Is NULL when running unit tests.
184 std::vector
<Profile
*> profiles(pm
->GetLoadedProfiles());
185 for (size_t i
= 0; i
< profiles
.size(); ++i
)
186 SessionServiceFactory::ShutdownForProfile(profiles
[i
]);
191 void ProfileManager::NukeDeletedProfilesFromDisk() {
192 for (std::vector
<FilePath
>::iterator it
=
193 ProfilesToDelete().begin();
194 it
!= ProfilesToDelete().end();
196 // Delete both the profile directory and its corresponding cache.
198 chrome::GetUserCacheDirectory(*it
, &cache_path
);
199 file_util::Delete(*it
, true);
200 file_util::Delete(cache_path
, true);
202 ProfilesToDelete().clear();
206 Profile
* ProfileManager::GetDefaultProfile() {
207 ProfileManager
* profile_manager
= g_browser_process
->profile_manager();
208 return profile_manager
->GetDefaultProfile(profile_manager
->user_data_dir_
);
212 Profile
* ProfileManager::GetDefaultProfileOrOffTheRecord() {
213 // TODO (mukai,nkostylev): In the long term we should fix those cases that
214 // crash on Guest mode and have only one GetDefaultProfile() method.
215 Profile
* profile
= GetDefaultProfile();
216 #if defined(OS_CHROMEOS)
217 if (chromeos::UserManager::Get()->IsLoggedInAsGuest())
218 profile
= profile
->GetOffTheRecordProfile();
224 Profile
* ProfileManager::GetLastUsedProfile() {
225 ProfileManager
* profile_manager
= g_browser_process
->profile_manager();
226 return profile_manager
->GetLastUsedProfile(profile_manager
->user_data_dir_
);
230 std::vector
<Profile
*> ProfileManager::GetLastOpenedProfiles() {
231 ProfileManager
* profile_manager
= g_browser_process
->profile_manager();
232 return profile_manager
->GetLastOpenedProfiles(
233 profile_manager
->user_data_dir_
);
236 ProfileManager::ProfileManager(const FilePath
& user_data_dir
)
237 : user_data_dir_(user_data_dir
),
240 profile_shortcut_manager_(NULL
),
241 #if !defined(OS_ANDROID) && !defined(OS_IOS)
242 ALLOW_THIS_IN_INITIALIZER_LIST(
243 browser_list_observer_(this)),
245 closing_all_browsers_(false) {
246 #if defined(OS_CHROMEOS)
249 chrome::NOTIFICATION_LOGIN_USER_CHANGED
,
250 content::NotificationService::AllSources());
254 chrome::NOTIFICATION_BROWSER_OPENED
,
255 content::NotificationService::AllSources());
258 chrome::NOTIFICATION_BROWSER_CLOSED
,
259 content::NotificationService::AllSources());
262 chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST
,
263 content::NotificationService::AllSources());
266 chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED
,
267 content::NotificationService::AllSources());
269 if (ProfileShortcutManager::IsFeatureEnabled() && !user_data_dir
.empty())
270 profile_shortcut_manager_
.reset(ProfileShortcutManager::Create(
274 ProfileManager::~ProfileManager() {
277 FilePath
ProfileManager::GetDefaultProfileDir(
278 const FilePath
& user_data_dir
) {
279 FilePath
default_profile_dir(user_data_dir
);
280 default_profile_dir
=
281 default_profile_dir
.AppendASCII(chrome::kInitialProfile
);
282 return default_profile_dir
;
285 FilePath
ProfileManager::GetProfilePrefsPath(
286 const FilePath
&profile_dir
) {
287 FilePath
default_prefs_path(profile_dir
);
288 default_prefs_path
= default_prefs_path
.Append(chrome::kPreferencesFilename
);
289 return default_prefs_path
;
292 FilePath
ProfileManager::GetInitialProfileDir() {
293 FilePath relative_profile_dir
;
294 #if defined(OS_CHROMEOS)
295 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
297 FilePath profile_dir
;
298 // If the user has logged in, pick up the new profile.
299 if (command_line
.HasSwitch(switches::kLoginProfile
)) {
300 profile_dir
= command_line
.GetSwitchValuePath(switches::kLoginProfile
);
302 // We should never be logged in with no profile dir.
306 relative_profile_dir
= relative_profile_dir
.Append(profile_dir
);
307 return relative_profile_dir
;
310 // TODO(mirandac): should not automatically be default profile.
311 relative_profile_dir
=
312 relative_profile_dir
.AppendASCII(chrome::kInitialProfile
);
313 return relative_profile_dir
;
316 Profile
* ProfileManager::GetLastUsedProfile(const FilePath
& user_data_dir
) {
317 #if defined(OS_CHROMEOS)
318 // Use default login profile if user has not logged in yet.
320 return GetDefaultProfile(user_data_dir
);
323 FilePath
last_used_profile_dir(user_data_dir
);
324 std::string last_profile_used
;
325 PrefService
* local_state
= g_browser_process
->local_state();
328 if (local_state
->HasPrefPath(prefs::kProfileLastUsed
))
329 last_profile_used
= local_state
->GetString(prefs::kProfileLastUsed
);
330 last_used_profile_dir
= last_profile_used
.empty() ?
331 last_used_profile_dir
.AppendASCII(chrome::kInitialProfile
) :
332 last_used_profile_dir
.AppendASCII(last_profile_used
);
333 return GetProfile(last_used_profile_dir
);
336 std::vector
<Profile
*> ProfileManager::GetLastOpenedProfiles(
337 const FilePath
& user_data_dir
) {
338 PrefService
* local_state
= g_browser_process
->local_state();
341 std::vector
<Profile
*> to_return
;
342 if (local_state
->HasPrefPath(prefs::kProfilesLastActive
)) {
343 const ListValue
* profile_list
=
344 local_state
->GetList(prefs::kProfilesLastActive
);
346 ListValue::const_iterator it
;
348 for (it
= profile_list
->begin(); it
!= profile_list
->end(); ++it
) {
349 if (!(*it
)->GetAsString(&profile
) || profile
.empty()) {
350 LOG(WARNING
) << "Invalid entry in " << prefs::kProfilesLastActive
;
353 to_return
.push_back(GetProfile(user_data_dir
.AppendASCII(profile
)));
360 Profile
* ProfileManager::GetDefaultProfile(const FilePath
& user_data_dir
) {
361 FilePath
default_profile_dir(user_data_dir
);
362 default_profile_dir
= default_profile_dir
.Append(GetInitialProfileDir());
363 #if defined(OS_CHROMEOS)
365 Profile
* profile
= GetProfile(default_profile_dir
);
366 // For cros, return the OTR profile so we never accidentally keep
367 // user data in an unencrypted profile. But doing this makes
368 // many of the browser and ui tests fail. We do return the OTR profile
369 // if the login-profile switch is passed so that we can test this.
370 // TODO(davemoore) Fix the tests so they allow OTR profiles.
371 if (ShouldGoOffTheRecord())
372 return profile
->GetOffTheRecordProfile();
376 return GetProfile(default_profile_dir
);
379 bool ProfileManager::IsValidProfile(Profile
* profile
) {
380 for (ProfilesInfoMap::iterator iter
= profiles_info_
.begin();
381 iter
!= profiles_info_
.end(); ++iter
) {
382 if (iter
->second
->created
) {
383 Profile
* candidate
= iter
->second
->profile
.get();
384 if (candidate
== profile
||
385 (candidate
->HasOffTheRecordProfile() &&
386 candidate
->GetOffTheRecordProfile() == profile
)) {
394 std::vector
<Profile
*> ProfileManager::GetLoadedProfiles() const {
395 std::vector
<Profile
*> profiles
;
396 for (ProfilesInfoMap::const_iterator iter
= profiles_info_
.begin();
397 iter
!= profiles_info_
.end(); ++iter
) {
398 if (iter
->second
->created
)
399 profiles
.push_back(iter
->second
->profile
.get());
404 Profile
* ProfileManager::GetProfile(const FilePath
& profile_dir
) {
405 // If the profile is already loaded (e.g., chrome.exe launched twice), just
407 Profile
* profile
= GetProfileByPath(profile_dir
);
411 profile
= CreateProfileHelper(profile_dir
);
414 bool result
= AddProfile(profile
);
420 void ProfileManager::CreateProfileAsync(
421 const FilePath
& profile_path
,
422 const CreateCallback
& callback
,
423 const string16
& name
,
424 const string16
& icon_url
) {
425 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
427 // Make sure that this profile is not pending deletion.
428 if (std::find(ProfilesToDelete().begin(), ProfilesToDelete().end(),
429 profile_path
) != ProfilesToDelete().end()) {
430 callback
.Run(NULL
, Profile::CREATE_STATUS_FAIL
);
434 ProfilesInfoMap::iterator iter
= profiles_info_
.find(profile_path
);
435 if (iter
!= profiles_info_
.end()) {
436 ProfileInfo
* info
= iter
->second
.get();
438 // Profile has already been created. Run callback immediately.
439 callback
.Run(info
->profile
.get(), Profile::CREATE_STATUS_INITIALIZED
);
441 // Profile is being created. Add callback to list.
442 info
->callbacks
.push_back(callback
);
445 // Initiate asynchronous creation process.
447 RegisterProfile(CreateProfileAsyncHelper(profile_path
, this), false);
448 ProfileInfoCache
& cache
= GetProfileInfoCache();
449 // Get the icon index from the user's icon url
451 std::string icon_url_std
= UTF16ToASCII(icon_url
);
452 if (cache
.IsDefaultAvatarIconUrl(icon_url_std
, &icon_index
)) {
453 // add profile to cache with user selected name and avatar
454 cache
.AddProfileToCache(profile_path
, name
, string16(), icon_index
);
456 info
->callbacks
.push_back(callback
);
461 void ProfileManager::CreateDefaultProfileAsync(const CreateCallback
& callback
) {
462 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
463 ProfileManager
* profile_manager
= g_browser_process
->profile_manager();
465 FilePath default_profile_dir
= profile_manager
->user_data_dir_
;
466 // TODO(mirandac): current directory will not always be default in the future
467 default_profile_dir
= default_profile_dir
.Append(
468 profile_manager
->GetInitialProfileDir());
470 profile_manager
->CreateProfileAsync(
471 default_profile_dir
, callback
, string16(), string16());
474 bool ProfileManager::AddProfile(Profile
* profile
) {
477 // Make sure that we're not loading a profile with the same ID as a profile
478 // that's already loaded.
479 if (GetProfileByPath(profile
->GetPath())) {
480 NOTREACHED() << "Attempted to add profile with the same path (" <<
481 profile
->GetPath().value() <<
482 ") as an already-loaded profile.";
486 RegisterProfile(profile
, true);
487 DoFinalInit(profile
, ShouldGoOffTheRecord());
491 ProfileManager::ProfileInfo
* ProfileManager::RegisterProfile(
494 ProfileInfo
* info
= new ProfileInfo(profile
, created
);
495 profiles_info_
.insert(
496 std::make_pair(profile
->GetPath(), linked_ptr
<ProfileInfo
>(info
)));
500 Profile
* ProfileManager::GetProfileByPath(const FilePath
& path
) const {
501 ProfilesInfoMap::const_iterator iter
= profiles_info_
.find(path
);
502 return (iter
== profiles_info_
.end()) ? NULL
: iter
->second
->profile
.get();
506 void ProfileManager::FindOrCreateNewWindowForProfile(
508 chrome::startup::IsProcessStartup process_startup
,
509 chrome::startup::IsFirstRun is_first_run
,
510 chrome::HostDesktopType desktop_type
,
511 bool always_create
) {
517 if (!always_create
) {
518 Browser
* browser
= browser::FindTabbedBrowser(profile
, false, desktop_type
);
520 browser
->window()->Activate();
525 content::RecordAction(UserMetricsAction("NewWindow"));
526 CommandLine
command_line(CommandLine::NO_PROGRAM
);
528 StartupBrowserCreator browser_creator
;
529 browser_creator
.LaunchBrowser(command_line
, profile
, FilePath(),
530 process_startup
, is_first_run
, &return_code
);
531 #endif // defined(OS_IOS)
534 void ProfileManager::Observe(
536 const content::NotificationSource
& source
,
537 const content::NotificationDetails
& details
) {
538 #if defined(OS_CHROMEOS)
539 if (type
== chrome::NOTIFICATION_LOGIN_USER_CHANGED
) {
542 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
543 if (!command_line
.HasSwitch(switches::kTestType
)) {
544 // If we don't have a mounted profile directory we're in trouble.
545 // TODO(davemoore) Once we have better api this check should ensure that
546 // our profile directory is the one that's mounted, and that it's mounted
547 // as the current user.
548 chromeos::DBusThreadManager::Get()->GetCryptohomeClient()->IsMounted(
549 base::Bind(&CheckCryptohomeIsMounted
));
551 // Confirm that we hadn't loaded the new profile previously.
552 FilePath default_profile_dir
=
553 user_data_dir_
.Append(GetInitialProfileDir());
554 CHECK(!GetProfileByPath(default_profile_dir
))
555 << "The default profile was loaded before we mounted the cryptohome.";
560 bool save_active_profiles
= false;
562 case chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST
: {
563 // Ignore any browsers closing from now on.
564 closing_all_browsers_
= true;
567 case chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED
: {
568 // This will cancel the shutdown process, so the active profiles are
569 // tracked again. Also, as the active profiles may have changed (i.e. if
570 // some windows were closed) we save the current list of active profiles
572 closing_all_browsers_
= false;
573 save_active_profiles
= true;
576 case chrome::NOTIFICATION_BROWSER_OPENED
: {
577 Browser
* browser
= content::Source
<Browser
>(source
).ptr();
579 Profile
* profile
= browser
->profile();
581 if (!profile
->IsOffTheRecord() && ++browser_counts_
[profile
] == 1) {
582 active_profiles_
.push_back(profile
);
583 save_active_profiles
= true;
585 // If browsers are opening, we can't be closing all the browsers. This
586 // can happen if the application was exited, but background mode or
587 // packaged apps prevented the process from shutting down, and then
588 // a new browser window was opened.
589 closing_all_browsers_
= false;
592 case chrome::NOTIFICATION_BROWSER_CLOSED
: {
593 Browser
* browser
= content::Source
<Browser
>(source
).ptr();
595 Profile
* profile
= browser
->profile();
597 if (!profile
->IsOffTheRecord() && --browser_counts_
[profile
] == 0) {
598 active_profiles_
.erase(std::find(active_profiles_
.begin(),
599 active_profiles_
.end(), profile
));
600 save_active_profiles
= !closing_all_browsers_
;
610 if (save_active_profiles
) {
611 PrefService
* local_state
= g_browser_process
->local_state();
613 ListPrefUpdate
update(local_state
, prefs::kProfilesLastActive
);
614 ListValue
* profile_list
= update
.Get();
616 profile_list
->Clear();
618 // crbug.com/120112 -> several non-incognito profiles might have the same
619 // GetPath().BaseName(). In that case, we cannot restore both
620 // profiles. Include each base name only once in the last active profile
622 std::set
<std::string
> profile_paths
;
623 std::vector
<Profile
*>::const_iterator it
;
624 for (it
= active_profiles_
.begin(); it
!= active_profiles_
.end(); ++it
) {
625 std::string profile_path
= (*it
)->GetPath().BaseName().MaybeAsASCII();
626 if (profile_paths
.find(profile_path
) == profile_paths
.end()) {
627 profile_paths
.insert(profile_path
);
628 profile_list
->Append(new StringValue(profile_path
));
634 void ProfileManager::SetWillImport() {
638 void ProfileManager::OnImportFinished(Profile
* profile
) {
639 will_import_
= false;
641 content::NotificationService::current()->Notify(
642 chrome::NOTIFICATION_IMPORT_FINISHED
,
643 content::Source
<Profile
>(profile
),
644 content::NotificationService::NoDetails());
647 #if !defined(OS_ANDROID) && !defined(OS_IOS)
648 ProfileManager::BrowserListObserver::BrowserListObserver(
649 ProfileManager
* manager
)
650 : profile_manager_(manager
) {
651 BrowserList::AddObserver(this);
654 ProfileManager::BrowserListObserver::~BrowserListObserver() {
655 BrowserList::RemoveObserver(this);
658 void ProfileManager::BrowserListObserver::OnBrowserAdded(
661 void ProfileManager::BrowserListObserver::OnBrowserRemoved(
664 void ProfileManager::BrowserListObserver::OnBrowserSetLastActive(
666 // If all browsers are being closed (e.g. the user is in the process of
667 // shutting down), this event will be fired after each browser is
668 // closed. This does not represent a user intention to change the active
669 // browser so is not handled here.
670 if (profile_manager_
->closing_all_browsers_
)
673 Profile
* last_active
= browser
->profile();
674 PrefService
* local_state
= g_browser_process
->local_state();
676 // Only keep track of profiles that we are managing; tests may create others.
677 if (profile_manager_
->profiles_info_
.find(
678 last_active
->GetPath()) != profile_manager_
->profiles_info_
.end()) {
679 local_state
->SetString(prefs::kProfileLastUsed
,
680 last_active
->GetPath().BaseName().MaybeAsASCII());
683 #endif // !defined(OS_ANDROID) && !defined(OS_IOS)
685 void ProfileManager::DoFinalInit(Profile
* profile
, bool go_off_the_record
) {
686 DoFinalInitForServices(profile
, go_off_the_record
);
687 InitProfileUserPrefs(profile
);
688 AddProfileToCache(profile
);
689 DoFinalInitLogging(profile
);
691 ProfileMetrics::LogNumberOfProfiles(this, ProfileMetrics::ADD_PROFILE_EVENT
);
692 content::NotificationService::current()->Notify(
693 chrome::NOTIFICATION_PROFILE_ADDED
,
694 content::Source
<Profile
>(profile
),
695 content::NotificationService::NoDetails());
699 void ProfileManager::DoFinalInitForServices(Profile
* profile
,
700 bool go_off_the_record
) {
701 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
702 #if defined(ENABLE_EXTENSIONS)
703 extensions::ExtensionSystem::Get(profile
)->InitForRegularProfile(
705 // During tests, when |profile| is an instance of TestingProfile,
706 // ExtensionSystem might not create an ExtensionService.
707 if (extensions::ExtensionSystem::Get(profile
)->extension_service()) {
708 profile
->GetHostContentSettingsMap()->RegisterExtensionService(
709 extensions::ExtensionSystem::Get(profile
)->extension_service());
712 if (!command_line
.HasSwitch(switches::kDisableWebResources
))
713 profile
->InitPromoResources();
716 void ProfileManager::DoFinalInitLogging(Profile
* profile
) {
717 // Count number of extensions in this profile.
718 int extension_count
= -1;
719 #if defined(ENABLE_EXTENSIONS)
720 ExtensionService
* extension_service
= profile
->GetExtensionService();
721 if (extension_service
)
722 extension_count
= extension_service
->GetAppIds().size();
725 // Log the profile size after a reasonable startup delay.
726 BrowserThread::PostDelayedTask(
727 BrowserThread::FILE, FROM_HERE
,
728 base::Bind(&ProfileSizeTask
, profile
->GetPath(), extension_count
),
729 base::TimeDelta::FromSeconds(112));
732 Profile
* ProfileManager::CreateProfileHelper(const FilePath
& path
) {
733 return Profile::CreateProfile(path
, NULL
, Profile::CREATE_MODE_SYNCHRONOUS
);
736 Profile
* ProfileManager::CreateProfileAsyncHelper(const FilePath
& path
,
737 Delegate
* delegate
) {
738 return Profile::CreateProfile(path
,
740 Profile::CREATE_MODE_ASYNCHRONOUS
);
743 void ProfileManager::OnProfileCreated(Profile
* profile
,
745 bool is_new_profile
) {
746 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
748 ProfilesInfoMap::iterator iter
= profiles_info_
.find(profile
->GetPath());
749 DCHECK(iter
!= profiles_info_
.end());
750 ProfileInfo
* info
= iter
->second
.get();
752 std::vector
<CreateCallback
> callbacks
;
753 info
->callbacks
.swap(callbacks
);
755 // Invoke CREATED callback for normal profiles.
756 bool go_off_the_record
= ShouldGoOffTheRecord();
757 if (success
&& !go_off_the_record
)
758 RunCallbacks(callbacks
, profile
, Profile::CREATE_STATUS_CREATED
);
760 // Perform initialization.
762 DoFinalInit(profile
, go_off_the_record
);
763 if (go_off_the_record
)
764 profile
= profile
->GetOffTheRecordProfile();
765 info
->created
= true;
768 profiles_info_
.erase(iter
);
771 // Invoke CREATED callback for incognito profiles.
772 if (profile
&& go_off_the_record
)
773 RunCallbacks(callbacks
, profile
, Profile::CREATE_STATUS_CREATED
);
775 // Invoke INITIALIZED or FAIL for all profiles.
776 RunCallbacks(callbacks
, profile
,
777 profile
? Profile::CREATE_STATUS_INITIALIZED
:
778 Profile::CREATE_STATUS_FAIL
);
781 FilePath
ProfileManager::GenerateNextProfileDirectoryPath() {
782 PrefService
* local_state
= g_browser_process
->local_state();
785 DCHECK(IsMultipleProfilesEnabled());
787 // Create the next profile in the next available directory slot.
788 int next_directory
= local_state
->GetInteger(prefs::kProfilesNumCreated
);
789 std::string profile_name
= chrome::kMultiProfileDirPrefix
;
790 profile_name
.append(base::IntToString(next_directory
));
791 FilePath new_path
= user_data_dir_
;
793 new_path
= new_path
.Append(ASCIIToUTF16(profile_name
));
795 new_path
= new_path
.Append(profile_name
);
797 local_state
->SetInteger(prefs::kProfilesNumCreated
, ++next_directory
);
801 // TODO(robertshield): ProfileManager should not be opening windows and should
802 // not have to care about HostDesktopType. See http://crbug.com/153864
804 void ProfileManager::CreateMultiProfileAsync(
805 const string16
& name
,
806 const string16
& icon_url
,
807 const CreateCallback
& callback
,
808 chrome::HostDesktopType desktop_type
) {
809 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
811 ProfileManager
* profile_manager
= g_browser_process
->profile_manager();
813 FilePath new_path
= profile_manager
->GenerateNextProfileDirectoryPath();
815 profile_manager
->CreateProfileAsync(new_path
,
816 base::Bind(&OnOpenWindowForNewProfile
,
824 void ProfileManager::RegisterPrefs(PrefService
* prefs
) {
825 prefs
->RegisterStringPref(prefs::kProfileLastUsed
, "");
826 prefs
->RegisterIntegerPref(prefs::kProfilesNumCreated
, 1);
827 prefs
->RegisterListPref(prefs::kProfilesLastActive
);
830 size_t ProfileManager::GetNumberOfProfiles() {
831 return GetProfileInfoCache().GetNumberOfProfiles();
834 bool ProfileManager::CompareProfilePathAndName(
835 const ProfileManager::ProfilePathAndName
& pair1
,
836 const ProfileManager::ProfilePathAndName
& pair2
) {
837 int name_compare
= pair1
.second
.compare(pair2
.second
);
838 if (name_compare
< 0) {
840 } else if (name_compare
> 0) {
843 return pair1
.first
< pair2
.first
;
847 ProfileInfoCache
& ProfileManager::GetProfileInfoCache() {
848 if (!profile_info_cache_
.get()) {
849 profile_info_cache_
.reset(new ProfileInfoCache(
850 g_browser_process
->local_state(), user_data_dir_
));
852 return *profile_info_cache_
.get();
855 ProfileShortcutManager
* ProfileManager::profile_shortcut_manager() {
856 return profile_shortcut_manager_
.get();
859 void ProfileManager::AddProfileToCache(Profile
* profile
) {
860 ProfileInfoCache
& cache
= GetProfileInfoCache();
861 if (profile
->GetPath().DirName() != cache
.GetUserDataDir())
864 if (cache
.GetIndexOfProfileWithPath(profile
->GetPath()) != std::string::npos
)
867 string16 username
= UTF8ToUTF16(profile
->GetPrefs()->GetString(
868 prefs::kGoogleServicesUsername
));
870 // Profile name and avatar are set by InitProfileUserPrefs and stored in the
871 // profile. Use those values to setup the cache entry.
872 string16 profile_name
= UTF8ToUTF16(profile
->GetPrefs()->GetString(
873 prefs::kProfileName
));
875 size_t icon_index
= profile
->GetPrefs()->GetInteger(
876 prefs::kProfileAvatarIndex
);
878 cache
.AddProfileToCache(profile
->GetPath(),
884 void ProfileManager::InitProfileUserPrefs(Profile
* profile
) {
885 ProfileInfoCache
& cache
= GetProfileInfoCache();
887 if (profile
->GetPath().DirName() != cache
.GetUserDataDir())
890 // Initialize the user preferences (name and avatar) only if the profile
891 // doesn't have default preference values for them.
892 if (HasAnyDefaultUserPrefs(profile
)) {
893 size_t profile_cache_index
=
894 cache
.GetIndexOfProfileWithPath(profile
->GetPath());
895 // If the cache has an entry for this profile, use the cache data
896 if (profile_cache_index
!= std::string::npos
) {
897 profile
->GetPrefs()->SetInteger(prefs::kProfileAvatarIndex
,
898 cache
.GetAvatarIconIndexOfProfileAtIndex(profile_cache_index
));
899 profile
->GetPrefs()->SetString(prefs::kProfileName
,
900 UTF16ToUTF8(cache
.GetNameOfProfileAtIndex(profile_cache_index
)));
901 } else if (profile
->GetPath() ==
902 GetDefaultProfileDir(cache
.GetUserDataDir())) {
903 profile
->GetPrefs()->SetInteger(prefs::kProfileAvatarIndex
, 0);
904 profile
->GetPrefs()->SetString(prefs::kProfileName
,
905 l10n_util::GetStringUTF8(IDS_DEFAULT_PROFILE_NAME
));
907 size_t icon_index
= cache
.ChooseAvatarIconIndexForNewProfile();
908 profile
->GetPrefs()->SetInteger(prefs::kProfileAvatarIndex
, icon_index
);
909 profile
->GetPrefs()->SetString(
911 UTF16ToUTF8(cache
.ChooseNameForNewProfile(icon_index
)));
916 bool ProfileManager::ShouldGoOffTheRecord() {
917 bool go_off_the_record
= false;
918 #if defined(OS_CHROMEOS)
919 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
921 (!command_line
.HasSwitch(switches::kTestType
) ||
922 command_line
.HasSwitch(switches::kLoginProfile
))) {
923 go_off_the_record
= true;
926 return go_off_the_record
;
929 // TODO(robertshield): ProfileManager should not be opening windows and should
930 // not have to care about HostDesktopType. See http://crbug.com/153864
931 void ProfileManager::ScheduleProfileForDeletion(
932 const FilePath
& profile_dir
,
933 chrome::HostDesktopType desktop_type
) {
934 DCHECK(IsMultipleProfilesEnabled());
936 // If we're deleting the last profile, then create a new profile in its
938 ProfileInfoCache
& cache
= GetProfileInfoCache();
939 if (cache
.GetNumberOfProfiles() == 1) {
940 FilePath new_path
= GenerateNextProfileDirectoryPath();
942 // TODO(robertshield): This desktop type needs to come from the invoker,
943 // currently that involves plumbing this through web UI.
944 chrome::HostDesktopType desktop_type
= chrome::HOST_DESKTOP_TYPE_NATIVE
;
945 CreateProfileAsync(new_path
,
946 base::Bind(&OnOpenWindowForNewProfile
,
953 // Update the last used profile pref before closing browser windows. This way
954 // the correct last used profile is set for any notification observers.
955 PrefService
* local_state
= g_browser_process
->local_state();
956 std::string last_profile
= local_state
->GetString(prefs::kProfileLastUsed
);
957 if (profile_dir
.BaseName().MaybeAsASCII() == last_profile
) {
958 for (size_t i
= 0; i
< cache
.GetNumberOfProfiles(); ++i
) {
959 FilePath cur_path
= cache
.GetPathOfProfileAtIndex(i
);
960 if (cur_path
!= profile_dir
) {
961 local_state
->SetString(
962 prefs::kProfileLastUsed
, cur_path
.BaseName().MaybeAsASCII());
968 // TODO(sail): Due to bug 88586 we don't delete the profile instance. Once we
969 // start deleting the profile instance we need to close background apps too.
970 Profile
* profile
= GetProfileByPath(profile_dir
);
972 BrowserList::CloseAllBrowsersWithProfile(profile
);
974 // Disable sync for doomed profile.
975 if (ProfileSyncServiceFactory::GetInstance()->HasProfileSyncService(
977 ProfileSyncServiceFactory::GetInstance()->GetForProfile(
978 profile
)->DisableForUser();
982 QueueProfileDirectoryForDeletion(profile_dir
);
983 cache
.DeleteProfileFromCache(profile_dir
);
985 ProfileMetrics::LogNumberOfProfiles(this,
986 ProfileMetrics::DELETE_PROFILE_EVENT
);
990 bool ProfileManager::IsMultipleProfilesEnabled() {
991 #if defined(OS_ANDROID)
994 #if defined(OS_CHROMEOS)
995 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kMultiProfiles
))
998 return !ManagedMode::IsInManagedMode();
1001 void ProfileManager::AutoloadProfiles() {
1002 ProfileInfoCache
& cache
= GetProfileInfoCache();
1003 size_t number_of_profiles
= cache
.GetNumberOfProfiles();
1004 for (size_t p
= 0; p
< number_of_profiles
; ++p
) {
1005 if (cache
.GetBackgroundStatusOfProfileAtIndex(p
)) {
1006 // If status is true, that profile is running background apps. By calling
1007 // GetProfile, we automatically cause the profile to be loaded which will
1008 // register it with the BackgroundModeManager.
1009 GetProfile(cache
.GetPathOfProfileAtIndex(p
));
1012 ProfileMetrics::LogNumberOfProfiles(this,
1013 ProfileMetrics::STARTUP_PROFILE_EVENT
);
1016 ProfileManagerWithoutInit::ProfileManagerWithoutInit(
1017 const FilePath
& user_data_dir
) : ProfileManager(user_data_dir
) {
1020 void ProfileManager::RegisterTestingProfile(Profile
* profile
,
1021 bool add_to_cache
) {
1022 RegisterProfile(profile
, true);
1024 InitProfileUserPrefs(profile
);
1025 AddProfileToCache(profile
);
1029 void ProfileManager::RunCallbacks(const std::vector
<CreateCallback
>& callbacks
,
1031 Profile::CreateStatus status
) {
1032 for (size_t i
= 0; i
< callbacks
.size(); ++i
)
1033 callbacks
[i
].Run(profile
, status
);
1036 ProfileManager::ProfileInfo::ProfileInfo(
1043 ProfileManager::ProfileInfo::~ProfileInfo() {
1044 ProfileDestroyer::DestroyProfileWhenAppropriate(profile
.release());