blob: d1e7ec58ce8be7edcf9e90e220c5a878a6350ca5 [file] [log] [blame]
[email protected]3b63f8f42011-03-28 01:54:151// Copyright (c) 2011 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]68bf9152008-09-25 19:47:3010#include "base/compiler_specific.h"
[email protected]270c6412010-03-29 22:02:4711#include "base/format_macros.h"
[email protected]3b63f8f42011-03-28 01:54:1512#include "base/memory/scoped_ptr.h"
[email protected]835d7c82010-10-14 04:38:3813#include "base/metrics/field_trial.h"
14#include "base/metrics/histogram.h"
15#include "base/metrics/stats_counters.h"
[email protected]7286e3fc2011-07-19 22:13:2416#include "base/stl_util.h"
[email protected]528c56d2010-07-30 19:28:4417#include "base/string_number_conversions.h"
[email protected]d8eb84242010-09-25 02:25:0618#include "base/string_util.h"
19#include "base/stringprintf.h"
[email protected]68bf9152008-09-25 19:47:3020#include "build/build_config.h"
[email protected]631f1322010-04-30 17:59:1121#include "googleurl/src/gurl.h"
[email protected]277d5942010-08-11 21:02:3522#include "net/base/auth.h"
[email protected]2d6728692011-03-12 01:39:5523#include "net/base/host_port_pair.h"
[email protected]74a85ce2009-02-12 00:03:1924#include "net/base/io_buffer.h"
initial.commit586acc5fe2008-07-26 22:42:5225#include "net/base/load_flags.h"
[email protected]597cf6e2009-05-29 09:43:2626#include "net/base/net_errors.h"
[email protected]c3b35c22008-09-27 03:19:4227#include "net/base/net_util.h"
[email protected]0b45559b2009-06-12 21:45:1128#include "net/base/ssl_cert_request_info.h"
[email protected]fc7de492010-07-12 14:49:0429#include "net/base/ssl_connection_status_flags.h"
initial.commit586acc5fe2008-07-26 22:42:5230#include "net/base/upload_data_stream.h"
[email protected]c3b35c22008-09-27 03:19:4231#include "net/http/http_auth.h"
32#include "net/http/http_auth_handler.h"
[email protected]fa82f932010-05-20 11:09:2433#include "net/http/http_auth_handler_factory.h"
[email protected]8d5a34e2009-06-11 21:21:3634#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5235#include "net/http/http_chunked_decoder.h"
[email protected]a7ea8832010-07-12 17:54:5436#include "net/http/http_net_log_params.h"
initial.commit586acc5fe2008-07-26 22:42:5237#include "net/http/http_network_session.h"
[email protected]a7ea8832010-07-12 17:54:5438#include "net/http/http_proxy_client_socket.h"
[email protected]e772db3f2010-07-12 18:11:1339#include "net/http/http_proxy_client_socket_pool.h"
[email protected]270c6412010-03-29 22:02:4740#include "net/http/http_request_headers.h"
initial.commit586acc5fe2008-07-26 22:42:5241#include "net/http/http_request_info.h"
[email protected]4bb1dc9e2010-09-23 22:36:5242#include "net/http/http_response_body_drainer.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]102e27c2011-02-23 01:01:3145#include "net/http/http_stream_factory.h"
initial.commit586acc5fe2008-07-26 22:42:5246#include "net/http/http_util.h"
[email protected]d7f16632010-03-29 18:02:3647#include "net/http/url_security_manager.h"
[email protected]f7984fc62009-06-22 23:26:4448#include "net/socket/client_socket_factory.h"
[email protected]a796bcec2010-03-22 17:17:2649#include "net/socket/socks_client_socket_pool.h"
[email protected]f7984fc62009-06-22 23:26:4450#include "net/socket/ssl_client_socket.h"
[email protected]e60e47a2010-07-14 03:37:1851#include "net/socket/ssl_client_socket_pool.h"
[email protected]ab739042011-04-07 15:22:2852#include "net/socket/transport_client_socket_pool.h"
[email protected]65d56aa2010-06-14 04:13:4053#include "net/spdy/spdy_http_stream.h"
[email protected]dab9c7d2010-02-06 21:44:3254#include "net/spdy/spdy_session.h"
55#include "net/spdy/spdy_session_pool.h"
initial.commit586acc5fe2008-07-26 22:42:5256
[email protected]e1acf6f2008-10-27 20:43:3357using base::Time;
58
initial.commit586acc5fe2008-07-26 22:42:5259namespace net {
60
[email protected]1c773ea12009-04-28 19:58:4261namespace {
62
[email protected]8e6441ca2010-08-19 05:56:3863void ProcessAlternateProtocol(HttpStreamFactory* factory,
64 HttpAlternateProtocols* alternate_protocols,
65 const HttpResponseHeaders& headers,
66 const HostPortPair& http_host_port_pair) {
[email protected]564b4912010-03-09 16:30:4267 std::string alternate_protocol_str;
[email protected]8e6441ca2010-08-19 05:56:3868
[email protected]564b4912010-03-09 16:30:4269 if (!headers.EnumerateHeader(NULL, HttpAlternateProtocols::kHeader,
70 &alternate_protocol_str)) {
71 // Header is not present.
72 return;
73 }
74
[email protected]8e6441ca2010-08-19 05:56:3875 factory->ProcessAlternateProtocol(alternate_protocols,
76 alternate_protocol_str,
77 http_host_port_pair);
[email protected]f45c1ee2010-08-03 00:54:3078}
79
[email protected]a1cb2cd2011-02-05 02:02:0880// Returns true if |error| is a client certificate authentication error.
81bool IsClientCertificateError(int error) {
82 switch (error) {
83 case ERR_BAD_SSL_CLIENT_AUTH_CERT:
84 case ERR_SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED:
85 case ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY:
86 case ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED:
87 return true;
88 default:
89 return false;
90 }
91}
92
[email protected]1c773ea12009-04-28 19:58:4293} // namespace
94
initial.commit586acc5fe2008-07-26 22:42:5295//-----------------------------------------------------------------------------
96
[email protected]5695b8c2009-09-30 21:36:4397HttpNetworkTransaction::HttpNetworkTransaction(HttpNetworkSession* session)
[email protected]0757e7702009-03-27 04:00:2298 : pending_auth_target_(HttpAuth::AUTH_NONE),
99 ALLOW_THIS_IN_INITIALIZER_LIST(
[email protected]68bf9152008-09-25 19:47:30100 io_callback_(this, &HttpNetworkTransaction::OnIOComplete)),
initial.commit586acc5fe2008-07-26 22:42:52101 user_callback_(NULL),
102 session_(session),
103 request_(NULL),
[email protected]0877e3d2009-10-17 22:29:57104 headers_valid_(false),
[email protected]8e3d2d32010-06-13 18:46:23105 logged_response_time_(false),
[email protected]b94f92d2010-10-27 16:45:20106 request_headers_(),
initial.commit586acc5fe2008-07-26 22:42:52107 read_buf_len_(0),
[email protected]a7ea8832010-07-12 17:54:54108 next_state_(STATE_NONE),
109 establishing_tunnel_(false) {
[email protected]102957f2011-09-02 17:10:14110 session->ssl_config_service()->GetSSLConfig(&server_ssl_config_);
111 if (session->http_stream_factory()->next_protos()) {
112 server_ssl_config_.next_protos =
113 *session->http_stream_factory()->next_protos();
114 }
[email protected]3ce7df0f2010-03-03 00:30:50115}
116
[email protected]0b0bf032010-09-21 18:08:50117HttpNetworkTransaction::~HttpNetworkTransaction() {
118 if (stream_.get()) {
119 HttpResponseHeaders* headers = GetResponseHeaders();
120 // TODO(mbelshe): The stream_ should be able to compute whether or not the
121 // stream should be kept alive. No reason to compute here
122 // and pass it in.
123 bool try_to_keep_alive =
124 next_state_ == STATE_NONE &&
125 stream_->CanFindEndOfResponse() &&
126 (!headers || headers->IsKeepAlive());
127 if (!try_to_keep_alive) {
128 stream_->Close(true /* not reusable */);
129 } else {
130 if (stream_->IsResponseBodyComplete()) {
131 // If the response body is complete, we can just reuse the socket.
132 stream_->Close(false /* reusable */);
[email protected]3a8d6852011-03-11 23:43:44133 } else if (stream_->IsSpdyHttpStream()) {
134 // Doesn't really matter for SpdyHttpStream. Just close it.
135 stream_->Close(true /* not reusable */);
[email protected]0b0bf032010-09-21 18:08:50136 } else {
137 // Otherwise, we try to drain the response body.
138 // TODO(willchan): Consider moving this response body draining to the
139 // stream implementation. For SPDY, there's clearly no point. For
140 // HTTP, it can vary depending on whether or not we're pipelining. It's
141 // stream dependent, so the different subtypes should be implementing
142 // their solutions.
[email protected]4bb1dc9e2010-09-23 22:36:52143 HttpResponseBodyDrainer* drainer =
144 new HttpResponseBodyDrainer(stream_.release());
[email protected]9b5e46cb2010-09-28 16:28:44145 drainer->Start(session_);
[email protected]4bb1dc9e2010-09-23 22:36:52146 // |drainer| will delete itself.
[email protected]0b0bf032010-09-21 18:08:50147 }
148 }
149 }
[email protected]0b0bf032010-09-21 18:08:50150}
151
[email protected]684970b2009-08-14 04:54:46152int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info,
153 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53154 const BoundNetLog& net_log) {
[email protected]5e2e6c77d12009-12-24 21:57:16155 SIMPLE_STATS_COUNTER("HttpNetworkTransaction.Count");
[email protected]5d0153c512009-01-12 19:08:36156
[email protected]9e743cd2010-03-16 07:03:53157 net_log_ = net_log;
[email protected]96d570e42008-08-05 22:43:04158 request_ = request_info;
[email protected]21b316a2009-03-23 18:25:06159 start_time_ = base::Time::Now();
[email protected]96d570e42008-08-05 22:43:04160
[email protected]6fbac162011-06-20 00:29:04161 if (request_->load_flags & LOAD_DISABLE_CERT_REVOCATION_CHECKING)
[email protected]102957f2011-09-02 17:10:14162 server_ssl_config_.rev_checking_enabled = false;
[email protected]6fbac162011-06-20 00:29:04163
[email protected]82918cc2010-08-25 17:24:50164 next_state_ = STATE_CREATE_STREAM;
[email protected]96d570e42008-08-05 22:43:04165 int rv = DoLoop(OK);
166 if (rv == ERR_IO_PENDING)
167 user_callback_ = callback;
168 return rv;
169}
170
171int HttpNetworkTransaction::RestartIgnoringLastError(
172 CompletionCallback* callback) {
[email protected]8e6441ca2010-08-19 05:56:38173 DCHECK(!stream_.get());
174 DCHECK(!stream_request_.get());
175 DCHECK_EQ(STATE_NONE, next_state_);
176
[email protected]82918cc2010-08-25 17:24:50177 next_state_ = STATE_CREATE_STREAM;
[email protected]8e6441ca2010-08-19 05:56:38178
[email protected]ccb40e52008-09-17 20:54:40179 int rv = DoLoop(OK);
180 if (rv == ERR_IO_PENDING)
181 user_callback_ = callback;
[email protected]aaead502008-10-15 00:20:11182 return rv;
[email protected]96d570e42008-08-05 22:43:04183}
184
[email protected]0b45559b2009-06-12 21:45:11185int HttpNetworkTransaction::RestartWithCertificate(
186 X509Certificate* client_cert,
187 CompletionCallback* callback) {
[email protected]8e6441ca2010-08-19 05:56:38188 // In HandleCertificateRequest(), we always tear down existing stream
189 // requests to force a new connection. So we shouldn't have one here.
190 DCHECK(!stream_request_.get());
191 DCHECK(!stream_.get());
192 DCHECK_EQ(STATE_NONE, next_state_);
193
[email protected]102957f2011-09-02 17:10:14194 SSLConfig* ssl_config = response_.cert_request_info->is_proxy ?
195 &proxy_ssl_config_ : &server_ssl_config_;
196 ssl_config->send_client_cert = true;
197 ssl_config->client_cert = client_cert;
[email protected]ec229bc92010-11-22 09:51:45198 session_->ssl_client_auth_cache()->Add(
199 response_.cert_request_info->host_and_port, client_cert);
[email protected]0b45559b2009-06-12 21:45:11200 // Reset the other member variables.
201 // Note: this is necessary only with SSL renegotiation.
202 ResetStateForRestart();
[email protected]82918cc2010-08-25 17:24:50203 next_state_ = STATE_CREATE_STREAM;
[email protected]0b45559b2009-06-12 21:45:11204 int rv = DoLoop(OK);
205 if (rv == ERR_IO_PENDING)
206 user_callback_ = callback;
207 return rv;
208}
209
[email protected]96d570e42008-08-05 22:43:04210int HttpNetworkTransaction::RestartWithAuth(
[email protected]13c8a092010-07-29 06:15:44211 const string16& username,
212 const string16& password,
[email protected]96d570e42008-08-05 22:43:04213 CompletionCallback* callback) {
[email protected]0757e7702009-03-27 04:00:22214 HttpAuth::Target target = pending_auth_target_;
215 if (target == HttpAuth::AUTH_NONE) {
216 NOTREACHED();
217 return ERR_UNEXPECTED;
218 }
[email protected]0757e7702009-03-27 04:00:22219 pending_auth_target_ = HttpAuth::AUTH_NONE;
[email protected]c3b35c22008-09-27 03:19:42220
[email protected]e772db3f2010-07-12 18:11:13221 auth_controllers_[target]->ResetAuth(username, password);
222
[email protected]8e6441ca2010-08-19 05:56:38223 DCHECK(user_callback_ == NULL);
224
225 int rv = OK;
226 if (target == HttpAuth::AUTH_PROXY && establishing_tunnel_) {
227 // In this case, we've gathered credentials for use with proxy
228 // authentication of a tunnel.
[email protected]82918cc2010-08-25 17:24:50229 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38230 DCHECK(stream_request_ != NULL);
[email protected]394816e92010-08-03 07:38:59231 auth_controllers_[target] = NULL;
[email protected]a7ea8832010-07-12 17:54:54232 ResetStateForRestart();
[email protected]8e6441ca2010-08-19 05:56:38233 rv = stream_request_->RestartTunnelWithProxyAuth(username, password);
[email protected]a7ea8832010-07-12 17:54:54234 } else {
[email protected]8e6441ca2010-08-19 05:56:38235 // In this case, we've gathered credentials for the server or the proxy
236 // but it is not during the tunneling phase.
237 DCHECK(stream_request_ == NULL);
[email protected]a7ea8832010-07-12 17:54:54238 PrepareForAuthRestart(target);
[email protected]8e6441ca2010-08-19 05:56:38239 rv = DoLoop(OK);
[email protected]a7ea8832010-07-12 17:54:54240 }
[email protected]c3b35c22008-09-27 03:19:42241
[email protected]c3b35c22008-09-27 03:19:42242 if (rv == ERR_IO_PENDING)
243 user_callback_ = callback;
[email protected]c3b35c22008-09-27 03:19:42244 return rv;
[email protected]96d570e42008-08-05 22:43:04245}
246
[email protected]f9ee6b52008-11-08 06:46:23247void HttpNetworkTransaction::PrepareForAuthRestart(HttpAuth::Target target) {
248 DCHECK(HaveAuth(target));
[email protected]8e6441ca2010-08-19 05:56:38249 DCHECK(!stream_request_.get());
250
[email protected]2d2697f92009-02-18 21:00:32251 bool keep_alive = false;
[email protected]0877e3d2009-10-17 22:29:57252 // Even if the server says the connection is keep-alive, we have to be
253 // able to find the end of each response in order to reuse the connection.
254 if (GetResponseHeaders()->IsKeepAlive() &&
[email protected]351ab642010-08-05 16:55:31255 stream_->CanFindEndOfResponse()) {
[email protected]0877e3d2009-10-17 22:29:57256 // If the response body hasn't been completely read, we need to drain
257 // it first.
[email protected]351ab642010-08-05 16:55:31258 if (!stream_->IsResponseBodyComplete()) {
[email protected]2d2697f92009-02-18 21:00:32259 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
[email protected]0877e3d2009-10-17 22:29:57260 read_buf_ = new IOBuffer(kDrainBodyBufferSize); // A bit bucket.
[email protected]2d2697f92009-02-18 21:00:32261 read_buf_len_ = kDrainBodyBufferSize;
262 return;
263 }
[email protected]0877e3d2009-10-17 22:29:57264 keep_alive = true;
[email protected]37832c6d2009-06-05 19:44:09265 }
266
[email protected]2d2697f92009-02-18 21:00:32267 // We don't need to drain the response body, so we act as if we had drained
268 // the response body.
269 DidDrainBodyForAuthRestart(keep_alive);
270}
271
272void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) {
[email protected]8e6441ca2010-08-19 05:56:38273 DCHECK(!stream_request_.get());
274
275 if (stream_.get()) {
[email protected]697ef4c2010-10-14 16:38:58276 HttpStream* new_stream = NULL;
[email protected]2d0a4f92011-05-05 16:38:46277 if (keep_alive && stream_->IsConnectionReusable()) {
[email protected]8e6441ca2010-08-19 05:56:38278 // We should call connection_->set_idle_time(), but this doesn't occur
279 // often enough to be worth the trouble.
280 stream_->SetConnectionReused();
[email protected]697ef4c2010-10-14 16:38:58281 new_stream = stream_->RenewStreamForAuth();
[email protected]8e6441ca2010-08-19 05:56:38282 }
[email protected]697ef4c2010-10-14 16:38:58283
284 if (!new_stream) {
[email protected]2d0a4f92011-05-05 16:38:46285 // Close the stream and mark it as not_reusable. Even in the
286 // keep_alive case, we've determined that the stream_ is not
287 // reusable if new_stream is NULL.
288 stream_->Close(true);
[email protected]697ef4c2010-10-14 16:38:58289 next_state_ = STATE_CREATE_STREAM;
290 } else {
291 next_state_ = STATE_INIT_STREAM;
292 }
293 stream_.reset(new_stream);
[email protected]2d2697f92009-02-18 21:00:32294 }
[email protected]f9ee6b52008-11-08 06:46:23295
296 // Reset the other member variables.
[email protected]697ef4c2010-10-14 16:38:58297 ResetStateForAuthRestart();
[email protected]f9ee6b52008-11-08 06:46:23298}
299
[email protected]8e6441ca2010-08-19 05:56:38300bool HttpNetworkTransaction::IsReadyToRestartForAuth() {
301 return pending_auth_target_ != HttpAuth::AUTH_NONE &&
302 HaveAuth(pending_auth_target_);
303}
304
[email protected]9dea9e1f2009-01-29 00:30:47305int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len,
[email protected]96d570e42008-08-05 22:43:04306 CompletionCallback* callback) {
[email protected]96d570e42008-08-05 22:43:04307 DCHECK(buf);
[email protected]e0c27be2009-07-15 13:09:35308 DCHECK_LT(0, buf_len);
[email protected]96d570e42008-08-05 22:43:04309
[email protected]1f14a912009-12-21 20:32:44310 State next_state = STATE_NONE;
[email protected]96d570e42008-08-05 22:43:04311
[email protected]ad8e04a2010-11-01 04:16:27312 scoped_refptr<HttpResponseHeaders> headers(GetResponseHeaders());
[email protected]8e6441ca2010-08-19 05:56:38313 if (headers_valid_ && headers.get() && stream_request_.get()) {
[email protected]8a1f3312010-05-25 19:25:04314 // We're trying to read the body of the response but we're still trying
[email protected]511f6f52010-12-17 03:58:29315 // to establish an SSL tunnel through an HTTP proxy. We can't read these
[email protected]8a1f3312010-05-25 19:25:04316 // bytes when establishing a tunnel because they might be controlled by
317 // an active network attacker. We don't worry about this for HTTP
318 // because an active network attacker can already control HTTP sessions.
[email protected]511f6f52010-12-17 03:58:29319 // We reach this case when the user cancels a 407 proxy auth prompt. We
320 // also don't worry about this for an HTTPS Proxy, because the
321 // communication with the proxy is secure.
[email protected]8a1f3312010-05-25 19:25:04322 // See http://crbug.com/8473.
[email protected]2df19bb2010-08-25 20:13:46323 DCHECK(proxy_info_.is_http() || proxy_info_.is_https());
[email protected]a7ea8832010-07-12 17:54:54324 DCHECK_EQ(headers->response_code(), 407);
325 LOG(WARNING) << "Blocked proxy response with status "
326 << headers->response_code() << " to CONNECT request for "
327 << GetHostAndPort(request_->url) << ".";
[email protected]8a1f3312010-05-25 19:25:04328 return ERR_TUNNEL_CONNECTION_FAILED;
[email protected]a8e9b162009-03-12 00:06:44329 }
330
[email protected]e60e47a2010-07-14 03:37:18331 // Are we using SPDY or HTTP?
[email protected]351ab642010-08-05 16:55:31332 next_state = STATE_READ_BODY;
[email protected]e60e47a2010-07-14 03:37:18333
[email protected]96d570e42008-08-05 22:43:04334 read_buf_ = buf;
335 read_buf_len_ = buf_len;
336
[email protected]1f14a912009-12-21 20:32:44337 next_state_ = next_state;
[email protected]96d570e42008-08-05 22:43:04338 int rv = DoLoop(OK);
339 if (rv == ERR_IO_PENDING)
340 user_callback_ = callback;
341 return rv;
342}
343
344const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const {
[email protected]a7e41312009-12-16 23:18:14345 return ((headers_valid_ && response_.headers) || response_.ssl_info.cert ||
346 response_.cert_request_info) ? &response_ : NULL;
[email protected]96d570e42008-08-05 22:43:04347}
348
349LoadState HttpNetworkTransaction::GetLoadState() const {
350 // TODO(wtc): Define a new LoadState value for the
351 // STATE_INIT_CONNECTION_COMPLETE state, which delays the HTTP request.
352 switch (next_state_) {
[email protected]82918cc2010-08-25 17:24:50353 case STATE_CREATE_STREAM_COMPLETE:
[email protected]8e6441ca2010-08-19 05:56:38354 return stream_request_->GetLoadState();
[email protected]044de0642010-06-17 10:42:15355 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE:
356 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE:
[email protected]0877e3d2009-10-17 22:29:57357 case STATE_SEND_REQUEST_COMPLETE:
[email protected]96d570e42008-08-05 22:43:04358 return LOAD_STATE_SENDING_REQUEST;
359 case STATE_READ_HEADERS_COMPLETE:
360 return LOAD_STATE_WAITING_FOR_RESPONSE;
361 case STATE_READ_BODY_COMPLETE:
362 return LOAD_STATE_READING_RESPONSE;
363 default:
364 return LOAD_STATE_IDLE;
365 }
366}
367
368uint64 HttpNetworkTransaction::GetUploadProgress() const {
[email protected]351ab642010-08-05 16:55:31369 if (!stream_.get())
[email protected]96d570e42008-08-05 22:43:04370 return 0;
371
[email protected]351ab642010-08-05 16:55:31372 return stream_->GetUploadProgress();
[email protected]96d570e42008-08-05 22:43:04373}
374
[email protected]102e27c2011-02-23 01:01:31375void HttpNetworkTransaction::OnStreamReady(const SSLConfig& used_ssl_config,
376 const ProxyInfo& used_proxy_info,
377 HttpStream* stream) {
[email protected]82918cc2010-08-25 17:24:50378 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38379 DCHECK(stream_request_.get());
380
381 stream_.reset(stream);
[email protected]102957f2011-09-02 17:10:14382 server_ssl_config_ = used_ssl_config;
[email protected]102e27c2011-02-23 01:01:31383 proxy_info_ = used_proxy_info;
[email protected]8e6441ca2010-08-19 05:56:38384 response_.was_npn_negotiated = stream_request_->was_npn_negotiated();
385 response_.was_fetched_via_spdy = stream_request_->using_spdy();
386 response_.was_fetched_via_proxy = !proxy_info_.is_direct();
[email protected]8e6441ca2010-08-19 05:56:38387
388 OnIOComplete(OK);
389}
390
[email protected]102e27c2011-02-23 01:01:31391void HttpNetworkTransaction::OnStreamFailed(int result,
392 const SSLConfig& used_ssl_config) {
[email protected]82918cc2010-08-25 17:24:50393 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38394 DCHECK_NE(OK, result);
395 DCHECK(stream_request_.get());
396 DCHECK(!stream_.get());
[email protected]102957f2011-09-02 17:10:14397 server_ssl_config_ = used_ssl_config;
[email protected]8e6441ca2010-08-19 05:56:38398
399 OnIOComplete(result);
400}
401
[email protected]102e27c2011-02-23 01:01:31402void HttpNetworkTransaction::OnCertificateError(
403 int result,
404 const SSLConfig& used_ssl_config,
405 const SSLInfo& ssl_info) {
[email protected]82918cc2010-08-25 17:24:50406 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38407 DCHECK_NE(OK, result);
408 DCHECK(stream_request_.get());
409 DCHECK(!stream_.get());
410
411 response_.ssl_info = ssl_info;
[email protected]102957f2011-09-02 17:10:14412 server_ssl_config_ = used_ssl_config;
[email protected]8e6441ca2010-08-19 05:56:38413
414 // TODO(mbelshe): For now, we're going to pass the error through, and that
415 // will close the stream_request in all cases. This means that we're always
[email protected]82918cc2010-08-25 17:24:50416 // going to restart an entire STATE_CREATE_STREAM, even if the connection is
417 // good and the user chooses to ignore the error. This is not ideal, but not
418 // the end of the world either.
[email protected]8e6441ca2010-08-19 05:56:38419
420 OnIOComplete(result);
421}
422
423void HttpNetworkTransaction::OnNeedsProxyAuth(
[email protected]6dc476da2010-09-01 04:43:50424 const HttpResponseInfo& proxy_response,
[email protected]102e27c2011-02-23 01:01:31425 const SSLConfig& used_ssl_config,
426 const ProxyInfo& used_proxy_info,
[email protected]6dc476da2010-09-01 04:43:50427 HttpAuthController* auth_controller) {
[email protected]8e6441ca2010-08-19 05:56:38428 DCHECK(stream_request_.get());
[email protected]82918cc2010-08-25 17:24:50429 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38430
431 establishing_tunnel_ = true;
432 response_.headers = proxy_response.headers;
433 response_.auth_challenge = proxy_response.auth_challenge;
434 headers_valid_ = true;
[email protected]102957f2011-09-02 17:10:14435 server_ssl_config_ = used_ssl_config;
[email protected]102e27c2011-02-23 01:01:31436 proxy_info_ = used_proxy_info;
[email protected]8e6441ca2010-08-19 05:56:38437
438 auth_controllers_[HttpAuth::AUTH_PROXY] = auth_controller;
439 pending_auth_target_ = HttpAuth::AUTH_PROXY;
440
441 DoCallback(OK);
442}
443
444void HttpNetworkTransaction::OnNeedsClientAuth(
[email protected]102e27c2011-02-23 01:01:31445 const SSLConfig& used_ssl_config,
[email protected]6dc476da2010-09-01 04:43:50446 SSLCertRequestInfo* cert_info) {
[email protected]82918cc2010-08-25 17:24:50447 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38448
[email protected]102957f2011-09-02 17:10:14449 server_ssl_config_ = used_ssl_config;
[email protected]8e6441ca2010-08-19 05:56:38450 response_.cert_request_info = cert_info;
[email protected]65a3b912010-08-21 05:46:58451 OnIOComplete(ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]8e6441ca2010-08-19 05:56:38452}
453
[email protected]511f6f52010-12-17 03:58:29454void HttpNetworkTransaction::OnHttpsProxyTunnelResponse(
455 const HttpResponseInfo& response_info,
[email protected]102e27c2011-02-23 01:01:31456 const SSLConfig& used_ssl_config,
457 const ProxyInfo& used_proxy_info,
[email protected]511f6f52010-12-17 03:58:29458 HttpStream* stream) {
459 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
460
461 headers_valid_ = true;
462 response_ = response_info;
[email protected]102957f2011-09-02 17:10:14463 server_ssl_config_ = used_ssl_config;
[email protected]102e27c2011-02-23 01:01:31464 proxy_info_ = used_proxy_info;
[email protected]511f6f52010-12-17 03:58:29465 stream_.reset(stream);
466 stream_request_.reset(); // we're done with the stream request
467 OnIOComplete(ERR_HTTPS_PROXY_TUNNEL_RESPONSE);
468}
469
[email protected]8e6441ca2010-08-19 05:56:38470bool HttpNetworkTransaction::is_https_request() const {
471 return request_->url.SchemeIs("https");
initial.commit586acc5fe2008-07-26 22:42:52472}
473
initial.commit586acc5fe2008-07-26 22:42:52474void HttpNetworkTransaction::DoCallback(int rv) {
[email protected]0b0bf032010-09-21 18:08:50475 DCHECK_NE(rv, ERR_IO_PENDING);
initial.commit586acc5fe2008-07-26 22:42:52476 DCHECK(user_callback_);
477
[email protected]96d570e42008-08-05 22:43:04478 // Since Run may result in Read being called, clear user_callback_ up front.
initial.commit586acc5fe2008-07-26 22:42:52479 CompletionCallback* c = user_callback_;
480 user_callback_ = NULL;
481 c->Run(rv);
482}
483
484void HttpNetworkTransaction::OnIOComplete(int result) {
485 int rv = DoLoop(result);
486 if (rv != ERR_IO_PENDING)
487 DoCallback(rv);
488}
489
490int HttpNetworkTransaction::DoLoop(int result) {
491 DCHECK(next_state_ != STATE_NONE);
492
493 int rv = result;
494 do {
495 State state = next_state_;
496 next_state_ = STATE_NONE;
497 switch (state) {
[email protected]82918cc2010-08-25 17:24:50498 case STATE_CREATE_STREAM:
499 DCHECK_EQ(OK, rv);
500 rv = DoCreateStream();
501 break;
502 case STATE_CREATE_STREAM_COMPLETE:
503 rv = DoCreateStreamComplete(rv);
504 break;
[email protected]351ab642010-08-05 16:55:31505 case STATE_INIT_STREAM:
506 DCHECK_EQ(OK, rv);
507 rv = DoInitStream();
508 break;
509 case STATE_INIT_STREAM_COMPLETE:
510 rv = DoInitStreamComplete(rv);
511 break;
[email protected]044de0642010-06-17 10:42:15512 case STATE_GENERATE_PROXY_AUTH_TOKEN:
513 DCHECK_EQ(OK, rv);
514 rv = DoGenerateProxyAuthToken();
515 break;
516 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE:
517 rv = DoGenerateProxyAuthTokenComplete(rv);
518 break;
519 case STATE_GENERATE_SERVER_AUTH_TOKEN:
520 DCHECK_EQ(OK, rv);
521 rv = DoGenerateServerAuthToken();
522 break;
523 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE:
524 rv = DoGenerateServerAuthTokenComplete(rv);
525 break;
[email protected]4875ba12011-03-30 22:31:51526 case STATE_BUILD_REQUEST:
[email protected]725355a2009-03-25 20:42:55527 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09528 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, NULL);
[email protected]4875ba12011-03-30 22:31:51529 rv = DoBuildRequest();
530 break;
531 case STATE_BUILD_REQUEST_COMPLETE:
532 rv = DoBuildRequestComplete(rv);
533 break;
534 case STATE_SEND_REQUEST:
535 DCHECK_EQ(OK, rv);
[email protected]0877e3d2009-10-17 22:29:57536 rv = DoSendRequest();
initial.commit586acc5fe2008-07-26 22:42:52537 break;
[email protected]0877e3d2009-10-17 22:29:57538 case STATE_SEND_REQUEST_COMPLETE:
539 rv = DoSendRequestComplete(rv);
[email protected]d7fd1782011-02-08 19:16:43540 net_log_.EndEventWithNetErrorCode(
541 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, rv);
initial.commit586acc5fe2008-07-26 22:42:52542 break;
543 case STATE_READ_HEADERS:
[email protected]725355a2009-03-25 20:42:55544 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09545 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, NULL);
initial.commit586acc5fe2008-07-26 22:42:52546 rv = DoReadHeaders();
547 break;
548 case STATE_READ_HEADERS_COMPLETE:
549 rv = DoReadHeadersComplete(rv);
[email protected]d7fd1782011-02-08 19:16:43550 net_log_.EndEventWithNetErrorCode(
551 NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, rv);
initial.commit586acc5fe2008-07-26 22:42:52552 break;
553 case STATE_READ_BODY:
[email protected]725355a2009-03-25 20:42:55554 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09555 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, NULL);
initial.commit586acc5fe2008-07-26 22:42:52556 rv = DoReadBody();
557 break;
558 case STATE_READ_BODY_COMPLETE:
559 rv = DoReadBodyComplete(rv);
[email protected]d7fd1782011-02-08 19:16:43560 net_log_.EndEventWithNetErrorCode(
561 NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, rv);
initial.commit586acc5fe2008-07-26 22:42:52562 break;
[email protected]2d2697f92009-02-18 21:00:32563 case STATE_DRAIN_BODY_FOR_AUTH_RESTART:
[email protected]725355a2009-03-25 20:42:55564 DCHECK_EQ(OK, rv);
[email protected]9e743cd2010-03-16 07:03:53565 net_log_.BeginEvent(
[email protected]ec11be62010-04-28 19:28:09566 NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART, NULL);
[email protected]2d2697f92009-02-18 21:00:32567 rv = DoDrainBodyForAuthRestart();
568 break;
569 case STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE:
570 rv = DoDrainBodyForAuthRestartComplete(rv);
[email protected]d7fd1782011-02-08 19:16:43571 net_log_.EndEventWithNetErrorCode(
572 NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART, rv);
[email protected]2d2697f92009-02-18 21:00:32573 break;
initial.commit586acc5fe2008-07-26 22:42:52574 default:
575 NOTREACHED() << "bad state";
576 rv = ERR_FAILED;
[email protected]96d570e42008-08-05 22:43:04577 break;
initial.commit586acc5fe2008-07-26 22:42:52578 }
579 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
580
581 return rv;
582}
583
[email protected]82918cc2010-08-25 17:24:50584int HttpNetworkTransaction::DoCreateStream() {
585 next_state_ = STATE_CREATE_STREAM_COMPLETE;
[email protected]351ab642010-08-05 16:55:31586
[email protected]26816882010-10-14 18:03:09587 stream_request_.reset(
588 session_->http_stream_factory()->RequestStream(
[email protected]102e27c2011-02-23 01:01:31589 *request_,
[email protected]102957f2011-09-02 17:10:14590 server_ssl_config_,
591 proxy_ssl_config_,
[email protected]26816882010-10-14 18:03:09592 this,
593 net_log_));
594 DCHECK(stream_request_.get());
[email protected]8e6441ca2010-08-19 05:56:38595 return ERR_IO_PENDING;
[email protected]351ab642010-08-05 16:55:31596}
597
[email protected]82918cc2010-08-25 17:24:50598int HttpNetworkTransaction::DoCreateStreamComplete(int result) {
[email protected]394816e92010-08-03 07:38:59599 if (result == OK) {
[email protected]82918cc2010-08-25 17:24:50600 next_state_ = STATE_INIT_STREAM;
[email protected]8e6441ca2010-08-19 05:56:38601 DCHECK(stream_.get());
[email protected]adb00242010-10-29 03:04:33602 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
603 result = HandleCertificateRequest(result);
[email protected]511f6f52010-12-17 03:58:29604 } else if (result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) {
605 // Return OK and let the caller read the proxy's error page
606 next_state_ = STATE_NONE;
607 return OK;
[email protected]394816e92010-08-03 07:38:59608 }
609
[email protected]bd0b6772011-01-11 19:59:30610 // Handle possible handshake errors that may have occurred if the stream
611 // used SSL for one or more of the layers.
612 result = HandleSSLHandshakeError(result);
613
[email protected]8e6441ca2010-08-19 05:56:38614 // At this point we are done with the stream_request_.
[email protected]26816882010-10-14 18:03:09615 stream_request_.reset();
[email protected]8e6441ca2010-08-19 05:56:38616 return result;
[email protected]394816e92010-08-03 07:38:59617}
618
[email protected]82918cc2010-08-25 17:24:50619int HttpNetworkTransaction::DoInitStream() {
620 DCHECK(stream_.get());
621 next_state_ = STATE_INIT_STREAM_COMPLETE;
622 return stream_->InitializeStream(request_, net_log_, &io_callback_);
623}
624
625int HttpNetworkTransaction::DoInitStreamComplete(int result) {
626 if (result == OK) {
627 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
[email protected]82918cc2010-08-25 17:24:50628 } else {
[email protected]82918cc2010-08-25 17:24:50629 if (result < 0)
[email protected]044dcc52010-09-17 15:44:26630 result = HandleIOError(result);
631
632 // The stream initialization failed, so this stream will never be useful.
633 stream_.reset();
[email protected]82918cc2010-08-25 17:24:50634 }
635
636 return result;
637}
638
[email protected]044de0642010-06-17 10:42:15639int HttpNetworkTransaction::DoGenerateProxyAuthToken() {
640 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE;
641 if (!ShouldApplyProxyAuth())
642 return OK;
[email protected]394816e92010-08-03 07:38:59643 HttpAuth::Target target = HttpAuth::AUTH_PROXY;
644 if (!auth_controllers_[target].get())
[email protected]3598c6022010-09-17 23:13:09645 auth_controllers_[target] =
646 new HttpAuthController(target,
647 AuthURL(target),
[email protected]102e27c2011-02-23 01:01:31648 session_->http_auth_cache(),
[email protected]3598c6022010-09-17 23:13:09649 session_->http_auth_handler_factory());
[email protected]394816e92010-08-03 07:38:59650 return auth_controllers_[target]->MaybeGenerateAuthToken(request_,
651 &io_callback_,
652 net_log_);
[email protected]044de0642010-06-17 10:42:15653}
654
655int HttpNetworkTransaction::DoGenerateProxyAuthTokenComplete(int rv) {
656 DCHECK_NE(ERR_IO_PENDING, rv);
657 if (rv == OK)
658 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN;
659 return rv;
660}
661
662int HttpNetworkTransaction::DoGenerateServerAuthToken() {
663 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE;
[email protected]394816e92010-08-03 07:38:59664 HttpAuth::Target target = HttpAuth::AUTH_SERVER;
665 if (!auth_controllers_[target].get())
[email protected]3598c6022010-09-17 23:13:09666 auth_controllers_[target] =
667 new HttpAuthController(target,
668 AuthURL(target),
[email protected]102e27c2011-02-23 01:01:31669 session_->http_auth_cache(),
[email protected]3598c6022010-09-17 23:13:09670 session_->http_auth_handler_factory());
[email protected]044de0642010-06-17 10:42:15671 if (!ShouldApplyServerAuth())
672 return OK;
[email protected]394816e92010-08-03 07:38:59673 return auth_controllers_[target]->MaybeGenerateAuthToken(request_,
674 &io_callback_,
675 net_log_);
[email protected]044de0642010-06-17 10:42:15676}
677
678int HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) {
679 DCHECK_NE(ERR_IO_PENDING, rv);
680 if (rv == OK)
[email protected]4875ba12011-03-30 22:31:51681 next_state_ = STATE_BUILD_REQUEST;
[email protected]044de0642010-06-17 10:42:15682 return rv;
683}
684
[email protected]2979a492011-04-06 00:29:14685void HttpNetworkTransaction::BuildRequestHeaders(bool using_proxy) {
686 request_headers_.SetHeader(HttpRequestHeaders::kHost,
687 GetHostAndOptionalPort(request_->url));
688
689 // For compat with HTTP/1.0 servers and proxies:
690 if (using_proxy) {
691 request_headers_.SetHeader(HttpRequestHeaders::kProxyConnection,
692 "keep-alive");
693 } else {
694 request_headers_.SetHeader(HttpRequestHeaders::kConnection, "keep-alive");
695 }
696
[email protected]2979a492011-04-06 00:29:14697 // Add a content length header?
698 if (request_body_.get()) {
699 if (request_body_->is_chunked()) {
700 request_headers_.SetHeader(
701 HttpRequestHeaders::kTransferEncoding, "chunked");
702 } else {
703 request_headers_.SetHeader(
704 HttpRequestHeaders::kContentLength,
705 base::Uint64ToString(request_body_->size()));
706 }
707 } else if (request_->method == "POST" || request_->method == "PUT" ||
708 request_->method == "HEAD") {
709 // An empty POST/PUT request still needs a content length. As for HEAD,
710 // IE and Safari also add a content length header. Presumably it is to
711 // support sending a HEAD request to an URL that only expects to be sent a
712 // POST or some other method that normally would have a message body.
713 request_headers_.SetHeader(HttpRequestHeaders::kContentLength, "0");
714 }
715
716 // Honor load flags that impact proxy caches.
717 if (request_->load_flags & LOAD_BYPASS_CACHE) {
718 request_headers_.SetHeader(HttpRequestHeaders::kPragma, "no-cache");
719 request_headers_.SetHeader(HttpRequestHeaders::kCacheControl, "no-cache");
720 } else if (request_->load_flags & LOAD_VALIDATE_CACHE) {
721 request_headers_.SetHeader(HttpRequestHeaders::kCacheControl, "max-age=0");
722 }
723
724 if (ShouldApplyProxyAuth() && HaveAuth(HttpAuth::AUTH_PROXY))
725 auth_controllers_[HttpAuth::AUTH_PROXY]->AddAuthorizationHeader(
726 &request_headers_);
727 if (ShouldApplyServerAuth() && HaveAuth(HttpAuth::AUTH_SERVER))
728 auth_controllers_[HttpAuth::AUTH_SERVER]->AddAuthorizationHeader(
729 &request_headers_);
730
[email protected]c10450102011-06-27 09:06:16731 request_headers_.MergeFrom(request_->extra_headers);
[email protected]2979a492011-04-06 00:29:14732}
733
[email protected]4875ba12011-03-30 22:31:51734int HttpNetworkTransaction::DoBuildRequest() {
735 next_state_ = STATE_BUILD_REQUEST_COMPLETE;
[email protected]4875ba12011-03-30 22:31:51736 request_body_.reset(NULL);
737 if (request_->upload_data) {
738 int error_code;
739 request_body_.reset(
740 UploadDataStream::Create(request_->upload_data, &error_code));
741 if (!request_body_.get())
742 return error_code;
743 }
744
745 headers_valid_ = false;
746
747 // This is constructed lazily (instead of within our Start method), so that
748 // we have proxy info available.
749 if (request_headers_.IsEmpty()) {
750 bool using_proxy = (proxy_info_.is_http() || proxy_info_.is_https()) &&
751 !is_https_request();
[email protected]2979a492011-04-06 00:29:14752 BuildRequestHeaders(using_proxy);
[email protected]4875ba12011-03-30 22:31:51753 }
754
[email protected]4875ba12011-03-30 22:31:51755 return OK;
756}
757
758int HttpNetworkTransaction::DoBuildRequestComplete(int result) {
[email protected]9f489d72011-04-04 23:29:24759 if (result == OK)
760 next_state_ = STATE_SEND_REQUEST;
[email protected]4875ba12011-03-30 22:31:51761 return result;
762}
763
[email protected]0877e3d2009-10-17 22:29:57764int HttpNetworkTransaction::DoSendRequest() {
765 next_state_ = STATE_SEND_REQUEST_COMPLETE;
766
[email protected]4875ba12011-03-30 22:31:51767 return stream_->SendRequest(
768 request_headers_, request_body_.release(), &response_, &io_callback_);
initial.commit586acc5fe2008-07-26 22:42:52769}
770
[email protected]0877e3d2009-10-17 22:29:57771int HttpNetworkTransaction::DoSendRequestComplete(int result) {
initial.commit586acc5fe2008-07-26 22:42:52772 if (result < 0)
773 return HandleIOError(result);
[email protected]0877e3d2009-10-17 22:29:57774 next_state_ = STATE_READ_HEADERS;
initial.commit586acc5fe2008-07-26 22:42:52775 return OK;
776}
777
778int HttpNetworkTransaction::DoReadHeaders() {
779 next_state_ = STATE_READ_HEADERS_COMPLETE;
[email protected]351ab642010-08-05 16:55:31780 return stream_->ReadResponseHeaders(&io_callback_);
initial.commit586acc5fe2008-07-26 22:42:52781}
782
[email protected]0e75a732008-10-16 20:36:09783int HttpNetworkTransaction::HandleConnectionClosedBeforeEndOfHeaders() {
[email protected]8e6441ca2010-08-19 05:56:38784 if (!response_.headers && !stream_->IsConnectionReused()) {
[email protected]0e75a732008-10-16 20:36:09785 // The connection was closed before any data was sent. Likely an error
786 // rather than empty HTTP/0.9 response.
[email protected]aecfbf22008-10-16 02:02:47787 return ERR_EMPTY_RESPONSE;
788 }
789
[email protected]aecfbf22008-10-16 02:02:47790 return OK;
791}
792
initial.commit586acc5fe2008-07-26 22:42:52793int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
[email protected]0b45559b2009-06-12 21:45:11794 // We can get a certificate error or ERR_SSL_CLIENT_AUTH_CERT_NEEDED here
795 // due to SSL renegotiation.
[email protected]8e6441ca2010-08-19 05:56:38796 if (IsCertificateError(result)) {
797 // We don't handle a certificate error during SSL renegotiation, so we
798 // have to return an error that's not in the certificate error range
799 // (-2xx).
800 LOG(ERROR) << "Got a server certificate with error " << result
801 << " during SSL renegotiation";
802 result = ERR_CERT_ERROR_IN_SSL_RENEGOTIATION;
803 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
804 // TODO(wtc): Need a test case for this code path!
805 DCHECK(stream_.get());
806 DCHECK(is_https_request());
807 response_.cert_request_info = new SSLCertRequestInfo;
808 stream_->GetSSLCertRequestInfo(response_.cert_request_info);
809 result = HandleCertificateRequest(result);
810 if (result == OK)
811 return result;
[email protected]2181ea002009-06-09 01:37:27812 }
813
[email protected]0877e3d2009-10-17 22:29:57814 if (result < 0 && result != ERR_CONNECTION_CLOSED)
initial.commit586acc5fe2008-07-26 22:42:52815 return HandleIOError(result);
816
[email protected]0877e3d2009-10-17 22:29:57817 if (result == ERR_CONNECTION_CLOSED && ShouldResendRequest(result)) {
[email protected]1c773ea12009-04-28 19:58:42818 ResetConnectionAndRequestForResend();
[email protected]0877e3d2009-10-17 22:29:57819 return OK;
[email protected]1c773ea12009-04-28 19:58:42820 }
[email protected]2a5c76b2008-09-25 22:15:16821
[email protected]0877e3d2009-10-17 22:29:57822 // After we call RestartWithAuth a new response_time will be recorded, and
823 // we need to be cautious about incorrectly logging the duration across the
824 // authentication activity.
[email protected]8e6441ca2010-08-19 05:56:38825 if (result == OK)
826 LogTransactionConnectedMetrics();
initial.commit586acc5fe2008-07-26 22:42:52827
[email protected]0877e3d2009-10-17 22:29:57828 if (result == ERR_CONNECTION_CLOSED) {
[email protected]02c92c492010-03-08 21:28:14829 // For now, if we get at least some data, we do the best we can to make
[email protected]9492e4a2010-02-24 00:58:46830 // sense of it and send it back up the stack.
[email protected]0e75a732008-10-16 20:36:09831 int rv = HandleConnectionClosedBeforeEndOfHeaders();
[email protected]aecfbf22008-10-16 02:02:47832 if (rv != OK)
833 return rv;
[email protected]0877e3d2009-10-17 22:29:57834 }
initial.commit586acc5fe2008-07-26 22:42:52835
[email protected]465aeb942010-10-14 19:58:14836 if (net_log_.IsLoggingAllEvents()) {
[email protected]8a1f3312010-05-25 19:25:04837 net_log_.AddEvent(
838 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
[email protected]00cd9c42010-11-02 20:15:57839 make_scoped_refptr(new NetLogHttpResponseParameter(response_.headers)));
[email protected]dbb83db2010-05-11 18:13:39840 }
841
[email protected]a7e41312009-12-16 23:18:14842 if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0)) {
[email protected]0877e3d2009-10-17 22:29:57843 // HTTP/0.9 doesn't support the PUT method, so lack of response headers
844 // indicates a buggy server. See:
845 // https://bugzilla.mozilla.org/show_bug.cgi?id=193921
846 if (request_->method == "PUT")
847 return ERR_METHOD_NOT_SUPPORTED;
848 }
[email protected]4ddaf2502008-10-23 18:26:19849
[email protected]0877e3d2009-10-17 22:29:57850 // Check for an intermediate 100 Continue response. An origin server is
851 // allowed to send this response even if we didn't ask for it, so we just
852 // need to skip over it.
853 // We treat any other 1xx in this same way (although in practice getting
854 // a 1xx that isn't a 100 is rare).
[email protected]a7e41312009-12-16 23:18:14855 if (response_.headers->response_code() / 100 == 1) {
[email protected]ee9410e72010-01-07 01:42:38856 response_.headers = new HttpResponseHeaders("");
[email protected]0877e3d2009-10-17 22:29:57857 next_state_ = STATE_READ_HEADERS;
858 return OK;
859 }
860
[email protected]8e6441ca2010-08-19 05:56:38861 HostPortPair endpoint = HostPortPair(request_->url.HostNoBrackets(),
862 request_->url.EffectiveIntPort());
863 ProcessAlternateProtocol(session_->http_stream_factory(),
864 session_->mutable_alternate_protocols(),
865 *response_.headers,
866 endpoint);
[email protected]564b4912010-03-09 16:30:42867
[email protected]e772db3f2010-07-12 18:11:13868 int rv = HandleAuthChallenge();
[email protected]0877e3d2009-10-17 22:29:57869 if (rv != OK)
870 return rv;
871
[email protected]8536ef52010-09-30 16:18:21872 if (is_https_request())
873 stream_->GetSSLInfo(&response_.ssl_info);
874
[email protected]0877e3d2009-10-17 22:29:57875 headers_valid_ = true;
876 return OK;
initial.commit586acc5fe2008-07-26 22:42:52877}
878
879int HttpNetworkTransaction::DoReadBody() {
880 DCHECK(read_buf_);
[email protected]6501bc02009-06-25 20:55:13881 DCHECK_GT(read_buf_len_, 0);
[email protected]8e6441ca2010-08-19 05:56:38882 DCHECK(stream_ != NULL);
initial.commit586acc5fe2008-07-26 22:42:52883
884 next_state_ = STATE_READ_BODY_COMPLETE;
[email protected]351ab642010-08-05 16:55:31885 return stream_->ReadResponseBody(read_buf_, read_buf_len_, &io_callback_);
initial.commit586acc5fe2008-07-26 22:42:52886}
887
888int HttpNetworkTransaction::DoReadBodyComplete(int result) {
889 // We are done with the Read call.
[email protected]8e6441ca2010-08-19 05:56:38890 bool done = false;
891 if (result <= 0) {
892 DCHECK_NE(ERR_IO_PENDING, result);
initial.commit586acc5fe2008-07-26 22:42:52893 done = true;
[email protected]8e6441ca2010-08-19 05:56:38894 }
[email protected]9492e4a2010-02-24 00:58:46895
[email protected]8e6441ca2010-08-19 05:56:38896 bool keep_alive = false;
[email protected]351ab642010-08-05 16:55:31897 if (stream_->IsResponseBodyComplete()) {
[email protected]8e6441ca2010-08-19 05:56:38898 // Note: Just because IsResponseBodyComplete is true, we're not
899 // necessarily "done". We're only "done" when it is the last
900 // read on this HttpNetworkTransaction, which will be signified
901 // by a zero-length read.
902 // TODO(mbelshe): The keepalive property is really a property of
903 // the stream. No need to compute it here just to pass back
904 // to the stream's Close function.
[email protected]351ab642010-08-05 16:55:31905 if (stream_->CanFindEndOfResponse())
[email protected]02c92c492010-03-08 21:28:14906 keep_alive = GetResponseHeaders()->IsKeepAlive();
initial.commit586acc5fe2008-07-26 22:42:52907 }
908
[email protected]8e6441ca2010-08-19 05:56:38909 // Clean up connection if we are done.
initial.commit586acc5fe2008-07-26 22:42:52910 if (done) {
[email protected]56300172008-11-06 18:42:55911 LogTransactionMetrics();
[email protected]5e6efa52011-06-27 17:26:41912 stream_->LogNumRttVsBytesMetrics();
[email protected]8e6441ca2010-08-19 05:56:38913 stream_->Close(!keep_alive);
[email protected]e2a915a2010-08-19 07:55:01914 // Note: we don't reset the stream here. We've closed it, but we still
915 // need it around so that callers can call methods such as
916 // GetUploadProgress() and have them be meaningful.
917 // TODO(mbelshe): This means we closed the stream here, and we close it
918 // again in ~HttpNetworkTransaction. Clean that up.
919
[email protected]8e6441ca2010-08-19 05:56:38920 // The next Read call will return 0 (EOF).
initial.commit586acc5fe2008-07-26 22:42:52921 }
922
923 // Clear these to avoid leaving around old state.
924 read_buf_ = NULL;
925 read_buf_len_ = 0;
926
927 return result;
928}
929
[email protected]2d2697f92009-02-18 21:00:32930int HttpNetworkTransaction::DoDrainBodyForAuthRestart() {
931 // This method differs from DoReadBody only in the next_state_. So we just
932 // call DoReadBody and override the next_state_. Perhaps there is a more
933 // elegant way for these two methods to share code.
934 int rv = DoReadBody();
935 DCHECK(next_state_ == STATE_READ_BODY_COMPLETE);
936 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE;
937 return rv;
938}
939
[email protected]0877e3d2009-10-17 22:29:57940// TODO(wtc): This method and the DoReadBodyComplete method are almost
941// the same. Figure out a good way for these two methods to share code.
[email protected]2d2697f92009-02-18 21:00:32942int HttpNetworkTransaction::DoDrainBodyForAuthRestartComplete(int result) {
[email protected]68873ba2009-06-04 21:49:23943 // keep_alive defaults to true because the very reason we're draining the
944 // response body is to reuse the connection for auth restart.
945 bool done = false, keep_alive = true;
[email protected]2d2697f92009-02-18 21:00:32946 if (result < 0) {
[email protected]0877e3d2009-10-17 22:29:57947 // Error or closed connection while reading the socket.
[email protected]2d2697f92009-02-18 21:00:32948 done = true;
[email protected]68873ba2009-06-04 21:49:23949 keep_alive = false;
[email protected]351ab642010-08-05 16:55:31950 } else if (stream_->IsResponseBodyComplete()) {
[email protected]0877e3d2009-10-17 22:29:57951 done = true;
[email protected]2d2697f92009-02-18 21:00:32952 }
953
954 if (done) {
955 DidDrainBodyForAuthRestart(keep_alive);
956 } else {
957 // Keep draining.
958 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
959 }
960
961 return OK;
962}
963
[email protected]8e3d2d32010-06-13 18:46:23964void HttpNetworkTransaction::LogTransactionConnectedMetrics() {
965 if (logged_response_time_)
966 return;
967
968 logged_response_time_ = true;
969
[email protected]a7e41312009-12-16 23:18:14970 base::TimeDelta total_duration = response_.response_time - start_time_;
[email protected]9a0a55f2009-04-13 23:23:03971
[email protected]d6b55392011-08-05 04:04:35972 UMA_HISTOGRAM_CUSTOM_TIMES(
973 "Net.Transaction_Connected",
[email protected]510e854f2009-04-20 18:39:08974 total_duration,
[email protected]9a0a55f2009-04-13 23:23:03975 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
976 100);
[email protected]1fa47592009-07-27 22:45:00977
[email protected]c38ec5a2010-08-25 23:32:38978 bool reused_socket = stream_->IsConnectionReused();
979 if (!reused_socket) {
[email protected]d6b55392011-08-05 04:04:35980 UMA_HISTOGRAM_CUSTOM_TIMES(
981 "Net.Transaction_Connected_New_b",
[email protected]b01998a2009-04-21 01:01:11982 total_duration,
983 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
984 100);
[email protected]d068f7a2010-06-07 15:12:59985
[email protected]edafd4c2011-05-10 17:18:53986 static const bool use_conn_impact_histogram =
987 base::FieldTrialList::TrialExists("ConnCountImpact");
[email protected]d068f7a2010-06-07 15:12:59988 if (use_conn_impact_histogram) {
[email protected]d6b55392011-08-05 04:04:35989 UMA_HISTOGRAM_CUSTOM_TIMES(
990 base::FieldTrial::MakeName("Net.Transaction_Connected_New_b",
[email protected]d068f7a2010-06-07 15:12:59991 "ConnCountImpact"),
992 total_duration,
993 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
994 100);
995 }
[email protected]0310d432009-08-25 07:49:52996 }
997
[email protected]edafd4c2011-05-10 17:18:53998 static const bool use_spdy_histogram =
999 base::FieldTrialList::TrialExists("SpdyImpact");
[email protected]8e3d2d32010-06-13 18:46:231000 if (use_spdy_histogram && response_.was_npn_negotiated) {
[email protected]d6b55392011-08-05 04:04:351001 UMA_HISTOGRAM_CUSTOM_TIMES(
1002 base::FieldTrial::MakeName("Net.Transaction_Connected",
[email protected]835d7c82010-10-14 04:38:381003 "SpdyImpact"),
[email protected]8e3d2d32010-06-13 18:46:231004 total_duration, base::TimeDelta::FromMilliseconds(1),
1005 base::TimeDelta::FromMinutes(10), 100);
1006
[email protected]c38ec5a2010-08-25 23:32:381007 if (!reused_socket) {
[email protected]d6b55392011-08-05 04:04:351008 UMA_HISTOGRAM_CUSTOM_TIMES(
1009 base::FieldTrial::MakeName("Net.Transaction_Connected_New_b",
[email protected]835d7c82010-10-14 04:38:381010 "SpdyImpact"),
[email protected]8e3d2d32010-06-13 18:46:231011 total_duration, base::TimeDelta::FromMilliseconds(1),
1012 base::TimeDelta::FromMinutes(10), 100);
1013 }
1014 }
1015
[email protected]510e854f2009-04-20 18:39:081016 // Currently, non-zero priority requests are frame or sub-frame resource
1017 // types. This will change when we also prioritize certain subresources like
1018 // css, js, etc.
1019 if (request_->priority) {
[email protected]d6b55392011-08-05 04:04:351020 UMA_HISTOGRAM_CUSTOM_TIMES(
1021 "Net.Priority_High_Latency_b",
[email protected]510e854f2009-04-20 18:39:081022 total_duration,
1023 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1024 100);
1025 } else {
[email protected]d6b55392011-08-05 04:04:351026 UMA_HISTOGRAM_CUSTOM_TIMES(
1027 "Net.Priority_Low_Latency_b",
[email protected]510e854f2009-04-20 18:39:081028 total_duration,
1029 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1030 100);
1031 }
[email protected]9a0a55f2009-04-13 23:23:031032}
1033
[email protected]56300172008-11-06 18:42:551034void HttpNetworkTransaction::LogTransactionMetrics() const {
[email protected]0877e3d2009-10-17 22:29:571035 base::TimeDelta duration = base::Time::Now() -
[email protected]2227c692010-05-04 15:36:111036 response_.request_time;
[email protected]56300172008-11-06 18:42:551037 if (60 < duration.InMinutes())
1038 return;
[email protected]0b48db42009-03-23 02:45:111039
[email protected]21b316a2009-03-23 18:25:061040 base::TimeDelta total_duration = base::Time::Now() - start_time_;
1041
[email protected]d6b55392011-08-05 04:04:351042 UMA_HISTOGRAM_CUSTOM_TIMES("Net.Transaction_Latency_b", duration,
1043 base::TimeDelta::FromMilliseconds(1),
1044 base::TimeDelta::FromMinutes(10),
1045 100);
1046 UMA_HISTOGRAM_CUSTOM_TIMES("Net.Transaction_Latency_Total",
1047 total_duration,
1048 base::TimeDelta::FromMilliseconds(1),
1049 base::TimeDelta::FromMinutes(10), 100);
[email protected]5c68d692011-08-24 04:59:411050
1051 static const bool use_warm_socket_impact_histogram =
1052 base::FieldTrialList::TrialExists("WarmSocketImpact");
1053 if (use_warm_socket_impact_histogram) {
1054 UMA_HISTOGRAM_CUSTOM_TIMES(
1055 base::FieldTrial::MakeName("Net.Transaction_Latency_b",
1056 "WarmSocketImpact"),
1057 duration,
1058 base::TimeDelta::FromMilliseconds(1),
1059 base::TimeDelta::FromMinutes(10),
1060 100);
1061 UMA_HISTOGRAM_CUSTOM_TIMES(
1062 base::FieldTrial::MakeName("Net.Transaction_Latency_Total",
1063 "WarmSocketImpact"),
1064 total_duration,
1065 base::TimeDelta::FromMilliseconds(1),
1066 base::TimeDelta::FromMinutes(10), 100);
1067 }
1068
[email protected]c38ec5a2010-08-25 23:32:381069 if (!stream_->IsConnectionReused()) {
[email protected]d6b55392011-08-05 04:04:351070 UMA_HISTOGRAM_CUSTOM_TIMES(
1071 "Net.Transaction_Latency_Total_New_Connection",
[email protected]808f6402009-03-30 20:02:071072 total_duration, base::TimeDelta::FromMilliseconds(1),
1073 base::TimeDelta::FromMinutes(10), 100);
1074 }
[email protected]56300172008-11-06 18:42:551075}
1076
[email protected]5e363962009-06-19 19:57:011077int HttpNetworkTransaction::HandleCertificateRequest(int error) {
[email protected]8e6441ca2010-08-19 05:56:381078 // There are two paths through which the server can request a certificate
1079 // from us. The first is during the initial handshake, the second is
1080 // during SSL renegotiation.
1081 //
1082 // In both cases, we want to close the connection before proceeding.
1083 // We do this for two reasons:
1084 // First, we don't want to keep the connection to the server hung for a
1085 // long time while the user selects a certificate.
1086 // Second, even if we did keep the connection open, NSS has a bug where
1087 // restarting the handshake for ClientAuth is currently broken.
[email protected]65a3b912010-08-21 05:46:581088 DCHECK_EQ(error, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]8e6441ca2010-08-19 05:56:381089
1090 if (stream_.get()) {
1091 // Since we already have a stream, we're being called as part of SSL
1092 // renegotiation.
1093 DCHECK(!stream_request_.get());
1094 stream_->Close(true);
1095 stream_.reset();
1096 }
1097
[email protected]26816882010-10-14 18:03:091098 // The server is asking for a client certificate during the initial
1099 // handshake.
1100 stream_request_.reset();
[email protected]5e363962009-06-19 19:57:011101
[email protected]ec229bc92010-11-22 09:51:451102 // If the user selected one of the certificates in client_certs or declined
1103 // to provide one for this server before, use the past decision
1104 // automatically.
1105 scoped_refptr<X509Certificate> client_cert;
1106 bool found_cached_cert = session_->ssl_client_auth_cache()->Lookup(
1107 response_.cert_request_info->host_and_port, &client_cert);
1108 if (!found_cached_cert)
1109 return error;
1110
1111 // Check that the certificate selected is still a certificate the server
1112 // is likely to accept, based on the criteria supplied in the
1113 // CertificateRequest message.
[email protected]5e363962009-06-19 19:57:011114 if (client_cert) {
1115 const std::vector<scoped_refptr<X509Certificate> >& client_certs =
[email protected]a7e41312009-12-16 23:18:141116 response_.cert_request_info->client_certs;
[email protected]ec229bc92010-11-22 09:51:451117 bool cert_still_valid = false;
[email protected]5e363962009-06-19 19:57:011118 for (size_t i = 0; i < client_certs.size(); ++i) {
[email protected]ec229bc92010-11-22 09:51:451119 if (client_cert->Equals(client_certs[i])) {
1120 cert_still_valid = true;
1121 break;
[email protected]5e363962009-06-19 19:57:011122 }
1123 }
[email protected]ec229bc92010-11-22 09:51:451124
1125 if (!cert_still_valid)
1126 return error;
[email protected]5e363962009-06-19 19:57:011127 }
[email protected]ec229bc92010-11-22 09:51:451128
1129 // TODO(davidben): Add a unit test which covers this path; we need to be
1130 // able to send a legitimate certificate and also bypass/clear the
1131 // SSL session cache.
[email protected]102957f2011-09-02 17:10:141132 SSLConfig* ssl_config = response_.cert_request_info->is_proxy ?
1133 &proxy_ssl_config_ : &server_ssl_config_;
1134 ssl_config->send_client_cert = true;
1135 ssl_config->client_cert = client_cert;
[email protected]ec229bc92010-11-22 09:51:451136 next_state_ = STATE_CREATE_STREAM;
1137 // Reset the other member variables.
1138 // Note: this is necessary only with SSL renegotiation.
1139 ResetStateForRestart();
1140 return OK;
[email protected]0b45559b2009-06-12 21:45:111141}
1142
[email protected]bd0b6772011-01-11 19:59:301143// TODO(rch): This does not correctly handle errors when an SSL proxy is
1144// being used, as all of the errors are handled as if they were generated
1145// by the endpoint host, request_->url, rather than considering if they were
[email protected]1c53a1f2011-01-13 00:36:381146// generated by the SSL proxy. http://crbug.com/69329
[email protected]bd0b6772011-01-11 19:59:301147int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
1148 DCHECK(request_);
[email protected]102957f2011-09-02 17:10:141149 if (server_ssl_config_.send_client_cert &&
[email protected]a1cb2cd2011-02-05 02:02:081150 (error == ERR_SSL_PROTOCOL_ERROR || IsClientCertificateError(error))) {
[email protected]bd0b6772011-01-11 19:59:301151 session_->ssl_client_auth_cache()->Remove(
1152 GetHostAndPort(request_->url));
1153 }
1154
initial.commit586acc5fe2008-07-26 22:42:521155 switch (error) {
[email protected]bd0b6772011-01-11 19:59:301156 case ERR_SSL_PROTOCOL_ERROR:
1157 case ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
1158 case ERR_SSL_DECOMPRESSION_FAILURE_ALERT:
1159 case ERR_SSL_BAD_RECORD_MAC_ALERT:
[email protected]102957f2011-09-02 17:10:141160 if (server_ssl_config_.tls1_enabled) {
[email protected]bd0b6772011-01-11 19:59:301161 // This could be a TLS-intolerant server, an SSL 3.0 server that
1162 // chose a TLS-only cipher suite or a server with buggy DEFLATE
1163 // support. Turn off TLS 1.0, DEFLATE support and retry.
[email protected]2d6728692011-03-12 01:39:551164 session_->http_stream_factory()->AddTLSIntolerantServer(
1165 HostPortPair::FromURL(request_->url));
[email protected]1c773ea12009-04-28 19:58:421166 ResetConnectionAndRequestForResend();
initial.commit586acc5fe2008-07-26 22:42:521167 error = OK;
[email protected]1c773ea12009-04-28 19:58:421168 }
initial.commit586acc5fe2008-07-26 22:42:521169 break;
1170 }
1171 return error;
1172}
1173
[email protected]bd0b6772011-01-11 19:59:301174// This method determines whether it is safe to resend the request after an
1175// IO error. It can only be called in response to request header or body
1176// write errors or response header read errors. It should not be used in
1177// other cases, such as a Connect error.
1178int HttpNetworkTransaction::HandleIOError(int error) {
1179 // SSL errors may happen at any time during the stream and indicate issues
1180 // with the underlying connection. Because the peer may request
1181 // renegotiation at any time, check and handle any possible SSL handshake
1182 // related errors. In addition to renegotiation, TLS False/Snap Start may
[email protected]1c53a1f2011-01-13 00:36:381183 // cause SSL handshake errors to be delayed until the first or second Write
1184 // (Snap Start) or the first Read (False & Snap Start) on the underlying
1185 // connection.
[email protected]bd0b6772011-01-11 19:59:301186 error = HandleSSLHandshakeError(error);
1187
1188 switch (error) {
1189 // If we try to reuse a connection that the server is in the process of
1190 // closing, we may end up successfully writing out our request (or a
1191 // portion of our request) only to find a connection error when we try to
1192 // read from (or finish writing to) the socket.
1193 case ERR_CONNECTION_RESET:
1194 case ERR_CONNECTION_CLOSED:
1195 case ERR_CONNECTION_ABORTED:
1196 if (ShouldResendRequest(error)) {
1197 ResetConnectionAndRequestForResend();
1198 error = OK;
1199 }
1200 break;
1201 }
1202 return error;
1203}
1204
[email protected]c3b35c22008-09-27 03:19:421205void HttpNetworkTransaction::ResetStateForRestart() {
[email protected]697ef4c2010-10-14 16:38:581206 ResetStateForAuthRestart();
1207 stream_.reset();
1208}
1209
1210void HttpNetworkTransaction::ResetStateForAuthRestart() {
[email protected]0757e7702009-03-27 04:00:221211 pending_auth_target_ = HttpAuth::AUTH_NONE;
[email protected]c3b35c22008-09-27 03:19:421212 read_buf_ = NULL;
1213 read_buf_len_ = 0;
[email protected]0877e3d2009-10-17 22:29:571214 headers_valid_ = false;
[email protected]b94f92d2010-10-27 16:45:201215 request_headers_.Clear();
[email protected]a7e41312009-12-16 23:18:141216 response_ = HttpResponseInfo();
[email protected]8e6441ca2010-08-19 05:56:381217 establishing_tunnel_ = false;
[email protected]0877e3d2009-10-17 22:29:571218}
1219
1220HttpResponseHeaders* HttpNetworkTransaction::GetResponseHeaders() const {
[email protected]a7e41312009-12-16 23:18:141221 return response_.headers;
[email protected]c3b35c22008-09-27 03:19:421222}
1223
[email protected]a19f1c602009-08-24 21:35:281224bool HttpNetworkTransaction::ShouldResendRequest(int error) const {
[email protected]8e6441ca2010-08-19 05:56:381225 bool connection_is_proven = stream_->IsConnectionReused();
1226 bool has_received_headers = GetResponseHeaders() != NULL;
[email protected]58cebf8f2010-07-31 19:20:161227
[email protected]2a5c76b2008-09-25 22:15:161228 // NOTE: we resend a request only if we reused a keep-alive connection.
1229 // This automatically prevents an infinite resend loop because we'll run
1230 // out of the cached keep-alive connections eventually.
[email protected]8e6441ca2010-08-19 05:56:381231 if (connection_is_proven && !has_received_headers)
1232 return true;
1233 return false;
[email protected]1c773ea12009-04-28 19:58:421234}
1235
1236void HttpNetworkTransaction::ResetConnectionAndRequestForResend() {
[email protected]8e6441ca2010-08-19 05:56:381237 if (stream_.get()) {
1238 stream_->Close(true);
1239 stream_.reset();
[email protected]58cebf8f2010-07-31 19:20:161240 }
1241
[email protected]0877e3d2009-10-17 22:29:571242 // We need to clear request_headers_ because it contains the real request
1243 // headers, but we may need to resend the CONNECT request first to recreate
1244 // the SSL tunnel.
[email protected]b94f92d2010-10-27 16:45:201245 request_headers_.Clear();
[email protected]82918cc2010-08-25 17:24:501246 next_state_ = STATE_CREATE_STREAM; // Resend the request.
[email protected]86ec30d2008-09-29 21:53:541247}
1248
[email protected]1c773ea12009-04-28 19:58:421249bool HttpNetworkTransaction::ShouldApplyProxyAuth() const {
[email protected]2df19bb2010-08-25 20:13:461250 return !is_https_request() &&
1251 (proxy_info_.is_https() || proxy_info_.is_http());
[email protected]1c773ea12009-04-28 19:58:421252}
license.botbf09a502008-08-24 00:55:551253
[email protected]1c773ea12009-04-28 19:58:421254bool HttpNetworkTransaction::ShouldApplyServerAuth() const {
[email protected]8a1f3312010-05-25 19:25:041255 return !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA);
[email protected]1c773ea12009-04-28 19:58:421256}
1257
[email protected]e772db3f2010-07-12 18:11:131258int HttpNetworkTransaction::HandleAuthChallenge() {
[email protected]ad8e04a2010-11-01 04:16:271259 scoped_refptr<HttpResponseHeaders> headers(GetResponseHeaders());
[email protected]0877e3d2009-10-17 22:29:571260 DCHECK(headers);
[email protected]c3b35c22008-09-27 03:19:421261
[email protected]0877e3d2009-10-17 22:29:571262 int status = headers->response_code();
[email protected]c3b35c22008-09-27 03:19:421263 if (status != 401 && status != 407)
1264 return OK;
1265 HttpAuth::Target target = status == 407 ?
[email protected]2227c692010-05-04 15:36:111266 HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER;
[email protected]038e9a32008-10-08 22:40:161267 if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct())
1268 return ERR_UNEXPECTED_PROXY_AUTH;
[email protected]c3b35c22008-09-27 03:19:421269
[email protected]7a67a8152010-11-05 18:31:101270 // This case can trigger when an HTTPS server responds with a 407 status
1271 // code through a non-authenticating proxy.
1272 if (!auth_controllers_[target].get())
1273 return ERR_UNEXPECTED_PROXY_AUTH;
1274
[email protected]a7ea8832010-07-12 17:54:541275 int rv = auth_controllers_[target]->HandleAuthChallenge(
[email protected]560c0432010-07-13 20:45:311276 headers, (request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA) != 0, false,
1277 net_log_);
[email protected]228404f2010-06-24 04:31:411278 if (auth_controllers_[target]->HaveAuthHandler())
1279 pending_auth_target_ = target;
1280
1281 scoped_refptr<AuthChallengeInfo> auth_info =
1282 auth_controllers_[target]->auth_info();
1283 if (auth_info.get())
1284 response_.auth_challenge = auth_info;
1285
[email protected]228404f2010-06-24 04:31:411286 return rv;
[email protected]f9ee6b52008-11-08 06:46:231287}
1288
[email protected]8e6441ca2010-08-19 05:56:381289bool HttpNetworkTransaction::HaveAuth(HttpAuth::Target target) const {
1290 return auth_controllers_[target].get() &&
1291 auth_controllers_[target]->HaveAuth();
1292}
1293
[email protected]228404f2010-06-24 04:31:411294GURL HttpNetworkTransaction::AuthURL(HttpAuth::Target target) const {
1295 switch (target) {
[email protected]2df19bb2010-08-25 20:13:461296 case HttpAuth::AUTH_PROXY: {
[email protected]228404f2010-06-24 04:31:411297 if (!proxy_info_.proxy_server().is_valid() ||
1298 proxy_info_.proxy_server().is_direct()) {
1299 return GURL(); // There is no proxy server.
1300 }
[email protected]2df19bb2010-08-25 20:13:461301 const char* scheme = proxy_info_.is_https() ? "https://" : "http://";
1302 return GURL(scheme +
[email protected]2fbaecf22010-07-22 22:20:351303 proxy_info_.proxy_server().host_port_pair().ToString());
[email protected]2df19bb2010-08-25 20:13:461304 }
[email protected]228404f2010-06-24 04:31:411305 case HttpAuth::AUTH_SERVER:
1306 return request_->url;
1307 default:
1308 return GURL();
1309 }
[email protected]c3b35c22008-09-27 03:19:421310}
1311
[email protected]d8eb84242010-09-25 02:25:061312#define STATE_CASE(s) \
1313 case s: \
1314 description = base::StringPrintf("%s (0x%08X)", #s, s); \
1315 break
[email protected]aef04272010-06-28 18:03:041316
1317std::string HttpNetworkTransaction::DescribeState(State state) {
1318 std::string description;
1319 switch (state) {
[email protected]82918cc2010-08-25 17:24:501320 STATE_CASE(STATE_CREATE_STREAM);
1321 STATE_CASE(STATE_CREATE_STREAM_COMPLETE);
[email protected]4875ba12011-03-30 22:31:511322 STATE_CASE(STATE_BUILD_REQUEST);
1323 STATE_CASE(STATE_BUILD_REQUEST_COMPLETE);
[email protected]aef04272010-06-28 18:03:041324 STATE_CASE(STATE_SEND_REQUEST);
1325 STATE_CASE(STATE_SEND_REQUEST_COMPLETE);
1326 STATE_CASE(STATE_READ_HEADERS);
1327 STATE_CASE(STATE_READ_HEADERS_COMPLETE);
[email protected]aef04272010-06-28 18:03:041328 STATE_CASE(STATE_READ_BODY);
1329 STATE_CASE(STATE_READ_BODY_COMPLETE);
1330 STATE_CASE(STATE_DRAIN_BODY_FOR_AUTH_RESTART);
1331 STATE_CASE(STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE);
[email protected]aef04272010-06-28 18:03:041332 STATE_CASE(STATE_NONE);
1333 default:
[email protected]d8eb84242010-09-25 02:25:061334 description = base::StringPrintf("Unknown state 0x%08X (%u)", state,
1335 state);
[email protected]aef04272010-06-28 18:03:041336 break;
1337 }
1338 return description;
1339}
1340
1341#undef STATE_CASE
1342
[email protected]c3b35c22008-09-27 03:19:421343} // namespace net