prefetch_browsertest.cc 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/files/file_path.h"
  5. #include "base/strings/stringprintf.h"
  6. #include "base/strings/utf_string_conversions.h"
  7. #include "base/synchronization/lock.h"
  8. #include "base/test/bind.h"
  9. #include "base/thread_annotations.h"
  10. #include "build/build_config.h"
  11. #include "components/network_session_configurator/common/network_switches.h"
  12. #include "content/public/browser/web_contents.h"
  13. #include "content/public/test/browser_test_utils.h"
  14. #include "net/base/network_change_notifier.h"
  15. #include "net/dns/mock_host_resolver.h"
  16. #include "net/test/embedded_test_server/embedded_test_server.h"
  17. #include "net/test/embedded_test_server/http_request.h"
  18. #include "net/test/embedded_test_server/http_response.h"
  19. #include "weblayer/browser/tab_impl.h"
  20. #include "weblayer/shell/browser/shell.h"
  21. #include "weblayer/test/weblayer_browser_test.h"
  22. #include "weblayer/test/weblayer_browser_test_utils.h"
  23. namespace weblayer {
  24. namespace {
  25. const char kPrefetchPage[] = "/simple_prefetch.html";
  26. const char kRedirectPrefetchPage[] = "/redirect_prefetch.html";
  27. const char kRedirectPrefetchUrl[] = "/redirect";
  28. const char kRedirectedPrefetchUrl[] = "/redirected";
  29. const char kPrefetchTarget[] = "/prefetch_target.lnk";
  30. } // namespace
  31. class PrefetchBrowserTest : public WebLayerBrowserTest {
  32. public:
  33. void SetUpOnMainThread() override {
  34. // The test makes requests to google.com which we want to redirect to the
  35. // test server.
  36. host_resolver()->AddRule("*", "127.0.0.1");
  37. embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
  38. &PrefetchBrowserTest::MonitorRequest, base::Unretained(this)));
  39. ASSERT_TRUE(embedded_test_server()->Start());
  40. }
  41. void SetUpCommandLine(base::CommandLine* command_line) override {
  42. // Set a dummy variation ID to send X-Client-Data header to Google hosts
  43. // in RedirectedPrefetch test.
  44. command_line->AppendSwitchASCII("force-variation-ids", "42");
  45. // Need to ignore cert errors to use a HTTPS server for the test domains.
  46. command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
  47. }
  48. bool RunPrefetchExperiment(GURL url, const std::u16string expected_title) {
  49. content::TitleWatcher title_watcher(
  50. static_cast<TabImpl*>(shell()->tab())->web_contents(), expected_title);
  51. NavigateAndWaitForCompletion(url, shell());
  52. return expected_title == title_watcher.WaitAndGetTitle();
  53. }
  54. protected:
  55. bool prefetch_target_request_seen_ = false;
  56. base::Lock lock_;
  57. // |requests_| is accessed on the UI thread by the test body and on the IO
  58. // thread by the test server's request handler, so must be guarded by a lock
  59. // to avoid data races.
  60. std::vector<net::test_server::HttpRequest> requests_ GUARDED_BY(lock_);
  61. private:
  62. void MonitorRequest(const net::test_server::HttpRequest& request) {
  63. if (request.relative_url == std::string(kPrefetchTarget)) {
  64. prefetch_target_request_seen_ = true;
  65. }
  66. }
  67. };
  68. IN_PROC_BROWSER_TEST_F(PrefetchBrowserTest, PrefetchWorks) {
  69. // Set real NetworkChangeNotifier singleton aside.
  70. std::unique_ptr<net::NetworkChangeNotifier::DisableForTest> disable_for_test(
  71. new net::NetworkChangeNotifier::DisableForTest);
  72. ASSERT_FALSE(prefetch_target_request_seen_);
  73. EXPECT_TRUE(RunPrefetchExperiment(
  74. embedded_test_server()->GetURL(kPrefetchPage), u"link onload"));
  75. EXPECT_TRUE(prefetch_target_request_seen_);
  76. }
  77. // https://crbug.com/922362: When the prefetched request is redirected, DCHECKs
  78. // in PrefetchURLLoader::FollowRedirect() failed due to "X-Client-Data" in
  79. // removed_headers. Verify that it no longer does.
  80. IN_PROC_BROWSER_TEST_F(PrefetchBrowserTest, RedirectedPrefetch) {
  81. net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
  82. https_server.RegisterRequestHandler(base::BindLambdaForTesting(
  83. [this](const net::test_server::HttpRequest& request)
  84. -> std::unique_ptr<net::test_server::HttpResponse> {
  85. auto response = std::make_unique<net::test_server::BasicHttpResponse>();
  86. base::AutoLock auto_lock(lock_);
  87. if (request.relative_url == std::string(kRedirectPrefetchPage)) {
  88. requests_.push_back(request);
  89. response->set_content_type("text/html");
  90. response->set_content(
  91. base::StringPrintf("<link rel=\"prefetch\" href=\"%s\" "
  92. "onload=\"document.title='done'\">",
  93. kRedirectPrefetchUrl));
  94. return response;
  95. } else if (request.relative_url == std::string(kRedirectPrefetchUrl)) {
  96. requests_.push_back(request);
  97. response->set_code(net::HTTP_MOVED_PERMANENTLY);
  98. response->AddCustomHeader(
  99. "Location", base::StringPrintf("https://example.com:%s%s",
  100. request.GetURL().port().c_str(),
  101. kRedirectedPrefetchUrl));
  102. return response;
  103. } else if (request.relative_url ==
  104. std::string(kRedirectedPrefetchUrl)) {
  105. requests_.push_back(request);
  106. return response;
  107. }
  108. return nullptr;
  109. }));
  110. https_server.ServeFilesFromSourceDirectory(
  111. base::FilePath(FILE_PATH_LITERAL("weblayer/test/data")));
  112. {
  113. base::AutoLock auto_lock(lock_);
  114. requests_.clear();
  115. }
  116. ASSERT_TRUE(https_server.Start());
  117. GURL url = https_server.GetURL("www.google.com", kRedirectPrefetchPage);
  118. EXPECT_TRUE(RunPrefetchExperiment(url, u"done"));
  119. {
  120. base::AutoLock auto_lock(lock_);
  121. ASSERT_EQ(3U, requests_.size());
  122. EXPECT_EQ(base::StringPrintf("www.google.com:%u", https_server.port()),
  123. requests_[0].headers["Host"]);
  124. EXPECT_EQ(kRedirectPrefetchPage, requests_[0].relative_url);
  125. }
  126. }
  127. } // namespace weblayer