| 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());
|
| -}
|
|
|