| Index: net/http/http_network_transaction.cc
|
| diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
|
| index 09a4772f8b5304f85d0f8a59e85a8d992669fae1..6d77eb1532a7c75f1aaebea486d270d0ea155f14 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));
|
|
|