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" |
19 #include "base/synchronization/lock.h" | 20 #include "base/synchronization/lock.h" |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
76 if (request.GetURL().path() != path) | 77 if (request.GetURL().path() != path) |
77 return nullptr; | 78 return nullptr; |
78 std::unique_ptr<net::test_server::BasicHttpResponse> response( | 79 std::unique_ptr<net::test_server::BasicHttpResponse> response( |
79 new net::test_server::BasicHttpResponse); | 80 new net::test_server::BasicHttpResponse); |
80 response->set_code(net::HTTP_MOVED_PERMANENTLY); | 81 response->set_code(net::HTTP_MOVED_PERMANENTLY); |
81 response->AddCustomHeader("Location", redirect_url.spec()); | 82 response->AddCustomHeader("Location", redirect_url.spec()); |
82 return std::move(response); | 83 return std::move(response); |
83 } | 84 } |
84 | 85 |
85 const char kBlinkPreconnectFeature[] = "LinkPreconnect"; | 86 const char kBlinkPreconnectFeature[] = "LinkPreconnect"; |
86 const char kChromiumHostname[] = "chromium.org"; | 87 const char kChromiumHost[] = "http://chromium.org"; |
eroman
2016/05/27 00:56:38
nit: Can you call this a "url" or "origin" now?
Charlie Harrison
2016/05/27 11:55:53
Done.
| |
87 const char kInvalidLongHostname[] = "illegally-long-hostname-over-255-" | 88 const char kInvalidLongHost[] = |
eroman
2016/05/27 00:56:38
same
Charlie Harrison
2016/05/27 11:55:53
Done.
| |
88 "characters-should-not-send-an-ipc-message-to-the-browser-" | 89 "http://" |
89 "0000000000000000000000000000000000000000000000000000000000000000000000000" | 90 "illegally-long-hostname-over-255-characters-should-not-send-an-ipc-" |
90 "0000000000000000000000000000000000000000000000000000000000000000000000000" | 91 "message-to-the-browser-" |
91 "000000000000000000000000000000000000000000000000000000.org"; | 92 "00000000000000000000000000000000000000000000000000000000000000000000000000" |
93 "00000000000000000000000000000000000000000000000000000000000000000000000000" | |
94 "0000000000000000000000000000000000000000000000000000.org"; | |
92 | 95 |
93 // Gets notified by the EmbeddedTestServer on incoming connections being | 96 // Gets notified by the EmbeddedTestServer on incoming connections being |
94 // accepted or read from, keeps track of them and exposes that info to | 97 // accepted or read from, keeps track of them and exposes that info to |
95 // the tests. | 98 // the tests. |
96 // A port being reused is currently considered an error. If a test | 99 // 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 | 100 // needs to verify multiple connections are opened in sequence, that will need |
98 // to be changed. | 101 // to be changed. |
99 class ConnectionListener | 102 class ConnectionListener |
100 : public net::test_server::EmbeddedTestServerConnectionListener { | 103 : public net::test_server::EmbeddedTestServerConnectionListener { |
101 public: | 104 public: |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
238 | 241 |
239 // If |num_accepted_connections_needed_| is non zero, then the object is | 242 // If |num_accepted_connections_needed_| is non zero, then the object is |
240 // waiting for |num_accepted_connections_needed_| sockets to be accepted | 243 // waiting for |num_accepted_connections_needed_| sockets to be accepted |
241 // before quitting the |num_accepted_connections_loop_|. | 244 // before quitting the |num_accepted_connections_loop_|. |
242 size_t num_accepted_connections_needed_; | 245 size_t num_accepted_connections_needed_; |
243 base::RunLoop* num_accepted_connections_loop_; | 246 base::RunLoop* num_accepted_connections_loop_; |
244 | 247 |
245 DISALLOW_COPY_AND_ASSIGN(ConnectionListener); | 248 DISALLOW_COPY_AND_ASSIGN(ConnectionListener); |
246 }; | 249 }; |
247 | 250 |
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* | 251 // This class intercepts URLRequests and responds with the URLRequestJob* |
321 // callback provided by the constructor. Note that the port of the URL must | 252 // callback provided by the constructor. Note that the port of the URL must |
322 // match the port given in the constructor. | 253 // match the port given in the constructor. |
323 class MatchingPortRequestInterceptor : public net::URLRequestInterceptor { | 254 class MatchingPortRequestInterceptor : public net::URLRequestInterceptor { |
324 public: | 255 public: |
325 typedef base::Callback<net::URLRequestJob*(net::URLRequest*, | 256 typedef base::Callback<net::URLRequestJob*(net::URLRequest*, |
326 net::NetworkDelegate*)> | 257 net::NetworkDelegate*)> |
327 CreateJobCallback; | 258 CreateJobCallback; |
328 | 259 |
329 MatchingPortRequestInterceptor( | 260 MatchingPortRequestInterceptor( |
(...skipping 25 matching lines...) Expand all Loading... | |
355 // two. | 286 // two. |
356 class CrossSitePredictorObserver | 287 class CrossSitePredictorObserver |
357 : public chrome_browser_net::PredictorObserver { | 288 : public chrome_browser_net::PredictorObserver { |
358 public: | 289 public: |
359 CrossSitePredictorObserver(const GURL& source_host, | 290 CrossSitePredictorObserver(const GURL& source_host, |
360 const GURL& cross_site_host) | 291 const GURL& cross_site_host) |
361 : source_host_(source_host), | 292 : source_host_(source_host), |
362 cross_site_host_(cross_site_host), | 293 cross_site_host_(cross_site_host), |
363 cross_site_learned_(0), | 294 cross_site_learned_(0), |
364 cross_site_preconnected_(0), | 295 cross_site_preconnected_(0), |
365 same_site_preconnected_(0) {} | 296 same_site_preconnected_(0), |
297 dns_run_loop_(nullptr) {} | |
366 | 298 |
367 void OnPreconnectUrl( | 299 void OnPreconnectUrl( |
368 const GURL& original_url, | 300 const GURL& original_url, |
369 const GURL& first_party_for_cookies, | 301 const GURL& first_party_for_cookies, |
370 chrome_browser_net::UrlInfo::ResolutionMotivation motivation, | 302 chrome_browser_net::UrlInfo::ResolutionMotivation motivation, |
371 int count) override { | 303 int count) override { |
372 base::AutoLock lock(lock_); | 304 base::AutoLock lock(lock_); |
373 if (original_url == cross_site_host_) { | 305 if (original_url == cross_site_host_) { |
374 cross_site_preconnected_ = std::max(cross_site_preconnected_, count); | 306 cross_site_preconnected_ = std::max(cross_site_preconnected_, count); |
375 } else if (original_url == source_host_) { | 307 } else if (original_url == source_host_) { |
(...skipping 19 matching lines...) Expand all Loading... | |
395 // Same site learned. Branch retained for clarity. | 327 // Same site learned. Branch retained for clarity. |
396 } else if (!(referring_url == cross_site_host_ && | 328 } else if (!(referring_url == cross_site_host_ && |
397 target_url == cross_site_host_)) { | 329 target_url == cross_site_host_)) { |
398 ADD_FAILURE() << "Learned " << referring_url << " => " << target_url | 330 ADD_FAILURE() << "Learned " << referring_url << " => " << target_url |
399 << " when should only be learning the source host: " | 331 << " when should only be learning the source host: " |
400 << source_host_ | 332 << source_host_ |
401 << " or the cross site host: " << cross_site_host_; | 333 << " or the cross site host: " << cross_site_host_; |
402 } | 334 } |
403 } | 335 } |
404 | 336 |
337 void OnDnsLookupFinished(const GURL& url, bool found) override { | |
338 base::AutoLock lock(lock_); | |
339 if (found) { | |
340 successful_dns_lookups_.insert(url); | |
341 } else { | |
342 unsuccessful_dns_lookups_.insert(url); | |
343 } | |
344 CheckForWaitingLoop(); | |
345 } | |
346 | |
405 void ResetCounts() { | 347 void ResetCounts() { |
406 base::AutoLock lock(lock_); | 348 base::AutoLock lock(lock_); |
407 cross_site_learned_ = 0; | 349 cross_site_learned_ = 0; |
408 cross_site_preconnected_ = 0; | 350 cross_site_preconnected_ = 0; |
409 same_site_preconnected_ = 0; | 351 same_site_preconnected_ = 0; |
410 } | 352 } |
411 | 353 |
412 int CrossSiteLearned() { | 354 int CrossSiteLearned() { |
413 base::AutoLock lock(lock_); | 355 base::AutoLock lock(lock_); |
414 return cross_site_learned_; | 356 return cross_site_learned_; |
415 } | 357 } |
416 | 358 |
417 int CrossSitePreconnected() { | 359 int CrossSitePreconnected() { |
418 base::AutoLock lock(lock_); | 360 base::AutoLock lock(lock_); |
419 return cross_site_preconnected_; | 361 return cross_site_preconnected_; |
420 } | 362 } |
421 | 363 |
422 int SameSitePreconnected() { | 364 int SameSitePreconnected() { |
423 base::AutoLock lock(lock_); | 365 base::AutoLock lock(lock_); |
424 return same_site_preconnected_; | 366 return same_site_preconnected_; |
425 } | 367 } |
426 | 368 |
369 // Spins a run loop until |url| is added to one of the lookup maps. | |
370 void WaitUntilHostLookedUp(const GURL& url) { | |
371 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
372 base::RunLoop run_loop; | |
373 { | |
374 base::AutoLock lock(lock_); | |
375 DCHECK(waiting_on_dns_.is_empty()); | |
376 DCHECK(!dns_run_loop_); | |
377 waiting_on_dns_ = url; | |
378 dns_run_loop_ = &run_loop; | |
379 CheckForWaitingLoop(); | |
380 } | |
381 run_loop.Run(); | |
382 } | |
383 | |
384 bool HasHostBeenLookedUpLocked(const GURL& url) { | |
385 lock_.AssertAcquired(); | |
386 return successful_dns_lookups_.find(url) != successful_dns_lookups_.end() || | |
eroman
2016/05/27 00:56:38
optional: can use ContainsKey() to simplify the va
Charlie Harrison
2016/05/27 11:55:52
Done.
| |
387 unsuccessful_dns_lookups_.find(url) != | |
388 unsuccessful_dns_lookups_.end(); | |
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" | |
eroman
2016/05/27 00:56:38
nit: add a space at the end of the string.
Charlie Harrison
2016/05/27 11:55:53
Done.
| |
418 << url.spec(); | |
419 return successful_dns_lookups_.find(url) != successful_dns_lookups_.end(); | |
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 predictors |results_| map. This | |
eroman
2016/05/27 00:56:38
nit: predictors --> predictor's
Charlie Harrison
2016/05/27 11:55:52
Done.
| |
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_NE(predictor()->results_.find(url), predictor()->results_.end()); | |
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 goog("http://www.example.test/"); | |
eroman
2016/05/27 00:56:38
probably better to call this "url" -- not actually
Charlie Harrison
2016/05/27 11:55:53
Done.
| |
763 | |
764 // Try to flood the predictor with many concurrent requests. | |
765 network_hints::UrlList names{goog}; | |
766 FloodResolveRequestsOnUIThread(names); | |
767 observer()->WaitUntilHostLookedUp(goog); | |
768 EXPECT_TRUE(observer()->HostFound(goog)); | |
769 ExpectValidPeakPendingLookupsOnUI(1u); | |
770 } | |
771 | |
772 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, ConcurrentLookupTest) { | |
773 DiscardAllResultsOnUIThread(); | |
774 GURL goog("http://www.example.test"), goog2("http://gmail.google.com"), | |
eroman
2016/05/27 00:56:38
same here -- at least for one of them.
Charlie Harrison
2016/05/27 11:55:53
Done.
| |
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{goog, goog3, goog2, goog4, goog}; | |
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(kChromiumHost)); |
1145 GURL(embedded_test_server()->GetURL("/predictor/dns_prefetch.html"))); | 1288 ASSERT_FALSE(observer()->HasHostBeenLookedUp(GURL(kInvalidLongHost))); |
1146 WaitUntilHostHasBeenRequested(kChromiumHostname); | 1289 |
1147 ASSERT_FALSE(HasHostBeenRequested(kInvalidLongHostname)); | 1290 EXPECT_FALSE(observer()->HostFound(GURL(kChromiumHost))); |
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 |