OLD | NEW |
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 <algorithm> | 8 #include <algorithm> |
9 #include <memory> | 9 #include <memory> |
| 10 #include <set> |
10 | 11 |
11 #include "base/base64.h" | 12 #include "base/base64.h" |
12 #include "base/bind.h" | 13 #include "base/bind.h" |
13 #include "base/callback.h" | 14 #include "base/callback.h" |
14 #include "base/command_line.h" | 15 #include "base/command_line.h" |
15 #include "base/json/json_string_value_serializer.h" | 16 #include "base/json/json_string_value_serializer.h" |
16 #include "base/macros.h" | 17 #include "base/macros.h" |
17 #include "base/memory/ptr_util.h" | 18 #include "base/memory/ptr_util.h" |
18 #include "base/memory/ref_counted.h" | 19 #include "base/memory/ref_counted.h" |
| 20 #include "base/stl_util.h" |
19 #include "base/synchronization/lock.h" | 21 #include "base/synchronization/lock.h" |
20 #include "base/threading/thread_task_runner_handle.h" | 22 #include "base/threading/thread_task_runner_handle.h" |
21 #include "build/build_config.h" | 23 #include "build/build_config.h" |
22 #include "chrome/browser/browser_process.h" | 24 #include "chrome/browser/browser_process.h" |
23 #include "chrome/browser/net/predictor.h" | 25 #include "chrome/browser/net/predictor.h" |
24 #include "chrome/browser/profiles/profile.h" | 26 #include "chrome/browser/profiles/profile.h" |
25 #include "chrome/browser/ui/browser.h" | 27 #include "chrome/browser/ui/browser.h" |
26 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 28 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
27 #include "chrome/common/pref_names.h" | 29 #include "chrome/common/pref_names.h" |
28 #include "chrome/test/base/in_process_browser_test.h" | 30 #include "chrome/test/base/in_process_browser_test.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 if (request.GetURL().path() != path) | 78 if (request.GetURL().path() != path) |
77 return nullptr; | 79 return nullptr; |
78 std::unique_ptr<net::test_server::BasicHttpResponse> response( | 80 std::unique_ptr<net::test_server::BasicHttpResponse> response( |
79 new net::test_server::BasicHttpResponse); | 81 new net::test_server::BasicHttpResponse); |
80 response->set_code(net::HTTP_MOVED_PERMANENTLY); | 82 response->set_code(net::HTTP_MOVED_PERMANENTLY); |
81 response->AddCustomHeader("Location", redirect_url.spec()); | 83 response->AddCustomHeader("Location", redirect_url.spec()); |
82 return std::move(response); | 84 return std::move(response); |
83 } | 85 } |
84 | 86 |
85 const char kBlinkPreconnectFeature[] = "LinkPreconnect"; | 87 const char kBlinkPreconnectFeature[] = "LinkPreconnect"; |
86 const char kChromiumHostname[] = "chromium.org"; | 88 const char kChromiumUrl[] = "http://chromium.org"; |
87 const char kInvalidLongHostname[] = "illegally-long-hostname-over-255-" | 89 const char kInvalidLongUrl[] = |
88 "characters-should-not-send-an-ipc-message-to-the-browser-" | 90 "http://" |
89 "0000000000000000000000000000000000000000000000000000000000000000000000000" | 91 "illegally-long-hostname-over-255-characters-should-not-send-an-ipc-" |
90 "0000000000000000000000000000000000000000000000000000000000000000000000000" | 92 "message-to-the-browser-" |
91 "000000000000000000000000000000000000000000000000000000.org"; | 93 "00000000000000000000000000000000000000000000000000000000000000000000000000" |
| 94 "00000000000000000000000000000000000000000000000000000000000000000000000000" |
| 95 "0000000000000000000000000000000000000000000000000000.org"; |
92 | 96 |
93 // Gets notified by the EmbeddedTestServer on incoming connections being | 97 // Gets notified by the EmbeddedTestServer on incoming connections being |
94 // accepted or read from, keeps track of them and exposes that info to | 98 // accepted or read from, keeps track of them and exposes that info to |
95 // the tests. | 99 // the tests. |
96 // A port being reused is currently considered an error. If a test | 100 // A port being reused is currently considered an error. If a test |
97 // needs to verify multiple connections are opened in sequence, that will need | 101 // needs to verify multiple connections are opened in sequence, that will need |
98 // to be changed. | 102 // to be changed. |
99 class ConnectionListener | 103 class ConnectionListener |
100 : public net::test_server::EmbeddedTestServerConnectionListener { | 104 : public net::test_server::EmbeddedTestServerConnectionListener { |
101 public: | 105 public: |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 | 242 |
239 // If |num_accepted_connections_needed_| is non zero, then the object is | 243 // If |num_accepted_connections_needed_| is non zero, then the object is |
240 // waiting for |num_accepted_connections_needed_| sockets to be accepted | 244 // waiting for |num_accepted_connections_needed_| sockets to be accepted |
241 // before quitting the |num_accepted_connections_loop_|. | 245 // before quitting the |num_accepted_connections_loop_|. |
242 size_t num_accepted_connections_needed_; | 246 size_t num_accepted_connections_needed_; |
243 base::RunLoop* num_accepted_connections_loop_; | 247 base::RunLoop* num_accepted_connections_loop_; |
244 | 248 |
245 DISALLOW_COPY_AND_ASSIGN(ConnectionListener); | 249 DISALLOW_COPY_AND_ASSIGN(ConnectionListener); |
246 }; | 250 }; |
247 | 251 |
248 // Records a history of all hostnames for which resolving has been requested, | |
249 // and immediately fails the resolution requests themselves. | |
250 class HostResolutionRequestRecorder : public net::HostResolverProc { | |
251 public: | |
252 HostResolutionRequestRecorder() | |
253 : HostResolverProc(NULL), | |
254 is_waiting_for_hostname_(false) { | |
255 } | |
256 | |
257 int Resolve(const std::string& host, | |
258 net::AddressFamily address_family, | |
259 net::HostResolverFlags host_resolver_flags, | |
260 net::AddressList* addrlist, | |
261 int* os_error) override { | |
262 BrowserThread::PostTask( | |
263 BrowserThread::UI, | |
264 FROM_HERE, | |
265 base::Bind(&HostResolutionRequestRecorder::AddToHistory, | |
266 base::Unretained(this), | |
267 host)); | |
268 return net::ERR_NAME_NOT_RESOLVED; | |
269 } | |
270 | |
271 int RequestedHostnameCount() const { | |
272 return requested_hostnames_.size(); | |
273 } | |
274 | |
275 bool HasHostBeenRequested(const std::string& hostname) const { | |
276 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
277 return std::find(requested_hostnames_.begin(), | |
278 requested_hostnames_.end(), | |
279 hostname) != requested_hostnames_.end(); | |
280 } | |
281 | |
282 void WaitUntilHostHasBeenRequested(const std::string& hostname) { | |
283 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
284 DCHECK(!is_waiting_for_hostname_); | |
285 if (HasHostBeenRequested(hostname)) | |
286 return; | |
287 waiting_for_hostname_ = hostname; | |
288 is_waiting_for_hostname_ = true; | |
289 content::RunMessageLoop(); | |
290 } | |
291 | |
292 private: | |
293 ~HostResolutionRequestRecorder() override {} | |
294 | |
295 void AddToHistory(const std::string& hostname) { | |
296 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
297 requested_hostnames_.push_back(hostname); | |
298 if (is_waiting_for_hostname_ && waiting_for_hostname_ == hostname) { | |
299 is_waiting_for_hostname_ = false; | |
300 waiting_for_hostname_.clear(); | |
301 base::MessageLoop::current()->QuitWhenIdle(); | |
302 } | |
303 } | |
304 | |
305 // The hostname which WaitUntilHostHasBeenRequested is currently waiting for | |
306 // to be requested. | |
307 std::string waiting_for_hostname_; | |
308 | |
309 // Whether WaitUntilHostHasBeenRequested is waiting for a hostname to be | |
310 // requested and thus is running a nested message loop. | |
311 bool is_waiting_for_hostname_; | |
312 | |
313 // A list of hostnames for which resolution has already been requested. Only | |
314 // to be accessed from the UI thread. | |
315 std::vector<std::string> requested_hostnames_; | |
316 | |
317 DISALLOW_COPY_AND_ASSIGN(HostResolutionRequestRecorder); | |
318 }; | |
319 | |
320 // This class intercepts URLRequests and responds with the URLRequestJob* | 252 // This class intercepts URLRequests and responds with the URLRequestJob* |
321 // callback provided by the constructor. Note that the port of the URL must | 253 // callback provided by the constructor. Note that the port of the URL must |
322 // match the port given in the constructor. | 254 // match the port given in the constructor. |
323 class MatchingPortRequestInterceptor : public net::URLRequestInterceptor { | 255 class MatchingPortRequestInterceptor : public net::URLRequestInterceptor { |
324 public: | 256 public: |
325 typedef base::Callback<net::URLRequestJob*(net::URLRequest*, | 257 typedef base::Callback<net::URLRequestJob*(net::URLRequest*, |
326 net::NetworkDelegate*)> | 258 net::NetworkDelegate*)> |
327 CreateJobCallback; | 259 CreateJobCallback; |
328 | 260 |
329 MatchingPortRequestInterceptor( | 261 MatchingPortRequestInterceptor( |
(...skipping 25 matching lines...) Expand all Loading... |
355 // two. | 287 // two. |
356 class CrossSitePredictorObserver | 288 class CrossSitePredictorObserver |
357 : public chrome_browser_net::PredictorObserver { | 289 : public chrome_browser_net::PredictorObserver { |
358 public: | 290 public: |
359 CrossSitePredictorObserver(const GURL& source_host, | 291 CrossSitePredictorObserver(const GURL& source_host, |
360 const GURL& cross_site_host) | 292 const GURL& cross_site_host) |
361 : source_host_(source_host), | 293 : source_host_(source_host), |
362 cross_site_host_(cross_site_host), | 294 cross_site_host_(cross_site_host), |
363 cross_site_learned_(0), | 295 cross_site_learned_(0), |
364 cross_site_preconnected_(0), | 296 cross_site_preconnected_(0), |
365 same_site_preconnected_(0) {} | 297 same_site_preconnected_(0), |
| 298 dns_run_loop_(nullptr) {} |
366 | 299 |
367 void OnPreconnectUrl( | 300 void OnPreconnectUrl( |
368 const GURL& original_url, | 301 const GURL& original_url, |
369 const GURL& first_party_for_cookies, | 302 const GURL& first_party_for_cookies, |
370 chrome_browser_net::UrlInfo::ResolutionMotivation motivation, | 303 chrome_browser_net::UrlInfo::ResolutionMotivation motivation, |
371 int count) override { | 304 int count) override { |
372 base::AutoLock lock(lock_); | 305 base::AutoLock lock(lock_); |
373 if (original_url == cross_site_host_) { | 306 if (original_url == cross_site_host_) { |
374 cross_site_preconnected_ = std::max(cross_site_preconnected_, count); | 307 cross_site_preconnected_ = std::max(cross_site_preconnected_, count); |
375 } else if (original_url == source_host_) { | 308 } else if (original_url == source_host_) { |
(...skipping 19 matching lines...) Expand all Loading... |
395 // Same site learned. Branch retained for clarity. | 328 // Same site learned. Branch retained for clarity. |
396 } else if (!(referring_url == cross_site_host_ && | 329 } else if (!(referring_url == cross_site_host_ && |
397 target_url == cross_site_host_)) { | 330 target_url == cross_site_host_)) { |
398 ADD_FAILURE() << "Learned " << referring_url << " => " << target_url | 331 ADD_FAILURE() << "Learned " << referring_url << " => " << target_url |
399 << " when should only be learning the source host: " | 332 << " when should only be learning the source host: " |
400 << source_host_ | 333 << source_host_ |
401 << " or the cross site host: " << cross_site_host_; | 334 << " or the cross site host: " << cross_site_host_; |
402 } | 335 } |
403 } | 336 } |
404 | 337 |
| 338 void OnDnsLookupFinished(const GURL& url, bool found) override { |
| 339 base::AutoLock lock(lock_); |
| 340 if (found) { |
| 341 successful_dns_lookups_.insert(url); |
| 342 } else { |
| 343 unsuccessful_dns_lookups_.insert(url); |
| 344 } |
| 345 CheckForWaitingLoop(); |
| 346 } |
| 347 |
405 void ResetCounts() { | 348 void ResetCounts() { |
406 base::AutoLock lock(lock_); | 349 base::AutoLock lock(lock_); |
407 cross_site_learned_ = 0; | 350 cross_site_learned_ = 0; |
408 cross_site_preconnected_ = 0; | 351 cross_site_preconnected_ = 0; |
409 same_site_preconnected_ = 0; | 352 same_site_preconnected_ = 0; |
410 } | 353 } |
411 | 354 |
412 int CrossSiteLearned() { | 355 int CrossSiteLearned() { |
413 base::AutoLock lock(lock_); | 356 base::AutoLock lock(lock_); |
414 return cross_site_learned_; | 357 return cross_site_learned_; |
415 } | 358 } |
416 | 359 |
417 int CrossSitePreconnected() { | 360 int CrossSitePreconnected() { |
418 base::AutoLock lock(lock_); | 361 base::AutoLock lock(lock_); |
419 return cross_site_preconnected_; | 362 return cross_site_preconnected_; |
420 } | 363 } |
421 | 364 |
422 int SameSitePreconnected() { | 365 int SameSitePreconnected() { |
423 base::AutoLock lock(lock_); | 366 base::AutoLock lock(lock_); |
424 return same_site_preconnected_; | 367 return same_site_preconnected_; |
425 } | 368 } |
426 | 369 |
| 370 // Spins a run loop until |url| is added to one of the lookup maps. |
| 371 void WaitUntilHostLookedUp(const GURL& url) { |
| 372 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 373 base::RunLoop run_loop; |
| 374 { |
| 375 base::AutoLock lock(lock_); |
| 376 DCHECK(waiting_on_dns_.is_empty()); |
| 377 DCHECK(!dns_run_loop_); |
| 378 waiting_on_dns_ = url; |
| 379 dns_run_loop_ = &run_loop; |
| 380 CheckForWaitingLoop(); |
| 381 } |
| 382 run_loop.Run(); |
| 383 } |
| 384 |
| 385 bool HasHostBeenLookedUpLocked(const GURL& url) { |
| 386 lock_.AssertAcquired(); |
| 387 return ContainsKey(successful_dns_lookups_, url) || |
| 388 ContainsKey(unsuccessful_dns_lookups_, url); |
| 389 } |
| 390 |
| 391 bool HasHostBeenLookedUp(const GURL& url) { |
| 392 base::AutoLock lock(lock_); |
| 393 return HasHostBeenLookedUpLocked(url); |
| 394 } |
| 395 |
| 396 void CheckForWaitingLoop() { |
| 397 lock_.AssertAcquired(); |
| 398 if (waiting_on_dns_.is_empty()) |
| 399 return; |
| 400 if (!HasHostBeenLookedUpLocked(waiting_on_dns_)) |
| 401 return; |
| 402 DCHECK(dns_run_loop_); |
| 403 DCHECK(task_runner_); |
| 404 waiting_on_dns_ = GURL(); |
| 405 task_runner_->PostTask(FROM_HERE, dns_run_loop_->QuitClosure()); |
| 406 dns_run_loop_ = nullptr; |
| 407 } |
| 408 |
| 409 size_t TotalHostsLookedUp() { |
| 410 base::AutoLock lock(lock_); |
| 411 return successful_dns_lookups_.size() + unsuccessful_dns_lookups_.size(); |
| 412 } |
| 413 |
| 414 // Note: this method expects the URL to have been looked up. |
| 415 bool HostFound(const GURL& url) { |
| 416 base::AutoLock lock(lock_); |
| 417 EXPECT_TRUE(HasHostBeenLookedUpLocked(url)) << "Expected to have looked up " |
| 418 << url.spec(); |
| 419 return ContainsKey(successful_dns_lookups_, url); |
| 420 } |
| 421 |
| 422 void set_task_runner( |
| 423 scoped_refptr<base::SingleThreadTaskRunner> task_runner) { |
| 424 task_runner_.swap(task_runner); |
| 425 } |
| 426 |
427 private: | 427 private: |
428 const GURL source_host_; | 428 const GURL source_host_; |
429 const GURL cross_site_host_; | 429 const GURL cross_site_host_; |
430 | 430 |
| 431 GURL waiting_on_dns_; |
| 432 |
| 433 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| 434 |
431 // Protects all following members. They are read and updated from different | 435 // Protects all following members. They are read and updated from different |
432 // threads. | 436 // threads. |
433 base::Lock lock_; | 437 base::Lock lock_; |
434 | 438 |
435 int cross_site_learned_; | 439 int cross_site_learned_; |
436 int cross_site_preconnected_; | 440 int cross_site_preconnected_; |
437 int same_site_preconnected_; | 441 int same_site_preconnected_; |
438 | 442 |
| 443 std::set<GURL> successful_dns_lookups_; |
| 444 std::set<GURL> unsuccessful_dns_lookups_; |
| 445 base::RunLoop* dns_run_loop_; |
| 446 |
439 DISALLOW_COPY_AND_ASSIGN(CrossSitePredictorObserver); | 447 DISALLOW_COPY_AND_ASSIGN(CrossSitePredictorObserver); |
440 }; | 448 }; |
441 | 449 |
442 } // namespace | 450 } // namespace |
443 | 451 |
444 namespace chrome_browser_net { | 452 namespace chrome_browser_net { |
445 | 453 |
446 class PredictorBrowserTest : public InProcessBrowserTest { | 454 class PredictorBrowserTest : public InProcessBrowserTest { |
447 public: | 455 public: |
448 PredictorBrowserTest() | 456 PredictorBrowserTest() |
449 : startup_url_("http://host1:1"), | 457 : startup_url_("http://host1/"), |
450 referring_url_("http://host2:1"), | 458 referring_url_("http://host2/"), |
451 target_url_("http://host3:1"), | 459 target_url_("http://host3/"), |
452 host_resolution_request_recorder_(new HostResolutionRequestRecorder), | 460 rule_based_resolver_proc_(new net::RuleBasedHostResolverProc(nullptr)), |
453 cross_site_test_server_(new net::EmbeddedTestServer()) {} | 461 cross_site_test_server_(new net::EmbeddedTestServer()) { |
| 462 rule_based_resolver_proc_->AddRuleWithLatency("www.example.test", |
| 463 "127.0.0.1", 50); |
| 464 rule_based_resolver_proc_->AddRuleWithLatency("gmail.google.com", |
| 465 "127.0.0.1", 70); |
| 466 rule_based_resolver_proc_->AddRuleWithLatency("mail.google.com", |
| 467 "127.0.0.1", 44); |
| 468 rule_based_resolver_proc_->AddRuleWithLatency("gmail.com", "127.0.0.1", 63); |
| 469 rule_based_resolver_proc_->AddSimulatedFailure("*.notfound"); |
| 470 rule_based_resolver_proc_->AddRuleWithLatency("delay.google.com", |
| 471 "127.0.0.1", 1000 * 60); |
| 472 } |
454 | 473 |
455 protected: | 474 protected: |
456 void SetUpInProcessBrowserTestFixture() override { | 475 void SetUpInProcessBrowserTestFixture() override { |
457 scoped_host_resolver_proc_.reset(new net::ScopedDefaultHostResolverProc( | 476 scoped_host_resolver_proc_.reset(new net::ScopedDefaultHostResolverProc( |
458 host_resolution_request_recorder_.get())); | 477 rule_based_resolver_proc_.get())); |
459 InProcessBrowserTest::SetUpInProcessBrowserTestFixture(); | 478 InProcessBrowserTest::SetUpInProcessBrowserTestFixture(); |
460 } | 479 } |
461 | 480 |
462 void SetUpCommandLine(base::CommandLine* command_line) override { | 481 void SetUpCommandLine(base::CommandLine* command_line) override { |
463 command_line->AppendSwitch( | 482 command_line->AppendSwitch( |
464 switches::kEnableExperimentalWebPlatformFeatures); | 483 switches::kEnableExperimentalWebPlatformFeatures); |
465 command_line->AppendSwitchASCII( | 484 command_line->AppendSwitchASCII( |
466 switches::kEnableBlinkFeatures, kBlinkPreconnectFeature); | 485 switches::kEnableBlinkFeatures, kBlinkPreconnectFeature); |
467 command_line->AppendSwitchASCII(switches::kEnableFeatures, | 486 command_line->AppendSwitchASCII(switches::kEnableFeatures, |
468 "PreconnectMore"); | 487 "PreconnectMore"); |
| 488 command_line->AppendSwitchASCII(switches::kEnableFeatures, |
| 489 "UsePredictorDNSQueue"); |
469 } | 490 } |
470 | 491 |
471 void SetUpOnMainThread() override { | 492 void SetUpOnMainThread() override { |
472 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 493 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
473 task_runner_ = base::ThreadTaskRunnerHandle::Get(); | 494 task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
474 cross_site_test_server_->ServeFilesFromSourceDirectory("chrome/test/data/"); | 495 cross_site_test_server_->ServeFilesFromSourceDirectory("chrome/test/data/"); |
475 | 496 |
476 connection_listener_.reset(new ConnectionListener()); | 497 connection_listener_.reset(new ConnectionListener()); |
477 cross_site_connection_listener_.reset(new ConnectionListener()); | 498 cross_site_connection_listener_.reset(new ConnectionListener()); |
478 embedded_test_server()->SetConnectionListener(connection_listener_.get()); | 499 embedded_test_server()->SetConnectionListener(connection_listener_.get()); |
479 cross_site_test_server_->SetConnectionListener( | 500 cross_site_test_server_->SetConnectionListener( |
480 cross_site_connection_listener_.get()); | 501 cross_site_connection_listener_.get()); |
481 ASSERT_TRUE(embedded_test_server()->Start()); | 502 ASSERT_TRUE(embedded_test_server()->Start()); |
482 ASSERT_TRUE(cross_site_test_server_->Start()); | 503 ASSERT_TRUE(cross_site_test_server_->Start()); |
483 | 504 |
484 embedded_test_server()->RegisterRequestHandler( | 505 embedded_test_server()->RegisterRequestHandler( |
485 base::Bind(&RedirectForPathHandler, "/", | 506 base::Bind(&RedirectForPathHandler, "/", |
486 cross_site_test_server()->GetURL("/title1.html"))); | 507 cross_site_test_server()->GetURL("/title1.html"))); |
487 | 508 |
488 predictor()->SetPreconnectEnabledForTest(true); | 509 predictor()->SetPreconnectEnabledForTest(true); |
489 InstallPredictorObserver(embedded_test_server()->base_url(), | 510 InstallPredictorObserver(embedded_test_server()->base_url(), |
490 cross_site_test_server()->base_url()); | 511 cross_site_test_server()->base_url()); |
| 512 observer()->set_task_runner(task_runner_); |
491 StartInterceptingCrossSiteOnUI(); | 513 StartInterceptingCrossSiteOnUI(); |
492 } | 514 } |
493 | 515 |
494 // Intercepts all requests to the specified host and returns a response with | 516 // Intercepts all requests to the specified host and returns a response with |
495 // an empty body. Needed to prevent requests from actually going to the test | 517 // an empty body. Needed to prevent requests from actually going to the test |
496 // server, to avoid any races related to socket accounting. Note, the | 518 // server, to avoid any races related to socket accounting. Note, the |
497 // interceptor also looks at the port, to differentiate between the | 519 // interceptor also looks at the port, to differentiate between the |
498 // two test servers. | 520 // two test servers. |
499 static void StartInterceptingHost(const GURL& url) { | 521 static void StartInterceptingHost(const GURL& url) { |
500 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 522 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
566 } | 588 } |
567 | 589 |
568 void GetListFromPrefsAsString(const char* list_path, | 590 void GetListFromPrefsAsString(const char* list_path, |
569 std::string* value_as_string) const { | 591 std::string* value_as_string) const { |
570 PrefService* prefs = browser()->profile()->GetPrefs(); | 592 PrefService* prefs = browser()->profile()->GetPrefs(); |
571 const base::ListValue* list_value = prefs->GetList(list_path); | 593 const base::ListValue* list_value = prefs->GetList(list_path); |
572 JSONStringValueSerializer serializer(value_as_string); | 594 JSONStringValueSerializer serializer(value_as_string); |
573 serializer.Serialize(*list_value); | 595 serializer.Serialize(*list_value); |
574 } | 596 } |
575 | 597 |
576 bool HasHostBeenRequested(const std::string& hostname) const { | 598 void WaitUntilHostsLookedUp(const network_hints::UrlList& names) { |
577 return host_resolution_request_recorder_->HasHostBeenRequested(hostname); | 599 for (const GURL& url : names) |
| 600 observer()->WaitUntilHostLookedUp(url); |
578 } | 601 } |
579 | 602 |
580 void WaitUntilHostHasBeenRequested(const std::string& hostname) { | 603 void FloodResolveRequestsOnUIThread(const network_hints::UrlList& names) { |
581 host_resolution_request_recorder_->WaitUntilHostHasBeenRequested(hostname); | 604 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 605 BrowserThread::PostTask( |
| 606 BrowserThread::IO, FROM_HERE, |
| 607 base::Bind(&PredictorBrowserTest::FloodResolveRequests, this, names)); |
582 } | 608 } |
583 | 609 |
584 int RequestedHostnameCount() const { | 610 void FloodResolveRequests(const network_hints::UrlList& names) { |
585 return host_resolution_request_recorder_->RequestedHostnameCount(); | 611 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 612 for (int i = 0; i < 10; i++) { |
| 613 predictor()->DnsPrefetchMotivatedList(names, |
| 614 UrlInfo::PAGE_SCAN_MOTIVATED); |
| 615 } |
586 } | 616 } |
587 | 617 |
588 net::EmbeddedTestServer* cross_site_test_server() { | 618 net::EmbeddedTestServer* cross_site_test_server() { |
589 return cross_site_test_server_.get(); | 619 return cross_site_test_server_.get(); |
590 } | 620 } |
591 | 621 |
592 Predictor* predictor() { return browser()->profile()->GetNetworkPredictor(); } | 622 Predictor* predictor() { return browser()->profile()->GetNetworkPredictor(); } |
593 | 623 |
594 void InstallPredictorObserver(const GURL& source_host, | 624 void InstallPredictorObserver(const GURL& source_host, |
595 const GURL& cross_site_host) { | 625 const GURL& cross_site_host) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
632 base::Unretained(this)), | 662 base::Unretained(this)), |
633 run_loop.QuitClosure()); | 663 run_loop.QuitClosure()); |
634 run_loop.Run(); | 664 run_loop.Run(); |
635 } | 665 } |
636 | 666 |
637 void FlushServerSocketsOnUIThread(net::EmbeddedTestServer* test_server) { | 667 void FlushServerSocketsOnUIThread(net::EmbeddedTestServer* test_server) { |
638 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 668 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
639 EXPECT_TRUE(test_server->FlushAllSocketsAndConnectionsOnUIThread()); | 669 EXPECT_TRUE(test_server->FlushAllSocketsAndConnectionsOnUIThread()); |
640 } | 670 } |
641 | 671 |
| 672 // Note this method also expects that all the urls (found or not) were looked |
| 673 // up. |
| 674 void ExpectFoundUrls( |
| 675 const network_hints::UrlList& found_names, |
| 676 const network_hints::UrlList& not_found_names) { |
| 677 for (const auto& name : found_names) { |
| 678 EXPECT_TRUE(observer()->HostFound(name)) << "Expected to have found " |
| 679 << name.spec(); |
| 680 } |
| 681 for (const auto& name : not_found_names) { |
| 682 EXPECT_FALSE(observer()->HostFound(name)) << "Did not expect to find " |
| 683 << name.spec(); |
| 684 } |
| 685 } |
| 686 |
| 687 // This method verifies that |url| is in the predictor's |results_| map. This |
| 688 // is used for pending lookups, and lookups performed before the observer is |
| 689 // attached. |
| 690 void ExpectUrlRequestedFromPredictorOnUIThread(const GURL& url) { |
| 691 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 692 BrowserThread::PostTask( |
| 693 BrowserThread::IO, FROM_HERE, |
| 694 base::Bind(&PredictorBrowserTest::ExpectUrlRequestedFromPredictor, |
| 695 base::Unretained(this), url)); |
| 696 } |
| 697 |
| 698 void ExpectUrlRequestedFromPredictor(const GURL& url) { |
| 699 EXPECT_TRUE(ContainsKey(predictor()->results_, url)); |
| 700 } |
| 701 |
| 702 void DiscardAllResultsOnUIThread() { |
| 703 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 704 base::Bind(&Predictor::DiscardAllResults, |
| 705 base::Unretained(predictor()))); |
| 706 } |
| 707 |
| 708 void ExpectValidPeakPendingLookupsOnUI(size_t num_names_requested) { |
| 709 BrowserThread::PostTask( |
| 710 BrowserThread::IO, FROM_HERE, |
| 711 base::Bind(&PredictorBrowserTest::ExpectValidPeakPendingLookups, |
| 712 base::Unretained(this), num_names_requested)); |
| 713 } |
| 714 |
| 715 void ExpectValidPeakPendingLookups(size_t num_names_requested) { |
| 716 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 717 EXPECT_LE(predictor()->peak_pending_lookups_, num_names_requested); |
| 718 EXPECT_LE(predictor()->peak_pending_lookups_, |
| 719 predictor()->max_concurrent_dns_lookups()); |
| 720 } |
| 721 |
642 CrossSitePredictorObserver* observer() { return observer_.get(); } | 722 CrossSitePredictorObserver* observer() { return observer_.get(); } |
643 | 723 |
644 // Navigate to an html file on embedded_test_server and tell it to request | 724 // Navigate to an html file on embedded_test_server and tell it to request |
645 // |num_cors| resources from the cross_site_test_server. It then waits for | 725 // |num_cors| resources from the cross_site_test_server. It then waits for |
646 // those requests to complete. Note that "cors" here means using cors-mode in | 726 // those requests to complete. Note that "cors" here means using cors-mode in |
647 // correspondence with the fetch spec. | 727 // correspondence with the fetch spec. |
648 void NavigateToCrossSiteHtmlUrl(int num_cors, const char* file_suffix) { | 728 void NavigateToCrossSiteHtmlUrl(int num_cors, const char* file_suffix) { |
649 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 729 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
650 const GURL& base_url = cross_site_test_server()->base_url(); | 730 const GURL& base_url = cross_site_test_server()->base_url(); |
651 std::string path = base::StringPrintf( | 731 std::string path = base::StringPrintf( |
(...skipping 10 matching lines...) Expand all Loading... |
662 EXPECT_TRUE(result); | 742 EXPECT_TRUE(result); |
663 } | 743 } |
664 | 744 |
665 const GURL startup_url_; | 745 const GURL startup_url_; |
666 const GURL referring_url_; | 746 const GURL referring_url_; |
667 const GURL target_url_; | 747 const GURL target_url_; |
668 std::unique_ptr<ConnectionListener> connection_listener_; | 748 std::unique_ptr<ConnectionListener> connection_listener_; |
669 std::unique_ptr<ConnectionListener> cross_site_connection_listener_; | 749 std::unique_ptr<ConnectionListener> cross_site_connection_listener_; |
670 | 750 |
671 private: | 751 private: |
672 scoped_refptr<HostResolutionRequestRecorder> | 752 scoped_refptr<net::RuleBasedHostResolverProc> rule_based_resolver_proc_; |
673 host_resolution_request_recorder_; | |
674 std::unique_ptr<net::ScopedDefaultHostResolverProc> | 753 std::unique_ptr<net::ScopedDefaultHostResolverProc> |
675 scoped_host_resolver_proc_; | 754 scoped_host_resolver_proc_; |
676 std::unique_ptr<net::EmbeddedTestServer> cross_site_test_server_; | 755 std::unique_ptr<net::EmbeddedTestServer> cross_site_test_server_; |
677 std::unique_ptr<CrossSitePredictorObserver> observer_; | 756 std::unique_ptr<CrossSitePredictorObserver> observer_; |
678 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | 757 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
679 }; | 758 }; |
680 | 759 |
| 760 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, SingleLookupTest) { |
| 761 DiscardAllResultsOnUIThread(); |
| 762 GURL url("http://www.example.test/"); |
| 763 |
| 764 // Try to flood the predictor with many concurrent requests. |
| 765 network_hints::UrlList names{url}; |
| 766 FloodResolveRequestsOnUIThread(names); |
| 767 observer()->WaitUntilHostLookedUp(url); |
| 768 EXPECT_TRUE(observer()->HostFound(url)); |
| 769 ExpectValidPeakPendingLookupsOnUI(1u); |
| 770 } |
| 771 |
| 772 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, ConcurrentLookupTest) { |
| 773 DiscardAllResultsOnUIThread(); |
| 774 GURL url("http://www.example.test"), goog2("http://gmail.google.com"), |
| 775 goog3("http://mail.google.com"), goog4("http://gmail.com"); |
| 776 GURL bad1("http://bad1.notfound"), bad2("http://bad2.notfound"); |
| 777 |
| 778 UrlList found_names{url, goog3, goog2, goog4}; |
| 779 UrlList not_found_names{bad1, bad2}; |
| 780 FloodResolveRequestsOnUIThread(found_names); |
| 781 FloodResolveRequestsOnUIThread(not_found_names); |
| 782 |
| 783 WaitUntilHostsLookedUp(found_names); |
| 784 WaitUntilHostsLookedUp(not_found_names); |
| 785 ExpectFoundUrls(found_names, not_found_names); |
| 786 ExpectValidPeakPendingLookupsOnUI(found_names.size() + |
| 787 not_found_names.size()); |
| 788 } |
| 789 |
| 790 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, MassiveConcurrentLookupTest) { |
| 791 DiscardAllResultsOnUIThread(); |
| 792 UrlList not_found_names; |
| 793 for (int i = 0; i < 100; i++) { |
| 794 not_found_names.push_back( |
| 795 GURL(base::StringPrintf("http://host%d.notfound:80", i))); |
| 796 } |
| 797 FloodResolveRequestsOnUIThread(not_found_names); |
| 798 |
| 799 WaitUntilHostsLookedUp(not_found_names); |
| 800 ExpectFoundUrls(network_hints::UrlList(), not_found_names); |
| 801 ExpectValidPeakPendingLookupsOnUI(not_found_names.size()); |
| 802 } |
| 803 |
| 804 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, |
| 805 ShutdownWhenResolutionIsPendingTest) { |
| 806 GURL delayed_url("http://delay.google.com:80"); |
| 807 UrlList names{delayed_url}; |
| 808 |
| 809 // Flood with delayed requests, then wait. |
| 810 FloodResolveRequestsOnUIThread(names); |
| 811 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 812 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(), |
| 813 base::TimeDelta::FromMilliseconds(500)); |
| 814 base::MessageLoop::current()->Run(); |
| 815 |
| 816 ExpectUrlRequestedFromPredictor(delayed_url); |
| 817 EXPECT_FALSE(observer()->HasHostBeenLookedUp(delayed_url)); |
| 818 } |
| 819 |
681 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, SimplePreconnectOne) { | 820 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, SimplePreconnectOne) { |
682 predictor()->PreconnectUrl( | 821 predictor()->PreconnectUrl( |
683 embedded_test_server()->base_url(), GURL(), | 822 embedded_test_server()->base_url(), GURL(), |
684 UrlInfo::ResolutionMotivation::EARLY_LOAD_MOTIVATED, | 823 UrlInfo::ResolutionMotivation::EARLY_LOAD_MOTIVATED, |
685 false /* allow credentials */, 1); | 824 false /* allow credentials */, 1); |
686 connection_listener_->WaitForAcceptedConnectionsOnUI(1u); | 825 connection_listener_->WaitForAcceptedConnectionsOnUI(1u); |
687 } | 826 } |
688 | 827 |
689 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, SimplePreconnectTwo) { | 828 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, SimplePreconnectTwo) { |
690 predictor()->PreconnectUrl( | 829 predictor()->PreconnectUrl( |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1121 GetListFromPrefsAsString(prefs::kDnsPrefetchingHostReferralList, | 1260 GetListFromPrefsAsString(prefs::kDnsPrefetchingHostReferralList, |
1122 &cleared_referral_list); | 1261 &cleared_referral_list); |
1123 | 1262 |
1124 EXPECT_THAT(cleared_startup_list, Not(HasSubstr(startup_url_.host()))); | 1263 EXPECT_THAT(cleared_startup_list, Not(HasSubstr(startup_url_.host()))); |
1125 EXPECT_THAT(cleared_referral_list, Not(HasSubstr(referring_url_.host()))); | 1264 EXPECT_THAT(cleared_referral_list, Not(HasSubstr(referring_url_.host()))); |
1126 EXPECT_THAT(cleared_referral_list, Not(HasSubstr(target_url_.host()))); | 1265 EXPECT_THAT(cleared_referral_list, Not(HasSubstr(target_url_.host()))); |
1127 | 1266 |
1128 // But also make sure this data has been first loaded into the Predictor, by | 1267 // But also make sure this data has been first loaded into the Predictor, by |
1129 // inspecting that the Predictor starts making the expected hostname requests. | 1268 // inspecting that the Predictor starts making the expected hostname requests. |
1130 PrepareFrameSubresources(referring_url_); | 1269 PrepareFrameSubresources(referring_url_); |
1131 WaitUntilHostHasBeenRequested(startup_url_.host()); | 1270 observer()->WaitUntilHostLookedUp(target_url_); |
1132 WaitUntilHostHasBeenRequested(target_url_.host()); | 1271 |
| 1272 // Verify that both urls were requested by the predictor. Note that the |
| 1273 // startup URL may be requested before the observer attaches itself. |
| 1274 ExpectUrlRequestedFromPredictor(startup_url_); |
| 1275 EXPECT_FALSE(observer()->HostFound(target_url_)); |
1133 } | 1276 } |
1134 | 1277 |
1135 // Flaky on Windows: http://crbug.com/469120 | 1278 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, DnsPrefetch) { |
1136 #if defined(OS_WIN) | 1279 // Navigate once to make sure all initial hostnames are requested. |
1137 #define MAYBE_DnsPrefetch DISABLED_DnsPrefetch | 1280 ui_test_utils::NavigateToURL(browser(), |
1138 #else | 1281 embedded_test_server()->GetURL("/title1.html")); |
1139 #define MAYBE_DnsPrefetch DnsPrefetch | 1282 |
1140 #endif | 1283 size_t hosts_looked_up_before_load = observer()->TotalHostsLookedUp(); |
1141 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, MAYBE_DnsPrefetch) { | 1284 |
1142 int hostnames_requested_before_load = RequestedHostnameCount(); | 1285 ui_test_utils::NavigateToURL(browser(), embedded_test_server()->GetURL( |
1143 ui_test_utils::NavigateToURL( | 1286 "/predictor/dns_prefetch.html")); |
1144 browser(), | 1287 observer()->WaitUntilHostLookedUp(GURL(kChromiumUrl)); |
1145 GURL(embedded_test_server()->GetURL("/predictor/dns_prefetch.html"))); | 1288 ASSERT_FALSE(observer()->HasHostBeenLookedUp(GURL(kInvalidLongUrl))); |
1146 WaitUntilHostHasBeenRequested(kChromiumHostname); | 1289 |
1147 ASSERT_FALSE(HasHostBeenRequested(kInvalidLongHostname)); | 1290 EXPECT_FALSE(observer()->HostFound(GURL(kChromiumUrl))); |
1148 ASSERT_EQ(hostnames_requested_before_load + 1, RequestedHostnameCount()); | 1291 ASSERT_EQ(hosts_looked_up_before_load + 1, observer()->TotalHostsLookedUp()); |
1149 } | 1292 } |
1150 | 1293 |
1151 // Tests that preconnect warms up a socket connection to a test server. | 1294 // Tests that preconnect warms up a socket connection to a test server. |
1152 // Note: This test uses a data URI to serve the preconnect hint, to make sure | 1295 // Note: This test uses a data URI to serve the preconnect hint, to make sure |
1153 // that the network stack doesn't just re-use its connection to the test server. | 1296 // that the network stack doesn't just re-use its connection to the test server. |
1154 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PreconnectNonCORS) { | 1297 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PreconnectNonCORS) { |
1155 GURL preconnect_url = embedded_test_server()->base_url(); | 1298 GURL preconnect_url = embedded_test_server()->base_url(); |
1156 std::string preconnect_content = | 1299 std::string preconnect_content = |
1157 "<link rel=\"preconnect\" href=\"" + preconnect_url.spec() + "\">"; | 1300 "<link rel=\"preconnect\" href=\"" + preconnect_url.spec() + "\">"; |
1158 NavigateToDataURLWithContent(preconnect_content); | 1301 NavigateToDataURLWithContent(preconnect_content); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1249 // Second navigation to content with an img. | 1392 // Second navigation to content with an img. |
1250 std::string img_content = | 1393 std::string img_content = |
1251 "<img src=\"" + preconnect_url.spec() + "test.gif\">"; | 1394 "<img src=\"" + preconnect_url.spec() + "test.gif\">"; |
1252 NavigateToDataURLWithContent(img_content); | 1395 NavigateToDataURLWithContent(img_content); |
1253 connection_listener_->WaitUntilFirstConnectionRead(); | 1396 connection_listener_->WaitUntilFirstConnectionRead(); |
1254 EXPECT_EQ(2u, connection_listener_->GetAcceptedSocketCount()); | 1397 EXPECT_EQ(2u, connection_listener_->GetAcceptedSocketCount()); |
1255 EXPECT_EQ(1u, connection_listener_->GetReadSocketCount()); | 1398 EXPECT_EQ(1u, connection_listener_->GetReadSocketCount()); |
1256 } | 1399 } |
1257 | 1400 |
1258 } // namespace chrome_browser_net | 1401 } // namespace chrome_browser_net |
OLD | NEW |