summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/base/net_error_list.h5
-rw-r--r--net/http/http_network_transaction.cc106
-rw-r--r--net/http/http_network_transaction.h7
-rw-r--r--net/http/http_network_transaction_unittest.cc105
-rw-r--r--net/http/http_proxy_client_socket.cc52
-rw-r--r--net/http/http_proxy_client_socket.h17
-rw-r--r--net/http/http_proxy_client_socket_pool.cc14
-rw-r--r--net/http/http_proxy_client_socket_pool.h9
-rw-r--r--net/http/http_proxy_client_socket_pool_unittest.cc70
-rw-r--r--net/socket/client_socket_handle.cc1
-rw-r--r--net/socket/client_socket_handle.h7
-rw-r--r--net/socket/socket_test_util.cc47
-rw-r--r--net/socket/socket_test_util.h40
-rw-r--r--net/socket/ssl_client_socket_pool.cc28
-rw-r--r--net/socket/ssl_client_socket_pool.h4
-rw-r--r--net/socket/ssl_client_socket_pool_unittest.cc236
16 files changed, 389 insertions, 359 deletions
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h
index 53849631..e302a9f 100644
--- a/net/base/net_error_list.h
+++ b/net/base/net_error_list.h
@@ -167,6 +167,11 @@ NET_ERROR(PROXY_AUTH_REQUESTED, -127)
// A known TLS strict server didn't offer the renegotiation extension.
NET_ERROR(SSL_UNSAFE_NEGOTIATION, -128)
+// The socket is reporting that we tried to provide new credentials after a
+// a failed attempt on a connection without keep alive. We need to
+// reestablish the transport socket in order to retry the authentication.
+NET_ERROR(RETRY_CONNECTION, -129)
+
// Certificate error codes
//
// The values of certificate error codes must be consecutive.
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index bb17bcb..fdf8e9f 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -337,8 +337,7 @@ int HttpNetworkTransaction::RestartWithAuth(
if (target == HttpAuth::AUTH_PROXY && using_ssl_ && proxy_info_.is_http()) {
DCHECK(establishing_tunnel_);
- next_state_ = STATE_RESTART_TUNNEL_AUTH;
- auth_controllers_[target] = NULL;
+ next_state_ = STATE_INIT_CONNECTION;
ResetStateForRestart();
} else {
PrepareForAuthRestart(target);
@@ -539,13 +538,6 @@ int HttpNetworkTransaction::DoLoop(int result) {
case STATE_INIT_CONNECTION_COMPLETE:
rv = DoInitConnectionComplete(rv);
break;
- case STATE_RESTART_TUNNEL_AUTH:
- DCHECK_EQ(OK, rv);
- rv = DoRestartTunnelAuth();
- break;
- case STATE_RESTART_TUNNEL_AUTH_COMPLETE:
- rv = DoRestartTunnelAuthComplete(rv);
- break;
case STATE_GENERATE_PROXY_AUTH_TOKEN:
DCHECK_EQ(OK, rv);
rv = DoGenerateProxyAuthToken();
@@ -731,6 +723,15 @@ int HttpNetworkTransaction::DoInitConnection() {
DCHECK(proxy_info_.proxy_server().is_valid());
next_state_ = STATE_INIT_CONNECTION_COMPLETE;
+ // Now that the proxy server has been resolved, create the auth_controllers_.
+ for (int i = 0; i < HttpAuth::AUTH_NUM_TARGETS; i++) {
+ HttpAuth::Target target = static_cast<HttpAuth::Target>(i);
+ if (!auth_controllers_[target].get())
+ auth_controllers_[target] = new HttpAuthController(target,
+ AuthURL(target),
+ session_);
+ }
+
bool want_spdy_over_npn = alternate_protocol_mode_ == kUsingAlternateProtocol
&& alternate_protocol_ == HttpAlternateProtocols::NPN_SPDY_2;
using_ssl_ = request_->url.SchemeIs("https") ||
@@ -780,10 +781,15 @@ int HttpNetworkTransaction::DoInitConnection() {
request_->referrer, disable_resolver_cache);
if (proxy_info_.is_http()) {
- establishing_tunnel_ = using_ssl_;
+ scoped_refptr<HttpAuthController> http_proxy_auth;
+ if (using_ssl_) {
+ http_proxy_auth = auth_controllers_[HttpAuth::AUTH_PROXY];
+ establishing_tunnel_ = true;
+ }
http_proxy_params = new HttpProxySocketParams(proxy_tcp_params,
request_->url, endpoint_,
- session_, using_ssl_);
+ http_proxy_auth,
+ using_ssl_);
} else {
DCHECK(proxy_info_.is_socks());
char socks_version;
@@ -891,13 +897,14 @@ int HttpNetworkTransaction::DoInitConnectionComplete(int result) {
if (result == ERR_PROXY_AUTH_REQUESTED) {
DCHECK(!ssl_started);
- // Other state (i.e. |using_ssl_|) suggests that |connection_| will have an
- // SSL socket, but there was an error before that could happened. This
- // puts the in progress HttpProxy socket into |connection_| in order to
- // complete the auth. The tunnel restart code is carefully to remove it
- // before returning control to the rest of this class.
- connection_.reset(connection_->release_pending_http_proxy_connection());
- return HandleTunnelAuthFailure(result);
+ const HttpResponseInfo& tunnel_auth_response =
+ connection_->ssl_error_response_info();
+
+ response_.headers = tunnel_auth_response.headers;
+ response_.auth_challenge = tunnel_auth_response.auth_challenge;
+ headers_valid_ = true;
+ pending_auth_target_ = HttpAuth::AUTH_PROXY;
+ return OK;
}
if ((!ssl_started && result < 0 &&
@@ -977,44 +984,12 @@ int HttpNetworkTransaction::DoInitConnectionComplete(int result) {
return OK;
}
-int HttpNetworkTransaction::DoRestartTunnelAuth() {
- next_state_ = STATE_RESTART_TUNNEL_AUTH_COMPLETE;
- HttpProxyClientSocket* http_proxy_socket =
- static_cast<HttpProxyClientSocket*>(connection_->socket());
- return http_proxy_socket->RestartWithAuth(&io_callback_);
-}
-
-int HttpNetworkTransaction::DoRestartTunnelAuthComplete(int result) {
- if (result == ERR_PROXY_AUTH_REQUESTED)
- return HandleTunnelAuthFailure(result);
-
- if (result == OK) {
- // Now that we've got the HttpProxyClientSocket connected. We have
- // to release it as an idle socket into the pool and start the connection
- // process from the beginning. Trying to pass it in with the
- // SSLSocketParams might cause a deadlock since params are dispatched
- // interchangeably. This request won't necessarily get this http proxy
- // socket, but there will be forward progress.
- connection_->Reset();
- establishing_tunnel_ = false;
- next_state_ = STATE_INIT_CONNECTION;
- return OK;
- }
-
- return ReconsiderProxyAfterError(result);
-}
-
int HttpNetworkTransaction::DoGenerateProxyAuthToken() {
next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE;
if (!ShouldApplyProxyAuth())
return OK;
- HttpAuth::Target target = HttpAuth::AUTH_PROXY;
- if (!auth_controllers_[target].get())
- auth_controllers_[target] = new HttpAuthController(target, AuthURL(target),
- session_);
- return auth_controllers_[target]->MaybeGenerateAuthToken(request_,
- &io_callback_,
- net_log_);
+ return auth_controllers_[HttpAuth::AUTH_PROXY]->MaybeGenerateAuthToken(
+ request_, &io_callback_, net_log_);
}
int HttpNetworkTransaction::DoGenerateProxyAuthTokenComplete(int rv) {
@@ -1026,15 +1001,10 @@ int HttpNetworkTransaction::DoGenerateProxyAuthTokenComplete(int rv) {
int HttpNetworkTransaction::DoGenerateServerAuthToken() {
next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE;
- HttpAuth::Target target = HttpAuth::AUTH_SERVER;
- if (!auth_controllers_[target].get())
- auth_controllers_[target] = new HttpAuthController(target, AuthURL(target),
- session_);
if (!ShouldApplyServerAuth())
return OK;
- return auth_controllers_[target]->MaybeGenerateAuthToken(request_,
- &io_callback_,
- net_log_);
+ return auth_controllers_[HttpAuth::AUTH_SERVER]->MaybeGenerateAuthToken(
+ request_, &io_callback_, net_log_);
}
int HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) {
@@ -1557,24 +1527,6 @@ void HttpNetworkTransaction::LogTransactionMetrics() const {
}
}
-int HttpNetworkTransaction::HandleTunnelAuthFailure(int error) {
- DCHECK(establishing_tunnel_);
- DCHECK_EQ(ERR_PROXY_AUTH_REQUESTED, error);
- HttpProxyClientSocket* http_proxy_socket =
- static_cast<HttpProxyClientSocket*>(connection_->socket());
-
- const HttpResponseInfo* tunnel_auth_response =
- http_proxy_socket->GetResponseInfo();
- response_.headers = tunnel_auth_response->headers;
- response_.auth_challenge = tunnel_auth_response->auth_challenge;
- headers_valid_ = true;
-
- auth_controllers_[HttpAuth::AUTH_PROXY] =
- http_proxy_socket->auth_controller();
- pending_auth_target_ = HttpAuth::AUTH_PROXY;
- return OK;
-}
-
int HttpNetworkTransaction::HandleCertificateError(int error) {
DCHECK(using_ssl_);
DCHECK(IsCertificateError(error));
diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h
index b3a083c..8117325 100644
--- a/net/http/http_network_transaction.h
+++ b/net/http/http_network_transaction.h
@@ -91,8 +91,6 @@ class HttpNetworkTransaction : public HttpTransaction {
STATE_RESOLVE_PROXY_COMPLETE,
STATE_INIT_CONNECTION,
STATE_INIT_CONNECTION_COMPLETE,
- STATE_RESTART_TUNNEL_AUTH,
- STATE_RESTART_TUNNEL_AUTH_COMPLETE,
STATE_GENERATE_PROXY_AUTH_TOKEN,
STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE,
STATE_GENERATE_SERVER_AUTH_TOKEN,
@@ -136,8 +134,6 @@ class HttpNetworkTransaction : public HttpTransaction {
int DoResolveProxyComplete(int result);
int DoInitConnection();
int DoInitConnectionComplete(int result);
- int DoRestartTunnelAuth();
- int DoRestartTunnelAuthComplete(int result);
int DoGenerateProxyAuthToken();
int DoGenerateProxyAuthTokenComplete(int result);
int DoGenerateServerAuthToken();
@@ -174,9 +170,6 @@ class HttpNetworkTransaction : public HttpTransaction {
static void LogIOErrorMetrics(const ClientSocketHandle& handle);
- // Called to handle an HTTP proxy tunnel request for auth.
- int HandleTunnelAuthFailure(int error);
-
// Called to handle a certificate error. Returns OK if the error should be
// ignored. Otherwise, stores the certificate in response_.ssl_info and
// returns the same error code.
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index d6e5779..b5f614c 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -1343,111 +1343,6 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
EXPECT_EQ(100, response->headers->GetContentLength());
}
-// 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(CreateFixedProxyService("myproxy:70"));
- CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
- session_deps.net_log = log.bound().net_log();
- scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
- scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
- 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;
-
- // Since we have proxy, should try to establish tunnel.
- MockWrite data_writes1[] = {
- MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
- "Host: www.google.com\r\n"
- "Proxy-Connection: keep-alive\r\n\r\n"),
-
- // After calling trans->RestartWithAuth(), this is the request we should
- // be issuing -- the final header line contains the credentials.
- MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
- "Host: www.google.com\r\n"
- "Proxy-Connection: keep-alive\r\n"
- "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
-
- MockWrite("GET / HTTP/1.1\r\n"
- "Host: www.google.com\r\n"
- "Connection: keep-alive\r\n\r\n"),
- };
-
- // The proxy responds to the connect with a 407, using a persistent
- // connection.
- MockRead data_reads1[] = {
- // No credentials.
- MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
- MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
- MockRead("Proxy-Connection: close\r\n\r\n"),
-
- MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
-
- MockRead("HTTP/1.1 200 OK\r\n"),
- MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
- MockRead("Content-Length: 100\r\n\r\n"),
- MockRead(false, OK),
- };
-
- StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
- data_writes1, arraysize(data_writes1));
- session_deps.socket_factory.AddSocketDataProvider(&data1);
- SSLSocketDataProvider ssl(true, OK);
- session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
-
- TestCompletionCallback callback1;
-
- int rv = trans->Start(&request, &callback1, log.bound());
- EXPECT_EQ(ERR_IO_PENDING, rv);
-
- rv = callback1.WaitForResult();
- EXPECT_EQ(OK, rv);
- size_t pos = ExpectLogContainsSomewhere(
- log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
- NetLog::PHASE_NONE);
- ExpectLogContainsSomewhere(
- log.entries(), pos,
- NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
- NetLog::PHASE_NONE);
-
- const HttpResponseInfo* response = trans->GetResponseInfo();
- ASSERT_FALSE(response == NULL);
-
- EXPECT_EQ(407, response->headers->response_code());
- EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
-
- // The password prompt info should have been set in response->auth_challenge.
- ASSERT_FALSE(response->auth_challenge.get() == NULL);
-
- EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
- EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
- EXPECT_EQ(L"basic", response->auth_challenge->scheme);
-
- TestCompletionCallback callback2;
-
- rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
- EXPECT_EQ(ERR_IO_PENDING, rv);
-
- rv = callback2.WaitForResult();
- EXPECT_EQ(OK, rv);
-
- response = trans->GetResponseInfo();
- ASSERT_FALSE(response == NULL);
-
- EXPECT_TRUE(response->headers->IsKeepAlive());
- EXPECT_EQ(200, response->headers->response_code());
- EXPECT_EQ(100, response->headers->GetContentLength());
- EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
-
- // The password prompt info should not be set.
- EXPECT_TRUE(response->auth_challenge.get() == NULL);
-}
-
// 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) {
diff --git a/net/http/http_proxy_client_socket.cc b/net/http/http_proxy_client_socket.cc
index 1c76c36..02c2666 100644
--- a/net/http/http_proxy_client_socket.cc
+++ b/net/http/http_proxy_client_socket.cc
@@ -50,20 +50,18 @@ void BuildTunnelRequest(const HttpRequestInfo* request_info,
HttpProxyClientSocket::HttpProxyClientSocket(
ClientSocketHandle* transport_socket, const GURL& request_url,
- const HostPortPair& endpoint, const HostPortPair& proxy_server,
- const scoped_refptr<HttpNetworkSession>& session, bool tunnel)
+ const HostPortPair& endpoint, const scoped_refptr<HttpAuthController>& auth,
+ bool tunnel)
: ALLOW_THIS_IN_INITIALIZER_LIST(
io_callback_(this, &HttpProxyClientSocket::OnIOComplete)),
next_state_(STATE_NONE),
user_callback_(NULL),
transport_(transport_socket),
endpoint_(endpoint),
- auth_(tunnel ?
- new HttpAuthController(HttpAuth::AUTH_PROXY,
- GURL("http://" + proxy_server.ToString()),
- session) : NULL),
+ auth_(auth),
tunnel_(tunnel),
net_log_(transport_socket->socket()->NetLog()) {
+ DCHECK_EQ(tunnel, auth != NULL);
// Synthesize the bits of a request that we actually use.
request_.url = request_url;
request_.method = "GET";
@@ -128,14 +126,13 @@ int HttpProxyClientSocket::PrepareForAuthRestart() {
}
int HttpProxyClientSocket::DidDrainBodyForAuthRestart(bool keep_alive) {
+ int rc = OK;
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();
+ rc = ERR_RETRY_CONNECTION;
}
// Reset the other member variables.
@@ -143,7 +140,7 @@ int HttpProxyClientSocket::DidDrainBodyForAuthRestart(bool keep_alive) {
http_stream_.reset();
request_headers_.clear();
response_ = HttpResponseInfo();
- return OK;
+ return rc;
}
void HttpProxyClientSocket::LogBlockedTunnelResponse(int response_code) const {
@@ -162,16 +159,19 @@ void HttpProxyClientSocket::Disconnect() {
}
bool HttpProxyClientSocket::IsConnected() const {
- return next_state_ == STATE_DONE && transport_->socket()->IsConnected();
+ return transport_->socket()->IsConnected();
}
bool HttpProxyClientSocket::IsConnectedAndIdle() const {
- return next_state_ == STATE_DONE &&
- transport_->socket()->IsConnectedAndIdle();
+ return transport_->socket()->IsConnectedAndIdle();
+}
+
+bool HttpProxyClientSocket::NeedsRestartWithAuth() const {
+ return next_state_ != STATE_DONE;
}
int HttpProxyClientSocket::Read(IOBuffer* buf, int buf_len,
- CompletionCallback* callback) {
+ CompletionCallback* callback) {
DCHECK(!user_callback_);
if (next_state_ != STATE_DONE) {
// We're trying to read the body of the response but we're still trying
@@ -273,13 +273,6 @@ int HttpProxyClientSocket::DoLoop(int last_io_result) {
case STATE_DRAIN_BODY_COMPLETE:
rv = DoDrainBodyComplete(rv);
break;
- case STATE_TCP_RESTART:
- DCHECK_EQ(OK, rv);
- rv = DoTCPRestart();
- break;
- case STATE_TCP_RESTART_COMPLETE:
- rv = DoTCPRestartComplete(rv);
- break;
case STATE_DONE:
break;
default:
@@ -287,8 +280,8 @@ int HttpProxyClientSocket::DoLoop(int last_io_result) {
rv = ERR_UNEXPECTED;
break;
}
- } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE &&
- next_state_ != STATE_DONE);
+ } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE
+ && next_state_ != STATE_DONE);
return rv;
}
@@ -413,19 +406,6 @@ int HttpProxyClientSocket::DoDrainBodyComplete(int result) {
return OK;
}
-int HttpProxyClientSocket::DoTCPRestart() {
- next_state_ = STATE_TCP_RESTART_COMPLETE;
- return transport_->socket()->Connect(&io_callback_);
-}
-
-int HttpProxyClientSocket::DoTCPRestartComplete(int result) {
- if (result != OK)
- return result;
-
- next_state_ = STATE_GENERATE_AUTH_TOKEN;
- return result;
-}
-
int HttpProxyClientSocket::HandleAuthChallenge() {
DCHECK(response_.headers);
diff --git a/net/http/http_proxy_client_socket.h b/net/http/http_proxy_client_socket.h
index ef4f76c..317b220 100644
--- a/net/http/http_proxy_client_socket.h
+++ b/net/http/http_proxy_client_socket.h
@@ -35,8 +35,7 @@ class HttpProxyClientSocket : public ClientSocket {
// this socket will establish an Http tunnel.
HttpProxyClientSocket(ClientSocketHandle* transport_socket,
const GURL& request_url, const HostPortPair& endpoint,
- const HostPortPair& proxy_server,
- const scoped_refptr<HttpNetworkSession>& session,
+ const scoped_refptr<HttpAuthController>& auth,
bool tunnel);
// On destruction Disconnect() is called.
@@ -47,12 +46,12 @@ class HttpProxyClientSocket : public ClientSocket {
// RestartWithAuth.
int RestartWithAuth(CompletionCallback* callback);
- const HttpResponseInfo* GetResponseInfo() const {
- return response_.headers ? &response_ : NULL;
- }
+ // Indicates if RestartWithAuth needs to be called. i.e. if Connect
+ // returned PROXY_AUTH_REQUESTED. Only valid after Connect has been called.
+ bool NeedsRestartWithAuth() const;
- const scoped_refptr<HttpAuthController>& auth_controller() {
- return auth_;
+ const HttpResponseInfo* GetResponseInfo() const {
+ return response_.headers ? &response_ : NULL;
}
// ClientSocket methods:
@@ -86,8 +85,6 @@ class HttpProxyClientSocket : public ClientSocket {
STATE_RESOLVE_CANONICAL_NAME_COMPLETE,
STATE_DRAIN_BODY,
STATE_DRAIN_BODY_COMPLETE,
- STATE_TCP_RESTART,
- STATE_TCP_RESTART_COMPLETE,
STATE_DONE,
};
@@ -115,8 +112,6 @@ class HttpProxyClientSocket : public ClientSocket {
int DoReadHeadersComplete(int result);
int DoDrainBody();
int DoDrainBodyComplete(int result);
- int DoTCPRestart();
- int DoTCPRestartComplete(int result);
CompletionCallbackImpl<HttpProxyClientSocket> io_callback_;
State next_state_;
diff --git a/net/http/http_proxy_client_socket_pool.cc b/net/http/http_proxy_client_socket_pool.cc
index 783c10f..a142576 100644
--- a/net/http/http_proxy_client_socket_pool.cc
+++ b/net/http/http_proxy_client_socket_pool.cc
@@ -7,7 +7,6 @@
#include "base/time.h"
#include "googleurl/src/gurl.h"
#include "net/base/net_errors.h"
-#include "net/http/http_network_session.h"
#include "net/http/http_proxy_client_socket.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/client_socket_handle.h"
@@ -19,12 +18,12 @@ HttpProxySocketParams::HttpProxySocketParams(
const scoped_refptr<TCPSocketParams>& proxy_server,
const GURL& request_url,
HostPortPair endpoint,
- scoped_refptr<HttpNetworkSession> session,
+ scoped_refptr<HttpAuthController> auth_controller,
bool tunnel)
: tcp_params_(proxy_server),
request_url_(request_url),
endpoint_(endpoint),
- session_(session),
+ auth_controller_(auth_controller),
tunnel_(tunnel) {
}
@@ -134,22 +133,19 @@ int HttpProxyConnectJob::DoTCPConnectComplete(int result) {
int HttpProxyConnectJob::DoHttpProxyConnect() {
next_state_ = kStateHttpProxyConnectComplete;
- const HostResolver::RequestInfo& tcp_destination =
- params_->tcp_params()->destination();
- HostPortPair proxy_server(tcp_destination.hostname(),
- tcp_destination.port());
// Add a HttpProxy connection on top of the tcp socket.
socket_.reset(new HttpProxyClientSocket(tcp_socket_handle_.release(),
params_->request_url(),
params_->endpoint(),
- proxy_server,
- params_->session(),
+ params_->auth_controller(),
params_->tunnel()));
return socket_->Connect(&callback_);
}
int HttpProxyConnectJob::DoHttpProxyConnectComplete(int result) {
+ DCHECK_NE(result, ERR_RETRY_CONNECTION);
+
if (result == OK || result == ERR_PROXY_AUTH_REQUESTED)
set_socket(socket_.release());
diff --git a/net/http/http_proxy_client_socket_pool.h b/net/http/http_proxy_client_socket_pool.h
index 347a2427..63d5c02 100644
--- a/net/http/http_proxy_client_socket_pool.h
+++ b/net/http/http_proxy_client_socket_pool.h
@@ -26,13 +26,12 @@ namespace net {
class ClientSocketFactory;
class ConnectJobFactory;
class HttpAuthController;
-class HttpNetworkSession;
class HttpProxySocketParams : public base::RefCounted<HttpProxySocketParams> {
public:
HttpProxySocketParams(const scoped_refptr<TCPSocketParams>& proxy_server,
const GURL& request_url, HostPortPair endpoint,
- scoped_refptr<HttpNetworkSession> session,
+ scoped_refptr<HttpAuthController> auth_controller,
bool tunnel);
const scoped_refptr<TCPSocketParams>& tcp_params() const {
@@ -40,8 +39,8 @@ class HttpProxySocketParams : public base::RefCounted<HttpProxySocketParams> {
}
const GURL& request_url() const { return request_url_; }
const HostPortPair& endpoint() const { return endpoint_; }
- const scoped_refptr<HttpNetworkSession>& session() {
- return session_;
+ const scoped_refptr<HttpAuthController>& auth_controller() {
+ return auth_controller_;
}
bool tunnel() const { return tunnel_; }
@@ -52,7 +51,7 @@ class HttpProxySocketParams : public base::RefCounted<HttpProxySocketParams> {
const scoped_refptr<TCPSocketParams> tcp_params_;
const GURL request_url_;
const HostPortPair endpoint_;
- const scoped_refptr<HttpNetworkSession> session_;
+ const scoped_refptr<HttpAuthController> auth_controller_;
const bool tunnel_;
DISALLOW_COPY_AND_ASSIGN(HttpProxySocketParams);
diff --git a/net/http/http_proxy_client_socket_pool_unittest.cc b/net/http/http_proxy_client_socket_pool_unittest.cc
index 3e06c3b..9400dd8 100644
--- a/net/http/http_proxy_client_socket_pool_unittest.cc
+++ b/net/http/http_proxy_client_socket_pool_unittest.cc
@@ -6,19 +6,12 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
-#include "base/string_util.h"
-#include "net/base/mock_host_resolver.h"
#include "net/base/net_errors.h"
-#include "net/base/ssl_config_service_defaults.h"
#include "net/base/test_completion_callback.h"
-#include "net/http/http_auth_handler_factory.h"
-#include "net/http/http_network_session.h"
#include "net/http/http_proxy_client_socket.h"
-#include "net/proxy/proxy_service.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/client_socket_pool_histograms.h"
#include "net/socket/socket_test_util.h"
-#include "net/spdy/spdy_session_pool.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
@@ -36,34 +29,19 @@ class HttpProxyClientSocketPoolTest : public ClientSocketPoolTest {
tcp_histograms_(new ClientSocketPoolHistograms("MockTCP")),
tcp_socket_pool_(new MockTCPClientSocketPool(kMaxSockets,
kMaxSocketsPerGroup, tcp_histograms_, &tcp_client_socket_factory_)),
- http_auth_handler_factory_(HttpAuthHandlerFactory::CreateDefault()),
- session_(new HttpNetworkSession(new MockHostResolver,
- ProxyService::CreateNull(),
- &socket_factory_,
- new SSLConfigServiceDefaults,
- new SpdySessionPool(),
- http_auth_handler_factory_.get(),
- NULL,
- NULL)),
notunnel_socket_params_(new HttpProxySocketParams(
ignored_tcp_socket_params_, GURL("http://host"),
HostPortPair("host", 80), NULL, false)),
+ auth_controller_(new MockHttpAuthController),
tunnel_socket_params_(new HttpProxySocketParams(
ignored_tcp_socket_params_, GURL("http://host"),
- HostPortPair("host", 80), session_, true)),
+ HostPortPair("host", 80), auth_controller_, true)),
http_proxy_histograms_(
new ClientSocketPoolHistograms("HttpProxyUnitTest")),
pool_(new HttpProxyClientSocketPool(kMaxSockets, kMaxSocketsPerGroup,
http_proxy_histograms_, NULL, tcp_socket_pool_, NULL)) {
}
- 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, "/");
- }
-
int StartRequest(const std::string& group_name, RequestPriority priority) {
return StartRequestUsingPool(
pool_, group_name, priority, tunnel_socket_params_);
@@ -74,10 +52,8 @@ class HttpProxyClientSocketPoolTest : public ClientSocketPoolTest {
MockClientSocketFactory tcp_client_socket_factory_;
scoped_refptr<MockTCPClientSocketPool> tcp_socket_pool_;
- MockClientSocketFactory socket_factory_;
- scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_;
- scoped_refptr<HttpNetworkSession> session_;
scoped_refptr<HttpProxySocketParams> notunnel_socket_params_;
+ scoped_refptr<MockHttpAuthController> auth_controller_;
scoped_refptr<HttpProxySocketParams> tunnel_socket_params_;
scoped_refptr<ClientSocketPoolHistograms> http_proxy_histograms_;
scoped_refptr<HttpProxyClientSocketPool> pool_;
@@ -96,7 +72,7 @@ TEST_F(HttpProxyClientSocketPoolTest, NoTunnel) {
EXPECT_TRUE(handle.socket());
HttpProxyClientSocket* tunnel_socket =
static_cast<HttpProxyClientSocket*>(handle.socket());
- EXPECT_TRUE(tunnel_socket->IsConnected());
+ EXPECT_FALSE(tunnel_socket->NeedsRestartWithAuth());
}
TEST_F(HttpProxyClientSocketPoolTest, NeedAuth) {
@@ -116,6 +92,10 @@ TEST_F(HttpProxyClientSocketPoolTest, NeedAuth) {
arraysize(writes));
tcp_client_socket_factory_.AddSocketDataProvider(&data);
+ MockHttpAuthControllerData auth_data[] = {
+ MockHttpAuthControllerData(""),
+ };
+ auth_controller_->SetMockAuthControllerData(auth_data, arraysize(auth_data));
ClientSocketHandle handle;
TestCompletionCallback callback;
@@ -130,7 +110,7 @@ TEST_F(HttpProxyClientSocketPoolTest, NeedAuth) {
EXPECT_TRUE(handle.socket());
HttpProxyClientSocket* tunnel_socket =
static_cast<HttpProxyClientSocket*>(handle.socket());
- EXPECT_FALSE(tunnel_socket->IsConnected());
+ EXPECT_TRUE(tunnel_socket->NeedsRestartWithAuth());
}
TEST_F(HttpProxyClientSocketPoolTest, HaveAuth) {
@@ -139,7 +119,7 @@ TEST_F(HttpProxyClientSocketPoolTest, HaveAuth) {
"CONNECT host:80 HTTP/1.1\r\n"
"Host: host\r\n"
"Proxy-Connection: keep-alive\r\n"
- "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
+ "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
};
MockRead reads[] = {
MockRead(false, "HTTP/1.1 200 Connection Established\r\n\r\n"),
@@ -149,7 +129,10 @@ TEST_F(HttpProxyClientSocketPoolTest, HaveAuth) {
data.set_connect_data(MockConnect(false, 0));
tcp_client_socket_factory_.AddSocketDataProvider(&data);
- AddAuthToCache();
+ MockHttpAuthControllerData auth_data[] = {
+ MockHttpAuthControllerData("Proxy-Authorization: Basic Zm9vOmJheg=="),
+ };
+ auth_controller_->SetMockAuthControllerData(auth_data, arraysize(auth_data));
ClientSocketHandle handle;
TestCompletionCallback callback;
@@ -160,7 +143,7 @@ TEST_F(HttpProxyClientSocketPoolTest, HaveAuth) {
EXPECT_TRUE(handle.socket());
HttpProxyClientSocket* tunnel_socket =
static_cast<HttpProxyClientSocket*>(handle.socket());
- EXPECT_TRUE(tunnel_socket->IsConnected());
+ EXPECT_FALSE(tunnel_socket->NeedsRestartWithAuth());
}
TEST_F(HttpProxyClientSocketPoolTest, AsyncHaveAuth) {
@@ -168,7 +151,7 @@ TEST_F(HttpProxyClientSocketPoolTest, AsyncHaveAuth) {
MockWrite("CONNECT host:80 HTTP/1.1\r\n"
"Host: host\r\n"
"Proxy-Connection: keep-alive\r\n"
- "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
+ "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
};
MockRead reads[] = {
MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
@@ -177,7 +160,10 @@ TEST_F(HttpProxyClientSocketPoolTest, AsyncHaveAuth) {
arraysize(writes));
tcp_client_socket_factory_.AddSocketDataProvider(&data);
- AddAuthToCache();
+ MockHttpAuthControllerData auth_data[] = {
+ MockHttpAuthControllerData("Proxy-Authorization: Basic Zm9vOmJheg=="),
+ };
+ auth_controller_->SetMockAuthControllerData(auth_data, arraysize(auth_data));
ClientSocketHandle handle;
TestCompletionCallback callback;
@@ -192,7 +178,7 @@ TEST_F(HttpProxyClientSocketPoolTest, AsyncHaveAuth) {
EXPECT_TRUE(handle.socket());
HttpProxyClientSocket* tunnel_socket =
static_cast<HttpProxyClientSocket*>(handle.socket());
- EXPECT_TRUE(tunnel_socket->IsConnected());
+ EXPECT_FALSE(tunnel_socket->NeedsRestartWithAuth());
}
TEST_F(HttpProxyClientSocketPoolTest, TCPError) {
@@ -219,7 +205,7 @@ TEST_F(HttpProxyClientSocketPoolTest, TunnelUnexpectedClose) {
MockWrite("CONNECT host:80 HTTP/1.1\r\n"
"Host: host\r\n"
"Proxy-Connection: keep-alive\r\n"
- "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
+ "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
};
MockRead reads[] = {
MockRead("HTTP/1.1 200 Conn"),
@@ -229,7 +215,10 @@ TEST_F(HttpProxyClientSocketPoolTest, TunnelUnexpectedClose) {
arraysize(writes));
tcp_client_socket_factory_.AddSocketDataProvider(&data);
- AddAuthToCache();
+ MockHttpAuthControllerData auth_data[] = {
+ MockHttpAuthControllerData("Proxy-Authorization: Basic Zm9vOmJheg=="),
+ };
+ auth_controller_->SetMockAuthControllerData(auth_data, arraysize(auth_data));
ClientSocketHandle handle;
TestCompletionCallback callback;
@@ -249,7 +238,7 @@ TEST_F(HttpProxyClientSocketPoolTest, TunnelSetupError) {
MockWrite("CONNECT host:80 HTTP/1.1\r\n"
"Host: host\r\n"
"Proxy-Connection: keep-alive\r\n"
- "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
+ "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
};
MockRead reads[] = {
MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
@@ -258,7 +247,10 @@ TEST_F(HttpProxyClientSocketPoolTest, TunnelSetupError) {
arraysize(writes));
tcp_client_socket_factory_.AddSocketDataProvider(&data);
- AddAuthToCache();
+ MockHttpAuthControllerData auth_data[] = {
+ MockHttpAuthControllerData("Proxy-Authorization: Basic Zm9vOmJheg=="),
+ };
+ auth_controller_->SetMockAuthControllerData(auth_data, arraysize(auth_data));
ClientSocketHandle handle;
TestCompletionCallback callback;
diff --git a/net/socket/client_socket_handle.cc b/net/socket/client_socket_handle.cc
index d9ccbd5..de2fd94 100644
--- a/net/socket/client_socket_handle.cc
+++ b/net/socket/client_socket_handle.cc
@@ -59,7 +59,6 @@ void ClientSocketHandle::ResetInternal(bool cancel) {
void ClientSocketHandle::ResetErrorState() {
is_ssl_error_ = false;
ssl_error_response_info_ = HttpResponseInfo();
- pending_http_proxy_connection_.reset();
}
LoadState ClientSocketHandle::GetLoadState() const {
diff --git a/net/socket/client_socket_handle.h b/net/socket/client_socket_handle.h
index adccc89..a25bfdb 100644
--- a/net/socket/client_socket_handle.h
+++ b/net/socket/client_socket_handle.h
@@ -109,9 +109,6 @@ class ClientSocketHandle {
void set_ssl_error_response_info(const HttpResponseInfo& ssl_error_state) {
ssl_error_response_info_ = ssl_error_state;
}
- void set_pending_http_proxy_connection(ClientSocketHandle* connection) {
- pending_http_proxy_connection_.reset(connection);
- }
// Only valid if there is no |socket_|.
bool is_ssl_error() const {
@@ -124,9 +121,6 @@ class ClientSocketHandle {
const HttpResponseInfo& ssl_error_response_info() const {
return ssl_error_response_info_;
}
- ClientSocketHandle* release_pending_http_proxy_connection() {
- return pending_http_proxy_connection_.release();
- }
// These may only be used if is_initialized() is true.
const std::string& group_name() const { return group_name_; }
@@ -185,7 +179,6 @@ class ClientSocketHandle {
int pool_id_; // See ClientSocketPool::ReleaseSocket() for an explanation.
bool is_ssl_error_;
HttpResponseInfo ssl_error_response_info_;
- scoped_ptr<ClientSocketHandle> pending_http_proxy_connection_;
base::TimeTicks init_time_;
base::TimeDelta setup_time_;
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc
index ce7f3fc06..d4d74a7 100644
--- a/net/socket/socket_test_util.cc
+++ b/net/socket/socket_test_util.cc
@@ -886,6 +886,53 @@ void MockSOCKSClientSocketPool::ReleaseSocket(const std::string& group_name,
MockSOCKSClientSocketPool::~MockSOCKSClientSocketPool() {}
+MockHttpAuthController::MockHttpAuthController()
+ : HttpAuthController(HttpAuth::AUTH_PROXY, GURL(),
+ scoped_refptr<HttpNetworkSession>(NULL)),
+ data_(NULL),
+ data_index_(0),
+ data_count_(0) {
+}
+
+void MockHttpAuthController::SetMockAuthControllerData(
+ struct MockHttpAuthControllerData* data, size_t count) {
+ data_ = data;
+ data_count_ = count;
+}
+
+int MockHttpAuthController::MaybeGenerateAuthToken(
+ const HttpRequestInfo* request,
+ CompletionCallback* callback,
+ const BoundNetLog& net_log) {
+ return OK;
+}
+
+void MockHttpAuthController::AddAuthorizationHeader(
+ HttpRequestHeaders* authorization_headers) {
+ authorization_headers->AddHeadersFromString(CurrentData().auth_header);
+}
+
+int MockHttpAuthController::HandleAuthChallenge(
+ scoped_refptr<HttpResponseHeaders> headers,
+ bool do_not_send_server_auth,
+ bool establishing_tunnel,
+ const BoundNetLog& net_log) {
+ return OK;
+}
+
+void MockHttpAuthController::ResetAuth(const string16& username,
+ const string16& password) {
+ data_index_++;
+}
+
+bool MockHttpAuthController::HaveAuth() const {
+ return CurrentData().auth_header.size() != 0;
+}
+
+bool MockHttpAuthController::HaveAuthHandler() const {
+ return HaveAuth();
+}
+
const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
const int kSOCKS5GreetRequestLength = arraysize(kSOCKS5GreetRequest);
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h
index 0ccf878..1a0ab11 100644
--- a/net/socket/socket_test_util.h
+++ b/net/socket/socket_test_util.h
@@ -695,6 +695,46 @@ class MockSOCKSClientSocketPool : public SOCKSClientSocketPool {
DISALLOW_COPY_AND_ASSIGN(MockSOCKSClientSocketPool);
};
+struct MockHttpAuthControllerData {
+ explicit MockHttpAuthControllerData(std::string header)
+ : auth_header(header) {}
+
+ std::string auth_header;
+};
+
+class MockHttpAuthController : public HttpAuthController {
+ public:
+ MockHttpAuthController();
+ void SetMockAuthControllerData(struct MockHttpAuthControllerData* data,
+ size_t data_length);
+
+ // HttpAuthController methods.
+ virtual int MaybeGenerateAuthToken(const HttpRequestInfo* request,
+ CompletionCallback* callback,
+ const BoundNetLog& net_log);
+ virtual void AddAuthorizationHeader(
+ HttpRequestHeaders* authorization_headers);
+ virtual int HandleAuthChallenge(scoped_refptr<HttpResponseHeaders> headers,
+ bool do_not_send_server_auth,
+ bool establishing_tunnel,
+ const BoundNetLog& net_log);
+ virtual void ResetAuth(const string16& username,
+ const string16& password);
+ virtual bool HaveAuthHandler() const;
+ virtual bool HaveAuth() const;
+
+ private:
+ virtual ~MockHttpAuthController() {}
+ const struct MockHttpAuthControllerData& CurrentData() const {
+ DCHECK(data_index_ < data_count_);
+ return data_[data_index_];
+ }
+
+ MockHttpAuthControllerData* data_;
+ size_t data_index_;
+ size_t data_count_;
+};
+
// Constants for a successful SOCKS v5 handshake.
extern const char kSOCKS5GreetRequest[];
extern const int kSOCKS5GreetRequestLength;
diff --git a/net/socket/ssl_client_socket_pool.cc b/net/socket/ssl_client_socket_pool.cc
index 5ed450e..03e2e80 100644
--- a/net/socket/ssl_client_socket_pool.cc
+++ b/net/socket/ssl_client_socket_pool.cc
@@ -103,6 +103,11 @@ LoadState SSLConnectJob::GetLoadState() const {
}
int SSLConnectJob::ConnectInternal() {
+ DetermineFirstState();
+ return DoLoop(OK);
+}
+
+void SSLConnectJob::DetermineFirstState() {
switch (params_->proxy()) {
case ProxyServer::SCHEME_DIRECT:
next_state_ = STATE_TCP_CONNECT;
@@ -118,7 +123,6 @@ int SSLConnectJob::ConnectInternal() {
NOTREACHED() << "unknown proxy type";
break;
}
- return DoLoop(OK);
}
void SSLConnectJob::OnIOComplete(int result) {
@@ -210,7 +214,6 @@ int SSLConnectJob::DoSOCKSConnectComplete(int result) {
int SSLConnectJob::DoTunnelConnect() {
DCHECK(http_proxy_pool_.get());
next_state_ = STATE_TUNNEL_CONNECT_COMPLETE;
-
transport_socket_handle_.reset(new ClientSocketHandle());
scoped_refptr<HttpProxySocketParams> http_proxy_params =
params_->http_proxy_params();
@@ -225,6 +228,12 @@ int SSLConnectJob::DoTunnelConnectComplete(int result) {
HttpProxyClientSocket* tunnel_socket =
static_cast<HttpProxyClientSocket*>(socket);
+ if (result == ERR_RETRY_CONNECTION) {
+ DetermineFirstState();
+ transport_socket_handle_->socket()->Disconnect();
+ return OK;
+ }
+
// Extract the information needed to prompt for the proxy authentication.
// so that when ClientSocketPoolBaseHelper calls |GetAdditionalErrorState|,
// we can easily set the state.
@@ -234,17 +243,20 @@ int SSLConnectJob::DoTunnelConnectComplete(int result) {
if (result < 0)
return result;
- DCHECK(tunnel_socket->IsConnected());
+ if (tunnel_socket->NeedsRestartWithAuth()) {
+ // We must have gotten an 'idle' tunnel socket that is waiting for auth.
+ // The HttpAuthController should have new credentials, we just need
+ // to retry.
+ next_state_ = STATE_TUNNEL_CONNECT_COMPLETE;
+ return tunnel_socket->RestartWithAuth(&callback_);
+ }
+
next_state_ = STATE_SSL_CONNECT;
return result;
}
void SSLConnectJob::GetAdditionalErrorState(ClientSocketHandle * handle) {
- if (error_response_info_.headers) {
- handle->set_ssl_error_response_info(error_response_info_);
- handle->set_pending_http_proxy_connection(
- transport_socket_handle_.release());
- }
+ handle->set_ssl_error_response_info(error_response_info_);
if (!ssl_connect_start_time_.is_null())
handle->set_is_ssl_error(true);
}
diff --git a/net/socket/ssl_client_socket_pool.h b/net/socket/ssl_client_socket_pool.h
index 9857c61..b44985f 100644
--- a/net/socket/ssl_client_socket_pool.h
+++ b/net/socket/ssl_client_socket_pool.h
@@ -44,7 +44,7 @@ class SSLSocketParams : public base::RefCounted<SSLSocketParams> {
bool want_spdy_over_npn);
const scoped_refptr<TCPSocketParams>& tcp_params() { return tcp_params_; }
- const scoped_refptr<HttpProxySocketParams>& http_proxy_params() {
+ const scoped_refptr<HttpProxySocketParams>& http_proxy_params () {
return http_proxy_params_;
}
const scoped_refptr<SOCKSSocketParams>& socks_params() {
@@ -114,6 +114,8 @@ class SSLConnectJob : public ConnectJob {
// Otherwise, it returns a net error code.
virtual int ConnectInternal();
+ void DetermineFirstState();
+
void OnIOComplete(int result);
// Runs the state transition loop.
diff --git a/net/socket/ssl_client_socket_pool_unittest.cc b/net/socket/ssl_client_socket_pool_unittest.cc
index 047a647..efc4795 100644
--- a/net/socket/ssl_client_socket_pool_unittest.cc
+++ b/net/socket/ssl_client_socket_pool_unittest.cc
@@ -6,14 +6,13 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
-#include "base/string_util.h"
#include "base/time.h"
#include "net/base/auth.h"
#include "net/base/mock_host_resolver.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
#include "net/base/ssl_config_service_defaults.h"
-#include "net/http/http_auth_handler_factory.h"
+#include "net/http/http_auth_controller.h"
#include "net/http/http_network_session.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
@@ -21,7 +20,6 @@
#include "net/socket/client_socket_handle.h"
#include "net/socket/client_socket_pool_histograms.h"
#include "net/socket/socket_test_util.h"
-#include "net/spdy/spdy_session_pool.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
@@ -34,16 +32,7 @@ const int kMaxSocketsPerGroup = 6;
class SSLClientSocketPoolTest : public ClientSocketPoolTest {
protected:
SSLClientSocketPoolTest()
- : http_auth_handler_factory_(HttpAuthHandlerFactory::CreateDefault()),
- session_(new HttpNetworkSession(new MockHostResolver,
- ProxyService::CreateNull(),
- &socket_factory_,
- new SSLConfigServiceDefaults,
- new SpdySessionPool(),
- http_auth_handler_factory_.get(),
- NULL,
- NULL)),
- direct_tcp_socket_params_(new TCPSocketParams(
+ : direct_tcp_socket_params_(new TCPSocketParams(
HostPortPair("host", 443), MEDIUM, GURL(), false)),
tcp_socket_pool_(new MockTCPClientSocketPool(
kMaxSockets,
@@ -52,9 +41,6 @@ class SSLClientSocketPoolTest : public ClientSocketPoolTest {
&socket_factory_)),
proxy_tcp_socket_params_(new TCPSocketParams(
HostPortPair("proxy", 443), MEDIUM, GURL(), false)),
- http_proxy_socket_params_(new HttpProxySocketParams(
- proxy_tcp_socket_params_, GURL("http://host"),
- HostPortPair("host", 80), session_, true)),
http_proxy_socket_pool_(new HttpProxyClientSocketPool(
kMaxSockets,
kMaxSocketsPerGroup,
@@ -88,30 +74,33 @@ class SSLClientSocketPoolTest : public ClientSocketPoolTest {
NULL);
}
- scoped_refptr<SSLSocketParams> SSLParams(ProxyServer::Scheme proxy,
- bool want_spdy_over_npn) {
+ scoped_refptr<SSLSocketParams> SSLParams(
+ ProxyServer::Scheme proxy, struct MockHttpAuthControllerData* auth_data,
+ size_t auth_data_len, bool want_spdy_over_ssl, bool want_spdy_over_npn) {
+ scoped_refptr<HttpProxySocketParams> http_proxy_params;
+ if (proxy == ProxyServer::SCHEME_HTTP) {
+ scoped_refptr<MockHttpAuthController> auth_controller =
+ new MockHttpAuthController();
+ auth_controller->SetMockAuthControllerData(auth_data, auth_data_len);
+ http_proxy_params = new HttpProxySocketParams(proxy_tcp_socket_params_,
+ GURL("http://host"),
+ HostPortPair("host", 80),
+ auth_controller, true);
+ }
+
return make_scoped_refptr(new SSLSocketParams(
proxy == ProxyServer::SCHEME_DIRECT ? direct_tcp_socket_params_ : NULL,
- proxy == ProxyServer::SCHEME_HTTP ? http_proxy_socket_params_ : NULL,
+ http_proxy_params,
proxy == ProxyServer::SCHEME_SOCKS5 ? socks_socket_params_ : NULL,
proxy,
"host",
ssl_config_,
0,
- false,
+ want_spdy_over_ssl,
want_spdy_over_npn));
}
- void AddAuthToCache() {
- const string16 kFoo(ASCIIToUTF16("foo"));
- const string16 kBar(ASCIIToUTF16("bar"));
- session_->auth_cache()->Add(GURL("http://proxy:443/"), "MyRealm1", "Basic",
- "Basic realm=MyRealm1", kFoo, kBar, "/");
- }
-
MockClientSocketFactory socket_factory_;
- scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_;
- scoped_refptr<HttpNetworkSession> session_;
scoped_refptr<TCPSocketParams> direct_tcp_socket_params_;
scoped_refptr<MockTCPClientSocketPool> tcp_socket_pool_;
@@ -134,7 +123,7 @@ TEST_F(SSLClientSocketPoolTest, TCPFail) {
CreatePool(true /* tcp pool */, false, false);
scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT,
- false);
+ NULL, 0, false, false);
ClientSocketHandle handle;
int rv = handle.Init("a", params, MEDIUM, NULL, pool_, BoundNetLog());
@@ -151,7 +140,7 @@ TEST_F(SSLClientSocketPoolTest, TCPFailAsync) {
CreatePool(true /* tcp pool */, false, false);
scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT,
- false);
+ NULL, 0, false, false);
ClientSocketHandle handle;
TestCompletionCallback callback;
@@ -175,7 +164,7 @@ TEST_F(SSLClientSocketPoolTest, BasicDirect) {
CreatePool(true /* tcp pool */, false, false);
scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT,
- false);
+ NULL, 0, false, false);
ClientSocketHandle handle;
TestCompletionCallback callback;
@@ -193,7 +182,7 @@ TEST_F(SSLClientSocketPoolTest, BasicDirectAsync) {
CreatePool(true /* tcp pool */, false, false);
scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT,
- false);
+ NULL, 0, false, false);
ClientSocketHandle handle;
TestCompletionCallback callback;
@@ -215,7 +204,7 @@ TEST_F(SSLClientSocketPoolTest, DirectCertError) {
CreatePool(true /* tcp pool */, false, false);
scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT,
- false);
+ NULL, 0, false, false);
ClientSocketHandle handle;
TestCompletionCallback callback;
@@ -237,7 +226,7 @@ TEST_F(SSLClientSocketPoolTest, DirectSSLError) {
CreatePool(true /* tcp pool */, false, false);
scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT,
- false);
+ NULL, 0, false, false);
ClientSocketHandle handle;
TestCompletionCallback callback;
@@ -262,7 +251,7 @@ TEST_F(SSLClientSocketPoolTest, DirectWithNPN) {
CreatePool(true /* tcp pool */, false, false);
scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT,
- false);
+ NULL, 0, false, false);
ClientSocketHandle handle;
TestCompletionCallback callback;
@@ -288,7 +277,7 @@ TEST_F(SSLClientSocketPoolTest, DirectNoSPDY) {
CreatePool(true /* tcp pool */, false, false);
scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT,
- true);
+ NULL, 0, false, true);
ClientSocketHandle handle;
TestCompletionCallback callback;
@@ -313,7 +302,7 @@ TEST_F(SSLClientSocketPoolTest, DirectGotSPDY) {
CreatePool(true /* tcp pool */, false, false);
scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT,
- true);
+ NULL, 0, false, true);
ClientSocketHandle handle;
TestCompletionCallback callback;
@@ -344,7 +333,7 @@ TEST_F(SSLClientSocketPoolTest, DirectGotBonusSPDY) {
CreatePool(true /* tcp pool */, false, false);
scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT,
- true);
+ NULL, 0, false, true);
ClientSocketHandle handle;
TestCompletionCallback callback;
@@ -372,7 +361,7 @@ TEST_F(SSLClientSocketPoolTest, SOCKSFail) {
CreatePool(false, true /* http proxy pool */, true /* socks pool */);
scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_SOCKS5,
- false);
+ NULL, 0, false, false);
ClientSocketHandle handle;
TestCompletionCallback callback;
@@ -390,7 +379,7 @@ TEST_F(SSLClientSocketPoolTest, SOCKSFailAsync) {
CreatePool(false, true /* http proxy pool */, true /* socks pool */);
scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_SOCKS5,
- false);
+ NULL, 0, false, false);
ClientSocketHandle handle;
TestCompletionCallback callback;
@@ -414,7 +403,7 @@ TEST_F(SSLClientSocketPoolTest, SOCKSBasic) {
CreatePool(false, true /* http proxy pool */, true /* socks pool */);
scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_SOCKS5,
- false);
+ NULL, 0, false, false);
ClientSocketHandle handle;
TestCompletionCallback callback;
@@ -432,7 +421,7 @@ TEST_F(SSLClientSocketPoolTest, SOCKSBasicAsync) {
CreatePool(false, true /* http proxy pool */, true /* socks pool */);
scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_SOCKS5,
- false);
+ NULL, 0, false, false);
ClientSocketHandle handle;
TestCompletionCallback callback;
@@ -453,7 +442,7 @@ TEST_F(SSLClientSocketPoolTest, HttpProxyFail) {
CreatePool(false, true /* http proxy pool */, true /* socks pool */);
scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_HTTP,
- false);
+ NULL, 0, false, false);
ClientSocketHandle handle;
TestCompletionCallback callback;
@@ -471,7 +460,7 @@ TEST_F(SSLClientSocketPoolTest, HttpProxyFailAsync) {
CreatePool(false, true /* http proxy pool */, true /* socks pool */);
scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_HTTP,
- false);
+ NULL, 0, false, false);
ClientSocketHandle handle;
TestCompletionCallback callback;
@@ -492,7 +481,7 @@ TEST_F(SSLClientSocketPoolTest, HttpProxyBasic) {
"CONNECT host:80 HTTP/1.1\r\n"
"Host: host\r\n"
"Proxy-Connection: keep-alive\r\n"
- "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
+ "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
};
MockRead reads[] = {
MockRead(false, "HTTP/1.1 200 Connection Established\r\n\r\n"),
@@ -501,12 +490,17 @@ TEST_F(SSLClientSocketPoolTest, HttpProxyBasic) {
arraysize(writes));
data.set_connect_data(MockConnect(false, OK));
socket_factory_.AddSocketDataProvider(&data);
- AddAuthToCache();
+ MockHttpAuthControllerData auth_data[] = {
+ MockHttpAuthControllerData("Proxy-Authorization: Basic Zm9vOmJheg=="),
+ };
SSLSocketDataProvider ssl(false, OK);
socket_factory_.AddSSLSocketDataProvider(&ssl);
CreatePool(false, true /* http proxy pool */, true /* socks pool */);
scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_HTTP,
+ auth_data,
+ arraysize(auth_data),
+ false,
false);
ClientSocketHandle handle;
@@ -522,7 +516,7 @@ TEST_F(SSLClientSocketPoolTest, HttpProxyBasicAsync) {
MockWrite("CONNECT host:80 HTTP/1.1\r\n"
"Host: host\r\n"
"Proxy-Connection: keep-alive\r\n"
- "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
+ "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
};
MockRead reads[] = {
MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
@@ -530,12 +524,17 @@ TEST_F(SSLClientSocketPoolTest, HttpProxyBasicAsync) {
StaticSocketDataProvider data(reads, arraysize(reads), writes,
arraysize(writes));
socket_factory_.AddSocketDataProvider(&data);
- AddAuthToCache();
+ MockHttpAuthControllerData auth_data[] = {
+ MockHttpAuthControllerData("Proxy-Authorization: Basic Zm9vOmJheg=="),
+ };
SSLSocketDataProvider ssl(true, OK);
socket_factory_.AddSSLSocketDataProvider(&ssl);
CreatePool(false, true /* http proxy pool */, true /* socks pool */);
scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_HTTP,
+ auth_data,
+ arraysize(auth_data),
+ false,
false);
ClientSocketHandle handle;
@@ -565,11 +564,135 @@ TEST_F(SSLClientSocketPoolTest, NeedProxyAuth) {
StaticSocketDataProvider data(reads, arraysize(reads), writes,
arraysize(writes));
socket_factory_.AddSocketDataProvider(&data);
+ MockHttpAuthControllerData auth_data[] = {
+ MockHttpAuthControllerData(""),
+ };
+ SSLSocketDataProvider ssl(true, OK);
+ socket_factory_.AddSSLSocketDataProvider(&ssl);
+
+ CreatePool(false, true /* http proxy pool */, true /* socks pool */);
+ scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_HTTP,
+ auth_data,
+ arraysize(auth_data),
+ false,
+ false);
+
+ ClientSocketHandle handle;
+ TestCompletionCallback callback;
+ int rv = handle.Init("a", params, MEDIUM, &callback, pool_, BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_FALSE(handle.is_initialized());
+ EXPECT_FALSE(handle.socket());
+
+ EXPECT_EQ(ERR_PROXY_AUTH_REQUESTED, callback.WaitForResult());
+ EXPECT_FALSE(handle.is_initialized());
+ EXPECT_FALSE(handle.socket());
+ EXPECT_FALSE(handle.is_ssl_error());
+ const HttpResponseInfo& tunnel_info = handle.ssl_error_response_info();
+ EXPECT_EQ(tunnel_info.headers->response_code(), 407);
+}
+
+TEST_F(SSLClientSocketPoolTest, DoProxyAuth) {
+ MockWrite writes[] = {
+ MockWrite("CONNECT host:80 HTTP/1.1\r\n"
+ "Host: host\r\n"
+ "Proxy-Connection: keep-alive\r\n\r\n"),
+ MockWrite("CONNECT host:80 HTTP/1.1\r\n"
+ "Host: host\r\n"
+ "Proxy-Connection: keep-alive\r\n"
+ "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
+ };
+ MockRead reads[] = {
+ MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
+ MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
+ MockRead("Content-Length: 10\r\n\r\n"),
+ MockRead("0123456789"),
+ MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
+ };
+ StaticSocketDataProvider data(reads, arraysize(reads), writes,
+ arraysize(writes));
+ socket_factory_.AddSocketDataProvider(&data);
+ MockHttpAuthControllerData auth_data[] = {
+ MockHttpAuthControllerData(""),
+ MockHttpAuthControllerData("Proxy-Authorization: Basic Zm9vOmJheg=="),
+ };
+ SSLSocketDataProvider ssl(true, OK);
+ socket_factory_.AddSSLSocketDataProvider(&ssl);
+
+ CreatePool(false, true /* http proxy pool */, true /* socks pool */);
+ scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_HTTP,
+ auth_data,
+ arraysize(auth_data),
+ false,
+ false);
+
+ ClientSocketHandle handle;
+ TestCompletionCallback callback;
+ int rv = handle.Init("a", params, MEDIUM, &callback, pool_, BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_FALSE(handle.is_initialized());
+ EXPECT_FALSE(handle.socket());
+
+ EXPECT_EQ(ERR_PROXY_AUTH_REQUESTED, callback.WaitForResult());
+ EXPECT_FALSE(handle.is_initialized());
+ EXPECT_FALSE(handle.socket());
+ EXPECT_FALSE(handle.is_ssl_error());
+ const HttpResponseInfo& tunnel_info = handle.ssl_error_response_info();
+ EXPECT_EQ(tunnel_info.headers->response_code(), 407);
+
+ params->http_proxy_params()->auth_controller()->ResetAuth(string16(),
+ string16());
+ rv = handle.Init("a", params, MEDIUM, &callback, pool_, BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_FALSE(handle.is_initialized());
+ EXPECT_FALSE(handle.socket());
+
+ // Test that http://crbug.com/49325 doesn't regress.
+ EXPECT_EQ(handle.GetLoadState(), LOAD_STATE_ESTABLISHING_PROXY_TUNNEL);
+
+ EXPECT_EQ(OK, callback.WaitForResult());
+ EXPECT_TRUE(handle.is_initialized());
+ EXPECT_TRUE(handle.socket());
+}
+
+TEST_F(SSLClientSocketPoolTest, DoProxyAuthNoKeepAlive) {
+ MockWrite writes1[] = {
+ MockWrite("CONNECT host:80 HTTP/1.1\r\n"
+ "Host: host\r\n"
+ "Proxy-Connection: keep-alive\r\n\r\n"),
+ };
+ MockWrite writes2[] = {
+ MockWrite("CONNECT host:80 HTTP/1.1\r\n"
+ "Host: host\r\n"
+ "Proxy-Connection: keep-alive\r\n"
+ "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
+ };
+ MockRead reads1[] = {
+ MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
+ MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
+ MockRead("Content0123456789"),
+ };
+ MockRead reads2[] = {
+ MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
+ };
+ StaticSocketDataProvider data1(reads1, arraysize(reads1), writes1,
+ arraysize(writes1));
+ socket_factory_.AddSocketDataProvider(&data1);
+ StaticSocketDataProvider data2(reads2, arraysize(reads2), writes2,
+ arraysize(writes2));
+ socket_factory_.AddSocketDataProvider(&data2);
+ MockHttpAuthControllerData auth_data[] = {
+ MockHttpAuthControllerData(""),
+ MockHttpAuthControllerData("Proxy-Authorization: Basic Zm9vOmJheg=="),
+ };
SSLSocketDataProvider ssl(true, OK);
socket_factory_.AddSSLSocketDataProvider(&ssl);
CreatePool(false, true /* http proxy pool */, true /* socks pool */);
scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_HTTP,
+ auth_data,
+ arraysize(auth_data),
+ false,
false);
ClientSocketHandle handle;
@@ -585,10 +708,17 @@ TEST_F(SSLClientSocketPoolTest, NeedProxyAuth) {
EXPECT_FALSE(handle.is_ssl_error());
const HttpResponseInfo& tunnel_info = handle.ssl_error_response_info();
EXPECT_EQ(tunnel_info.headers->response_code(), 407);
- scoped_ptr<ClientSocketHandle> tunnel_handle(
- handle.release_pending_http_proxy_connection());
- EXPECT_TRUE(tunnel_handle->socket());
- EXPECT_FALSE(tunnel_handle->socket()->IsConnected());
+
+ params->http_proxy_params()->auth_controller()->ResetAuth(string16(),
+ string16());
+ rv = handle.Init("a", params, MEDIUM, &callback, pool_, BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_FALSE(handle.is_initialized());
+ EXPECT_FALSE(handle.socket());
+
+ EXPECT_EQ(OK, callback.WaitForResult());
+ EXPECT_TRUE(handle.is_initialized());
+ EXPECT_TRUE(handle.socket());
}
// It would be nice to also test the timeouts in SSLClientSocketPool.