diff options
author | vandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-03 07:38:59 +0000 |
---|---|---|
committer | vandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-03 07:38:59 +0000 |
commit | 394816e907ab5e328899e41a402537c0ff3c0381 (patch) | |
tree | 157bbb558f7f686d500e55e073b7978137469451 | |
parent | 9c1fe143f8e11092424875fbcdaccec16f141981 (diff) | |
download | chromium_src-394816e907ab5e328899e41a402537c0ff3c0381.zip chromium_src-394816e907ab5e328899e41a402537c0ff3c0381.tar.gz chromium_src-394816e907ab5e328899e41a402537c0ff3c0381.tar.bz2 |
Recommit 54405 - Fix late binding induced mismatch of Socket and AuthController
ClientSocketPool treats all pending SocketParams as interchangeable. Therefore they can not contain any connection specific data. This only affects the Http Proxy tunnel case. The lowest risk change to fix this problem is to create the HttpAuthController in the HttpProxyClientSocket. If we get a 407 and need to restart the Tunnel, the pending HttpProxyClientSocket is returned to the HttpNetworkTransaction in the additional error state of the connection and then complete the auth in a pair of states in the HttpNetworkTransaction. This reintroduces a dependency between tunnel setup and the HttpNetworkTransaction, but that will need to be fixed at a later date.
Original Review URL: http://codereview.chromium.org/3058013
BUG=49493
TEST=existing unit tests + manually visiting many SSL sites through a kerberized http proxy.
Review URL: http://codereview.chromium.org/3029052
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@54714 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | net/base/net_error_list.h | 5 | ||||
-rw-r--r-- | net/http/http_network_transaction.cc | 128 | ||||
-rw-r--r-- | net/http/http_network_transaction.h | 7 | ||||
-rw-r--r-- | net/http/http_network_transaction_unittest.cc | 188 | ||||
-rw-r--r-- | net/http/http_proxy_client_socket.cc | 52 | ||||
-rw-r--r-- | net/http/http_proxy_client_socket.h | 17 | ||||
-rw-r--r-- | net/http/http_proxy_client_socket_pool.cc | 14 | ||||
-rw-r--r-- | net/http/http_proxy_client_socket_pool.h | 9 | ||||
-rw-r--r-- | net/http/http_proxy_client_socket_pool_unittest.cc | 70 | ||||
-rw-r--r-- | net/socket/client_socket_handle.cc | 1 | ||||
-rw-r--r-- | net/socket/client_socket_handle.h | 7 | ||||
-rw-r--r-- | net/socket/socket_test_util.cc | 48 | ||||
-rw-r--r-- | net/socket/socket_test_util.h | 40 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_pool.cc | 28 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_pool.h | 4 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_pool_unittest.cc | 236 |
16 files changed, 417 insertions, 437 deletions
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h index e302a9f..53849631 100644 --- a/net/base/net_error_list.h +++ b/net/base/net_error_list.h @@ -167,11 +167,6 @@ 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 09a4772..6d77eb1 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc @@ -348,7 +348,8 @@ int HttpNetworkTransaction::RestartWithAuth( if (target == HttpAuth::AUTH_PROXY && using_ssl_ && proxy_info_.is_http()) { DCHECK(establishing_tunnel_); - next_state_ = STATE_INIT_CONNECTION; + next_state_ = STATE_RESTART_TUNNEL_AUTH; + auth_controllers_[target] = NULL; ResetStateForRestart(); } else { PrepareForAuthRestart(target); @@ -549,6 +550,13 @@ 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(); @@ -726,15 +734,6 @@ 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") || @@ -784,29 +783,24 @@ int HttpNetworkTransaction::DoInitConnection() { request_->referrer, disable_resolver_cache); if (proxy_info_.is_http()) { - scoped_refptr<HttpAuthController> http_proxy_auth; GURL authentication_url = request_->url; - if (using_ssl_) { - if (!authentication_url.SchemeIs("https")) { - // If a proxy tunnel connection needs to be established due to - // an Alternate-Protocol, the URL needs to be changed to indicate - // https or digest authentication attempts will fail. - // For example, suppose the initial request was for - // "http://www.example.com/index.html". If this is an SSL - // upgrade due to alternate protocol, the digest authorization - // should have a uri="www.example.com:443" field rather than a - // "/index.html" entry, even though the original request URL has not - // changed. - authentication_url = UpgradeUrlToHttps(authentication_url); - } - http_proxy_auth = auth_controllers_[HttpAuth::AUTH_PROXY]; - establishing_tunnel_ = true; + if (using_ssl_ && !authentication_url.SchemeIs("https")) { + // If a proxy tunnel connection needs to be established due to + // an Alternate-Protocol, the URL needs to be changed to indicate + // https or digest authentication attempts will fail. + // For example, suppose the initial request was for + // "http://www.example.com/index.html". If this is an SSL + // upgrade due to alternate protocol, the digest authorization + // should have a uri="www.example.com:443" field rather than a + // "/index.html" entry, even though the original request URL has not + // changed. + authentication_url = UpgradeUrlToHttps(authentication_url); } + establishing_tunnel_ = using_ssl_; http_proxy_params = new HttpProxySocketParams(proxy_tcp_params, authentication_url, endpoint_, - http_proxy_auth, - using_ssl_); + session_, using_ssl_); } else { DCHECK(proxy_info_.is_socks()); char socks_version; @@ -914,14 +908,13 @@ int HttpNetworkTransaction::DoInitConnectionComplete(int result) { if (result == ERR_PROXY_AUTH_REQUESTED) { DCHECK(!ssl_started); - 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; + // 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); } if ((!ssl_started && result < 0 && @@ -1001,12 +994,44 @@ 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; - return auth_controllers_[HttpAuth::AUTH_PROXY]->MaybeGenerateAuthToken( - request_, &io_callback_, net_log_); + 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_); } int HttpNetworkTransaction::DoGenerateProxyAuthTokenComplete(int rv) { @@ -1018,10 +1043,15 @@ 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_[HttpAuth::AUTH_SERVER]->MaybeGenerateAuthToken( - request_, &io_callback_, net_log_); + return auth_controllers_[target]->MaybeGenerateAuthToken(request_, + &io_callback_, + net_log_); } int HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) { @@ -1544,6 +1574,24 @@ 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 8117325..b3a083c 100644 --- a/net/http/http_network_transaction.h +++ b/net/http/http_network_transaction.h @@ -91,6 +91,8 @@ 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, @@ -134,6 +136,8 @@ 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(); @@ -170,6 +174,9 @@ 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 72fa8aa..4e0d354 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc @@ -1343,6 +1343,111 @@ 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) { @@ -6296,6 +6401,7 @@ TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) { "\r\n"), }; MockRead data_reads_1[] = { + MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), MockRead("HTTP/1.1 200 OK\r\n" "Alternate-Protocol: 443:npn-spdy/2\r\n" "Proxy-Connection: close\r\n" @@ -6307,55 +6413,64 @@ TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) { // Second round tries to tunnel to www.google.com due to the // Alternate-Protocol announcement in the first round. It fails due // to a proxy authentication challenge. + // After the failure, a tunnel is established to www.google.com using + // Proxy-Authorization headers. There is then a SPDY request round. + // + // NOTE: Despite the "Proxy-Connection: Close", these are done on the + // same MockTCPClientSocket since the underlying HttpNetworkClientSocket + // does a Disconnect and Connect on the same socket, rather than trying + // to obtain a new one. + // + // NOTE: Originally, the proxy response to the second CONNECT request + // simply returned another 407 so the unit test could skip the SSL connection + // establishment and SPDY framing issues. Alas, the + // retry-http-when-alternate-protocol fails logic kicks in, which was more + // complicated to set up expectations for than the SPDY session. + + scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); + scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true)); + MockWrite data_writes_2[] = { + // First connection attempt without Proxy-Authorization. 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"), - }; - MockRead data_reads_2[] = { - MockRead("HTTP/1.0 407 Unauthorized\r\n" - "Proxy-Authenticate: Mock\r\n" - "Proxy-Connection: close\r\n" - "\r\n"), - }; - StaticSocketDataProvider data_2(data_reads_2, arraysize(data_reads_2), - data_writes_2, arraysize(data_writes_2)); - // Third round establishes a tunnel to www.google.com due to the - // Alternate-Protocol announcement in the first round, and does a SPDY - // request round. - // TODO(cbentzel): Originally, this just returned another 407 so the unit test - // could skip the SSL connection establishment and SPDY framing issues. Alas, - // the retry-http-when-alternate-protocol fails logic kicks in, which was more - // complicated to set up expectations for than the SPDY session. - scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); - scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); - scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true)); - - MockWrite data_writes_3[] = { - // TUNNEL connection established + // Second connection attempt with Proxy-Authorization. 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: auth_token\r\n" "\r\n"), + // SPDY request - CreateMockWrite(*req), // 3 + CreateMockWrite(*req), }; + const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n" + "Proxy-Authenticate: Mock\r\n" + "Proxy-Connection: close\r\n" + "\r\n"); + const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n"; + MockRead data_reads_2[] = { + // First connection attempt fails + MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1), + MockRead(true, kRejectConnectResponse, + arraysize(kRejectConnectResponse) - 1, 1), - const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n"; - MockRead data_reads_3[] = { - // Proxy response - MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), - // SPDY response. - CreateMockRead(*resp.get(), 4), - CreateMockRead(*data.get(), 4), - MockRead(true, 0, 0, 4), - }; - scoped_refptr<OrderedSocketData> data_3( - new OrderedSocketData(data_reads_3, arraysize(data_reads_3), - data_writes_3, arraysize(data_writes_3))); + // Second connection attempt passes + MockRead(true, kAcceptConnectResponse, + arraysize(kAcceptConnectResponse) -1, 4), + + // SPDY response + CreateMockRead(*resp.get(), 6), + CreateMockRead(*data.get(), 6), + MockRead(true, 0, 0, 6), + }; + scoped_refptr<OrderedSocketData> data_2( + new OrderedSocketData(data_reads_2, arraysize(data_reads_2), + data_writes_2, arraysize(data_writes_2))); SSLSocketDataProvider ssl(true, OK); ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; @@ -6363,8 +6478,7 @@ TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) { ssl.was_npn_negotiated = true; session_deps.socket_factory.AddSocketDataProvider(&data_1); - session_deps.socket_factory.AddSocketDataProvider(&data_2); - session_deps.socket_factory.AddSocketDataProvider(data_3.get()); + session_deps.socket_factory.AddSocketDataProvider(data_2.get()); session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); diff --git a/net/http/http_proxy_client_socket.cc b/net/http/http_proxy_client_socket.cc index 02c2666..1c76c36 100644 --- a/net/http/http_proxy_client_socket.cc +++ b/net/http/http_proxy_client_socket.cc @@ -50,18 +50,20 @@ void BuildTunnelRequest(const HttpRequestInfo* request_info, HttpProxyClientSocket::HttpProxyClientSocket( ClientSocketHandle* transport_socket, const GURL& request_url, - const HostPortPair& endpoint, const scoped_refptr<HttpAuthController>& auth, - bool tunnel) + const HostPortPair& endpoint, const HostPortPair& proxy_server, + const scoped_refptr<HttpNetworkSession>& session, 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_(auth), + auth_(tunnel ? + new HttpAuthController(HttpAuth::AUTH_PROXY, + GURL("http://" + proxy_server.ToString()), + session) : NULL), 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"; @@ -126,13 +128,14 @@ 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. @@ -140,7 +143,7 @@ int HttpProxyClientSocket::DidDrainBodyForAuthRestart(bool keep_alive) { http_stream_.reset(); request_headers_.clear(); response_ = HttpResponseInfo(); - return rc; + return OK; } void HttpProxyClientSocket::LogBlockedTunnelResponse(int response_code) const { @@ -159,19 +162,16 @@ void HttpProxyClientSocket::Disconnect() { } bool HttpProxyClientSocket::IsConnected() const { - return transport_->socket()->IsConnected(); + return next_state_ == STATE_DONE && transport_->socket()->IsConnected(); } bool HttpProxyClientSocket::IsConnectedAndIdle() const { - return transport_->socket()->IsConnectedAndIdle(); -} - -bool HttpProxyClientSocket::NeedsRestartWithAuth() const { - return next_state_ != STATE_DONE; + return next_state_ == STATE_DONE && + transport_->socket()->IsConnectedAndIdle(); } 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,6 +273,13 @@ 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: @@ -280,8 +287,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; } @@ -406,6 +413,19 @@ 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 317b220..ef4f76c 100644 --- a/net/http/http_proxy_client_socket.h +++ b/net/http/http_proxy_client_socket.h @@ -35,7 +35,8 @@ class HttpProxyClientSocket : public ClientSocket { // this socket will establish an Http tunnel. HttpProxyClientSocket(ClientSocketHandle* transport_socket, const GURL& request_url, const HostPortPair& endpoint, - const scoped_refptr<HttpAuthController>& auth, + const HostPortPair& proxy_server, + const scoped_refptr<HttpNetworkSession>& session, bool tunnel); // On destruction Disconnect() is called. @@ -46,12 +47,12 @@ class HttpProxyClientSocket : public ClientSocket { // RestartWithAuth. int RestartWithAuth(CompletionCallback* callback); - // 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 HttpResponseInfo* GetResponseInfo() const { - return response_.headers ? &response_ : NULL; + return response_.headers ? &response_ : NULL; + } + + const scoped_refptr<HttpAuthController>& auth_controller() { + return auth_; } // ClientSocket methods: @@ -85,6 +86,8 @@ 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, }; @@ -112,6 +115,8 @@ 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 a142576..783c10f 100644 --- a/net/http/http_proxy_client_socket_pool.cc +++ b/net/http/http_proxy_client_socket_pool.cc @@ -7,6 +7,7 @@ #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" @@ -18,12 +19,12 @@ HttpProxySocketParams::HttpProxySocketParams( const scoped_refptr<TCPSocketParams>& proxy_server, const GURL& request_url, HostPortPair endpoint, - scoped_refptr<HttpAuthController> auth_controller, + scoped_refptr<HttpNetworkSession> session, bool tunnel) : tcp_params_(proxy_server), request_url_(request_url), endpoint_(endpoint), - auth_controller_(auth_controller), + session_(session), tunnel_(tunnel) { } @@ -133,19 +134,22 @@ 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(), - params_->auth_controller(), + proxy_server, + params_->session(), 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 63d5c02..347a2427 100644 --- a/net/http/http_proxy_client_socket_pool.h +++ b/net/http/http_proxy_client_socket_pool.h @@ -26,12 +26,13 @@ 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<HttpAuthController> auth_controller, + scoped_refptr<HttpNetworkSession> session, bool tunnel); const scoped_refptr<TCPSocketParams>& tcp_params() const { @@ -39,8 +40,8 @@ class HttpProxySocketParams : public base::RefCounted<HttpProxySocketParams> { } const GURL& request_url() const { return request_url_; } const HostPortPair& endpoint() const { return endpoint_; } - const scoped_refptr<HttpAuthController>& auth_controller() { - return auth_controller_; + const scoped_refptr<HttpNetworkSession>& session() { + return session_; } bool tunnel() const { return tunnel_; } @@ -51,7 +52,7 @@ class HttpProxySocketParams : public base::RefCounted<HttpProxySocketParams> { const scoped_refptr<TCPSocketParams> tcp_params_; const GURL request_url_; const HostPortPair endpoint_; - const scoped_refptr<HttpAuthController> auth_controller_; + const scoped_refptr<HttpNetworkSession> session_; 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 9400dd8..3e06c3b 100644 --- a/net/http/http_proxy_client_socket_pool_unittest.cc +++ b/net/http/http_proxy_client_socket_pool_unittest.cc @@ -6,12 +6,19 @@ #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 { @@ -29,19 +36,34 @@ 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), auth_controller_, true)), + HostPortPair("host", 80), session_, 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_); @@ -52,8 +74,10 @@ 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_; @@ -72,7 +96,7 @@ TEST_F(HttpProxyClientSocketPoolTest, NoTunnel) { EXPECT_TRUE(handle.socket()); HttpProxyClientSocket* tunnel_socket = static_cast<HttpProxyClientSocket*>(handle.socket()); - EXPECT_FALSE(tunnel_socket->NeedsRestartWithAuth()); + EXPECT_TRUE(tunnel_socket->IsConnected()); } TEST_F(HttpProxyClientSocketPoolTest, NeedAuth) { @@ -92,10 +116,6 @@ 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; @@ -110,7 +130,7 @@ TEST_F(HttpProxyClientSocketPoolTest, NeedAuth) { EXPECT_TRUE(handle.socket()); HttpProxyClientSocket* tunnel_socket = static_cast<HttpProxyClientSocket*>(handle.socket()); - EXPECT_TRUE(tunnel_socket->NeedsRestartWithAuth()); + EXPECT_FALSE(tunnel_socket->IsConnected()); } TEST_F(HttpProxyClientSocketPoolTest, HaveAuth) { @@ -119,7 +139,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 Zm9vOmJheg==\r\n\r\n"), + "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), }; MockRead reads[] = { MockRead(false, "HTTP/1.1 200 Connection Established\r\n\r\n"), @@ -129,10 +149,7 @@ TEST_F(HttpProxyClientSocketPoolTest, HaveAuth) { data.set_connect_data(MockConnect(false, 0)); tcp_client_socket_factory_.AddSocketDataProvider(&data); - MockHttpAuthControllerData auth_data[] = { - MockHttpAuthControllerData("Proxy-Authorization: Basic Zm9vOmJheg=="), - }; - auth_controller_->SetMockAuthControllerData(auth_data, arraysize(auth_data)); + AddAuthToCache(); ClientSocketHandle handle; TestCompletionCallback callback; @@ -143,7 +160,7 @@ TEST_F(HttpProxyClientSocketPoolTest, HaveAuth) { EXPECT_TRUE(handle.socket()); HttpProxyClientSocket* tunnel_socket = static_cast<HttpProxyClientSocket*>(handle.socket()); - EXPECT_FALSE(tunnel_socket->NeedsRestartWithAuth()); + EXPECT_TRUE(tunnel_socket->IsConnected()); } TEST_F(HttpProxyClientSocketPoolTest, AsyncHaveAuth) { @@ -151,7 +168,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 Zm9vOmJheg==\r\n\r\n"), + "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), }; MockRead reads[] = { MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), @@ -160,10 +177,7 @@ TEST_F(HttpProxyClientSocketPoolTest, AsyncHaveAuth) { arraysize(writes)); tcp_client_socket_factory_.AddSocketDataProvider(&data); - MockHttpAuthControllerData auth_data[] = { - MockHttpAuthControllerData("Proxy-Authorization: Basic Zm9vOmJheg=="), - }; - auth_controller_->SetMockAuthControllerData(auth_data, arraysize(auth_data)); + AddAuthToCache(); ClientSocketHandle handle; TestCompletionCallback callback; @@ -178,7 +192,7 @@ TEST_F(HttpProxyClientSocketPoolTest, AsyncHaveAuth) { EXPECT_TRUE(handle.socket()); HttpProxyClientSocket* tunnel_socket = static_cast<HttpProxyClientSocket*>(handle.socket()); - EXPECT_FALSE(tunnel_socket->NeedsRestartWithAuth()); + EXPECT_TRUE(tunnel_socket->IsConnected()); } TEST_F(HttpProxyClientSocketPoolTest, TCPError) { @@ -205,7 +219,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 Zm9vOmJheg==\r\n\r\n"), + "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), }; MockRead reads[] = { MockRead("HTTP/1.1 200 Conn"), @@ -215,10 +229,7 @@ TEST_F(HttpProxyClientSocketPoolTest, TunnelUnexpectedClose) { arraysize(writes)); tcp_client_socket_factory_.AddSocketDataProvider(&data); - MockHttpAuthControllerData auth_data[] = { - MockHttpAuthControllerData("Proxy-Authorization: Basic Zm9vOmJheg=="), - }; - auth_controller_->SetMockAuthControllerData(auth_data, arraysize(auth_data)); + AddAuthToCache(); ClientSocketHandle handle; TestCompletionCallback callback; @@ -238,7 +249,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 Zm9vOmJheg==\r\n\r\n"), + "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), }; MockRead reads[] = { MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"), @@ -247,10 +258,7 @@ TEST_F(HttpProxyClientSocketPoolTest, TunnelSetupError) { arraysize(writes)); tcp_client_socket_factory_.AddSocketDataProvider(&data); - MockHttpAuthControllerData auth_data[] = { - MockHttpAuthControllerData("Proxy-Authorization: Basic Zm9vOmJheg=="), - }; - auth_controller_->SetMockAuthControllerData(auth_data, arraysize(auth_data)); + AddAuthToCache(); ClientSocketHandle handle; TestCompletionCallback callback; diff --git a/net/socket/client_socket_handle.cc b/net/socket/client_socket_handle.cc index de2fd94..d9ccbd5 100644 --- a/net/socket/client_socket_handle.cc +++ b/net/socket/client_socket_handle.cc @@ -59,6 +59,7 @@ 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 a25bfdb..adccc89 100644 --- a/net/socket/client_socket_handle.h +++ b/net/socket/client_socket_handle.h @@ -109,6 +109,9 @@ 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 { @@ -121,6 +124,9 @@ 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_; } @@ -179,6 +185,7 @@ 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 d4d74a7..142a39e 100644 --- a/net/socket/socket_test_util.cc +++ b/net/socket/socket_test_util.cc @@ -187,6 +187,7 @@ int MockTCPClientSocket::Connect(net::CompletionCallback* callback) { if (connected_) return net::OK; connected_ = true; + peer_closed_connection_ = false; if (data_->connect_data().async) { RunCallbackAsync(callback, data_->connect_data().result); return net::ERR_IO_PENDING; @@ -886,53 +887,6 @@ 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 1a0ab11..0ccf878 100644 --- a/net/socket/socket_test_util.h +++ b/net/socket/socket_test_util.h @@ -695,46 +695,6 @@ 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 03e2e80..5ed450e 100644 --- a/net/socket/ssl_client_socket_pool.cc +++ b/net/socket/ssl_client_socket_pool.cc @@ -103,11 +103,6 @@ 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; @@ -123,6 +118,7 @@ void SSLConnectJob::DetermineFirstState() { NOTREACHED() << "unknown proxy type"; break; } + return DoLoop(OK); } void SSLConnectJob::OnIOComplete(int result) { @@ -214,6 +210,7 @@ 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(); @@ -228,12 +225,6 @@ 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. @@ -243,20 +234,17 @@ int SSLConnectJob::DoTunnelConnectComplete(int result) { if (result < 0) return result; - 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_); - } - + DCHECK(tunnel_socket->IsConnected()); next_state_ = STATE_SSL_CONNECT; return result; } void SSLConnectJob::GetAdditionalErrorState(ClientSocketHandle * handle) { - handle->set_ssl_error_response_info(error_response_info_); + if (error_response_info_.headers) { + handle->set_ssl_error_response_info(error_response_info_); + handle->set_pending_http_proxy_connection( + transport_socket_handle_.release()); + } 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 b44985f..9857c61 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,8 +114,6 @@ 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 efc4795..047a647 100644 --- a/net/socket/ssl_client_socket_pool_unittest.cc +++ b/net/socket/ssl_client_socket_pool_unittest.cc @@ -6,13 +6,14 @@ #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_controller.h" +#include "net/http/http_auth_handler_factory.h" #include "net/http/http_network_session.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_headers.h" @@ -20,6 +21,7 @@ #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 { @@ -32,7 +34,16 @@ const int kMaxSocketsPerGroup = 6; class SSLClientSocketPoolTest : public ClientSocketPoolTest { protected: SSLClientSocketPoolTest() - : direct_tcp_socket_params_(new TCPSocketParams( + : 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( HostPortPair("host", 443), MEDIUM, GURL(), false)), tcp_socket_pool_(new MockTCPClientSocketPool( kMaxSockets, @@ -41,6 +52,9 @@ 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, @@ -74,33 +88,30 @@ class SSLClientSocketPoolTest : public ClientSocketPoolTest { NULL); } - 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); - } - + scoped_refptr<SSLSocketParams> SSLParams(ProxyServer::Scheme proxy, + bool want_spdy_over_npn) { return make_scoped_refptr(new SSLSocketParams( proxy == ProxyServer::SCHEME_DIRECT ? direct_tcp_socket_params_ : NULL, - http_proxy_params, + proxy == ProxyServer::SCHEME_HTTP ? http_proxy_socket_params_ : NULL, proxy == ProxyServer::SCHEME_SOCKS5 ? socks_socket_params_ : NULL, proxy, "host", ssl_config_, 0, - want_spdy_over_ssl, + false, 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_; @@ -123,7 +134,7 @@ TEST_F(SSLClientSocketPoolTest, TCPFail) { CreatePool(true /* tcp pool */, false, false); scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, - NULL, 0, false, false); + false); ClientSocketHandle handle; int rv = handle.Init("a", params, MEDIUM, NULL, pool_, BoundNetLog()); @@ -140,7 +151,7 @@ TEST_F(SSLClientSocketPoolTest, TCPFailAsync) { CreatePool(true /* tcp pool */, false, false); scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, - NULL, 0, false, false); + false); ClientSocketHandle handle; TestCompletionCallback callback; @@ -164,7 +175,7 @@ TEST_F(SSLClientSocketPoolTest, BasicDirect) { CreatePool(true /* tcp pool */, false, false); scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, - NULL, 0, false, false); + false); ClientSocketHandle handle; TestCompletionCallback callback; @@ -182,7 +193,7 @@ TEST_F(SSLClientSocketPoolTest, BasicDirectAsync) { CreatePool(true /* tcp pool */, false, false); scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, - NULL, 0, false, false); + false); ClientSocketHandle handle; TestCompletionCallback callback; @@ -204,7 +215,7 @@ TEST_F(SSLClientSocketPoolTest, DirectCertError) { CreatePool(true /* tcp pool */, false, false); scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, - NULL, 0, false, false); + false); ClientSocketHandle handle; TestCompletionCallback callback; @@ -226,7 +237,7 @@ TEST_F(SSLClientSocketPoolTest, DirectSSLError) { CreatePool(true /* tcp pool */, false, false); scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, - NULL, 0, false, false); + false); ClientSocketHandle handle; TestCompletionCallback callback; @@ -251,7 +262,7 @@ TEST_F(SSLClientSocketPoolTest, DirectWithNPN) { CreatePool(true /* tcp pool */, false, false); scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, - NULL, 0, false, false); + false); ClientSocketHandle handle; TestCompletionCallback callback; @@ -277,7 +288,7 @@ TEST_F(SSLClientSocketPoolTest, DirectNoSPDY) { CreatePool(true /* tcp pool */, false, false); scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, - NULL, 0, false, true); + true); ClientSocketHandle handle; TestCompletionCallback callback; @@ -302,7 +313,7 @@ TEST_F(SSLClientSocketPoolTest, DirectGotSPDY) { CreatePool(true /* tcp pool */, false, false); scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, - NULL, 0, false, true); + true); ClientSocketHandle handle; TestCompletionCallback callback; @@ -333,7 +344,7 @@ TEST_F(SSLClientSocketPoolTest, DirectGotBonusSPDY) { CreatePool(true /* tcp pool */, false, false); scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, - NULL, 0, false, true); + true); ClientSocketHandle handle; TestCompletionCallback callback; @@ -361,7 +372,7 @@ TEST_F(SSLClientSocketPoolTest, SOCKSFail) { CreatePool(false, true /* http proxy pool */, true /* socks pool */); scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_SOCKS5, - NULL, 0, false, false); + false); ClientSocketHandle handle; TestCompletionCallback callback; @@ -379,7 +390,7 @@ TEST_F(SSLClientSocketPoolTest, SOCKSFailAsync) { CreatePool(false, true /* http proxy pool */, true /* socks pool */); scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_SOCKS5, - NULL, 0, false, false); + false); ClientSocketHandle handle; TestCompletionCallback callback; @@ -403,7 +414,7 @@ TEST_F(SSLClientSocketPoolTest, SOCKSBasic) { CreatePool(false, true /* http proxy pool */, true /* socks pool */); scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_SOCKS5, - NULL, 0, false, false); + false); ClientSocketHandle handle; TestCompletionCallback callback; @@ -421,7 +432,7 @@ TEST_F(SSLClientSocketPoolTest, SOCKSBasicAsync) { CreatePool(false, true /* http proxy pool */, true /* socks pool */); scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_SOCKS5, - NULL, 0, false, false); + false); ClientSocketHandle handle; TestCompletionCallback callback; @@ -442,7 +453,7 @@ TEST_F(SSLClientSocketPoolTest, HttpProxyFail) { CreatePool(false, true /* http proxy pool */, true /* socks pool */); scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_HTTP, - NULL, 0, false, false); + false); ClientSocketHandle handle; TestCompletionCallback callback; @@ -460,7 +471,7 @@ TEST_F(SSLClientSocketPoolTest, HttpProxyFailAsync) { CreatePool(false, true /* http proxy pool */, true /* socks pool */); scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_HTTP, - NULL, 0, false, false); + false); ClientSocketHandle handle; TestCompletionCallback callback; @@ -481,7 +492,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 Zm9vOmJheg==\r\n\r\n"), + "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), }; MockRead reads[] = { MockRead(false, "HTTP/1.1 200 Connection Established\r\n\r\n"), @@ -490,17 +501,12 @@ TEST_F(SSLClientSocketPoolTest, HttpProxyBasic) { arraysize(writes)); data.set_connect_data(MockConnect(false, OK)); socket_factory_.AddSocketDataProvider(&data); - MockHttpAuthControllerData auth_data[] = { - MockHttpAuthControllerData("Proxy-Authorization: Basic Zm9vOmJheg=="), - }; + AddAuthToCache(); 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; @@ -516,7 +522,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 Zm9vOmJheg==\r\n\r\n"), + "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), }; MockRead reads[] = { MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), @@ -524,17 +530,12 @@ TEST_F(SSLClientSocketPoolTest, HttpProxyBasicAsync) { StaticSocketDataProvider data(reads, arraysize(reads), writes, arraysize(writes)); socket_factory_.AddSocketDataProvider(&data); - MockHttpAuthControllerData auth_data[] = { - MockHttpAuthControllerData("Proxy-Authorization: Basic Zm9vOmJheg=="), - }; + AddAuthToCache(); 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; @@ -564,135 +565,11 @@ 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; @@ -708,17 +585,10 @@ TEST_F(SSLClientSocketPoolTest, DoProxyAuthNoKeepAlive) { 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()); - - EXPECT_EQ(OK, callback.WaitForResult()); - EXPECT_TRUE(handle.is_initialized()); - EXPECT_TRUE(handle.socket()); + scoped_ptr<ClientSocketHandle> tunnel_handle( + handle.release_pending_http_proxy_connection()); + EXPECT_TRUE(tunnel_handle->socket()); + EXPECT_FALSE(tunnel_handle->socket()->IsConnected()); } // It would be nice to also test the timeouts in SSLClientSocketPool. |