| // Copyright 2016 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 "chrome/browser/ui/webui/settings/settings_manage_profile_handler.h" |
| |
| #include "base/strings/utf_string_conversions.h" |
| #include "chrome/browser/profiles/profile_attributes_entry.h" |
| #include "chrome/browser/profiles/profile_avatar_icon_util.h" |
| #include "chrome/browser/ui/signin/profile_colors_util.h" |
| #include "chrome/browser/ui/ui_features.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/test/base/testing_browser_process.h" |
| #include "chrome/test/base/testing_profile_manager.h" |
| #include "components/prefs/pref_service.h" |
| #include "content/public/browser/web_ui_data_source.h" |
| #include "content/public/test/browser_task_environment.h" |
| #include "content/public/test/test_web_ui.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/base/webui/web_ui_util.h" |
| #include "ui/gfx/image/image_unittest_util.h" |
| |
| namespace settings { |
| |
| namespace { |
| |
| class TestManageProfileHandler : public ManageProfileHandler { |
| public: |
| explicit TestManageProfileHandler(Profile* profile) |
| : ManageProfileHandler(profile) {} |
| |
| using ManageProfileHandler::set_web_ui; |
| using ManageProfileHandler::AllowJavascript; |
| }; |
| |
| } // namespace |
| |
| class ManageProfileHandlerTest : public testing::Test { |
| public: |
| ManageProfileHandlerTest() |
| : profile_manager_(TestingBrowserProcess::GetGlobal()) {} |
| |
| void SetUp() override { |
| ASSERT_TRUE(profile_manager_.SetUp()); |
| profile_ = profile_manager_.CreateTestingProfile("Profile 1"); |
| ASSERT_TRUE( |
| profile_manager_.profile_attributes_storage() |
| ->GetProfileAttributesWithPath(profile_->GetPath(), &entry_)); |
| entry_->SetAvatarIconIndex(profiles::GetPlaceholderAvatarIndex()); |
| |
| handler_ = std::make_unique<TestManageProfileHandler>(profile_); |
| handler_->set_web_ui(&web_ui_); |
| handler()->AllowJavascript(); |
| web_ui()->ClearTrackedCalls(); |
| } |
| |
| void SetSignedInProfile() { |
| gfx::Image gaia_image(gfx::test::CreateImage(256, 256)); |
| entry()->SetAuthInfo("gaia_id", base::UTF8ToUTF16("user@gmail.com"), false); |
| entry()->SetGAIAPicture("GAIA_IMAGE_URL_WITH_SIZE", gaia_image); |
| EXPECT_TRUE(entry()->IsUsingDefaultAvatar()); |
| EXPECT_TRUE(entry()->IsUsingGAIAPicture()); |
| } |
| |
| void VerifyIconListWithOnlyCustomAvatars(const base::Value* value, |
| size_t selected_index) { |
| VerifyIconList(value, selected_index, false, false, false); |
| } |
| |
| void VerifyIconList(const base::Value* value, |
| size_t selected_index, |
| bool gaia_included, |
| bool gaia_selected, |
| bool default_avatar_included) { |
| const base::ListValue* icons = nullptr; |
| ASSERT_TRUE(value->GetAsList(&icons)); |
| |
| // Expect a non-empty list of dictionaries containing non-empty strings for |
| // profile avatar icon urls and labels. |
| EXPECT_FALSE(icons->empty()); |
| size_t i = (gaia_included || default_avatar_included) ? 1 : 0; |
| if (gaia_included) { |
| ASSERT_FALSE(default_avatar_included); |
| VerifyGaiaAvatar(icons, gaia_selected); |
| } else if (default_avatar_included) { |
| VerifyDefaultGenericAvatar(icons, selected_index); |
| } |
| bool selected_found = |
| gaia_selected || |
| (selected_index == profiles::GetPlaceholderAvatarIndex()); |
| |
| for (; i < icons->GetSize(); ++i) { |
| const base::DictionaryValue* icon = nullptr; |
| EXPECT_TRUE(icons->GetDictionary(i, &icon)); |
| std::string icon_url; |
| EXPECT_TRUE(icon->GetString("url", &icon_url)); |
| EXPECT_FALSE(icon_url.empty()); |
| int icon_index_int = *icon->FindIntPath("index"); |
| EXPECT_TRUE(profiles::IsDefaultAvatarIconIndex(icon_index_int)); |
| size_t icon_index = static_cast<size_t>(icon_index_int); |
| EXPECT_NE(icon_index, profiles::GetPlaceholderAvatarIndex()); |
| EXPECT_NE(icon_index_int, 0); |
| size_t url_icon_index; |
| EXPECT_TRUE(profiles::IsDefaultAvatarIconUrl(icon_url, &url_icon_index)); |
| EXPECT_EQ(icon_index, url_icon_index); |
| EXPECT_TRUE(!icon->FindStringPath("label")->empty()); |
| base::Optional<bool> current_selected = icon->FindBoolPath("selected"); |
| if (selected_index == icon_index) { |
| EXPECT_FALSE(selected_found); |
| EXPECT_TRUE(current_selected.value_or(false)); |
| selected_found = true; |
| } else { |
| EXPECT_FALSE(current_selected.value_or(false)); |
| } |
| } |
| |
| EXPECT_TRUE(selected_index == 0 || selected_found); |
| } |
| |
| content::TestWebUI* web_ui() { return &web_ui_; } |
| Profile* profile() const { return profile_; } |
| ProfileAttributesEntry* entry() const { return entry_; } |
| TestManageProfileHandler* handler() const { return handler_.get(); } |
| |
| private: |
| content::BrowserTaskEnvironment task_environment_; |
| TestingProfileManager profile_manager_; |
| ProfileAttributesEntry* entry_ = nullptr; |
| content::TestWebUI web_ui_; |
| |
| Profile* profile_ = nullptr; |
| std::unique_ptr<TestManageProfileHandler> handler_; |
| |
| void VerifyGaiaAvatar(const base::ListValue* icons, bool gaia_selected) { |
| const base::DictionaryValue* icon = nullptr; |
| EXPECT_TRUE(icons->GetDictionary(0, &icon)); |
| EXPECT_EQ(*icon->FindIntPath("index"), 0); |
| |
| const gfx::Image* avatar_icon = entry()->GetGAIAPicture(); |
| ASSERT_TRUE(avatar_icon); |
| EXPECT_EQ( |
| *icon->FindStringPath("url"), |
| webui::GetBitmapDataUrl( |
| profiles::GetAvatarIconForWebUI(*avatar_icon, true).AsBitmap())); |
| EXPECT_TRUE(!icon->FindStringPath("label")->empty()); |
| EXPECT_EQ(*icon->FindBoolPath("selected"), gaia_selected); |
| } |
| |
| void VerifyDefaultGenericAvatar(const base::ListValue* icons, |
| size_t selected_index) { |
| const base::DictionaryValue* icon = nullptr; |
| EXPECT_TRUE(icons->GetDictionary(0, &icon)); |
| EXPECT_TRUE(!icon->FindStringPath("label")->empty()); |
| int icon_index_int = icon->FindIntPath("index").value_or(0); |
| EXPECT_TRUE(icon_index_int != 0); |
| size_t icon_index = static_cast<size_t>(icon_index_int); |
| EXPECT_EQ(icon_index, profiles::GetPlaceholderAvatarIndex()); |
| EXPECT_EQ(*icon->FindBoolPath("selected"), selected_index == icon_index); |
| } |
| }; |
| |
| TEST_F(ManageProfileHandlerTest, HandleSetProfileIconToGaiaAvatar) { |
| handler()->HandleSetProfileIconToGaiaAvatar(nullptr); |
| |
| PrefService* pref_service = profile()->GetPrefs(); |
| EXPECT_FALSE(pref_service->GetBoolean(prefs::kProfileUsingDefaultAvatar)); |
| EXPECT_TRUE(pref_service->GetBoolean(prefs::kProfileUsingGAIAAvatar)); |
| } |
| |
| TEST_F(ManageProfileHandlerTest, HandleSetProfileIconToDefaultCustomAvatar) { |
| base::ListValue list_args; |
| list_args.AppendInteger(15); |
| handler()->HandleSetProfileIconToDefaultAvatar(&list_args); |
| |
| PrefService* pref_service = profile()->GetPrefs(); |
| EXPECT_EQ(15, pref_service->GetInteger(prefs::kProfileAvatarIndex)); |
| EXPECT_FALSE(pref_service->GetBoolean(prefs::kProfileUsingDefaultAvatar)); |
| EXPECT_FALSE(pref_service->GetBoolean(prefs::kProfileUsingGAIAAvatar)); |
| } |
| |
| TEST_F(ManageProfileHandlerTest, HandleSetProfileIconToDefaultGenericAvatar) { |
| int generic_avatar_index = profiles::GetPlaceholderAvatarIndex(); |
| base::ListValue list_args; |
| list_args.AppendInteger(generic_avatar_index); |
| handler()->HandleSetProfileIconToDefaultAvatar(&list_args); |
| |
| PrefService* pref_service = profile()->GetPrefs(); |
| EXPECT_EQ(generic_avatar_index, |
| pref_service->GetInteger(prefs::kProfileAvatarIndex)); |
| EXPECT_TRUE(pref_service->GetBoolean(prefs::kProfileUsingDefaultAvatar)); |
| EXPECT_FALSE(pref_service->GetBoolean(prefs::kProfileUsingGAIAAvatar)); |
| } |
| |
| TEST_F(ManageProfileHandlerTest, HandleSetProfileName) { |
| base::ListValue list_args; |
| list_args.AppendString("New Profile Name"); |
| handler()->HandleSetProfileName(&list_args); |
| |
| PrefService* pref_service = profile()->GetPrefs(); |
| EXPECT_EQ("New Profile Name", pref_service->GetString(prefs::kProfileName)); |
| } |
| |
| TEST_F(ManageProfileHandlerTest, HandleGetAvailableIcons) { |
| // Set avatar icon will trigger avatar icons updated event. |
| entry()->SetIsUsingDefaultAvatar(false); |
| entry()->SetAvatarIconIndex(27); |
| EXPECT_EQ(1U, web_ui()->call_data().size()); |
| web_ui()->ClearTrackedCalls(); |
| |
| base::ListValue list_args_1; |
| list_args_1.AppendString("get-icons-callback-id"); |
| handler()->HandleGetAvailableIcons(&list_args_1); |
| |
| EXPECT_EQ(1U, web_ui()->call_data().size()); |
| |
| const content::TestWebUI::CallData& data_1 = *web_ui()->call_data().back(); |
| EXPECT_EQ("cr.webUIResponse", data_1.function_name()); |
| EXPECT_EQ("get-icons-callback-id", data_1.arg1()->GetString()); |
| |
| VerifyIconListWithOnlyCustomAvatars(data_1.arg3(), 27); |
| } |
| |
| TEST_F(ManageProfileHandlerTest, HandleGetAvailableIconsOldIconSelected) { |
| // Set avatar icon will trigger avatar icons updated event. |
| entry()->SetAvatarIconIndex(7); |
| EXPECT_EQ(1U, web_ui()->call_data().size()); |
| web_ui()->ClearTrackedCalls(); |
| |
| base::ListValue list_args; |
| list_args.AppendString("get-icons-callback-id"); |
| handler()->HandleGetAvailableIcons(&list_args); |
| |
| EXPECT_EQ(1U, web_ui()->call_data().size()); |
| |
| const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); |
| EXPECT_EQ("cr.webUIResponse", data.function_name()); |
| EXPECT_EQ("get-icons-callback-id", data.arg1()->GetString()); |
| |
| VerifyIconListWithOnlyCustomAvatars(data.arg3(), 0); |
| } |
| |
| TEST_F(ManageProfileHandlerTest, GetAvailableIconsSignedInProfile) { |
| SetSignedInProfile(); |
| EXPECT_TRUE(entry()->IsUsingDefaultAvatar()); |
| EXPECT_TRUE(entry()->IsUsingGAIAPicture()); |
| web_ui()->ClearTrackedCalls(); |
| |
| base::ListValue list_args; |
| list_args.AppendString("get-icons-callback-id"); |
| handler()->HandleGetAvailableIcons(&list_args); |
| |
| EXPECT_EQ(1U, web_ui()->call_data().size()); |
| |
| const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); |
| EXPECT_EQ("cr.webUIResponse", data.function_name()); |
| |
| EXPECT_EQ("get-icons-callback-id", data.arg1()->GetString()); |
| VerifyIconList(data.arg3(), /*selected_index=*/0, |
| /*gaia_included=*/true, |
| /*gaia_selected=*/true, |
| /*default_avatar_included=*/false); |
| |
| web_ui()->ClearTrackedCalls(); |
| |
| // Set custom avatar |
| entry()->SetIsUsingDefaultAvatar(false); |
| entry()->SetAvatarIconIndex(30); |
| |
| const content::TestWebUI::CallData& data_1 = *web_ui()->call_data().back(); |
| EXPECT_EQ("cr.webUIListenerCallback", data_1.function_name()); |
| |
| EXPECT_EQ("available-icons-changed", data_1.arg1()->GetString()); |
| VerifyIconList(data_1.arg2(), /*selected_index=*/30, |
| /*gaia_included=*/true, |
| /*gaia_selected=*/false, |
| /*default_avatar_included=*/false); |
| |
| // Sign out. |
| entry()->SetAuthInfo("", base::string16(), false); |
| entry()->SetGAIAPicture(std::string(), gfx::Image()); |
| |
| const content::TestWebUI::CallData& data_2 = *web_ui()->call_data().back(); |
| EXPECT_EQ("cr.webUIListenerCallback", data_2.function_name()); |
| |
| EXPECT_EQ("available-icons-changed", data_2.arg1()->GetString()); |
| VerifyIconList(data_2.arg2(), /*selected_index=*/30, |
| /*gaia_included=*/false, |
| /*gaia_selected=*/false, |
| /*default_avatar_included=*/false); |
| } |
| |
| TEST_F(ManageProfileHandlerTest, GetAvailableIconsLocalProfile) { |
| base::test::ScopedFeatureList scoped_feature_list; |
| scoped_feature_list.InitAndEnableFeature(features::kNewProfilePicker); |
| EXPECT_FALSE(entry()->IsUsingGAIAPicture()); |
| EXPECT_EQ(entry()->GetAvatarIconIndex(), |
| profiles::GetPlaceholderAvatarIndex()); |
| |
| base::ListValue list_args; |
| list_args.AppendString("get-icons-callback-id"); |
| handler()->HandleGetAvailableIcons(&list_args); |
| |
| EXPECT_EQ(1U, web_ui()->call_data().size()); |
| |
| const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); |
| EXPECT_EQ("cr.webUIResponse", data.function_name()); |
| |
| std::string callback_id = data.arg1()->GetString(); |
| EXPECT_EQ("get-icons-callback-id", callback_id); |
| VerifyIconList(data.arg3(), /*selected_index=*/entry()->GetAvatarIconIndex(), |
| /*gaia_included=*/false, |
| /*gaia_selected=*/false, |
| /*default_avatar_included=*/true); |
| |
| // Sign in. |
| SetSignedInProfile(); |
| EXPECT_TRUE(entry()->IsUsingGAIAPicture()); |
| const content::TestWebUI::CallData& data_1 = *web_ui()->call_data().back(); |
| EXPECT_EQ("cr.webUIListenerCallback", data_1.function_name()); |
| |
| EXPECT_EQ("available-icons-changed", data_1.arg1()->GetString()); |
| VerifyIconList(data_1.arg2(), /*selected_index=*/0, |
| /*gaia_included=*/true, |
| /*gaia_selected=*/true, |
| /*default_avatar_included=*/false); |
| } |
| |
| TEST_F(ManageProfileHandlerTest, ProfileAvatarChangedWebUIEvent) { |
| entry()->SetIsUsingDefaultAvatar(false); |
| entry()->SetAvatarIconIndex(27); |
| |
| EXPECT_EQ(1U, web_ui()->call_data().size()); |
| |
| const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); |
| EXPECT_EQ("cr.webUIListenerCallback", data.function_name()); |
| |
| EXPECT_EQ("available-icons-changed", data.arg1()->GetString()); |
| VerifyIconListWithOnlyCustomAvatars(data.arg2(), 27); |
| } |
| |
| TEST_F(ManageProfileHandlerTest, ProfileThemeColorsChangedWebUIEvent) { |
| base::test::ScopedFeatureList scoped_feature_list; |
| scoped_feature_list.InitAndEnableFeature(features::kNewProfilePicker); |
| ProfileThemeColors colors = {SK_ColorTRANSPARENT, SK_ColorBLACK, |
| SK_ColorWHITE}; |
| entry()->SetProfileThemeColors(colors); |
| |
| // The expected number of calls are two, since the profile avatar has changed |
| // along with the color, as the current profile avatar is the generic colored |
| // avatar. |
| EXPECT_EQ(2U, web_ui()->call_data().size()); |
| |
| const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); |
| EXPECT_EQ("cr.webUIListenerCallback", data.function_name()); |
| EXPECT_EQ("available-icons-changed", data.arg1()->GetString()); |
| VerifyIconList(data.arg2(), /*selected_index=*/entry()->GetAvatarIconIndex(), |
| /*gaia_included=*/false, |
| /*gaia_selected=*/false, |
| /*default_avatar_included=*/true); |
| |
| // Set custom avatar. |
| entry()->SetIsUsingDefaultAvatar(false); |
| entry()->SetAvatarIconIndex(37); |
| web_ui()->ClearTrackedCalls(); |
| |
| entry()->SetProfileThemeColors(base::nullopt); |
| EXPECT_EQ(1U, web_ui()->call_data().size()); |
| |
| const content::TestWebUI::CallData& data_1 = *web_ui()->call_data().back(); |
| EXPECT_EQ("cr.webUIListenerCallback", data_1.function_name()); |
| EXPECT_EQ("available-icons-changed", data_1.arg1()->GetString()); |
| VerifyIconList(data_1.arg2(), |
| /*selected_index=*/entry()->GetAvatarIconIndex(), |
| /*gaia_included=*/false, |
| /*gaia_selected=*/false, |
| /*default_avatar_included=*/true); |
| } |
| |
| } // namespace settings |