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(); |