| Index: net/http/http_network_transaction.cc
 | 
| diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
 | 
| index c12f95dfa6764397b7e7900121e191f017dda604..7644df733ab5f938b5abfb27a003b0e402733af4 100644
 | 
| --- a/net/http/http_network_transaction.cc
 | 
| +++ b/net/http/http_network_transaction.cc
 | 
| @@ -709,6 +709,12 @@ int HttpNetworkTransaction::DoLoop(int result) {
 | 
|          net_log_.EndEventWithNetErrorCode(
 | 
|              NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, rv);
 | 
|          break;
 | 
| +      case STATE_HANDLE_AUTH_CHALLENGE:
 | 
| +        rv = DoHandleAuthChallenge();
 | 
| +        break;
 | 
| +      case STATE_HANDLE_AUTH_CHALLENGE_COMPLETE:
 | 
| +        rv = DoHandleAuthChallengeComplete(rv);
 | 
| +        break;
 | 
|        case STATE_READ_BODY:
 | 
|          DCHECK_EQ(OK, rv);
 | 
|          net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_BODY);
 | 
| @@ -1102,17 +1108,72 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
 | 
|    ProcessAlternativeServices(session_, *response_.headers.get(),
 | 
|                               HostPortPair::FromURL(request_->url));
 | 
|  
 | 
| -  int rv = HandleAuthChallenge();
 | 
| -  if (rv != OK)
 | 
| -    return rv;
 | 
| -
 | 
|    if (IsSecureRequest())
 | 
|      stream_->GetSSLInfo(&response_.ssl_info);
 | 
|  
 | 
| -  headers_valid_ = true;
 | 
| +  next_state_ = STATE_HANDLE_AUTH_CHALLENGE;
 | 
|    return OK;
 | 
|  }
 | 
|  
 | 
| +int HttpNetworkTransaction::DoHandleAuthChallenge() {
 | 
| +  const HttpResponseHeaders* headers = GetResponseHeaders();
 | 
| +  DCHECK(headers);
 | 
| +  // Note that the server or a proxy can send an authentication header with a
 | 
| +  // response that doesn't have a 401 or 407 status code. This method is
 | 
| +  // typically used to send the final authentication token for a multi-round
 | 
| +  // authentication handshake where no further responses are necessary from the
 | 
| +  // client.
 | 
| +  // TODO(asanka): The logic below doesn't handle authentication headers if the
 | 
| +  // status code isn't 401 or 407. Fix it.
 | 
| +
 | 
| +  int status = headers->response_code();
 | 
| +  if (status != HTTP_UNAUTHORIZED &&
 | 
| +      status != HTTP_PROXY_AUTHENTICATION_REQUIRED)
 | 
| +    return OK;
 | 
| +  HttpAuth::Target target = status == HTTP_PROXY_AUTHENTICATION_REQUIRED
 | 
| +                                ? HttpAuth::AUTH_PROXY
 | 
| +                                : HttpAuth::AUTH_SERVER;
 | 
| +  if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct())
 | 
| +    return ERR_UNEXPECTED_PROXY_AUTH;
 | 
| +
 | 
| +  // This case can trigger when an HTTPS server responds with a "Proxy
 | 
| +  // authentication required" status code through a non-authenticating
 | 
| +  // proxy.
 | 
| +  if (!auth_controllers_[target].get())
 | 
| +    return ERR_UNEXPECTED_PROXY_AUTH;
 | 
| +
 | 
| +  if (target == HttpAuth::AUTH_SERVER && !ShouldApplyServerAuth())
 | 
| +    return OK;
 | 
| +
 | 
| +  net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_HANDLE_AUTH_CHALLENGE);
 | 
| +  pending_auth_target_ = target;
 | 
| +  next_state_ = STATE_HANDLE_AUTH_CHALLENGE_COMPLETE;
 | 
| +  return auth_controllers_[target]->HandleAuthChallenge(response_, io_callback_,
 | 
| +                                                        net_log_);
 | 
| +}
 | 
| +
 | 
| +int HttpNetworkTransaction::DoHandleAuthChallengeComplete(int result) {
 | 
| +  DCHECK(pending_auth_target_ == HttpAuth::AUTH_PROXY ||
 | 
| +         pending_auth_target_ == HttpAuth::AUTH_SERVER);
 | 
| +  net_log_.EndEventWithNetErrorCode(
 | 
| +      NetLog::TYPE_HTTP_TRANSACTION_HANDLE_AUTH_CHALLENGE, result);
 | 
| +  if (result == OK)
 | 
| +    headers_valid_ = true;
 | 
| +  // If there's no AuthHandler, then we won't be able to generate an
 | 
| +  // authentication token next time around regardless of whether the caller
 | 
| +  // provides credentials via ResetAuth().
 | 
| +  if (!auth_controllers_[pending_auth_target_]->HaveAuthHandler()) {
 | 
| +    pending_auth_target_ = HttpAuth::AUTH_NONE;
 | 
| +    return result;
 | 
| +  }
 | 
| +  scoped_refptr<AuthChallengeInfo> auth_info =
 | 
| +      auth_controllers_[pending_auth_target_]->auth_info();
 | 
| +  if (auth_info.get())
 | 
| +    response_.auth_challenge = auth_info;
 | 
| +
 | 
| +  return result;
 | 
| +}
 | 
| +
 | 
|  int HttpNetworkTransaction::DoReadBody() {
 | 
|    DCHECK(read_buf_.get());
 | 
|    DCHECK_GT(read_buf_len_, 0);
 | 
| @@ -1562,39 +1623,6 @@ bool HttpNetworkTransaction::ShouldApplyServerAuth() const {
 | 
|    return !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA);
 | 
|  }
 | 
|  
 | 
| -int HttpNetworkTransaction::HandleAuthChallenge() {
 | 
| -  scoped_refptr<HttpResponseHeaders> headers(GetResponseHeaders());
 | 
| -  DCHECK(headers.get());
 | 
| -
 | 
| -  int status = headers->response_code();
 | 
| -  if (status != HTTP_UNAUTHORIZED &&
 | 
| -      status != HTTP_PROXY_AUTHENTICATION_REQUIRED)
 | 
| -    return OK;
 | 
| -  HttpAuth::Target target = status == HTTP_PROXY_AUTHENTICATION_REQUIRED ?
 | 
| -                            HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER;
 | 
| -  if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct())
 | 
| -    return ERR_UNEXPECTED_PROXY_AUTH;
 | 
| -
 | 
| -  // This case can trigger when an HTTPS server responds with a "Proxy
 | 
| -  // authentication required" status code through a non-authenticating
 | 
| -  // proxy.
 | 
| -  if (!auth_controllers_[target].get())
 | 
| -    return ERR_UNEXPECTED_PROXY_AUTH;
 | 
| -
 | 
| -  int rv = auth_controllers_[target]->HandleAuthChallenge(
 | 
| -      headers, (request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA) != 0, false,
 | 
| -      net_log_);
 | 
| -  if (auth_controllers_[target]->HaveAuthHandler())
 | 
| -      pending_auth_target_ = target;
 | 
| -
 | 
| -  scoped_refptr<AuthChallengeInfo> auth_info =
 | 
| -      auth_controllers_[target]->auth_info();
 | 
| -  if (auth_info.get())
 | 
| -      response_.auth_challenge = auth_info;
 | 
| -
 | 
| -  return rv;
 | 
| -}
 | 
| -
 | 
|  bool HttpNetworkTransaction::HaveAuth(HttpAuth::Target target) const {
 | 
|    return auth_controllers_[target].get() &&
 | 
|        auth_controllers_[target]->HaveAuth();
 | 
| 
 |