| // Copyright 2022 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 <string> |
| |
| #include "chrome/browser/prerender/prerender_manager.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "chrome/browser/prerender/prerender_utils.h" |
| #include "chrome/common/chrome_features.h" |
| #include "chrome/test/base/chrome_render_view_host_test_harness.h" |
| #include "content/public/browser/render_frame_host.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/test/prerender_test_util.h" |
| #include "content/public/test/web_contents_tester.h" |
| #include "net/test/embedded_test_server/embedded_test_server.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace { |
| |
| class PrerenderManagerTest : public ChromeRenderViewHostTestHarness { |
| public: |
| PrerenderManagerTest(const PrerenderManagerTest&) = delete; |
| PrerenderManagerTest& operator=(const PrerenderManagerTest&) = delete; |
| PrerenderManagerTest() |
| : prerender_helper_( |
| base::BindRepeating(&PrerenderManagerTest::GetActiveWebContents, |
| base::Unretained(this))) { |
| scoped_feature_list_.InitAndEnableFeatureWithParameters( |
| features::kOmniboxTriggerForPrerender2, |
| {{"SupportSearchSuggestion", "true"}}); |
| } |
| |
| void SetUp() override { |
| prerender_helper_.SetUp(&test_server_); |
| ASSERT_TRUE(test_server_.Start()); |
| ChromeRenderViewHostTestHarness::SetUp(); |
| |
| PrerenderManager::CreateForWebContents(GetActiveWebContents()); |
| prerender_manager_ = PrerenderManager::FromWebContents(web_contents()); |
| ASSERT_TRUE(prerender_manager_); |
| prerender_manager_->set_skip_template_url_service_for_testing(); |
| } |
| |
| content::WebContents* GetActiveWebContents() { return web_contents(); } |
| |
| GURL GetSearchSuggestionUrl(const std::string& search_site, |
| const std::string& original_query, |
| const std::string& search_terms) { |
| return test_server_.GetURL(search_site + "?q=" + search_terms + |
| "&oq=" + original_query); |
| } |
| |
| content::WebContentsTester* web_contents_tester() { |
| return content::WebContentsTester::For(web_contents()); |
| } |
| |
| protected: |
| AutocompleteMatch CreateSearchSuggestionMatch( |
| const std::string& search_site, |
| const std::string& original_query, |
| const std::string& search_terms) { |
| AutocompleteMatch match; |
| match.search_terms_args = std::make_unique<TemplateURLRef::SearchTermsArgs>( |
| base::UTF8ToUTF16(search_terms)); |
| match.search_terms_args->original_query = base::UTF8ToUTF16(original_query); |
| match.destination_url = |
| GetSearchSuggestionUrl(search_site, original_query, search_terms); |
| match.keyword = base::UTF8ToUTF16(original_query); |
| match.RecordAdditionalInfo("should_prerender", "true"); |
| return match; |
| } |
| |
| GURL GetUrl(const std::string& path) { return test_server_.GetURL(path); } |
| |
| PrerenderManager* prerender_manager() { return prerender_manager_; } |
| |
| content::test::PrerenderTestHelper& prerender_helper() { |
| return prerender_helper_; |
| } |
| |
| private: |
| content::test::PrerenderTestHelper prerender_helper_; |
| base::test::ScopedFeatureList scoped_feature_list_; |
| net::EmbeddedTestServer test_server_; |
| raw_ptr<PrerenderManager> prerender_manager_; |
| }; |
| |
| TEST_F(PrerenderManagerTest, StartCleanSearchSuggestionPrerender) { |
| GURL prerendering_url = |
| GetSearchSuggestionUrl("/title1.html", "pre", "prerender"); |
| content::test::PrerenderHostRegistryObserver registry_observer( |
| *GetActiveWebContents()); |
| AutocompleteMatch match = |
| CreateSearchSuggestionMatch("/title1.html", "pre", "prerender"); |
| prerender_manager()->StartPrerenderSearchSuggestion(match); |
| registry_observer.WaitForTrigger(prerendering_url); |
| int prerender_host_id = prerender_helper().GetHostForUrl(prerendering_url); |
| EXPECT_NE(prerender_host_id, content::RenderFrameHost::kNoFrameTreeNodeId); |
| } |
| |
| // Tests that the old prerender will be destroyed when starting prerendering a |
| // different search result. |
| TEST_F(PrerenderManagerTest, StartNewSuggestionPrerender) { |
| GURL prerendering_url = |
| GetSearchSuggestionUrl("/title1.html", "pre", "prefetch"); |
| content::test::PrerenderHostRegistryObserver registry_observer( |
| *GetActiveWebContents()); |
| AutocompleteMatch match = |
| CreateSearchSuggestionMatch("/title1.html", "pre", "prefetch"); |
| prerender_manager()->StartPrerenderSearchSuggestion(match); |
| |
| registry_observer.WaitForTrigger(prerendering_url); |
| int prerender_host_id = prerender_helper().GetHostForUrl(prerendering_url); |
| ASSERT_NE(prerender_host_id, content::RenderFrameHost::kNoFrameTreeNodeId); |
| content::test::PrerenderHostObserver host_observer(*GetActiveWebContents(), |
| prerender_host_id); |
| GURL prerendering_url2 = |
| GetSearchSuggestionUrl("/title1.html", "prer", "prerender"); |
| match = CreateSearchSuggestionMatch("/title1.html", "prer", "prerender"); |
| prerender_manager()->StartPrerenderSearchSuggestion(match); |
| host_observer.WaitForDestroyed(); |
| registry_observer.WaitForTrigger(prerendering_url2); |
| EXPECT_TRUE(prerender_manager()->HasSearchResultPagePrerendered()); |
| EXPECT_EQ(std::u16string(u"prerender"), |
| prerender_manager()->GetPrerenderSearchTermForTesting()); |
| } |
| |
| // Tests that the old prerender is not destroyed when starting prerendering the |
| // same search suggestion. |
| TEST_F(PrerenderManagerTest, StartSameSuggestionPrerender) { |
| GURL prerendering_url = |
| GetSearchSuggestionUrl("/title1.html", "pre", "prerender"); |
| content::test::PrerenderHostRegistryObserver registry_observer( |
| *GetActiveWebContents()); |
| AutocompleteMatch match = |
| CreateSearchSuggestionMatch("/title1.html", "pre", "prerender"); |
| prerender_manager()->StartPrerenderSearchSuggestion(match); |
| registry_observer.WaitForTrigger(prerendering_url); |
| int prerender_host_id = prerender_helper().GetHostForUrl(prerendering_url); |
| EXPECT_NE(prerender_host_id, content::RenderFrameHost::kNoFrameTreeNodeId); |
| match = CreateSearchSuggestionMatch("/title1.html", "prer", "prerender"); |
| prerender_manager()->StartPrerenderSearchSuggestion(match); |
| EXPECT_TRUE(prerender_manager()->HasSearchResultPagePrerendered()); |
| |
| // The created prerender for `prerendering_url` still exists, so the |
| // prerender_host_id should be the same. |
| int prerender_host_id2 = prerender_helper().GetHostForUrl(prerendering_url); |
| EXPECT_EQ(prerender_host_id2, prerender_host_id); |
| } |
| |
| // Tests that the PrerenderHandle is destroyed when the primary page changed. |
| TEST_F(PrerenderManagerTest, DestroyedOnNavigateAway) { |
| GURL prerendering_url = |
| GetSearchSuggestionUrl("/title1.html", "pre", "prerende"); |
| content::test::PrerenderHostRegistryObserver registry_observer( |
| *GetActiveWebContents()); |
| AutocompleteMatch match = |
| CreateSearchSuggestionMatch("/title1.html", "pre", "prerende"); |
| prerender_manager()->StartPrerenderSearchSuggestion(match); |
| |
| registry_observer.WaitForTrigger(prerendering_url); |
| int prerender_host_id = prerender_helper().GetHostForUrl(prerendering_url); |
| EXPECT_NE(prerender_host_id, content::RenderFrameHost::kNoFrameTreeNodeId); |
| content::test::PrerenderHostObserver host_observer(*GetActiveWebContents(), |
| prerender_host_id); |
| web_contents_tester()->NavigateAndCommit(GetUrl("/empty.html")); |
| host_observer.WaitForDestroyed(); |
| EXPECT_FALSE(prerender_manager()->HasSearchResultPagePrerendered()); |
| } |
| |
| } // namespace |