| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/http/http_network_transaction.h" | 5 #include "net/http/http_network_transaction.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 } else { | 150 } else { |
| 151 if (stream_->IsResponseBodyComplete()) { | 151 if (stream_->IsResponseBodyComplete()) { |
| 152 // If the response body is complete, we can just reuse the socket. | 152 // If the response body is complete, we can just reuse the socket. |
| 153 stream_->Close(false /* reusable */); | 153 stream_->Close(false /* reusable */); |
| 154 } else if (stream_->IsSpdyHttpStream()) { | 154 } else if (stream_->IsSpdyHttpStream()) { |
| 155 // Doesn't really matter for SpdyHttpStream. Just close it. | 155 // Doesn't really matter for SpdyHttpStream. Just close it. |
| 156 stream_->Close(true /* not reusable */); | 156 stream_->Close(true /* not reusable */); |
| 157 } else { | 157 } else { |
| 158 // Otherwise, we try to drain the response body. | 158 // Otherwise, we try to drain the response body. |
| 159 HttpStreamBase* stream = stream_.release(); | 159 HttpStreamBase* stream = stream_.release(); |
| 160 stream->Drain(session_); | 160 stream->Drain(session_.get()); |
| 161 } | 161 } |
| 162 } | 162 } |
| 163 } | 163 } |
| 164 } | 164 } |
| 165 | 165 |
| 166 int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info, | 166 int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info, |
| 167 const CompletionCallback& callback, | 167 const CompletionCallback& callback, |
| 168 const BoundNetLog& net_log) { | 168 const BoundNetLog& net_log) { |
| 169 SIMPLE_STATS_COUNTER("HttpNetworkTransaction.Count"); | 169 SIMPLE_STATS_COUNTER("HttpNetworkTransaction.Count"); |
| 170 | 170 |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 read_buf_len_ = buf_len; | 355 read_buf_len_ = buf_len; |
| 356 | 356 |
| 357 next_state_ = next_state; | 357 next_state_ = next_state; |
| 358 int rv = DoLoop(OK); | 358 int rv = DoLoop(OK); |
| 359 if (rv == ERR_IO_PENDING) | 359 if (rv == ERR_IO_PENDING) |
| 360 callback_ = callback; | 360 callback_ = callback; |
| 361 return rv; | 361 return rv; |
| 362 } | 362 } |
| 363 | 363 |
| 364 const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const { | 364 const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const { |
| 365 return ((headers_valid_ && response_.headers) || response_.ssl_info.cert || | 365 return ((headers_valid_ && response_.headers.get()) || |
| 366 response_.cert_request_info) ? &response_ : NULL; | 366 response_.ssl_info.cert.get() || response_.cert_request_info.get()) |
| 367 ? &response_ |
| 368 : NULL; |
| 367 } | 369 } |
| 368 | 370 |
| 369 LoadState HttpNetworkTransaction::GetLoadState() const { | 371 LoadState HttpNetworkTransaction::GetLoadState() const { |
| 370 // TODO(wtc): Define a new LoadState value for the | 372 // TODO(wtc): Define a new LoadState value for the |
| 371 // STATE_INIT_CONNECTION_COMPLETE state, which delays the HTTP request. | 373 // STATE_INIT_CONNECTION_COMPLETE state, which delays the HTTP request. |
| 372 switch (next_state_) { | 374 switch (next_state_) { |
| 373 case STATE_CREATE_STREAM_COMPLETE: | 375 case STATE_CREATE_STREAM_COMPLETE: |
| 374 return stream_request_->GetLoadState(); | 376 return stream_request_->GetLoadState(); |
| 375 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE: | 377 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE: |
| 376 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE: | 378 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE: |
| (...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 834 next_state_ = STATE_READ_HEADERS; | 836 next_state_ = STATE_READ_HEADERS; |
| 835 return OK; | 837 return OK; |
| 836 } | 838 } |
| 837 | 839 |
| 838 int HttpNetworkTransaction::DoReadHeaders() { | 840 int HttpNetworkTransaction::DoReadHeaders() { |
| 839 next_state_ = STATE_READ_HEADERS_COMPLETE; | 841 next_state_ = STATE_READ_HEADERS_COMPLETE; |
| 840 return stream_->ReadResponseHeaders(io_callback_); | 842 return stream_->ReadResponseHeaders(io_callback_); |
| 841 } | 843 } |
| 842 | 844 |
| 843 int HttpNetworkTransaction::HandleConnectionClosedBeforeEndOfHeaders() { | 845 int HttpNetworkTransaction::HandleConnectionClosedBeforeEndOfHeaders() { |
| 844 if (!response_.headers && !stream_->IsConnectionReused()) { | 846 if (!response_.headers.get() && !stream_->IsConnectionReused()) { |
| 845 // The connection was closed before any data was sent. Likely an error | 847 // The connection was closed before any data was sent. Likely an error |
| 846 // rather than empty HTTP/0.9 response. | 848 // rather than empty HTTP/0.9 response. |
| 847 return ERR_EMPTY_RESPONSE; | 849 return ERR_EMPTY_RESPONSE; |
| 848 } | 850 } |
| 849 | 851 |
| 850 return OK; | 852 return OK; |
| 851 } | 853 } |
| 852 | 854 |
| 853 int HttpNetworkTransaction::DoReadHeadersComplete(int result) { | 855 int HttpNetworkTransaction::DoReadHeadersComplete(int result) { |
| 854 // We can get a certificate error or ERR_SSL_CLIENT_AUTH_CERT_NEEDED here | 856 // We can get a certificate error or ERR_SSL_CLIENT_AUTH_CERT_NEEDED here |
| 855 // due to SSL renegotiation. | 857 // due to SSL renegotiation. |
| 856 if (IsCertificateError(result)) { | 858 if (IsCertificateError(result)) { |
| 857 // We don't handle a certificate error during SSL renegotiation, so we | 859 // We don't handle a certificate error during SSL renegotiation, so we |
| 858 // have to return an error that's not in the certificate error range | 860 // have to return an error that's not in the certificate error range |
| 859 // (-2xx). | 861 // (-2xx). |
| 860 LOG(ERROR) << "Got a server certificate with error " << result | 862 LOG(ERROR) << "Got a server certificate with error " << result |
| 861 << " during SSL renegotiation"; | 863 << " during SSL renegotiation"; |
| 862 result = ERR_CERT_ERROR_IN_SSL_RENEGOTIATION; | 864 result = ERR_CERT_ERROR_IN_SSL_RENEGOTIATION; |
| 863 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { | 865 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { |
| 864 // TODO(wtc): Need a test case for this code path! | 866 // TODO(wtc): Need a test case for this code path! |
| 865 DCHECK(stream_.get()); | 867 DCHECK(stream_.get()); |
| 866 DCHECK(is_https_request()); | 868 DCHECK(is_https_request()); |
| 867 response_.cert_request_info = new SSLCertRequestInfo; | 869 response_.cert_request_info = new SSLCertRequestInfo; |
| 868 stream_->GetSSLCertRequestInfo(response_.cert_request_info); | 870 stream_->GetSSLCertRequestInfo(response_.cert_request_info.get()); |
| 869 result = HandleCertificateRequest(result); | 871 result = HandleCertificateRequest(result); |
| 870 if (result == OK) | 872 if (result == OK) |
| 871 return result; | 873 return result; |
| 872 } | 874 } |
| 873 | 875 |
| 874 if (result < 0 && result != ERR_CONNECTION_CLOSED) | 876 if (result < 0 && result != ERR_CONNECTION_CLOSED) |
| 875 return HandleIOError(result); | 877 return HandleIOError(result); |
| 876 | 878 |
| 877 if (result == ERR_CONNECTION_CLOSED && ShouldResendRequest(result)) { | 879 if (result == ERR_CONNECTION_CLOSED && ShouldResendRequest(result)) { |
| 878 ResetConnectionAndRequestForResend(); | 880 ResetConnectionAndRequestForResend(); |
| 879 return OK; | 881 return OK; |
| 880 } | 882 } |
| 881 | 883 |
| 882 // After we call RestartWithAuth a new response_time will be recorded, and | 884 // After we call RestartWithAuth a new response_time will be recorded, and |
| 883 // we need to be cautious about incorrectly logging the duration across the | 885 // we need to be cautious about incorrectly logging the duration across the |
| 884 // authentication activity. | 886 // authentication activity. |
| 885 if (result == OK) | 887 if (result == OK) |
| 886 LogTransactionConnectedMetrics(); | 888 LogTransactionConnectedMetrics(); |
| 887 | 889 |
| 888 if (result == ERR_CONNECTION_CLOSED) { | 890 if (result == ERR_CONNECTION_CLOSED) { |
| 889 // For now, if we get at least some data, we do the best we can to make | 891 // For now, if we get at least some data, we do the best we can to make |
| 890 // sense of it and send it back up the stack. | 892 // sense of it and send it back up the stack. |
| 891 int rv = HandleConnectionClosedBeforeEndOfHeaders(); | 893 int rv = HandleConnectionClosedBeforeEndOfHeaders(); |
| 892 if (rv != OK) | 894 if (rv != OK) |
| 893 return rv; | 895 return rv; |
| 894 } | 896 } |
| 895 DCHECK(response_.headers); | 897 DCHECK(response_.headers.get()); |
| 896 | 898 |
| 897 // Server-induced fallback is supported only if this is a PAC configured | 899 // Server-induced fallback is supported only if this is a PAC configured |
| 898 // proxy. See: http://crbug.com/143712 | 900 // proxy. See: http://crbug.com/143712 |
| 899 if (response_.was_fetched_via_proxy && proxy_info_.did_use_pac_script() && | 901 if (response_.was_fetched_via_proxy && proxy_info_.did_use_pac_script() && |
| 900 response_.headers != NULL) { | 902 response_.headers.get() != NULL) { |
| 901 bool should_fallback = | 903 bool should_fallback = |
| 902 response_.headers->HasHeaderValue("connection", "proxy-bypass"); | 904 response_.headers->HasHeaderValue("connection", "proxy-bypass"); |
| 903 // Additionally, fallback if a 500 is returned via the data reduction proxy. | 905 // Additionally, fallback if a 500 is returned via the data reduction proxy. |
| 904 // This is conservative, as the 500 might have been generated by the origin, | 906 // This is conservative, as the 500 might have been generated by the origin, |
| 905 // and not the proxy. | 907 // and not the proxy. |
| 906 #if defined(SPDY_PROXY_AUTH_ORIGIN) | 908 #if defined(SPDY_PROXY_AUTH_ORIGIN) |
| 907 if (!should_fallback) { | 909 if (!should_fallback) { |
| 908 should_fallback = | 910 should_fallback = |
| 909 response_.headers->response_code() == HTTP_INTERNAL_SERVER_ERROR && | 911 response_.headers->response_code() == HTTP_INTERNAL_SERVER_ERROR && |
| 910 proxy_info_.proxy_server().host_port_pair().Equals( | 912 proxy_info_.proxy_server().host_port_pair().Equals( |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 951 if (response_.headers->response_code() / 100 == 1) { | 953 if (response_.headers->response_code() / 100 == 1) { |
| 952 response_.headers = new HttpResponseHeaders(std::string()); | 954 response_.headers = new HttpResponseHeaders(std::string()); |
| 953 next_state_ = STATE_READ_HEADERS; | 955 next_state_ = STATE_READ_HEADERS; |
| 954 return OK; | 956 return OK; |
| 955 } | 957 } |
| 956 | 958 |
| 957 HostPortPair endpoint = HostPortPair(request_->url.HostNoBrackets(), | 959 HostPortPair endpoint = HostPortPair(request_->url.HostNoBrackets(), |
| 958 request_->url.EffectiveIntPort()); | 960 request_->url.EffectiveIntPort()); |
| 959 ProcessAlternateProtocol(session_->http_stream_factory(), | 961 ProcessAlternateProtocol(session_->http_stream_factory(), |
| 960 session_->http_server_properties(), | 962 session_->http_server_properties(), |
| 961 *response_.headers, | 963 *response_.headers.get(), |
| 962 endpoint); | 964 endpoint); |
| 963 | 965 |
| 964 int rv = HandleAuthChallenge(); | 966 int rv = HandleAuthChallenge(); |
| 965 if (rv != OK) | 967 if (rv != OK) |
| 966 return rv; | 968 return rv; |
| 967 | 969 |
| 968 if (is_https_request()) | 970 if (is_https_request()) |
| 969 stream_->GetSSLInfo(&response_.ssl_info); | 971 stream_->GetSSLInfo(&response_.ssl_info); |
| 970 | 972 |
| 971 headers_valid_ = true; | 973 headers_valid_ = true; |
| 972 return OK; | 974 return OK; |
| 973 } | 975 } |
| 974 | 976 |
| 975 int HttpNetworkTransaction::DoReadBody() { | 977 int HttpNetworkTransaction::DoReadBody() { |
| 976 DCHECK(read_buf_); | 978 DCHECK(read_buf_.get()); |
| 977 DCHECK_GT(read_buf_len_, 0); | 979 DCHECK_GT(read_buf_len_, 0); |
| 978 DCHECK(stream_ != NULL); | 980 DCHECK(stream_ != NULL); |
| 979 | 981 |
| 980 next_state_ = STATE_READ_BODY_COMPLETE; | 982 next_state_ = STATE_READ_BODY_COMPLETE; |
| 981 return stream_->ReadResponseBody(read_buf_, read_buf_len_, io_callback_); | 983 return stream_->ReadResponseBody( |
| 984 read_buf_.get(), read_buf_len_, io_callback_); |
| 982 } | 985 } |
| 983 | 986 |
| 984 int HttpNetworkTransaction::DoReadBodyComplete(int result) { | 987 int HttpNetworkTransaction::DoReadBodyComplete(int result) { |
| 985 // We are done with the Read call. | 988 // We are done with the Read call. |
| 986 bool done = false; | 989 bool done = false; |
| 987 if (result <= 0) { | 990 if (result <= 0) { |
| 988 DCHECK_NE(ERR_IO_PENDING, result); | 991 DCHECK_NE(ERR_IO_PENDING, result); |
| 989 done = true; | 992 done = true; |
| 990 } | 993 } |
| 991 | 994 |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1157 // automatically. | 1160 // automatically. |
| 1158 scoped_refptr<X509Certificate> client_cert; | 1161 scoped_refptr<X509Certificate> client_cert; |
| 1159 bool found_cached_cert = session_->ssl_client_auth_cache()->Lookup( | 1162 bool found_cached_cert = session_->ssl_client_auth_cache()->Lookup( |
| 1160 response_.cert_request_info->host_and_port, &client_cert); | 1163 response_.cert_request_info->host_and_port, &client_cert); |
| 1161 if (!found_cached_cert) | 1164 if (!found_cached_cert) |
| 1162 return error; | 1165 return error; |
| 1163 | 1166 |
| 1164 // Check that the certificate selected is still a certificate the server | 1167 // Check that the certificate selected is still a certificate the server |
| 1165 // is likely to accept, based on the criteria supplied in the | 1168 // is likely to accept, based on the criteria supplied in the |
| 1166 // CertificateRequest message. | 1169 // CertificateRequest message. |
| 1167 if (client_cert) { | 1170 if (client_cert.get()) { |
| 1168 const std::vector<std::string>& cert_authorities = | 1171 const std::vector<std::string>& cert_authorities = |
| 1169 response_.cert_request_info->cert_authorities; | 1172 response_.cert_request_info->cert_authorities; |
| 1170 | 1173 |
| 1171 bool cert_still_valid = cert_authorities.empty() || | 1174 bool cert_still_valid = cert_authorities.empty() || |
| 1172 client_cert->IsIssuedByEncoded(cert_authorities); | 1175 client_cert->IsIssuedByEncoded(cert_authorities); |
| 1173 if (!cert_still_valid) | 1176 if (!cert_still_valid) |
| 1174 return error; | 1177 return error; |
| 1175 } | 1178 } |
| 1176 | 1179 |
| 1177 // TODO(davidben): Add a unit test which covers this path; we need to be | 1180 // TODO(davidben): Add a unit test which covers this path; we need to be |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1315 pending_auth_target_ = HttpAuth::AUTH_NONE; | 1318 pending_auth_target_ = HttpAuth::AUTH_NONE; |
| 1316 read_buf_ = NULL; | 1319 read_buf_ = NULL; |
| 1317 read_buf_len_ = 0; | 1320 read_buf_len_ = 0; |
| 1318 headers_valid_ = false; | 1321 headers_valid_ = false; |
| 1319 request_headers_.Clear(); | 1322 request_headers_.Clear(); |
| 1320 response_ = HttpResponseInfo(); | 1323 response_ = HttpResponseInfo(); |
| 1321 establishing_tunnel_ = false; | 1324 establishing_tunnel_ = false; |
| 1322 } | 1325 } |
| 1323 | 1326 |
| 1324 HttpResponseHeaders* HttpNetworkTransaction::GetResponseHeaders() const { | 1327 HttpResponseHeaders* HttpNetworkTransaction::GetResponseHeaders() const { |
| 1325 return response_.headers; | 1328 return response_.headers.get(); |
| 1326 } | 1329 } |
| 1327 | 1330 |
| 1328 bool HttpNetworkTransaction::ShouldResendRequest(int error) const { | 1331 bool HttpNetworkTransaction::ShouldResendRequest(int error) const { |
| 1329 bool connection_is_proven = stream_->IsConnectionReused(); | 1332 bool connection_is_proven = stream_->IsConnectionReused(); |
| 1330 bool has_received_headers = GetResponseHeaders() != NULL; | 1333 bool has_received_headers = GetResponseHeaders() != NULL; |
| 1331 | 1334 |
| 1332 // NOTE: we resend a request only if we reused a keep-alive connection. | 1335 // NOTE: we resend a request only if we reused a keep-alive connection. |
| 1333 // This automatically prevents an infinite resend loop because we'll run | 1336 // This automatically prevents an infinite resend loop because we'll run |
| 1334 // out of the cached keep-alive connections eventually. | 1337 // out of the cached keep-alive connections eventually. |
| 1335 if (connection_is_proven && !has_received_headers) | 1338 if (connection_is_proven && !has_received_headers) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1354 return !is_https_request() && | 1357 return !is_https_request() && |
| 1355 (proxy_info_.is_https() || proxy_info_.is_http()); | 1358 (proxy_info_.is_https() || proxy_info_.is_http()); |
| 1356 } | 1359 } |
| 1357 | 1360 |
| 1358 bool HttpNetworkTransaction::ShouldApplyServerAuth() const { | 1361 bool HttpNetworkTransaction::ShouldApplyServerAuth() const { |
| 1359 return !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA); | 1362 return !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA); |
| 1360 } | 1363 } |
| 1361 | 1364 |
| 1362 int HttpNetworkTransaction::HandleAuthChallenge() { | 1365 int HttpNetworkTransaction::HandleAuthChallenge() { |
| 1363 scoped_refptr<HttpResponseHeaders> headers(GetResponseHeaders()); | 1366 scoped_refptr<HttpResponseHeaders> headers(GetResponseHeaders()); |
| 1364 DCHECK(headers); | 1367 DCHECK(headers.get()); |
| 1365 | 1368 |
| 1366 int status = headers->response_code(); | 1369 int status = headers->response_code(); |
| 1367 if (status != HTTP_UNAUTHORIZED && | 1370 if (status != HTTP_UNAUTHORIZED && |
| 1368 status != HTTP_PROXY_AUTHENTICATION_REQUIRED) | 1371 status != HTTP_PROXY_AUTHENTICATION_REQUIRED) |
| 1369 return OK; | 1372 return OK; |
| 1370 HttpAuth::Target target = status == HTTP_PROXY_AUTHENTICATION_REQUIRED ? | 1373 HttpAuth::Target target = status == HTTP_PROXY_AUTHENTICATION_REQUIRED ? |
| 1371 HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER; | 1374 HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER; |
| 1372 if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct()) | 1375 if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct()) |
| 1373 return ERR_UNEXPECTED_PROXY_AUTH; | 1376 return ERR_UNEXPECTED_PROXY_AUTH; |
| 1374 | 1377 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1442 description = base::StringPrintf("Unknown state 0x%08X (%u)", state, | 1445 description = base::StringPrintf("Unknown state 0x%08X (%u)", state, |
| 1443 state); | 1446 state); |
| 1444 break; | 1447 break; |
| 1445 } | 1448 } |
| 1446 return description; | 1449 return description; |
| 1447 } | 1450 } |
| 1448 | 1451 |
| 1449 #undef STATE_CASE | 1452 #undef STATE_CASE |
| 1450 | 1453 |
| 1451 } // namespace net | 1454 } // namespace net |
| OLD | NEW |