diff options
author | marja@chromium.org <marja@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-10 16:10:08 +0000 |
---|---|---|
committer | marja@chromium.org <marja@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-10 16:10:08 +0000 |
commit | 2e2929bd78578081b5665fcea6d085793df2c233 (patch) | |
tree | 7b3aaf7bfaca9ad5dde7a2da2771823051f77b9d /chrome/browser/profiles | |
parent | d7760a94d03ac373592ef9952e6c20492c617283 (diff) | |
download | chromium_src-2e2929bd78578081b5665fcea6d085793df2c233.zip chromium_src-2e2929bd78578081b5665fcea6d085793df2c233.tar.gz chromium_src-2e2929bd78578081b5665fcea6d085793df2c233.tar.bz2 |
Restore all profiles which were active when restoring the last open pages.
Upon startup, all profiles which had browsers open at the last exit are restored.
This will restore the last open pages if the profile settings so dictate.
BUG=99088
TEST=see bug & ProfileManagerTest.LastActiveProfiles(AtShutdown)?, BrowserInitTest.StartupURLsForTwoProfiles
Review URL: http://codereview.chromium.org/9087009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@117033 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/profiles')
-rw-r--r-- | chrome/browser/profiles/profile_manager.cc | 103 | ||||
-rw-r--r-- | chrome/browser/profiles/profile_manager.h | 22 | ||||
-rw-r--r-- | chrome/browser/profiles/profile_manager_unittest.cc | 110 |
3 files changed, 229 insertions, 6 deletions
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc index b1943b6..f621be6 100644 --- a/chrome/browser/profiles/profile_manager.cc +++ b/chrome/browser/profiles/profile_manager.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -181,10 +181,18 @@ Profile* ProfileManager::GetLastUsedProfile() { return profile_manager->GetLastUsedProfile(profile_manager->user_data_dir_); } +// static +std::vector<Profile*> ProfileManager::GetLastActiveProfiles() { + ProfileManager* profile_manager = g_browser_process->profile_manager(); + return profile_manager->GetLastActiveProfiles( + profile_manager->user_data_dir_); +} + ProfileManager::ProfileManager(const FilePath& user_data_dir) : user_data_dir_(user_data_dir), logged_in_(false), - will_import_(false) { + will_import_(false), + shutdown_started_(false) { BrowserList::AddObserver(this); #if defined(OS_CHROMEOS) registrar_.Add( @@ -192,6 +200,18 @@ ProfileManager::ProfileManager(const FilePath& user_data_dir) 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, + content::NOTIFICATION_APP_EXITING, + content::NotificationService::AllSources()); } ProfileManager::~ProfileManager() { @@ -255,6 +275,30 @@ Profile* ProfileManager::GetLastUsedProfile(const FilePath& user_data_dir) { return GetProfile(last_used_profile_dir); } +std::vector<Profile*> ProfileManager::GetLastActiveProfiles( + const FilePath& user_data_dir) { + PrefService* local_state = g_browser_process->local_state(); + DCHECK(local_state); + + std::vector<Profile*> to_return; + if (local_state->HasPrefPath(prefs::kProfilesLastActive)) { + const ListValue* profile_list = + local_state->GetList(prefs::kProfilesLastActive); + if (profile_list) { + ListValue::const_iterator it; + std::string profile; + for (it = profile_list->begin(); it != profile_list->end(); ++it) { + if (!(*it)->GetAsString(&profile) || profile.empty()) { + LOG(WARNING) << "Invalid entry in " << prefs::kProfilesLastActive; + continue; + } + to_return.push_back(GetProfile(user_data_dir.AppendASCII(profile))); + } + } + } + return to_return; +} + Profile* ProfileManager::GetDefaultProfile(const FilePath& user_data_dir) { FilePath default_profile_dir(user_data_dir); default_profile_dir = default_profile_dir.Append(GetInitialProfileDir()); @@ -413,8 +457,62 @@ void ProfileManager::Observe( CHECK(chromeos::CrosLibrary::Get()->GetCryptohomeLibrary()->IsMounted()); } logged_in_ = true; + return; } #endif + if (shutdown_started_) + return; + + bool update_active_profiles = false; + switch (type) { + case content::NOTIFICATION_APP_EXITING: { + // Ignore any browsers closing from now on. + shutdown_started_ = true; + break; + } + case chrome::NOTIFICATION_BROWSER_OPENED: { + Browser* browser = content::Source<Browser>(source).ptr(); + DCHECK(browser); + Profile* profile = browser->profile(); + DCHECK(profile); + if (++browser_counts_[profile] == 1) { + active_profiles_.push_back(profile); + update_active_profiles = true; + } + break; + } + case chrome::NOTIFICATION_BROWSER_CLOSED: { + Browser* browser = content::Source<Browser>(source).ptr(); + DCHECK(browser); + Profile* profile = browser->profile(); + DCHECK(profile); + if (--browser_counts_[profile] == 0) { + active_profiles_.erase( + std::remove(active_profiles_.begin(), active_profiles_.end(), + profile), + active_profiles_.end()); + update_active_profiles = true; + } + break; + } + default: { + NOTREACHED(); + break; + } + } + if (update_active_profiles) { + PrefService* local_state = g_browser_process->local_state(); + DCHECK(local_state); + ListPrefUpdate update(local_state, prefs::kProfilesLastActive); + ListValue* profile_list = update.Get(); + + profile_list->Clear(); + std::vector<Profile*>::const_iterator it; + for (it = active_profiles_.begin(); it != active_profiles_.end(); ++it) { + profile_list->Append( + new StringValue((*it)->GetPath().BaseName().MaybeAsASCII())); + } + } } void ProfileManager::SetWillImport() { @@ -553,6 +651,7 @@ void ProfileManager::CreateMultiProfileAsync() { void ProfileManager::RegisterPrefs(PrefService* prefs) { prefs->RegisterStringPref(prefs::kProfileLastUsed, ""); prefs->RegisterIntegerPref(prefs::kProfilesNumCreated, 1); + prefs->RegisterListPref(prefs::kProfilesLastActive); } size_t ProfileManager::GetNumberOfProfiles() { diff --git a/chrome/browser/profiles/profile_manager.h b/chrome/browser/profiles/profile_manager.h index 229d702..14c1aef 100644 --- a/chrome/browser/profiles/profile_manager.h +++ b/chrome/browser/profiles/profile_manager.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -86,13 +86,24 @@ class ProfileManager : public base::NonThreadSafe, // relative to the user data directory currently in use.. FilePath GetInitialProfileDir(); - // Get the Profile last used with this Chrome build. If no signed profile has - // been stored in Local State, hand back the Default profile. + // Get the Profile last used (the Profile to which owns the most recently + // focused window) with this Chrome build. If no signed profile has been + // stored in Local State, hand back the Default profile. Profile* GetLastUsedProfile(const FilePath& user_data_dir); // Same as instance method but provides the default user_data_dir as well. static Profile* GetLastUsedProfile(); + // Get the Profiles which are currently active, i.e., have open browsers, or + // were active the last time Chrome was running. The Profiles appear in the + // order they became active. The last used profile will be on the list, but + // its index on the list will depend on when it became active (so, it is not + // necessarily the last one). + std::vector<Profile*> GetLastActiveProfiles(const FilePath& user_data_dir); + + // Same as instance method but provides the default user_data_dir as well. + static std::vector<Profile*> GetLastActiveProfiles(); + // Returns created profiles. Note, profiles order is NOT guaranteed to be // related with the creation order. std::vector<Profile*> GetLoadedProfiles() const; @@ -289,6 +300,11 @@ class ProfileManager : public base::NonThreadSafe, scoped_ptr<ProfileShortcutManagerWin> profile_shortcut_manager_; #endif + // For keeping track of the last active profiles. + std::map<Profile*, int> browser_counts_; + std::vector<Profile*> active_profiles_; + bool shutdown_started_; + DISALLOW_COPY_AND_ASSIGN(ProfileManager); }; diff --git a/chrome/browser/profiles/profile_manager_unittest.cc b/chrome/browser/profiles/profile_manager_unittest.cc index 7d598c3..6802985 100644 --- a/chrome/browser/profiles/profile_manager_unittest.cc +++ b/chrome/browser/profiles/profile_manager_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -384,3 +384,111 @@ TEST_F(ProfileManagerTest, InitProfileInfoCacheForAProfile) { EXPECT_EQ(avatar_index, cache.GetAvatarIconIndexOfProfileAtIndex(profile_index)); } + +TEST_F(ProfileManagerTest, LastActiveProfiles) { + FilePath dest_path1 = temp_dir_.path(); + dest_path1 = dest_path1.Append(FILE_PATH_LITERAL("New Profile 1")); + + FilePath dest_path2 = temp_dir_.path(); + dest_path2 = dest_path2.Append(FILE_PATH_LITERAL("New Profile 2")); + + ProfileManager* profile_manager = g_browser_process->profile_manager(); + + // Successfully create the profiles. + TestingProfile* profile1 = + static_cast<TestingProfile*>(profile_manager->GetProfile(dest_path1)); + ASSERT_TRUE(profile1); + + TestingProfile* profile2 = + static_cast<TestingProfile*>(profile_manager->GetProfile(dest_path2)); + ASSERT_TRUE(profile2); + + std::vector<Profile*> last_active_profiles = + profile_manager->GetLastActiveProfiles(); + ASSERT_EQ(0U, last_active_profiles.size()); + + // Create a browser for profile1. + scoped_ptr<Browser> browser1a(new Browser(Browser::TYPE_TABBED, profile1)); + + last_active_profiles = profile_manager->GetLastActiveProfiles(); + ASSERT_EQ(1U, last_active_profiles.size()); + EXPECT_EQ(profile1, last_active_profiles[0]); + + // And for profile2. + scoped_ptr<Browser> browser2(new Browser(Browser::TYPE_TABBED, profile2)); + + last_active_profiles = profile_manager->GetLastActiveProfiles(); + ASSERT_EQ(2U, last_active_profiles.size()); + EXPECT_EQ(profile1, last_active_profiles[0]); + EXPECT_EQ(profile2, last_active_profiles[1]); + + // Adding more browsers doesn't change anything. + scoped_ptr<Browser> browser1b(new Browser(Browser::TYPE_TABBED, profile1)); + last_active_profiles = profile_manager->GetLastActiveProfiles(); + ASSERT_EQ(2U, last_active_profiles.size()); + EXPECT_EQ(profile1, last_active_profiles[0]); + EXPECT_EQ(profile2, last_active_profiles[1]); + + // Close the browsers. + browser1a.reset(); + last_active_profiles = profile_manager->GetLastActiveProfiles(); + ASSERT_EQ(2U, last_active_profiles.size()); + EXPECT_EQ(profile1, last_active_profiles[0]); + EXPECT_EQ(profile2, last_active_profiles[1]); + + browser1b.reset(); + last_active_profiles = profile_manager->GetLastActiveProfiles(); + ASSERT_EQ(1U, last_active_profiles.size()); + EXPECT_EQ(profile2, last_active_profiles[0]); + + browser2.reset(); + last_active_profiles = profile_manager->GetLastActiveProfiles(); + ASSERT_EQ(0U, last_active_profiles.size()); +} + +TEST_F(ProfileManagerTest, LastActiveProfilesAtShutdown) { + FilePath dest_path1 = temp_dir_.path(); + dest_path1 = dest_path1.Append(FILE_PATH_LITERAL("New Profile 1")); + + FilePath dest_path2 = temp_dir_.path(); + dest_path2 = dest_path2.Append(FILE_PATH_LITERAL("New Profile 2")); + + ProfileManager* profile_manager = g_browser_process->profile_manager(); + + // Successfully create the profiles. + TestingProfile* profile1 = + static_cast<TestingProfile*>(profile_manager->GetProfile(dest_path1)); + ASSERT_TRUE(profile1); + + TestingProfile* profile2 = + static_cast<TestingProfile*>(profile_manager->GetProfile(dest_path2)); + ASSERT_TRUE(profile2); + + // Create a browser for profile1. + scoped_ptr<Browser> browser1(new Browser(Browser::TYPE_TABBED, profile1)); + + // And for profile2. + scoped_ptr<Browser> browser2(new Browser(Browser::TYPE_TABBED, profile2)); + + std::vector<Profile*> last_active_profiles = + profile_manager->GetLastActiveProfiles(); + ASSERT_EQ(2U, last_active_profiles.size()); + EXPECT_EQ(profile1, last_active_profiles[0]); + EXPECT_EQ(profile2, last_active_profiles[1]); + + // Simulate a shutdown. + content::NotificationService::current()->Notify( + content::NOTIFICATION_APP_EXITING, + content::NotificationService::AllSources(), + content::NotificationService::NoDetails()); + + // Even if the browsers are destructed during shutdown, the profiles stay + // active. + browser1.reset(); + browser2.reset(); + + last_active_profiles = profile_manager->GetLastActiveProfiles(); + ASSERT_EQ(2U, last_active_profiles.size()); + EXPECT_EQ(profile1, last_active_profiles[0]); + EXPECT_EQ(profile2, last_active_profiles[1]); +} |