Chromium Code Reviews| Index: net/http/http_network_transaction.cc |
| diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc |
| index 5cc3895cfc4755d372ea82b84febab410f0c1f9f..c9036dd5ae997ad59fd7bdba2f75fb3392f96053 100644 |
| --- a/net/http/http_network_transaction.cc |
| +++ b/net/http/http_network_transaction.cc |
| @@ -332,7 +332,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); |
| @@ -533,6 +534,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(); |
| @@ -716,15 +724,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_1; |
| using_ssl_ = request_->url.SchemeIs("https") || |
| @@ -773,15 +772,10 @@ int HttpNetworkTransaction::DoInitConnection() { |
| request_->referrer, disable_resolver_cache); |
| if (proxy_info_.is_http()) { |
| - scoped_refptr<HttpAuthController> http_proxy_auth; |
| - if (using_ssl_) { |
| - http_proxy_auth = auth_controllers_[HttpAuth::AUTH_PROXY]; |
| - establishing_tunnel_ = true; |
| - } |
| + establishing_tunnel_ = using_ssl_; |
| http_proxy_params = new HttpProxySocketParams(proxy_tcp_params, |
| request_->url, endpoint_, |
| - http_proxy_auth, |
| - using_ssl_); |
| + session_, using_ssl_); |
| } else { |
| DCHECK(proxy_info_.is_socks()); |
| char socks_version; |
| @@ -889,14 +883,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 |
|
eroman
2010/07/30 22:11:11
This seems like an unmatched parenthesis.
|
| + // 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 && |
| @@ -976,12 +969,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) { |
| @@ -993,10 +1018,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) { |
| @@ -1516,6 +1546,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)); |