| // Copyright 2022 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/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.h" |
| |
| #include <functional> |
| #include <memory> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/memory/raw_ptr.h" |
| #include "base/test/metrics/histogram_tester.h" |
| #include "base/test/mock_callback.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "chrome/browser/new_tab_page/chrome_colors/chrome_colors_factory.h" |
| #include "chrome/browser/new_tab_page/chrome_colors/chrome_colors_service.h" |
| #include "chrome/browser/new_tab_page/chrome_colors/selected_colors_info.h" |
| #include "chrome/browser/search/background/ntp_background_data.h" |
| #include "chrome/browser/search/background/ntp_background_service_factory.h" |
| #include "chrome/browser/search/background/ntp_custom_background_service.h" |
| #include "chrome/browser/search/background/ntp_custom_background_service_observer.h" |
| #include "chrome/browser/search_engines/template_url_service_factory.h" |
| #include "chrome/browser/themes/theme_service.h" |
| #include "chrome/browser/themes/theme_service_factory.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/chrome_select_file_policy.h" |
| #include "chrome/browser/ui/color/chrome_color_id.h" |
| #include "chrome/browser/ui/webui/new_tab_page/ntp_pref_names.h" |
| #include "chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom.h" |
| #include "chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_colors.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/common/themes/autogenerated_theme_util.h" |
| #include "chrome/grit/generated_resources.h" |
| #include "chrome/test/base/test_browser_window.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "components/keyed_service/core/keyed_service.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/search/ntp_features.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/test/browser_task_environment.h" |
| #include "content/public/test/test_web_contents_factory.h" |
| #include "extensions/browser/extension_registry.h" |
| #include "extensions/common/extension_builder.h" |
| #include "mojo/public/cpp/bindings/pending_receiver.h" |
| #include "services/network/public/cpp/shared_url_loader_factory.h" |
| #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" |
| #include "services/network/test/test_url_loader_factory.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/skia/include/core/SkColor.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/color/color_provider.h" |
| #include "ui/native_theme/native_theme.h" |
| #include "ui/shell_dialogs/select_file_dialog_factory.h" |
| |
| namespace content { |
| class BrowserContext; |
| } // namespace content |
| |
| namespace { |
| |
| using testing::_; |
| |
| // A test SelectFileDialog to go straight to calling the listener. |
| class TestSelectFileDialog : public ui::SelectFileDialog { |
| public: |
| TestSelectFileDialog(Listener* listener, |
| std::unique_ptr<ui::SelectFilePolicy> policy, |
| const bool auto_cancel) |
| : ui::SelectFileDialog(listener, std::move(policy)), |
| auto_cancel_(auto_cancel) {} |
| |
| TestSelectFileDialog(const TestSelectFileDialog&) = delete; |
| TestSelectFileDialog& operator=(const TestSelectFileDialog&) = delete; |
| |
| protected: |
| ~TestSelectFileDialog() override = default; |
| |
| void SelectFileImpl(Type type, |
| const std::u16string& title, |
| const base::FilePath& default_path, |
| const FileTypeInfo* file_types, |
| int file_type_index, |
| const base::FilePath::StringType& default_extension, |
| gfx::NativeWindow owning_window, |
| void* params, |
| const GURL* caller) override { |
| if (auto_cancel_) { |
| listener_->FileSelectionCanceled(params); |
| } else { |
| listener_->FileSelected(base::FilePath(FILE_PATH_LITERAL("/test/path")), |
| file_type_index, params); |
| } |
| } |
| // Pure virtual methods that need to be implemented. |
| bool IsRunning(gfx::NativeWindow owning_window) const override { |
| return false; |
| } |
| void ListenerDestroyed() override {} |
| bool HasMultipleFileTypeChoicesImpl() override { return false; } |
| |
| private: |
| bool auto_cancel_; |
| }; |
| |
| class TestSelectFilePolicy : public ui::SelectFilePolicy { |
| public: |
| TestSelectFilePolicy& operator=(const TestSelectFilePolicy&) = delete; |
| |
| // Pure virtual methods that need to be implemented. |
| bool CanOpenSelectFileDialog() override { return true; } |
| void SelectFileDenied() override {} |
| }; |
| |
| // A test SelectFileDialogFactory so that the TestSelectFileDialog is used. |
| class TestSelectFileDialogFactory : public ui::SelectFileDialogFactory { |
| public: |
| explicit TestSelectFileDialogFactory(bool auto_cancel) |
| : auto_cancel_(auto_cancel) {} |
| |
| TestSelectFileDialogFactory& operator=(const TestSelectFileDialogFactory&) = |
| delete; |
| |
| ui::SelectFileDialog* Create( |
| ui::SelectFileDialog::Listener* listener, |
| std::unique_ptr<ui::SelectFilePolicy> policy) override { |
| return new TestSelectFileDialog( |
| listener, std::make_unique<TestSelectFilePolicy>(), auto_cancel_); |
| } |
| |
| private: |
| bool auto_cancel_; |
| }; |
| |
| class MockPage : public side_panel::mojom::CustomizeChromePage { |
| public: |
| MockPage() = default; |
| ~MockPage() override = default; |
| |
| mojo::PendingRemote<side_panel::mojom::CustomizeChromePage> |
| BindAndGetRemote() { |
| DCHECK(!receiver_.is_bound()); |
| return receiver_.BindNewPipeAndPassRemote(); |
| } |
| |
| void FlushForTesting() { receiver_.FlushForTesting(); } |
| |
| MOCK_METHOD3( |
| SetModulesSettings, |
| void(std::vector<side_panel::mojom::ModuleSettingsPtr> modules_settings, |
| bool managed, |
| bool visible)); |
| MOCK_METHOD2(SetMostVisitedSettings, |
| void(bool custom_links_enabled, bool visible)); |
| MOCK_METHOD1(SetTheme, void(side_panel::mojom::ThemePtr)); |
| |
| mojo::Receiver<side_panel::mojom::CustomizeChromePage> receiver_{this}; |
| }; |
| |
| class MockNtpCustomBackgroundService : public NtpCustomBackgroundService { |
| public: |
| explicit MockNtpCustomBackgroundService(Profile* profile) |
| : NtpCustomBackgroundService(profile) {} |
| MOCK_METHOD0(GetCustomBackground, absl::optional<CustomBackground>()); |
| MOCK_METHOD0(ResetCustomBackgroundInfo, void()); |
| MOCK_METHOD1(SelectLocalBackgroundImage, void(const base::FilePath&)); |
| MOCK_METHOD1(AddObserver, void(NtpCustomBackgroundServiceObserver*)); |
| MOCK_METHOD6(SetCustomBackgroundInfo, |
| void(const GURL&, |
| const GURL&, |
| const std::string&, |
| const std::string&, |
| const GURL&, |
| const std::string&)); |
| }; |
| |
| class MockNtpBackgroundService : public NtpBackgroundService { |
| public: |
| explicit MockNtpBackgroundService( |
| scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) |
| : NtpBackgroundService(url_loader_factory) {} |
| MOCK_CONST_METHOD0(collection_info, std::vector<CollectionInfo>&()); |
| MOCK_CONST_METHOD0(collection_images, std::vector<CollectionImage>&()); |
| MOCK_METHOD0(FetchCollectionInfo, void()); |
| MOCK_METHOD1(FetchCollectionImageInfo, void(const std::string&)); |
| MOCK_METHOD1(AddObserver, void(NtpBackgroundServiceObserver*)); |
| }; |
| |
| class MockThemeService : public ThemeService { |
| public: |
| MockThemeService() : ThemeService(nullptr, theme_helper_) { set_ready(); } |
| using ThemeService::NotifyThemeChanged; |
| MOCK_CONST_METHOD0(UsingDefaultTheme, bool()); |
| MOCK_CONST_METHOD0(UsingExtensionTheme, bool()); |
| MOCK_CONST_METHOD0(UsingSystemTheme, bool()); |
| MOCK_CONST_METHOD0(UsingPolicyTheme, bool()); |
| MOCK_CONST_METHOD0(GetAutogeneratedThemeColor, SkColor()); |
| MOCK_CONST_METHOD0(GetThemeID, std::string()); |
| MOCK_METHOD0(UseDefaultTheme, void()); |
| MOCK_METHOD1(BuildAutogeneratedThemeFromColor, void(SkColor)); |
| |
| private: |
| ThemeHelper theme_helper_; |
| }; |
| |
| std::unique_ptr<TestingProfile> MakeTestingProfile( |
| scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) { |
| TestingProfile::Builder profile_builder; |
| profile_builder.AddTestingFactory( |
| NtpBackgroundServiceFactory::GetInstance(), |
| base::BindRepeating( |
| [](scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, |
| content::BrowserContext* context) |
| -> std::unique_ptr<KeyedService> { |
| return std::make_unique< |
| testing::NiceMock<MockNtpBackgroundService>>( |
| url_loader_factory); |
| }, |
| url_loader_factory)); |
| profile_builder.AddTestingFactory( |
| ThemeServiceFactory::GetInstance(), |
| base::BindRepeating([](content::BrowserContext* context) |
| -> std::unique_ptr<KeyedService> { |
| return std::make_unique<testing::NiceMock<MockThemeService>>(); |
| })); |
| profile_builder.SetSharedURLLoaderFactory(url_loader_factory); |
| auto profile = profile_builder.Build(); |
| return profile; |
| } |
| |
| } // namespace |
| |
| class CustomizeChromePageHandlerTest : public testing::Test { |
| public: |
| CustomizeChromePageHandlerTest() |
| : profile_(MakeTestingProfile( |
| base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( |
| &test_url_loader_factory_))), |
| mock_ntp_custom_background_service_(profile_.get()), |
| mock_ntp_background_service_(static_cast<MockNtpBackgroundService*>( |
| NtpBackgroundServiceFactory::GetForProfile(profile_.get()))), |
| web_contents_(web_contents_factory_.CreateWebContents(profile_.get())), |
| mock_theme_service_(static_cast<MockThemeService*>( |
| ThemeServiceFactory::GetForProfile(profile_.get()))) {} |
| |
| void SetUp() override { |
| EXPECT_CALL(mock_ntp_background_service(), AddObserver) |
| .Times(1) |
| .WillOnce(testing::SaveArg<0>(&ntp_background_service_observer_)); |
| EXPECT_CALL(mock_ntp_custom_background_service_, AddObserver) |
| .Times(1) |
| .WillOnce( |
| testing::SaveArg<0>(&ntp_custom_background_service_observer_)); |
| const std::vector<std::pair<const std::string, int>> module_id_names = { |
| {"recipe_tasks", IDS_NTP_MODULES_RECIPE_TASKS_SENTENCE}, |
| {"chrome_cart", IDS_NTP_MODULES_CART_SENTENCE}}; |
| handler_ = std::make_unique<CustomizeChromePageHandler>( |
| mojo::PendingReceiver<side_panel::mojom::CustomizeChromePageHandler>(), |
| mock_page_.BindAndGetRemote(), &mock_ntp_custom_background_service_, |
| web_contents_, module_id_names); |
| mock_page_.FlushForTesting(); |
| EXPECT_EQ(handler_.get(), ntp_background_service_observer_); |
| EXPECT_EQ(handler_.get(), ntp_custom_background_service_observer_); |
| |
| browser_window_ = std::make_unique<TestBrowserWindow>(); |
| Browser::CreateParams browser_params(profile_.get(), true); |
| browser_params.type = Browser::TYPE_NORMAL; |
| browser_params.window = browser_window_.get(); |
| browser_ = std::unique_ptr<Browser>(Browser::Create(browser_params)); |
| } |
| |
| void TearDown() override { |
| browser_->tab_strip_model()->CloseAllTabs(); |
| browser_.reset(); |
| browser_window_.reset(); |
| } |
| |
| TestingProfile& profile() { return *profile_; } |
| content::WebContents& web_contents() { return *web_contents_; } |
| CustomizeChromePageHandler& handler() { return *handler_; } |
| NtpCustomBackgroundServiceObserver& ntp_custom_background_service_observer() { |
| return *ntp_custom_background_service_observer_; |
| } |
| MockNtpBackgroundService& mock_ntp_background_service() { |
| return *mock_ntp_background_service_; |
| } |
| NtpBackgroundServiceObserver& ntp_background_service_observer() { |
| return *ntp_background_service_observer_; |
| } |
| MockThemeService& mock_theme_service() { return *mock_theme_service_; } |
| Browser& browser() { return *browser_; } |
| base::HistogramTester& histogram_tester() { return histogram_tester_; } |
| |
| protected: |
| // NOTE: The initialization order of these members matters. |
| content::BrowserTaskEnvironment task_environment_; |
| std::unique_ptr<TestingProfile> profile_; |
| testing::NiceMock<MockNtpCustomBackgroundService> |
| mock_ntp_custom_background_service_; |
| NtpCustomBackgroundServiceObserver* ntp_custom_background_service_observer_; |
| network::TestURLLoaderFactory test_url_loader_factory_; |
| raw_ptr<MockNtpBackgroundService> mock_ntp_background_service_; |
| content::TestWebContentsFactory web_contents_factory_; |
| raw_ptr<content::WebContents> web_contents_; |
| testing::NiceMock<MockPage> mock_page_; |
| NtpBackgroundServiceObserver* ntp_background_service_observer_; |
| raw_ptr<MockThemeService> mock_theme_service_; |
| std::unique_ptr<Browser> browser_; |
| std::unique_ptr<TestBrowserWindow> browser_window_; |
| base::HistogramTester histogram_tester_; |
| std::unique_ptr<CustomizeChromePageHandler> handler_; |
| }; |
| |
| TEST_F(CustomizeChromePageHandlerTest, SetMostVisitedSettings) { |
| bool custom_links_enabled; |
| bool visible; |
| EXPECT_CALL(mock_page_, SetMostVisitedSettings) |
| .Times(4) |
| .WillRepeatedly( |
| testing::Invoke([&custom_links_enabled, &visible]( |
| bool custom_links_enabled_arg, bool visible_arg) { |
| custom_links_enabled = custom_links_enabled_arg; |
| visible = visible_arg; |
| })); |
| |
| profile().GetPrefs()->SetBoolean(ntp_prefs::kNtpUseMostVisitedTiles, false); |
| profile().GetPrefs()->SetBoolean(ntp_prefs::kNtpShortcutsVisible, false); |
| |
| histogram_tester().ExpectTotalCount("NewTabPage.CustomizeShortcutAction", 0); |
| EXPECT_FALSE( |
| profile().GetPrefs()->GetBoolean(ntp_prefs::kNtpUseMostVisitedTiles)); |
| EXPECT_FALSE( |
| profile().GetPrefs()->GetBoolean(ntp_prefs::kNtpShortcutsVisible)); |
| |
| handler().SetMostVisitedSettings(/*custom_links_enabled=*/false, |
| /*visible=*/true); |
| mock_page_.FlushForTesting(); |
| |
| EXPECT_TRUE( |
| profile().GetPrefs()->GetBoolean(ntp_prefs::kNtpUseMostVisitedTiles)); |
| EXPECT_TRUE( |
| profile().GetPrefs()->GetBoolean(ntp_prefs::kNtpShortcutsVisible)); |
| histogram_tester().ExpectTotalCount("NewTabPage.CustomizeShortcutAction", 2); |
| } |
| |
| TEST_F(CustomizeChromePageHandlerTest, GetChromeColors) { |
| std::vector<side_panel::mojom::ChromeColorPtr> colors; |
| base::MockCallback<CustomizeChromePageHandler::GetChromeColorsCallback> |
| callback; |
| EXPECT_CALL(callback, Run(testing::_)) |
| .Times(1) |
| .WillOnce(testing::Invoke( |
| [&colors](std::vector<side_panel::mojom::ChromeColorPtr> colors_arg) { |
| colors = std::move(colors_arg); |
| })); |
| handler().GetChromeColors(callback.Get()); |
| |
| ASSERT_EQ(kCustomizeChromeColors.size(), colors.size()); |
| for (size_t i = 0; i < kCustomizeChromeColors.size(); i++) { |
| EXPECT_EQ(l10n_util::GetStringUTF8(kCustomizeChromeColors[i].label_id), |
| colors[i]->name); |
| EXPECT_EQ(kCustomizeChromeColors[i].color, colors[i]->seed); |
| EXPECT_EQ(GetAutogeneratedThemeColors(kCustomizeChromeColors[i].color) |
| .active_tab_color, |
| colors[i]->background); |
| EXPECT_EQ(GetAutogeneratedThemeColors(kCustomizeChromeColors[i].color) |
| .frame_color, |
| colors[i]->foreground); |
| } |
| } |
| |
| enum class ThemeUpdateSource { |
| kMojo, |
| kThemeService, |
| kNativeTheme, |
| kCustomBackgroundService, |
| }; |
| |
| class CustomizeChromePageHandlerSetThemeTest |
| : public CustomizeChromePageHandlerTest, |
| public ::testing::WithParamInterface<ThemeUpdateSource> { |
| public: |
| void UpdateTheme() { |
| switch (GetParam()) { |
| case ThemeUpdateSource::kMojo: |
| handler().UpdateTheme(); |
| break; |
| case ThemeUpdateSource::kThemeService: |
| mock_theme_service().NotifyThemeChanged(); |
| break; |
| case ThemeUpdateSource::kNativeTheme: |
| ui::NativeTheme::GetInstanceForNativeUi()->NotifyOnNativeThemeUpdated(); |
| break; |
| case ThemeUpdateSource::kCustomBackgroundService: |
| ntp_custom_background_service_observer() |
| .OnCustomBackgroundImageUpdated(); |
| break; |
| } |
| } |
| }; |
| |
| TEST_P(CustomizeChromePageHandlerSetThemeTest, SetTheme) { |
| side_panel::mojom::ThemePtr theme; |
| EXPECT_CALL(mock_page_, SetTheme) |
| .Times(1) |
| .WillOnce(testing::Invoke([&theme](side_panel::mojom::ThemePtr arg) { |
| theme = std::move(arg); |
| })); |
| CustomBackground custom_background; |
| custom_background.custom_background_url = GURL("https://foo.com/img.png"); |
| custom_background.custom_background_attribution_line_1 = "foo line"; |
| custom_background.is_uploaded_image = false; |
| custom_background.custom_background_main_color = SK_ColorGREEN; |
| custom_background.collection_id = "test_collection"; |
| ON_CALL(mock_ntp_custom_background_service_, GetCustomBackground()) |
| .WillByDefault(testing::Return(absl::make_optional(custom_background))); |
| ON_CALL(mock_theme_service(), GetAutogeneratedThemeColor()) |
| .WillByDefault(testing::Return(SK_ColorBLUE)); |
| ON_CALL(mock_theme_service(), UsingDefaultTheme()) |
| .WillByDefault(testing::Return(false)); |
| ON_CALL(mock_theme_service(), UsingSystemTheme()) |
| .WillByDefault(testing::Return(false)); |
| ON_CALL(mock_theme_service(), UsingPolicyTheme()) |
| .WillByDefault(testing::Return(true)); |
| ui::NativeTheme::GetInstanceForNativeUi()->set_use_dark_colors(true); |
| |
| UpdateTheme(); |
| mock_page_.FlushForTesting(); |
| |
| ASSERT_TRUE(theme); |
| ASSERT_TRUE(theme->background_image); |
| EXPECT_EQ("https://foo.com/img.png", theme->background_image->url); |
| EXPECT_FALSE(theme->background_image->is_uploaded_image); |
| EXPECT_EQ(SK_ColorGREEN, |
| theme->background_image->main_color.value_or(SK_ColorWHITE)); |
| EXPECT_EQ("foo line", theme->background_image->title); |
| EXPECT_TRUE(theme->system_dark_mode); |
| EXPECT_EQ(SK_ColorBLUE, theme->seed_color); |
| EXPECT_EQ( |
| web_contents().GetColorProvider().GetColor(kColorNewTabPageBackground), |
| theme->background_color); |
| EXPECT_EQ(web_contents().GetColorProvider().GetColor(ui::kColorFrameActive), |
| theme->foreground_color); |
| EXPECT_EQ(web_contents().GetColorProvider().GetColor(kColorNewTabPageText), |
| theme->color_picker_icon_color); |
| EXPECT_TRUE(theme->colors_managed_by_policy); |
| EXPECT_EQ("test_collection", theme->daily_refresh_collection_id); |
| } |
| |
| TEST_P(CustomizeChromePageHandlerSetThemeTest, SetUploadedImage) { |
| side_panel::mojom::ThemePtr theme; |
| EXPECT_CALL(mock_page_, SetTheme) |
| .Times(1) |
| .WillOnce(testing::Invoke([&theme](side_panel::mojom::ThemePtr arg) { |
| theme = std::move(arg); |
| })); |
| CustomBackground custom_background; |
| custom_background.custom_background_url = GURL("https://foo.com/img.png"); |
| custom_background.is_uploaded_image = true; |
| ON_CALL(mock_ntp_custom_background_service_, GetCustomBackground()) |
| .WillByDefault(testing::Return(absl::make_optional(custom_background))); |
| ON_CALL(mock_theme_service(), UsingDefaultTheme()) |
| .WillByDefault(testing::Return(false)); |
| ON_CALL(mock_theme_service(), UsingSystemTheme()) |
| .WillByDefault(testing::Return(false)); |
| |
| UpdateTheme(); |
| mock_page_.FlushForTesting(); |
| |
| ASSERT_TRUE(theme); |
| ASSERT_TRUE(theme->background_image); |
| EXPECT_EQ("https://foo.com/img.png", theme->background_image->url); |
| ASSERT_TRUE(theme->background_image->is_uploaded_image); |
| } |
| |
| TEST_P(CustomizeChromePageHandlerSetThemeTest, SetThirdPartyTheme) { |
| side_panel::mojom::ThemePtr theme; |
| EXPECT_CALL(mock_page_, SetTheme) |
| .Times(1) |
| .WillOnce(testing::Invoke([&theme](side_panel::mojom::ThemePtr arg) { |
| theme = std::move(arg); |
| })); |
| CustomBackground custom_background; |
| custom_background.custom_background_url = GURL("https://foo.com/img.png"); |
| custom_background.is_uploaded_image = true; |
| |
| auto* extension_registry = extensions::ExtensionRegistry::Get(profile_.get()); |
| scoped_refptr<const extensions::Extension> extension; |
| extension = extensions::ExtensionBuilder() |
| .SetManifest(extensions::DictionaryBuilder() |
| .Set("name", "Foo Extension") |
| .Set("version", "1.0.0") |
| .Set("manifest_version", 2) |
| .Build()) |
| .SetID("foo") |
| .Build(); |
| extension_registry->AddEnabled(extension); |
| |
| ON_CALL(mock_ntp_custom_background_service_, GetCustomBackground()) |
| .WillByDefault(testing::Return(absl::make_optional(custom_background))); |
| ON_CALL(mock_theme_service(), UsingDefaultTheme()) |
| .WillByDefault(testing::Return(false)); |
| ON_CALL(mock_theme_service(), UsingExtensionTheme()) |
| .WillByDefault(testing::Return(true)); |
| ON_CALL(mock_theme_service(), UsingSystemTheme()) |
| .WillByDefault(testing::Return(false)); |
| ON_CALL(mock_theme_service(), GetThemeID()) |
| .WillByDefault(testing::Return("foo")); |
| |
| UpdateTheme(); |
| mock_page_.FlushForTesting(); |
| |
| ASSERT_TRUE(theme); |
| ASSERT_TRUE(theme->background_image); |
| EXPECT_EQ("https://foo.com/img.png", theme->background_image->url); |
| ASSERT_TRUE(theme->background_image->is_uploaded_image); |
| ASSERT_TRUE(theme->third_party_theme_info); |
| EXPECT_EQ("foo", theme->third_party_theme_info->id); |
| EXPECT_EQ("Foo Extension", theme->third_party_theme_info->name); |
| } |
| |
| INSTANTIATE_TEST_SUITE_P( |
| All, |
| CustomizeChromePageHandlerSetThemeTest, |
| ::testing::Values(ThemeUpdateSource::kMojo, |
| ThemeUpdateSource::kThemeService, |
| ThemeUpdateSource::kNativeTheme, |
| ThemeUpdateSource::kCustomBackgroundService)); |
| |
| TEST_F(CustomizeChromePageHandlerTest, GetBackgroundCollections) { |
| std::vector<CollectionInfo> test_collection_info; |
| CollectionInfo test_collection; |
| test_collection.collection_id = "test_id"; |
| test_collection.collection_name = "test_name"; |
| test_collection.preview_image_url = GURL("https://test.jpg"); |
| test_collection_info.push_back(test_collection); |
| ON_CALL(mock_ntp_background_service(), collection_info()) |
| .WillByDefault(testing::ReturnRef(test_collection_info)); |
| |
| std::vector<side_panel::mojom::BackgroundCollectionPtr> collections; |
| base::MockCallback< |
| CustomizeChromePageHandler::GetBackgroundCollectionsCallback> |
| callback; |
| EXPECT_CALL(callback, Run(testing::_)) |
| .Times(1) |
| .WillOnce(testing::Invoke( |
| [&collections](std::vector<side_panel::mojom::BackgroundCollectionPtr> |
| collections_arg) { |
| collections = std::move(collections_arg); |
| })); |
| EXPECT_CALL(mock_ntp_background_service(), FetchCollectionInfo).Times(1); |
| handler().GetBackgroundCollections(callback.Get()); |
| ntp_background_service_observer().OnCollectionInfoAvailable(); |
| |
| EXPECT_EQ(collections.size(), test_collection_info.size()); |
| EXPECT_EQ(test_collection_info[0].collection_id, collections[0]->id); |
| EXPECT_EQ(test_collection_info[0].collection_name, collections[0]->label); |
| EXPECT_EQ(test_collection_info[0].preview_image_url, |
| collections[0]->preview_image_url); |
| } |
| |
| TEST_F(CustomizeChromePageHandlerTest, GetBackgroundImages) { |
| std::vector<CollectionImage> test_collection_images; |
| CollectionImage test_image; |
| std::vector<std::string> attribution{"test1", "test2"}; |
| test_image.attribution = attribution; |
| test_image.attribution_action_url = GURL("https://action.com"); |
| test_image.image_url = GURL("https://test_image.jpg"); |
| test_image.thumbnail_image_url = GURL("https://test_thumbnail.jpg"); |
| test_collection_images.push_back(test_image); |
| ON_CALL(mock_ntp_background_service(), collection_images()) |
| .WillByDefault(testing::ReturnRef(test_collection_images)); |
| |
| std::vector<side_panel::mojom::CollectionImagePtr> images; |
| base::MockCallback<CustomizeChromePageHandler::GetBackgroundImagesCallback> |
| callback; |
| EXPECT_CALL(callback, Run(testing::_)) |
| .Times(1) |
| .WillOnce(testing::Invoke( |
| [&images]( |
| std::vector<side_panel::mojom::CollectionImagePtr> images_arg) { |
| images = std::move(images_arg); |
| })); |
| EXPECT_CALL(mock_ntp_background_service(), FetchCollectionImageInfo).Times(1); |
| handler().GetBackgroundImages("test_id", callback.Get()); |
| ntp_background_service_observer().OnCollectionImagesAvailable(); |
| |
| EXPECT_EQ(images.size(), test_collection_images.size()); |
| EXPECT_EQ(test_collection_images[0].attribution[0], images[0]->attribution_1); |
| EXPECT_EQ(test_collection_images[0].attribution[1], images[0]->attribution_2); |
| EXPECT_EQ(test_collection_images[0].attribution_action_url, |
| images[0]->attribution_url); |
| EXPECT_EQ(test_collection_images[0].image_url, images[0]->image_url); |
| EXPECT_EQ(test_collection_images[0].thumbnail_image_url, |
| images[0]->preview_image_url); |
| } |
| |
| TEST_F(CustomizeChromePageHandlerTest, SetDefaultColor) { |
| EXPECT_CALL(mock_theme_service(), UseDefaultTheme).Times(1); |
| |
| handler().SetDefaultColor(); |
| } |
| |
| TEST_F(CustomizeChromePageHandlerTest, SetSeedColor) { |
| SkColor color = SK_ColorWHITE; |
| EXPECT_CALL(mock_theme_service(), BuildAutogeneratedThemeFromColor) |
| .Times(1) |
| .WillOnce(testing::SaveArg<0>(&color)); |
| |
| handler().SetSeedColor(SK_ColorBLUE); |
| |
| EXPECT_EQ(SK_ColorBLUE, color); |
| } |
| |
| TEST_F(CustomizeChromePageHandlerTest, SetClassicChromeDefaultTheme) { |
| EXPECT_CALL(mock_ntp_custom_background_service_, ResetCustomBackgroundInfo) |
| .Times(1); |
| EXPECT_CALL(mock_theme_service(), UseDefaultTheme).Times(1); |
| |
| handler().SetClassicChromeDefaultTheme(); |
| } |
| |
| TEST_F(CustomizeChromePageHandlerTest, ChooseLocalCustomBackgroundSuccess) { |
| bool success; |
| base::MockCallback< |
| CustomizeChromePageHandler::ChooseLocalCustomBackgroundCallback> |
| callback; |
| ui::SelectFileDialog::SetFactory(new TestSelectFileDialogFactory(false)); |
| EXPECT_CALL(callback, Run(testing::_)) |
| .Times(1) |
| .WillOnce(testing::Invoke( |
| [&success](bool success_arg) { success = std::move(success_arg); })); |
| EXPECT_CALL(mock_ntp_custom_background_service_, SelectLocalBackgroundImage) |
| .Times(1); |
| handler().ChooseLocalCustomBackground(callback.Get()); |
| EXPECT_TRUE(success); |
| } |
| |
| TEST_F(CustomizeChromePageHandlerTest, ChooseLocalCustomBackgroundCancel) { |
| bool success; |
| base::MockCallback< |
| CustomizeChromePageHandler::ChooseLocalCustomBackgroundCallback> |
| callback; |
| ui::SelectFileDialog::SetFactory(new TestSelectFileDialogFactory(true)); |
| EXPECT_CALL(callback, Run(testing::_)) |
| .Times(1) |
| .WillOnce(testing::Invoke( |
| [&success](bool success_arg) { success = std::move(success_arg); })); |
| handler().ChooseLocalCustomBackground(callback.Get()); |
| EXPECT_TRUE(!success); |
| } |
| |
| TEST_F(CustomizeChromePageHandlerTest, SetBackgroundImage) { |
| EXPECT_CALL(mock_ntp_custom_background_service_, SetCustomBackgroundInfo) |
| .Times(1); |
| handler().SetBackgroundImage( |
| "attribution1", "attribution2", GURL("https://attribution.com"), |
| GURL("https://image.jpg"), GURL("https://thumbnail.jpg")); |
| } |
| |
| TEST_F(CustomizeChromePageHandlerTest, OpenChromeWebStore) { |
| handler().OpenChromeWebStore(); |
| ASSERT_EQ(1, browser().tab_strip_model()->count()); |
| ASSERT_EQ("https://chrome.google.com/webstore?category=theme", |
| browser().tab_strip_model()->GetWebContentsAt(0)->GetURL()); |
| } |
| |
| TEST_F(CustomizeChromePageHandlerTest, OpenThirdPartyThemePage) { |
| handler().OpenThirdPartyThemePage("foo"); |
| ASSERT_EQ(1, browser().tab_strip_model()->count()); |
| ASSERT_EQ("https://chrome.google.com/webstore/detail/foo", |
| browser().tab_strip_model()->GetWebContentsAt(0)->GetURL()); |
| } |
| |
| TEST_F(CustomizeChromePageHandlerTest, SetDailyRefreshCollectionId) { |
| EXPECT_CALL(mock_ntp_custom_background_service_, SetCustomBackgroundInfo) |
| .Times(1); |
| handler().SetDailyRefreshCollectionId("test_id"); |
| } |
| |
| class CustomizeChromePageHandlerWithModulesTest |
| : public CustomizeChromePageHandlerTest { |
| public: |
| void SetUp() override { |
| base::test::ScopedFeatureList features; |
| features.InitWithFeatures( |
| /*enabled_features=*/{ntp_features::kNtpRecipeTasksModule, |
| ntp_features::kNtpChromeCartModule}, |
| /*disabled_features=*/{}); |
| CustomizeChromePageHandlerTest::SetUp(); |
| } |
| }; |
| |
| TEST_F(CustomizeChromePageHandlerWithModulesTest, SetModulesSettings) { |
| std::vector<side_panel::mojom::ModuleSettingsPtr> modules_settings; |
| bool managed; |
| bool visible; |
| EXPECT_CALL(mock_page_, SetModulesSettings) |
| .Times(2) |
| .WillRepeatedly( |
| testing::Invoke([&modules_settings, &managed, &visible]( |
| std::vector<side_panel::mojom::ModuleSettingsPtr> |
| modules_settings_arg, |
| bool managed_arg, bool visible_arg) { |
| modules_settings = std::move(modules_settings_arg); |
| managed = managed_arg; |
| visible = visible_arg; |
| })); |
| |
| constexpr char kChromeCartId[] = "chrome_cart"; |
| profile().GetPrefs()->SetBoolean(prefs::kNtpModulesVisible, true); |
| auto disabled_module_ids = base::Value::List(); |
| disabled_module_ids.Append(kChromeCartId); |
| profile().GetPrefs()->SetList(prefs::kNtpDisabledModules, |
| std::move(disabled_module_ids)); |
| mock_page_.FlushForTesting(); |
| |
| EXPECT_TRUE(visible); |
| EXPECT_FALSE(managed); |
| EXPECT_EQ(2u, modules_settings.size()); |
| EXPECT_EQ("recipe_tasks", modules_settings[0]->id); |
| EXPECT_TRUE(modules_settings[0]->enabled); |
| EXPECT_EQ(kChromeCartId, modules_settings[1]->id); |
| EXPECT_FALSE(modules_settings[1]->enabled); |
| } |
| |
| TEST_F(CustomizeChromePageHandlerWithModulesTest, SetModulesVisible) { |
| profile().GetPrefs()->SetBoolean(prefs::kNtpModulesVisible, false); |
| handler().SetModulesVisible(true); |
| |
| EXPECT_CALL(mock_page_, SetModulesSettings).Times(2); |
| mock_page_.FlushForTesting(); |
| |
| EXPECT_TRUE(profile().GetPrefs()->GetBoolean(prefs::kNtpModulesVisible)); |
| } |
| |
| TEST_F(CustomizeChromePageHandlerWithModulesTest, SetModuleDisabled) { |
| const std::string kDriveModuleId = "drive"; |
| handler().SetModuleDisabled(kDriveModuleId, true); |
| const auto& disabled_module_ids = |
| profile().GetPrefs()->GetList(prefs::kNtpDisabledModules); |
| |
| EXPECT_CALL(mock_page_, SetModulesSettings).Times(1); |
| mock_page_.FlushForTesting(); |
| |
| EXPECT_EQ(1u, disabled_module_ids.size()); |
| EXPECT_EQ(kDriveModuleId, disabled_module_ids.front().GetString()); |
| } |