| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/profiles/profile_manager.h" |
| |
| #include <stddef.h> |
| |
| #include <sstream> |
| #include <string> |
| #include <utility> |
| |
| #include "base/command_line.h" |
| #include "base/files/file_path.h" |
| #include "base/files/file_path_watcher.h" |
| #include "base/files/file_util.h" |
| #include "base/files/scoped_temp_dir.h" |
| #include "base/functional/bind.h" |
| #include "base/functional/callback_helpers.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/run_loop.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/test/bind.h" |
| #include "base/test/metrics/histogram_tester.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/values.h" |
| #include "build/build_config.h" |
| #include "build/chromeos_buildflags.h" |
| #include "chrome/browser/browser_features.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/policy/profile_policy_connector.h" |
| #include "chrome/browser/prefs/browser_prefs.h" |
| #include "chrome/browser/prefs/incognito_mode_prefs.h" |
| #include "chrome/browser/profiles/delete_profile_helper.h" |
| #include "chrome/browser/profiles/keep_alive/profile_keep_alive_types.h" |
| #include "chrome/browser/profiles/keep_alive/scoped_profile_keep_alive.h" |
| #include "chrome/browser/profiles/nuke_profile_directory_utils.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/profiles/profile_attributes_init_params.h" |
| #include "chrome/browser/profiles/profile_attributes_storage.h" |
| #include "chrome/browser/profiles/profile_avatar_icon_util.h" |
| #include "chrome/browser/profiles/profiles_state.h" |
| #include "chrome/browser/signin/identity_manager_factory.h" |
| #include "chrome/browser/signin/identity_test_environment_profile_adaptor.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/grit/generated_resources.h" |
| #include "chrome/test/base/fake_profile_manager.h" |
| #include "chrome/test/base/scoped_testing_local_state.h" |
| #include "chrome/test/base/testing_browser_process.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "components/account_id/account_id.h" |
| #include "components/keyed_service/content/browser_context_dependency_manager.h" |
| #include "components/policy/core/common/policy_pref_names.h" |
| #include "components/supervised_user/core/common/pref_names.h" |
| #include "components/supervised_user/core/common/supervised_user_constants.h" |
| #include "content/public/common/content_switches.h" |
| #include "content/public/test/browser_task_environment.h" |
| #include "content/public/test/test_utils.h" |
| #include "google_apis/gaia/gaia_id.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/base/l10n/l10n_util.h" |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| #include "chrome/browser/lifetime/application_lifetime_desktop.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/test/base/test_browser_window.h" |
| #endif |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| #include "ash/constants/ash_switches.h" |
| #include "base/check_deref.h" |
| #include "chrome/browser/ash/login/users/avatar/user_image_manager_impl.h" |
| #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" |
| #include "chrome/browser/ash/login/users/user_manager_delegate_impl.h" |
| #include "chrome/browser/ash/profiles/profile_helper.h" |
| #include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h" |
| #include "chrome/browser/ash/wallpaper_handlers/test_wallpaper_fetcher_delegate.h" |
| #include "chrome/browser/ui/ash/wallpaper/test_wallpaper_controller.h" |
| #include "chrome/browser/ui/ash/wallpaper/wallpaper_controller_client_impl.h" |
| #include "chromeos/ash/components/settings/cros_settings.h" |
| #include "chromeos/ash/components/system/fake_statistics_provider.h" |
| #include "chromeos/ash/experiences/arc/arc_features.h" |
| #include "chromeos/ash/experiences/arc/arc_prefs.h" |
| #include "chromeos/ash/experiences/arc/session/arc_management_transition.h" |
| #include "components/user_manager/fake_user_manager.h" |
| #include "components/user_manager/scoped_user_manager.h" |
| #include "components/user_manager/test_helper.h" |
| #include "components/user_manager/user_manager.h" |
| #include "components/user_manager/user_manager_impl.h" |
| #include "components/user_manager/user_names.h" |
| #include "extensions/common/features/feature_session_type.h" |
| #include "extensions/common/mojom/feature_session_type.mojom.h" |
| #endif // BUILDFLAG(IS_CHROMEOS) |
| |
| using base::ASCIIToUTF16; |
| |
| namespace { |
| |
| // This global variable is used to check that value returned to different |
| // observers is the same. |
| Profile* g_created_profile = nullptr; |
| |
| void ExpectNullProfile(base::OnceClosure closure, Profile* profile) { |
| EXPECT_EQ(nullptr, profile); |
| std::move(closure).Run(); |
| } |
| |
| void ExpectProfileWithName(const std::string& profile_name, |
| bool incognito, |
| base::OnceClosure closure, |
| Profile* profile) { |
| EXPECT_NE(nullptr, profile); |
| EXPECT_EQ(incognito, profile->IsOffTheRecord()); |
| if (incognito) |
| profile = profile->GetOriginalProfile(); |
| |
| // Create a profile on the fly so the the same comparison |
| // can be used in Windows and other platforms. |
| EXPECT_EQ(base::FilePath().AppendASCII(profile_name), profile->GetBaseName()); |
| std::move(closure).Run(); |
| } |
| |
| class ProfileDeletionWaiter { |
| public: |
| explicit ProfileDeletionWaiter(const Profile* profile) |
| : profile_path_(profile->GetPath()) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| } |
| |
| ProfileDeletionWaiter(const ProfileDeletionWaiter&) = delete; |
| ProfileDeletionWaiter& operator=(const ProfileDeletionWaiter&) = delete; |
| |
| void Wait() { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| DCHECK(!watcher_); |
| base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()}) |
| ->PostTask(FROM_HERE, |
| base::BindOnce(&ProfileDeletionWaiter::StartWatchingPath, |
| base::Unretained(this))); |
| run_loop_.Run(); |
| } |
| |
| private: |
| void StartWatchingPath() { |
| DCHECK(!watcher_); |
| watcher_ = std::make_unique<base::FilePathWatcher>(); |
| EXPECT_TRUE(watcher_->Watch( |
| profile_path_, base::FilePathWatcher::Type::kNonRecursive, |
| base::BindRepeating(&ProfileDeletionWaiter::OnChanged, |
| base::Unretained(this)))); |
| CheckIfPathExists(); |
| } |
| |
| void OnChanged(const base::FilePath& path, bool error) { |
| EXPECT_EQ(profile_path_, path); |
| EXPECT_FALSE(error); |
| CheckIfPathExists(); |
| } |
| |
| void CheckIfPathExists() { |
| if (!base::PathExists(profile_path_)) { |
| watcher_.reset(); |
| run_loop_.Quit(); |
| } |
| } |
| |
| base::RunLoop run_loop_; |
| const base::FilePath profile_path_; |
| std::unique_ptr<base::FilePathWatcher> watcher_; |
| }; |
| |
| } // namespace |
| |
| class ProfileManagerTest : public testing::Test { |
| public: |
| class MockObserver { |
| public: |
| MOCK_METHOD1(OnProfileInitialized, void(Profile* profile)); |
| MOCK_METHOD1(OnProfileCreated, void(Profile* profile)); |
| }; |
| |
| ProfileManagerTest() |
| : local_state_(TestingBrowserProcess::GetGlobal()) { |
| } |
| |
| ProfileManagerTest(const ProfileManagerTest&) = delete; |
| ProfileManagerTest& operator=(const ProfileManagerTest&) = delete; |
| ~ProfileManagerTest() override = default; |
| |
| void SetUp() override { |
| // Create a new temporary directory, and store the path |
| ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| TestingBrowserProcess::GetGlobal()->SetProfileManager( |
| CreateProfileManagerForTest()); |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| base::CommandLine::ForCurrentProcess()->AppendSwitch(switches::kTestType); |
| ash::UserImageManagerImpl::SkipDefaultUserImageDownloadForTesting(); |
| wallpaper_controller_client_ = std::make_unique< |
| WallpaperControllerClientImpl>( |
| CHECK_DEREF(TestingBrowserProcess::GetGlobal()->local_state()), |
| std::make_unique<wallpaper_handlers::TestWallpaperFetcherDelegate>()); |
| wallpaper_controller_client_->InitForTesting(&test_wallpaper_controller_); |
| |
| // Have to manually reset the session type in between test runs because |
| // some tests log in users. |
| ASSERT_EQ(extensions::mojom::FeatureSessionType::kInitial, |
| extensions::GetCurrentFeatureSessionType()); |
| session_type_ = extensions::ScopedCurrentFeatureSessionType( |
| extensions::GetCurrentFeatureSessionType()); |
| |
| // Initializes ProfileHelper. |
| // TODO(crbug.com/40225390): Migrate into BrowserContextHelper. |
| ash::ProfileHelper::Get(); |
| #endif |
| } |
| |
| void TearDown() override { |
| TestingBrowserProcess::GetGlobal()->SetProfileManager(nullptr); |
| content::RunAllTasksUntilIdle(); |
| #if BUILDFLAG(IS_CHROMEOS) |
| session_type_.reset(); |
| wallpaper_controller_client_.reset(); |
| #endif |
| } |
| |
| protected: |
| virtual std::unique_ptr<ProfileManager> CreateProfileManagerForTest() { |
| return std::make_unique<FakeProfileManager>(temp_dir_.GetPath()); |
| } |
| |
| // Helper function to create a profile at `path` for a profile `manager`. |
| void CreateProfileAsync(ProfileManager* manager, |
| const base::FilePath& profile_path, |
| MockObserver* mock_observer) { |
| manager->CreateProfileAsync( |
| profile_path, |
| base::BindOnce(&MockObserver::OnProfileInitialized, |
| base::Unretained(mock_observer)), |
| base::BindOnce(&MockObserver::OnProfileCreated, |
| base::Unretained(mock_observer))); |
| } |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| // Helper function to create a profile with |name| for a profile |manager|. |
| void CreateMultiProfileAsync(ProfileManager* manager, |
| const std::string& name, |
| MockObserver* mock_observer) { |
| ProfileManager::CreateMultiProfileAsync( |
| base::UTF8ToUTF16(name), /*icon_index=*/0, /*is_hidden=*/false, |
| base::BindOnce(&MockObserver::OnProfileInitialized, |
| base::Unretained(mock_observer)), |
| base::BindOnce(&MockObserver::OnProfileCreated, |
| base::Unretained(mock_observer))); |
| } |
| #endif // !BUILDFLAG(IS_ANDROID) |
| |
| // Helper function to add a profile with |profile_name| to |profile_manager|'s |
| // ProfileAttributesStorage, and return the profile created. |
| Profile* AddProfileToStorage(ProfileManager* profile_manager, |
| const std::string& path_suffix, |
| const std::u16string& profile_name) { |
| ProfileAttributesStorage& storage = |
| profile_manager->GetProfileAttributesStorage(); |
| size_t num_profiles = storage.GetNumberOfProfiles(); |
| base::FilePath path = temp_dir_.GetPath().AppendASCII(path_suffix); |
| ProfileAttributesInitParams params; |
| params.profile_path = path; |
| params.profile_name = profile_name; |
| storage.AddProfile(std::move(params)); |
| EXPECT_EQ(num_profiles + 1u, storage.GetNumberOfProfiles()); |
| return profile_manager->GetProfile(path); |
| } |
| |
| // Helper function to set profile ephemeral at prefs and attributes storage. |
| void SetProfileEphemeral(Profile* profile) { |
| profile->GetPrefs()->SetBoolean(prefs::kForceEphemeralProfiles, true); |
| |
| // Update IsEphemeral in attributes storage, normally it happened via |
| // kForceEphemeralProfiles pref change event routed to |
| // ProfileImpl::UpdateIsEphemeralInStorage(). |
| ProfileAttributesStorage& storage = |
| g_browser_process->profile_manager()->GetProfileAttributesStorage(); |
| ProfileAttributesEntry* entry = |
| storage.GetProfileAttributesWithPath(profile->GetPath()); |
| ASSERT_NE(entry, nullptr); |
| entry->SetIsEphemeral(true); |
| } |
| |
| TestingPrefServiceSimple* local_state() { return local_state_.Get(); } |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| // Helper function to register an user with id |user_id| and create profile |
| // with a correct path. |
| void RegisterUser(const AccountId& account_id) { |
| auto* user_manager = user_manager::UserManager::Get(); |
| |
| // Add user for testing. |
| { |
| user_manager::TestHelper test_helper(user_manager); |
| if (account_id == user_manager::GuestAccountId()) { |
| ASSERT_TRUE(test_helper.AddGuestUser()); |
| } else { |
| ASSERT_TRUE(test_helper.AddRegularUser(account_id)); |
| } |
| } |
| |
| const std::string user_id_hash = |
| user_manager::TestHelper::GetFakeUsernameHash(account_id); |
| user_manager::UserManager::Get()->UserLoggedIn(account_id, user_id_hash); |
| ash::ProfileHelper* profile_helper = ash::ProfileHelper::Get(); |
| g_browser_process->profile_manager()->GetProfile( |
| profile_helper->GetProfilePathByUserIdHash(user_id_hash)); |
| } |
| |
| std::unique_ptr<Profile> InitProfileForArcTransitionTest( |
| bool profile_is_new, |
| bool arc_signed_in, |
| bool profile_is_child, |
| bool user_is_child, |
| bool profile_is_managed, |
| std::optional<bool> arc_is_managed) { |
| ash::ProfileHelper* profile_helper = ash::ProfileHelper::Get(); |
| user_manager::UserManager* user_manager = user_manager::UserManager::Get(); |
| |
| const std::string user_email = "user_for_transition@example.com"; |
| const AccountId account_id = |
| AccountId::FromUserEmailGaiaId(user_email, GaiaId("1")); |
| const std::string user_id_hash = |
| user_manager::TestHelper::GetFakeUsernameHash(account_id); |
| const base::FilePath dest_path = |
| profile_helper->GetProfilePathByUserIdHash(user_id_hash); |
| |
| { |
| user_manager::TestHelper test_helper(user_manager); |
| if (user_is_child) { |
| CHECK(test_helper.AddChildUser(account_id)); |
| } else { |
| CHECK(test_helper.AddRegularUser(account_id)); |
| } |
| } |
| |
| TestingProfile::Builder builder; |
| builder.SetPath(dest_path); |
| builder.SetIsNewProfile(profile_is_new); |
| |
| if (profile_is_child) |
| builder.SetIsSupervisedProfile(); |
| |
| builder.OverridePolicyConnectorIsManagedForTesting(profile_is_managed); |
| std::unique_ptr<Profile> profile = builder.Build(); |
| |
| profile->GetPrefs()->SetBoolean(arc::prefs::kArcSignedIn, arc_signed_in); |
| |
| if (arc_is_managed.has_value()) { |
| profile->GetPrefs()->SetBoolean(arc::prefs::kArcIsManaged, |
| *arc_is_managed); |
| } |
| |
| user_manager->UserLoggedIn(account_id, user_id_hash); |
| g_browser_process->profile_manager()->InitProfileUserPrefs(profile.get()); |
| |
| return profile; |
| } |
| |
| ash::ScopedCrosSettingsTestHelper cros_settings_test_helper_; |
| #endif |
| |
| // The path to temporary directory used to contain the test operations. These |
| // come before |task_environment_| to avoid issues around backend threads |
| // still using the temp directories upon teardown. |
| base::ScopedTempDir temp_dir_; |
| ScopedTestingLocalState local_state_; |
| |
| content::BrowserTaskEnvironment task_environment_; |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| user_manager::ScopedUserManager user_manager_{ |
| std::make_unique<user_manager::UserManagerImpl>( |
| std::make_unique<ash::UserManagerDelegateImpl>(), |
| local_state_.Get(), |
| ash::CrosSettings::Get())}; |
| std::unique_ptr<base::AutoReset<extensions::mojom::FeatureSessionType>> |
| session_type_; |
| std::unique_ptr<WallpaperControllerClientImpl> wallpaper_controller_client_; |
| TestWallpaperController test_wallpaper_controller_; |
| ash::system::ScopedFakeStatisticsProvider fake_statistics_provider_; |
| #endif |
| }; |
| |
| TEST_F(ProfileManagerTest, GetProfile) { |
| base::FilePath dest_path = temp_dir_.GetPath(); |
| 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(), |
| ProfileManager::GetInitialProfileDir().value()); |
| } |
| |
| MATCHER(SameNotNull, "The same non-NULL value for all calls.") { |
| if (!g_created_profile && arg) |
| g_created_profile = arg; |
| return arg && arg == g_created_profile; |
| } |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| |
| // This functionality only exists on Chrome OS. |
| TEST_F(ProfileManagerTest, LoggedInProfileDir) { |
| base::FilePath expected_default = |
| base::FilePath().AppendASCII(chrome::kInitialProfile); |
| EXPECT_EQ(expected_default.value(), |
| ProfileManager::GetInitialProfileDir().value()); |
| |
| constexpr char kTestUserName[] = "test-user@example.com"; |
| constexpr GaiaId::Literal kTestUserGaiaId("0123456789"); |
| const AccountId test_account_id( |
| AccountId::FromUserEmailGaiaId(kTestUserName, kTestUserGaiaId)); |
| auto* user_manager = new ash::FakeChromeUserManager(); |
| user_manager::ScopedUserManager enabler(base::WrapUnique(user_manager)); |
| |
| const user_manager::User* active_user = |
| user_manager->AddUser(test_account_id); |
| user_manager->LoginUser(test_account_id); |
| user_manager->SwitchActiveUser(test_account_id); |
| |
| base::FilePath expected_logged_in( |
| ash::ProfileHelper::GetUserProfileDir(active_user->username_hash())); |
| EXPECT_EQ(expected_logged_in.value(), |
| ProfileManager::GetInitialProfileDir().value()); |
| VLOG(1) << temp_dir_.GetPath() |
| .Append(ProfileManager::GetInitialProfileDir()) |
| .value(); |
| } |
| |
| // Test Get[ActiveUser|PrimaryUser|LastUsed]Profile does not load user profile. |
| TEST_F(ProfileManagerTest, UserProfileLoading) { |
| using ::ash::ProfileHelper; |
| |
| Profile* const signin_profile = ProfileHelper::GetSigninProfile(); |
| |
| // Get[Active|Primary|LastUsed]Profile return the sign-in profile before login |
| // happens. IsSameOrParent() is used to properly test against TestProfile |
| // whose OTR version uses a different temp path. |
| EXPECT_TRUE( |
| ProfileManager::GetActiveUserProfile()->IsSameOrParent(signin_profile)); |
| EXPECT_TRUE( |
| ProfileManager::GetPrimaryUserProfile()->IsSameOrParent(signin_profile)); |
| EXPECT_TRUE( |
| ProfileManager::GetLastUsedProfile()->IsSameOrParent(signin_profile)); |
| |
| // User signs in but user profile loading has not started. |
| const AccountId account_id = AccountId::FromUserEmailGaiaId( |
| "test-user@example.com", GaiaId("0123456789")); |
| const std::string user_id_hash = |
| user_manager::TestHelper::GetFakeUsernameHash(account_id); |
| auto* user_manager = user_manager::UserManager::Get(); |
| ASSERT_TRUE( |
| user_manager::TestHelper(user_manager).AddRegularUser(account_id)); |
| user_manager->UserLoggedIn(account_id, user_id_hash); |
| |
| // Sign-in profile should be returned at this stage. Otherwise, login code |
| // ends up in an invalid state. Strange things as in http://crbug.com/728683 |
| // and http://crbug.com/718734 happens. |
| EXPECT_TRUE( |
| ProfileManager::GetActiveUserProfile()->IsSameOrParent(signin_profile)); |
| EXPECT_TRUE( |
| ProfileManager::GetPrimaryUserProfile()->IsSameOrParent(signin_profile)); |
| |
| // GetLastUsedProfile() after login but before a user profile is loaded is |
| // fatal. |
| EXPECT_DEATH_IF_SUPPORTED(ProfileManager::GetLastUsedProfile(), ".*"); |
| |
| // Simulate UserSessionManager loads the profile. |
| Profile* const user_profile = |
| g_browser_process->profile_manager()->GetProfile( |
| ProfileHelper::Get()->GetProfilePathByUserIdHash(user_id_hash)); |
| ASSERT_FALSE(user_profile->IsSameOrParent(signin_profile)); |
| |
| // User profile is returned thereafter. |
| EXPECT_TRUE( |
| ProfileManager::GetActiveUserProfile()->IsSameOrParent(user_profile)); |
| EXPECT_TRUE( |
| ProfileManager::GetPrimaryUserProfile()->IsSameOrParent(user_profile)); |
| EXPECT_TRUE( |
| ProfileManager::GetLastUsedProfile()->IsSameOrParent(user_profile)); |
| } |
| |
| #endif // BUILDFLAG(IS_CHROMEOS) |
| |
| TEST_F(ProfileManagerTest, CreateAndUseTwoProfiles) { |
| base::FilePath dest_path1 = temp_dir_.GetPath(); |
| dest_path1 = dest_path1.Append(FILE_PATH_LITERAL("New Profile 1")); |
| |
| base::FilePath dest_path2 = temp_dir_.GetPath(); |
| 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); |
| |
| // Access some keyed service to simulate use. |
| EXPECT_TRUE(IdentityManagerFactory::GetForProfile(profile1)); |
| EXPECT_TRUE(IdentityManagerFactory::GetForProfile(profile2)); |
| |
| // Make sure any pending tasks run before we destroy the profiles. |
| content::RunAllTasksUntilIdle(); |
| |
| TestingBrowserProcess::GetGlobal()->SetProfileManager(nullptr); |
| |
| // Make sure backend sequences clean up correctly. |
| content::RunAllTasksUntilIdle(); |
| } |
| |
| TEST_F(ProfileManagerTest, LoadNonExistingProfile) { |
| base::FilePath profile_name(FILE_PATH_LITERAL("NonExistingProfile")); |
| base::RunLoop run_loop_1; |
| base::RunLoop run_loop_2; |
| |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| profile_manager->LoadProfile( |
| profile_name, false /* incognito */, |
| base::BindOnce(&ExpectNullProfile, run_loop_1.QuitClosure())); |
| run_loop_1.Run(); |
| |
| profile_manager->LoadProfile( |
| profile_name, true /* incognito */, |
| base::BindOnce(&ExpectNullProfile, run_loop_2.QuitClosure())); |
| run_loop_2.Run(); |
| } |
| |
| TEST_F(ProfileManagerTest, LoadExistingProfile) { |
| base::FilePath profile_basename(FILE_PATH_LITERAL("MyProfile")); |
| base::FilePath profile_path = temp_dir_.GetPath().Append(profile_basename); |
| const base::FilePath other_basename(FILE_PATH_LITERAL("SomeOtherProfile")); |
| MockObserver mock_observer1; |
| EXPECT_CALL(mock_observer1, OnProfileInitialized(SameNotNull())) |
| .Times(testing::AtLeast(1)); |
| |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| CreateProfileAsync(profile_manager, profile_path, &mock_observer1); |
| |
| // Make sure a real profile is created before continuing. |
| content::RunAllTasksUntilIdle(); |
| |
| base::RunLoop load_profile; |
| bool incognito = false; |
| profile_manager->LoadProfile( |
| profile_basename, incognito, |
| base::BindOnce(&ExpectProfileWithName, profile_basename.AsUTF8Unsafe(), |
| incognito, load_profile.QuitClosure())); |
| load_profile.Run(); |
| |
| base::RunLoop load_profile_incognito; |
| incognito = true; |
| profile_manager->LoadProfile( |
| profile_basename, incognito, |
| base::BindOnce(&ExpectProfileWithName, profile_basename.AsUTF8Unsafe(), |
| incognito, load_profile_incognito.QuitClosure())); |
| load_profile_incognito.Run(); |
| |
| // Loading some other non existing profile should still return null. |
| base::RunLoop load_other_profile; |
| profile_manager->LoadProfile( |
| other_basename, false, |
| base::BindOnce(&ExpectNullProfile, load_other_profile.QuitClosure())); |
| load_other_profile.Run(); |
| } |
| |
| TEST_F(ProfileManagerTest, CreateProfileAsyncMultipleRequests) { |
| g_created_profile = nullptr; |
| |
| MockObserver mock_observer1; |
| EXPECT_CALL(mock_observer1, OnProfileInitialized(SameNotNull())) |
| .Times(testing::AtLeast(1)); |
| MockObserver mock_observer2; |
| EXPECT_CALL(mock_observer2, OnProfileInitialized(SameNotNull())) |
| .Times(testing::AtLeast(1)); |
| MockObserver mock_observer3; |
| EXPECT_CALL(mock_observer3, OnProfileInitialized(SameNotNull())) |
| .Times(testing::AtLeast(1)); |
| |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| base::FilePath profile_path = temp_dir_.GetPath().AppendASCII("New Profile"); |
| CreateProfileAsync(profile_manager, profile_path, &mock_observer1); |
| CreateProfileAsync(profile_manager, profile_path, &mock_observer2); |
| CreateProfileAsync(profile_manager, profile_path, &mock_observer3); |
| |
| content::RunAllTasksUntilIdle(); |
| } |
| |
| TEST_F(ProfileManagerTest, CreateProfilesAsync) { |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| |
| base::FilePath profile_path1 = |
| temp_dir_.GetPath().AppendASCII("New Profile 1"); |
| base::FilePath profile_path2 = |
| temp_dir_.GetPath().AppendASCII("New Profile 2"); |
| |
| MockObserver mock_observer; |
| EXPECT_CALL(mock_observer, OnProfileCreated(testing::NotNull())) |
| .Times(testing::AtLeast(2)); |
| EXPECT_CALL(mock_observer, OnProfileInitialized(testing::NotNull())) |
| .Times(testing::AtLeast(2)); |
| |
| CreateProfileAsync(profile_manager, profile_path1, &mock_observer); |
| CreateProfileAsync(profile_manager, profile_path2, &mock_observer); |
| |
| content::RunAllTasksUntilIdle(); |
| } |
| |
| // Regression test for https://crbug.com/1472849 |
| TEST_F(ProfileManagerTest, ConcurrentCreationAsyncAndSync) { |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| |
| MockObserver mock_observer; |
| EXPECT_CALL(mock_observer, OnProfileCreated(testing::_)).Times(0); |
| EXPECT_CALL(mock_observer, OnProfileInitialized(testing::_)).Times(0); |
| |
| base::FilePath profile_path = temp_dir_.GetPath().AppendASCII("New Profile"); |
| CreateProfileAsync(profile_manager, profile_path, &mock_observer); |
| |
| // The profile is being created, but creation is not complete. |
| EXPECT_EQ(nullptr, profile_manager->GetProfileByPath(profile_path)); |
| |
| // Request synchronous creation of the same profile, this should not crash. |
| Profile* profile_created = nullptr; |
| Profile* profile_initialized = nullptr; |
| EXPECT_CALL(mock_observer, OnProfileCreated(testing::NotNull())) |
| .Times(1) |
| .WillOnce(testing::SaveArg<0>(&profile_created)); |
| EXPECT_CALL(mock_observer, OnProfileInitialized(testing::NotNull())) |
| .Times(1) |
| .WillOnce(testing::SaveArg<0>(&profile_initialized)); |
| Profile* profile = profile_manager->GetProfile(profile_path); |
| |
| // The profile has been loaded correctly, and all callbacks were called. |
| EXPECT_EQ(profile, profile_manager->GetProfileByPath(profile_path)); |
| testing::Mock::VerifyAndClearExpectations(&mock_observer); |
| EXPECT_EQ(profile->GetPath(), profile_path); |
| EXPECT_EQ(profile, profile_initialized); |
| EXPECT_EQ(profile, profile_created); |
| } |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| // There's no multi-profiles on Android. |
| TEST_F(ProfileManagerTest, CreateMultiProfileAsync) { |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| ASSERT_TRUE(profile_manager); |
| |
| const std::string profile_name = "New Profile"; |
| |
| base::RunLoop run_loop; |
| MockObserver mock_observer; |
| Profile* profile = nullptr; |
| EXPECT_CALL(mock_observer, OnProfileCreated(testing::NotNull())) |
| .WillOnce(testing::SaveArg<0>(&profile)); |
| EXPECT_CALL(mock_observer, OnProfileInitialized(testing::NotNull())) |
| .WillOnce([&run_loop] { run_loop.Quit(); }); |
| |
| CreateMultiProfileAsync(profile_manager, profile_name, &mock_observer); |
| run_loop.Run(); |
| |
| // Check that the profile name is set correctly both in the profile prefs and |
| // in storage. |
| ASSERT_NE(profile, nullptr); |
| ProfileAttributesEntry* entry = |
| profile_manager->GetProfileAttributesStorage() |
| .GetProfileAttributesWithPath(profile->GetPath()); |
| ASSERT_NE(entry, nullptr); |
| EXPECT_EQ(base::UTF16ToUTF8(entry->GetName()), profile_name); |
| EXPECT_EQ(profile->GetPrefs()->GetString(prefs::kProfileName), profile_name); |
| } |
| |
| TEST_F(ProfileManagerTest, CreateMultiProfilesAsync) { |
| const std::string profile_name1 = "New Profile 1"; |
| const std::string profile_name2 = "New Profile 2"; |
| |
| base::RunLoop run_loop; |
| MockObserver mock_observer; |
| EXPECT_CALL(mock_observer, OnProfileCreated(testing::NotNull())).Times(2); |
| EXPECT_CALL(mock_observer, OnProfileInitialized(testing::NotNull())) |
| .WillOnce(testing::Return()) |
| .WillOnce([&run_loop] { run_loop.Quit(); }); |
| |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| |
| CreateMultiProfileAsync(profile_manager, profile_name1, &mock_observer); |
| CreateMultiProfileAsync(profile_manager, profile_name2, &mock_observer); |
| run_loop.Run(); |
| } |
| |
| TEST_F(ProfileManagerTest, CreateMultiProfileAsyncMultipleRequests) { |
| base::RunLoop run_loop; |
| MockObserver mock_observer; |
| Profile *profile1 = nullptr, *profile2 = nullptr, *profile3 = nullptr; |
| EXPECT_CALL(mock_observer, OnProfileCreated(testing::NotNull())).Times(3); |
| EXPECT_CALL(mock_observer, OnProfileInitialized(testing::NotNull())) |
| .WillOnce(testing::SaveArg<0>(&profile1)) |
| .WillOnce(testing::SaveArg<0>(&profile2)) |
| .WillOnce(testing::DoAll(testing::SaveArg<0>(&profile3), |
| [&run_loop] { run_loop.Quit(); })); |
| |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| const std::string profile_name = "New Profile"; |
| CreateMultiProfileAsync(profile_manager, profile_name, &mock_observer); |
| CreateMultiProfileAsync(profile_manager, profile_name, &mock_observer); |
| CreateMultiProfileAsync(profile_manager, profile_name, &mock_observer); |
| run_loop.Run(); |
| |
| // A new profile should have been created for each call. |
| EXPECT_NE(profile1, profile2); |
| EXPECT_NE(profile1, profile3); |
| EXPECT_NE(profile2, profile3); |
| } |
| |
| TEST_F(ProfileManagerTest, |
| CreateMultiProfilesAsyncWithBrokenPrefAndProfileInCache) { |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| ASSERT_TRUE(profile_manager); |
| |
| // Simulate having "Profile 1" in the storage without properly incrementing |
| // the prefs::kProfilesNumCreated counter. |
| ProfileAttributesInitParams params_1; |
| params_1.profile_path = |
| profile_manager->user_data_dir().AppendASCII("Profile 1"); |
| params_1.profile_name = u"name_1"; |
| params_1.gaia_id = GaiaId("12345"); |
| params_1.is_consented_primary_account = true; |
| profile_manager->GetProfileAttributesStorage().AddProfile( |
| std::move(params_1)); |
| |
| base::RunLoop run_loop; |
| MockObserver mock_observer; |
| Profile* profile2 = nullptr; |
| EXPECT_CALL(mock_observer, OnProfileCreated(testing::NotNull())) |
| .WillOnce(testing::SaveArg<0>(&profile2)); |
| EXPECT_CALL(mock_observer, OnProfileInitialized(testing::NotNull())) |
| .WillOnce([&run_loop] { run_loop.Quit(); }); |
| |
| CreateMultiProfileAsync(profile_manager, "Profile B", &mock_observer); |
| run_loop.Run(); |
| |
| ASSERT_NE(profile2, nullptr); |
| EXPECT_EQ(profile2->GetPath().BaseName().value(), |
| FILE_PATH_LITERAL("Profile 2")); |
| ProfileAttributesEntry* entry2 = |
| profile_manager->GetProfileAttributesStorage() |
| .GetProfileAttributesWithPath(profile2->GetPath()); |
| ASSERT_NE(entry2, nullptr); |
| } |
| |
| TEST_F(ProfileManagerTest, |
| PRE_CreateMultiProfilesAsyncWithBrokenPrefAndProfileOnDisk) { |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| ASSERT_TRUE(profile_manager); |
| |
| base::RunLoop run_loop; |
| MockObserver mock_observer; |
| Profile* profile1 = nullptr; |
| EXPECT_CALL(mock_observer, OnProfileCreated(testing::NotNull())) |
| .WillOnce(testing::SaveArg<0>(&profile1)); |
| EXPECT_CALL(mock_observer, OnProfileInitialized(testing::NotNull())) |
| .WillOnce([&run_loop] { run_loop.Quit(); }); |
| CreateMultiProfileAsync(profile_manager, "Profile A", &mock_observer); |
| run_loop.Run(); |
| |
| ASSERT_NE(profile1, nullptr); |
| EXPECT_EQ(profile1->GetPath().BaseName().value(), |
| FILE_PATH_LITERAL("Profile 1")); |
| ProfileAttributesEntry* entry1 = |
| profile_manager->GetProfileAttributesStorage() |
| .GetProfileAttributesWithPath(profile1->GetPath()); |
| ASSERT_NE(entry1, nullptr); |
| |
| // Decrement next profile number to simulate it was never incremented. |
| EXPECT_EQ(local_state()->GetUserPref(prefs::kProfilesNumCreated)->GetInt(), |
| 2); |
| local_state()->SetUserPref(prefs::kProfilesNumCreated, |
| std::make_unique<base::Value>(1)); |
| // Wipe the profile from profile attributes storage to simulate it got deleted |
| // but not wiped from disk. |
| profile_manager->GetProfileAttributesStorage().RemoveProfile( |
| profile1->GetPath()); |
| } |
| |
| // We need to restart Chrome in the mean-time to make sure the profile is not |
| // loaded in memory. |
| TEST_F(ProfileManagerTest, |
| CreateMultiProfilesAsyncWithBrokenPrefAndProfileOnDisk) { |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| ASSERT_TRUE(profile_manager); |
| |
| base::RunLoop run_loop; |
| MockObserver mock_observer; |
| Profile* profile2 = nullptr; |
| EXPECT_CALL(mock_observer, OnProfileCreated(testing::NotNull())) |
| .WillOnce(testing::SaveArg<0>(&profile2)); |
| EXPECT_CALL(mock_observer, OnProfileInitialized(testing::NotNull())) |
| .WillOnce([&run_loop] { run_loop.Quit(); }); |
| CreateMultiProfileAsync(profile_manager, "Profile B", &mock_observer); |
| run_loop.Run(); |
| |
| ASSERT_NE(profile2, nullptr); |
| // The profile uses the same base name as in the pre test. |
| EXPECT_EQ(profile2->GetPath().BaseName().value(), |
| FILE_PATH_LITERAL("Profile 1")); |
| ProfileAttributesEntry* entry2 = |
| profile_manager->GetProfileAttributesStorage() |
| .GetProfileAttributesWithPath(profile2->GetPath()); |
| ASSERT_NE(entry2, nullptr); |
| EXPECT_EQ(base::UTF16ToUTF8(entry2->GetName()), "Profile B"); |
| } |
| |
| TEST_F(ProfileManagerTest, CreateHiddenProfileAsync) { |
| base::RunLoop run_loop; |
| Profile* profile = nullptr; |
| MockObserver mock_observer; |
| EXPECT_CALL(mock_observer, OnProfileCreated(testing::NotNull())) |
| .WillOnce(testing::SaveArg<0>(&profile)); |
| EXPECT_CALL(mock_observer, OnProfileInitialized(testing::NotNull())) |
| .WillOnce([&run_loop] { run_loop.Quit(); }); |
| |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| |
| profile_manager->CreateMultiProfileAsync( |
| u"New Profile", 0, /*is_hidden=*/true, |
| base::BindOnce(&MockObserver::OnProfileInitialized, |
| base::Unretained(&mock_observer)), |
| base::BindOnce(&MockObserver::OnProfileCreated, |
| base::Unretained(&mock_observer))); |
| |
| run_loop.Run(); |
| ASSERT_NE(profile, nullptr); |
| |
| ProfileAttributesEntry* entry = |
| profile_manager->GetProfileAttributesStorage() |
| .GetProfileAttributesWithPath(profile->GetPath()); |
| ASSERT_NE(entry, nullptr); |
| EXPECT_TRUE(entry->IsOmitted()); |
| EXPECT_TRUE(entry->IsEphemeral()); |
| } |
| #endif // !BUILDFLAG(IS_ANDROID) |
| |
| // Checks that the supervised profiles no longer marked as omitted on creation. |
| TEST_F(ProfileManagerTest, AddProfileToStorageCheckNotOmitted) { |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| ProfileAttributesStorage& storage = |
| profile_manager->GetProfileAttributesStorage(); |
| EXPECT_EQ(0u, storage.GetNumberOfProfiles()); |
| |
| const base::FilePath supervised_path = |
| temp_dir_.GetPath().AppendASCII("Supervised"); |
| auto supervised_profile = std::make_unique<TestingProfile>( |
| supervised_path, nullptr, Profile::CreateMode::kSynchronous); |
| supervised_profile->GetPrefs()->SetString(prefs::kSupervisedUserId, |
| supervised_user::kChildAccountSUID); |
| |
| // RegisterTestingProfile adds the profile to the attributes storage and takes |
| // ownership. |
| profile_manager->RegisterTestingProfile(std::move(supervised_profile), true); |
| ASSERT_EQ(1u, storage.GetNumberOfProfiles()); |
| EXPECT_FALSE( |
| storage.GetAllProfilesAttributesSortedByNameWithCheck()[0]->IsOmitted()); |
| |
| const base::FilePath nonsupervised_path = |
| temp_dir_.GetPath().AppendASCII("Non-Supervised"); |
| auto nonsupervised_profile = std::make_unique<TestingProfile>( |
| nonsupervised_path, nullptr, Profile::CreateMode::kSynchronous); |
| profile_manager->RegisterTestingProfile(std::move(nonsupervised_profile), |
| true); |
| |
| EXPECT_EQ(2u, storage.GetNumberOfProfiles()); |
| ProfileAttributesEntry* entry; |
| entry = storage.GetProfileAttributesWithPath(supervised_path); |
| ASSERT_NE(entry, nullptr); |
| EXPECT_FALSE(entry->IsOmitted()); |
| |
| entry = storage.GetProfileAttributesWithPath(nonsupervised_path); |
| ASSERT_NE(entry, nullptr); |
| EXPECT_FALSE(entry->IsOmitted()); |
| } |
| |
| #if !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_ANDROID) |
| TEST_F(ProfileManagerTest, GetSystemProfilePath) { |
| base::FilePath system_profile_path = ProfileManager::GetSystemProfilePath(); |
| base::FilePath expected_path = temp_dir_.GetPath(); |
| expected_path = expected_path.Append(chrome::kSystemProfileDir); |
| EXPECT_EQ(expected_path, system_profile_path); |
| } |
| #endif // !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_ANDROID) |
| |
| // Test profile manager that creates all profiles as guest by default. |
| class UnittestGuestProfileManager : public FakeProfileManager { |
| public: |
| explicit UnittestGuestProfileManager(const base::FilePath& user_data_dir) |
| : FakeProfileManager(user_data_dir) {} |
| |
| std::unique_ptr<TestingProfile> BuildTestingProfile( |
| const base::FilePath& path, |
| Delegate* delegate, |
| Profile::CreateMode create_mode) override { |
| TestingProfile::Builder builder; |
| if (create_profiles_as_guest_) |
| builder.SetGuestSession(); |
| builder.SetPath(path); |
| builder.SetDelegate(delegate); |
| builder.SetCreateMode(create_mode); |
| return builder.Build(); |
| } |
| |
| void set_create_profiles_as_guest(bool create_profiles_as_guest) { |
| create_profiles_as_guest_ = create_profiles_as_guest; |
| } |
| |
| private: |
| bool create_profiles_as_guest_ = true; |
| }; |
| |
| class ProfileManagerGuestTest : public ProfileManagerTest { |
| public: |
| ProfileManagerGuestTest() = default; |
| ProfileManagerGuestTest(const ProfileManagerGuestTest&) = delete; |
| ProfileManagerGuestTest& operator=(const ProfileManagerGuestTest&) = delete; |
| ~ProfileManagerGuestTest() override = default; |
| |
| void SetUp() override { |
| #if BUILDFLAG(IS_CHROMEOS) |
| base::CommandLine* cl = base::CommandLine::ForCurrentProcess(); |
| cl->AppendSwitch(ash::switches::kGuestSession); |
| cl->AppendSwitch(::switches::kIncognito); |
| #endif |
| |
| ProfileManagerTest::SetUp(); |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| RegisterUser(user_manager::GuestAccountId()); |
| #endif |
| } |
| |
| // Call this function if the test shouldn't create all profiles as guest by |
| // default. |
| void DoNotCreateNewProfilesAsGuest() { |
| unittest_profile_manager_->set_create_profiles_as_guest(false); |
| } |
| |
| protected: |
| std::unique_ptr<ProfileManager> CreateProfileManagerForTest() override { |
| auto profile_manager_unique = |
| std::make_unique<UnittestGuestProfileManager>(temp_dir_.GetPath()); |
| unittest_profile_manager_ = profile_manager_unique.get(); |
| return profile_manager_unique; |
| } |
| |
| private: |
| raw_ptr<UnittestGuestProfileManager, DanglingUntriaged> |
| unittest_profile_manager_ = nullptr; |
| }; |
| |
| TEST_F(ProfileManagerGuestTest, GetLastUsedProfileAllowedByPolicy) { |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| ASSERT_TRUE(profile_manager); |
| |
| Profile* profile = profile_manager->GetLastUsedProfileAllowedByPolicy(); |
| ASSERT_TRUE(profile); |
| EXPECT_TRUE(profile->IsGuestSession()); |
| EXPECT_TRUE(profile->IsOffTheRecord()); |
| } |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| TEST_F(ProfileManagerGuestTest, GuestProfileIncognito) { |
| Profile* primary_profile = ProfileManager::GetPrimaryUserProfile(); |
| EXPECT_TRUE(primary_profile->IsOffTheRecord()); |
| |
| Profile* active_profile = ProfileManager::GetActiveUserProfile(); |
| EXPECT_TRUE(active_profile->IsOffTheRecord()); |
| |
| EXPECT_TRUE(active_profile->IsSameOrParent(primary_profile)); |
| |
| Profile* last_used_profile = ProfileManager::GetLastUsedProfile(); |
| EXPECT_TRUE(last_used_profile->IsOffTheRecord()); |
| |
| EXPECT_TRUE(last_used_profile->IsSameOrParent(active_profile)); |
| } |
| #endif |
| |
| TEST_F(ProfileManagerGuestTest, GetGuestProfilePath) { |
| base::FilePath guest_path = ProfileManager::GetGuestProfilePath(); |
| base::FilePath expected_path = |
| temp_dir_.GetPath().AppendASCII("Guest Profile"); |
| EXPECT_EQ(expected_path, guest_path); |
| } |
| |
| TEST_F(ProfileManagerGuestTest, GuestProfileAttributes) { |
| // In these tests, the primary profile is a guest one. |
| Profile* primary_profile = ProfileManager::GetLastUsedProfile(); |
| ASSERT_TRUE(primary_profile); |
| ProfileAttributesEntry* entry = |
| g_browser_process->profile_manager() |
| ->GetProfileAttributesStorage() |
| .GetProfileAttributesWithPath(primary_profile->GetPath()); |
| EXPECT_EQ(entry, nullptr); |
| } |
| |
| TEST_F(ProfileManagerTest, AutoloadProfilesWithBackgroundApps) { |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| ProfileAttributesStorage& storage = |
| profile_manager->GetProfileAttributesStorage(); |
| local_state()->SetUserPref(prefs::kBackgroundModeEnabled, |
| std::make_unique<base::Value>(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()->HasPrefPath(prefs::kBackgroundModeEnabled)) |
| return; |
| |
| EXPECT_EQ(0u, storage.GetNumberOfProfiles()); |
| |
| ProfileAttributesInitParams params_1; |
| params_1.profile_path = |
| profile_manager->user_data_dir().AppendASCII("path_1"); |
| params_1.profile_name = u"name_1"; |
| params_1.gaia_id = GaiaId("12345"); |
| params_1.is_consented_primary_account = true; |
| storage.AddProfile(std::move(params_1)); |
| ProfileAttributesInitParams params_2; |
| params_2.profile_path = |
| profile_manager->user_data_dir().AppendASCII("path_2"); |
| params_2.profile_name = u"name_2"; |
| params_2.gaia_id = GaiaId("23456"); |
| params_2.is_consented_primary_account = true; |
| storage.AddProfile(std::move(params_2)); |
| ProfileAttributesInitParams params_3; |
| params_3.profile_path = |
| profile_manager->user_data_dir().AppendASCII("path_3"); |
| params_3.profile_name = u"name_3"; |
| params_3.gaia_id = GaiaId("34567"); |
| params_3.is_consented_primary_account = true; |
| storage.AddProfile(std::move(params_3)); |
| |
| ASSERT_EQ(3u, storage.GetNumberOfProfiles()); |
| |
| std::vector<ProfileAttributesEntry*> entries = |
| storage.GetAllProfilesAttributes(); |
| entries[0]->SetBackgroundStatus(true); |
| entries[2]->SetBackgroundStatus(true); |
| |
| profile_manager->AutoloadProfiles(); |
| |
| EXPECT_EQ(2u, profile_manager->GetLoadedProfiles().size()); |
| } |
| |
| TEST_F(ProfileManagerTest, DoNotAutoloadProfilesIfBackgroundModeOff) { |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| ProfileAttributesStorage& storage = |
| profile_manager->GetProfileAttributesStorage(); |
| local_state()->SetUserPref(prefs::kBackgroundModeEnabled, |
| std::make_unique<base::Value>(false)); |
| |
| EXPECT_EQ(0u, storage.GetNumberOfProfiles()); |
| |
| ProfileAttributesInitParams params_1; |
| params_1.profile_path = |
| profile_manager->user_data_dir().AppendASCII("path_1"); |
| params_1.profile_name = u"name_1"; |
| params_1.gaia_id = GaiaId("12345"); |
| params_1.is_consented_primary_account = true; |
| storage.AddProfile(std::move(params_1)); |
| ProfileAttributesInitParams params_2; |
| params_2.profile_path = |
| profile_manager->user_data_dir().AppendASCII("path_2"); |
| params_2.profile_name = u"name_2"; |
| params_2.gaia_id = GaiaId("23456"); |
| params_2.is_consented_primary_account = true; |
| storage.AddProfile(std::move(params_2)); |
| |
| ASSERT_EQ(2u, storage.GetNumberOfProfiles()); |
| |
| std::vector<ProfileAttributesEntry*> entries = |
| storage.GetAllProfilesAttributes(); |
| entries[0]->SetBackgroundStatus(false); |
| entries[1]->SetBackgroundStatus(true); |
| |
| profile_manager->AutoloadProfiles(); |
| |
| EXPECT_EQ(0u, profile_manager->GetLoadedProfiles().size()); |
| } |
| |
| TEST_F(ProfileManagerTest, InitProfileUserPrefs) { |
| base::FilePath dest_path = temp_dir_.GetPath(); |
| 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(profiles::IsDefaultAvatarIconIndex( |
| avatar_index)); |
| } |
| |
| // Tests that a new profile's entry in the profile attributes storage is setup |
| // with the same values that are in the profile prefs. |
| TEST_F(ProfileManagerTest, InitProfileAttributesStorageForAProfile) { |
| base::FilePath dest_path = temp_dir_.GetPath(); |
| dest_path = dest_path.Append(FILE_PATH_LITERAL("New Profile")); |
| |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| |
| // 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); |
| |
| ProfileAttributesEntry* entry = profile_manager->GetProfileAttributesStorage() |
| .GetProfileAttributesWithPath(dest_path); |
| ASSERT_NE(entry, nullptr); |
| |
| // Check if the profile prefs are the same as the storage prefs. |
| EXPECT_EQ(profile_name, base::UTF16ToUTF8(entry->GetName())); |
| EXPECT_EQ(avatar_index, entry->GetAvatarIconIndex()); |
| } |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| TEST_F(ProfileManagerTest, InitProfileForChildOnFirstSignIn) { |
| std::unique_ptr<Profile> profile = InitProfileForArcTransitionTest( |
| true /* profile_is_new */, false /* arc_signed_in */, |
| false /* profile_is_child */, true /* user_is_child */, |
| false /* profile_is_managed */, false /* arc_is_managed */); |
| |
| EXPECT_EQ( |
| profile->GetPrefs()->GetInteger(arc::prefs::kArcManagementTransition), |
| static_cast<int>(arc::ArcManagementTransition::NO_TRANSITION)); |
| EXPECT_EQ(profile->GetPrefs()->GetString(prefs::kSupervisedUserId), |
| supervised_user::kChildAccountSUID); |
| } |
| |
| TEST_F(ProfileManagerTest, InitProfileForRegularToChildTransition) { |
| std::unique_ptr<Profile> profile = InitProfileForArcTransitionTest( |
| false /* profile_is_new */, true /* arc_signed_in */, |
| false /* profile_is_child */, true /* user_is_child */, |
| false /* profile_is_managed */, false /* arc_is_managed */); |
| |
| EXPECT_EQ( |
| profile->GetPrefs()->GetInteger(arc::prefs::kArcManagementTransition), |
| static_cast<int>(arc::ArcManagementTransition::REGULAR_TO_CHILD)); |
| EXPECT_EQ(profile->GetPrefs()->GetString(prefs::kSupervisedUserId), |
| supervised_user::kChildAccountSUID); |
| } |
| |
| TEST_F(ProfileManagerTest, InitProfileForChildToRegularTransition) { |
| std::unique_ptr<Profile> profile = InitProfileForArcTransitionTest( |
| false /* profile_is_new */, true /* arc_signed_in */, |
| true /* profile_is_child */, false /* user_is_child */, |
| true /* profile_is_managed */, false /* arc_is_managed */); |
| |
| EXPECT_EQ( |
| profile->GetPrefs()->GetInteger(arc::prefs::kArcManagementTransition), |
| static_cast<int>(arc::ArcManagementTransition::CHILD_TO_REGULAR)); |
| EXPECT_TRUE(profile->GetPrefs()->GetString(prefs::kSupervisedUserId).empty()); |
| } |
| |
| TEST_F(ProfileManagerTest, InitProfileForUnmanagedToManagedTransition) { |
| std::unique_ptr<Profile> profile = InitProfileForArcTransitionTest( |
| false /* profile_is_new */, true /* arc_signed_in */, |
| false /* profile_is_child */, false /* user_is_child */, |
| true /* profile_is_managed */, false /* arc_is_managed */); |
| |
| EXPECT_EQ( |
| profile->GetPrefs()->GetInteger(arc::prefs::kArcManagementTransition), |
| static_cast<int>(arc::ArcManagementTransition::UNMANAGED_TO_MANAGED)); |
| } |
| |
| TEST_F(ProfileManagerTest, InitProfileForManagedUserOnFirstSignIn) { |
| std::unique_ptr<Profile> profile = InitProfileForArcTransitionTest( |
| true /* profile_is_new */, false /* arc_signed_in */, |
| false /* profile_is_child */, false /* user_is_child */, |
| true /* profile_is_managed */, false /* arc_is_managed */); |
| |
| EXPECT_EQ( |
| profile->GetPrefs()->GetInteger(arc::prefs::kArcManagementTransition), |
| static_cast<int>(arc::ArcManagementTransition::NO_TRANSITION)); |
| } |
| |
| TEST_F(ProfileManagerTest, |
| InitProfileForChildToRegularTransitionArcNotSignedIn) { |
| std::unique_ptr<Profile> profile = InitProfileForArcTransitionTest( |
| false /* profile_is_new */, false /* arc_signed_in */, |
| true /* profile_is_child */, false /* user_is_child */, |
| true /* profile_is_managed */, false /* arc_is_managed */); |
| |
| EXPECT_EQ( |
| profile->GetPrefs()->GetInteger(arc::prefs::kArcManagementTransition), |
| static_cast<int>(arc::ArcManagementTransition::NO_TRANSITION)); |
| EXPECT_TRUE(profile->GetPrefs()->GetString(prefs::kSupervisedUserId).empty()); |
| } |
| |
| TEST_F(ProfileManagerTest, |
| InitProfileForManagedUserForFirstSignInOnNewVersion) { |
| std::unique_ptr<Profile> profile = InitProfileForArcTransitionTest( |
| false /* profile_is_new */, true /* arc_signed_in */, |
| false /* profile_is_child */, false /* user_is_child */, |
| true /* profile_is_managed */, std::nullopt /* arc_is_managed */); |
| |
| EXPECT_EQ( |
| profile->GetPrefs()->GetInteger(arc::prefs::kArcManagementTransition), |
| static_cast<int>(arc::ArcManagementTransition::NO_TRANSITION)); |
| } |
| |
| TEST_F(ProfileManagerTest, InitProfileForChildUserForFirstSignInOnNewVersion) { |
| std::unique_ptr<Profile> profile = InitProfileForArcTransitionTest( |
| false /* profile_is_new */, true /* arc_signed_in */, |
| true /* profile_is_child */, true /* user_is_child */, |
| true /* profile_is_managed */, std::nullopt /* arc_is_managed */); |
| |
| EXPECT_EQ( |
| profile->GetPrefs()->GetInteger(arc::prefs::kArcManagementTransition), |
| static_cast<int>(arc::ArcManagementTransition::NO_TRANSITION)); |
| EXPECT_EQ(profile->GetPrefs()->GetString(prefs::kSupervisedUserId), |
| supervised_user::kChildAccountSUID); |
| } |
| |
| #endif |
| |
| TEST_F(ProfileManagerTest, GetLastUsedProfileAllowedByPolicy) { |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| ASSERT_TRUE(profile_manager); |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| // On CrOS, profile returned by GetLastUsedProfile is a sign-in profile that |
| // is forced to be off-the-record. That's why we need to create at least one |
| // user to get a regular profile. |
| RegisterUser(AccountId::FromUserEmailGaiaId("test-user@example.com", |
| GaiaId("1234567890"))); |
| #endif |
| |
| Profile* profile = profile_manager->GetLastUsedProfileAllowedByPolicy(); |
| ASSERT_TRUE(profile); |
| EXPECT_FALSE(profile->IsOffTheRecord()); |
| PrefService* prefs = profile->GetPrefs(); |
| EXPECT_EQ(IncognitoModePrefs::kDefaultAvailability, |
| IncognitoModePrefs::GetAvailability(prefs)); |
| |
| ASSERT_TRUE(profile->GetPrimaryOTRProfile(/*create_if_needed=*/true)); |
| |
| IncognitoModePrefs::SetAvailability( |
| prefs, policy::IncognitoModeAvailability::kDisabled); |
| EXPECT_FALSE( |
| profile_manager->GetLastUsedProfileAllowedByPolicy()->IsOffTheRecord()); |
| |
| // GetLastUsedProfileAllowedByPolicy() returns the off-the-record Profile when |
| // incognito mode is forced. |
| IncognitoModePrefs::SetAvailability( |
| prefs, policy::IncognitoModeAvailability::kForced); |
| EXPECT_TRUE( |
| profile_manager->GetLastUsedProfileAllowedByPolicy()->IsOffTheRecord()); |
| } |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| // There's no Browser object on Android. |
| TEST_F(ProfileManagerTest, LastOpenedProfiles) { |
| base::FilePath dest_path1 = temp_dir_.GetPath(); |
| dest_path1 = dest_path1.Append(FILE_PATH_LITERAL("New Profile 1")); |
| |
| base::FilePath dest_path2 = temp_dir_.GetPath(); |
| 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()); |
| EXPECT_FALSE(profile_manager->has_updated_last_opened_profiles()); |
| |
| // Create a browser for profile1. |
| Browser::CreateParams profile1_params(profile1, true); |
| std::unique_ptr<Browser> browser1a( |
| CreateBrowserWithTestWindowForParams(profile1_params)); |
| |
| last_opened_profiles = profile_manager->GetLastOpenedProfiles(); |
| ASSERT_EQ(1U, last_opened_profiles.size()); |
| EXPECT_TRUE(profile_manager->has_updated_last_opened_profiles()); |
| EXPECT_EQ(profile1, last_opened_profiles[0]); |
| |
| // And for profile2. |
| Browser::CreateParams profile2_params(profile2, true); |
| std::unique_ptr<Browser> browser2( |
| CreateBrowserWithTestWindowForParams(profile2_params)); |
| |
| last_opened_profiles = profile_manager->GetLastOpenedProfiles(); |
| ASSERT_EQ(2U, last_opened_profiles.size()); |
| EXPECT_TRUE(profile_manager->has_updated_last_opened_profiles()); |
| EXPECT_EQ(profile1, last_opened_profiles[0]); |
| EXPECT_EQ(profile2, last_opened_profiles[1]); |
| |
| // Adding more browsers doesn't change anything. |
| std::unique_ptr<Browser> browser1b( |
| CreateBrowserWithTestWindowForParams(profile1_params)); |
| last_opened_profiles = profile_manager->GetLastOpenedProfiles(); |
| ASSERT_EQ(2U, last_opened_profiles.size()); |
| EXPECT_TRUE(profile_manager->has_updated_last_opened_profiles()); |
| 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_TRUE(profile_manager->has_updated_last_opened_profiles()); |
| 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_TRUE(profile_manager->has_updated_last_opened_profiles()); |
| EXPECT_EQ(profile2, last_opened_profiles[0]); |
| |
| // `has_updated_last_opened_profiles()` should return true even after all |
| // profiles have been cleared from the list. |
| browser2.reset(); |
| last_opened_profiles = profile_manager->GetLastOpenedProfiles(); |
| ASSERT_EQ(0U, last_opened_profiles.size()); |
| EXPECT_TRUE(profile_manager->has_updated_last_opened_profiles()); |
| } |
| |
| TEST_F(ProfileManagerTest, LastOpenedProfilesAtShutdown) { |
| base::FilePath dest_path1 = temp_dir_.GetPath(); |
| dest_path1 = dest_path1.Append(FILE_PATH_LITERAL("New Profile 1")); |
| |
| base::FilePath dest_path2 = temp_dir_.GetPath(); |
| 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, true); |
| std::unique_ptr<Browser> browser1( |
| CreateBrowserWithTestWindowForParams(profile1_params)); |
| |
| // And for profile2. |
| Browser::CreateParams profile2_params(profile2, true); |
| std::unique_ptr<Browser> browser2( |
| 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. |
| chrome::OnClosingAllBrowsers(true); |
| |
| // 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_.GetPath(); |
| dest_path1 = dest_path1.Append(FILE_PATH_LITERAL("New Profile 1")); |
| base::FilePath dest_path2 = temp_dir_.GetPath(); |
| 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); |
| |
| 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, true); |
| std::unique_ptr<Browser> browser1( |
| 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->GetPrimaryOTRProfile(/*create_if_needed=*/true), true); |
| std::unique_ptr<Browser> browser2a( |
| 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. |
| std::unique_ptr<Browser> browser2b( |
| 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 // !BUILDFLAG(IS_ANDROID) |
| |
| #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_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_.GetPath(); |
| 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); |
| SetProfileEphemeral(profile); |
| |
| // 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, true); |
| std::unique_ptr<Browser> browser( |
| 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_.GetPath(); |
| dest_path1 = dest_path1.Append(FILE_PATH_LITERAL("Normal Profile")); |
| |
| base::FilePath dest_path2 = temp_dir_.GetPath(); |
| dest_path2 = dest_path2.Append(FILE_PATH_LITERAL("Ephemeral Profile 1")); |
| |
| base::FilePath dest_path3 = temp_dir_.GetPath(); |
| 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); |
| SetProfileEphemeral(ephemeral_profile1); |
| |
| // 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, true); |
| std::unique_ptr<Browser> browser1( |
| CreateBrowserWithTestWindowForParams(profile1_params)); |
| |
| // Create browsers for the ephemeral profile. |
| Browser::CreateParams profile2_params(ephemeral_profile1, true); |
| std::unique_ptr<Browser> browser2( |
| CreateBrowserWithTestWindowForParams(profile2_params)); |
| |
| Browser::CreateParams profile3_params(ephemeral_profile2, true); |
| std::unique_ptr<Browser> browser3( |
| 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. |
| SetProfileEphemeral(ephemeral_profile2); |
| |
| // Simulate a shutdown. |
| chrome::OnClosingAllBrowsers(true); |
| 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, CleanUpEphemeralProfiles) { |
| // Create two profiles, one of them ephemeral. |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| ProfileAttributesStorage& storage = |
| profile_manager->GetProfileAttributesStorage(); |
| ASSERT_EQ(0u, storage.GetNumberOfProfiles()); |
| |
| const std::string profile_name1 = "Homer"; |
| base::FilePath path1 = |
| profile_manager->user_data_dir().AppendASCII(profile_name1); |
| ProfileAttributesInitParams params_1; |
| params_1.profile_path = path1; |
| params_1.profile_name = base::UTF8ToUTF16(profile_name1); |
| params_1.user_name = base::UTF8ToUTF16(profile_name1); |
| params_1.is_consented_primary_account = true; |
| storage.AddProfile(std::move(params_1)); |
| storage.GetAllProfilesAttributes()[0]->SetIsEphemeral(true); |
| ASSERT_TRUE(base::CreateDirectory(path1)); |
| |
| const std::string profile_name2 = "Marge"; |
| base::FilePath path2 = |
| profile_manager->user_data_dir().AppendASCII(profile_name2); |
| ProfileAttributesInitParams params_2; |
| params_2.profile_path = path2; |
| params_2.profile_name = base::UTF8ToUTF16(profile_name2); |
| params_2.user_name = base::UTF8ToUTF16(profile_name2); |
| params_2.is_consented_primary_account = true; |
| storage.AddProfile(std::move(params_2)); |
| ASSERT_EQ(2u, storage.GetNumberOfProfiles()); |
| ASSERT_TRUE(base::CreateDirectory(path2)); |
| |
| // Set the active profile. |
| PrefService* local_state = g_browser_process->local_state(); |
| local_state->SetString(prefs::kProfileLastUsed, profile_name1); |
| |
| // Set the last used profiles. |
| ScopedListPrefUpdate update(local_state, prefs::kProfilesLastActive); |
| base::Value::List& initial_last_active_profile_list = update.Get(); |
| initial_last_active_profile_list.Append( |
| base::Value(path1.BaseName().MaybeAsASCII())); |
| initial_last_active_profile_list.Append( |
| base::Value(path2.BaseName().MaybeAsASCII())); |
| |
| profile_manager->GetDeleteProfileHelper().CleanUpEphemeralProfiles(); |
| content::RunAllTasksUntilIdle(); |
| const base::Value::List& final_last_active_profile_list = |
| local_state->GetList(prefs::kProfilesLastActive); |
| |
| // The ephemeral profile should be deleted, and the last used profile set to |
| // the other one. Also, the ephemeral profile should be removed from the |
| // kProfilesLastActive list. |
| EXPECT_FALSE(base::DirectoryExists(path1)); |
| EXPECT_TRUE(base::DirectoryExists(path2)); |
| EXPECT_EQ(profile_name2, local_state->GetString(prefs::kProfileLastUsed)); |
| ASSERT_EQ(1u, storage.GetNumberOfProfiles()); |
| ASSERT_EQ(1u, final_last_active_profile_list.size()); |
| ASSERT_EQ(path2.BaseName().MaybeAsASCII(), |
| (final_last_active_profile_list)[0].GetString()); |
| |
| // Mark the remaining profile ephemeral and clean up. |
| storage.GetAllProfilesAttributes()[0]->SetIsEphemeral(true); |
| profile_manager->GetDeleteProfileHelper().CleanUpEphemeralProfiles(); |
| content::RunAllTasksUntilIdle(); |
| |
| // The profile should be deleted, and the last used profile set to a new one. |
| EXPECT_FALSE(base::DirectoryExists(path2)); |
| EXPECT_EQ(0u, storage.GetNumberOfProfiles()); |
| EXPECT_EQ("Profile 1", local_state->GetString(prefs::kProfileLastUsed)); |
| ASSERT_EQ(0u, final_last_active_profile_list.size()); |
| } |
| |
| TEST_F(ProfileManagerGuestTest, CleanUpOnlyEphemeralProfiles) { |
| // Create two profiles, one of them is guest. |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| ProfileAttributesStorage& storage = |
| profile_manager->GetProfileAttributesStorage(); |
| ASSERT_EQ(0u, storage.GetNumberOfProfiles()); |
| |
| // Create the guest profile and register it. |
| base::FilePath guest_path = ProfileManager::GetGuestProfilePath(); |
| const std::string guest_profile_name = guest_path.BaseName().MaybeAsASCII(); |
| TestingProfile::Builder builder; |
| builder.SetGuestSession(); |
| builder.SetPath(guest_path); |
| builder.SetProfileName(guest_profile_name); |
| std::unique_ptr<TestingProfile> guest_profile = builder.Build(); |
| profile_manager->RegisterTestingProfile(std::move(guest_profile), true); |
| |
| // Create a regular profile. |
| const std::string profile_name = "Homer"; |
| base::FilePath path = |
| profile_manager->user_data_dir().AppendASCII(profile_name); |
| ProfileAttributesInitParams params; |
| params.profile_path = path; |
| params.profile_name = base::UTF8ToUTF16(profile_name); |
| params.user_name = base::UTF8ToUTF16(profile_name); |
| params.is_consented_primary_account = true; |
| storage.AddProfile(std::move(params)); |
| ASSERT_TRUE(base::CreateDirectory(path)); |
| |
| ASSERT_EQ(1u, storage.GetNumberOfProfiles()); |
| |
| // Set the active profile. |
| PrefService* local_state = g_browser_process->local_state(); |
| local_state->SetString(prefs::kProfileLastUsed, guest_profile_name); |
| |
| // Set the last used profiles. |
| ScopedListPrefUpdate update(local_state, prefs::kProfilesLastActive); |
| base::Value::List& initial_last_active_profile_list = update.Get(); |
| initial_last_active_profile_list.Append( |
| base::Value(guest_path.BaseName().MaybeAsASCII())); |
| initial_last_active_profile_list.Append( |
| base::Value(path.BaseName().MaybeAsASCII())); |
| |
| profile_manager->GetDeleteProfileHelper().CleanUpEphemeralProfiles(); |
| content::RunAllTasksUntilIdle(); |
| const base::Value::List& final_last_active_profile_list = |
| local_state->GetList(prefs::kProfilesLastActive); |
| |
| // The guest and the non-ephemeral regular profile aren't impacted. |
| EXPECT_TRUE(base::DirectoryExists(guest_path)); |
| EXPECT_TRUE(base::DirectoryExists(path)); |
| EXPECT_EQ(guest_profile_name, |
| local_state->GetString(prefs::kProfileLastUsed)); |
| ASSERT_EQ(1u, storage.GetNumberOfProfiles()); |
| ASSERT_EQ(2u, final_last_active_profile_list.size()); |
| ASSERT_EQ(guest_path.BaseName().MaybeAsASCII(), |
| (final_last_active_profile_list)[0].GetString()); |
| } |
| |
| TEST_F(ProfileManagerTest, CleanUpEphemeralProfilesWithGuestLastUsedProfile) { |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| ProfileAttributesStorage& storage = |
| profile_manager->GetProfileAttributesStorage(); |
| ASSERT_EQ(0u, storage.GetNumberOfProfiles()); |
| |
| const std::string profile_name1 = "Homer"; |
| base::FilePath path1 = |
| profile_manager->user_data_dir().AppendASCII(profile_name1); |
| ProfileAttributesInitParams params; |
| params.profile_path = path1; |
| params.profile_name = base::UTF8ToUTF16(profile_name1); |
| params.user_name = base::UTF8ToUTF16(profile_name1); |
| params.is_consented_primary_account = true; |
| storage.AddProfile(std::move(params)); |
| storage.GetAllProfilesAttributes()[0]->SetIsEphemeral(true); |
| ASSERT_TRUE(base::CreateDirectory(path1)); |
| ASSERT_EQ(1u, storage.GetNumberOfProfiles()); |
| |
| // Set the active profile. |
| PrefService* local_state = g_browser_process->local_state(); |
| local_state->SetString(prefs::kProfileLastUsed, std::string("Guest Profile")); |
| |
| profile_manager->GetDeleteProfileHelper().CleanUpEphemeralProfiles(); |
| content::RunAllTasksUntilIdle(); |
| |
| ASSERT_EQ(0u, storage.GetNumberOfProfiles()); |
| EXPECT_EQ("Profile 1", local_state->GetString(prefs::kProfileLastUsed)); |
| } |
| |
| TEST_F(ProfileManagerTest, DestroyProfileOnBrowserClose) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitAndEnableFeature(features::kDestroyProfileOnBrowserClose); |
| |
| base::FilePath dest_path1 = temp_dir_.GetPath().AppendASCII("New Profile 1"); |
| base::FilePath dest_path2 = temp_dir_.GetPath().AppendASCII("New Profile 2"); |
| |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| |
| 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 profile2. |
| Browser::CreateParams profile_params2(profile2, true); |
| std::unique_ptr<Browser> browser2( |
| CreateBrowserWithTestWindowForParams(profile_params2)); |
| |
| EXPECT_TRUE(profile_manager->IsValidProfile(profile1)); |
| EXPECT_TRUE(profile_manager->IsValidProfile(profile2)); |
| |
| // Close the browser for profile2. |
| browser2.reset(); |
| content::RunAllTasksUntilIdle(); |
| |
| EXPECT_TRUE(profile_manager->IsValidProfile(profile1)); |
| EXPECT_FALSE(profile_manager->IsValidProfile(profile2)); |
| } |
| |
| TEST_F(ProfileManagerTest, DestroyEphemeralProfileOnBrowserClose) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitAndEnableFeature(features::kDestroyProfileOnBrowserClose); |
| |
| base::FilePath dest_path1 = temp_dir_.GetPath().AppendASCII("New Profile 1"); |
| base::FilePath dest_path2 = temp_dir_.GetPath().AppendASCII("New Profile 2"); |
| |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| ProfileAttributesStorage& storage = |
| profile_manager->GetProfileAttributesStorage(); |
| |
| // Create 2 ephemeral profiles. |
| TestingProfile* profile1 = |
| static_cast<TestingProfile*>(profile_manager->GetProfile(dest_path1)); |
| ASSERT_TRUE(profile1); |
| SetProfileEphemeral(profile1); |
| TestingProfile* profile2 = |
| static_cast<TestingProfile*>(profile_manager->GetProfile(dest_path2)); |
| ASSERT_TRUE(profile2); |
| SetProfileEphemeral(profile2); |
| |
| content::RunAllTasksUntilIdle(); |
| Profile* last_used_profile = profile_manager->GetLastUsedProfile(); |
| EXPECT_NE(profile1, last_used_profile); |
| EXPECT_NE(profile2, last_used_profile); |
| EXPECT_EQ(3u, storage.GetNumberOfProfiles()); |
| EXPECT_TRUE(base::PathExists(dest_path1)); |
| EXPECT_TRUE(base::PathExists(dest_path2)); |
| |
| // Create a browser for profile2. |
| Browser::CreateParams profile_params2(profile2, true); |
| std::unique_ptr<Browser> browser2( |
| CreateBrowserWithTestWindowForParams(profile_params2)); |
| |
| // All asynchronous profile loading must complete to prevent accidental |
| // reconstruction of profile2's path. This happens because |
| // SimpleBackendImpl::InitializeIndex() is performed async which, if not |
| // allowed to complete, may be performed after browser2.reset() and profile |
| // path deletion. |
| content::RunAllTasksUntilIdle(); |
| |
| ProfileDeletionWaiter waiter(profile2); |
| |
| // Confirm that we are not currently waiting for the profile to be destroyed. |
| ASSERT_FALSE(IsProfileDirectoryMarkedForDeletion(dest_path2)); |
| |
| // Destroy the browser and let browser close tasks run. |
| browser2.reset(); |
| content::RunAllTasksUntilIdle(); |
| |
| // Confirm that either we have marked profile2's path for deletion or the path |
| // has been deleted. |
| ASSERT_TRUE(IsProfileDirectoryMarkedForDeletion(dest_path2) || |
| !base::PathExists(dest_path2)); |
| |
| waiter.Wait(); |
| EXPECT_FALSE(base::PathExists(dest_path2)); |
| |
| last_used_profile = profile_manager->GetLastUsedProfile(); |
| EXPECT_NE(profile1, last_used_profile); |
| EXPECT_NE(profile2, last_used_profile); |
| EXPECT_EQ(2u, storage.GetNumberOfProfiles()); |
| EXPECT_TRUE(base::PathExists(dest_path1)); |
| } |
| |
| 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_basename1 = "New Profile 1"; |
| const std::string profile_basename2 = "New Profile 2"; |
| base::FilePath profile_path1 = |
| temp_dir_.GetPath().AppendASCII(profile_basename1); |
| base::FilePath profile_path2 = |
| temp_dir_.GetPath().AppendASCII(profile_basename2); |
| |
| MockObserver mock_observer; |
| EXPECT_CALL(mock_observer, OnProfileInitialized(testing::NotNull())) |
| .Times(testing::AtLeast(2)); |
| EXPECT_CALL(mock_observer, OnProfileCreated(testing::NotNull())) |
| .Times(testing::AtLeast(2)); |
| |
| CreateProfileAsync(profile_manager, profile_path1, &mock_observer); |
| CreateProfileAsync(profile_manager, profile_path2, &mock_observer); |
| content::RunAllTasksUntilIdle(); |
| |
| EXPECT_EQ(2u, profile_manager->GetLoadedProfiles().size()); |
| EXPECT_EQ( |
| 2u, profile_manager->GetProfileAttributesStorage().GetNumberOfProfiles()); |
| |
| // Set the active profile. |
| PrefService* local_state = g_browser_process->local_state(); |
| local_state->SetString(prefs::kProfileLastUsed, profile_basename1); |
| |
| // Delete the active profile. |
| profile_manager->GetDeleteProfileHelper().MaybeScheduleProfileForDeletion( |
| profile_path1, base::DoNothing(), |
| ProfileMetrics::DELETE_PROFILE_USER_MANAGER); |
| content::RunAllTasksUntilIdle(); |
| |
| EXPECT_EQ(profile_path2, profile_manager->GetLastUsedProfile()->GetPath()); |
| EXPECT_EQ(profile_basename2, local_state->GetString(prefs::kProfileLastUsed)); |
| } |
| |
| TEST_F(ProfileManagerTest, LastProfileDeleted) { |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| ASSERT_TRUE(profile_manager); |
| ProfileAttributesStorage& storage = |
| profile_manager->GetProfileAttributesStorage(); |
| |
| // Create and load a profile. |
| const std::string profile_basename1 = "New Profile 1"; |
| base::FilePath profile_path1 = |
| temp_dir_.GetPath().AppendASCII(profile_basename1); |
| |
| MockObserver mock_observer; |
| EXPECT_CALL(mock_observer, OnProfileInitialized(testing::NotNull())) |
| .Times(testing::AtLeast(1)); |
| |
| CreateProfileAsync(profile_manager, profile_path1, &mock_observer); |
| content::RunAllTasksUntilIdle(); |
| |
| EXPECT_EQ(1u, profile_manager->GetLoadedProfiles().size()); |
| EXPECT_EQ(1u, storage.GetNumberOfProfiles()); |
| |
| // Set it as the active profile. |
| PrefService* local_state = g_browser_process->local_state(); |
| local_state->SetString(prefs::kProfileLastUsed, profile_basename1); |
| |
| // Delete the active profile. |
| profile_manager->GetDeleteProfileHelper().MaybeScheduleProfileForDeletion( |
| profile_path1, base::DoNothing(), |
| ProfileMetrics::DELETE_PROFILE_USER_MANAGER); |
| content::RunAllTasksUntilIdle(); |
| |
| // A new profile should have been created |
| const std::string profile_basename2 = "Profile 1"; |
| base::FilePath profile_path2 = |
| temp_dir_.GetPath().AppendASCII(profile_basename2); |
| |
| EXPECT_EQ(profile_path2, profile_manager->GetLastUsedProfile()->GetPath()); |
| EXPECT_EQ(profile_basename2, local_state->GetString(prefs::kProfileLastUsed)); |
| ASSERT_EQ(1u, storage.GetNumberOfProfiles()); |
| EXPECT_EQ(profile_path2, storage.GetAllProfilesAttributes()[0]->GetPath()); |
| } |
| |
| TEST_F(ProfileManagerGuestTest, LastProfileDeletedWithGuestActiveProfile) { |
| // Make new profiles to be created as non-guest by default. |
| DoNotCreateNewProfilesAsGuest(); |
| |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| ASSERT_TRUE(profile_manager); |
| ProfileAttributesStorage& storage = |
| profile_manager->GetProfileAttributesStorage(); |
| |
| // Create and load a profile. |
| const std::string profile_basename1 = "New Profile 1"; |
| base::FilePath profile_path1 = |
| temp_dir_.GetPath().AppendASCII(profile_basename1); |
| |
| MockObserver mock_observer; |
| EXPECT_CALL(mock_observer, OnProfileCreated(testing::NotNull())) |
| .Times(testing::AtLeast(1)); |
| EXPECT_CALL(mock_observer, OnProfileInitialized(testing::NotNull())) |
| .Times(testing::AtLeast(1)); |
| |
| CreateProfileAsync(profile_manager, profile_path1, &mock_observer); |
| content::RunAllTasksUntilIdle(); |
| |
| EXPECT_EQ(1u, profile_manager->GetLoadedProfiles().size()); |
| EXPECT_EQ(1u, storage.GetNumberOfProfiles()); |
| |
| // Create the profile and register it. |
| const std::string guest_profile_basename = |
| ProfileManager::GetGuestProfilePath().BaseName().MaybeAsASCII(); |
| |
| TestingProfile::Builder builder; |
| builder.SetGuestSession(); |
| builder.SetPath(ProfileManager::GetGuestProfilePath()); |
| std::unique_ptr<TestingProfile> guest_profile = builder.Build(); |
| guest_profile->set_profile_name(guest_profile_basename); |
| profile_manager->RegisterTestingProfile(std::move(guest_profile), false); |
| |
| // The Guest profile does not get added to the ProfileAttributesStorage. |
| EXPECT_EQ(2u, profile_manager->GetLoadedProfiles().size()); |
| EXPECT_EQ(1u, storage.GetNumberOfProfiles()); |
| |
| // Set the Guest profile as the active profile. |
| PrefService* local_state = g_browser_process->local_state(); |
| local_state->SetString(prefs::kProfileLastUsed, guest_profile_basename); |
| |
| // Delete the other profile. |
| profile_manager->GetDeleteProfileHelper().MaybeScheduleProfileForDeletion( |
| profile_path1, base::DoNothing(), |
| ProfileMetrics::DELETE_PROFILE_USER_MANAGER); |
| content::RunAllTasksUntilIdle(); |
| |
| // A new profile should have been created. |
| const std::string profile_basename2 = "Profile 1"; |
| base::FilePath profile_path2 = |
| temp_dir_.GetPath().AppendASCII(profile_basename2); |
| |
| if (base::FeatureList::IsEnabled(features::kDestroyProfileOnBrowserClose)) |
| EXPECT_EQ(2u, profile_manager->GetLoadedProfiles().size()); |
| else |
| EXPECT_EQ(3u, profile_manager->GetLoadedProfiles().size()); |
| ASSERT_EQ(1u, storage.GetNumberOfProfiles()); |
| EXPECT_EQ(profile_path2, storage.GetAllProfilesAttributes()[0]->GetPath()); |
| } |
| |
| TEST_F(ProfileManagerTest, ProfileDisplayNameResetsDefaultName) { |
| if (!profiles::IsMultipleProfilesEnabled()) |
| return; |
| |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| ProfileAttributesStorage& storage = |
| profile_manager->GetProfileAttributesStorage(); |
| EXPECT_EQ(0u, storage.GetNumberOfProfiles()); |
| |
| // Only one local profile means we display IDS_SINGLE_PROFILE_DISPLAY_NAME. |
| const std::u16string default_profile_name = |
| l10n_util::GetStringUTF16(IDS_SINGLE_PROFILE_DISPLAY_NAME); |
| const std::u16string profile_name1 = storage.ChooseNameForNewProfile(); |
| Profile* profile1 = AddProfileToStorage(profile_manager, |
| "path_1", profile_name1); |
| EXPECT_EQ(default_profile_name, |
| profiles::GetAvatarNameForProfile(profile1->GetPath())); |
| |
| // Multiple profiles means displaying the actual profile names. |
| const std::u16string profile_name2 = storage.ChooseNameForNewProfile(); |
| Profile* profile2 = AddProfileToStorage(profile_manager, |
| "path_2", profile_name2); |
| EXPECT_EQ(profile_name1, |
| profiles::GetAvatarNameForProfile(profile1->GetPath())); |
| EXPECT_EQ(profile_name2, |
| profiles::GetAvatarNameForProfile(profile2->GetPath())); |
| |
| // Deleting a profile means returning to the default name. |
| profile_manager->GetDeleteProfileHelper().MaybeScheduleProfileForDeletion( |
| profile2->GetPath(), base::DoNothing(), |
| ProfileMetrics::DELETE_PROFILE_USER_MANAGER); |
| content::RunAllTasksUntilIdle(); |
| EXPECT_EQ(default_profile_name, |
| profiles::GetAvatarNameForProfile(profile1->GetPath())); |
| } |
| |
| TEST_F(ProfileManagerTest, ProfileDisplayNamePreservesCustomName) { |
| if (!profiles::IsMultipleProfilesEnabled()) |
| return; |
| |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| ProfileAttributesStorage& storage = |
| profile_manager->GetProfileAttributesStorage(); |
| EXPECT_EQ(0u, storage.GetNumberOfProfiles()); |
| |
| // Only one local profile means we display IDS_SINGLE_PROFILE_DISPLAY_NAME. |
| const std::u16string default_profile_name = |
| l10n_util::GetStringUTF16(IDS_SINGLE_PROFILE_DISPLAY_NAME); |
| const std::u16string profile_name1 = storage.ChooseNameForNewProfile(); |
| Profile* profile1 = AddProfileToStorage(profile_manager, |
| "path_1", profile_name1); |
| EXPECT_EQ(default_profile_name, |
| profiles::GetAvatarNameForProfile(profile1->GetPath())); |
| ASSERT_EQ(1u, storage.GetNumberOfProfiles()); |
| |
| // We should display custom names for local profiles. |
| const std::u16string custom_profile_name = u"Batman"; |
| ProfileAttributesEntry* entry = storage.GetAllProfilesAttributes()[0]; |
| entry->SetLocalProfileName(custom_profile_name, false); |
| EXPECT_EQ(custom_profile_name, entry->GetName()); |
| EXPECT_EQ(custom_profile_name, |
| profiles::GetAvatarNameForProfile(profile1->GetPath())); |
| |
| // Multiple profiles means displaying the actual profile names. |
| const std::u16string profile_name2 = storage.ChooseNameForNewProfile(); |
| Profile* profile2 = AddProfileToStorage(profile_manager, |
| "path_2", profile_name2); |
| EXPECT_EQ(custom_profile_name, |
| profiles::GetAvatarNameForProfile(profile1->GetPath())); |
| EXPECT_EQ(profile_name2, |
| profiles::GetAvatarNameForProfile(profile2->GetPath())); |
| |
| // Deleting a profile means returning to the original, custom name. |
| profile_manager->GetDeleteProfileHelper().MaybeScheduleProfileForDeletion( |
| profile2->GetPath(), base::DoNothing(), |
| ProfileMetrics::DELETE_PROFILE_USER_MANAGER); |
| content::RunAllTasksUntilIdle(); |
| EXPECT_EQ(custom_profile_name, |
| profiles::GetAvatarNameForProfile(profile1->GetPath())); |
| } |
| |
| TEST_F(ProfileManagerTest, ProfileDisplayNamePreservesSignedInName) { |
| if (!profiles::IsMultipleProfilesEnabled()) |
| return; |
| |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| ProfileAttributesStorage& storage = |
| profile_manager->GetProfileAttributesStorage(); |
| EXPECT_EQ(0u, storage.GetNumberOfProfiles()); |
| |
| // Only one local profile means we display IDS_SINGLE_PROFILE_DISPLAY_NAME. |
| const std::u16string default_profile_name = |
| l10n_util::GetStringUTF16(IDS_SINGLE_PROFILE_DISPLAY_NAME); |
| const std::u16string profile_name1 = storage.ChooseNameForNewProfile(); |
| Profile* profile1 = AddProfileToStorage(profile_manager, |
| "path_1", profile_name1); |
| EXPECT_EQ(default_profile_name, |
| profiles::GetAvatarNameForProfile(profile1->GetPath())); |
| |
| ASSERT_EQ(1u, storage.GetNumberOfProfiles()); |
| ProfileAttributesEntry* entry = storage.GetAllProfilesAttributes()[0]; |
| // For a signed in profile with a default name we still display |
| // IDS_SINGLE_PROFILE_DISPLAY_NAME. |
| entry->SetAuthInfo(GaiaId("12345"), u"user@gmail.com", true); |
| EXPECT_EQ(profile_name1, entry->GetName()); |
| EXPECT_EQ(default_profile_name, |
| profiles::GetAvatarNameForProfile(profile1->GetPath())); |
| |
| // For a signed in profile with a non-default Gaia given name we display the |
| // Gaia given name. |
| entry->SetAuthInfo(GaiaId("12345"), u"user@gmail.com", true); |
| const std::u16string gaia_given_name(u"given name"); |
| entry->SetGAIAGivenName(gaia_given_name); |
| EXPECT_EQ(gaia_given_name, entry->GetName()); |
| EXPECT_EQ(gaia_given_name, |
| profiles::GetAvatarNameForProfile(profile1->GetPath())); |
| |
| // Multiple profiles means displaying the actual profile names. |
| const std::u16string profile_name2 = storage.ChooseNameForNewProfile(); |
| Profile* profile2 = AddProfileToStorage(profile_manager, |
| "path_2", profile_name2); |
| EXPECT_EQ(gaia_given_name, |
| profiles::GetAvatarNameForProfile(profile1->GetPath())); |
| EXPECT_EQ(profile_name2, |
| profiles::GetAvatarNameForProfile(profile2->GetPath())); |
| |
| // Deleting a profile means returning to the original, actual profile name. |
| profile_manager->GetDeleteProfileHelper().MaybeScheduleProfileForDeletion( |
| profile2->GetPath(), base::DoNothing(), |
| ProfileMetrics::DELETE_PROFILE_USER_MANAGER); |
| content::RunAllTasksUntilIdle(); |
| EXPECT_EQ(gaia_given_name, |
| profiles::GetAvatarNameForProfile(profile1->GetPath())); |
| } |
| #endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS) |
| |
| // GetAvatarNameForProfile() is not defined on Android. |
| #if !BUILDFLAG(IS_ANDROID) |
| TEST_F(ProfileManagerTest, ProfileDisplayNameIsEmailIfDefaultName) { |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| ProfileAttributesStorage& storage = |
| profile_manager->GetProfileAttributesStorage(); |
| EXPECT_EQ(0u, storage.GetNumberOfProfiles()); |
| |
| // Create two signed in profiles, with both new and legacy default names, and |
| // a profile with a custom name. |
| Profile* profile1 = |
| AddProfileToStorage(profile_manager, "path_1", u"Person 1"); |
| Profile* profile2 = |
| AddProfileToStorage(profile_manager, "path_2", u"Default Profile"); |
| const std::u16string profile_name3(u"Batman"); |
| Profile* profile3 = AddProfileToStorage(profile_manager, "path_3", |
| profile_name3); |
| EXPECT_EQ(3u, storage.GetNumberOfProfiles()); |
| |
| // Sign in all profiles, and make sure they do not have a Gaia name set. |
| const std::u16string email1(u"user1@gmail.com"); |
| const std::u16string email2(u"user2@gmail.com"); |
| const std::u16string email3(u"user3@gmail.com"); |
| |
| ProfileAttributesEntry* entry = |
| storage.GetProfileAttributesWithPath(profile1->GetPath()); |
| |
| ASSERT_NE(entry, nullptr); |
| entry->SetAuthInfo(GaiaId("12345"), email1, true); |
| entry->SetGAIAGivenName(std::u16string()); |
| entry->SetGAIAName(std::u16string()); |
| |
| entry = storage.GetProfileAttributesWithPath(profile2->GetPath()); |
| ASSERT_NE(entry, nullptr); |
| #if !BUILDFLAG(IS_CHROMEOS) |
| // (Default profile, Batman,..) are legacy profile names on Desktop and are |
| // not considered default profile names for newly created profiles. |
| // We use "Person %n" as the default profile name. Set |SetIsUsingDefaultName| |
| // manually to mimick pre-existing profiles. |
| entry->SetLocalProfileName(u"Default Profile", true); |
| #endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS) |
| |
| entry->SetAuthInfo(GaiaId("23456"), email2, true); |
| entry->SetGAIAGivenName(std::u16string()); |
| entry->SetGAIAName(std::u16string()); |
| |
| entry = storage.GetProfileAttributesWithPath(profile3->GetPath()); |
| ASSERT_NE(entry, nullptr); |
| |
| entry->SetAuthInfo(GaiaId("34567"), email3, true); |
| entry->SetGAIAGivenName(std::u16string()); |
| entry->SetGAIAName(std::u16string()); |
| |
| // The profiles with default names should display the email address. |
| EXPECT_EQ(email1, profiles::GetAvatarNameForProfile(profile1->GetPath())); |
| EXPECT_EQ(email2, profiles::GetAvatarNameForProfile(profile2->GetPath())); |
| |
| // The profile with the custom name should display that. |
| EXPECT_EQ(profile_name3, |
| profiles::GetAvatarNameForProfile(profile3->GetPath())); |
| |
| // Adding a Gaia name to a profile that previously had a default name should |
| // start displaying it. |
| const std::u16string gaia_given_name(u"Robin"); |
| entry = storage.GetProfileAttributesWithPath(profile1->GetPath()); |
| ASSERT_NE(entry, nullptr); |
| entry->SetGAIAGivenName(gaia_given_name); |
| EXPECT_EQ(gaia_given_name, |
| profiles::GetAvatarNameForProfile(profile1->GetPath())); |
| } |
| #endif // !BUILDFLAG(IS_ANDROID) |
| |
| #if BUILDFLAG(IS_MAC) |
| // 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_basename1 = "New Profile 1"; |
| const std::string profile_basename2 = "New Profile 2"; |
| base::FilePath profile_path1 = |
| temp_dir_.GetPath().AppendASCII(profile_basename1); |
| base::FilePath profile_path2 = |
| temp_dir_.GetPath().AppendASCII(profile_basename2); |
| |
| MockObserver mock_observer; |
| EXPECT_CALL(mock_observer, OnProfileCreated(testing::NotNull())) |
| .Times(testing::AtLeast(1)); |
| EXPECT_CALL(mock_observer, OnProfileInitialized(testing::NotNull())) |
| .Times(testing::AtLeast(1)); |
| CreateProfileAsync(profile_manager, profile_path1, &mock_observer); |
| content::RunAllTasksUntilIdle(); |
| |
| // Track the profile, but don't load it. |
| ProfileAttributesStorage& storage = |
| profile_manager->GetProfileAttributesStorage(); |
| ProfileAttributesInitParams params; |
| params.profile_path = profile_path2; |
| params.profile_name = ASCIIToUTF16(profile_basename2); |
| params.gaia_id = GaiaId("23456"); |
| params.is_consented_primary_account = true; |
| storage.AddProfile(std::move(params)); |
| content::RunAllTasksUntilIdle(); |
| |
| EXPECT_EQ(1u, profile_manager->GetLoadedProfiles().size()); |
| EXPECT_EQ(2u, storage.GetNumberOfProfiles()); |
| |
| // Set the active profile. |
| PrefService* local_state = g_browser_process->local_state(); |
| local_state->SetString(prefs::kProfileLastUsed, profile_basename1); |
| |
| // Delete the active profile. This should switch and load the unloaded |
| // profile. |
| profile_manager->GetDeleteProfileHelper().MaybeScheduleProfileForDeletion( |
| profile_path1, base::DoNothing(), |
| ProfileMetrics::DELETE_PROFILE_USER_MANAGER); |
| |
| content::RunAllTasksUntilIdle(); |
| |
| EXPECT_EQ(profile_path2, profile_manager->GetLastUsedProfile()->GetPath()); |
| EXPECT_EQ(profile_basename2, 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_basename1 = "New Profile 1"; |
| const std::string profile_basename2 = "New Profile 2"; |
| const std::string profile_basename3 = "New Profile 3"; |
| base::FilePath profile_path1 = |
| temp_dir_.GetPath().AppendASCII(profile_basename1); |
| base::FilePath profile_path2 = |
| temp_dir_.GetPath().AppendASCII(profile_basename2); |
| base::FilePath profile_path3 = |
| temp_dir_.GetPath().AppendASCII(profile_basename3); |
| |
| MockObserver mock_observer; |
| EXPECT_CALL(mock_observer, OnProfileCreated(testing::NotNull())) |
| .Times(testing::AtLeast(1)); |
| EXPECT_CALL(mock_observer, OnProfileInitialized(testing::NotNull())) |
| .Times(testing::AtLeast(1)); |
| CreateProfileAsync(profile_manager, profile_path1, &mock_observer); |
| content::RunAllTasksUntilIdle(); |
| |
| // Create the other profiles, but don't load them. Assign a fake avatar icon |
| // to ensure that profiles in the profile attributes storage are sorted by the |
| // profile name, and not randomly by the avatar name. |
| ProfileAttributesStorage& storage = |
| profile_manager->GetProfileAttributesStorage(); |
| ProfileAttributesInitParams params2; |
| params2.profile_path = profile_path2; |
| params2.profile_name = ASCIIToUTF16(profile_basename2); |
| params2.gaia_id = GaiaId("23456"); |
| params2.user_name = ASCIIToUTF16(profile_basename2); |
| params2.is_consented_primary_account = true; |
| params2.icon_index = 1; |
| storage.AddProfile(std::move(params2)); |
| ProfileAttributesInitParams params3; |
| params3.profile_path = profile_path3; |
| params3.profile_name = ASCIIToUTF16(profile_basename3); |
| params3.gaia_id = GaiaId("34567"); |
| params3.user_name = ASCIIToUTF16(profile_basename3); |
| params3.is_consented_primary_account = true; |
| params3.icon_index = 2; |
| storage.AddProfile(std::move(params3)); |
| |
| content::RunAllTasksUntilIdle(); |
| |
| EXPECT_EQ(1u, profile_manager->GetLoadedProfiles().size()); |
| EXPECT_EQ(3u, storage.GetNumberOfProfiles()); |
| |
| // Set the active profile. |
| PrefService* local_state = g_browser_process->local_state(); |
| local_state->SetString(prefs::kProfileLastUsed, |
| profile_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->GetDeleteProfileHelper().MaybeScheduleProfileForDeletion( |
| profile_path1, base::DoNothing(), |
| ProfileMetrics::DELETE_PROFILE_USER_MANAGER); |
| local_state->SetString(prefs::kProfileLastUsed, |
| profile_path2.BaseName().MaybeAsASCII()); |
| profile_manager->GetDeleteProfileHelper().MaybeScheduleProfileForDeletion( |
| profile_path2, base::DoNothing(), |
| ProfileMetrics::DELETE_PROFILE_USER_MANAGER); |
| content::RunAllTasksUntilIdle(); |
| |
| EXPECT_EQ(profile_path3, profile_manager->GetLastUsedProfile()->GetPath()); |
| EXPECT_EQ(profile_basename3, local_state->GetString(prefs::kProfileLastUsed)); |
| } |
| #endif // BUILDFLAG(IS_MAC) |
| |
| TEST_F(ProfileManagerTest, CannotCreateProfileOutsideUserDir) { |
| base::ScopedTempDir non_user_dir; |
| ASSERT_TRUE(non_user_dir.CreateUniqueTempDir()); |
| |
| base::FilePath dest_path = non_user_dir.GetPath(); |
| dest_path = dest_path.Append(FILE_PATH_LITERAL("New Profile")); |
| |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| |
| Profile* profile = profile_manager->GetProfile(dest_path); |
| EXPECT_EQ(nullptr, profile); |
| } |
| |
| TEST_F(ProfileManagerTest, CannotCreateProfileOutsideUserDirAsync) { |
| base::ScopedTempDir non_user_dir; |
| ASSERT_TRUE(non_user_dir.CreateUniqueTempDir()); |
| |
| base::FilePath profile_path = |
| non_user_dir.GetPath().AppendASCII("New Profile"); |
| |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| |
| MockObserver mock_observer; |
| EXPECT_CALL(mock_observer, OnProfileInitialized(nullptr)); |
| |
| CreateProfileAsync(profile_manager, profile_path, &mock_observer); |
| content::RunAllTasksUntilIdle(); |
| } |
| |
| struct ProfileKeepAliveParam { |
| ProfileKeepAliveOrigin origin; |
| bool should_clear_waiting_for_first_browser_window = false; |
| }; |
| |
| constexpr ProfileKeepAliveParam params[] = { |
| // Origins that clears |
| // `ProfileKeepAliveOrigin::kWaitingForFirstBrowserWindow`. |
| {.origin = ProfileKeepAliveOrigin::kBrowserWindow, |
| .should_clear_waiting_for_first_browser_window = true}, |
| {.origin = ProfileKeepAliveOrigin::kProfileCreationFlow, |
| .should_clear_waiting_for_first_browser_window = true}, |
| {.origin = ProfileKeepAliveOrigin::kProfileStatistics, |
| .should_clear_waiting_for_first_browser_window = true}, |
| {.origin = ProfileKeepAliveOrigin::kProfilePickerView, |
| .should_clear_waiting_for_first_browser_window = true}, |
| {.origin = ProfileKeepAliveOrigin::kWaitingForGlicView, |
| .should_clear_waiting_for_first_browser_window = true}, |
| |
| // Origins that do NOT clear |
| // `ProfileKeepAliveOrigin::kWaitingForFirstBrowserWindow`. |
| {.origin = ProfileKeepAliveOrigin::kBackgroundMode, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kOffTheRecordProfile, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kDownloadInProgress, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kClearingBrowsingData, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kAppWindow, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kBackgroundSync, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kNotification, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kPendingNotificationClickEvent, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kInFlightPushMessage, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kSessionRestore, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kChromeViewsDelegate, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kDevToolsWindow, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kWebAppPermissionDialogWindow, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kExtensionUpdater, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kPendingNotificationCloseEvent, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kFeedbackDialog, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kWebAppUpdate, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kGettingWebAppInfo, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kCrxInstaller, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kHistoryMenuBridge, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kProfileCreationSamlFlow, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kProfileDeletionProcess, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kIsolatedWebAppInstall, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kIsolatedWebAppUpdate, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kWebAppUninstall, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kOsIntegrationForceUnregistration, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kRemoteDebugging, |
| .should_clear_waiting_for_first_browser_window = false}, |
| {.origin = ProfileKeepAliveOrigin::kHeadlessCommand, |
| .should_clear_waiting_for_first_browser_window = false}, |
| }; |
| |
| std::string ParamsToTestSuffix( |
| const ::testing::TestParamInfo<ProfileKeepAliveParam>& info) { |
| std::stringstream stream; |
| stream << info.param.origin; |
| return stream.str(); |
| } |
| |
| class ProfileManagerTestWithParam |
| : public ProfileManagerTest, |
| public testing::WithParamInterface<ProfileKeepAliveParam> { |
| public: |
| ProfileManagerTestWithParam() { |
| scoped_feature_list_.InitWithFeatures( |
| {features::kDestroySystemProfiles, |
| features::kDestroyProfileOnBrowserClose}, |
| {}); |
| } |
| |
| private: |
| base::test::ScopedFeatureList scoped_feature_list_; |
| }; |
| |
| TEST_P(ProfileManagerTestWithParam, ScopedProfileKeepAlive) { |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| |
| base::FilePath dest_path = temp_dir_.GetPath().AppendASCII("New Profile"); |
| Profile* profile = profile_manager->GetProfile(dest_path); |
| |
| // Starts with a kWaitingForFirstBrowserWindow ref. |
| EXPECT_THAT(profile_manager->GetProfileInfoByPath(dest_path)->keep_alives, |
| ::testing::ElementsAre(std::pair<ProfileKeepAliveOrigin, int>( |
| ProfileKeepAliveOrigin::kWaitingForFirstBrowserWindow, 1))); |
| |
| { |
| // Set |profile| refcount to 1. If this added keep alive has an origin that |
| // should remove the `kWaitingForFirstBrowserWindow` keep alive, it will |
| // cause the profile to get deleted at the end of this block. |
| ScopedProfileKeepAlive keep_alive(profile, GetParam().origin); |
| |
| // We added a keep alive that should be part of the list of keep alives. |
| // Whether `kWaitingForFirstBrowserWindow` ref is removed depends on |
| // `GetParam().should_clear_waiting_for_first_browser_window`. |
| EXPECT_THAT( |
| profile_manager->GetProfileInfoByPath(dest_path)->keep_alives, |
| ::testing::UnorderedElementsAre( |
| std::pair<ProfileKeepAliveOrigin, int>( |
| ProfileKeepAliveOrigin::kWaitingForFirstBrowserWindow, |
| GetParam().should_clear_waiting_for_first_browser_window ? 0 |
| : 1), |
| std::pair<ProfileKeepAliveOrigin, int>(GetParam().origin, 1))); |
| } |
| |
| base::RunLoop().RunUntilIdle(); |
| if (GetParam().should_clear_waiting_for_first_browser_window) { |
| #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS) |
| // Profile* should've been destroyed by now. |
| EXPECT_EQ(nullptr, profile_manager->GetProfileByPath(dest_path)); |
| #endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS) |
| } else { |
| // `profile` is still valid since `kWaitingForFirstBrowserWindow` was not |
| // cleared. |
| EXPECT_EQ(profile, profile_manager->GetProfileByPath(dest_path)); |
| } |
| } |
| |
| INSTANTIATE_TEST_SUITE_P(, |
| ProfileManagerTestWithParam, |
| testing::ValuesIn(params), |
| &ParamsToTestSuffix); |
| |
| TEST_F(ProfileManagerTest, ProfileCountRecordedAtProfileInit) { |
| using base::Bucket; |
| using base::BucketsAre; |
| |
| base::HistogramTester histogram_tester; |
| const std::string kHistogramName = "Profile.NumberOfProfilesAtProfileInit"; |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| base::FilePath dest_path = temp_dir_.GetPath(); |
| |
| base::FilePath path_1 = dest_path.Append(FILE_PATH_LITERAL("Profile 1")); |
| profile_manager->GetProfile(path_1); |
| EXPECT_THAT(histogram_tester.GetAllSamples(kHistogramName), |
| BucketsAre(Bucket(1, 1))); |
| |
| Profile* profile_2 = profile_manager->GetProfile( |
| dest_path.Append(FILE_PATH_LITERAL("Profile 2"))); |
| EXPECT_EQ(profile_manager->GetNumberOfProfiles(), 2u); |
| EXPECT_THAT(histogram_tester.GetAllSamples(kHistogramName), |
| BucketsAre(Bucket(1, 1), Bucket(2, 1))); |
| |
| // Incognito profile should not affect the count. |
| EXPECT_TRUE(profile_2->GetPrimaryOTRProfile(/*create_if_needed=*/true)); |
| EXPECT_THAT(histogram_tester.GetAllSamples(kHistogramName), |
| BucketsAre(Bucket(1, 1), Bucket(2, 1))); |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| // Delete one profile to decrement the count. |
| profile_manager->GetDeleteProfileHelper().MaybeScheduleProfileForDeletion( |
| path_1, base::DoNothing(), ProfileMetrics::DELETE_PROFILE_USER_MANAGER); |
| content::RunAllTasksUntilIdle(); |
| |
| profile_manager->GetProfile(dest_path.Append(FILE_PATH_LITERAL("Profile 3"))); |
| EXPECT_THAT(histogram_tester.GetAllSamples(kHistogramName), |
| BucketsAre(Bucket(1, 1), Bucket(2, 2))); |
| #endif // !BUILDFLAG(IS_ANDROID) |
| } |