| // Copyright 2020 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/optional.h" |
| #include "base/run_loop.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/time/time.h" |
| #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h" |
| #include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
| #include "chrome/browser/net/prediction_options.h" |
| #include "chrome/browser/prefetch/search_prefetch/field_trial_settings.h" |
| #include "chrome/browser/prefetch/search_prefetch/search_prefetch_service.h" |
| #include "chrome/browser/prefetch/search_prefetch/search_prefetch_service_factory.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/search_engines/template_url_service_factory.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/browser_window.h" |
| #include "chrome/browser/ui/location_bar/location_bar.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/test/base/in_process_browser_test.h" |
| #include "chrome/test/base/search_test_utils.h" |
| #include "chrome/test/base/ui_test_utils.h" |
| #include "components/content_settings/core/browser/host_content_settings_map.h" |
| #include "components/content_settings/core/common/content_settings.h" |
| #include "components/omnibox/browser/autocomplete_input.h" |
| #include "components/omnibox/browser/autocomplete_match.h" |
| #include "components/omnibox/browser/autocomplete_provider.h" |
| #include "components/omnibox/browser/omnibox_popup_model.h" |
| #include "components/omnibox/browser/omnibox_view.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/search_engines/template_url_service.h" |
| #include "content/public/browser/browser_task_traits.h" |
| #include "content/public/browser/browsing_data_filter_builder.h" |
| #include "content/public/browser/browsing_data_remover.h" |
| #include "content/public/test/browser_test.h" |
| #include "content/public/test/browser_test_utils.h" |
| #include "content/public/test/browsing_data_remover_test_util.h" |
| #include "net/dns/mock_host_resolver.h" |
| #include "net/http/http_status_code.h" |
| #include "net/test/embedded_test_server/default_handlers.h" |
| #include "net/test/embedded_test_server/embedded_test_server.h" |
| #include "net/test/embedded_test_server/embedded_test_server_connection_listener.h" |
| #include "net/test/embedded_test_server/http_request.h" |
| #include "net/test/embedded_test_server/http_response.h" |
| #include "url/gurl.h" |
| |
| namespace { |
| constexpr char kSuggestDomain[] = "suggest.com"; |
| constexpr char kSearchDomain[] = "search.com"; |
| constexpr char kOmniboxSuggestPrefetchQuery[] = "porgs"; |
| constexpr char kOmniboxSuggestPrefetchSecondItemQuery[] = "porgsandwich"; |
| constexpr char kOmniboxSuggestNonPrefetchQuery[] = "puffins"; |
| constexpr char kLoadInSubframe[] = "/load_in_subframe"; |
| } // namespace |
| |
| // A response that hangs after serving the start of the response. |
| class HangRequestAfterStart : public net::test_server::BasicHttpResponse { |
| public: |
| HangRequestAfterStart() = default; |
| |
| void SendResponse(const net::test_server::SendBytesCallback& send, |
| net::test_server::SendCompleteCallback done) override { |
| send.Run("HTTP/1.1 200 OK\r\nContent-Length:100\r\n\r\n", |
| base::DoNothing()); |
| } |
| }; |
| |
| class SearchPrefetchBaseBrowserTest : public InProcessBrowserTest { |
| public: |
| SearchPrefetchBaseBrowserTest() { |
| search_server_ = std::make_unique<net::EmbeddedTestServer>( |
| net::EmbeddedTestServer::TYPE_HTTPS); |
| search_server_->ServeFilesFromSourceDirectory("chrome/test/data"); |
| search_server_->RegisterRequestHandler( |
| base::BindRepeating(&SearchPrefetchBaseBrowserTest::HandleSearchRequest, |
| base::Unretained(this))); |
| EXPECT_TRUE(search_server_->Start()); |
| |
| search_suggest_server_ = std::make_unique<net::EmbeddedTestServer>( |
| net::EmbeddedTestServer::TYPE_HTTPS); |
| search_suggest_server_->ServeFilesFromSourceDirectory("chrome/test/data"); |
| search_suggest_server_->RegisterRequestHandler(base::BindRepeating( |
| &SearchPrefetchBaseBrowserTest::HandleSearchSuggestRequest, |
| base::Unretained(this))); |
| EXPECT_TRUE(search_suggest_server_->Start()); |
| } |
| |
| void SetUpOnMainThread() override { |
| InProcessBrowserTest::SetUpOnMainThread(); |
| |
| host_resolver()->AddRule(kSearchDomain, "127.0.0.1"); |
| host_resolver()->AddRule(kSuggestDomain, "127.0.0.1"); |
| |
| TemplateURLService* model = |
| TemplateURLServiceFactory::GetForProfile(browser()->profile()); |
| ASSERT_TRUE(model); |
| search_test_utils::WaitForTemplateURLServiceToLoad(model); |
| ASSERT_TRUE(model->loaded()); |
| |
| SetDSEWithURL( |
| GetSearchServerQueryURL("{searchTerms}&{google:prefetchSource}")); |
| } |
| |
| void SetUpCommandLine(base::CommandLine* cmd) override { |
| InProcessBrowserTest::SetUpCommandLine(cmd); |
| // For the proxy. |
| cmd->AppendSwitch("ignore-certificate-errors"); |
| cmd->AppendSwitch("force-enable-metrics-reporting"); |
| } |
| |
| size_t search_server_request_count() const { |
| return search_server_request_count_; |
| } |
| |
| size_t search_server_prefetch_request_count() const { |
| return search_server_prefetch_request_count_; |
| } |
| |
| const std::vector<net::test_server::HttpRequest>& search_server_requests() |
| const { |
| return search_server_requests_; |
| } |
| |
| GURL GetSearchServerQueryURL(const std::string& path) const { |
| return search_server_->GetURL(kSearchDomain, "/search_page.html?q=" + path); |
| } |
| |
| GURL GetSearchServerQueryURLWithNoQuery(const std::string& path) const { |
| return search_server_->GetURL(kSearchDomain, path); |
| } |
| |
| // Get a URL for a page that embeds the search |path| as an iframe. |
| GURL GetSearchServerQueryURLWithSubframeLoad(const std::string& path) const { |
| return search_server_->GetURL(kSearchDomain, |
| std::string(kLoadInSubframe) |
| .append("/search_page.html?q=") |
| .append(path)); |
| } |
| |
| GURL GetSuggestServerURL(const std::string& path) const { |
| return search_suggest_server_->GetURL(kSuggestDomain, path); |
| } |
| |
| void WaitUntilStatusChanges(base::string16 search_terms) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| auto status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| search_terms); |
| while (status == search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| search_terms)) { |
| base::RunLoop run_loop; |
| run_loop.RunUntilIdle(); |
| } |
| } |
| |
| void WaitUntilStatusChangesTo(base::string16 search_terms, |
| SearchPrefetchStatus status) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| while (!search_prefetch_service |
| ->GetSearchPrefetchStatusForTesting(search_terms) |
| .has_value() || |
| status != search_prefetch_service |
| ->GetSearchPrefetchStatusForTesting(search_terms) |
| .value()) { |
| base::RunLoop run_loop; |
| run_loop.RunUntilIdle(); |
| } |
| } |
| |
| content::WebContents* GetWebContents() const { |
| return browser()->tab_strip_model()->GetActiveWebContents(); |
| } |
| |
| std::string GetDocumentInnerHTML() const { |
| return content::EvalJs(GetWebContents(), |
| "document.documentElement.innerHTML") |
| .ExtractString(); |
| } |
| |
| void set_should_hang_requests(bool should_hang_requests) { |
| should_hang_requests_ = should_hang_requests; |
| } |
| |
| void set_hang_requests_after_start(bool hang_requests_after_start) { |
| hang_requests_after_start_ = hang_requests_after_start; |
| } |
| |
| void WaitForDuration(base::TimeDelta duration) { |
| base::RunLoop run_loop; |
| base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| FROM_HERE, run_loop.QuitClosure(), duration); |
| run_loop.Run(); |
| } |
| |
| void set_phi_is_one(bool phi_is_one) { phi_is_one_ = phi_is_one; } |
| |
| void ClearBrowsingCacheData(base::Optional<GURL> url_origin) { |
| auto filter = content::BrowsingDataFilterBuilder::Create( |
| url_origin ? content::BrowsingDataFilterBuilder::Mode::kDelete |
| : content::BrowsingDataFilterBuilder::Mode::kPreserve); |
| if (url_origin) |
| filter->AddOrigin(url::Origin::Create(url_origin.value())); |
| content::BrowsingDataRemover* remover = |
| content::BrowserContext::GetBrowsingDataRemover(browser()->profile()); |
| content::BrowsingDataRemoverCompletionObserver completion_observer(remover); |
| remover->RemoveWithFilterAndReply( |
| base::Time(), base::Time::Max(), |
| content::BrowsingDataRemover::DATA_TYPE_CACHE, |
| content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB, |
| std::move(filter), &completion_observer); |
| } |
| |
| void SetDSEWithURL(const GURL& url) { |
| TemplateURLService* model = |
| TemplateURLServiceFactory::GetForProfile(browser()->profile()); |
| TemplateURLData data; |
| data.SetShortName(base::ASCIIToUTF16(kSearchDomain)); |
| data.SetKeyword(data.short_name()); |
| data.SetURL(url.spec()); |
| data.suggestions_url = |
| search_suggest_server_->GetURL(kSuggestDomain, "/?q={searchTerms}") |
| .spec(); |
| |
| TemplateURL* template_url = model->Add(std::make_unique<TemplateURL>(data)); |
| ASSERT_TRUE(template_url); |
| model->SetUserSelectedDefaultSearchProvider(template_url); |
| } |
| |
| // This is sufficient to cause observer calls about updated template URL, but |
| // doesn't change DSE at all. |
| void UpdateButChangeNothingInDSE() { |
| TemplateURLService* model = |
| TemplateURLServiceFactory::GetForProfile(browser()->profile()); |
| TemplateURLData data; |
| data.SetShortName(base::ASCIIToUTF16(kSuggestDomain)); |
| data.SetKeyword(data.short_name()); |
| data.SetURL( |
| search_suggest_server_->GetURL(kSuggestDomain, "/?q={searchTerms}") |
| .spec()); |
| data.suggestions_url = |
| search_suggest_server_->GetURL(kSuggestDomain, "/?q={searchTerms}") |
| .spec(); |
| |
| model->Add(std::make_unique<TemplateURL>(data)); |
| } |
| |
| private: |
| std::unique_ptr<net::test_server::HttpResponse> HandleSearchRequest( |
| const net::test_server::HttpRequest& request) { |
| if (request.GetURL().spec().find("favicon") != std::string::npos) |
| return nullptr; |
| |
| if (hang_requests_after_start_) { |
| return std::make_unique<HangRequestAfterStart>(); |
| } |
| |
| if (should_hang_requests_) |
| return std::make_unique<net::test_server::HungResponse>(); |
| |
| bool is_prefetch = |
| request.headers.find("Purpose") != request.headers.end() && |
| request.headers.find("Purpose")->second == "prefetch"; |
| |
| content::GetUIThreadTaskRunner({})->PostTask( |
| FROM_HERE, |
| base::BindOnce(&SearchPrefetchBaseBrowserTest:: |
| MonitorSearchResourceRequestOnUIThread, |
| base::Unretained(this), request, is_prefetch)); |
| |
| // If this is an embedded search for load in iframe, parse out the iframe |
| // URL and serve it as an iframe in the returned HTML. |
| if (request.relative_url.find(kLoadInSubframe) == 0) { |
| std::string subframe_path = |
| request.relative_url.substr(std::string(kLoadInSubframe).size()); |
| std::string content = "<html><body><iframe src=\""; |
| content.append(subframe_path); |
| content.append("\"/></body></html>"); |
| |
| std::unique_ptr<net::test_server::BasicHttpResponse> resp = |
| std::make_unique<net::test_server::BasicHttpResponse>(); |
| resp->set_code(is_prefetch ? net::HTTP_BAD_GATEWAY : net::HTTP_OK); |
| resp->set_content_type("text/html"); |
| resp->set_content(content); |
| return resp; |
| } |
| |
| if (request.GetURL().spec().find("502_on_prefetch") != std::string::npos) { |
| std::unique_ptr<net::test_server::BasicHttpResponse> resp = |
| std::make_unique<net::test_server::BasicHttpResponse>(); |
| resp->set_code(is_prefetch ? net::HTTP_BAD_GATEWAY : net::HTTP_OK); |
| resp->set_content_type("text/html"); |
| resp->set_content("<html><body></body></html>"); |
| return resp; |
| } |
| |
| std::unique_ptr<net::test_server::BasicHttpResponse> resp = |
| std::make_unique<net::test_server::BasicHttpResponse>(); |
| resp->set_code(net::HTTP_OK); |
| resp->set_content_type("text/html"); |
| std::string content = "<html><body> "; |
| content.append(is_prefetch ? "prefetch" : "regular"); |
| content.append(" </body></html>"); |
| resp->set_content(content); |
| return resp; |
| } |
| |
| void MonitorSearchResourceRequestOnUIThread( |
| net::test_server::HttpRequest request, |
| bool has_prefetch_header) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| search_server_request_count_++; |
| search_server_requests_.push_back(request); |
| if (has_prefetch_header) { |
| search_server_prefetch_request_count_++; |
| } |
| } |
| |
| std::unique_ptr<net::test_server::HttpResponse> HandleSearchSuggestRequest( |
| const net::test_server::HttpRequest& request) { |
| // |content| is a json request that contains the search suggest response. |
| // The first item is the query (not used), the second is the results list, |
| // the third is descriptions, fifth is an extra data dictionary. The |
| // google:clientdata contains "phi" which is the prefetch index (i.e., which |
| // suggest can be prefetched). |
| std::string content = R"([ |
| "empty", |
| ["empty", "porgs"], |
| ["", ""], |
| [], |
| {}])"; |
| |
| if (request.GetURL().spec().find(kOmniboxSuggestPrefetchQuery) != |
| std::string::npos) { |
| if (phi_is_one_) { |
| content = R"([ |
| "porgs", |
| ["porgs","porgsandwich"], |
| ["", ""], |
| [], |
| { |
| "google:clientdata": { |
| "phi": 1 |
| } |
| }])"; |
| } else { |
| content = R"([ |
| "porgs", |
| ["porgs","porgsandwich"], |
| ["", ""], |
| [], |
| { |
| "google:clientdata": { |
| "phi": 0 |
| } |
| }])"; |
| } |
| } |
| |
| if (request.GetURL().spec().find(kOmniboxSuggestNonPrefetchQuery) != |
| std::string::npos) { |
| content = R"([ |
| "puffins", |
| ["puffins","puffinsalad"], |
| ["", ""], |
| [], |
| {}])"; |
| } |
| |
| std::unique_ptr<net::test_server::BasicHttpResponse> resp = |
| std::make_unique<net::test_server::BasicHttpResponse>(); |
| resp->set_code(net::HTTP_OK); |
| resp->set_content_type("application/json"); |
| resp->set_content(content); |
| return resp; |
| } |
| |
| std::vector<net::test_server::HttpRequest> search_server_requests_; |
| std::unique_ptr<net::EmbeddedTestServer> search_server_; |
| |
| std::unique_ptr<net::EmbeddedTestServer> search_suggest_server_; |
| |
| bool should_hang_requests_ = false; |
| |
| size_t search_server_request_count_ = 0; |
| size_t search_server_prefetch_request_count_ = 0; |
| |
| // Sets the prefetch index to be 1 instead of 0, making the second result |
| // prefetchable, but marking the first result as not prefetchable (must be |
| // used with |kkOmniboxSuggestPrefetchQuery|). |
| bool phi_is_one_ = false; |
| |
| // When set to true, serves a response that hangs after the start of the body. |
| bool hang_requests_after_start_ = false; |
| }; |
| |
| class SearchPrefetchServiceDisabledBrowserTest |
| : public SearchPrefetchBaseBrowserTest { |
| public: |
| SearchPrefetchServiceDisabledBrowserTest() { |
| feature_list_.InitAndDisableFeature(kSearchPrefetchService); |
| } |
| |
| private: |
| base::test::ScopedFeatureList feature_list_; |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(SearchPrefetchServiceDisabledBrowserTest, |
| ServiceNotCreatedWhenDisabled) { |
| EXPECT_EQ(nullptr, |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile())); |
| } |
| |
| class SearchPrefetchServiceEnabledWithoutPrefetchingBrowserTest |
| : public SearchPrefetchBaseBrowserTest { |
| public: |
| SearchPrefetchServiceEnabledWithoutPrefetchingBrowserTest() { |
| feature_list_.InitWithFeatures({kSearchPrefetchService}, |
| {kSearchPrefetchServicePrefetching}); |
| } |
| |
| private: |
| base::test::ScopedFeatureList feature_list_; |
| }; |
| |
| IN_PROC_BROWSER_TEST_F( |
| SearchPrefetchServiceEnabledWithoutPrefetchingBrowserTest, |
| ServiceNotCreatedWhenIncognito) { |
| EXPECT_EQ(nullptr, SearchPrefetchServiceFactory::GetForProfile( |
| browser()->profile()->GetPrimaryOTRProfile())); |
| } |
| |
| IN_PROC_BROWSER_TEST_F( |
| SearchPrefetchServiceEnabledWithoutPrefetchingBrowserTest, |
| ServiceCreatedWhenFeatureEnabled) { |
| EXPECT_NE(nullptr, |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile())); |
| } |
| |
| IN_PROC_BROWSER_TEST_F( |
| SearchPrefetchServiceEnabledWithoutPrefetchingBrowserTest, |
| NoFetchWhenPrefetchDisabled) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_terms = "prefetch_content"; |
| |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms); |
| |
| EXPECT_FALSE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| |
| EXPECT_FALSE(prefetch_status.has_value()); |
| } |
| |
| // General test for standard behavior. The interface bool represents streaming |
| // vs full body responses. |
| class SearchPrefetchServiceEnabledBrowserTest |
| : public SearchPrefetchBaseBrowserTest, |
| public testing::WithParamInterface<bool> { |
| public: |
| SearchPrefetchServiceEnabledBrowserTest() { |
| feature_list_.InitWithFeaturesAndParameters( |
| {{kSearchPrefetchServicePrefetching, |
| {{"stream_responses", GetParam() ? "true" : "false"}}}, |
| {{kSearchPrefetchService}, {}}}, |
| {}); |
| } |
| |
| private: |
| base::test::ScopedFeatureList feature_list_; |
| }; |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| ServiceNotCreatedWhenIncognito) { |
| EXPECT_EQ(nullptr, SearchPrefetchServiceFactory::GetForProfile( |
| browser()->profile()->GetPrimaryOTRProfile())); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| ServiceCreatedWhenFeatureEnabled) { |
| EXPECT_NE(nullptr, |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile())); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| BasicPrefetchFunctionality) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_terms = "prefetch_content"; |
| |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kInFlight, prefetch_status.value()); |
| |
| WaitUntilStatusChanges(base::ASCIIToUTF16(search_terms)); |
| |
| EXPECT_EQ(1u, search_server_requests().size()); |
| EXPECT_NE(std::string::npos, |
| search_server_requests()[0].GetURL().spec().find(search_terms)); |
| auto headers = search_server_requests()[0].headers; |
| ASSERT_TRUE(base::Contains(headers, "Accept")); |
| EXPECT_TRUE(base::Contains(headers["Accept"], "text/html")); |
| EXPECT_EQ(1u, search_server_request_count()); |
| EXPECT_EQ(1u, search_server_prefetch_request_count()); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kCanBeServed, prefetch_status.value()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| PrefetchRateLimiting) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL( |
| GetSearchServerQueryURL("prefetch_1"))); |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL( |
| GetSearchServerQueryURL("prefetch_2"))); |
| EXPECT_FALSE(search_prefetch_service->MaybePrefetchURL( |
| GetSearchServerQueryURL("prefetch_3"))); |
| |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16("prefetch_1")); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kInFlight, prefetch_status.value()); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16("prefetch_2")); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kInFlight, prefetch_status.value()); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16("prefetch_3")); |
| EXPECT_FALSE(prefetch_status.has_value()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| 502PrefetchFunctionality) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_terms = "502_on_prefetch"; |
| |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kInFlight, prefetch_status.value()); |
| |
| WaitUntilStatusChanges(base::ASCIIToUTF16(search_terms)); |
| |
| EXPECT_EQ(1u, search_server_requests().size()); |
| EXPECT_NE(std::string::npos, |
| search_server_requests()[0].GetURL().spec().find(search_terms)); |
| EXPECT_EQ(1u, search_server_request_count()); |
| EXPECT_EQ(1u, search_server_prefetch_request_count()); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kRequestFailed, prefetch_status.value()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| FetchSameTermsOnlyOnce) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_terms = "prefetch_content"; |
| |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| |
| WaitUntilStatusChanges(base::ASCIIToUTF16(search_terms)); |
| |
| EXPECT_FALSE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, BadURL) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_path = "/bad_path"; |
| |
| GURL prefetch_url = GetSearchServerQueryURLWithNoQuery(search_path); |
| |
| EXPECT_FALSE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| PreloadDisabled) { |
| browser()->profile()->GetPrefs()->SetInteger( |
| prefs::kNetworkPredictionOptions, |
| chrome_browser_net::NETWORK_PREDICTION_NEVER); |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_terms = "prefetch_content"; |
| |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms); |
| |
| EXPECT_FALSE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| BasicPrefetchServed) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_terms = "prefetch_content"; |
| |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| WaitUntilStatusChanges(base::ASCIIToUTF16(search_terms)); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kCanBeServed, prefetch_status.value()); |
| |
| ui_test_utils::NavigateToURL(browser(), prefetch_url); |
| |
| auto inner_html = GetDocumentInnerHTML(); |
| |
| EXPECT_FALSE(base::Contains(inner_html, "regular")); |
| EXPECT_TRUE(base::Contains(inner_html, "prefetch")); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| RegularSearchQueryWhenNoPrefetch) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_terms = "prefetch_content"; |
| |
| GURL search_url = GetSearchServerQueryURL(search_terms); |
| |
| ui_test_utils::NavigateToURL(browser(), search_url); |
| |
| auto inner_html = GetDocumentInnerHTML(); |
| |
| EXPECT_TRUE(base::Contains(inner_html, "regular")); |
| EXPECT_FALSE(base::Contains(inner_html, "prefetch")); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| NonMatchingPrefetchURL) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_terms = "prefetch_content"; |
| std::string search_terms_other = "other"; |
| |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| WaitUntilStatusChanges(base::ASCIIToUTF16(search_terms)); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kCanBeServed, prefetch_status.value()); |
| |
| ui_test_utils::NavigateToURL(browser(), |
| GetSearchServerQueryURL(search_terms_other)); |
| |
| auto inner_html = GetDocumentInnerHTML(); |
| |
| EXPECT_TRUE(base::Contains(inner_html, "regular")); |
| EXPECT_FALSE(base::Contains(inner_html, "prefetch")); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| ErrorCausesNoFetch) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_terms = "502_on_prefetch"; |
| |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| WaitUntilStatusChanges(base::ASCIIToUTF16(search_terms)); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kRequestFailed, prefetch_status.value()); |
| |
| EXPECT_FALSE(search_prefetch_service->MaybePrefetchURL( |
| GetSearchServerQueryURL("other_query"))); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| OmniboxEditTriggersPrefetch) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| std::string search_terms = kOmniboxSuggestPrefetchQuery; |
| |
| // Trigger an omnibox suggest fetch that has a prefetch hint. |
| AutocompleteInput input( |
| base::ASCIIToUTF16(search_terms), metrics::OmniboxEventProto::BLANK, |
| ChromeAutocompleteSchemeClassifier(browser()->profile())); |
| LocationBar* location_bar = browser()->window()->GetLocationBar(); |
| OmniboxView* omnibox = location_bar->GetOmniboxView(); |
| AutocompleteController* autocomplete_controller = |
| omnibox->model()->autocomplete_controller(); |
| |
| // Prevent the stop timer from killing the hints fetch early. |
| autocomplete_controller->SetStartStopTimerDurationForTesting( |
| base::TimeDelta::FromSeconds(10)); |
| autocomplete_controller->Start(input); |
| |
| ui_test_utils::WaitForAutocompleteDone(browser()); |
| EXPECT_TRUE(autocomplete_controller->done()); |
| |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kCanBeServed); |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kCanBeServed, prefetch_status.value()); |
| |
| ui_test_utils::NavigateToURL(browser(), |
| GetSearchServerQueryURL(search_terms)); |
| |
| auto inner_html = GetDocumentInnerHTML(); |
| |
| EXPECT_FALSE(base::Contains(inner_html, "regular")); |
| EXPECT_TRUE(base::Contains(inner_html, "prefetch")); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| OmniboxURLHasPfParam) { |
| std::string search_terms = kOmniboxSuggestPrefetchQuery; |
| |
| // Trigger an omnibox suggest fetch that has a prefetch hint. |
| AutocompleteInput input( |
| base::ASCIIToUTF16(search_terms), metrics::OmniboxEventProto::BLANK, |
| ChromeAutocompleteSchemeClassifier(browser()->profile())); |
| LocationBar* location_bar = browser()->window()->GetLocationBar(); |
| OmniboxView* omnibox = location_bar->GetOmniboxView(); |
| AutocompleteController* autocomplete_controller = |
| omnibox->model()->autocomplete_controller(); |
| |
| // Prevent the stop timer from killing the hints fetch early. |
| autocomplete_controller->SetStartStopTimerDurationForTesting( |
| base::TimeDelta::FromSeconds(10)); |
| autocomplete_controller->Start(input); |
| |
| ui_test_utils::WaitForAutocompleteDone(browser()); |
| EXPECT_TRUE(autocomplete_controller->done()); |
| |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kCanBeServed); |
| ASSERT_TRUE(search_server_requests().size() > 0); |
| EXPECT_NE(std::string::npos, |
| search_server_requests()[0].GetURL().spec().find("pf=cs")); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| OmniboxEditDoesNotTriggersPrefetch) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| std::string search_terms = kOmniboxSuggestNonPrefetchQuery; |
| |
| // Trigger an omnibox suggest fetch that does not have a prefetch hint. |
| AutocompleteInput input( |
| base::ASCIIToUTF16(search_terms), metrics::OmniboxEventProto::BLANK, |
| ChromeAutocompleteSchemeClassifier(browser()->profile())); |
| LocationBar* location_bar = browser()->window()->GetLocationBar(); |
| OmniboxView* omnibox = location_bar->GetOmniboxView(); |
| AutocompleteController* autocomplete_controller = |
| omnibox->model()->autocomplete_controller(); |
| |
| // Prevent the stop timer from killing the hints fetch early. |
| autocomplete_controller->SetStartStopTimerDurationForTesting( |
| base::TimeDelta::FromSeconds(10)); |
| autocomplete_controller->Start(input); |
| |
| ui_test_utils::WaitForAutocompleteDone(browser()); |
| EXPECT_TRUE(autocomplete_controller->done()); |
| |
| WaitForDuration(base::TimeDelta::FromMilliseconds(100)); |
| |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| EXPECT_FALSE(prefetch_status.has_value()); |
| ui_test_utils::NavigateToURL(browser(), |
| GetSearchServerQueryURL(search_terms)); |
| |
| auto inner_html = GetDocumentInnerHTML(); |
| |
| EXPECT_TRUE(base::Contains(inner_html, "regular")); |
| EXPECT_FALSE(base::Contains(inner_html, "prefetch")); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| OmniboxEditTriggersPrefetchForSecondMatch) { |
| // phi being set to one causes the order of prefetch suggest to be different. |
| // This should still prefetch a result for the |kOmniboxSuggestPrefetchQuery|. |
| set_phi_is_one(true); |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| std::string search_terms = kOmniboxSuggestPrefetchQuery; |
| |
| // Trigger an omnibox suggest fetch that has a prefetch hint. |
| AutocompleteInput input( |
| base::ASCIIToUTF16(search_terms), metrics::OmniboxEventProto::BLANK, |
| ChromeAutocompleteSchemeClassifier(browser()->profile())); |
| LocationBar* location_bar = browser()->window()->GetLocationBar(); |
| OmniboxView* omnibox = location_bar->GetOmniboxView(); |
| AutocompleteController* autocomplete_controller = |
| omnibox->model()->autocomplete_controller(); |
| |
| // Prevent the stop timer from killing the hints fetch early. |
| autocomplete_controller->SetStartStopTimerDurationForTesting( |
| base::TimeDelta::FromSeconds(10)); |
| autocomplete_controller->Start(input); |
| |
| ui_test_utils::WaitForAutocompleteDone(browser()); |
| EXPECT_TRUE(autocomplete_controller->done()); |
| |
| WaitUntilStatusChangesTo( |
| base::ASCIIToUTF16(kOmniboxSuggestPrefetchSecondItemQuery), |
| SearchPrefetchStatus::kCanBeServed); |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(kOmniboxSuggestPrefetchSecondItemQuery)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kCanBeServed, prefetch_status.value()); |
| |
| ui_test_utils::NavigateToURL( |
| browser(), |
| GetSearchServerQueryURL(kOmniboxSuggestPrefetchSecondItemQuery)); |
| |
| auto inner_html = GetDocumentInnerHTML(); |
| |
| EXPECT_FALSE(base::Contains(inner_html, "regular")); |
| EXPECT_TRUE(base::Contains(inner_html, "prefetch")); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| RemovingMatchCancelsInFlight) { |
| set_should_hang_requests(true); |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| std::string search_terms = kOmniboxSuggestPrefetchQuery; |
| |
| // Trigger an omnibox suggest fetch that has a prefetch hint. |
| AutocompleteInput input( |
| base::ASCIIToUTF16(search_terms), metrics::OmniboxEventProto::BLANK, |
| ChromeAutocompleteSchemeClassifier(browser()->profile())); |
| LocationBar* location_bar = browser()->window()->GetLocationBar(); |
| OmniboxView* omnibox = location_bar->GetOmniboxView(); |
| AutocompleteController* autocomplete_controller = |
| omnibox->model()->autocomplete_controller(); |
| |
| // Prevent the stop timer from killing the hints fetch early. |
| autocomplete_controller->SetStartStopTimerDurationForTesting( |
| base::TimeDelta::FromSeconds(10)); |
| autocomplete_controller->Start(input); |
| |
| ui_test_utils::WaitForAutocompleteDone(browser()); |
| EXPECT_TRUE(autocomplete_controller->done()); |
| |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kInFlight); |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kInFlight, prefetch_status.value()); |
| |
| // Change the autocomplete to remove "porgs" entirely. |
| AutocompleteInput other_input( |
| base::ASCIIToUTF16(kOmniboxSuggestNonPrefetchQuery), |
| metrics::OmniboxEventProto::BLANK, |
| ChromeAutocompleteSchemeClassifier(browser()->profile())); |
| autocomplete_controller->Start(other_input); |
| ui_test_utils::WaitForAutocompleteDone(browser()); |
| EXPECT_TRUE(autocomplete_controller->done()); |
| |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kRequestCancelled); |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kRequestCancelled, prefetch_status.value()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| ClearCacheRemovesPrefetch) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_terms = "prefetch_content"; |
| |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| EXPECT_TRUE(prefetch_status.has_value()); |
| |
| ClearBrowsingCacheData(base::nullopt); |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| EXPECT_FALSE(prefetch_status.has_value()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| ClearCacheSearchRemovesPrefetch) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_terms = "prefetch_content"; |
| |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| EXPECT_TRUE(prefetch_status.has_value()); |
| |
| ClearBrowsingCacheData(GURL(GetSearchServerQueryURLWithNoQuery("/"))); |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| EXPECT_FALSE(prefetch_status.has_value()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| ClearCacheOtherSavesCache) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_terms = "prefetch_content"; |
| |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| EXPECT_TRUE(prefetch_status.has_value()); |
| |
| ClearBrowsingCacheData(GetSuggestServerURL("/")); |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| EXPECT_TRUE(prefetch_status.has_value()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| ChangeDSESameOriginClearsPrefetches) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_terms = "prefetch_content"; |
| |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| EXPECT_TRUE(prefetch_status.has_value()); |
| |
| SetDSEWithURL(GetSearchServerQueryURL("blah/q={searchTerms}&extra_stuff")); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| EXPECT_FALSE(prefetch_status.has_value()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| ChangeDSECrossOriginClearsPrefetches) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_terms = "prefetch_content"; |
| |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| EXPECT_TRUE(prefetch_status.has_value()); |
| |
| SetDSEWithURL(GetSuggestServerURL("/q={searchTerms}")); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| EXPECT_FALSE(prefetch_status.has_value()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| ChangeDSESameDoesntClearPrefetches) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_terms = "prefetch_content"; |
| |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| EXPECT_TRUE(prefetch_status.has_value()); |
| |
| UpdateButChangeNothingInDSE(); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| EXPECT_TRUE(prefetch_status.has_value()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| NoPrefetchWhenJSDisabled) { |
| browser()->profile()->GetPrefs()->SetBoolean(prefs::kWebKitJavascriptEnabled, |
| false); |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_terms = "prefetch_content"; |
| |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms); |
| |
| EXPECT_FALSE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| NoPrefetchWhenJSDisabledOnDSE) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_terms = "prefetch_content"; |
| |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms); |
| |
| HostContentSettingsMapFactory::GetForProfile(browser()->profile()) |
| ->SetContentSettingDefaultScope(prefetch_url, GURL(), |
| ContentSettingsType::JAVASCRIPT, |
| CONTENT_SETTING_BLOCK); |
| |
| EXPECT_FALSE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| EXPECT_FALSE(prefetch_status.has_value()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| NoServeWhenJSDisabled) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_terms = "prefetch_content"; |
| |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kInFlight, prefetch_status.value()); |
| |
| WaitUntilStatusChanges(base::ASCIIToUTF16(search_terms)); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kCanBeServed, prefetch_status.value()); |
| browser()->profile()->GetPrefs()->SetBoolean(prefs::kWebKitJavascriptEnabled, |
| false); |
| |
| ui_test_utils::NavigateToURL(browser(), prefetch_url); |
| |
| // The prefetch request and the new non-prefetched served request. |
| EXPECT_EQ(2u, search_server_request_count()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| NoServeWhenJSDisabledOnDSE) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_terms = "prefetch_content"; |
| |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kInFlight, prefetch_status.value()); |
| |
| WaitUntilStatusChanges(base::ASCIIToUTF16(search_terms)); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kCanBeServed, prefetch_status.value()); |
| |
| HostContentSettingsMapFactory::GetForProfile(browser()->profile()) |
| ->SetContentSettingDefaultScope(prefetch_url, GURL(), |
| ContentSettingsType::JAVASCRIPT, |
| CONTENT_SETTING_BLOCK); |
| |
| ui_test_utils::NavigateToURL(browser(), prefetch_url); |
| |
| // The prefetch request and the new non-prefetched served request. |
| EXPECT_EQ(2u, search_server_request_count()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| OnlyStreamedResponseCanServePartialRequest) { |
| set_hang_requests_after_start(true); |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_terms = "prefetch_content"; |
| |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kInFlight, prefetch_status.value()); |
| |
| if (GetParam()) { |
| WaitUntilStatusChanges(base::ASCIIToUTF16(search_terms)); |
| } else { |
| WaitForDuration(base::TimeDelta::FromMilliseconds(100)); |
| } |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| if (GetParam()) { |
| EXPECT_EQ(SearchPrefetchStatus::kCanBeServed, prefetch_status.value()); |
| } else { |
| EXPECT_EQ(SearchPrefetchStatus::kInFlight, prefetch_status.value()); |
| } |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| DontInterceptSubframes) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_terms = "prefetch_content"; |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms); |
| GURL navigation_url = GetSearchServerQueryURLWithSubframeLoad(search_terms); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kInFlight, prefetch_status.value()); |
| |
| WaitUntilStatusChanges(base::ASCIIToUTF16(search_terms)); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kCanBeServed, prefetch_status.value()); |
| |
| ui_test_utils::NavigateToURL(browser(), navigation_url); |
| |
| const auto& requests = search_server_requests(); |
| EXPECT_EQ(3u, requests.size()); |
| // This flow should have resulted in a prefetch of the search terms, a main |
| // frame navigation to the special subframe loader page, and a navigation to |
| // the subframe that matches the prefetch URL. |
| |
| // 2 requests should be to the search terms directly, one for the prefetch and |
| // one for the subframe (that can't be served from the prefetch cache). |
| EXPECT_EQ(2, |
| std::count_if(requests.begin(), requests.end(), |
| [search_terms](const auto& request) { |
| return request.relative_url.find(kLoadInSubframe) == |
| std::string::npos && |
| request.relative_url.find(search_terms) != |
| std::string::npos; |
| })); |
| // 1 request should specify to load content in a subframe but also contain the |
| // search terms. |
| EXPECT_EQ(1, |
| std::count_if(requests.begin(), requests.end(), |
| [search_terms](const auto& request) { |
| return request.relative_url.find(kLoadInSubframe) != |
| std::string::npos && |
| request.relative_url.find(search_terms) != |
| std::string::npos; |
| })); |
| } |
| |
| // True means that responses are streamed, false means full responses must be |
| // received in order to server the response. |
| INSTANTIATE_TEST_SUITE_P(All, |
| SearchPrefetchServiceEnabledBrowserTest, |
| testing::Bool()); |
| |
| class SearchPrefetchServiceZeroCacheTimeBrowserTest |
| : public SearchPrefetchBaseBrowserTest { |
| public: |
| SearchPrefetchServiceZeroCacheTimeBrowserTest() { |
| feature_list_.InitWithFeaturesAndParameters( |
| {{kSearchPrefetchServicePrefetching, |
| {{"prefetch_caching_limit_ms", "10"}}}, |
| {{kSearchPrefetchService}, {}}}, |
| {}); |
| |
| // Hang responses so the status will stay as InFlight until the entry is |
| // removed. |
| set_should_hang_requests(true); |
| } |
| |
| private: |
| base::test::ScopedFeatureList feature_list_; |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(SearchPrefetchServiceZeroCacheTimeBrowserTest, |
| ExpireAfterDuration) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_terms = "prefetch_content"; |
| |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| |
| // Make sure a new fetch doesn't happen before expiry. |
| EXPECT_FALSE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| EXPECT_TRUE(prefetch_status.has_value()); |
| |
| WaitUntilStatusChanges(base::ASCIIToUTF16(search_terms)); |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| |
| // Prefetch should be gone now. |
| EXPECT_FALSE(prefetch_status.has_value()); |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(SearchPrefetchServiceZeroCacheTimeBrowserTest, |
| PrefetchRateLimitingClearsAfterRemoval) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL( |
| GetSearchServerQueryURL("prefetch_1"))); |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL( |
| GetSearchServerQueryURL("prefetch_2"))); |
| EXPECT_FALSE(search_prefetch_service->MaybePrefetchURL( |
| GetSearchServerQueryURL("prefetch_3"))); |
| |
| WaitUntilStatusChanges(base::ASCIIToUTF16("prefetch_1")); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL( |
| GetSearchServerQueryURL("prefetch_4"))); |
| } |
| |
| class SearchPrefetchServiceZeroErrorTimeBrowserTest |
| : public SearchPrefetchBaseBrowserTest { |
| public: |
| SearchPrefetchServiceZeroErrorTimeBrowserTest() { |
| feature_list_.InitWithFeaturesAndParameters( |
| {{kSearchPrefetchServicePrefetching, |
| {{"error_backoff_duration_ms", "10"}}}, |
| {{kSearchPrefetchService}, {}}}, |
| {}); |
| } |
| |
| private: |
| base::test::ScopedFeatureList feature_list_; |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(SearchPrefetchServiceZeroErrorTimeBrowserTest, |
| ErrorClearedAfterDuration) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| std::string search_terms = "502_on_prefetch"; |
| |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| WaitUntilStatusChanges(base::ASCIIToUTF16(search_terms)); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kRequestFailed, prefetch_status.value()); |
| |
| WaitForDuration(base::TimeDelta::FromMilliseconds(30)); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL( |
| GetSearchServerQueryURL("other_query"))); |
| } |
| |
| class SearchPrefetchServiceDefaultMatchOnlyBrowserTest |
| : public SearchPrefetchBaseBrowserTest { |
| public: |
| SearchPrefetchServiceDefaultMatchOnlyBrowserTest() { |
| feature_list_.InitWithFeaturesAndParameters( |
| {{kSearchPrefetchServicePrefetching, |
| {{"only_prefetch_default_match", "true"}}}, |
| {{kSearchPrefetchService}, {}}}, |
| {}); |
| } |
| |
| private: |
| base::test::ScopedFeatureList feature_list_; |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(SearchPrefetchServiceDefaultMatchOnlyBrowserTest, |
| OmniboxEditDoesNotTriggerPrefetchForSecondMatch) { |
| // phi being set to one causes the order of prefetch suggest to be different. |
| // This should still prefetch a result for the |kOmniboxSuggestPrefetchQuery|. |
| set_phi_is_one(true); |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| std::string search_terms = kOmniboxSuggestPrefetchQuery; |
| |
| // Trigger an omnibox suggest fetch that does not have a prefetch hint. |
| AutocompleteInput input( |
| base::ASCIIToUTF16(search_terms), metrics::OmniboxEventProto::BLANK, |
| ChromeAutocompleteSchemeClassifier(browser()->profile())); |
| LocationBar* location_bar = browser()->window()->GetLocationBar(); |
| OmniboxView* omnibox = location_bar->GetOmniboxView(); |
| AutocompleteController* autocomplete_controller = |
| omnibox->model()->autocomplete_controller(); |
| |
| // Prevent the stop timer from killing the hints fetch early. |
| autocomplete_controller->SetStartStopTimerDurationForTesting( |
| base::TimeDelta::FromSeconds(10)); |
| autocomplete_controller->Start(input); |
| |
| ui_test_utils::WaitForAutocompleteDone(browser()); |
| EXPECT_TRUE(autocomplete_controller->done()); |
| |
| WaitForDuration(base::TimeDelta::FromMilliseconds(100)); |
| |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(kOmniboxSuggestPrefetchSecondItemQuery)); |
| EXPECT_FALSE(prefetch_status.has_value()); |
| ui_test_utils::NavigateToURL( |
| browser(), |
| GetSearchServerQueryURL(kOmniboxSuggestPrefetchSecondItemQuery)); |
| |
| auto inner_html = GetDocumentInnerHTML(); |
| |
| EXPECT_TRUE(base::Contains(inner_html, "regular")); |
| EXPECT_FALSE(base::Contains(inner_html, "prefetch")); |
| } |
| |
| class GooglePFTest : public InProcessBrowserTest { |
| public: |
| GooglePFTest() = default; |
| |
| void SetUpOnMainThread() override { |
| TemplateURLService* model = |
| TemplateURLServiceFactory::GetForProfile(browser()->profile()); |
| ASSERT_TRUE(model); |
| search_test_utils::WaitForTemplateURLServiceToLoad(model); |
| ASSERT_TRUE(model->loaded()); |
| } |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(GooglePFTest, BaseGoogleSearchHasPFForPrefetch) { |
| TemplateURLService* template_url_service = |
| TemplateURLServiceFactory::GetForProfile(browser()->profile()); |
| auto* default_search = template_url_service->GetDefaultSearchProvider(); |
| |
| TemplateURLRef::SearchTermsArgs search_terms_args = |
| TemplateURLRef::SearchTermsArgs(base::string16()); |
| search_terms_args.is_prefetch = true; |
| |
| std::string generated_url = default_search->url_ref().ReplaceSearchTerms( |
| search_terms_args, template_url_service->search_terms_data(), nullptr); |
| EXPECT_TRUE(base::Contains(generated_url, "pf=cs")); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(GooglePFTest, BaseGoogleSearchNoPFForNonPrefetch) { |
| TemplateURLService* template_url_service = |
| TemplateURLServiceFactory::GetForProfile(browser()->profile()); |
| auto* default_search = template_url_service->GetDefaultSearchProvider(); |
| |
| TemplateURLRef::SearchTermsArgs search_terms_args = |
| TemplateURLRef::SearchTermsArgs(base::string16()); |
| search_terms_args.is_prefetch = false; |
| |
| std::string generated_url = default_search->url_ref().ReplaceSearchTerms( |
| search_terms_args, template_url_service->search_terms_data(), nullptr); |
| EXPECT_FALSE(base::Contains(generated_url, "pf=cs")); |
| } |