// 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. #include <string> #include "base/command_line.h" #include "base/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/path_service.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "build/build_config.h" #include "chrome/browser/bookmarks/bookmark_model_factory.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/history/history_service.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/io_thread.h" #include "chrome/browser/prefs/browser_prefs.h" #include "chrome/browser/prefs/incognito_mode_prefs.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_info_cache.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/test_browser_window.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "content/public/browser/notification_service.h" #include "content/public/test/test_browser_thread_bundle.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/login/mock_user_manager.h" #include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/chromeos/settings/device_settings_service.h" #include "chromeos/chromeos_switches.h" #endif using content::BrowserThread; namespace { // This global variable is used to check that value returned to different // observers is the same. Profile* g_created_profile; class UnittestProfileManager : public ::ProfileManagerWithoutInit { public: explicit UnittestProfileManager(const base::FilePath& user_data_dir) : ::ProfileManagerWithoutInit(user_data_dir) {} protected: virtual Profile* CreateProfileHelper( const base::FilePath& file_path) OVERRIDE { if (!base::PathExists(file_path)) { if (!base::CreateDirectory(file_path)) return NULL; } return new TestingProfile(file_path, NULL); } virtual Profile* CreateProfileAsyncHelper(const base::FilePath& path, Delegate* delegate) OVERRIDE { // This is safe while all file operations are done on the FILE thread. BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, base::Bind(base::IgnoreResult(&base::CreateDirectory), path)); return new TestingProfile(path, this); } }; } // namespace class ProfileManagerTest : public testing::Test { protected: class MockObserver { public: MOCK_METHOD2(OnProfileCreated, void(Profile* profile, Profile::CreateStatus status)); }; ProfileManagerTest() : local_state_(TestingBrowserProcess::GetGlobal()) { } virtual void SetUp() { // Create a new temporary directory, and store the path ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); TestingBrowserProcess::GetGlobal()->SetProfileManager( new UnittestProfileManager(temp_dir_.path())); #if defined(OS_CHROMEOS) CommandLine* cl = CommandLine::ForCurrentProcess(); cl->AppendSwitch(switches::kTestType); #endif } virtual void TearDown() { TestingBrowserProcess::GetGlobal()->SetProfileManager(NULL); base::RunLoop().RunUntilIdle(); } // Helper function to create a profile with |name| for a profile |manager|. void CreateProfileAsync(ProfileManager* manager, const std::string& name, MockObserver* mock_observer) { manager->CreateProfileAsync( temp_dir_.path().AppendASCII(name), base::Bind(&MockObserver::OnProfileCreated, base::Unretained(mock_observer)), UTF8ToUTF16(name), base::string16(), std::string()); } #if defined(OS_CHROMEOS) chromeos::ScopedTestDeviceSettingsService test_device_settings_service_; chromeos::ScopedTestCrosSettings test_cros_settings_; #endif // The path to temporary directory used to contain the test operations. base::ScopedTempDir temp_dir_; ScopedTestingLocalState local_state_; content::TestBrowserThreadBundle thread_bundle_; #if defined(OS_CHROMEOS) chromeos::ScopedTestUserManager test_user_manager_; #endif }; TEST_F(ProfileManagerTest, GetProfile) { base::FilePath dest_path = temp_dir_.path(); dest_path = dest_path.Append(FILE_PATH_LITERAL("New Profile")); ProfileManager* profile_manager = g_browser_process->profile_manager(); // Successfully create a profile. Profile* profile = profile_manager->GetProfile(dest_path); EXPECT_TRUE(profile); // The profile already exists when we call GetProfile. Just load it. EXPECT_EQ(profile, profile_manager->GetProfile(dest_path)); } TEST_F(ProfileManagerTest, DefaultProfileDir) { base::FilePath expected_default = base::FilePath().AppendASCII(chrome::kInitialProfile); EXPECT_EQ( expected_default.value(), g_browser_process->profile_manager()->GetInitialProfileDir().value()); } #if defined(OS_CHROMEOS) // This functionality only exists on Chrome OS. TEST_F(ProfileManagerTest, LoggedInProfileDir) { CommandLine *cl = CommandLine::ForCurrentProcess(); std::string profile_dir(chrome::kTestUserProfileDir); cl->AppendSwitchASCII(chromeos::switches::kLoginProfile, profile_dir); base::FilePath expected_default = base::FilePath().AppendASCII(chrome::kInitialProfile); ProfileManager* profile_manager = g_browser_process->profile_manager(); EXPECT_EQ(expected_default.value(), profile_manager->GetInitialProfileDir().value()); scoped_ptr<chromeos::MockUserManager> mock_user_manager; mock_user_manager.reset(new chromeos::MockUserManager()); mock_user_manager->SetActiveUser("user@gmail.com"); chromeos::User* active_user = mock_user_manager->GetActiveUser(); profile_manager->Observe(chrome::NOTIFICATION_LOGIN_USER_CHANGED, content::NotificationService::AllSources(), content::Details<const chromeos::User>(active_user)); base::FilePath expected_logged_in(profile_dir); EXPECT_EQ(expected_logged_in.value(), profile_manager->GetInitialProfileDir().value()); VLOG(1) << temp_dir_.path().Append( profile_manager->GetInitialProfileDir()).value(); } #endif TEST_F(ProfileManagerTest, CreateAndUseTwoProfiles) { base::FilePath dest_path1 = temp_dir_.path(); dest_path1 = dest_path1.Append(FILE_PATH_LITERAL("New Profile 1")); base::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); // Force lazy-init of some profile services to simulate use. ASSERT_TRUE(profile1->CreateHistoryService(true, false)); EXPECT_TRUE(HistoryServiceFactory::GetForProfile(profile1, Profile::EXPLICIT_ACCESS)); profile1->CreateBookmarkModel(true); EXPECT_TRUE(BookmarkModelFactory::GetForProfile(profile1)); profile2->CreateBookmarkModel(true); EXPECT_TRUE(BookmarkModelFactory::GetForProfile(profile2)); ASSERT_TRUE(profile2->CreateHistoryService(true, false)); EXPECT_TRUE(HistoryServiceFactory::GetForProfile(profile2, Profile::EXPLICIT_ACCESS)); // Make sure any pending tasks run before we destroy the profiles. base::RunLoop().RunUntilIdle(); TestingBrowserProcess::GetGlobal()->SetProfileManager(NULL); // Make sure history cleans up correctly. base::RunLoop().RunUntilIdle(); } MATCHER(NotFail, "Profile creation failure status is not reported.") { return arg == Profile::CREATE_STATUS_CREATED || arg == Profile::CREATE_STATUS_INITIALIZED; } // Tests asynchronous profile creation mechanism. // Crashes: http://crbug.com/89421 TEST_F(ProfileManagerTest, DISABLED_CreateProfileAsync) { MockObserver mock_observer; EXPECT_CALL(mock_observer, OnProfileCreated( testing::NotNull(), NotFail())).Times(testing::AtLeast(1)); CreateProfileAsync(g_browser_process->profile_manager(), "New Profile", &mock_observer); base::RunLoop().RunUntilIdle(); } MATCHER(SameNotNull, "The same non-NULL value for all calls.") { if (!g_created_profile) g_created_profile = arg; return arg != NULL && arg == g_created_profile; } TEST_F(ProfileManagerTest, CreateProfileAsyncMultipleRequests) { g_created_profile = NULL; MockObserver mock_observer1; EXPECT_CALL(mock_observer1, OnProfileCreated( SameNotNull(), NotFail())).Times(testing::AtLeast(1)); MockObserver mock_observer2; EXPECT_CALL(mock_observer2, OnProfileCreated( SameNotNull(), NotFail())).Times(testing::AtLeast(1)); MockObserver mock_observer3; EXPECT_CALL(mock_observer3, OnProfileCreated( SameNotNull(), NotFail())).Times(testing::AtLeast(1)); ProfileManager* profile_manager = g_browser_process->profile_manager(); const std::string profile_name = "New Profile"; CreateProfileAsync(profile_manager, profile_name, &mock_observer1); CreateProfileAsync(profile_manager, profile_name, &mock_observer2); CreateProfileAsync(profile_manager, profile_name, &mock_observer3); base::RunLoop().RunUntilIdle(); } TEST_F(ProfileManagerTest, CreateProfilesAsync) { const std::string profile_name1 = "New Profile 1"; const std::string profile_name2 = "New Profile 2"; MockObserver mock_observer; EXPECT_CALL(mock_observer, OnProfileCreated( testing::NotNull(), NotFail())).Times(testing::AtLeast(3)); ProfileManager* profile_manager = g_browser_process->profile_manager(); CreateProfileAsync(profile_manager, profile_name1, &mock_observer); CreateProfileAsync(profile_manager, profile_name2, &mock_observer); base::RunLoop().RunUntilIdle(); } TEST_F(ProfileManagerTest, GetGuestProfilePath) { base::FilePath guest_path = ProfileManager::GetGuestProfilePath(); base::FilePath expected_path = temp_dir_.path(); expected_path = expected_path.Append(chrome::kGuestProfileDir); EXPECT_EQ(expected_path, guest_path); } TEST_F(ProfileManagerTest, AutoloadProfilesWithBackgroundApps) { ProfileManager* profile_manager = g_browser_process->profile_manager(); ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); local_state_.Get()->SetUserPref(prefs::kBackgroundModeEnabled, Value::CreateBooleanValue(true)); // Setting a pref which is not applicable to a system (i.e., Android in this // case) does not necessarily create it. Don't bother continuing with the // test if this pref doesn't exist because it will not load the profiles if // it cannot verify that the pref for background mode is enabled. if (!local_state_.Get()->HasPrefPath(prefs::kBackgroundModeEnabled)) return; EXPECT_EQ(0u, cache.GetNumberOfProfiles()); cache.AddProfileToCache(cache.GetUserDataDir().AppendASCII("path_1"), ASCIIToUTF16("name_1"), base::string16(), 0, std::string()); cache.AddProfileToCache(cache.GetUserDataDir().AppendASCII("path_2"), ASCIIToUTF16("name_2"), base::string16(), 0, std::string()); cache.AddProfileToCache(cache.GetUserDataDir().AppendASCII("path_3"), ASCIIToUTF16("name_3"), base::string16(), 0, std::string()); cache.SetBackgroundStatusOfProfileAtIndex(0, true); cache.SetBackgroundStatusOfProfileAtIndex(2, true); EXPECT_EQ(3u, cache.GetNumberOfProfiles()); profile_manager->AutoloadProfiles(); EXPECT_EQ(2u, profile_manager->GetLoadedProfiles().size()); } TEST_F(ProfileManagerTest, DoNotAutoloadProfilesIfBackgroundModeOff) { ProfileManager* profile_manager = g_browser_process->profile_manager(); ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); local_state_.Get()->SetUserPref(prefs::kBackgroundModeEnabled, Value::CreateBooleanValue(false)); EXPECT_EQ(0u, cache.GetNumberOfProfiles()); cache.AddProfileToCache(cache.GetUserDataDir().AppendASCII("path_1"), ASCIIToUTF16("name_1"), base::string16(), 0, std::string()); cache.AddProfileToCache(cache.GetUserDataDir().AppendASCII("path_2"), ASCIIToUTF16("name_2"), base::string16(), 0, std::string()); cache.SetBackgroundStatusOfProfileAtIndex(0, false); cache.SetBackgroundStatusOfProfileAtIndex(1, true); EXPECT_EQ(2u, cache.GetNumberOfProfiles()); profile_manager->AutoloadProfiles(); EXPECT_EQ(0u, profile_manager->GetLoadedProfiles().size()); } TEST_F(ProfileManagerTest, InitProfileUserPrefs) { base::FilePath dest_path = temp_dir_.path(); dest_path = dest_path.Append(FILE_PATH_LITERAL("New Profile")); ProfileManager* profile_manager = g_browser_process->profile_manager(); Profile* profile; // Successfully create the profile profile = profile_manager->GetProfile(dest_path); ASSERT_TRUE(profile); // Check that the profile name is non empty std::string profile_name = profile->GetPrefs()->GetString(prefs::kProfileName); EXPECT_FALSE(profile_name.empty()); // Check that the profile avatar index is valid size_t avatar_index = profile->GetPrefs()->GetInteger(prefs::kProfileAvatarIndex); EXPECT_TRUE(profile_manager->GetProfileInfoCache().IsDefaultAvatarIconIndex( avatar_index)); } // Tests that a new profile's entry in the profile info cache is setup with the // same values that are in the profile prefs. TEST_F(ProfileManagerTest, InitProfileInfoCacheForAProfile) { base::FilePath dest_path = temp_dir_.path(); dest_path = dest_path.Append(FILE_PATH_LITERAL("New Profile")); ProfileManager* profile_manager = g_browser_process->profile_manager(); ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); // Successfully create the profile Profile* profile = profile_manager->GetProfile(dest_path); ASSERT_TRUE(profile); std::string profile_name = profile->GetPrefs()->GetString(prefs::kProfileName); size_t avatar_index = profile->GetPrefs()->GetInteger(prefs::kProfileAvatarIndex); size_t profile_index = cache.GetIndexOfProfileWithPath(dest_path); // Check if the profile prefs are the same as the cache prefs EXPECT_EQ(profile_name, UTF16ToUTF8(cache.GetNameOfProfileAtIndex(profile_index))); EXPECT_EQ(avatar_index, cache.GetAvatarIconIndexOfProfileAtIndex(profile_index)); } TEST_F(ProfileManagerTest, GetLastUsedProfileAllowedByPolicy) { ProfileManager* profile_manager = g_browser_process->profile_manager(); ASSERT_TRUE(profile_manager); Profile* profile = profile_manager->GetLastUsedProfileAllowedByPolicy(); ASSERT_TRUE(profile); EXPECT_FALSE(profile->IsOffTheRecord()); PrefService* prefs = profile->GetPrefs(); EXPECT_EQ(IncognitoModePrefs::ENABLED, IncognitoModePrefs::GetAvailability(prefs)); // Attach an incognito Profile to the TestingProfile. ASSERT_FALSE(profile->GetOffTheRecordProfile()); TestingProfile::Builder builder; builder.SetIncognito(); scoped_ptr<TestingProfile> incognito_profile = builder.Build(); EXPECT_TRUE(incognito_profile->IsOffTheRecord()); TestingProfile* testing_profile = static_cast<TestingProfile*>(profile); testing_profile->SetOffTheRecordProfile(incognito_profile.PassAs<Profile>()); ASSERT_TRUE(profile->GetOffTheRecordProfile()); IncognitoModePrefs::SetAvailability(prefs, IncognitoModePrefs::DISABLED); EXPECT_FALSE( profile_manager->GetLastUsedProfileAllowedByPolicy()->IsOffTheRecord()); // GetLastUsedProfileAllowedByPolicy() returns the incognito Profile when // incognito mode is forced. IncognitoModePrefs::SetAvailability(prefs, IncognitoModePrefs::FORCED); EXPECT_TRUE( profile_manager->GetLastUsedProfileAllowedByPolicy()->IsOffTheRecord()); } #if !defined(OS_ANDROID) // There's no Browser object on Android. TEST_F(ProfileManagerTest, LastOpenedProfiles) { base::FilePath dest_path1 = temp_dir_.path(); dest_path1 = dest_path1.Append(FILE_PATH_LITERAL("New Profile 1")); base::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_opened_profiles = profile_manager->GetLastOpenedProfiles(); ASSERT_EQ(0U, last_opened_profiles.size()); // Create a browser for profile1. Browser::CreateParams profile1_params(profile1, chrome::GetActiveDesktop()); scoped_ptr<Browser> browser1a( chrome::CreateBrowserWithTestWindowForParams(&profile1_params)); last_opened_profiles = profile_manager->GetLastOpenedProfiles(); ASSERT_EQ(1U, last_opened_profiles.size()); EXPECT_EQ(profile1, last_opened_profiles[0]); // And for profile2. Browser::CreateParams profile2_params(profile2, chrome::GetActiveDesktop()); scoped_ptr<Browser> browser2( chrome::CreateBrowserWithTestWindowForParams(&profile2_params)); last_opened_profiles = profile_manager->GetLastOpenedProfiles(); ASSERT_EQ(2U, last_opened_profiles.size()); EXPECT_EQ(profile1, last_opened_profiles[0]); EXPECT_EQ(profile2, last_opened_profiles[1]); // Adding more browsers doesn't change anything. scoped_ptr<Browser> browser1b( chrome::CreateBrowserWithTestWindowForParams(&profile1_params)); last_opened_profiles = profile_manager->GetLastOpenedProfiles(); ASSERT_EQ(2U, last_opened_profiles.size()); EXPECT_EQ(profile1, last_opened_profiles[0]); EXPECT_EQ(profile2, last_opened_profiles[1]); // Close the browsers. browser1a.reset(); last_opened_profiles = profile_manager->GetLastOpenedProfiles(); ASSERT_EQ(2U, last_opened_profiles.size()); EXPECT_EQ(profile1, last_opened_profiles[0]); EXPECT_EQ(profile2, last_opened_profiles[1]); browser1b.reset(); last_opened_profiles = profile_manager->GetLastOpenedProfiles(); ASSERT_EQ(1U, last_opened_profiles.size()); EXPECT_EQ(profile2, last_opened_profiles[0]); browser2.reset(); last_opened_profiles = profile_manager->GetLastOpenedProfiles(); ASSERT_EQ(0U, last_opened_profiles.size()); } TEST_F(ProfileManagerTest, LastOpenedProfilesAtShutdown) { base::FilePath dest_path1 = temp_dir_.path(); dest_path1 = dest_path1.Append(FILE_PATH_LITERAL("New Profile 1")); base::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. Browser::CreateParams profile1_params(profile1, chrome::GetActiveDesktop()); scoped_ptr<Browser> browser1( chrome::CreateBrowserWithTestWindowForParams(&profile1_params)); // And for profile2. Browser::CreateParams profile2_params(profile2, chrome::GetActiveDesktop()); scoped_ptr<Browser> browser2( chrome::CreateBrowserWithTestWindowForParams(&profile2_params)); std::vector<Profile*> last_opened_profiles = profile_manager->GetLastOpenedProfiles(); ASSERT_EQ(2U, last_opened_profiles.size()); EXPECT_EQ(profile1, last_opened_profiles[0]); EXPECT_EQ(profile2, last_opened_profiles[1]); // Simulate a shutdown. content::NotificationService::current()->Notify( chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST, content::NotificationService::AllSources(), content::NotificationService::NoDetails()); // Even if the browsers are destructed during shutdown, the profiles stay // open. browser1.reset(); browser2.reset(); last_opened_profiles = profile_manager->GetLastOpenedProfiles(); ASSERT_EQ(2U, last_opened_profiles.size()); EXPECT_EQ(profile1, last_opened_profiles[0]); EXPECT_EQ(profile2, last_opened_profiles[1]); } TEST_F(ProfileManagerTest, LastOpenedProfilesDoesNotContainIncognito) { base::FilePath dest_path1 = temp_dir_.path(); dest_path1 = dest_path1.Append(FILE_PATH_LITERAL("New Profile 1")); base::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); // incognito profiles should not be managed by the profile manager but by the // original profile. TestingProfile::Builder builder; builder.SetIncognito(); scoped_ptr<TestingProfile> profile2 = builder.Build(); profile1->SetOffTheRecordProfile(profile2.PassAs<Profile>()); std::vector<Profile*> last_opened_profiles = profile_manager->GetLastOpenedProfiles(); ASSERT_EQ(0U, last_opened_profiles.size()); // Create a browser for profile1. Browser::CreateParams profile1_params(profile1, chrome::GetActiveDesktop()); scoped_ptr<Browser> browser1( chrome::CreateBrowserWithTestWindowForParams(&profile1_params)); last_opened_profiles = profile_manager->GetLastOpenedProfiles(); ASSERT_EQ(1U, last_opened_profiles.size()); EXPECT_EQ(profile1, last_opened_profiles[0]); // And for profile2. Browser::CreateParams profile2_params(profile1->GetOffTheRecordProfile(), chrome::GetActiveDesktop()); scoped_ptr<Browser> browser2a( chrome::CreateBrowserWithTestWindowForParams(&profile2_params)); last_opened_profiles = profile_manager->GetLastOpenedProfiles(); ASSERT_EQ(1U, last_opened_profiles.size()); EXPECT_EQ(profile1, last_opened_profiles[0]); // Adding more browsers doesn't change anything. scoped_ptr<Browser> browser2b( chrome::CreateBrowserWithTestWindowForParams(&profile2_params)); last_opened_profiles = profile_manager->GetLastOpenedProfiles(); ASSERT_EQ(1U, last_opened_profiles.size()); EXPECT_EQ(profile1, last_opened_profiles[0]); // Close the browsers. browser2a.reset(); last_opened_profiles = profile_manager->GetLastOpenedProfiles(); ASSERT_EQ(1U, last_opened_profiles.size()); EXPECT_EQ(profile1, last_opened_profiles[0]); browser2b.reset(); last_opened_profiles = profile_manager->GetLastOpenedProfiles(); ASSERT_EQ(1U, last_opened_profiles.size()); EXPECT_EQ(profile1, last_opened_profiles[0]); browser1.reset(); last_opened_profiles = profile_manager->GetLastOpenedProfiles(); ASSERT_EQ(0U, last_opened_profiles.size()); } #endif // !defined(OS_ANDROID) #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) // There's no Browser object on Android and there's no multi-profiles on Chrome. TEST_F(ProfileManagerTest, EphemeralProfilesDontEndUpAsLastProfile) { base::FilePath dest_path = temp_dir_.path(); dest_path = dest_path.Append(FILE_PATH_LITERAL("Ephemeral Profile")); ProfileManager* profile_manager = g_browser_process->profile_manager(); TestingProfile* profile = static_cast<TestingProfile*>(profile_manager->GetProfile(dest_path)); ASSERT_TRUE(profile); profile->GetPrefs()->SetBoolean(prefs::kForceEphemeralProfiles, true); // Here the last used profile is still the "Default" profile. Profile* last_used_profile = profile_manager->GetLastUsedProfile(); EXPECT_NE(profile, last_used_profile); // Create a browser for the profile. Browser::CreateParams profile_params(profile, chrome::GetActiveDesktop()); scoped_ptr<Browser> browser( chrome::CreateBrowserWithTestWindowForParams(&profile_params)); last_used_profile = profile_manager->GetLastUsedProfile(); EXPECT_NE(profile, last_used_profile); // Close the browser. browser.reset(); last_used_profile = profile_manager->GetLastUsedProfile(); EXPECT_NE(profile, last_used_profile); } TEST_F(ProfileManagerTest, EphemeralProfilesDontEndUpAsLastOpenedAtShutdown) { base::FilePath dest_path1 = temp_dir_.path(); dest_path1 = dest_path1.Append(FILE_PATH_LITERAL("Normal Profile")); base::FilePath dest_path2 = temp_dir_.path(); dest_path2 = dest_path2.Append(FILE_PATH_LITERAL("Ephemeral Profile 1")); base::FilePath dest_path3 = temp_dir_.path(); dest_path3 = dest_path3.Append(FILE_PATH_LITERAL("Ephemeral Profile 2")); ProfileManager* profile_manager = g_browser_process->profile_manager(); // Successfully create the profiles. TestingProfile* normal_profile = static_cast<TestingProfile*>(profile_manager->GetProfile(dest_path1)); ASSERT_TRUE(normal_profile); // Add one ephemeral profile which should not end up in this list. TestingProfile* ephemeral_profile1 = static_cast<TestingProfile*>(profile_manager->GetProfile(dest_path2)); ASSERT_TRUE(ephemeral_profile1); ephemeral_profile1->GetPrefs()->SetBoolean(prefs::kForceEphemeralProfiles, true); // Add second ephemeral profile but don't mark it as such yet. TestingProfile* ephemeral_profile2 = static_cast<TestingProfile*>(profile_manager->GetProfile(dest_path3)); ASSERT_TRUE(ephemeral_profile2); // Create a browser for profile1. Browser::CreateParams profile1_params(normal_profile, chrome::GetActiveDesktop()); scoped_ptr<Browser> browser1( chrome::CreateBrowserWithTestWindowForParams(&profile1_params)); // Create browsers for the ephemeral profile. Browser::CreateParams profile2_params(ephemeral_profile1, chrome::GetActiveDesktop()); scoped_ptr<Browser> browser2( chrome::CreateBrowserWithTestWindowForParams(&profile2_params)); Browser::CreateParams profile3_params(ephemeral_profile2, chrome::GetActiveDesktop()); scoped_ptr<Browser> browser3( chrome::CreateBrowserWithTestWindowForParams(&profile3_params)); std::vector<Profile*> last_opened_profiles = profile_manager->GetLastOpenedProfiles(); ASSERT_EQ(2U, last_opened_profiles.size()); EXPECT_EQ(normal_profile, last_opened_profiles[0]); EXPECT_EQ(ephemeral_profile2, last_opened_profiles[1]); // Mark the second profile ephemeral. ephemeral_profile2->GetPrefs()->SetBoolean(prefs::kForceEphemeralProfiles, true); // Simulate a shutdown. content::NotificationService::current()->Notify( chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST, content::NotificationService::AllSources(), content::NotificationService::NoDetails()); browser1.reset(); browser2.reset(); browser3.reset(); last_opened_profiles = profile_manager->GetLastOpenedProfiles(); ASSERT_EQ(1U, last_opened_profiles.size()); EXPECT_EQ(normal_profile, last_opened_profiles[0]); } TEST_F(ProfileManagerTest, ActiveProfileDeleted) { ProfileManager* profile_manager = g_browser_process->profile_manager(); ASSERT_TRUE(profile_manager); // Create and load two profiles. const std::string profile_name1 = "New Profile 1"; const std::string profile_name2 = "New Profile 2"; base::FilePath dest_path1 = temp_dir_.path().AppendASCII(profile_name1); base::FilePath dest_path2 = temp_dir_.path().AppendASCII(profile_name2); MockObserver mock_observer; EXPECT_CALL(mock_observer, OnProfileCreated( testing::NotNull(), NotFail())).Times(testing::AtLeast(3)); CreateProfileAsync(profile_manager, profile_name1, &mock_observer); CreateProfileAsync(profile_manager, profile_name2, &mock_observer); base::RunLoop().RunUntilIdle(); EXPECT_EQ(2u, profile_manager->GetLoadedProfiles().size()); EXPECT_EQ(2u, profile_manager->GetProfileInfoCache().GetNumberOfProfiles()); // Set the active profile. PrefService* local_state = g_browser_process->local_state(); local_state->SetString(prefs::kProfileLastUsed, profile_name1); // Delete the active profile. profile_manager->ScheduleProfileForDeletion(dest_path1, ProfileManager::CreateCallback()); // Spin the message loop so that all the callbacks can finish running. base::RunLoop().RunUntilIdle(); EXPECT_EQ(dest_path2, profile_manager->GetLastUsedProfile()->GetPath()); EXPECT_EQ(profile_name2, local_state->GetString(prefs::kProfileLastUsed)); } #endif // !defined(OS_ANDROID) && !defined(OS_CHROMEOS) #if defined(OS_MACOSX) // These tests are for a Mac-only code path that assumes the browser // process isn't killed when all browser windows are closed. TEST_F(ProfileManagerTest, ActiveProfileDeletedNeedsToLoadNextProfile) { ProfileManager* profile_manager = g_browser_process->profile_manager(); ASSERT_TRUE(profile_manager); // Create and load one profile, and just create a second profile. const std::string profile_name1 = "New Profile 1"; const std::string profile_name2 = "New Profile 2"; base::FilePath dest_path1 = temp_dir_.path().AppendASCII(profile_name1); base::FilePath dest_path2 = temp_dir_.path().AppendASCII(profile_name2); MockObserver mock_observer; EXPECT_CALL(mock_observer, OnProfileCreated( testing::NotNull(), NotFail())).Times(testing::AtLeast(2)); CreateProfileAsync(profile_manager, profile_name1, &mock_observer); base::RunLoop().RunUntilIdle(); // Track the profile, but don't load it. ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); cache.AddProfileToCache(dest_path2, ASCIIToUTF16(profile_name2), base::string16(), 0, std::string()); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1u, profile_manager->GetLoadedProfiles().size()); EXPECT_EQ(2u, cache.GetNumberOfProfiles()); // Set the active profile. PrefService* local_state = g_browser_process->local_state(); local_state->SetString(prefs::kProfileLastUsed, dest_path1.BaseName().MaybeAsASCII()); // Delete the active profile. This should switch and load the unloaded // profile. profile_manager->ScheduleProfileForDeletion(dest_path1, ProfileManager::CreateCallback()); // Spin the message loop so that all the callbacks can finish running. base::RunLoop().RunUntilIdle(); EXPECT_EQ(dest_path2, profile_manager->GetLastUsedProfile()->GetPath()); EXPECT_EQ(profile_name2, local_state->GetString(prefs::kProfileLastUsed)); } // This tests the recursive call in ProfileManager::OnNewActiveProfileLoaded // by simulating a scenario in which the profile that is being loaded as // the next active profile has also been marked for deletion, so the // ProfileManager needs to recursively select a different next profile. TEST_F(ProfileManagerTest, ActiveProfileDeletedNextProfileDeletedToo) { ProfileManager* profile_manager = g_browser_process->profile_manager(); ASSERT_TRUE(profile_manager); // Create and load one profile, and create two more profiles. const std::string profile_name1 = "New Profile 1"; const std::string profile_name2 = "New Profile 2"; const std::string profile_name3 = "New Profile 3"; base::FilePath dest_path1 = temp_dir_.path().AppendASCII(profile_name1); base::FilePath dest_path2 = temp_dir_.path().AppendASCII(profile_name2); base::FilePath dest_path3 = temp_dir_.path().AppendASCII(profile_name3); MockObserver mock_observer; EXPECT_CALL(mock_observer, OnProfileCreated( testing::NotNull(), NotFail())).Times(testing::AtLeast(2)); CreateProfileAsync(profile_manager, profile_name1, &mock_observer); base::RunLoop().RunUntilIdle(); // Create the other profiles, but don't load them. Assign a fake avatar icon // to ensure that profiles in the info cache are sorted by the profile name, // and not randomly by the avatar name. ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); cache.AddProfileToCache(dest_path2, ASCIIToUTF16(profile_name2), ASCIIToUTF16(profile_name2), 1, std::string()); cache.AddProfileToCache(dest_path3, ASCIIToUTF16(profile_name3), ASCIIToUTF16(profile_name3), 2, std::string()); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1u, profile_manager->GetLoadedProfiles().size()); EXPECT_EQ(3u, cache.GetNumberOfProfiles()); // Set the active profile. PrefService* local_state = g_browser_process->local_state(); local_state->SetString(prefs::kProfileLastUsed, dest_path1.BaseName().MaybeAsASCII()); // Delete the active profile, Profile1. // This will post a CreateProfileAsync message, that tries to load Profile2, // which checks that the profile is not being deleted, and then calls back // FinishDeletingProfile for Profile1. // Try to break this flow by setting the active profile to Profile2 in the // middle (so after the first posted message), and trying to delete Profile2, // so that the ProfileManager has to look for a different profile to load. profile_manager->ScheduleProfileForDeletion(dest_path1, ProfileManager::CreateCallback()); local_state->SetString(prefs::kProfileLastUsed, dest_path2.BaseName().MaybeAsASCII()); profile_manager->ScheduleProfileForDeletion(dest_path2, ProfileManager::CreateCallback()); // Spin the message loop so that all the callbacks can finish running. base::RunLoop().RunUntilIdle(); EXPECT_EQ(dest_path3, profile_manager->GetLastUsedProfile()->GetPath()); EXPECT_EQ(profile_name3, local_state->GetString(prefs::kProfileLastUsed)); } #endif // !defined(OS_MACOSX)