Making autoload of profiles obey the kBackgroundModeEnabled preference. That is,...
[chromium-blink-merge.git] / chrome / browser / profiles / profile_manager.cc
blobf5416451d35f5a0d0d293d66fad671ef1a1a8134
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 <set>
7 #include "chrome/browser/profiles/profile_manager.h"
9 #include "base/bind.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"
46 #if !defined(OS_IOS)
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)
56 #if defined(OS_WIN)
57 #include "base/win/metro.h"
58 #include "chrome/installer/util/browser_distribution.h"
59 #endif
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"
65 #endif
67 using content::BrowserThread;
68 using content::UserMetricsAction;
70 namespace {
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);
82 DCHECK(avatar_index);
83 const PrefService::Preference* profile_name =
84 profile->GetPrefs()->FindPreference(prefs::kProfileName);
85 DCHECK(profile_name);
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
145 // account.
146 void OnOpenWindowForNewProfile(
147 chrome::HostDesktopType desktop_type,
148 const ProfileManager::CreateCallback& callback,
149 Profile* profile,
150 Profile::CreateStatus status) {
151 if (status == Profile::CREATE_STATUS_INITIALIZED) {
153 ProfileManager::FindOrCreateNewWindowForProfile(
154 profile,
155 chrome::startup::IS_PROCESS_STARTUP,
156 chrome::startup::IS_FIRST_RUN,
157 desktop_type,
158 false);
160 if (!callback.is_null())
161 callback.Run(profile, status);
164 #if defined(OS_CHROMEOS)
165 void CheckCryptohomeIsMounted(chromeos::DBusMethodCallStatus call_status,
166 bool is_mounted) {
167 if (call_status != chromeos::DBUS_METHOD_CALL_SUCCESS) {
168 LOG(ERROR) << "IsMounted call failed.";
169 return;
171 if (!is_mounted)
172 LOG(ERROR) << "Cryptohome is not mounted.";
174 #endif
176 } // namespace
178 #if defined(ENABLE_SESSION_SERVICE)
179 // static
180 void ProfileManager::ShutdownSessionServices() {
181 ProfileManager* pm = g_browser_process->profile_manager();
182 if (!pm) // Is NULL when running unit tests.
183 return;
184 std::vector<Profile*> profiles(pm->GetLoadedProfiles());
185 for (size_t i = 0; i < profiles.size(); ++i)
186 SessionServiceFactory::ShutdownForProfile(profiles[i]);
188 #endif
190 // static
191 void ProfileManager::NukeDeletedProfilesFromDisk() {
192 for (std::vector<FilePath>::iterator it =
193 ProfilesToDelete().begin();
194 it != ProfilesToDelete().end();
195 ++it) {
196 // Delete both the profile directory and its corresponding cache.
197 FilePath cache_path;
198 chrome::GetUserCacheDirectory(*it, &cache_path);
199 file_util::Delete(*it, true);
200 file_util::Delete(cache_path, true);
202 ProfilesToDelete().clear();
205 // static
206 Profile* ProfileManager::GetDefaultProfile() {
207 ProfileManager* profile_manager = g_browser_process->profile_manager();
208 return profile_manager->GetDefaultProfile(profile_manager->user_data_dir_);
211 // static
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();
219 #endif
220 return profile;
223 // static
224 Profile* ProfileManager::GetLastUsedProfile() {
225 ProfileManager* profile_manager = g_browser_process->profile_manager();
226 return profile_manager->GetLastUsedProfile(profile_manager->user_data_dir_);
229 // static
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),
238 logged_in_(false),
239 will_import_(false),
240 profile_shortcut_manager_(NULL),
241 #if !defined(OS_ANDROID) && !defined(OS_IOS)
242 ALLOW_THIS_IN_INITIALIZER_LIST(
243 browser_list_observer_(this)),
244 #endif
245 closing_all_browsers_(false) {
246 #if defined(OS_CHROMEOS)
247 registrar_.Add(
248 this,
249 chrome::NOTIFICATION_LOGIN_USER_CHANGED,
250 content::NotificationService::AllSources());
251 #endif
252 registrar_.Add(
253 this,
254 chrome::NOTIFICATION_BROWSER_OPENED,
255 content::NotificationService::AllSources());
256 registrar_.Add(
257 this,
258 chrome::NOTIFICATION_BROWSER_CLOSED,
259 content::NotificationService::AllSources());
260 registrar_.Add(
261 this,
262 chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST,
263 content::NotificationService::AllSources());
264 registrar_.Add(
265 this,
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(
271 this));
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();
296 if (logged_in_) {
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);
301 } else {
302 // We should never be logged in with no profile dir.
303 NOTREACHED();
304 return FilePath("");
306 relative_profile_dir = relative_profile_dir.Append(profile_dir);
307 return relative_profile_dir;
309 #endif
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.
319 if (!logged_in_)
320 return GetDefaultProfile(user_data_dir);
321 #endif
323 FilePath last_used_profile_dir(user_data_dir);
324 std::string last_profile_used;
325 PrefService* local_state = g_browser_process->local_state();
326 DCHECK(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();
339 DCHECK(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);
345 if (profile_list) {
346 ListValue::const_iterator it;
347 std::string profile;
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;
351 continue;
353 to_return.push_back(GetProfile(user_data_dir.AppendASCII(profile)));
357 return to_return;
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)
364 if (!logged_in_) {
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();
373 return profile;
375 #endif
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)) {
387 return true;
391 return false;
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());
401 return profiles;
404 Profile* ProfileManager::GetProfile(const FilePath& profile_dir) {
405 // If the profile is already loaded (e.g., chrome.exe launched twice), just
406 // return it.
407 Profile* profile = GetProfileByPath(profile_dir);
408 if (NULL != profile)
409 return profile;
411 profile = CreateProfileHelper(profile_dir);
412 DCHECK(profile);
413 if (profile) {
414 bool result = AddProfile(profile);
415 DCHECK(result);
417 return 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);
431 return;
434 ProfilesInfoMap::iterator iter = profiles_info_.find(profile_path);
435 if (iter != profiles_info_.end()) {
436 ProfileInfo* info = iter->second.get();
437 if (info->created) {
438 // Profile has already been created. Run callback immediately.
439 callback.Run(info->profile.get(), Profile::CREATE_STATUS_INITIALIZED);
440 } else {
441 // Profile is being created. Add callback to list.
442 info->callbacks.push_back(callback);
444 } else {
445 // Initiate asynchronous creation process.
446 ProfileInfo* info =
447 RegisterProfile(CreateProfileAsyncHelper(profile_path, this), false);
448 ProfileInfoCache& cache = GetProfileInfoCache();
449 // Get the icon index from the user's icon url
450 size_t icon_index;
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);
460 // static
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) {
475 DCHECK(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.";
483 return false;
486 RegisterProfile(profile, true);
487 DoFinalInit(profile, ShouldGoOffTheRecord());
488 return true;
491 ProfileManager::ProfileInfo* ProfileManager::RegisterProfile(
492 Profile* profile,
493 bool created) {
494 ProfileInfo* info = new ProfileInfo(profile, created);
495 profiles_info_.insert(
496 std::make_pair(profile->GetPath(), linked_ptr<ProfileInfo>(info)));
497 return 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();
505 // static
506 void ProfileManager::FindOrCreateNewWindowForProfile(
507 Profile* profile,
508 chrome::startup::IsProcessStartup process_startup,
509 chrome::startup::IsFirstRun is_first_run,
510 chrome::HostDesktopType desktop_type,
511 bool always_create) {
512 #if defined(OS_IOS)
513 NOTREACHED();
514 #else
515 DCHECK(profile);
517 if (!always_create) {
518 Browser* browser = browser::FindTabbedBrowser(profile, false, desktop_type);
519 if (browser) {
520 browser->window()->Activate();
521 return;
525 content::RecordAction(UserMetricsAction("NewWindow"));
526 CommandLine command_line(CommandLine::NO_PROGRAM);
527 int return_code;
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(
535 int type,
536 const content::NotificationSource& source,
537 const content::NotificationDetails& details) {
538 #if defined(OS_CHROMEOS)
539 if (type == chrome::NOTIFICATION_LOGIN_USER_CHANGED) {
540 logged_in_ = true;
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.";
557 return;
559 #endif
560 bool save_active_profiles = false;
561 switch (type) {
562 case chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST: {
563 // Ignore any browsers closing from now on.
564 closing_all_browsers_ = true;
565 break;
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
571 // again.
572 closing_all_browsers_ = false;
573 save_active_profiles = true;
574 break;
576 case chrome::NOTIFICATION_BROWSER_OPENED: {
577 Browser* browser = content::Source<Browser>(source).ptr();
578 DCHECK(browser);
579 Profile* profile = browser->profile();
580 DCHECK(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;
590 break;
592 case chrome::NOTIFICATION_BROWSER_CLOSED: {
593 Browser* browser = content::Source<Browser>(source).ptr();
594 DCHECK(browser);
595 Profile* profile = browser->profile();
596 DCHECK(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_;
602 break;
604 default: {
605 NOTREACHED();
606 break;
610 if (save_active_profiles) {
611 PrefService* local_state = g_browser_process->local_state();
612 DCHECK(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
621 // list.
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() {
635 will_import_ = true;
638 void ProfileManager::OnImportFinished(Profile* profile) {
639 will_import_ = false;
640 DCHECK(profile);
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(
659 Browser* browser) {}
661 void ProfileManager::BrowserListObserver::OnBrowserRemoved(
662 Browser* browser) {}
664 void ProfileManager::BrowserListObserver::OnBrowserSetLastActive(
665 Browser* browser) {
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_)
671 return;
673 Profile* last_active = browser->profile();
674 PrefService* local_state = g_browser_process->local_state();
675 DCHECK(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(
704 !go_off_the_record);
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());
711 #endif
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();
723 #endif
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,
739 delegate,
740 Profile::CREATE_MODE_ASYNCHRONOUS);
743 void ProfileManager::OnProfileCreated(Profile* profile,
744 bool success,
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.
761 if (success) {
762 DoFinalInit(profile, go_off_the_record);
763 if (go_off_the_record)
764 profile = profile->GetOffTheRecordProfile();
765 info->created = true;
766 } else {
767 profile = NULL;
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();
783 DCHECK(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_;
792 #if defined(OS_WIN)
793 new_path = new_path.Append(ASCIIToUTF16(profile_name));
794 #else
795 new_path = new_path.Append(profile_name);
796 #endif
797 local_state->SetInteger(prefs::kProfilesNumCreated, ++next_directory);
798 return new_path;
801 // TODO(robertshield): ProfileManager should not be opening windows and should
802 // not have to care about HostDesktopType. See http://crbug.com/153864
803 // static
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,
817 desktop_type,
818 callback),
819 name,
820 icon_url);
823 // static
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) {
839 return true;
840 } else if (name_compare > 0) {
841 return false;
842 } else {
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())
862 return;
864 if (cache.GetIndexOfProfileWithPath(profile->GetPath()) != std::string::npos)
865 return;
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(),
879 profile_name,
880 username,
881 icon_index);
884 void ProfileManager::InitProfileUserPrefs(Profile* profile) {
885 ProfileInfoCache& cache = GetProfileInfoCache();
887 if (profile->GetPath().DirName() != cache.GetUserDataDir())
888 return;
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));
906 } else {
907 size_t icon_index = cache.ChooseAvatarIconIndexForNewProfile();
908 profile->GetPrefs()->SetInteger(prefs::kProfileAvatarIndex, icon_index);
909 profile->GetPrefs()->SetString(
910 prefs::kProfileName,
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();
920 if (!logged_in_ &&
921 (!command_line.HasSwitch(switches::kTestType) ||
922 command_line.HasSwitch(switches::kLoginProfile))) {
923 go_off_the_record = true;
925 #endif
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
937 // place.
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,
947 desktop_type,
948 CreateCallback()),
949 string16(),
950 string16());
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());
963 break;
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);
971 if (profile) {
972 BrowserList::CloseAllBrowsersWithProfile(profile);
974 // Disable sync for doomed profile.
975 if (ProfileSyncServiceFactory::GetInstance()->HasProfileSyncService(
976 profile)) {
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);
989 // static
990 bool ProfileManager::IsMultipleProfilesEnabled() {
991 #if defined(OS_ANDROID)
992 return false;
993 #endif
994 #if defined(OS_CHROMEOS)
995 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kMultiProfiles))
996 return false;
997 #endif
998 return !ManagedMode::IsInManagedMode();
1001 void ProfileManager::AutoloadProfiles() {
1002 // If running in the background is disabled for the browser, do not autoload
1003 // any profiles.
1004 PrefService* local_state = g_browser_process->local_state();
1005 if (!local_state->GetBoolean(prefs::kBackgroundModeEnabled))
1006 return;
1007 ProfileInfoCache& cache = GetProfileInfoCache();
1008 size_t number_of_profiles = cache.GetNumberOfProfiles();
1009 for (size_t p = 0; p < number_of_profiles; ++p) {
1010 if (cache.GetBackgroundStatusOfProfileAtIndex(p)) {
1011 // If status is true, that profile is running background apps. By calling
1012 // GetProfile, we automatically cause the profile to be loaded which will
1013 // register it with the BackgroundModeManager.
1014 GetProfile(cache.GetPathOfProfileAtIndex(p));
1017 ProfileMetrics::LogNumberOfProfiles(this,
1018 ProfileMetrics::STARTUP_PROFILE_EVENT);
1021 ProfileManagerWithoutInit::ProfileManagerWithoutInit(
1022 const FilePath& user_data_dir) : ProfileManager(user_data_dir) {
1025 void ProfileManager::RegisterTestingProfile(Profile* profile,
1026 bool add_to_cache) {
1027 RegisterProfile(profile, true);
1028 if (add_to_cache) {
1029 InitProfileUserPrefs(profile);
1030 AddProfileToCache(profile);
1034 void ProfileManager::RunCallbacks(const std::vector<CreateCallback>& callbacks,
1035 Profile* profile,
1036 Profile::CreateStatus status) {
1037 for (size_t i = 0; i < callbacks.size(); ++i)
1038 callbacks[i].Run(profile, status);
1041 ProfileManager::ProfileInfo::ProfileInfo(
1042 Profile* profile,
1043 bool created)
1044 : profile(profile),
1045 created(created) {
1048 ProfileManager::ProfileInfo::~ProfileInfo() {
1049 ProfileDestroyer::DestroyProfileWhenAppropriate(profile.release());