blob: 4bd867d1432d96545f9b820f8c0c34126681c809 [file] [log] [blame]
[email protected]d102f542010-06-30 14:51:051// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// 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]835d7c82010-10-14 04:38:3812#include "base/metrics/field_trial.h"
13#include "base/metrics/histogram.h"
14#include "base/metrics/stats_counters.h"
[email protected]270c6412010-03-29 22:02:4715#include "base/scoped_ptr.h"
[email protected]aeaca1f2010-04-20 22:05:2116#include "base/stl_util-inl.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]0651b812011-02-24 00:22:5028#include "net/base/network_delegate.h"
[email protected]0b45559b2009-06-12 21:45:1129#include "net/base/ssl_cert_request_info.h"
[email protected]fc7de492010-07-12 14:49:0430#include "net/base/ssl_connection_status_flags.h"
initial.commit586acc5fe2008-07-26 22:42:5231#include "net/base/upload_data_stream.h"
[email protected]c3b35c22008-09-27 03:19:4232#include "net/http/http_auth.h"
33#include "net/http/http_auth_handler.h"
[email protected]fa82f932010-05-20 11:09:2434#include "net/http/http_auth_handler_factory.h"
[email protected]8d5a34e2009-06-11 21:21:3635#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5236#include "net/http/http_chunked_decoder.h"
[email protected]a7ea8832010-07-12 17:54:5437#include "net/http/http_net_log_params.h"
initial.commit586acc5fe2008-07-26 22:42:5238#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]4bb1dc9e2010-09-23 22:36:5243#include "net/http/http_response_body_drainer.h"
[email protected]319d9e6f2009-02-18 19:47:2144#include "net/http/http_response_headers.h"
[email protected]0877e3d2009-10-17 22:29:5745#include "net/http/http_response_info.h"
[email protected]102e27c2011-02-23 01:01:3146#include "net/http/http_stream_factory.h"
initial.commit586acc5fe2008-07-26 22:42:5247#include "net/http/http_util.h"
[email protected]d7f16632010-03-29 18:02:3648#include "net/http/url_security_manager.h"
[email protected]f7984fc62009-06-22 23:26:4449#include "net/socket/client_socket_factory.h"
[email protected]a796bcec2010-03-22 17:17:2650#include "net/socket/socks_client_socket_pool.h"
[email protected]f7984fc62009-06-22 23:26:4451#include "net/socket/ssl_client_socket.h"
[email protected]e60e47a2010-07-14 03:37:1852#include "net/socket/ssl_client_socket_pool.h"
[email protected]7fc5b09a2010-02-27 00:07:3853#include "net/socket/tcp_client_socket_pool.h"
[email protected]65d56aa2010-06-14 04:13:4054#include "net/spdy/spdy_http_stream.h"
[email protected]dab9c7d2010-02-06 21:44:3255#include "net/spdy/spdy_session.h"
56#include "net/spdy/spdy_session_pool.h"
initial.commit586acc5fe2008-07-26 22:42:5257
[email protected]e1acf6f2008-10-27 20:43:3358using base::Time;
59
initial.commit586acc5fe2008-07-26 22:42:5260namespace net {
61
[email protected]1c773ea12009-04-28 19:58:4262namespace {
63
[email protected]8e6441ca2010-08-19 05:56:3864void ProcessAlternateProtocol(HttpStreamFactory* factory,
65 HttpAlternateProtocols* alternate_protocols,
66 const HttpResponseHeaders& headers,
67 const HostPortPair& http_host_port_pair) {
[email protected]564b4912010-03-09 16:30:4268 std::string alternate_protocol_str;
[email protected]8e6441ca2010-08-19 05:56:3869
[email protected]564b4912010-03-09 16:30:4270 if (!headers.EnumerateHeader(NULL, HttpAlternateProtocols::kHeader,
71 &alternate_protocol_str)) {
72 // Header is not present.
73 return;
74 }
75
[email protected]8e6441ca2010-08-19 05:56:3876 factory->ProcessAlternateProtocol(alternate_protocols,
77 alternate_protocol_str,
78 http_host_port_pair);
[email protected]f45c1ee2010-08-03 00:54:3079}
80
[email protected]a1cb2cd2011-02-05 02:02:0881// Returns true if |error| is a client certificate authentication error.
82bool IsClientCertificateError(int error) {
83 switch (error) {
84 case ERR_BAD_SSL_CLIENT_AUTH_CERT:
85 case ERR_SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED:
86 case ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY:
87 case ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED:
88 return true;
89 default:
90 return false;
91 }
92}
93
[email protected]1c773ea12009-04-28 19:58:4294} // namespace
95
initial.commit586acc5fe2008-07-26 22:42:5296//-----------------------------------------------------------------------------
97
[email protected]5695b8c2009-09-30 21:36:4398HttpNetworkTransaction::HttpNetworkTransaction(HttpNetworkSession* session)
[email protected]0757e7702009-03-27 04:00:2299 : pending_auth_target_(HttpAuth::AUTH_NONE),
100 ALLOW_THIS_IN_INITIALIZER_LIST(
[email protected]68bf9152008-09-25 19:47:30101 io_callback_(this, &HttpNetworkTransaction::OnIOComplete)),
initial.commit586acc5fe2008-07-26 22:42:52102 user_callback_(NULL),
103 session_(session),
104 request_(NULL),
[email protected]0877e3d2009-10-17 22:29:57105 headers_valid_(false),
[email protected]8e3d2d32010-06-13 18:46:23106 logged_response_time_(false),
[email protected]b94f92d2010-10-27 16:45:20107 request_headers_(),
initial.commit586acc5fe2008-07-26 22:42:52108 read_buf_len_(0),
[email protected]a7ea8832010-07-12 17:54:54109 next_state_(STATE_NONE),
110 establishing_tunnel_(false) {
[email protected]2cd713f2008-10-21 17:54:28111 session->ssl_config_service()->GetSSLConfig(&ssl_config_);
[email protected]8e6441ca2010-08-19 05:56:38112 if (session->http_stream_factory()->next_protos())
113 ssl_config_.next_protos = *session->http_stream_factory()->next_protos();
[email protected]3ce7df0f2010-03-03 00:30:50114}
115
[email protected]0b0bf032010-09-21 18:08:50116HttpNetworkTransaction::~HttpNetworkTransaction() {
117 if (stream_.get()) {
118 HttpResponseHeaders* headers = GetResponseHeaders();
119 // TODO(mbelshe): The stream_ should be able to compute whether or not the
120 // stream should be kept alive. No reason to compute here
121 // and pass it in.
122 bool try_to_keep_alive =
123 next_state_ == STATE_NONE &&
124 stream_->CanFindEndOfResponse() &&
125 (!headers || headers->IsKeepAlive());
126 if (!try_to_keep_alive) {
127 stream_->Close(true /* not reusable */);
128 } else {
129 if (stream_->IsResponseBodyComplete()) {
130 // If the response body is complete, we can just reuse the socket.
131 stream_->Close(false /* reusable */);
[email protected]3a8d6852011-03-11 23:43:44132 } else if (stream_->IsSpdyHttpStream()) {
133 // Doesn't really matter for SpdyHttpStream. Just close it.
134 stream_->Close(true /* not reusable */);
[email protected]0b0bf032010-09-21 18:08:50135 } else {
136 // Otherwise, we try to drain the response body.
137 // TODO(willchan): Consider moving this response body draining to the
138 // stream implementation. For SPDY, there's clearly no point. For
139 // HTTP, it can vary depending on whether or not we're pipelining. It's
140 // stream dependent, so the different subtypes should be implementing
141 // their solutions.
[email protected]4bb1dc9e2010-09-23 22:36:52142 HttpResponseBodyDrainer* drainer =
143 new HttpResponseBodyDrainer(stream_.release());
[email protected]9b5e46cb2010-09-28 16:28:44144 drainer->Start(session_);
[email protected]4bb1dc9e2010-09-23 22:36:52145 // |drainer| will delete itself.
[email protected]0b0bf032010-09-21 18:08:50146 }
147 }
148 }
[email protected]0b0bf032010-09-21 18:08:50149}
150
[email protected]684970b2009-08-14 04:54:46151int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info,
152 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53153 const BoundNetLog& net_log) {
[email protected]5e2e6c77d12009-12-24 21:57:16154 SIMPLE_STATS_COUNTER("HttpNetworkTransaction.Count");
[email protected]5d0153c512009-01-12 19:08:36155
[email protected]9e743cd2010-03-16 07:03:53156 net_log_ = net_log;
[email protected]96d570e42008-08-05 22:43:04157 request_ = request_info;
[email protected]21b316a2009-03-23 18:25:06158 start_time_ = base::Time::Now();
[email protected]96d570e42008-08-05 22:43:04159
[email protected]82918cc2010-08-25 17:24:50160 next_state_ = STATE_CREATE_STREAM;
[email protected]96d570e42008-08-05 22:43:04161 int rv = DoLoop(OK);
162 if (rv == ERR_IO_PENDING)
163 user_callback_ = callback;
164 return rv;
165}
166
167int HttpNetworkTransaction::RestartIgnoringLastError(
168 CompletionCallback* callback) {
[email protected]8e6441ca2010-08-19 05:56:38169 DCHECK(!stream_.get());
170 DCHECK(!stream_request_.get());
171 DCHECK_EQ(STATE_NONE, next_state_);
172
[email protected]82918cc2010-08-25 17:24:50173 next_state_ = STATE_CREATE_STREAM;
[email protected]8e6441ca2010-08-19 05:56:38174
[email protected]ccb40e52008-09-17 20:54:40175 int rv = DoLoop(OK);
176 if (rv == ERR_IO_PENDING)
177 user_callback_ = callback;
[email protected]aaead502008-10-15 00:20:11178 return rv;
[email protected]96d570e42008-08-05 22:43:04179}
180
[email protected]0b45559b2009-06-12 21:45:11181int HttpNetworkTransaction::RestartWithCertificate(
182 X509Certificate* client_cert,
183 CompletionCallback* callback) {
[email protected]8e6441ca2010-08-19 05:56:38184 // In HandleCertificateRequest(), we always tear down existing stream
185 // requests to force a new connection. So we shouldn't have one here.
186 DCHECK(!stream_request_.get());
187 DCHECK(!stream_.get());
188 DCHECK_EQ(STATE_NONE, next_state_);
189
[email protected]0b45559b2009-06-12 21:45:11190 ssl_config_.client_cert = client_cert;
[email protected]ec229bc92010-11-22 09:51:45191 session_->ssl_client_auth_cache()->Add(
192 response_.cert_request_info->host_and_port, client_cert);
[email protected]0b45559b2009-06-12 21:45:11193 ssl_config_.send_client_cert = true;
[email protected]0b45559b2009-06-12 21:45:11194 // Reset the other member variables.
195 // Note: this is necessary only with SSL renegotiation.
196 ResetStateForRestart();
[email protected]82918cc2010-08-25 17:24:50197 next_state_ = STATE_CREATE_STREAM;
[email protected]0b45559b2009-06-12 21:45:11198 int rv = DoLoop(OK);
199 if (rv == ERR_IO_PENDING)
200 user_callback_ = callback;
201 return rv;
202}
203
[email protected]96d570e42008-08-05 22:43:04204int HttpNetworkTransaction::RestartWithAuth(
[email protected]13c8a092010-07-29 06:15:44205 const string16& username,
206 const string16& password,
[email protected]96d570e42008-08-05 22:43:04207 CompletionCallback* callback) {
[email protected]0757e7702009-03-27 04:00:22208 HttpAuth::Target target = pending_auth_target_;
209 if (target == HttpAuth::AUTH_NONE) {
210 NOTREACHED();
211 return ERR_UNEXPECTED;
212 }
[email protected]0757e7702009-03-27 04:00:22213 pending_auth_target_ = HttpAuth::AUTH_NONE;
[email protected]c3b35c22008-09-27 03:19:42214
[email protected]e772db3f2010-07-12 18:11:13215 auth_controllers_[target]->ResetAuth(username, password);
216
[email protected]8e6441ca2010-08-19 05:56:38217 DCHECK(user_callback_ == NULL);
218
219 int rv = OK;
220 if (target == HttpAuth::AUTH_PROXY && establishing_tunnel_) {
221 // In this case, we've gathered credentials for use with proxy
222 // authentication of a tunnel.
[email protected]82918cc2010-08-25 17:24:50223 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38224 DCHECK(stream_request_ != NULL);
[email protected]394816e92010-08-03 07:38:59225 auth_controllers_[target] = NULL;
[email protected]a7ea8832010-07-12 17:54:54226 ResetStateForRestart();
[email protected]8e6441ca2010-08-19 05:56:38227 rv = stream_request_->RestartTunnelWithProxyAuth(username, password);
[email protected]a7ea8832010-07-12 17:54:54228 } else {
[email protected]8e6441ca2010-08-19 05:56:38229 // In this case, we've gathered credentials for the server or the proxy
230 // but it is not during the tunneling phase.
231 DCHECK(stream_request_ == NULL);
[email protected]a7ea8832010-07-12 17:54:54232 PrepareForAuthRestart(target);
[email protected]8e6441ca2010-08-19 05:56:38233 rv = DoLoop(OK);
[email protected]a7ea8832010-07-12 17:54:54234 }
[email protected]c3b35c22008-09-27 03:19:42235
[email protected]c3b35c22008-09-27 03:19:42236 if (rv == ERR_IO_PENDING)
237 user_callback_ = callback;
[email protected]c3b35c22008-09-27 03:19:42238 return rv;
[email protected]96d570e42008-08-05 22:43:04239}
240
[email protected]f9ee6b52008-11-08 06:46:23241void HttpNetworkTransaction::PrepareForAuthRestart(HttpAuth::Target target) {
242 DCHECK(HaveAuth(target));
[email protected]8e6441ca2010-08-19 05:56:38243 DCHECK(!stream_request_.get());
244
[email protected]2d2697f92009-02-18 21:00:32245 bool keep_alive = false;
[email protected]0877e3d2009-10-17 22:29:57246 // Even if the server says the connection is keep-alive, we have to be
247 // able to find the end of each response in order to reuse the connection.
248 if (GetResponseHeaders()->IsKeepAlive() &&
[email protected]351ab642010-08-05 16:55:31249 stream_->CanFindEndOfResponse()) {
[email protected]0877e3d2009-10-17 22:29:57250 // If the response body hasn't been completely read, we need to drain
251 // it first.
[email protected]351ab642010-08-05 16:55:31252 if (!stream_->IsResponseBodyComplete()) {
[email protected]2d2697f92009-02-18 21:00:32253 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
[email protected]0877e3d2009-10-17 22:29:57254 read_buf_ = new IOBuffer(kDrainBodyBufferSize); // A bit bucket.
[email protected]2d2697f92009-02-18 21:00:32255 read_buf_len_ = kDrainBodyBufferSize;
256 return;
257 }
[email protected]0877e3d2009-10-17 22:29:57258 keep_alive = true;
[email protected]37832c6d2009-06-05 19:44:09259 }
260
[email protected]2d2697f92009-02-18 21:00:32261 // We don't need to drain the response body, so we act as if we had drained
262 // the response body.
263 DidDrainBodyForAuthRestart(keep_alive);
264}
265
266void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) {
[email protected]8e6441ca2010-08-19 05:56:38267 DCHECK(!stream_request_.get());
268
269 if (stream_.get()) {
[email protected]697ef4c2010-10-14 16:38:58270 HttpStream* new_stream = NULL;
[email protected]8e6441ca2010-08-19 05:56:38271 if (keep_alive) {
272 // We should call connection_->set_idle_time(), but this doesn't occur
273 // often enough to be worth the trouble.
274 stream_->SetConnectionReused();
[email protected]697ef4c2010-10-14 16:38:58275 new_stream = stream_->RenewStreamForAuth();
[email protected]8e6441ca2010-08-19 05:56:38276 }
[email protected]697ef4c2010-10-14 16:38:58277
278 if (!new_stream) {
279 stream_->Close(!keep_alive);
280 next_state_ = STATE_CREATE_STREAM;
281 } else {
282 next_state_ = STATE_INIT_STREAM;
283 }
284 stream_.reset(new_stream);
[email protected]2d2697f92009-02-18 21:00:32285 }
[email protected]f9ee6b52008-11-08 06:46:23286
287 // Reset the other member variables.
[email protected]697ef4c2010-10-14 16:38:58288 ResetStateForAuthRestart();
[email protected]f9ee6b52008-11-08 06:46:23289}
290
[email protected]8e6441ca2010-08-19 05:56:38291bool HttpNetworkTransaction::IsReadyToRestartForAuth() {
292 return pending_auth_target_ != HttpAuth::AUTH_NONE &&
293 HaveAuth(pending_auth_target_);
294}
295
[email protected]9dea9e1f2009-01-29 00:30:47296int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len,
[email protected]96d570e42008-08-05 22:43:04297 CompletionCallback* callback) {
[email protected]96d570e42008-08-05 22:43:04298 DCHECK(buf);
[email protected]e0c27be2009-07-15 13:09:35299 DCHECK_LT(0, buf_len);
[email protected]96d570e42008-08-05 22:43:04300
[email protected]1f14a912009-12-21 20:32:44301 State next_state = STATE_NONE;
[email protected]96d570e42008-08-05 22:43:04302
[email protected]ad8e04a2010-11-01 04:16:27303 scoped_refptr<HttpResponseHeaders> headers(GetResponseHeaders());
[email protected]8e6441ca2010-08-19 05:56:38304 if (headers_valid_ && headers.get() && stream_request_.get()) {
[email protected]8a1f3312010-05-25 19:25:04305 // We're trying to read the body of the response but we're still trying
[email protected]511f6f52010-12-17 03:58:29306 // to establish an SSL tunnel through an HTTP proxy. We can't read these
[email protected]8a1f3312010-05-25 19:25:04307 // bytes when establishing a tunnel because they might be controlled by
308 // an active network attacker. We don't worry about this for HTTP
309 // because an active network attacker can already control HTTP sessions.
[email protected]511f6f52010-12-17 03:58:29310 // We reach this case when the user cancels a 407 proxy auth prompt. We
311 // also don't worry about this for an HTTPS Proxy, because the
312 // communication with the proxy is secure.
[email protected]8a1f3312010-05-25 19:25:04313 // See http://crbug.com/8473.
[email protected]2df19bb2010-08-25 20:13:46314 DCHECK(proxy_info_.is_http() || proxy_info_.is_https());
[email protected]a7ea8832010-07-12 17:54:54315 DCHECK_EQ(headers->response_code(), 407);
316 LOG(WARNING) << "Blocked proxy response with status "
317 << headers->response_code() << " to CONNECT request for "
318 << GetHostAndPort(request_->url) << ".";
[email protected]8a1f3312010-05-25 19:25:04319 return ERR_TUNNEL_CONNECTION_FAILED;
[email protected]a8e9b162009-03-12 00:06:44320 }
321
[email protected]e60e47a2010-07-14 03:37:18322 // Are we using SPDY or HTTP?
[email protected]351ab642010-08-05 16:55:31323 next_state = STATE_READ_BODY;
[email protected]e60e47a2010-07-14 03:37:18324
[email protected]96d570e42008-08-05 22:43:04325 read_buf_ = buf;
326 read_buf_len_ = buf_len;
327
[email protected]1f14a912009-12-21 20:32:44328 next_state_ = next_state;
[email protected]96d570e42008-08-05 22:43:04329 int rv = DoLoop(OK);
330 if (rv == ERR_IO_PENDING)
331 user_callback_ = callback;
332 return rv;
333}
334
335const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const {
[email protected]a7e41312009-12-16 23:18:14336 return ((headers_valid_ && response_.headers) || response_.ssl_info.cert ||
337 response_.cert_request_info) ? &response_ : NULL;
[email protected]96d570e42008-08-05 22:43:04338}
339
340LoadState HttpNetworkTransaction::GetLoadState() const {
341 // TODO(wtc): Define a new LoadState value for the
342 // STATE_INIT_CONNECTION_COMPLETE state, which delays the HTTP request.
343 switch (next_state_) {
[email protected]82918cc2010-08-25 17:24:50344 case STATE_CREATE_STREAM_COMPLETE:
[email protected]8e6441ca2010-08-19 05:56:38345 return stream_request_->GetLoadState();
[email protected]044de0642010-06-17 10:42:15346 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE:
347 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE:
[email protected]0877e3d2009-10-17 22:29:57348 case STATE_SEND_REQUEST_COMPLETE:
[email protected]96d570e42008-08-05 22:43:04349 return LOAD_STATE_SENDING_REQUEST;
350 case STATE_READ_HEADERS_COMPLETE:
351 return LOAD_STATE_WAITING_FOR_RESPONSE;
352 case STATE_READ_BODY_COMPLETE:
353 return LOAD_STATE_READING_RESPONSE;
354 default:
355 return LOAD_STATE_IDLE;
356 }
357}
358
359uint64 HttpNetworkTransaction::GetUploadProgress() const {
[email protected]351ab642010-08-05 16:55:31360 if (!stream_.get())
[email protected]96d570e42008-08-05 22:43:04361 return 0;
362
[email protected]351ab642010-08-05 16:55:31363 return stream_->GetUploadProgress();
[email protected]96d570e42008-08-05 22:43:04364}
365
[email protected]102e27c2011-02-23 01:01:31366void HttpNetworkTransaction::OnStreamReady(const SSLConfig& used_ssl_config,
367 const ProxyInfo& used_proxy_info,
368 HttpStream* stream) {
[email protected]82918cc2010-08-25 17:24:50369 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38370 DCHECK(stream_request_.get());
371
372 stream_.reset(stream);
[email protected]102e27c2011-02-23 01:01:31373 ssl_config_ = used_ssl_config;
374 proxy_info_ = used_proxy_info;
[email protected]8e6441ca2010-08-19 05:56:38375 response_.was_npn_negotiated = stream_request_->was_npn_negotiated();
376 response_.was_fetched_via_spdy = stream_request_->using_spdy();
377 response_.was_fetched_via_proxy = !proxy_info_.is_direct();
[email protected]8e6441ca2010-08-19 05:56:38378
379 OnIOComplete(OK);
380}
381
[email protected]102e27c2011-02-23 01:01:31382void HttpNetworkTransaction::OnStreamFailed(int result,
383 const SSLConfig& used_ssl_config) {
[email protected]82918cc2010-08-25 17:24:50384 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38385 DCHECK_NE(OK, result);
386 DCHECK(stream_request_.get());
387 DCHECK(!stream_.get());
[email protected]102e27c2011-02-23 01:01:31388 ssl_config_ = used_ssl_config;
[email protected]8e6441ca2010-08-19 05:56:38389
390 OnIOComplete(result);
391}
392
[email protected]102e27c2011-02-23 01:01:31393void HttpNetworkTransaction::OnCertificateError(
394 int result,
395 const SSLConfig& used_ssl_config,
396 const SSLInfo& ssl_info) {
[email protected]82918cc2010-08-25 17:24:50397 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38398 DCHECK_NE(OK, result);
399 DCHECK(stream_request_.get());
400 DCHECK(!stream_.get());
401
402 response_.ssl_info = ssl_info;
[email protected]102e27c2011-02-23 01:01:31403 ssl_config_ = used_ssl_config;
[email protected]8e6441ca2010-08-19 05:56:38404
405 // TODO(mbelshe): For now, we're going to pass the error through, and that
406 // will close the stream_request in all cases. This means that we're always
[email protected]82918cc2010-08-25 17:24:50407 // going to restart an entire STATE_CREATE_STREAM, even if the connection is
408 // good and the user chooses to ignore the error. This is not ideal, but not
409 // the end of the world either.
[email protected]8e6441ca2010-08-19 05:56:38410
411 OnIOComplete(result);
412}
413
414void HttpNetworkTransaction::OnNeedsProxyAuth(
[email protected]6dc476da2010-09-01 04:43:50415 const HttpResponseInfo& proxy_response,
[email protected]102e27c2011-02-23 01:01:31416 const SSLConfig& used_ssl_config,
417 const ProxyInfo& used_proxy_info,
[email protected]6dc476da2010-09-01 04:43:50418 HttpAuthController* auth_controller) {
[email protected]8e6441ca2010-08-19 05:56:38419 DCHECK(stream_request_.get());
[email protected]82918cc2010-08-25 17:24:50420 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38421
422 establishing_tunnel_ = true;
423 response_.headers = proxy_response.headers;
424 response_.auth_challenge = proxy_response.auth_challenge;
425 headers_valid_ = true;
[email protected]102e27c2011-02-23 01:01:31426 ssl_config_ = used_ssl_config;
427 proxy_info_ = used_proxy_info;
[email protected]8e6441ca2010-08-19 05:56:38428
429 auth_controllers_[HttpAuth::AUTH_PROXY] = auth_controller;
430 pending_auth_target_ = HttpAuth::AUTH_PROXY;
431
432 DoCallback(OK);
433}
434
435void HttpNetworkTransaction::OnNeedsClientAuth(
[email protected]102e27c2011-02-23 01:01:31436 const SSLConfig& used_ssl_config,
[email protected]6dc476da2010-09-01 04:43:50437 SSLCertRequestInfo* cert_info) {
[email protected]82918cc2010-08-25 17:24:50438 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38439
[email protected]102e27c2011-02-23 01:01:31440 ssl_config_ = used_ssl_config;
[email protected]8e6441ca2010-08-19 05:56:38441 response_.cert_request_info = cert_info;
[email protected]65a3b912010-08-21 05:46:58442 OnIOComplete(ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]8e6441ca2010-08-19 05:56:38443}
444
[email protected]511f6f52010-12-17 03:58:29445void HttpNetworkTransaction::OnHttpsProxyTunnelResponse(
446 const HttpResponseInfo& response_info,
[email protected]102e27c2011-02-23 01:01:31447 const SSLConfig& used_ssl_config,
448 const ProxyInfo& used_proxy_info,
[email protected]511f6f52010-12-17 03:58:29449 HttpStream* stream) {
450 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
451
452 headers_valid_ = true;
453 response_ = response_info;
[email protected]102e27c2011-02-23 01:01:31454 ssl_config_ = used_ssl_config;
455 proxy_info_ = used_proxy_info;
[email protected]511f6f52010-12-17 03:58:29456 stream_.reset(stream);
457 stream_request_.reset(); // we're done with the stream request
458 OnIOComplete(ERR_HTTPS_PROXY_TUNNEL_RESPONSE);
459}
460
[email protected]8e6441ca2010-08-19 05:56:38461bool HttpNetworkTransaction::is_https_request() const {
462 return request_->url.SchemeIs("https");
initial.commit586acc5fe2008-07-26 22:42:52463}
464
initial.commit586acc5fe2008-07-26 22:42:52465void HttpNetworkTransaction::DoCallback(int rv) {
[email protected]0b0bf032010-09-21 18:08:50466 DCHECK_NE(rv, ERR_IO_PENDING);
initial.commit586acc5fe2008-07-26 22:42:52467 DCHECK(user_callback_);
468
[email protected]96d570e42008-08-05 22:43:04469 // Since Run may result in Read being called, clear user_callback_ up front.
initial.commit586acc5fe2008-07-26 22:42:52470 CompletionCallback* c = user_callback_;
471 user_callback_ = NULL;
472 c->Run(rv);
473}
474
475void HttpNetworkTransaction::OnIOComplete(int result) {
476 int rv = DoLoop(result);
477 if (rv != ERR_IO_PENDING)
478 DoCallback(rv);
479}
480
481int HttpNetworkTransaction::DoLoop(int result) {
482 DCHECK(next_state_ != STATE_NONE);
483
484 int rv = result;
485 do {
486 State state = next_state_;
487 next_state_ = STATE_NONE;
488 switch (state) {
[email protected]82918cc2010-08-25 17:24:50489 case STATE_CREATE_STREAM:
490 DCHECK_EQ(OK, rv);
491 rv = DoCreateStream();
492 break;
493 case STATE_CREATE_STREAM_COMPLETE:
494 rv = DoCreateStreamComplete(rv);
495 break;
[email protected]351ab642010-08-05 16:55:31496 case STATE_INIT_STREAM:
497 DCHECK_EQ(OK, rv);
498 rv = DoInitStream();
499 break;
500 case STATE_INIT_STREAM_COMPLETE:
501 rv = DoInitStreamComplete(rv);
502 break;
[email protected]044de0642010-06-17 10:42:15503 case STATE_GENERATE_PROXY_AUTH_TOKEN:
504 DCHECK_EQ(OK, rv);
505 rv = DoGenerateProxyAuthToken();
506 break;
507 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE:
508 rv = DoGenerateProxyAuthTokenComplete(rv);
509 break;
510 case STATE_GENERATE_SERVER_AUTH_TOKEN:
511 DCHECK_EQ(OK, rv);
512 rv = DoGenerateServerAuthToken();
513 break;
514 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE:
515 rv = DoGenerateServerAuthTokenComplete(rv);
516 break;
[email protected]0877e3d2009-10-17 22:29:57517 case STATE_SEND_REQUEST:
[email protected]725355a2009-03-25 20:42:55518 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09519 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, NULL);
[email protected]0877e3d2009-10-17 22:29:57520 rv = DoSendRequest();
initial.commit586acc5fe2008-07-26 22:42:52521 break;
[email protected]0877e3d2009-10-17 22:29:57522 case STATE_SEND_REQUEST_COMPLETE:
523 rv = DoSendRequestComplete(rv);
[email protected]d7fd1782011-02-08 19:16:43524 net_log_.EndEventWithNetErrorCode(
525 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, rv);
initial.commit586acc5fe2008-07-26 22:42:52526 break;
527 case STATE_READ_HEADERS:
[email protected]725355a2009-03-25 20:42:55528 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09529 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, NULL);
initial.commit586acc5fe2008-07-26 22:42:52530 rv = DoReadHeaders();
531 break;
532 case STATE_READ_HEADERS_COMPLETE:
533 rv = DoReadHeadersComplete(rv);
[email protected]d7fd1782011-02-08 19:16:43534 net_log_.EndEventWithNetErrorCode(
535 NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, rv);
initial.commit586acc5fe2008-07-26 22:42:52536 break;
537 case STATE_READ_BODY:
[email protected]725355a2009-03-25 20:42:55538 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09539 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, NULL);
initial.commit586acc5fe2008-07-26 22:42:52540 rv = DoReadBody();
541 break;
542 case STATE_READ_BODY_COMPLETE:
543 rv = DoReadBodyComplete(rv);
[email protected]d7fd1782011-02-08 19:16:43544 net_log_.EndEventWithNetErrorCode(
545 NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, rv);
initial.commit586acc5fe2008-07-26 22:42:52546 break;
[email protected]2d2697f92009-02-18 21:00:32547 case STATE_DRAIN_BODY_FOR_AUTH_RESTART:
[email protected]725355a2009-03-25 20:42:55548 DCHECK_EQ(OK, rv);
[email protected]9e743cd2010-03-16 07:03:53549 net_log_.BeginEvent(
[email protected]ec11be62010-04-28 19:28:09550 NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART, NULL);
[email protected]2d2697f92009-02-18 21:00:32551 rv = DoDrainBodyForAuthRestart();
552 break;
553 case STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE:
554 rv = DoDrainBodyForAuthRestartComplete(rv);
[email protected]d7fd1782011-02-08 19:16:43555 net_log_.EndEventWithNetErrorCode(
556 NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART, rv);
[email protected]2d2697f92009-02-18 21:00:32557 break;
initial.commit586acc5fe2008-07-26 22:42:52558 default:
559 NOTREACHED() << "bad state";
560 rv = ERR_FAILED;
[email protected]96d570e42008-08-05 22:43:04561 break;
initial.commit586acc5fe2008-07-26 22:42:52562 }
563 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
564
565 return rv;
566}
567
[email protected]82918cc2010-08-25 17:24:50568int HttpNetworkTransaction::DoCreateStream() {
569 next_state_ = STATE_CREATE_STREAM_COMPLETE;
[email protected]351ab642010-08-05 16:55:31570
[email protected]26816882010-10-14 18:03:09571 stream_request_.reset(
572 session_->http_stream_factory()->RequestStream(
[email protected]102e27c2011-02-23 01:01:31573 *request_,
574 ssl_config_,
[email protected]26816882010-10-14 18:03:09575 this,
576 net_log_));
577 DCHECK(stream_request_.get());
[email protected]8e6441ca2010-08-19 05:56:38578 return ERR_IO_PENDING;
[email protected]351ab642010-08-05 16:55:31579}
580
[email protected]82918cc2010-08-25 17:24:50581int HttpNetworkTransaction::DoCreateStreamComplete(int result) {
[email protected]394816e92010-08-03 07:38:59582 if (result == OK) {
[email protected]82918cc2010-08-25 17:24:50583 next_state_ = STATE_INIT_STREAM;
[email protected]8e6441ca2010-08-19 05:56:38584 DCHECK(stream_.get());
[email protected]adb00242010-10-29 03:04:33585 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
586 result = HandleCertificateRequest(result);
[email protected]511f6f52010-12-17 03:58:29587 } else if (result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) {
588 // Return OK and let the caller read the proxy's error page
589 next_state_ = STATE_NONE;
590 return OK;
[email protected]394816e92010-08-03 07:38:59591 }
592
[email protected]bd0b6772011-01-11 19:59:30593 // Handle possible handshake errors that may have occurred if the stream
594 // used SSL for one or more of the layers.
595 result = HandleSSLHandshakeError(result);
596
[email protected]8e6441ca2010-08-19 05:56:38597 // At this point we are done with the stream_request_.
[email protected]26816882010-10-14 18:03:09598 stream_request_.reset();
[email protected]8e6441ca2010-08-19 05:56:38599 return result;
[email protected]394816e92010-08-03 07:38:59600}
601
[email protected]82918cc2010-08-25 17:24:50602int HttpNetworkTransaction::DoInitStream() {
603 DCHECK(stream_.get());
604 next_state_ = STATE_INIT_STREAM_COMPLETE;
605 return stream_->InitializeStream(request_, net_log_, &io_callback_);
606}
607
608int HttpNetworkTransaction::DoInitStreamComplete(int result) {
609 if (result == OK) {
610 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
[email protected]82918cc2010-08-25 17:24:50611 } else {
[email protected]82918cc2010-08-25 17:24:50612 if (result < 0)
[email protected]044dcc52010-09-17 15:44:26613 result = HandleIOError(result);
614
615 // The stream initialization failed, so this stream will never be useful.
616 stream_.reset();
[email protected]82918cc2010-08-25 17:24:50617 }
618
619 return result;
620}
621
[email protected]044de0642010-06-17 10:42:15622int HttpNetworkTransaction::DoGenerateProxyAuthToken() {
623 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE;
624 if (!ShouldApplyProxyAuth())
625 return OK;
[email protected]394816e92010-08-03 07:38:59626 HttpAuth::Target target = HttpAuth::AUTH_PROXY;
627 if (!auth_controllers_[target].get())
[email protected]3598c6022010-09-17 23:13:09628 auth_controllers_[target] =
629 new HttpAuthController(target,
630 AuthURL(target),
[email protected]102e27c2011-02-23 01:01:31631 session_->http_auth_cache(),
[email protected]3598c6022010-09-17 23:13:09632 session_->http_auth_handler_factory());
[email protected]394816e92010-08-03 07:38:59633 return auth_controllers_[target]->MaybeGenerateAuthToken(request_,
634 &io_callback_,
635 net_log_);
[email protected]044de0642010-06-17 10:42:15636}
637
638int HttpNetworkTransaction::DoGenerateProxyAuthTokenComplete(int rv) {
639 DCHECK_NE(ERR_IO_PENDING, rv);
640 if (rv == OK)
641 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN;
642 return rv;
643}
644
645int HttpNetworkTransaction::DoGenerateServerAuthToken() {
646 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE;
[email protected]394816e92010-08-03 07:38:59647 HttpAuth::Target target = HttpAuth::AUTH_SERVER;
648 if (!auth_controllers_[target].get())
[email protected]3598c6022010-09-17 23:13:09649 auth_controllers_[target] =
650 new HttpAuthController(target,
651 AuthURL(target),
[email protected]102e27c2011-02-23 01:01:31652 session_->http_auth_cache(),
[email protected]3598c6022010-09-17 23:13:09653 session_->http_auth_handler_factory());
[email protected]044de0642010-06-17 10:42:15654 if (!ShouldApplyServerAuth())
655 return OK;
[email protected]394816e92010-08-03 07:38:59656 return auth_controllers_[target]->MaybeGenerateAuthToken(request_,
657 &io_callback_,
658 net_log_);
[email protected]044de0642010-06-17 10:42:15659}
660
661int HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) {
662 DCHECK_NE(ERR_IO_PENDING, rv);
663 if (rv == OK)
[email protected]8e6441ca2010-08-19 05:56:38664 next_state_ = STATE_SEND_REQUEST;
[email protected]044de0642010-06-17 10:42:15665 return rv;
666}
667
[email protected]0877e3d2009-10-17 22:29:57668int HttpNetworkTransaction::DoSendRequest() {
669 next_state_ = STATE_SEND_REQUEST_COMPLETE;
670
671 UploadDataStream* request_body = NULL;
[email protected]8a1f3312010-05-25 19:25:04672 if (request_->upload_data) {
[email protected]7a6db4022010-03-24 23:37:50673 int error_code;
674 request_body = UploadDataStream::Create(request_->upload_data, &error_code);
675 if (!request_body)
676 return error_code;
677 }
initial.commit586acc5fe2008-07-26 22:42:52678
679 // This is constructed lazily (instead of within our Start method), so that
680 // we have proxy info available.
[email protected]b94f92d2010-10-27 16:45:20681 if (request_headers_.IsEmpty()) {
[email protected]7213e7c2010-10-20 15:33:52682 bool using_proxy = (proxy_info_.is_http()|| proxy_info_.is_https()) &&
683 !is_https_request();
[email protected]7213e7c2010-10-20 15:33:52684 HttpUtil::BuildRequestHeaders(request_, request_body, auth_controllers_,
685 ShouldApplyServerAuth(),
686 ShouldApplyProxyAuth(), using_proxy,
[email protected]b94f92d2010-10-27 16:45:20687 &request_headers_);
[email protected]ac039522010-06-15 16:39:44688
689 if (session_->network_delegate())
[email protected]0651b812011-02-24 00:22:50690 session_->network_delegate()->NotifySendHttpRequest(&request_headers_);
[email protected]b94f92d2010-10-27 16:45:20691 }
initial.commit586acc5fe2008-07-26 22:42:52692
[email protected]1f14a912009-12-21 20:32:44693 headers_valid_ = false;
[email protected]351ab642010-08-05 16:55:31694 return stream_->SendRequest(request_headers_, request_body, &response_,
695 &io_callback_);
initial.commit586acc5fe2008-07-26 22:42:52696}
697
[email protected]0877e3d2009-10-17 22:29:57698int HttpNetworkTransaction::DoSendRequestComplete(int result) {
initial.commit586acc5fe2008-07-26 22:42:52699 if (result < 0)
700 return HandleIOError(result);
[email protected]0877e3d2009-10-17 22:29:57701 next_state_ = STATE_READ_HEADERS;
initial.commit586acc5fe2008-07-26 22:42:52702 return OK;
703}
704
705int HttpNetworkTransaction::DoReadHeaders() {
706 next_state_ = STATE_READ_HEADERS_COMPLETE;
[email protected]351ab642010-08-05 16:55:31707 return stream_->ReadResponseHeaders(&io_callback_);
initial.commit586acc5fe2008-07-26 22:42:52708}
709
[email protected]0e75a732008-10-16 20:36:09710int HttpNetworkTransaction::HandleConnectionClosedBeforeEndOfHeaders() {
[email protected]8e6441ca2010-08-19 05:56:38711 if (!response_.headers && !stream_->IsConnectionReused()) {
[email protected]0e75a732008-10-16 20:36:09712 // The connection was closed before any data was sent. Likely an error
713 // rather than empty HTTP/0.9 response.
[email protected]aecfbf22008-10-16 02:02:47714 return ERR_EMPTY_RESPONSE;
715 }
716
[email protected]aecfbf22008-10-16 02:02:47717 return OK;
718}
719
initial.commit586acc5fe2008-07-26 22:42:52720int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
[email protected]0b45559b2009-06-12 21:45:11721 // We can get a certificate error or ERR_SSL_CLIENT_AUTH_CERT_NEEDED here
722 // due to SSL renegotiation.
[email protected]8e6441ca2010-08-19 05:56:38723 if (IsCertificateError(result)) {
724 // We don't handle a certificate error during SSL renegotiation, so we
725 // have to return an error that's not in the certificate error range
726 // (-2xx).
727 LOG(ERROR) << "Got a server certificate with error " << result
728 << " during SSL renegotiation";
729 result = ERR_CERT_ERROR_IN_SSL_RENEGOTIATION;
730 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
731 // TODO(wtc): Need a test case for this code path!
732 DCHECK(stream_.get());
733 DCHECK(is_https_request());
734 response_.cert_request_info = new SSLCertRequestInfo;
735 stream_->GetSSLCertRequestInfo(response_.cert_request_info);
736 result = HandleCertificateRequest(result);
737 if (result == OK)
738 return result;
[email protected]2181ea002009-06-09 01:37:27739 }
740
[email protected]0877e3d2009-10-17 22:29:57741 if (result < 0 && result != ERR_CONNECTION_CLOSED)
initial.commit586acc5fe2008-07-26 22:42:52742 return HandleIOError(result);
743
[email protected]0877e3d2009-10-17 22:29:57744 if (result == ERR_CONNECTION_CLOSED && ShouldResendRequest(result)) {
[email protected]1c773ea12009-04-28 19:58:42745 ResetConnectionAndRequestForResend();
[email protected]0877e3d2009-10-17 22:29:57746 return OK;
[email protected]1c773ea12009-04-28 19:58:42747 }
[email protected]2a5c76b2008-09-25 22:15:16748
[email protected]0877e3d2009-10-17 22:29:57749 // After we call RestartWithAuth a new response_time will be recorded, and
750 // we need to be cautious about incorrectly logging the duration across the
751 // authentication activity.
[email protected]8e6441ca2010-08-19 05:56:38752 if (result == OK)
753 LogTransactionConnectedMetrics();
initial.commit586acc5fe2008-07-26 22:42:52754
[email protected]0877e3d2009-10-17 22:29:57755 if (result == ERR_CONNECTION_CLOSED) {
[email protected]02c92c492010-03-08 21:28:14756 // For now, if we get at least some data, we do the best we can to make
[email protected]9492e4a2010-02-24 00:58:46757 // sense of it and send it back up the stack.
[email protected]0e75a732008-10-16 20:36:09758 int rv = HandleConnectionClosedBeforeEndOfHeaders();
[email protected]aecfbf22008-10-16 02:02:47759 if (rv != OK)
760 return rv;
[email protected]0877e3d2009-10-17 22:29:57761 }
initial.commit586acc5fe2008-07-26 22:42:52762
[email protected]465aeb942010-10-14 19:58:14763 if (net_log_.IsLoggingAllEvents()) {
[email protected]8a1f3312010-05-25 19:25:04764 net_log_.AddEvent(
765 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
[email protected]00cd9c42010-11-02 20:15:57766 make_scoped_refptr(new NetLogHttpResponseParameter(response_.headers)));
[email protected]dbb83db2010-05-11 18:13:39767 }
768
[email protected]a7e41312009-12-16 23:18:14769 if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0)) {
[email protected]0877e3d2009-10-17 22:29:57770 // HTTP/0.9 doesn't support the PUT method, so lack of response headers
771 // indicates a buggy server. See:
772 // https://bugzilla.mozilla.org/show_bug.cgi?id=193921
773 if (request_->method == "PUT")
774 return ERR_METHOD_NOT_SUPPORTED;
775 }
[email protected]4ddaf2502008-10-23 18:26:19776
[email protected]0877e3d2009-10-17 22:29:57777 // Check for an intermediate 100 Continue response. An origin server is
778 // allowed to send this response even if we didn't ask for it, so we just
779 // need to skip over it.
780 // We treat any other 1xx in this same way (although in practice getting
781 // a 1xx that isn't a 100 is rare).
[email protected]a7e41312009-12-16 23:18:14782 if (response_.headers->response_code() / 100 == 1) {
[email protected]ee9410e72010-01-07 01:42:38783 response_.headers = new HttpResponseHeaders("");
[email protected]0877e3d2009-10-17 22:29:57784 next_state_ = STATE_READ_HEADERS;
785 return OK;
786 }
787
[email protected]8e6441ca2010-08-19 05:56:38788 HostPortPair endpoint = HostPortPair(request_->url.HostNoBrackets(),
789 request_->url.EffectiveIntPort());
790 ProcessAlternateProtocol(session_->http_stream_factory(),
791 session_->mutable_alternate_protocols(),
792 *response_.headers,
793 endpoint);
[email protected]564b4912010-03-09 16:30:42794
[email protected]e772db3f2010-07-12 18:11:13795 int rv = HandleAuthChallenge();
[email protected]0877e3d2009-10-17 22:29:57796 if (rv != OK)
797 return rv;
798
[email protected]8536ef52010-09-30 16:18:21799 if (is_https_request())
800 stream_->GetSSLInfo(&response_.ssl_info);
801
[email protected]0877e3d2009-10-17 22:29:57802 headers_valid_ = true;
803 return OK;
initial.commit586acc5fe2008-07-26 22:42:52804}
805
806int HttpNetworkTransaction::DoReadBody() {
807 DCHECK(read_buf_);
[email protected]6501bc02009-06-25 20:55:13808 DCHECK_GT(read_buf_len_, 0);
[email protected]8e6441ca2010-08-19 05:56:38809 DCHECK(stream_ != NULL);
initial.commit586acc5fe2008-07-26 22:42:52810
811 next_state_ = STATE_READ_BODY_COMPLETE;
[email protected]351ab642010-08-05 16:55:31812 return stream_->ReadResponseBody(read_buf_, read_buf_len_, &io_callback_);
initial.commit586acc5fe2008-07-26 22:42:52813}
814
815int HttpNetworkTransaction::DoReadBodyComplete(int result) {
816 // We are done with the Read call.
[email protected]8e6441ca2010-08-19 05:56:38817 bool done = false;
818 if (result <= 0) {
819 DCHECK_NE(ERR_IO_PENDING, result);
initial.commit586acc5fe2008-07-26 22:42:52820 done = true;
[email protected]8e6441ca2010-08-19 05:56:38821 }
[email protected]9492e4a2010-02-24 00:58:46822
[email protected]8e6441ca2010-08-19 05:56:38823 bool keep_alive = false;
[email protected]351ab642010-08-05 16:55:31824 if (stream_->IsResponseBodyComplete()) {
[email protected]8e6441ca2010-08-19 05:56:38825 // Note: Just because IsResponseBodyComplete is true, we're not
826 // necessarily "done". We're only "done" when it is the last
827 // read on this HttpNetworkTransaction, which will be signified
828 // by a zero-length read.
829 // TODO(mbelshe): The keepalive property is really a property of
830 // the stream. No need to compute it here just to pass back
831 // to the stream's Close function.
[email protected]351ab642010-08-05 16:55:31832 if (stream_->CanFindEndOfResponse())
[email protected]02c92c492010-03-08 21:28:14833 keep_alive = GetResponseHeaders()->IsKeepAlive();
initial.commit586acc5fe2008-07-26 22:42:52834 }
835
[email protected]8e6441ca2010-08-19 05:56:38836 // Clean up connection if we are done.
initial.commit586acc5fe2008-07-26 22:42:52837 if (done) {
[email protected]56300172008-11-06 18:42:55838 LogTransactionMetrics();
[email protected]8e6441ca2010-08-19 05:56:38839 stream_->Close(!keep_alive);
[email protected]e2a915a2010-08-19 07:55:01840 // Note: we don't reset the stream here. We've closed it, but we still
841 // need it around so that callers can call methods such as
842 // GetUploadProgress() and have them be meaningful.
843 // TODO(mbelshe): This means we closed the stream here, and we close it
844 // again in ~HttpNetworkTransaction. Clean that up.
845
[email protected]8e6441ca2010-08-19 05:56:38846 // The next Read call will return 0 (EOF).
initial.commit586acc5fe2008-07-26 22:42:52847 }
848
849 // Clear these to avoid leaving around old state.
850 read_buf_ = NULL;
851 read_buf_len_ = 0;
852
853 return result;
854}
855
[email protected]2d2697f92009-02-18 21:00:32856int HttpNetworkTransaction::DoDrainBodyForAuthRestart() {
857 // This method differs from DoReadBody only in the next_state_. So we just
858 // call DoReadBody and override the next_state_. Perhaps there is a more
859 // elegant way for these two methods to share code.
860 int rv = DoReadBody();
861 DCHECK(next_state_ == STATE_READ_BODY_COMPLETE);
862 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE;
863 return rv;
864}
865
[email protected]0877e3d2009-10-17 22:29:57866// TODO(wtc): This method and the DoReadBodyComplete method are almost
867// the same. Figure out a good way for these two methods to share code.
[email protected]2d2697f92009-02-18 21:00:32868int HttpNetworkTransaction::DoDrainBodyForAuthRestartComplete(int result) {
[email protected]68873ba2009-06-04 21:49:23869 // keep_alive defaults to true because the very reason we're draining the
870 // response body is to reuse the connection for auth restart.
871 bool done = false, keep_alive = true;
[email protected]2d2697f92009-02-18 21:00:32872 if (result < 0) {
[email protected]0877e3d2009-10-17 22:29:57873 // Error or closed connection while reading the socket.
[email protected]2d2697f92009-02-18 21:00:32874 done = true;
[email protected]68873ba2009-06-04 21:49:23875 keep_alive = false;
[email protected]351ab642010-08-05 16:55:31876 } else if (stream_->IsResponseBodyComplete()) {
[email protected]0877e3d2009-10-17 22:29:57877 done = true;
[email protected]2d2697f92009-02-18 21:00:32878 }
879
880 if (done) {
881 DidDrainBodyForAuthRestart(keep_alive);
882 } else {
883 // Keep draining.
884 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
885 }
886
887 return OK;
888}
889
[email protected]8e3d2d32010-06-13 18:46:23890void HttpNetworkTransaction::LogTransactionConnectedMetrics() {
891 if (logged_response_time_)
892 return;
893
894 logged_response_time_ = true;
895
[email protected]a7e41312009-12-16 23:18:14896 base::TimeDelta total_duration = response_.response_time - start_time_;
[email protected]9a0a55f2009-04-13 23:23:03897
[email protected]510e854f2009-04-20 18:39:08898 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:58899 "Net.Transaction_Connected_Under_10",
[email protected]510e854f2009-04-20 18:39:08900 total_duration,
[email protected]9a0a55f2009-04-13 23:23:03901 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
902 100);
[email protected]1fa47592009-07-27 22:45:00903
[email protected]c38ec5a2010-08-25 23:32:38904 bool reused_socket = stream_->IsConnectionReused();
905 if (!reused_socket) {
[email protected]b01998a2009-04-21 01:01:11906 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:58907 "Net.Transaction_Connected_New",
[email protected]b01998a2009-04-21 01:01:11908 total_duration,
909 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
910 100);
[email protected]d068f7a2010-06-07 15:12:59911
912 static bool use_conn_impact_histogram(
[email protected]835d7c82010-10-14 04:38:38913 base::FieldTrialList::Find("ConnCountImpact") &&
914 !base::FieldTrialList::Find("ConnCountImpact")->group_name().empty());
[email protected]d068f7a2010-06-07 15:12:59915 if (use_conn_impact_histogram) {
916 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]835d7c82010-10-14 04:38:38917 base::FieldTrial::MakeName("Net.Transaction_Connected_New",
[email protected]d068f7a2010-06-07 15:12:59918 "ConnCountImpact"),
919 total_duration,
920 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
921 100);
922 }
[email protected]0310d432009-08-25 07:49:52923 }
924
[email protected]835d7c82010-10-14 04:38:38925 static bool use_spdy_histogram(base::FieldTrialList::Find("SpdyImpact") &&
926 !base::FieldTrialList::Find("SpdyImpact")->group_name().empty());
[email protected]8e3d2d32010-06-13 18:46:23927 if (use_spdy_histogram && response_.was_npn_negotiated) {
928 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]835d7c82010-10-14 04:38:38929 base::FieldTrial::MakeName("Net.Transaction_Connected_Under_10",
930 "SpdyImpact"),
[email protected]8e3d2d32010-06-13 18:46:23931 total_duration, base::TimeDelta::FromMilliseconds(1),
932 base::TimeDelta::FromMinutes(10), 100);
933
[email protected]c38ec5a2010-08-25 23:32:38934 if (!reused_socket) {
[email protected]8e3d2d32010-06-13 18:46:23935 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]835d7c82010-10-14 04:38:38936 base::FieldTrial::MakeName("Net.Transaction_Connected_New",
937 "SpdyImpact"),
[email protected]8e3d2d32010-06-13 18:46:23938 total_duration, base::TimeDelta::FromMilliseconds(1),
939 base::TimeDelta::FromMinutes(10), 100);
940 }
941 }
942
[email protected]510e854f2009-04-20 18:39:08943 // Currently, non-zero priority requests are frame or sub-frame resource
944 // types. This will change when we also prioritize certain subresources like
945 // css, js, etc.
946 if (request_->priority) {
947 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:58948 "Net.Priority_High_Latency",
[email protected]510e854f2009-04-20 18:39:08949 total_duration,
950 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
951 100);
952 } else {
953 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:58954 "Net.Priority_Low_Latency",
[email protected]510e854f2009-04-20 18:39:08955 total_duration,
956 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
957 100);
958 }
[email protected]9a0a55f2009-04-13 23:23:03959}
960
[email protected]56300172008-11-06 18:42:55961void HttpNetworkTransaction::LogTransactionMetrics() const {
[email protected]0877e3d2009-10-17 22:29:57962 base::TimeDelta duration = base::Time::Now() -
[email protected]2227c692010-05-04 15:36:11963 response_.request_time;
[email protected]56300172008-11-06 18:42:55964 if (60 < duration.InMinutes())
965 return;
[email protected]0b48db42009-03-23 02:45:11966
[email protected]21b316a2009-03-23 18:25:06967 base::TimeDelta total_duration = base::Time::Now() - start_time_;
968
[email protected]f929f2f22009-06-12 16:56:58969 UMA_HISTOGRAM_LONG_TIMES("Net.Transaction_Latency", duration);
970 UMA_HISTOGRAM_CLIPPED_TIMES("Net.Transaction_Latency_Under_10", duration,
[email protected]2227c692010-05-04 15:36:11971 base::TimeDelta::FromMilliseconds(1),
972 base::TimeDelta::FromMinutes(10),
973 100);
[email protected]f929f2f22009-06-12 16:56:58974 UMA_HISTOGRAM_CLIPPED_TIMES("Net.Transaction_Latency_Total_Under_10",
[email protected]2227c692010-05-04 15:36:11975 total_duration,
976 base::TimeDelta::FromMilliseconds(1),
977 base::TimeDelta::FromMinutes(10), 100);
[email protected]c38ec5a2010-08-25 23:32:38978 if (!stream_->IsConnectionReused()) {
[email protected]f929f2f22009-06-12 16:56:58979 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]808f6402009-03-30 20:02:07980 "Net.Transaction_Latency_Total_New_Connection_Under_10",
[email protected]808f6402009-03-30 20:02:07981 total_duration, base::TimeDelta::FromMilliseconds(1),
982 base::TimeDelta::FromMinutes(10), 100);
983 }
[email protected]56300172008-11-06 18:42:55984}
985
[email protected]5e363962009-06-19 19:57:01986int HttpNetworkTransaction::HandleCertificateRequest(int error) {
[email protected]8e6441ca2010-08-19 05:56:38987 // There are two paths through which the server can request a certificate
988 // from us. The first is during the initial handshake, the second is
989 // during SSL renegotiation.
990 //
991 // In both cases, we want to close the connection before proceeding.
992 // We do this for two reasons:
993 // First, we don't want to keep the connection to the server hung for a
994 // long time while the user selects a certificate.
995 // Second, even if we did keep the connection open, NSS has a bug where
996 // restarting the handshake for ClientAuth is currently broken.
[email protected]65a3b912010-08-21 05:46:58997 DCHECK_EQ(error, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]8e6441ca2010-08-19 05:56:38998
999 if (stream_.get()) {
1000 // Since we already have a stream, we're being called as part of SSL
1001 // renegotiation.
1002 DCHECK(!stream_request_.get());
1003 stream_->Close(true);
1004 stream_.reset();
1005 }
1006
[email protected]26816882010-10-14 18:03:091007 // The server is asking for a client certificate during the initial
1008 // handshake.
1009 stream_request_.reset();
[email protected]5e363962009-06-19 19:57:011010
[email protected]ec229bc92010-11-22 09:51:451011 // If the user selected one of the certificates in client_certs or declined
1012 // to provide one for this server before, use the past decision
1013 // automatically.
1014 scoped_refptr<X509Certificate> client_cert;
1015 bool found_cached_cert = session_->ssl_client_auth_cache()->Lookup(
1016 response_.cert_request_info->host_and_port, &client_cert);
1017 if (!found_cached_cert)
1018 return error;
1019
1020 // Check that the certificate selected is still a certificate the server
1021 // is likely to accept, based on the criteria supplied in the
1022 // CertificateRequest message.
[email protected]5e363962009-06-19 19:57:011023 if (client_cert) {
1024 const std::vector<scoped_refptr<X509Certificate> >& client_certs =
[email protected]a7e41312009-12-16 23:18:141025 response_.cert_request_info->client_certs;
[email protected]ec229bc92010-11-22 09:51:451026 bool cert_still_valid = false;
[email protected]5e363962009-06-19 19:57:011027 for (size_t i = 0; i < client_certs.size(); ++i) {
[email protected]ec229bc92010-11-22 09:51:451028 if (client_cert->Equals(client_certs[i])) {
1029 cert_still_valid = true;
1030 break;
[email protected]5e363962009-06-19 19:57:011031 }
1032 }
[email protected]ec229bc92010-11-22 09:51:451033
1034 if (!cert_still_valid)
1035 return error;
[email protected]5e363962009-06-19 19:57:011036 }
[email protected]ec229bc92010-11-22 09:51:451037
1038 // TODO(davidben): Add a unit test which covers this path; we need to be
1039 // able to send a legitimate certificate and also bypass/clear the
1040 // SSL session cache.
1041 ssl_config_.client_cert = client_cert;
1042 ssl_config_.send_client_cert = true;
1043 next_state_ = STATE_CREATE_STREAM;
1044 // Reset the other member variables.
1045 // Note: this is necessary only with SSL renegotiation.
1046 ResetStateForRestart();
1047 return OK;
[email protected]0b45559b2009-06-12 21:45:111048}
1049
[email protected]bd0b6772011-01-11 19:59:301050// TODO(rch): This does not correctly handle errors when an SSL proxy is
1051// being used, as all of the errors are handled as if they were generated
1052// by the endpoint host, request_->url, rather than considering if they were
[email protected]1c53a1f2011-01-13 00:36:381053// generated by the SSL proxy. http://crbug.com/69329
[email protected]bd0b6772011-01-11 19:59:301054int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
1055 DCHECK(request_);
1056 if (ssl_config_.send_client_cert &&
[email protected]a1cb2cd2011-02-05 02:02:081057 (error == ERR_SSL_PROTOCOL_ERROR || IsClientCertificateError(error))) {
[email protected]bd0b6772011-01-11 19:59:301058 session_->ssl_client_auth_cache()->Remove(
1059 GetHostAndPort(request_->url));
1060 }
1061
initial.commit586acc5fe2008-07-26 22:42:521062 switch (error) {
[email protected]bd0b6772011-01-11 19:59:301063 case ERR_SSL_PROTOCOL_ERROR:
1064 case ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
1065 case ERR_SSL_DECOMPRESSION_FAILURE_ALERT:
1066 case ERR_SSL_BAD_RECORD_MAC_ALERT:
1067 if (ssl_config_.tls1_enabled &&
1068 !SSLConfigService::IsKnownStrictTLSServer(request_->url.host())) {
1069 // This could be a TLS-intolerant server, an SSL 3.0 server that
1070 // chose a TLS-only cipher suite or a server with buggy DEFLATE
1071 // support. Turn off TLS 1.0, DEFLATE support and retry.
[email protected]2d6728692011-03-12 01:39:551072 session_->http_stream_factory()->AddTLSIntolerantServer(
1073 HostPortPair::FromURL(request_->url));
[email protected]1c773ea12009-04-28 19:58:421074 ResetConnectionAndRequestForResend();
initial.commit586acc5fe2008-07-26 22:42:521075 error = OK;
[email protected]1c773ea12009-04-28 19:58:421076 }
initial.commit586acc5fe2008-07-26 22:42:521077 break;
[email protected]73b8dd222010-11-11 19:55:241078 case ERR_SSL_SNAP_START_NPN_MISPREDICTION:
1079 // This means that we tried to Snap Start a connection, but we
1080 // mispredicted the NPN result. This isn't a problem from the point of
1081 // view of the SSL layer because the server will ignore the application
1082 // data in the Snap Start extension. However, at the HTTP layer, we have
1083 // already decided that it's a HTTP or SPDY connection and it's easier to
1084 // abort and start again.
1085 ResetConnectionAndRequestForResend();
1086 error = OK;
1087 break;
initial.commit586acc5fe2008-07-26 22:42:521088 }
1089 return error;
1090}
1091
[email protected]bd0b6772011-01-11 19:59:301092// This method determines whether it is safe to resend the request after an
1093// IO error. It can only be called in response to request header or body
1094// write errors or response header read errors. It should not be used in
1095// other cases, such as a Connect error.
1096int HttpNetworkTransaction::HandleIOError(int error) {
1097 // SSL errors may happen at any time during the stream and indicate issues
1098 // with the underlying connection. Because the peer may request
1099 // renegotiation at any time, check and handle any possible SSL handshake
1100 // related errors. In addition to renegotiation, TLS False/Snap Start may
[email protected]1c53a1f2011-01-13 00:36:381101 // cause SSL handshake errors to be delayed until the first or second Write
1102 // (Snap Start) or the first Read (False & Snap Start) on the underlying
1103 // connection.
[email protected]bd0b6772011-01-11 19:59:301104 error = HandleSSLHandshakeError(error);
1105
1106 switch (error) {
1107 // If we try to reuse a connection that the server is in the process of
1108 // closing, we may end up successfully writing out our request (or a
1109 // portion of our request) only to find a connection error when we try to
1110 // read from (or finish writing to) the socket.
1111 case ERR_CONNECTION_RESET:
1112 case ERR_CONNECTION_CLOSED:
1113 case ERR_CONNECTION_ABORTED:
1114 if (ShouldResendRequest(error)) {
1115 ResetConnectionAndRequestForResend();
1116 error = OK;
1117 }
1118 break;
1119 }
1120 return error;
1121}
1122
[email protected]c3b35c22008-09-27 03:19:421123void HttpNetworkTransaction::ResetStateForRestart() {
[email protected]697ef4c2010-10-14 16:38:581124 ResetStateForAuthRestart();
1125 stream_.reset();
1126}
1127
1128void HttpNetworkTransaction::ResetStateForAuthRestart() {
[email protected]0757e7702009-03-27 04:00:221129 pending_auth_target_ = HttpAuth::AUTH_NONE;
[email protected]c3b35c22008-09-27 03:19:421130 read_buf_ = NULL;
1131 read_buf_len_ = 0;
[email protected]0877e3d2009-10-17 22:29:571132 headers_valid_ = false;
[email protected]b94f92d2010-10-27 16:45:201133 request_headers_.Clear();
[email protected]a7e41312009-12-16 23:18:141134 response_ = HttpResponseInfo();
[email protected]8e6441ca2010-08-19 05:56:381135 establishing_tunnel_ = false;
[email protected]0877e3d2009-10-17 22:29:571136}
1137
1138HttpResponseHeaders* HttpNetworkTransaction::GetResponseHeaders() const {
[email protected]a7e41312009-12-16 23:18:141139 return response_.headers;
[email protected]c3b35c22008-09-27 03:19:421140}
1141
[email protected]a19f1c602009-08-24 21:35:281142bool HttpNetworkTransaction::ShouldResendRequest(int error) const {
[email protected]8e6441ca2010-08-19 05:56:381143 bool connection_is_proven = stream_->IsConnectionReused();
1144 bool has_received_headers = GetResponseHeaders() != NULL;
[email protected]58cebf8f2010-07-31 19:20:161145
[email protected]2a5c76b2008-09-25 22:15:161146 // NOTE: we resend a request only if we reused a keep-alive connection.
1147 // This automatically prevents an infinite resend loop because we'll run
1148 // out of the cached keep-alive connections eventually.
[email protected]8e6441ca2010-08-19 05:56:381149 if (connection_is_proven && !has_received_headers)
1150 return true;
1151 return false;
[email protected]1c773ea12009-04-28 19:58:421152}
1153
1154void HttpNetworkTransaction::ResetConnectionAndRequestForResend() {
[email protected]8e6441ca2010-08-19 05:56:381155 if (stream_.get()) {
1156 stream_->Close(true);
1157 stream_.reset();
[email protected]58cebf8f2010-07-31 19:20:161158 }
1159
[email protected]0877e3d2009-10-17 22:29:571160 // We need to clear request_headers_ because it contains the real request
1161 // headers, but we may need to resend the CONNECT request first to recreate
1162 // the SSL tunnel.
[email protected]b94f92d2010-10-27 16:45:201163 request_headers_.Clear();
[email protected]82918cc2010-08-25 17:24:501164 next_state_ = STATE_CREATE_STREAM; // Resend the request.
[email protected]86ec30d2008-09-29 21:53:541165}
1166
[email protected]1c773ea12009-04-28 19:58:421167bool HttpNetworkTransaction::ShouldApplyProxyAuth() const {
[email protected]2df19bb2010-08-25 20:13:461168 return !is_https_request() &&
1169 (proxy_info_.is_https() || proxy_info_.is_http());
[email protected]1c773ea12009-04-28 19:58:421170}
license.botbf09a502008-08-24 00:55:551171
[email protected]1c773ea12009-04-28 19:58:421172bool HttpNetworkTransaction::ShouldApplyServerAuth() const {
[email protected]8a1f3312010-05-25 19:25:041173 return !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA);
[email protected]1c773ea12009-04-28 19:58:421174}
1175
[email protected]e772db3f2010-07-12 18:11:131176int HttpNetworkTransaction::HandleAuthChallenge() {
[email protected]ad8e04a2010-11-01 04:16:271177 scoped_refptr<HttpResponseHeaders> headers(GetResponseHeaders());
[email protected]0877e3d2009-10-17 22:29:571178 DCHECK(headers);
[email protected]c3b35c22008-09-27 03:19:421179
[email protected]0877e3d2009-10-17 22:29:571180 int status = headers->response_code();
[email protected]c3b35c22008-09-27 03:19:421181 if (status != 401 && status != 407)
1182 return OK;
1183 HttpAuth::Target target = status == 407 ?
[email protected]2227c692010-05-04 15:36:111184 HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER;
[email protected]038e9a32008-10-08 22:40:161185 if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct())
1186 return ERR_UNEXPECTED_PROXY_AUTH;
[email protected]c3b35c22008-09-27 03:19:421187
[email protected]7a67a8152010-11-05 18:31:101188 // This case can trigger when an HTTPS server responds with a 407 status
1189 // code through a non-authenticating proxy.
1190 if (!auth_controllers_[target].get())
1191 return ERR_UNEXPECTED_PROXY_AUTH;
1192
[email protected]a7ea8832010-07-12 17:54:541193 int rv = auth_controllers_[target]->HandleAuthChallenge(
[email protected]560c0432010-07-13 20:45:311194 headers, (request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA) != 0, false,
1195 net_log_);
[email protected]228404f2010-06-24 04:31:411196 if (auth_controllers_[target]->HaveAuthHandler())
1197 pending_auth_target_ = target;
1198
1199 scoped_refptr<AuthChallengeInfo> auth_info =
1200 auth_controllers_[target]->auth_info();
1201 if (auth_info.get())
1202 response_.auth_challenge = auth_info;
1203
[email protected]228404f2010-06-24 04:31:411204 return rv;
[email protected]f9ee6b52008-11-08 06:46:231205}
1206
[email protected]8e6441ca2010-08-19 05:56:381207bool HttpNetworkTransaction::HaveAuth(HttpAuth::Target target) const {
1208 return auth_controllers_[target].get() &&
1209 auth_controllers_[target]->HaveAuth();
1210}
1211
1212
[email protected]228404f2010-06-24 04:31:411213GURL HttpNetworkTransaction::AuthURL(HttpAuth::Target target) const {
1214 switch (target) {
[email protected]2df19bb2010-08-25 20:13:461215 case HttpAuth::AUTH_PROXY: {
[email protected]228404f2010-06-24 04:31:411216 if (!proxy_info_.proxy_server().is_valid() ||
1217 proxy_info_.proxy_server().is_direct()) {
1218 return GURL(); // There is no proxy server.
1219 }
[email protected]2df19bb2010-08-25 20:13:461220 const char* scheme = proxy_info_.is_https() ? "https://" : "http://";
1221 return GURL(scheme +
[email protected]2fbaecf22010-07-22 22:20:351222 proxy_info_.proxy_server().host_port_pair().ToString());
[email protected]2df19bb2010-08-25 20:13:461223 }
[email protected]228404f2010-06-24 04:31:411224 case HttpAuth::AUTH_SERVER:
1225 return request_->url;
1226 default:
1227 return GURL();
1228 }
[email protected]c3b35c22008-09-27 03:19:421229}
1230
[email protected]d8eb84242010-09-25 02:25:061231#define STATE_CASE(s) \
1232 case s: \
1233 description = base::StringPrintf("%s (0x%08X)", #s, s); \
1234 break
[email protected]aef04272010-06-28 18:03:041235
1236std::string HttpNetworkTransaction::DescribeState(State state) {
1237 std::string description;
1238 switch (state) {
[email protected]82918cc2010-08-25 17:24:501239 STATE_CASE(STATE_CREATE_STREAM);
1240 STATE_CASE(STATE_CREATE_STREAM_COMPLETE);
[email protected]aef04272010-06-28 18:03:041241 STATE_CASE(STATE_SEND_REQUEST);
1242 STATE_CASE(STATE_SEND_REQUEST_COMPLETE);
1243 STATE_CASE(STATE_READ_HEADERS);
1244 STATE_CASE(STATE_READ_HEADERS_COMPLETE);
[email protected]aef04272010-06-28 18:03:041245 STATE_CASE(STATE_READ_BODY);
1246 STATE_CASE(STATE_READ_BODY_COMPLETE);
1247 STATE_CASE(STATE_DRAIN_BODY_FOR_AUTH_RESTART);
1248 STATE_CASE(STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE);
[email protected]aef04272010-06-28 18:03:041249 STATE_CASE(STATE_NONE);
1250 default:
[email protected]d8eb84242010-09-25 02:25:061251 description = base::StringPrintf("Unknown state 0x%08X (%u)", state,
1252 state);
[email protected]aef04272010-06-28 18:03:041253 break;
1254 }
1255 return description;
1256}
1257
1258#undef STATE_CASE
1259
[email protected]c3b35c22008-09-27 03:19:421260} // namespace net