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

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

Issue 1857383002: Refactor net predictor to use ResourceThrottles (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix test Created 4 years, 7 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 <algorithm> 8 #include <algorithm>
9 #include <memory> 9 #include <memory>
10 10
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 net::NetworkDelegate* delegate) { 60 net::NetworkDelegate* delegate) {
61 const char kPlainTextHeaders[] = 61 const char kPlainTextHeaders[] =
62 "HTTP/1.1 200 OK\n" 62 "HTTP/1.1 200 OK\n"
63 "Content-Type: text/plain\n" 63 "Content-Type: text/plain\n"
64 "Access-Control-Allow-Origin: *\n" 64 "Access-Control-Allow-Origin: *\n"
65 "\n"; 65 "\n";
66 return new net::URLRequestTestJob(request, delegate, kPlainTextHeaders, "", 66 return new net::URLRequestTestJob(request, delegate, kPlainTextHeaders, "",
67 true); 67 true);
68 } 68 }
69 69
70 net::URLRequestJob* CreateRedirectRequestJob(std::string location,
71 net::URLRequest* request,
72 net::NetworkDelegate* delegate) {
73 char kPlainTextHeaders[] =
74 "HTTP/1.1 302 \n"
75 "Location: %s\n"
76 "Access-Control-Allow-Origin: *\n"
77 "\n";
78 return new net::URLRequestTestJob(
79 request, delegate,
80 base::StringPrintf(kPlainTextHeaders, location.c_str()), "", true);
81 }
82
70 // Override the test server to redirect requests matching some path. This is 83 // Override the test server to redirect requests matching some path. This is
71 // used because the predictor only learns simple redirects with a path of "/" 84 // used because the predictor only learns simple redirects with a path of "/"
72 std::unique_ptr<net::test_server::HttpResponse> RedirectForPathHandler( 85 std::unique_ptr<net::test_server::HttpResponse> RedirectForPathHandler(
73 const std::string& path, 86 const std::string& path,
74 const GURL& redirect_url, 87 const GURL& redirect_url,
75 const net::test_server::HttpRequest& request) { 88 const net::test_server::HttpRequest& request) {
76 if (request.GetURL().path() != path) 89 if (request.GetURL().path() != path)
77 return nullptr; 90 return nullptr;
78 std::unique_ptr<net::test_server::BasicHttpResponse> response( 91 std::unique_ptr<net::test_server::BasicHttpResponse> response(
79 new net::test_server::BasicHttpResponse); 92 new net::test_server::BasicHttpResponse);
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 // two. 368 // two.
356 class CrossSitePredictorObserver 369 class CrossSitePredictorObserver
357 : public chrome_browser_net::PredictorObserver { 370 : public chrome_browser_net::PredictorObserver {
358 public: 371 public:
359 CrossSitePredictorObserver(const GURL& source_host, 372 CrossSitePredictorObserver(const GURL& source_host,
360 const GURL& cross_site_host) 373 const GURL& cross_site_host)
361 : source_host_(source_host), 374 : source_host_(source_host),
362 cross_site_host_(cross_site_host), 375 cross_site_host_(cross_site_host),
363 cross_site_learned_(0), 376 cross_site_learned_(0),
364 cross_site_preconnected_(0), 377 cross_site_preconnected_(0),
365 same_site_preconnected_(0) {} 378 same_site_preconnected_(0),
379 strict_(true) {}
366 380
367 void OnPreconnectUrl( 381 void OnPreconnectUrl(
368 const GURL& original_url, 382 const GURL& original_url,
369 const GURL& first_party_for_cookies, 383 const GURL& first_party_for_cookies,
370 chrome_browser_net::UrlInfo::ResolutionMotivation motivation, 384 chrome_browser_net::UrlInfo::ResolutionMotivation motivation,
371 int count) override { 385 int count) override {
372 base::AutoLock lock(lock_); 386 base::AutoLock lock(lock_);
373 if (original_url == cross_site_host_) { 387 if (original_url == cross_site_host_) {
374 cross_site_preconnected_ = std::max(cross_site_preconnected_, count); 388 cross_site_preconnected_ = std::max(cross_site_preconnected_, count);
375 } else if (original_url == source_host_) { 389 } else if (original_url == source_host_) {
376 same_site_preconnected_ = std::max(same_site_preconnected_, count); 390 same_site_preconnected_ = std::max(same_site_preconnected_, count);
377 } else { 391 } else if (strict_) {
378 ADD_FAILURE() << "Preconnected " << original_url 392 ADD_FAILURE() << "Preconnected " << original_url
379 << " when should only be preconnecting the source host: " 393 << " when should only be preconnecting the source host: "
380 << source_host_ 394 << source_host_
381 << " or the cross site host: " << cross_site_host_; 395 << " or the cross site host: " << cross_site_host_;
382 } 396 }
383 } 397 }
384 398
385 void OnLearnFromNavigation(const GURL& referring_url, 399 void OnLearnFromNavigation(const GURL& referring_url,
386 const GURL& target_url) override { 400 const GURL& target_url) override {
387 base::AutoLock lock(lock_); 401 base::AutoLock lock(lock_);
388 // There are three possibilities: 402 // There are three possibilities:
389 // source => target 403 // source => target
390 // source => source 404 // source => source
391 // target => target 405 // target => target
392 if (referring_url == source_host_ && target_url == cross_site_host_) { 406 if (referring_url == source_host_ && target_url == cross_site_host_) {
393 cross_site_learned_++; 407 cross_site_learned_++;
394 } else if (referring_url == source_host_ && target_url == source_host_) { 408 } else if (referring_url == source_host_ && target_url == source_host_) {
395 // Same site learned. Branch retained for clarity. 409 // Same site learned. Branch retained for clarity.
396 } else if (!(referring_url == cross_site_host_ && 410 } else if (strict_ &&
411 !(referring_url == cross_site_host_ &&
397 target_url == cross_site_host_)) { 412 target_url == cross_site_host_)) {
398 ADD_FAILURE() << "Learned " << referring_url << " => " << target_url 413 ADD_FAILURE() << "Learned " << referring_url << " => " << target_url
399 << " when should only be learning the source host: " 414 << " when should only be learning the source host: "
400 << source_host_ 415 << source_host_
401 << " or the cross site host: " << cross_site_host_; 416 << " or the cross site host: " << cross_site_host_;
402 } 417 }
403 } 418 }
404 419
405 void ResetCounts() { 420 void ResetCounts() {
406 base::AutoLock lock(lock_); 421 base::AutoLock lock(lock_);
(...skipping 10 matching lines...) Expand all
417 int CrossSitePreconnected() { 432 int CrossSitePreconnected() {
418 base::AutoLock lock(lock_); 433 base::AutoLock lock(lock_);
419 return cross_site_preconnected_; 434 return cross_site_preconnected_;
420 } 435 }
421 436
422 int SameSitePreconnected() { 437 int SameSitePreconnected() {
423 base::AutoLock lock(lock_); 438 base::AutoLock lock(lock_);
424 return same_site_preconnected_; 439 return same_site_preconnected_;
425 } 440 }
426 441
442 // Optionally allows the object to observe preconnects / learning from other
443 // hosts.
444 void SetStrict(bool strict) {
445 base::AutoLock lock(lock_);
446 strict_ = strict;
447 }
448
427 private: 449 private:
428 const GURL source_host_; 450 const GURL source_host_;
429 const GURL cross_site_host_; 451 const GURL cross_site_host_;
430 452
431 // Protects all following members. They are read and updated from different 453 // Protects all following members. They are read and updated from different
432 // threads. 454 // threads.
433 base::Lock lock_; 455 base::Lock lock_;
434 456
435 int cross_site_learned_; 457 int cross_site_learned_;
436 int cross_site_preconnected_; 458 int cross_site_preconnected_;
437 int same_site_preconnected_; 459 int same_site_preconnected_;
438 460
461 // This member can be set to optionally allow url learning other than from
462 // source => source, source => target, or target => target. It will also allow
463 // preconnects to other hosts.
464 bool strict_;
465
439 DISALLOW_COPY_AND_ASSIGN(CrossSitePredictorObserver); 466 DISALLOW_COPY_AND_ASSIGN(CrossSitePredictorObserver);
440 }; 467 };
441 468
442 } // namespace 469 } // namespace
443 470
444 namespace chrome_browser_net { 471 namespace chrome_browser_net {
445 472
446 class PredictorBrowserTest : public InProcessBrowserTest { 473 class PredictorBrowserTest : public InProcessBrowserTest {
447 public: 474 public:
448 PredictorBrowserTest() 475 PredictorBrowserTest()
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 embedded_test_server()->RegisterRequestHandler( 511 embedded_test_server()->RegisterRequestHandler(
485 base::Bind(&RedirectForPathHandler, "/", 512 base::Bind(&RedirectForPathHandler, "/",
486 cross_site_test_server()->GetURL("/title1.html"))); 513 cross_site_test_server()->GetURL("/title1.html")));
487 514
488 predictor()->SetPreconnectEnabledForTest(true); 515 predictor()->SetPreconnectEnabledForTest(true);
489 InstallPredictorObserver(embedded_test_server()->base_url(), 516 InstallPredictorObserver(embedded_test_server()->base_url(),
490 cross_site_test_server()->base_url()); 517 cross_site_test_server()->base_url());
491 StartInterceptingCrossSiteOnUI(); 518 StartInterceptingCrossSiteOnUI();
492 } 519 }
493 520
494 // Intercepts all requests to the specified host and returns a response with 521 static void StartInterceptingHostWithCreateJobCallback(
495 // an empty body. Needed to prevent requests from actually going to the test 522 const GURL& url,
496 // server, to avoid any races related to socket accounting. Note, the 523 const MatchingPortRequestInterceptor::CreateJobCallback& callback) {
497 // interceptor also looks at the port, to differentiate between the
498 // two test servers.
499 static void StartInterceptingHost(const GURL& url) {
500 DCHECK_CURRENTLY_ON(BrowserThread::IO); 524 DCHECK_CURRENTLY_ON(BrowserThread::IO);
501 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor( 525 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
502 url.scheme(), url.host(), 526 url.scheme(), url.host(),
503 base::WrapUnique(new MatchingPortRequestInterceptor( 527 base::WrapUnique(new MatchingPortRequestInterceptor(
504 url.EffectiveIntPort(), base::Bind(&CreateEmptyBodyRequestJob)))); 528 url.EffectiveIntPort(), callback)));
505 } 529 }
506 530
507 static void StopInterceptingHost(const GURL& url) { 531 static void StopInterceptingHost(const GURL& url) {
508 DCHECK_CURRENTLY_ON(BrowserThread::IO); 532 DCHECK_CURRENTLY_ON(BrowserThread::IO);
509 net::URLRequestFilter::GetInstance()->RemoveHostnameHandler(url.scheme(), 533 net::URLRequestFilter::GetInstance()->RemoveHostnameHandler(url.scheme(),
510 url.host()); 534 url.host());
511 } 535 }
512 536
537 // Intercepts all requests to the specified host and returns a response with
538 // an empty body. Needed to prevent requests from actually going to the test
539 // server, to avoid any races related to socket accounting. Note, the
540 // interceptor also looks at the port, to differentiate between the
541 // two test servers.
513 void StartInterceptingCrossSiteOnUI() { 542 void StartInterceptingCrossSiteOnUI() {
514 DCHECK_CURRENTLY_ON(BrowserThread::UI); 543 DCHECK_CURRENTLY_ON(BrowserThread::UI);
515 content::BrowserThread::PostTask( 544 content::BrowserThread::PostTask(
516 content::BrowserThread::IO, FROM_HERE, 545 content::BrowserThread::IO, FROM_HERE,
517 base::Bind(&PredictorBrowserTest::StartInterceptingHost, 546 base::Bind(
518 cross_site_test_server()->base_url())); 547 &PredictorBrowserTest::StartInterceptingHostWithCreateJobCallback,
548 cross_site_test_server()->base_url(),
549 base::Bind(&CreateEmptyBodyRequestJob)));
519 } 550 }
520 551
521 void StopInterceptingCrossSiteOnUI() { 552 void StopInterceptingCrossSiteOnUI() {
522 DCHECK_CURRENTLY_ON(BrowserThread::UI); 553 DCHECK_CURRENTLY_ON(BrowserThread::UI);
523 content::BrowserThread::PostTask( 554 content::BrowserThread::PostTask(
524 content::BrowserThread::IO, FROM_HERE, 555 content::BrowserThread::IO, FROM_HERE,
525 base::Bind(&PredictorBrowserTest::StopInterceptingHost, 556 base::Bind(&PredictorBrowserTest::StopInterceptingHost,
526 cross_site_test_server()->base_url())); 557 cross_site_test_server()->base_url()));
527 } 558 }
528 559
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
770 // embedded test servers have the same host_piece, an extra preconnect is 801 // embedded test servers have the same host_piece, an extra preconnect is
771 // issued. This results in ceil(2.33) + 1 = 4 preconnects. 802 // issued. This results in ceil(2.33) + 1 = 4 preconnects.
772 ui_test_utils::NavigateToURL(browser(), 803 ui_test_utils::NavigateToURL(browser(),
773 embedded_test_server()->GetURL("/title1.html")); 804 embedded_test_server()->GetURL("/title1.html"));
774 // Just check that predictor has initiated preconnects to the cross site test 805 // Just check that predictor has initiated preconnects to the cross site test
775 // server. It's tricky to reset the connections to the test server, and 806 // server. It's tricky to reset the connections to the test server, and
776 // sockets can be reused. 807 // sockets can be reused.
777 EXPECT_EQ(4, observer()->CrossSitePreconnected()); 808 EXPECT_EQ(4, observer()->CrossSitePreconnected());
778 } 809 }
779 810
811 // 1. Navigate to A.com learning B.com
812 // 2. Navigate to B.com with subresource from C.com redirecting to A.com.
813 // 3. Assert that the redirect does not cause us to preconnect to B.com (via
814 // A.com).
815 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, DontPredictBasedOnSubresources) {
816 GURL redirector_url = GURL("http://redirector.com");
817
818 NavigateToCrossSiteHtmlUrl(1 /* num_cors */, "" /* file_suffix */);
819 EXPECT_EQ(1, observer()->CrossSiteLearned());
820 EXPECT_EQ(0, observer()->CrossSitePreconnected());
821
822 EXPECT_EQ(0u, cross_site_connection_listener_->GetAcceptedSocketCount());
823
824 // Stop intercepting so that the test can actually navigate to the cross site
825 // server.
826 StopInterceptingCrossSiteOnUI();
827
828 // All requests with the redirector url as base url should redirect to the
829 // embedded_test_server_.
830 content::BrowserThread::PostTask(
831 content::BrowserThread::IO, FROM_HERE,
832 base::Bind(
833 &PredictorBrowserTest::StartInterceptingHostWithCreateJobCallback,
834 redirector_url,
835 base::Bind(
836 &CreateRedirectRequestJob,
837 embedded_test_server()->GetURL("/predictor/empty.js").spec())));
838
839 // Reduce the strictness, because the below logic causes the predictor to
840 // learn cross_site_test_server_ => redirector, as well as
841 // cross_site_test_server_ => embedded_test_server_ (via referrer header).
842 observer()->SetStrict(false);
843
844 GURL redirecting_url = cross_site_test_server()->GetURL(base::StringPrintf(
mmenke 2016/05/25 18:16:04 The URL doesn't redirect, it requests a subresourc
Charlie Harrison 2016/05/25 18:45:15 Done.
845 "/predictor/"
846 "predictor_cross_site.html?subresourceHost=%s&numCORSResources=1",
847 redirector_url.spec().c_str()));
848 ui_test_utils::NavigateToURL(browser(), redirecting_url);
849 bool result = false;
850
851 int navigation_preconnects = observer()->CrossSitePreconnected();
mmenke 2016/05/25 18:16:04 Should we call WaitForAcceptedConnectionsOnUI? Lo
Charlie Harrison 2016/05/25 18:45:15 I don't think we should here. We stopped blocking
852 EXPECT_EQ(2, navigation_preconnects);
853
854 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
855 browser()->tab_strip_model()->GetActiveWebContents(),
856 "startFetchesAndWaitForReply()", &result));
857 EXPECT_TRUE(result);
858
859 // The number of preconnects should not increase. Note that the predictor
860 // would preconnect 4 sockets if it were doing so based on learning.
861 EXPECT_EQ(navigation_preconnects, observer()->CrossSitePreconnected());
862 }
863
864 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PredictBasedOnSubframeRedirect) {
865 // A test server is needed here because data url navigations with redirect
866 // interceptors don't interact well with the ResourceTiming API.
867 // TODO(csharrison): Possibly this is a bug in either net or Blink, and it
868 // might be worthwhile to investigate.
869 std::unique_ptr<net::EmbeddedTestServer> redirector =
870 base::WrapUnique(new net::EmbeddedTestServer());
871 ASSERT_TRUE(redirector->Start());
872
873 NavigateToCrossSiteHtmlUrl(1 /* num_cors */, "" /* file_suffix */);
874 EXPECT_EQ(1, observer()->CrossSiteLearned());
875 EXPECT_EQ(0u, cross_site_connection_listener_->GetAcceptedSocketCount());
876
877 redirector->RegisterRequestHandler(
878 base::Bind(&RedirectForPathHandler, "/",
879 embedded_test_server()->GetURL("/title1.html")));
880
881 // Note that the observer will see preconnects to the redirector, and the
882 // predictor will learn redirector->embedded_test_server.
883 observer()->SetStrict(false);
884
885 NavigateToDataURLWithContent(base::StringPrintf(
886 "<iframe src='%s'></iframe>", redirector->base_url().spec().c_str()));
887
mmenke 2016/05/25 18:16:04 WaitForAcceptedConnectionsOnUI?
Charlie Harrison 2016/05/25 18:45:15 We do the check after checking observer()->CrossSi
888 EXPECT_EQ(4, observer()->CrossSitePreconnected());
889 cross_site_connection_listener_->WaitForAcceptedConnectionsOnUI(4u);
890 }
891
780 // Expect that the predictor correctly predicts subframe navigations. 892 // Expect that the predictor correctly predicts subframe navigations.
781 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, SubframeCrossSitePrediction) { 893 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, SubframeCrossSitePrediction) {
782 ui_test_utils::NavigateToURL( 894 ui_test_utils::NavigateToURL(
783 browser(), embedded_test_server()->GetURL( 895 browser(), embedded_test_server()->GetURL(
784 "/predictor/predictor_cross_site_subframe_nav.html")); 896 "/predictor/predictor_cross_site_subframe_nav.html"));
785 bool result = false; 897 bool result = false;
786 EXPECT_TRUE(content::ExecuteScriptAndExtractBool( 898 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
787 browser()->tab_strip_model()->GetActiveWebContents(), 899 browser()->tab_strip_model()->GetActiveWebContents(),
788 base::StringPrintf( 900 base::StringPrintf(
789 "navigateSubframe('%s')", 901 "navigateSubframe('%s')",
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after
1249 // Second navigation to content with an img. 1361 // Second navigation to content with an img.
1250 std::string img_content = 1362 std::string img_content =
1251 "<img src=\"" + preconnect_url.spec() + "test.gif\">"; 1363 "<img src=\"" + preconnect_url.spec() + "test.gif\">";
1252 NavigateToDataURLWithContent(img_content); 1364 NavigateToDataURLWithContent(img_content);
1253 connection_listener_->WaitUntilFirstConnectionRead(); 1365 connection_listener_->WaitUntilFirstConnectionRead();
1254 EXPECT_EQ(2u, connection_listener_->GetAcceptedSocketCount()); 1366 EXPECT_EQ(2u, connection_listener_->GetAcceptedSocketCount());
1255 EXPECT_EQ(1u, connection_listener_->GetReadSocketCount()); 1367 EXPECT_EQ(1u, connection_listener_->GetReadSocketCount());
1256 } 1368 }
1257 1369
1258 } // namespace chrome_browser_net 1370 } // namespace chrome_browser_net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698