Fix build break
[chromium-blink-merge.git] / chrome / browser / profiles / profile_manager.cc
blobe157d1f75efa2be903f47e462f7c55133715ca0d
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/profiles/profile_manager.h"
7 #include <set>
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/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"
52 #endif
54 #if !defined(OS_IOS)
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)
64 #if defined(OS_WIN)
65 #include "base/win/metro.h"
66 #include "chrome/installer/util/browser_distribution.h"
67 #endif
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"
76 #endif
78 using content::BrowserThread;
79 using content::UserMetricsAction;
81 namespace {
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,
94 pattern);
95 while (!iter.Next().empty()) {
96 file_util::FileEnumerator::FindInfo info;
97 iter.GetFindInfo(&info);
98 running_size += file_util::FileEnumerator::GetFilesize(info);
100 return running_size;
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
162 // account.
163 void OnOpenWindowForNewProfile(
164 chrome::HostDesktopType desktop_type,
165 const ProfileManager::CreateCallback& callback,
166 Profile* profile,
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(
177 profile,
178 chrome::startup::IS_PROCESS_STARTUP,
179 chrome::startup::IS_FIRST_RUN,
180 desktop_type,
181 false);
185 #if defined(OS_CHROMEOS)
186 void CheckCryptohomeIsMounted(chromeos::DBusMethodCallStatus call_status,
187 bool is_mounted) {
188 if (call_status != chromeos::DBUS_METHOD_CALL_SUCCESS) {
189 LOG(ERROR) << "IsMounted call failed.";
190 return;
192 if (!is_mounted)
193 LOG(ERROR) << "Cryptohome is not mounted.";
196 // 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);
202 return profile_dir;
204 #endif
206 } // namespace
208 #if defined(ENABLE_SESSION_SERVICE)
209 // static
210 void ProfileManager::ShutdownSessionServices() {
211 ProfileManager* pm = g_browser_process->profile_manager();
212 if (!pm) // Is NULL when running unit tests.
213 return;
214 std::vector<Profile*> profiles(pm->GetLoadedProfiles());
215 for (size_t i = 0; i < profiles.size(); ++i)
216 SessionServiceFactory::ShutdownForProfile(profiles[i]);
218 #endif
220 // static
221 void ProfileManager::NukeDeletedProfilesFromDisk() {
222 for (std::vector<base::FilePath>::iterator it =
223 ProfilesToDelete().begin();
224 it != ProfilesToDelete().end();
225 ++it) {
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();
235 // static
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_);
242 // static
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();
251 #endif
252 return profile;
255 // static
256 Profile* ProfileManager::GetLastUsedProfile() {
257 ProfileManager* profile_manager = g_browser_process->profile_manager();
258 return profile_manager->GetLastUsedProfile(profile_manager->user_data_dir_);
261 // static
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),
270 logged_in_(false),
271 will_import_(false),
272 profile_shortcut_manager_(NULL),
273 #if !defined(OS_ANDROID) && !defined(OS_IOS)
274 ALLOW_THIS_IN_INITIALIZER_LIST(
275 browser_list_observer_(this)),
276 #endif
277 closing_all_browsers_(false) {
278 #if defined(OS_CHROMEOS)
279 registrar_.Add(
280 this,
281 chrome::NOTIFICATION_LOGIN_USER_CHANGED,
282 content::NotificationService::AllSources());
283 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kMultiProfiles)) {
284 registrar_.Add(
285 this,
286 chrome::NOTIFICATION_ACTIVE_USER_CHANGED,
287 content::NotificationService::AllSources());
289 #endif
290 registrar_.Add(
291 this,
292 chrome::NOTIFICATION_BROWSER_OPENED,
293 content::NotificationService::AllSources());
294 registrar_.Add(
295 this,
296 chrome::NOTIFICATION_BROWSER_CLOSED,
297 content::NotificationService::AllSources());
298 registrar_.Add(
299 this,
300 chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST,
301 content::NotificationService::AllSources());
302 registrar_.Add(
303 this,
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(
309 this));
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();
334 if (logged_in_) {
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);
340 } else {
341 // We should never be logged in with no profile dir.
342 NOTREACHED();
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;
355 #endif
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.
366 if (!logged_in_)
367 return GetDefaultProfile(user_data_dir);
368 #endif
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();
378 DCHECK(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();
391 DCHECK(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);
397 if (profile_list) {
398 ListValue::const_iterator it;
399 std::string profile;
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;
403 continue;
405 to_return.push_back(GetProfile(user_data_dir.AppendASCII(profile)));
409 return to_return;
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);
416 if (logged_in_) {
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());
421 } else {
422 default_profile_dir = default_profile_dir.Append(GetInitialProfileDir());
424 } else {
425 default_profile_dir = GetDefaultProfileDir(user_data_dir);
427 #else
428 base::FilePath default_profile_dir(user_data_dir);
429 default_profile_dir = default_profile_dir.Append(GetInitialProfileDir());
430 #endif
431 #if defined(OS_CHROMEOS)
432 if (!logged_in_) {
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();
441 return profile;
444 ProfileInfo* profile_info = GetProfileInfoByPath(default_profile_dir);
445 // Fallback to default off-the-record profile, if user profile has not fully
446 // loaded yet.
447 if (profile_info && !profile_info->created)
448 default_profile_dir = GetDefaultProfileDir(user_data_dir);
449 #endif
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)) {
461 return true;
465 return false;
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());
475 return profiles;
478 Profile* ProfileManager::GetProfile(const base::FilePath& profile_dir) {
479 // If the profile is already loaded (e.g., chrome.exe launched twice), just
480 // return it.
481 Profile* profile = GetProfileByPath(profile_dir);
482 if (NULL != profile)
483 return profile;
485 profile = CreateProfileHelper(profile_dir);
486 DCHECK(profile);
487 if (profile) {
488 bool result = AddProfile(profile);
489 DCHECK(result);
491 return profile;
494 void ProfileManager::CreateProfileAsync(
495 const base::FilePath& profile_path,
496 const CreateCallback& callback,
497 const string16& name,
498 const string16& icon_url,
499 bool is_managed) {
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);
506 return;
509 ProfilesInfoMap::iterator iter = profiles_info_.find(profile_path);
510 if (iter != profiles_info_.end()) {
511 ProfileInfo* info = iter->second.get();
512 if (info->created) {
513 // Profile has already been created. Run callback immediately.
514 callback.Run(info->profile.get(), Profile::CREATE_STATUS_INITIALIZED);
515 } else {
516 // Profile is being created. Add callback to list.
517 info->callbacks.push_back(callback);
519 } else {
520 // Initiate asynchronous creation process.
521 ProfileInfo* info =
522 RegisterProfile(CreateProfileAsyncHelper(profile_path, this), false);
523 ProfileInfoCache& cache = GetProfileInfoCache();
524 // Get the icon index from the user's icon url
525 size_t icon_index;
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,
530 is_managed);
532 info->callbacks.push_back(callback);
534 if (is_managed) {
535 content::RecordAction(
536 UserMetricsAction("ManagedMode_LocallyManagedUserCreated"));
541 // static
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());
558 #endif
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) {
570 DCHECK(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.";
578 return false;
581 RegisterProfile(profile, true);
582 DoFinalInit(profile, ShouldGoOffTheRecord());
583 return true;
586 ProfileManager::ProfileInfo* ProfileManager::RegisterProfile(
587 Profile* profile,
588 bool created) {
589 ProfileInfo* info = new ProfileInfo(profile, created);
590 profiles_info_.insert(
591 std::make_pair(profile->GetPath(), linked_ptr<ProfileInfo>(info)));
592 return 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;
606 // static
607 void ProfileManager::FindOrCreateNewWindowForProfile(
608 Profile* profile,
609 chrome::startup::IsProcessStartup process_startup,
610 chrome::startup::IsFirstRun is_first_run,
611 chrome::HostDesktopType desktop_type,
612 bool always_create) {
613 #if defined(OS_IOS)
614 NOTREACHED();
615 #else
616 DCHECK(profile);
618 if (!always_create) {
619 Browser* browser = chrome::FindTabbedBrowser(profile, false, desktop_type);
620 if (browser) {
621 browser->window()->Activate();
622 return;
626 content::RecordAction(UserMetricsAction("NewWindow"));
627 CommandLine command_line(CommandLine::NO_PROGRAM);
628 int return_code;
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(
636 int type,
637 const content::NotificationSource& source,
638 const content::NotificationDetails& details) {
639 #if defined(OS_CHROMEOS)
640 if (type == chrome::NOTIFICATION_LOGIN_USER_CHANGED) {
641 logged_in_ = true;
643 chromeos::User* user = content::Details<chromeos::User>(details).ptr();
644 DCHECK(user);
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.";
668 return;
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_;
674 return;
676 #endif
677 bool save_active_profiles = false;
678 switch (type) {
679 case chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST: {
680 // Ignore any browsers closing from now on.
681 closing_all_browsers_ = true;
682 break;
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
688 // again.
689 closing_all_browsers_ = false;
690 save_active_profiles = true;
691 break;
693 case chrome::NOTIFICATION_BROWSER_OPENED: {
694 Browser* browser = content::Source<Browser>(source).ptr();
695 DCHECK(browser);
696 Profile* profile = browser->profile();
697 DCHECK(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;
707 break;
709 case chrome::NOTIFICATION_BROWSER_CLOSED: {
710 Browser* browser = content::Source<Browser>(source).ptr();
711 DCHECK(browser);
712 Profile* profile = browser->profile();
713 DCHECK(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_;
719 break;
721 default: {
722 NOTREACHED();
723 break;
727 if (save_active_profiles) {
728 PrefService* local_state = g_browser_process->local_state();
729 DCHECK(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
738 // list.
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));
751 // static
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() {
758 will_import_ = true;
761 void ProfileManager::OnImportFinished(Profile* profile) {
762 will_import_ = false;
763 DCHECK(profile);
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));
770 #endif
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(
790 Browser* browser) {}
792 void ProfileManager::BrowserListObserver::OnBrowserRemoved(
793 Browser* browser) {}
795 void ProfileManager::BrowserListObserver::OnBrowserSetLastActive(
796 Browser* browser) {
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_)
802 return;
804 Profile* last_active = browser->profile();
805 PrefService* local_state = g_browser_process->local_state();
806 DCHECK(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(
835 !go_off_the_record);
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());
843 #endif
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();
849 #endif
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();
859 #endif
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,
875 delegate,
876 Profile::CREATE_MODE_ASYNCHRONOUS);
879 void ProfileManager::OnProfileCreated(Profile* profile,
880 bool success,
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.
897 if (success) {
898 DoFinalInit(profile, go_off_the_record);
899 if (go_off_the_record)
900 profile = profile->GetOffTheRecordProfile();
901 info->created = true;
902 } else {
903 profile = NULL;
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();
919 DCHECK(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_;
928 #if defined(OS_WIN)
929 new_path = new_path.Append(ASCIIToUTF16(profile_name));
930 #else
931 new_path = new_path.Append(profile_name);
932 #endif
933 local_state->SetInteger(prefs::kProfilesNumCreated, ++next_directory);
934 return new_path;
937 // TODO(robertshield): ProfileManager should not be opening windows and should
938 // not have to care about HostDesktopType. See http://crbug.com/153864
939 // static
940 void ProfileManager::CreateMultiProfileAsync(
941 const string16& name,
942 const string16& icon_url,
943 const CreateCallback& callback,
944 chrome::HostDesktopType desktop_type,
945 bool is_managed) {
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,
954 desktop_type,
955 callback),
956 name,
957 icon_url,
958 is_managed);
961 // static
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) {
977 return true;
978 } else if (name_compare > 0) {
979 return false;
980 } else {
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())
1000 return;
1002 if (cache.GetIndexOfProfileWithPath(profile->GetPath()) != std::string::npos)
1003 return;
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(),
1019 profile_name,
1020 username,
1021 icon_index,
1022 is_managed);
1025 void ProfileManager::InitProfileUserPrefs(Profile* profile) {
1026 ProfileInfoCache& cache = GetProfileInfoCache();
1028 if (profile->GetPath().DirName() != cache.GetUserDataDir())
1029 return;
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) {
1038 avatar_index =
1039 cache.GetAvatarIconIndexOfProfileAtIndex(profile_cache_index);
1040 profile_name =
1041 UTF16ToUTF8(cache.GetNameOfProfileAtIndex(profile_cache_index));
1042 is_managed = cache.ProfileIsManagedAtIndex(profile_cache_index);
1043 } else if (profile->GetPath() ==
1044 GetDefaultProfileDir(cache.GetUserDataDir())) {
1045 avatar_index = 0;
1046 profile_name = l10n_util::GetStringUTF8(IDS_DEFAULT_PROFILE_NAME);
1047 } else {
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();
1066 if (!logged_in_ &&
1067 (!command_line.HasSwitch(switches::kTestType) ||
1068 command_line.HasSwitch(chromeos::switches::kLoginProfile))) {
1069 go_off_the_record = true;
1071 #endif
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();
1093 break;
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,
1109 desktop_type,
1110 CreateCallback()),
1111 string16(),
1112 string16(),
1113 false);
1114 } else {
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);
1122 if (profile) {
1123 BrowserList::CloseAllBrowsersWithProfile(profile);
1125 // Disable sync for doomed profile.
1126 if (ProfileSyncServiceFactory::GetInstance()->HasProfileSyncService(
1127 profile)) {
1128 ProfileSyncServiceFactory::GetInstance()->GetForProfile(
1129 profile)->DisableForUser();
1133 QueueProfileDirectoryForDeletion(profile_dir);
1134 cache.DeleteProfileFromCache(profile_dir);
1137 // static
1138 bool ProfileManager::IsMultipleProfilesEnabled() {
1139 #if defined(OS_ANDROID)
1140 return false;
1141 #endif
1142 #if defined(OS_CHROMEOS)
1143 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kMultiProfiles))
1144 return false;
1145 #endif
1147 return true;
1150 void ProfileManager::AutoloadProfiles() {
1151 // If running in the background is disabled for the browser, do not autoload
1152 // any profiles.
1153 PrefService* local_state = g_browser_process->local_state();
1154 if (!local_state->HasPrefPath(prefs::kBackgroundModeEnabled) ||
1155 !local_state->GetBoolean(prefs::kBackgroundModeEnabled)) {
1156 return;
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);
1178 if (add_to_cache) {
1179 InitProfileUserPrefs(profile);
1180 AddProfileToCache(profile);
1184 void ProfileManager::RunCallbacks(const std::vector<CreateCallback>& callbacks,
1185 Profile* profile,
1186 Profile::CreateStatus status) {
1187 for (size_t i = 0; i < callbacks.size(); ++i)
1188 callbacks[i].Run(profile, status);
1191 ProfileManager::ProfileInfo::ProfileInfo(
1192 Profile* profile,
1193 bool created)
1194 : profile(profile),
1195 created(created) {
1198 ProfileManager::ProfileInfo::~ProfileInfo() {
1199 ProfileDestroyer::DestroyProfileWhenAppropriate(profile.release());