| // 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/callback_helpers.h" |
| #include "base/containers/contains.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/run_loop.h" |
| #include "base/strings/string_split.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/time/time.h" |
| #include "build/build_config.h" |
| #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h" |
| #include "chrome/browser/chrome_content_browser_client.h" |
| #include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
| #include "chrome/browser/devtools/devtools_window.h" |
| #include "chrome/browser/devtools/devtools_window_testing.h" |
| #include "chrome/browser/prefetch/prefetch_prefs.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_edit_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/browser/service_worker_context.h" |
| #include "content/public/browser/storage_partition.h" |
| #include "content/public/common/content_client.h" |
| #include "content/public/common/content_features.h" |
| #include "content/public/common/referrer.h" |
| #include "content/public/test/back_forward_cache_util.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 "content/public/test/content_mock_cert_verifier.h" |
| #include "content/public/test/test_navigation_observer.h" |
| #include "net/base/url_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 "services/network/public/mojom/network_context.mojom.h" |
| #include "services/network/public/mojom/url_response_head.mojom.h" |
| #include "third_party/abseil-cpp/absl/types/optional.h" |
| #include "third_party/blink/public/common/loader/url_loader_throttle.h" |
| #include "third_party/blink/public/common/storage_key/storage_key.h" |
| #include "third_party/blink/public/mojom/service_worker/service_worker_registration_options.mojom.h" |
| #include "ui/base/page_transition_types.h" |
| #include "url/gurl.h" |
| #include "url/origin.h" |
| |
| namespace { |
| constexpr char kSuggestDomain[] = "suggest.com"; |
| constexpr char16_t kSuggestDomain16[] = u"suggest.com"; |
| constexpr char kSearchDomain[] = "search.com"; |
| constexpr char16_t kSearchDomain16[] = u"search.com"; |
| constexpr char kOmniboxSuggestPrefetchQuery[] = "porgs"; |
| constexpr char kOmniboxSuggestPrefetchSecondItemQuery[] = "porgsandwich"; |
| constexpr char16_t kOmniboxSuggestPrefetchSecondItemQuery16[] = u"porgsandwich"; |
| constexpr char kOmniboxSuggestNonPrefetchQuery[] = "puffins"; |
| constexpr char16_t kOmniboxSuggestNonPrefetchQuery16[] = u"puffins"; |
| constexpr char kLoadInSubframe[] = "/load_in_subframe"; |
| constexpr char kClientHintsURL[] = "/accept_ch.html"; |
| constexpr char kThrottleHeader[] = "porgs-header"; |
| constexpr char kThrottleHeaderValue[] = "porgs-header-value"; |
| constexpr char kServiceWorkerUrl[] = "/navigation_preload.js"; |
| } // namespace |
| |
| // A delegate to cancel prefetch requests by setting |defer| to true. |
| class DeferringThrottle : public blink::URLLoaderThrottle { |
| public: |
| DeferringThrottle() = default; |
| ~DeferringThrottle() override = default; |
| |
| void WillStartRequest(network::ResourceRequest* request, |
| bool* defer) override { |
| *defer = true; |
| } |
| }; |
| |
| class ThrottleAllContentBrowserClient : public ChromeContentBrowserClient { |
| public: |
| ThrottleAllContentBrowserClient() = default; |
| ~ThrottleAllContentBrowserClient() override = default; |
| |
| // ContentBrowserClient overrides: |
| std::vector<std::unique_ptr<blink::URLLoaderThrottle>> |
| CreateURLLoaderThrottles( |
| const network::ResourceRequest& request, |
| content::BrowserContext* browser_context, |
| const base::RepeatingCallback<content::WebContents*()>& wc_getter, |
| content::NavigationUIData* navigation_ui_data, |
| int frame_tree_node_id) override { |
| std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles; |
| throttles.push_back(std::make_unique<DeferringThrottle>()); |
| return throttles; |
| } |
| }; |
| |
| // A delegate to cancel prefetch requests by calling cancel on |delegate_|. |
| class CancellingThrottle : public blink::URLLoaderThrottle { |
| public: |
| CancellingThrottle() = default; |
| ~CancellingThrottle() override = default; |
| |
| void WillStartRequest(network::ResourceRequest* request, |
| bool* defer) override { |
| delegate_->CancelWithError(net::ERR_ABORTED); |
| } |
| }; |
| |
| class CancelAllContentBrowserClient : public ChromeContentBrowserClient { |
| public: |
| CancelAllContentBrowserClient() = default; |
| ~CancelAllContentBrowserClient() override = default; |
| |
| // ContentBrowserClient overrides: |
| std::vector<std::unique_ptr<blink::URLLoaderThrottle>> |
| CreateURLLoaderThrottles( |
| const network::ResourceRequest& request, |
| content::BrowserContext* browser_context, |
| const base::RepeatingCallback<content::WebContents*()>& wc_getter, |
| content::NavigationUIData* navigation_ui_data, |
| int frame_tree_node_id) override { |
| std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles; |
| throttles.push_back(std::make_unique<CancellingThrottle>()); |
| return throttles; |
| } |
| }; |
| |
| // A delegate to add a custom header to prefetches. |
| class AddHeaderModifyingThrottle : public blink::URLLoaderThrottle { |
| public: |
| AddHeaderModifyingThrottle() = default; |
| ~AddHeaderModifyingThrottle() override = default; |
| |
| void WillStartRequest(network::ResourceRequest* request, |
| bool* defer) override { |
| request->headers.SetHeader(kThrottleHeader, kThrottleHeaderValue); |
| } |
| }; |
| |
| class AddHeaderContentBrowserClient : public ChromeContentBrowserClient { |
| public: |
| AddHeaderContentBrowserClient() = default; |
| ~AddHeaderContentBrowserClient() override = default; |
| |
| // ContentBrowserClient overrides: |
| std::vector<std::unique_ptr<blink::URLLoaderThrottle>> |
| CreateURLLoaderThrottles( |
| const network::ResourceRequest& request, |
| content::BrowserContext* browser_context, |
| const base::RepeatingCallback<content::WebContents*()>& wc_getter, |
| content::NavigationUIData* navigation_ui_data, |
| int frame_tree_node_id) override { |
| std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles; |
| throttles.push_back(std::make_unique<AddHeaderModifyingThrottle>()); |
| return throttles; |
| } |
| }; |
| |
| // A delegate to add a custom header to prefetches. |
| class AddQueryParamModifyingThrottle : public blink::URLLoaderThrottle { |
| public: |
| AddQueryParamModifyingThrottle() = default; |
| ~AddQueryParamModifyingThrottle() override = default; |
| |
| void WillStartRequest(network::ResourceRequest* request, |
| bool* defer) override { |
| request->url = |
| net::AppendOrReplaceQueryParameter(request->url, "fakeparam", "0"); |
| } |
| }; |
| |
| class AddQueryParamContentBrowserClient : public ChromeContentBrowserClient { |
| public: |
| AddQueryParamContentBrowserClient() = default; |
| ~AddQueryParamContentBrowserClient() override = default; |
| |
| // ContentBrowserClient overrides: |
| std::vector<std::unique_ptr<blink::URLLoaderThrottle>> |
| CreateURLLoaderThrottles( |
| const network::ResourceRequest& request, |
| content::BrowserContext* browser_context, |
| const base::RepeatingCallback<content::WebContents*()>& wc_getter, |
| content::NavigationUIData* navigation_ui_data, |
| int frame_tree_node_id) override { |
| std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles; |
| throttles.push_back(std::make_unique<AddQueryParamModifyingThrottle>()); |
| return throttles; |
| } |
| }; |
| |
| // A delegate to add a custom header to prefetches. |
| class ChangeQueryModifyingThrottle : public blink::URLLoaderThrottle { |
| public: |
| ChangeQueryModifyingThrottle() = default; |
| ~ChangeQueryModifyingThrottle() override = default; |
| |
| void WillStartRequest(network::ResourceRequest* request, |
| bool* defer) override { |
| request->url = |
| net::AppendOrReplaceQueryParameter(request->url, "q", "modifiedsearch"); |
| } |
| }; |
| |
| class ChangeQueryContentBrowserClient : public ChromeContentBrowserClient { |
| public: |
| ChangeQueryContentBrowserClient() = default; |
| ~ChangeQueryContentBrowserClient() override = default; |
| |
| // ContentBrowserClient overrides: |
| std::vector<std::unique_ptr<blink::URLLoaderThrottle>> |
| CreateURLLoaderThrottles( |
| const network::ResourceRequest& request, |
| content::BrowserContext* browser_context, |
| const base::RepeatingCallback<content::WebContents*()>& wc_getter, |
| content::NavigationUIData* navigation_ui_data, |
| int frame_tree_node_id) override { |
| std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles; |
| throttles.push_back(std::make_unique<ChangeQueryModifyingThrottle>()); |
| return throttles; |
| } |
| }; |
| |
| 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_->ServeFilesFromSourceDirectory( |
| "chrome/test/data/client_hints"); |
| 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}")); |
| |
| mock_cert_verifier_.mock_cert_verifier()->set_default_result(net::OK); |
| } |
| |
| void SetUpInProcessBrowserTestFixture() override { |
| mock_cert_verifier_.SetUpInProcessBrowserTestFixture(); |
| } |
| |
| void TearDownInProcessBrowserTestFixture() override { |
| mock_cert_verifier_.TearDownInProcessBrowserTestFixture(); |
| } |
| |
| void SetUpCommandLine(base::CommandLine* cmd) override { |
| cmd->AppendSwitch("ignore-certificate-errors"); |
| |
| mock_cert_verifier_.SetUpCommandLine(cmd); |
| } |
| |
| 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 WaitUntilStatusChangesTo(std::u16string search_terms, |
| absl::optional<SearchPrefetchStatus> status) { |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| while (search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| search_terms) != status) { |
| 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(absl::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 = |
| browser()->profile()->GetBrowsingDataRemover(); |
| 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(kSearchDomain16); |
| 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(kSuggestDomain16); |
| 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)); |
| } |
| |
| void OpenDevToolsWindow(content::WebContents* tab) { |
| window_ = DevToolsWindowTesting::OpenDevToolsWindowSync(tab, true); |
| } |
| |
| void CloseDevToolsWindow() { |
| DevToolsWindowTesting::CloseDevToolsWindowSync(window_); |
| } |
| |
| // Allows the search server to serve |content| with |content_type| when |
| // |relative_url| is requested. |
| void RegisterStaticFile(const std::string& relative_url, |
| const std::string& content, |
| const std::string& content_type) { |
| static_files_[relative_url] = std::make_pair(content, content_type); |
| } |
| |
| 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 (request.relative_url == kClientHintsURL) |
| return nullptr; |
| |
| if (hang_requests_after_start_) { |
| base::StringPairs headers = {{"Content-Length", "100"}}; |
| return std::make_unique<net::test_server::HungAfterHeadersHttpResponse>( |
| headers); |
| } |
| |
| 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 (base::Contains(static_files_, request.relative_url)) { |
| std::unique_ptr<net::test_server::BasicHttpResponse> resp = |
| std::make_unique<net::test_server::BasicHttpResponse>(); |
| resp->set_code(net::HTTP_OK); |
| resp->set_content(static_files_[request.relative_url].first); |
| resp->set_content_type(static_files_[request.relative_url].second); |
| resp->AddCustomHeader("cache-control", "private, max-age=0"); |
| return resp; |
| } |
| |
| // 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); |
| resp->AddCustomHeader("cache-control", "private, max-age=0"); |
| 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); |
| resp->AddCustomHeader("cache-control", "private, max-age=0"); |
| 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; |
| } |
| |
| content::ContentMockCertVerifier mock_cert_verifier_; |
| |
| 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; |
| |
| // Test cases can add path, content, content type tuples to be served. |
| std::map<std::string /* path */, |
| std::pair<std::string /* content */, std::string /* content_type */>> |
| static_files_; |
| |
| raw_ptr<DevToolsWindow> window_ = nullptr; |
| }; |
| |
| 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( |
| /*create_if_needed=*/true))); |
| } |
| |
| 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"}, |
| {"max_attempts_per_caching_duration", "3"}, |
| {"cache_size", "1"}, |
| {"device_memory_threshold_MB", "0"}}}, |
| {{kSearchPrefetchService}, {}}}, |
| {}); |
| } |
| |
| private: |
| base::test::ScopedFeatureList feature_list_; |
| }; |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| ServiceNotCreatedWhenIncognito) { |
| EXPECT_EQ(nullptr, SearchPrefetchServiceFactory::GetForProfile( |
| browser()->profile()->GetPrimaryOTRProfile( |
| /*create_if_needed=*/true))); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| ServiceCreatedWhenFeatureEnabled) { |
| EXPECT_NE(nullptr, |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile())); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| BasicPrefetchFunctionality) { |
| base::HistogramTester histogram_tester; |
| 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)); |
| histogram_tester.ExpectUniqueSample( |
| "Omnibox.SearchPrefetch.PrefetchEligibilityReason", |
| SearchPrefetchEligibilityReason::kPrefetchStarted, 1); |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kInFlight, prefetch_status.value()); |
| |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| |
| 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()); |
| // Make sure we don't get client hints headers by default. |
| EXPECT_FALSE(base::Contains(headers, "viewport-width")); |
| EXPECT_TRUE(base::Contains(headers, "User-Agent")); |
| ASSERT_TRUE(base::Contains(headers, "Upgrade-Insecure-Requests")); |
| EXPECT_TRUE(base::Contains(headers["Upgrade-Insecure-Requests"], "1")); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kComplete, prefetch_status.value()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| PrefetchThrottled) { |
| base::HistogramTester histogram_tester; |
| ThrottleAllContentBrowserClient browser_client; |
| auto* old_client = content::SetBrowserClientForTesting(&browser_client); |
| 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)); |
| histogram_tester.ExpectUniqueSample( |
| "Omnibox.SearchPrefetch.PrefetchEligibilityReason", |
| SearchPrefetchEligibilityReason::kThrottled, 1); |
| EXPECT_FALSE(prefetch_status.has_value()); |
| content::SetBrowserClientForTesting(old_client); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| PrefetchCancelledByThrottle) { |
| CancelAllContentBrowserClient browser_client; |
| base::HistogramTester histogram_tester; |
| auto* old_client = content::SetBrowserClientForTesting(&browser_client); |
| 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)); |
| histogram_tester.ExpectUniqueSample( |
| "Omnibox.SearchPrefetch.PrefetchEligibilityReason", |
| SearchPrefetchEligibilityReason::kThrottled, 1); |
| EXPECT_FALSE(prefetch_status.has_value()); |
| content::SetBrowserClientForTesting(old_client); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| PrefetchThrottleAddsHeader) { |
| AddHeaderContentBrowserClient browser_client; |
| auto* old_client = content::SetBrowserClientForTesting(&browser_client); |
| 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()); |
| |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| |
| auto headers = search_server_requests()[0].headers; |
| EXPECT_EQ(1u, search_server_requests().size()); |
| ASSERT_TRUE(base::Contains(headers, kThrottleHeader)); |
| EXPECT_TRUE(base::Contains(headers[kThrottleHeader], kThrottleHeaderValue)); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kComplete, prefetch_status.value()); |
| content::SetBrowserClientForTesting(old_client); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| QueryParamAddedInThrottle) { |
| AddQueryParamContentBrowserClient browser_client; |
| auto* old_client = content::SetBrowserClientForTesting(&browser_client); |
| 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()); |
| |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kComplete, prefetch_status.value()); |
| content::SetBrowserClientForTesting(old_client); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| ChangeQueryCancelsPrefetch) { |
| ChangeQueryContentBrowserClient browser_client; |
| base::HistogramTester histogram_tester; |
| auto* old_client = content::SetBrowserClientForTesting(&browser_client); |
| 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)); |
| histogram_tester.ExpectUniqueSample( |
| "Omnibox.SearchPrefetch.PrefetchEligibilityReason", |
| SearchPrefetchEligibilityReason::kThrottled, 1); |
| EXPECT_FALSE(prefetch_status.has_value()); |
| content::SetBrowserClientForTesting(old_client); |
| } |
| |
| class HeaderObserverContentBrowserClient : public ChromeContentBrowserClient { |
| public: |
| HeaderObserverContentBrowserClient() = default; |
| ~HeaderObserverContentBrowserClient() override = default; |
| |
| // ContentBrowserClient overrides: |
| std::vector<std::unique_ptr<blink::URLLoaderThrottle>> |
| CreateURLLoaderThrottles( |
| const network::ResourceRequest& request, |
| content::BrowserContext* browser_context, |
| const base::RepeatingCallback<content::WebContents*()>& wc_getter, |
| content::NavigationUIData* navigation_ui_data, |
| int frame_tree_node_id) override; |
| |
| bool had_raw_request_info() { return had_raw_request_info_; } |
| |
| void set_had_raw_request_info(bool had_raw_request_info) { |
| had_raw_request_info_ = had_raw_request_info; |
| } |
| |
| private: |
| bool had_raw_request_info_ = false; |
| }; |
| |
| std::vector<std::unique_ptr<blink::URLLoaderThrottle>> |
| HeaderObserverContentBrowserClient::CreateURLLoaderThrottles( |
| const network::ResourceRequest& request, |
| content::BrowserContext* browser_context, |
| const base::RepeatingCallback<content::WebContents*()>& wc_getter, |
| content::NavigationUIData* navigation_ui_data, |
| int frame_tree_node_id) { |
| std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles = |
| ChromeContentBrowserClient::CreateURLLoaderThrottles( |
| request, browser_context, wc_getter, navigation_ui_data, |
| frame_tree_node_id); |
| return throttles; |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| HeadersNotReportedFromNetwork) { |
| 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()); |
| |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| |
| HeaderObserverContentBrowserClient browser_client; |
| auto* old_client = content::SetBrowserClientForTesting(&browser_client); |
| ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), prefetch_url)); |
| |
| EXPECT_FALSE(browser_client.had_raw_request_info()); |
| content::SetBrowserClientForTesting(old_client); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| PrefetchRateLimiting) { |
| base::HistogramTester histogram_tester; |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL( |
| GetSearchServerQueryURL("prefetch_1"))); |
| histogram_tester.ExpectUniqueSample( |
| "Omnibox.SearchPrefetch.PrefetchEligibilityReason", |
| SearchPrefetchEligibilityReason::kPrefetchStarted, 1); |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL( |
| GetSearchServerQueryURL("prefetch_2"))); |
| histogram_tester.ExpectUniqueSample( |
| "Omnibox.SearchPrefetch.PrefetchEligibilityReason", |
| SearchPrefetchEligibilityReason::kPrefetchStarted, 2); |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL( |
| GetSearchServerQueryURL("prefetch_3"))); |
| histogram_tester.ExpectUniqueSample( |
| "Omnibox.SearchPrefetch.PrefetchEligibilityReason", |
| SearchPrefetchEligibilityReason::kPrefetchStarted, 3); |
| EXPECT_FALSE(search_prefetch_service->MaybePrefetchURL( |
| GetSearchServerQueryURL("prefetch_4"))); |
| histogram_tester.ExpectBucketCount( |
| "Omnibox.SearchPrefetch.PrefetchEligibilityReason", |
| SearchPrefetchEligibilityReason::kMaxAttemptsReached, 1); |
| |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting(u"prefetch_1"); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kInFlight, prefetch_status.value()); |
| |
| prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting(u"prefetch_2"); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kInFlight, prefetch_status.value()); |
| |
| prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting(u"prefetch_3"); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kInFlight, prefetch_status.value()); |
| |
| prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting(u"prefetch_4"); |
| EXPECT_FALSE(prefetch_status.has_value()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| BasicClientHintsFunctionality) { |
| // Fetch a response that will set client hints on future requests. |
| GURL client_hints = GetSearchServerQueryURLWithNoQuery(kClientHintsURL); |
| ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), client_hints)); |
| |
| 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()); |
| |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| |
| 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; |
| |
| // Make sure we can get client hints headers. |
| EXPECT_TRUE(base::Contains(headers, "viewport-width")); |
| } |
| |
| 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()); |
| |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kRequestFailed); |
| |
| 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) { |
| base::HistogramTester histogram_tester; |
| 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)); |
| histogram_tester.ExpectUniqueSample( |
| "Omnibox.SearchPrefetch.PrefetchEligibilityReason", |
| SearchPrefetchEligibilityReason::kPrefetchStarted, 1); |
| |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| |
| EXPECT_FALSE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| histogram_tester.ExpectBucketCount( |
| "Omnibox.SearchPrefetch.PrefetchEligibilityReason", |
| SearchPrefetchEligibilityReason::kAttemptedQueryRecently, 1); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, BadURL) { |
| base::HistogramTester histogram_tester; |
| 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)); |
| histogram_tester.ExpectUniqueSample( |
| "Omnibox.SearchPrefetch.PrefetchEligibilityReason", |
| SearchPrefetchEligibilityReason::kNotDefaultSearchWithTerms, 1); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| PreloadDisabled) { |
| base::HistogramTester histogram_tester; |
| prefetch::SetPreloadPagesState(browser()->profile()->GetPrefs(), |
| prefetch::PreloadPagesState::kNoPreloading); |
| 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)); |
| histogram_tester.ExpectUniqueSample( |
| "Omnibox.SearchPrefetch.PrefetchEligibilityReason", |
| SearchPrefetchEligibilityReason::kPrefetchDisabled, 1); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| BasicPrefetchServed) { |
| base::HistogramTester histogram_tester; |
| 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)); |
| histogram_tester.ExpectUniqueSample( |
| "Omnibox.SearchPrefetch.PrefetchEligibilityReason", |
| SearchPrefetchEligibilityReason::kPrefetchStarted, 1); |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kComplete, prefetch_status.value()); |
| |
| ASSERT_TRUE(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")); |
| histogram_tester.ExpectUniqueSample( |
| "Omnibox.SearchPrefetch.PrefetchFinalStatus", |
| SearchPrefetchStatus::kComplete, 1); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| BackPrefetchServed) { |
| // This test prefetches and serves two SRP responses. It then navigates back |
| // then forward, the back navigation should not be cached, due to cache limit |
| // size of 1, the second navigation should be cached. |
| |
| base::HistogramTester histogram_tester; |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| // Disable back/forward cache to ensure that it doesn't get preserved in the |
| // back/forward cache. |
| content::DisableBackForwardCacheForTesting( |
| GetWebContents(), content::BackForwardCache::TEST_REQUIRES_NO_CACHING); |
| |
| std::string search_terms = "prefetch_content"; |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms + "&pf=cs"); |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| ASSERT_TRUE(ui_test_utils::NavigateToURL( |
| browser(), GetSearchServerQueryURL(search_terms))); |
| |
| // The prefetch should be served, and only 1 request should be issued. |
| EXPECT_EQ(1u, search_server_requests().size()); |
| auto inner_html = GetDocumentInnerHTML(); |
| EXPECT_FALSE(base::Contains(inner_html, "regular")); |
| EXPECT_TRUE(base::Contains(inner_html, "prefetch")); |
| |
| search_terms = "prefetch_content_2"; |
| prefetch_url = GetSearchServerQueryURL(search_terms + "&pf=cs"); |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| ASSERT_TRUE(ui_test_utils::NavigateToURL( |
| browser(), GetSearchServerQueryURL(search_terms))); |
| |
| // The prefetch should be served, and only 1 request (now the second total |
| // request) should be issued. |
| EXPECT_EQ(2u, search_server_requests().size()); |
| inner_html = GetDocumentInnerHTML(); |
| EXPECT_FALSE(base::Contains(inner_html, "regular")); |
| EXPECT_TRUE(base::Contains(inner_html, "prefetch")); |
| |
| content::TestNavigationObserver back_load_observer(GetWebContents()); |
| GetWebContents()->GetController().GoBack(); |
| back_load_observer.Wait(); |
| |
| // There should not be a cached prefetch request, so there should be a network |
| // request. |
| EXPECT_EQ(3u, search_server_requests().size()); |
| inner_html = GetDocumentInnerHTML(); |
| EXPECT_TRUE(base::Contains(inner_html, "regular")); |
| EXPECT_FALSE(base::Contains(inner_html, "prefetch")); |
| |
| content::TestNavigationObserver forward_load_observer(GetWebContents()); |
| GetWebContents()->GetController().GoForward(); |
| forward_load_observer.Wait(); |
| |
| // There should be a cached prefetch request, so there should not be a new |
| // network request. |
| EXPECT_EQ(3u, search_server_requests().size()); |
| inner_html = GetDocumentInnerHTML(); |
| EXPECT_FALSE(base::Contains(inner_html, "regular")); |
| EXPECT_TRUE(base::Contains(inner_html, "prefetch")); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| BackPrefetchServedAfterPrefs) { |
| // This test prefetches and serves two SRP responses. It then navigates back |
| // then forward, the back navigation should not be cached, due to cache limit |
| // size of 1, the second navigation should be cached. |
| |
| base::HistogramTester histogram_tester; |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| // Disable back/forward cache to ensure that it doesn't get preserved in the |
| // back/forward cache. |
| content::DisableBackForwardCacheForTesting( |
| GetWebContents(), content::BackForwardCache::TEST_REQUIRES_NO_CACHING); |
| |
| std::string search_terms = "prefetch_content"; |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms + "&pf=cs"); |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| ASSERT_TRUE(ui_test_utils::NavigateToURL( |
| browser(), GetSearchServerQueryURL(search_terms))); |
| |
| // The prefetch should be served, and only 1 request should be issued. |
| EXPECT_EQ(1u, search_server_requests().size()); |
| auto inner_html = GetDocumentInnerHTML(); |
| EXPECT_FALSE(base::Contains(inner_html, "regular")); |
| EXPECT_TRUE(base::Contains(inner_html, "prefetch")); |
| |
| search_terms = "prefetch_content_2"; |
| prefetch_url = GetSearchServerQueryURL(search_terms + "&pf=cs"); |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| ASSERT_TRUE(ui_test_utils::NavigateToURL( |
| browser(), GetSearchServerQueryURL(search_terms))); |
| |
| // The prefetch should be served, and only 1 request (now the second total |
| // request) should be issued. |
| EXPECT_EQ(2u, search_server_requests().size()); |
| inner_html = GetDocumentInnerHTML(); |
| EXPECT_FALSE(base::Contains(inner_html, "regular")); |
| EXPECT_TRUE(base::Contains(inner_html, "prefetch")); |
| |
| content::TestNavigationObserver back_load_observer(GetWebContents()); |
| GetWebContents()->GetController().GoBack(); |
| back_load_observer.Wait(); |
| |
| // There should not be a cached prefetch request, so there should be a network |
| // request. |
| EXPECT_EQ(3u, search_server_requests().size()); |
| inner_html = GetDocumentInnerHTML(); |
| EXPECT_TRUE(base::Contains(inner_html, "regular")); |
| EXPECT_FALSE(base::Contains(inner_html, "prefetch")); |
| |
| // Reload the map from prefs. |
| EXPECT_FALSE(search_prefetch_service->LoadFromPrefsForTesting()); |
| |
| content::TestNavigationObserver forward_load_observer(GetWebContents()); |
| GetWebContents()->GetController().GoForward(); |
| forward_load_observer.Wait(); |
| |
| // There should be a cached prefetch request, so there should not be a new |
| // network request. |
| EXPECT_EQ(3u, search_server_requests().size()); |
| inner_html = GetDocumentInnerHTML(); |
| EXPECT_FALSE(base::Contains(inner_html, "regular")); |
| EXPECT_TRUE(base::Contains(inner_html, "prefetch")); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| BackPrefetchServedAfterPrefsNoOverflow) { |
| // This test prefetches and serves two SRP responses. It then navigates back |
| // then forward, the back navigation should not be cached, due to cache limit |
| // size of 1, the second navigation should be cached. |
| |
| base::HistogramTester histogram_tester; |
| 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 + "&pf=cs"); |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| ASSERT_TRUE(ui_test_utils::NavigateToURL( |
| browser(), GetSearchServerQueryURL(search_terms))); |
| |
| // The prefetch should be served, and only 1 request should be issued. |
| EXPECT_EQ(1u, search_server_requests().size()); |
| auto inner_html = GetDocumentInnerHTML(); |
| EXPECT_FALSE(base::Contains(inner_html, "regular")); |
| EXPECT_TRUE(base::Contains(inner_html, "prefetch")); |
| |
| search_terms = "prefetch_content_2"; |
| ASSERT_TRUE(ui_test_utils::NavigateToURL( |
| browser(), GetSearchServerQueryURL(search_terms))); |
| |
| // No prefetch request started, and only 1 request (now the second total |
| // request) should be issued. |
| EXPECT_EQ(2u, search_server_requests().size()); |
| inner_html = GetDocumentInnerHTML(); |
| EXPECT_TRUE(base::Contains(inner_html, "regular")); |
| EXPECT_FALSE(base::Contains(inner_html, "prefetch")); |
| |
| // Reload the map from prefs. |
| EXPECT_FALSE(search_prefetch_service->LoadFromPrefsForTesting()); |
| |
| content::TestNavigationObserver back_load_observer(GetWebContents()); |
| GetWebContents()->GetController().GoBack(); |
| back_load_observer.Wait(); |
| |
| // There should be a cached prefetch request, so there should not be a new |
| // network request. |
| EXPECT_EQ(2u, search_server_requests().size()); |
| inner_html = GetDocumentInnerHTML(); |
| EXPECT_FALSE(base::Contains(inner_html, "regular")); |
| EXPECT_TRUE(base::Contains(inner_html, "prefetch")); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| EvictedCacheFallsback) { |
| // This test prefetches and serves a SRP responses. It then navigates to a |
| // different URL. Then it clears cache as if it was evicted. Then it navigates |
| // back to the prefetched SRP. As a result, the back forward cache should |
| // attempt to use the prefetch, but fall back to network on the original URL. |
| |
| base::HistogramTester histogram_tester; |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| // Disable back/forward cache to ensure that it doesn't get preserved in the |
| // back/forward cache. |
| content::DisableBackForwardCacheForTesting( |
| GetWebContents(), content::BackForwardCache::TEST_REQUIRES_NO_CACHING); |
| |
| std::string search_terms = "prefetch_content"; |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms + "&pf=cs"); |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| ASSERT_TRUE(ui_test_utils::NavigateToURL( |
| browser(), GetSearchServerQueryURL(search_terms))); |
| |
| // The prefetch should be served, and only 1 request should be issued. |
| ASSERT_EQ(1u, search_server_requests().size()); |
| EXPECT_TRUE( |
| base::Contains(search_server_requests()[0].GetURL().spec(), "pf=cs")); |
| auto inner_html = GetDocumentInnerHTML(); |
| EXPECT_FALSE(base::Contains(inner_html, "regular")); |
| EXPECT_TRUE(base::Contains(inner_html, "prefetch")); |
| |
| ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), |
| GetSearchServerQueryURL("search"))); |
| |
| // The prefetch should be served, and only 1 request (now the second total |
| // request) should be issued. |
| EXPECT_EQ(2u, search_server_requests().size()); |
| inner_html = GetDocumentInnerHTML(); |
| EXPECT_TRUE(base::Contains(inner_html, "regular")); |
| EXPECT_FALSE(base::Contains(inner_html, "prefetch")); |
| |
| // Clearing cache should cause the back forward loader to fail over to the |
| // regular URL. |
| base::RunLoop run_loop; |
| browser() |
| ->profile() |
| ->GetDefaultStoragePartition() |
| ->GetNetworkContext() |
| ->ClearHttpCache(base::Time(), base::Time(), nullptr, |
| run_loop.QuitClosure()); |
| run_loop.Run(); |
| |
| content::TestNavigationObserver back_load_observer(GetWebContents()); |
| GetWebContents()->GetController().GoBack(); |
| back_load_observer.Wait(); |
| |
| // There should not be a cached prefetch request, so there should be a network |
| // request. |
| ASSERT_EQ(3u, search_server_requests().size()); |
| EXPECT_FALSE( |
| base::Contains(search_server_requests()[2].GetURL().spec(), "pf=cs")); |
| inner_html = GetDocumentInnerHTML(); |
| EXPECT_TRUE(base::Contains(inner_html, "regular")); |
| EXPECT_FALSE(base::Contains(inner_html, "prefetch")); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| RegularSearchQueryWhenNoPrefetch) { |
| base::HistogramTester histogram_tester; |
| 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); |
| |
| ASSERT_TRUE(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")); |
| histogram_tester.ExpectUniqueSample( |
| "Omnibox.SearchPrefetch.PrefetchServingReason", |
| SearchPrefetchServingReason::kNoPrefetch, 1); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| NonMatchingPrefetchURL) { |
| base::HistogramTester histogram_tester; |
| 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)); |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kComplete, prefetch_status.value()); |
| |
| ASSERT_TRUE(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")); |
| histogram_tester.ExpectUniqueSample( |
| "Omnibox.SearchPrefetch.PrefetchServingReason", |
| SearchPrefetchServingReason::kNoPrefetch, 1); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| ErrorCausesNoFetch) { |
| base::HistogramTester histogram_tester; |
| 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)); |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kRequestFailed); |
| |
| 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"))); |
| histogram_tester.ExpectBucketCount( |
| "Omnibox.SearchPrefetch.PrefetchEligibilityReason", |
| SearchPrefetchEligibilityReason::kErrorBackoff, 1); |
| } |
| |
| 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::Seconds(10)); |
| autocomplete_controller->Start(input); |
| |
| ui_test_utils::WaitForAutocompleteDone(browser()); |
| EXPECT_TRUE(autocomplete_controller->done()); |
| |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kComplete, prefetch_status.value()); |
| |
| ASSERT_TRUE(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::Seconds(10)); |
| autocomplete_controller->Start(input); |
| |
| ui_test_utils::WaitForAutocompleteDone(browser()); |
| EXPECT_TRUE(autocomplete_controller->done()); |
| |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| 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::Seconds(10)); |
| autocomplete_controller->Start(input); |
| |
| ui_test_utils::WaitForAutocompleteDone(browser()); |
| EXPECT_TRUE(autocomplete_controller->done()); |
| |
| WaitForDuration(base::Milliseconds(100)); |
| |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| EXPECT_FALSE(prefetch_status.has_value()); |
| ASSERT_TRUE(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::Seconds(10)); |
| autocomplete_controller->Start(input); |
| |
| ui_test_utils::WaitForAutocompleteDone(browser()); |
| EXPECT_TRUE(autocomplete_controller->done()); |
| |
| WaitUntilStatusChangesTo(kOmniboxSuggestPrefetchSecondItemQuery16, |
| SearchPrefetchStatus::kComplete); |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| kOmniboxSuggestPrefetchSecondItemQuery16); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kComplete, prefetch_status.value()); |
| |
| ASSERT_TRUE(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::Seconds(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( |
| kOmniboxSuggestNonPrefetchQuery16, 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, |
| OmniboxNavigateToMatchingEntryStreaming) { |
| // This behavior only works for streaming requests. |
| if (GetParam() == false) |
| return; |
| set_hang_requests_after_start(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::Seconds(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()); |
| |
| omnibox->model()->AcceptInput(WindowOpenDisposition::CURRENT_TAB); |
| |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), absl::nullopt); |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_FALSE(prefetch_status.has_value()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| OmniboxNavigateToNonMatchingEntryStreamingCancels) { |
| // This behavior only works for streaming requests. |
| if (GetParam() == false) |
| return; |
| set_hang_requests_after_start(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::Seconds(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()); |
| omnibox->model()->OnUpOrDownKeyPressed(1); |
| omnibox->model()->AcceptInput(WindowOpenDisposition::CURRENT_TAB); |
| |
| 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(absl::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) { |
| base::HistogramTester histogram_tester; |
| 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)); |
| |
| histogram_tester.ExpectUniqueSample( |
| "Omnibox.SearchPrefetch.PrefetchEligibilityReason", |
| SearchPrefetchEligibilityReason::kJavascriptDisabled, 1); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| NoPrefetchWhenJSDisabledOnDSE) { |
| base::HistogramTester histogram_tester; |
| 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)); |
| |
| histogram_tester.ExpectUniqueSample( |
| "Omnibox.SearchPrefetch.PrefetchEligibilityReason", |
| SearchPrefetchEligibilityReason::kJavascriptDisabled, 1); |
| |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| EXPECT_FALSE(prefetch_status.has_value()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| NoServeWhenJSDisabled) { |
| base::HistogramTester histogram_tester; |
| 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()); |
| |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kComplete, prefetch_status.value()); |
| browser()->profile()->GetPrefs()->SetBoolean(prefs::kWebKitJavascriptEnabled, |
| false); |
| |
| ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), prefetch_url)); |
| |
| histogram_tester.ExpectUniqueSample( |
| "Omnibox.SearchPrefetch.PrefetchServingReason", |
| SearchPrefetchServingReason::kJavascriptDisabled, 1); |
| // The prefetch request and the new non-prefetched served request. |
| EXPECT_EQ(2u, search_server_request_count()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| NoServeWhenJSDisabledOnDSE) { |
| base::HistogramTester histogram_tester; |
| 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()); |
| |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kComplete, prefetch_status.value()); |
| |
| HostContentSettingsMapFactory::GetForProfile(browser()->profile()) |
| ->SetContentSettingDefaultScope(prefetch_url, GURL(), |
| ContentSettingsType::JAVASCRIPT, |
| CONTENT_SETTING_BLOCK); |
| |
| ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), prefetch_url)); |
| |
| histogram_tester.ExpectUniqueSample( |
| "Omnibox.SearchPrefetch.PrefetchServingReason", |
| SearchPrefetchServingReason::kJavascriptDisabled, 1); |
| // The prefetch request and the new non-prefetched served request. |
| EXPECT_EQ(2u, search_server_request_count()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| NoServeLinkClick) { |
| base::HistogramTester histogram_tester; |
| 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()); |
| |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kComplete, prefetch_status.value()); |
| EXPECT_EQ(1u, search_server_request_count()); |
| |
| // Link click. |
| NavigateParams params(browser(), prefetch_url, ui::PAGE_TRANSITION_LINK); |
| ui_test_utils::NavigateToURL(¶ms); |
| |
| EXPECT_EQ(2u, search_server_request_count()); |
| histogram_tester.ExpectUniqueSample( |
| "Omnibox.SearchPrefetch.PrefetchServingReason", |
| SearchPrefetchServingReason::kPostReloadOrLink, 1); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, NoServeReload) { |
| base::HistogramTester histogram_tester; |
| 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); |
| ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), prefetch_url)); |
| |
| 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()); |
| |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kComplete, prefetch_status.value()); |
| EXPECT_EQ(2u, search_server_request_count()); |
| |
| // Reload. |
| content::TestNavigationObserver load_observer(GetWebContents()); |
| GetWebContents()->GetController().Reload(content::ReloadType::NORMAL, false); |
| load_observer.Wait(); |
| |
| EXPECT_EQ(3u, search_server_request_count()); |
| histogram_tester.ExpectBucketCount( |
| "Omnibox.SearchPrefetch.PrefetchServingReason", |
| SearchPrefetchServingReason::kPostReloadOrLink, 1); |
| } |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, NoServePost) { |
| base::HistogramTester histogram_tester; |
| 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()); |
| |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kComplete, prefetch_status.value()); |
| EXPECT_EQ(1u, search_server_request_count()); |
| |
| // Post request. |
| ui_test_utils::NavigateToURLWithPost(browser(), prefetch_url); |
| |
| EXPECT_EQ(2u, search_server_request_count()); |
| histogram_tester.ExpectUniqueSample( |
| "Omnibox.SearchPrefetch.PrefetchServingReason", |
| SearchPrefetchServingReason::kPostReloadOrLink, 1); |
| } |
| |
| 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()) { |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kCanBeServed); |
| } else { |
| WaitForDuration(base::Milliseconds(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()); |
| |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kComplete, prefetch_status.value()); |
| |
| ASSERT_TRUE(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; |
| })); |
| } |
| |
| void RunFirstParam(base::RepeatingClosure closure, |
| blink::ServiceWorkerStatusCode status) { |
| ASSERT_EQ(status, blink::ServiceWorkerStatusCode::kOk); |
| closure.Run(); |
| } |
| |
| // crbug.com/1272805 |
| #if BUILDFLAG(IS_MAC) |
| #define MAYBE_ServiceWorkerServedPrefetchWithPreload \ |
| DISABLED_ServiceWorkerServedPrefetchWithPreload |
| #else |
| #define MAYBE_ServiceWorkerServedPrefetchWithPreload \ |
| ServiceWorkerServedPrefetchWithPreload |
| #endif |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| MAYBE_ServiceWorkerServedPrefetchWithPreload) { |
| const GURL worker_url = GetSearchServerQueryURLWithNoQuery(kServiceWorkerUrl); |
| const std::string kEnableNavigationPreloadScript = R"( |
| self.addEventListener('activate', event => { |
| event.waitUntil(self.registration.navigationPreload.enable()); |
| }); |
| self.addEventListener('fetch', event => { |
| if (event.preloadResponse !== undefined) { |
| event.respondWith(async function() { |
| const response = await event.preloadResponse; |
| if (response) return response; |
| return fetch(event.request); |
| }); |
| } |
| });)"; |
| std::string search_terms = "prefetch_content"; |
| |
| GURL prefetch_url = GetSearchServerQueryURL(search_terms); |
| |
| RegisterStaticFile(kServiceWorkerUrl, kEnableNavigationPreloadScript, |
| "text/javascript"); |
| |
| auto* service_worker_context = browser() |
| ->profile() |
| ->GetDefaultStoragePartition() |
| ->GetServiceWorkerContext(); |
| |
| base::RunLoop run_loop; |
| blink::mojom::ServiceWorkerRegistrationOptions options( |
| GetSearchServerQueryURLWithNoQuery("/"), |
| blink::mojom::ScriptType::kClassic, |
| blink::mojom::ServiceWorkerUpdateViaCache::kImports); |
| blink::StorageKey key(url::Origin::Create(options.scope)); |
| service_worker_context->RegisterServiceWorker( |
| worker_url, key, options, |
| base::BindOnce(&RunFirstParam, run_loop.QuitClosure())); |
| run_loop.Run(); |
| |
| auto* search_prefetch_service = |
| SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); |
| EXPECT_NE(nullptr, search_prefetch_service); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kComplete, prefetch_status.value()); |
| |
| ASSERT_TRUE(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")); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| EXPECT_FALSE(prefetch_status.has_value()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, |
| RequestTimingIsNonNegative) { |
| base::HistogramTester histogram_tester; |
| 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)); |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| ASSERT_TRUE(prefetch_status.has_value()); |
| EXPECT_EQ(SearchPrefetchStatus::kComplete, prefetch_status.value()); |
| |
| ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), prefetch_url)); |
| |
| content::RenderFrameHost* frame = GetWebContents()->GetMainFrame(); |
| |
| // Check the request total time is non-negative. |
| int value = -1; |
| std::string script = |
| "window.domAutomationController.send(window.performance.timing." |
| "responseEnd - window.performance.timing.requestStart)"; |
| EXPECT_TRUE(content::ExecuteScriptAndExtractInt(frame, script, &value)); |
| EXPECT_LE(0, value); |
| |
| // Check the response time is non-negative. |
| value = -1; |
| script = |
| "window.domAutomationController.send(window.performance.timing." |
| "responseEnd - window.performance.timing.responseStart)"; |
| EXPECT_TRUE(content::ExecuteScriptAndExtractInt(frame, script, &value)); |
| EXPECT_LE(0, value); |
| |
| // Check request start is after (or the same as) navigation start. |
| value = -1; |
| script = |
| "window.domAutomationController.send(window.performance.timing." |
| "requestStart - window.performance.timing.navigationStart)"; |
| EXPECT_TRUE(content::ExecuteScriptAndExtractInt(frame, script, &value)); |
| EXPECT_LE(0, value); |
| |
| // Check response end is after (or the same as) navigation start. |
| value = -1; |
| script = |
| "window.domAutomationController.send(window.performance.timing." |
| "responseEnd - window.performance.timing.navigationStart)"; |
| EXPECT_TRUE(content::ExecuteScriptAndExtractInt(frame, script, &value)); |
| EXPECT_LE(0, value); |
| } |
| |
| // 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 SearchPrefetchServiceBFCacheTest : public SearchPrefetchBaseBrowserTest { |
| public: |
| SearchPrefetchServiceBFCacheTest() { |
| feature_list_.InitWithFeaturesAndParameters( |
| {{kSearchPrefetchServicePrefetching, |
| {{"stream_responses", "true"}, {"cache_size", "1"}}}, |
| {{kSearchPrefetchService}, {}}, |
| {{features::kBackForwardCache}, |
| {{"enable_same_site", "true"}, |
| {"ignore_outstanding_network_request_for_testing", "true"}}}}, |
| // Allow BackForwardCache for all devices regardless of their memory. |
| {features::kBackForwardCacheMemoryControls}); |
| } |
| |
| private: |
| base::test::ScopedFeatureList feature_list_; |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(SearchPrefetchServiceBFCacheTest, |
| BackForwardPrefetchServedFromBFCache) { |
| // This test prefetches and serves two SRP responses. It then navigates back |
| // then forward, the back navigation should not be cached, due to cache limit |
| // size of 1, the second navigation should be cached. |
| |
| base::HistogramTester histogram_tester; |
| 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 + "&pf=cs"); |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| ASSERT_TRUE(ui_test_utils::NavigateToURL( |
| browser(), GetSearchServerQueryURL(search_terms))); |
| |
| // The prefetch should be served, and only 1 request should be issued. |
| EXPECT_EQ(1u, search_server_requests().size()); |
| auto inner_html = GetDocumentInnerHTML(); |
| EXPECT_FALSE(base::Contains(inner_html, "regular")); |
| EXPECT_TRUE(base::Contains(inner_html, "prefetch")); |
| |
| search_terms = "prefetch_content_2"; |
| prefetch_url = GetSearchServerQueryURL(search_terms + "&pf=cs"); |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kComplete); |
| ASSERT_TRUE(ui_test_utils::NavigateToURL( |
| browser(), GetSearchServerQueryURL(search_terms))); |
| |
| // The page should be restored from BF cache. |
| EXPECT_EQ(2u, search_server_requests().size()); |
| inner_html = GetDocumentInnerHTML(); |
| EXPECT_FALSE(base::Contains(inner_html, "regular")); |
| EXPECT_TRUE(base::Contains(inner_html, "prefetch")); |
| histogram_tester.ExpectTotalCount("BackForwardCache.HistoryNavigationOutcome", |
| 0); |
| |
| content::TestNavigationObserver back_load_observer(GetWebContents()); |
| GetWebContents()->GetController().GoBack(); |
| back_load_observer.Wait(); |
| |
| // The page should be restored from BF cache. |
| EXPECT_EQ(2u, search_server_requests().size()); |
| inner_html = GetDocumentInnerHTML(); |
| EXPECT_FALSE(base::Contains(inner_html, "regular")); |
| EXPECT_TRUE(base::Contains(inner_html, "prefetch")); |
| histogram_tester.ExpectUniqueSample( |
| "BackForwardCache.HistoryNavigationOutcome", 0 /* Restored */, 1); |
| |
| content::TestNavigationObserver forward_load_observer(GetWebContents()); |
| GetWebContents()->GetController().GoForward(); |
| forward_load_observer.Wait(); |
| |
| // The page should be restored from BF cache. |
| EXPECT_EQ(2u, search_server_requests().size()); |
| inner_html = GetDocumentInnerHTML(); |
| EXPECT_FALSE(base::Contains(inner_html, "regular")); |
| EXPECT_TRUE(base::Contains(inner_html, "prefetch")); |
| histogram_tester.ExpectUniqueSample( |
| "BackForwardCache.HistoryNavigationOutcome", 0 /* Restored */, 2); |
| } |
| |
| class SearchPrefetchServiceZeroCacheTimeBrowserTest |
| : public SearchPrefetchBaseBrowserTest { |
| public: |
| SearchPrefetchServiceZeroCacheTimeBrowserTest() { |
| feature_list_.InitWithFeaturesAndParameters( |
| {{kSearchPrefetchServicePrefetching, |
| {{"prefetch_caching_limit_ms", "10"}, |
| {"max_attempts_per_caching_duration", "3"}, |
| {"device_memory_threshold_MB", "0"}}}, |
| {{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) { |
| set_should_hang_requests(true); |
| base::HistogramTester histogram_tester; |
| 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()); |
| |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), absl::nullopt); |
| prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| base::ASCIIToUTF16(search_terms)); |
| |
| histogram_tester.ExpectUniqueSample( |
| "Omnibox.SearchPrefetch.PrefetchFinalStatus", |
| SearchPrefetchStatus::kInFlight, 1); |
| |
| // 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_TRUE(search_prefetch_service->MaybePrefetchURL( |
| GetSearchServerQueryURL("prefetch_3"))); |
| EXPECT_FALSE(search_prefetch_service->MaybePrefetchURL( |
| GetSearchServerQueryURL("prefetch_4"))); |
| |
| WaitUntilStatusChangesTo(u"prefetch_1", absl::nullopt); |
| |
| EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL( |
| GetSearchServerQueryURL("prefetch_4"))); |
| } |
| |
| class SearchPrefetchServiceZeroErrorTimeBrowserTest |
| : public SearchPrefetchBaseBrowserTest { |
| public: |
| SearchPrefetchServiceZeroErrorTimeBrowserTest() { |
| feature_list_.InitWithFeaturesAndParameters( |
| {{kSearchPrefetchServicePrefetching, |
| {{"error_backoff_duration_ms", "10"}, |
| {"device_memory_threshold_MB", "0"}}}, |
| {{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)); |
| WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), |
| SearchPrefetchStatus::kRequestFailed); |
| |
| 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::Milliseconds(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"}, |
| {"device_memory_threshold_MB", "0"}}}, |
| {{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::Seconds(10)); |
| autocomplete_controller->Start(input); |
| |
| ui_test_utils::WaitForAutocompleteDone(browser()); |
| EXPECT_TRUE(autocomplete_controller->done()); |
| |
| WaitForDuration(base::Milliseconds(100)); |
| |
| auto prefetch_status = |
| search_prefetch_service->GetSearchPrefetchStatusForTesting( |
| kOmniboxSuggestPrefetchSecondItemQuery16); |
| EXPECT_FALSE(prefetch_status.has_value()); |
| ASSERT_TRUE(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 SearchPrefetchServiceLowMemoryDeviceBrowserTest |
| : public SearchPrefetchBaseBrowserTest { |
| public: |
| SearchPrefetchServiceLowMemoryDeviceBrowserTest() { |
| feature_list_.InitWithFeaturesAndParameters( |
| {{kSearchPrefetchServicePrefetching, |
| {{"device_memory_threshold_MB", "2000000000"}}}, |
| {{kSearchPrefetchService}, {}}}, |
| {}); |
| } |
| |
| private: |
| base::test::ScopedFeatureList feature_list_; |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(SearchPrefetchServiceLowMemoryDeviceBrowserTest, |
| NoFetchWhenLowMemoryDevice) { |
| 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()); |
| } |
| |
| 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(std::u16string()); |
| 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(std::u16string()); |
| 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")); |
| } |