Index: chrome/browser/profiles/profile_manager.cc |
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc |
index c1494e8ecd036b51f6b7ca9dff65fe76de731150..b1ce3f7ad7a7a578f5bd6751cfa4b4efe9bcb30d 100644 |
--- a/chrome/browser/profiles/profile_manager.cc |
+++ b/chrome/browser/profiles/profile_manager.cc |
@@ -190,6 +190,48 @@ void CheckCryptohomeIsMounted(chromeos::DBusMethodCallStatus call_status, |
} // namespace |
+ProfileManager::ProfileManager(const base::FilePath& user_data_dir) |
+ : user_data_dir_(user_data_dir), |
+ logged_in_(false), |
+#if !defined(OS_ANDROID) && !defined(OS_IOS) |
+ browser_list_observer_(this), |
+#endif |
+ closing_all_browsers_(false) { |
+#if defined(OS_CHROMEOS) |
+ registrar_.Add( |
+ this, |
+ chrome::NOTIFICATION_LOGIN_USER_CHANGED, |
+ content::NotificationService::AllSources()); |
+#endif |
+ registrar_.Add( |
+ this, |
+ chrome::NOTIFICATION_BROWSER_OPENED, |
+ content::NotificationService::AllSources()); |
+ registrar_.Add( |
+ this, |
+ chrome::NOTIFICATION_BROWSER_CLOSED, |
+ content::NotificationService::AllSources()); |
+ registrar_.Add( |
+ this, |
+ chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST, |
+ content::NotificationService::AllSources()); |
+ registrar_.Add( |
+ this, |
+ chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, |
+ content::NotificationService::AllSources()); |
+ registrar_.Add( |
+ this, |
+ chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED, |
+ content::NotificationService::AllSources()); |
+ |
+ if (ProfileShortcutManager::IsFeatureEnabled() && !user_data_dir_.empty()) |
+ profile_shortcut_manager_.reset(ProfileShortcutManager::Create( |
+ this)); |
+} |
+ |
+ProfileManager::~ProfileManager() { |
+} |
+ |
#if defined(ENABLE_SESSION_SERVICE) |
// static |
void ProfileManager::ShutdownSessionServices() { |
@@ -214,14 +256,6 @@ void ProfileManager::NukeDeletedProfilesFromDisk() { |
} |
// static |
-// TODO(skuhne): Remove this method once all clients are migrated. |
-Profile* ProfileManager::GetDefaultProfile() { |
- ProfileManager* profile_manager = g_browser_process->profile_manager(); |
- return profile_manager->GetActiveUserOrOffTheRecordProfileFromPath( |
- profile_manager->user_data_dir_); |
-} |
- |
-// static |
Profile* ProfileManager::GetLastUsedProfile() { |
ProfileManager* profile_manager = g_browser_process->profile_manager(); |
return profile_manager->GetLastUsedProfile(profile_manager->user_data_dir_); |
@@ -244,47 +278,133 @@ std::vector<Profile*> ProfileManager::GetLastOpenedProfiles() { |
profile_manager->user_data_dir_); |
} |
-ProfileManager::ProfileManager(const base::FilePath& user_data_dir) |
- : user_data_dir_(user_data_dir), |
- logged_in_(false), |
- |
-#if !defined(OS_ANDROID) && !defined(OS_IOS) |
- browser_list_observer_(this), |
+// static |
+Profile* ProfileManager::GetPrimaryUserProfile() { |
+ ProfileManager* profile_manager = g_browser_process->profile_manager(); |
+#if defined(OS_CHROMEOS) |
+ if (!profile_manager->IsLoggedIn() || !chromeos::UserManager::IsInitialized()) |
+ return profile_manager->GetActiveUserOrOffTheRecordProfileFromPath( |
+ profile_manager->user_data_dir()); |
+ chromeos::UserManager* manager = chromeos::UserManager::Get(); |
+ // Note: The user manager will take care of guest profiles. |
+ return manager->GetProfileByUser(manager->GetPrimaryUser()); |
+#else |
+ return profile_manager->GetActiveUserOrOffTheRecordProfileFromPath( |
+ profile_manager->user_data_dir()); |
#endif |
- closing_all_browsers_(false) { |
+} |
+ |
+// static |
+Profile* ProfileManager::GetActiveUserProfile() { |
+ ProfileManager* profile_manager = g_browser_process->profile_manager(); |
#if defined(OS_CHROMEOS) |
- registrar_.Add( |
- this, |
- chrome::NOTIFICATION_LOGIN_USER_CHANGED, |
- content::NotificationService::AllSources()); |
+ if (!chromeos::UserManager::IsMultipleProfilesAllowed() || |
+ !profile_manager->IsLoggedIn() || |
+ !chromeos::UserManager::IsInitialized()) |
+ return profile_manager->GetActiveUserOrOffTheRecordProfileFromPath( |
+ profile_manager->user_data_dir()); |
+ chromeos::UserManager* manager = chromeos::UserManager::Get(); |
+ // Note: The user manager will take care of guest profiles. |
+ return manager->GetProfileByUser(manager->GetActiveUser()); |
+#else |
+ return profile_manager->GetActiveUserOrOffTheRecordProfileFromPath( |
+ profile_manager->user_data_dir()); |
#endif |
- registrar_.Add( |
- this, |
- chrome::NOTIFICATION_BROWSER_OPENED, |
- content::NotificationService::AllSources()); |
- registrar_.Add( |
- this, |
- chrome::NOTIFICATION_BROWSER_CLOSED, |
- content::NotificationService::AllSources()); |
- registrar_.Add( |
- this, |
- chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST, |
- content::NotificationService::AllSources()); |
- registrar_.Add( |
- this, |
- chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, |
- content::NotificationService::AllSources()); |
- registrar_.Add( |
- this, |
- chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED, |
- content::NotificationService::AllSources()); |
+} |
- if (ProfileShortcutManager::IsFeatureEnabled() && !user_data_dir_.empty()) |
- profile_shortcut_manager_.reset(ProfileShortcutManager::Create( |
- this)); |
+Profile* ProfileManager::GetProfile(const base::FilePath& profile_dir) { |
+ TRACE_EVENT0("browser", "ProfileManager::GetProfile") |
+ // If the profile is already loaded (e.g., chrome.exe launched twice), just |
+ // return it. |
+ Profile* profile = GetProfileByPath(profile_dir); |
+ if (NULL != profile) |
+ return profile; |
+ |
+ profile = CreateProfileHelper(profile_dir); |
+ DCHECK(profile); |
+ if (profile) { |
+ bool result = AddProfile(profile); |
+ DCHECK(result); |
+ } |
+ return profile; |
} |
-ProfileManager::~ProfileManager() { |
+size_t ProfileManager::GetNumberOfProfiles() { |
+ return GetProfileInfoCache().GetNumberOfProfiles(); |
+} |
+ |
+void ProfileManager::CreateProfileAsync( |
+ const base::FilePath& profile_path, |
+ const CreateCallback& callback, |
+ const base::string16& name, |
+ const base::string16& icon_url, |
+ const std::string& managed_user_id) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ |
+ // Make sure that this profile is not pending deletion. |
+ if (IsProfileMarkedForDeletion(profile_path)) { |
+ if (!callback.is_null()) |
+ callback.Run(NULL, Profile::CREATE_STATUS_LOCAL_FAIL); |
+ return; |
+ } |
+ |
+ // Create the profile if needed and collect its ProfileInfo. |
+ ProfilesInfoMap::iterator iter = profiles_info_.find(profile_path); |
+ ProfileInfo* info = NULL; |
+ |
+ if (iter != profiles_info_.end()) { |
+ info = iter->second.get(); |
+ } else { |
+ // Initiate asynchronous creation process. |
+ info = RegisterProfile(CreateProfileAsyncHelper(profile_path, this), false); |
+ ProfileInfoCache& cache = GetProfileInfoCache(); |
+ // Get the icon index from the user's icon url |
+ size_t icon_index; |
+ std::string icon_url_std = UTF16ToASCII(icon_url); |
+ if (cache.IsDefaultAvatarIconUrl(icon_url_std, &icon_index)) { |
+ // add profile to cache with user selected name and avatar |
+ cache.AddProfileToCache(profile_path, name, base::string16(), icon_index, |
+ managed_user_id); |
+ } |
+ |
+ if (!managed_user_id.empty()) { |
+ content::RecordAction( |
+ UserMetricsAction("ManagedMode_LocallyManagedUserCreated")); |
+ } |
+ |
+ ProfileMetrics::UpdateReportedProfilesStatistics(this); |
+ } |
+ |
+ // Call or enqueue the callback. |
+ if (!callback.is_null()) { |
+ if (iter != profiles_info_.end() && info->created) { |
+ Profile* profile = info->profile.get(); |
+ // If this was the guest profile, apply settings. |
+ if (profile->GetPath() == ProfileManager::GetGuestProfilePath()) |
+ SetGuestProfilePrefs(profile); |
+ // Profile has already been created. Run callback immediately. |
+ callback.Run(profile, Profile::CREATE_STATUS_INITIALIZED); |
+ } else { |
+ // Profile is either already in the process of being created, or new. |
+ // Add callback to the list. |
+ info->callbacks.push_back(callback); |
+ } |
+ } |
+} |
+ |
+bool ProfileManager::IsValidProfile(Profile* profile) { |
+ for (ProfilesInfoMap::iterator iter = profiles_info_.begin(); |
+ iter != profiles_info_.end(); ++iter) { |
+ if (iter->second->created) { |
+ Profile* candidate = iter->second->profile.get(); |
+ if (candidate == profile || |
+ (candidate->HasOffTheRecordProfile() && |
+ candidate->GetOffTheRecordProfile() == profile)) { |
+ return true; |
+ } |
+ } |
+ } |
+ return false; |
} |
base::FilePath ProfileManager::GetInitialProfileDir() { |
@@ -397,49 +517,6 @@ std::vector<Profile*> ProfileManager::GetLastOpenedProfiles( |
return to_return; |
} |
-Profile* ProfileManager::GetPrimaryUserProfile() { |
-#if defined(OS_CHROMEOS) |
- ProfileManager* profile_manager = g_browser_process->profile_manager(); |
- if (!profile_manager->IsLoggedIn() || !chromeos::UserManager::IsInitialized()) |
- return GetDefaultProfile(); |
- chromeos::UserManager* manager = chromeos::UserManager::Get(); |
- // Note: The user manager will take care of guest profiles. |
- return manager->GetProfileByUser(manager->GetPrimaryUser()); |
-#else |
- return GetDefaultProfile(); |
-#endif |
-} |
- |
-Profile* ProfileManager::GetActiveUserProfile() { |
-#if defined(OS_CHROMEOS) |
- ProfileManager* profile_manager = g_browser_process->profile_manager(); |
- if (!chromeos::UserManager::IsMultipleProfilesAllowed() || |
- !profile_manager->IsLoggedIn() || |
- !chromeos::UserManager::IsInitialized()) |
- return GetDefaultProfile(); |
- chromeos::UserManager* manager = chromeos::UserManager::Get(); |
- // Note: The user manager will take care of guest profiles. |
- return manager->GetProfileByUser(manager->GetActiveUser()); |
-#else |
- return GetDefaultProfile(); |
-#endif |
-} |
- |
-bool ProfileManager::IsValidProfile(Profile* profile) { |
- for (ProfilesInfoMap::iterator iter = profiles_info_.begin(); |
- iter != profiles_info_.end(); ++iter) { |
- if (iter->second->created) { |
- Profile* candidate = iter->second->profile.get(); |
- if (candidate == profile || |
- (candidate->HasOffTheRecordProfile() && |
- candidate->GetOffTheRecordProfile() == profile)) { |
- return true; |
- } |
- } |
- } |
- return false; |
-} |
- |
std::vector<Profile*> ProfileManager::GetLoadedProfiles() const { |
std::vector<Profile*> profiles; |
for (ProfilesInfoMap::const_iterator iter = profiles_info_.begin(); |
@@ -450,155 +527,232 @@ std::vector<Profile*> ProfileManager::GetLoadedProfiles() const { |
return profiles; |
} |
-Profile* ProfileManager::GetProfile(const base::FilePath& profile_dir) { |
- TRACE_EVENT0("browser", "ProfileManager::GetProfile") |
- // If the profile is already loaded (e.g., chrome.exe launched twice), just |
- // return it. |
- Profile* profile = GetProfileByPath(profile_dir); |
- if (NULL != profile) |
- return profile; |
- |
- profile = CreateProfileHelper(profile_dir); |
- DCHECK(profile); |
- if (profile) { |
- bool result = AddProfile(profile); |
- DCHECK(result); |
- } |
- return profile; |
+Profile* ProfileManager::GetProfileByPath(const base::FilePath& path) const { |
+ ProfileInfo* profile_info = GetProfileInfoByPath(path); |
+ return profile_info ? profile_info->profile.get() : NULL; |
} |
-void ProfileManager::CreateProfileAsync( |
- const base::FilePath& profile_path, |
- const CreateCallback& callback, |
+// static |
+base::FilePath ProfileManager::CreateMultiProfileAsync( |
const base::string16& name, |
const base::string16& icon_url, |
+ const CreateCallback& callback, |
const std::string& managed_user_id) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- // Make sure that this profile is not pending deletion. |
- if (IsProfileMarkedForDeletion(profile_path)) { |
- if (!callback.is_null()) |
- callback.Run(NULL, Profile::CREATE_STATUS_LOCAL_FAIL); |
- return; |
- } |
+ ProfileManager* profile_manager = g_browser_process->profile_manager(); |
- // Create the profile if needed and collect its ProfileInfo. |
- ProfilesInfoMap::iterator iter = profiles_info_.find(profile_path); |
- ProfileInfo* info = NULL; |
+ base::FilePath new_path = profile_manager->GenerateNextProfileDirectoryPath(); |
- if (iter != profiles_info_.end()) { |
- info = iter->second.get(); |
- } else { |
- // Initiate asynchronous creation process. |
- info = RegisterProfile(CreateProfileAsyncHelper(profile_path, this), false); |
- ProfileInfoCache& cache = GetProfileInfoCache(); |
- // Get the icon index from the user's icon url |
- size_t icon_index; |
- std::string icon_url_std = UTF16ToASCII(icon_url); |
- if (cache.IsDefaultAvatarIconUrl(icon_url_std, &icon_index)) { |
- // add profile to cache with user selected name and avatar |
- cache.AddProfileToCache(profile_path, name, base::string16(), icon_index, |
- managed_user_id); |
- } |
+ profile_manager->CreateProfileAsync(new_path, |
+ callback, |
+ name, |
+ icon_url, |
+ managed_user_id); |
+ return new_path; |
+} |
- if (!managed_user_id.empty()) { |
- content::RecordAction( |
- UserMetricsAction("ManagedMode_LocallyManagedUserCreated")); |
- } |
+// static |
+base::FilePath ProfileManager::GetGuestProfilePath() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- ProfileMetrics::UpdateReportedProfilesStatistics(this); |
+ ProfileManager* profile_manager = g_browser_process->profile_manager(); |
+ |
+ base::FilePath guest_path = profile_manager->user_data_dir(); |
+ return guest_path.Append(chrome::kGuestProfileDir); |
+} |
+ |
+base::FilePath ProfileManager::GenerateNextProfileDirectoryPath() { |
+ PrefService* local_state = g_browser_process->local_state(); |
+ DCHECK(local_state); |
+ |
+ DCHECK(profiles::IsMultipleProfilesEnabled()); |
+ |
+ // Create the next profile in the next available directory slot. |
+ int next_directory = local_state->GetInteger(prefs::kProfilesNumCreated); |
+ std::string profile_name = chrome::kMultiProfileDirPrefix; |
+ profile_name.append(base::IntToString(next_directory)); |
+ base::FilePath new_path = user_data_dir_; |
+#if defined(OS_WIN) |
+ new_path = new_path.Append(base::ASCIIToUTF16(profile_name)); |
+#else |
+ new_path = new_path.Append(profile_name); |
+#endif |
+ local_state->SetInteger(prefs::kProfilesNumCreated, ++next_directory); |
+ return new_path; |
+} |
+ |
+ProfileInfoCache& ProfileManager::GetProfileInfoCache() { |
+ if (!profile_info_cache_) { |
+ profile_info_cache_.reset(new ProfileInfoCache( |
+ g_browser_process->local_state(), user_data_dir_)); |
} |
+ return *profile_info_cache_.get(); |
+} |
- // Call or enqueue the callback. |
- if (!callback.is_null()) { |
- if (iter != profiles_info_.end() && info->created) { |
- Profile* profile = info->profile.get(); |
- // If this was the guest profile, apply settings. |
- if (profile->GetPath() == ProfileManager::GetGuestProfilePath()) |
- SetGuestProfilePrefs(profile); |
- // Profile has already been created. Run callback immediately. |
- callback.Run(profile, Profile::CREATE_STATUS_INITIALIZED); |
+ProfileShortcutManager* ProfileManager::profile_shortcut_manager() { |
+ return profile_shortcut_manager_.get(); |
+} |
+ |
+void ProfileManager::ScheduleProfileForDeletion( |
+ const base::FilePath& profile_dir, |
+ const CreateCallback& callback) { |
+ DCHECK(profiles::IsMultipleProfilesEnabled()); |
+ PrefService* local_state = g_browser_process->local_state(); |
+ ProfileInfoCache& cache = GetProfileInfoCache(); |
+ |
+ if (profile_dir.BaseName().MaybeAsASCII() == |
+ local_state->GetString(prefs::kProfileLastUsed)) { |
+ // Update the last used profile pref before closing browser windows. This |
+ // way the correct last used profile is set for any notification observers. |
+ base::FilePath last_non_managed_profile_path; |
+ for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) { |
+ base::FilePath cur_path = cache.GetPathOfProfileAtIndex(i); |
+ // Make sure that this profile is not pending deletion. |
+ if (cur_path != profile_dir && !cache.ProfileIsManagedAtIndex(i) && |
+ !IsProfileMarkedForDeletion(cur_path)) { |
+ last_non_managed_profile_path = cur_path; |
+ break; |
+ } |
+ } |
+ |
+ // If we're deleting the last (non-managed) profile, then create a new |
+ // profile in its place. |
+ const std::string last_non_managed_profile = |
+ last_non_managed_profile_path.BaseName().MaybeAsASCII(); |
+ if (last_non_managed_profile.empty()) { |
+ base::FilePath new_path = GenerateNextProfileDirectoryPath(); |
+ // Make sure the last used profile path is pointing at it. This way the |
+ // correct last used profile is set for any notification observers. |
+ local_state->SetString(prefs::kProfileLastUsed, |
+ new_path.BaseName().MaybeAsASCII()); |
+ CreateProfileAsync(new_path, |
+ callback, |
+ base::string16(), |
+ base::string16(), |
+ std::string()); |
} else { |
- // Profile is either already in the process of being created, or new. |
- // Add callback to the list. |
- info->callbacks.push_back(callback); |
+ // On the Mac, the browser process is not killed when all browser windows |
+ // are closed, so just in case we are deleting the active profile, and no |
+ // other profile has been loaded, we must pre-load a next one. |
+#if defined(OS_MACOSX) |
+ CreateProfileAsync(last_non_managed_profile_path, |
+ base::Bind(&ProfileManager::OnNewActiveProfileLoaded, |
+ base::Unretained(this), |
+ profile_dir, |
+ last_non_managed_profile_path, |
+ callback), |
+ base::string16(), |
+ base::string16(), |
+ std::string()); |
+ return; |
+#else |
+ // For OS_MACOSX the pref is updated in the callback to make sure that |
+ // it isn't used before the profile is actually loaded. |
+ local_state->SetString(prefs::kProfileLastUsed, last_non_managed_profile); |
+#endif |
} |
} |
+ FinishDeletingProfile(profile_dir); |
} |
-Profile* ProfileManager::GetActiveUserOrOffTheRecordProfileFromPath( |
- const base::FilePath& user_data_dir) { |
-#if defined(OS_CHROMEOS) |
- base::FilePath default_profile_dir(user_data_dir); |
- if (!logged_in_) { |
- default_profile_dir = profiles::GetDefaultProfileDir(user_data_dir); |
- Profile* profile = GetProfile(default_profile_dir); |
- // For cros, return the OTR profile so we never accidentally keep |
- // user data in an unencrypted profile. But doing this makes |
- // many of the browser and ui tests fail. We do return the OTR profile |
- // if the login-profile switch is passed so that we can test this. |
- if (ShouldGoOffTheRecord(profile)) |
- return profile->GetOffTheRecordProfile(); |
- DCHECK(!chromeos::UserManager::Get()->IsLoggedInAsGuest()); |
- return profile; |
+// static |
+void ProfileManager::CleanUpStaleProfiles( |
+ const std::vector<base::FilePath>& profile_paths) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
+ |
+ for (std::vector<base::FilePath>::const_iterator it = profile_paths.begin(); |
+ it != profile_paths.end(); ++it) { |
+ NukeProfileFromDisk(*it); |
} |
+} |
- default_profile_dir = default_profile_dir.Append(GetInitialProfileDir()); |
- ProfileInfo* profile_info = GetProfileInfoByPath(default_profile_dir); |
- // Fallback to default off-the-record profile, if user profile has not fully |
- // loaded yet. |
- if (profile_info && !profile_info->created) |
- default_profile_dir = profiles::GetDefaultProfileDir(user_data_dir); |
+void ProfileManager::AutoloadProfiles() { |
+ // If running in the background is disabled for the browser, do not autoload |
+ // any profiles. |
+ PrefService* local_state = g_browser_process->local_state(); |
+ if (!local_state->HasPrefPath(prefs::kBackgroundModeEnabled) || |
+ !local_state->GetBoolean(prefs::kBackgroundModeEnabled)) { |
+ return; |
+ } |
- Profile* profile = GetProfile(default_profile_dir); |
- // Some unit tests didn't initialize the UserManager. |
- if (chromeos::UserManager::IsInitialized() && |
- chromeos::UserManager::Get()->IsLoggedInAsGuest()) |
- return profile->GetOffTheRecordProfile(); |
- return profile; |
-#else |
- base::FilePath default_profile_dir(user_data_dir); |
- default_profile_dir = default_profile_dir.Append(GetInitialProfileDir()); |
- return GetProfile(default_profile_dir); |
-#endif |
+ ProfileInfoCache& cache = GetProfileInfoCache(); |
+ size_t number_of_profiles = cache.GetNumberOfProfiles(); |
+ for (size_t p = 0; p < number_of_profiles; ++p) { |
+ if (cache.GetBackgroundStatusOfProfileAtIndex(p)) { |
+ // If status is true, that profile is running background apps. By calling |
+ // GetProfile, we automatically cause the profile to be loaded which will |
+ // register it with the BackgroundModeManager. |
+ GetProfile(cache.GetPathOfProfileAtIndex(p)); |
+ } |
+ } |
} |
-bool ProfileManager::AddProfile(Profile* profile) { |
- DCHECK(profile); |
+void ProfileManager::InitProfileUserPrefs(Profile* profile) { |
+ ProfileInfoCache& cache = GetProfileInfoCache(); |
- // Make sure that we're not loading a profile with the same ID as a profile |
- // that's already loaded. |
- if (GetProfileByPath(profile->GetPath())) { |
- NOTREACHED() << "Attempted to add profile with the same path (" << |
- profile->GetPath().value() << |
- ") as an already-loaded profile."; |
- return false; |
+ if (profile->GetPath().DirName() != cache.GetUserDataDir()) |
+ return; |
+ |
+ size_t avatar_index; |
+ std::string profile_name; |
+ std::string managed_user_id; |
+ if (profile->IsGuestSession()) { |
+ profile_name = l10n_util::GetStringUTF8(IDS_PROFILES_GUEST_PROFILE_NAME); |
+ avatar_index = 0; |
+ } else { |
+ size_t profile_cache_index = |
+ cache.GetIndexOfProfileWithPath(profile->GetPath()); |
+ // If the cache has an entry for this profile, use the cache data. |
+ if (profile_cache_index != std::string::npos) { |
+ avatar_index = |
+ cache.GetAvatarIconIndexOfProfileAtIndex(profile_cache_index); |
+ profile_name = |
+ base::UTF16ToUTF8(cache.GetNameOfProfileAtIndex(profile_cache_index)); |
+ managed_user_id = |
+ cache.GetManagedUserIdOfProfileAtIndex(profile_cache_index); |
+ } else if (profile->GetPath() == |
+ profiles::GetDefaultProfileDir(cache.GetUserDataDir())) { |
+ avatar_index = 0; |
+ profile_name = l10n_util::GetStringUTF8(IDS_DEFAULT_PROFILE_NAME); |
+ } else { |
+ avatar_index = cache.ChooseAvatarIconIndexForNewProfile(); |
+ profile_name = |
+ base::UTF16ToUTF8(cache.ChooseNameForNewProfile(avatar_index)); |
+ } |
} |
- RegisterProfile(profile, true); |
- InitProfileUserPrefs(profile); |
- DoFinalInit(profile, ShouldGoOffTheRecord(profile)); |
- return true; |
-} |
+ if (!profile->GetPrefs()->HasPrefPath(prefs::kProfileAvatarIndex)) |
+ profile->GetPrefs()->SetInteger(prefs::kProfileAvatarIndex, avatar_index); |
-ProfileManager::ProfileInfo* ProfileManager::RegisterProfile( |
- Profile* profile, |
- bool created) { |
- ProfileInfo* info = new ProfileInfo(profile, created); |
- profiles_info_.insert( |
- std::make_pair(profile->GetPath(), linked_ptr<ProfileInfo>(info))); |
- return info; |
-} |
+ if (!profile->GetPrefs()->HasPrefPath(prefs::kProfileName)) |
+ profile->GetPrefs()->SetString(prefs::kProfileName, profile_name); |
-ProfileManager::ProfileInfo* ProfileManager::GetProfileInfoByPath( |
- const base::FilePath& path) const { |
- ProfilesInfoMap::const_iterator iter = profiles_info_.find(path); |
- return (iter == profiles_info_.end()) ? NULL : iter->second.get(); |
+ CommandLine* command_line = CommandLine::ForCurrentProcess(); |
+ bool force_managed_user_id = |
+ command_line->HasSwitch(switches::kManagedUserId); |
+ if (force_managed_user_id) { |
+ managed_user_id = |
+ command_line->GetSwitchValueASCII(switches::kManagedUserId); |
+ } |
+ if (force_managed_user_id || |
+ !profile->GetPrefs()->HasPrefPath(prefs::kManagedUserId)) { |
+ profile->GetPrefs()->SetString(prefs::kManagedUserId, managed_user_id); |
+ } |
} |
-Profile* ProfileManager::GetProfileByPath(const base::FilePath& path) const { |
- ProfileInfo* profile_info = GetProfileInfoByPath(path); |
- return profile_info ? profile_info->profile.get() : NULL; |
+void ProfileManager::RegisterTestingProfile(Profile* profile, |
+ bool add_to_cache, |
+ bool start_deferred_task_runners) { |
+ RegisterProfile(profile, true); |
+ if (add_to_cache) { |
+ InitProfileUserPrefs(profile); |
+ AddProfileToCache(profile); |
+ } |
+ if (start_deferred_task_runners) { |
+ StartupTaskRunnerServiceFactory::GetForProfile(profile)-> |
+ StartDeferredTaskRunners(); |
+ } |
} |
void ProfileManager::Observe( |
@@ -711,65 +865,49 @@ void ProfileManager::Observe( |
} |
} |
-#if !defined(OS_ANDROID) && !defined(OS_IOS) |
-ProfileManager::BrowserListObserver::BrowserListObserver( |
- ProfileManager* manager) |
- : profile_manager_(manager) { |
- BrowserList::AddObserver(this); |
-} |
+void ProfileManager::OnProfileCreated(Profile* profile, |
+ bool success, |
+ bool is_new_profile) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
-ProfileManager::BrowserListObserver::~BrowserListObserver() { |
- BrowserList::RemoveObserver(this); |
-} |
+ ProfilesInfoMap::iterator iter = profiles_info_.find(profile->GetPath()); |
+ DCHECK(iter != profiles_info_.end()); |
+ ProfileInfo* info = iter->second.get(); |
-void ProfileManager::BrowserListObserver::OnBrowserAdded( |
- Browser* browser) {} |
+ std::vector<CreateCallback> callbacks; |
+ info->callbacks.swap(callbacks); |
-void ProfileManager::BrowserListObserver::OnBrowserRemoved( |
- Browser* browser) { |
- Profile* profile = browser->profile(); |
- for (chrome::BrowserIterator it; !it.done(); it.Next()) { |
- if (it->profile()->GetOriginalProfile() == profile->GetOriginalProfile()) |
- // Not the last window for this profile. |
- return; |
- } |
+ // Invoke CREATED callback for normal profiles. |
+ bool go_off_the_record = ShouldGoOffTheRecord(profile); |
+ if (success && !go_off_the_record) |
+ RunCallbacks(callbacks, profile, Profile::CREATE_STATUS_CREATED); |
- // If the last browser of a profile that is scheduled for deletion is closed |
- // do that now. |
- base::FilePath path = profile->GetPath(); |
- if (profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles) && |
- !IsProfileMarkedForDeletion(path)) { |
- g_browser_process->profile_manager()->ScheduleProfileForDeletion( |
- path, ProfileManager::CreateCallback()); |
+ // Perform initialization. |
+ if (success) { |
+ DoFinalInit(profile, go_off_the_record); |
+ if (go_off_the_record) |
+ profile = profile->GetOffTheRecordProfile(); |
+ info->created = true; |
+ } else { |
+ profile = NULL; |
+ profiles_info_.erase(iter); |
} |
-} |
- |
-void ProfileManager::BrowserListObserver::OnBrowserSetLastActive( |
- Browser* browser) { |
- // If all browsers are being closed (e.g. the user is in the process of |
- // shutting down), this event will be fired after each browser is |
- // closed. This does not represent a user intention to change the active |
- // browser so is not handled here. |
- if (profile_manager_->closing_all_browsers_) |
- return; |
- |
- Profile* last_active = browser->profile(); |
- // Don't remember ephemeral profiles as last because they are not going to |
- // persist after restart. |
- if (last_active->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles)) |
- return; |
+ if (profile) { |
+ // If this was the guest profile, finish setting its incognito status. |
+ if (profile->GetPath() == ProfileManager::GetGuestProfilePath()) |
+ SetGuestProfilePrefs(profile); |
- PrefService* local_state = g_browser_process->local_state(); |
- DCHECK(local_state); |
- // Only keep track of profiles that we are managing; tests may create others. |
- if (profile_manager_->profiles_info_.find( |
- last_active->GetPath()) != profile_manager_->profiles_info_.end()) { |
- local_state->SetString(prefs::kProfileLastUsed, |
- last_active->GetPath().BaseName().MaybeAsASCII()); |
+ // Invoke CREATED callback for incognito profiles. |
+ if (go_off_the_record) |
+ RunCallbacks(callbacks, profile, Profile::CREATE_STATUS_CREATED); |
} |
+ |
+ // Invoke INITIALIZED or FAIL for all profiles. |
+ RunCallbacks(callbacks, profile, |
+ profile ? Profile::CREATE_STATUS_INITIALIZED : |
+ Profile::CREATE_STATUS_LOCAL_FAIL); |
} |
-#endif // !defined(OS_ANDROID) && !defined(OS_IOS) |
void ProfileManager::DoFinalInit(Profile* profile, bool go_off_the_record) { |
DoFinalInitForServices(profile, go_off_the_record); |
@@ -836,215 +974,131 @@ Profile* ProfileManager::CreateProfileAsyncHelper(const base::FilePath& path, |
Profile::CREATE_MODE_ASYNCHRONOUS); |
} |
-void ProfileManager::OnProfileCreated(Profile* profile, |
- bool success, |
- bool is_new_profile) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- ProfilesInfoMap::iterator iter = profiles_info_.find(profile->GetPath()); |
- DCHECK(iter != profiles_info_.end()); |
- ProfileInfo* info = iter->second.get(); |
- |
- std::vector<CreateCallback> callbacks; |
- info->callbacks.swap(callbacks); |
- |
- // Invoke CREATED callback for normal profiles. |
- bool go_off_the_record = ShouldGoOffTheRecord(profile); |
- if (success && !go_off_the_record) |
- RunCallbacks(callbacks, profile, Profile::CREATE_STATUS_CREATED); |
- |
- // Perform initialization. |
- if (success) { |
- DoFinalInit(profile, go_off_the_record); |
- if (go_off_the_record) |
- profile = profile->GetOffTheRecordProfile(); |
- info->created = true; |
- } else { |
- profile = NULL; |
- profiles_info_.erase(iter); |
- } |
- |
- if (profile) { |
- // If this was the guest profile, finish setting its incognito status. |
- if (profile->GetPath() == ProfileManager::GetGuestProfilePath()) |
- SetGuestProfilePrefs(profile); |
- |
- // Invoke CREATED callback for incognito profiles. |
- if (go_off_the_record) |
- RunCallbacks(callbacks, profile, Profile::CREATE_STATUS_CREATED); |
+Profile* ProfileManager::GetActiveUserOrOffTheRecordProfileFromPath( |
+ const base::FilePath& user_data_dir) { |
+#if defined(OS_CHROMEOS) |
+ base::FilePath default_profile_dir(user_data_dir); |
+ if (!logged_in_) { |
+ default_profile_dir = profiles::GetDefaultProfileDir(user_data_dir); |
+ Profile* profile = GetProfile(default_profile_dir); |
+ // For cros, return the OTR profile so we never accidentally keep |
+ // user data in an unencrypted profile. But doing this makes |
+ // many of the browser and ui tests fail. We do return the OTR profile |
+ // if the login-profile switch is passed so that we can test this. |
+ if (ShouldGoOffTheRecord(profile)) |
+ return profile->GetOffTheRecordProfile(); |
+ DCHECK(!chromeos::UserManager::Get()->IsLoggedInAsGuest()); |
+ return profile; |
} |
- // Invoke INITIALIZED or FAIL for all profiles. |
- RunCallbacks(callbacks, profile, |
- profile ? Profile::CREATE_STATUS_INITIALIZED : |
- Profile::CREATE_STATUS_LOCAL_FAIL); |
-} |
- |
-base::FilePath ProfileManager::GenerateNextProfileDirectoryPath() { |
- PrefService* local_state = g_browser_process->local_state(); |
- DCHECK(local_state); |
- |
- DCHECK(profiles::IsMultipleProfilesEnabled()); |
+ default_profile_dir = default_profile_dir.Append(GetInitialProfileDir()); |
+ ProfileInfo* profile_info = GetProfileInfoByPath(default_profile_dir); |
+ // Fallback to default off-the-record profile, if user profile has not fully |
+ // loaded yet. |
+ if (profile_info && !profile_info->created) |
+ default_profile_dir = profiles::GetDefaultProfileDir(user_data_dir); |
- // Create the next profile in the next available directory slot. |
- int next_directory = local_state->GetInteger(prefs::kProfilesNumCreated); |
- std::string profile_name = chrome::kMultiProfileDirPrefix; |
- profile_name.append(base::IntToString(next_directory)); |
- base::FilePath new_path = user_data_dir_; |
-#if defined(OS_WIN) |
- new_path = new_path.Append(base::ASCIIToUTF16(profile_name)); |
+ Profile* profile = GetProfile(default_profile_dir); |
+ // Some unit tests didn't initialize the UserManager. |
+ if (chromeos::UserManager::IsInitialized() && |
+ chromeos::UserManager::Get()->IsLoggedInAsGuest()) |
+ return profile->GetOffTheRecordProfile(); |
+ return profile; |
#else |
- new_path = new_path.Append(profile_name); |
+ base::FilePath default_profile_dir(user_data_dir); |
+ default_profile_dir = default_profile_dir.Append(GetInitialProfileDir()); |
+ return GetProfile(default_profile_dir); |
#endif |
- local_state->SetInteger(prefs::kProfilesNumCreated, ++next_directory); |
- return new_path; |
-} |
- |
-// static |
-base::FilePath ProfileManager::CreateMultiProfileAsync( |
- const base::string16& name, |
- const base::string16& icon_url, |
- const CreateCallback& callback, |
- const std::string& managed_user_id) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- ProfileManager* profile_manager = g_browser_process->profile_manager(); |
- |
- base::FilePath new_path = profile_manager->GenerateNextProfileDirectoryPath(); |
- |
- profile_manager->CreateProfileAsync(new_path, |
- callback, |
- name, |
- icon_url, |
- managed_user_id); |
- return new_path; |
-} |
- |
-// static |
-base::FilePath ProfileManager::GetGuestProfilePath() { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- ProfileManager* profile_manager = g_browser_process->profile_manager(); |
- |
- base::FilePath guest_path = profile_manager->user_data_dir(); |
- return guest_path.Append(chrome::kGuestProfileDir); |
} |
-size_t ProfileManager::GetNumberOfProfiles() { |
- return GetProfileInfoCache().GetNumberOfProfiles(); |
-} |
+bool ProfileManager::AddProfile(Profile* profile) { |
+ DCHECK(profile); |
-bool ProfileManager::CompareProfilePathAndName( |
- const ProfileManager::ProfilePathAndName& pair1, |
- const ProfileManager::ProfilePathAndName& pair2) { |
- int name_compare = pair1.second.compare(pair2.second); |
- if (name_compare < 0) { |
- return true; |
- } else if (name_compare > 0) { |
+ // Make sure that we're not loading a profile with the same ID as a profile |
+ // that's already loaded. |
+ if (GetProfileByPath(profile->GetPath())) { |
+ NOTREACHED() << "Attempted to add profile with the same path (" << |
+ profile->GetPath().value() << |
+ ") as an already-loaded profile."; |
return false; |
- } else { |
- return pair1.first < pair2.first; |
- } |
-} |
- |
-ProfileInfoCache& ProfileManager::GetProfileInfoCache() { |
- if (!profile_info_cache_) { |
- profile_info_cache_.reset(new ProfileInfoCache( |
- g_browser_process->local_state(), user_data_dir_)); |
} |
- return *profile_info_cache_.get(); |
-} |
-ProfileShortcutManager* ProfileManager::profile_shortcut_manager() { |
- return profile_shortcut_manager_.get(); |
+ RegisterProfile(profile, true); |
+ InitProfileUserPrefs(profile); |
+ DoFinalInit(profile, ShouldGoOffTheRecord(profile)); |
+ return true; |
} |
-void ProfileManager::AddProfileToCache(Profile* profile) { |
- if (profile->IsGuestSession()) |
- return; |
+void ProfileManager::FinishDeletingProfile(const base::FilePath& profile_dir) { |
ProfileInfoCache& cache = GetProfileInfoCache(); |
- if (profile->GetPath().DirName() != cache.GetUserDataDir()) |
- return; |
- |
- if (cache.GetIndexOfProfileWithPath(profile->GetPath()) != std::string::npos) |
- return; |
- |
- base::string16 username = base::UTF8ToUTF16(profile->GetPrefs()->GetString( |
- prefs::kGoogleServicesUsername)); |
- |
- // Profile name and avatar are set by InitProfileUserPrefs and stored in the |
- // profile. Use those values to setup the cache entry. |
- base::string16 profile_name = |
- base::UTF8ToUTF16(profile->GetPrefs()->GetString(prefs::kProfileName)); |
- |
- size_t icon_index = profile->GetPrefs()->GetInteger( |
- prefs::kProfileAvatarIndex); |
- |
- std::string managed_user_id = |
- profile->GetPrefs()->GetString(prefs::kManagedUserId); |
+ // TODO(sail): Due to bug 88586 we don't delete the profile instance. Once we |
+ // start deleting the profile instance we need to close background apps too. |
+ Profile* profile = GetProfileByPath(profile_dir); |
- cache.AddProfileToCache(profile->GetPath(), |
- profile_name, |
- username, |
- icon_index, |
- managed_user_id); |
+ if (profile) { |
+ BrowserList::CloseAllBrowsersWithProfile(profile); |
- if (profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles)) { |
- cache.SetProfileIsEphemeralAtIndex( |
- cache.GetIndexOfProfileWithPath(profile->GetPath()), true); |
+ // Disable sync for doomed profile. |
+ if (ProfileSyncServiceFactory::GetInstance()->HasProfileSyncService( |
+ profile)) { |
+ ProfileSyncServiceFactory::GetInstance()->GetForProfile( |
+ profile)->DisableForUser(); |
+ } |
} |
-} |
-void ProfileManager::InitProfileUserPrefs(Profile* profile) { |
- ProfileInfoCache& cache = GetProfileInfoCache(); |
+ QueueProfileDirectoryForDeletion(profile_dir); |
+ cache.DeleteProfileFromCache(profile_dir); |
+ ProfileMetrics::UpdateReportedProfilesStatistics(this); |
+} |
- if (profile->GetPath().DirName() != cache.GetUserDataDir()) |
- return; |
+ProfileManager::ProfileInfo* ProfileManager::RegisterProfile( |
+ Profile* profile, |
+ bool created) { |
+ ProfileInfo* info = new ProfileInfo(profile, created); |
+ profiles_info_.insert( |
+ std::make_pair(profile->GetPath(), linked_ptr<ProfileInfo>(info))); |
+ return info; |
+} |
- size_t avatar_index; |
- std::string profile_name; |
- std::string managed_user_id; |
- if (profile->IsGuestSession()) { |
- profile_name = l10n_util::GetStringUTF8(IDS_PROFILES_GUEST_PROFILE_NAME); |
- avatar_index = 0; |
- } else { |
- size_t profile_cache_index = |
- cache.GetIndexOfProfileWithPath(profile->GetPath()); |
- // If the cache has an entry for this profile, use the cache data. |
- if (profile_cache_index != std::string::npos) { |
- avatar_index = |
- cache.GetAvatarIconIndexOfProfileAtIndex(profile_cache_index); |
- profile_name = |
- base::UTF16ToUTF8(cache.GetNameOfProfileAtIndex(profile_cache_index)); |
- managed_user_id = |
- cache.GetManagedUserIdOfProfileAtIndex(profile_cache_index); |
- } else if (profile->GetPath() == |
- profiles::GetDefaultProfileDir(cache.GetUserDataDir())) { |
- avatar_index = 0; |
- profile_name = l10n_util::GetStringUTF8(IDS_DEFAULT_PROFILE_NAME); |
- } else { |
- avatar_index = cache.ChooseAvatarIconIndexForNewProfile(); |
- profile_name = |
- base::UTF16ToUTF8(cache.ChooseNameForNewProfile(avatar_index)); |
- } |
- } |
+ProfileManager::ProfileInfo* ProfileManager::GetProfileInfoByPath( |
+ const base::FilePath& path) const { |
+ ProfilesInfoMap::const_iterator iter = profiles_info_.find(path); |
+ return (iter == profiles_info_.end()) ? NULL : iter->second.get(); |
+} |
- if (!profile->GetPrefs()->HasPrefPath(prefs::kProfileAvatarIndex)) |
- profile->GetPrefs()->SetInteger(prefs::kProfileAvatarIndex, avatar_index); |
+void ProfileManager::AddProfileToCache(Profile* profile) { |
+ if (profile->IsGuestSession()) |
+ return; |
+ ProfileInfoCache& cache = GetProfileInfoCache(); |
+ if (profile->GetPath().DirName() != cache.GetUserDataDir()) |
+ return; |
- if (!profile->GetPrefs()->HasPrefPath(prefs::kProfileName)) |
- profile->GetPrefs()->SetString(prefs::kProfileName, profile_name); |
+ if (cache.GetIndexOfProfileWithPath(profile->GetPath()) != std::string::npos) |
+ return; |
- CommandLine* command_line = CommandLine::ForCurrentProcess(); |
- bool force_managed_user_id = |
- command_line->HasSwitch(switches::kManagedUserId); |
- if (force_managed_user_id) { |
- managed_user_id = |
- command_line->GetSwitchValueASCII(switches::kManagedUserId); |
- } |
- if (force_managed_user_id || |
- !profile->GetPrefs()->HasPrefPath(prefs::kManagedUserId)) { |
- profile->GetPrefs()->SetString(prefs::kManagedUserId, managed_user_id); |
+ base::string16 username = base::UTF8ToUTF16(profile->GetPrefs()->GetString( |
+ prefs::kGoogleServicesUsername)); |
+ |
+ // Profile name and avatar are set by InitProfileUserPrefs and stored in the |
+ // profile. Use those values to setup the cache entry. |
+ base::string16 profile_name = |
+ base::UTF8ToUTF16(profile->GetPrefs()->GetString(prefs::kProfileName)); |
+ |
+ size_t icon_index = profile->GetPrefs()->GetInteger( |
+ prefs::kProfileAvatarIndex); |
+ |
+ std::string managed_user_id = |
+ profile->GetPrefs()->GetString(prefs::kManagedUserId); |
+ |
+ cache.AddProfileToCache(profile->GetPath(), |
+ profile_name, |
+ username, |
+ icon_index, |
+ managed_user_id); |
+ |
+ if (profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles)) { |
+ cache.SetProfileIsEphemeralAtIndex( |
+ cache.GetIndexOfProfileWithPath(profile->GetPath()), true); |
} |
} |
@@ -1068,79 +1122,85 @@ bool ProfileManager::ShouldGoOffTheRecord(Profile* profile) { |
return go_off_the_record; |
} |
-void ProfileManager::ScheduleProfileForDeletion( |
- const base::FilePath& profile_dir, |
- const CreateCallback& callback) { |
- DCHECK(profiles::IsMultipleProfilesEnabled()); |
- PrefService* local_state = g_browser_process->local_state(); |
- ProfileInfoCache& cache = GetProfileInfoCache(); |
+void ProfileManager::RunCallbacks(const std::vector<CreateCallback>& callbacks, |
+ Profile* profile, |
+ Profile::CreateStatus status) { |
+ for (size_t i = 0; i < callbacks.size(); ++i) |
+ callbacks[i].Run(profile, status); |
+} |
- if (profile_dir.BaseName().MaybeAsASCII() == |
- local_state->GetString(prefs::kProfileLastUsed)) { |
- // Update the last used profile pref before closing browser windows. This |
- // way the correct last used profile is set for any notification observers. |
- base::FilePath last_non_managed_profile_path; |
- for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) { |
- base::FilePath cur_path = cache.GetPathOfProfileAtIndex(i); |
- // Make sure that this profile is not pending deletion. |
- if (cur_path != profile_dir && !cache.ProfileIsManagedAtIndex(i) && |
- !IsProfileMarkedForDeletion(cur_path)) { |
- last_non_managed_profile_path = cur_path; |
- break; |
- } |
- } |
+ProfileManager::ProfileInfo::ProfileInfo( |
+ Profile* profile, |
+ bool created) |
+ : profile(profile), |
+ created(created) { |
+} |
- // If we're deleting the last (non-managed) profile, then create a new |
- // profile in its place. |
- const std::string last_non_managed_profile = |
- last_non_managed_profile_path.BaseName().MaybeAsASCII(); |
- if (last_non_managed_profile.empty()) { |
- base::FilePath new_path = GenerateNextProfileDirectoryPath(); |
- // Make sure the last used profile path is pointing at it. This way the |
- // correct last used profile is set for any notification observers. |
- local_state->SetString(prefs::kProfileLastUsed, |
- new_path.BaseName().MaybeAsASCII()); |
- CreateProfileAsync(new_path, |
- callback, |
- base::string16(), |
- base::string16(), |
- std::string()); |
- } else { |
- // On the Mac, the browser process is not killed when all browser windows |
- // are closed, so just in case we are deleting the active profile, and no |
- // other profile has been loaded, we must pre-load a next one. |
-#if defined(OS_MACOSX) |
- CreateProfileAsync(last_non_managed_profile_path, |
- base::Bind(&ProfileManager::OnNewActiveProfileLoaded, |
- base::Unretained(this), |
- profile_dir, |
- last_non_managed_profile_path, |
- callback), |
- base::string16(), |
- base::string16(), |
- std::string()); |
+ProfileManager::ProfileInfo::~ProfileInfo() { |
+ ProfileDestroyer::DestroyProfileWhenAppropriate(profile.release()); |
+} |
+ |
+#if !defined(OS_ANDROID) && !defined(OS_IOS) |
+ProfileManager::BrowserListObserver::BrowserListObserver( |
+ ProfileManager* manager) |
+ : profile_manager_(manager) { |
+ BrowserList::AddObserver(this); |
+} |
+ |
+ProfileManager::BrowserListObserver::~BrowserListObserver() { |
+ BrowserList::RemoveObserver(this); |
+} |
+ |
+void ProfileManager::BrowserListObserver::OnBrowserAdded( |
+ Browser* browser) {} |
+ |
+void ProfileManager::BrowserListObserver::OnBrowserRemoved( |
+ Browser* browser) { |
+ Profile* profile = browser->profile(); |
+ for (chrome::BrowserIterator it; !it.done(); it.Next()) { |
+ if (it->profile()->GetOriginalProfile() == profile->GetOriginalProfile()) |
+ // Not the last window for this profile. |
return; |
-#else |
- // For OS_MACOSX the pref is updated in the callback to make sure that |
- // it isn't used before the profile is actually loaded. |
- local_state->SetString(prefs::kProfileLastUsed, last_non_managed_profile); |
-#endif |
- } |
} |
- FinishDeletingProfile(profile_dir); |
+ |
+ // If the last browser of a profile that is scheduled for deletion is closed |
+ // do that now. |
+ base::FilePath path = profile->GetPath(); |
+ if (profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles) && |
+ !IsProfileMarkedForDeletion(path)) { |
+ g_browser_process->profile_manager()->ScheduleProfileForDeletion( |
+ path, ProfileManager::CreateCallback()); |
+ } |
} |
-// static |
-void ProfileManager::CleanUpStaleProfiles( |
- const std::vector<base::FilePath>& profile_paths) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
+void ProfileManager::BrowserListObserver::OnBrowserSetLastActive( |
+ Browser* browser) { |
+ // If all browsers are being closed (e.g. the user is in the process of |
+ // shutting down), this event will be fired after each browser is |
+ // closed. This does not represent a user intention to change the active |
+ // browser so is not handled here. |
+ if (profile_manager_->closing_all_browsers_) |
+ return; |
- for (std::vector<base::FilePath>::const_iterator it = profile_paths.begin(); |
- it != profile_paths.end(); ++it) { |
- NukeProfileFromDisk(*it); |
+ Profile* last_active = browser->profile(); |
+ |
+ // Don't remember ephemeral profiles as last because they are not going to |
+ // persist after restart. |
+ if (last_active->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles)) |
+ return; |
+ |
+ PrefService* local_state = g_browser_process->local_state(); |
+ DCHECK(local_state); |
+ // Only keep track of profiles that we are managing; tests may create others. |
+ if (profile_manager_->profiles_info_.find( |
+ last_active->GetPath()) != profile_manager_->profiles_info_.end()) { |
+ local_state->SetString(prefs::kProfileLastUsed, |
+ last_active->GetPath().BaseName().MaybeAsASCII()); |
} |
} |
+#endif // !defined(OS_ANDROID) && !defined(OS_IOS) |
+#if defined(OS_MACOSX) |
void ProfileManager::OnNewActiveProfileLoaded( |
const base::FilePath& profile_to_delete_path, |
const base::FilePath& last_non_managed_profile_path, |
@@ -1166,82 +1226,8 @@ void ProfileManager::OnNewActiveProfileLoaded( |
} |
} |
} |
- |
-void ProfileManager::FinishDeletingProfile(const base::FilePath& profile_dir) { |
- ProfileInfoCache& cache = GetProfileInfoCache(); |
- // TODO(sail): Due to bug 88586 we don't delete the profile instance. Once we |
- // start deleting the profile instance we need to close background apps too. |
- Profile* profile = GetProfileByPath(profile_dir); |
- |
- if (profile) { |
- BrowserList::CloseAllBrowsersWithProfile(profile); |
- |
- // Disable sync for doomed profile. |
- if (ProfileSyncServiceFactory::GetInstance()->HasProfileSyncService( |
- profile)) { |
- ProfileSyncServiceFactory::GetInstance()->GetForProfile( |
- profile)->DisableForUser(); |
- } |
- } |
- |
- QueueProfileDirectoryForDeletion(profile_dir); |
- cache.DeleteProfileFromCache(profile_dir); |
- ProfileMetrics::UpdateReportedProfilesStatistics(this); |
-} |
- |
-void ProfileManager::AutoloadProfiles() { |
- // If running in the background is disabled for the browser, do not autoload |
- // any profiles. |
- PrefService* local_state = g_browser_process->local_state(); |
- if (!local_state->HasPrefPath(prefs::kBackgroundModeEnabled) || |
- !local_state->GetBoolean(prefs::kBackgroundModeEnabled)) { |
- return; |
- } |
- |
- ProfileInfoCache& cache = GetProfileInfoCache(); |
- size_t number_of_profiles = cache.GetNumberOfProfiles(); |
- for (size_t p = 0; p < number_of_profiles; ++p) { |
- if (cache.GetBackgroundStatusOfProfileAtIndex(p)) { |
- // If status is true, that profile is running background apps. By calling |
- // GetProfile, we automatically cause the profile to be loaded which will |
- // register it with the BackgroundModeManager. |
- GetProfile(cache.GetPathOfProfileAtIndex(p)); |
- } |
- } |
-} |
+#endif |
ProfileManagerWithoutInit::ProfileManagerWithoutInit( |
const base::FilePath& user_data_dir) : ProfileManager(user_data_dir) { |
} |
- |
-void ProfileManager::RegisterTestingProfile(Profile* profile, |
- bool add_to_cache, |
- bool start_deferred_task_runners) { |
- RegisterProfile(profile, true); |
- if (add_to_cache) { |
- InitProfileUserPrefs(profile); |
- AddProfileToCache(profile); |
- } |
- if (start_deferred_task_runners) { |
- StartupTaskRunnerServiceFactory::GetForProfile(profile)-> |
- StartDeferredTaskRunners(); |
- } |
-} |
- |
-void ProfileManager::RunCallbacks(const std::vector<CreateCallback>& callbacks, |
- Profile* profile, |
- Profile::CreateStatus status) { |
- for (size_t i = 0; i < callbacks.size(); ++i) |
- callbacks[i].Run(profile, status); |
-} |
- |
-ProfileManager::ProfileInfo::ProfileInfo( |
- Profile* profile, |
- bool created) |
- : profile(profile), |
- created(created) { |
-} |
- |
-ProfileManager::ProfileInfo::~ProfileInfo() { |
- ProfileDestroyer::DestroyProfileWhenAppropriate(profile.release()); |
-} |