Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(186)

Side by Side Diff: chrome/browser/net/predictor_browsertest.cc

Issue 1881463003: Add a browsertest suite for net predictor (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add a "forgetting" test + fix typo Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stddef.h> 5 #include <stddef.h>
6 #include <stdint.h> 6 #include <stdint.h>
7 7
8 #include "base/base64.h" 8 #include "base/base64.h"
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/json/json_string_value_serializer.h" 10 #include "base/json/json_string_value_serializer.h"
11 #include "base/macros.h" 11 #include "base/macros.h"
12 #include "base/synchronization/lock.h" 12 #include "base/synchronization/lock.h"
13 #include "base/thread_task_runner_handle.h" 13 #include "base/thread_task_runner_handle.h"
14 #include "build/build_config.h" 14 #include "build/build_config.h"
15 #include "chrome/browser/browser_process.h" 15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/net/predictor.h" 16 #include "chrome/browser/net/predictor.h"
17 #include "chrome/browser/profiles/profile.h" 17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ui/browser.h" 18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/tabs/tab_strip_model.h"
19 #include "chrome/common/pref_names.h" 20 #include "chrome/common/pref_names.h"
20 #include "chrome/test/base/in_process_browser_test.h" 21 #include "chrome/test/base/in_process_browser_test.h"
21 #include "chrome/test/base/ui_test_utils.h" 22 #include "chrome/test/base/ui_test_utils.h"
22 #include "components/prefs/pref_service.h" 23 #include "components/prefs/pref_service.h"
23 #include "content/public/common/content_switches.h" 24 #include "content/public/common/content_switches.h"
25 #include "content/public/test/browser_test_utils.h"
24 #include "content/public/test/test_utils.h" 26 #include "content/public/test/test_utils.h"
25 #include "net/base/host_port_pair.h" 27 #include "net/base/host_port_pair.h"
26 #include "net/base/ip_endpoint.h" 28 #include "net/base/ip_endpoint.h"
27 #include "net/base/net_errors.h" 29 #include "net/base/net_errors.h"
28 #include "net/dns/host_resolver_proc.h" 30 #include "net/dns/host_resolver_proc.h"
29 #include "net/dns/mock_host_resolver.h" 31 #include "net/dns/mock_host_resolver.h"
30 #include "net/socket/stream_socket.h" 32 #include "net/socket/stream_socket.h"
31 #include "net/test/embedded_test_server/embedded_test_server.h" 33 #include "net/test/embedded_test_server/embedded_test_server.h"
32 #include "net/test/embedded_test_server/embedded_test_server_connection_listener .h" 34 #include "net/test/embedded_test_server/embedded_test_server_connection_listener .h"
35 #include "net/test/embedded_test_server/http_request.h"
36 #include "net/test/embedded_test_server/http_response.h"
37 #include "net/url_request/url_request_filter.h"
38 #include "net/url_request/url_request_interceptor.h"
39 #include "net/url_request/url_request_test_job.h"
33 #include "testing/gmock/include/gmock/gmock.h" 40 #include "testing/gmock/include/gmock/gmock.h"
34 41
35 using content::BrowserThread; 42 using content::BrowserThread;
36 using testing::HasSubstr; 43 using testing::HasSubstr;
37 44
38 namespace { 45 namespace {
39 46
40 const char kBlinkPreconnectFeature[] = "LinkPreconnect"; 47 const char kBlinkPreconnectFeature[] = "LinkPreconnect";
41 const char kChromiumHostname[] = "chromium.org"; 48 const char kChromiumHostname[] = "chromium.org";
42 const char kInvalidLongHostname[] = "illegally-long-hostname-over-255-" 49 const char kInvalidLongHostname[] = "illegally-long-hostname-over-255-"
(...skipping 21 matching lines...) Expand all
64 base::AutoLock lock(lock_); 71 base::AutoLock lock(lock_);
65 uint16_t socket = GetPort(connection); 72 uint16_t socket = GetPort(connection);
66 EXPECT_TRUE(sockets_.find(socket) == sockets_.end()); 73 EXPECT_TRUE(sockets_.find(socket) == sockets_.end());
67 74
68 sockets_[socket] = SOCKET_ACCEPTED; 75 sockets_[socket] = SOCKET_ACCEPTED;
69 task_runner_->PostTask(FROM_HERE, accept_loop_.QuitClosure()); 76 task_runner_->PostTask(FROM_HERE, accept_loop_.QuitClosure());
70 } 77 }
71 78
72 // Get called from the EmbeddedTestServer thread to be notified that 79 // Get called from the EmbeddedTestServer thread to be notified that
73 // a connection was read from. 80 // a connection was read from.
74 void ReadFromSocket(const net::StreamSocket& connection) override { 81 void ReadFromSocket(const net::StreamSocket& connection, int rv) override {
75 base::AutoLock lock(lock_); 82 base::AutoLock lock(lock_);
mmenke 2016/04/15 15:44:03 This can be below the rv <= 0 check
Charlie Harrison 2016/04/20 12:36:42 Done.
83 // Don't log a read if no data was transferred. This case often happens if
84 // the sockets of the test server are being flushed and disconnected.
85 if (rv <= 0)
86 return;
76 uint16_t socket = GetPort(connection); 87 uint16_t socket = GetPort(connection);
77 EXPECT_FALSE(sockets_.find(socket) == sockets_.end()); 88 EXPECT_FALSE(sockets_.find(socket) == sockets_.end());
78 89
79 sockets_[socket] = SOCKET_READ_FROM; 90 sockets_[socket] = SOCKET_READ_FROM;
80 task_runner_->PostTask(FROM_HERE, read_loop_.QuitClosure()); 91 task_runner_->PostTask(FROM_HERE, read_loop_.QuitClosure());
81 } 92 }
82 93
83 // Returns the number of sockets that were accepted by the server. 94 // Returns the number of sockets that were accepted by the server.
84 size_t GetAcceptedSocketCount() const { 95 size_t GetAcceptedSocketCount() const {
85 base::AutoLock lock(lock_); 96 base::AutoLock lock(lock_);
86 return sockets_.size(); 97 return sockets_.size();
87 } 98 }
88 99
89 // Returns the number of sockets that were read from by the server. 100 // Returns the number of sockets that were read from by the server.
90 size_t GetReadSocketCount() const { 101 size_t GetReadSocketCount() const {
91 base::AutoLock lock(lock_);
92 size_t read_sockets = 0; 102 size_t read_sockets = 0;
mmenke 2016/04/15 15:44:02 Why did you remove the lock? If this coincides wi
Charlie Harrison 2016/04/20 12:36:43 This was a careless mistake probably from rearrang
93 for (const auto& socket : sockets_) { 103 for (const auto& socket : sockets_) {
94 if (socket.second == SOCKET_READ_FROM) 104 if (socket.second == SOCKET_READ_FROM)
95 ++read_sockets; 105 ++read_sockets;
96 } 106 }
97 return read_sockets; 107 return read_sockets;
98 } 108 }
99 109
100 void WaitUntilFirstConnectionAccepted() { accept_loop_.Run(); } 110 void WaitUntilFirstConnectionAccepted() { accept_loop_.Run(); }
101 111
102 void WaitUntilFirstConnectionRead() { read_loop_.Run(); } 112 void WaitUntilFirstConnectionRead() { read_loop_.Run(); }
103 113
114 void ClearSockets() {
115 base::AutoLock lock(lock_);
116 sockets_.clear();
117 }
118
104 private: 119 private:
105 static uint16_t GetPort(const net::StreamSocket& connection) { 120 static uint16_t GetPort(const net::StreamSocket& connection) {
106 // Get the remote port of the peer, since the local port will always be the 121 // Get the remote port of the peer, since the local port will always be the
107 // port the test server is listening on. This isn't strictly correct - it's 122 // port the test server is listening on. This isn't strictly correct - it's
108 // possible for multiple peers to connect with the same remote port but 123 // possible for multiple peers to connect with the same remote port but
109 // different remote IPs - but the tests here assume that connections to the 124 // different remote IPs - but the tests here assume that connections to the
110 // test server (running on localhost) will always come from localhost, and 125 // test server (running on localhost) will always come from localhost, and
111 // thus the peer port is all thats needed to distinguish two connections. 126 // thus the peer port is all thats needed to distinguish two connections.
112 // This also would be problematic if the OS reused ports, but that's not 127 // This also would be problematic if the OS reused ports, but that's not
113 // something to worry about for these tests. 128 // something to worry about for these tests.
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 // requested and thus is running a nested message loop. 210 // requested and thus is running a nested message loop.
196 bool is_waiting_for_hostname_; 211 bool is_waiting_for_hostname_;
197 212
198 // A list of hostnames for which resolution has already been requested. Only 213 // A list of hostnames for which resolution has already been requested. Only
199 // to be accessed from the UI thread. 214 // to be accessed from the UI thread.
200 std::vector<std::string> requested_hostnames_; 215 std::vector<std::string> requested_hostnames_;
201 216
202 DISALLOW_COPY_AND_ASSIGN(HostResolutionRequestRecorder); 217 DISALLOW_COPY_AND_ASSIGN(HostResolutionRequestRecorder);
203 }; 218 };
204 219
220 // This class intercepts URLRequests and responds with 404s.
221 class NotFoundRequestInterceptor : public net::URLRequestInterceptor {
mmenke 2016/04/15 15:44:03 Give this a public constructor and destructor, and
Charlie Harrison 2016/04/20 12:36:43 Done.
222 net::URLRequestJob* MaybeInterceptRequest(
223 net::URLRequest* request,
224 net::NetworkDelegate* network_delegate) const override {
225 const char kHeaders[] =
226 "HTTP/1.1 404 Not Found\n"
227 "\n";
228 std::string headers(kHeaders, arraysize(kHeaders));
229
230 return new net::URLRequestTestJob(request, network_delegate, headers, "",
231 true);
mmenke 2016/04/15 15:44:02 URLRequestTestJobs are weird. Can we just use URL
Charlie Harrison 2016/04/20 12:36:43 Sure. I'm not sure what the best error is, but ABO
232 }
233 };
234
205 } // namespace 235 } // namespace
206 236
207 namespace chrome_browser_net { 237 namespace chrome_browser_net {
208 238
209 class PredictorBrowserTest : public InProcessBrowserTest { 239 class PredictorBrowserTest : public InProcessBrowserTest,
240 public PredictorObserver {
210 public: 241 public:
211 PredictorBrowserTest() 242 PredictorBrowserTest()
212 : startup_url_("http://host1:1"), 243 : startup_url_("http://host1:1"),
213 referring_url_("http://host2:1"), 244 referring_url_("http://host2:1"),
214 target_url_("http://host3:1"), 245 target_url_("http://host3:1"),
215 host_resolution_request_recorder_(new HostResolutionRequestRecorder) { 246 source_target_learned_(0),
247 preconnected_target_(0),
248 preconnected_source_(0),
249 host_resolution_request_recorder_(new HostResolutionRequestRecorder),
250 target_test_server_(new net::EmbeddedTestServer()) {}
251
252 protected:
253 // PredictorObserver:
254 void OnPreconnectUrl(const GURL& original_url,
mmenke 2016/04/15 15:44:02 I don't think these should be part of the test fix
Charlie Harrison 2016/04/20 12:36:42 Fair enough, done.
255 const GURL& first_party_for_cookies,
256 UrlInfo::ResolutionMotivation motivation,
257 int count) override {
mmenke 2016/04/15 15:44:02 These are called on the IO thread, but you're acce
Charlie Harrison 2016/04/20 12:36:42 I added locks.
258 if (original_url == target_test_server()->base_url())
259 preconnected_target_ = std::max(preconnected_target_, count);
260 else if (original_url == embedded_test_server()->base_url())
261 preconnected_source_ = std::max(preconnected_source_, count);
mmenke 2016/04/15 15:44:02 nit: Use braces in if/else (Style varies in Chrom
mmenke 2016/04/15 15:44:03 If we're preconnecting some other URL, should we f
mmenke 2016/04/15 15:44:03 If it's neither of those URLs, should we fail?
Charlie Harrison 2016/04/20 12:36:42 Done.
Charlie Harrison 2016/04/20 12:36:42 Yeah. Done.
Charlie Harrison 2016/04/20 12:36:43 Yupp, done.
216 } 262 }
217 263
218 protected: 264 void OnLearnFromNavigation(const GURL& referring_url,
265 const GURL& target_url) override {
266 if (referring_url == embedded_test_server()->base_url() &&
267 target_url == target_test_server()->base_url()) {
268 source_target_learned_++;
269 }
mmenke 2016/04/15 15:44:02 What if they aren't equal? Should we do something
Charlie Harrison 2016/04/20 12:36:42 I've added failure conditions.
270 }
271
219 void SetUpInProcessBrowserTestFixture() override { 272 void SetUpInProcessBrowserTestFixture() override {
220 scoped_host_resolver_proc_.reset(new net::ScopedDefaultHostResolverProc( 273 scoped_host_resolver_proc_.reset(new net::ScopedDefaultHostResolverProc(
221 host_resolution_request_recorder_.get())); 274 host_resolution_request_recorder_.get()));
222 InProcessBrowserTest::SetUpInProcessBrowserTestFixture(); 275 InProcessBrowserTest::SetUpInProcessBrowserTestFixture();
223 } 276 }
224 277
225 void SetUpCommandLine(base::CommandLine* command_line) override { 278 void SetUpCommandLine(base::CommandLine* command_line) override {
226 command_line->AppendSwitch( 279 command_line->AppendSwitch(
227 switches::kEnableExperimentalWebPlatformFeatures); 280 switches::kEnableExperimentalWebPlatformFeatures);
228 command_line->AppendSwitchASCII( 281 command_line->AppendSwitchASCII(
229 switches::kEnableBlinkFeatures, kBlinkPreconnectFeature); 282 switches::kEnableBlinkFeatures, kBlinkPreconnectFeature);
230 } 283 }
231 284
285 std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
286 const net::test_server::HttpRequest& request) {
287 if (request.GetURL().path() != "/")
288 return nullptr;
289 std::unique_ptr<net::test_server::BasicHttpResponse> response(
290 new net::test_server::BasicHttpResponse);
291 response->set_code(net::HTTP_MOVED_PERMANENTLY);
292 response->AddCustomHeader(
293 "Location", target_test_server()->GetURL("/title1.html").spec());
294 return std::move(response);
295 }
296
232 void SetUpOnMainThread() override { 297 void SetUpOnMainThread() override {
298 embedded_test_server()->RegisterRequestHandler(base::Bind(
299 &PredictorBrowserTest::HandleRequest, base::Unretained(this)));
300 predictor()->SetObserver(this);
mmenke 2016/04/15 15:44:03 Calling this on the UI thread after the IOThread h
Charlie Harrison 2016/04/20 12:36:42 Done. The tests now call "InstallPredictorObserver
301 predictor()->set_preconnect_enabled(true);
302 target_test_server_->ServeFilesFromSourceDirectory("chrome/test/data/");
303
233 connection_listener_.reset(new ConnectionListener()); 304 connection_listener_.reset(new ConnectionListener());
305 target_connection_listener_.reset(new ConnectionListener());
234 embedded_test_server()->SetConnectionListener(connection_listener_.get()); 306 embedded_test_server()->SetConnectionListener(connection_listener_.get());
307 target_test_server_->SetConnectionListener(
308 target_connection_listener_.get());
235 ASSERT_TRUE(embedded_test_server()->Start()); 309 ASSERT_TRUE(embedded_test_server()->Start());
310 ASSERT_TRUE(target_test_server_->Start());
311
312 // Ignore all favicon requests. These are tricky to deal with because they
313 // are scheduled on the UI thread and are not accounted for in the load
314 // event. The interceptor will respond with 404s, and we won't connect any
315 // sockets to the test server.
mmenke 2016/04/15 15:44:03 nit avoid "we" in comments.
Charlie Harrison 2016/04/20 12:36:43 Done. Removed all "we"s in comments in this file.
316 BrowserThread::PostTask(
317 BrowserThread::IO, FROM_HERE,
318 base::Bind(&PredictorBrowserTest::AddUrlInterceptor,
319 target_test_server()->GetURL("/favicon.ico")));
mmenke 2016/04/13 17:50:23 Do we still learn from these requests? Just wonde
Charlie Harrison 2016/04/13 18:16:00 I think we do still learn from these. They are a h
236 } 320 }
237 321
238 void TearDownOnMainThread() override { 322 void TearDownOnMainThread() override {
239 ASSERT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete()); 323 ASSERT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
240 } 324 }
241 325
242 // Navigates to a data URL containing the given content, with a MIME type of 326 // Navigates to a data URL containing the given content, with a MIME type of
243 // text/html. 327 // text/html.
244 void NavigateToDataURLWithContent(const std::string& content) { 328 void NavigateToDataURLWithContent(const std::string& content) {
245 std::string encoded_content; 329 std::string encoded_content;
246 base::Base64Encode(content, &encoded_content); 330 base::Base64Encode(content, &encoded_content);
247 std::string data_uri_content = "data:text/html;base64," + encoded_content; 331 std::string data_uri_content = "data:text/html;base64," + encoded_content;
248 ui_test_utils::NavigateToURL(browser(), GURL(data_uri_content)); 332 ui_test_utils::NavigateToURL(browser(), GURL(data_uri_content));
249 } 333 }
250 334
251 void TearDownInProcessBrowserTestFixture() override { 335 void TearDownInProcessBrowserTestFixture() override {
252 InProcessBrowserTest::TearDownInProcessBrowserTestFixture(); 336 InProcessBrowserTest::TearDownInProcessBrowserTestFixture();
253 scoped_host_resolver_proc_.reset(); 337 scoped_host_resolver_proc_.reset();
254 } 338 }
255 339
256 void LearnAboutInitialNavigation(const GURL& url) { 340 void LearnAboutInitialNavigation(const GURL& url) {
257 Predictor* predictor = browser()->profile()->GetNetworkPredictor(); 341 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
258 BrowserThread::PostTask(BrowserThread::IO,
259 FROM_HERE,
260 base::Bind(&Predictor::LearnAboutInitialNavigation, 342 base::Bind(&Predictor::LearnAboutInitialNavigation,
261 base::Unretained(predictor), 343 base::Unretained(predictor()), url));
262 url));
263 content::RunAllPendingInMessageLoop(BrowserThread::IO); 344 content::RunAllPendingInMessageLoop(BrowserThread::IO);
264 } 345 }
265 346
266 void LearnFromNavigation(const GURL& referring_url, const GURL& target_url) { 347 void LearnFromNavigation(const GURL& referring_url, const GURL& target_url) {
267 Predictor* predictor = browser()->profile()->GetNetworkPredictor(); 348 BrowserThread::PostTask(
268 BrowserThread::PostTask(BrowserThread::IO, 349 BrowserThread::IO, FROM_HERE,
269 FROM_HERE, 350 base::Bind(&Predictor::LearnFromNavigation,
270 base::Bind(&Predictor::LearnFromNavigation, 351 base::Unretained(predictor()), referring_url, target_url));
271 base::Unretained(predictor),
272 referring_url,
273 target_url));
274 content::RunAllPendingInMessageLoop(BrowserThread::IO); 352 content::RunAllPendingInMessageLoop(BrowserThread::IO);
275 } 353 }
276 354
277 void PrepareFrameSubresources(const GURL& url) { 355 void PrepareFrameSubresources(const GURL& url) {
278 Predictor* predictor = browser()->profile()->GetNetworkPredictor(); 356 predictor()->PredictFrameSubresources(url, GURL());
279 predictor->PredictFrameSubresources(url, GURL());
280 } 357 }
281 358
282 void GetListFromPrefsAsString(const char* list_path, 359 void GetListFromPrefsAsString(const char* list_path,
283 std::string* value_as_string) const { 360 std::string* value_as_string) const {
284 PrefService* prefs = browser()->profile()->GetPrefs(); 361 PrefService* prefs = browser()->profile()->GetPrefs();
285 const base::ListValue* list_value = prefs->GetList(list_path); 362 const base::ListValue* list_value = prefs->GetList(list_path);
286 JSONStringValueSerializer serializer(value_as_string); 363 JSONStringValueSerializer serializer(value_as_string);
287 serializer.Serialize(*list_value); 364 serializer.Serialize(*list_value);
288 } 365 }
289 366
290 bool HasHostBeenRequested(const std::string& hostname) const { 367 bool HasHostBeenRequested(const std::string& hostname) const {
291 return host_resolution_request_recorder_->HasHostBeenRequested(hostname); 368 return host_resolution_request_recorder_->HasHostBeenRequested(hostname);
292 } 369 }
293 370
294 void WaitUntilHostHasBeenRequested(const std::string& hostname) { 371 void WaitUntilHostHasBeenRequested(const std::string& hostname) {
295 host_resolution_request_recorder_->WaitUntilHostHasBeenRequested(hostname); 372 host_resolution_request_recorder_->WaitUntilHostHasBeenRequested(hostname);
296 } 373 }
297 374
298 int RequestedHostnameCount() const { 375 int RequestedHostnameCount() const {
299 return host_resolution_request_recorder_->RequestedHostnameCount(); 376 return host_resolution_request_recorder_->RequestedHostnameCount();
300 } 377 }
301 378
379 net::EmbeddedTestServer* target_test_server() {
380 return target_test_server_.get();
381 }
382
383 Predictor* predictor() { return browser()->profile()->GetNetworkPredictor(); }
384
385 // Navigate to an html file and request async fetches. Wait until the fetches
386 // complete before continuing.
387 void NavigateToCrossSiteHTMLURL(int num_cors,
388 int num_non_cors,
mmenke 2016/04/15 15:44:02 Think we should rename cors/non_cors to match the
mmenke 2016/04/15 20:27:17 Oh...The fact that non_cors does not mean same sit
Charlie Harrison 2016/04/20 12:36:43 Ok, I will update with a comment.
Charlie Harrison 2016/04/20 12:36:43 So actually the non cors perform a fetch() to the
389 const char* file_suffix) {
390 const GURL& base_url = target_test_server()->base_url();
391 std::string url = base::StringPrintf(
mmenke 2016/04/15 15:44:03 Not a url - this is a path. As-is, the GetURL(url
Charlie Harrison 2016/04/20 12:36:42 Done.
392 "/predictor/"
393 "predictor_cross_site%s.html?subresourceHost=%s&"
394 "numCORSResources=%d&numNonCORSResources=%d",
395 file_suffix, base_url.spec().c_str(), num_cors, num_non_cors);
396 ui_test_utils::NavigateToURL(browser(),
397 embedded_test_server()->GetURL(url));
398 bool result = false;
399 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
400 browser()->tab_strip_model()->GetActiveWebContents(), "sendFetches()",
401 &result));
402 EXPECT_TRUE(result);
403 }
404
405 // Simulate the target server restarting. Delete all sockets and reset members
406 // tracking preconnects.
407 void ResetTarget() {
408 preconnected_target_ = 0;
409 target_test_server()->FlushAllSocketsAndConnectionsOnUIThread();
410 target_connection_listener_->ClearSockets();
411 EXPECT_EQ(0u, target_connection_listener_->GetAcceptedSocketCount());
412 }
413
414 static void AddUrlInterceptor(const GURL url) {
415 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
416 url, make_scoped_ptr(new NotFoundRequestInterceptor()));
417 }
418
302 const GURL startup_url_; 419 const GURL startup_url_;
303 const GURL referring_url_; 420 const GURL referring_url_;
304 const GURL target_url_; 421 const GURL target_url_;
305 scoped_ptr<ConnectionListener> connection_listener_; 422 std::unique_ptr<ConnectionListener> connection_listener_;
423 std::unique_ptr<ConnectionListener> target_connection_listener_;
424
425 int source_target_learned_;
426 int preconnected_target_;
427 int preconnected_source_;
306 428
307 private: 429 private:
308 scoped_refptr<HostResolutionRequestRecorder> 430 scoped_refptr<HostResolutionRequestRecorder>
309 host_resolution_request_recorder_; 431 host_resolution_request_recorder_;
310 scoped_ptr<net::ScopedDefaultHostResolverProc> scoped_host_resolver_proc_; 432 std::unique_ptr<net::ScopedDefaultHostResolverProc>
433 scoped_host_resolver_proc_;
434 std::unique_ptr<net::EmbeddedTestServer> target_test_server_;
mmenke 2016/04/15 15:44:02 Think this needs a comment. I suggest calling it
Charlie Harrison 2016/04/20 12:36:42 Done. Renamed to "cross_site_test_server".
311 }; 435 };
312 436
437 // Test the html test harness used to initiate cross site fetches. These
438 // initiate cross site subresource requests (CORS and non-CORS) to the target
439 // test server. Inspect the predictor's internal state to make sure that they
440 // are properly logged.
441 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, CrossSiteNonCORSUseOneSocket) {
442 NavigateToCrossSiteHTMLURL(0, 1, "");
mmenke 2016/04/15 15:44:03 Suggest you should add comments with the variable
Charlie Harrison 2016/04/20 12:36:42 Done.
443 EXPECT_EQ(1u, target_connection_listener_->GetAcceptedSocketCount());
444 EXPECT_EQ(1, source_target_learned_);
445 EXPECT_EQ(2, preconnected_source_);
446 }
447
448 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, CrossSiteNonCORSUseThreeSockets) {
449 NavigateToCrossSiteHTMLURL(0, 3, "");
450 EXPECT_EQ(3u, target_connection_listener_->GetAcceptedSocketCount());
451 EXPECT_EQ(3, source_target_learned_);
452 EXPECT_EQ(2, preconnected_source_);
453 }
454
455 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest,
456 CrossSiteCORSAndNonCORSUseOneSocket) {
457 NavigateToCrossSiteHTMLURL(1, 1, "");
mmenke 2016/04/15 20:27:17 Why do we care so much about the cors vs. non-cors
Charlie Harrison 2016/04/20 12:36:42 It was originally because these separate into priv
458 EXPECT_EQ(2u, target_connection_listener_->GetAcceptedSocketCount());
459 EXPECT_EQ(2, source_target_learned_);
460 EXPECT_EQ(2, preconnected_source_);
461 }
462
463 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, CrossSiteCORSUseTwoSockets) {
464 NavigateToCrossSiteHTMLURL(2, 0, "");
465 EXPECT_EQ(2u, target_connection_listener_->GetAcceptedSocketCount());
466 EXPECT_EQ(2, source_target_learned_);
467 EXPECT_EQ(2, preconnected_source_);
468 }
469
470 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, CrossSiteNoReferrerNoLearning) {
471 NavigateToCrossSiteHTMLURL(1, 0, "_no_referrer");
472 EXPECT_EQ(1u, target_connection_listener_->GetAcceptedSocketCount());
473 EXPECT_EQ(0, source_target_learned_);
474 EXPECT_EQ(2, preconnected_source_);
475 }
476
477 // The following tests confirm that we accurately predict preconnects after
478 // learning from navigations. Note that every "learned" connection adds ~.33 to
479 // the expected connection number, which starts at 2. Every preconnect we
480 // perform multiplies the expected connections by .66. One additional complexity
481 // is that if we've learned to preconnect to host B on a navigation from host A,
482 // we add a preconnect if the host part of A and B match (ignoring port). This
483 // logic could probably be removed.
mmenke 2016/04/15 20:27:16 Oh wow...that's funky. Could we have a test where
Charlie Harrison 2016/04/20 12:36:43 Added a test using localhost.
484 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest,
485 CrossSiteSimplePredictionAfterOneNavigation) {
486 NavigateToCrossSiteHTMLURL(2, 0, "");
487 EXPECT_EQ(2u, target_connection_listener_->GetAcceptedSocketCount());
488 EXPECT_EQ(2, source_target_learned_);
489 EXPECT_EQ(2, preconnected_source_);
490
491 ResetTarget();
492
493 // Navigate again and confirm we preconnect. Note that because the two
494 // embedded test servers have the same host_piece, we preconnect an additional
495 // time. This gives us ceil(2.66) + 1 = 4 preconnects.
496 ui_test_utils::NavigateToURL(browser(),
497 embedded_test_server()->GetURL("/title1.html"));
498 EXPECT_EQ(4u, target_connection_listener_->GetAcceptedSocketCount());
499 EXPECT_EQ(4, preconnected_target_);
500 }
501
502 // Expect that the predictor correctly predicts subframe navigations.
503 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, SubframeCrossSitePrediction) {
504 ui_test_utils::NavigateToURL(
505 browser(), embedded_test_server()->GetURL(
506 "/predictor/predictor_cross_site_subframe_nav.html"));
507 bool result = false;
508 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
509 browser()->tab_strip_model()->GetActiveWebContents(),
510 base::StringPrintf(
511 "navigateSubframe('%s')",
512 target_test_server()->GetURL("/title1.html").spec().c_str()),
513 &result));
514 EXPECT_TRUE(result);
515 EXPECT_EQ(2u, target_connection_listener_->GetAcceptedSocketCount());
516 EXPECT_EQ(1, source_target_learned_);
517 EXPECT_EQ(2, preconnected_source_);
518
519 ResetTarget();
520
521 // Navigate again and confirm we preconnect. Note that because the two
522 // embedded test servers have the same host_piece, we preconnect an additional
523 // time. This gives us ceil(2 + .33) + 1 = 4 preconnects.
524 ui_test_utils::NavigateToURL(browser(),
525 embedded_test_server()->GetURL("/title1.html"));
526 EXPECT_EQ(4u, target_connection_listener_->GetAcceptedSocketCount());
527 EXPECT_EQ(4, preconnected_target_);
mmenke 2016/04/15 20:27:17 How about also having a test where you just re-nav
Charlie Harrison 2016/04/20 12:36:42 Hm, so this test classifies the subframe as "subre
528 }
529
530 // This test navigates to an html file with a tag:
531 // <meta name="referrer" content="never">
mmenke 2016/04/15 20:27:17 Is this really desired behavior, or just testing a
Charlie Harrison 2016/04/20 12:36:42 Well, the referrer tag is pretty architecturally i
532 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest,
533 CrossSiteNoReferrerNoPredictionAfterOneNavigation) {
534 NavigateToCrossSiteHTMLURL(2, 0, "_no_referrer");
535 EXPECT_EQ(2u, target_connection_listener_->GetAcceptedSocketCount());
536 EXPECT_EQ(0, source_target_learned_);
537 EXPECT_EQ(2, preconnected_source_);
538
539 ResetTarget();
540
541 // Navigate again and confirm that no preconnects occurred.
542 ui_test_utils::NavigateToURL(browser(),
543 embedded_test_server()->GetURL("/title1.html"));
544 EXPECT_EQ(0u, target_connection_listener_->GetAcceptedSocketCount());
545 EXPECT_EQ(0, preconnected_target_);
546 }
547
548 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest,
549 CrossSiteCORSSimplePredictionAfterTwoNavigations) {
550 NavigateToCrossSiteHTMLURL(0, 1, "");
551 NavigateToCrossSiteHTMLURL(0, 1, "");
552
553 ResetTarget();
554
555 // Navigate again and confirm we preconnect. Note that because the two
556 // embedded test servers have the same host_piece, we preconnect an additional
557 // time. This gives us (2 + .33)*.66 + .33 + 1 ~= 2.87.
mmenke 2016/04/15 20:27:17 nit: --we (x3). Well, one's an "us".
Charlie Harrison 2016/04/20 12:36:42 Done.
558 ui_test_utils::NavigateToURL(browser(),
559 embedded_test_server()->GetURL("/title1.html"));
560 EXPECT_EQ(3u, target_connection_listener_->GetAcceptedSocketCount());
561 EXPECT_EQ(3, preconnected_target_);
562 }
563
564 IN_PROC_BROWSER_TEST_F(
565 PredictorBrowserTest,
566 CrossSiteCORSAndNonCORSSimplePredictionAfterTwoNavigations) {
567 NavigateToCrossSiteHTMLURL(1, 1, "");
568 NavigateToCrossSiteHTMLURL(1, 1, "");
569
570 ResetTarget();
571
572 // Navigate again and confirm we preconnect. Note that because the two
573 // embedded test servers have the same host_piece, we preconnect an additional
574 // time. This gives us (((2 + .66)*.66) + .66) + 1 ~= 3.4
575 ui_test_utils::NavigateToURL(browser(),
576 embedded_test_server()->GetURL("/title1.html"));
577 EXPECT_EQ(4u, target_connection_listener_->GetAcceptedSocketCount());
578 EXPECT_EQ(4, preconnected_target_);
579 }
580
581 // The first navigation uses a subresource. Subsequent navigations don't use
582 // that subresource. This tests how the predictor forgets about these bad
583 // navigations.
584 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, ForgetBadPrediction) {
585 NavigateToCrossSiteHTMLURL(1, 0, "");
586
587 ResetTarget();
588
589 ui_test_utils::NavigateToURL(browser(),
590 embedded_test_server()->GetURL("/title1.html"));
591 // ceil(2 + .33) + 1 = 4.
592 EXPECT_EQ(4u, target_connection_listener_->GetAcceptedSocketCount());
593 EXPECT_EQ(4, preconnected_target_);
594
595 ResetTarget();
596
597 ui_test_utils::NavigateToURL(browser(),
598 embedded_test_server()->GetURL("/title1.html"));
599
600 // ceil((2 + .33) * .66) + 1 = 3.
601 EXPECT_EQ(3u, target_connection_listener_->GetAcceptedSocketCount());
602 EXPECT_EQ(3, preconnected_target_);
603
604 ResetTarget();
605
606 ui_test_utils::NavigateToURL(browser(),
607 embedded_test_server()->GetURL("/title1.html"));
608 // ceil((2 + .33) * .66 * .66) + 1 = 3.
609 EXPECT_EQ(3u, target_connection_listener_->GetAcceptedSocketCount());
610 EXPECT_EQ(3, preconnected_target_);
611
612 ResetTarget();
613
614 ui_test_utils::NavigateToURL(browser(),
615 embedded_test_server()->GetURL("/title1.html"));
616 // Finally, (2 + .33) * .66^3 ~= .67. Not enough for a preconnect.
617 EXPECT_EQ(0u, target_connection_listener_->GetAcceptedSocketCount());
618 EXPECT_EQ(0, preconnected_target_);
619 }
620
621 // The predictor does not follow redirects if the original url had a non-empty
622 // path (a path that was more than just "/").
623 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest,
624 CrossSiteRedirectNoPredictionWithPath) {
625 ui_test_utils::NavigateToURL(
626 browser(),
627 embedded_test_server()->GetURL(base::StringPrintf(
628 "/server-redirect?%s",
629 target_test_server()->GetURL("/title1.html").spec().c_str())));
630 EXPECT_EQ(2u, target_connection_listener_->GetAcceptedSocketCount());
631 EXPECT_EQ(0, source_target_learned_);
632 EXPECT_EQ(2, preconnected_source_);
633
634 ResetTarget();
635
636 ui_test_utils::NavigateToURL(browser(),
637 embedded_test_server()->GetURL("/title1.html"));
638 EXPECT_EQ(0u, target_connection_listener_->GetAcceptedSocketCount());
639 EXPECT_EQ(0, preconnected_target_);
640 }
641
642 // The predictor does follow redirects if the original url had an empty path
643 // (a path that was more than just "/"). Here we use the registered "/" path to
644 // redirect to the target test server.
645 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest,
646 CrossSiteRedirectPredictionWithNoPath) {
647 ui_test_utils::NavigateToURL(browser(), embedded_test_server()->GetURL("/"));
648 EXPECT_EQ(2u, target_connection_listener_->GetAcceptedSocketCount());
649 EXPECT_EQ(1, source_target_learned_);
650 EXPECT_EQ(2, preconnected_source_);
651
652 ResetTarget();
653
654 ui_test_utils::NavigateToURL(browser(),
655 embedded_test_server()->GetURL("/title1.html"));
656 // We preconnect 4 sockets because ceil(2 + .33) + 1 = 4.
657 EXPECT_EQ(4u, target_connection_listener_->GetAcceptedSocketCount());
658 EXPECT_EQ(4, preconnected_target_);
659 }
660
661 // Perform the "/" redirect twice and make sure the predictor updates twice.
662 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest,
663 CrossSiteTwoRedirectsPredictionWithNoPath) {
664 ui_test_utils::NavigateToURL(browser(), embedded_test_server()->GetURL("/"));
665 EXPECT_EQ(1, source_target_learned_);
666 EXPECT_EQ(2, preconnected_source_);
667
668 ui_test_utils::NavigateToURL(browser(), embedded_test_server()->GetURL("/"));
669 EXPECT_EQ(2, source_target_learned_);
670 EXPECT_EQ(2, preconnected_source_);
671
672 ResetTarget();
673
674 ui_test_utils::NavigateToURL(browser(),
675 embedded_test_server()->GetURL("/title1.html"));
676 // 3 preconnects expected because (2 + .33) * .66 + .33 + 1 ~= 2.87.
677 EXPECT_EQ(3u, target_connection_listener_->GetAcceptedSocketCount());
678 EXPECT_EQ(3, preconnected_target_);
679 }
680
313 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PRE_ShutdownStartupCycle) { 681 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PRE_ShutdownStartupCycle) {
314 // Prepare state that will be serialized on this shut-down and read on next 682 // Prepare state that will be serialized on this shut-down and read on next
315 // start-up. 683 // start-up.
316 LearnAboutInitialNavigation(startup_url_); 684 LearnAboutInitialNavigation(startup_url_);
317 LearnFromNavigation(referring_url_, target_url_); 685 LearnFromNavigation(referring_url_, target_url_);
318 } 686 }
319 687
320 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, ShutdownStartupCycle) { 688 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, ShutdownStartupCycle) {
321 // Make sure that the Preferences file is actually wiped of all DNS prefetch 689 // Make sure that the Preferences file is actually wiped of all DNS prefetch
322 // related data after start-up. 690 // related data after start-up.
323 std::string cleared_startup_list; 691 std::string cleared_startup_list;
324 std::string cleared_referral_list; 692 std::string cleared_referral_list;
325 GetListFromPrefsAsString(prefs::kDnsPrefetchingStartupList, 693 GetListFromPrefsAsString(prefs::kDnsPrefetchingStartupList,
326 &cleared_startup_list); 694 &cleared_startup_list);
327 GetListFromPrefsAsString(prefs::kDnsPrefetchingHostReferralList, 695 GetListFromPrefsAsString(prefs::kDnsPrefetchingHostReferralList,
328 &cleared_referral_list); 696 &cleared_referral_list);
329 697
330 EXPECT_THAT(cleared_startup_list, Not(HasSubstr(startup_url_.host()))); 698 EXPECT_THAT(cleared_startup_list, Not(HasSubstr(startup_url_.host())));
331 EXPECT_THAT(cleared_referral_list, Not(HasSubstr(referring_url_.host()))); 699 EXPECT_THAT(cleared_referral_list, Not(HasSubstr(referring_url_.host())));
332 EXPECT_THAT(cleared_referral_list, Not(HasSubstr(target_url_.host()))); 700 EXPECT_THAT(cleared_referral_list, Not(HasSubstr(target_url_.host())));
333 701
334 // But also make sure this data has been first loaded into the Predictor, by 702 // But also make sure this data has been first loaded into the Predictor, by
335 // inspecting that the Predictor starts making the expected hostname requests. 703 // inspecting that the Predictor starts making the expected hostname requests.
704 predictor()->set_preconnect_enabled(false);
336 PrepareFrameSubresources(referring_url_); 705 PrepareFrameSubresources(referring_url_);
337 WaitUntilHostHasBeenRequested(startup_url_.host()); 706 WaitUntilHostHasBeenRequested(startup_url_.host());
338 WaitUntilHostHasBeenRequested(target_url_.host()); 707 WaitUntilHostHasBeenRequested(target_url_.host());
339 } 708 }
340 709
341 // Flaky on Windows: http://crbug.com/469120 710 // Flaky on Windows: http://crbug.com/469120
342 #if defined(OS_WIN) 711 #if defined(OS_WIN)
343 #define MAYBE_DnsPrefetch DISABLED_DnsPrefetch 712 #define MAYBE_DnsPrefetch DISABLED_DnsPrefetch
344 #else 713 #else
345 #define MAYBE_DnsPrefetch DnsPrefetch 714 #define MAYBE_DnsPrefetch DnsPrefetch
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 // Second navigation to content with an img. 824 // Second navigation to content with an img.
456 std::string img_content = 825 std::string img_content =
457 "<img src=\"" + preconnect_url.spec() + "test.gif\">"; 826 "<img src=\"" + preconnect_url.spec() + "test.gif\">";
458 NavigateToDataURLWithContent(img_content); 827 NavigateToDataURLWithContent(img_content);
459 connection_listener_->WaitUntilFirstConnectionRead(); 828 connection_listener_->WaitUntilFirstConnectionRead();
460 EXPECT_EQ(2u, connection_listener_->GetAcceptedSocketCount()); 829 EXPECT_EQ(2u, connection_listener_->GetAcceptedSocketCount());
461 EXPECT_EQ(1u, connection_listener_->GetReadSocketCount()); 830 EXPECT_EQ(1u, connection_listener_->GetReadSocketCount());
462 } 831 }
463 832
464 } // namespace chrome_browser_net 833 } // namespace chrome_browser_net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698