| // Copyright 2020 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/realbox/realbox_handler.h" |
| |
| #include <string> |
| #include <unordered_map> |
| |
| #include <gtest/gtest.h> |
| #include "base/check.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "chrome/browser/browser_features.h" |
| #include "chrome/browser/preloading/prefetch/search_prefetch/field_trial_settings.h" |
| #include "chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_browser_test_base.h" |
| #include "chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service.h" |
| #include "chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service_factory.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/omnibox/omnibox_pedal_implementations.h" |
| #include "chrome/test/base/in_process_browser_test.h" |
| #include "chrome/test/base/ui_test_utils.h" |
| #include "components/omnibox/browser/actions/history_clusters_action.h" |
| #include "components/omnibox/browser/actions/omnibox_pedal.h" |
| #include "components/omnibox/browser/autocomplete_match.h" |
| #include "components/omnibox/browser/autocomplete_match_type.h" |
| #include "components/omnibox/browser/suggestion_answer.h" |
| #include "components/omnibox/browser/vector_icons.h" |
| #include "components/omnibox/common/omnibox_features.h" |
| #include "content/public/test/browser_test.h" |
| #include "content/public/test/prerender_test_util.h" |
| #include "mojo/public/cpp/bindings/remote.h" |
| #include "ui/gfx/vector_icon_types.h" |
| |
| namespace { |
| |
| class BrowserTestWithParam : public InProcessBrowserTest, |
| public testing::WithParamInterface<bool> { |
| public: |
| BrowserTestWithParam() = default; |
| BrowserTestWithParam(const BrowserTestWithParam&) = delete; |
| BrowserTestWithParam& operator=(const BrowserTestWithParam&) = delete; |
| ~BrowserTestWithParam() override = default; |
| |
| private: |
| base::test::ScopedFeatureList scoped_feature_list_; |
| }; |
| |
| } // namespace |
| |
| INSTANTIATE_TEST_SUITE_P(RealboxHandlerMatchIconTest, |
| BrowserTestWithParam, |
| testing::Bool()); |
| |
| // Tests that all Omnibox match vector icons map to an equivalent SVG for use in |
| // the NTP Realbox. |
| IN_PROC_BROWSER_TEST_P(BrowserTestWithParam, MatchVectorIcons) { |
| for (int type = AutocompleteMatchType::URL_WHAT_YOU_TYPED; |
| type != AutocompleteMatchType::NUM_TYPES; type++) { |
| AutocompleteMatch match; |
| match.type = static_cast<AutocompleteMatchType::Type>(type); |
| const bool is_bookmark = BrowserTestWithParam::GetParam(); |
| const gfx::VectorIcon& vector_icon = match.GetVectorIcon(is_bookmark); |
| const std::string& svg_name = |
| RealboxHandler::AutocompleteMatchVectorIconToResourceName(vector_icon); |
| if (vector_icon.is_empty()) { |
| // An empty resource name is effectively a blank icon. |
| EXPECT_TRUE(svg_name.empty()); |
| } else if (vector_icon.name == omnibox::kPedalIcon.name) { |
| // Pedals are not supported in the NTP Realbox. |
| EXPECT_TRUE(svg_name.empty()); |
| } else if (is_bookmark) { |
| EXPECT_EQ("//resources/images/icon_bookmark.svg", svg_name); |
| } else { |
| EXPECT_FALSE(svg_name.empty()); |
| } |
| } |
| } |
| |
| // Tests that all Omnibox Answer vector icons map to an equivalent SVG for use |
| // in the NTP Realbox. |
| IN_PROC_BROWSER_TEST_P(BrowserTestWithParam, AnswerVectorIcons) { |
| for (int answer_type = SuggestionAnswer::ANSWER_TYPE_DICTIONARY; |
| answer_type != SuggestionAnswer::ANSWER_TYPE_TOTAL_COUNT; |
| answer_type++) { |
| AutocompleteMatch match; |
| SuggestionAnswer answer; |
| answer.set_type(answer_type); |
| match.answer = answer; |
| const bool is_bookmark = BrowserTestWithParam::GetParam(); |
| const gfx::VectorIcon& vector_icon = match.GetVectorIcon(is_bookmark); |
| const std::string& svg_name = |
| RealboxHandler::AutocompleteMatchVectorIconToResourceName(vector_icon); |
| if (is_bookmark) { |
| EXPECT_EQ("//resources/images/icon_bookmark.svg", svg_name); |
| } else { |
| EXPECT_FALSE(svg_name.empty()); |
| EXPECT_NE("search.svg", svg_name); |
| } |
| } |
| } |
| |
| using RealboxHandlerPedalIconTest = InProcessBrowserTest; |
| |
| // Tests that all Omnibox Pedal vector icons map to an equivalent SVG for use in |
| // the NTP Realbox. |
| IN_PROC_BROWSER_TEST_F(RealboxHandlerPedalIconTest, PedalVectorIcons) { |
| std::unordered_map<OmniboxPedalId, scoped_refptr<OmniboxPedal>> pedals = |
| GetPedalImplementations(/*incognito=*/true, /*guest=*/false, |
| /*testing=*/true); |
| for (auto const& it : pedals) { |
| const scoped_refptr<OmniboxPedal> pedal = it.second; |
| const gfx::VectorIcon& vector_icon = pedal->GetVectorIcon(); |
| const std::string& svg_name = |
| RealboxHandler::PedalVectorIconToResourceName(vector_icon); |
| EXPECT_FALSE(svg_name.empty()); |
| } |
| |
| const scoped_refptr<OmniboxAction> history_clusters_action = |
| base::MakeRefCounted<history_clusters::HistoryClustersAction>( |
| "test", history::ClusterKeywordData(), /*takes_over_match=*/false); |
| const gfx::VectorIcon& vector_icon = history_clusters_action->GetVectorIcon(); |
| const std::string& svg_name = |
| RealboxHandler::PedalVectorIconToResourceName(vector_icon); |
| EXPECT_FALSE(svg_name.empty()); |
| } |
| |
| class RealboxSearchPreloadBrowserTest : public SearchPrefetchBaseBrowserTest { |
| public: |
| RealboxSearchPreloadBrowserTest() |
| : prerender_helper_(base::BindRepeating( |
| &RealboxSearchPreloadBrowserTest::GetWebContents, |
| base::Unretained(this))) { |
| scoped_feature_list_.InitWithFeaturesAndParameters( |
| {{features::kSupportSearchSuggestionForPrerender2, {}}, |
| {kSearchPrefetchServicePrefetching, |
| {{"max_attempts_per_caching_duration", "3"}, |
| {"cache_size", "1"}, |
| {"device_memory_threshold_MB", "0"}}}}, |
| /*disabled_features=*/{kSearchPrefetchBlockBeforeHeaders}); |
| } |
| |
| private: |
| content::test::PrerenderTestHelper prerender_helper_; |
| base::test::ScopedFeatureList scoped_feature_list_; |
| }; |
| |
| // A sink instance that allows Realbox to make IPC without failing DCHECK. |
| class RealboxSearchBrowserTestPage : public omnibox::mojom::Page { |
| public: |
| // omnibox::mojom::Page |
| void OmniboxAutocompleteResultChanged( |
| omnibox::mojom::AutocompleteResultPtr result) override {} |
| void AutocompleteResultChanged( |
| omnibox::mojom::AutocompleteResultPtr result) override {} |
| void SelectMatchAtLine(uint8_t line) override {} |
| mojo::PendingRemote<omnibox::mojom::Page> GetRemotePage() { |
| return receiver_.BindNewPipeAndPassRemote(); |
| } |
| |
| private: |
| mojo::Receiver<omnibox::mojom::Page> receiver_{this}; |
| }; |
| |
| // Tests the realbox input can trigger prerender and prefetch. |
| IN_PROC_BROWSER_TEST_F(RealboxSearchPreloadBrowserTest, SearchPreloadSuccess) { |
| mojo::Remote<omnibox::mojom::PageHandler> remote_page_handler; |
| RealboxSearchBrowserTestPage page; |
| RealboxHandler realbox_handler = RealboxHandler( |
| remote_page_handler.BindNewPipeAndPassReceiver(), browser()->profile(), |
| GetWebContents(), /*metrics_reporter=*/nullptr); |
| realbox_handler.SetPage(page.GetRemotePage()); |
| content::test::PrerenderHostRegistryObserver registry_observer( |
| *GetWebContents()); |
| |
| std::string input_query = "prerender"; |
| std::string search_terms = "prerender"; |
| AddNewSuggestionRule(input_query, {search_terms}, /*prefetch_index=*/0, |
| /*prerender_index=*/0); |
| GURL prerender_url = GetSearchServerQueryURL(search_terms + "&pf=cs&"); |
| |
| // Fake a WebUI input. |
| remote_page_handler->QueryAutocomplete(base::ASCIIToUTF16(input_query), |
| /*prevent_inline_autocomplete=*/false); |
| remote_page_handler.FlushForTesting(); |
| |
| // Prerender and Prefetch should be triggered. |
| WaitUntilStatusChangesTo(GetCanonicalSearchURL(prerender_url), |
| SearchPrefetchStatus::kComplete); |
| registry_observer.WaitForTrigger(prerender_url); |
| } |