summaryrefslogtreecommitdiffstats
path: root/net/http
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2011-01-07 14:18:56 +0000
committerBen Murdoch <benm@google.com>2011-01-11 10:23:13 +0000
commit201ade2fbba22bfb27ae029f4d23fca6ded109a0 (patch)
treeb793f4ed916f73cf18357ea467ff3deb5ffb5b52 /net/http
parentd8c4c37a7d0961944bfdfaa117d5c68c8e129c97 (diff)
downloadexternal_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.cc161
-rw-r--r--net/http/http_cache.cc4
-rw-r--r--net/http/http_cache.h2
-rw-r--r--net/http/http_cache_transaction.cc9
-rw-r--r--net/http/http_cache_transaction.h1
-rw-r--r--net/http/http_cache_unittest.cc33
-rw-r--r--net/http/http_network_layer.cc9
-rw-r--r--net/http/http_network_layer.h5
-rw-r--r--net/http/http_network_layer_unittest.cc3
-rw-r--r--net/http/http_network_session.cc3
-rw-r--r--net/http/http_network_session.h6
-rw-r--r--net/http/http_network_transaction.cc53
-rw-r--r--net/http/http_network_transaction_unittest.cc3
-rw-r--r--net/http/http_proxy_client_socket_pool.cc3
-rw-r--r--net/http/http_proxy_client_socket_pool_unittest.cc2
-rw-r--r--net/http/http_request_info.h9
-rw-r--r--net/http/http_response_body_drainer_unittest.cc5
-rw-r--r--net/http/http_stream_factory_unittest.cc3
-rw-r--r--net/http/http_stream_request.cc7
-rw-r--r--net/http/stream_factory.h3
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,