summaryrefslogtreecommitdiffstats
path: root/net/http
diff options
context:
space:
mode:
authorKristian Monsen <kristianm@google.com>2011-05-31 20:30:28 +0100
committerKristian Monsen <kristianm@google.com>2011-06-14 20:31:41 -0700
commit72a454cd3513ac24fbdd0e0cb9ad70b86a99b801 (patch)
tree382278a54ce7a744d62fa510a9a80688cc12434b /net/http
parentc4becdd46e31d261b930e4b5a539cbc1d45c23a6 (diff)
downloadexternal_chromium-72a454cd3513ac24fbdd0e0cb9ad70b86a99b801.zip
external_chromium-72a454cd3513ac24fbdd0e0cb9ad70b86a99b801.tar.gz
external_chromium-72a454cd3513ac24fbdd0e0cb9ad70b86a99b801.tar.bz2
Merge Chromium.org at r11.0.672.0: Initial merge by git.
Change-Id: I8b4aaf611a2a405fe3fe10e8a94ea7658645c192
Diffstat (limited to 'net/http')
-rw-r--r--net/http/disk_cache_based_ssl_host_info.cc200
-rw-r--r--net/http/disk_cache_based_ssl_host_info.h34
-rw-r--r--net/http/http_alternate_protocols.cc23
-rw-r--r--net/http/http_alternate_protocols.h10
-rw-r--r--net/http/http_auth.cc78
-rw-r--r--net/http/http_auth.h16
-rw-r--r--net/http/http_auth_cache.cc23
-rw-r--r--net/http/http_auth_cache.h26
-rw-r--r--net/http/http_auth_cache_unittest.cc146
-rw-r--r--net/http/http_auth_controller.cc25
-rw-r--r--net/http/http_auth_controller.h6
-rw-r--r--net/http/http_auth_filter.cc30
-rw-r--r--net/http/http_auth_filter.h6
-rw-r--r--net/http/http_auth_gssapi_posix_unittest.cc31
-rw-r--r--net/http/http_auth_handler.cc7
-rw-r--r--net/http/http_auth_handler.h20
-rw-r--r--net/http/http_auth_handler_basic.cc3
-rw-r--r--net/http/http_auth_handler_digest.cc323
-rw-r--r--net/http/http_auth_handler_digest.h6
-rw-r--r--net/http/http_auth_handler_factory.cc80
-rw-r--r--net/http/http_auth_handler_factory.h30
-rw-r--r--net/http/http_auth_handler_factory_unittest.cc11
-rw-r--r--net/http/http_auth_handler_mock.cc19
-rw-r--r--net/http/http_auth_handler_mock.h54
-rw-r--r--net/http/http_auth_handler_negotiate.cc313
-rw-r--r--net/http/http_auth_handler_negotiate.h25
-rw-r--r--net/http/http_auth_handler_negotiate_unittest.cc37
-rw-r--r--net/http/http_auth_handler_ntlm.cc27
-rw-r--r--net/http/http_auth_handler_ntlm.h8
-rw-r--r--net/http/http_auth_handler_ntlm_portable.cc37
-rw-r--r--net/http/http_auth_sspi_win.cc5
-rw-r--r--net/http/http_auth_unittest.cc40
-rw-r--r--net/http/http_basic_stream.cc4
-rw-r--r--net/http/http_cache.cc117
-rw-r--r--net/http/http_cache.h30
-rw-r--r--net/http/http_cache_transaction.cc128
-rw-r--r--net/http/http_cache_transaction.h38
-rw-r--r--net/http/http_net_log_params.h10
-rw-r--r--net/http/http_network_delegate.h4
-rw-r--r--net/http/http_network_layer.cc189
-rw-r--r--net/http/http_network_layer.h78
-rw-r--r--net/http/http_network_layer_unittest.cc131
-rw-r--r--net/http/http_network_session.cc61
-rw-r--r--net/http/http_network_session.h80
-rw-r--r--net/http/http_network_session_peer.h59
-rw-r--r--net/http/http_network_transaction.cc124
-rw-r--r--net/http/http_network_transaction.h7
-rw-r--r--net/http/http_network_transaction_unittest.cc1105
-rw-r--r--net/http/http_proxy_client_socket.cc164
-rw-r--r--net/http/http_proxy_client_socket.h17
-rw-r--r--net/http/http_proxy_client_socket_pool.cc50
-rw-r--r--net/http/http_proxy_client_socket_pool.h18
-rw-r--r--net/http/http_proxy_client_socket_pool_unittest.cc54
-rw-r--r--net/http/http_request_headers.cc8
-rw-r--r--net/http/http_request_headers.h7
-rw-r--r--net/http/http_request_headers_unittest.cc8
-rw-r--r--net/http/http_response_body_drainer_unittest.cc27
-rw-r--r--net/http/http_response_headers.cc83
-rw-r--r--net/http/http_response_headers.h14
-rw-r--r--net/http/http_stream_factory.cc16
-rw-r--r--net/http/http_stream_factory.h54
-rw-r--r--net/http/http_stream_factory_unittest.cc105
-rw-r--r--net/http/http_stream_parser.cc47
-rw-r--r--net/http/http_stream_parser.h5
-rw-r--r--net/http/http_stream_request.cc55
-rw-r--r--net/http/http_stream_request.h5
-rw-r--r--net/http/http_transaction_unittest.cc232
-rw-r--r--net/http/http_transaction_unittest.h217
-rw-r--r--net/http/http_util.cc11
-rw-r--r--net/http/mock_gssapi_library_posix.cc75
-rw-r--r--net/http/mock_gssapi_library_posix.h112
-rw-r--r--net/http/url_security_manager.h19
72 files changed, 2907 insertions, 2360 deletions
diff --git a/net/http/disk_cache_based_ssl_host_info.cc b/net/http/disk_cache_based_ssl_host_info.cc
index 1b1dfaf..7021cfb 100644
--- a/net/http/disk_cache_based_ssl_host_info.cc
+++ b/net/http/disk_cache_based_ssl_host_info.cc
@@ -13,12 +13,32 @@
namespace net {
+DiskCacheBasedSSLHostInfo::CallbackImpl::CallbackImpl(
+ const base::WeakPtr<DiskCacheBasedSSLHostInfo>& obj,
+ void (DiskCacheBasedSSLHostInfo::*meth)(int))
+ : obj_(obj),
+ meth_(meth),
+ backend_(NULL),
+ entry_(NULL) {
+}
+
+DiskCacheBasedSSLHostInfo::CallbackImpl::~CallbackImpl() {}
+
+void DiskCacheBasedSSLHostInfo::CallbackImpl::RunWithParams(
+ const Tuple1<int>& params) {
+ if (!obj_) {
+ delete this;
+ } else {
+ DispatchToMethod(obj_.get(), meth_, params);
+ }
+}
+
DiskCacheBasedSSLHostInfo::DiskCacheBasedSSLHostInfo(
const std::string& hostname,
const SSLConfig& ssl_config,
+ CertVerifier* cert_verifier,
HttpCache* http_cache)
- : SSLHostInfo(hostname, ssl_config,
- http_cache->network_layer()->GetSession()->cert_verifier()),
+ : SSLHostInfo(hostname, ssl_config, cert_verifier),
weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
callback_(new CallbackImpl(weak_ptr_factory_.GetWeakPtr(),
&DiskCacheBasedSSLHostInfo::DoLoop)),
@@ -37,6 +57,35 @@ void DiskCacheBasedSSLHostInfo::Start() {
DoLoop(OK);
}
+int DiskCacheBasedSSLHostInfo::WaitForDataReady(CompletionCallback* callback) {
+ DCHECK(CalledOnValidThread());
+ DCHECK(state_ != GET_BACKEND);
+
+ if (ready_)
+ return OK;
+ if (callback) {
+ DCHECK(!user_callback_);
+ user_callback_ = callback;
+ }
+ return ERR_IO_PENDING;
+}
+
+void DiskCacheBasedSSLHostInfo::Persist() {
+ DCHECK(CalledOnValidThread());
+ DCHECK(state_ != GET_BACKEND);
+
+ DCHECK(new_data_.empty());
+ CHECK(ready_);
+ DCHECK(user_callback_ == NULL);
+ new_data_ = Serialize();
+
+ if (!backend_)
+ return;
+
+ state_ = CREATE;
+ DoLoop(OK);
+}
+
DiskCacheBasedSSLHostInfo::~DiskCacheBasedSSLHostInfo() {
DCHECK(!user_callback_);
if (entry_)
@@ -95,24 +144,6 @@ void DiskCacheBasedSSLHostInfo::DoLoop(int rv) {
} while (rv != ERR_IO_PENDING && state_ != NONE);
}
-bool DiskCacheBasedSSLHostInfo::IsCallbackPending() const {
- switch (state_) {
- case GET_BACKEND_COMPLETE:
- case OPEN_COMPLETE:
- case READ_COMPLETE:
- case CREATE_COMPLETE:
- case WRITE_COMPLETE:
- return true;
- default:
- return false;
- }
-}
-
-int DiskCacheBasedSSLHostInfo::DoGetBackend() {
- state_ = GET_BACKEND_COMPLETE;
- return http_cache_->GetBackend(callback_->backend_pointer(), callback_);
-}
-
int DiskCacheBasedSSLHostInfo::DoGetBackendComplete(int rv) {
if (rv == OK) {
backend_ = callback_->backend();
@@ -123,11 +154,6 @@ int DiskCacheBasedSSLHostInfo::DoGetBackendComplete(int rv) {
return OK;
}
-int DiskCacheBasedSSLHostInfo::DoOpen() {
- state_ = OPEN_COMPLETE;
- return backend_->OpenEntry(key(), callback_->entry_pointer(), callback_);
-}
-
int DiskCacheBasedSSLHostInfo::DoOpenComplete(int rv) {
if (rv == OK) {
entry_ = callback_->entry();
@@ -139,6 +165,39 @@ int DiskCacheBasedSSLHostInfo::DoOpenComplete(int rv) {
return OK;
}
+int DiskCacheBasedSSLHostInfo::DoReadComplete(int rv) {
+ if (rv > 0)
+ data_ = std::string(read_buffer_->data(), rv);
+
+ state_ = WAIT_FOR_DATA_READY_DONE;
+ return OK;
+}
+
+int DiskCacheBasedSSLHostInfo::DoWriteComplete(int rv) {
+ state_ = SET_DONE;
+ return OK;
+}
+
+int DiskCacheBasedSSLHostInfo::DoCreateComplete(int rv) {
+ if (rv != OK) {
+ state_ = SET_DONE;
+ } else {
+ entry_ = callback_->entry();
+ state_ = WRITE;
+ }
+ return OK;
+}
+
+int DiskCacheBasedSSLHostInfo::DoGetBackend() {
+ state_ = GET_BACKEND_COMPLETE;
+ return http_cache_->GetBackend(callback_->backend_pointer(), callback_);
+}
+
+int DiskCacheBasedSSLHostInfo::DoOpen() {
+ state_ = OPEN_COMPLETE;
+ return backend_->OpenEntry(key(), callback_->entry_pointer(), callback_);
+}
+
int DiskCacheBasedSSLHostInfo::DoRead() {
const int32 size = entry_->GetDataSize(0 /* index */);
if (!size) {
@@ -152,12 +211,19 @@ int DiskCacheBasedSSLHostInfo::DoRead() {
size, callback_);
}
-int DiskCacheBasedSSLHostInfo::DoReadComplete(int rv) {
- if (rv > 0)
- data_ = std::string(read_buffer_->data(), rv);
+int DiskCacheBasedSSLHostInfo::DoWrite() {
+ write_buffer_ = new IOBuffer(new_data_.size());
+ memcpy(write_buffer_->data(), new_data_.data(), new_data_.size());
+ state_ = WRITE_COMPLETE;
- state_ = WAIT_FOR_DATA_READY_DONE;
- return OK;
+ return entry_->WriteData(0 /* index */, 0 /* offset */, write_buffer_,
+ new_data_.size(), callback_, true /* truncate */);
+}
+
+int DiskCacheBasedSSLHostInfo::DoCreate() {
+ DCHECK(entry_ == NULL);
+ state_ = CREATE_COMPLETE;
+ return backend_->CreateEntry(key(), callback_->entry_pointer(), callback_);
}
int DiskCacheBasedSSLHostInfo::WaitForDataReadyDone() {
@@ -181,65 +247,6 @@ int DiskCacheBasedSSLHostInfo::WaitForDataReadyDone() {
return OK;
}
-int DiskCacheBasedSSLHostInfo::WaitForDataReady(CompletionCallback* callback) {
- DCHECK(CalledOnValidThread());
- DCHECK(state_ != GET_BACKEND);
-
- if (ready_)
- return OK;
- if (callback) {
- DCHECK(!user_callback_);
- user_callback_ = callback;
- }
- return ERR_IO_PENDING;
-}
-
-void DiskCacheBasedSSLHostInfo::Persist() {
- DCHECK(CalledOnValidThread());
- DCHECK(state_ != GET_BACKEND);
-
- DCHECK(new_data_.empty());
- CHECK(ready_);
- DCHECK(user_callback_ == NULL);
- new_data_ = Serialize();
-
- if (!backend_)
- return;
-
- state_ = CREATE;
- DoLoop(OK);
-}
-
-int DiskCacheBasedSSLHostInfo::DoCreate() {
- DCHECK(entry_ == NULL);
- state_ = CREATE_COMPLETE;
- return backend_->CreateEntry(key(), callback_->entry_pointer(), callback_);
-}
-
-int DiskCacheBasedSSLHostInfo::DoCreateComplete(int rv) {
- if (rv != OK) {
- state_ = SET_DONE;
- } else {
- entry_ = callback_->entry();
- state_ = WRITE;
- }
- return OK;
-}
-
-int DiskCacheBasedSSLHostInfo::DoWrite() {
- write_buffer_ = new IOBuffer(new_data_.size());
- memcpy(write_buffer_->data(), new_data_.data(), new_data_.size());
- state_ = WRITE_COMPLETE;
-
- return entry_->WriteData(0 /* index */, 0 /* offset */, write_buffer_,
- new_data_.size(), callback_, true /* truncate */);
-}
-
-int DiskCacheBasedSSLHostInfo::DoWriteComplete(int rv) {
- state_ = SET_DONE;
- return OK;
-}
-
int DiskCacheBasedSSLHostInfo::SetDone() {
if (entry_)
entry_->Close();
@@ -248,4 +255,17 @@ int DiskCacheBasedSSLHostInfo::SetDone() {
return OK;
}
-} // namespace net
+bool DiskCacheBasedSSLHostInfo::IsCallbackPending() const {
+ switch (state_) {
+ case GET_BACKEND_COMPLETE:
+ case OPEN_COMPLETE:
+ case READ_COMPLETE:
+ case CREATE_COMPLETE:
+ case WRITE_COMPLETE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+} // namespace net
diff --git a/net/http/disk_cache_based_ssl_host_info.h b/net/http/disk_cache_based_ssl_host_info.h
index c094163..905a3a9 100644
--- a/net/http/disk_cache_based_ssl_host_info.h
+++ b/net/http/disk_cache_based_ssl_host_info.h
@@ -2,12 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_HTTP_DISK_CACHE_BASED_SSL_HOST_INFO_H
-#define NET_HTTP_DISK_CACHE_BASED_SSL_HOST_INFO_H
+#ifndef NET_HTTP_DISK_CACHE_BASED_SSL_HOST_INFO_H_
+#define NET_HTTP_DISK_CACHE_BASED_SSL_HOST_INFO_H_
#include <string>
-#include "base/lock.h"
#include "base/scoped_ptr.h"
#include "base/threading/non_thread_safe.h"
#include "base/weak_ptr.h"
@@ -29,6 +28,7 @@ class DiskCacheBasedSSLHostInfo : public SSLHostInfo,
public:
DiskCacheBasedSSLHostInfo(const std::string& hostname,
const SSLConfig& ssl_config,
+ CertVerifier* cert_verifier,
HttpCache* http_cache);
// Implementation of SSLHostInfo
@@ -53,37 +53,30 @@ class DiskCacheBasedSSLHostInfo : public SSLHostInfo,
NONE,
};
- ~DiskCacheBasedSSLHostInfo();
-
class CallbackImpl : public CallbackRunner<Tuple1<int> > {
public:
CallbackImpl(const base::WeakPtr<DiskCacheBasedSSLHostInfo>& obj,
- void (DiskCacheBasedSSLHostInfo::*meth) (int))
- : obj_(obj),
- meth_(meth) {
- }
-
- virtual void RunWithParams(const Tuple1<int>& params) {
- if (!obj_) {
- delete this;
- } else {
- DispatchToMethod(obj_.get(), meth_, params);
- }
- }
+ void (DiskCacheBasedSSLHostInfo::*meth)(int));
+ virtual ~CallbackImpl();
disk_cache::Backend** backend_pointer() { return &backend_; }
disk_cache::Entry** entry_pointer() { return &entry_; }
disk_cache::Backend* backend() const { return backend_; }
disk_cache::Entry* entry() const { return entry_; }
+ // CallbackRunner<Tuple1<int> >:
+ virtual void RunWithParams(const Tuple1<int>& params);
+
private:
base::WeakPtr<DiskCacheBasedSSLHostInfo> obj_;
- void (DiskCacheBasedSSLHostInfo::*meth_) (int);
+ void (DiskCacheBasedSSLHostInfo::*meth_)(int);
disk_cache::Backend* backend_;
disk_cache::Entry* entry_;
};
+ virtual ~DiskCacheBasedSSLHostInfo();
+
std::string key() const;
void DoLoop(int rv);
@@ -97,11 +90,12 @@ class DiskCacheBasedSSLHostInfo : public SSLHostInfo,
int DoGetBackend();
int DoOpen();
int DoRead();
- int DoCreate();
int DoWrite();
+ int DoCreate();
// WaitForDataReadyDone is the terminal state of the read operation.
int WaitForDataReadyDone();
+
// SetDone is the terminal state of the write operation.
int SetDone();
@@ -125,4 +119,4 @@ class DiskCacheBasedSSLHostInfo : public SSLHostInfo,
} // namespace net
-#endif // NET_HTTP_DISK_CACHE_BASED_SSL_HOST_INFO_H
+#endif // NET_HTTP_DISK_CACHE_BASED_SSL_HOST_INFO_H_
diff --git a/net/http/http_alternate_protocols.cc b/net/http/http_alternate_protocols.cc
index 3e6b488..28c52dc 100644
--- a/net/http/http_alternate_protocols.cc
+++ b/net/http/http_alternate_protocols.cc
@@ -5,6 +5,7 @@
#include "net/http/http_alternate_protocols.h"
#include "base/logging.h"
+#include "base/stringprintf.h"
#include "base/stl_util-inl.h"
namespace net {
@@ -15,6 +16,28 @@ const char* const HttpAlternateProtocols::kProtocolStrings[] = {
"npn-spdy/2",
};
+const char* HttpAlternateProtocols::ProtocolToString(
+ HttpAlternateProtocols::Protocol protocol) {
+ switch (protocol) {
+ case HttpAlternateProtocols::NPN_SPDY_1:
+ case HttpAlternateProtocols::NPN_SPDY_2:
+ return HttpAlternateProtocols::kProtocolStrings[protocol];
+ case HttpAlternateProtocols::BROKEN:
+ return "Broken";
+ case HttpAlternateProtocols::UNINITIALIZED:
+ return "Uninitialized";
+ default:
+ NOTREACHED();
+ return "";
+ }
+}
+
+
+std::string HttpAlternateProtocols::PortProtocolPair::ToString() const {
+ return base::StringPrintf("%d:%s", port,
+ HttpAlternateProtocols::ProtocolToString(protocol));
+}
+
// static
HttpAlternateProtocols::PortProtocolPair*
HttpAlternateProtocols::forced_alternate_protocol_ = NULL;
diff --git a/net/http/http_alternate_protocols.h b/net/http/http_alternate_protocols.h
index d5f9d77..10b1a06 100644
--- a/net/http/http_alternate_protocols.h
+++ b/net/http/http_alternate_protocols.h
@@ -34,10 +34,14 @@ class HttpAlternateProtocols {
return port == other.port && protocol == other.protocol;
}
+ std::string ToString() const;
+
uint16 port;
Protocol protocol;
};
+ typedef std::map<HostPortPair, PortProtocolPair> ProtocolMap;
+
static const char kHeader[];
static const char* const kProtocolStrings[NUM_ALTERNATE_PROTOCOLS];
@@ -64,6 +68,8 @@ class HttpAlternateProtocols {
// attempts to set the alternate protocol for |http_host_port_pair| will fail.
void MarkBrokenAlternateProtocolFor(const HostPortPair& http_host_port_pair);
+ const ProtocolMap& protocol_map() const { return protocol_map_; }
+
// Debugging to simulate presence of an AlternateProtocol.
// If we don't have an alternate protocol in the map for any given host/port
// pair, force this ProtocolPortPair.
@@ -71,10 +77,10 @@ class HttpAlternateProtocols {
static void DisableForcedAlternateProtocol();
private:
- typedef std::map<HostPortPair, PortProtocolPair> ProtocolMap;
-
ProtocolMap protocol_map_;
+ static const char* ProtocolToString(Protocol protocol);
+
// The forced alternate protocol. If not-null, there is a protocol being
// forced.
static PortProtocolPair* forced_alternate_protocol_;
diff --git a/net/http/http_auth.cc b/net/http/http_auth.cc
index e7002cf..d5d6e0c 100644
--- a/net/http/http_auth.cc
+++ b/net/http/http_auth.cc
@@ -26,7 +26,7 @@ void HttpAuth::ChooseBestChallenge(
const HttpResponseHeaders* headers,
Target target,
const GURL& origin,
- const std::set<std::string>& disabled_schemes,
+ const std::set<Scheme>& disabled_schemes,
const BoundNetLog& net_log,
scoped_ptr<HttpAuthHandler>* handler) {
DCHECK(http_auth_handler_factory);
@@ -47,7 +47,7 @@ void HttpAuth::ChooseBestChallenge(
continue;
}
if (cur.get() && (!best.get() || best->score() < cur->score()) &&
- (disabled_schemes.find(cur->scheme()) == disabled_schemes.end()))
+ (disabled_schemes.find(cur->auth_scheme()) == disabled_schemes.end()))
best.swap(cur);
}
handler->swap(best);
@@ -58,15 +58,16 @@ HttpAuth::AuthorizationResult HttpAuth::HandleChallengeResponse(
HttpAuthHandler* handler,
const HttpResponseHeaders* headers,
Target target,
- const std::set<std::string>& disabled_schemes,
+ const std::set<Scheme>& disabled_schemes,
std::string* challenge_used) {
DCHECK(handler);
DCHECK(headers);
DCHECK(challenge_used);
challenge_used->clear();
- const std::string& current_scheme = handler->scheme();
+ HttpAuth::Scheme current_scheme = handler->auth_scheme();
if (disabled_schemes.find(current_scheme) != disabled_schemes.end())
return HttpAuth::AUTHORIZATION_RESULT_REJECT;
+ std::string current_scheme_name = SchemeToString(current_scheme);
const std::string header_name = GetChallengeHeaderName(target);
void* iter = NULL;
std::string challenge;
@@ -74,7 +75,7 @@ HttpAuth::AuthorizationResult HttpAuth::HandleChallengeResponse(
HttpAuth::AUTHORIZATION_RESULT_INVALID;
while (headers->EnumerateHeader(&iter, header_name, &challenge)) {
HttpAuth::ChallengeTokenizer props(challenge.begin(), challenge.end());
- if (!LowerCaseEqualsASCII(props.scheme(), current_scheme.c_str()))
+ if (!LowerCaseEqualsASCII(props.scheme(), current_scheme_name.c_str()))
continue;
authorization_result = handler->HandleAnotherChallenge(&props);
if (authorization_result != HttpAuth::AUTHORIZATION_RESULT_INVALID) {
@@ -86,6 +87,24 @@ HttpAuth::AuthorizationResult HttpAuth::HandleChallengeResponse(
return HttpAuth::AUTHORIZATION_RESULT_REJECT;
}
+HttpUtil::NameValuePairsIterator HttpAuth::ChallengeTokenizer::param_pairs()
+ const {
+ return HttpUtil::NameValuePairsIterator(params_begin_, params_end_, ',');
+}
+
+std::string HttpAuth::ChallengeTokenizer::base64_param() const {
+ // Strip off any padding.
+ // (See https://bugzilla.mozilla.org/show_bug.cgi?id=230351.)
+ //
+ // Our base64 decoder requires that the length be a multiple of 4.
+ int encoded_length = params_end_ - params_begin_;
+ while (encoded_length > 0 && encoded_length % 4 != 0 &&
+ params_begin_[encoded_length - 1] == '=') {
+ --encoded_length;
+ }
+ return std::string(params_begin_, params_begin_ + encoded_length);
+}
+
void HttpAuth::ChallengeTokenizer::Init(std::string::const_iterator begin,
std::string::const_iterator end) {
// The first space-separated token is the auth-scheme.
@@ -106,24 +125,6 @@ void HttpAuth::ChallengeTokenizer::Init(std::string::const_iterator begin,
HttpUtil::TrimLWS(&params_begin_, &params_end_);
}
-HttpUtil::NameValuePairsIterator HttpAuth::ChallengeTokenizer::param_pairs()
- const {
- return HttpUtil::NameValuePairsIterator(params_begin_, params_end_, ',');
-}
-
-std::string HttpAuth::ChallengeTokenizer::base64_param() const {
- // Strip off any padding.
- // (See https://bugzilla.mozilla.org/show_bug.cgi?id=230351.)
- //
- // Our base64 decoder requires that the length be a multiple of 4.
- int encoded_length = params_end_ - params_begin_;
- while (encoded_length > 0 && encoded_length % 4 != 0 &&
- params_begin_[encoded_length - 1] == '=') {
- --encoded_length;
- }
- return std::string(params_begin_, params_begin_ + encoded_length);
-}
-
// static
std::string HttpAuth::GetChallengeHeaderName(Target target) {
switch (target) {
@@ -151,9 +152,34 @@ std::string HttpAuth::GetAuthorizationHeaderName(Target target) {
}
// static
-std::string HttpAuth::GetAuthTargetString(
- HttpAuth::Target target) {
- return target == HttpAuth::AUTH_PROXY ? "proxy" : "server";
+std::string HttpAuth::GetAuthTargetString(Target target) {
+ switch (target) {
+ case AUTH_PROXY:
+ return "proxy";
+ case AUTH_SERVER:
+ return "server";
+ default:
+ NOTREACHED();
+ return "";
+ }
+}
+
+// static
+const char* HttpAuth::SchemeToString(Scheme scheme) {
+ static const char* const kSchemeNames[] = {
+ "basic",
+ "digest",
+ "ntlm",
+ "negotiate",
+ "mock",
+ };
+ COMPILE_ASSERT(arraysize(kSchemeNames) == AUTH_SCHEME_MAX,
+ http_auth_scheme_names_incorrect_size);
+ if (scheme < AUTH_SCHEME_BASIC || scheme >= AUTH_SCHEME_MAX) {
+ NOTREACHED();
+ return "invalid_scheme";
+ }
+ return kSchemeNames[scheme];
}
} // namespace net
diff --git a/net/http/http_auth.h b/net/http/http_auth.h
index 0034b1f..ef779a1 100644
--- a/net/http/http_auth.h
+++ b/net/http/http_auth.h
@@ -80,6 +80,15 @@ class HttpAuth {
IDENT_SRC_DEFAULT_CREDENTIALS,
};
+ enum Scheme {
+ AUTH_SCHEME_BASIC = 0,
+ AUTH_SCHEME_DIGEST,
+ AUTH_SCHEME_NTLM,
+ AUTH_SCHEME_NEGOTIATE,
+ AUTH_SCHEME_MOCK,
+ AUTH_SCHEME_MAX,
+ };
+
// Helper structure used by HttpNetworkTransaction to track
// the current identity being used for authorization.
struct Identity {
@@ -103,6 +112,9 @@ class HttpAuth {
// messages.
static std::string GetAuthTargetString(Target target);
+ // Returns a string representation of an authentication Scheme.
+ static const char* SchemeToString(Scheme scheme);
+
// Iterate through the challenge headers, and pick the best one that
// we support. Obtains the implementation class for handling the challenge,
// and passes it back in |*handler|. If no supported challenge was found,
@@ -117,7 +129,7 @@ class HttpAuth {
const HttpResponseHeaders* headers,
Target target,
const GURL& origin,
- const std::set<std::string>& disabled_schemes,
+ const std::set<Scheme>& disabled_schemes,
const BoundNetLog& net_log,
scoped_ptr<HttpAuthHandler>* handler);
@@ -146,7 +158,7 @@ class HttpAuth {
HttpAuthHandler* handler,
const HttpResponseHeaders* headers,
Target target,
- const std::set<std::string>& disabled_schemes,
+ const std::set<Scheme>& disabled_schemes,
std::string* challenge_used);
// Breaks up a challenge string into the the auth scheme and parameter list,
diff --git a/net/http/http_auth_cache.cc b/net/http/http_auth_cache.cc
index cc80861..95d0d69 100644
--- a/net/http/http_auth_cache.cc
+++ b/net/http/http_auth_cache.cc
@@ -68,7 +68,7 @@ HttpAuthCache::~HttpAuthCache() {
// Performance: O(n), where n is the number of realm entries.
HttpAuthCache::Entry* HttpAuthCache::Lookup(const GURL& origin,
const std::string& realm,
- const std::string& scheme) {
+ HttpAuth::Scheme scheme) {
CheckOriginIsValid(origin);
// Linear scan through the realm entries.
@@ -104,7 +104,7 @@ HttpAuthCache::Entry* HttpAuthCache::LookupByPath(const GURL& origin,
HttpAuthCache::Entry* HttpAuthCache::Add(const GURL& origin,
const std::string& realm,
- const std::string& scheme,
+ HttpAuth::Scheme scheme,
const std::string& auth_challenge,
const string16& username,
const string16& password,
@@ -143,8 +143,15 @@ HttpAuthCache::Entry* HttpAuthCache::Add(const GURL& origin,
HttpAuthCache::Entry::~Entry() {
}
+void HttpAuthCache::Entry::UpdateStaleChallenge(
+ const std::string& auth_challenge) {
+ auth_challenge_ = auth_challenge;
+ nonce_count_ = 1;
+}
+
HttpAuthCache::Entry::Entry()
- : nonce_count_(0) {
+ : scheme_(HttpAuth::AUTH_SCHEME_MAX),
+ nonce_count_(0) {
}
void HttpAuthCache::Entry::AddPath(const std::string& path) {
@@ -175,15 +182,9 @@ bool HttpAuthCache::Entry::HasEnclosingPath(const std::string& dir) {
return false;
}
-void HttpAuthCache::Entry::UpdateStaleChallenge(
- const std::string& auth_challenge) {
- auth_challenge_ = auth_challenge;
- nonce_count_ = 1;
-}
-
bool HttpAuthCache::Remove(const GURL& origin,
const std::string& realm,
- const std::string& scheme,
+ HttpAuth::Scheme scheme,
const string16& username,
const string16& password) {
for (EntryList::iterator it = entries_.begin(); it != entries_.end(); ++it) {
@@ -201,7 +202,7 @@ bool HttpAuthCache::Remove(const GURL& origin,
bool HttpAuthCache::UpdateStaleChallenge(const GURL& origin,
const std::string& realm,
- const std::string& scheme,
+ HttpAuth::Scheme scheme,
const std::string& auth_challenge) {
HttpAuthCache::Entry* entry = Lookup(origin, realm, scheme);
if (!entry)
diff --git a/net/http/http_auth_cache.h b/net/http/http_auth_cache.h
index b6c382c..a130956 100644
--- a/net/http/http_auth_cache.h
+++ b/net/http/http_auth_cache.h
@@ -13,6 +13,7 @@
#include "base/ref_counted.h"
#include "base/string16.h"
#include "googleurl/src/gurl.h"
+#include "net/http/http_auth.h"
namespace net {
@@ -42,10 +43,11 @@ class HttpAuthCache {
// scheme |scheme|.
// |origin| - the {scheme, host, port} of the server.
// |realm| - case sensitive realm string.
- // |scheme| - case sensitive authentication scheme, should be lower-case.
+ // |scheme| - the authentication scheme (i.e. basic, negotiate).
// returns - the matched entry or NULL.
- Entry* Lookup(const GURL& origin, const std::string& realm,
- const std::string& scheme);
+ Entry* Lookup(const GURL& origin,
+ const std::string& realm,
+ HttpAuth::Scheme scheme);
// Find the entry on server |origin| whose protection space includes
// |path|. This uses the assumption in RFC 2617 section 2 that deeper
@@ -62,7 +64,7 @@ class HttpAuthCache {
// paths list.
// |origin| - the {scheme, host, port} of the server.
// |realm| - the auth realm for the challenge.
- // |scheme| - the authentication scheme for the challenge.
+ // |scheme| - the authentication scheme (i.e. basic, negotiate).
// |username| - login information for the realm.
// |password| - login information for the realm.
// |path| - absolute path for a resource contained in the protection
@@ -70,7 +72,7 @@ class HttpAuthCache {
// returns - the entry that was just added/updated.
Entry* Add(const GURL& origin,
const std::string& realm,
- const std::string& scheme,
+ HttpAuth::Scheme scheme,
const std::string& auth_challenge,
const string16& username,
const string16& password,
@@ -80,13 +82,13 @@ class HttpAuthCache {
// if one exists AND if the cached identity matches (|username|, |password|).
// |origin| - the {scheme, host, port} of the server.
// |realm| - case sensitive realm string.
- // |scheme| - authentication scheme
+ // |scheme| - the authentication scheme (i.e. basic, negotiate).
// |username| - condition to match.
// |password| - condition to match.
// returns - true if an entry was removed.
bool Remove(const GURL& origin,
const std::string& realm,
- const std::string& scheme,
+ HttpAuth::Scheme scheme,
const string16& username,
const string16& password);
@@ -97,7 +99,7 @@ class HttpAuthCache {
// cache, false otherwise.
bool UpdateStaleChallenge(const GURL& origin,
const std::string& realm,
- const std::string& scheme,
+ HttpAuth::Scheme scheme,
const std::string& auth_challenge);
private:
@@ -119,8 +121,8 @@ class HttpAuthCache::Entry {
return realm_;
}
- // The authentication scheme string of the challenge
- const std::string scheme() const {
+ // The authentication scheme of the challenge.
+ HttpAuth::Scheme scheme() const {
return scheme_;
}
@@ -161,10 +163,10 @@ class HttpAuthCache::Entry {
// Returns true if |dir| is contained within the realm's protection space.
bool HasEnclosingPath(const std::string& dir);
- // |origin_| contains the {scheme, host, port} of the server.
+ // |origin_| contains the {protocol, host, port} of the server.
GURL origin_;
std::string realm_;
- std::string scheme_;
+ HttpAuth::Scheme scheme_;
// Identity.
std::string auth_challenge_;
diff --git a/net/http/http_auth_cache_unittest.cc b/net/http/http_auth_cache_unittest.cc
index 2c28969..e940527 100644
--- a/net/http/http_auth_cache_unittest.cc
+++ b/net/http/http_auth_cache_unittest.cc
@@ -19,10 +19,11 @@ namespace {
class MockAuthHandler : public HttpAuthHandler {
public:
- MockAuthHandler(const char* scheme, const std::string& realm,
+ MockAuthHandler(HttpAuth::Scheme scheme,
+ const std::string& realm,
HttpAuth::Target target) {
// Can't use initializer list since these are members of the base class.
- scheme_ = scheme;
+ auth_scheme_ = scheme;
realm_ = realm;
score_ = 1;
target_ = target;
@@ -53,8 +54,6 @@ class MockAuthHandler : public HttpAuthHandler {
~MockAuthHandler() {}
};
-const char* kBasic = "basic";
-const char* kDigest = "digest";
const char* kRealm1 = "Realm1";
const char* kRealm2 = "Realm2";
const char* kRealm3 = "Realm3";
@@ -80,48 +79,58 @@ TEST(HttpAuthCacheTest, Basic) {
// Add cache entries for 3 realms: "Realm1", "Realm2", "Realm3"
scoped_ptr<HttpAuthHandler> realm1_handler(
- new MockAuthHandler(kBasic, kRealm1, HttpAuth::AUTH_SERVER));
- cache.Add(origin, realm1_handler->realm(), realm1_handler->scheme(),
+ new MockAuthHandler(HttpAuth::AUTH_SCHEME_BASIC,
+ kRealm1,
+ HttpAuth::AUTH_SERVER));
+ cache.Add(origin, realm1_handler->realm(), realm1_handler->auth_scheme(),
"Basic realm=Realm1", ASCIIToUTF16("realm1-user"),
ASCIIToUTF16("realm1-password"), "/foo/bar/index.html");
scoped_ptr<HttpAuthHandler> realm2_handler(
- new MockAuthHandler(kBasic, kRealm2, HttpAuth::AUTH_SERVER));
- cache.Add(origin, realm2_handler->realm(), realm2_handler->scheme(),
+ new MockAuthHandler(HttpAuth::AUTH_SCHEME_BASIC,
+ kRealm2,
+ HttpAuth::AUTH_SERVER));
+ cache.Add(origin, realm2_handler->realm(), realm2_handler->auth_scheme(),
"Basic realm=Realm2", ASCIIToUTF16("realm2-user"),
ASCIIToUTF16("realm2-password"), "/foo2/index.html");
scoped_ptr<HttpAuthHandler> realm3_basic_handler(
- new MockAuthHandler(kBasic, kRealm3, HttpAuth::AUTH_PROXY));
+ new MockAuthHandler(HttpAuth::AUTH_SCHEME_BASIC,
+ kRealm3,
+ HttpAuth::AUTH_PROXY));
cache.Add(origin, realm3_basic_handler->realm(),
- realm3_basic_handler->scheme(), "Basic realm=Realm3",
+ realm3_basic_handler->auth_scheme(), "Basic realm=Realm3",
ASCIIToUTF16("realm3-basic-user"),
ASCIIToUTF16("realm3-basic-password"), "");
scoped_ptr<HttpAuthHandler> realm3_digest_handler(
- new MockAuthHandler(kDigest, kRealm3, HttpAuth::AUTH_PROXY));
+ new MockAuthHandler(HttpAuth::AUTH_SCHEME_DIGEST,
+ kRealm3,
+ HttpAuth::AUTH_PROXY));
cache.Add(origin, realm3_digest_handler->realm(),
- realm3_digest_handler->scheme(), "Digest realm=Realm3",
+ realm3_digest_handler->auth_scheme(), "Digest realm=Realm3",
ASCIIToUTF16("realm3-digest-user"),
ASCIIToUTF16("realm3-digest-password"), "/baz/index.html");
// There is no Realm4
- entry = cache.Lookup(origin, kRealm4, kBasic);
+ entry = cache.Lookup(origin, kRealm4, HttpAuth::AUTH_SCHEME_BASIC);
EXPECT_TRUE(NULL == entry);
// While Realm3 does exist, the origin scheme is wrong.
entry = cache.Lookup(GURL("https://www.google.com"), kRealm3,
- kBasic);
+ HttpAuth::AUTH_SCHEME_BASIC);
EXPECT_TRUE(NULL == entry);
// Realm, origin scheme ok, authentication scheme wrong
- entry = cache.Lookup(GURL("http://www.google.com"), kRealm1, kDigest);
+ entry = cache.Lookup
+ (GURL("http://www.google.com"), kRealm1, HttpAuth::AUTH_SCHEME_DIGEST);
EXPECT_TRUE(NULL == entry);
// Valid lookup by origin, realm, scheme.
- entry = cache.Lookup(GURL("http://www.google.com:80"), kRealm3, kBasic);
+ entry = cache.Lookup(
+ GURL("http://www.google.com:80"), kRealm3, HttpAuth::AUTH_SCHEME_BASIC);
ASSERT_FALSE(NULL == entry);
- EXPECT_EQ(kBasic, entry->scheme());
+ EXPECT_EQ(HttpAuth::AUTH_SCHEME_BASIC, entry->scheme());
EXPECT_EQ(kRealm3, entry->realm());
EXPECT_EQ("Basic realm=Realm3", entry->auth_challenge());
EXPECT_EQ(ASCIIToUTF16("realm3-basic-user"), entry->username());
@@ -129,25 +138,27 @@ TEST(HttpAuthCacheTest, Basic) {
// Valid lookup by origin, realm, scheme when there's a duplicate
// origin, realm in the cache
- entry = cache.Lookup(GURL("http://www.google.com:80"), kRealm3, kDigest);
+ entry = cache.Lookup(
+ GURL("http://www.google.com:80"), kRealm3, HttpAuth::AUTH_SCHEME_DIGEST);
ASSERT_FALSE(NULL == entry);
- EXPECT_EQ(kDigest, entry->scheme());
+ EXPECT_EQ(HttpAuth::AUTH_SCHEME_DIGEST, entry->scheme());
EXPECT_EQ(kRealm3, entry->realm());
EXPECT_EQ("Digest realm=Realm3", entry->auth_challenge());
EXPECT_EQ(ASCIIToUTF16("realm3-digest-user"), entry->username());
EXPECT_EQ(ASCIIToUTF16("realm3-digest-password"), entry->password());
// Valid lookup by realm.
- entry = cache.Lookup(origin, kRealm2, kBasic);
+ entry = cache.Lookup(origin, kRealm2, HttpAuth::AUTH_SCHEME_BASIC);
ASSERT_FALSE(NULL == entry);
- EXPECT_EQ(kBasic, entry->scheme());
+ EXPECT_EQ(HttpAuth::AUTH_SCHEME_BASIC, entry->scheme());
EXPECT_EQ(kRealm2, entry->realm());
EXPECT_EQ("Basic realm=Realm2", entry->auth_challenge());
EXPECT_EQ(ASCIIToUTF16("realm2-user"), entry->username());
EXPECT_EQ(ASCIIToUTF16("realm2-password"), entry->password());
// Check that subpaths are recognized.
- HttpAuthCache::Entry* realm2_entry = cache.Lookup(origin, kRealm2, kBasic);
+ HttpAuthCache::Entry* realm2_entry = cache.Lookup(
+ origin, kRealm2, HttpAuth::AUTH_SCHEME_BASIC);
EXPECT_FALSE(NULL == realm2_entry);
// Positive tests:
entry = cache.LookupByPath(origin, "/foo2/index.html");
@@ -171,7 +182,7 @@ TEST(HttpAuthCacheTest, Basic) {
// Confirm we find the same realm, different auth scheme by path lookup
HttpAuthCache::Entry* realm3_digest_entry =
- cache.Lookup(origin, kRealm3, kDigest);
+ cache.Lookup(origin, kRealm3, HttpAuth::AUTH_SCHEME_DIGEST);
EXPECT_FALSE(NULL == realm3_digest_entry);
entry = cache.LookupByPath(origin, "/baz/index.html");
EXPECT_TRUE(realm3_digest_entry == entry);
@@ -182,7 +193,7 @@ TEST(HttpAuthCacheTest, Basic) {
// Confirm we find the same realm, different auth scheme by path lookup
HttpAuthCache::Entry* realm3DigestEntry =
- cache.Lookup(origin, kRealm3, kDigest);
+ cache.Lookup(origin, kRealm3, HttpAuth::AUTH_SCHEME_DIGEST);
EXPECT_FALSE(NULL == realm3DigestEntry);
entry = cache.LookupByPath(origin, "/baz/index.html");
EXPECT_TRUE(realm3DigestEntry == entry);
@@ -194,7 +205,7 @@ TEST(HttpAuthCacheTest, Basic) {
// Lookup using empty path (may be used for proxy).
entry = cache.LookupByPath(origin, "");
EXPECT_FALSE(NULL == entry);
- EXPECT_EQ(kBasic, entry->scheme());
+ EXPECT_EQ(HttpAuth::AUTH_SCHEME_BASIC, entry->scheme());
EXPECT_EQ(kRealm3, entry->realm());
}
@@ -238,17 +249,18 @@ TEST(HttpAuthCacheTest, AddToExistingEntry) {
const std::string auth_challenge = "Basic realm=MyRealm";
scoped_ptr<HttpAuthHandler> handler(
- new MockAuthHandler(kBasic, "MyRealm", HttpAuth::AUTH_SERVER));
-
+ new MockAuthHandler(
+ HttpAuth::AUTH_SCHEME_BASIC, "MyRealm", HttpAuth::AUTH_SERVER));
HttpAuthCache::Entry* orig_entry = cache.Add(
- origin, handler->realm(), handler->scheme(), auth_challenge,
+ origin, handler->realm(), handler->auth_scheme(), auth_challenge,
ASCIIToUTF16("user1"), ASCIIToUTF16("password1"), "/x/y/z/");
- cache.Add(origin, handler->realm(), handler->scheme(), auth_challenge,
+ cache.Add(origin, handler->realm(), handler->auth_scheme(), auth_challenge,
ASCIIToUTF16("user2"), ASCIIToUTF16("password2"), "/z/y/x/");
- cache.Add(origin, handler->realm(), handler->scheme(), auth_challenge,
+ cache.Add(origin, handler->realm(), handler->auth_scheme(), auth_challenge,
ASCIIToUTF16("user3"), ASCIIToUTF16("password3"), "/z/y");
- HttpAuthCache::Entry* entry = cache.Lookup(origin, "MyRealm", kBasic);
+ HttpAuthCache::Entry* entry = cache.Lookup(
+ origin, "MyRealm", HttpAuth::AUTH_SCHEME_BASIC);
EXPECT_TRUE(entry == orig_entry);
EXPECT_EQ(ASCIIToUTF16("user3"), entry->username());
@@ -263,64 +275,80 @@ TEST(HttpAuthCacheTest, Remove) {
GURL origin("http://foobar2.com");
scoped_ptr<HttpAuthHandler> realm1_handler(
- new MockAuthHandler(kBasic, kRealm1, HttpAuth::AUTH_SERVER));
+ new MockAuthHandler(
+ HttpAuth::AUTH_SCHEME_BASIC, kRealm1, HttpAuth::AUTH_SERVER));
scoped_ptr<HttpAuthHandler> realm2_handler(
- new MockAuthHandler(kBasic, kRealm2, HttpAuth::AUTH_SERVER));
+ new MockAuthHandler(
+ HttpAuth::AUTH_SCHEME_BASIC, kRealm2, HttpAuth::AUTH_SERVER));
scoped_ptr<HttpAuthHandler> realm3_basic_handler(
- new MockAuthHandler(kBasic, kRealm3, HttpAuth::AUTH_SERVER));
+ new MockAuthHandler(
+ HttpAuth::AUTH_SCHEME_BASIC, kRealm3, HttpAuth::AUTH_SERVER));
scoped_ptr<HttpAuthHandler> realm3_digest_handler(
- new MockAuthHandler(kDigest, kRealm3, HttpAuth::AUTH_SERVER));
+ new MockAuthHandler(
+ HttpAuth::AUTH_SCHEME_DIGEST, kRealm3, HttpAuth::AUTH_SERVER));
HttpAuthCache cache;
- cache.Add(origin, realm1_handler->realm(), realm1_handler->scheme(),
+ cache.Add(origin, realm1_handler->realm(), realm1_handler->auth_scheme(),
"basic realm=Realm1", kAlice, k123, "/");
- cache.Add(origin, realm2_handler->realm(), realm2_handler->scheme(),
+ cache.Add(origin, realm2_handler->realm(), realm2_handler->auth_scheme(),
"basic realm=Realm2", ASCIIToUTF16("bob"), ASCIIToUTF16("princess"),
"/");
cache.Add(origin, realm3_basic_handler->realm(),
- realm3_basic_handler->scheme(), "basic realm=Realm3",
+ realm3_basic_handler->auth_scheme(), "basic realm=Realm3",
kAdmin, kPassword, "/");
cache.Add(origin, realm3_digest_handler->realm(),
- realm3_digest_handler->scheme(), "digest realm=Realm3",
+ realm3_digest_handler->auth_scheme(), "digest realm=Realm3",
kRoot, kWileCoyote, "/");
// Fails, because there is no realm "Realm4".
- EXPECT_FALSE(cache.Remove(origin, kRealm4, kBasic, kAlice, k123));
+ EXPECT_FALSE(cache.Remove(
+ origin, kRealm4, HttpAuth::AUTH_SCHEME_BASIC, kAlice, k123));
// Fails because the origin is wrong.
- EXPECT_FALSE(cache.Remove(
- GURL("http://foobar2.com:100"), kRealm1, kBasic, kAlice, k123));
+ EXPECT_FALSE(cache.Remove(GURL("http://foobar2.com:100"),
+ kRealm1,
+ HttpAuth::AUTH_SCHEME_BASIC,
+ kAlice,
+ k123));
// Fails because the username is wrong.
- EXPECT_FALSE(cache.Remove(origin, kRealm1, kBasic, kAlice2, k123));
+ EXPECT_FALSE(cache.Remove(
+ origin, kRealm1, HttpAuth::AUTH_SCHEME_BASIC, kAlice2, k123));
// Fails because the password is wrong.
- EXPECT_FALSE(cache.Remove(origin, kRealm1, kBasic, kAlice, k1234));
+ EXPECT_FALSE(cache.Remove(
+ origin, kRealm1, HttpAuth::AUTH_SCHEME_BASIC, kAlice, k1234));
// Fails because the authentication type is wrong.
- EXPECT_FALSE(cache.Remove(origin, kRealm1, kDigest, kAlice, k123));
+ EXPECT_FALSE(cache.Remove(
+ origin, kRealm1, HttpAuth::AUTH_SCHEME_DIGEST, kAlice, k123));
// Succeeds.
- EXPECT_TRUE(cache.Remove(origin, kRealm1, kBasic, kAlice, k123));
+ EXPECT_TRUE(cache.Remove(
+ origin, kRealm1, HttpAuth::AUTH_SCHEME_BASIC, kAlice, k123));
// Fails because we just deleted the entry!
- EXPECT_FALSE(cache.Remove(origin, kRealm1, kBasic, kAlice, k123));
+ EXPECT_FALSE(cache.Remove(
+ origin, kRealm1, HttpAuth::AUTH_SCHEME_BASIC, kAlice, k123));
// Succeed when there are two authentication types for the same origin,realm.
- EXPECT_TRUE(cache.Remove(origin, kRealm3, kDigest, kRoot, kWileCoyote));
+ EXPECT_TRUE(cache.Remove(
+ origin, kRealm3, HttpAuth::AUTH_SCHEME_DIGEST, kRoot, kWileCoyote));
// Succeed as above, but when entries were added in opposite order
cache.Add(origin, realm3_digest_handler->realm(),
- realm3_digest_handler->scheme(), "digest realm=Realm3",
+ realm3_digest_handler->auth_scheme(), "digest realm=Realm3",
kRoot, kWileCoyote, "/");
- EXPECT_TRUE(cache.Remove(origin, kRealm3, kBasic, kAdmin, kPassword));
+ EXPECT_TRUE(cache.Remove(
+ origin, kRealm3, HttpAuth::AUTH_SCHEME_BASIC, kAdmin, kPassword));
// Make sure that removing one entry still leaves the other available for
// lookup.
- HttpAuthCache::Entry* entry = cache.Lookup(origin, kRealm3, kDigest);
+ HttpAuthCache::Entry* entry = cache.Lookup(
+ origin, kRealm3, HttpAuth::AUTH_SCHEME_DIGEST);
EXPECT_FALSE(NULL == entry);
}
@@ -328,11 +356,12 @@ TEST(HttpAuthCacheTest, UpdateStaleChallenge) {
HttpAuthCache cache;
GURL origin("http://foobar2.com");
scoped_ptr<HttpAuthHandler> digest_handler(
- new MockAuthHandler(kDigest, kRealm1, HttpAuth::AUTH_PROXY));
+ new MockAuthHandler(
+ HttpAuth::AUTH_SCHEME_DIGEST, kRealm1, HttpAuth::AUTH_PROXY));
HttpAuthCache::Entry* entry_pre = cache.Add(
origin,
digest_handler->realm(),
- digest_handler->scheme(),
+ digest_handler->auth_scheme(),
"Digest realm=Realm1,"
"nonce=\"s3MzvFhaBAA=4c520af5acd9d8d7ae26947529d18c8eae1e98f4\"",
ASCIIToUTF16("realm-digest-user"),
@@ -347,7 +376,7 @@ TEST(HttpAuthCacheTest, UpdateStaleChallenge) {
bool update_success = cache.UpdateStaleChallenge(
origin,
digest_handler->realm(),
- digest_handler->scheme(),
+ digest_handler->auth_scheme(),
"Digest realm=Realm1,"
"nonce=\"claGgoRXBAA=7583377687842fdb7b56ba0555d175baa0b800e3\","
"stale=\"true\"");
@@ -358,7 +387,7 @@ TEST(HttpAuthCacheTest, UpdateStaleChallenge) {
HttpAuthCache::Entry* entry_post = cache.Lookup(
origin,
digest_handler->realm(),
- digest_handler->scheme());
+ digest_handler->auth_scheme());
ASSERT_TRUE(entry_post != NULL);
EXPECT_EQ(2, entry_post->IncrementNonceCount());
@@ -366,7 +395,7 @@ TEST(HttpAuthCacheTest, UpdateStaleChallenge) {
bool update_failure = cache.UpdateStaleChallenge(
origin,
kRealm2,
- digest_handler->scheme(),
+ digest_handler->auth_scheme(),
"Digest realm=Realm2,"
"nonce=\"claGgoRXBAA=7583377687842fdb7b56ba0555d175baa0b800e3\","
"stale=\"true\"");
@@ -392,13 +421,14 @@ class HttpAuthCacheEvictionTest : public testing::Test {
}
void AddPathToRealm(int realm_i, int path_i) {
- cache_.Add(origin_, GenerateRealm(realm_i), kBasic, "",
+ cache_.Add(origin_, GenerateRealm(realm_i), HttpAuth::AUTH_SCHEME_BASIC, "",
kUsername, kPassword, GeneratePath(realm_i, path_i));
}
void CheckRealmExistence(int realm_i, bool exists) {
const HttpAuthCache::Entry* entry =
- cache_.Lookup(origin_, GenerateRealm(realm_i), kBasic);
+ cache_.Lookup(
+ origin_, GenerateRealm(realm_i), HttpAuth::AUTH_SCHEME_BASIC);
if (exists) {
EXPECT_FALSE(entry == NULL);
EXPECT_EQ(GenerateRealm(realm_i), entry->realm());
diff --git a/net/http/http_auth_controller.cc b/net/http/http_auth_controller.cc
index ddd0bdb..f438ea4 100644
--- a/net/http/http_auth_controller.cc
+++ b/net/http/http_auth_controller.cc
@@ -96,8 +96,8 @@ void HistogramAuthEvent(HttpAuthHandler* handler, AuthEvent auth_event) {
DCHECK_EQ(first_thread, base::PlatformThread::CurrentId());
#endif
- HttpAuthHandler::AuthScheme auth_scheme = handler->auth_scheme();
- DCHECK(auth_scheme >= 0 && auth_scheme < HttpAuthHandler::AUTH_SCHEME_MAX);
+ HttpAuth::Scheme auth_scheme = handler->auth_scheme();
+ DCHECK(auth_scheme >= 0 && auth_scheme < HttpAuth::AUTH_SCHEME_MAX);
// Record start and rejection events for authentication.
//
@@ -111,7 +111,7 @@ void HistogramAuthEvent(HttpAuthHandler* handler, AuthEvent auth_event) {
// Negotiate Start: 6
// Negotiate Reject: 7
static const int kEventBucketsEnd =
- HttpAuthHandler::AUTH_SCHEME_MAX * AUTH_EVENT_MAX;
+ HttpAuth::AUTH_SCHEME_MAX * AUTH_EVENT_MAX;
int event_bucket = auth_scheme * AUTH_EVENT_MAX + auth_event;
DCHECK(event_bucket >= 0 && event_bucket < kEventBucketsEnd);
UMA_HISTOGRAM_ENUMERATION("Net.HttpAuthCount", event_bucket,
@@ -139,7 +139,7 @@ void HistogramAuthEvent(HttpAuthHandler* handler, AuthEvent auth_event) {
if (auth_event != AUTH_EVENT_START)
return;
static const int kTargetBucketsEnd =
- HttpAuthHandler::AUTH_SCHEME_MAX * AUTH_TARGET_MAX;
+ HttpAuth::AUTH_SCHEME_MAX * AUTH_TARGET_MAX;
AuthTarget auth_target = DetermineAuthTarget(handler);
int target_bucket = auth_scheme * AUTH_TARGET_MAX + auth_target;
DCHECK(target_bucket >= 0 && target_bucket < kTargetBucketsEnd);
@@ -282,7 +282,7 @@ int HttpAuthController::HandleAuthChallenge(
case HttpAuth::AUTHORIZATION_RESULT_STALE:
if (http_auth_cache_->UpdateStaleChallenge(auth_origin_,
handler_->realm(),
- handler_->scheme(),
+ handler_->auth_scheme(),
challenge_used)) {
handler_.reset();
identity_ = HttpAuth::Identity();
@@ -388,7 +388,7 @@ void HttpAuthController::ResetAuth(const string16& username,
break;
default:
http_auth_cache_->Add(auth_origin_, handler_->realm(),
- handler_->scheme(), handler_->challenge(),
+ handler_->auth_scheme(), handler_->challenge(),
identity_.username, identity_.password,
auth_path_);
break;
@@ -426,7 +426,7 @@ void HttpAuthController::InvalidateRejectedAuthFromCache() {
// Note: we require the username/password to match before invalidating
// since the entry in the cache may be newer than what we used last time.
http_auth_cache_->Remove(auth_origin_, handler_->realm(),
- handler_->scheme(), identity_.username,
+ handler_->auth_scheme(), identity_.username,
identity_.password);
}
@@ -453,7 +453,7 @@ bool HttpAuthController::SelectNextAuthIdentityToTry() {
// Check the auth cache for a realm entry.
HttpAuthCache::Entry* entry =
http_auth_cache_->Lookup(auth_origin_, handler_->realm(),
- handler_->scheme());
+ handler_->auth_scheme());
if (entry) {
identity_.source = HttpAuth::IDENT_SRC_REALM_LOOKUP;
@@ -487,7 +487,8 @@ void HttpAuthController::PopulateAuthChallenge() {
auth_info_ = new AuthChallengeInfo;
auth_info_->is_proxy = target_ == HttpAuth::AUTH_PROXY;
auth_info_->host_and_port = ASCIIToWide(GetHostAndPort(auth_origin_));
- auth_info_->scheme = ASCIIToWide(handler_->scheme());
+ auth_info_->scheme = ASCIIToWide(
+ HttpAuth::SchemeToString(handler_->auth_scheme()));
// TODO(eroman): decode realm according to RFC 2047.
auth_info_->realm = ASCIIToWide(handler_->realm());
}
@@ -497,7 +498,7 @@ void HttpAuthController::OnIOComplete(int result) {
// This error occurs with GSSAPI, if the user has not already logged in.
// In that case, disable the current scheme as it cannot succeed.
if (result == ERR_MISSING_AUTH_CREDENTIALS) {
- DisableAuthScheme(handler_->scheme());
+ DisableAuthScheme(handler_->auth_scheme());
auth_token_.clear();
result = OK;
}
@@ -513,12 +514,12 @@ scoped_refptr<AuthChallengeInfo> HttpAuthController::auth_info() {
return auth_info_;
}
-bool HttpAuthController::IsAuthSchemeDisabled(const std::string& scheme) const {
+bool HttpAuthController::IsAuthSchemeDisabled(HttpAuth::Scheme scheme) const {
DCHECK(CalledOnValidThread());
return disabled_schemes_.find(scheme) != disabled_schemes_.end();
}
-void HttpAuthController::DisableAuthScheme(const std::string& scheme) {
+void HttpAuthController::DisableAuthScheme(HttpAuth::Scheme scheme) {
DCHECK(CalledOnValidThread());
disabled_schemes_.insert(scheme);
}
diff --git a/net/http/http_auth_controller.h b/net/http/http_auth_controller.h
index 85d9fa1..0b7f430 100644
--- a/net/http/http_auth_controller.h
+++ b/net/http/http_auth_controller.h
@@ -69,8 +69,8 @@ class HttpAuthController : public base::RefCounted<HttpAuthController>,
virtual scoped_refptr<AuthChallengeInfo> auth_info();
- virtual bool IsAuthSchemeDisabled(const std::string& scheme) const;
- virtual void DisableAuthScheme(const std::string& scheme);
+ virtual bool IsAuthSchemeDisabled(HttpAuth::Scheme scheme) const;
+ virtual void DisableAuthScheme(HttpAuth::Scheme scheme);
private:
// So that we can mock this object.
@@ -146,7 +146,7 @@ class HttpAuthController : public base::RefCounted<HttpAuthController>,
HttpAuthCache* const http_auth_cache_;
HttpAuthHandlerFactory* const http_auth_handler_factory_;
- std::set<std::string> disabled_schemes_;
+ std::set<HttpAuth::Scheme> disabled_schemes_;
CompletionCallbackImpl<HttpAuthController> io_callback_;
CompletionCallback* user_callback_;
diff --git a/net/http/http_auth_filter.cc b/net/http/http_auth_filter.cc
index a61e7f7..2109e4d 100644
--- a/net/http/http_auth_filter.cc
+++ b/net/http/http_auth_filter.cc
@@ -24,21 +24,6 @@ HttpAuthFilterWhitelist::HttpAuthFilterWhitelist(
HttpAuthFilterWhitelist::~HttpAuthFilterWhitelist() {
}
-void HttpAuthFilterWhitelist::SetWhitelist(
- const std::string& server_whitelist) {
- rules_.ParseFromString(server_whitelist);
-}
-
-bool HttpAuthFilterWhitelist::IsValid(const GURL& url,
- HttpAuth::Target target) const {
- if ((target != HttpAuth::AUTH_SERVER) && (target != HttpAuth::AUTH_PROXY))
- return false;
- // All proxies pass
- if (target == HttpAuth::AUTH_PROXY)
- return true;
- return rules_.Matches(url);
-}
-
// Add a new domain |filter| to the whitelist, if it's not already there
bool HttpAuthFilterWhitelist::AddFilter(const std::string& filter,
HttpAuth::Target target) {
@@ -55,4 +40,19 @@ void HttpAuthFilterWhitelist::AddRuleToBypassLocal() {
rules_.AddRuleToBypassLocal();
}
+bool HttpAuthFilterWhitelist::IsValid(const GURL& url,
+ HttpAuth::Target target) const {
+ if ((target != HttpAuth::AUTH_SERVER) && (target != HttpAuth::AUTH_PROXY))
+ return false;
+ // All proxies pass
+ if (target == HttpAuth::AUTH_PROXY)
+ return true;
+ return rules_.Matches(url);
+}
+
+void HttpAuthFilterWhitelist::SetWhitelist(
+ const std::string& server_whitelist) {
+ rules_.ParseFromString(server_whitelist);
+}
+
} // namespace net
diff --git a/net/http/http_auth_filter.h b/net/http/http_auth_filter.h
index 334bc91..81d414c 100644
--- a/net/http/http_auth_filter.h
+++ b/net/http/http_auth_filter.h
@@ -37,9 +37,6 @@ class HttpAuthFilterWhitelist : public HttpAuthFilter {
explicit HttpAuthFilterWhitelist(const std::string& server_whitelist);
virtual ~HttpAuthFilterWhitelist();
- // HttpAuthFilter methods:
- virtual bool IsValid(const GURL& url, HttpAuth::Target target) const;
-
// Adds an individual URL |filter| to the list, of the specified |target|.
bool AddFilter(const std::string& filter, HttpAuth::Target target);
@@ -48,6 +45,9 @@ class HttpAuthFilterWhitelist : public HttpAuthFilter {
const ProxyBypassRules& rules() const { return rules_; }
+ // HttpAuthFilter methods:
+ virtual bool IsValid(const GURL& url, HttpAuth::Target target) const;
+
private:
// Installs the whitelist.
// |server_whitelist| is parsed by ProxyBypassRules.
diff --git a/net/http/http_auth_gssapi_posix_unittest.cc b/net/http/http_auth_gssapi_posix_unittest.cc
index f83acb4..43a3285 100644
--- a/net/http/http_auth_gssapi_posix_unittest.cc
+++ b/net/http/http_auth_gssapi_posix_unittest.cc
@@ -109,23 +109,20 @@ TEST(HttpAuthGSSAPIPOSIXTest, GSSAPICycle) {
1, // Locally initiated
1); // Open
test::MockGSSAPILibrary::SecurityContextQuery queries[] = {
- { "Negotiate", // Package name
- GSS_S_CONTINUE_NEEDED, // Major response code
- 0, // Minor response code
- context1, // Context
- { 0, NULL }, // Expected input token
- { arraysize(kAuthResponse),
- const_cast<char*>(kAuthResponse) } // Output token
- },
- { "Negotiate", // Package name
- GSS_S_COMPLETE, // Major response code
- 0, // Minor response code
- context2, // Context
- { arraysize(kAuthResponse),
- const_cast<char*>(kAuthResponse) }, // Expected input token
- { arraysize(kAuthResponse),
- const_cast<char*>(kAuthResponse) } // Output token
- },
+ test::MockGSSAPILibrary::SecurityContextQuery(
+ "Negotiate", // Package name
+ GSS_S_CONTINUE_NEEDED, // Major response code
+ 0, // Minor response code
+ context1, // Context
+ NULL, // Expected input token
+ kAuthResponse), // Output token
+ test::MockGSSAPILibrary::SecurityContextQuery(
+ "Negotiate", // Package name
+ GSS_S_COMPLETE, // Major response code
+ 0, // Minor response code
+ context2, // Context
+ kAuthResponse, // Expected input token
+ kAuthResponse) // Output token
};
for (size_t i = 0; i < arraysize(queries); ++i) {
diff --git a/net/http/http_auth_handler.cc b/net/http/http_auth_handler.cc
index 130123b..51bd6aa 100644
--- a/net/http/http_auth_handler.cc
+++ b/net/http/http_auth_handler.cc
@@ -5,14 +5,12 @@
#include "net/http/http_auth_handler.h"
#include "base/logging.h"
-#include "base/string_util.h"
-#include "base/stringprintf.h"
#include "net/base/net_errors.h"
namespace net {
HttpAuthHandler::HttpAuthHandler()
- : auth_scheme_(AUTH_SCHEME_MAX),
+ : auth_scheme_(HttpAuth::AUTH_SCHEME_MAX),
score_(-1),
target_(HttpAuth::AUTH_NONE),
properties_(-1),
@@ -41,10 +39,9 @@ bool HttpAuthHandler::InitFromChallenge(
// Init() is expected to set the scheme, realm, score, and properties. The
// realm may be empty.
- DCHECK(!ok || !scheme().empty());
DCHECK(!ok || score_ != -1);
DCHECK(!ok || properties_ != -1);
- DCHECK(!ok || auth_scheme_ != AUTH_SCHEME_MAX);
+ DCHECK(!ok || auth_scheme_ != HttpAuth::AUTH_SCHEME_MAX);
return ok;
}
diff --git a/net/http/http_auth_handler.h b/net/http/http_auth_handler.h
index 65340df..0a574e5 100644
--- a/net/http/http_auth_handler.h
+++ b/net/http/http_auth_handler.h
@@ -22,14 +22,6 @@ struct HttpRequestInfo;
// HttpAuthHandler objects are typically created by an HttpAuthHandlerFactory.
class HttpAuthHandler {
public:
- enum AuthScheme {
- AUTH_SCHEME_BASIC = 0,
- AUTH_SCHEME_DIGEST,
- AUTH_SCHEME_NTLM,
- AUTH_SCHEME_NEGOTIATE,
- AUTH_SCHEME_MAX,
- };
-
HttpAuthHandler();
virtual ~HttpAuthHandler();
@@ -84,15 +76,10 @@ class HttpAuthHandler {
std::string* auth_token);
// The authentication scheme as an enumerated value.
- AuthScheme auth_scheme() const {
+ HttpAuth::Scheme auth_scheme() const {
return auth_scheme_;
}
- // Lowercase name of the auth scheme
- const std::string& scheme() const {
- return scheme_;
- }
-
// The realm value that was parsed during Init().
const std::string& realm() const {
return realm_;
@@ -171,10 +158,7 @@ class HttpAuthHandler {
std::string* auth_token) = 0;
// The auth-scheme as an enumerated value.
- AuthScheme auth_scheme_;
-
- // The lowercase auth-scheme {"basic", "digest", "ntlm", "negotiate"}
- std::string scheme_;
+ HttpAuth::Scheme auth_scheme_;
// The realm. Used by "basic" and "digest".
std::string realm_;
diff --git a/net/http/http_auth_handler_basic.cc b/net/http/http_auth_handler_basic.cc
index 8ee775d..e48aa67 100644
--- a/net/http/http_auth_handler_basic.cc
+++ b/net/http/http_auth_handler_basic.cc
@@ -23,8 +23,7 @@ namespace net {
// We allow it to be compatibility with certain embedded webservers that don't
// include a realm (see http://crbug.com/20984.)
bool HttpAuthHandlerBasic::Init(HttpAuth::ChallengeTokenizer* challenge) {
- auth_scheme_ = AUTH_SCHEME_BASIC;
- scheme_ = "basic";
+ auth_scheme_ = HttpAuth::AUTH_SCHEME_BASIC;
score_ = 1;
properties_ = 0;
return ParseChallenge(challenge);
diff --git a/net/http/http_auth_handler_digest.cc b/net/http/http_auth_handler_digest.cc
index 2b103f4..e8cb819 100644
--- a/net/http/http_auth_handler_digest.cc
+++ b/net/http/http_auth_handler_digest.cc
@@ -74,46 +74,60 @@ std::string HttpAuthHandlerDigest::FixedNonceGenerator::GenerateNonce() const {
return nonce_;
}
-// static
-std::string HttpAuthHandlerDigest::QopToString(QualityOfProtection qop) {
- switch (qop) {
- case QOP_UNSPECIFIED:
- return "";
- case QOP_AUTH:
- return "auth";
- default:
- NOTREACHED();
- return "";
- }
+HttpAuthHandlerDigest::Factory::Factory()
+ : nonce_generator_(new DynamicNonceGenerator()) {
}
-// static
-std::string HttpAuthHandlerDigest::AlgorithmToString(
- DigestAlgorithm algorithm) {
- switch (algorithm) {
- case ALGORITHM_UNSPECIFIED:
- return "";
- case ALGORITHM_MD5:
- return "MD5";
- case ALGORITHM_MD5_SESS:
- return "MD5-sess";
- default:
- NOTREACHED();
- return "";
- }
+HttpAuthHandlerDigest::Factory::~Factory() {
}
-HttpAuthHandlerDigest::HttpAuthHandlerDigest(
- int nonce_count, const NonceGenerator* nonce_generator)
- : stale_(false),
- algorithm_(ALGORITHM_UNSPECIFIED),
- qop_(QOP_UNSPECIFIED),
- nonce_count_(nonce_count),
- nonce_generator_(nonce_generator) {
- DCHECK(nonce_generator_);
+void HttpAuthHandlerDigest::Factory::set_nonce_generator(
+ const NonceGenerator* nonce_generator) {
+ nonce_generator_.reset(nonce_generator);
}
-HttpAuthHandlerDigest::~HttpAuthHandlerDigest() {
+int HttpAuthHandlerDigest::Factory::CreateAuthHandler(
+ HttpAuth::ChallengeTokenizer* challenge,
+ HttpAuth::Target target,
+ const GURL& origin,
+ CreateReason reason,
+ int digest_nonce_count,
+ const BoundNetLog& net_log,
+ scoped_ptr<HttpAuthHandler>* handler) {
+ // TODO(cbentzel): Move towards model of parsing in the factory
+ // method and only constructing when valid.
+ scoped_ptr<HttpAuthHandler> tmp_handler(
+ new HttpAuthHandlerDigest(digest_nonce_count, nonce_generator_.get()));
+ if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
+ return ERR_INVALID_RESPONSE;
+ handler->swap(tmp_handler);
+ return OK;
+}
+
+HttpAuth::AuthorizationResult HttpAuthHandlerDigest::HandleAnotherChallenge(
+ HttpAuth::ChallengeTokenizer* challenge) {
+ // Even though Digest is not connection based, a "second round" is parsed
+ // to differentiate between stale and rejected responses.
+ // Note that the state of the current handler is not mutated - this way if
+ // there is a rejection the realm hasn't changed.
+ if (!LowerCaseEqualsASCII(challenge->scheme(), "digest"))
+ return HttpAuth::AUTHORIZATION_RESULT_INVALID;
+
+ HttpUtil::NameValuePairsIterator parameters = challenge->param_pairs();
+
+ // Try to find the "stale" value.
+ while (parameters.GetNext()) {
+ if (!LowerCaseEqualsASCII(parameters.name(), "stale"))
+ continue;
+ if (LowerCaseEqualsASCII(parameters.value(), "true"))
+ return HttpAuth::AUTHORIZATION_RESULT_STALE;
+ }
+
+ return HttpAuth::AUTHORIZATION_RESULT_REJECT;
+}
+
+bool HttpAuthHandlerDigest::Init(HttpAuth::ChallengeTokenizer* challenge) {
+ return ParseChallenge(challenge);
}
int HttpAuthHandlerDigest::GenerateAuthTokenImpl(
@@ -138,112 +152,17 @@ int HttpAuthHandlerDigest::GenerateAuthTokenImpl(
return OK;
}
-void HttpAuthHandlerDigest::GetRequestMethodAndPath(
- const HttpRequestInfo* request,
- std::string* method,
- std::string* path) const {
- DCHECK(request);
-
- const GURL& url = request->url;
-
- if (target_ == HttpAuth::AUTH_PROXY && url.SchemeIs("https")) {
- *method = "CONNECT";
- *path = GetHostAndPort(url);
- } else {
- *method = request->method;
- *path = HttpUtil::PathForRequest(url);
- }
-}
-
-std::string HttpAuthHandlerDigest::AssembleResponseDigest(
- const std::string& method,
- const std::string& path,
- const string16& username,
- const string16& password,
- const std::string& cnonce,
- const std::string& nc) const {
- // ha1 = MD5(A1)
- // TODO(eroman): is this the right encoding?
- std::string ha1 = MD5String(UTF16ToUTF8(username) + ":" + realm_ + ":" +
- UTF16ToUTF8(password));
- if (algorithm_ == HttpAuthHandlerDigest::ALGORITHM_MD5_SESS)
- ha1 = MD5String(ha1 + ":" + nonce_ + ":" + cnonce);
-
- // ha2 = MD5(A2)
- // TODO(eroman): need to add MD5(req-entity-body) for qop=auth-int.
- std::string ha2 = MD5String(method + ":" + path);
-
- std::string nc_part;
- if (qop_ != HttpAuthHandlerDigest::QOP_UNSPECIFIED) {
- nc_part = nc + ":" + cnonce + ":" + QopToString(qop_) + ":";
- }
-
- return MD5String(ha1 + ":" + nonce_ + ":" + nc_part + ha2);
-}
-
-std::string HttpAuthHandlerDigest::AssembleCredentials(
- const std::string& method,
- const std::string& path,
- const string16& username,
- const string16& password,
- const std::string& cnonce,
- int nonce_count) const {
- // the nonce-count is an 8 digit hex string.
- std::string nc = base::StringPrintf("%08x", nonce_count);
-
- // TODO(eroman): is this the right encoding?
- std::string authorization = (std::string("Digest username=") +
- HttpUtil::Quote(UTF16ToUTF8(username)));
- authorization += ", realm=" + HttpUtil::Quote(realm_);
- authorization += ", nonce=" + HttpUtil::Quote(nonce_);
- authorization += ", uri=" + HttpUtil::Quote(path);
-
- if (algorithm_ != ALGORITHM_UNSPECIFIED) {
- authorization += ", algorithm=" + AlgorithmToString(algorithm_);
- }
- std::string response = AssembleResponseDigest(method, path, username,
- password, cnonce, nc);
- // No need to call HttpUtil::Quote() as the response digest cannot contain
- // any characters needing to be escaped.
- authorization += ", response=\"" + response + "\"";
-
- if (!opaque_.empty()) {
- authorization += ", opaque=" + HttpUtil::Quote(opaque_);
- }
- if (qop_ != QOP_UNSPECIFIED) {
- // TODO(eroman): Supposedly IIS server requires quotes surrounding qop.
- authorization += ", qop=" + QopToString(qop_);
- authorization += ", nc=" + nc;
- authorization += ", cnonce=" + HttpUtil::Quote(cnonce);
- }
-
- return authorization;
-}
-
-bool HttpAuthHandlerDigest::Init(HttpAuth::ChallengeTokenizer* challenge) {
- return ParseChallenge(challenge);
+HttpAuthHandlerDigest::HttpAuthHandlerDigest(
+ int nonce_count, const NonceGenerator* nonce_generator)
+ : stale_(false),
+ algorithm_(ALGORITHM_UNSPECIFIED),
+ qop_(QOP_UNSPECIFIED),
+ nonce_count_(nonce_count),
+ nonce_generator_(nonce_generator) {
+ DCHECK(nonce_generator_);
}
-HttpAuth::AuthorizationResult HttpAuthHandlerDigest::HandleAnotherChallenge(
- HttpAuth::ChallengeTokenizer* challenge) {
- // Even though Digest is not connection based, a "second round" is parsed
- // to differentiate between stale and rejected responses.
- // Note that the state of the current handler is not mutated - this way if
- // there is a rejection the realm hasn't changed.
- if (!LowerCaseEqualsASCII(challenge->scheme(), "digest"))
- return HttpAuth::AUTHORIZATION_RESULT_INVALID;
-
- HttpUtil::NameValuePairsIterator parameters = challenge->param_pairs();
-
- // Try to find the "stale" value.
- while (parameters.GetNext()) {
- if (!LowerCaseEqualsASCII(parameters.name(), "stale"))
- continue;
- if (LowerCaseEqualsASCII(parameters.value(), "true"))
- return HttpAuth::AUTHORIZATION_RESULT_STALE;
- }
-
- return HttpAuth::AUTHORIZATION_RESULT_REJECT;
+HttpAuthHandlerDigest::~HttpAuthHandlerDigest() {
}
// The digest challenge header looks like:
@@ -266,8 +185,7 @@ HttpAuth::AuthorizationResult HttpAuthHandlerDigest::HandleAnotherChallenge(
// webserver was not sending the realm with a BASIC challenge).
bool HttpAuthHandlerDigest::ParseChallenge(
HttpAuth::ChallengeTokenizer* challenge) {
- auth_scheme_ = AUTH_SCHEME_DIGEST;
- scheme_ = "digest";
+ auth_scheme_ = HttpAuth::AUTH_SCHEME_DIGEST;
score_ = 2;
properties_ = ENCRYPTS_IDENTITY;
@@ -343,34 +261,115 @@ bool HttpAuthHandlerDigest::ParseChallengeProperty(const std::string& name,
return true;
}
-HttpAuthHandlerDigest::Factory::Factory()
- : nonce_generator_(new DynamicNonceGenerator()) {
+// static
+std::string HttpAuthHandlerDigest::QopToString(QualityOfProtection qop) {
+ switch (qop) {
+ case QOP_UNSPECIFIED:
+ return "";
+ case QOP_AUTH:
+ return "auth";
+ default:
+ NOTREACHED();
+ return "";
+ }
}
-HttpAuthHandlerDigest::Factory::~Factory() {
+// static
+std::string HttpAuthHandlerDigest::AlgorithmToString(
+ DigestAlgorithm algorithm) {
+ switch (algorithm) {
+ case ALGORITHM_UNSPECIFIED:
+ return "";
+ case ALGORITHM_MD5:
+ return "MD5";
+ case ALGORITHM_MD5_SESS:
+ return "MD5-sess";
+ default:
+ NOTREACHED();
+ return "";
+ }
}
-void HttpAuthHandlerDigest::Factory::set_nonce_generator(
- const NonceGenerator* nonce_generator) {
- nonce_generator_.reset(nonce_generator);
+void HttpAuthHandlerDigest::GetRequestMethodAndPath(
+ const HttpRequestInfo* request,
+ std::string* method,
+ std::string* path) const {
+ DCHECK(request);
+
+ const GURL& url = request->url;
+
+ if (target_ == HttpAuth::AUTH_PROXY && url.SchemeIs("https")) {
+ *method = "CONNECT";
+ *path = GetHostAndPort(url);
+ } else {
+ *method = request->method;
+ *path = HttpUtil::PathForRequest(url);
+ }
}
-int HttpAuthHandlerDigest::Factory::CreateAuthHandler(
- HttpAuth::ChallengeTokenizer* challenge,
- HttpAuth::Target target,
- const GURL& origin,
- CreateReason reason,
- int digest_nonce_count,
- const BoundNetLog& net_log,
- scoped_ptr<HttpAuthHandler>* handler) {
- // TODO(cbentzel): Move towards model of parsing in the factory
- // method and only constructing when valid.
- scoped_ptr<HttpAuthHandler> tmp_handler(
- new HttpAuthHandlerDigest(digest_nonce_count, nonce_generator_.get()));
- if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
- return ERR_INVALID_RESPONSE;
- handler->swap(tmp_handler);
- return OK;
+std::string HttpAuthHandlerDigest::AssembleResponseDigest(
+ const std::string& method,
+ const std::string& path,
+ const string16& username,
+ const string16& password,
+ const std::string& cnonce,
+ const std::string& nc) const {
+ // ha1 = MD5(A1)
+ // TODO(eroman): is this the right encoding?
+ std::string ha1 = MD5String(UTF16ToUTF8(username) + ":" + realm_ + ":" +
+ UTF16ToUTF8(password));
+ if (algorithm_ == HttpAuthHandlerDigest::ALGORITHM_MD5_SESS)
+ ha1 = MD5String(ha1 + ":" + nonce_ + ":" + cnonce);
+
+ // ha2 = MD5(A2)
+ // TODO(eroman): need to add MD5(req-entity-body) for qop=auth-int.
+ std::string ha2 = MD5String(method + ":" + path);
+
+ std::string nc_part;
+ if (qop_ != HttpAuthHandlerDigest::QOP_UNSPECIFIED) {
+ nc_part = nc + ":" + cnonce + ":" + QopToString(qop_) + ":";
+ }
+
+ return MD5String(ha1 + ":" + nonce_ + ":" + nc_part + ha2);
+}
+
+std::string HttpAuthHandlerDigest::AssembleCredentials(
+ const std::string& method,
+ const std::string& path,
+ const string16& username,
+ const string16& password,
+ const std::string& cnonce,
+ int nonce_count) const {
+ // the nonce-count is an 8 digit hex string.
+ std::string nc = base::StringPrintf("%08x", nonce_count);
+
+ // TODO(eroman): is this the right encoding?
+ std::string authorization = (std::string("Digest username=") +
+ HttpUtil::Quote(UTF16ToUTF8(username)));
+ authorization += ", realm=" + HttpUtil::Quote(realm_);
+ authorization += ", nonce=" + HttpUtil::Quote(nonce_);
+ authorization += ", uri=" + HttpUtil::Quote(path);
+
+ if (algorithm_ != ALGORITHM_UNSPECIFIED) {
+ authorization += ", algorithm=" + AlgorithmToString(algorithm_);
+ }
+ std::string response = AssembleResponseDigest(method, path, username,
+ password, cnonce, nc);
+ // No need to call HttpUtil::Quote() as the response digest cannot contain
+ // any characters needing to be escaped.
+ authorization += ", response=\"" + response + "\"";
+
+ if (!opaque_.empty()) {
+ authorization += ", opaque=" + HttpUtil::Quote(opaque_);
+ }
+ if (qop_ != QOP_UNSPECIFIED) {
+ // TODO(eroman): Supposedly IIS server requires quotes surrounding qop.
+ authorization += ", qop=" + QopToString(qop_);
+ authorization += ", nc=" + nc;
+ authorization += ", cnonce=" + HttpUtil::Quote(cnonce);
+ }
+
+ return authorization;
}
} // namespace net
diff --git a/net/http/http_auth_handler_digest.h b/net/http/http_auth_handler_digest.h
index c319f5d..fca77e4 100644
--- a/net/http/http_auth_handler_digest.h
+++ b/net/http/http_auth_handler_digest.h
@@ -62,6 +62,9 @@ class HttpAuthHandlerDigest : public HttpAuthHandler {
Factory();
virtual ~Factory();
+ // This factory owns the passed in |nonce_generator|.
+ void set_nonce_generator(const NonceGenerator* nonce_generator);
+
virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge,
HttpAuth::Target target,
const GURL& origin,
@@ -70,9 +73,6 @@ class HttpAuthHandlerDigest : public HttpAuthHandler {
const BoundNetLog& net_log,
scoped_ptr<HttpAuthHandler>* handler);
- // This factory owns the passed in |nonce_generator|.
- void set_nonce_generator(const NonceGenerator* nonce_generator);
-
private:
scoped_ptr<const NonceGenerator> nonce_generator_;
};
diff --git a/net/http/http_auth_handler_factory.cc b/net/http/http_auth_handler_factory.cc
index 7d34cff..8cf7d3e 100644
--- a/net/http/http_auth_handler_factory.cc
+++ b/net/http/http_auth_handler_factory.cc
@@ -79,6 +79,46 @@ bool IsSupportedScheme(const std::vector<std::string>& supported_schemes,
} // namespace
+HttpAuthHandlerRegistryFactory::HttpAuthHandlerRegistryFactory() {
+}
+
+HttpAuthHandlerRegistryFactory::~HttpAuthHandlerRegistryFactory() {
+ STLDeleteContainerPairSecondPointers(factory_map_.begin(),
+ factory_map_.end());
+}
+
+void HttpAuthHandlerRegistryFactory::SetURLSecurityManager(
+ const std::string& scheme,
+ URLSecurityManager* security_manager) {
+ HttpAuthHandlerFactory* factory = GetSchemeFactory(scheme);
+ if (factory)
+ factory->set_url_security_manager(security_manager);
+}
+
+void HttpAuthHandlerRegistryFactory::RegisterSchemeFactory(
+ const std::string& scheme,
+ HttpAuthHandlerFactory* factory) {
+ std::string lower_scheme = StringToLowerASCII(scheme);
+ FactoryMap::iterator it = factory_map_.find(lower_scheme);
+ if (it != factory_map_.end()) {
+ delete it->second;
+ }
+ if (factory)
+ factory_map_[lower_scheme] = factory;
+ else
+ factory_map_.erase(it);
+}
+
+HttpAuthHandlerFactory* HttpAuthHandlerRegistryFactory::GetSchemeFactory(
+ const std::string& scheme) const {
+ std::string lower_scheme = StringToLowerASCII(scheme);
+ FactoryMap::const_iterator it = factory_map_.find(lower_scheme);
+ if (it == factory_map_.end()) {
+ return NULL; // |scheme| is not registered.
+ }
+ return it->second;
+}
+
// static
HttpAuthHandlerRegistryFactory* HttpAuthHandlerRegistryFactory::Create(
const std::vector<std::string>& supported_schemes,
@@ -124,36 +164,6 @@ HttpAuthHandlerRegistryFactory* HttpAuthHandlerRegistryFactory::Create(
return registry_factory;
}
-HttpAuthHandlerRegistryFactory::HttpAuthHandlerRegistryFactory() {
-}
-
-HttpAuthHandlerRegistryFactory::~HttpAuthHandlerRegistryFactory() {
- STLDeleteContainerPairSecondPointers(factory_map_.begin(),
- factory_map_.end());
-}
-
-void HttpAuthHandlerRegistryFactory::SetURLSecurityManager(
- const std::string& scheme,
- URLSecurityManager* security_manager) {
- HttpAuthHandlerFactory* factory = GetSchemeFactory(scheme);
- if (factory)
- factory->set_url_security_manager(security_manager);
-}
-
-void HttpAuthHandlerRegistryFactory::RegisterSchemeFactory(
- const std::string& scheme,
- HttpAuthHandlerFactory* factory) {
- std::string lower_scheme = StringToLowerASCII(scheme);
- FactoryMap::iterator it = factory_map_.find(lower_scheme);
- if (it != factory_map_.end()) {
- delete it->second;
- }
- if (factory)
- factory_map_[lower_scheme] = factory;
- else
- factory_map_.erase(it);
-}
-
int HttpAuthHandlerRegistryFactory::CreateAuthHandler(
HttpAuth::ChallengeTokenizer* challenge,
HttpAuth::Target target,
@@ -178,14 +188,4 @@ int HttpAuthHandlerRegistryFactory::CreateAuthHandler(
digest_nonce_count, net_log, handler);
}
-HttpAuthHandlerFactory* HttpAuthHandlerRegistryFactory::GetSchemeFactory(
- const std::string& scheme) const {
- std::string lower_scheme = StringToLowerASCII(scheme);
- FactoryMap::const_iterator it = factory_map_.find(lower_scheme);
- if (it == factory_map_.end()) {
- return NULL; // |scheme| is not registered.
- }
- return it->second;
-}
-
} // namespace net
diff --git a/net/http/http_auth_handler_factory.h b/net/http/http_auth_handler_factory.h
index 2879aed..1e4134f 100644
--- a/net/http/http_auth_handler_factory.h
+++ b/net/http/http_auth_handler_factory.h
@@ -28,6 +28,11 @@ class HttpAuthHandlerRegistryFactory;
// objects that it creates.
class HttpAuthHandlerFactory {
public:
+ enum CreateReason {
+ CREATE_CHALLENGE, // Create a handler in response to a challenge.
+ CREATE_PREEMPTIVE, // Create a handler preemptively.
+ };
+
HttpAuthHandlerFactory() : url_security_manager_(NULL) {}
virtual ~HttpAuthHandlerFactory() {}
@@ -42,11 +47,6 @@ class HttpAuthHandlerFactory {
return url_security_manager_;
}
- enum CreateReason {
- CREATE_CHALLENGE, // Create a handler in response to a challenge.
- CREATE_PREEMPTIVE, // Create a handler preemptively.
- };
-
// Creates an HttpAuthHandler object based on the authentication
// challenge specified by |*challenge|. |challenge| must point to a valid
// non-NULL tokenizer.
@@ -152,16 +152,6 @@ class HttpAuthHandlerRegistryFactory : public HttpAuthHandlerFactory {
// registry factory is destroyed.
HttpAuthHandlerFactory* GetSchemeFactory(const std::string& scheme) const;
- // Creates an auth handler by dispatching out to the registered factories
- // based on the first token in |challenge|.
- virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge,
- HttpAuth::Target target,
- const GURL& origin,
- CreateReason reason,
- int digest_nonce_count,
- const BoundNetLog& net_log,
- scoped_ptr<HttpAuthHandler>* handler);
-
// Creates an HttpAuthHandlerRegistryFactory.
//
// |supported_schemes| is a list of authentication schemes. Valid values
@@ -189,6 +179,16 @@ class HttpAuthHandlerRegistryFactory : public HttpAuthHandlerFactory {
bool negotiate_disable_cname_lookup,
bool negotiate_enable_port);
+ // Creates an auth handler by dispatching out to the registered factories
+ // based on the first token in |challenge|.
+ virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge,
+ HttpAuth::Target target,
+ const GURL& origin,
+ CreateReason reason,
+ int digest_nonce_count,
+ const BoundNetLog& net_log,
+ scoped_ptr<HttpAuthHandler>* handler);
+
private:
typedef std::map<std::string, HttpAuthHandlerFactory*> FactoryMap;
diff --git a/net/http/http_auth_handler_factory_unittest.cc b/net/http/http_auth_handler_factory_unittest.cc
index 0b90f19..3145c4b 100644
--- a/net/http/http_auth_handler_factory_unittest.cc
+++ b/net/http/http_auth_handler_factory_unittest.cc
@@ -7,6 +7,7 @@
#include "net/base/net_errors.h"
#include "net/http/http_auth_handler.h"
#include "net/http/http_auth_handler_factory.h"
+#include "net/http/mock_allow_url_security_manager.h"
#include "net/http/url_security_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -97,7 +98,7 @@ TEST(HttpAuthHandlerFactoryTest, RegistryFactory) {
TEST(HttpAuthHandlerFactoryTest, DefaultFactory) {
scoped_ptr<HostResolver> host_resolver(new MockHostResolver());
- URLSecurityManagerAllow url_security_manager;
+ MockAllowURLSecurityManager url_security_manager;
scoped_ptr<HttpAuthHandlerRegistryFactory> http_auth_handler_factory(
HttpAuthHandlerFactory::CreateDefault(host_resolver.get()));
http_auth_handler_factory->SetURLSecurityManager(
@@ -114,7 +115,7 @@ TEST(HttpAuthHandlerFactoryTest, DefaultFactory) {
&handler);
EXPECT_EQ(OK, rv);
ASSERT_FALSE(handler.get() == NULL);
- EXPECT_STREQ("basic", handler->scheme().c_str());
+ EXPECT_EQ(HttpAuth::AUTH_SCHEME_BASIC, handler->auth_scheme());
EXPECT_STREQ("FooBar", handler->realm().c_str());
EXPECT_EQ(HttpAuth::AUTH_SERVER, handler->target());
EXPECT_FALSE(handler->encrypts_identity());
@@ -141,7 +142,7 @@ TEST(HttpAuthHandlerFactoryTest, DefaultFactory) {
&handler);
EXPECT_EQ(OK, rv);
ASSERT_FALSE(handler.get() == NULL);
- EXPECT_STREQ("digest", handler->scheme().c_str());
+ EXPECT_EQ(HttpAuth::AUTH_SCHEME_DIGEST, handler->auth_scheme());
EXPECT_STREQ("FooBar", handler->realm().c_str());
EXPECT_EQ(HttpAuth::AUTH_PROXY, handler->target());
EXPECT_TRUE(handler->encrypts_identity());
@@ -157,7 +158,7 @@ TEST(HttpAuthHandlerFactoryTest, DefaultFactory) {
&handler);
EXPECT_EQ(OK, rv);
ASSERT_FALSE(handler.get() == NULL);
- EXPECT_STREQ("ntlm", handler->scheme().c_str());
+ EXPECT_EQ(HttpAuth::AUTH_SCHEME_NTLM, handler->auth_scheme());
EXPECT_STREQ("", handler->realm().c_str());
EXPECT_EQ(HttpAuth::AUTH_SERVER, handler->target());
EXPECT_TRUE(handler->encrypts_identity());
@@ -173,7 +174,7 @@ TEST(HttpAuthHandlerFactoryTest, DefaultFactory) {
&handler);
EXPECT_EQ(OK, rv);
ASSERT_FALSE(handler.get() == NULL);
- EXPECT_STREQ("negotiate", handler->scheme().c_str());
+ EXPECT_EQ(HttpAuth::AUTH_SCHEME_NEGOTIATE, handler->auth_scheme());
EXPECT_STREQ("", handler->realm().c_str());
EXPECT_EQ(HttpAuth::AUTH_SERVER, handler->target());
EXPECT_TRUE(handler->encrypts_identity());
diff --git a/net/http/http_auth_handler_mock.cc b/net/http/http_auth_handler_mock.cc
index 0a49169..aad1bd1 100644
--- a/net/http/http_auth_handler_mock.cc
+++ b/net/http/http_auth_handler_mock.cc
@@ -71,14 +71,6 @@ void HttpAuthHandlerMock::SetGenerateExpectation(bool async, int rv) {
generate_rv_ = rv;
}
-bool HttpAuthHandlerMock::Init(HttpAuth::ChallengeTokenizer* challenge) {
- auth_scheme_ = AUTH_SCHEME_BASIC;
- scheme_ = "mock";
- score_ = 1;
- properties_ = connection_based_ ? IS_CONNECTION_BASED : 0;
- return true;
-}
-
HttpAuth::AuthorizationResult HttpAuthHandlerMock::HandleAnotherChallenge(
HttpAuth::ChallengeTokenizer* challenge) {
if (!is_connection_based())
@@ -88,6 +80,17 @@ HttpAuth::AuthorizationResult HttpAuthHandlerMock::HandleAnotherChallenge(
return HttpAuth::AUTHORIZATION_RESULT_ACCEPT;
}
+bool HttpAuthHandlerMock::NeedsIdentity() {
+ return first_round_;
+}
+
+bool HttpAuthHandlerMock::Init(HttpAuth::ChallengeTokenizer* challenge) {
+ auth_scheme_ = HttpAuth::AUTH_SCHEME_MOCK;
+ score_ = 1;
+ properties_ = connection_based_ ? IS_CONNECTION_BASED : 0;
+ return true;
+}
+
int HttpAuthHandlerMock::GenerateAuthTokenImpl(const string16* username,
const string16* password,
const HttpRequestInfo* request,
diff --git a/net/http/http_auth_handler_mock.h b/net/http/http_auth_handler_mock.h
index bef8b2b..473ca2e 100644
--- a/net/http/http_auth_handler_mock.h
+++ b/net/http/http_auth_handler_mock.h
@@ -29,32 +29,6 @@ class HttpAuthHandlerMock : public HttpAuthHandler {
RESOLVE_TESTED,
};
- HttpAuthHandlerMock();
-
- virtual ~HttpAuthHandlerMock();
-
- void SetResolveExpectation(Resolve resolve);
-
- virtual bool NeedsCanonicalName();
-
- virtual int ResolveCanonicalName(HostResolver* host_resolver,
- CompletionCallback* callback);
-
- virtual bool NeedsIdentity() { return first_round_; }
-
- void SetGenerateExpectation(bool async, int rv);
-
- void set_connection_based(bool connection_based) {
- connection_based_ = connection_based;
- }
-
- const GURL& request_url() const {
- return request_url_;
- }
-
- HttpAuth::AuthorizationResult HandleAnotherChallenge(
- HttpAuth::ChallengeTokenizer* challenge);
-
// The Factory class simply returns the same handler each time
// CreateAuthHandler is called.
class Factory : public HttpAuthHandlerFactory {
@@ -68,6 +42,7 @@ class HttpAuthHandlerMock : public HttpAuthHandler {
do_init_from_challenge_ = do_init_from_challenge;
}
+ // HttpAuthHandlerFactory:
virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge,
HttpAuth::Target target,
const GURL& origin,
@@ -81,6 +56,33 @@ class HttpAuthHandlerMock : public HttpAuthHandler {
bool do_init_from_challenge_;
};
+ HttpAuthHandlerMock();
+
+ virtual ~HttpAuthHandlerMock();
+
+ void SetResolveExpectation(Resolve resolve);
+
+ virtual bool NeedsCanonicalName();
+
+ virtual int ResolveCanonicalName(HostResolver* host_resolver,
+ CompletionCallback* callback);
+
+
+ void SetGenerateExpectation(bool async, int rv);
+
+ void set_connection_based(bool connection_based) {
+ connection_based_ = connection_based;
+ }
+
+ const GURL& request_url() const {
+ return request_url_;
+ }
+
+ // HttpAuthHandler:
+ virtual HttpAuth::AuthorizationResult HandleAnotherChallenge(
+ HttpAuth::ChallengeTokenizer* challenge);
+ virtual bool NeedsIdentity();
+
protected:
virtual bool Init(HttpAuth::ChallengeTokenizer* challenge);
diff --git a/net/http/http_auth_handler_negotiate.cc b/net/http/http_auth_handler_negotiate.cc
index 2544728..a96902d 100644
--- a/net/http/http_auth_handler_negotiate.cc
+++ b/net/http/http_auth_handler_negotiate.cc
@@ -16,6 +16,68 @@
namespace net {
+HttpAuthHandlerNegotiate::Factory::Factory()
+ : disable_cname_lookup_(false),
+ use_port_(false),
+#if defined(OS_WIN)
+ max_token_length_(0),
+ first_creation_(true),
+ is_unsupported_(false),
+#endif
+ auth_library_(NULL) {
+}
+
+HttpAuthHandlerNegotiate::Factory::~Factory() {
+}
+
+void HttpAuthHandlerNegotiate::Factory::set_host_resolver(
+ HostResolver* resolver) {
+ resolver_ = resolver;
+}
+
+int HttpAuthHandlerNegotiate::Factory::CreateAuthHandler(
+ HttpAuth::ChallengeTokenizer* challenge,
+ HttpAuth::Target target,
+ const GURL& origin,
+ CreateReason reason,
+ int digest_nonce_count,
+ const BoundNetLog& net_log,
+ scoped_ptr<HttpAuthHandler>* handler) {
+#if defined(OS_WIN)
+ if (is_unsupported_ || reason == CREATE_PREEMPTIVE)
+ return ERR_UNSUPPORTED_AUTH_SCHEME;
+ if (max_token_length_ == 0) {
+ int rv = DetermineMaxTokenLength(auth_library_.get(), NEGOSSP_NAME,
+ &max_token_length_);
+ if (rv == ERR_UNSUPPORTED_AUTH_SCHEME)
+ is_unsupported_ = true;
+ if (rv != OK)
+ return rv;
+ }
+ // TODO(cbentzel): Move towards model of parsing in the factory
+ // method and only constructing when valid.
+ scoped_ptr<HttpAuthHandler> tmp_handler(
+ new HttpAuthHandlerNegotiate(auth_library_.get(), max_token_length_,
+ url_security_manager(), resolver_,
+ disable_cname_lookup_, use_port_));
+ if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
+ return ERR_INVALID_RESPONSE;
+ handler->swap(tmp_handler);
+ return OK;
+#elif defined(OS_POSIX)
+ // TODO(ahendrickson): Move towards model of parsing in the factory
+ // method and only constructing when valid.
+ scoped_ptr<HttpAuthHandler> tmp_handler(
+ new HttpAuthHandlerNegotiate(auth_library_.get(), url_security_manager(),
+ resolver_, disable_cname_lookup_,
+ use_port_));
+ if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
+ return ERR_INVALID_RESPONSE;
+ handler->swap(tmp_handler);
+ return OK;
+#endif
+}
+
HttpAuthHandlerNegotiate::HttpAuthHandlerNegotiate(
AuthLibrary* auth_library,
#if defined(OS_WIN)
@@ -46,89 +108,6 @@ HttpAuthHandlerNegotiate::HttpAuthHandlerNegotiate(
HttpAuthHandlerNegotiate::~HttpAuthHandlerNegotiate() {
}
-int HttpAuthHandlerNegotiate::GenerateAuthTokenImpl(
- const string16* username,
- const string16* password,
- const HttpRequestInfo* request,
- CompletionCallback* callback,
- std::string* auth_token) {
- DCHECK(user_callback_ == NULL);
- DCHECK((username == NULL) == (password == NULL));
- DCHECK(auth_token_ == NULL);
- auth_token_ = auth_token;
- if (already_called_) {
- DCHECK((!has_username_and_password_ && username == NULL) ||
- (has_username_and_password_ && *username == username_ &&
- *password == password_));
- next_state_ = STATE_GENERATE_AUTH_TOKEN;
- } else {
- already_called_ = true;
- if (username) {
- has_username_and_password_ = true;
- username_ = *username;
- password_ = *password;
- }
- next_state_ = STATE_RESOLVE_CANONICAL_NAME;
- }
- int rv = DoLoop(OK);
- if (rv == ERR_IO_PENDING)
- user_callback_ = callback;
- return rv;
-}
-
-// The Negotiate challenge header looks like:
-// WWW-Authenticate: NEGOTIATE auth-data
-bool HttpAuthHandlerNegotiate::Init(HttpAuth::ChallengeTokenizer* challenge) {
-#if defined(OS_POSIX)
- if (!auth_system_.Init()) {
- VLOG(1) << "can't initialize GSSAPI library";
- return false;
- }
- // GSSAPI does not provide a way to enter username/password to
- // obtain a TGT. If the default credentials are not allowed for
- // a particular site (based on whitelist), fall back to a
- // different scheme.
- if (!AllowsDefaultCredentials())
- return false;
-#endif
- if (CanDelegate())
- auth_system_.Delegate();
- auth_scheme_ = AUTH_SCHEME_NEGOTIATE;
- scheme_ = "negotiate";
- score_ = 4;
- properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED;
- HttpAuth::AuthorizationResult auth_result =
- auth_system_.ParseChallenge(challenge);
- return (auth_result == HttpAuth::AUTHORIZATION_RESULT_ACCEPT);
-}
-
-HttpAuth::AuthorizationResult HttpAuthHandlerNegotiate::HandleAnotherChallenge(
- HttpAuth::ChallengeTokenizer* challenge) {
- return auth_system_.ParseChallenge(challenge);
-}
-
-// Require identity on first pass instead of second.
-bool HttpAuthHandlerNegotiate::NeedsIdentity() {
- return auth_system_.NeedsIdentity();
-}
-
-bool HttpAuthHandlerNegotiate::AllowsDefaultCredentials() {
- if (target_ == HttpAuth::AUTH_PROXY)
- return true;
- if (!url_security_manager_)
- return false;
- return url_security_manager_->CanUseDefaultCredentials(origin_);
-}
-
-bool HttpAuthHandlerNegotiate::CanDelegate() const {
- // TODO(cbentzel): Should delegation be allowed on proxies?
- if (target_ == HttpAuth::AUTH_PROXY)
- return false;
- if (!url_security_manager_)
- return false;
- return url_security_manager_->CanDelegate(origin_);
-}
-
std::wstring HttpAuthHandlerNegotiate::CreateSPN(
const AddressList& address_list, const GURL& origin) {
// Kerberos Web Server SPNs are in the form HTTP/<host>:<port> through SSPI,
@@ -178,6 +157,93 @@ std::wstring HttpAuthHandlerNegotiate::CreateSPN(
}
}
+HttpAuth::AuthorizationResult HttpAuthHandlerNegotiate::HandleAnotherChallenge(
+ HttpAuth::ChallengeTokenizer* challenge) {
+ return auth_system_.ParseChallenge(challenge);
+}
+
+// Require identity on first pass instead of second.
+bool HttpAuthHandlerNegotiate::NeedsIdentity() {
+ return auth_system_.NeedsIdentity();
+}
+
+bool HttpAuthHandlerNegotiate::AllowsDefaultCredentials() {
+ if (target_ == HttpAuth::AUTH_PROXY)
+ return true;
+ if (!url_security_manager_)
+ return false;
+ return url_security_manager_->CanUseDefaultCredentials(origin_);
+}
+
+// The Negotiate challenge header looks like:
+// WWW-Authenticate: NEGOTIATE auth-data
+bool HttpAuthHandlerNegotiate::Init(HttpAuth::ChallengeTokenizer* challenge) {
+#if defined(OS_POSIX)
+ if (!auth_system_.Init()) {
+ VLOG(1) << "can't initialize GSSAPI library";
+ return false;
+ }
+ // GSSAPI does not provide a way to enter username/password to
+ // obtain a TGT. If the default credentials are not allowed for
+ // a particular site (based on whitelist), fall back to a
+ // different scheme.
+ if (!AllowsDefaultCredentials())
+ return false;
+#endif
+ if (CanDelegate())
+ auth_system_.Delegate();
+ auth_scheme_ = HttpAuth::AUTH_SCHEME_NEGOTIATE;
+ score_ = 4;
+ properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED;
+ HttpAuth::AuthorizationResult auth_result =
+ auth_system_.ParseChallenge(challenge);
+ return (auth_result == HttpAuth::AUTHORIZATION_RESULT_ACCEPT);
+}
+
+int HttpAuthHandlerNegotiate::GenerateAuthTokenImpl(
+ const string16* username,
+ const string16* password,
+ const HttpRequestInfo* request,
+ CompletionCallback* callback,
+ std::string* auth_token) {
+ DCHECK(user_callback_ == NULL);
+ DCHECK((username == NULL) == (password == NULL));
+ DCHECK(auth_token_ == NULL);
+ auth_token_ = auth_token;
+ if (already_called_) {
+ DCHECK((!has_username_and_password_ && username == NULL) ||
+ (has_username_and_password_ && *username == username_ &&
+ *password == password_));
+ next_state_ = STATE_GENERATE_AUTH_TOKEN;
+ } else {
+ already_called_ = true;
+ if (username) {
+ has_username_and_password_ = true;
+ username_ = *username;
+ password_ = *password;
+ }
+ next_state_ = STATE_RESOLVE_CANONICAL_NAME;
+ }
+ int rv = DoLoop(OK);
+ if (rv == ERR_IO_PENDING)
+ user_callback_ = callback;
+ return rv;
+}
+
+void HttpAuthHandlerNegotiate::OnIOComplete(int result) {
+ int rv = DoLoop(result);
+ if (rv != ERR_IO_PENDING)
+ DoCallback(rv);
+}
+
+void HttpAuthHandlerNegotiate::DoCallback(int rv) {
+ DCHECK(rv != ERR_IO_PENDING);
+ DCHECK(user_callback_);
+ CompletionCallback* callback = user_callback_;
+ user_callback_ = NULL;
+ callback->Run(rv);
+}
+
int HttpAuthHandlerNegotiate::DoLoop(int result) {
DCHECK(next_state_ != STATE_NONE);
@@ -254,80 +320,13 @@ int HttpAuthHandlerNegotiate::DoGenerateAuthTokenComplete(int rv) {
return rv;
}
-void HttpAuthHandlerNegotiate::OnIOComplete(int result) {
- int rv = DoLoop(result);
- if (rv != ERR_IO_PENDING)
- DoCallback(rv);
-}
-
-void HttpAuthHandlerNegotiate::DoCallback(int rv) {
- DCHECK(rv != ERR_IO_PENDING);
- DCHECK(user_callback_);
- CompletionCallback* callback = user_callback_;
- user_callback_ = NULL;
- callback->Run(rv);
-}
-
-HttpAuthHandlerNegotiate::Factory::Factory()
- : disable_cname_lookup_(false),
- use_port_(false),
-#if defined(OS_WIN)
- max_token_length_(0),
- first_creation_(true),
- is_unsupported_(false),
-#endif
- auth_library_(NULL) {
-}
-
-HttpAuthHandlerNegotiate::Factory::~Factory() {
-}
-
-void HttpAuthHandlerNegotiate::Factory::set_host_resolver(
- HostResolver* resolver) {
- resolver_ = resolver;
-}
-
-int HttpAuthHandlerNegotiate::Factory::CreateAuthHandler(
- HttpAuth::ChallengeTokenizer* challenge,
- HttpAuth::Target target,
- const GURL& origin,
- CreateReason reason,
- int digest_nonce_count,
- const BoundNetLog& net_log,
- scoped_ptr<HttpAuthHandler>* handler) {
-#if defined(OS_WIN)
- if (is_unsupported_ || reason == CREATE_PREEMPTIVE)
- return ERR_UNSUPPORTED_AUTH_SCHEME;
- if (max_token_length_ == 0) {
- int rv = DetermineMaxTokenLength(auth_library_.get(), NEGOSSP_NAME,
- &max_token_length_);
- if (rv == ERR_UNSUPPORTED_AUTH_SCHEME)
- is_unsupported_ = true;
- if (rv != OK)
- return rv;
- }
- // TODO(cbentzel): Move towards model of parsing in the factory
- // method and only constructing when valid.
- scoped_ptr<HttpAuthHandler> tmp_handler(
- new HttpAuthHandlerNegotiate(auth_library_.get(), max_token_length_,
- url_security_manager(), resolver_,
- disable_cname_lookup_, use_port_));
- if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
- return ERR_INVALID_RESPONSE;
- handler->swap(tmp_handler);
- return OK;
-#elif defined(OS_POSIX)
- // TODO(ahendrickson): Move towards model of parsing in the factory
- // method and only constructing when valid.
- scoped_ptr<HttpAuthHandler> tmp_handler(
- new HttpAuthHandlerNegotiate(auth_library_.get(), url_security_manager(),
- resolver_, disable_cname_lookup_,
- use_port_));
- if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
- return ERR_INVALID_RESPONSE;
- handler->swap(tmp_handler);
- return OK;
-#endif
+bool HttpAuthHandlerNegotiate::CanDelegate() const {
+ // TODO(cbentzel): Should delegation be allowed on proxies?
+ if (target_ == HttpAuth::AUTH_PROXY)
+ return false;
+ if (!url_security_manager_)
+ return false;
+ return url_security_manager_->CanDelegate(origin_);
}
} // namespace net
diff --git a/net/http/http_auth_handler_negotiate.h b/net/http/http_auth_handler_negotiate.h
index a19d182..de2a6e6 100644
--- a/net/http/http_auth_handler_negotiate.h
+++ b/net/http/http_auth_handler_negotiate.h
@@ -64,6 +64,12 @@ class HttpAuthHandlerNegotiate : public HttpAuthHandler {
void set_host_resolver(HostResolver* host_resolver);
+ // Sets the system library to use, thereby assuming ownership of
+ // |auth_library|.
+ void set_library(AuthLibrary* auth_library) {
+ auth_library_.reset(auth_library);
+ }
+
virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge,
HttpAuth::Target target,
const GURL& origin,
@@ -72,12 +78,6 @@ class HttpAuthHandlerNegotiate : public HttpAuthHandler {
const BoundNetLog& net_log,
scoped_ptr<HttpAuthHandler>* handler);
- // Sets the system library to use, thereby assuming ownership of
- // |auth_library|.
- void set_library(AuthLibrary* auth_library) {
- auth_library_.reset(auth_library);
- }
-
private:
bool disable_cname_lookup_;
bool use_port_;
@@ -101,17 +101,16 @@ class HttpAuthHandlerNegotiate : public HttpAuthHandler {
virtual ~HttpAuthHandlerNegotiate();
- virtual bool NeedsIdentity();
-
- virtual bool AllowsDefaultCredentials();
-
- virtual HttpAuth::AuthorizationResult HandleAnotherChallenge(
- HttpAuth::ChallengeTokenizer* challenge);
-
// These are public for unit tests
std::wstring CreateSPN(const AddressList& address_list, const GURL& orign);
const std::wstring& spn() const { return spn_; }
+ // HttpAuthHandler:
+ virtual HttpAuth::AuthorizationResult HandleAnotherChallenge(
+ HttpAuth::ChallengeTokenizer* challenge);
+ virtual bool NeedsIdentity();
+ virtual bool AllowsDefaultCredentials();
+
protected:
virtual bool Init(HttpAuth::ChallengeTokenizer* challenge);
diff --git a/net/http/http_auth_handler_negotiate_unittest.cc b/net/http/http_auth_handler_negotiate_unittest.cc
index 684ff55..cdaa5f3 100644
--- a/net/http/http_auth_handler_negotiate_unittest.cc
+++ b/net/http/http_auth_handler_negotiate_unittest.cc
@@ -10,6 +10,7 @@
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
#include "net/http/http_request_info.h"
+#include "net/http/mock_allow_url_security_manager.h"
#if defined(OS_WIN)
#include "net/http/mock_sspi_library_win.h"
#elif defined(OS_POSIX)
@@ -36,7 +37,7 @@ class HttpAuthHandlerNegotiateTest : public PlatformTest {
resolver_->rules()->AddIPLiteralRule("alias", "10.0.0.2",
"canonical.example.com");
- url_security_manager_.reset(new URLSecurityManagerAllow());
+ url_security_manager_.reset(new MockAllowURLSecurityManager());
factory_.reset(new HttpAuthHandlerNegotiate::Factory());
factory_->set_url_security_manager(url_security_manager_.get());
factory_->set_library(auth_library_);
@@ -115,23 +116,20 @@ class HttpAuthHandlerNegotiateTest : public PlatformTest {
1, // Locally initiated
1); // Open
test::MockGSSAPILibrary::SecurityContextQuery queries[] = {
- { "Negotiate", // Package name
+ test::MockGSSAPILibrary::SecurityContextQuery(
+ "Negotiate", // Package name
GSS_S_CONTINUE_NEEDED, // Major response code
0, // Minor response code
context1, // Context
- { 0, NULL }, // Expected input token
- { arraysize(kAuthResponse),
- const_cast<char*>(kAuthResponse) } // Output token
- },
- { "Negotiate", // Package name
+ NULL, // Expected input token
+ kAuthResponse), // Output token
+ test::MockGSSAPILibrary::SecurityContextQuery(
+ "Negotiate", // Package name
GSS_S_COMPLETE, // Major response code
0, // Minor response code
context2, // Context
- { arraysize(kAuthResponse),
- const_cast<char*>(kAuthResponse) }, // Expected input token
- { arraysize(kAuthResponse),
- const_cast<char*>(kAuthResponse) } // Output token
- },
+ kAuthResponse, // Expected input token
+ kAuthResponse) // Output token
};
for (size_t i = 0; i < arraysize(queries); ++i) {
@@ -158,14 +156,13 @@ class HttpAuthHandlerNegotiateTest : public PlatformTest {
0, // Context flags
1, // Locally initiated
0); // Open
- test::MockGSSAPILibrary::SecurityContextQuery query = {
- "Negotiate", // Package name
- major_status, // Major response code
- minor_status, // Minor response code
- context, // Context
- { 0, NULL }, // Expected input token
- { 0, NULL } // Output token
- };
+ test::MockGSSAPILibrary::SecurityContextQuery query(
+ "Negotiate", // Package name
+ major_status, // Major response code
+ minor_status, // Minor response code
+ context, // Context
+ NULL, // Expected input token
+ NULL); // Output token
mock_library->ExpectSecurityContext(query.expected_package,
query.response_code,
diff --git a/net/http/http_auth_handler_ntlm.cc b/net/http/http_auth_handler_ntlm.cc
index f987e48..5090918 100644
--- a/net/http/http_auth_handler_ntlm.cc
+++ b/net/http/http_auth_handler_ntlm.cc
@@ -15,6 +15,19 @@
namespace net {
+HttpAuth::AuthorizationResult HttpAuthHandlerNTLM::HandleAnotherChallenge(
+ HttpAuth::ChallengeTokenizer* challenge) {
+ return ParseChallenge(challenge, false);
+}
+
+bool HttpAuthHandlerNTLM::Init(HttpAuth::ChallengeTokenizer* tok) {
+ auth_scheme_ = HttpAuth::AUTH_SCHEME_NTLM;
+ score_ = 3;
+ properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED;
+
+ return ParseChallenge(tok, true) == HttpAuth::AUTHORIZATION_RESULT_ACCEPT;
+}
+
int HttpAuthHandlerNTLM::GenerateAuthTokenImpl(
const string16* username,
const string16* password,
@@ -92,20 +105,6 @@ int HttpAuthHandlerNTLM::GenerateAuthTokenImpl(
#endif
}
-bool HttpAuthHandlerNTLM::Init(HttpAuth::ChallengeTokenizer* tok) {
- auth_scheme_ = AUTH_SCHEME_NTLM;
- scheme_ = "ntlm";
- score_ = 3;
- properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED;
-
- return ParseChallenge(tok, true) == HttpAuth::AUTHORIZATION_RESULT_ACCEPT;
-}
-
-HttpAuth::AuthorizationResult HttpAuthHandlerNTLM::HandleAnotherChallenge(
- HttpAuth::ChallengeTokenizer* challenge) {
- return ParseChallenge(challenge, false);
-}
-
// The NTLM challenge header looks like:
// WWW-Authenticate: NTLM auth-data
HttpAuth::AuthorizationResult HttpAuthHandlerNTLM::ParseChallenge(
diff --git a/net/http/http_auth_handler_ntlm.h b/net/http/http_auth_handler_ntlm.h
index 831e43d..ae7c78b 100644
--- a/net/http/http_auth_handler_ntlm.h
+++ b/net/http/http_auth_handler_ntlm.h
@@ -114,6 +114,10 @@ class HttpAuthHandlerNTLM : public HttpAuthHandler {
HttpAuth::ChallengeTokenizer* challenge);
protected:
+ // This function acquires a credentials handle in the SSPI implementation.
+ // It does nothing in the portable implementation.
+ int InitializeBeforeFirstChallenge();
+
virtual bool Init(HttpAuth::ChallengeTokenizer* tok);
virtual int GenerateAuthTokenImpl(const string16* username,
@@ -122,10 +126,6 @@ class HttpAuthHandlerNTLM : public HttpAuthHandler {
CompletionCallback* callback,
std::string* auth_token);
- // This function acquires a credentials handle in the SSPI implementation.
- // It does nothing in the portable implementation.
- int InitializeBeforeFirstChallenge();
-
private:
~HttpAuthHandlerNTLM();
diff --git a/net/http/http_auth_handler_ntlm_portable.cc b/net/http/http_auth_handler_ntlm_portable.cc
index d3abc98..fac37c8 100644
--- a/net/http/http_auth_handler_ntlm_portable.cc
+++ b/net/http/http_auth_handler_ntlm_portable.cc
@@ -643,14 +643,11 @@ HttpAuthHandlerNTLM::get_host_name_proc_ = GetHostName;
HttpAuthHandlerNTLM::HttpAuthHandlerNTLM() {
}
-HttpAuthHandlerNTLM::~HttpAuthHandlerNTLM() {
- // Wipe our copy of the password from memory, to reduce the chance of being
- // written to the paging file on disk.
- ZapString(&password_);
-}
-
bool HttpAuthHandlerNTLM::NeedsIdentity() {
- return !auth_data_.empty();
+ // This gets called for each round-trip. Only require identity on
+ // the first call (when auth_data_ is empty). On subsequent calls,
+ // we use the initially established identity.
+ return auth_data_.empty();
}
bool HttpAuthHandlerNTLM::AllowsDefaultCredentials() {
@@ -659,6 +656,16 @@ bool HttpAuthHandlerNTLM::AllowsDefaultCredentials() {
return false;
}
+int HttpAuthHandlerNTLM::InitializeBeforeFirstChallenge() {
+ return OK;
+}
+
+HttpAuthHandlerNTLM::~HttpAuthHandlerNTLM() {
+ // Wipe our copy of the password from memory, to reduce the chance of being
+ // written to the paging file on disk.
+ ZapString(&password_);
+}
+
// static
HttpAuthHandlerNTLM::GenerateRandomProc
HttpAuthHandlerNTLM::SetGenerateRandomProc(
@@ -676,6 +683,12 @@ HttpAuthHandlerNTLM::HostNameProc HttpAuthHandlerNTLM::SetHostNameProc(
return old_proc;
}
+HttpAuthHandlerNTLM::Factory::Factory() {
+}
+
+HttpAuthHandlerNTLM::Factory::~Factory() {
+}
+
int HttpAuthHandlerNTLM::GetNextToken(const void* in_token,
uint32 in_token_len,
void** out_token,
@@ -702,16 +715,6 @@ int HttpAuthHandlerNTLM::GetNextToken(const void* in_token,
return rv;
}
-int HttpAuthHandlerNTLM::InitializeBeforeFirstChallenge() {
- return OK;
-}
-
-HttpAuthHandlerNTLM::Factory::Factory() {
-}
-
-HttpAuthHandlerNTLM::Factory::~Factory() {
-}
-
int HttpAuthHandlerNTLM::Factory::CreateAuthHandler(
HttpAuth::ChallengeTokenizer* challenge,
HttpAuth::Target target,
diff --git a/net/http/http_auth_sspi_win.cc b/net/http/http_auth_sspi_win.cc
index c5264cd..1a629f1 100644
--- a/net/http/http_auth_sspi_win.cc
+++ b/net/http/http_auth_sspi_win.cc
@@ -27,6 +27,9 @@ int MapAcquireCredentialsStatusToError(SECURITY_STATUS status,
case SEC_E_INSUFFICIENT_MEMORY:
return ERR_OUT_OF_MEMORY;
case SEC_E_INTERNAL_ERROR:
+ LOG(WARNING)
+ << "AcquireCredentialsHandle returned unexpected status 0x"
+ << std::hex << status;
return ERR_UNEXPECTED_SECURITY_LIBRARY_STATUS;
case SEC_E_NO_CREDENTIALS:
case SEC_E_NOT_OWNER:
@@ -37,7 +40,7 @@ int MapAcquireCredentialsStatusToError(SECURITY_STATUS status,
return ERR_UNSUPPORTED_AUTH_SCHEME;
default:
LOG(WARNING)
- << "AcquireSecurityCredentials returned undocumented status 0x"
+ << "AcquireCredentialsHandle returned undocumented status 0x"
<< std::hex << status;
return ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS;
}
diff --git a/net/http/http_auth_unittest.cc b/net/http/http_auth_unittest.cc
index 63ae3b0..6788be2 100644
--- a/net/http/http_auth_unittest.cc
+++ b/net/http/http_auth_unittest.cc
@@ -17,6 +17,7 @@
#include "net/http/http_auth_handler_mock.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
+#include "net/http/mock_allow_url_security_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
@@ -26,7 +27,7 @@ namespace {
HttpAuthHandlerMock* CreateMockHandler(bool connection_based) {
HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
auth_handler->set_connection_based(connection_based);
- std::string challenge_text = "Mock";
+ std::string challenge_text = "Basic";
HttpAuth::ChallengeTokenizer challenge(challenge_text.begin(),
challenge_text.end());
GURL origin("www.example.com");
@@ -48,7 +49,7 @@ HttpAuth::AuthorizationResult HandleChallengeResponse(
std::string* challenge_used) {
scoped_ptr<HttpAuthHandlerMock> mock_handler(
CreateMockHandler(connection_based));
- std::set<std::string> disabled_schemes;
+ std::set<HttpAuth::Scheme> disabled_schemes;
scoped_refptr<HttpResponseHeaders> headers(
HeadersFromResponseText(headers_text));
return HttpAuth::HandleChallengeResponse(
@@ -64,57 +65,58 @@ HttpAuth::AuthorizationResult HandleChallengeResponse(
TEST(HttpAuthTest, ChooseBestChallenge) {
static const struct {
const char* headers;
- const char* challenge_scheme;
+ HttpAuth::Scheme challenge_scheme;
const char* challenge_realm;
} tests[] = {
{
+ // Basic is the only challenge type, pick it.
"Y: Digest realm=\"X\", nonce=\"aaaaaaaaaa\"\n"
"www-authenticate: Basic realm=\"BasicRealm\"\n",
- // Basic is the only challenge type, pick it.
- "basic",
+ HttpAuth::AUTH_SCHEME_BASIC,
"BasicRealm",
},
{
+ // Fake is the only challenge type, but it is unsupported.
"Y: Digest realm=\"FooBar\", nonce=\"aaaaaaaaaa\"\n"
"www-authenticate: Fake realm=\"FooBar\"\n",
- // Fake is the only challenge type, but it is unsupported.
- "",
+ HttpAuth::AUTH_SCHEME_MAX,
"",
},
{
+ // Pick Digest over Basic.
"www-authenticate: Basic realm=\"FooBar\"\n"
"www-authenticate: Fake realm=\"FooBar\"\n"
"www-authenticate: nonce=\"aaaaaaaaaa\"\n"
"www-authenticate: Digest realm=\"DigestRealm\", nonce=\"aaaaaaaaaa\"\n",
- // Pick Digset over Basic
- "digest",
+ HttpAuth::AUTH_SCHEME_DIGEST,
"DigestRealm",
},
{
+ // Handle an empty header correctly.
"Y: Digest realm=\"X\", nonce=\"aaaaaaaaaa\"\n"
"www-authenticate:\n",
- // Handle null header value.
- "",
+ HttpAuth::AUTH_SCHEME_MAX,
"",
},
{
- "WWW-Authenticate: Negotiate\n"
- "WWW-Authenticate: NTLM\n",
-
+ // Choose Negotiate over NTLM on all platforms.
// TODO(ahendrickson): This may be flaky on Linux and OSX as it
// relies on being able to load one of the known .so files
// for gssapi.
- "negotiate",
+ "WWW-Authenticate: Negotiate\n"
+ "WWW-Authenticate: NTLM\n",
+
+ HttpAuth::AUTH_SCHEME_NEGOTIATE,
"",
}
};
GURL origin("http://www.example.com");
- std::set<std::string> disabled_schemes;
- URLSecurityManagerAllow url_security_manager;
+ std::set<HttpAuth::Scheme> disabled_schemes;
+ MockAllowURLSecurityManager url_security_manager;
scoped_ptr<HostResolver> host_resolver(new MockHostResolver());
scoped_ptr<HttpAuthHandlerRegistryFactory> http_auth_handler_factory(
HttpAuthHandlerFactory::CreateDefault(host_resolver.get()));
@@ -138,10 +140,10 @@ TEST(HttpAuthTest, ChooseBestChallenge) {
&handler);
if (handler.get()) {
- EXPECT_STREQ(tests[i].challenge_scheme, handler->scheme().c_str());
+ EXPECT_EQ(tests[i].challenge_scheme, handler->auth_scheme());
EXPECT_STREQ(tests[i].challenge_realm, handler->realm().c_str());
} else {
- EXPECT_STREQ("", tests[i].challenge_scheme);
+ EXPECT_EQ(HttpAuth::AUTH_SCHEME_MAX, tests[i].challenge_scheme);
EXPECT_STREQ("", tests[i].challenge_realm);
}
}
diff --git a/net/http/http_basic_stream.cc b/net/http/http_basic_stream.cc
index 061bb30..3e69d7a 100644
--- a/net/http/http_basic_stream.cc
+++ b/net/http/http_basic_stream.cc
@@ -25,6 +25,8 @@ HttpBasicStream::HttpBasicStream(ClientSocketHandle* connection,
request_info_(NULL) {
}
+HttpBasicStream::~HttpBasicStream() {}
+
int HttpBasicStream::InitializeStream(const HttpRequestInfo* request_info,
const BoundNetLog& net_log,
CompletionCallback* callback) {
@@ -52,8 +54,6 @@ int HttpBasicStream::SendRequest(const HttpRequestHeaders& headers,
callback);
}
-HttpBasicStream::~HttpBasicStream() {}
-
uint64 HttpBasicStream::GetUploadProgress() const {
return parser_->GetUploadProgress();
}
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc
index 5710491..7c35f69 100644
--- a/net/http/http_cache.cc
+++ b/net/http/http_cache.cc
@@ -34,10 +34,38 @@
#include "net/http/http_response_info.h"
#include "net/http/http_util.h"
#include "net/socket/ssl_host_info.h"
-#include "net/spdy/spdy_session_pool.h"
namespace net {
+namespace {
+
+HttpNetworkSession* CreateNetworkSession(
+ HostResolver* host_resolver,
+ CertVerifier* cert_verifier,
+ DnsRRResolver* dnsrr_resolver,
+ DnsCertProvenanceChecker* dns_cert_checker,
+ ProxyService* proxy_service,
+ SSLHostInfoFactory* ssl_host_info_factory,
+ SSLConfigService* ssl_config_service,
+ HttpAuthHandlerFactory* http_auth_handler_factory,
+ HttpNetworkDelegate* network_delegate,
+ NetLog* net_log) {
+ HttpNetworkSession::Params params;
+ params.host_resolver = host_resolver;
+ params.cert_verifier = cert_verifier;
+ params.dnsrr_resolver = dnsrr_resolver;
+ params.dns_cert_checker = dns_cert_checker;
+ params.proxy_service = proxy_service;
+ params.ssl_host_info_factory = ssl_host_info_factory;
+ params.ssl_config_service = ssl_config_service;
+ params.http_auth_handler_factory = http_auth_handler_factory;
+ params.network_delegate = network_delegate;
+ params.net_log = net_log;
+ return new HttpNetworkSession(params);
+}
+
+} // namespace
+
HttpCache::DefaultBackend::DefaultBackend(CacheType type,
const FilePath& path,
int max_bytes,
@@ -264,21 +292,23 @@ void HttpCache::MetadataWriter::OnIOComplete(int result) {
class HttpCache::SSLHostInfoFactoryAdaptor : public SSLHostInfoFactory {
public:
- explicit SSLHostInfoFactoryAdaptor(HttpCache* http_cache)
- : http_cache_(http_cache) {
+ SSLHostInfoFactoryAdaptor(CertVerifier* cert_verifier, HttpCache* http_cache)
+ : cert_verifier_(cert_verifier),
+ http_cache_(http_cache) {
}
- SSLHostInfo* GetForHost(const std::string& hostname,
- const SSLConfig& ssl_config) {
- return new DiskCacheBasedSSLHostInfo(hostname, ssl_config, http_cache_);
+ virtual SSLHostInfo* GetForHost(const std::string& hostname,
+ const SSLConfig& ssl_config) {
+ return new DiskCacheBasedSSLHostInfo(
+ hostname, ssl_config, cert_verifier_, http_cache_);
}
private:
+ CertVerifier* const cert_verifier_;
HttpCache* const http_cache_;
};
//-----------------------------------------------------------------------------
-
HttpCache::HttpCache(HostResolver* host_resolver,
CertVerifier* cert_verifier,
DnsRRResolver* dnsrr_resolver,
@@ -294,22 +324,35 @@ HttpCache::HttpCache(HostResolver* host_resolver,
building_backend_(false),
mode_(NORMAL),
ssl_host_info_factory_(new SSLHostInfoFactoryAdaptor(
- ALLOW_THIS_IN_INITIALIZER_LIST(this))),
- network_layer_(HttpNetworkLayer::CreateFactory(host_resolver,
- cert_verifier, dnsrr_resolver, dns_cert_checker_,
- ssl_host_info_factory_.get(),
- proxy_service, ssl_config_service,
- http_auth_handler_factory, network_delegate, net_log)),
+ cert_verifier,
+ ALLOW_THIS_IN_INITIALIZER_LIST(this))),
+ network_layer_(
+ new HttpNetworkLayer(
+ CreateNetworkSession(
+ host_resolver,
+ cert_verifier,
+ dnsrr_resolver,
+ dns_cert_checker_,
+ proxy_service,
+ ssl_host_info_factory_.get(),
+ ssl_config_service,
+ http_auth_handler_factory,
+ network_delegate,
+ net_log))),
ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)) {
}
+
HttpCache::HttpCache(HttpNetworkSession* session,
BackendFactory* backend_factory)
: net_log_(session->net_log()),
backend_factory_(backend_factory),
building_backend_(false),
mode_(NORMAL),
- network_layer_(HttpNetworkLayer::CreateFactory(session)),
+ ssl_host_info_factory_(new SSLHostInfoFactoryAdaptor(
+ session->cert_verifier(),
+ ALLOW_THIS_IN_INITIALIZER_LIST(this))),
+ network_layer_(new HttpNetworkLayer(session)),
ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)) {
}
@@ -383,29 +426,6 @@ disk_cache::Backend* HttpCache::GetCurrentBackend() {
return disk_cache_.get();
}
-int HttpCache::CreateTransaction(scoped_ptr<HttpTransaction>* trans) {
- // Do lazy initialization of disk cache if needed.
- if (!disk_cache_.get())
- CreateBackend(NULL, NULL); // We don't care about the result.
-
- trans->reset(new HttpCache::Transaction(this));
- return OK;
-}
-
-HttpCache* HttpCache::GetCache() {
- return this;
-}
-
-HttpNetworkSession* HttpCache::GetSession() {
- net::HttpNetworkLayer* network =
- static_cast<net::HttpNetworkLayer*>(network_layer_.get());
- return network->GetSession();
-}
-
-void HttpCache::Suspend(bool suspend) {
- network_layer_->Suspend(suspend);
-}
-
// static
bool HttpCache::ParseResponseInfo(const char* data, int len,
HttpResponseInfo* response_info,
@@ -442,6 +462,29 @@ void HttpCache::CloseCurrentConnections() {
}
}
+int HttpCache::CreateTransaction(scoped_ptr<HttpTransaction>* trans) {
+ // Do lazy initialization of disk cache if needed.
+ if (!disk_cache_.get())
+ CreateBackend(NULL, NULL); // We don't care about the result.
+
+ trans->reset(new HttpCache::Transaction(this));
+ return OK;
+}
+
+HttpCache* HttpCache::GetCache() {
+ return this;
+}
+
+HttpNetworkSession* HttpCache::GetSession() {
+ net::HttpNetworkLayer* network =
+ static_cast<net::HttpNetworkLayer*>(network_layer_.get());
+ return network->GetSession();
+}
+
+void HttpCache::Suspend(bool suspend) {
+ network_layer_->Suspend(suspend);
+}
+
//-----------------------------------------------------------------------------
int HttpCache::CreateBackend(disk_cache::Backend** backend,
diff --git a/net/http/http_cache.h b/net/http/http_cache.h
index 0641ca4..cdbddfe 100644
--- a/net/http/http_cache.h
+++ b/net/http/http_cache.h
@@ -60,8 +60,6 @@ class HttpCache : public HttpTransactionFactory,
public base::SupportsWeakPtr<HttpCache>,
public base::NonThreadSafe {
public:
- ~HttpCache();
-
// The cache mode of operation.
enum Mode {
// Normal mode just behaves like a standard web cache.
@@ -133,7 +131,7 @@ class HttpCache : public HttpTransactionFactory,
// The disk cache is initialized lazily (by CreateTransaction) in this case.
// Provide an existing HttpNetworkSession, the cache can construct a
// network layer with a shared HttpNetworkSession in order for multiple
- // network layers to share information (e.g. authenication data). The
+ // network layers to share information (e.g. authentication data). The
// HttpCache takes ownership of the |backend_factory|.
HttpCache(HttpNetworkSession* session, BackendFactory* backend_factory);
@@ -145,6 +143,8 @@ class HttpCache : public HttpTransactionFactory,
NetLog* net_log,
BackendFactory* backend_factory);
+ ~HttpCache();
+
HttpTransactionFactory* network_layer() { return network_layer_.get(); }
// Retrieves the cache backend for this HttpCache instance. If the backend
@@ -157,12 +157,6 @@ class HttpCache : public HttpTransactionFactory,
// Returns the current backend (can be NULL).
disk_cache::Backend* GetCurrentBackend();
- // HttpTransactionFactory implementation:
- virtual int CreateTransaction(scoped_ptr<HttpTransaction>* trans);
- virtual HttpCache* GetCache();
- virtual HttpNetworkSession* GetSession();
- virtual void Suspend(bool suspend);
-
// Given a header data blob, convert it to a response info object.
static bool ParseResponseInfo(const char* data, int len,
HttpResponseInfo* response_info,
@@ -184,6 +178,12 @@ class HttpCache : public HttpTransactionFactory,
// immediately, but they will not be reusable. This is for debugging.
void CloseCurrentConnections();
+ // HttpTransactionFactory implementation:
+ virtual int CreateTransaction(scoped_ptr<HttpTransaction>* trans);
+ virtual HttpCache* GetCache();
+ virtual HttpNetworkSession* GetSession();
+ virtual void Suspend(bool suspend);
+
protected:
// Disk cache entry data indices.
enum {
@@ -211,20 +211,21 @@ class HttpCache : public HttpTransactionFactory,
typedef std::list<WorkItem*> WorkItemList;
struct ActiveEntry {
+ explicit ActiveEntry(disk_cache::Entry* entry);
+ ~ActiveEntry();
+
disk_cache::Entry* disk_entry;
Transaction* writer;
TransactionList readers;
TransactionList pending_queue;
bool will_process_pending_queue;
bool doomed;
-
- explicit ActiveEntry(disk_cache::Entry* entry);
- ~ActiveEntry();
};
typedef base::hash_map<std::string, ActiveEntry*> ActiveEntriesMap;
typedef base::hash_map<std::string, PendingOp*> PendingOpsMap;
typedef std::set<ActiveEntry*> ActiveEntriesSet;
+ typedef base::hash_map<std::string, int> PlaybackCacheMap;
// Methods ------------------------------------------------------------------
@@ -355,9 +356,9 @@ class HttpCache : public HttpTransactionFactory,
Mode mode_;
- scoped_ptr<SSLHostInfoFactoryAdaptor> ssl_host_info_factory_;
+ const scoped_ptr<SSLHostInfoFactoryAdaptor> ssl_host_info_factory_;
- scoped_ptr<HttpTransactionFactory> network_layer_;
+ const scoped_ptr<HttpTransactionFactory> network_layer_;
scoped_ptr<disk_cache::Backend> disk_cache_;
// The set of active entries indexed by cache key.
@@ -371,7 +372,6 @@ class HttpCache : public HttpTransactionFactory,
ScopedRunnableMethodFactory<HttpCache> task_factory_;
- typedef base::hash_map<std::string, int> PlaybackCacheMap;
scoped_ptr<PlaybackCacheMap> playback_cache_map_;
DISALLOW_COPY_AND_ASSIGN(HttpCache);
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index b506edc..32386f0 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -163,6 +163,70 @@ HttpCache::Transaction::~Transaction() {
cache_.reset();
}
+int HttpCache::Transaction::WriteMetadata(IOBuffer* buf, int buf_len,
+ CompletionCallback* callback) {
+ DCHECK(buf);
+ DCHECK_GT(buf_len, 0);
+ DCHECK(callback);
+ if (!cache_ || !entry_)
+ return ERR_UNEXPECTED;
+
+ // We don't need to track this operation for anything.
+ // It could be possible to check if there is something already written and
+ // avoid writing again (it should be the same, right?), but let's allow the
+ // caller to "update" the contents with something new.
+ return entry_->disk_entry->WriteData(kMetadataIndex, 0, buf, buf_len,
+ callback, true);
+}
+
+// Histogram data from the end of 2010 show the following distribution of
+// response headers:
+//
+// Content-Length............... 87%
+// Date......................... 98%
+// Last-Modified................ 49%
+// Etag......................... 19%
+// Accept-Ranges: bytes......... 25%
+// Accept-Ranges: none.......... 0.4%
+// Strong Validator............. 50%
+// Strong Validator + ranges.... 24%
+// Strong Validator + CL........ 49%
+//
+bool HttpCache::Transaction::AddTruncatedFlag() {
+ DCHECK(mode_ & WRITE);
+
+ // Don't set the flag for sparse entries.
+ if (partial_.get() && !truncated_)
+ return true;
+
+ // Double check that there is something worth keeping.
+ if (!entry_->disk_entry->GetDataSize(kResponseContentIndex))
+ return false;
+
+ if (response_.headers->GetContentLength() <= 0 ||
+ response_.headers->HasHeaderValue("Accept-Ranges", "none") ||
+ !response_.headers->HasStrongValidators())
+ return false;
+
+ truncated_ = true;
+ target_state_ = STATE_NONE;
+ next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE;
+ DoLoop(OK);
+ return true;
+}
+
+LoadState HttpCache::Transaction::GetWriterLoadState() const {
+ if (network_trans_.get())
+ return network_trans_->GetLoadState();
+ if (entry_ || !request_)
+ return LOAD_STATE_IDLE;
+ return LOAD_STATE_WAITING_FOR_CACHE;
+}
+
+const BoundNetLog& HttpCache::Transaction::net_log() const {
+ return net_log_;
+}
+
int HttpCache::Transaction::Start(const HttpRequestInfo* request,
CompletionCallback* callback,
const BoundNetLog& net_log) {
@@ -338,70 +402,6 @@ uint64 HttpCache::Transaction::GetUploadProgress() const {
return final_upload_progress_;
}
-int HttpCache::Transaction::WriteMetadata(IOBuffer* buf, int buf_len,
- CompletionCallback* callback) {
- DCHECK(buf);
- DCHECK_GT(buf_len, 0);
- DCHECK(callback);
- if (!cache_ || !entry_)
- return ERR_UNEXPECTED;
-
- // We don't need to track this operation for anything.
- // It could be possible to check if there is something already written and
- // avoid writing again (it should be the same, right?), but let's allow the
- // caller to "update" the contents with something new.
- return entry_->disk_entry->WriteData(kMetadataIndex, 0, buf, buf_len,
- callback, true);
-}
-
-// Histogram data from the end of 2010 show the following distribution of
-// response headers:
-//
-// Content-Length............... 87%
-// Date......................... 98%
-// Last-Modified................ 49%
-// Etag......................... 19%
-// Accept-Ranges: bytes......... 25%
-// Accept-Ranges: none.......... 0.4%
-// Strong Validator............. 50%
-// Strong Validator + ranges.... 24%
-// Strong Validator + CL........ 49%
-//
-bool HttpCache::Transaction::AddTruncatedFlag() {
- DCHECK(mode_ & WRITE);
-
- // Don't set the flag for sparse entries.
- if (partial_.get() && !truncated_)
- return true;
-
- // Double check that there is something worth keeping.
- if (!entry_->disk_entry->GetDataSize(kResponseContentIndex))
- return false;
-
- if (response_.headers->GetContentLength() <= 0 ||
- response_.headers->HasHeaderValue("Accept-Ranges", "none") ||
- !response_.headers->HasStrongValidators())
- return false;
-
- truncated_ = true;
- target_state_ = STATE_NONE;
- next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE;
- DoLoop(OK);
- return true;
-}
-
-LoadState HttpCache::Transaction::GetWriterLoadState() const {
- if (network_trans_.get())
- return network_trans_->GetLoadState();
- if (entry_ || !request_)
- return LOAD_STATE_IDLE;
- return LOAD_STATE_WAITING_FOR_CACHE;
-}
-
-const BoundNetLog& HttpCache::Transaction::net_log() const {
- return net_log_;
-}
-
//-----------------------------------------------------------------------------
void HttpCache::Transaction::DoCallback(int rv) {
diff --git a/net/http/http_cache_transaction.h b/net/http/http_cache_transaction.h
index 316c15b..81160d5 100644
--- a/net/http/http_cache_transaction.h
+++ b/net/http/http_cache_transaction.h
@@ -28,25 +28,6 @@ struct HttpRequestInfo;
// factory.
class HttpCache::Transaction : public HttpTransaction {
public:
- Transaction(HttpCache* cache);
- virtual ~Transaction();
-
- // HttpTransaction methods:
- virtual int Start(const HttpRequestInfo*, CompletionCallback*,
- const BoundNetLog&);
- virtual int RestartIgnoringLastError(CompletionCallback* callback);
- virtual int RestartWithCertificate(X509Certificate* client_cert,
- CompletionCallback* callback);
- virtual int RestartWithAuth(const string16& username,
- const string16& password,
- CompletionCallback* callback);
- virtual bool IsReadyToRestartForAuth();
- virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
- virtual void StopCaching();
- virtual const HttpResponseInfo* GetResponseInfo() const;
- virtual LoadState GetLoadState() const;
- virtual uint64 GetUploadProgress(void) const;
-
// The transaction has the following modes, which apply to how it may access
// its cache entry.
//
@@ -76,6 +57,9 @@ class HttpCache::Transaction : public HttpTransaction {
UPDATE = READ_META | WRITE, // READ_WRITE & ~READ_DATA
};
+ Transaction(HttpCache* cache);
+ virtual ~Transaction();
+
Mode mode() const { return mode_; }
const std::string& key() const { return cache_key_; }
@@ -112,6 +96,22 @@ class HttpCache::Transaction : public HttpTransaction {
const BoundNetLog& net_log() const;
+ // HttpTransaction methods:
+ virtual int Start(const HttpRequestInfo*, CompletionCallback*,
+ const BoundNetLog&);
+ virtual int RestartIgnoringLastError(CompletionCallback* callback);
+ virtual int RestartWithCertificate(X509Certificate* client_cert,
+ CompletionCallback* callback);
+ virtual int RestartWithAuth(const string16& username,
+ const string16& password,
+ CompletionCallback* callback);
+ virtual bool IsReadyToRestartForAuth();
+ virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
+ virtual void StopCaching();
+ virtual const HttpResponseInfo* GetResponseInfo() const;
+ virtual LoadState GetLoadState() const;
+ virtual uint64 GetUploadProgress(void) const;
+
private:
static const size_t kNumValidationHeaders = 2;
// Helper struct to pair a header name with its value, for
diff --git a/net/http/http_net_log_params.h b/net/http/http_net_log_params.h
index 1631363..c32250e 100644
--- a/net/http/http_net_log_params.h
+++ b/net/http/http_net_log_params.h
@@ -24,8 +24,6 @@ class NetLogHttpRequestParameter : public NetLog::EventParameters {
NetLogHttpRequestParameter(const std::string& line,
const HttpRequestHeaders& headers);
- virtual Value* ToValue() const;
-
const HttpRequestHeaders& GetHeaders() const {
return headers_;
}
@@ -34,6 +32,9 @@ class NetLogHttpRequestParameter : public NetLog::EventParameters {
return line_;
}
+ // NetLog::EventParameters
+ virtual Value* ToValue() const;
+
private:
virtual ~NetLogHttpRequestParameter();
@@ -48,12 +49,13 @@ class NetLogHttpResponseParameter : public NetLog::EventParameters {
explicit NetLogHttpResponseParameter(
const scoped_refptr<HttpResponseHeaders>& headers);
- virtual Value* ToValue() const;
-
const HttpResponseHeaders& GetHeaders() const {
return *headers_;
}
+ // NetLog::EventParameters
+ virtual Value* ToValue() const;
+
private:
virtual ~NetLogHttpResponseParameter();
diff --git a/net/http/http_network_delegate.h b/net/http/http_network_delegate.h
index 6b60aba..1533bc3 100644
--- a/net/http/http_network_delegate.h
+++ b/net/http/http_network_delegate.h
@@ -9,9 +9,13 @@
namespace net {
class HttpRequestHeaders;
+class URLRequest;
class HttpNetworkDelegate {
public:
+ // Called before a request is sent.
+ virtual void OnBeforeURLRequest(net::URLRequest* request) = 0;
+
// Called right before the HTTP headers are sent. Allows the delegate to
// read/write |headers| before they get sent out.
virtual void OnSendHttpRequest(HttpRequestHeaders* headers) = 0;
diff --git a/net/http/http_network_layer.cc b/net/http/http_network_layer.cc
index 9a11034..73e6f8d 100644
--- a/net/http/http_network_layer.cc
+++ b/net/http/http_network_layer.cc
@@ -10,121 +10,14 @@
#include "base/string_util.h"
#include "net/http/http_network_session.h"
#include "net/http/http_network_transaction.h"
-#include "net/socket/client_socket_factory.h"
#include "net/spdy/spdy_framer.h"
#include "net/spdy/spdy_session.h"
-#include "net/spdy/spdy_session_pool.h"
namespace net {
//-----------------------------------------------------------------------------
-
-// static
-HttpTransactionFactory* HttpNetworkLayer::CreateFactory(
- HostResolver* host_resolver,
- CertVerifier* cert_verifier,
- DnsRRResolver* dnsrr_resolver,
- DnsCertProvenanceChecker* dns_cert_checker,
- SSLHostInfoFactory* ssl_host_info_factory,
- ProxyService* proxy_service,
- SSLConfigService* ssl_config_service,
- HttpAuthHandlerFactory* http_auth_handler_factory,
- HttpNetworkDelegate* network_delegate,
- NetLog* net_log) {
- DCHECK(proxy_service);
-
- return new HttpNetworkLayer(ClientSocketFactory::GetDefaultFactory(),
- host_resolver, cert_verifier, dnsrr_resolver,
- dns_cert_checker,
- ssl_host_info_factory, proxy_service,
- ssl_config_service, http_auth_handler_factory,
- network_delegate,
- net_log);
-}
-
-// static
-HttpTransactionFactory* HttpNetworkLayer::CreateFactory(
- HttpNetworkSession* session) {
- DCHECK(session);
-
- return new HttpNetworkLayer(session);
-}
-
-//-----------------------------------------------------------------------------
-HttpNetworkLayer::HttpNetworkLayer(
- ClientSocketFactory* socket_factory,
- HostResolver* host_resolver,
- CertVerifier* cert_verifier,
- DnsRRResolver* dnsrr_resolver,
- DnsCertProvenanceChecker* dns_cert_checker,
- SSLHostInfoFactory* ssl_host_info_factory,
- ProxyService* proxy_service,
- SSLConfigService* ssl_config_service,
- HttpAuthHandlerFactory* http_auth_handler_factory,
- HttpNetworkDelegate* network_delegate,
- NetLog* net_log)
- : socket_factory_(socket_factory),
- host_resolver_(host_resolver),
- cert_verifier_(cert_verifier),
- 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),
- session_(NULL),
- spdy_session_pool_(NULL),
- http_auth_handler_factory_(http_auth_handler_factory),
- network_delegate_(network_delegate),
- net_log_(net_log),
- suspended_(false) {
- DCHECK(proxy_service_);
- DCHECK(ssl_config_service_.get());
-}
-
-HttpNetworkLayer::HttpNetworkLayer(
- ClientSocketFactory* socket_factory,
- HostResolver* host_resolver,
- CertVerifier* cert_verifier,
- DnsRRResolver* dnsrr_resolver,
- DnsCertProvenanceChecker* dns_cert_checker,
- SSLHostInfoFactory* ssl_host_info_factory,
- ProxyService* proxy_service,
- SSLConfigService* ssl_config_service,
- SpdySessionPool* spdy_session_pool,
- HttpAuthHandlerFactory* http_auth_handler_factory,
- HttpNetworkDelegate* network_delegate,
- NetLog* net_log)
- : socket_factory_(socket_factory),
- host_resolver_(host_resolver),
- cert_verifier_(cert_verifier),
- 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),
- session_(NULL),
- spdy_session_pool_(spdy_session_pool),
- http_auth_handler_factory_(http_auth_handler_factory),
- network_delegate_(network_delegate),
- net_log_(net_log),
- suspended_(false) {
- DCHECK(proxy_service_);
- DCHECK(ssl_config_service_.get());
-}
-
HttpNetworkLayer::HttpNetworkLayer(HttpNetworkSession* session)
- : socket_factory_(ClientSocketFactory::GetDefaultFactory()),
- host_resolver_(NULL),
- cert_verifier_(NULL),
- dnsrr_resolver_(NULL),
- dns_cert_checker_(NULL),
- ssl_host_info_factory_(NULL),
- ssl_config_service_(NULL),
- session_(session),
- spdy_session_pool_(NULL),
- http_auth_handler_factory_(NULL),
- network_delegate_(NULL),
- net_log_(NULL),
+ : session_(session),
suspended_(false) {
DCHECK(session_.get());
}
@@ -132,56 +25,14 @@ HttpNetworkLayer::HttpNetworkLayer(HttpNetworkSession* session)
HttpNetworkLayer::~HttpNetworkLayer() {
}
-int HttpNetworkLayer::CreateTransaction(scoped_ptr<HttpTransaction>* trans) {
- if (suspended_)
- return ERR_NETWORK_IO_SUSPENDED;
-
- trans->reset(new HttpNetworkTransaction(GetSession()));
- return OK;
-}
-
-HttpCache* HttpNetworkLayer::GetCache() {
- return NULL;
-}
-
-void HttpNetworkLayer::Suspend(bool suspend) {
- suspended_ = suspend;
+//-----------------------------------------------------------------------------
- if (suspend && session_)
- session_->tcp_socket_pool()->CloseIdleSockets();
-}
+// static
+HttpTransactionFactory* HttpNetworkLayer::CreateFactory(
+ HttpNetworkSession* session) {
+ DCHECK(session);
-HttpNetworkSession* HttpNetworkLayer::GetSession() {
- if (!session_) {
- DCHECK(proxy_service_);
- if (!spdy_session_pool_.get())
- spdy_session_pool_.reset(new SpdySessionPool(ssl_config_service_));
- session_ = new HttpNetworkSession(
- host_resolver_,
- cert_verifier_,
- dnsrr_resolver_,
- dns_cert_checker_,
- ssl_host_info_factory_,
- proxy_service_,
- socket_factory_,
- ssl_config_service_,
- spdy_session_pool_.release(),
- http_auth_handler_factory_,
- network_delegate_,
- net_log_);
- // These were just temps for lazy-initializing HttpNetworkSession.
- host_resolver_ = NULL;
- cert_verifier_ = NULL;
- dnsrr_resolver_ = NULL;
- dns_cert_checker_ = NULL;
- ssl_host_info_factory_ = NULL;
- proxy_service_ = NULL;
- socket_factory_ = NULL;
- http_auth_handler_factory_ = NULL;
- net_log_ = NULL;
- network_delegate_ = NULL;
- }
- return session_;
+ return new HttpNetworkLayer(session);
}
// static
@@ -277,4 +128,30 @@ void HttpNetworkLayer::EnableSpdy(const std::string& mode) {
}
}
}
+
+//-----------------------------------------------------------------------------
+
+int HttpNetworkLayer::CreateTransaction(scoped_ptr<HttpTransaction>* trans) {
+ if (suspended_)
+ return ERR_NETWORK_IO_SUSPENDED;
+
+ trans->reset(new HttpNetworkTransaction(GetSession()));
+ return OK;
+}
+
+HttpCache* HttpNetworkLayer::GetCache() {
+ return NULL;
+}
+
+HttpNetworkSession* HttpNetworkLayer::GetSession() {
+ return session_;
+}
+
+void HttpNetworkLayer::Suspend(bool suspend) {
+ suspended_ = suspend;
+
+ if (suspend && session_)
+ session_->tcp_socket_pool()->CloseIdleSockets();
+}
+
} // namespace net
diff --git a/net/http/http_network_layer.h b/net/http/http_network_layer.h
index 730b5c7..da92761 100644
--- a/net/http/http_network_layer.h
+++ b/net/http/http_network_layer.h
@@ -32,52 +32,11 @@ class SSLHostInfoFactory;
class HttpNetworkLayer : public HttpTransactionFactory,
public base::NonThreadSafe {
public:
- // |socket_factory|, |proxy_service|, |host_resolver|, etc. must remain
- // valid for the lifetime of HttpNetworkLayer.
- // TODO(wtc): we only need the next constructor.
- HttpNetworkLayer(ClientSocketFactory* socket_factory,
- HostResolver* host_resolver,
- CertVerifier* cert_verifier,
- DnsRRResolver* dnsrr_resolver,
- DnsCertProvenanceChecker* dns_cert_checker,
- SSLHostInfoFactory* ssl_host_info_factory,
- ProxyService* proxy_service,
- SSLConfigService* ssl_config_service,
- HttpAuthHandlerFactory* http_auth_handler_factory,
- HttpNetworkDelegate* network_delegate,
- NetLog* net_log);
- HttpNetworkLayer(
- ClientSocketFactory* socket_factory,
- HostResolver* host_resolver,
- CertVerifier* cert_verifier,
- DnsRRResolver* dnsrr_resolver,
- DnsCertProvenanceChecker* dns_cert_checker,
- SSLHostInfoFactory* ssl_host_info_factory,
- ProxyService* proxy_service,
- SSLConfigService* ssl_config_service,
- SpdySessionPool* spdy_session_pool,
- HttpAuthHandlerFactory* http_auth_handler_factory,
- HttpNetworkDelegate* network_delegate,
- NetLog* net_log);
-
// Construct a HttpNetworkLayer with an existing HttpNetworkSession which
// contains a valid ProxyService.
explicit HttpNetworkLayer(HttpNetworkSession* session);
- ~HttpNetworkLayer();
+ virtual ~HttpNetworkLayer();
- // This function hides the details of how a network layer gets instantiated
- // and allows other implementations to be substituted.
- static HttpTransactionFactory* CreateFactory(
- HostResolver* host_resolver,
- CertVerifier* cert_verifier,
- DnsRRResolver* dnsrr_resolver,
- DnsCertProvenanceChecker* dns_cert_checker,
- SSLHostInfoFactory* ssl_host_info_factory,
- ProxyService* proxy_service,
- SSLConfigService* ssl_config_service,
- HttpAuthHandlerFactory* http_auth_handler_factory,
- HttpNetworkDelegate* network_delegate,
- NetLog* net_log);
// Create a transaction factory that instantiate a network layer over an
// existing network session. Network session contains some valuable
// information (e.g. authentication data) that we want to share across
@@ -86,12 +45,6 @@ class HttpNetworkLayer : public HttpTransactionFactory,
// when network session is shared.
static HttpTransactionFactory* CreateFactory(HttpNetworkSession* session);
- // HttpTransactionFactory methods:
- virtual int CreateTransaction(scoped_ptr<HttpTransaction>* trans);
- virtual HttpCache* GetCache();
- virtual HttpNetworkSession* GetSession();
- virtual void Suspend(bool suspend);
-
// Enable the spdy protocol.
// Without calling this function, SPDY is disabled. The mode can be:
// "" : (default) SSL and compression are enabled, flow
@@ -102,29 +55,14 @@ class HttpNetworkLayer : public HttpTransactionFactory,
// "none" : disables both SSL and compression.
static void EnableSpdy(const std::string& mode);
- private:
- // The factory we will use to create network sockets.
- ClientSocketFactory* socket_factory_;
-
- // The host resolver, proxy service, etc. that will be used when lazily
- // creating |session_|.
- HostResolver* host_resolver_;
- CertVerifier* cert_verifier_;
- DnsRRResolver* dnsrr_resolver_;
- DnsCertProvenanceChecker* dns_cert_checker_;
- SSLHostInfoFactory* ssl_host_info_factory_;
- scoped_refptr<ProxyService> proxy_service_;
-
- // The SSL config service being used for the session.
- scoped_refptr<SSLConfigService> ssl_config_service_;
-
- scoped_refptr<HttpNetworkSession> session_;
- scoped_ptr<SpdySessionPool> spdy_session_pool_;
-
- HttpAuthHandlerFactory* http_auth_handler_factory_;
- HttpNetworkDelegate* network_delegate_;
- NetLog* net_log_;
+ // HttpTransactionFactory methods:
+ virtual int CreateTransaction(scoped_ptr<HttpTransaction>* trans);
+ virtual HttpCache* GetCache();
+ virtual HttpNetworkSession* GetSession();
+ virtual void Suspend(bool suspend);
+ private:
+ const scoped_refptr<HttpNetworkSession> session_;
bool suspended_;
};
diff --git a/net/http/http_network_layer_unittest.cc b/net/http/http_network_layer_unittest.cc
index 2720c10..5120fac 100644
--- a/net/http/http_network_layer_unittest.cc
+++ b/net/http/http_network_layer_unittest.cc
@@ -7,9 +7,11 @@
#include "net/base/net_log.h"
#include "net/base/ssl_config_service_defaults.h"
#include "net/http/http_network_layer.h"
+#include "net/http/http_network_session.h"
#include "net/http/http_transaction_unittest.h"
#include "net/proxy/proxy_service.h"
#include "net/socket/socket_test_util.h"
+#include "net/spdy/spdy_session_pool.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
@@ -18,118 +20,93 @@ namespace net {
namespace {
class HttpNetworkLayerTest : public PlatformTest {
+ protected:
+ HttpNetworkLayerTest()
+ : proxy_service_(ProxyService::CreateDirect()),
+ ssl_config_service_(new SSLConfigServiceDefaults) {
+ HttpNetworkSession::Params session_params;
+ session_params.client_socket_factory = &mock_socket_factory_;
+ session_params.host_resolver = &host_resolver_;
+ session_params.cert_verifier = &cert_verifier_;
+ session_params.proxy_service = proxy_service_;
+ session_params.ssl_config_service = ssl_config_service_;
+ network_session_ = new HttpNetworkSession(session_params);
+ factory_.reset(new HttpNetworkLayer(network_session_));
+ }
+
+ MockClientSocketFactory mock_socket_factory_;
+ MockHostResolver host_resolver_;
+ CertVerifier cert_verifier_;
+ const scoped_refptr<ProxyService> proxy_service_;
+ const scoped_refptr<SSLConfigService> ssl_config_service_;
+ scoped_refptr<HttpNetworkSession> network_session_;
+ scoped_ptr<HttpNetworkLayer> factory_;
};
TEST_F(HttpNetworkLayerTest, CreateAndDestroy) {
- MockHostResolver host_resolver;
- net::CertVerifier cert_verifier;
- net::HttpNetworkLayer factory(
- NULL,
- &host_resolver,
- &cert_verifier,
- NULL /* dnsrr_resolver */,
- NULL /* dns_cert_checker */,
- NULL /* ssl_host_info_factory */,
- net::ProxyService::CreateDirect(),
- new net::SSLConfigServiceDefaults,
- NULL,
- NULL,
- NULL);
-
- scoped_ptr<net::HttpTransaction> trans;
- int rv = factory.CreateTransaction(&trans);
- EXPECT_EQ(net::OK, rv);
+ scoped_ptr<HttpTransaction> trans;
+ int rv = factory_->CreateTransaction(&trans);
+ EXPECT_EQ(OK, rv);
EXPECT_TRUE(trans.get() != NULL);
}
TEST_F(HttpNetworkLayerTest, Suspend) {
- MockHostResolver host_resolver;
- net::CertVerifier cert_verifier;
- net::HttpNetworkLayer factory(
- NULL,
- &host_resolver,
- &cert_verifier,
- NULL /* dnsrr_resolver */,
- NULL /* dns_cert_checker */,
- NULL /* ssl_host_info_factory */,
- net::ProxyService::CreateDirect(),
- new net::SSLConfigServiceDefaults,
- NULL,
- NULL,
- NULL);
-
- scoped_ptr<net::HttpTransaction> trans;
- int rv = factory.CreateTransaction(&trans);
- EXPECT_EQ(net::OK, rv);
+ scoped_ptr<HttpTransaction> trans;
+ int rv = factory_->CreateTransaction(&trans);
+ EXPECT_EQ(OK, rv);
trans.reset();
- factory.Suspend(true);
+ factory_->Suspend(true);
- rv = factory.CreateTransaction(&trans);
- EXPECT_EQ(net::ERR_NETWORK_IO_SUSPENDED, rv);
+ rv = factory_->CreateTransaction(&trans);
+ EXPECT_EQ(ERR_NETWORK_IO_SUSPENDED, rv);
ASSERT_TRUE(trans == NULL);
- factory.Suspend(false);
+ factory_->Suspend(false);
- rv = factory.CreateTransaction(&trans);
- EXPECT_EQ(net::OK, rv);
+ rv = factory_->CreateTransaction(&trans);
+ EXPECT_EQ(OK, rv);
}
TEST_F(HttpNetworkLayerTest, GET) {
- net::MockClientSocketFactory mock_socket_factory;
- net::MockRead data_reads[] = {
- net::MockRead("HTTP/1.0 200 OK\r\n\r\n"),
- net::MockRead("hello world"),
- net::MockRead(false, net::OK),
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.0 200 OK\r\n\r\n"),
+ MockRead("hello world"),
+ MockRead(false, OK),
};
- net::MockWrite data_writes[] = {
- net::MockWrite("GET / HTTP/1.1\r\n"
+ MockWrite data_writes[] = {
+ MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"User-Agent: Foo/1.0\r\n\r\n"),
};
- net::StaticSocketDataProvider data(data_reads, arraysize(data_reads),
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
- mock_socket_factory.AddSocketDataProvider(&data);
-
- MockHostResolver host_resolver;
- net::CertVerifier cert_verifier;
- net::HttpNetworkLayer factory(
- &mock_socket_factory,
- &host_resolver,
- &cert_verifier,
- NULL /* dnsrr_resolver */,
- NULL /* dns_cert_checker */,
- NULL /* ssl_host_info_factory */,
- net::ProxyService::CreateDirect(),
- new net::SSLConfigServiceDefaults,
- NULL,
- NULL,
- NULL);
+ mock_socket_factory_.AddSocketDataProvider(&data);
TestCompletionCallback callback;
- scoped_ptr<net::HttpTransaction> trans;
- int rv = factory.CreateTransaction(&trans);
- EXPECT_EQ(net::OK, rv);
-
- net::HttpRequestInfo request_info;
+ HttpRequestInfo request_info;
request_info.url = GURL("http://www.google.com/");
request_info.method = "GET";
- request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kUserAgent,
+ request_info.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
"Foo/1.0");
- request_info.load_flags = net::LOAD_NORMAL;
+ request_info.load_flags = LOAD_NORMAL;
+
+ scoped_ptr<HttpTransaction> trans;
+ int rv = factory_->CreateTransaction(&trans);
+ EXPECT_EQ(OK, rv);
- rv = trans->Start(&request_info, &callback, net::BoundNetLog());
- if (rv == net::ERR_IO_PENDING)
+ rv = trans->Start(&request_info, &callback, BoundNetLog());
+ if (rv == ERR_IO_PENDING)
rv = callback.WaitForResult();
- ASSERT_EQ(net::OK, rv);
+ ASSERT_EQ(OK, rv);
std::string contents;
rv = ReadTransaction(trans.get(), &contents);
- EXPECT_EQ(net::OK, rv);
+ EXPECT_EQ(OK, rv);
EXPECT_EQ("hello world", contents);
}
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index e3de475..b50b6e9 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -13,51 +13,38 @@
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_response_body_drainer.h"
#include "net/http/url_security_manager.h"
+#include "net/socket/client_socket_factory.h"
#include "net/spdy/spdy_session_pool.h"
namespace net {
// TODO(mbelshe): Move the socket factories into HttpStreamFactory.
-HttpNetworkSession::HttpNetworkSession(
- HostResolver* host_resolver,
- CertVerifier* cert_verifier,
- DnsRRResolver* dnsrr_resolver,
- DnsCertProvenanceChecker* dns_cert_checker,
- SSLHostInfoFactory* ssl_host_info_factory,
- ProxyService* proxy_service,
- ClientSocketFactory* client_socket_factory,
- SSLConfigService* ssl_config_service,
- SpdySessionPool* spdy_session_pool,
- HttpAuthHandlerFactory* http_auth_handler_factory,
- HttpNetworkDelegate* network_delegate,
- NetLog* net_log)
- : socket_factory_(client_socket_factory),
- host_resolver_(host_resolver),
- cert_verifier_(cert_verifier),
- 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,
- cert_verifier,
- dnsrr_resolver,
- dns_cert_checker,
- ssl_host_info_factory,
- proxy_service,
- ssl_config_service),
- spdy_session_pool_(spdy_session_pool),
- http_auth_handler_factory_(http_auth_handler_factory),
- network_delegate_(network_delegate),
- net_log_(net_log) {
- DCHECK(proxy_service);
- DCHECK(ssl_config_service);
+HttpNetworkSession::HttpNetworkSession(const Params& params)
+ : cert_verifier_(NULL),
+ proxy_service_(params.proxy_service),
+ ssl_config_service_(params.ssl_config_service),
+ socket_pool_manager_(params.net_log,
+ params.client_socket_factory ?
+ params.client_socket_factory :
+ ClientSocketFactory::GetDefaultFactory(),
+ params.host_resolver,
+ params.cert_verifier,
+ params.dnsrr_resolver,
+ params.dns_cert_checker,
+ params.ssl_host_info_factory,
+ params.proxy_service,
+ params.ssl_config_service),
+ spdy_session_pool_(params.ssl_config_service),
+ http_auth_handler_factory_(params.http_auth_handler_factory),
+ network_delegate_(params.network_delegate),
+ net_log_(params.net_log) {
+ DCHECK(params.proxy_service);
+ DCHECK(params.ssl_config_service);
}
HttpNetworkSession::~HttpNetworkSession() {
STLDeleteElements(&response_drainers_);
- spdy_session_pool_->CloseAllSessions();
+ spdy_session_pool_.CloseAllSessions();
}
void HttpNetworkSession::AddResponseDrainer(HttpResponseBodyDrainer* drainer) {
@@ -72,7 +59,7 @@ void HttpNetworkSession::RemoveResponseDrainer(
}
Value* HttpNetworkSession::SpdySessionPoolInfoToValue() const {
- return spdy_session_pool_->SpdySessionPoolInfoToValue();
+ return spdy_session_pool_.SpdySessionPoolInfoToValue();
}
} // namespace net
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index b36d7f7..36cb652 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -6,22 +6,17 @@
#define NET_HTTP_HTTP_NETWORK_SESSION_H_
#pragma once
-#include <map>
#include <set>
#include "base/ref_counted.h"
-#include "base/scoped_ptr.h"
#include "base/threading/non_thread_safe.h"
#include "net/base/host_port_pair.h"
#include "net/base/host_resolver.h"
#include "net/base/ssl_client_auth_cache.h"
-#include "net/base/ssl_config_service.h"
#include "net/http/http_alternate_protocols.h"
#include "net/http/http_auth_cache.h"
-#include "net/http/http_network_delegate.h"
-#include "net/http/http_network_transaction.h"
#include "net/http/http_stream_factory.h"
-#include "net/proxy/proxy_service.h"
#include "net/socket/client_socket_pool_manager.h"
+#include "net/spdy/spdy_session_pool.h"
#include "net/spdy/spdy_settings_storage.h"
class Value;
@@ -32,34 +27,49 @@ class CertVerifier;
class ClientSocketFactory;
class DnsCertProvenanceChecker;
class DnsRRResolver;
+class HostResolver;
class HttpAuthHandlerFactory;
class HttpNetworkDelegate;
class HttpNetworkSessionPeer;
class HttpProxyClientSocketPool;
class HttpResponseBodyDrainer;
-class SpdySessionPool;
-class SOCKSClientSocketPool;
-class SSLClientSocketPool;
+class NetLog;
+class ProxyService;
+class SSLConfigService;
class SSLHostInfoFactory;
-class TCPClientSocketPool;
// This class holds session objects used by HttpNetworkTransaction objects.
class HttpNetworkSession : public base::RefCounted<HttpNetworkSession>,
public base::NonThreadSafe {
public:
- HttpNetworkSession(
- HostResolver* host_resolver,
- CertVerifier* cert_verifier,
- DnsRRResolver* dnsrr_resolver,
- DnsCertProvenanceChecker* dns_cert_checker,
- SSLHostInfoFactory* ssl_host_info_factory,
- ProxyService* proxy_service,
- ClientSocketFactory* client_socket_factory,
- SSLConfigService* ssl_config_service,
- SpdySessionPool* spdy_session_pool,
- HttpAuthHandlerFactory* http_auth_handler_factory,
- HttpNetworkDelegate* network_delegate,
- NetLog* net_log);
+ struct Params {
+ Params()
+ : client_socket_factory(NULL),
+ host_resolver(NULL),
+ cert_verifier(NULL),
+ dnsrr_resolver(NULL),
+ dns_cert_checker(NULL),
+ proxy_service(NULL),
+ ssl_host_info_factory(NULL),
+ ssl_config_service(NULL),
+ http_auth_handler_factory(NULL),
+ network_delegate(NULL),
+ net_log(NULL) {}
+
+ ClientSocketFactory* client_socket_factory;
+ HostResolver* host_resolver;
+ CertVerifier* cert_verifier;
+ DnsRRResolver* dnsrr_resolver;
+ DnsCertProvenanceChecker* dns_cert_checker;
+ ProxyService* proxy_service;
+ SSLHostInfoFactory* ssl_host_info_factory;
+ SSLConfigService* ssl_config_service;
+ HttpAuthHandlerFactory* http_auth_handler_factory;
+ HttpNetworkDelegate* network_delegate;
+ NetLog* net_log;
+ };
+
+ explicit HttpNetworkSession(const Params& params);
HttpAuthCache* auth_cache() { return &auth_cache_; }
SSLClientAuthCache* ssl_client_auth_cache() {
@@ -108,17 +118,10 @@ class HttpNetworkSession : public base::RefCounted<HttpNetworkSession>,
return socket_pool_manager_.GetSocketPoolForSSLWithProxy(proxy_server);
}
- // SSL sockets come from the socket_factory().
- ClientSocketFactory* socket_factory() { return socket_factory_; }
- HostResolver* host_resolver() { return host_resolver_; }
CertVerifier* cert_verifier() { return cert_verifier_; }
- 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(); }
+ SpdySessionPool* spdy_session_pool() { return &spdy_session_pool_; }
HttpAuthHandlerFactory* http_auth_handler_factory() {
return http_auth_handler_factory_;
}
@@ -154,24 +157,19 @@ class HttpNetworkSession : public base::RefCounted<HttpNetworkSession>,
~HttpNetworkSession();
- ClientSocketFactory* const socket_factory_;
HttpAuthCache auth_cache_;
SSLClientAuthCache ssl_client_auth_cache_;
HttpAlternateProtocols alternate_protocols_;
- HostResolver* const host_resolver_;
CertVerifier* cert_verifier_;
- DnsRRResolver* dnsrr_resolver_;
- DnsCertProvenanceChecker* dns_cert_checker_;
+ // Not const since it's modified by HttpNetworkSessionPeer for testing.
scoped_refptr<ProxyService> proxy_service_;
- scoped_refptr<SSLConfigService> ssl_config_service_;
+ const scoped_refptr<SSLConfigService> ssl_config_service_;
ClientSocketPoolManager socket_pool_manager_;
- // TODO(willchan): Move this out to IOThread so it can be shared across
- // URLRequestContexts.
- scoped_ptr<SpdySessionPool> spdy_session_pool_;
+ SpdySessionPool spdy_session_pool_;
HttpStreamFactory http_stream_factory_;
- HttpAuthHandlerFactory* http_auth_handler_factory_;
+ HttpAuthHandlerFactory* const http_auth_handler_factory_;
HttpNetworkDelegate* const network_delegate_;
- NetLog* net_log_;
+ NetLog* const net_log_;
SpdySettingsStorage spdy_settings_;
std::set<HttpResponseBodyDrainer*> response_drainers_;
};
diff --git a/net/http/http_network_session_peer.h b/net/http/http_network_session_peer.h
index 13f3fa7..398488b 100644
--- a/net/http/http_network_session_peer.h
+++ b/net/http/http_network_session_peer.h
@@ -6,66 +6,41 @@
#define NET_HTTP_HTTP_NETWORK_SESSION_PEER_H_
#pragma once
-#include "net/http/http_network_session.h"
-#include "net/http/http_proxy_client_socket_pool.h"
-#include "net/socket/socks_client_socket_pool.h"
-#include "net/socket/ssl_client_socket_pool.h"
+#include "base/ref_counted.h"
namespace net {
+class HostPortPair;
+class HttpNetworkSession;
+class HttpProxyClientSocketPool;
+class ProxyService;
+class SOCKSClientSocketPool;
+class SSLClientSocketPool;
+class TCPClientSocketPool;
+
class HttpNetworkSessionPeer {
public:
explicit HttpNetworkSessionPeer(
- const scoped_refptr<HttpNetworkSession>& session)
- : session_(session) {}
+ const scoped_refptr<HttpNetworkSession>& session);
+ ~HttpNetworkSessionPeer();
- void SetTCPSocketPool(TCPClientSocketPool* pool) {
- session_->socket_pool_manager_.tcp_socket_pool_.reset(pool);
- }
+ void SetTCPSocketPool(TCPClientSocketPool* pool);
void SetSocketPoolForSOCKSProxy(
const HostPortPair& socks_proxy,
- SOCKSClientSocketPool* pool) {
- ClientSocketPoolManager* socket_pool_manager =
- &session_->socket_pool_manager_;
-
- // Call through the public interface to force initialization of the
- // wrapped socket pools.
- delete socket_pool_manager->GetSocketPoolForSOCKSProxy(socks_proxy);
- socket_pool_manager->socks_socket_pools_[socks_proxy] = pool;
- }
+ SOCKSClientSocketPool* pool);
void SetSocketPoolForHTTPProxy(
const HostPortPair& http_proxy,
- HttpProxyClientSocketPool* pool) {
- ClientSocketPoolManager* socket_pool_manager =
- &session_->socket_pool_manager_;
+ HttpProxyClientSocketPool* pool);
- // Call through the public interface to force initialization of the
- // wrapped socket pools.
- delete socket_pool_manager->GetSocketPoolForHTTPProxy(http_proxy);
- socket_pool_manager->http_proxy_socket_pools_[http_proxy] = pool;
- }
-
- void SetSSLSocketPool(SSLClientSocketPool* pool) {
- session_->socket_pool_manager_.ssl_socket_pool_.reset(pool);
- }
+ void SetSSLSocketPool(SSLClientSocketPool* pool);
void SetSocketPoolForSSLWithProxy(
const HostPortPair& proxy_host,
- SSLClientSocketPool* pool) {
- ClientSocketPoolManager* socket_pool_manager =
- &session_->socket_pool_manager_;
-
- // Call through the public interface to force initialization of the
- // wrapped socket pools.
- delete socket_pool_manager->GetSocketPoolForSSLWithProxy(proxy_host);
- socket_pool_manager->ssl_socket_pools_for_proxies_[proxy_host] = pool;
- }
+ SSLClientSocketPool* pool);
- void SetProxyService(ProxyService* proxy_service) {
- session_->proxy_service_ = proxy_service;
- }
+ void SetProxyService(ProxyService* proxy_service);
private:
const scoped_refptr<HttpNetworkSession> session_;
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 64a4fa7..128497f 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -33,6 +33,7 @@
#include "net/http/http_basic_stream.h"
#include "net/http/http_chunked_decoder.h"
#include "net/http/http_net_log_params.h"
+#include "net/http/http_network_delegate.h"
#include "net/http/http_network_session.h"
#include "net/http/http_proxy_client_socket.h"
#include "net/http/http_proxy_client_socket_pool.h"
@@ -76,6 +77,19 @@ void ProcessAlternateProtocol(HttpStreamFactory* factory,
http_host_port_pair);
}
+// Returns true if |error| is a client certificate authentication error.
+bool IsClientCertificateError(int error) {
+ switch (error) {
+ case ERR_BAD_SSL_CLIENT_AUTH_CERT:
+ case ERR_SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED:
+ case ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY:
+ case ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED:
+ return true;
+ default:
+ return false;
+ }
+}
+
} // namespace
//-----------------------------------------------------------------------------
@@ -486,7 +500,8 @@ int HttpNetworkTransaction::DoLoop(int result) {
break;
case STATE_SEND_REQUEST_COMPLETE:
rv = DoSendRequestComplete(rv);
- net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, NULL);
+ net_log_.EndEventWithNetErrorCode(
+ NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, rv);
break;
case STATE_READ_HEADERS:
DCHECK_EQ(OK, rv);
@@ -495,7 +510,8 @@ int HttpNetworkTransaction::DoLoop(int result) {
break;
case STATE_READ_HEADERS_COMPLETE:
rv = DoReadHeadersComplete(rv);
- net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, NULL);
+ net_log_.EndEventWithNetErrorCode(
+ NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, rv);
break;
case STATE_READ_BODY:
DCHECK_EQ(OK, rv);
@@ -504,7 +520,8 @@ int HttpNetworkTransaction::DoLoop(int result) {
break;
case STATE_READ_BODY_COMPLETE:
rv = DoReadBodyComplete(rv);
- net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, NULL);
+ net_log_.EndEventWithNetErrorCode(
+ NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, rv);
break;
case STATE_DRAIN_BODY_FOR_AUTH_RESTART:
DCHECK_EQ(OK, rv);
@@ -514,8 +531,8 @@ int HttpNetworkTransaction::DoLoop(int result) {
break;
case STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE:
rv = DoDrainBodyForAuthRestartComplete(rv);
- net_log_.EndEvent(
- NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART, NULL);
+ net_log_.EndEventWithNetErrorCode(
+ NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART, rv);
break;
default:
NOTREACHED() << "bad state";
@@ -554,6 +571,10 @@ int HttpNetworkTransaction::DoCreateStreamComplete(int result) {
return OK;
}
+ // Handle possible handshake errors that may have occurred if the stream
+ // used SSL for one or more of the layers.
+ result = HandleSSLHandshakeError(result);
+
// At this point we are done with the stream_request_.
stream_request_.reset();
return result;
@@ -696,23 +717,6 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
result = HandleCertificateRequest(result);
if (result == OK)
return result;
- } else if ((result == ERR_SSL_DECOMPRESSION_FAILURE_ALERT ||
- result == ERR_SSL_BAD_RECORD_MAC_ALERT) &&
- ssl_config_.tls1_enabled &&
- !SSLConfigService::IsKnownStrictTLSServer(request_->url.host())) {
- // Some buggy servers select DEFLATE compression when offered and then
- // fail to ever decompress anything. They will send a fatal alert telling
- // us this. Normally we would pick this up during the handshake because
- // our Finished message is compressed and we'll never get the server's
- // Finished if it fails to process ours.
- //
- // However, with False Start, we'll believe that the handshake is
- // complete as soon as we've /sent/ our Finished message. In this case,
- // we only find out that the server is buggy here, when we try to read
- // the initial reply.
- session_->http_stream_factory()->AddTLSIntolerantServer(request_->url);
- ResetConnectionAndRequestForResend();
- return OK;
}
if (result < 0 && result != ERR_CONNECTION_CLOSED)
@@ -1024,11 +1028,61 @@ int HttpNetworkTransaction::HandleCertificateRequest(int error) {
return OK;
}
+// TODO(rch): This does not correctly handle errors when an SSL proxy is
+// being used, as all of the errors are handled as if they were generated
+// by the endpoint host, request_->url, rather than considering if they were
+// generated by the SSL proxy. http://crbug.com/69329
+int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
+ DCHECK(request_);
+ if (ssl_config_.send_client_cert &&
+ (error == ERR_SSL_PROTOCOL_ERROR || IsClientCertificateError(error))) {
+ session_->ssl_client_auth_cache()->Remove(
+ GetHostAndPort(request_->url));
+ }
+
+ switch (error) {
+ case ERR_SSL_PROTOCOL_ERROR:
+ case ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
+ case ERR_SSL_DECOMPRESSION_FAILURE_ALERT:
+ case ERR_SSL_BAD_RECORD_MAC_ALERT:
+ if (ssl_config_.tls1_enabled &&
+ !SSLConfigService::IsKnownStrictTLSServer(request_->url.host())) {
+ // This could be a TLS-intolerant server, an SSL 3.0 server that
+ // chose a TLS-only cipher suite or a server with buggy DEFLATE
+ // support. Turn off TLS 1.0, DEFLATE support and retry.
+ session_->http_stream_factory()->AddTLSIntolerantServer(request_->url);
+ ResetConnectionAndRequestForResend();
+ error = OK;
+ }
+ break;
+ case ERR_SSL_SNAP_START_NPN_MISPREDICTION:
+ // This means that we tried to Snap Start a connection, but we
+ // mispredicted the NPN result. This isn't a problem from the point of
+ // view of the SSL layer because the server will ignore the application
+ // data in the Snap Start extension. However, at the HTTP layer, we have
+ // already decided that it's a HTTP or SPDY connection and it's easier to
+ // abort and start again.
+ ResetConnectionAndRequestForResend();
+ error = OK;
+ break;
+ }
+ return error;
+}
+
// This method determines whether it is safe to resend the request after an
// IO error. It can only be called in response to request header or body
// write errors or response header read errors. It should not be used in
// other cases, such as a Connect error.
int HttpNetworkTransaction::HandleIOError(int error) {
+ // SSL errors may happen at any time during the stream and indicate issues
+ // with the underlying connection. Because the peer may request
+ // renegotiation at any time, check and handle any possible SSL handshake
+ // related errors. In addition to renegotiation, TLS False/Snap Start may
+ // cause SSL handshake errors to be delayed until the first or second Write
+ // (Snap Start) or the first Read (False & Snap Start) on the underlying
+ // connection.
+ error = HandleSSLHandshakeError(error);
+
switch (error) {
// If we try to reuse a connection that the server is in the process of
// closing, we may end up successfully writing out our request (or a
@@ -1042,16 +1096,6 @@ int HttpNetworkTransaction::HandleIOError(int error) {
error = OK;
}
break;
- case ERR_SSL_SNAP_START_NPN_MISPREDICTION:
- // This means that we tried to Snap Start a connection, but we
- // mispredicted the NPN result. This isn't a problem from the point of
- // view of the SSL layer because the server will ignore the application
- // data in the Snap Start extension. However, at the HTTP layer, we have
- // already decided that it's a HTTP or SPDY connection and it's easier to
- // abort and start again.
- ResetConnectionAndRequestForResend();
- error = OK;
- break;
}
return error;
}
@@ -1191,22 +1235,6 @@ std::string HttpNetworkTransaction::DescribeState(State state) {
return description;
}
-// TODO(gavinp): re-adjust this once SPDY v3 has three priority bits,
-// eliminating the need for this folding.
-int ConvertRequestPriorityToSpdyPriority(const RequestPriority priority) {
- DCHECK(HIGHEST <= priority && priority < NUM_PRIORITIES);
- switch (priority) {
- case LOWEST:
- return SPDY_PRIORITY_LOWEST-1;
- case IDLE:
- return SPDY_PRIORITY_LOWEST;
- default:
- return priority;
- }
-}
-
-
-
#undef STATE_CASE
} // namespace net
diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h
index dfcee41..66b6b29 100644
--- a/net/http/http_network_transaction.h
+++ b/net/http/http_network_transaction.h
@@ -137,6 +137,11 @@ class HttpNetworkTransaction : public HttpTransaction,
// Called to handle a client certificate request.
int HandleCertificateRequest(int error);
+ // Called to possibly recover from an SSL handshake error. Sets next_state_
+ // and returns OK if recovering from the error. Otherwise, the same error
+ // code is returned.
+ int HandleSSLHandshakeError(int error);
+
// Called to possibly recover from the given error. Sets next_state_ and
// returns OK if recovering from the error. Otherwise, the same error code
// is returned.
@@ -249,8 +254,6 @@ class HttpNetworkTransaction : public HttpTransaction,
DISALLOW_COPY_AND_ASSIGN(HttpNetworkTransaction);
};
-int ConvertRequestPriorityToSpdyPriority(RequestPriority priority);
-
} // namespace net
#endif // NET_HTTP_HTTP_NETWORK_TRANSACTION_H_
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index 260de13..8c87136 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -20,6 +20,7 @@
#include "net/base/net_log.h"
#include "net/base/net_log_unittest.h"
#include "net/base/request_priority.h"
+#include "net/base/ssl_cert_request_info.h"
#include "net/base/ssl_config_service_defaults.h"
#include "net/base/ssl_info.h"
#include "net/base/test_completion_callback.h"
@@ -101,18 +102,16 @@ struct SessionDependencies {
};
HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
- return new HttpNetworkSession(session_deps->host_resolver.get(),
- session_deps->cert_verifier.get(),
- NULL /* dnsrr_resolver */,
- NULL /* dns_cert_checker */,
- NULL /* ssl_host_info_factory */,
- session_deps->proxy_service,
- &session_deps->socket_factory,
- session_deps->ssl_config_service,
- new SpdySessionPool(NULL),
- session_deps->http_auth_handler_factory.get(),
- NULL,
- session_deps->net_log);
+ net::HttpNetworkSession::Params params;
+ params.client_socket_factory = &session_deps->socket_factory;
+ params.host_resolver = session_deps->host_resolver.get();
+ params.cert_verifier = session_deps->cert_verifier.get();
+ params.proxy_service = session_deps->proxy_service;
+ params.ssl_config_service = session_deps->ssl_config_service;
+ params.http_auth_handler_factory =
+ session_deps->http_auth_handler_factory.get();
+ params.net_log = session_deps->net_log;
+ return new HttpNetworkSession(params);
}
class HttpNetworkTransactionTest : public PlatformTest {
@@ -147,15 +146,15 @@ class HttpNetworkTransactionTest : public PlatformTest {
size_t reads_count) {
SimpleGetHelperResult out;
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
session_deps.socket_factory.AddSocketDataProvider(&data);
@@ -253,7 +252,8 @@ std::string MockGetHostName() {
template<typename ParentPool>
class CaptureGroupNameSocketPool : public ParentPool {
public:
- explicit CaptureGroupNameSocketPool(HttpNetworkSession* session);
+ CaptureGroupNameSocketPool(HostResolver* host_resolver,
+ CertVerifier* cert_verifier);
const std::string last_group_name_received() const {
return last_group_name_;
@@ -271,7 +271,8 @@ class CaptureGroupNameSocketPool : public ParentPool {
virtual void CancelRequest(const std::string& group_name,
ClientSocketHandle* handle) {}
virtual void ReleaseSocket(const std::string& group_name,
- ClientSocket* socket) {}
+ ClientSocket* socket,
+ int id) {}
virtual void CloseIdleSockets() {}
virtual int IdleSocketCount() const {
return 0;
@@ -302,20 +303,21 @@ CaptureGroupNameSSLSocketPool;
template<typename ParentPool>
CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
- HttpNetworkSession* session)
- : ParentPool(0, 0, NULL, session->host_resolver(), NULL, NULL) {}
+ HostResolver* host_resolver,
+ CertVerifier* /* cert_verifier */)
+ : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {}
template<>
CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
- HttpNetworkSession* session)
- : HttpProxyClientSocketPool(0, 0, NULL, session->host_resolver(), NULL,
- NULL, NULL) {}
+ HostResolver* host_resolver,
+ CertVerifier* /* cert_verifier */)
+ : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {}
template<>
CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
- HttpNetworkSession* session)
- : SSLClientSocketPool(0, 0, NULL, session->host_resolver(),
- session->cert_verifier(), NULL, NULL,
+ HostResolver* host_resolver,
+ CertVerifier* cert_verifier)
+ : SSLClientSocketPool(0, 0, NULL, host_resolver, cert_verifier, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL) {}
//-----------------------------------------------------------------------------
@@ -563,15 +565,15 @@ TEST_F(HttpNetworkTransactionTest,
// Do a request using the HEAD method. Verify that we don't try to read the
// message body (since HEAD has none).
TEST_F(HttpNetworkTransactionTest, Head) {
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "HEAD";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
MockWrite data_writes1[] = {
MockWrite("HEAD / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -641,13 +643,13 @@ TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
};
for (int i = 0; i < 2; ++i) {
- scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
TestCompletionCallback callback;
int rv = trans->Start(&request, &callback, BoundNetLog());
@@ -670,10 +672,6 @@ TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
}
TEST_F(HttpNetworkTransactionTest, Ignores100) {
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "POST";
request.url = GURL("http://www.foo.com/");
@@ -681,6 +679,10 @@ TEST_F(HttpNetworkTransactionTest, Ignores100) {
request.upload_data->AppendBytes("foo", 3);
request.load_flags = 0;
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
MockRead data_reads[] = {
MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
MockRead("HTTP/1.0 200 OK\r\n\r\n"),
@@ -714,15 +716,15 @@ TEST_F(HttpNetworkTransactionTest, Ignores100) {
// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
// HTTP/1.1 and the two status headers are read in one read.
TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.foo.com/");
request.load_flags = 0;
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
MockRead data_reads[] = {
MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
"HTTP/1.1 200 OK\r\n\r\n"),
@@ -753,15 +755,15 @@ TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
}
TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "POST";
request.url = GURL("http://www.foo.com/");
request.load_flags = 0;
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
MockRead data_reads[] = {
MockRead(false, "HTTP/1.0 100 Continue\r\n"),
MockRead(true, 0),
@@ -784,15 +786,15 @@ TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
}
TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "POST";
request.url = GURL("http://www.foo.com/");
request.load_flags = 0;
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
MockRead data_reads[] = {
MockRead(true, 0),
};
@@ -812,14 +814,14 @@ TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
// transaction to resend the request.
void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
const MockRead& read_failure) {
- SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.foo.com/");
request.load_flags = 0;
+ SessionDependencies session_deps;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
MockRead data1_reads[] = {
MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
MockRead("hello"),
@@ -875,15 +877,15 @@ TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
}
TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
MockRead data_reads[] = {
MockRead(true, ERR_CONNECTION_RESET),
MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
@@ -929,14 +931,14 @@ TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
// Test that we correctly reuse a keep-alive connection after not explicitly
// reading the body.
TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
- SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.foo.com/");
request.load_flags = 0;
+ SessionDependencies session_deps;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
// Note that because all these reads happen in the same
// StaticSocketDataProvider, it shows that the same socket is being reused for
// all transactions.
@@ -1024,15 +1026,15 @@ TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
// Test the request-challenge-retry sequence for basic auth.
// (basic auth is the easiest to mock, because it has no randomness).
TEST_F(HttpNetworkTransactionTest, BasicAuth) {
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
MockWrite data_writes1[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -1109,15 +1111,15 @@ TEST_F(HttpNetworkTransactionTest, BasicAuth) {
}
TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -1152,14 +1154,14 @@ TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
// Test the request-challenge-retry sequence for basic auth, over a keep-alive
// connection.
TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
- SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ SessionDependencies session_deps;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
MockWrite data_writes1[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -1227,14 +1229,14 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
// Test the request-challenge-retry sequence for basic auth, over a keep-alive
// connection and with no response body to drain.
TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
- SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ SessionDependencies session_deps;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
MockWrite data_writes1[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -1300,14 +1302,14 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
// Test the request-challenge-retry sequence for basic auth, over a keep-alive
// connection and with a large response body to drain.
TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
- SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ SessionDependencies session_deps;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
MockWrite data_writes1[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -1381,14 +1383,14 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
// Test the request-challenge-retry sequence for basic auth, over a keep-alive
// connection, but the server gets impatient and closes the connection.
TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
- SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ SessionDependencies session_deps;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
MockWrite data_writes1[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -1472,18 +1474,18 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
// Test the request-challenge-retry sequence for basic auth, over a connection
// that requires a restart when setting up an SSL tunnel.
TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
- // Configure against proxy server "myproxy:70".
- SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
- CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
- session_deps.net_log = log.bound().net_log();
- scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
// when the no authentication data flag is set.
request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
+ // Configure against proxy server "myproxy:70".
+ SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
+ CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
+ session_deps.net_log = log.bound().net_log();
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
// Since we have proxy, should try to establish tunnel.
MockWrite data_writes1[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
@@ -1582,6 +1584,13 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
// Test the request-challenge-retry sequence for basic auth, over a keep-alive
// proxy connection, when setting up an SSL tunnel.
TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("https://www.google.com/");
+ // Ensure that proxy authentication is attempted even
+ // when the no authentication data flag is set.
+ request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
+
// Configure against proxy server "myproxy:70".
SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
@@ -1590,13 +1599,6 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
- HttpRequestInfo request;
- request.method = "GET";
- request.url = GURL("https://www.google.com/");
- // Ensure that proxy authentication is attempted even
- // when the no authentication data flag is set.
- request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
-
// Since we have proxy, should try to establish tunnel.
MockWrite data_writes1[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
@@ -1696,6 +1698,11 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
// Test that we don't read the response body when we fail to establish a tunnel,
// even if the user cancels the proxy's auth attempt.
TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("https://www.google.com/");
+ request.load_flags = 0;
+
// Configure against proxy server "myproxy:70".
SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
@@ -1703,11 +1710,6 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
- HttpRequestInfo request;
- request.method = "GET";
- request.url = GURL("https://www.google.com/");
- request.load_flags = 0;
-
// Since we have proxy, should try to establish tunnel.
MockWrite data_writes[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
@@ -1754,16 +1756,16 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
- // We are using a DIRECT connection (i.e. no proxy) for this session.
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ // We are using a DIRECT connection (i.e. no proxy) for this session.
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
MockWrite data_writes1[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -1799,15 +1801,15 @@ TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
// response came from the proxy or the server, so it is treated as if the proxy
// issued the challenge.
TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("https://www.google.com/");
+
SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
session_deps.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
- HttpRequestInfo request;
- request.method = "GET";
- request.url = GURL("https://www.google.com/");
-
// Since we have proxy, should try to establish tunnel.
MockWrite data_writes1[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
@@ -1856,16 +1858,16 @@ TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
// Test a simple get through an HTTPS Proxy.
TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("http://www.google.com/");
+
// Configure against https proxy server "proxy:70".
SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
session_deps.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
- HttpRequestInfo request;
- request.method = "GET";
- request.url = GURL("http://www.google.com/");
-
// Since we have proxy, should use full url
MockWrite data_writes1[] = {
MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
@@ -1910,17 +1912,17 @@ TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
// Test a SPDY get through an HTTPS Proxy.
TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("http://www.google.com/");
+ request.load_flags = 0;
+
// Configure against https proxy server "proxy:70".
SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
session_deps.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
- HttpRequestInfo request;
- request.method = "GET";
- request.url = GURL("http://www.google.com/");
- request.load_flags = 0;
-
// fetch http://www.google.com/ via SPDY
scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST,
false));
@@ -1969,6 +1971,11 @@ TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
// Test a SPDY get through an HTTPS Proxy.
TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("http://www.google.com/");
+ request.load_flags = 0;
+
// Configure against https proxy server "proxy:70".
SessionDependencies session_deps(
ProxyService::CreateFixed("https://proxy:70"));
@@ -1976,11 +1983,6 @@ TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
session_deps.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
- HttpRequestInfo request;
- request.method = "GET";
- request.url = GURL("http://www.google.com/");
- request.load_flags = 0;
-
// The first request will be a bare GET, the second request will be a
// GET with a Proxy-Authorization header.
scoped_ptr<spdy::SpdyFrame> req_get(
@@ -2076,6 +2078,11 @@ TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("https://www.google.com/");
+ request.load_flags = 0;
+
// Configure against https proxy server "proxy:70".
SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
@@ -2084,11 +2091,6 @@ TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
- HttpRequestInfo request;
- request.method = "GET";
- request.url = GURL("https://www.google.com/");
- request.load_flags = 0;
-
// CONNECT to www.google.com:443 via SPDY
scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
// fetch https://www.google.com/ via HTTP
@@ -2154,6 +2156,11 @@ TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("https://www.google.com/");
+ request.load_flags = 0;
+
// Configure against https proxy server "proxy:70".
SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
@@ -2162,11 +2169,6 @@ TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
- HttpRequestInfo request;
- request.method = "GET";
- request.url = GURL("https://www.google.com/");
- request.load_flags = 0;
-
// CONNECT to www.google.com:443 via SPDY
scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
// fetch https://www.google.com/ via SPDY
@@ -2228,6 +2230,11 @@ TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
// Test a SPDY CONNECT failure through an HTTPS Proxy.
TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("https://www.google.com/");
+ request.load_flags = 0;
+
// Configure against https proxy server "proxy:70".
SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
@@ -2236,11 +2243,6 @@ TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
- HttpRequestInfo request;
- request.method = "GET";
- request.url = GURL("https://www.google.com/");
- request.load_flags = 0;
-
// CONNECT to www.google.com:443 via SPDY
scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyRstStream(1, spdy::CANCEL));
@@ -2289,18 +2291,18 @@ TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
// Test the challenge-response-retry sequence through an HTTPS Proxy
TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
- // Configure against https proxy server "proxy:70".
- SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
- CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
- session_deps.net_log = log.bound().net_log();
- scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
// when the no authentication data flag is set.
request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
+ // Configure against https proxy server "proxy:70".
+ SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
+ CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
+ session_deps.net_log = log.bound().net_log();
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
// Since we have proxy, should use full url
MockWrite data_writes1[] = {
MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
@@ -2381,16 +2383,16 @@ TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
const MockRead& status, int expected_status) {
- // Configure against proxy server "myproxy:70".
- SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
-
- scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
+ // Configure against proxy server "myproxy:70".
+ SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
// Since we have proxy, should try to establish tunnel.
MockWrite data_writes[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
@@ -2593,17 +2595,17 @@ TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
// authentication. Again, this uses basic auth for both since that is
// the simplest to mock.
TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("http://www.google.com/");
+ request.load_flags = 0;
+
SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
// Configure against proxy server "myproxy:70".
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
CreateSession(&session_deps)));
- HttpRequestInfo request;
- request.method = "GET";
- request.url = GURL("http://www.google.com/");
- request.load_flags = 0;
-
MockWrite data_writes1[] = {
MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -2730,16 +2732,16 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
// Enter the correct password and authenticate successfully.
TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
- HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
- MockGetHostName);
- SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://172.22.68.17/kids/login.aspx");
request.load_flags = 0;
+ HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
+ MockGetHostName);
+ SessionDependencies session_deps;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
MockWrite data_writes1[] = {
MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
"Host: 172.22.68.17\r\n"
@@ -2822,28 +2824,37 @@ TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
- EXPECT_TRUE(trans->IsReadyToRestartForAuth());
- TestCompletionCallback callback2;
- rv = trans->RestartWithAuth(string16(), string16(), &callback2);
- EXPECT_EQ(ERR_IO_PENDING, rv);
- rv = callback2.WaitForResult();
- EXPECT_EQ(OK, rv);
EXPECT_FALSE(trans->IsReadyToRestartForAuth());
const HttpResponseInfo* response = trans->GetResponseInfo();
- ASSERT_FALSE(response == NULL);
+ ASSERT_TRUE(response != NULL);
// The password prompt info should have been set in
// response->auth_challenge.
- EXPECT_FALSE(response->auth_challenge.get() == NULL);
+ ASSERT_FALSE(response->auth_challenge.get() == NULL);
EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
EXPECT_EQ(L"", response->auth_challenge->realm);
EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
+ TestCompletionCallback callback2;
+
+ rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback2);
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback2.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ EXPECT_TRUE(trans->IsReadyToRestartForAuth());
+
+ response = trans->GetResponseInfo();
+ ASSERT_TRUE(response != NULL);
+
+ EXPECT_TRUE(response->auth_challenge.get() == NULL);
+
TestCompletionCallback callback3;
- rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback3);
+ rv = trans->RestartWithAuth(string16(), string16(), &callback3);
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback3.WaitForResult();
@@ -2851,23 +2862,22 @@ TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
response = trans->GetResponseInfo();
ASSERT_FALSE(response == NULL);
-
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_EQ(13, response->headers->GetContentLength());
}
// Enter a wrong password, and then the correct one.
TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
- HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
- MockGetHostName);
- SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://172.22.68.17/kids/login.aspx");
request.load_flags = 0;
+ HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
+ MockGetHostName);
+ SessionDependencies session_deps;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
MockWrite data_writes1[] = {
MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
"Host: 172.22.68.17\r\n"
@@ -3001,12 +3011,6 @@ TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
- EXPECT_TRUE(trans->IsReadyToRestartForAuth());
- TestCompletionCallback callback2;
- rv = trans->RestartWithAuth(string16(), string16(), &callback2);
- EXPECT_EQ(ERR_IO_PENDING, rv);
- rv = callback2.WaitForResult();
- EXPECT_EQ(OK, rv);
EXPECT_FALSE(trans->IsReadyToRestartForAuth());
const HttpResponseInfo* response = trans->GetResponseInfo();
@@ -3019,25 +3023,25 @@ TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
EXPECT_EQ(L"", response->auth_challenge->realm);
EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
- TestCompletionCallback callback3;
+ TestCompletionCallback callback2;
// Enter the wrong password.
- rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback3);
+ rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback2);
EXPECT_EQ(ERR_IO_PENDING, rv);
- rv = callback3.WaitForResult();
+ rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_TRUE(trans->IsReadyToRestartForAuth());
- TestCompletionCallback callback4;
- rv = trans->RestartWithAuth(string16(), string16(), &callback4);
+ TestCompletionCallback callback3;
+ rv = trans->RestartWithAuth(string16(), string16(), &callback3);
EXPECT_EQ(ERR_IO_PENDING, rv);
- rv = callback4.WaitForResult();
+ rv = callback3.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_FALSE(trans->IsReadyToRestartForAuth());
response = trans->GetResponseInfo();
- EXPECT_FALSE(response == NULL);
+ ASSERT_TRUE(response != NULL);
// The password prompt info should have been set in response->auth_challenge.
EXPECT_FALSE(response->auth_challenge.get() == NULL);
@@ -3046,10 +3050,21 @@ TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
EXPECT_EQ(L"", response->auth_challenge->realm);
EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
- TestCompletionCallback callback5;
+ TestCompletionCallback callback4;
// Now enter the right password.
- rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback5);
+ rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback4);
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback4.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ EXPECT_TRUE(trans->IsReadyToRestartForAuth());
+
+ TestCompletionCallback callback5;
+
+ // One more roundtrip
+ rv = trans->RestartWithAuth(string16(), string16(), &callback5);
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback5.WaitForResult();
@@ -3065,15 +3080,15 @@ TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
// After some maximum number of bytes is consumed, the transaction should
// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
// Respond with 300 kb of headers (we should fail after 256 kb).
std::string large_headers_string;
FillLargeHeadersString(&large_headers_string, 300 * 1024);
@@ -3103,6 +3118,11 @@ TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
// establish tunnel.
// http://code.google.com/p/chromium/issues/detail?id=3772
TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("https://www.google.com/");
+ request.load_flags = 0;
+
// Configure against proxy server "myproxy:70".
SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
@@ -3110,11 +3130,6 @@ TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
- HttpRequestInfo request;
- request.method = "GET";
- request.url = GURL("https://www.google.com/");
- request.load_flags = 0;
-
// Since we have proxy, should try to establish tunnel.
MockWrite data_writes1[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
@@ -3161,16 +3176,16 @@ TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
// Make sure that we recycle a socket after reading all of the response body.
TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
- SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
- scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ SessionDependencies session_deps;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
+ scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
MockRead data_reads[] = {
// A part of the response body is received with the response headers.
MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
@@ -3371,11 +3386,6 @@ TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
// Make sure that we recycle a socket after a zero-length response.
// http://crbug.com/9880
TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
- SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
- scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
@@ -3384,6 +3394,11 @@ TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
"rt=prt.2642,ol.2649,xjs.2951");
request.load_flags = 0;
+ SessionDependencies session_deps;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
+ scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
MockRead data_reads[] = {
MockRead("HTTP/1.1 204 No Content\r\n"
"Content-Length: 0\r\n"
@@ -3516,15 +3531,15 @@ TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
// an identity in the URL. The request should be sent as normal, but when
// it fails the identity from the URL is used to answer the challenge.
TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "GET";
// Note: the URL has a username:password in it.
request.url = GURL("http://foo:b@r@www.google.com/");
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
// The password contains an escaped character -- for this test to pass it
// will need to be unescaped by HttpNetworkTransaction.
EXPECT_EQ("b%40r", request.url.password());
@@ -3598,10 +3613,6 @@ TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
// an incorrect identity in the URL. The identity from the URL should be used
// only once.
TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "GET";
// Note: the URL has a username:password in it. The password "baz" is
@@ -3610,6 +3621,10 @@ TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
request.load_flags = LOAD_NORMAL;
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
MockWrite data_writes1[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -3715,13 +3730,13 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
// Transaction 1: authenticate (foo, bar) on MyRealm1
{
- scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/x/y/z");
request.load_flags = 0;
+ scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
MockWrite data_writes1[] = {
MockWrite("GET /x/y/z HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -3794,8 +3809,6 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
// Transaction 2: authenticate (foo2, bar2) on MyRealm2
{
- scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
HttpRequestInfo request;
request.method = "GET";
// Note that Transaction 1 was at /x/y/z, so this is in the same
@@ -3803,6 +3816,8 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
request.url = GURL("http://www.google.com/x/y/a/b");
request.load_flags = 0;
+ scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
MockWrite data_writes1[] = {
MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -3880,13 +3895,13 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
// Transaction 3: Resend a request in MyRealm's protection space --
// succeed with preemptive authorization.
{
- scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/x/y/z2");
request.load_flags = 0;
+ scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
MockWrite data_writes1[] = {
MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -3927,13 +3942,13 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
// Transaction 4: request another URL in MyRealm (however the
// url is not known to belong to the protection space, so no pre-auth).
{
- scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/x/1");
request.load_flags = 0;
+ scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
MockWrite data_writes1[] = {
MockWrite("GET /x/1 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -3996,13 +4011,13 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
// Transaction 5: request a URL in MyRealm, but the server rejects the
// cached identity. Should invalidate and re-prompt.
{
- scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/p/q/t");
request.load_flags = 0;
+ scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
MockWrite data_writes1[] = {
MockWrite("GET /p/q/t HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -4114,13 +4129,13 @@ TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
// Transaction 1: authenticate (foo, bar) on MyRealm1
{
- scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/x/y/z");
request.load_flags = 0;
+ scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
MockWrite data_writes1[] = {
MockWrite("GET /x/y/z HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -4196,8 +4211,6 @@ TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
// This will preemptively add an Authorization header which should have an
// "nc" value of 2 (as compared to 1 in the first use.
{
- scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
HttpRequestInfo request;
request.method = "GET";
// Note that Transaction 1 was at /x/y/z, so this is in the same
@@ -4205,6 +4218,8 @@ TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
request.url = GURL("http://www.google.com/x/y/a/b");
request.load_flags = 0;
+ scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
MockWrite data_writes1[] = {
MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -4285,15 +4300,15 @@ TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
// Test HTTPS connections to a site with a bad certificate
TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -4786,16 +4801,16 @@ TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
}
TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
"Chromium Ultra Awesome X Edition");
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -4825,16 +4840,16 @@ TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
}
TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
- SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
"Chromium Ultra Awesome X Edition");
+ SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
MockWrite data_writes[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -4863,16 +4878,16 @@ TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
}
TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
request.referrer = GURL("http://the.previous.site.com/");
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -4902,14 +4917,14 @@ TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
}
TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "POST";
request.url = GURL("http://www.google.com/");
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
MockWrite data_writes[] = {
MockWrite("POST / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -4939,14 +4954,14 @@ TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
}
TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "PUT";
request.url = GURL("http://www.google.com/");
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
MockWrite data_writes[] = {
MockWrite("PUT / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -4976,14 +4991,14 @@ TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
}
TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "HEAD";
request.url = GURL("http://www.google.com/");
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
MockWrite data_writes[] = {
MockWrite("HEAD / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -5013,15 +5028,15 @@ TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
}
TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = LOAD_BYPASS_CACHE;
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -5053,15 +5068,15 @@ TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
TEST_F(HttpNetworkTransactionTest,
BuildRequest_CacheControlValidateCache) {
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = LOAD_VALIDATE_CACHE;
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -5091,15 +5106,15 @@ TEST_F(HttpNetworkTransactionTest,
}
TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.extra_headers.SetHeader("FooHeader", "Bar");
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -5129,10 +5144,6 @@ TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
}
TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
@@ -5140,6 +5151,10 @@ TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
request.extra_headers.SetHeader("hEllo", "Kitty");
request.extra_headers.SetHeader("FoO", "bar");
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
@@ -5170,17 +5185,17 @@ TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
}
TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("http://www.google.com/");
+ request.load_flags = 0;
+
SessionDependencies session_deps(
ProxyService::CreateFixed("socks4://myproxy:1080"));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(CreateSession(&session_deps)));
- HttpRequestInfo request;
- request.method = "GET";
- request.url = GURL("http://www.google.com/");
- request.load_flags = 0;
-
char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
@@ -5221,17 +5236,17 @@ TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
}
TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("https://www.google.com/");
+ request.load_flags = 0;
+
SessionDependencies session_deps(
ProxyService::CreateFixed("socks4://myproxy:1080"));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(CreateSession(&session_deps)));
- HttpRequestInfo request;
- request.method = "GET";
- request.url = GURL("https://www.google.com/");
- request.load_flags = 0;
-
unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
@@ -5277,17 +5292,17 @@ TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
}
TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("http://www.google.com/");
+ request.load_flags = 0;
+
SessionDependencies session_deps(
ProxyService::CreateFixed("socks5://myproxy:1080"));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(CreateSession(&session_deps)));
- HttpRequestInfo request;
- request.method = "GET";
- request.url = GURL("http://www.google.com/");
- request.load_flags = 0;
-
const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
const char kSOCKS5OkRequest[] = {
@@ -5342,17 +5357,17 @@ TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
}
TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("https://www.google.com/");
+ request.load_flags = 0;
+
SessionDependencies session_deps(
ProxyService::CreateFixed("socks5://myproxy:1080"));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(CreateSession(&session_deps)));
- HttpRequestInfo request;
- request.method = "GET";
- request.url = GURL("https://www.google.com/");
- request.load_flags = 0;
-
const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
const unsigned char kSOCKS5OkRequest[] = {
@@ -5437,13 +5452,13 @@ scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
int GroupNameTransactionHelper(
const std::string& url,
const scoped_refptr<HttpNetworkSession>& session) {
- scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL(url);
request.load_flags = 0;
+ scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
TestCompletionCallback callback;
// We do not complete this request, the dtor will clean the transaction up.
@@ -5494,10 +5509,10 @@ TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
HttpNetworkSessionPeer peer(session);
CaptureGroupNameTCPSocketPool* tcp_conn_pool =
- new CaptureGroupNameTCPSocketPool(session);
+ new CaptureGroupNameTCPSocketPool(NULL, NULL);
peer.SetTCPSocketPool(tcp_conn_pool);
CaptureGroupNameSSLSocketPool* ssl_conn_pool =
- new CaptureGroupNameSSLSocketPool(session.get());
+ new CaptureGroupNameSSLSocketPool(NULL, NULL);
peer.SetSSLSocketPool(ssl_conn_pool);
EXPECT_EQ(ERR_IO_PENDING,
@@ -5548,10 +5563,10 @@ TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
HostPortPair proxy_host("http_proxy", 80);
CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
- new CaptureGroupNameHttpProxySocketPool(session);
+ new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
CaptureGroupNameSSLSocketPool* ssl_conn_pool =
- new CaptureGroupNameSSLSocketPool(session);
+ new CaptureGroupNameSSLSocketPool(NULL, NULL);
peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
EXPECT_EQ(ERR_IO_PENDING,
@@ -5613,10 +5628,10 @@ TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
HostPortPair proxy_host("socks_proxy", 1080);
CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
- new CaptureGroupNameSOCKSSocketPool(session);
+ new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
CaptureGroupNameSSLSocketPool* ssl_conn_pool =
- new CaptureGroupNameSSLSocketPool(session);
+ new CaptureGroupNameSSLSocketPool(NULL, NULL);
peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
@@ -5635,6 +5650,10 @@ TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
}
TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("http://www.google.com/");
+
SessionDependencies session_deps(
ProxyService::CreateFixed("myproxy:70;foobar:80"));
@@ -5645,10 +5664,6 @@ TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(CreateSession(&session_deps)));
- HttpRequestInfo request;
- request.method = "GET";
- request.url = GURL("http://www.google.com/");
-
TestCompletionCallback callback;
int rv = trans->Start(&request, &callback, BoundNetLog());
@@ -5705,6 +5720,12 @@ TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
EXPECT_TRUE(referrer.is_valid());
ResolutionReferrerObserver resolution_observer(referrer);
+ // Issue a request, containing an HTTP referrer.
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.referrer = referrer;
+ request.url = GURL("http://www.google.com/");
+
SessionDependencies session_deps;
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
CreateSession(&session_deps)));
@@ -5719,12 +5740,6 @@ TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
session_deps.socket_factory.AddSocketDataProvider(&data);
- // Issue a request, containing an HTTP referrer.
- HttpRequestInfo request;
- request.method = "GET";
- request.referrer = referrer;
- request.url = GURL("http://www.google.com/");
-
// Run the request until it fails reading from the socket.
TestCompletionCallback callback;
int rv = trans->Start(&request, &callback, BoundNetLog());
@@ -5739,6 +5754,12 @@ TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
// Base test to make sure that when the load flags for a request specify to
// bypass the cache, the DNS cache is not used.
void BypassHostCacheOnRefreshHelper(int load_flags) {
+ // Issue a request, asking to bypass the cache(s).
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.load_flags = load_flags;
+ request.url = GURL("http://www.google.com/");
+
SessionDependencies session_deps;
// Select a host resolver that does caching.
@@ -5774,12 +5795,6 @@ void BypassHostCacheOnRefreshHelper(int load_flags) {
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
session_deps.socket_factory.AddSocketDataProvider(&data);
- // Issue a request, asking to bypass the cache(s).
- HttpRequestInfo request;
- request.method = "GET";
- request.load_flags = load_flags;
- request.url = GURL("http://www.google.com/");
-
// Run the request.
TestCompletionCallback callback;
rv = trans->Start(&request, &callback, BoundNetLog());
@@ -5995,15 +6010,15 @@ TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
}
TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
MockRead(false, OK),
@@ -6031,16 +6046,16 @@ TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
}
TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
- SessionDependencies session_deps;
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "POST";
request.url = GURL("http://www.google.com/upload");
request.upload_data = new UploadData;
request.load_flags = 0;
+ SessionDependencies session_deps;
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
FilePath temp_file_path;
ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
const uint64 kFakeSize = 100000; // file is actually blank
@@ -6084,6 +6099,12 @@ TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
}
TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
+ HttpRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.google.com/upload");
+ request.upload_data = new UploadData;
+ request.load_flags = 0;
+
// If we try to upload an unreadable file, the network stack should report
// the file size as zero and upload zero bytes for that file.
SessionDependencies session_deps;
@@ -6097,12 +6118,6 @@ TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
temp_file_content.length()));
ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
- HttpRequestInfo request;
- request.method = "POST";
- request.url = GURL("http://www.google.com/upload");
- request.upload_data = new UploadData;
- request.load_flags = 0;
-
std::vector<UploadData::Element> elements;
UploadData::Element element;
element.SetToFilePath(temp_file);
@@ -6141,6 +6156,12 @@ TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
}
TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
+ HttpRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.google.com/upload");
+ request.upload_data = new UploadData;
+ request.load_flags = 0;
+
SessionDependencies session_deps;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(CreateSession(&session_deps)));
@@ -6152,12 +6173,6 @@ TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
temp_file_contents.length()));
- HttpRequestInfo request;
- request.method = "POST";
- request.url = GURL("http://www.google.com/upload");
- request.upload_data = new UploadData;
- request.load_flags = 0;
-
std::vector<UploadData::Element> elements;
UploadData::Element element;
element.SetToFilePath(temp_file);
@@ -6919,15 +6934,14 @@ TEST_F(HttpNetworkTransactionTest,
SSLConfig ssl_config;
session->ssl_config_service()->GetSSLConfig(&ssl_config);
- ClientSocket* socket = connection->release_socket();
- socket = session->socket_factory()->CreateSSLClientSocket(
- socket, HostPortPair("" , 443), ssl_config, NULL /* ssl_host_info */,
- session->cert_verifier());
- connection->set_socket(socket);
- EXPECT_EQ(ERR_IO_PENDING, socket->Connect(&callback));
+ scoped_ptr<ClientSocketHandle> ssl_connection(new ClientSocketHandle);
+ ssl_connection->set_socket(session_deps.socket_factory.CreateSSLClientSocket(
+ connection.release(), HostPortPair("" , 443), ssl_config,
+ NULL /* ssl_host_info */, session_deps.cert_verifier.get(), NULL));
+ EXPECT_EQ(ERR_IO_PENDING, ssl_connection->socket()->Connect(&callback));
EXPECT_EQ(OK, callback.WaitForResult());
- EXPECT_EQ(OK, spdy_session->InitializeWithSocket(connection.release(),
+ EXPECT_EQ(OK, spdy_session->InitializeWithSocket(ssl_connection.release(),
true, OK));
trans.reset(new HttpNetworkTransaction(session));
@@ -7383,15 +7397,30 @@ TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
origin, BoundNetLog());
auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
- scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
- scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
int rv = OK;
const HttpResponseInfo* response = NULL;
HttpRequestInfo request;
request.method = "GET";
request.url = origin;
request.load_flags = 0;
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
+ // Use a TCP Socket Pool with only one connection per group. This is used
+ // to validate that the TCP socket is not released to the pool between
+ // each round of multi-round authentication.
+ HttpNetworkSessionPeer session_peer(session);
+ ClientSocketPoolHistograms tcp_pool_histograms("SmallTCP");
+ TCPClientSocketPool* tcp_pool = new TCPClientSocketPool(
+ 50, // Max sockets for pool
+ 1, // Max sockets per group
+ &tcp_pool_histograms,
+ session_deps.host_resolver.get(),
+ &session_deps.socket_factory,
+ session_deps.net_log);
+ session_peer.SetTCPSocketPool(tcp_pool);
+
+ scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
TestCompletionCallback callback;
const MockWrite kGet(
@@ -7424,7 +7453,9 @@ TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
// Third round
kGetAuth,
// Fourth round
- kGetAuth
+ kGetAuth,
+ // Competing request
+ kGet,
};
MockRead reads[] = {
// First round
@@ -7435,12 +7466,16 @@ TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
kServerChallenge,
// Fourth round
kSuccess,
+ // Competing response
+ kSuccess,
};
StaticSocketDataProvider data_provider(reads, arraysize(reads),
writes, arraysize(writes));
session_deps.socket_factory.AddSocketDataProvider(&data_provider);
- // First round
+ const char* const kSocketGroup = "www.example.com:80";
+
+ // First round of authentication.
auth_handler->SetGenerateExpectation(false, OK);
rv = trans->Start(&request, &callback, BoundNetLog());
if (rv == ERR_IO_PENDING)
@@ -7449,8 +7484,21 @@ TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
response = trans->GetResponseInfo();
ASSERT_FALSE(response == NULL);
EXPECT_FALSE(response->auth_challenge.get() == NULL);
+ EXPECT_EQ(0, tcp_pool->IdleSocketCountInGroup(kSocketGroup));
+
+ // In between rounds, another request comes in for the same domain.
+ // It should not be able to grab the TCP socket that trans has already
+ // claimed.
+ scoped_ptr<HttpTransaction> trans_compete(
+ new HttpNetworkTransaction(session));
+ TestCompletionCallback callback_compete;
+ rv = trans_compete->Start(&request, &callback_compete, BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ // callback_compete.WaitForResult at this point would stall forever,
+ // since the HttpNetworkTransaction does not release the request back to
+ // the pool until after authentication completes.
- // Second round
+ // Second round of authentication.
auth_handler->SetGenerateExpectation(false, OK);
rv = trans->RestartWithAuth(kFoo, kBar, &callback);
if (rv == ERR_IO_PENDING)
@@ -7459,8 +7507,9 @@ TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
response = trans->GetResponseInfo();
ASSERT_FALSE(response == NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
+ EXPECT_EQ(0, tcp_pool->IdleSocketCountInGroup(kSocketGroup));
- // Third round
+ // Third round of authentication.
auth_handler->SetGenerateExpectation(false, OK);
rv = trans->RestartWithAuth(string16(), string16(), &callback);
if (rv == ERR_IO_PENDING)
@@ -7469,8 +7518,9 @@ TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
response = trans->GetResponseInfo();
ASSERT_FALSE(response == NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
+ EXPECT_EQ(0, tcp_pool->IdleSocketCountInGroup(kSocketGroup));
- // Fourth round
+ // Fourth round of authentication, which completes successfully.
auth_handler->SetGenerateExpectation(false, OK);
rv = trans->RestartWithAuth(string16(), string16(), &callback);
if (rv == ERR_IO_PENDING)
@@ -7479,6 +7529,34 @@ TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
response = trans->GetResponseInfo();
ASSERT_FALSE(response == NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
+ EXPECT_EQ(0, tcp_pool->IdleSocketCountInGroup(kSocketGroup));
+
+ // Read the body since the fourth round was successful. This will also
+ // release the socket back to the pool.
+ scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
+ rv = trans->Read(io_buf, io_buf->size(), &callback);
+ if (rv == ERR_IO_PENDING)
+ rv = callback.WaitForResult();
+ EXPECT_EQ(3, rv);
+ rv = trans->Read(io_buf, io_buf->size(), &callback);
+ EXPECT_EQ(0, rv);
+ // There are still 0 idle sockets, since the trans_compete transaction
+ // will be handed it immediately after trans releases it to the group.
+ EXPECT_EQ(0, tcp_pool->IdleSocketCountInGroup(kSocketGroup));
+
+ // The competing request can now finish. Wait for the headers and then
+ // read the body.
+ rv = callback_compete.WaitForResult();
+ EXPECT_EQ(OK, rv);
+ rv = trans_compete->Read(io_buf, io_buf->size(), &callback);
+ if (rv == ERR_IO_PENDING)
+ rv = callback.WaitForResult();
+ EXPECT_EQ(3, rv);
+ rv = trans_compete->Read(io_buf, io_buf->size(), &callback);
+ EXPECT_EQ(0, rv);
+
+ // Finally, the socket is released to the group.
+ EXPECT_EQ(1, tcp_pool->IdleSocketCountInGroup(kSocketGroup));
}
class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
@@ -7858,16 +7936,16 @@ TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
MockRead(false, OK),
};
- SessionDependencies session_deps;
- session_deps.host_resolver->set_synchronous_mode(true);
- scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(CreateSession(&session_deps)));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ SessionDependencies session_deps;
+ session_deps.host_resolver->set_synchronous_mode(true);
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
data.set_connect_data(mock_connect);
session_deps.socket_factory.AddSocketDataProvider(&data);
@@ -8118,6 +8196,11 @@ TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
// Given a net error, cause that error to be returned from the first Write()
// call and verify that the HttpTransaction fails with that error.
static void CheckErrorIsPassedBack(int error, bool async) {
+ net::HttpRequestInfo request_info;
+ request_info.url = GURL("https://www.example.com/");
+ request_info.method = "GET";
+ request_info.load_flags = net::LOAD_NORMAL;
+
SessionDependencies session_deps;
SSLSocketDataProvider ssl_data(async, OK);
@@ -8132,11 +8215,6 @@ static void CheckErrorIsPassedBack(int error, bool async) {
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
- net::HttpRequestInfo request_info;
- request_info.url = GURL("https://www.example.com/");
- request_info.method = "GET";
- request_info.load_flags = net::LOAD_NORMAL;
-
TestCompletionCallback callback;
int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
if (rv == net::ERR_IO_PENDING)
@@ -8159,6 +8237,11 @@ TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
// Test that the transaction is restarted in the event of an NPN misprediction.
TEST_F(HttpNetworkTransactionTest, NPNMispredict) {
+ net::HttpRequestInfo request_info;
+ request_info.url = GURL("https://www.example.com/");
+ request_info.method = "GET";
+ request_info.load_flags = net::LOAD_NORMAL;
+
SessionDependencies session_deps;
SSLSocketDataProvider ssl_data1(true /* async */, OK);
@@ -8190,11 +8273,6 @@ TEST_F(HttpNetworkTransactionTest, NPNMispredict) {
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
- net::HttpRequestInfo request_info;
- request_info.url = GURL("https://www.example.com/");
- request_info.method = "GET";
- request_info.load_flags = net::LOAD_NORMAL;
-
TestCompletionCallback callback;
int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
if (rv == net::ERR_IO_PENDING)
@@ -8207,4 +8285,303 @@ TEST_F(HttpNetworkTransactionTest, NPNMispredict) {
EXPECT_EQ("hello world", contents);
}
+// Ensure that a client certificate is removed from the SSL client auth
+// cache when:
+// 1) No proxy is involved.
+// 2) TLS False Start is disabled.
+// 3) The initial TLS handshake requests a client certificate.
+// 4) The client supplies an invalid/unacceptable certificate.
+TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
+ net::HttpRequestInfo request_info;
+ request_info.url = GURL("https://www.example.com/");
+ request_info.method = "GET";
+ request_info.load_flags = net::LOAD_NORMAL;
+
+ SessionDependencies session_deps;
+
+ scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
+ cert_request->host_and_port = "www.example.com:443";
+
+ // [ssl_]data1 contains the data for the first SSL handshake. When a
+ // CertificateRequest is received for the first time, the handshake will
+ // be aborted to allow the caller to provide a certificate.
+ SSLSocketDataProvider ssl_data1(true /* async */,
+ net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
+ ssl_data1.cert_request_info = cert_request.get();
+ session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
+ net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
+ session_deps.socket_factory.AddSocketDataProvider(&data1);
+
+ // [ssl_]data2 contains the data for the second SSL handshake. When TLS
+ // False Start is not being used, the result of the SSL handshake will be
+ // returned as part of the SSLClientSocket::Connect() call. This test
+ // matches the result of a server sending a handshake_failure alert,
+ // rather than a Finished message, because it requires a client
+ // certificate and none was supplied.
+ SSLSocketDataProvider ssl_data2(true /* async */,
+ net::ERR_SSL_PROTOCOL_ERROR);
+ ssl_data2.cert_request_info = cert_request.get();
+ session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
+ net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
+ session_deps.socket_factory.AddSocketDataProvider(&data2);
+
+ // [ssl_]data3 contains the data for the third SSL handshake. When a
+ // connection to a server fails during an SSL handshake,
+ // HttpNetworkTransaction will attempt to fallback to SSLv3 if the initial
+ // connection was attempted with TLSv1. This is transparent to the caller
+ // of the HttpNetworkTransaction. Because this test failure is due to
+ // requiring a client certificate, this fallback handshake should also
+ // fail.
+ SSLSocketDataProvider ssl_data3(true /* async */,
+ net::ERR_SSL_PROTOCOL_ERROR);
+ ssl_data3.cert_request_info = cert_request.get();
+ session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
+ net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
+ session_deps.socket_factory.AddSocketDataProvider(&data3);
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+ scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
+
+ // Begin the SSL handshake with the peer. This consumes ssl_data1.
+ TestCompletionCallback callback;
+ int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
+ ASSERT_EQ(net::ERR_IO_PENDING, rv);
+
+ // Complete the SSL handshake, which should abort due to requiring a
+ // client certificate.
+ rv = callback.WaitForResult();
+ ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
+
+ // Indicate that no certificate should be supplied. From the perspective
+ // of SSLClientCertCache, NULL is just as meaningful as a real
+ // certificate, so this is the same as supply a
+ // legitimate-but-unacceptable certificate.
+ rv = trans->RestartWithCertificate(NULL, &callback);
+ ASSERT_EQ(net::ERR_IO_PENDING, rv);
+
+ // Ensure the certificate was added to the client auth cache before
+ // allowing the connection to continue restarting.
+ scoped_refptr<X509Certificate> client_cert;
+ ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
+ &client_cert));
+ ASSERT_EQ(NULL, client_cert.get());
+
+ // Restart the handshake. This will consume ssl_data2, which fails, and
+ // then consume ssl_data3, which should also fail. The result code is
+ // checked against what ssl_data3 should return.
+ rv = callback.WaitForResult();
+ ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
+
+ // Ensure that the client certificate is removed from the cache on a
+ // handshake failure.
+ ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
+ &client_cert));
+}
+
+// Ensure that a client certificate is removed from the SSL client auth
+// cache when:
+// 1) No proxy is involved.
+// 2) TLS False Start is enabled.
+// 3) The initial TLS handshake requests a client certificate.
+// 4) The client supplies an invalid/unacceptable certificate.
+TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
+ net::HttpRequestInfo request_info;
+ request_info.url = GURL("https://www.example.com/");
+ request_info.method = "GET";
+ request_info.load_flags = net::LOAD_NORMAL;
+
+ SessionDependencies session_deps;
+
+ scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
+ cert_request->host_and_port = "www.example.com:443";
+
+ // When TLS False Start is used, SSLClientSocket::Connect() calls will
+ // return successfully after reading up to the peer's Certificate message.
+ // This is to allow the caller to call SSLClientSocket::Write(), which can
+ // enqueue application data to be sent in the same packet as the
+ // ChangeCipherSpec and Finished messages.
+ // The actual handshake will be finished when SSLClientSocket::Read() is
+ // called, which expects to process the peer's ChangeCipherSpec and
+ // Finished messages. If there was an error negotiating with the peer,
+ // such as due to the peer requiring a client certificate when none was
+ // supplied, the alert sent by the peer won't be processed until Read() is
+ // called.
+
+ // Like the non-False Start case, when a client certificate is requested by
+ // the peer, the handshake is aborted during the Connect() call.
+ // [ssl_]data1 represents the initial SSL handshake with the peer.
+ SSLSocketDataProvider ssl_data1(true /* async */,
+ net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
+ ssl_data1.cert_request_info = cert_request.get();
+ session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
+ net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
+ session_deps.socket_factory.AddSocketDataProvider(&data1);
+
+ // When a client certificate is supplied, Connect() will not be aborted
+ // when the peer requests the certificate. Instead, the handshake will
+ // artificially succeed, allowing the caller to write the HTTP request to
+ // the socket. The handshake messages are not processed until Read() is
+ // called, which then detects that the handshake was aborted, due to the
+ // peer sending a handshake_failure because it requires a client
+ // certificate.
+ SSLSocketDataProvider ssl_data2(true /* async */, net::OK);
+ ssl_data2.cert_request_info = cert_request.get();
+ session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
+ net::MockRead data2_reads[] = {
+ net::MockRead(true /* async */, net::ERR_SSL_PROTOCOL_ERROR),
+ };
+ net::StaticSocketDataProvider data2(
+ data2_reads, arraysize(data2_reads), NULL, 0);
+ session_deps.socket_factory.AddSocketDataProvider(&data2);
+
+ // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
+ // the data for the SSL handshake once the TLSv1 connection falls back to
+ // SSLv3. It has the same behaviour as [ssl_]data2.
+ SSLSocketDataProvider ssl_data3(true /* async */, net::OK);
+ ssl_data3.cert_request_info = cert_request.get();
+ session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
+ net::StaticSocketDataProvider data3(
+ data2_reads, arraysize(data2_reads), NULL, 0);
+ session_deps.socket_factory.AddSocketDataProvider(&data3);
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+ scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
+
+ // Begin the initial SSL handshake.
+ TestCompletionCallback callback;
+ int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
+ ASSERT_EQ(net::ERR_IO_PENDING, rv);
+
+ // Complete the SSL handshake, which should abort due to requiring a
+ // client certificate.
+ rv = callback.WaitForResult();
+ ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
+
+ // Indicate that no certificate should be supplied. From the perspective
+ // of SSLClientCertCache, NULL is just as meaningful as a real
+ // certificate, so this is the same as supply a
+ // legitimate-but-unacceptable certificate.
+ rv = trans->RestartWithCertificate(NULL, &callback);
+ ASSERT_EQ(net::ERR_IO_PENDING, rv);
+
+ // Ensure the certificate was added to the client auth cache before
+ // allowing the connection to continue restarting.
+ scoped_refptr<X509Certificate> client_cert;
+ ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
+ &client_cert));
+ ASSERT_EQ(NULL, client_cert.get());
+
+
+ // Restart the handshake. This will consume ssl_data2, which fails, and
+ // then consume ssl_data3, which should also fail. The result code is
+ // checked against what ssl_data3 should return.
+ rv = callback.WaitForResult();
+ ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
+
+ // Ensure that the client certificate is removed from the cache on a
+ // handshake failure.
+ ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
+ &client_cert));
+}
+
+// Ensure that a client certificate is removed from the SSL client auth
+// cache when:
+// 1) An HTTPS proxy is involved.
+// 3) The HTTPS proxy requests a client certificate.
+// 4) The client supplies an invalid/unacceptable certificate for the
+// proxy.
+// The test is repeated twice, first for connecting to an HTTPS endpoint,
+// then for connecting to an HTTP endpoint.
+TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
+ SessionDependencies session_deps(
+ ProxyService::CreateFixed("https://proxy:70"));
+ CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
+ session_deps.net_log = log.bound().net_log();
+
+ scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
+ cert_request->host_and_port = "proxy:70";
+
+ // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
+ // [ssl_]data[1-3]. Rather than represending the endpoint
+ // (www.example.com:443), they represent failures with the HTTPS proxy
+ // (proxy:70).
+ SSLSocketDataProvider ssl_data1(true /* async */,
+ net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
+ ssl_data1.cert_request_info = cert_request.get();
+ session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
+ net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
+ session_deps.socket_factory.AddSocketDataProvider(&data1);
+
+ SSLSocketDataProvider ssl_data2(true /* async */,
+ net::ERR_SSL_PROTOCOL_ERROR);
+ ssl_data2.cert_request_info = cert_request.get();
+ session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
+ net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
+ session_deps.socket_factory.AddSocketDataProvider(&data2);
+
+ SSLSocketDataProvider ssl_data3(true /* async */,
+ net::ERR_SSL_PROTOCOL_ERROR);
+ ssl_data3.cert_request_info = cert_request.get();
+ session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
+ net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
+ session_deps.socket_factory.AddSocketDataProvider(&data3);
+
+ net::HttpRequestInfo requests[2];
+ requests[0].url = GURL("https://www.example.com/");
+ requests[0].method = "GET";
+ requests[0].load_flags = net::LOAD_NORMAL;
+
+ requests[1].url = GURL("http://www.example.com/");
+ requests[1].method = "GET";
+ requests[1].load_flags = net::LOAD_NORMAL;
+
+ for (size_t i = 0; i < arraysize(requests); ++i) {
+ session_deps.socket_factory.ResetNextMockIndexes();
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+ scoped_ptr<HttpNetworkTransaction> trans(
+ new HttpNetworkTransaction(session));
+
+ // Begin the SSL handshake with the proxy.
+ TestCompletionCallback callback;
+ int rv = trans->Start(&requests[i], &callback, net::BoundNetLog());
+ ASSERT_EQ(net::ERR_IO_PENDING, rv);
+
+ // Complete the SSL handshake, which should abort due to requiring a
+ // client certificate.
+ rv = callback.WaitForResult();
+ ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
+
+ // Indicate that no certificate should be supplied. From the perspective
+ // of SSLClientCertCache, NULL is just as meaningful as a real
+ // certificate, so this is the same as supply a
+ // legitimate-but-unacceptable certificate.
+ rv = trans->RestartWithCertificate(NULL, &callback);
+ ASSERT_EQ(net::ERR_IO_PENDING, rv);
+
+ // Ensure the certificate was added to the client auth cache before
+ // allowing the connection to continue restarting.
+ scoped_refptr<X509Certificate> client_cert;
+ ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70",
+ &client_cert));
+ ASSERT_EQ(NULL, client_cert.get());
+ // Ensure the certificate was NOT cached for the endpoint. This only
+ // applies to HTTPS requests, but is fine to check for HTTP requests.
+ ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
+ &client_cert));
+
+ // Restart the handshake. This will consume ssl_data2, which fails, and
+ // then consume ssl_data3, which should also fail. The result code is
+ // checked against what ssl_data3 should return.
+ rv = callback.WaitForResult();
+ ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
+
+ // Now that the new handshake has failed, ensure that the client
+ // certificate was removed from the client auth cache.
+ ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70",
+ &client_cert));
+ ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
+ &client_cert));
+ }
+}
+
} // namespace net
diff --git a/net/http/http_proxy_client_socket.cc b/net/http/http_proxy_client_socket.cc
index ce108b1..4932da0 100644
--- a/net/http/http_proxy_client_socket.cc
+++ b/net/http/http_proxy_client_socket.cc
@@ -62,6 +62,24 @@ HttpProxyClientSocket::~HttpProxyClientSocket() {
Disconnect();
}
+int HttpProxyClientSocket::RestartWithAuth(CompletionCallback* callback) {
+ DCHECK_EQ(STATE_NONE, next_state_);
+ DCHECK(!user_callback_);
+
+ int rv = PrepareForAuthRestart();
+ if (rv != OK)
+ return rv;
+
+ rv = DoLoop(OK);
+ if (rv == ERR_IO_PENDING)
+ user_callback_ = callback;
+ return rv;
+}
+
+const HttpResponseInfo* HttpProxyClientSocket::GetConnectResponseInfo() const {
+ return response_.headers ? &response_ : NULL;
+}
+
HttpStream* HttpProxyClientSocket::CreateConnectResponseStream() {
return new HttpBasicStream(transport_.release(),
http_stream_parser_.release(), false);
@@ -99,67 +117,6 @@ int HttpProxyClientSocket::Connect(CompletionCallback* callback
return rv;
}
-int HttpProxyClientSocket::RestartWithAuth(CompletionCallback* callback) {
- DCHECK_EQ(STATE_NONE, next_state_);
- DCHECK(!user_callback_);
-
- int rv = PrepareForAuthRestart();
- if (rv != OK)
- return rv;
-
- rv = DoLoop(OK);
- if (rv == ERR_IO_PENDING)
- user_callback_ = callback;
- return rv;
-}
-
-int HttpProxyClientSocket::PrepareForAuthRestart() {
- if (!response_.headers.get())
- return ERR_CONNECTION_RESET;
-
- bool keep_alive = false;
- if (response_.headers->IsKeepAlive() &&
- http_stream_parser_->CanFindEndOfResponse()) {
- if (!http_stream_parser_->IsResponseBodyComplete()) {
- next_state_ = STATE_DRAIN_BODY;
- drain_buf_ = new IOBuffer(kDrainBodyBufferSize);
- return OK;
- }
- keep_alive = true;
- }
-
- // We don't need to drain the response body, so we act as if we had drained
- // the response body.
- return DidDrainBodyForAuthRestart(keep_alive);
-}
-
-int HttpProxyClientSocket::DidDrainBodyForAuthRestart(bool keep_alive) {
- if (keep_alive && transport_->socket()->IsConnectedAndIdle()) {
- next_state_ = STATE_GENERATE_AUTH_TOKEN;
- transport_->set_is_reused(true);
- } else {
- // This assumes that the underlying transport socket is a TCP socket,
- // since only TCP sockets are restartable.
- next_state_ = STATE_TCP_RESTART;
- transport_->socket()->Disconnect();
- }
-
- // Reset the other member variables.
- drain_buf_ = NULL;
- parser_buf_ = NULL;
- http_stream_parser_.reset();
- request_line_.clear();
- request_headers_.Clear();
- response_ = HttpResponseInfo();
- return OK;
-}
-
-void HttpProxyClientSocket::LogBlockedTunnelResponse(int response_code) const {
- LOG(WARNING) << "Blocked proxy response with status " << response_code
- << " to CONNECT request for "
- << GetHostAndPort(request_.url) << ".";
-}
-
void HttpProxyClientSocket::Disconnect() {
if (transport_.get())
transport_->socket()->Disconnect();
@@ -255,6 +212,64 @@ int HttpProxyClientSocket::GetPeerAddress(AddressList* address) const {
return transport_->socket()->GetPeerAddress(address);
}
+int HttpProxyClientSocket::PrepareForAuthRestart() {
+ if (!response_.headers.get())
+ return ERR_CONNECTION_RESET;
+
+ bool keep_alive = false;
+ if (response_.headers->IsKeepAlive() &&
+ http_stream_parser_->CanFindEndOfResponse()) {
+ if (!http_stream_parser_->IsResponseBodyComplete()) {
+ next_state_ = STATE_DRAIN_BODY;
+ drain_buf_ = new IOBuffer(kDrainBodyBufferSize);
+ return OK;
+ }
+ keep_alive = true;
+ }
+
+ // We don't need to drain the response body, so we act as if we had drained
+ // the response body.
+ return DidDrainBodyForAuthRestart(keep_alive);
+}
+
+int HttpProxyClientSocket::DidDrainBodyForAuthRestart(bool keep_alive) {
+ if (keep_alive && transport_->socket()->IsConnectedAndIdle()) {
+ next_state_ = STATE_GENERATE_AUTH_TOKEN;
+ transport_->set_is_reused(true);
+ } else {
+ // This assumes that the underlying transport socket is a TCP socket,
+ // since only TCP sockets are restartable.
+ next_state_ = STATE_TCP_RESTART;
+ transport_->socket()->Disconnect();
+ }
+
+ // Reset the other member variables.
+ drain_buf_ = NULL;
+ parser_buf_ = NULL;
+ http_stream_parser_.reset();
+ request_line_.clear();
+ request_headers_.Clear();
+ response_ = HttpResponseInfo();
+ return OK;
+}
+
+int HttpProxyClientSocket::HandleAuthChallenge() {
+ DCHECK(response_.headers);
+
+ int rv = auth_->HandleAuthChallenge(response_.headers, false, true, net_log_);
+ response_.auth_challenge = auth_->auth_info();
+ if (rv == OK)
+ return ERR_PROXY_AUTH_REQUESTED;
+
+ return rv;
+}
+
+void HttpProxyClientSocket::LogBlockedTunnelResponse(int response_code) const {
+ LOG(WARNING) << "Blocked proxy response with status " << response_code
+ << " to CONNECT request for "
+ << GetHostAndPort(request_.url) << ".";
+}
+
void HttpProxyClientSocket::DoCallback(int result) {
DCHECK_NE(ERR_IO_PENDING, result);
DCHECK(user_callback_);
@@ -291,25 +306,25 @@ int HttpProxyClientSocket::DoLoop(int last_io_result) {
break;
case STATE_SEND_REQUEST:
DCHECK_EQ(OK, rv);
- net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST,
- NULL);
+ net_log_.BeginEvent(
+ NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST, NULL);
rv = DoSendRequest();
break;
case STATE_SEND_REQUEST_COMPLETE:
rv = DoSendRequestComplete(rv);
- net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST,
- NULL);
+ net_log_.EndEventWithNetErrorCode(
+ NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST, rv);
break;
case STATE_READ_HEADERS:
DCHECK_EQ(OK, rv);
- net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS,
- NULL);
+ net_log_.BeginEvent(
+ NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS, NULL);
rv = DoReadHeaders();
break;
case STATE_READ_HEADERS_COMPLETE:
rv = DoReadHeadersComplete(rv);
- net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS,
- NULL);
+ net_log_.EndEventWithNetErrorCode(
+ NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS, rv);
break;
case STATE_DRAIN_BODY:
DCHECK_EQ(OK, rv);
@@ -479,15 +494,4 @@ int HttpProxyClientSocket::DoTCPRestartComplete(int result) {
return result;
}
-int HttpProxyClientSocket::HandleAuthChallenge() {
- DCHECK(response_.headers);
-
- int rv = auth_->HandleAuthChallenge(response_.headers, false, true, net_log_);
- response_.auth_challenge = auth_->auth_info();
- if (rv == OK)
- return ERR_PROXY_AUTH_REQUESTED;
-
- return rv;
-}
-
} // namespace net
diff --git a/net/http/http_proxy_client_socket.h b/net/http/http_proxy_client_socket.h
index ef53c2d..daede3c 100644
--- a/net/http/http_proxy_client_socket.h
+++ b/net/http/http_proxy_client_socket.h
@@ -56,12 +56,6 @@ class HttpProxyClientSocket : public ProxyClientSocket {
// RestartWithAuth.
int RestartWithAuth(CompletionCallback* callback);
- const HttpResponseInfo* GetConnectResponseInfo() const {
- return response_.headers ? &response_ : NULL;
- }
-
- virtual HttpStream* CreateConnectResponseStream();
-
const scoped_refptr<HttpAuthController>& auth_controller() {
return auth_;
}
@@ -70,14 +64,21 @@ class HttpProxyClientSocket : public ProxyClientSocket {
return using_spdy_;
}
- // ClientSocket methods:
+ // ProxyClientSocket methods:
+ virtual const HttpResponseInfo* GetConnectResponseInfo() const;
+ virtual HttpStream* CreateConnectResponseStream();
+<<<<<<< HEAD
// Authenticates to the Http Proxy and then passes data freely.
virtual int Connect(CompletionCallback* callback
#ifdef ANDROID
, bool wait_for_connect
#endif
);
+=======
+ // ClientSocket methods:
+ virtual int Connect(CompletionCallback* callback);
+>>>>>>> chromium.org at r11.0.672.0
virtual void Disconnect();
virtual bool IsConnected() const;
virtual bool IsConnectedAndIdle() const;
@@ -90,10 +91,8 @@ class HttpProxyClientSocket : public ProxyClientSocket {
// Socket methods:
virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
virtual int Write(IOBuffer* buf, int buf_len, CompletionCallback* callback);
-
virtual bool SetReceiveBufferSize(int32 size);
virtual bool SetSendBufferSize(int32 size);
-
virtual int GetPeerAddress(AddressList* address) const;
private:
diff --git a/net/http/http_proxy_client_socket_pool.cc b/net/http/http_proxy_client_socket_pool.cc
index d297542..fd875ca 100644
--- a/net/http/http_proxy_client_socket_pool.cc
+++ b/net/http/http_proxy_client_socket_pool.cc
@@ -111,12 +111,11 @@ LoadState HttpProxyConnectJob::GetLoadState() const {
}
}
-int HttpProxyConnectJob::ConnectInternal() {
- if (params_->tcp_params())
- next_state_ = STATE_TCP_CONNECT;
- else
- next_state_ = STATE_SSL_CONNECT;
- return DoLoop(OK);
+void HttpProxyConnectJob::GetAdditionalErrorState(ClientSocketHandle * handle) {
+ if (error_response_info_.cert_request_info) {
+ handle->set_ssl_error_response_info(error_response_info_);
+ handle->set_is_ssl_error(true);
+ }
}
void HttpProxyConnectJob::OnIOComplete(int result) {
@@ -254,11 +253,33 @@ int HttpProxyConnectJob::DoSSLConnectComplete(int result) {
return result;
}
-void HttpProxyConnectJob::GetAdditionalErrorState(ClientSocketHandle * handle) {
- if (error_response_info_.cert_request_info) {
- handle->set_ssl_error_response_info(error_response_info_);
- handle->set_is_ssl_error(true);
+int HttpProxyConnectJob::DoHttpProxyConnect() {
+ next_state_ = STATE_HTTP_PROXY_CONNECT_COMPLETE;
+ const HostResolver::RequestInfo& tcp_destination = params_->destination();
+ const HostPortPair& proxy_server = tcp_destination.host_port_pair();
+
+ // Add a HttpProxy connection on top of the tcp socket.
+ transport_socket_.reset(
+ new HttpProxyClientSocket(transport_socket_handle_.release(),
+ params_->request_url(),
+ params_->user_agent(),
+ params_->endpoint(),
+ proxy_server,
+ params_->http_auth_cache(),
+ params_->http_auth_handler_factory(),
+ params_->tunnel(),
+ using_spdy_,
+ params_->ssl_params() != NULL));
+ return transport_socket_->Connect(&callback_);
+}
+
+int HttpProxyConnectJob::DoHttpProxyConnectComplete(int result) {
+ if (result == OK || result == ERR_PROXY_AUTH_REQUESTED ||
+ result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) {
+ set_socket(transport_socket_.release());
}
+
+ return result;
}
int HttpProxyConnectJob::DoSpdyProxyCreateStream() {
@@ -316,6 +337,7 @@ int HttpProxyConnectJob::DoSpdyProxyCreateStreamComplete(int result) {
);
}
+<<<<<<< HEAD
#ifdef ANDROID
// TODO(kristianm): Find out if Connect should block
#endif
@@ -350,6 +372,14 @@ int HttpProxyConnectJob::DoHttpProxyConnectComplete(int result) {
}
return result;
+=======
+int HttpProxyConnectJob::ConnectInternal() {
+ if (params_->tcp_params())
+ next_state_ = STATE_TCP_CONNECT;
+ else
+ next_state_ = STATE_SSL_CONNECT;
+ return DoLoop(OK);
+>>>>>>> chromium.org at r11.0.672.0
}
HttpProxyClientSocketPool::
diff --git a/net/http/http_proxy_client_socket_pool.h b/net/http/http_proxy_client_socket_pool.h
index 39a8896..70d4bba 100644
--- a/net/http/http_proxy_client_socket_pool.h
+++ b/net/http/http_proxy_client_socket_pool.h
@@ -129,15 +129,6 @@ class HttpProxyConnectJob : public ConnectJob {
STATE_NONE,
};
- // Begins the tcp connection and the optional Http proxy tunnel. If the
- // request is not immediately servicable (likely), the request will return
- // ERR_IO_PENDING. An OK return from this function or the callback means
- // that the connection is established; ERR_PROXY_AUTH_REQUESTED means
- // that the tunnel needs authentication credentials, the socket will be
- // returned in this case, and must be release back to the pool; or
- // a standard net error code will be returned.
- virtual int ConnectInternal();
-
void OnIOComplete(int result);
// Runs the state transition loop.
@@ -156,6 +147,15 @@ class HttpProxyConnectJob : public ConnectJob {
int DoSpdyProxyCreateStream();
int DoSpdyProxyCreateStreamComplete(int result);
+ // Begins the tcp connection and the optional Http proxy tunnel. If the
+ // request is not immediately servicable (likely), the request will return
+ // ERR_IO_PENDING. An OK return from this function or the callback means
+ // that the connection is established; ERR_PROXY_AUTH_REQUESTED means
+ // that the tunnel needs authentication credentials, the socket will be
+ // returned in this case, and must be release back to the pool; or
+ // a standard net error code will be returned.
+ virtual int ConnectInternal();
+
scoped_refptr<HttpProxySocketParams> params_;
TCPClientSocketPool* const tcp_pool_;
SSLClientSocketPool* const ssl_pool_;
diff --git a/net/http/http_proxy_client_socket_pool_unittest.cc b/net/http/http_proxy_client_socket_pool_unittest.cc
index 8c6d545..359a058 100644
--- a/net/http/http_proxy_client_socket_pool_unittest.cc
+++ b/net/http/http_proxy_client_socket_pool_unittest.cc
@@ -20,7 +20,6 @@
#include "net/socket/client_socket_pool_histograms.h"
#include "net/socket/socket_test_util.h"
#include "net/spdy/spdy_protocol.h"
-#include "net/spdy/spdy_session_pool.h"
#include "net/spdy/spdy_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -60,13 +59,12 @@ class HttpProxyClientSocketPoolTest : public TestWithHttpParam {
&tcp_histograms_,
&socket_factory_),
ssl_histograms_("MockSSL"),
+ proxy_service_(ProxyService::CreateDirect()),
ssl_config_service_(new SSLConfigServiceDefaults),
- host_resolver_(new MockHostResolver),
- cert_verifier_(new CertVerifier),
ssl_socket_pool_(kMaxSockets, kMaxSocketsPerGroup,
&ssl_histograms_,
- host_resolver_.get(),
- cert_verifier_.get(),
+ &host_resolver_,
+ &cert_verifier_,
NULL /* dnsrr_resolver */,
NULL /* dns_cert_checker */,
NULL /* ssl_host_info_factory */,
@@ -77,19 +75,8 @@ class HttpProxyClientSocketPoolTest : public TestWithHttpParam {
ssl_config_service_.get(),
BoundNetLog().net_log()),
http_auth_handler_factory_(
- HttpAuthHandlerFactory::CreateDefault(host_resolver_.get())),
- session_(new HttpNetworkSession(host_resolver_.get(),
- cert_verifier_.get(),
- NULL /* dnsrr_resolver */,
- NULL /* dns_cert_checker */,
- NULL /* ssl_host_info_factory */,
- ProxyService::CreateDirect(),
- &socket_factory_,
- new SSLConfigServiceDefaults,
- new SpdySessionPool(NULL),
- http_auth_handler_factory_.get(),
- NULL,
- NULL)),
+ HttpAuthHandlerFactory::CreateDefault(&host_resolver_)),
+ session_(CreateNetworkSession()),
http_proxy_histograms_("HttpProxyUnitTest"),
ssl_data_(NULL),
data_(NULL),
@@ -107,8 +94,13 @@ class HttpProxyClientSocketPoolTest : public TestWithHttpParam {
void AddAuthToCache() {
const string16 kFoo(ASCIIToUTF16("foo"));
const string16 kBar(ASCIIToUTF16("bar"));
- session_->auth_cache()->Add(GURL("http://proxy/"), "MyRealm1", "Basic",
- "Basic realm=MyRealm1", kFoo, kBar, "/");
+ session_->auth_cache()->Add(GURL("http://proxy/"),
+ "MyRealm1",
+ HttpAuth::AUTH_SCHEME_BASIC,
+ "Basic realm=MyRealm1",
+ kFoo,
+ kBar,
+ "/");
}
scoped_refptr<TCPSocketParams> GetTcpParams() {
@@ -184,6 +176,17 @@ class HttpProxyClientSocketPoolTest : public TestWithHttpParam {
ssl_data_->was_npn_negotiated = true;
}
+ HttpNetworkSession* CreateNetworkSession() {
+ HttpNetworkSession::Params params;
+ params.host_resolver = &host_resolver_;
+ params.cert_verifier = &cert_verifier_;
+ params.proxy_service = proxy_service_;
+ params.client_socket_factory = &socket_factory_;
+ params.ssl_config_service = ssl_config_service_;
+ params.http_auth_handler_factory = http_auth_handler_factory_.get();
+ return new HttpNetworkSession(params);
+ }
+
private:
SSLConfig ssl_config_;
@@ -193,13 +196,14 @@ class HttpProxyClientSocketPoolTest : public TestWithHttpParam {
DeterministicMockClientSocketFactory socket_factory_;
MockTCPClientSocketPool tcp_socket_pool_;
ClientSocketPoolHistograms ssl_histograms_;
- scoped_refptr<SSLConfigService> ssl_config_service_;
- scoped_ptr<HostResolver> host_resolver_;
- scoped_ptr<CertVerifier> cert_verifier_;
+ MockHostResolver host_resolver_;
+ CertVerifier cert_verifier_;
+ const scoped_refptr<ProxyService> proxy_service_;
+ const scoped_refptr<SSLConfigService> ssl_config_service_;
SSLClientSocketPool ssl_socket_pool_;
- scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_;
- scoped_refptr<HttpNetworkSession> session_;
+ const scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_;
+ const scoped_refptr<HttpNetworkSession> session_;
ClientSocketPoolHistograms http_proxy_histograms_;
protected:
diff --git a/net/http/http_request_headers.cc b/net/http/http_request_headers.cc
index fc2ebcd..9d523c1 100644
--- a/net/http/http_request_headers.cc
+++ b/net/http/http_request_headers.cc
@@ -30,6 +30,7 @@ const char HttpRequestHeaders::kProxyConnection[] = "Proxy-Connection";
const char HttpRequestHeaders::kRange[] = "Range";
const char HttpRequestHeaders::kReferer[] = "Referer";
const char HttpRequestHeaders::kUserAgent[] = "User-Agent";
+const char HttpRequestHeaders::kTransferEncoding[] = "Transfer-Encoding";
HttpRequestHeaders::HeaderKeyValuePair::HeaderKeyValuePair() {
}
@@ -85,6 +86,13 @@ void HttpRequestHeaders::SetHeader(const base::StringPiece& key,
headers_.push_back(HeaderKeyValuePair(key.as_string(), value.as_string()));
}
+void HttpRequestHeaders::SetHeaderIfMissing(const base::StringPiece& key,
+ const base::StringPiece& value) {
+ HeaderVector::iterator it = FindHeader(key);
+ if (it == headers_.end())
+ headers_.push_back(HeaderKeyValuePair(key.as_string(), value.as_string()));
+}
+
void HttpRequestHeaders::RemoveHeader(const base::StringPiece& key) {
HeaderVector::iterator it = FindHeader(key);
if (it != headers_.end())
diff --git a/net/http/http_request_headers.h b/net/http/http_request_headers.h
index 734194a..ef4b60d 100644
--- a/net/http/http_request_headers.h
+++ b/net/http/http_request_headers.h
@@ -73,6 +73,7 @@ class HttpRequestHeaders {
static const char kRange[];
static const char kReferer[];
static const char kUserAgent[];
+ static const char kTransferEncoding[];
HttpRequestHeaders();
~HttpRequestHeaders();
@@ -95,6 +96,12 @@ class HttpRequestHeaders {
// in the vector remains the same. When comparing |key|, case is ignored.
void SetHeader(const base::StringPiece& key, const base::StringPiece& value);
+ // Sets the header value pair for |key| and |value|, if |key| does not exist.
+ // If |key| already exists, the call is a no-op.
+ // When comparing |key|, case is ignored.
+ void SetHeaderIfMissing(const base::StringPiece& key,
+ const base::StringPiece& value);
+
// Removes the first header that matches (case insensitive) |key|.
void RemoveHeader(const base::StringPiece& key);
diff --git a/net/http/http_request_headers_unittest.cc b/net/http/http_request_headers_unittest.cc
index f3abfbe..384ceeb 100644
--- a/net/http/http_request_headers_unittest.cc
+++ b/net/http/http_request_headers_unittest.cc
@@ -67,6 +67,14 @@ TEST(HttpRequestHeaders, SetEmptyHeader) {
EXPECT_EQ("Foo: Bar\r\nBar:\r\n\r\n", headers.ToString());
}
+TEST(HttpRequestHeaders, SetHeaderIfMissing) {
+ HttpRequestHeaders headers;
+ headers.SetHeaderIfMissing("Foo", "Bar");
+ EXPECT_EQ("Foo: Bar\r\n\r\n", headers.ToString());
+ headers.SetHeaderIfMissing("Foo", "Baz");
+ EXPECT_EQ("Foo: Bar\r\n\r\n", headers.ToString());
+}
+
TEST(HttpRequestHeaders, RemoveHeader) {
HttpRequestHeaders headers;
headers.SetHeader("Foo", "bar");
diff --git a/net/http/http_response_body_drainer_unittest.cc b/net/http/http_response_body_drainer_unittest.cc
index 76304f8..5745865 100644
--- a/net/http/http_response_body_drainer_unittest.cc
+++ b/net/http/http_response_body_drainer_unittest.cc
@@ -16,7 +16,6 @@
#include "net/http/http_network_session.h"
#include "net/http/http_stream.h"
#include "net/proxy/proxy_service.h"
-#include "net/spdy/spdy_session_pool.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
@@ -174,23 +173,23 @@ void MockHttpStream::CompleteRead() {
class HttpResponseBodyDrainerTest : public testing::Test {
protected:
HttpResponseBodyDrainerTest()
- : session_(new HttpNetworkSession(
- NULL /* host_resolver */,
- NULL /* dnsrr_resolver */,
- NULL /* dns_cert_checker */,
- NULL,
- NULL /* ssl_host_info_factory */,
- ProxyService::CreateDirect(),
- NULL,
- new SSLConfigServiceDefaults,
- new SpdySessionPool(NULL),
- NULL,
- NULL,
- NULL)),
+ : proxy_service_(ProxyService::CreateDirect()),
+ ssl_config_service_(new SSLConfigServiceDefaults),
+ session_(CreateNetworkSession()),
mock_stream_(new MockHttpStream(&result_waiter_)),
drainer_(new HttpResponseBodyDrainer(mock_stream_)) {}
+
~HttpResponseBodyDrainerTest() {}
+ HttpNetworkSession* CreateNetworkSession() const {
+ HttpNetworkSession::Params params;
+ params.proxy_service = proxy_service_;
+ params.ssl_config_service = ssl_config_service_;
+ return new HttpNetworkSession(params);
+ }
+
+ scoped_refptr<ProxyService> proxy_service_;
+ scoped_refptr<SSLConfigService> ssl_config_service_;
const scoped_refptr<HttpNetworkSession> session_;
CloseResultWaiter result_waiter_;
MockHttpStream* const mock_stream_; // Owned by |drainer_|.
diff --git a/net/http/http_response_headers.cc b/net/http/http_response_headers.cc
index c2d098c..5bf2beb 100644
--- a/net/http/http_response_headers.cc
+++ b/net/http/http_response_headers.cc
@@ -12,6 +12,7 @@
#include <algorithm>
#include "base/logging.h"
+#include "base/metrics/histogram.h"
#include "base/pickle.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
@@ -85,13 +86,69 @@ bool ShouldUpdateHeader(const std::string::const_iterator& name_begin,
return true;
}
+// Functions for histogram initialization. The code 0 is put in the
+// response map to track response codes that are invalid.
+// TODO(gavinp): Greatly prune the collected codes once we learn which
+// ones are not sent in practice, to reduce upload size & memory use.
+
+enum {
+ HISTOGRAM_MIN_HTTP_RESPONSE_CODE = 100,
+ HISTOGRAM_MAX_HTTP_RESPONSE_CODE = 599,
+};
+
+std::vector<int> GetAllHttpResponseCodes() {
+ std::vector<int> codes;
+ codes.reserve(
+ HISTOGRAM_MAX_HTTP_RESPONSE_CODE - HISTOGRAM_MIN_HTTP_RESPONSE_CODE + 2);
+ codes.push_back(0);
+ for (int i = HISTOGRAM_MIN_HTTP_RESPONSE_CODE;
+ i <= HISTOGRAM_MAX_HTTP_RESPONSE_CODE; ++i)
+ codes.push_back(i);
+ return codes;
+}
+
+int MapHttpResponseCode(int code) {
+ if (HISTOGRAM_MIN_HTTP_RESPONSE_CODE <= code &&
+ code <= HISTOGRAM_MAX_HTTP_RESPONSE_CODE)
+ return code;
+ return 0;
+}
+
} // namespace
+struct HttpResponseHeaders::ParsedHeader {
+ // A header "continuation" contains only a subsequent value for the
+ // preceding header. (Header values are comma separated.)
+ bool is_continuation() const { return name_begin == name_end; }
+
+ std::string::const_iterator name_begin;
+ std::string::const_iterator name_end;
+ std::string::const_iterator value_begin;
+ std::string::const_iterator value_end;
+};
+
//-----------------------------------------------------------------------------
HttpResponseHeaders::HttpResponseHeaders(const std::string& raw_input)
: response_code_(-1) {
Parse(raw_input);
+
+ // The most important thing to do with this histogram is find out
+ // the existence of unusual HTTP response codes. As it happens
+ // right now, there aren't double-constructions of response headers
+ // using this constructor, so our counts should also be accurate,
+ // without instantiating the histogram in two places. It is also
+ // important that this histogram not collect data in the other
+ // constructor, which rebuilds an histogram from a pickle, since
+ // that would actually create a double call between the original
+ // HttpResponseHeader that was serialized, and initialization of the
+ // new object from that pickle.
+ UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.HttpResponseCode",
+ MapHttpResponseCode(response_code_),
+ // Note the third argument is only
+ // evaluated once, see macro
+ // definition for details.
+ GetAllHttpResponseCodes());
}
HttpResponseHeaders::HttpResponseHeaders(const Pickle& pickle, void** iter)
@@ -359,30 +416,6 @@ void HttpResponseHeaders::GetNormalizedHeaders(std::string* output) const {
output->push_back('\n');
}
-void HttpResponseHeaders::GetRawHeaders(std::string* output) const {
- if (!output)
- return;
- output->erase();
- const char* headers_string = raw_headers().c_str();
- size_t headers_length = raw_headers().length();
- if (!headers_string)
- return;
- // The headers_string is a NULL-terminated status line, followed by NULL-
- // terminated headers.
- std::string raw_string = headers_string;
- size_t current_length = strlen(headers_string) + 1;
- while (headers_length > current_length) {
- // Move to the next header, and append it.
- headers_string += current_length;
- headers_length -= current_length;
- raw_string += "\n";
- raw_string += headers_string;
- // Get the next header location.
- current_length = strlen(headers_string) + 1;
- }
- *output = raw_string;
-}
-
bool HttpResponseHeaders::GetNormalizedHeader(const std::string& name,
std::string* value) const {
// If you hit this assertion, please use EnumerateHeader instead!
@@ -494,7 +527,7 @@ bool HttpResponseHeaders::HasHeader(const std::string& name) const {
return FindHeader(0, name) != std::string::npos;
}
-HttpResponseHeaders::HttpResponseHeaders() {
+HttpResponseHeaders::HttpResponseHeaders() : response_code_(-1) {
}
HttpResponseHeaders::~HttpResponseHeaders() {
diff --git a/net/http/http_response_headers.h b/net/http/http_response_headers.h
index 2b556b3..3c2eae0 100644
--- a/net/http/http_response_headers.h
+++ b/net/http/http_response_headers.h
@@ -100,9 +100,6 @@ class HttpResponseHeaders
//
void GetNormalizedHeaders(std::string* output) const;
- // Gets the raw stored headers, in human-readable form.
- void GetRawHeaders(std::string* output) const;
-
// Fetch the "normalized" value of a single header, where all values for the
// header name are separated by commas. See the GetNormalizedHeaders for
// format details. Returns false if this header wasn't found.
@@ -254,16 +251,7 @@ class HttpResponseHeaders
typedef base::hash_set<std::string> HeaderSet;
// The members of this structure point into raw_headers_.
- struct ParsedHeader {
- std::string::const_iterator name_begin;
- std::string::const_iterator name_end;
- std::string::const_iterator value_begin;
- std::string::const_iterator value_end;
-
- // A header "continuation" contains only a subsequent value for the
- // preceding header. (Header values are comma separated.)
- bool is_continuation() const { return name_begin == name_end; }
- };
+ struct ParsedHeader;
typedef std::vector<ParsedHeader> HeaderList;
HttpResponseHeaders();
diff --git a/net/http/http_stream_factory.cc b/net/http/http_stream_factory.cc
index b575f48..4673d58 100644
--- a/net/http/http_stream_factory.cc
+++ b/net/http/http_stream_factory.cc
@@ -32,14 +32,6 @@ std::list<HostPortPair>* HttpStreamFactory::forced_spdy_exclusions_ = NULL;
// static
bool HttpStreamFactory::ignore_certificate_errors_ = false;
-// static
-void HttpStreamFactory::SetHostMappingRules(const std::string& rules) {
- HostMappingRules* host_mapping_rules = new HostMappingRules();
- host_mapping_rules->SetRulesFromString(rules);
- delete host_mapping_rules_;
- host_mapping_rules_ = host_mapping_rules;
-}
-
HttpStreamFactory::HttpStreamFactory() {
}
@@ -53,6 +45,14 @@ HttpStreamFactory::~HttpStreamFactory() {
}
}
+// static
+void HttpStreamFactory::SetHostMappingRules(const std::string& rules) {
+ HostMappingRules* host_mapping_rules = new HostMappingRules();
+ host_mapping_rules->SetRulesFromString(rules);
+ delete host_mapping_rules_;
+ host_mapping_rules_ = host_mapping_rules;
+}
+
StreamRequest* HttpStreamFactory::RequestStream(
const HttpRequestInfo* request_info,
SSLConfig* ssl_config,
diff --git a/net/http/http_stream_factory.h b/net/http/http_stream_factory.h
index 3bb6d2f..97bd79c 100644
--- a/net/http/http_stream_factory.h
+++ b/net/http/http_stream_factory.h
@@ -34,35 +34,6 @@ class HttpStreamFactory : public StreamFactory,
HttpStreamFactory();
virtual ~HttpStreamFactory();
- // StreamFactory Interface
- virtual StreamRequest* RequestStream(const HttpRequestInfo* info,
- SSLConfig* ssl_config,
- ProxyInfo* proxy_info,
- HttpNetworkSession* session,
- StreamRequest::Delegate* delegate,
- const BoundNetLog& net_log);
-
- virtual int PreconnectStreams(int num_streams,
- const HttpRequestInfo* info,
- SSLConfig* ssl_config,
- ProxyInfo* proxy_info,
- HttpNetworkSession* session,
- const BoundNetLog& net_log,
- CompletionCallback* callback);
-
- virtual void AddTLSIntolerantServer(const GURL& url);
- virtual bool IsTLSIntolerantServer(const GURL& url);
-
- virtual void ProcessAlternateProtocol(
- HttpAlternateProtocols* alternate_protocols,
- const std::string& alternate_protocol_str,
- const HostPortPair& http_host_port_pair);
-
- virtual GURL ApplyHostMappingRules(const GURL& url, HostPortPair* endpoint);
-
- // HttpStreamRequest::PreconnectDelegate API
- virtual void OnPreconnectsComplete(HttpStreamRequest* request, int result);
-
// Static settings
// Turns spdy on or off.
@@ -122,6 +93,31 @@ class HttpStreamFactory : public StreamFactory,
static void SetHostMappingRules(const std::string& rules);
+ // StreamFactory Interface
+ virtual StreamRequest* RequestStream(const HttpRequestInfo* info,
+ SSLConfig* ssl_config,
+ ProxyInfo* proxy_info,
+ HttpNetworkSession* session,
+ StreamRequest::Delegate* delegate,
+ const BoundNetLog& net_log);
+ virtual int PreconnectStreams(int num_streams,
+ const HttpRequestInfo* info,
+ SSLConfig* ssl_config,
+ ProxyInfo* proxy_info,
+ HttpNetworkSession* session,
+ const BoundNetLog& net_log,
+ CompletionCallback* callback);
+ virtual void AddTLSIntolerantServer(const GURL& url);
+ virtual bool IsTLSIntolerantServer(const GURL& url);
+ virtual void ProcessAlternateProtocol(
+ HttpAlternateProtocols* alternate_protocols,
+ const std::string& alternate_protocol_str,
+ const HostPortPair& http_host_port_pair);
+ virtual GURL ApplyHostMappingRules(const GURL& url, HostPortPair* endpoint);
+
+ // HttpStreamRequest::PreconnectDelegate API
+ virtual void OnPreconnectsComplete(HttpStreamRequest* request, int result);
+
private:
typedef std::map<HttpStreamRequest*, CompletionCallback*> RequestCallbackMap;
RequestCallbackMap request_callback_map_;
diff --git a/net/http/http_stream_factory_unittest.cc b/net/http/http_stream_factory_unittest.cc
index 646f79c..617d885 100644
--- a/net/http/http_stream_factory_unittest.cc
+++ b/net/http/http_stream_factory_unittest.cc
@@ -17,6 +17,7 @@
#include "net/http/http_network_session_peer.h"
#include "net/http/http_request_info.h"
#include "net/socket/socket_test_util.h"
+#include "net/spdy/spdy_session.h"
#include "net/spdy/spdy_session_pool.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -45,18 +46,16 @@ struct SessionDependencies {
};
HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
- return new HttpNetworkSession(session_deps->host_resolver.get(),
- session_deps->cert_verifier.get(),
- NULL /* dnsrr_resolver */,
- NULL /* dns_cert_checker */,
- NULL /* ssl_host_info_factory */,
- session_deps->proxy_service,
- &session_deps->socket_factory,
- session_deps->ssl_config_service,
- new SpdySessionPool(NULL),
- session_deps->http_auth_handler_factory.get(),
- NULL,
- session_deps->net_log);
+ HttpNetworkSession::Params params;
+ params.host_resolver = session_deps->host_resolver.get();
+ params.cert_verifier = session_deps->cert_verifier.get();
+ params.proxy_service = session_deps->proxy_service;
+ params.ssl_config_service = session_deps->ssl_config_service;
+ params.client_socket_factory = &session_deps->socket_factory;
+ params.http_auth_handler_factory =
+ session_deps->http_auth_handler_factory.get();
+ params.net_log = session_deps->net_log;
+ return new HttpNetworkSession(params);
}
struct TestCase {
@@ -96,7 +95,8 @@ int PreconnectHelper(const TestCase& test,
template<typename ParentPool>
class CapturePreconnectsSocketPool : public ParentPool {
public:
- explicit CapturePreconnectsSocketPool(HttpNetworkSession* session);
+ CapturePreconnectsSocketPool(HostResolver* host_resolver,
+ CertVerifier* cert_verifier);
int last_num_streams() const {
return last_num_streams_;
@@ -124,7 +124,8 @@ class CapturePreconnectsSocketPool : public ParentPool {
ADD_FAILURE();
}
virtual void ReleaseSocket(const std::string& group_name,
- ClientSocket* socket) {
+ ClientSocket* socket,
+ int id) {
ADD_FAILURE();
}
virtual void CloseIdleSockets() {
@@ -162,21 +163,22 @@ CapturePreconnectsSSLSocketPool;
template<typename ParentPool>
CapturePreconnectsSocketPool<ParentPool>::CapturePreconnectsSocketPool(
- HttpNetworkSession* session)
- : ParentPool(0, 0, NULL, session->host_resolver(), NULL, NULL) {}
+ HostResolver* host_resolver, CertVerifier* /* cert_verifier */)
+ : ParentPool(0, 0, NULL, host_resolver, NULL, NULL),
+ last_num_streams_(-1) {}
template<>
CapturePreconnectsHttpProxySocketPool::CapturePreconnectsSocketPool(
- HttpNetworkSession* session)
- : HttpProxyClientSocketPool(0, 0, NULL, session->host_resolver(), NULL,
- NULL, NULL) {}
+ HostResolver* host_resolver, CertVerifier* /* cert_verifier */)
+ : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL),
+ last_num_streams_(-1) {}
template<>
CapturePreconnectsSSLSocketPool::CapturePreconnectsSocketPool(
- HttpNetworkSession* session)
- : SSLClientSocketPool(0, 0, NULL, session->host_resolver(),
- session->cert_verifier(), NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL) {}
+ HostResolver* host_resolver, CertVerifier* cert_verifier)
+ : SSLClientSocketPool(0, 0, NULL, host_resolver, cert_verifier, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ last_num_streams_(-1) {}
TEST(HttpStreamFactoryTest, PreconnectDirect) {
for (size_t i = 0; i < arraysize(kTests); ++i) {
@@ -184,10 +186,14 @@ TEST(HttpStreamFactoryTest, PreconnectDirect) {
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
HttpNetworkSessionPeer peer(session);
CapturePreconnectsTCPSocketPool* tcp_conn_pool =
- new CapturePreconnectsTCPSocketPool(session);
+ new CapturePreconnectsTCPSocketPool(
+ session_deps.host_resolver.get(),
+ session_deps.cert_verifier.get());
peer.SetTCPSocketPool(tcp_conn_pool);
CapturePreconnectsSSLSocketPool* ssl_conn_pool =
- new CapturePreconnectsSSLSocketPool(session.get());
+ new CapturePreconnectsSSLSocketPool(
+ session_deps.host_resolver.get(),
+ session_deps.cert_verifier.get());
peer.SetSSLSocketPool(ssl_conn_pool);
EXPECT_EQ(OK, PreconnectHelper(kTests[i], session));
if (kTests[i].ssl)
@@ -204,10 +210,14 @@ TEST(HttpStreamFactoryTest, PreconnectHttpProxy) {
HttpNetworkSessionPeer peer(session);
HostPortPair proxy_host("http_proxy", 80);
CapturePreconnectsHttpProxySocketPool* http_proxy_pool =
- new CapturePreconnectsHttpProxySocketPool(session);
+ new CapturePreconnectsHttpProxySocketPool(
+ session_deps.host_resolver.get(),
+ session_deps.cert_verifier.get());
peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
CapturePreconnectsSSLSocketPool* ssl_conn_pool =
- new CapturePreconnectsSSLSocketPool(session);
+ new CapturePreconnectsSSLSocketPool(
+ session_deps.host_resolver.get(),
+ session_deps.cert_verifier.get());
peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
EXPECT_EQ(OK, PreconnectHelper(kTests[i], session));
if (kTests[i].ssl)
@@ -225,10 +235,14 @@ TEST(HttpStreamFactoryTest, PreconnectSocksProxy) {
HttpNetworkSessionPeer peer(session);
HostPortPair proxy_host("socks_proxy", 1080);
CapturePreconnectsSOCKSSocketPool* socks_proxy_pool =
- new CapturePreconnectsSOCKSSocketPool(session);
+ new CapturePreconnectsSOCKSSocketPool(
+ session_deps.host_resolver.get(),
+ session_deps.cert_verifier.get());
peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_proxy_pool);
CapturePreconnectsSSLSocketPool* ssl_conn_pool =
- new CapturePreconnectsSSLSocketPool(session);
+ new CapturePreconnectsSSLSocketPool(
+ session_deps.host_resolver.get(),
+ session_deps.cert_verifier.get());
peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
EXPECT_EQ(OK, PreconnectHelper(kTests[i], session));
if (kTests[i].ssl)
@@ -238,6 +252,39 @@ TEST(HttpStreamFactoryTest, PreconnectSocksProxy) {
}
}
+TEST(HttpStreamFactoryTest, PreconnectDirectWithExistingSpdySession) {
+ for (size_t i = 0; i < arraysize(kTests); ++i) {
+ SessionDependencies session_deps(ProxyService::CreateDirect());
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+ HttpNetworkSessionPeer peer(session);
+
+ // Set an existing SpdySession in the pool.
+ HostPortPair host_port_pair("www.google.com", 443);
+ HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
+ scoped_refptr<SpdySession> spdy_session =
+ session->spdy_session_pool()->Get(
+ pair, session->mutable_spdy_settings(), BoundNetLog());
+
+ CapturePreconnectsTCPSocketPool* tcp_conn_pool =
+ new CapturePreconnectsTCPSocketPool(
+ session_deps.host_resolver.get(),
+ session_deps.cert_verifier.get());
+ peer.SetTCPSocketPool(tcp_conn_pool);
+ CapturePreconnectsSSLSocketPool* ssl_conn_pool =
+ new CapturePreconnectsSSLSocketPool(
+ session_deps.host_resolver.get(),
+ session_deps.cert_verifier.get());
+ peer.SetSSLSocketPool(ssl_conn_pool);
+ EXPECT_EQ(OK, PreconnectHelper(kTests[i], session));
+ // We shouldn't be preconnecting if we have an existing session, which is
+ // the case for https://www.google.com.
+ if (kTests[i].ssl)
+ EXPECT_EQ(-1, ssl_conn_pool->last_num_streams());
+ else
+ EXPECT_EQ(kTests[i].num_streams, tcp_conn_pool->last_num_streams());
+ }
+}
+
} // namespace
} // namespace net
diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc
index 2a3fb15..20ebd87 100644
--- a/net/http/http_stream_parser.cc
+++ b/net/http/http_stream_parser.cc
@@ -43,7 +43,10 @@ HttpStreamParser::HttpStreamParser(ClientSocketHandle* connection,
DCHECK_EQ(0, read_buffer->offset());
}
-HttpStreamParser::~HttpStreamParser() {}
+HttpStreamParser::~HttpStreamParser() {
+ if (request_body_ != NULL && request_body_->is_chunked())
+ request_body_->set_chunk_callback(NULL);
+}
int HttpStreamParser::SendRequest(const std::string& request_line,
const HttpRequestHeaders& headers,
@@ -67,6 +70,8 @@ int HttpStreamParser::SendRequest(const std::string& request_line,
request_headers_ = new DrainableIOBuffer(headers_io_buf,
headers_io_buf->size());
request_body_.reset(request_body);
+ if (request_body_ != NULL && request_body_->is_chunked())
+ request_body_->set_chunk_callback(this);
io_state_ = STATE_SENDING_HEADERS;
int result = DoLoop(OK);
@@ -143,6 +148,16 @@ void HttpStreamParser::OnIOComplete(int result) {
}
}
+void HttpStreamParser::OnChunkAvailable() {
+ // This method may get called while sending the headers or body, so check
+ // before processing the new data. If we were still initializing or sending
+ // headers, we will automatically start reading the chunks once we get into
+ // STATE_SENDING_BODY so nothing to do here.
+ DCHECK(io_state_ == STATE_SENDING_HEADERS || io_state_ == STATE_SENDING_BODY);
+ if (io_state_ == STATE_SENDING_BODY)
+ OnIOComplete(0);
+}
+
int HttpStreamParser::DoLoop(int result) {
bool can_do_more = true;
do {
@@ -169,7 +184,8 @@ int HttpStreamParser::DoLoop(int result) {
break;
case STATE_READ_HEADERS_COMPLETE:
result = DoReadHeadersComplete(result);
- net_log_.EndEvent(NetLog::TYPE_HTTP_STREAM_PARSER_READ_HEADERS, NULL);
+ net_log_.EndEventWithNetErrorCode(
+ NetLog::TYPE_HTTP_STREAM_PARSER_READ_HEADERS, result);
break;
case STATE_BODY_PENDING:
DCHECK(result != ERR_IO_PENDING);
@@ -208,12 +224,16 @@ int HttpStreamParser::DoSendHeaders(int result) {
// We'll record the count of uncoalesced packets IFF coalescing will help,
// and otherwise we'll use an enum to tell why it won't help.
enum COALESCE_POTENTIAL {
- NO_ADVANTAGE = 0, // Coalescing won't reduce packet count.
- HEADER_ONLY = 1, // There is only a header packet (can't coalesce).
- COALESCE_POTENTIAL_MAX = 30 // Various cases of coalasced savings.
+ // Coalescing won't reduce packet count.
+ NO_ADVANTAGE = 0,
+ // There is only a header packet or we have a request body but the
+ // request body isn't available yet (can't coalesce).
+ HEADER_ONLY = 1,
+ // Various cases of coalasced savings.
+ COALESCE_POTENTIAL_MAX = 30
};
size_t coalesce = HEADER_ONLY;
- if (request_body_ != NULL) {
+ if (request_body_ != NULL && !request_body_->is_chunked()) {
const size_t kBytesPerPacket = 1430;
uint64 body_packets = (request_body_->size() + kBytesPerPacket - 1) /
kBytesPerPacket;
@@ -236,7 +256,8 @@ int HttpStreamParser::DoSendHeaders(int result) {
result = connection_->socket()->Write(request_headers_,
bytes_remaining,
&io_callback_);
- } else if (request_body_ != NULL && request_body_->size()) {
+ } else if (request_body_ != NULL &&
+ (request_body_->is_chunked() || request_body_->size())) {
io_state_ = STATE_SENDING_BODY;
result = OK;
} else {
@@ -246,13 +267,17 @@ int HttpStreamParser::DoSendHeaders(int result) {
}
int HttpStreamParser::DoSendBody(int result) {
- if (result > 0)
- request_body_->DidConsume(result);
+ request_body_->MarkConsumedAndFillBuffer(result);
if (!request_body_->eof()) {
int buf_len = static_cast<int>(request_body_->buf_len());
- result = connection_->socket()->Write(request_body_->buf(), buf_len,
- &io_callback_);
+ if (buf_len) {
+ result = connection_->socket()->Write(request_body_->buf(), buf_len,
+ &io_callback_);
+ } else {
+ // More POST data is to come hence wait for the callback.
+ result = ERR_IO_PENDING;
+ }
} else {
io_state_ = STATE_REQUEST_SENT;
}
diff --git a/net/http/http_stream_parser.h b/net/http/http_stream_parser.h
index bbd551f..5f7e943 100644
--- a/net/http/http_stream_parser.h
+++ b/net/http/http_stream_parser.h
@@ -26,7 +26,7 @@ class IOBuffer;
class SSLCertRequestInfo;
class SSLInfo;
-class HttpStreamParser {
+class HttpStreamParser : public ChunkCallback {
public:
// Any data in |read_buffer| will be used before reading from the socket
// and any data left over after parsing the stream will be put into
@@ -71,6 +71,9 @@ class HttpStreamParser {
void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info);
+ // ChunkCallback methods.
+ virtual void OnChunkAvailable();
+
private:
// FOO_COMPLETE states implement the second half of potentially asynchronous
// operations and don't necessarily mean that FOO is complete.
diff --git a/net/http/http_stream_request.cc b/net/http/http_stream_request.cc
index 242f899..8794ea2 100644
--- a/net/http/http_stream_request.cc
+++ b/net/http/http_stream_request.cc
@@ -492,8 +492,11 @@ int HttpStreamRequest::DoInitConnection() {
// Check first if we have a spdy session for this group. If so, then go
// straight to using that.
HostPortProxyPair pair(endpoint_, proxy_info()->proxy_server());
- if (!preconnect_delegate_ &&
- session_->spdy_session_pool()->HasSession(pair)) {
+ if (session_->spdy_session_pool()->HasSession(pair)) {
+ // If we're preconnecting, but we already have a SpdySession, we don't
+ // actually need to preconnect any sockets, so we're done.
+ if (preconnect_delegate_)
+ return OK;
using_spdy_ = true;
next_state_ = STATE_CREATE_STREAM;
return OK;
@@ -769,7 +772,7 @@ int HttpStreamRequest::DoInitConnectionComplete(int result) {
}
}
if (result < 0)
- return HandleSSLHandshakeError(result);
+ return result;
}
next_state_ = STATE_CREATE_STREAM;
@@ -917,6 +920,18 @@ scoped_refptr<SSLSocketParams> HttpStreamRequest::GenerateSSLParams(
ssl_config()->tls1_enabled = false;
}
+ if (proxy_info()->is_https() && ssl_config()->send_client_cert) {
+ // When connecting through an HTTPS proxy, disable TLS False Start so
+ // that client authentication errors can be distinguished between those
+ // originating from the proxy server (ERR_PROXY_CONNECTION_FAILED) and
+ // those originating from the endpoint (ERR_SSL_PROTOCOL_ERROR /
+ // ERR_BAD_SSL_CLIENT_AUTH_CERT).
+ // TODO(rch): This assumes that the HTTPS proxy will only request a
+ // client certificate during the initial handshake.
+ // http://crbug.com/59292
+ ssl_config()->false_start_enabled = false;
+ }
+
UMA_HISTOGRAM_ENUMERATION("Net.ConnectionUsedSSLv3Fallback",
static_cast<int>(ssl_config()->ssl3_fallback), 2);
@@ -1005,6 +1020,11 @@ int HttpStreamRequest::ReconsiderProxyAfterError(int error) {
return error;
}
+ if (proxy_info()->is_https() && ssl_config()->send_client_cert) {
+ session_->ssl_client_auth_cache()->Remove(
+ proxy_info()->proxy_server().host_port_pair().ToString());
+ }
+
int rv = session_->proxy_service()->ReconsiderProxyAfterError(
request_info().url, proxy_info(), &io_callback_, &pac_request_,
net_log_);
@@ -1051,35 +1071,6 @@ int HttpStreamRequest::HandleCertificateError(int error) {
return error;
}
-int HttpStreamRequest::HandleSSLHandshakeError(int error) {
- if (ssl_config()->send_client_cert &&
- (error == ERR_SSL_PROTOCOL_ERROR ||
- error == ERR_BAD_SSL_CLIENT_AUTH_CERT)) {
- session_->ssl_client_auth_cache()->Remove(
- GetHostAndPort(request_info().url));
- }
-
- switch (error) {
- case ERR_SSL_PROTOCOL_ERROR:
- case ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
- case ERR_SSL_DECOMPRESSION_FAILURE_ALERT:
- case ERR_SSL_BAD_RECORD_MAC_ALERT:
- if (ssl_config()->tls1_enabled &&
- !SSLConfigService::IsKnownStrictTLSServer(
- request_info().url.host())) {
- // This could be a TLS-intolerant server, an SSL 3.0 server that
- // chose a TLS-only cipher suite or a server with buggy DEFLATE
- // support. Turn off TLS 1.0, DEFLATE support and retry.
- factory_->AddTLSIntolerantServer(request_info().url);
- next_state_ = STATE_INIT_CONNECTION;
- DCHECK(!connection_.get() || !connection_->socket());
- error = OK;
- }
- break;
- }
- return error;
-}
-
void HttpStreamRequest::SwitchToSpdyMode() {
if (HttpStreamFactory::spdy_enabled())
using_spdy_ = true;
diff --git a/net/http/http_stream_request.h b/net/http/http_stream_request.h
index 62ba5d8..fca2332 100644
--- a/net/http/http_stream_request.h
+++ b/net/http/http_stream_request.h
@@ -172,11 +172,6 @@ class HttpStreamRequest : public StreamRequest {
// Called to handle a client certificate request.
int HandleCertificateRequest(int error);
- // Called to possibly recover from an SSL handshake error. Sets next_state_
- // and returns OK if recovering from the error. Otherwise, the same error
- // code is returned.
- int HandleSSLHandshakeError(int error);
-
// Moves this stream request into SPDY mode.
void SwitchToSpdyMode();
diff --git a/net/http/http_transaction_unittest.cc b/net/http/http_transaction_unittest.cc
index 518c1f8..fabfb01 100644
--- a/net/http/http_transaction_unittest.cc
+++ b/net/http/http_transaction_unittest.cc
@@ -1,10 +1,11 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/http/http_transaction_unittest.h"
-#include "base/hash_tables.h"
+#include <algorithm>
+
#include "base/message_loop.h"
#include "base/string_util.h"
#include "net/base/net_errors.h"
@@ -16,6 +17,11 @@
#include "net/http/http_transaction.h"
#include "testing/gtest/include/gtest/gtest.h"
+namespace {
+typedef base::hash_map<std::string, const MockTransaction*> MockTransactionMap;
+static MockTransactionMap mock_transactions;
+} // namespace
+
//-----------------------------------------------------------------------------
// mock transaction data
@@ -104,18 +110,6 @@ static const MockTransaction* const kBuiltinMockTransactions[] = {
&kRangeGET_Transaction
};
-typedef base::hash_map<std::string, const MockTransaction*>
-MockTransactionMap;
-static MockTransactionMap mock_transactions;
-
-void AddMockTransaction(const MockTransaction* trans) {
- mock_transactions[GURL(trans->url).spec()] = trans;
-}
-
-void RemoveMockTransaction(const MockTransaction* trans) {
- mock_transactions.erase(GURL(trans->url).spec());
-}
-
const MockTransaction* FindMockTransaction(const GURL& url) {
// look for overrides:
MockTransactionMap::const_iterator it = mock_transactions.find(url.spec());
@@ -130,12 +124,222 @@ const MockTransaction* FindMockTransaction(const GURL& url) {
return NULL;
}
+void AddMockTransaction(const MockTransaction* trans) {
+ mock_transactions[GURL(trans->url).spec()] = trans;
+}
+
+void RemoveMockTransaction(const MockTransaction* trans) {
+ mock_transactions.erase(GURL(trans->url).spec());
+}
+
+MockHttpRequest::MockHttpRequest(const MockTransaction& t) {
+ url = GURL(t.url);
+ method = t.method;
+ extra_headers.AddHeadersFromString(t.request_headers);
+ load_flags = t.load_flags;
+}
//-----------------------------------------------------------------------------
// static
int TestTransactionConsumer::quit_counter_ = 0;
+TestTransactionConsumer::TestTransactionConsumer(
+ net::HttpTransactionFactory* factory)
+ : state_(IDLE),
+ trans_(NULL),
+ error_(net::OK) {
+ // Disregard the error code.
+ factory->CreateTransaction(&trans_);
+ ++quit_counter_;
+}
+
+TestTransactionConsumer::~TestTransactionConsumer() {
+}
+
+void TestTransactionConsumer::Start(const net::HttpRequestInfo* request,
+ const net::BoundNetLog& net_log) {
+ state_ = STARTING;
+ int result = trans_->Start(request, this, net_log);
+ if (result != net::ERR_IO_PENDING)
+ DidStart(result);
+}
+
+void TestTransactionConsumer::DidStart(int result) {
+ if (result != net::OK) {
+ DidFinish(result);
+ } else {
+ Read();
+ }
+}
+
+void TestTransactionConsumer::DidRead(int result) {
+ if (result <= 0) {
+ DidFinish(result);
+ } else {
+ content_.append(read_buf_->data(), result);
+ Read();
+ }
+}
+
+void TestTransactionConsumer::DidFinish(int result) {
+ state_ = DONE;
+ error_ = result;
+ if (--quit_counter_ == 0)
+ MessageLoop::current()->Quit();
+}
+
+void TestTransactionConsumer::Read() {
+ state_ = READING;
+ read_buf_ = new net::IOBuffer(1024);
+ int result = trans_->Read(read_buf_, 1024, this);
+ if (result != net::ERR_IO_PENDING)
+ DidRead(result);
+}
+
+void TestTransactionConsumer::RunWithParams(const Tuple1<int>& params) {
+ int result = params.a;
+ switch (state_) {
+ case STARTING:
+ DidStart(result);
+ break;
+ case READING:
+ DidRead(result);
+ break;
+ default:
+ NOTREACHED();
+ }
+}
+
+
+MockNetworkTransaction::MockNetworkTransaction() :
+ ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), data_cursor_(0) {
+}
+
+MockNetworkTransaction::~MockNetworkTransaction() {}
+
+int MockNetworkTransaction::Start(const net::HttpRequestInfo* request,
+ net::CompletionCallback* callback,
+ const net::BoundNetLog& net_log) {
+ const MockTransaction* t = FindMockTransaction(request->url);
+ if (!t)
+ return net::ERR_FAILED;
+
+ std::string resp_status = t->status;
+ std::string resp_headers = t->response_headers;
+ std::string resp_data = t->data;
+ if (t->handler)
+ (t->handler)(request, &resp_status, &resp_headers, &resp_data);
+
+ std::string header_data = base::StringPrintf(
+ "%s\n%s\n", resp_status.c_str(), resp_headers.c_str());
+ std::replace(header_data.begin(), header_data.end(), '\n', '\0');
+
+ response_.request_time = base::Time::Now();
+ if (!t->request_time.is_null())
+ response_.request_time = t->request_time;
+
+ response_.was_cached = false;
+
+ response_.response_time = base::Time::Now();
+ if (!t->response_time.is_null())
+ response_.response_time = t->response_time;
+
+ response_.headers = new net::HttpResponseHeaders(header_data);
+ response_.ssl_info.cert_status = t->cert_status;
+ data_ = resp_data;
+ test_mode_ = t->test_mode;
+
+ if (test_mode_ & TEST_MODE_SYNC_NET_START)
+ return net::OK;
+
+ CallbackLater(callback, net::OK);
+ return net::ERR_IO_PENDING;
+}
+
+int MockNetworkTransaction::RestartIgnoringLastError(
+ net::CompletionCallback* callback) {
+ return net::ERR_FAILED;
+}
+
+int MockNetworkTransaction::RestartWithCertificate(
+ net::X509Certificate* client_cert,
+ net::CompletionCallback* callback) {
+ return net::ERR_FAILED;
+}
+
+int MockNetworkTransaction::RestartWithAuth(const string16& username,
+ const string16& password,
+ net::CompletionCallback* callback) {
+ return net::ERR_FAILED;
+}
+
+bool MockNetworkTransaction::IsReadyToRestartForAuth() {
+ return false;
+}
+
+int MockNetworkTransaction::Read(net::IOBuffer* buf, int buf_len,
+ net::CompletionCallback* callback) {
+ int data_len = static_cast<int>(data_.size());
+ int num = std::min(buf_len, data_len - data_cursor_);
+ if (num) {
+ memcpy(buf->data(), data_.data() + data_cursor_, num);
+ data_cursor_ += num;
+ }
+ if (test_mode_ & TEST_MODE_SYNC_NET_READ)
+ return num;
+
+ CallbackLater(callback, num);
+ return net::ERR_IO_PENDING;
+}
+
+void MockNetworkTransaction::StopCaching() {}
+
+const net::HttpResponseInfo* MockNetworkTransaction::GetResponseInfo() const {
+ return &response_;
+}
+
+net::LoadState MockNetworkTransaction::GetLoadState() const {
+ if (data_cursor_)
+ return net::LOAD_STATE_READING_RESPONSE;
+ return net::LOAD_STATE_IDLE;
+}
+
+uint64 MockNetworkTransaction::GetUploadProgress() const {
+ return 0;
+}
+
+void MockNetworkTransaction::CallbackLater(net::CompletionCallback* callback,
+ int result) {
+ MessageLoop::current()->PostTask(FROM_HERE, task_factory_.NewRunnableMethod(
+ &MockNetworkTransaction::RunCallback, callback, result));
+}
+
+void MockNetworkTransaction::RunCallback(net::CompletionCallback* callback,
+ int result) {
+ callback->Run(result);
+}
+
+MockNetworkLayer::MockNetworkLayer() : transaction_count_(0) {}
+
+MockNetworkLayer::~MockNetworkLayer() {}
+
+int MockNetworkLayer::CreateTransaction(
+ scoped_ptr<net::HttpTransaction>* trans) {
+ transaction_count_++;
+ trans->reset(new MockNetworkTransaction());
+ return net::OK;
+}
+
+net::HttpCache* MockNetworkLayer::GetCache() {
+ return NULL;
+}
+
+net::HttpNetworkSession* MockNetworkLayer::GetSession() {
+ return NULL;
+}
+
+void MockNetworkLayer::Suspend(bool suspend) {}
//-----------------------------------------------------------------------------
// helpers
diff --git a/net/http/http_transaction_unittest.h b/net/http/http_transaction_unittest.h
index 3149534..0a11bb5 100644
--- a/net/http/http_transaction_unittest.h
+++ b/net/http/http_transaction_unittest.h
@@ -8,15 +8,11 @@
#include "net/http/http_transaction.h"
-#include <algorithm>
#include <string>
#include "base/callback.h"
#include "base/compiler_specific.h"
-#include "base/message_loop.h"
#include "base/string16.h"
-#include "base/string_util.h"
-#include "base/stringprintf.h"
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
@@ -27,6 +23,10 @@
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
+namespace net {
+class IOBuffer;
+}
+
//-----------------------------------------------------------------------------
// mock transaction data
@@ -97,12 +97,7 @@ struct ScopedMockTransaction : MockTransaction {
class MockHttpRequest : public net::HttpRequestInfo {
public:
- explicit MockHttpRequest(const MockTransaction& t) {
- url = GURL(t.url);
- method = t.method;
- extra_headers.AddHeadersFromString(t.request_headers);
- load_flags = t.load_flags;
- }
+ explicit MockHttpRequest(const MockTransaction& t);
};
//-----------------------------------------------------------------------------
@@ -110,25 +105,11 @@ class MockHttpRequest : public net::HttpRequestInfo {
class TestTransactionConsumer : public CallbackRunner< Tuple1<int> > {
public:
- explicit TestTransactionConsumer(net::HttpTransactionFactory* factory)
- : state_(IDLE),
- trans_(NULL),
- error_(net::OK) {
- // Disregard the error code.
- factory->CreateTransaction(&trans_);
- ++quit_counter_;
- }
-
- ~TestTransactionConsumer() {
- }
+ explicit TestTransactionConsumer(net::HttpTransactionFactory* factory);
+ virtual ~TestTransactionConsumer();
void Start(const net::HttpRequestInfo* request,
- const net::BoundNetLog& net_log) {
- state_ = STARTING;
- int result = trans_->Start(request, this, net_log);
- if (result != net::ERR_IO_PENDING)
- DidStart(result);
- }
+ const net::BoundNetLog& net_log);
bool is_done() const { return state_ == DONE; }
int error() const { return error_; }
@@ -139,60 +120,22 @@ class TestTransactionConsumer : public CallbackRunner< Tuple1<int> > {
const std::string& content() const { return content_; }
private:
- // Callback implementation:
- virtual void RunWithParams(const Tuple1<int>& params) {
- int result = params.a;
- switch (state_) {
- case STARTING:
- DidStart(result);
- break;
- case READING:
- DidRead(result);
- break;
- default:
- NOTREACHED();
- }
- }
-
- void DidStart(int result) {
- if (result != net::OK) {
- DidFinish(result);
- } else {
- Read();
- }
- }
-
- void DidRead(int result) {
- if (result <= 0) {
- DidFinish(result);
- } else {
- content_.append(read_buf_->data(), result);
- Read();
- }
- }
-
- void DidFinish(int result) {
- state_ = DONE;
- error_ = result;
- if (--quit_counter_ == 0)
- MessageLoop::current()->Quit();
- }
-
- void Read() {
- state_ = READING;
- read_buf_ = new net::IOBuffer(1024);
- int result = trans_->Read(read_buf_, 1024, this);
- if (result != net::ERR_IO_PENDING)
- DidRead(result);
- }
-
enum State {
IDLE,
STARTING,
READING,
DONE
- } state_;
+ };
+
+ void DidStart(int result);
+ void DidRead(int result);
+ void DidFinish(int result);
+ void Read();
+
+ // Callback implementation:
+ virtual void RunWithParams(const Tuple1<int>& params);
+ State state_;
scoped_ptr<net::HttpTransaction> trans_;
std::string content_;
scoped_refptr<net::IOBuffer> read_buf_;
@@ -210,107 +153,38 @@ class TestTransactionConsumer : public CallbackRunner< Tuple1<int> > {
// HttpCache implementation.
class MockNetworkTransaction : public net::HttpTransaction {
public:
- MockNetworkTransaction() :
- ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), data_cursor_(0) {
- }
+ MockNetworkTransaction();
+ virtual ~MockNetworkTransaction();
virtual int Start(const net::HttpRequestInfo* request,
net::CompletionCallback* callback,
- const net::BoundNetLog& net_log) {
- const MockTransaction* t = FindMockTransaction(request->url);
- if (!t)
- return net::ERR_FAILED;
-
- std::string resp_status = t->status;
- std::string resp_headers = t->response_headers;
- std::string resp_data = t->data;
- if (t->handler)
- (t->handler)(request, &resp_status, &resp_headers, &resp_data);
-
- std::string header_data = base::StringPrintf(
- "%s\n%s\n", resp_status.c_str(), resp_headers.c_str());
- std::replace(header_data.begin(), header_data.end(), '\n', '\0');
-
- response_.request_time = base::Time::Now();
- if (!t->request_time.is_null())
- response_.request_time = t->request_time;
-
- response_.was_cached = false;
+ const net::BoundNetLog& net_log);
- response_.response_time = base::Time::Now();
- if (!t->response_time.is_null())
- response_.response_time = t->response_time;
-
- response_.headers = new net::HttpResponseHeaders(header_data);
- response_.ssl_info.cert_status = t->cert_status;
- data_ = resp_data;
- test_mode_ = t->test_mode;
-
- if (test_mode_ & TEST_MODE_SYNC_NET_START)
- return net::OK;
-
- CallbackLater(callback, net::OK);
- return net::ERR_IO_PENDING;
- }
-
- virtual int RestartIgnoringLastError(net::CompletionCallback* callback) {
- return net::ERR_FAILED;
- }
+ virtual int RestartIgnoringLastError(net::CompletionCallback* callback);
virtual int RestartWithCertificate(net::X509Certificate* client_cert,
- net::CompletionCallback* callback) {
- return net::ERR_FAILED;
- }
+ net::CompletionCallback* callback);
virtual int RestartWithAuth(const string16& username,
const string16& password,
- net::CompletionCallback* callback) {
- return net::ERR_FAILED;
- }
+ net::CompletionCallback* callback);
- virtual bool IsReadyToRestartForAuth() {
- return false;
- }
+ virtual bool IsReadyToRestartForAuth();
virtual int Read(net::IOBuffer* buf, int buf_len,
- net::CompletionCallback* callback) {
- int data_len = static_cast<int>(data_.size());
- int num = std::min(buf_len, data_len - data_cursor_);
- if (num) {
- memcpy(buf->data(), data_.data() + data_cursor_, num);
- data_cursor_ += num;
- }
- if (test_mode_ & TEST_MODE_SYNC_NET_READ)
- return num;
-
- CallbackLater(callback, num);
- return net::ERR_IO_PENDING;
- }
+ net::CompletionCallback* callback);
- virtual void StopCaching() {}
+ virtual void StopCaching();
- virtual const net::HttpResponseInfo* GetResponseInfo() const {
- return &response_;
- }
+ virtual const net::HttpResponseInfo* GetResponseInfo() const;
- virtual net::LoadState GetLoadState() const {
- if (data_cursor_)
- return net::LOAD_STATE_READING_RESPONSE;
- return net::LOAD_STATE_IDLE;
- }
+ virtual net::LoadState GetLoadState() const;
- virtual uint64 GetUploadProgress() const {
- return 0;
- }
+ virtual uint64 GetUploadProgress() const;
private:
- void CallbackLater(net::CompletionCallback* callback, int result) {
- MessageLoop::current()->PostTask(FROM_HERE, task_factory_.NewRunnableMethod(
- &MockNetworkTransaction::RunCallback, callback, result));
- }
- void RunCallback(net::CompletionCallback* callback, int result) {
- callback->Run(result);
- }
+ void CallbackLater(net::CompletionCallback* callback, int result);
+ void RunCallback(net::CompletionCallback* callback, int result);
ScopedRunnableMethodFactory<MockNetworkTransaction> task_factory_;
net::HttpResponseInfo response_;
@@ -321,32 +195,21 @@ class MockNetworkTransaction : public net::HttpTransaction {
class MockNetworkLayer : public net::HttpTransactionFactory {
public:
- MockNetworkLayer() : transaction_count_(0) {
- }
-
- virtual int CreateTransaction(scoped_ptr<net::HttpTransaction>* trans) {
- transaction_count_++;
- trans->reset(new MockNetworkTransaction());
- return net::OK;
- }
-
- virtual net::HttpCache* GetCache() {
- return NULL;
- }
-
- virtual net::HttpNetworkSession* GetSession() {
- return NULL;
- }
-
- virtual void Suspend(bool suspend) {}
+ MockNetworkLayer();
+ virtual ~MockNetworkLayer();
int transaction_count() const { return transaction_count_; }
+ // net::HttpTransactionFactory:
+ virtual int CreateTransaction(scoped_ptr<net::HttpTransaction>* trans);
+ virtual net::HttpCache* GetCache();
+ virtual net::HttpNetworkSession* GetSession();
+ virtual void Suspend(bool suspend);
+
private:
int transaction_count_;
};
-
//-----------------------------------------------------------------------------
// helpers
diff --git a/net/http/http_util.cc b/net/http/http_util.cc
index bf56136..0f28c83 100644
--- a/net/http/http_util.cc
+++ b/net/http/http_util.cc
@@ -674,9 +674,14 @@ void HttpUtil::BuildRequestHeaders(const HttpRequestInfo* request_info,
// Add a content length header?
if (upload_data_stream) {
- request_headers->SetHeader(
- HttpRequestHeaders::kContentLength,
- base::Uint64ToString(upload_data_stream->size()));
+ if (upload_data_stream->is_chunked()) {
+ request_headers->SetHeader(
+ HttpRequestHeaders::kTransferEncoding, "chunked");
+ } else {
+ request_headers->SetHeader(
+ HttpRequestHeaders::kContentLength,
+ base::Uint64ToString(upload_data_stream->size()));
+ }
} else if (request_info->method == "POST" || request_info->method == "PUT" ||
request_info->method == "HEAD") {
// An empty POST/PUT request still needs a content length. As for HEAD,
diff --git a/net/http/mock_gssapi_library_posix.cc b/net/http/mock_gssapi_library_posix.cc
index ec69964..5ae4721 100644
--- a/net/http/mock_gssapi_library_posix.cc
+++ b/net/http/mock_gssapi_library_posix.cc
@@ -188,12 +188,70 @@ void GssContextMockImpl::Assign(
open = other.open;
}
+MockGSSAPILibrary::SecurityContextQuery::SecurityContextQuery()
+ : expected_package(),
+ response_code(0),
+ minor_response_code(0),
+ context_info() {
+ expected_input_token.length = 0;
+ expected_input_token.value = NULL;
+ output_token.length = 0;
+ output_token.value = NULL;
+}
+
+MockGSSAPILibrary::SecurityContextQuery::SecurityContextQuery(
+ const std::string& in_expected_package,
+ OM_uint32 in_response_code,
+ OM_uint32 in_minor_response_code,
+ const test::GssContextMockImpl& in_context_info,
+ const char* in_expected_input_token,
+ const char* in_output_token)
+ : expected_package(in_expected_package),
+ response_code(in_response_code),
+ minor_response_code(in_minor_response_code),
+ context_info(in_context_info) {
+ if (in_expected_input_token) {
+ expected_input_token.length = strlen(in_expected_input_token);
+ expected_input_token.value = const_cast<char*>(in_expected_input_token);
+ } else {
+ expected_input_token.length = 0;
+ expected_input_token.value = NULL;
+ }
+
+ if (in_output_token) {
+ output_token.length = strlen(in_output_token);
+ output_token.value = const_cast<char*>(in_output_token);
+ } else {
+ output_token.length = 0;
+ output_token.value = NULL;
+ }
+}
+
+MockGSSAPILibrary::SecurityContextQuery::~SecurityContextQuery() {}
+
MockGSSAPILibrary::MockGSSAPILibrary() {
}
MockGSSAPILibrary::~MockGSSAPILibrary() {
}
+void MockGSSAPILibrary::ExpectSecurityContext(
+ const std::string& expected_package,
+ OM_uint32 response_code,
+ OM_uint32 minor_response_code,
+ const GssContextMockImpl& context_info,
+ const gss_buffer_desc& expected_input_token,
+ const gss_buffer_desc& output_token) {
+ SecurityContextQuery security_query;
+ security_query.expected_package = expected_package;
+ security_query.response_code = response_code;
+ security_query.minor_response_code = minor_response_code;
+ security_query.context_info.Assign(context_info);
+ security_query.expected_input_token = expected_input_token;
+ security_query.output_token = output_token;
+ expected_security_queries_.push_back(security_query);
+}
+
bool MockGSSAPILibrary::Init() {
return true;
}
@@ -417,23 +475,6 @@ OM_uint32 MockGSSAPILibrary::inquire_context(
return GSS_S_COMPLETE;
}
-void MockGSSAPILibrary::ExpectSecurityContext(
- const std::string& expected_package,
- OM_uint32 response_code,
- OM_uint32 minor_response_code,
- const GssContextMockImpl& context_info,
- const gss_buffer_desc& expected_input_token,
- const gss_buffer_desc& output_token) {
- SecurityContextQuery security_query;
- security_query.expected_package = expected_package;
- security_query.response_code = response_code;
- security_query.minor_response_code = minor_response_code;
- security_query.context_info.Assign(context_info);
- security_query.expected_input_token = expected_input_token;
- security_query.output_token = output_token;
- expected_security_queries_.push_back(security_query);
-}
-
} // namespace test
} // namespace net
diff --git a/net/http/mock_gssapi_library_posix.h b/net/http/mock_gssapi_library_posix.h
index 15e14f2..aad5de8 100644
--- a/net/http/mock_gssapi_library_posix.h
+++ b/net/http/mock_gssapi_library_posix.h
@@ -45,10 +45,70 @@ class GssContextMockImpl {
// the system GSSAPI library calls.
class MockGSSAPILibrary : public GSSAPILibrary {
public:
+ // Unit tests need access to this. "Friend"ing didn't help.
+ struct SecurityContextQuery {
+ SecurityContextQuery();
+ SecurityContextQuery(const std::string& expected_package,
+ OM_uint32 response_code,
+ OM_uint32 minor_response_code,
+ const test::GssContextMockImpl& context_info,
+ const char* expected_input_token,
+ const char* output_token);
+ ~SecurityContextQuery();
+
+ std::string expected_package;
+ OM_uint32 response_code;
+ OM_uint32 minor_response_code;
+ test::GssContextMockImpl context_info;
+ gss_buffer_desc expected_input_token;
+ gss_buffer_desc output_token;
+ };
MockGSSAPILibrary();
virtual ~MockGSSAPILibrary();
+ // Establishes an expectation for a |init_sec_context()| call.
+ //
+ // Each expectation established by |ExpectSecurityContext()| must be
+ // matched by a call to |init_sec_context()| during the lifetime of
+ // the MockGSSAPILibrary. The |expected_package| argument must equal the
+ // value associated with the |target_name| argument to |init_sec_context()|
+ // for there to be a match. The expectations also establish an explicit
+ // ordering.
+ //
+ // For example, this sequence will be successful.
+ // MockGSSAPILibrary lib;
+ // lib.ExpectSecurityContext("NTLM", ...)
+ // lib.ExpectSecurityContext("Negotiate", ...)
+ // lib.init_sec_context("NTLM", ...)
+ // lib.init_sec_context("Negotiate", ...)
+ //
+ // This sequence will fail since the queries do not occur in the order
+ // established by the expectations.
+ // MockGSSAPILibrary lib;
+ // lib.ExpectSecurityContext("NTLM", ...)
+ // lib.ExpectSecurityContext("Negotiate", ...)
+ // lib.init_sec_context("Negotiate", ...)
+ // lib.init_sec_context("NTLM", ...)
+ //
+ // This sequence will fail because there were not enough queries.
+ // MockGSSAPILibrary lib;
+ // lib.ExpectSecurityContext("NTLM", ...)
+ // lib.ExpectSecurityContext("Negotiate", ...)
+ // lib.init_sec_context("NTLM", ...)
+ //
+ // |response_code| is used as the return value for |init_sec_context()|.
+ // If |response_code| is GSS_S_COMPLETE,
+ //
+ // |context_info| is the expected value of the |**context_handle| in after
+ // |init_sec_context()| returns.
+ void ExpectSecurityContext(const std::string& expected_package,
+ OM_uint32 response_code,
+ OM_uint32 minor_response_code,
+ const test::GssContextMockImpl& context_info,
+ const gss_buffer_desc& expected_input_token,
+ const gss_buffer_desc& output_token);
+
// GSSAPILibrary methods:
// Initializes the library, including any necessary dynamic libraries.
@@ -116,58 +176,6 @@ class MockGSSAPILibrary : public GSSAPILibrary {
int* locally_initiated,
int* open);
- // Establishes an expectation for a |init_sec_context()| call.
- //
- // Each expectation established by |ExpectSecurityContext()| must be
- // matched by a call to |init_sec_context()| during the lifetime of
- // the MockGSSAPILibrary. The |expected_package| argument must equal the
- // value associated with the |target_name| argument to |init_sec_context()|
- // for there to be a match. The expectations also establish an explicit
- // ordering.
- //
- // For example, this sequence will be successful.
- // MockGSSAPILibrary lib;
- // lib.ExpectSecurityContext("NTLM", ...)
- // lib.ExpectSecurityContext("Negotiate", ...)
- // lib.init_sec_context("NTLM", ...)
- // lib.init_sec_context("Negotiate", ...)
- //
- // This sequence will fail since the queries do not occur in the order
- // established by the expectations.
- // MockGSSAPILibrary lib;
- // lib.ExpectSecurityContext("NTLM", ...)
- // lib.ExpectSecurityContext("Negotiate", ...)
- // lib.init_sec_context("Negotiate", ...)
- // lib.init_sec_context("NTLM", ...)
- //
- // This sequence will fail because there were not enough queries.
- // MockGSSAPILibrary lib;
- // lib.ExpectSecurityContext("NTLM", ...)
- // lib.ExpectSecurityContext("Negotiate", ...)
- // lib.init_sec_context("NTLM", ...)
- //
- // |response_code| is used as the return value for |init_sec_context()|.
- // If |response_code| is GSS_S_COMPLETE,
- //
- // |context_info| is the expected value of the |**context_handle| in after
- // |init_sec_context()| returns.
- void ExpectSecurityContext(const std::string& expected_package,
- OM_uint32 response_code,
- OM_uint32 minor_response_code,
- const test::GssContextMockImpl& context_info,
- const gss_buffer_desc& expected_input_token,
- const gss_buffer_desc& output_token);
-
- // Unit tests need access to this. "Friend"ing didn't help.
- struct SecurityContextQuery {
- std::string expected_package;
- OM_uint32 response_code;
- OM_uint32 minor_response_code;
- test::GssContextMockImpl context_info;
- gss_buffer_desc expected_input_token;
- gss_buffer_desc output_token;
- };
-
private:
FRIEND_TEST_ALL_PREFIXES(HttpAuthGSSAPIPOSIXTest, GSSAPICycle);
diff --git a/net/http/url_security_manager.h b/net/http/url_security_manager.h
index c6a5ec9..119d6bd 100644
--- a/net/http/url_security_manager.h
+++ b/net/http/url_security_manager.h
@@ -74,25 +74,6 @@ class URLSecurityManagerWhitelist : public URLSecurityManager {
DISALLOW_COPY_AND_ASSIGN(URLSecurityManagerWhitelist);
};
-#if defined(UNIT_TEST)
-// An URLSecurityManager which is very permissive.
-class URLSecurityManagerAllow : public URLSecurityManager {
- public:
- URLSecurityManagerAllow() {}
- virtual ~URLSecurityManagerAllow() {}
-
- virtual bool CanUseDefaultCredentials(const GURL& auth_origin) const {
- return true;
- }
- virtual bool CanDelegate(const GURL& auth_origin) const {
- return true;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(URLSecurityManagerAllow);
-};
-#endif // defined(UNIT_TEST)
-
} // namespace net
#endif // NET_HTTP_URL_SECURITY_MANAGER_H_