summaryrefslogtreecommitdiff
path: root/chromium/weblayer/browser/prefetch_browsertest.cc
blob: 796d8905d7376c118fdd67342b9692b1ef001d3a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Copyright 2019 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/files/file_path.h"
#include "base/test/bind_test_util.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h"
#include "net/base/network_change_notifier.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "weblayer/browser/tab_impl.h"
#include "weblayer/shell/browser/shell.h"
#include "weblayer/test/weblayer_browser_test.h"
#include "weblayer/test/weblayer_browser_test_utils.h"

namespace weblayer {
namespace {
const char kPrefetchPage[] = "/simple_prefetch.html";
const char kRedirectPrefetchPage[] = "/redirect_prefetch.html";
const char kRedirectPrefetchUrl[] = "/redirect";
const char kRedirectedPrefetchUrl[] = "/redirected";
const char kPrefetchTarget[] = "/prefetch_target.lnk";
}  // namespace

class PrefetchBrowserTest : public WebLayerBrowserTest {
 public:
  void SetUpOnMainThread() override {
    // The test makes requests to google.com which we want to redirect to the
    // test server.
    host_resolver()->AddRule("*", "127.0.0.1");

    embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
        &PrefetchBrowserTest::MonitorRequest, base::Unretained(this)));
    ASSERT_TRUE(embedded_test_server()->Start());
  }

  void SetUpCommandLine(base::CommandLine* command_line) override {
    // Set a dummy variation ID to send X-Client-Data header to Google hosts
    // in RedirectedPrefetch test.
    command_line->AppendSwitchASCII("force-variation-ids", "42");
    // Need to ignore cert errors to use a HTTPS server for the test domains.
    command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
  }

  bool RunPrefetchExperiment(GURL url, const base::string16 expected_title) {
    content::TitleWatcher title_watcher(
        static_cast<TabImpl*>(shell()->tab())->web_contents(), expected_title);
    NavigateAndWaitForCompletion(url, shell());
    return expected_title == title_watcher.WaitAndGetTitle();
  }

 protected:
  bool prefetch_target_request_seen_ = false;

 private:
  void MonitorRequest(const net::test_server::HttpRequest& request) {
    if (request.relative_url == std::string(kPrefetchTarget)) {
      prefetch_target_request_seen_ = true;
    }
  }
};

IN_PROC_BROWSER_TEST_F(PrefetchBrowserTest, PrefetchWorks) {
  // Set real NetworkChangeNotifier singleton aside.
  std::unique_ptr<net::NetworkChangeNotifier::DisableForTest> disable_for_test(
      new net::NetworkChangeNotifier::DisableForTest);
  ASSERT_FALSE(prefetch_target_request_seen_);
  EXPECT_TRUE(
      RunPrefetchExperiment(embedded_test_server()->GetURL(kPrefetchPage),
                            base::ASCIIToUTF16("link onload")));
  EXPECT_TRUE(prefetch_target_request_seen_);
}

// https://crbug.com/922362: When the prefetched request is redirected, DCHECKs
// in PrefetchURLLoader::FollowRedirect() failed due to "X-Client-Data" in
// removed_headers. Verify that it no longer does.
IN_PROC_BROWSER_TEST_F(PrefetchBrowserTest, RedirectedPrefetch) {
  std::vector<net::test_server::HttpRequest> requests;
  net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
  https_server.RegisterRequestHandler(base::BindLambdaForTesting(
      [&requests](const net::test_server::HttpRequest& request)
          -> std::unique_ptr<net::test_server::HttpResponse> {
        auto response = std::make_unique<net::test_server::BasicHttpResponse>();
        if (request.relative_url == std::string(kRedirectPrefetchPage)) {
          requests.push_back(request);
          response->set_content_type("text/html");
          response->set_content(
              base::StringPrintf("<link rel=\"prefetch\" href=\"%s\" "
                                 "onload=\"document.title='done'\">",
                                 kRedirectPrefetchUrl));
          return response;
        } else if (request.relative_url == std::string(kRedirectPrefetchUrl)) {
          requests.push_back(request);
          response->set_code(net::HTTP_MOVED_PERMANENTLY);
          response->AddCustomHeader(
              "Location", base::StringPrintf("https://example.com:%s%s",
                                             request.GetURL().port().c_str(),
                                             kRedirectedPrefetchUrl));
          return response;
        } else if (request.relative_url ==
                   std::string(kRedirectedPrefetchUrl)) {
          requests.push_back(request);
          return response;
        }
        return nullptr;
      }));

  https_server.ServeFilesFromSourceDirectory(
      base::FilePath(FILE_PATH_LITERAL("weblayer/test/data")));
  ASSERT_TRUE(https_server.Start());

  GURL url = https_server.GetURL("www.google.com", kRedirectPrefetchPage);
  EXPECT_TRUE(RunPrefetchExperiment(url, base::ASCIIToUTF16("done")));
  ASSERT_EQ(3U, requests.size());

  EXPECT_EQ(base::StringPrintf("www.google.com:%u", https_server.port()),
            requests[0].headers["Host"]);
  EXPECT_EQ(kRedirectPrefetchPage, requests[0].relative_url);
}

}  // namespace weblayer