diff options
author | Ben Murdoch <benm@google.com> | 2011-01-07 14:18:56 +0000 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-01-11 10:23:13 +0000 |
commit | 201ade2fbba22bfb27ae029f4d23fca6ded109a0 (patch) | |
tree | b793f4ed916f73cf18357ea467ff3deb5ffb5b52 /net/http | |
parent | d8c4c37a7d0961944bfdfaa117d5c68c8e129c97 (diff) | |
download | external_chromium-201ade2fbba22bfb27ae029f4d23fca6ded109a0.zip external_chromium-201ade2fbba22bfb27ae029f4d23fca6ded109a0.tar.gz external_chromium-201ade2fbba22bfb27ae029f4d23fca6ded109a0.tar.bz2 |
Merge chromium at 9.0.597.55: Initial merge by git.
Change-Id: Id686a88437441ec7e17abb3328a404c7b6c3c6ad
Diffstat (limited to 'net/http')
-rw-r--r-- | net/http/http_auth_handler_digest_unittest.cc | 161 | ||||
-rw-r--r-- | net/http/http_cache.cc | 4 | ||||
-rw-r--r-- | net/http/http_cache.h | 2 | ||||
-rw-r--r-- | net/http/http_cache_transaction.cc | 9 | ||||
-rw-r--r-- | net/http/http_cache_transaction.h | 1 | ||||
-rw-r--r-- | net/http/http_cache_unittest.cc | 33 | ||||
-rw-r--r-- | net/http/http_network_layer.cc | 9 | ||||
-rw-r--r-- | net/http/http_network_layer.h | 5 | ||||
-rw-r--r-- | net/http/http_network_layer_unittest.cc | 3 | ||||
-rw-r--r-- | net/http/http_network_session.cc | 3 | ||||
-rw-r--r-- | net/http/http_network_session.h | 6 | ||||
-rw-r--r-- | net/http/http_network_transaction.cc | 53 | ||||
-rw-r--r-- | net/http/http_network_transaction_unittest.cc | 3 | ||||
-rw-r--r-- | net/http/http_proxy_client_socket_pool.cc | 3 | ||||
-rw-r--r-- | net/http/http_proxy_client_socket_pool_unittest.cc | 2 | ||||
-rw-r--r-- | net/http/http_request_info.h | 9 | ||||
-rw-r--r-- | net/http/http_response_body_drainer_unittest.cc | 5 | ||||
-rw-r--r-- | net/http/http_stream_factory_unittest.cc | 3 | ||||
-rw-r--r-- | net/http/http_stream_request.cc | 7 | ||||
-rw-r--r-- | net/http/stream_factory.h | 3 |
20 files changed, 277 insertions, 47 deletions
diff --git a/net/http/http_auth_handler_digest_unittest.cc b/net/http/http_auth_handler_digest_unittest.cc index ff37e99..9338bca 100644 --- a/net/http/http_auth_handler_digest_unittest.cc +++ b/net/http/http_auth_handler_digest_unittest.cc @@ -8,7 +8,9 @@ #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "net/base/net_errors.h" +#include "net/base/test_completion_callback.h" #include "net/http/http_auth_handler_digest.h" +#include "net/http/http_request_info.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { @@ -291,6 +293,10 @@ TEST(HttpAuthHandlerDigestTest, ParseChallenge) { EXPECT_EQ(tests[i].parsed_stale, digest->stale_); EXPECT_EQ(tests[i].parsed_algorithm, digest->algorithm_); EXPECT_EQ(tests[i].parsed_qop, digest->qop_); + EXPECT_TRUE(handler->encrypts_identity()); + EXPECT_FALSE(handler->is_connection_based()); + EXPECT_TRUE(handler->NeedsIdentity()); + EXPECT_FALSE(handler->AllowsDefaultCredentials()); } } @@ -482,4 +488,159 @@ TEST(HttpAuthHandlerDigest, HandleAnotherChallenge) { handler->HandleAnotherChallenge(&tok_stale_false)); } +namespace { + +const char* const kSimpleChallenge = + "Digest realm=\"Oblivion\", nonce=\"nonce-value\""; + +// RespondToChallenge creates an HttpAuthHandlerDigest for the specified +// |challenge|, and generates a response to the challenge which is returned in +// |token|. +// +// The return value is an error string - an empty string indicates no errors. +// +// If |target| is HttpAuth::AUTH_PROXY, then |proxy_name| specifies the source +// of the |challenge|. Otherwise, the scheme and host and port of |request_url| +// indicates the origin of the challenge. +std::string RespondToChallenge(HttpAuth::Target target, + const std::string& proxy_name, + const std::string& request_url, + const std::string& challenge, + std::string* token) { + // Input validation. + DCHECK(token); + DCHECK(target != HttpAuth::AUTH_PROXY || !proxy_name.empty()); + DCHECK(!request_url.empty()); + DCHECK(!challenge.empty()); + + token->clear(); + scoped_ptr<HttpAuthHandlerDigest::Factory> factory( + new HttpAuthHandlerDigest::Factory()); + HttpAuthHandlerDigest::NonceGenerator* nonce_generator = + new HttpAuthHandlerDigest::FixedNonceGenerator("client_nonce"); + factory->set_nonce_generator(nonce_generator); + scoped_ptr<HttpAuthHandler> handler; + + // Create a handler for a particular challenge. + GURL url_origin(target == HttpAuth::AUTH_SERVER ? request_url : proxy_name); + int rv_create = factory->CreateAuthHandlerFromString( + challenge, target, url_origin.GetOrigin(), BoundNetLog(), &handler); + if (rv_create != OK || handler.get() == NULL) + return "Unable to create auth handler."; + + // Create a token in response to the challenge. + // NOTE: HttpAuthHandlerDigest's implementation of GenerateAuthToken always + // completes synchronously. That's why this test can get away with a + // TestCompletionCallback without an IO thread. + TestCompletionCallback callback; + scoped_ptr<HttpRequestInfo> request(new HttpRequestInfo()); + request->url = GURL(request_url); + const string16 kFoo = ASCIIToUTF16("foo"); + const string16 kBar = ASCIIToUTF16("bar"); + int rv_generate = handler->GenerateAuthToken( + &kFoo, &kBar, request.get(), &callback, token); + if (rv_generate != OK) + return "Problems generating auth token"; + + // The token was correctly generated and is returned in |token|. + return std::string(); +} + +} // namespace + +TEST(HttpAuthHandlerDigest, RespondToServerChallenge) { + std::string auth_token; + std::string error_text = RespondToChallenge( + HttpAuth::AUTH_SERVER, + std::string(), + "http://www.example.com/path/to/resource", + kSimpleChallenge, + &auth_token); + EXPECT_EQ("", error_text); + EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", " + "nonce=\"nonce-value\", uri=\"/path/to/resource\", " + "response=\"6779f90bd0d658f937c1af967614fe84\"", + auth_token); +} + +TEST(HttpAuthHandlerDigest, RespondToHttpsServerChallenge) { + std::string auth_token; + std::string error_text = RespondToChallenge( + HttpAuth::AUTH_SERVER, + std::string(), + "https://www.example.com/path/to/resource", + kSimpleChallenge, + &auth_token); + EXPECT_EQ("", error_text); + EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", " + "nonce=\"nonce-value\", uri=\"/path/to/resource\", " + "response=\"6779f90bd0d658f937c1af967614fe84\"", + auth_token); +} + +TEST(HttpAuthHandlerDigest, RespondToProxyChallenge) { + std::string auth_token; + std::string error_text = RespondToChallenge( + HttpAuth::AUTH_PROXY, + "http://proxy.intranet.corp.com:3128", + "http://www.example.com/path/to/resource", + kSimpleChallenge, + &auth_token); + EXPECT_EQ("", error_text); + EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", " + "nonce=\"nonce-value\", uri=\"/path/to/resource\", " + "response=\"6779f90bd0d658f937c1af967614fe84\"", + auth_token); +} + +TEST(HttpAuthHandlerDigest, RespondToProxyChallengeHttps) { + std::string auth_token; + std::string error_text = RespondToChallenge( + HttpAuth::AUTH_PROXY, + "http://proxy.intranet.corp.com:3128", + "https://www.example.com/path/to/resource", + kSimpleChallenge, + &auth_token); + EXPECT_EQ("", error_text); + EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", " + "nonce=\"nonce-value\", uri=\"www.example.com:443\", " + "response=\"3270da8467afbe9ddf2334a48d46e9b9\"", + auth_token); +} + +TEST(HttpAuthHandlerDigest, RespondToChallengeAuthQop) { + std::string auth_token; + std::string error_text = RespondToChallenge( + HttpAuth::AUTH_SERVER, + std::string(), + "http://www.example.com/path/to/resource", + "Digest realm=\"Oblivion\", nonce=\"nonce-value\", qop=\"auth\"", + &auth_token); + EXPECT_EQ("", error_text); + EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", " + "nonce=\"nonce-value\", uri=\"/path/to/resource\", " + "response=\"5b1459beda5cee30d6ff9e970a69c0ea\", " + "qop=auth, nc=00000001, cnonce=\"client_nonce\"", + auth_token); +} + +TEST(HttpAuthHandlerDigest, RespondToChallengeOpaque) { + std::string auth_token; + std::string error_text = RespondToChallenge( + HttpAuth::AUTH_SERVER, + std::string(), + "http://www.example.com/path/to/resource", + "Digest realm=\"Oblivion\", nonce=\"nonce-value\", " + "qop=\"auth\", opaque=\"opaque text\"", + &auth_token); + EXPECT_EQ("", error_text); + EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", " + "nonce=\"nonce-value\", uri=\"/path/to/resource\", " + "response=\"5b1459beda5cee30d6ff9e970a69c0ea\", " + "opaque=\"opaque text\", " + "qop=auth, nc=00000001, cnonce=\"client_nonce\"", + auth_token); +} + + } // namespace net diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc index 1342afa..896a6ac 100644 --- a/net/http/http_cache.cc +++ b/net/http/http_cache.cc @@ -280,6 +280,7 @@ class HttpCache::SSLHostInfoFactoryAdaptor : public SSLHostInfoFactory { HttpCache::HttpCache(HostResolver* host_resolver, DnsRRResolver* dnsrr_resolver, + DnsCertProvenanceChecker* dns_cert_checker_, ProxyService* proxy_service, SSLConfigService* ssl_config_service, HttpAuthHandlerFactory* http_auth_handler_factory, @@ -292,7 +293,8 @@ HttpCache::HttpCache(HostResolver* host_resolver, ssl_host_info_factory_(new SSLHostInfoFactoryAdaptor( ALLOW_THIS_IN_INITIALIZER_LIST(this))), network_layer_(HttpNetworkLayer::CreateFactory(host_resolver, - dnsrr_resolver, ssl_host_info_factory_.get(), + dnsrr_resolver, dns_cert_checker_, + ssl_host_info_factory_.get(), proxy_service, ssl_config_service, http_auth_handler_factory, network_delegate, net_log)), ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), diff --git a/net/http/http_cache.h b/net/http/http_cache.h index 0ce22e5..06c2ab9 100644 --- a/net/http/http_cache.h +++ b/net/http/http_cache.h @@ -41,6 +41,7 @@ class Entry; namespace net { +class DnsCertProvenanceChecker; class DnsRRResolver; class HostResolver; class HttpAuthHandlerFactory; @@ -117,6 +118,7 @@ class HttpCache : public HttpTransactionFactory, // The HttpCache takes ownership of the |backend_factory|. HttpCache(HostResolver* host_resolver, DnsRRResolver* dnsrr_resolver, + DnsCertProvenanceChecker* dns_cert_checker, ProxyService* proxy_service, SSLConfigService* ssl_config_service, HttpAuthHandlerFactory* http_auth_handler_factory, diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc index 873ccf4..1720509 100644 --- a/net/http/http_cache_transaction.cc +++ b/net/http/http_cache_transaction.cc @@ -112,6 +112,7 @@ HttpCache::Transaction::Transaction(HttpCache* cache, bool enable_range_support) invalid_range_(false), enable_range_support_(enable_range_support), truncated_(false), + is_sparse_(false), server_responded_206_(false), cache_pending_(false), read_offset_(0), @@ -676,7 +677,7 @@ int HttpCache::Transaction::DoSuccessfulSendRequest() { return OK; } if (server_responded_206_ && mode_ == READ_WRITE && !truncated_ && - response_.headers->response_code() == 200) { + !is_sparse_) { // We have stored the full entry, but it changed and the server is // sending a range. We have to delete the old entry. DoneWritingToEntry(false); @@ -886,6 +887,7 @@ int HttpCache::Transaction::DoAddToEntryComplete(int result) { return OK; } +// We may end up here multiple times for a given request. int HttpCache::Transaction::DoStartPartialCacheValidation() { if (mode_ == NONE) return OK; @@ -1446,6 +1448,7 @@ int HttpCache::Transaction::BeginPartialCacheValidation() { return ValidateEntryHeadersAndContinue(false); } +// This should only be called once per request. int HttpCache::Transaction::ValidateEntryHeadersAndContinue( bool byte_range_requested) { DCHECK(mode_ == READ_WRITE); @@ -1461,6 +1464,9 @@ int HttpCache::Transaction::ValidateEntryHeadersAndContinue( return OK; } + if (response_.headers->response_code() == 206) + is_sparse_ = true; + if (!partial_->IsRequestedRangeOK()) { // The stored data is fine, but the request may be invalid. invalid_range_ = true; @@ -1842,6 +1848,7 @@ void HttpCache::Transaction::DoomPartialEntry(bool delete_object) { DCHECK_EQ(OK, rv); cache_->DoneWithEntry(entry_, this, false); entry_ = NULL; + is_sparse_ = false; if (delete_object) partial_.reset(NULL); } diff --git a/net/http/http_cache_transaction.h b/net/http/http_cache_transaction.h index 4d3673c..a842ade 100644 --- a/net/http/http_cache_transaction.h +++ b/net/http/http_cache_transaction.h @@ -341,6 +341,7 @@ class HttpCache::Transaction : public HttpTransaction { bool invalid_range_; // We may bypass the cache for this request. bool enable_range_support_; bool truncated_; // We don't have all the response data. + bool is_sparse_; // The data is stored in sparse byte ranges. bool server_responded_206_; bool cache_pending_; // We are waiting for the HttpCache. scoped_refptr<IOBuffer> read_buf_; diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc index 6ca1da1..b4dde9b 100644 --- a/net/http/http_cache_unittest.cc +++ b/net/http/http_cache_unittest.cc @@ -3216,36 +3216,41 @@ TEST(HttpCache, GET_Previous206) { } // Tests that we can handle non-range requests when we have cached the first -// part of the object and server replies with 304 (Not Modified). +// part of the object and the server replies with 304 (Not Modified). TEST(HttpCache, GET_Previous206_NotModified) { MockHttpCache cache; cache.http_cache()->set_enable_range_support(true); MockTransaction transaction(kRangeGET_TransactionOK); - transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER; - transaction.data = "rg: 00-09 "; AddMockTransaction(&transaction); std::string headers; // Write to the cache (0-9). + transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER; + transaction.data = "rg: 00-09 "; RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); - Verify206Response(headers, 0, 9); - EXPECT_EQ(1, cache.network_layer()->transaction_count()); - EXPECT_EQ(0, cache.disk_cache()->open_count()); + + // Write to the cache (70-79). + transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER; + transaction.data = "rg: 70-79 "; + RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); + Verify206Response(headers, 70, 79); + + EXPECT_EQ(2, cache.network_layer()->transaction_count()); + EXPECT_EQ(1, cache.disk_cache()->open_count()); EXPECT_EQ(1, cache.disk_cache()->create_count()); - // Read from the cache (0-9), write and read from cache (10 - 79), - MockTransaction transaction2(kRangeGET_TransactionOK); - transaction2.load_flags |= net::LOAD_VALIDATE_CACHE; - transaction2.request_headers = "Foo: bar\r\n" EXTRA_HEADER; - transaction2.data = "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49 " + // Read from the cache (0-9), write and read from cache (10 - 79). + transaction.load_flags |= net::LOAD_VALIDATE_CACHE; + transaction.request_headers = "Foo: bar\r\n" EXTRA_HEADER; + transaction.data = "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49 " "rg: 50-59 rg: 60-69 rg: 70-79 "; - RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers); + RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n")); - EXPECT_EQ(3, cache.network_layer()->transaction_count()); - EXPECT_EQ(1, cache.disk_cache()->open_count()); + EXPECT_EQ(4, cache.network_layer()->transaction_count()); + EXPECT_EQ(2, cache.disk_cache()->open_count()); EXPECT_EQ(1, cache.disk_cache()->create_count()); RemoveMockTransaction(&transaction); diff --git a/net/http/http_network_layer.cc b/net/http/http_network_layer.cc index 5322e85..3da23c2 100644 --- a/net/http/http_network_layer.cc +++ b/net/http/http_network_layer.cc @@ -22,6 +22,7 @@ namespace net { HttpTransactionFactory* HttpNetworkLayer::CreateFactory( HostResolver* host_resolver, DnsRRResolver* dnsrr_resolver, + DnsCertProvenanceChecker* dns_cert_checker, SSLHostInfoFactory* ssl_host_info_factory, ProxyService* proxy_service, SSLConfigService* ssl_config_service, @@ -32,6 +33,7 @@ HttpTransactionFactory* HttpNetworkLayer::CreateFactory( return new HttpNetworkLayer(ClientSocketFactory::GetDefaultFactory(), host_resolver, dnsrr_resolver, + dns_cert_checker, ssl_host_info_factory, proxy_service, ssl_config_service, http_auth_handler_factory, network_delegate, @@ -51,6 +53,7 @@ HttpNetworkLayer::HttpNetworkLayer( ClientSocketFactory* socket_factory, HostResolver* host_resolver, DnsRRResolver* dnsrr_resolver, + DnsCertProvenanceChecker* dns_cert_checker, SSLHostInfoFactory* ssl_host_info_factory, ProxyService* proxy_service, SSLConfigService* ssl_config_service, @@ -60,6 +63,7 @@ HttpNetworkLayer::HttpNetworkLayer( : socket_factory_(socket_factory), host_resolver_(host_resolver), dnsrr_resolver_(dnsrr_resolver), + dns_cert_checker_(dns_cert_checker), ssl_host_info_factory_(ssl_host_info_factory), proxy_service_(proxy_service), ssl_config_service_(ssl_config_service), @@ -77,6 +81,7 @@ HttpNetworkLayer::HttpNetworkLayer( ClientSocketFactory* socket_factory, HostResolver* host_resolver, DnsRRResolver* dnsrr_resolver, + DnsCertProvenanceChecker* dns_cert_checker, SSLHostInfoFactory* ssl_host_info_factory, ProxyService* proxy_service, SSLConfigService* ssl_config_service, @@ -87,6 +92,7 @@ HttpNetworkLayer::HttpNetworkLayer( : socket_factory_(socket_factory), host_resolver_(host_resolver), dnsrr_resolver_(dnsrr_resolver), + dns_cert_checker_(dns_cert_checker), ssl_host_info_factory_(ssl_host_info_factory), proxy_service_(proxy_service), ssl_config_service_(ssl_config_service), @@ -103,6 +109,7 @@ HttpNetworkLayer::HttpNetworkLayer( HttpNetworkLayer::HttpNetworkLayer(HttpNetworkSession* session) : socket_factory_(ClientSocketFactory::GetDefaultFactory()), dnsrr_resolver_(NULL), + dns_cert_checker_(NULL), ssl_host_info_factory_(NULL), ssl_config_service_(NULL), session_(session), @@ -144,6 +151,7 @@ HttpNetworkSession* HttpNetworkLayer::GetSession() { session_ = new HttpNetworkSession( host_resolver_, dnsrr_resolver_, + dns_cert_checker_, ssl_host_info_factory_, proxy_service_, socket_factory_, @@ -155,6 +163,7 @@ HttpNetworkSession* HttpNetworkLayer::GetSession() { // These were just temps for lazy-initializing HttpNetworkSession. host_resolver_ = NULL; dnsrr_resolver_ = NULL; + dns_cert_checker_ = NULL; ssl_host_info_factory_ = NULL; proxy_service_ = NULL; socket_factory_ = NULL; diff --git a/net/http/http_network_layer.h b/net/http/http_network_layer.h index 63ae3f2..7781efb 100644 --- a/net/http/http_network_layer.h +++ b/net/http/http_network_layer.h @@ -16,6 +16,7 @@ namespace net { class ClientSocketFactory; +class DnsCertProvenanceChecker; class DnsRRResolver; class HostResolver; class HttpAuthHandlerFactory; @@ -34,6 +35,7 @@ class HttpNetworkLayer : public HttpTransactionFactory, public NonThreadSafe { HttpNetworkLayer(ClientSocketFactory* socket_factory, HostResolver* host_resolver, DnsRRResolver* dnsrr_resolver, + DnsCertProvenanceChecker* dns_cert_checker, SSLHostInfoFactory* ssl_host_info_factory, ProxyService* proxy_service, SSLConfigService* ssl_config_service, @@ -46,6 +48,7 @@ class HttpNetworkLayer : public HttpTransactionFactory, public NonThreadSafe { ClientSocketFactory* socket_factory, HostResolver* host_resolver, DnsRRResolver* dnsrr_resolver, + DnsCertProvenanceChecker* dns_cert_checker, SSLHostInfoFactory* ssl_host_info_factory, ProxyService* proxy_service, SSLConfigService* ssl_config_service, @@ -62,6 +65,7 @@ class HttpNetworkLayer : public HttpTransactionFactory, public NonThreadSafe { static HttpTransactionFactory* CreateFactory( HostResolver* host_resolver, DnsRRResolver* dnsrr_resolver, + DnsCertProvenanceChecker* dns_cert_checker, SSLHostInfoFactory* ssl_host_info_factory, ProxyService* proxy_service, SSLConfigService* ssl_config_service, @@ -100,6 +104,7 @@ class HttpNetworkLayer : public HttpTransactionFactory, public NonThreadSafe { // creating |session_|. HostResolver* host_resolver_; DnsRRResolver* dnsrr_resolver_; + DnsCertProvenanceChecker* dns_cert_checker_; SSLHostInfoFactory* ssl_host_info_factory_; scoped_refptr<ProxyService> proxy_service_; diff --git a/net/http/http_network_layer_unittest.cc b/net/http/http_network_layer_unittest.cc index 2850404..3ed54bf 100644 --- a/net/http/http_network_layer_unittest.cc +++ b/net/http/http_network_layer_unittest.cc @@ -25,6 +25,7 @@ TEST_F(HttpNetworkLayerTest, CreateAndDestroy) { NULL, &host_resolver, NULL /* dnsrr_resolver */, + NULL /* dns_cert_checker */, NULL /* ssl_host_info_factory */, net::ProxyService::CreateDirect(), new net::SSLConfigServiceDefaults, @@ -44,6 +45,7 @@ TEST_F(HttpNetworkLayerTest, Suspend) { NULL, &host_resolver, NULL /* dnsrr_resolver */, + NULL /* dns_cert_checker */, NULL /* ssl_host_info_factory */, net::ProxyService::CreateDirect(), new net::SSLConfigServiceDefaults, @@ -92,6 +94,7 @@ TEST_F(HttpNetworkLayerTest, GET) { &mock_socket_factory, &host_resolver, NULL /* dnsrr_resolver */, + NULL /* dns_cert_checker */, NULL /* ssl_host_info_factory */, net::ProxyService::CreateDirect(), new net::SSLConfigServiceDefaults, diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index d96f901..1e77b49 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc @@ -21,6 +21,7 @@ namespace net { HttpNetworkSession::HttpNetworkSession( HostResolver* host_resolver, DnsRRResolver* dnsrr_resolver, + DnsCertProvenanceChecker* dns_cert_checker, SSLHostInfoFactory* ssl_host_info_factory, ProxyService* proxy_service, ClientSocketFactory* client_socket_factory, @@ -32,12 +33,14 @@ HttpNetworkSession::HttpNetworkSession( : socket_factory_(client_socket_factory), host_resolver_(host_resolver), dnsrr_resolver_(dnsrr_resolver), + dns_cert_checker_(dns_cert_checker), proxy_service_(proxy_service), ssl_config_service_(ssl_config_service), socket_pool_manager_(net_log, client_socket_factory, host_resolver, dnsrr_resolver, + dns_cert_checker, ssl_host_info_factory, proxy_service, ssl_config_service), diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h index 53ae36a..43424d2 100644 --- a/net/http/http_network_session.h +++ b/net/http/http_network_session.h @@ -29,6 +29,7 @@ class Value; namespace net { class ClientSocketFactory; +class DnsCertProvenanceChecker; class DnsRRResolver; class HttpAuthHandlerFactory; class HttpNetworkDelegate; @@ -48,6 +49,7 @@ class HttpNetworkSession : public base::RefCounted<HttpNetworkSession>, HttpNetworkSession( HostResolver* host_resolver, DnsRRResolver* dnsrr_resolver, + DnsCertProvenanceChecker* dns_cert_checker, SSLHostInfoFactory* ssl_host_info_factory, ProxyService* proxy_service, ClientSocketFactory* client_socket_factory, @@ -108,6 +110,9 @@ class HttpNetworkSession : public base::RefCounted<HttpNetworkSession>, ClientSocketFactory* socket_factory() { return socket_factory_; } HostResolver* host_resolver() { return host_resolver_; } DnsRRResolver* dnsrr_resolver() { return dnsrr_resolver_; } + DnsCertProvenanceChecker* dns_cert_checker() { + return dns_cert_checker_; + } ProxyService* proxy_service() { return proxy_service_; } SSLConfigService* ssl_config_service() { return ssl_config_service_; } SpdySessionPool* spdy_session_pool() { return spdy_session_pool_.get(); } @@ -148,6 +153,7 @@ class HttpNetworkSession : public base::RefCounted<HttpNetworkSession>, HttpAlternateProtocols alternate_protocols_; HostResolver* const host_resolver_; DnsRRResolver* dnsrr_resolver_; + DnsCertProvenanceChecker* dns_cert_checker_; scoped_refptr<ProxyService> proxy_service_; scoped_refptr<SSLConfigService> ssl_config_service_; ClientSocketPoolManager socket_pool_manager_; diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index 3e1d8d1..c84dfa4 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc @@ -96,7 +96,6 @@ HttpNetworkTransaction::HttpNetworkTransaction(HttpNetworkSession* session) session->ssl_config_service()->GetSSLConfig(&ssl_config_); if (session->http_stream_factory()->next_protos()) ssl_config_.next_protos = *session->http_stream_factory()->next_protos(); - } HttpNetworkTransaction::~HttpNetworkTransaction() { @@ -171,10 +170,8 @@ int HttpNetworkTransaction::RestartWithCertificate( DCHECK_EQ(STATE_NONE, next_state_); ssl_config_.client_cert = client_cert; - if (client_cert) { - session_->ssl_client_auth_cache()->Add( - response_.cert_request_info->host_and_port, client_cert); - } + session_->ssl_client_auth_cache()->Add( + response_.cert_request_info->host_and_port, client_cert); ssl_config_.send_client_cert = true; // Reset the other member variables. // Note: this is necessary only with SSL renegotiation. @@ -971,29 +968,43 @@ int HttpNetworkTransaction::HandleCertificateRequest(int error) { // handshake. stream_request_.reset(); - // If the user selected one of the certificate in client_certs for this - // server before, use it automatically. - X509Certificate* client_cert = session_->ssl_client_auth_cache()->Lookup( - response_.cert_request_info->host_and_port); + // If the user selected one of the certificates in client_certs or declined + // to provide one for this server before, use the past decision + // automatically. + scoped_refptr<X509Certificate> client_cert; + bool found_cached_cert = session_->ssl_client_auth_cache()->Lookup( + response_.cert_request_info->host_and_port, &client_cert); + if (!found_cached_cert) + return error; + + // Check that the certificate selected is still a certificate the server + // is likely to accept, based on the criteria supplied in the + // CertificateRequest message. if (client_cert) { const std::vector<scoped_refptr<X509Certificate> >& client_certs = response_.cert_request_info->client_certs; + bool cert_still_valid = false; for (size_t i = 0; i < client_certs.size(); ++i) { - if (client_cert->fingerprint().Equals(client_certs[i]->fingerprint())) { - // TODO(davidben): Add a unit test which covers this path; we need to be - // able to send a legitimate certificate and also bypass/clear the - // SSL session cache. - ssl_config_.client_cert = client_cert; - ssl_config_.send_client_cert = true; - next_state_ = STATE_CREATE_STREAM; - // Reset the other member variables. - // Note: this is necessary only with SSL renegotiation. - ResetStateForRestart(); - return OK; + if (client_cert->Equals(client_certs[i])) { + cert_still_valid = true; + break; } } + + if (!cert_still_valid) + return error; } - return error; + + // TODO(davidben): Add a unit test which covers this path; we need to be + // able to send a legitimate certificate and also bypass/clear the + // SSL session cache. + ssl_config_.client_cert = client_cert; + ssl_config_.send_client_cert = true; + next_state_ = STATE_CREATE_STREAM; + // Reset the other member variables. + // Note: this is necessary only with SSL renegotiation. + ResetStateForRestart(); + return OK; } // This method determines whether it is safe to resend the request after an diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index 6a389af..f765696 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc @@ -100,6 +100,7 @@ struct SessionDependencies { HttpNetworkSession* CreateSession(SessionDependencies* session_deps) { return new HttpNetworkSession(session_deps->host_resolver.get(), NULL /* dnsrr_resolver */, + NULL /* dns_cert_checker */, NULL /* ssl_host_info_factory */, session_deps->proxy_service, &session_deps->socket_factory, @@ -307,7 +308,7 @@ template<> CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool( HttpNetworkSession* session) : SSLClientSocketPool(0, 0, NULL, session->host_resolver(), NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL) {} + NULL, NULL, NULL, NULL, NULL, NULL, NULL) {} //----------------------------------------------------------------------------- diff --git a/net/http/http_proxy_client_socket_pool.cc b/net/http/http_proxy_client_socket_pool.cc index e43d02b..d0c177d 100644 --- a/net/http/http_proxy_client_socket_pool.cc +++ b/net/http/http_proxy_client_socket_pool.cc @@ -283,7 +283,8 @@ int HttpProxyConnectJob::DoSpdyProxyCreateStream() { next_state_ = STATE_SPDY_PROXY_CREATE_STREAM_COMPLETE; return spdy_session->CreateStream(params_->request_url(), params_->destination().priority(), - &spdy_stream_, net_log(), &callback_); + &spdy_stream_, spdy_session->net_log(), + &callback_); } int HttpProxyConnectJob::DoSpdyProxyCreateStreamComplete(int result) { diff --git a/net/http/http_proxy_client_socket_pool_unittest.cc b/net/http/http_proxy_client_socket_pool_unittest.cc index f5bc2e7..56fae19 100644 --- a/net/http/http_proxy_client_socket_pool_unittest.cc +++ b/net/http/http_proxy_client_socket_pool_unittest.cc @@ -66,6 +66,7 @@ class HttpProxyClientSocketPoolTest : public TestWithHttpParam { &ssl_histograms_, host_resolver_.get(), NULL /* dnsrr_resolver */, + NULL /* dns_cert_checker */, NULL /* ssl_host_info_factory */, &socket_factory_, &tcp_socket_pool_, @@ -77,6 +78,7 @@ class HttpProxyClientSocketPoolTest : public TestWithHttpParam { HttpAuthHandlerFactory::CreateDefault(host_resolver_.get())), session_(new HttpNetworkSession(host_resolver_.get(), NULL /* dnsrr_resolver */, + NULL /* dns_cert_checker */, NULL /* ssl_host_info_factory */, ProxyService::CreateDirect(), &socket_factory_, diff --git a/net/http/http_request_info.h b/net/http/http_request_info.h index f740d7c..7c73aa6 100644 --- a/net/http/http_request_info.h +++ b/net/http/http_request_info.h @@ -18,9 +18,12 @@ namespace net { struct HttpRequestInfo { enum RequestMotivation{ // TODO(mbelshe): move these into Client Socket. - PRECONNECT_MOTIVATED, // This request was motivated by a prefetch. - OMNIBOX_MOTIVATED, // This request was motivated by the omnibox. - NORMAL_MOTIVATION // No special motivation associated with the request. + PRECONNECT_MOTIVATED, // Request was motivated by a prefetch. + OMNIBOX_MOTIVATED, // Request was motivated by the omnibox. + NORMAL_MOTIVATION, // No special motivation associated with the request. + EARLY_LOAD_MOTIVATED, // When browser asks a tab to open an URL, this short + // circuits that path (of waiting for the renderer to + // do the URL request), and starts loading ASAP. }; HttpRequestInfo(); diff --git a/net/http/http_response_body_drainer_unittest.cc b/net/http/http_response_body_drainer_unittest.cc index d8c9bb7..75f099a 100644 --- a/net/http/http_response_body_drainer_unittest.cc +++ b/net/http/http_response_body_drainer_unittest.cc @@ -175,8 +175,9 @@ class HttpResponseBodyDrainerTest : public testing::Test { protected: HttpResponseBodyDrainerTest() : session_(new HttpNetworkSession( - NULL, - NULL, + NULL /* host_resolver */, + NULL /* dnsrr_resolver */, + NULL /* dns_cert_checker */, NULL /* ssl_host_info_factory */, ProxyService::CreateDirect(), NULL, diff --git a/net/http/http_stream_factory_unittest.cc b/net/http/http_stream_factory_unittest.cc index c295363..63fce33 100644 --- a/net/http/http_stream_factory_unittest.cc +++ b/net/http/http_stream_factory_unittest.cc @@ -44,6 +44,7 @@ struct SessionDependencies { HttpNetworkSession* CreateSession(SessionDependencies* session_deps) { return new HttpNetworkSession(session_deps->host_resolver.get(), NULL /* dnsrr_resolver */, + NULL /* dns_cert_checker */, NULL /* ssl_host_info_factory */, session_deps->proxy_service, &session_deps->socket_factory, @@ -170,7 +171,7 @@ template<> CapturePreconnectsSSLSocketPool::CapturePreconnectsSocketPool( HttpNetworkSession* session) : SSLClientSocketPool(0, 0, NULL, session->host_resolver(), NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL) {} + NULL, NULL, NULL, NULL, NULL, NULL, NULL) {} TEST(HttpStreamFactoryTest, PreconnectDirect) { for (size_t i = 0; i < arraysize(kTests); ++i) { diff --git a/net/http/http_stream_request.cc b/net/http/http_stream_request.cc index eaaad16..6f0a39e 100644 --- a/net/http/http_stream_request.cc +++ b/net/http/http_stream_request.cc @@ -759,7 +759,12 @@ int HttpStreamRequest::DoCreateStream() { direct = false; } - if (!spdy_session.get()) { + if (spdy_session.get()) { + // We picked up an existing session, so we don't need our socket. + if (connection_->socket()) + connection_->socket()->Disconnect(); + connection_->Reset(); + } else { // SPDY can be negotiated using the TLS next protocol negotiation (NPN) // extension, or just directly using SSL. Either way, |connection_| must // contain an SSLClientSocket. diff --git a/net/http/stream_factory.h b/net/http/stream_factory.h index 480df06..94b3cc8 100644 --- a/net/http/stream_factory.h +++ b/net/http/stream_factory.h @@ -122,7 +122,8 @@ class StreamFactory { // Requests that enough connections for |num_streams| be opened. If // ERR_IO_PENDING is returned, |info|, |ssl_config|, and |proxy_info| must - // be kept alive until |callback| is invoked. + // be kept alive until |callback| is invoked. That callback will be given the + // final error code. virtual int PreconnectStreams(int num_streams, const HttpRequestInfo* info, SSLConfig* ssl_config, |