Convert remoting_unittests to run exclusively on Swarming
[chromium-blink-merge.git] / chrome / browser / net / predictor_browsertest.cc
blob345b4ecdc690c99ddb9aecf3286ba0911229b26a
1 // Copyright (c) 2012 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.
5 #include "base/base64.h"
6 #include "base/command_line.h"
7 #include "base/json/json_string_value_serializer.h"
8 #include "base/prefs/pref_service.h"
9 #include "chrome/browser/browser_process.h"
10 #include "chrome/browser/net/chrome_net_log.h"
11 #include "chrome/browser/net/predictor.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/ui/browser.h"
14 #include "chrome/common/pref_names.h"
15 #include "chrome/test/base/in_process_browser_test.h"
16 #include "chrome/test/base/ui_test_utils.h"
17 #include "content/public/common/content_switches.h"
18 #include "content/public/test/test_utils.h"
19 #include "net/base/host_port_pair.h"
20 #include "net/base/net_errors.h"
21 #include "net/dns/host_resolver_proc.h"
22 #include "net/dns/mock_host_resolver.h"
23 #include "net/log/net_log.h"
24 #include "testing/gmock/include/gmock/gmock.h"
26 using content::BrowserThread;
27 using testing::HasSubstr;
29 namespace {
31 const char kBlinkPreconnectFeature[] = "LinkPreconnect";
32 const char kChromiumHostname[] = "chromium.org";
33 const char kInvalidLongHostname[] = "illegally-long-hostname-over-255-"
34 "characters-should-not-send-an-ipc-message-to-the-browser-"
35 "0000000000000000000000000000000000000000000000000000000000000000000000000"
36 "0000000000000000000000000000000000000000000000000000000000000000000000000"
37 "000000000000000000000000000000000000000000000000000000.org";
39 // Records a history of all hostnames for which resolving has been requested,
40 // and immediately fails the resolution requests themselves.
41 class HostResolutionRequestRecorder : public net::HostResolverProc {
42 public:
43 HostResolutionRequestRecorder()
44 : HostResolverProc(NULL),
45 is_waiting_for_hostname_(false) {
48 int Resolve(const std::string& host,
49 net::AddressFamily address_family,
50 net::HostResolverFlags host_resolver_flags,
51 net::AddressList* addrlist,
52 int* os_error) override {
53 BrowserThread::PostTask(
54 BrowserThread::UI,
55 FROM_HERE,
56 base::Bind(&HostResolutionRequestRecorder::AddToHistory,
57 base::Unretained(this),
58 host));
59 return net::ERR_NAME_NOT_RESOLVED;
62 int RequestedHostnameCount() const {
63 return requested_hostnames_.size();
66 bool HasHostBeenRequested(const std::string& hostname) const {
67 DCHECK_CURRENTLY_ON(BrowserThread::UI);
68 return std::find(requested_hostnames_.begin(),
69 requested_hostnames_.end(),
70 hostname) != requested_hostnames_.end();
73 void WaitUntilHostHasBeenRequested(const std::string& hostname) {
74 DCHECK_CURRENTLY_ON(BrowserThread::UI);
75 DCHECK(!is_waiting_for_hostname_);
76 if (HasHostBeenRequested(hostname))
77 return;
78 waiting_for_hostname_ = hostname;
79 is_waiting_for_hostname_ = true;
80 content::RunMessageLoop();
83 private:
84 ~HostResolutionRequestRecorder() override {}
86 void AddToHistory(const std::string& hostname) {
87 DCHECK_CURRENTLY_ON(BrowserThread::UI);
88 requested_hostnames_.push_back(hostname);
89 if (is_waiting_for_hostname_ && waiting_for_hostname_ == hostname) {
90 is_waiting_for_hostname_ = false;
91 waiting_for_hostname_.clear();
92 base::MessageLoop::current()->Quit();
96 // The hostname which WaitUntilHostHasBeenRequested is currently waiting for
97 // to be requested.
98 std::string waiting_for_hostname_;
100 // Whether WaitUntilHostHasBeenRequested is waiting for a hostname to be
101 // requested and thus is running a nested message loop.
102 bool is_waiting_for_hostname_;
104 // A list of hostnames for which resolution has already been requested. Only
105 // to be accessed from the UI thread.
106 std::vector<std::string> requested_hostnames_;
108 DISALLOW_COPY_AND_ASSIGN(HostResolutionRequestRecorder);
111 // Watches the NetLog event stream for a connect event to the provided
112 // host:port pair.
113 class ConnectNetLogObserver : public net::NetLog::ThreadSafeObserver {
114 public:
115 explicit ConnectNetLogObserver(const std::string& host_port_pair)
116 : host_port_pair_(host_port_pair) {
119 ~ConnectNetLogObserver() override {
122 void Attach() {
123 g_browser_process->net_log()->DeprecatedAddObserver(
124 this, net::NetLogCaptureMode::IncludeCookiesAndCredentials());
127 void Detach() {
128 if (net_log())
129 net_log()->DeprecatedRemoveObserver(this);
132 void WaitForConnect() {
133 run_loop_.Run();
136 private:
137 void OnAddEntry(const net::NetLog::Entry& entry) override {
138 scoped_ptr<base::Value> param_value(entry.ParametersToValue());
139 base::DictionaryValue* param_dict = NULL;
140 std::string group_name;
142 if (entry.source().type == net::NetLog::SOURCE_CONNECT_JOB &&
143 param_value.get() != NULL &&
144 param_value->GetAsDictionary(&param_dict) &&
145 param_dict != NULL &&
146 param_dict->GetString("group_name", &group_name) &&
147 host_port_pair_ == group_name) {
148 run_loop_.Quit();
152 base::RunLoop run_loop_;
153 const std::string host_port_pair_;
156 } // namespace
158 namespace chrome_browser_net {
160 class PredictorBrowserTest : public InProcessBrowserTest {
161 public:
162 PredictorBrowserTest()
163 : startup_url_("http://host1:1"),
164 referring_url_("http://host2:1"),
165 target_url_("http://host3:1"),
166 host_resolution_request_recorder_(new HostResolutionRequestRecorder) {
169 protected:
170 void SetUpInProcessBrowserTestFixture() override {
171 scoped_host_resolver_proc_.reset(new net::ScopedDefaultHostResolverProc(
172 host_resolution_request_recorder_.get()));
173 InProcessBrowserTest::SetUpInProcessBrowserTestFixture();
176 void SetUpCommandLine(base::CommandLine* command_line) override {
177 command_line->AppendSwitch(
178 switches::kEnableExperimentalWebPlatformFeatures);
179 command_line->AppendSwitchASCII(
180 switches::kEnableBlinkFeatures, kBlinkPreconnectFeature);
183 void TearDownInProcessBrowserTestFixture() override {
184 InProcessBrowserTest::TearDownInProcessBrowserTestFixture();
185 scoped_host_resolver_proc_.reset();
188 void LearnAboutInitialNavigation(const GURL& url) {
189 Predictor* predictor = browser()->profile()->GetNetworkPredictor();
190 BrowserThread::PostTask(BrowserThread::IO,
191 FROM_HERE,
192 base::Bind(&Predictor::LearnAboutInitialNavigation,
193 base::Unretained(predictor),
194 url));
195 content::RunAllPendingInMessageLoop(BrowserThread::IO);
198 void LearnFromNavigation(const GURL& referring_url, const GURL& target_url) {
199 Predictor* predictor = browser()->profile()->GetNetworkPredictor();
200 BrowserThread::PostTask(BrowserThread::IO,
201 FROM_HERE,
202 base::Bind(&Predictor::LearnFromNavigation,
203 base::Unretained(predictor),
204 referring_url,
205 target_url));
206 content::RunAllPendingInMessageLoop(BrowserThread::IO);
209 void PrepareFrameSubresources(const GURL& url) {
210 Predictor* predictor = browser()->profile()->GetNetworkPredictor();
211 predictor->PredictFrameSubresources(url, GURL());
214 void GetListFromPrefsAsString(const char* list_path,
215 std::string* value_as_string) const {
216 PrefService* prefs = browser()->profile()->GetPrefs();
217 const base::ListValue* list_value = prefs->GetList(list_path);
218 JSONStringValueSerializer serializer(value_as_string);
219 serializer.Serialize(*list_value);
222 bool HasHostBeenRequested(const std::string& hostname) const {
223 return host_resolution_request_recorder_->HasHostBeenRequested(hostname);
226 void WaitUntilHostHasBeenRequested(const std::string& hostname) {
227 host_resolution_request_recorder_->WaitUntilHostHasBeenRequested(hostname);
230 int RequestedHostnameCount() const {
231 return host_resolution_request_recorder_->RequestedHostnameCount();
234 const GURL startup_url_;
235 const GURL referring_url_;
236 const GURL target_url_;
238 private:
239 scoped_refptr<HostResolutionRequestRecorder>
240 host_resolution_request_recorder_;
241 scoped_ptr<net::ScopedDefaultHostResolverProc> scoped_host_resolver_proc_;
244 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PRE_ShutdownStartupCycle) {
245 // Prepare state that will be serialized on this shut-down and read on next
246 // start-up.
247 LearnAboutInitialNavigation(startup_url_);
248 LearnFromNavigation(referring_url_, target_url_);
251 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, ShutdownStartupCycle) {
252 // Make sure that the Preferences file is actually wiped of all DNS prefetch
253 // related data after start-up.
254 std::string cleared_startup_list;
255 std::string cleared_referral_list;
256 GetListFromPrefsAsString(prefs::kDnsPrefetchingStartupList,
257 &cleared_startup_list);
258 GetListFromPrefsAsString(prefs::kDnsPrefetchingHostReferralList,
259 &cleared_referral_list);
261 EXPECT_THAT(cleared_startup_list, Not(HasSubstr(startup_url_.host())));
262 EXPECT_THAT(cleared_referral_list, Not(HasSubstr(referring_url_.host())));
263 EXPECT_THAT(cleared_referral_list, Not(HasSubstr(target_url_.host())));
265 // But also make sure this data has been first loaded into the Predictor, by
266 // inspecting that the Predictor starts making the expected hostname requests.
267 PrepareFrameSubresources(referring_url_);
268 WaitUntilHostHasBeenRequested(startup_url_.host());
269 WaitUntilHostHasBeenRequested(target_url_.host());
272 // Flaky on Windows: http://crbug.com/469120
273 #if defined(OS_WIN)
274 #define MAYBE_DnsPrefetch DISABLED_DnsPrefetch
275 #else
276 #define MAYBE_DnsPrefetch DnsPrefetch
277 #endif
278 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, MAYBE_DnsPrefetch) {
279 ASSERT_TRUE(test_server()->Start());
280 int hostnames_requested_before_load = RequestedHostnameCount();
281 ui_test_utils::NavigateToURL(
282 browser(),
283 GURL(test_server()->GetURL("files/predictor/dns_prefetch.html")));
284 WaitUntilHostHasBeenRequested(kChromiumHostname);
285 ASSERT_FALSE(HasHostBeenRequested(kInvalidLongHostname));
286 ASSERT_EQ(hostnames_requested_before_load + 1, RequestedHostnameCount());
289 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, Preconnect) {
290 ASSERT_TRUE(test_server()->Start());
292 // Create a HTML preconnect reference to the local server in the form
293 // <link rel="preconnect" href="http://test-server/">
294 // and navigate to it as a data URI.
295 GURL preconnect_url = test_server()->GetURL("");
296 std::string preconnect_content =
297 "<link rel=\"preconnect\" href=\"" + preconnect_url.spec() + "\">";
298 std::string encoded;
299 base::Base64Encode(preconnect_content, &encoded);
300 std::string data_uri = "data:text/html;base64," + encoded;
302 net::HostPortPair host_port_pair = net::HostPortPair::FromURL(preconnect_url);
303 ConnectNetLogObserver net_log_observer(host_port_pair.ToString());
304 net_log_observer.Attach();
306 ui_test_utils::NavigateToURL(browser(), GURL(data_uri));
308 net_log_observer.WaitForConnect();
309 net_log_observer.Detach();
312 } // namespace chrome_browser_net