blob: 2a3bce16108ba5bc5cbf84bab82164a52327f72a [file] [log] [blame]
[email protected]49ed6cc2012-02-02 08:59:161// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]d102f542010-06-30 14:51:052// Use of this source code is governed by a BSD-style license that can be
license.botbf09a502008-08-24 00:55:553// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
5#include "net/http/http_network_transaction.h"
6
[email protected]2fbaecf22010-07-22 22:20:357#include <set>
8#include <vector>
9
[email protected]49639fa2011-12-20 23:22:4110#include "base/bind.h"
11#include "base/bind_helpers.h"
[email protected]68bf9152008-09-25 19:47:3012#include "base/compiler_specific.h"
[email protected]270c6412010-03-29 22:02:4713#include "base/format_macros.h"
[email protected]3b63f8f42011-03-28 01:54:1514#include "base/memory/scoped_ptr.h"
[email protected]835d7c82010-10-14 04:38:3815#include "base/metrics/field_trial.h"
16#include "base/metrics/histogram.h"
17#include "base/metrics/stats_counters.h"
[email protected]7286e3fc2011-07-19 22:13:2418#include "base/stl_util.h"
[email protected]125ef482013-06-11 18:32:4719#include "base/strings/string_number_conversions.h"
20#include "base/strings/string_util.h"
21#include "base/strings/stringprintf.h"
[email protected]3d498f72013-10-28 21:17:4022#include "base/time/time.h"
[email protected]db74b0102012-05-31 19:55:5323#include "base/values.h"
[email protected]68bf9152008-09-25 19:47:3024#include "build/build_config.h"
[email protected]277d5942010-08-11 21:02:3525#include "net/base/auth.h"
[email protected]2d6728692011-03-12 01:39:5526#include "net/base/host_port_pair.h"
[email protected]74a85ce2009-02-12 00:03:1927#include "net/base/io_buffer.h"
initial.commit586acc5fe2008-07-26 22:42:5228#include "net/base/load_flags.h"
[email protected]58e32bb2013-01-21 18:23:2529#include "net/base/load_timing_info.h"
[email protected]597cf6e2009-05-29 09:43:2630#include "net/base/net_errors.h"
[email protected]c3b35c22008-09-27 03:19:4231#include "net/base/net_util.h"
initial.commit586acc5fe2008-07-26 22:42:5232#include "net/base/upload_data_stream.h"
[email protected]c3b35c22008-09-27 03:19:4233#include "net/http/http_auth.h"
34#include "net/http/http_auth_handler.h"
[email protected]fa82f932010-05-20 11:09:2435#include "net/http/http_auth_handler_factory.h"
[email protected]8d5a34e2009-06-11 21:21:3636#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5237#include "net/http/http_chunked_decoder.h"
38#include "net/http/http_network_session.h"
[email protected]a7ea8832010-07-12 17:54:5439#include "net/http/http_proxy_client_socket.h"
[email protected]e772db3f2010-07-12 18:11:1340#include "net/http/http_proxy_client_socket_pool.h"
[email protected]270c6412010-03-29 22:02:4741#include "net/http/http_request_headers.h"
initial.commit586acc5fe2008-07-26 22:42:5242#include "net/http/http_request_info.h"
[email protected]319d9e6f2009-02-18 19:47:2143#include "net/http/http_response_headers.h"
[email protected]0877e3d2009-10-17 22:29:5744#include "net/http/http_response_info.h"
[email protected]17291a022011-10-10 07:32:5345#include "net/http/http_server_properties.h"
[email protected]9094b602012-02-27 21:44:5846#include "net/http/http_status_code.h"
[email protected]92b9a3e2012-11-09 08:52:5247#include "net/http/http_stream_base.h"
[email protected]102e27c2011-02-23 01:01:3148#include "net/http/http_stream_factory.h"
initial.commit586acc5fe2008-07-26 22:42:5249#include "net/http/http_util.h"
[email protected]158ac972013-04-19 23:29:2350#include "net/http/transport_security_state.h"
[email protected]d7f16632010-03-29 18:02:3651#include "net/http/url_security_manager.h"
[email protected]f7984fc62009-06-22 23:26:4452#include "net/socket/client_socket_factory.h"
[email protected]a796bcec2010-03-22 17:17:2653#include "net/socket/socks_client_socket_pool.h"
[email protected]f7984fc62009-06-22 23:26:4454#include "net/socket/ssl_client_socket.h"
[email protected]e60e47a2010-07-14 03:37:1855#include "net/socket/ssl_client_socket_pool.h"
[email protected]ab739042011-04-07 15:22:2856#include "net/socket/transport_client_socket_pool.h"
[email protected]65d56aa2010-06-14 04:13:4057#include "net/spdy/spdy_http_stream.h"
[email protected]dab9c7d2010-02-06 21:44:3258#include "net/spdy/spdy_session.h"
59#include "net/spdy/spdy_session_pool.h"
[email protected]536fd0b2013-03-14 17:41:5760#include "net/ssl/ssl_cert_request_info.h"
61#include "net/ssl/ssl_connection_status_flags.h"
[email protected]f89276a72013-07-12 06:41:5462#include "url/gurl.h"
initial.commit586acc5fe2008-07-26 22:42:5263
[email protected]e1acf6f2008-10-27 20:43:3364using base::Time;
65
initial.commit586acc5fe2008-07-26 22:42:5266namespace net {
67
[email protected]1c773ea12009-04-28 19:58:4268namespace {
69
[email protected]30d4c022013-07-18 22:58:1670void ProcessAlternateProtocol(
71 HttpStreamFactory* factory,
72 const base::WeakPtr<HttpServerProperties>& http_server_properties,
73 const HttpResponseHeaders& headers,
74 const HostPortPair& http_host_port_pair) {
[email protected]564b4912010-03-09 16:30:4275 std::string alternate_protocol_str;
[email protected]8e6441ca2010-08-19 05:56:3876
[email protected]17291a022011-10-10 07:32:5377 if (!headers.EnumerateHeader(NULL, kAlternateProtocolHeader,
[email protected]564b4912010-03-09 16:30:4278 &alternate_protocol_str)) {
79 // Header is not present.
80 return;
81 }
82
[email protected]17291a022011-10-10 07:32:5383 factory->ProcessAlternateProtocol(http_server_properties,
[email protected]8e6441ca2010-08-19 05:56:3884 alternate_protocol_str,
85 http_host_port_pair);
[email protected]f45c1ee2010-08-03 00:54:3086}
87
[email protected]a1cb2cd2011-02-05 02:02:0888// Returns true if |error| is a client certificate authentication error.
89bool IsClientCertificateError(int error) {
90 switch (error) {
91 case ERR_BAD_SSL_CLIENT_AUTH_CERT:
92 case ERR_SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED:
93 case ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY:
94 case ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED:
95 return true;
96 default:
97 return false;
98 }
99}
100
[email protected]ea5ef4c2013-06-13 22:50:27101base::Value* NetLogSSLVersionFallbackCallback(
102 const GURL* url,
103 int net_error,
104 uint16 version_before,
105 uint16 version_after,
106 NetLog::LogLevel /* log_level */) {
107 base::DictionaryValue* dict = new base::DictionaryValue();
[email protected]b6754252012-06-13 23:14:38108 dict->SetString("host_and_port", GetHostAndPort(*url));
109 dict->SetInteger("net_error", net_error);
110 dict->SetInteger("version_before", version_before);
111 dict->SetInteger("version_after", version_after);
112 return dict;
113}
[email protected]db74b0102012-05-31 19:55:53114
[email protected]1c773ea12009-04-28 19:58:42115} // namespace
116
initial.commit586acc5fe2008-07-26 22:42:52117//-----------------------------------------------------------------------------
118
[email protected]262eec82013-03-19 21:01:36119HttpNetworkTransaction::HttpNetworkTransaction(RequestPriority priority,
120 HttpNetworkSession* session)
[email protected]0757e7702009-03-27 04:00:22121 : pending_auth_target_(HttpAuth::AUTH_NONE),
[email protected]aa249b52013-04-30 01:04:32122 io_callback_(base::Bind(&HttpNetworkTransaction::OnIOComplete,
123 base::Unretained(this))),
initial.commit586acc5fe2008-07-26 22:42:52124 session_(session),
125 request_(NULL),
[email protected]262eec82013-03-19 21:01:36126 priority_(priority),
[email protected]0877e3d2009-10-17 22:29:57127 headers_valid_(false),
[email protected]8e3d2d32010-06-13 18:46:23128 logged_response_time_(false),
[email protected]b94f92d2010-10-27 16:45:20129 request_headers_(),
initial.commit586acc5fe2008-07-26 22:42:52130 read_buf_len_(0),
[email protected]a7ea8832010-07-12 17:54:54131 next_state_(STATE_NONE),
[email protected]831e4a32013-11-14 02:14:44132 establishing_tunnel_(false),
133 websocket_handshake_stream_base_create_helper_(NULL) {
[email protected]102957f2011-09-02 17:10:14134 session->ssl_config_service()->GetSSLConfig(&server_ssl_config_);
[email protected]5285d972011-10-18 18:56:34135 if (session->http_stream_factory()->has_next_protos()) {
[email protected]102957f2011-09-02 17:10:14136 server_ssl_config_.next_protos =
[email protected]5285d972011-10-18 18:56:34137 session->http_stream_factory()->next_protos();
[email protected]102957f2011-09-02 17:10:14138 }
[email protected]99ffa5a2011-10-06 04:20:19139 proxy_ssl_config_ = server_ssl_config_;
[email protected]3ce7df0f2010-03-03 00:30:50140}
141
[email protected]0b0bf032010-09-21 18:08:50142HttpNetworkTransaction::~HttpNetworkTransaction() {
143 if (stream_.get()) {
144 HttpResponseHeaders* headers = GetResponseHeaders();
145 // TODO(mbelshe): The stream_ should be able to compute whether or not the
146 // stream should be kept alive. No reason to compute here
147 // and pass it in.
148 bool try_to_keep_alive =
149 next_state_ == STATE_NONE &&
150 stream_->CanFindEndOfResponse() &&
151 (!headers || headers->IsKeepAlive());
152 if (!try_to_keep_alive) {
153 stream_->Close(true /* not reusable */);
154 } else {
155 if (stream_->IsResponseBodyComplete()) {
156 // If the response body is complete, we can just reuse the socket.
157 stream_->Close(false /* reusable */);
[email protected]3a8d6852011-03-11 23:43:44158 } else if (stream_->IsSpdyHttpStream()) {
159 // Doesn't really matter for SpdyHttpStream. Just close it.
160 stream_->Close(true /* not reusable */);
[email protected]0b0bf032010-09-21 18:08:50161 } else {
162 // Otherwise, we try to drain the response body.
[email protected]92b9a3e2012-11-09 08:52:52163 HttpStreamBase* stream = stream_.release();
[email protected]3fe8d2f82013-10-17 08:56:07164 stream->Drain(session_);
[email protected]0b0bf032010-09-21 18:08:50165 }
166 }
167 }
[email protected]02cad5d2013-10-02 08:14:03168
169 if (request_ && request_->upload_data_stream)
170 request_->upload_data_stream->Reset(); // Invalidate pending callbacks.
[email protected]0b0bf032010-09-21 18:08:50171}
172
[email protected]684970b2009-08-14 04:54:46173int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info,
[email protected]49639fa2011-12-20 23:22:41174 const CompletionCallback& callback,
[email protected]9e743cd2010-03-16 07:03:53175 const BoundNetLog& net_log) {
[email protected]5e2e6c77d12009-12-24 21:57:16176 SIMPLE_STATS_COUNTER("HttpNetworkTransaction.Count");
[email protected]5d0153c512009-01-12 19:08:36177
[email protected]9e743cd2010-03-16 07:03:53178 net_log_ = net_log;
[email protected]96d570e42008-08-05 22:43:04179 request_ = request_info;
[email protected]21b316a2009-03-23 18:25:06180 start_time_ = base::Time::Now();
[email protected]96d570e42008-08-05 22:43:04181
[email protected]99ffa5a2011-10-06 04:20:19182 if (request_->load_flags & LOAD_DISABLE_CERT_REVOCATION_CHECKING) {
[email protected]102957f2011-09-02 17:10:14183 server_ssl_config_.rev_checking_enabled = false;
[email protected]99ffa5a2011-10-06 04:20:19184 proxy_ssl_config_.rev_checking_enabled = false;
185 }
[email protected]6fbac162011-06-20 00:29:04186
[email protected]e6d017652013-05-17 18:01:40187 // Channel ID is enabled unless --disable-tls-channel-id flag is set,
188 // or if privacy mode is enabled.
189 bool channel_id_enabled = server_ssl_config_.channel_id_enabled &&
190 (request_->privacy_mode == kPrivacyModeDisabled);
191 server_ssl_config_.channel_id_enabled = channel_id_enabled;
192
[email protected]82918cc2010-08-25 17:24:50193 next_state_ = STATE_CREATE_STREAM;
[email protected]96d570e42008-08-05 22:43:04194 int rv = DoLoop(OK);
195 if (rv == ERR_IO_PENDING)
[email protected]49639fa2011-12-20 23:22:41196 callback_ = callback;
[email protected]96d570e42008-08-05 22:43:04197 return rv;
198}
199
200int HttpNetworkTransaction::RestartIgnoringLastError(
[email protected]49639fa2011-12-20 23:22:41201 const CompletionCallback& callback) {
[email protected]8e6441ca2010-08-19 05:56:38202 DCHECK(!stream_.get());
203 DCHECK(!stream_request_.get());
204 DCHECK_EQ(STATE_NONE, next_state_);
205
[email protected]82918cc2010-08-25 17:24:50206 next_state_ = STATE_CREATE_STREAM;
[email protected]8e6441ca2010-08-19 05:56:38207
[email protected]ccb40e52008-09-17 20:54:40208 int rv = DoLoop(OK);
209 if (rv == ERR_IO_PENDING)
[email protected]49639fa2011-12-20 23:22:41210 callback_ = callback;
[email protected]aaead502008-10-15 00:20:11211 return rv;
[email protected]96d570e42008-08-05 22:43:04212}
213
[email protected]0b45559b2009-06-12 21:45:11214int HttpNetworkTransaction::RestartWithCertificate(
[email protected]49639fa2011-12-20 23:22:41215 X509Certificate* client_cert, const CompletionCallback& callback) {
[email protected]8e6441ca2010-08-19 05:56:38216 // In HandleCertificateRequest(), we always tear down existing stream
217 // requests to force a new connection. So we shouldn't have one here.
218 DCHECK(!stream_request_.get());
219 DCHECK(!stream_.get());
220 DCHECK_EQ(STATE_NONE, next_state_);
221
[email protected]102957f2011-09-02 17:10:14222 SSLConfig* ssl_config = response_.cert_request_info->is_proxy ?
223 &proxy_ssl_config_ : &server_ssl_config_;
224 ssl_config->send_client_cert = true;
225 ssl_config->client_cert = client_cert;
[email protected]ec229bc92010-11-22 09:51:45226 session_->ssl_client_auth_cache()->Add(
227 response_.cert_request_info->host_and_port, client_cert);
[email protected]0b45559b2009-06-12 21:45:11228 // Reset the other member variables.
229 // Note: this is necessary only with SSL renegotiation.
230 ResetStateForRestart();
[email protected]82918cc2010-08-25 17:24:50231 next_state_ = STATE_CREATE_STREAM;
[email protected]0b45559b2009-06-12 21:45:11232 int rv = DoLoop(OK);
233 if (rv == ERR_IO_PENDING)
[email protected]49639fa2011-12-20 23:22:41234 callback_ = callback;
[email protected]0b45559b2009-06-12 21:45:11235 return rv;
236}
237
[email protected]49639fa2011-12-20 23:22:41238int HttpNetworkTransaction::RestartWithAuth(
239 const AuthCredentials& credentials, const CompletionCallback& callback) {
[email protected]0757e7702009-03-27 04:00:22240 HttpAuth::Target target = pending_auth_target_;
241 if (target == HttpAuth::AUTH_NONE) {
242 NOTREACHED();
243 return ERR_UNEXPECTED;
244 }
[email protected]0757e7702009-03-27 04:00:22245 pending_auth_target_ = HttpAuth::AUTH_NONE;
[email protected]c3b35c22008-09-27 03:19:42246
[email protected]f3cf9802011-10-28 18:44:58247 auth_controllers_[target]->ResetAuth(credentials);
[email protected]e772db3f2010-07-12 18:11:13248
[email protected]49639fa2011-12-20 23:22:41249 DCHECK(callback_.is_null());
[email protected]8e6441ca2010-08-19 05:56:38250
251 int rv = OK;
252 if (target == HttpAuth::AUTH_PROXY && establishing_tunnel_) {
253 // In this case, we've gathered credentials for use with proxy
254 // authentication of a tunnel.
[email protected]82918cc2010-08-25 17:24:50255 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38256 DCHECK(stream_request_ != NULL);
[email protected]394816e92010-08-03 07:38:59257 auth_controllers_[target] = NULL;
[email protected]a7ea8832010-07-12 17:54:54258 ResetStateForRestart();
[email protected]f3cf9802011-10-28 18:44:58259 rv = stream_request_->RestartTunnelWithProxyAuth(credentials);
[email protected]a7ea8832010-07-12 17:54:54260 } else {
[email protected]8e6441ca2010-08-19 05:56:38261 // In this case, we've gathered credentials for the server or the proxy
262 // but it is not during the tunneling phase.
263 DCHECK(stream_request_ == NULL);
[email protected]a7ea8832010-07-12 17:54:54264 PrepareForAuthRestart(target);
[email protected]8e6441ca2010-08-19 05:56:38265 rv = DoLoop(OK);
[email protected]a7ea8832010-07-12 17:54:54266 }
[email protected]c3b35c22008-09-27 03:19:42267
[email protected]c3b35c22008-09-27 03:19:42268 if (rv == ERR_IO_PENDING)
[email protected]49639fa2011-12-20 23:22:41269 callback_ = callback;
[email protected]c3b35c22008-09-27 03:19:42270 return rv;
[email protected]96d570e42008-08-05 22:43:04271}
272
[email protected]f9ee6b52008-11-08 06:46:23273void HttpNetworkTransaction::PrepareForAuthRestart(HttpAuth::Target target) {
274 DCHECK(HaveAuth(target));
[email protected]8e6441ca2010-08-19 05:56:38275 DCHECK(!stream_request_.get());
276
[email protected]2d2697f92009-02-18 21:00:32277 bool keep_alive = false;
[email protected]0877e3d2009-10-17 22:29:57278 // Even if the server says the connection is keep-alive, we have to be
279 // able to find the end of each response in order to reuse the connection.
280 if (GetResponseHeaders()->IsKeepAlive() &&
[email protected]351ab642010-08-05 16:55:31281 stream_->CanFindEndOfResponse()) {
[email protected]0877e3d2009-10-17 22:29:57282 // If the response body hasn't been completely read, we need to drain
283 // it first.
[email protected]351ab642010-08-05 16:55:31284 if (!stream_->IsResponseBodyComplete()) {
[email protected]2d2697f92009-02-18 21:00:32285 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
[email protected]0877e3d2009-10-17 22:29:57286 read_buf_ = new IOBuffer(kDrainBodyBufferSize); // A bit bucket.
[email protected]2d2697f92009-02-18 21:00:32287 read_buf_len_ = kDrainBodyBufferSize;
288 return;
289 }
[email protected]0877e3d2009-10-17 22:29:57290 keep_alive = true;
[email protected]37832c6d2009-06-05 19:44:09291 }
292
[email protected]2d2697f92009-02-18 21:00:32293 // We don't need to drain the response body, so we act as if we had drained
294 // the response body.
295 DidDrainBodyForAuthRestart(keep_alive);
296}
297
298void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) {
[email protected]8e6441ca2010-08-19 05:56:38299 DCHECK(!stream_request_.get());
300
301 if (stream_.get()) {
[email protected]697ef4c2010-10-14 16:38:58302 HttpStream* new_stream = NULL;
[email protected]2d0a4f92011-05-05 16:38:46303 if (keep_alive && stream_->IsConnectionReusable()) {
[email protected]8e6441ca2010-08-19 05:56:38304 // We should call connection_->set_idle_time(), but this doesn't occur
305 // often enough to be worth the trouble.
306 stream_->SetConnectionReused();
[email protected]92b9a3e2012-11-09 08:52:52307 new_stream =
308 static_cast<HttpStream*>(stream_.get())->RenewStreamForAuth();
[email protected]8e6441ca2010-08-19 05:56:38309 }
[email protected]697ef4c2010-10-14 16:38:58310
311 if (!new_stream) {
[email protected]2d0a4f92011-05-05 16:38:46312 // Close the stream and mark it as not_reusable. Even in the
313 // keep_alive case, we've determined that the stream_ is not
314 // reusable if new_stream is NULL.
315 stream_->Close(true);
[email protected]697ef4c2010-10-14 16:38:58316 next_state_ = STATE_CREATE_STREAM;
317 } else {
318 next_state_ = STATE_INIT_STREAM;
319 }
320 stream_.reset(new_stream);
[email protected]2d2697f92009-02-18 21:00:32321 }
[email protected]f9ee6b52008-11-08 06:46:23322
323 // Reset the other member variables.
[email protected]697ef4c2010-10-14 16:38:58324 ResetStateForAuthRestart();
[email protected]f9ee6b52008-11-08 06:46:23325}
326
[email protected]8e6441ca2010-08-19 05:56:38327bool HttpNetworkTransaction::IsReadyToRestartForAuth() {
328 return pending_auth_target_ != HttpAuth::AUTH_NONE &&
329 HaveAuth(pending_auth_target_);
330}
331
[email protected]9dea9e1f2009-01-29 00:30:47332int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len,
[email protected]49639fa2011-12-20 23:22:41333 const CompletionCallback& callback) {
[email protected]96d570e42008-08-05 22:43:04334 DCHECK(buf);
[email protected]e0c27be2009-07-15 13:09:35335 DCHECK_LT(0, buf_len);
[email protected]96d570e42008-08-05 22:43:04336
[email protected]1f14a912009-12-21 20:32:44337 State next_state = STATE_NONE;
[email protected]96d570e42008-08-05 22:43:04338
[email protected]ad8e04a2010-11-01 04:16:27339 scoped_refptr<HttpResponseHeaders> headers(GetResponseHeaders());
[email protected]8e6441ca2010-08-19 05:56:38340 if (headers_valid_ && headers.get() && stream_request_.get()) {
[email protected]8a1f3312010-05-25 19:25:04341 // We're trying to read the body of the response but we're still trying
[email protected]511f6f52010-12-17 03:58:29342 // to establish an SSL tunnel through an HTTP proxy. We can't read these
[email protected]8a1f3312010-05-25 19:25:04343 // bytes when establishing a tunnel because they might be controlled by
344 // an active network attacker. We don't worry about this for HTTP
345 // because an active network attacker can already control HTTP sessions.
[email protected]511f6f52010-12-17 03:58:29346 // We reach this case when the user cancels a 407 proxy auth prompt. We
347 // also don't worry about this for an HTTPS Proxy, because the
348 // communication with the proxy is secure.
[email protected]8a1f3312010-05-25 19:25:04349 // See http://crbug.com/8473.
[email protected]2df19bb2010-08-25 20:13:46350 DCHECK(proxy_info_.is_http() || proxy_info_.is_https());
[email protected]9094b602012-02-27 21:44:58351 DCHECK_EQ(headers->response_code(), HTTP_PROXY_AUTHENTICATION_REQUIRED);
[email protected]a7ea8832010-07-12 17:54:54352 LOG(WARNING) << "Blocked proxy response with status "
353 << headers->response_code() << " to CONNECT request for "
354 << GetHostAndPort(request_->url) << ".";
[email protected]8a1f3312010-05-25 19:25:04355 return ERR_TUNNEL_CONNECTION_FAILED;
[email protected]a8e9b162009-03-12 00:06:44356 }
357
[email protected]e60e47a2010-07-14 03:37:18358 // Are we using SPDY or HTTP?
[email protected]351ab642010-08-05 16:55:31359 next_state = STATE_READ_BODY;
[email protected]e60e47a2010-07-14 03:37:18360
[email protected]96d570e42008-08-05 22:43:04361 read_buf_ = buf;
362 read_buf_len_ = buf_len;
363
[email protected]1f14a912009-12-21 20:32:44364 next_state_ = next_state;
[email protected]96d570e42008-08-05 22:43:04365 int rv = DoLoop(OK);
366 if (rv == ERR_IO_PENDING)
[email protected]49639fa2011-12-20 23:22:41367 callback_ = callback;
[email protected]96d570e42008-08-05 22:43:04368 return rv;
369}
370
[email protected]79e1fd62013-06-20 06:50:04371bool HttpNetworkTransaction::GetFullRequestHeaders(
372 HttpRequestHeaders* headers) const {
373 // TODO(ttuttle): Make sure we've populated request_headers_.
374 *headers = request_headers_;
375 return true;
376}
377
[email protected]96d570e42008-08-05 22:43:04378const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const {
[email protected]90499482013-06-01 00:39:50379 return ((headers_valid_ && response_.headers.get()) ||
380 response_.ssl_info.cert.get() || response_.cert_request_info.get())
381 ? &response_
382 : NULL;
[email protected]96d570e42008-08-05 22:43:04383}
384
385LoadState HttpNetworkTransaction::GetLoadState() const {
386 // TODO(wtc): Define a new LoadState value for the
387 // STATE_INIT_CONNECTION_COMPLETE state, which delays the HTTP request.
388 switch (next_state_) {
[email protected]82918cc2010-08-25 17:24:50389 case STATE_CREATE_STREAM_COMPLETE:
[email protected]8e6441ca2010-08-19 05:56:38390 return stream_request_->GetLoadState();
[email protected]044de0642010-06-17 10:42:15391 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE:
392 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE:
[email protected]0877e3d2009-10-17 22:29:57393 case STATE_SEND_REQUEST_COMPLETE:
[email protected]96d570e42008-08-05 22:43:04394 return LOAD_STATE_SENDING_REQUEST;
395 case STATE_READ_HEADERS_COMPLETE:
396 return LOAD_STATE_WAITING_FOR_RESPONSE;
397 case STATE_READ_BODY_COMPLETE:
398 return LOAD_STATE_READING_RESPONSE;
399 default:
400 return LOAD_STATE_IDLE;
401 }
402}
403
[email protected]196d18a2012-08-30 03:47:31404UploadProgress HttpNetworkTransaction::GetUploadProgress() const {
[email protected]351ab642010-08-05 16:55:31405 if (!stream_.get())
[email protected]196d18a2012-08-30 03:47:31406 return UploadProgress();
[email protected]96d570e42008-08-05 22:43:04407
[email protected]92b9a3e2012-11-09 08:52:52408 // TODO(bashi): This cast is temporary. Remove later.
409 return static_cast<HttpStream*>(stream_.get())->GetUploadProgress();
[email protected]96d570e42008-08-05 22:43:04410}
411
[email protected]5033ab82013-03-22 20:17:46412bool HttpNetworkTransaction::GetLoadTimingInfo(
413 LoadTimingInfo* load_timing_info) const {
414 if (!stream_ || !stream_->GetLoadTimingInfo(load_timing_info))
415 return false;
416
417 load_timing_info->proxy_resolve_start =
418 proxy_info_.proxy_resolve_start_time();
419 load_timing_info->proxy_resolve_end = proxy_info_.proxy_resolve_end_time();
420 load_timing_info->send_start = send_start_time_;
421 load_timing_info->send_end = send_end_time_;
[email protected]5033ab82013-03-22 20:17:46422 return true;
423}
424
425void HttpNetworkTransaction::SetPriority(RequestPriority priority) {
426 priority_ = priority;
[email protected]bf828982013-08-14 18:01:47427 if (stream_request_)
428 stream_request_->SetPriority(priority);
[email protected]e86839fd2013-08-14 18:29:03429 if (stream_)
430 stream_->SetPriority(priority);
[email protected]5033ab82013-03-22 20:17:46431}
432
[email protected]831e4a32013-11-14 02:14:44433void HttpNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper(
434 WebSocketHandshakeStreamBase::CreateHelper* create_helper) {
435 websocket_handshake_stream_base_create_helper_ = create_helper;
436}
437
[email protected]102e27c2011-02-23 01:01:31438void HttpNetworkTransaction::OnStreamReady(const SSLConfig& used_ssl_config,
439 const ProxyInfo& used_proxy_info,
[email protected]92b9a3e2012-11-09 08:52:52440 HttpStreamBase* stream) {
[email protected]82918cc2010-08-25 17:24:50441 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38442 DCHECK(stream_request_.get());
443
444 stream_.reset(stream);
[email protected]102957f2011-09-02 17:10:14445 server_ssl_config_ = used_ssl_config;
[email protected]102e27c2011-02-23 01:01:31446 proxy_info_ = used_proxy_info;
[email protected]8e6441ca2010-08-19 05:56:38447 response_.was_npn_negotiated = stream_request_->was_npn_negotiated();
[email protected]c30bcce2011-12-20 17:50:51448 response_.npn_negotiated_protocol = SSLClientSocket::NextProtoToString(
449 stream_request_->protocol_negotiated());
[email protected]8e6441ca2010-08-19 05:56:38450 response_.was_fetched_via_spdy = stream_request_->using_spdy();
451 response_.was_fetched_via_proxy = !proxy_info_.is_direct();
[email protected]8e6441ca2010-08-19 05:56:38452
453 OnIOComplete(OK);
454}
455
[email protected]a9cf2b92013-10-30 12:08:49456void HttpNetworkTransaction::OnWebSocketHandshakeStreamReady(
[email protected]3732cea2013-06-21 06:50:50457 const SSLConfig& used_ssl_config,
458 const ProxyInfo& used_proxy_info,
[email protected]a9cf2b92013-10-30 12:08:49459 WebSocketHandshakeStreamBase* stream) {
[email protected]831e4a32013-11-14 02:14:44460 OnStreamReady(used_ssl_config, used_proxy_info, stream);
[email protected]3732cea2013-06-21 06:50:50461}
462
[email protected]102e27c2011-02-23 01:01:31463void HttpNetworkTransaction::OnStreamFailed(int result,
464 const SSLConfig& used_ssl_config) {
[email protected]82918cc2010-08-25 17:24:50465 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38466 DCHECK_NE(OK, result);
467 DCHECK(stream_request_.get());
468 DCHECK(!stream_.get());
[email protected]102957f2011-09-02 17:10:14469 server_ssl_config_ = used_ssl_config;
[email protected]8e6441ca2010-08-19 05:56:38470
471 OnIOComplete(result);
472}
473
[email protected]102e27c2011-02-23 01:01:31474void HttpNetworkTransaction::OnCertificateError(
475 int result,
476 const SSLConfig& used_ssl_config,
477 const SSLInfo& ssl_info) {
[email protected]82918cc2010-08-25 17:24:50478 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38479 DCHECK_NE(OK, result);
480 DCHECK(stream_request_.get());
481 DCHECK(!stream_.get());
482
483 response_.ssl_info = ssl_info;
[email protected]102957f2011-09-02 17:10:14484 server_ssl_config_ = used_ssl_config;
[email protected]8e6441ca2010-08-19 05:56:38485
486 // TODO(mbelshe): For now, we're going to pass the error through, and that
487 // will close the stream_request in all cases. This means that we're always
[email protected]82918cc2010-08-25 17:24:50488 // going to restart an entire STATE_CREATE_STREAM, even if the connection is
489 // good and the user chooses to ignore the error. This is not ideal, but not
490 // the end of the world either.
[email protected]8e6441ca2010-08-19 05:56:38491
492 OnIOComplete(result);
493}
494
495void HttpNetworkTransaction::OnNeedsProxyAuth(
[email protected]6dc476da2010-09-01 04:43:50496 const HttpResponseInfo& proxy_response,
[email protected]102e27c2011-02-23 01:01:31497 const SSLConfig& used_ssl_config,
498 const ProxyInfo& used_proxy_info,
[email protected]6dc476da2010-09-01 04:43:50499 HttpAuthController* auth_controller) {
[email protected]8e6441ca2010-08-19 05:56:38500 DCHECK(stream_request_.get());
[email protected]82918cc2010-08-25 17:24:50501 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38502
503 establishing_tunnel_ = true;
504 response_.headers = proxy_response.headers;
505 response_.auth_challenge = proxy_response.auth_challenge;
506 headers_valid_ = true;
[email protected]102957f2011-09-02 17:10:14507 server_ssl_config_ = used_ssl_config;
[email protected]102e27c2011-02-23 01:01:31508 proxy_info_ = used_proxy_info;
[email protected]8e6441ca2010-08-19 05:56:38509
510 auth_controllers_[HttpAuth::AUTH_PROXY] = auth_controller;
511 pending_auth_target_ = HttpAuth::AUTH_PROXY;
512
513 DoCallback(OK);
514}
515
516void HttpNetworkTransaction::OnNeedsClientAuth(
[email protected]102e27c2011-02-23 01:01:31517 const SSLConfig& used_ssl_config,
[email protected]6dc476da2010-09-01 04:43:50518 SSLCertRequestInfo* cert_info) {
[email protected]82918cc2010-08-25 17:24:50519 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38520
[email protected]102957f2011-09-02 17:10:14521 server_ssl_config_ = used_ssl_config;
[email protected]8e6441ca2010-08-19 05:56:38522 response_.cert_request_info = cert_info;
[email protected]65a3b912010-08-21 05:46:58523 OnIOComplete(ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]8e6441ca2010-08-19 05:56:38524}
525
[email protected]511f6f52010-12-17 03:58:29526void HttpNetworkTransaction::OnHttpsProxyTunnelResponse(
527 const HttpResponseInfo& response_info,
[email protected]102e27c2011-02-23 01:01:31528 const SSLConfig& used_ssl_config,
529 const ProxyInfo& used_proxy_info,
[email protected]92b9a3e2012-11-09 08:52:52530 HttpStreamBase* stream) {
[email protected]511f6f52010-12-17 03:58:29531 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
532
533 headers_valid_ = true;
534 response_ = response_info;
[email protected]102957f2011-09-02 17:10:14535 server_ssl_config_ = used_ssl_config;
[email protected]102e27c2011-02-23 01:01:31536 proxy_info_ = used_proxy_info;
[email protected]511f6f52010-12-17 03:58:29537 stream_.reset(stream);
538 stream_request_.reset(); // we're done with the stream request
539 OnIOComplete(ERR_HTTPS_PROXY_TUNNEL_RESPONSE);
540}
541
[email protected]8e6441ca2010-08-19 05:56:38542bool HttpNetworkTransaction::is_https_request() const {
543 return request_->url.SchemeIs("https");
initial.commit586acc5fe2008-07-26 22:42:52544}
545
initial.commit586acc5fe2008-07-26 22:42:52546void HttpNetworkTransaction::DoCallback(int rv) {
[email protected]0b0bf032010-09-21 18:08:50547 DCHECK_NE(rv, ERR_IO_PENDING);
[email protected]49639fa2011-12-20 23:22:41548 DCHECK(!callback_.is_null());
initial.commit586acc5fe2008-07-26 22:42:52549
[email protected]96d570e42008-08-05 22:43:04550 // Since Run may result in Read being called, clear user_callback_ up front.
[email protected]49639fa2011-12-20 23:22:41551 CompletionCallback c = callback_;
552 callback_.Reset();
553 c.Run(rv);
initial.commit586acc5fe2008-07-26 22:42:52554}
555
556void HttpNetworkTransaction::OnIOComplete(int result) {
557 int rv = DoLoop(result);
558 if (rv != ERR_IO_PENDING)
559 DoCallback(rv);
560}
561
562int HttpNetworkTransaction::DoLoop(int result) {
563 DCHECK(next_state_ != STATE_NONE);
564
565 int rv = result;
566 do {
567 State state = next_state_;
568 next_state_ = STATE_NONE;
569 switch (state) {
[email protected]82918cc2010-08-25 17:24:50570 case STATE_CREATE_STREAM:
571 DCHECK_EQ(OK, rv);
572 rv = DoCreateStream();
573 break;
574 case STATE_CREATE_STREAM_COMPLETE:
575 rv = DoCreateStreamComplete(rv);
576 break;
[email protected]351ab642010-08-05 16:55:31577 case STATE_INIT_STREAM:
578 DCHECK_EQ(OK, rv);
579 rv = DoInitStream();
580 break;
581 case STATE_INIT_STREAM_COMPLETE:
582 rv = DoInitStreamComplete(rv);
583 break;
[email protected]044de0642010-06-17 10:42:15584 case STATE_GENERATE_PROXY_AUTH_TOKEN:
585 DCHECK_EQ(OK, rv);
586 rv = DoGenerateProxyAuthToken();
587 break;
588 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE:
589 rv = DoGenerateProxyAuthTokenComplete(rv);
590 break;
591 case STATE_GENERATE_SERVER_AUTH_TOKEN:
592 DCHECK_EQ(OK, rv);
593 rv = DoGenerateServerAuthToken();
594 break;
595 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE:
596 rv = DoGenerateServerAuthTokenComplete(rv);
597 break;
[email protected]daddea62012-09-19 05:51:13598 case STATE_INIT_REQUEST_BODY:
599 DCHECK_EQ(OK, rv);
600 rv = DoInitRequestBody();
601 break;
602 case STATE_INIT_REQUEST_BODY_COMPLETE:
603 rv = DoInitRequestBodyComplete(rv);
604 break;
[email protected]4875ba12011-03-30 22:31:51605 case STATE_BUILD_REQUEST:
[email protected]725355a2009-03-25 20:42:55606 DCHECK_EQ(OK, rv);
[email protected]b6754252012-06-13 23:14:38607 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST);
[email protected]4875ba12011-03-30 22:31:51608 rv = DoBuildRequest();
609 break;
610 case STATE_BUILD_REQUEST_COMPLETE:
611 rv = DoBuildRequestComplete(rv);
612 break;
613 case STATE_SEND_REQUEST:
614 DCHECK_EQ(OK, rv);
[email protected]0877e3d2009-10-17 22:29:57615 rv = DoSendRequest();
initial.commit586acc5fe2008-07-26 22:42:52616 break;
[email protected]0877e3d2009-10-17 22:29:57617 case STATE_SEND_REQUEST_COMPLETE:
618 rv = DoSendRequestComplete(rv);
[email protected]d7fd1782011-02-08 19:16:43619 net_log_.EndEventWithNetErrorCode(
620 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, rv);
initial.commit586acc5fe2008-07-26 22:42:52621 break;
622 case STATE_READ_HEADERS:
[email protected]725355a2009-03-25 20:42:55623 DCHECK_EQ(OK, rv);
[email protected]b6754252012-06-13 23:14:38624 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS);
initial.commit586acc5fe2008-07-26 22:42:52625 rv = DoReadHeaders();
626 break;
627 case STATE_READ_HEADERS_COMPLETE:
628 rv = DoReadHeadersComplete(rv);
[email protected]d7fd1782011-02-08 19:16:43629 net_log_.EndEventWithNetErrorCode(
630 NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, rv);
initial.commit586acc5fe2008-07-26 22:42:52631 break;
632 case STATE_READ_BODY:
[email protected]725355a2009-03-25 20:42:55633 DCHECK_EQ(OK, rv);
[email protected]b6754252012-06-13 23:14:38634 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_BODY);
initial.commit586acc5fe2008-07-26 22:42:52635 rv = DoReadBody();
636 break;
637 case STATE_READ_BODY_COMPLETE:
638 rv = DoReadBodyComplete(rv);
[email protected]d7fd1782011-02-08 19:16:43639 net_log_.EndEventWithNetErrorCode(
640 NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, rv);
initial.commit586acc5fe2008-07-26 22:42:52641 break;
[email protected]2d2697f92009-02-18 21:00:32642 case STATE_DRAIN_BODY_FOR_AUTH_RESTART:
[email protected]725355a2009-03-25 20:42:55643 DCHECK_EQ(OK, rv);
[email protected]9e743cd2010-03-16 07:03:53644 net_log_.BeginEvent(
[email protected]b6754252012-06-13 23:14:38645 NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART);
[email protected]2d2697f92009-02-18 21:00:32646 rv = DoDrainBodyForAuthRestart();
647 break;
648 case STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE:
649 rv = DoDrainBodyForAuthRestartComplete(rv);
[email protected]d7fd1782011-02-08 19:16:43650 net_log_.EndEventWithNetErrorCode(
651 NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART, rv);
[email protected]2d2697f92009-02-18 21:00:32652 break;
initial.commit586acc5fe2008-07-26 22:42:52653 default:
654 NOTREACHED() << "bad state";
655 rv = ERR_FAILED;
[email protected]96d570e42008-08-05 22:43:04656 break;
initial.commit586acc5fe2008-07-26 22:42:52657 }
658 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
659
660 return rv;
661}
662
[email protected]82918cc2010-08-25 17:24:50663int HttpNetworkTransaction::DoCreateStream() {
664 next_state_ = STATE_CREATE_STREAM_COMPLETE;
[email protected]351ab642010-08-05 16:55:31665
[email protected]831e4a32013-11-14 02:14:44666 if (ForWebSocketHandshake()) {
667 stream_request_.reset(
[email protected]0191b51c2013-11-18 10:55:23668 session_->http_stream_factory_for_websocket()
[email protected]831e4a32013-11-14 02:14:44669 ->RequestWebSocketHandshakeStream(
670 *request_,
671 priority_,
672 server_ssl_config_,
673 proxy_ssl_config_,
674 this,
675 websocket_handshake_stream_base_create_helper_,
676 net_log_));
677 } else {
678 stream_request_.reset(
679 session_->http_stream_factory()->RequestStream(
680 *request_,
681 priority_,
682 server_ssl_config_,
683 proxy_ssl_config_,
684 this,
685 net_log_));
686 }
[email protected]26816882010-10-14 18:03:09687 DCHECK(stream_request_.get());
[email protected]8e6441ca2010-08-19 05:56:38688 return ERR_IO_PENDING;
[email protected]351ab642010-08-05 16:55:31689}
690
[email protected]82918cc2010-08-25 17:24:50691int HttpNetworkTransaction::DoCreateStreamComplete(int result) {
[email protected]394816e92010-08-03 07:38:59692 if (result == OK) {
[email protected]82918cc2010-08-25 17:24:50693 next_state_ = STATE_INIT_STREAM;
[email protected]8e6441ca2010-08-19 05:56:38694 DCHECK(stream_.get());
[email protected]adb00242010-10-29 03:04:33695 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
696 result = HandleCertificateRequest(result);
[email protected]511f6f52010-12-17 03:58:29697 } else if (result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) {
698 // Return OK and let the caller read the proxy's error page
699 next_state_ = STATE_NONE;
700 return OK;
[email protected]394816e92010-08-03 07:38:59701 }
702
[email protected]bd0b6772011-01-11 19:59:30703 // Handle possible handshake errors that may have occurred if the stream
704 // used SSL for one or more of the layers.
705 result = HandleSSLHandshakeError(result);
706
[email protected]8e6441ca2010-08-19 05:56:38707 // At this point we are done with the stream_request_.
[email protected]26816882010-10-14 18:03:09708 stream_request_.reset();
[email protected]8e6441ca2010-08-19 05:56:38709 return result;
[email protected]394816e92010-08-03 07:38:59710}
711
[email protected]82918cc2010-08-25 17:24:50712int HttpNetworkTransaction::DoInitStream() {
713 DCHECK(stream_.get());
714 next_state_ = STATE_INIT_STREAM_COMPLETE;
[email protected]262eec82013-03-19 21:01:36715 return stream_->InitializeStream(request_, priority_, net_log_, io_callback_);
[email protected]82918cc2010-08-25 17:24:50716}
717
718int HttpNetworkTransaction::DoInitStreamComplete(int result) {
719 if (result == OK) {
720 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
[email protected]82918cc2010-08-25 17:24:50721 } else {
[email protected]82918cc2010-08-25 17:24:50722 if (result < 0)
[email protected]044dcc52010-09-17 15:44:26723 result = HandleIOError(result);
724
725 // The stream initialization failed, so this stream will never be useful.
726 stream_.reset();
[email protected]82918cc2010-08-25 17:24:50727 }
728
729 return result;
730}
731
[email protected]044de0642010-06-17 10:42:15732int HttpNetworkTransaction::DoGenerateProxyAuthToken() {
733 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE;
734 if (!ShouldApplyProxyAuth())
735 return OK;
[email protected]394816e92010-08-03 07:38:59736 HttpAuth::Target target = HttpAuth::AUTH_PROXY;
737 if (!auth_controllers_[target].get())
[email protected]3598c6022010-09-17 23:13:09738 auth_controllers_[target] =
739 new HttpAuthController(target,
740 AuthURL(target),
[email protected]102e27c2011-02-23 01:01:31741 session_->http_auth_cache(),
[email protected]3598c6022010-09-17 23:13:09742 session_->http_auth_handler_factory());
[email protected]394816e92010-08-03 07:38:59743 return auth_controllers_[target]->MaybeGenerateAuthToken(request_,
[email protected]49639fa2011-12-20 23:22:41744 io_callback_,
[email protected]394816e92010-08-03 07:38:59745 net_log_);
[email protected]044de0642010-06-17 10:42:15746}
747
748int HttpNetworkTransaction::DoGenerateProxyAuthTokenComplete(int rv) {
749 DCHECK_NE(ERR_IO_PENDING, rv);
750 if (rv == OK)
751 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN;
752 return rv;
753}
754
755int HttpNetworkTransaction::DoGenerateServerAuthToken() {
756 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE;
[email protected]394816e92010-08-03 07:38:59757 HttpAuth::Target target = HttpAuth::AUTH_SERVER;
[email protected]2217aa22013-10-11 03:03:54758 if (!auth_controllers_[target].get()) {
[email protected]3598c6022010-09-17 23:13:09759 auth_controllers_[target] =
760 new HttpAuthController(target,
761 AuthURL(target),
[email protected]102e27c2011-02-23 01:01:31762 session_->http_auth_cache(),
[email protected]3598c6022010-09-17 23:13:09763 session_->http_auth_handler_factory());
[email protected]2217aa22013-10-11 03:03:54764 if (request_->load_flags & LOAD_DO_NOT_USE_EMBEDDED_IDENTITY)
765 auth_controllers_[target]->DisableEmbeddedIdentity();
766 }
[email protected]044de0642010-06-17 10:42:15767 if (!ShouldApplyServerAuth())
768 return OK;
[email protected]394816e92010-08-03 07:38:59769 return auth_controllers_[target]->MaybeGenerateAuthToken(request_,
[email protected]49639fa2011-12-20 23:22:41770 io_callback_,
[email protected]394816e92010-08-03 07:38:59771 net_log_);
[email protected]044de0642010-06-17 10:42:15772}
773
774int HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) {
775 DCHECK_NE(ERR_IO_PENDING, rv);
776 if (rv == OK)
[email protected]daddea62012-09-19 05:51:13777 next_state_ = STATE_INIT_REQUEST_BODY;
[email protected]044de0642010-06-17 10:42:15778 return rv;
779}
780
[email protected]2979a492011-04-06 00:29:14781void HttpNetworkTransaction::BuildRequestHeaders(bool using_proxy) {
782 request_headers_.SetHeader(HttpRequestHeaders::kHost,
783 GetHostAndOptionalPort(request_->url));
784
785 // For compat with HTTP/1.0 servers and proxies:
786 if (using_proxy) {
787 request_headers_.SetHeader(HttpRequestHeaders::kProxyConnection,
788 "keep-alive");
789 } else {
790 request_headers_.SetHeader(HttpRequestHeaders::kConnection, "keep-alive");
791 }
792
[email protected]2979a492011-04-06 00:29:14793 // Add a content length header?
[email protected]bf3eb002012-11-15 05:50:11794 if (request_->upload_data_stream) {
795 if (request_->upload_data_stream->is_chunked()) {
[email protected]2979a492011-04-06 00:29:14796 request_headers_.SetHeader(
797 HttpRequestHeaders::kTransferEncoding, "chunked");
798 } else {
799 request_headers_.SetHeader(
800 HttpRequestHeaders::kContentLength,
[email protected]bf3eb002012-11-15 05:50:11801 base::Uint64ToString(request_->upload_data_stream->size()));
[email protected]2979a492011-04-06 00:29:14802 }
803 } else if (request_->method == "POST" || request_->method == "PUT" ||
804 request_->method == "HEAD") {
805 // An empty POST/PUT request still needs a content length. As for HEAD,
806 // IE and Safari also add a content length header. Presumably it is to
807 // support sending a HEAD request to an URL that only expects to be sent a
808 // POST or some other method that normally would have a message body.
809 request_headers_.SetHeader(HttpRequestHeaders::kContentLength, "0");
810 }
811
812 // Honor load flags that impact proxy caches.
813 if (request_->load_flags & LOAD_BYPASS_CACHE) {
814 request_headers_.SetHeader(HttpRequestHeaders::kPragma, "no-cache");
815 request_headers_.SetHeader(HttpRequestHeaders::kCacheControl, "no-cache");
816 } else if (request_->load_flags & LOAD_VALIDATE_CACHE) {
817 request_headers_.SetHeader(HttpRequestHeaders::kCacheControl, "max-age=0");
818 }
819
820 if (ShouldApplyProxyAuth() && HaveAuth(HttpAuth::AUTH_PROXY))
821 auth_controllers_[HttpAuth::AUTH_PROXY]->AddAuthorizationHeader(
822 &request_headers_);
823 if (ShouldApplyServerAuth() && HaveAuth(HttpAuth::AUTH_SERVER))
824 auth_controllers_[HttpAuth::AUTH_SERVER]->AddAuthorizationHeader(
825 &request_headers_);
826
[email protected]c10450102011-06-27 09:06:16827 request_headers_.MergeFrom(request_->extra_headers);
[email protected]173f8e22013-04-10 04:18:20828 response_.did_use_http_auth =
829 request_headers_.HasHeader(HttpRequestHeaders::kAuthorization) ||
830 request_headers_.HasHeader(HttpRequestHeaders::kProxyAuthorization);
[email protected]2979a492011-04-06 00:29:14831}
832
[email protected]daddea62012-09-19 05:51:13833int HttpNetworkTransaction::DoInitRequestBody() {
834 next_state_ = STATE_INIT_REQUEST_BODY_COMPLETE;
[email protected]daddea62012-09-19 05:51:13835 int rv = OK;
[email protected]bf3eb002012-11-15 05:50:11836 if (request_->upload_data_stream)
837 rv = request_->upload_data_stream->Init(io_callback_);
[email protected]daddea62012-09-19 05:51:13838 return rv;
839}
[email protected]4875ba12011-03-30 22:31:51840
[email protected]daddea62012-09-19 05:51:13841int HttpNetworkTransaction::DoInitRequestBodyComplete(int result) {
842 if (result == OK)
843 next_state_ = STATE_BUILD_REQUEST;
[email protected]daddea62012-09-19 05:51:13844 return result;
845}
846
847int HttpNetworkTransaction::DoBuildRequest() {
848 next_state_ = STATE_BUILD_REQUEST_COMPLETE;
[email protected]4875ba12011-03-30 22:31:51849 headers_valid_ = false;
850
851 // This is constructed lazily (instead of within our Start method), so that
852 // we have proxy info available.
853 if (request_headers_.IsEmpty()) {
854 bool using_proxy = (proxy_info_.is_http() || proxy_info_.is_https()) &&
855 !is_https_request();
[email protected]2979a492011-04-06 00:29:14856 BuildRequestHeaders(using_proxy);
[email protected]4875ba12011-03-30 22:31:51857 }
858
[email protected]4875ba12011-03-30 22:31:51859 return OK;
860}
861
862int HttpNetworkTransaction::DoBuildRequestComplete(int result) {
[email protected]9f489d72011-04-04 23:29:24863 if (result == OK)
864 next_state_ = STATE_SEND_REQUEST;
[email protected]4875ba12011-03-30 22:31:51865 return result;
866}
867
[email protected]0877e3d2009-10-17 22:29:57868int HttpNetworkTransaction::DoSendRequest() {
[email protected]58e32bb2013-01-21 18:23:25869 send_start_time_ = base::TimeTicks::Now();
[email protected]0877e3d2009-10-17 22:29:57870 next_state_ = STATE_SEND_REQUEST_COMPLETE;
871
[email protected]bf3eb002012-11-15 05:50:11872 return stream_->SendRequest(request_headers_, &response_, io_callback_);
initial.commit586acc5fe2008-07-26 22:42:52873}
874
[email protected]0877e3d2009-10-17 22:29:57875int HttpNetworkTransaction::DoSendRequestComplete(int result) {
[email protected]58e32bb2013-01-21 18:23:25876 send_end_time_ = base::TimeTicks::Now();
initial.commit586acc5fe2008-07-26 22:42:52877 if (result < 0)
878 return HandleIOError(result);
[email protected]7cf7ccb2013-04-20 02:53:08879 response_.network_accessed = true;
[email protected]0877e3d2009-10-17 22:29:57880 next_state_ = STATE_READ_HEADERS;
initial.commit586acc5fe2008-07-26 22:42:52881 return OK;
882}
883
884int HttpNetworkTransaction::DoReadHeaders() {
885 next_state_ = STATE_READ_HEADERS_COMPLETE;
[email protected]49639fa2011-12-20 23:22:41886 return stream_->ReadResponseHeaders(io_callback_);
initial.commit586acc5fe2008-07-26 22:42:52887}
888
[email protected]0e75a732008-10-16 20:36:09889int HttpNetworkTransaction::HandleConnectionClosedBeforeEndOfHeaders() {
[email protected]90499482013-06-01 00:39:50890 if (!response_.headers.get() && !stream_->IsConnectionReused()) {
[email protected]0e75a732008-10-16 20:36:09891 // The connection was closed before any data was sent. Likely an error
892 // rather than empty HTTP/0.9 response.
[email protected]aecfbf22008-10-16 02:02:47893 return ERR_EMPTY_RESPONSE;
894 }
895
[email protected]aecfbf22008-10-16 02:02:47896 return OK;
897}
898
initial.commit586acc5fe2008-07-26 22:42:52899int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
[email protected]0b45559b2009-06-12 21:45:11900 // We can get a certificate error or ERR_SSL_CLIENT_AUTH_CERT_NEEDED here
901 // due to SSL renegotiation.
[email protected]8e6441ca2010-08-19 05:56:38902 if (IsCertificateError(result)) {
903 // We don't handle a certificate error during SSL renegotiation, so we
904 // have to return an error that's not in the certificate error range
905 // (-2xx).
906 LOG(ERROR) << "Got a server certificate with error " << result
907 << " during SSL renegotiation";
908 result = ERR_CERT_ERROR_IN_SSL_RENEGOTIATION;
909 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
910 // TODO(wtc): Need a test case for this code path!
911 DCHECK(stream_.get());
912 DCHECK(is_https_request());
913 response_.cert_request_info = new SSLCertRequestInfo;
[email protected]90499482013-06-01 00:39:50914 stream_->GetSSLCertRequestInfo(response_.cert_request_info.get());
[email protected]8e6441ca2010-08-19 05:56:38915 result = HandleCertificateRequest(result);
916 if (result == OK)
917 return result;
[email protected]2181ea002009-06-09 01:37:27918 }
919
[email protected]4d283b32013-10-17 12:57:27920 if (result == ERR_QUIC_HANDSHAKE_FAILED) {
921 ResetConnectionAndRequestForResend();
922 return OK;
923 }
924
[email protected]0877e3d2009-10-17 22:29:57925 if (result < 0 && result != ERR_CONNECTION_CLOSED)
initial.commit586acc5fe2008-07-26 22:42:52926 return HandleIOError(result);
927
[email protected]0877e3d2009-10-17 22:29:57928 if (result == ERR_CONNECTION_CLOSED && ShouldResendRequest(result)) {
[email protected]1c773ea12009-04-28 19:58:42929 ResetConnectionAndRequestForResend();
[email protected]0877e3d2009-10-17 22:29:57930 return OK;
[email protected]1c773ea12009-04-28 19:58:42931 }
[email protected]2a5c76b2008-09-25 22:15:16932
[email protected]0877e3d2009-10-17 22:29:57933 // After we call RestartWithAuth a new response_time will be recorded, and
934 // we need to be cautious about incorrectly logging the duration across the
935 // authentication activity.
[email protected]8e6441ca2010-08-19 05:56:38936 if (result == OK)
937 LogTransactionConnectedMetrics();
initial.commit586acc5fe2008-07-26 22:42:52938
[email protected]0877e3d2009-10-17 22:29:57939 if (result == ERR_CONNECTION_CLOSED) {
[email protected]02c92c492010-03-08 21:28:14940 // For now, if we get at least some data, we do the best we can to make
[email protected]9492e4a2010-02-24 00:58:46941 // sense of it and send it back up the stack.
[email protected]0e75a732008-10-16 20:36:09942 int rv = HandleConnectionClosedBeforeEndOfHeaders();
[email protected]aecfbf22008-10-16 02:02:47943 if (rv != OK)
944 return rv;
[email protected]0877e3d2009-10-17 22:29:57945 }
[email protected]90499482013-06-01 00:39:50946 DCHECK(response_.headers.get());
initial.commit586acc5fe2008-07-26 22:42:52947
[email protected]3d498f72013-10-28 21:17:40948#if defined(SPDY_PROXY_AUTH_ORIGIN)
[email protected]ebab0c12013-10-20 05:25:38949 // Server-induced fallback; see: http://crbug.com/143712
950 if (response_.was_fetched_via_proxy && response_.headers.get() != NULL) {
[email protected]6ee97bc92013-11-08 00:51:18951 ProxyService::DataReductionProxyBypassEventType proxy_bypass_event =
952 ProxyService::BYPASS_EVENT_TYPE_MAX;
[email protected]3d498f72013-10-28 21:17:40953 base::TimeDelta bypass_duration;
954 bool chrome_proxy_used =
[email protected]6ee97bc92013-11-08 00:51:18955 proxy_info_.proxy_server().isDataReductionProxy();
956 bool chrome_fallback_proxy_used = false;
[email protected]3d498f72013-10-28 21:17:40957#if defined(DATA_REDUCTION_FALLBACK_HOST)
958 if (!chrome_proxy_used) {
[email protected]6ee97bc92013-11-08 00:51:18959 chrome_fallback_proxy_used =
960 proxy_info_.proxy_server().isDataReductionProxyFallback();
[email protected]3d498f72013-10-28 21:17:40961 }
962#endif
[email protected]3d498f72013-10-28 21:17:40963
[email protected]6ee97bc92013-11-08 00:51:18964 if (chrome_proxy_used || chrome_fallback_proxy_used) {
965 if (response_.headers->GetChromeProxyInfo(&bypass_duration)) {
966 proxy_bypass_event =
967 (bypass_duration < base::TimeDelta::FromMinutes(30) ?
968 ProxyService::SHORT_BYPASS :
969 ProxyService::LONG_BYPASS);
970 } else {
971 // Additionally, fallback if a 500 is returned via the data reduction
972 // proxy. This is conservative, as the 500 might have been generated by
973 // the origin, and not the proxy.
974 if (response_.headers->response_code() == HTTP_INTERNAL_SERVER_ERROR)
975 proxy_bypass_event = ProxyService::INTERNAL_SERVER_ERROR_BYPASS;
976 }
977
978 if (proxy_bypass_event < ProxyService::BYPASS_EVENT_TYPE_MAX) {
979 ProxyService* proxy_service = session_->proxy_service();
980
981 proxy_service->RecordDataReductionProxyBypassInfo(
982 chrome_proxy_used, proxy_info_.proxy_server(), proxy_bypass_event);
983
984 if (proxy_service->MarkProxyAsBad(proxy_info_, bypass_duration,
985 net_log_)) {
986 // Only retry in the case of GETs. We don't want to resubmit a POST
987 // if the proxy took some action.
988 if (request_->method == "GET") {
989 ResetConnectionAndRequestForResend();
990 return OK;
991 }
[email protected]14b7e9a2012-10-16 19:51:29992 }
993 }
994 }
995 }
[email protected]3d498f72013-10-28 21:17:40996#endif
[email protected]14b7e9a2012-10-16 19:51:29997
[email protected]93f8b562012-03-27 01:00:16998 // Like Net.HttpResponseCode, but only for MAIN_FRAME loads.
999 if (request_->load_flags & LOAD_MAIN_FRAME) {
1000 const int response_code = response_.headers->response_code();
1001 UMA_HISTOGRAM_ENUMERATION(
1002 "Net.HttpResponseCode_Nxx_MainFrame", response_code/100, 10);
1003 }
1004
[email protected]3abacd62012-06-10 20:20:321005 net_log_.AddEvent(
1006 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
1007 base::Bind(&HttpResponseHeaders::NetLogCallback, response_.headers));
[email protected]dbb83db2010-05-11 18:13:391008
[email protected]a7e41312009-12-16 23:18:141009 if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0)) {
[email protected]0877e3d2009-10-17 22:29:571010 // HTTP/0.9 doesn't support the PUT method, so lack of response headers
1011 // indicates a buggy server. See:
1012 // https://bugzilla.mozilla.org/show_bug.cgi?id=193921
1013 if (request_->method == "PUT")
1014 return ERR_METHOD_NOT_SUPPORTED;
1015 }
[email protected]4ddaf2502008-10-23 18:26:191016
[email protected]0877e3d2009-10-17 22:29:571017 // Check for an intermediate 100 Continue response. An origin server is
1018 // allowed to send this response even if we didn't ask for it, so we just
1019 // need to skip over it.
1020 // We treat any other 1xx in this same way (although in practice getting
1021 // a 1xx that isn't a 100 is rare).
[email protected]831e4a32013-11-14 02:14:441022 // Unless this is a WebSocket request, in which case we pass it on up.
1023 if (response_.headers->response_code() / 100 == 1 &&
1024 !ForWebSocketHandshake()) {
[email protected]007b3f82013-04-09 08:46:451025 response_.headers = new HttpResponseHeaders(std::string());
[email protected]0877e3d2009-10-17 22:29:571026 next_state_ = STATE_READ_HEADERS;
1027 return OK;
1028 }
1029
[email protected]8e6441ca2010-08-19 05:56:381030 HostPortPair endpoint = HostPortPair(request_->url.HostNoBrackets(),
1031 request_->url.EffectiveIntPort());
1032 ProcessAlternateProtocol(session_->http_stream_factory(),
[email protected]17291a022011-10-10 07:32:531033 session_->http_server_properties(),
[email protected]90499482013-06-01 00:39:501034 *response_.headers.get(),
[email protected]8e6441ca2010-08-19 05:56:381035 endpoint);
[email protected]564b4912010-03-09 16:30:421036
[email protected]e772db3f2010-07-12 18:11:131037 int rv = HandleAuthChallenge();
[email protected]0877e3d2009-10-17 22:29:571038 if (rv != OK)
1039 return rv;
1040
[email protected]8536ef52010-09-30 16:18:211041 if (is_https_request())
1042 stream_->GetSSLInfo(&response_.ssl_info);
1043
[email protected]0877e3d2009-10-17 22:29:571044 headers_valid_ = true;
1045 return OK;
initial.commit586acc5fe2008-07-26 22:42:521046}
1047
1048int HttpNetworkTransaction::DoReadBody() {
[email protected]90499482013-06-01 00:39:501049 DCHECK(read_buf_.get());
[email protected]6501bc02009-06-25 20:55:131050 DCHECK_GT(read_buf_len_, 0);
[email protected]8e6441ca2010-08-19 05:56:381051 DCHECK(stream_ != NULL);
initial.commit586acc5fe2008-07-26 22:42:521052
1053 next_state_ = STATE_READ_BODY_COMPLETE;
[email protected]90499482013-06-01 00:39:501054 return stream_->ReadResponseBody(
1055 read_buf_.get(), read_buf_len_, io_callback_);
initial.commit586acc5fe2008-07-26 22:42:521056}
1057
1058int HttpNetworkTransaction::DoReadBodyComplete(int result) {
1059 // We are done with the Read call.
[email protected]8e6441ca2010-08-19 05:56:381060 bool done = false;
1061 if (result <= 0) {
1062 DCHECK_NE(ERR_IO_PENDING, result);
initial.commit586acc5fe2008-07-26 22:42:521063 done = true;
[email protected]8e6441ca2010-08-19 05:56:381064 }
[email protected]9492e4a2010-02-24 00:58:461065
[email protected]8e6441ca2010-08-19 05:56:381066 bool keep_alive = false;
[email protected]351ab642010-08-05 16:55:311067 if (stream_->IsResponseBodyComplete()) {
[email protected]8e6441ca2010-08-19 05:56:381068 // Note: Just because IsResponseBodyComplete is true, we're not
1069 // necessarily "done". We're only "done" when it is the last
1070 // read on this HttpNetworkTransaction, which will be signified
1071 // by a zero-length read.
1072 // TODO(mbelshe): The keepalive property is really a property of
1073 // the stream. No need to compute it here just to pass back
1074 // to the stream's Close function.
[email protected]5c6908e2012-08-06 18:53:471075 // TODO(rtenneti): CanFindEndOfResponse should return false if there are no
1076 // ResponseHeaders.
1077 if (stream_->CanFindEndOfResponse()) {
1078 HttpResponseHeaders* headers = GetResponseHeaders();
1079 if (headers)
1080 keep_alive = headers->IsKeepAlive();
1081 }
initial.commit586acc5fe2008-07-26 22:42:521082 }
1083
[email protected]8e6441ca2010-08-19 05:56:381084 // Clean up connection if we are done.
initial.commit586acc5fe2008-07-26 22:42:521085 if (done) {
[email protected]56300172008-11-06 18:42:551086 LogTransactionMetrics();
[email protected]8e6441ca2010-08-19 05:56:381087 stream_->Close(!keep_alive);
[email protected]e2a915a2010-08-19 07:55:011088 // Note: we don't reset the stream here. We've closed it, but we still
1089 // need it around so that callers can call methods such as
1090 // GetUploadProgress() and have them be meaningful.
1091 // TODO(mbelshe): This means we closed the stream here, and we close it
1092 // again in ~HttpNetworkTransaction. Clean that up.
1093
[email protected]8e6441ca2010-08-19 05:56:381094 // The next Read call will return 0 (EOF).
initial.commit586acc5fe2008-07-26 22:42:521095 }
1096
1097 // Clear these to avoid leaving around old state.
1098 read_buf_ = NULL;
1099 read_buf_len_ = 0;
1100
1101 return result;
1102}
1103
[email protected]2d2697f92009-02-18 21:00:321104int HttpNetworkTransaction::DoDrainBodyForAuthRestart() {
1105 // This method differs from DoReadBody only in the next_state_. So we just
1106 // call DoReadBody and override the next_state_. Perhaps there is a more
1107 // elegant way for these two methods to share code.
1108 int rv = DoReadBody();
1109 DCHECK(next_state_ == STATE_READ_BODY_COMPLETE);
1110 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE;
1111 return rv;
1112}
1113
[email protected]0877e3d2009-10-17 22:29:571114// TODO(wtc): This method and the DoReadBodyComplete method are almost
1115// the same. Figure out a good way for these two methods to share code.
[email protected]2d2697f92009-02-18 21:00:321116int HttpNetworkTransaction::DoDrainBodyForAuthRestartComplete(int result) {
[email protected]68873ba2009-06-04 21:49:231117 // keep_alive defaults to true because the very reason we're draining the
1118 // response body is to reuse the connection for auth restart.
1119 bool done = false, keep_alive = true;
[email protected]2d2697f92009-02-18 21:00:321120 if (result < 0) {
[email protected]0877e3d2009-10-17 22:29:571121 // Error or closed connection while reading the socket.
[email protected]2d2697f92009-02-18 21:00:321122 done = true;
[email protected]68873ba2009-06-04 21:49:231123 keep_alive = false;
[email protected]351ab642010-08-05 16:55:311124 } else if (stream_->IsResponseBodyComplete()) {
[email protected]0877e3d2009-10-17 22:29:571125 done = true;
[email protected]2d2697f92009-02-18 21:00:321126 }
1127
1128 if (done) {
1129 DidDrainBodyForAuthRestart(keep_alive);
1130 } else {
1131 // Keep draining.
1132 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
1133 }
1134
1135 return OK;
1136}
1137
[email protected]8e3d2d32010-06-13 18:46:231138void HttpNetworkTransaction::LogTransactionConnectedMetrics() {
1139 if (logged_response_time_)
1140 return;
1141
1142 logged_response_time_ = true;
1143
[email protected]a7e41312009-12-16 23:18:141144 base::TimeDelta total_duration = response_.response_time - start_time_;
[email protected]9a0a55f2009-04-13 23:23:031145
[email protected]d6b55392011-08-05 04:04:351146 UMA_HISTOGRAM_CUSTOM_TIMES(
1147 "Net.Transaction_Connected",
[email protected]510e854f2009-04-20 18:39:081148 total_duration,
[email protected]9a0a55f2009-04-13 23:23:031149 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1150 100);
[email protected]1fa47592009-07-27 22:45:001151
[email protected]c38ec5a2010-08-25 23:32:381152 bool reused_socket = stream_->IsConnectionReused();
1153 if (!reused_socket) {
[email protected]d6b55392011-08-05 04:04:351154 UMA_HISTOGRAM_CUSTOM_TIMES(
1155 "Net.Transaction_Connected_New_b",
[email protected]b01998a2009-04-21 01:01:111156 total_duration,
1157 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1158 100);
[email protected]0310d432009-08-25 07:49:521159 }
1160
[email protected]31ae7ab2012-04-24 21:09:051161 // Currently, non-HIGHEST priority requests are frame or sub-frame resource
[email protected]510e854f2009-04-20 18:39:081162 // types. This will change when we also prioritize certain subresources like
1163 // css, js, etc.
[email protected]262eec82013-03-19 21:01:361164 if (priority_ != HIGHEST) {
[email protected]d6b55392011-08-05 04:04:351165 UMA_HISTOGRAM_CUSTOM_TIMES(
1166 "Net.Priority_High_Latency_b",
[email protected]510e854f2009-04-20 18:39:081167 total_duration,
1168 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1169 100);
1170 } else {
[email protected]d6b55392011-08-05 04:04:351171 UMA_HISTOGRAM_CUSTOM_TIMES(
1172 "Net.Priority_Low_Latency_b",
[email protected]510e854f2009-04-20 18:39:081173 total_duration,
1174 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1175 100);
1176 }
[email protected]9a0a55f2009-04-13 23:23:031177}
1178
[email protected]56300172008-11-06 18:42:551179void HttpNetworkTransaction::LogTransactionMetrics() const {
[email protected]0877e3d2009-10-17 22:29:571180 base::TimeDelta duration = base::Time::Now() -
[email protected]2227c692010-05-04 15:36:111181 response_.request_time;
[email protected]56300172008-11-06 18:42:551182 if (60 < duration.InMinutes())
1183 return;
[email protected]0b48db42009-03-23 02:45:111184
[email protected]21b316a2009-03-23 18:25:061185 base::TimeDelta total_duration = base::Time::Now() - start_time_;
1186
[email protected]d6b55392011-08-05 04:04:351187 UMA_HISTOGRAM_CUSTOM_TIMES("Net.Transaction_Latency_b", duration,
1188 base::TimeDelta::FromMilliseconds(1),
1189 base::TimeDelta::FromMinutes(10),
1190 100);
1191 UMA_HISTOGRAM_CUSTOM_TIMES("Net.Transaction_Latency_Total",
1192 total_duration,
1193 base::TimeDelta::FromMilliseconds(1),
1194 base::TimeDelta::FromMinutes(10), 100);
[email protected]5c68d692011-08-24 04:59:411195
[email protected]c38ec5a2010-08-25 23:32:381196 if (!stream_->IsConnectionReused()) {
[email protected]d6b55392011-08-05 04:04:351197 UMA_HISTOGRAM_CUSTOM_TIMES(
1198 "Net.Transaction_Latency_Total_New_Connection",
[email protected]808f6402009-03-30 20:02:071199 total_duration, base::TimeDelta::FromMilliseconds(1),
1200 base::TimeDelta::FromMinutes(10), 100);
1201 }
[email protected]56300172008-11-06 18:42:551202}
1203
[email protected]5e363962009-06-19 19:57:011204int HttpNetworkTransaction::HandleCertificateRequest(int error) {
[email protected]8e6441ca2010-08-19 05:56:381205 // There are two paths through which the server can request a certificate
1206 // from us. The first is during the initial handshake, the second is
1207 // during SSL renegotiation.
1208 //
1209 // In both cases, we want to close the connection before proceeding.
1210 // We do this for two reasons:
1211 // First, we don't want to keep the connection to the server hung for a
1212 // long time while the user selects a certificate.
1213 // Second, even if we did keep the connection open, NSS has a bug where
1214 // restarting the handshake for ClientAuth is currently broken.
[email protected]65a3b912010-08-21 05:46:581215 DCHECK_EQ(error, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]8e6441ca2010-08-19 05:56:381216
1217 if (stream_.get()) {
1218 // Since we already have a stream, we're being called as part of SSL
1219 // renegotiation.
1220 DCHECK(!stream_request_.get());
1221 stream_->Close(true);
1222 stream_.reset();
1223 }
1224
[email protected]26816882010-10-14 18:03:091225 // The server is asking for a client certificate during the initial
1226 // handshake.
1227 stream_request_.reset();
[email protected]5e363962009-06-19 19:57:011228
[email protected]ec229bc92010-11-22 09:51:451229 // If the user selected one of the certificates in client_certs or declined
1230 // to provide one for this server before, use the past decision
1231 // automatically.
1232 scoped_refptr<X509Certificate> client_cert;
1233 bool found_cached_cert = session_->ssl_client_auth_cache()->Lookup(
1234 response_.cert_request_info->host_and_port, &client_cert);
1235 if (!found_cached_cert)
1236 return error;
1237
1238 // Check that the certificate selected is still a certificate the server
1239 // is likely to accept, based on the criteria supplied in the
1240 // CertificateRequest message.
[email protected]90499482013-06-01 00:39:501241 if (client_cert.get()) {
[email protected]f1958c382013-02-07 00:15:261242 const std::vector<std::string>& cert_authorities =
1243 response_.cert_request_info->cert_authorities;
[email protected]ec229bc92010-11-22 09:51:451244
[email protected]f1958c382013-02-07 00:15:261245 bool cert_still_valid = cert_authorities.empty() ||
1246 client_cert->IsIssuedByEncoded(cert_authorities);
[email protected]ec229bc92010-11-22 09:51:451247 if (!cert_still_valid)
1248 return error;
[email protected]5e363962009-06-19 19:57:011249 }
[email protected]ec229bc92010-11-22 09:51:451250
1251 // TODO(davidben): Add a unit test which covers this path; we need to be
1252 // able to send a legitimate certificate and also bypass/clear the
1253 // SSL session cache.
[email protected]102957f2011-09-02 17:10:141254 SSLConfig* ssl_config = response_.cert_request_info->is_proxy ?
1255 &proxy_ssl_config_ : &server_ssl_config_;
1256 ssl_config->send_client_cert = true;
1257 ssl_config->client_cert = client_cert;
[email protected]ec229bc92010-11-22 09:51:451258 next_state_ = STATE_CREATE_STREAM;
1259 // Reset the other member variables.
1260 // Note: this is necessary only with SSL renegotiation.
1261 ResetStateForRestart();
1262 return OK;
[email protected]0b45559b2009-06-12 21:45:111263}
1264
[email protected]bd0b6772011-01-11 19:59:301265// TODO(rch): This does not correctly handle errors when an SSL proxy is
1266// being used, as all of the errors are handled as if they were generated
1267// by the endpoint host, request_->url, rather than considering if they were
[email protected]1c53a1f2011-01-13 00:36:381268// generated by the SSL proxy. http://crbug.com/69329
[email protected]bd0b6772011-01-11 19:59:301269int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
1270 DCHECK(request_);
[email protected]102957f2011-09-02 17:10:141271 if (server_ssl_config_.send_client_cert &&
[email protected]a1cb2cd2011-02-05 02:02:081272 (error == ERR_SSL_PROTOCOL_ERROR || IsClientCertificateError(error))) {
[email protected]bd0b6772011-01-11 19:59:301273 session_->ssl_client_auth_cache()->Remove(
1274 GetHostAndPort(request_->url));
1275 }
1276
[email protected]02d1d442013-08-10 13:38:261277 bool should_fallback = false;
[email protected]158ac972013-04-19 23:29:231278 uint16 version_max = server_ssl_config_.version_max;
1279
initial.commit586acc5fe2008-07-26 22:42:521280 switch (error) {
[email protected]bd0b6772011-01-11 19:59:301281 case ERR_SSL_PROTOCOL_ERROR:
1282 case ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
[email protected]158ac972013-04-19 23:29:231283 if (version_max >= SSL_PROTOCOL_VERSION_TLS1 &&
1284 version_max > server_ssl_config_.version_min) {
[email protected]80c75f682012-05-26 16:22:171285 // This could be a TLS-intolerant server or a server that chose a
1286 // cipher suite defined only for higher protocol versions (such as
1287 // an SSL 3.0 server that chose a TLS-only cipher suite). Fall
1288 // back to the next lower version and retry.
1289 // NOTE: if the SSLClientSocket class doesn't support TLS 1.1,
1290 // specifying TLS 1.1 in version_max will result in a TLS 1.0
1291 // handshake, so falling back from TLS 1.1 to TLS 1.0 will simply
1292 // repeat the TLS 1.0 handshake. To avoid this problem, the default
1293 // version_max should match the maximum protocol version supported
1294 // by the SSLClientSocket class.
[email protected]158ac972013-04-19 23:29:231295 version_max--;
[email protected]c57ec022013-11-25 21:30:511296
1297 // Fallback to the lower SSL version.
1298 // While SSL 3.0 fallback should be eliminated because of security
1299 // reasons, there is a high risk of breaking the servers if this is
1300 // done in general.
1301 // For now SSL 3.0 fallback is disabled for Google servers first,
1302 // and will be expanded to other servers after enough experiences
1303 // have been gained showing that this experiment works well with
1304 // today's Internet.
1305 if (version_max > SSL_PROTOCOL_VERSION_SSL3 ||
1306 (server_ssl_config_.unrestricted_ssl3_fallback_enabled ||
1307 !TransportSecurityState::IsGooglePinnedProperty(
1308 request_->url.host(), true /* include SNI */))) {
1309 should_fallback = true;
1310 }
[email protected]1c773ea12009-04-28 19:58:421311 }
initial.commit586acc5fe2008-07-26 22:42:521312 break;
[email protected]02d1d442013-08-10 13:38:261313 case ERR_SSL_BAD_RECORD_MAC_ALERT:
1314 if (version_max >= SSL_PROTOCOL_VERSION_TLS1_1 &&
1315 version_max > server_ssl_config_.version_min) {
1316 // Some broken SSL devices negotiate TLS 1.0 when sent a TLS 1.1 or
1317 // 1.2 ClientHello, but then return a bad_record_mac alert. See
1318 // crbug.com/260358. In order to make the fallback as minimal as
1319 // possible, this fallback is only triggered for >= TLS 1.1.
1320 version_max--;
1321 should_fallback = true;
1322 }
1323 break;
1324 }
1325
1326 if (should_fallback) {
1327 net_log_.AddEvent(
1328 NetLog::TYPE_SSL_VERSION_FALLBACK,
1329 base::Bind(&NetLogSSLVersionFallbackCallback,
1330 &request_->url, error, server_ssl_config_.version_max,
1331 version_max));
1332 server_ssl_config_.version_max = version_max;
1333 server_ssl_config_.version_fallback = true;
1334 ResetConnectionAndRequestForResend();
1335 error = OK;
initial.commit586acc5fe2008-07-26 22:42:521336 }
[email protected]158ac972013-04-19 23:29:231337
initial.commit586acc5fe2008-07-26 22:42:521338 return error;
1339}
1340
[email protected]bd0b6772011-01-11 19:59:301341// This method determines whether it is safe to resend the request after an
1342// IO error. It can only be called in response to request header or body
1343// write errors or response header read errors. It should not be used in
1344// other cases, such as a Connect error.
1345int HttpNetworkTransaction::HandleIOError(int error) {
1346 // SSL errors may happen at any time during the stream and indicate issues
1347 // with the underlying connection. Because the peer may request
1348 // renegotiation at any time, check and handle any possible SSL handshake
[email protected]80c75f682012-05-26 16:22:171349 // related errors. In addition to renegotiation, TLS False Start may cause
1350 // SSL handshake errors (specifically servers with buggy DEFLATE support)
1351 // to be delayed until the first Read on the underlying connection.
[email protected]bd0b6772011-01-11 19:59:301352 error = HandleSSLHandshakeError(error);
1353
1354 switch (error) {
1355 // If we try to reuse a connection that the server is in the process of
1356 // closing, we may end up successfully writing out our request (or a
1357 // portion of our request) only to find a connection error when we try to
1358 // read from (or finish writing to) the socket.
1359 case ERR_CONNECTION_RESET:
1360 case ERR_CONNECTION_CLOSED:
1361 case ERR_CONNECTION_ABORTED:
[email protected]202965992011-12-07 23:04:511362 // There can be a race between the socket pool checking checking whether a
1363 // socket is still connected, receiving the FIN, and sending/reading data
1364 // on a reused socket. If we receive the FIN between the connectedness
1365 // check and writing/reading from the socket, we may first learn the socket
1366 // is disconnected when we get a ERR_SOCKET_NOT_CONNECTED. This will most
1367 // likely happen when trying to retrieve its IP address.
1368 // See http://crbug.com/105824 for more details.
1369 case ERR_SOCKET_NOT_CONNECTED:
[email protected]bd0b6772011-01-11 19:59:301370 if (ShouldResendRequest(error)) {
[email protected]b6754252012-06-13 23:14:381371 net_log_.AddEventWithNetErrorCode(
1372 NetLog::TYPE_HTTP_TRANSACTION_RESTART_AFTER_ERROR, error);
[email protected]bd0b6772011-01-11 19:59:301373 ResetConnectionAndRequestForResend();
1374 error = OK;
1375 }
1376 break;
[email protected]5a60c8b2011-10-19 20:14:291377 case ERR_PIPELINE_EVICTION:
[email protected]5477d892012-03-01 21:31:311378 if (!session_->force_http_pipelining()) {
[email protected]b6754252012-06-13 23:14:381379 net_log_.AddEventWithNetErrorCode(
1380 NetLog::TYPE_HTTP_TRANSACTION_RESTART_AFTER_ERROR, error);
[email protected]5477d892012-03-01 21:31:311381 ResetConnectionAndRequestForResend();
1382 error = OK;
1383 }
1384 break;
[email protected]8753a122011-10-16 08:05:081385 case ERR_SPDY_PING_FAILED:
[email protected]721c0ce2011-10-13 02:41:001386 case ERR_SPDY_SERVER_REFUSED_STREAM:
[email protected]4d283b32013-10-17 12:57:271387 case ERR_QUIC_HANDSHAKE_FAILED:
[email protected]b6754252012-06-13 23:14:381388 net_log_.AddEventWithNetErrorCode(
1389 NetLog::TYPE_HTTP_TRANSACTION_RESTART_AFTER_ERROR, error);
[email protected]721c0ce2011-10-13 02:41:001390 ResetConnectionAndRequestForResend();
1391 error = OK;
1392 break;
[email protected]bd0b6772011-01-11 19:59:301393 }
1394 return error;
1395}
1396
[email protected]c3b35c22008-09-27 03:19:421397void HttpNetworkTransaction::ResetStateForRestart() {
[email protected]697ef4c2010-10-14 16:38:581398 ResetStateForAuthRestart();
1399 stream_.reset();
1400}
1401
1402void HttpNetworkTransaction::ResetStateForAuthRestart() {
[email protected]58e32bb2013-01-21 18:23:251403 send_start_time_ = base::TimeTicks();
1404 send_end_time_ = base::TimeTicks();
[email protected]58e32bb2013-01-21 18:23:251405
[email protected]0757e7702009-03-27 04:00:221406 pending_auth_target_ = HttpAuth::AUTH_NONE;
[email protected]c3b35c22008-09-27 03:19:421407 read_buf_ = NULL;
1408 read_buf_len_ = 0;
[email protected]0877e3d2009-10-17 22:29:571409 headers_valid_ = false;
[email protected]b94f92d2010-10-27 16:45:201410 request_headers_.Clear();
[email protected]a7e41312009-12-16 23:18:141411 response_ = HttpResponseInfo();
[email protected]8e6441ca2010-08-19 05:56:381412 establishing_tunnel_ = false;
[email protected]0877e3d2009-10-17 22:29:571413}
1414
1415HttpResponseHeaders* HttpNetworkTransaction::GetResponseHeaders() const {
[email protected]90499482013-06-01 00:39:501416 return response_.headers.get();
[email protected]c3b35c22008-09-27 03:19:421417}
1418
[email protected]a19f1c602009-08-24 21:35:281419bool HttpNetworkTransaction::ShouldResendRequest(int error) const {
[email protected]8e6441ca2010-08-19 05:56:381420 bool connection_is_proven = stream_->IsConnectionReused();
1421 bool has_received_headers = GetResponseHeaders() != NULL;
[email protected]58cebf8f2010-07-31 19:20:161422
[email protected]2a5c76b2008-09-25 22:15:161423 // NOTE: we resend a request only if we reused a keep-alive connection.
1424 // This automatically prevents an infinite resend loop because we'll run
1425 // out of the cached keep-alive connections eventually.
[email protected]8e6441ca2010-08-19 05:56:381426 if (connection_is_proven && !has_received_headers)
1427 return true;
1428 return false;
[email protected]1c773ea12009-04-28 19:58:421429}
1430
1431void HttpNetworkTransaction::ResetConnectionAndRequestForResend() {
[email protected]8e6441ca2010-08-19 05:56:381432 if (stream_.get()) {
1433 stream_->Close(true);
1434 stream_.reset();
[email protected]58cebf8f2010-07-31 19:20:161435 }
1436
[email protected]0877e3d2009-10-17 22:29:571437 // We need to clear request_headers_ because it contains the real request
1438 // headers, but we may need to resend the CONNECT request first to recreate
1439 // the SSL tunnel.
[email protected]b94f92d2010-10-27 16:45:201440 request_headers_.Clear();
[email protected]82918cc2010-08-25 17:24:501441 next_state_ = STATE_CREATE_STREAM; // Resend the request.
[email protected]86ec30d2008-09-29 21:53:541442}
1443
[email protected]1c773ea12009-04-28 19:58:421444bool HttpNetworkTransaction::ShouldApplyProxyAuth() const {
[email protected]2df19bb2010-08-25 20:13:461445 return !is_https_request() &&
1446 (proxy_info_.is_https() || proxy_info_.is_http());
[email protected]1c773ea12009-04-28 19:58:421447}
license.botbf09a502008-08-24 00:55:551448
[email protected]1c773ea12009-04-28 19:58:421449bool HttpNetworkTransaction::ShouldApplyServerAuth() const {
[email protected]8a1f3312010-05-25 19:25:041450 return !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA);
[email protected]1c773ea12009-04-28 19:58:421451}
1452
[email protected]e772db3f2010-07-12 18:11:131453int HttpNetworkTransaction::HandleAuthChallenge() {
[email protected]ad8e04a2010-11-01 04:16:271454 scoped_refptr<HttpResponseHeaders> headers(GetResponseHeaders());
[email protected]90499482013-06-01 00:39:501455 DCHECK(headers.get());
[email protected]c3b35c22008-09-27 03:19:421456
[email protected]0877e3d2009-10-17 22:29:571457 int status = headers->response_code();
[email protected]9094b602012-02-27 21:44:581458 if (status != HTTP_UNAUTHORIZED &&
1459 status != HTTP_PROXY_AUTHENTICATION_REQUIRED)
[email protected]c3b35c22008-09-27 03:19:421460 return OK;
[email protected]9094b602012-02-27 21:44:581461 HttpAuth::Target target = status == HTTP_PROXY_AUTHENTICATION_REQUIRED ?
[email protected]2227c692010-05-04 15:36:111462 HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER;
[email protected]038e9a32008-10-08 22:40:161463 if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct())
1464 return ERR_UNEXPECTED_PROXY_AUTH;
[email protected]c3b35c22008-09-27 03:19:421465
[email protected]9094b602012-02-27 21:44:581466 // This case can trigger when an HTTPS server responds with a "Proxy
1467 // authentication required" status code through a non-authenticating
1468 // proxy.
[email protected]7a67a8152010-11-05 18:31:101469 if (!auth_controllers_[target].get())
1470 return ERR_UNEXPECTED_PROXY_AUTH;
1471
[email protected]a7ea8832010-07-12 17:54:541472 int rv = auth_controllers_[target]->HandleAuthChallenge(
[email protected]560c0432010-07-13 20:45:311473 headers, (request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA) != 0, false,
1474 net_log_);
[email protected]228404f2010-06-24 04:31:411475 if (auth_controllers_[target]->HaveAuthHandler())
1476 pending_auth_target_ = target;
1477
1478 scoped_refptr<AuthChallengeInfo> auth_info =
1479 auth_controllers_[target]->auth_info();
1480 if (auth_info.get())
1481 response_.auth_challenge = auth_info;
1482
[email protected]228404f2010-06-24 04:31:411483 return rv;
[email protected]f9ee6b52008-11-08 06:46:231484}
1485
[email protected]8e6441ca2010-08-19 05:56:381486bool HttpNetworkTransaction::HaveAuth(HttpAuth::Target target) const {
1487 return auth_controllers_[target].get() &&
1488 auth_controllers_[target]->HaveAuth();
1489}
1490
[email protected]228404f2010-06-24 04:31:411491GURL HttpNetworkTransaction::AuthURL(HttpAuth::Target target) const {
1492 switch (target) {
[email protected]2df19bb2010-08-25 20:13:461493 case HttpAuth::AUTH_PROXY: {
[email protected]228404f2010-06-24 04:31:411494 if (!proxy_info_.proxy_server().is_valid() ||
1495 proxy_info_.proxy_server().is_direct()) {
1496 return GURL(); // There is no proxy server.
1497 }
[email protected]2df19bb2010-08-25 20:13:461498 const char* scheme = proxy_info_.is_https() ? "https://" : "http://";
1499 return GURL(scheme +
[email protected]2fbaecf22010-07-22 22:20:351500 proxy_info_.proxy_server().host_port_pair().ToString());
[email protected]2df19bb2010-08-25 20:13:461501 }
[email protected]228404f2010-06-24 04:31:411502 case HttpAuth::AUTH_SERVER:
1503 return request_->url;
1504 default:
1505 return GURL();
1506 }
[email protected]c3b35c22008-09-27 03:19:421507}
1508
[email protected]831e4a32013-11-14 02:14:441509bool HttpNetworkTransaction::ForWebSocketHandshake() const {
[email protected]23d3e022013-11-23 20:38:141510 return websocket_handshake_stream_base_create_helper_ &&
1511 request_->url.SchemeIsWSOrWSS();
[email protected]831e4a32013-11-14 02:14:441512}
1513
[email protected]d8eb84242010-09-25 02:25:061514#define STATE_CASE(s) \
1515 case s: \
1516 description = base::StringPrintf("%s (0x%08X)", #s, s); \
1517 break
[email protected]aef04272010-06-28 18:03:041518
1519std::string HttpNetworkTransaction::DescribeState(State state) {
1520 std::string description;
1521 switch (state) {
[email protected]82918cc2010-08-25 17:24:501522 STATE_CASE(STATE_CREATE_STREAM);
1523 STATE_CASE(STATE_CREATE_STREAM_COMPLETE);
[email protected]daddea62012-09-19 05:51:131524 STATE_CASE(STATE_INIT_REQUEST_BODY);
1525 STATE_CASE(STATE_INIT_REQUEST_BODY_COMPLETE);
[email protected]4875ba12011-03-30 22:31:511526 STATE_CASE(STATE_BUILD_REQUEST);
1527 STATE_CASE(STATE_BUILD_REQUEST_COMPLETE);
[email protected]aef04272010-06-28 18:03:041528 STATE_CASE(STATE_SEND_REQUEST);
1529 STATE_CASE(STATE_SEND_REQUEST_COMPLETE);
1530 STATE_CASE(STATE_READ_HEADERS);
1531 STATE_CASE(STATE_READ_HEADERS_COMPLETE);
[email protected]aef04272010-06-28 18:03:041532 STATE_CASE(STATE_READ_BODY);
1533 STATE_CASE(STATE_READ_BODY_COMPLETE);
1534 STATE_CASE(STATE_DRAIN_BODY_FOR_AUTH_RESTART);
1535 STATE_CASE(STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE);
[email protected]aef04272010-06-28 18:03:041536 STATE_CASE(STATE_NONE);
1537 default:
[email protected]d8eb84242010-09-25 02:25:061538 description = base::StringPrintf("Unknown state 0x%08X (%u)", state,
1539 state);
[email protected]aef04272010-06-28 18:03:041540 break;
1541 }
1542 return description;
1543}
1544
1545#undef STATE_CASE
1546
[email protected]c3b35c22008-09-27 03:19:421547} // namespace net