// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/profiles/profile_info_cache.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile_manager.h" #include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" namespace { // The ProfileMetadataEntry accessors aren't just plain old accessors to local // members so they'll be tested. The following helpers will make the testing // code less verbose. #define TEST_ACCESSORS(entry_type, entry, member, first_value, second_value) \ TestAccessors(&entry, \ &entry_type::Get ## member, \ &entry_type::Set ## member, \ first_value, \ second_value); #define TEST_STRING16_ACCESSORS(entry_type, entry, member) \ TEST_ACCESSORS(entry_type, entry, member, \ base::ASCIIToUTF16("first_" #member "_value"), \ base::ASCIIToUTF16("second_" #member "_value")); #define TEST_STRING_ACCESSORS(entry_type, entry, member) \ TEST_ACCESSORS(entry_type, entry, member, \ std::string("first_" #member "_value"), \ std::string("second_" #member "_value")); #define TEST_BOOL_ACCESSORS(entry_type, entry, member) \ TestAccessors(&entry, \ &entry_type::member, \ &entry_type::Set ## member, \ false, \ true); #define TEST_STAT_ACCESSORS(entry_type, entry, member) \ TestStatAccessors(&entry, \ &entry_type::Has ## member, \ &entry_type::Get ## member, \ &entry_type::Set ## member, \ 10, \ 20); template void TestAccessors(ProfileAttributesEntry** entry, TGetter getter_func, TSetter setter_func, TValue first_value, TValue second_value) { (*entry->*setter_func)(first_value); EXPECT_EQ(first_value, (*entry->*getter_func)()); (*entry->*setter_func)(second_value); EXPECT_EQ(second_value, (*entry->*getter_func)()); } template void TestStatAccessors(ProfileAttributesEntry** entry, TExist exist_func, TGetter getter_func, TSetter setter_func, TValue first_value, TValue second_value) { EXPECT_FALSE((*entry->*exist_func)()); (*entry->*setter_func)(first_value); EXPECT_TRUE((*entry->*exist_func)()); EXPECT_EQ(first_value, (*entry->*getter_func)()); (*entry->*setter_func)(second_value); EXPECT_TRUE((*entry->*exist_func)()); EXPECT_EQ(second_value, (*entry->*getter_func)()); } } // namespace class ProfileAttributesStorageTest : public testing::Test { public: ProfileAttributesStorageTest() : testing_profile_manager_(TestingBrowserProcess::GetGlobal()) {} ~ProfileAttributesStorageTest() override {} protected: void SetUp() override { ASSERT_TRUE(testing_profile_manager_.SetUp()); } void TearDown() override { } base::FilePath GetProfilePath(const std::string& base_name) { return testing_profile_manager_.profile_manager()->user_data_dir(). AppendASCII(base_name); } ProfileAttributesStorage* storage() { return profile_info_cache(); } ProfileInfoCache* profile_info_cache() { return testing_profile_manager_.profile_info_cache(); } void AddTestingProfile() { unsigned long number_of_profiles = static_cast(storage()->GetNumberOfProfiles()); storage()->AddProfile( GetProfilePath( base::StringPrintf("testing_profile_path%lu", number_of_profiles)), base::ASCIIToUTF16( base::StringPrintf("testing_profile_name%lu", number_of_profiles)), std::string( base::StringPrintf("testing_profile_gaia%lu", number_of_profiles)), base::ASCIIToUTF16( base::StringPrintf("testing_profile_user%lu", number_of_profiles)), number_of_profiles, std::string("")); EXPECT_EQ(number_of_profiles + 1, storage()->GetNumberOfProfiles()); } private: TestingProfileManager testing_profile_manager_; content::TestBrowserThreadBundle thread_bundle_; }; TEST_F(ProfileAttributesStorageTest, ProfileNotFound) { EXPECT_EQ(0U, storage()->GetNumberOfProfiles()); ProfileAttributesEntry* entry; ASSERT_FALSE(storage()->GetProfileAttributesWithPath( GetProfilePath("testing_profile_path0"), &entry)); AddTestingProfile(); EXPECT_EQ(1U, storage()->GetNumberOfProfiles()); ASSERT_TRUE(storage()->GetProfileAttributesWithPath( GetProfilePath("testing_profile_path0"), &entry)); ASSERT_FALSE(storage()->GetProfileAttributesWithPath( GetProfilePath("testing_profile_path1"), &entry)); } TEST_F(ProfileAttributesStorageTest, AddProfile) { EXPECT_EQ(0U, storage()->GetNumberOfProfiles()); storage()->AddProfile(GetProfilePath("new_profile_path_1"), base::ASCIIToUTF16("new_profile_name_1"), std::string("new_profile_gaia_1"), base::ASCIIToUTF16("new_profile_username_1"), 1, std::string("")); EXPECT_EQ(1U, storage()->GetNumberOfProfiles()); ProfileAttributesEntry* entry; ASSERT_TRUE(storage()->GetProfileAttributesWithPath( GetProfilePath("new_profile_path_1"), &entry)); EXPECT_EQ(base::ASCIIToUTF16("new_profile_name_1"), entry->GetName()); } TEST_F(ProfileAttributesStorageTest, RemoveProfile) { EXPECT_EQ(0U, storage()->GetNumberOfProfiles()); ProfileAttributesEntry* entry; ASSERT_FALSE(storage()->GetProfileAttributesWithPath( GetProfilePath("testing_profile_path0"), &entry)); AddTestingProfile(); EXPECT_EQ(1U, storage()->GetNumberOfProfiles()); // Deleting an existing profile should make it un-retrievable. storage()->RemoveProfile(GetProfilePath("testing_profile_path0")); EXPECT_EQ(0U, storage()->GetNumberOfProfiles()); ASSERT_FALSE(storage()->GetProfileAttributesWithPath( GetProfilePath("testing_profile_path1"), &entry)); ASSERT_FALSE(storage()->GetProfileAttributesWithPath( GetProfilePath("testing_profile_path1"), &entry)); } TEST_F(ProfileAttributesStorageTest, MultipleProfiles) { EXPECT_EQ(0U, storage()->GetNumberOfProfiles()); for (size_t i = 0; i < 5; ++i) { AddTestingProfile(); EXPECT_EQ(i + 1, storage()->GetNumberOfProfiles()); std::vector entries = storage()->GetAllProfilesAttributes(); EXPECT_EQ(i + 1, entries.size()); } EXPECT_EQ(5U, storage()->GetNumberOfProfiles()); ProfileAttributesEntry* entry; ASSERT_TRUE(storage()->GetProfileAttributesWithPath( GetProfilePath("testing_profile_path0"), &entry)); EXPECT_EQ(base::ASCIIToUTF16("testing_profile_name0"), entry->GetName()); storage()->RemoveProfile(GetProfilePath("testing_profile_path0")); ASSERT_FALSE(storage()->GetProfileAttributesWithPath( GetProfilePath("testing_profile_path0"), &entry)); EXPECT_EQ(4U, storage()->GetNumberOfProfiles()); std::vector entries = storage()->GetAllProfilesAttributes(); for (auto& entry : entries) { EXPECT_NE(GetProfilePath("testing_profile_path0"), entry->GetPath()); } } TEST_F(ProfileAttributesStorageTest, InitialValues) { AddTestingProfile(); ProfileAttributesEntry* entry; ASSERT_TRUE(storage()->GetProfileAttributesWithPath( GetProfilePath("testing_profile_path0"), &entry)); EXPECT_EQ(GetProfilePath("testing_profile_path0"), entry->GetPath()); EXPECT_EQ(base::ASCIIToUTF16("testing_profile_name0"), entry->GetName()); EXPECT_EQ(std::string("testing_profile_gaia0"), entry->GetGAIAId()); EXPECT_EQ(base::ASCIIToUTF16("testing_profile_user0"), entry->GetUserName()); EXPECT_EQ(0U, entry->GetAvatarIconIndex()); EXPECT_EQ(std::string(""), entry->GetSupervisedUserId()); } TEST_F(ProfileAttributesStorageTest, EntryAccessors) { AddTestingProfile(); ProfileAttributesEntry* entry; ASSERT_TRUE(storage()->GetProfileAttributesWithPath( GetProfilePath("testing_profile_path0"), &entry)); EXPECT_EQ(GetProfilePath("testing_profile_path0"), entry->GetPath()); TEST_STRING16_ACCESSORS(ProfileAttributesEntry, entry, Name); TEST_STRING16_ACCESSORS(ProfileAttributesEntry, entry, ShortcutName); TEST_STRING_ACCESSORS(ProfileAttributesEntry, entry, LocalAuthCredentials); TEST_STRING_ACCESSORS( ProfileAttributesEntry, entry, PasswordChangeDetectionToken); TEST_ACCESSORS(ProfileAttributesEntry, entry, BackgroundStatus, false, true); TEST_STRING16_ACCESSORS(ProfileAttributesEntry, entry, GAIAName); TEST_STRING16_ACCESSORS(ProfileAttributesEntry, entry, GAIAGivenName); TEST_BOOL_ACCESSORS(ProfileAttributesEntry, entry, IsUsingGAIAPicture); TEST_BOOL_ACCESSORS(ProfileAttributesEntry, entry, IsOmitted); TEST_BOOL_ACCESSORS(ProfileAttributesEntry, entry, IsSigninRequired); TEST_STRING_ACCESSORS(ProfileAttributesEntry, entry, SupervisedUserId); TEST_BOOL_ACCESSORS(ProfileAttributesEntry, entry, IsEphemeral); TEST_BOOL_ACCESSORS(ProfileAttributesEntry, entry, IsUsingDefaultName); TEST_BOOL_ACCESSORS(ProfileAttributesEntry, entry, IsUsingDefaultAvatar); TEST_BOOL_ACCESSORS(ProfileAttributesEntry, entry, IsAuthError); TEST_STAT_ACCESSORS(ProfileAttributesEntry, entry, StatsBrowsingHistory); TEST_STAT_ACCESSORS(ProfileAttributesEntry, entry, StatsBookmarks); TEST_STAT_ACCESSORS(ProfileAttributesEntry, entry, StatsPasswords); TEST_STAT_ACCESSORS(ProfileAttributesEntry, entry, StatsSettings); } TEST_F(ProfileAttributesStorageTest, AuthInfo) { AddTestingProfile(); ProfileAttributesEntry* entry; ASSERT_TRUE(storage()->GetProfileAttributesWithPath( GetProfilePath("testing_profile_path0"), &entry)); entry->SetAuthInfo("", base::string16()); ASSERT_FALSE(entry->IsAuthenticated()); EXPECT_EQ(base::string16(), entry->GetUserName()); EXPECT_EQ("", entry->GetGAIAId()); entry->SetAuthInfo("foo", base::ASCIIToUTF16("bar")); ASSERT_TRUE(entry->IsAuthenticated()); EXPECT_EQ(base::ASCIIToUTF16("bar"), entry->GetUserName()); EXPECT_EQ("foo", entry->GetGAIAId()); } TEST_F(ProfileAttributesStorageTest, SupervisedUsersAccessors) { AddTestingProfile(); ProfileAttributesEntry* entry; ASSERT_TRUE(storage()->GetProfileAttributesWithPath( GetProfilePath("testing_profile_path0"), &entry)); entry->SetSupervisedUserId(""); ASSERT_FALSE(entry->IsSupervised()); ASSERT_FALSE(entry->IsChild()); ASSERT_FALSE(entry->IsLegacySupervised()); entry->SetSupervisedUserId("some_supervised_user_id"); ASSERT_TRUE(entry->IsSupervised()); ASSERT_FALSE(entry->IsChild()); ASSERT_TRUE(entry->IsLegacySupervised()); entry->SetSupervisedUserId(supervised_users::kChildAccountSUID); ASSERT_TRUE(entry->IsSupervised()); ASSERT_TRUE(entry->IsChild()); ASSERT_FALSE(entry->IsLegacySupervised()); } TEST_F(ProfileAttributesStorageTest, ReSortTriggered) { storage()->AddProfile(GetProfilePath("alpha_path"), base::ASCIIToUTF16("alpha"), std::string("alpha_gaia"), base::ASCIIToUTF16("alpha_username"), 1, std::string("")); storage()->AddProfile(GetProfilePath("lima_path"), base::ASCIIToUTF16("lima"), std::string("lima_gaia"), base::ASCIIToUTF16("lima_username"), 1, std::string("")); ProfileAttributesEntry* entry; ASSERT_TRUE(storage()->GetProfileAttributesWithPath( GetProfilePath("alpha_path"), &entry)); // Trigger a ProfileInfoCache re-sort. entry->SetName(base::ASCIIToUTF16("zulu_name")); EXPECT_EQ(GetProfilePath("alpha_path"), entry->GetPath()); } TEST_F(ProfileAttributesStorageTest, RemoveOtherProfile) { AddTestingProfile(); AddTestingProfile(); AddTestingProfile(); EXPECT_EQ(3U, storage()->GetNumberOfProfiles()); ProfileAttributesEntry* first_entry; ASSERT_TRUE(storage()->GetProfileAttributesWithPath( GetProfilePath("testing_profile_path0"), &first_entry)); ProfileAttributesEntry* second_entry; ASSERT_TRUE(storage()->GetProfileAttributesWithPath( GetProfilePath("testing_profile_path1"), &second_entry)); EXPECT_EQ( base::ASCIIToUTF16("testing_profile_name0"), first_entry->GetName()); storage()->RemoveProfile(GetProfilePath("testing_profile_path1")); ASSERT_FALSE(storage()->GetProfileAttributesWithPath( GetProfilePath("testing_profile_path1"), &second_entry)); EXPECT_EQ(GetProfilePath("testing_profile_path0"), first_entry->GetPath()); EXPECT_EQ( base::ASCIIToUTF16("testing_profile_name0"), first_entry->GetName()); // Deleting through the ProfileInfoCache should be reflected in the // ProfileAttributesStorage as well. profile_info_cache()->RemoveProfile( GetProfilePath("testing_profile_path2")); ASSERT_FALSE(storage()->GetProfileAttributesWithPath( GetProfilePath("testing_profile_path2"), &second_entry)); } TEST_F(ProfileAttributesStorageTest, AccessFromElsewhere) { AddTestingProfile(); ProfileAttributesEntry* first_entry; ASSERT_TRUE(storage()->GetProfileAttributesWithPath( GetProfilePath("testing_profile_path0"), &first_entry)); ProfileAttributesEntry* second_entry; ASSERT_TRUE(storage()->GetProfileAttributesWithPath( GetProfilePath("testing_profile_path0"), &second_entry)); first_entry->SetName(base::ASCIIToUTF16("NewName")); EXPECT_EQ(base::ASCIIToUTF16("NewName"), second_entry->GetName()); EXPECT_EQ(first_entry, second_entry); // The ProfileInfoCache should also reflect the changes and its changes // should be reflected by the ProfileAttributesStorage. size_t index = profile_info_cache()->GetIndexOfProfileWithPath( GetProfilePath("testing_profile_path0")); EXPECT_EQ(base::ASCIIToUTF16("NewName"), profile_info_cache()->GetNameOfProfileAtIndex(index)); profile_info_cache()->SetNameOfProfileAtIndex( index, base::ASCIIToUTF16("OtherNewName")); EXPECT_EQ(base::ASCIIToUTF16("OtherNewName"), first_entry->GetName()); }