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/file_util.h"
12 #include "base/files/file_path.h"
13 #include "base/metrics/histogram.h"
14 #include "base/prefs/pref_registry_simple.h"
15 #include "base/prefs/pref_service.h"
16 #include "base/string_util.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/utf_string_conversions.h"
19 #include "chrome/browser/bookmarks/bookmark_model.h"
20 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
21 #include "chrome/browser/browser_process.h"
22 #include "chrome/browser/content_settings/host_content_settings_map.h"
23 #include "chrome/browser/prefs/scoped_user_pref_update.h"
24 #include "chrome/browser/profiles/bookmark_model_loaded_observer.h"
25 #include "chrome/browser/profiles/profile_destroyer.h"
26 #include "chrome/browser/profiles/profile_info_cache.h"
27 #include "chrome/browser/profiles/profile_metrics.h"
28 #include "chrome/browser/sync/profile_sync_service.h"
29 #include "chrome/browser/sync/profile_sync_service_factory.h"
30 #include "chrome/browser/ui/browser.h"
31 #include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
32 #include "chrome/common/chrome_constants.h"
33 #include "chrome/common/chrome_notification_types.h"
34 #include "chrome/common/chrome_paths_internal.h"
35 #include "chrome/common/chrome_switches.h"
36 #include "chrome/common/logging_chrome.h"
37 #include "chrome/common/pref_names.h"
38 #include "chrome/common/url_constants.h"
39 #include "content/public/browser/browser_thread.h"
40 #include "content/public/browser/notification_service.h"
41 #include "content/public/browser/user_metrics.h"
42 #include "grit/generated_resources.h"
43 #include "net/http/http_transaction_factory.h"
44 #include "net/url_request/url_request_context.h"
45 #include "net/url_request/url_request_context_getter.h"
46 #include "net/url_request/url_request_job.h"
47 #include "ui/base/l10n/l10n_util.h"
49 #if defined(ENABLE_MANAGED_USERS)
50 #include "chrome/browser/managed_mode/managed_user_service.h"
51 #include "chrome/browser/managed_mode/managed_user_service_factory.h"
55 #include "chrome/browser/extensions/extension_service.h"
56 #include "chrome/browser/extensions/extension_system.h"
57 #include "chrome/browser/sessions/session_service_factory.h"
58 #include "chrome/browser/ui/browser_finder.h"
59 #include "chrome/browser/ui/browser_list.h"
60 #include "chrome/browser/ui/browser_window.h"
61 #include "chrome/browser/ui/startup/startup_browser_creator.h"
62 #endif // !defined (OS_IOS)
65 #include "base/win/metro.h"
66 #include "chrome/installer/util/browser_distribution.h"
69 #if defined(OS_CHROMEOS)
70 #include "base/chromeos/chromeos_version.h"
71 #include "chrome/browser/chromeos/login/user.h"
72 #include "chrome/browser/chromeos/login/user_manager.h"
73 #include "chromeos/chromeos_switches.h"
74 #include "chromeos/dbus/cryptohome_client.h"
75 #include "chromeos/dbus/dbus_thread_manager.h"
78 using content::BrowserThread
;
79 using content::UserMetricsAction
;
83 // Profiles that should be deleted on shutdown.
84 std::vector
<base::FilePath
>& ProfilesToDelete() {
85 CR_DEFINE_STATIC_LOCAL(std::vector
<base::FilePath
>, profiles_to_delete
, ());
86 return profiles_to_delete
;
89 int64
ComputeFilesSize(const base::FilePath
& directory
,
90 const base::FilePath::StringType
& pattern
) {
91 int64 running_size
= 0;
92 file_util::FileEnumerator
iter(directory
, false,
93 file_util::FileEnumerator::FILES
,
95 while (!iter
.Next().empty()) {
96 file_util::FileEnumerator::FindInfo info
;
97 iter
.GetFindInfo(&info
);
98 running_size
+= file_util::FileEnumerator::GetFilesize(info
);
103 // Simple task to log the size of the current profile.
104 void ProfileSizeTask(const base::FilePath
& path
, int extension_count
) {
105 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
107 int64 size
= ComputeFilesSize(path
, FILE_PATH_LITERAL("*"));
108 int size_MB
= static_cast<int>(size
/ (1024 * 1024));
109 UMA_HISTOGRAM_COUNTS_10000("Profile.TotalSize", size_MB
);
111 size
= ComputeFilesSize(path
, FILE_PATH_LITERAL("History"));
112 size_MB
= static_cast<int>(size
/ (1024 * 1024));
113 UMA_HISTOGRAM_COUNTS_10000("Profile.HistorySize", size_MB
);
115 size
= ComputeFilesSize(path
, FILE_PATH_LITERAL("History*"));
116 size_MB
= static_cast<int>(size
/ (1024 * 1024));
117 UMA_HISTOGRAM_COUNTS_10000("Profile.TotalHistorySize", size_MB
);
119 size
= ComputeFilesSize(path
, FILE_PATH_LITERAL("Cookies"));
120 size_MB
= static_cast<int>(size
/ (1024 * 1024));
121 UMA_HISTOGRAM_COUNTS_10000("Profile.CookiesSize", size_MB
);
123 size
= ComputeFilesSize(path
, FILE_PATH_LITERAL("Bookmarks"));
124 size_MB
= static_cast<int>(size
/ (1024 * 1024));
125 UMA_HISTOGRAM_COUNTS_10000("Profile.BookmarksSize", size_MB
);
127 size
= ComputeFilesSize(path
, FILE_PATH_LITERAL("Favicons"));
128 size_MB
= static_cast<int>(size
/ (1024 * 1024));
129 UMA_HISTOGRAM_COUNTS_10000("Profile.FaviconsSize", size_MB
);
131 size
= ComputeFilesSize(path
, FILE_PATH_LITERAL("Top Sites"));
132 size_MB
= static_cast<int>(size
/ (1024 * 1024));
133 UMA_HISTOGRAM_COUNTS_10000("Profile.TopSitesSize", size_MB
);
135 size
= ComputeFilesSize(path
, FILE_PATH_LITERAL("Visited Links"));
136 size_MB
= static_cast<int>(size
/ (1024 * 1024));
137 UMA_HISTOGRAM_COUNTS_10000("Profile.VisitedLinksSize", size_MB
);
139 size
= ComputeFilesSize(path
, FILE_PATH_LITERAL("Web Data"));
140 size_MB
= static_cast<int>(size
/ (1024 * 1024));
141 UMA_HISTOGRAM_COUNTS_10000("Profile.WebDataSize", size_MB
);
143 size
= ComputeFilesSize(path
, FILE_PATH_LITERAL("Extension*"));
144 size_MB
= static_cast<int>(size
/ (1024 * 1024));
145 UMA_HISTOGRAM_COUNTS_10000("Profile.ExtensionSize", size_MB
);
147 size
= ComputeFilesSize(path
, FILE_PATH_LITERAL("Policy"));
148 size_MB
= static_cast<int>(size
/ (1024 * 1024));
149 UMA_HISTOGRAM_COUNTS_10000("Profile.PolicySize", size_MB
);
151 // Count number of extensions in this profile, if we know.
152 if (extension_count
!= -1)
153 UMA_HISTOGRAM_COUNTS_10000("Profile.AppCount", extension_count
);
156 void QueueProfileDirectoryForDeletion(const base::FilePath
& path
) {
157 ProfilesToDelete().push_back(path
);
160 // Called upon completion of profile creation. This function takes care of
161 // launching a new browser window and signing the user in to their Google
163 void OnOpenWindowForNewProfile(
164 chrome::HostDesktopType desktop_type
,
165 const ProfileManager::CreateCallback
& callback
,
167 Profile::CreateStatus status
) {
168 // Invoke the callback before we open a window for this new profile, so the
169 // callback has a chance to update the profile state first (to do things like
170 // sign in the profile).
171 if (!callback
.is_null())
172 callback
.Run(profile
, status
);
174 if (status
== Profile::CREATE_STATUS_INITIALIZED
) {
176 ProfileManager::FindOrCreateNewWindowForProfile(
178 chrome::startup::IS_PROCESS_STARTUP
,
179 chrome::startup::IS_FIRST_RUN
,
185 #if defined(OS_CHROMEOS)
186 void CheckCryptohomeIsMounted(chromeos::DBusMethodCallStatus call_status
,
188 if (call_status
!= chromeos::DBUS_METHOD_CALL_SUCCESS
) {
189 LOG(ERROR
) << "IsMounted call failed.";
193 LOG(ERROR
) << "Cryptohome is not mounted.";
196 // TODO(nkostylev): Remove this hack when http://crbug.com/224291 is fixed.
197 // Now user homedirs are mounted to /home/user which is different from
198 // user data dir (/home/chronos).
199 base::FilePath
GetChromeOSProfileDir(const base::FilePath
& path
) {
200 base::FilePath
profile_dir(FILE_PATH_LITERAL("/home/user/"));
201 profile_dir
= profile_dir
.Append(path
);
208 #if defined(ENABLE_SESSION_SERVICE)
210 void ProfileManager::ShutdownSessionServices() {
211 ProfileManager
* pm
= g_browser_process
->profile_manager();
212 if (!pm
) // Is NULL when running unit tests.
214 std::vector
<Profile
*> profiles(pm
->GetLoadedProfiles());
215 for (size_t i
= 0; i
< profiles
.size(); ++i
)
216 SessionServiceFactory::ShutdownForProfile(profiles
[i
]);
221 void ProfileManager::NukeDeletedProfilesFromDisk() {
222 for (std::vector
<base::FilePath
>::iterator it
=
223 ProfilesToDelete().begin();
224 it
!= ProfilesToDelete().end();
226 // Delete both the profile directory and its corresponding cache.
227 base::FilePath cache_path
;
228 chrome::GetUserCacheDirectory(*it
, &cache_path
);
229 file_util::Delete(*it
, true);
230 file_util::Delete(cache_path
, true);
232 ProfilesToDelete().clear();
236 // TODO(nkostylev): Remove this method once all clients are migrated.
237 Profile
* ProfileManager::GetDefaultProfile() {
238 ProfileManager
* profile_manager
= g_browser_process
->profile_manager();
239 return profile_manager
->GetDefaultProfile(profile_manager
->user_data_dir_
);
243 // TODO(nkostylev): Remove this method once all clients are migrated.
244 Profile
* ProfileManager::GetDefaultProfileOrOffTheRecord() {
245 // TODO (mukai,nkostylev): In the long term we should fix those cases that
246 // crash on Guest mode and have only one GetDefaultProfile() method.
247 Profile
* profile
= GetDefaultProfile();
248 #if defined(OS_CHROMEOS)
249 if (chromeos::UserManager::Get()->IsLoggedInAsGuest())
250 profile
= profile
->GetOffTheRecordProfile();
256 Profile
* ProfileManager::GetLastUsedProfile() {
257 ProfileManager
* profile_manager
= g_browser_process
->profile_manager();
258 return profile_manager
->GetLastUsedProfile(profile_manager
->user_data_dir_
);
262 std::vector
<Profile
*> ProfileManager::GetLastOpenedProfiles() {
263 ProfileManager
* profile_manager
= g_browser_process
->profile_manager();
264 return profile_manager
->GetLastOpenedProfiles(
265 profile_manager
->user_data_dir_
);
268 ProfileManager::ProfileManager(const base::FilePath
& user_data_dir
)
269 : user_data_dir_(user_data_dir
),
272 profile_shortcut_manager_(NULL
),
273 #if !defined(OS_ANDROID) && !defined(OS_IOS)
274 ALLOW_THIS_IN_INITIALIZER_LIST(
275 browser_list_observer_(this)),
277 closing_all_browsers_(false) {
278 #if defined(OS_CHROMEOS)
281 chrome::NOTIFICATION_LOGIN_USER_CHANGED
,
282 content::NotificationService::AllSources());
283 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kMultiProfiles
)) {
286 chrome::NOTIFICATION_ACTIVE_USER_CHANGED
,
287 content::NotificationService::AllSources());
292 chrome::NOTIFICATION_BROWSER_OPENED
,
293 content::NotificationService::AllSources());
296 chrome::NOTIFICATION_BROWSER_CLOSED
,
297 content::NotificationService::AllSources());
300 chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST
,
301 content::NotificationService::AllSources());
304 chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED
,
305 content::NotificationService::AllSources());
307 if (ProfileShortcutManager::IsFeatureEnabled() && !user_data_dir_
.empty())
308 profile_shortcut_manager_
.reset(ProfileShortcutManager::Create(
312 ProfileManager::~ProfileManager() {
315 base::FilePath
ProfileManager::GetDefaultProfileDir(
316 const base::FilePath
& user_data_dir
) {
317 base::FilePath
default_profile_dir(user_data_dir
);
318 default_profile_dir
=
319 default_profile_dir
.AppendASCII(chrome::kInitialProfile
);
320 return default_profile_dir
;
323 base::FilePath
ProfileManager::GetProfilePrefsPath(
324 const base::FilePath
&profile_dir
) {
325 base::FilePath
default_prefs_path(profile_dir
);
326 default_prefs_path
= default_prefs_path
.Append(chrome::kPreferencesFilename
);
327 return default_prefs_path
;
330 base::FilePath
ProfileManager::GetInitialProfileDir() {
331 base::FilePath relative_profile_dir
;
332 #if defined(OS_CHROMEOS)
333 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
335 base::FilePath profile_dir
;
336 // If the user has logged in, pick up the new profile.
337 if (command_line
.HasSwitch(chromeos::switches::kLoginProfile
)) {
338 profile_dir
= command_line
.GetSwitchValuePath(
339 chromeos::switches::kLoginProfile
);
341 // We should never be logged in with no profile dir.
343 return base::FilePath("");
345 // In case of multi-profiles ignore --login-profile switch.
346 // TODO(nkostylev): Some cases like Guest mode will have empty username_hash
347 // so default kLoginProfile dir will be used.
348 if (command_line
.HasSwitch(switches::kMultiProfiles
) &&
349 !active_profile_username_hash_
.empty()) {
350 profile_dir
= base::FilePath(active_profile_username_hash_
);
352 relative_profile_dir
= relative_profile_dir
.Append(profile_dir
);
353 return relative_profile_dir
;
356 // TODO(mirandac): should not automatically be default profile.
357 relative_profile_dir
=
358 relative_profile_dir
.AppendASCII(chrome::kInitialProfile
);
359 return relative_profile_dir
;
362 Profile
* ProfileManager::GetLastUsedProfile(
363 const base::FilePath
& user_data_dir
) {
364 #if defined(OS_CHROMEOS)
365 // Use default login profile if user has not logged in yet.
367 return GetDefaultProfile(user_data_dir
);
370 return GetProfile(GetLastUsedProfileDir(user_data_dir
));
373 base::FilePath
ProfileManager::GetLastUsedProfileDir(
374 const base::FilePath
& user_data_dir
) {
375 base::FilePath
last_used_profile_dir(user_data_dir
);
376 std::string last_used_profile
;
377 PrefService
* local_state
= g_browser_process
->local_state();
380 if (local_state
->HasPrefPath(prefs::kProfileLastUsed
)) {
381 return last_used_profile_dir
.AppendASCII(
382 local_state
->GetString(prefs::kProfileLastUsed
));
385 return last_used_profile_dir
.AppendASCII(chrome::kInitialProfile
);
388 std::vector
<Profile
*> ProfileManager::GetLastOpenedProfiles(
389 const base::FilePath
& user_data_dir
) {
390 PrefService
* local_state
= g_browser_process
->local_state();
393 std::vector
<Profile
*> to_return
;
394 if (local_state
->HasPrefPath(prefs::kProfilesLastActive
)) {
395 const ListValue
* profile_list
=
396 local_state
->GetList(prefs::kProfilesLastActive
);
398 ListValue::const_iterator it
;
400 for (it
= profile_list
->begin(); it
!= profile_list
->end(); ++it
) {
401 if (!(*it
)->GetAsString(&profile
) || profile
.empty()) {
402 LOG(WARNING
) << "Invalid entry in " << prefs::kProfilesLastActive
;
405 to_return
.push_back(GetProfile(user_data_dir
.AppendASCII(profile
)));
412 Profile
* ProfileManager::GetDefaultProfile(
413 const base::FilePath
& user_data_dir
) {
414 #if defined(OS_CHROMEOS)
415 base::FilePath
default_profile_dir(user_data_dir
);
417 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kMultiProfiles
) &&
418 base::chromeos::IsRunningOnChromeOS()) {
419 // TODO(nkostylev): Change to [user_data_dir]/profile-[hash]
420 default_profile_dir
= GetChromeOSProfileDir(GetInitialProfileDir());
422 default_profile_dir
= default_profile_dir
.Append(GetInitialProfileDir());
425 default_profile_dir
= GetDefaultProfileDir(user_data_dir
);
428 base::FilePath
default_profile_dir(user_data_dir
);
429 default_profile_dir
= default_profile_dir
.Append(GetInitialProfileDir());
431 #if defined(OS_CHROMEOS)
433 Profile
* profile
= GetProfile(default_profile_dir
);
434 // For cros, return the OTR profile so we never accidentally keep
435 // user data in an unencrypted profile. But doing this makes
436 // many of the browser and ui tests fail. We do return the OTR profile
437 // if the login-profile switch is passed so that we can test this.
438 // TODO(davemoore) Fix the tests so they allow OTR profiles.
439 if (ShouldGoOffTheRecord())
440 return profile
->GetOffTheRecordProfile();
444 ProfileInfo
* profile_info
= GetProfileInfoByPath(default_profile_dir
);
445 // Fallback to default off-the-record profile, if user profile has not fully
447 if (profile_info
&& !profile_info
->created
)
448 default_profile_dir
= GetDefaultProfileDir(user_data_dir
);
450 return GetProfile(default_profile_dir
);
453 bool ProfileManager::IsValidProfile(Profile
* profile
) {
454 for (ProfilesInfoMap::iterator iter
= profiles_info_
.begin();
455 iter
!= profiles_info_
.end(); ++iter
) {
456 if (iter
->second
->created
) {
457 Profile
* candidate
= iter
->second
->profile
.get();
458 if (candidate
== profile
||
459 (candidate
->HasOffTheRecordProfile() &&
460 candidate
->GetOffTheRecordProfile() == profile
)) {
468 std::vector
<Profile
*> ProfileManager::GetLoadedProfiles() const {
469 std::vector
<Profile
*> profiles
;
470 for (ProfilesInfoMap::const_iterator iter
= profiles_info_
.begin();
471 iter
!= profiles_info_
.end(); ++iter
) {
472 if (iter
->second
->created
)
473 profiles
.push_back(iter
->second
->profile
.get());
478 Profile
* ProfileManager::GetProfile(const base::FilePath
& profile_dir
) {
479 // If the profile is already loaded (e.g., chrome.exe launched twice), just
481 Profile
* profile
= GetProfileByPath(profile_dir
);
485 profile
= CreateProfileHelper(profile_dir
);
488 bool result
= AddProfile(profile
);
494 void ProfileManager::CreateProfileAsync(
495 const base::FilePath
& profile_path
,
496 const CreateCallback
& callback
,
497 const string16
& name
,
498 const string16
& icon_url
,
500 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
502 // Make sure that this profile is not pending deletion.
503 if (std::find(ProfilesToDelete().begin(), ProfilesToDelete().end(),
504 profile_path
) != ProfilesToDelete().end()) {
505 callback
.Run(NULL
, Profile::CREATE_STATUS_FAIL
);
509 ProfilesInfoMap::iterator iter
= profiles_info_
.find(profile_path
);
510 if (iter
!= profiles_info_
.end()) {
511 ProfileInfo
* info
= iter
->second
.get();
513 // Profile has already been created. Run callback immediately.
514 callback
.Run(info
->profile
.get(), Profile::CREATE_STATUS_INITIALIZED
);
516 // Profile is being created. Add callback to list.
517 info
->callbacks
.push_back(callback
);
520 // Initiate asynchronous creation process.
522 RegisterProfile(CreateProfileAsyncHelper(profile_path
, this), false);
523 ProfileInfoCache
& cache
= GetProfileInfoCache();
524 // Get the icon index from the user's icon url
526 std::string icon_url_std
= UTF16ToASCII(icon_url
);
527 if (cache
.IsDefaultAvatarIconUrl(icon_url_std
, &icon_index
)) {
528 // add profile to cache with user selected name and avatar
529 cache
.AddProfileToCache(profile_path
, name
, string16(), icon_index
,
532 info
->callbacks
.push_back(callback
);
535 content::RecordAction(
536 UserMetricsAction("ManagedMode_LocallyManagedUserCreated"));
542 void ProfileManager::CreateDefaultProfileAsync(const CreateCallback
& callback
) {
543 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
544 ProfileManager
* profile_manager
= g_browser_process
->profile_manager();
546 base::FilePath default_profile_dir
= profile_manager
->user_data_dir_
;
547 // TODO(mirandac): current directory will not always be default in the future
548 default_profile_dir
= default_profile_dir
.Append(
549 profile_manager
->GetInitialProfileDir());
551 #if defined(OS_CHROMEOS)
552 // TODO(nkostylev): Change to [user_data_dir]/profile-[hash]
553 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kMultiProfiles
) &&
554 base::chromeos::IsRunningOnChromeOS()) {
555 default_profile_dir
= GetChromeOSProfileDir(
556 profile_manager
->GetInitialProfileDir());
560 // Chrome OS specific note: since we pass string16() here as the icon_url,
561 // profile cache information will not get updated with the is_managed value
562 // so we're fine with passing all default values here.
563 // On Chrome OS |is_managed| preference will get initialized in
564 // Profile::CREATE_STATUS_CREATED callback.
565 profile_manager
->CreateProfileAsync(
566 default_profile_dir
, callback
, string16(), string16(), false);
569 bool ProfileManager::AddProfile(Profile
* profile
) {
572 // Make sure that we're not loading a profile with the same ID as a profile
573 // that's already loaded.
574 if (GetProfileByPath(profile
->GetPath())) {
575 NOTREACHED() << "Attempted to add profile with the same path (" <<
576 profile
->GetPath().value() <<
577 ") as an already-loaded profile.";
581 RegisterProfile(profile
, true);
582 DoFinalInit(profile
, ShouldGoOffTheRecord());
586 ProfileManager::ProfileInfo
* ProfileManager::RegisterProfile(
589 ProfileInfo
* info
= new ProfileInfo(profile
, created
);
590 profiles_info_
.insert(
591 std::make_pair(profile
->GetPath(), linked_ptr
<ProfileInfo
>(info
)));
595 ProfileManager::ProfileInfo
* ProfileManager::GetProfileInfoByPath(
596 const base::FilePath
& path
) const {
597 ProfilesInfoMap::const_iterator iter
= profiles_info_
.find(path
);
598 return (iter
== profiles_info_
.end()) ? NULL
: iter
->second
.get();
601 Profile
* ProfileManager::GetProfileByPath(const base::FilePath
& path
) const {
602 ProfileInfo
* profile_info
= GetProfileInfoByPath(path
);
603 return profile_info
? profile_info
->profile
.get() : NULL
;
607 void ProfileManager::FindOrCreateNewWindowForProfile(
609 chrome::startup::IsProcessStartup process_startup
,
610 chrome::startup::IsFirstRun is_first_run
,
611 chrome::HostDesktopType desktop_type
,
612 bool always_create
) {
618 if (!always_create
) {
619 Browser
* browser
= chrome::FindTabbedBrowser(profile
, false, desktop_type
);
621 browser
->window()->Activate();
626 content::RecordAction(UserMetricsAction("NewWindow"));
627 CommandLine
command_line(CommandLine::NO_PROGRAM
);
629 StartupBrowserCreator browser_creator
;
630 browser_creator
.LaunchBrowser(command_line
, profile
, base::FilePath(),
631 process_startup
, is_first_run
, &return_code
);
632 #endif // defined(OS_IOS)
635 void ProfileManager::Observe(
637 const content::NotificationSource
& source
,
638 const content::NotificationDetails
& details
) {
639 #if defined(OS_CHROMEOS)
640 if (type
== chrome::NOTIFICATION_LOGIN_USER_CHANGED
) {
643 chromeos::User
* user
= content::Details
<chromeos::User
>(details
).ptr();
646 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
647 if (!command_line
.HasSwitch(switches::kTestType
)) {
648 // If we don't have a mounted profile directory we're in trouble.
649 // TODO(davemoore) Once we have better api this check should ensure that
650 // our profile directory is the one that's mounted, and that it's mounted
651 // as the current user.
652 chromeos::DBusThreadManager::Get()->GetCryptohomeClient()->IsMounted(
653 base::Bind(&CheckCryptohomeIsMounted
));
655 // Confirm that we hadn't loaded the new profile previously.
656 if (command_line
.HasSwitch(switches::kMultiProfiles
)) {
657 // TODO(nkostylev): We could not enforce username_hash not being
658 // empty here till all cases like Guest mode are migrated.
659 active_profile_username_hash_
= user
->username_hash();
660 LOG(INFO
) << "Switching to custom profile_dir: "
661 << active_profile_username_hash_
;
663 base::FilePath default_profile_dir
= user_data_dir_
.Append(
664 GetInitialProfileDir(/*active_profile_username_hash_*/));
665 CHECK(!GetProfileByPath(default_profile_dir
))
666 << "The default profile was loaded before we mounted the cryptohome.";
669 } else if (type
== chrome::NOTIFICATION_ACTIVE_USER_CHANGED
) {
670 chromeos::User
* user
= content::Details
<chromeos::User
>(details
).ptr();
671 active_profile_username_hash_
= user
->username_hash();
672 LOG(INFO
) << "Switching to custom profile_dir: "
673 << active_profile_username_hash_
;
677 bool save_active_profiles
= false;
679 case chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST
: {
680 // Ignore any browsers closing from now on.
681 closing_all_browsers_
= true;
684 case chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED
: {
685 // This will cancel the shutdown process, so the active profiles are
686 // tracked again. Also, as the active profiles may have changed (i.e. if
687 // some windows were closed) we save the current list of active profiles
689 closing_all_browsers_
= false;
690 save_active_profiles
= true;
693 case chrome::NOTIFICATION_BROWSER_OPENED
: {
694 Browser
* browser
= content::Source
<Browser
>(source
).ptr();
696 Profile
* profile
= browser
->profile();
698 if (!profile
->IsOffTheRecord() && ++browser_counts_
[profile
] == 1) {
699 active_profiles_
.push_back(profile
);
700 save_active_profiles
= true;
702 // If browsers are opening, we can't be closing all the browsers. This
703 // can happen if the application was exited, but background mode or
704 // packaged apps prevented the process from shutting down, and then
705 // a new browser window was opened.
706 closing_all_browsers_
= false;
709 case chrome::NOTIFICATION_BROWSER_CLOSED
: {
710 Browser
* browser
= content::Source
<Browser
>(source
).ptr();
712 Profile
* profile
= browser
->profile();
714 if (!profile
->IsOffTheRecord() && --browser_counts_
[profile
] == 0) {
715 active_profiles_
.erase(std::find(active_profiles_
.begin(),
716 active_profiles_
.end(), profile
));
717 save_active_profiles
= !closing_all_browsers_
;
727 if (save_active_profiles
) {
728 PrefService
* local_state
= g_browser_process
->local_state();
730 ListPrefUpdate
update(local_state
, prefs::kProfilesLastActive
);
731 ListValue
* profile_list
= update
.Get();
733 profile_list
->Clear();
735 // crbug.com/120112 -> several non-incognito profiles might have the same
736 // GetPath().BaseName(). In that case, we cannot restore both
737 // profiles. Include each base name only once in the last active profile
739 std::set
<std::string
> profile_paths
;
740 std::vector
<Profile
*>::const_iterator it
;
741 for (it
= active_profiles_
.begin(); it
!= active_profiles_
.end(); ++it
) {
742 std::string profile_path
= (*it
)->GetPath().BaseName().MaybeAsASCII();
743 if (profile_paths
.find(profile_path
) == profile_paths
.end()) {
744 profile_paths
.insert(profile_path
);
745 profile_list
->Append(new StringValue(profile_path
));
752 bool ProfileManager::IsImportProcess(const CommandLine
& command_line
) {
753 return (command_line
.HasSwitch(switches::kImport
) ||
754 command_line
.HasSwitch(switches::kImportFromFile
));
757 void ProfileManager::SetWillImport() {
761 void ProfileManager::OnImportFinished(Profile
* profile
) {
762 will_import_
= false;
765 #if !defined(OS_CHROMEOS)
766 // If the import process was not run, it means this branch was not called,
767 // and it was handled by ProfileImpl::DoFinalInit().
768 BookmarkModel
* model
= BookmarkModelFactory::GetForProfile(profile
);
769 model
->AddObserver(new BookmarkModelLoadedObserver(profile
));
772 content::NotificationService::current()->Notify(
773 chrome::NOTIFICATION_IMPORT_FINISHED
,
774 content::Source
<Profile
>(profile
),
775 content::NotificationService::NoDetails());
778 #if !defined(OS_ANDROID) && !defined(OS_IOS)
779 ProfileManager::BrowserListObserver::BrowserListObserver(
780 ProfileManager
* manager
)
781 : profile_manager_(manager
) {
782 BrowserList::AddObserver(this);
785 ProfileManager::BrowserListObserver::~BrowserListObserver() {
786 BrowserList::RemoveObserver(this);
789 void ProfileManager::BrowserListObserver::OnBrowserAdded(
792 void ProfileManager::BrowserListObserver::OnBrowserRemoved(
795 void ProfileManager::BrowserListObserver::OnBrowserSetLastActive(
797 // If all browsers are being closed (e.g. the user is in the process of
798 // shutting down), this event will be fired after each browser is
799 // closed. This does not represent a user intention to change the active
800 // browser so is not handled here.
801 if (profile_manager_
->closing_all_browsers_
)
804 Profile
* last_active
= browser
->profile();
805 PrefService
* local_state
= g_browser_process
->local_state();
807 // Only keep track of profiles that we are managing; tests may create others.
808 if (profile_manager_
->profiles_info_
.find(
809 last_active
->GetPath()) != profile_manager_
->profiles_info_
.end()) {
810 local_state
->SetString(prefs::kProfileLastUsed
,
811 last_active
->GetPath().BaseName().MaybeAsASCII());
814 #endif // !defined(OS_ANDROID) && !defined(OS_IOS)
816 void ProfileManager::DoFinalInit(Profile
* profile
, bool go_off_the_record
) {
817 InitProfileUserPrefs(profile
);
818 DoFinalInitForServices(profile
, go_off_the_record
);
819 AddProfileToCache(profile
);
820 DoFinalInitLogging(profile
);
822 ProfileMetrics::LogNumberOfProfiles(this);
823 content::NotificationService::current()->Notify(
824 chrome::NOTIFICATION_PROFILE_ADDED
,
825 content::Source
<Profile
>(profile
),
826 content::NotificationService::NoDetails());
829 void ProfileManager::DoFinalInitForServices(Profile
* profile
,
830 bool go_off_the_record
) {
831 #if defined(ENABLE_EXTENSIONS)
832 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
833 if (!IsImportProcess(command_line
)) {
834 extensions::ExtensionSystem::Get(profile
)->InitForRegularProfile(
836 // During tests, when |profile| is an instance of TestingProfile,
837 // ExtensionSystem might not create an ExtensionService.
838 if (extensions::ExtensionSystem::Get(profile
)->extension_service()) {
839 profile
->GetHostContentSettingsMap()->RegisterExtensionService(
840 extensions::ExtensionSystem::Get(profile
)->extension_service());
844 #if defined(ENABLE_MANAGED_USERS)
845 // Initialization needs to happen after extension system initialization (for
846 // extension::ManagementPolicy) and InitProfileUserPrefs (for setting the
847 // initializing the managed flag if necessary).
848 ManagedUserServiceFactory::GetForProfile(profile
)->Init();
852 void ProfileManager::DoFinalInitLogging(Profile
* profile
) {
853 // Count number of extensions in this profile.
854 int extension_count
= -1;
855 #if defined(ENABLE_EXTENSIONS)
856 ExtensionService
* extension_service
= profile
->GetExtensionService();
857 if (extension_service
)
858 extension_count
= extension_service
->GetAppIds().size();
861 // Log the profile size after a reasonable startup delay.
862 BrowserThread::PostDelayedTask(
863 BrowserThread::FILE, FROM_HERE
,
864 base::Bind(&ProfileSizeTask
, profile
->GetPath(), extension_count
),
865 base::TimeDelta::FromSeconds(112));
868 Profile
* ProfileManager::CreateProfileHelper(const base::FilePath
& path
) {
869 return Profile::CreateProfile(path
, NULL
, Profile::CREATE_MODE_SYNCHRONOUS
);
872 Profile
* ProfileManager::CreateProfileAsyncHelper(const base::FilePath
& path
,
873 Delegate
* delegate
) {
874 return Profile::CreateProfile(path
,
876 Profile::CREATE_MODE_ASYNCHRONOUS
);
879 void ProfileManager::OnProfileCreated(Profile
* profile
,
881 bool is_new_profile
) {
882 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
884 ProfilesInfoMap::iterator iter
= profiles_info_
.find(profile
->GetPath());
885 DCHECK(iter
!= profiles_info_
.end());
886 ProfileInfo
* info
= iter
->second
.get();
888 std::vector
<CreateCallback
> callbacks
;
889 info
->callbacks
.swap(callbacks
);
891 // Invoke CREATED callback for normal profiles.
892 bool go_off_the_record
= ShouldGoOffTheRecord();
893 if (success
&& !go_off_the_record
)
894 RunCallbacks(callbacks
, profile
, Profile::CREATE_STATUS_CREATED
);
896 // Perform initialization.
898 DoFinalInit(profile
, go_off_the_record
);
899 if (go_off_the_record
)
900 profile
= profile
->GetOffTheRecordProfile();
901 info
->created
= true;
904 profiles_info_
.erase(iter
);
907 // Invoke CREATED callback for incognito profiles.
908 if (profile
&& go_off_the_record
)
909 RunCallbacks(callbacks
, profile
, Profile::CREATE_STATUS_CREATED
);
911 // Invoke INITIALIZED or FAIL for all profiles.
912 RunCallbacks(callbacks
, profile
,
913 profile
? Profile::CREATE_STATUS_INITIALIZED
:
914 Profile::CREATE_STATUS_FAIL
);
917 base::FilePath
ProfileManager::GenerateNextProfileDirectoryPath() {
918 PrefService
* local_state
= g_browser_process
->local_state();
921 DCHECK(IsMultipleProfilesEnabled());
923 // Create the next profile in the next available directory slot.
924 int next_directory
= local_state
->GetInteger(prefs::kProfilesNumCreated
);
925 std::string profile_name
= chrome::kMultiProfileDirPrefix
;
926 profile_name
.append(base::IntToString(next_directory
));
927 base::FilePath new_path
= user_data_dir_
;
929 new_path
= new_path
.Append(ASCIIToUTF16(profile_name
));
931 new_path
= new_path
.Append(profile_name
);
933 local_state
->SetInteger(prefs::kProfilesNumCreated
, ++next_directory
);
937 // TODO(robertshield): ProfileManager should not be opening windows and should
938 // not have to care about HostDesktopType. See http://crbug.com/153864
940 void ProfileManager::CreateMultiProfileAsync(
941 const string16
& name
,
942 const string16
& icon_url
,
943 const CreateCallback
& callback
,
944 chrome::HostDesktopType desktop_type
,
946 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
948 ProfileManager
* profile_manager
= g_browser_process
->profile_manager();
950 base::FilePath new_path
= profile_manager
->GenerateNextProfileDirectoryPath();
952 profile_manager
->CreateProfileAsync(new_path
,
953 base::Bind(&OnOpenWindowForNewProfile
,
962 void ProfileManager::RegisterPrefs(PrefRegistrySimple
* registry
) {
963 registry
->RegisterStringPref(prefs::kProfileLastUsed
, std::string());
964 registry
->RegisterIntegerPref(prefs::kProfilesNumCreated
, 1);
965 registry
->RegisterListPref(prefs::kProfilesLastActive
);
968 size_t ProfileManager::GetNumberOfProfiles() {
969 return GetProfileInfoCache().GetNumberOfProfiles();
972 bool ProfileManager::CompareProfilePathAndName(
973 const ProfileManager::ProfilePathAndName
& pair1
,
974 const ProfileManager::ProfilePathAndName
& pair2
) {
975 int name_compare
= pair1
.second
.compare(pair2
.second
);
976 if (name_compare
< 0) {
978 } else if (name_compare
> 0) {
981 return pair1
.first
< pair2
.first
;
985 ProfileInfoCache
& ProfileManager::GetProfileInfoCache() {
986 if (!profile_info_cache_
.get()) {
987 profile_info_cache_
.reset(new ProfileInfoCache(
988 g_browser_process
->local_state(), user_data_dir_
));
990 return *profile_info_cache_
.get();
993 ProfileShortcutManager
* ProfileManager::profile_shortcut_manager() {
994 return profile_shortcut_manager_
.get();
997 void ProfileManager::AddProfileToCache(Profile
* profile
) {
998 ProfileInfoCache
& cache
= GetProfileInfoCache();
999 if (profile
->GetPath().DirName() != cache
.GetUserDataDir())
1002 if (cache
.GetIndexOfProfileWithPath(profile
->GetPath()) != std::string::npos
)
1005 string16 username
= UTF8ToUTF16(profile
->GetPrefs()->GetString(
1006 prefs::kGoogleServicesUsername
));
1008 // Profile name and avatar are set by InitProfileUserPrefs and stored in the
1009 // profile. Use those values to setup the cache entry.
1010 string16 profile_name
= UTF8ToUTF16(profile
->GetPrefs()->GetString(
1011 prefs::kProfileName
));
1013 size_t icon_index
= profile
->GetPrefs()->GetInteger(
1014 prefs::kProfileAvatarIndex
);
1016 bool is_managed
= profile
->GetPrefs()->GetBoolean(prefs::kProfileIsManaged
);
1018 cache
.AddProfileToCache(profile
->GetPath(),
1025 void ProfileManager::InitProfileUserPrefs(Profile
* profile
) {
1026 ProfileInfoCache
& cache
= GetProfileInfoCache();
1028 if (profile
->GetPath().DirName() != cache
.GetUserDataDir())
1031 size_t avatar_index
;
1032 std::string profile_name
;
1033 bool is_managed
= false;
1034 size_t profile_cache_index
=
1035 cache
.GetIndexOfProfileWithPath(profile
->GetPath());
1036 // If the cache has an entry for this profile, use the cache data.
1037 if (profile_cache_index
!= std::string::npos
) {
1039 cache
.GetAvatarIconIndexOfProfileAtIndex(profile_cache_index
);
1041 UTF16ToUTF8(cache
.GetNameOfProfileAtIndex(profile_cache_index
));
1042 is_managed
= cache
.ProfileIsManagedAtIndex(profile_cache_index
);
1043 } else if (profile
->GetPath() ==
1044 GetDefaultProfileDir(cache
.GetUserDataDir())) {
1046 profile_name
= l10n_util::GetStringUTF8(IDS_DEFAULT_PROFILE_NAME
);
1048 avatar_index
= cache
.ChooseAvatarIconIndexForNewProfile();
1049 profile_name
= UTF16ToUTF8(cache
.ChooseNameForNewProfile(avatar_index
));
1052 if (!profile
->GetPrefs()->HasPrefPath(prefs::kProfileAvatarIndex
))
1053 profile
->GetPrefs()->SetInteger(prefs::kProfileAvatarIndex
, avatar_index
);
1055 if (!profile
->GetPrefs()->HasPrefPath(prefs::kProfileName
))
1056 profile
->GetPrefs()->SetString(prefs::kProfileName
, profile_name
);
1058 if (!profile
->GetPrefs()->HasPrefPath(prefs::kProfileIsManaged
))
1059 profile
->GetPrefs()->SetBoolean(prefs::kProfileIsManaged
, is_managed
);
1062 bool ProfileManager::ShouldGoOffTheRecord() {
1063 bool go_off_the_record
= false;
1064 #if defined(OS_CHROMEOS)
1065 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
1067 (!command_line
.HasSwitch(switches::kTestType
) ||
1068 command_line
.HasSwitch(chromeos::switches::kLoginProfile
))) {
1069 go_off_the_record
= true;
1072 return go_off_the_record
;
1075 // TODO(robertshield): ProfileManager should not be opening windows and should
1076 // not have to care about HostDesktopType. See http://crbug.com/153864
1077 void ProfileManager::ScheduleProfileForDeletion(
1078 const base::FilePath
& profile_dir
,
1079 chrome::HostDesktopType desktop_type
) {
1080 DCHECK(IsMultipleProfilesEnabled());
1082 PrefService
* local_state
= g_browser_process
->local_state();
1083 ProfileInfoCache
& cache
= GetProfileInfoCache();
1084 if (profile_dir
.BaseName().MaybeAsASCII() ==
1085 local_state
->GetString(prefs::kProfileLastUsed
)) {
1086 // Update the last used profile pref before closing browser windows. This
1087 // way the correct last used profile is set for any notification observers.
1088 std::string last_non_managed_profile
;
1089 for (size_t i
= 0; i
< cache
.GetNumberOfProfiles(); ++i
) {
1090 base::FilePath cur_path
= cache
.GetPathOfProfileAtIndex(i
);
1091 if (cur_path
!= profile_dir
&& !cache
.ProfileIsManagedAtIndex(i
)) {
1092 last_non_managed_profile
= cur_path
.BaseName().MaybeAsASCII();
1096 // If we're deleting the last (non-managed) profile, then create a new
1097 // profile in its place.
1098 if (last_non_managed_profile
.empty()) {
1099 base::FilePath new_path
= GenerateNextProfileDirectoryPath();
1100 // Make sure the last used profile path is pointing at it. This way the
1101 // correct last used profile is set for any notification observers.
1102 local_state
->SetString(prefs::kProfileLastUsed
,
1103 new_path
.BaseName().MaybeAsASCII());
1104 // TODO(robertshield): This desktop type needs to come from the invoker,
1105 // currently that involves plumbing this through web UI.
1106 chrome::HostDesktopType desktop_type
= chrome::HOST_DESKTOP_TYPE_NATIVE
;
1107 CreateProfileAsync(new_path
,
1108 base::Bind(&OnOpenWindowForNewProfile
,
1115 local_state
->SetString(prefs::kProfileLastUsed
, last_non_managed_profile
);
1119 // TODO(sail): Due to bug 88586 we don't delete the profile instance. Once we
1120 // start deleting the profile instance we need to close background apps too.
1121 Profile
* profile
= GetProfileByPath(profile_dir
);
1123 BrowserList::CloseAllBrowsersWithProfile(profile
);
1125 // Disable sync for doomed profile.
1126 if (ProfileSyncServiceFactory::GetInstance()->HasProfileSyncService(
1128 ProfileSyncServiceFactory::GetInstance()->GetForProfile(
1129 profile
)->DisableForUser();
1133 QueueProfileDirectoryForDeletion(profile_dir
);
1134 cache
.DeleteProfileFromCache(profile_dir
);
1138 bool ProfileManager::IsMultipleProfilesEnabled() {
1139 #if defined(OS_ANDROID)
1142 #if defined(OS_CHROMEOS)
1143 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kMultiProfiles
))
1150 void ProfileManager::AutoloadProfiles() {
1151 // If running in the background is disabled for the browser, do not autoload
1153 PrefService
* local_state
= g_browser_process
->local_state();
1154 if (!local_state
->HasPrefPath(prefs::kBackgroundModeEnabled
) ||
1155 !local_state
->GetBoolean(prefs::kBackgroundModeEnabled
)) {
1159 ProfileInfoCache
& cache
= GetProfileInfoCache();
1160 size_t number_of_profiles
= cache
.GetNumberOfProfiles();
1161 for (size_t p
= 0; p
< number_of_profiles
; ++p
) {
1162 if (cache
.GetBackgroundStatusOfProfileAtIndex(p
)) {
1163 // If status is true, that profile is running background apps. By calling
1164 // GetProfile, we automatically cause the profile to be loaded which will
1165 // register it with the BackgroundModeManager.
1166 GetProfile(cache
.GetPathOfProfileAtIndex(p
));
1171 ProfileManagerWithoutInit::ProfileManagerWithoutInit(
1172 const base::FilePath
& user_data_dir
) : ProfileManager(user_data_dir
) {
1175 void ProfileManager::RegisterTestingProfile(Profile
* profile
,
1176 bool add_to_cache
) {
1177 RegisterProfile(profile
, true);
1179 InitProfileUserPrefs(profile
);
1180 AddProfileToCache(profile
);
1184 void ProfileManager::RunCallbacks(const std::vector
<CreateCallback
>& callbacks
,
1186 Profile::CreateStatus status
) {
1187 for (size_t i
= 0; i
< callbacks
.size(); ++i
)
1188 callbacks
[i
].Run(profile
, status
);
1191 ProfileManager::ProfileInfo::ProfileInfo(
1198 ProfileManager::ProfileInfo::~ProfileInfo() {
1199 ProfileDestroyer::DestroyProfileWhenAppropriate(profile
.release());