blob: df3bcafc68a7d33fba7d5e5399612d8a115e1e09 [file] [log] [blame]
// 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/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "build/build_config.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.
// TODO(https://crbug.com/1144142): Fails on TSan due to data race.
#if defined(THREAD_SANITIZER)
#define MAYBE_RedirectedPrefetch DISABLED_RedirectedPrefetch
#else
#define MAYBE_RedirectedPrefetch RedirectedPrefetch
#endif
IN_PROC_BROWSER_TEST_F(PrefetchBrowserTest, MAYBE_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