diff options
Diffstat (limited to 'chrome/browser/net')
-rw-r--r-- | chrome/browser/net/preconnect.cc | 29 | ||||
-rw-r--r-- | chrome/browser/net/preconnect.h | 3 | ||||
-rw-r--r-- | chrome/browser/net/predictor.cc | 39 | ||||
-rw-r--r-- | chrome/browser/net/predictor.h | 8 | ||||
-rw-r--r-- | chrome/browser/net/predictor_browsertest.cc | 85 | ||||
-rw-r--r-- | chrome/browser/net/predictor_unittest.cc | 3 |
6 files changed, 133 insertions, 34 deletions
diff --git a/chrome/browser/net/preconnect.cc b/chrome/browser/net/preconnect.cc index dfa91a3..17673c3 100644 --- a/chrome/browser/net/preconnect.cc +++ b/chrome/browser/net/preconnect.cc @@ -8,6 +8,7 @@ #include "base/logging.h" #include "base/metrics/histogram.h" #include "content/public/browser/browser_thread.h" +#include "net/base/load_flags.h" #include "net/http/http_network_session.h" #include "net/http/http_request_info.h" #include "net/http/http_stream_factory.h" @@ -30,20 +31,18 @@ void PreconnectOnUIThread( net::URLRequestContextGetter* getter) { // Prewarm connection to Search URL. BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, + BrowserThread::IO, FROM_HERE, base::Bind(&PreconnectOnIOThread, url, first_party_for_cookies, - motivation, count, make_scoped_refptr(getter))); + motivation, count, make_scoped_refptr(getter), true)); return; } - -void PreconnectOnIOThread( - const GURL& url, - const GURL& first_party_for_cookies, - UrlInfo::ResolutionMotivation motivation, - int count, - net::URLRequestContextGetter* getter) { +void PreconnectOnIOThread(const GURL& url, + const GURL& first_party_for_cookies, + UrlInfo::ResolutionMotivation motivation, + int count, + net::URLRequestContextGetter* getter, + bool allow_credentials) { if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { LOG(DFATAL) << "This must be run only on the IO thread."; return; @@ -71,6 +70,16 @@ void PreconnectOnIOThread( if (delegate->CanEnablePrivacyMode(url, first_party_for_cookies)) request_info.privacy_mode = net::PRIVACY_MODE_ENABLED; + // TODO(yoav): Fix this layering violation, since when credentials are not + // allowed we should turn on a flag indicating that, rather then turn on + // private mode, even if lower layers would treat both the same. + if (!allow_credentials) { + request_info.privacy_mode = net::PRIVACY_MODE_ENABLED; + request_info.load_flags = net::LOAD_DO_NOT_SEND_COOKIES | + net::LOAD_DO_NOT_SAVE_COOKIES | + net::LOAD_DO_NOT_SEND_AUTH_DATA; + } + // Translate the motivation from UrlRequest motivations to HttpRequest // motivations. switch (motivation) { diff --git a/chrome/browser/net/preconnect.h b/chrome/browser/net/preconnect.h index 6e8442c..72718c1 100644 --- a/chrome/browser/net/preconnect.h +++ b/chrome/browser/net/preconnect.h @@ -34,7 +34,8 @@ void PreconnectOnIOThread(const GURL& url, const GURL& first_party_for_cookies, UrlInfo::ResolutionMotivation motivation, int count, - net::URLRequestContextGetter* getter); + net::URLRequestContextGetter* getter, + bool allow_credentials); } // namespace chrome_browser_net diff --git a/chrome/browser/net/predictor.cc b/chrome/browser/net/predictor.cc index d18979a..c435a8c 100644 --- a/chrome/browser/net/predictor.cc +++ b/chrome/browser/net/predictor.cc @@ -87,6 +87,9 @@ const int Predictor::kMaxSpeculativeResolveQueueDelayMs = (kExpectedResolutionTimeMs * Predictor::kTypicalSpeculativeGroupSize) / Predictor::kMaxSpeculativeParallelResolves; +// The default value of the credentials flag when preconnecting. +static bool kAllowCredentialsOnPreconnectByDefault = true; + static int g_max_queueing_delay_ms = Predictor::kMaxSpeculativeResolveQueueDelayMs; static size_t g_max_parallel_resolves = @@ -265,8 +268,9 @@ void Predictor::AnticipateOmniboxUrl(const GURL& url, bool preconnectable) { return; // We've done a preconnect recently. last_omnibox_preconnect_ = now; const int kConnectionsNeeded = 1; - PreconnectUrl( - CanonicalizeUrl(url), GURL(), motivation, kConnectionsNeeded); + PreconnectUrl(CanonicalizeUrl(url), GURL(), motivation, + kAllowCredentialsOnPreconnectByDefault, + kConnectionsNeeded); return; // Skip pre-resolution, since we'll open a connection. } } else { @@ -305,8 +309,8 @@ void Predictor::PreconnectUrlAndSubresources(const GURL& url, UrlInfo::ResolutionMotivation motivation(UrlInfo::EARLY_LOAD_MOTIVATED); const int kConnectionsNeeded = 1; - PreconnectUrl(CanonicalizeUrl(url), first_party_for_cookies, - motivation, kConnectionsNeeded); + PreconnectUrl(CanonicalizeUrl(url), first_party_for_cookies, motivation, + kConnectionsNeeded, kAllowCredentialsOnPreconnectByDefault); PredictFrameSubresources(url.GetWithEmptyPath(), first_party_for_cookies); } @@ -840,19 +844,20 @@ void Predictor::SaveDnsPrefetchStateForNextStartupAndTrim( void Predictor::PreconnectUrl(const GURL& url, const GURL& first_party_for_cookies, UrlInfo::ResolutionMotivation motivation, + bool allow_credentials, int count) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || BrowserThread::CurrentlyOn(BrowserThread::IO)); if (BrowserThread::CurrentlyOn(BrowserThread::IO)) { - PreconnectUrlOnIOThread(url, first_party_for_cookies, motivation, count); + PreconnectUrlOnIOThread(url, first_party_for_cookies, motivation, + allow_credentials, count); } else { BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, - base::Bind(&Predictor::PreconnectUrlOnIOThread, - base::Unretained(this), url, first_party_for_cookies, - motivation, count)); + BrowserThread::IO, FROM_HERE, + base::Bind(&Predictor::PreconnectUrlOnIOThread, base::Unretained(this), + url, first_party_for_cookies, motivation, allow_credentials, + count)); } } @@ -860,6 +865,7 @@ void Predictor::PreconnectUrlOnIOThread( const GURL& original_url, const GURL& first_party_for_cookies, UrlInfo::ResolutionMotivation motivation, + bool allow_credentials, int count) { // Skip the HSTS redirect. GURL url = GetHSTSRedirectOnIOThread(original_url); @@ -869,11 +875,8 @@ void Predictor::PreconnectUrlOnIOThread( url, first_party_for_cookies, motivation, count); } - PreconnectOnIOThread(url, - first_party_for_cookies, - motivation, - count, - url_request_context_getter_.get()); + PreconnectOnIOThread(url, first_party_for_cookies, motivation, count, + url_request_context_getter_.get(), allow_credentials); } void Predictor::PredictFrameSubresources(const GURL& url, @@ -941,7 +944,8 @@ void Predictor::PrepareFrameSubresources(const GURL& original_url, // provide a more carefully estimated preconnection count. if (preconnect_enabled_) { PreconnectUrlOnIOThread(url, first_party_for_cookies, - UrlInfo::SELF_REFERAL_MOTIVATED, 2); + UrlInfo::SELF_REFERAL_MOTIVATED, + kAllowCredentialsOnPreconnectByDefault, 2); } return; } @@ -966,7 +970,8 @@ void Predictor::PrepareFrameSubresources(const GURL& original_url, if (url.host() == future_url->first.host()) ++count; PreconnectUrlOnIOThread(future_url->first, first_party_for_cookies, - motivation, count); + motivation, + kAllowCredentialsOnPreconnectByDefault, count); } else if (connection_expectation > kDNSPreresolutionWorthyExpectedValue) { evalution = PRERESOLUTION; future_url->second.preresolution_increment(); diff --git a/chrome/browser/net/predictor.h b/chrome/browser/net/predictor.h index d1983e3..8601ff0 100644 --- a/chrome/browser/net/predictor.h +++ b/chrome/browser/net/predictor.h @@ -242,12 +242,16 @@ class Predictor { // May be called from either the IO or UI thread and will PostTask // to the IO thread if necessary. - void PreconnectUrl(const GURL& url, const GURL& first_party_for_cookies, - UrlInfo::ResolutionMotivation motivation, int count); + void PreconnectUrl(const GURL& url, + const GURL& first_party_for_cookies, + UrlInfo::ResolutionMotivation motivation, + bool allow_credentials, + int count); void PreconnectUrlOnIOThread(const GURL& url, const GURL& first_party_for_cookies, UrlInfo::ResolutionMotivation motivation, + bool allow_credentials, int count); // ------------- End IO thread methods. diff --git a/chrome/browser/net/predictor_browsertest.cc b/chrome/browser/net/predictor_browsertest.cc index c4ebc55..98cbab1 100644 --- a/chrome/browser/net/predictor_browsertest.cc +++ b/chrome/browser/net/predictor_browsertest.cc @@ -103,8 +103,16 @@ class ConnectionListener private: static uint16_t GetPort( const net::test_server::StreamListenSocket& connection) { + // Get the remote port of the peer, since the local port will always be the + // port the test server is listening on. This isn't strictly correct - it's + // possible for multiple peers to connect with the same remote port but + // different remote IPs - but the tests here assume that connections to the + // test server (running on localhost) will always come from localhost, and + // thus the peer port is all thats needed to distinguish two connections. + // This also would be problematic if the OS reused ports, but that's not + // something to worry about for these tests. net::IPEndPoint address; - EXPECT_EQ(net::OK, connection.GetLocalAddress(&address)); + EXPECT_EQ(net::OK, connection.GetPeerAddress(&address)); return address.port(); } @@ -350,7 +358,7 @@ IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, MAYBE_DnsPrefetch) { // Tests that preconnect warms up a socket connection to a test server. // Note: This test uses a data URI to serve the preconnect hint, to make sure // that the network stack doesn't just re-use its connection to the test server. -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, Preconnect) { +IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PreconnectNonCORS) { GURL preconnect_url = embedded_test_server()->base_url(); std::string preconnect_content = "<link rel=\"preconnect\" href=\"" + preconnect_url.spec() + "\">"; @@ -364,7 +372,7 @@ IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, Preconnect) { // and that that socket is later used when fetching a resource. // Note: This test uses a data URI to serve the preconnect hint, to make sure // that the network stack doesn't just re-use its connection to the test server. -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PreconnectAndUse) { +IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PreconnectAndFetchNonCORS) { GURL preconnect_url = embedded_test_server()->base_url(); // First navigation to content with a preconnect hint. std::string preconnect_content = @@ -383,5 +391,76 @@ IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PreconnectAndUse) { EXPECT_EQ(1u, connection_listener_->GetReadSocketCount()); } +// Tests that preconnect warms up a CORS connection to a test +// server, and that socket is later used when fetching a CORS resource. +// Note: This test uses a data URI to serve the preconnect hint, to make sure +// that the network stack doesn't just re-use its connection to the test server. +IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PreconnectAndFetchCORS) { + GURL preconnect_url = embedded_test_server()->base_url(); + // First navigation to content with a preconnect hint. + std::string preconnect_content = "<link rel=\"preconnect\" href=\"" + + preconnect_url.spec() + "\" crossorigin>"; + NavigateToDataURLWithContent(preconnect_content); + connection_listener_->WaitUntilFirstConnectionAccepted(); + EXPECT_EQ(1u, connection_listener_->GetAcceptedSocketCount()); + EXPECT_EQ(0u, connection_listener_->GetReadSocketCount()); + + // Second navigation to content with a font. + std::string font_content = "<script>var font = new FontFace('FontA', 'url(" + + preconnect_url.spec() + + "test.woff2)');font.load();</script>"; + NavigateToDataURLWithContent(font_content); + connection_listener_->WaitUntilFirstConnectionRead(); + EXPECT_EQ(1u, connection_listener_->GetAcceptedSocketCount()); + EXPECT_EQ(1u, connection_listener_->GetReadSocketCount()); +} + +// Tests that preconnect warms up a non-CORS connection to a test +// server, but that socket is not used when fetching a CORS resource. +// Note: This test uses a data URI to serve the preconnect hint, to make sure +// that the network stack doesn't just re-use its connection to the test server. +IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PreconnectNonCORSAndFetchCORS) { + GURL preconnect_url = embedded_test_server()->base_url(); + // First navigation to content with a preconnect hint. + std::string preconnect_content = + "<link rel=\"preconnect\" href=\"" + preconnect_url.spec() + "\">"; + NavigateToDataURLWithContent(preconnect_content); + connection_listener_->WaitUntilFirstConnectionAccepted(); + EXPECT_EQ(1u, connection_listener_->GetAcceptedSocketCount()); + EXPECT_EQ(0u, connection_listener_->GetReadSocketCount()); + + // Second navigation to content with a font. + std::string font_content = "<script>var font = new FontFace('FontA', 'url(" + + preconnect_url.spec() + + "test.woff2)');font.load();</script>"; + NavigateToDataURLWithContent(font_content); + connection_listener_->WaitUntilFirstConnectionRead(); + EXPECT_EQ(2u, connection_listener_->GetAcceptedSocketCount()); + EXPECT_EQ(1u, connection_listener_->GetReadSocketCount()); +} + +// Tests that preconnect warms up a CORS connection to a test server, +// but that socket is not used when fetching a non-CORS resource. +// Note: This test uses a data URI to serve the preconnect hint, to make sure +// that the network stack doesn't just re-use its connection to the test server. +IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PreconnectCORSAndFetchNonCORS) { + GURL preconnect_url = embedded_test_server()->base_url(); + // First navigation to content with a preconnect hint. + std::string preconnect_content = "<link rel=\"preconnect\" href=\"" + + preconnect_url.spec() + "\" crossorigin>"; + NavigateToDataURLWithContent(preconnect_content); + connection_listener_->WaitUntilFirstConnectionAccepted(); + EXPECT_EQ(1u, connection_listener_->GetAcceptedSocketCount()); + EXPECT_EQ(0u, connection_listener_->GetReadSocketCount()); + + // Second navigation to content with an img. + std::string img_content = + "<img src=\"" + preconnect_url.spec() + "test.gif\">"; + NavigateToDataURLWithContent(img_content); + connection_listener_->WaitUntilFirstConnectionRead(); + EXPECT_EQ(2u, connection_listener_->GetAcceptedSocketCount()); + EXPECT_EQ(1u, connection_listener_->GetReadSocketCount()); +} + } // namespace chrome_browser_net diff --git a/chrome/browser/net/predictor_unittest.cc b/chrome/browser/net/predictor_unittest.cc index 76c7333..61460ae 100644 --- a/chrome/browser/net/predictor_unittest.cc +++ b/chrome/browser/net/predictor_unittest.cc @@ -731,7 +731,8 @@ TEST_F(PredictorTest, HSTSRedirect) { predictor.SetObserver(&observer); predictor.SetTransportSecurityState(&state); - predictor.PreconnectUrl(kHttpUrl, GURL(), UrlInfo::OMNIBOX_MOTIVATED, 2); + predictor.PreconnectUrl(kHttpUrl, GURL(), UrlInfo::OMNIBOX_MOTIVATED, true, + 2); ASSERT_EQ(1u, observer.preconnected_urls_.size()); EXPECT_EQ(kHttpsUrl, observer.preconnected_urls_[0]); |