blob: e6084bc5d35d843497aebaf77d770288f17a545f [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]0b48db42009-03-23 02:45:1111#include "base/field_trial.h"
[email protected]270c6412010-03-29 22:02:4712#include "base/format_macros.h"
[email protected]21983942009-08-18 06:17:5013#include "base/histogram.h"
[email protected]270c6412010-03-29 22:02:4714#include "base/scoped_ptr.h"
[email protected]5e2e6c77d12009-12-24 21:57:1615#include "base/stats_counters.h"
[email protected]aeaca1f2010-04-20 22:05:2116#include "base/stl_util-inl.h"
initial.commit586acc5fe2008-07-26 22:42:5217#include "base/string_util.h"
[email protected]528c56d2010-07-30 19:28:4418#include "base/string_number_conversions.h"
[email protected]68bf9152008-09-25 19:47:3019#include "build/build_config.h"
[email protected]631f1322010-04-30 17:59:1120#include "googleurl/src/gurl.h"
[email protected]277d5942010-08-11 21:02:3521#include "net/base/auth.h"
[email protected]74a85ce2009-02-12 00:03:1922#include "net/base/io_buffer.h"
initial.commit586acc5fe2008-07-26 22:42:5223#include "net/base/load_flags.h"
[email protected]597cf6e2009-05-29 09:43:2624#include "net/base/net_errors.h"
[email protected]c3b35c22008-09-27 03:19:4225#include "net/base/net_util.h"
[email protected]0b45559b2009-06-12 21:45:1126#include "net/base/ssl_cert_request_info.h"
[email protected]fc7de492010-07-12 14:49:0427#include "net/base/ssl_connection_status_flags.h"
initial.commit586acc5fe2008-07-26 22:42:5228#include "net/base/upload_data_stream.h"
[email protected]c3b35c22008-09-27 03:19:4229#include "net/http/http_auth.h"
30#include "net/http/http_auth_handler.h"
[email protected]fa82f932010-05-20 11:09:2431#include "net/http/http_auth_handler_factory.h"
[email protected]8d5a34e2009-06-11 21:21:3632#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5233#include "net/http/http_chunked_decoder.h"
[email protected]a7ea8832010-07-12 17:54:5434#include "net/http/http_net_log_params.h"
initial.commit586acc5fe2008-07-26 22:42:5235#include "net/http/http_network_session.h"
[email protected]a7ea8832010-07-12 17:54:5436#include "net/http/http_proxy_client_socket.h"
[email protected]e772db3f2010-07-12 18:11:1337#include "net/http/http_proxy_client_socket_pool.h"
[email protected]270c6412010-03-29 22:02:4738#include "net/http/http_request_headers.h"
initial.commit586acc5fe2008-07-26 22:42:5239#include "net/http/http_request_info.h"
[email protected]319d9e6f2009-02-18 19:47:2140#include "net/http/http_response_headers.h"
[email protected]0877e3d2009-10-17 22:29:5741#include "net/http/http_response_info.h"
[email protected]8e6441ca2010-08-19 05:56:3842#include "net/http/http_stream_handle.h"
43#include "net/http/http_stream_request.h"
initial.commit586acc5fe2008-07-26 22:42:5244#include "net/http/http_util.h"
[email protected]d7f16632010-03-29 18:02:3645#include "net/http/url_security_manager.h"
[email protected]f7984fc62009-06-22 23:26:4446#include "net/socket/client_socket_factory.h"
[email protected]a796bcec2010-03-22 17:17:2647#include "net/socket/socks_client_socket_pool.h"
[email protected]f7984fc62009-06-22 23:26:4448#include "net/socket/ssl_client_socket.h"
[email protected]e60e47a2010-07-14 03:37:1849#include "net/socket/ssl_client_socket_pool.h"
[email protected]7fc5b09a2010-02-27 00:07:3850#include "net/socket/tcp_client_socket_pool.h"
[email protected]65d56aa2010-06-14 04:13:4051#include "net/spdy/spdy_http_stream.h"
[email protected]dab9c7d2010-02-06 21:44:3252#include "net/spdy/spdy_session.h"
53#include "net/spdy/spdy_session_pool.h"
initial.commit586acc5fe2008-07-26 22:42:5254
[email protected]e1acf6f2008-10-27 20:43:3355using base::Time;
56
initial.commit586acc5fe2008-07-26 22:42:5257namespace net {
58
[email protected]1c773ea12009-04-28 19:58:4259namespace {
60
61void BuildRequestHeaders(const HttpRequestInfo* request_info,
[email protected]270c6412010-03-29 22:02:4762 const HttpRequestHeaders& authorization_headers,
[email protected]1c773ea12009-04-28 19:58:4263 const UploadDataStream* upload_data_stream,
64 bool using_proxy,
[email protected]8c76ae22010-04-20 22:15:4365 std::string* request_line,
[email protected]270c6412010-03-29 22:02:4766 HttpRequestHeaders* request_headers) {
67 const std::string path = using_proxy ?
[email protected]2227c692010-05-04 15:36:1168 HttpUtil::SpecForRequest(request_info->url) :
69 HttpUtil::PathForRequest(request_info->url);
[email protected]8c76ae22010-04-20 22:15:4370 *request_line = StringPrintf(
71 "%s %s HTTP/1.1\r\n", request_info->method.c_str(), path.c_str());
[email protected]270c6412010-03-29 22:02:4772 request_headers->SetHeader(HttpRequestHeaders::kHost,
73 GetHostAndOptionalPort(request_info->url));
74
75 // For compat with HTTP/1.0 servers and proxies:
76 if (using_proxy) {
77 request_headers->SetHeader(HttpRequestHeaders::kProxyConnection,
78 "keep-alive");
79 } else {
80 request_headers->SetHeader(HttpRequestHeaders::kConnection, "keep-alive");
81 }
82
[email protected]270c6412010-03-29 22:02:4783 // Our consumer should have made sure that this is a safe referrer. See for
84 // instance WebCore::FrameLoader::HideReferrer.
85 if (request_info->referrer.is_valid()) {
86 request_headers->SetHeader(HttpRequestHeaders::kReferer,
87 request_info->referrer.spec());
88 }
89
90 // Add a content length header?
91 if (upload_data_stream) {
92 request_headers->SetHeader(
93 HttpRequestHeaders::kContentLength,
[email protected]e83326f2010-07-31 17:29:2594 base::Uint64ToString(upload_data_stream->size()));
[email protected]270c6412010-03-29 22:02:4795 } else if (request_info->method == "POST" || request_info->method == "PUT" ||
96 request_info->method == "HEAD") {
97 // An empty POST/PUT request still needs a content length. As for HEAD,
98 // IE and Safari also add a content length header. Presumably it is to
99 // support sending a HEAD request to an URL that only expects to be sent a
100 // POST or some other method that normally would have a message body.
101 request_headers->SetHeader(HttpRequestHeaders::kContentLength, "0");
102 }
103
104 // Honor load flags that impact proxy caches.
105 if (request_info->load_flags & LOAD_BYPASS_CACHE) {
106 request_headers->SetHeader(HttpRequestHeaders::kPragma, "no-cache");
107 request_headers->SetHeader(HttpRequestHeaders::kCacheControl, "no-cache");
108 } else if (request_info->load_flags & LOAD_VALIDATE_CACHE) {
109 request_headers->SetHeader(HttpRequestHeaders::kCacheControl, "max-age=0");
110 }
111
112 request_headers->MergeFrom(authorization_headers);
113
[email protected]860c85d2010-02-10 07:22:40114 // Headers that will be stripped from request_info->extra_headers to prevent,
115 // e.g., plugins from overriding headers that are controlled using other
116 // means. Otherwise a plugin could set a referrer although sending the
117 // referrer is inhibited.
118 // TODO(jochen): check whether also other headers should be stripped.
119 static const char* const kExtraHeadersToBeStripped[] = {
120 "Referer"
121 };
122
[email protected]8c76ae22010-04-20 22:15:43123 HttpRequestHeaders stripped_extra_headers;
124 stripped_extra_headers.CopyFrom(request_info->extra_headers);
[email protected]2227c692010-05-04 15:36:11125 for (size_t i = 0; i < arraysize(kExtraHeadersToBeStripped); ++i)
126 stripped_extra_headers.RemoveHeader(kExtraHeadersToBeStripped[i]);
[email protected]8c76ae22010-04-20 22:15:43127 request_headers->MergeFrom(stripped_extra_headers);
[email protected]1c773ea12009-04-28 19:58:42128}
129
[email protected]8e6441ca2010-08-19 05:56:38130void ProcessAlternateProtocol(HttpStreamFactory* factory,
131 HttpAlternateProtocols* alternate_protocols,
132 const HttpResponseHeaders& headers,
133 const HostPortPair& http_host_port_pair) {
[email protected]564b4912010-03-09 16:30:42134 std::string alternate_protocol_str;
[email protected]8e6441ca2010-08-19 05:56:38135
[email protected]564b4912010-03-09 16:30:42136 if (!headers.EnumerateHeader(NULL, HttpAlternateProtocols::kHeader,
137 &alternate_protocol_str)) {
138 // Header is not present.
139 return;
140 }
141
[email protected]8e6441ca2010-08-19 05:56:38142 factory->ProcessAlternateProtocol(alternate_protocols,
143 alternate_protocol_str,
144 http_host_port_pair);
[email protected]f45c1ee2010-08-03 00:54:30145}
146
[email protected]1c773ea12009-04-28 19:58:42147} // namespace
148
initial.commit586acc5fe2008-07-26 22:42:52149//-----------------------------------------------------------------------------
150
[email protected]5695b8c2009-09-30 21:36:43151HttpNetworkTransaction::HttpNetworkTransaction(HttpNetworkSession* session)
[email protected]0757e7702009-03-27 04:00:22152 : pending_auth_target_(HttpAuth::AUTH_NONE),
153 ALLOW_THIS_IN_INITIALIZER_LIST(
[email protected]68bf9152008-09-25 19:47:30154 io_callback_(this, &HttpNetworkTransaction::OnIOComplete)),
initial.commit586acc5fe2008-07-26 22:42:52155 user_callback_(NULL),
156 session_(session),
157 request_(NULL),
[email protected]0877e3d2009-10-17 22:29:57158 headers_valid_(false),
[email protected]8e3d2d32010-06-13 18:46:23159 logged_response_time_(false),
initial.commit586acc5fe2008-07-26 22:42:52160 read_buf_len_(0),
[email protected]a7ea8832010-07-12 17:54:54161 next_state_(STATE_NONE),
162 establishing_tunnel_(false) {
[email protected]2cd713f2008-10-21 17:54:28163 session->ssl_config_service()->GetSSLConfig(&ssl_config_);
[email protected]8e6441ca2010-08-19 05:56:38164 if (session->http_stream_factory()->next_protos())
165 ssl_config_.next_protos = *session->http_stream_factory()->next_protos();
[email protected]1f14a912009-12-21 20:32:44166
[email protected]3ce7df0f2010-03-03 00:30:50167}
168
[email protected]0b0bf032010-09-21 18:08:50169HttpNetworkTransaction::~HttpNetworkTransaction() {
170 if (stream_.get()) {
171 HttpResponseHeaders* headers = GetResponseHeaders();
172 // TODO(mbelshe): The stream_ should be able to compute whether or not the
173 // stream should be kept alive. No reason to compute here
174 // and pass it in.
175 bool try_to_keep_alive =
176 next_state_ == STATE_NONE &&
177 stream_->CanFindEndOfResponse() &&
178 (!headers || headers->IsKeepAlive());
179 if (!try_to_keep_alive) {
180 stream_->Close(true /* not reusable */);
181 } else {
182 if (stream_->IsResponseBodyComplete()) {
183 // If the response body is complete, we can just reuse the socket.
184 stream_->Close(false /* reusable */);
185 } else {
186 // Otherwise, we try to drain the response body.
187 // TODO(willchan): Consider moving this response body draining to the
188 // stream implementation. For SPDY, there's clearly no point. For
189 // HTTP, it can vary depending on whether or not we're pipelining. It's
190 // stream dependent, so the different subtypes should be implementing
191 // their solutions.
192 HttpUtil::DrainStreamBodyAndClose(stream_.release());
193 }
194 }
195 }
196
197 if (stream_request_.get()) {
198 stream_request_->Cancel();
199 stream_request_ = NULL;
200 }
201}
202
[email protected]684970b2009-08-14 04:54:46203int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info,
204 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53205 const BoundNetLog& net_log) {
[email protected]5e2e6c77d12009-12-24 21:57:16206 SIMPLE_STATS_COUNTER("HttpNetworkTransaction.Count");
[email protected]5d0153c512009-01-12 19:08:36207
[email protected]9e743cd2010-03-16 07:03:53208 net_log_ = net_log;
[email protected]96d570e42008-08-05 22:43:04209 request_ = request_info;
[email protected]21b316a2009-03-23 18:25:06210 start_time_ = base::Time::Now();
[email protected]96d570e42008-08-05 22:43:04211
[email protected]82918cc2010-08-25 17:24:50212 next_state_ = STATE_CREATE_STREAM;
[email protected]96d570e42008-08-05 22:43:04213 int rv = DoLoop(OK);
214 if (rv == ERR_IO_PENDING)
215 user_callback_ = callback;
216 return rv;
217}
218
219int HttpNetworkTransaction::RestartIgnoringLastError(
220 CompletionCallback* callback) {
[email protected]8e6441ca2010-08-19 05:56:38221 DCHECK(!stream_.get());
222 DCHECK(!stream_request_.get());
223 DCHECK_EQ(STATE_NONE, next_state_);
224
[email protected]82918cc2010-08-25 17:24:50225 next_state_ = STATE_CREATE_STREAM;
[email protected]8e6441ca2010-08-19 05:56:38226
[email protected]ccb40e52008-09-17 20:54:40227 int rv = DoLoop(OK);
228 if (rv == ERR_IO_PENDING)
229 user_callback_ = callback;
[email protected]aaead502008-10-15 00:20:11230 return rv;
[email protected]96d570e42008-08-05 22:43:04231}
232
[email protected]0b45559b2009-06-12 21:45:11233int HttpNetworkTransaction::RestartWithCertificate(
234 X509Certificate* client_cert,
235 CompletionCallback* callback) {
[email protected]8e6441ca2010-08-19 05:56:38236 // In HandleCertificateRequest(), we always tear down existing stream
237 // requests to force a new connection. So we shouldn't have one here.
238 DCHECK(!stream_request_.get());
239 DCHECK(!stream_.get());
240 DCHECK_EQ(STATE_NONE, next_state_);
241
[email protected]0b45559b2009-06-12 21:45:11242 ssl_config_.client_cert = client_cert;
[email protected]5e363962009-06-19 19:57:01243 if (client_cert) {
244 session_->ssl_client_auth_cache()->Add(GetHostAndPort(request_->url),
245 client_cert);
246 }
[email protected]0b45559b2009-06-12 21:45:11247 ssl_config_.send_client_cert = true;
[email protected]0b45559b2009-06-12 21:45:11248 // Reset the other member variables.
249 // Note: this is necessary only with SSL renegotiation.
250 ResetStateForRestart();
[email protected]82918cc2010-08-25 17:24:50251 next_state_ = STATE_CREATE_STREAM;
[email protected]0b45559b2009-06-12 21:45:11252 int rv = DoLoop(OK);
253 if (rv == ERR_IO_PENDING)
254 user_callback_ = callback;
255 return rv;
256}
257
[email protected]96d570e42008-08-05 22:43:04258int HttpNetworkTransaction::RestartWithAuth(
[email protected]13c8a092010-07-29 06:15:44259 const string16& username,
260 const string16& password,
[email protected]96d570e42008-08-05 22:43:04261 CompletionCallback* callback) {
[email protected]0757e7702009-03-27 04:00:22262 HttpAuth::Target target = pending_auth_target_;
263 if (target == HttpAuth::AUTH_NONE) {
264 NOTREACHED();
265 return ERR_UNEXPECTED;
266 }
[email protected]0757e7702009-03-27 04:00:22267 pending_auth_target_ = HttpAuth::AUTH_NONE;
[email protected]c3b35c22008-09-27 03:19:42268
[email protected]e772db3f2010-07-12 18:11:13269 auth_controllers_[target]->ResetAuth(username, password);
270
[email protected]8e6441ca2010-08-19 05:56:38271 DCHECK(user_callback_ == NULL);
272
273 int rv = OK;
274 if (target == HttpAuth::AUTH_PROXY && establishing_tunnel_) {
275 // In this case, we've gathered credentials for use with proxy
276 // authentication of a tunnel.
[email protected]82918cc2010-08-25 17:24:50277 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38278 DCHECK(stream_request_ != NULL);
[email protected]394816e92010-08-03 07:38:59279 auth_controllers_[target] = NULL;
[email protected]a7ea8832010-07-12 17:54:54280 ResetStateForRestart();
[email protected]8e6441ca2010-08-19 05:56:38281 rv = stream_request_->RestartTunnelWithProxyAuth(username, password);
[email protected]a7ea8832010-07-12 17:54:54282 } else {
[email protected]8e6441ca2010-08-19 05:56:38283 // In this case, we've gathered credentials for the server or the proxy
284 // but it is not during the tunneling phase.
285 DCHECK(stream_request_ == NULL);
[email protected]a7ea8832010-07-12 17:54:54286 PrepareForAuthRestart(target);
[email protected]8e6441ca2010-08-19 05:56:38287 rv = DoLoop(OK);
[email protected]a7ea8832010-07-12 17:54:54288 }
[email protected]c3b35c22008-09-27 03:19:42289
[email protected]c3b35c22008-09-27 03:19:42290 if (rv == ERR_IO_PENDING)
291 user_callback_ = callback;
[email protected]c3b35c22008-09-27 03:19:42292 return rv;
[email protected]96d570e42008-08-05 22:43:04293}
294
[email protected]f9ee6b52008-11-08 06:46:23295void HttpNetworkTransaction::PrepareForAuthRestart(HttpAuth::Target target) {
296 DCHECK(HaveAuth(target));
[email protected]8e6441ca2010-08-19 05:56:38297 DCHECK(!stream_request_.get());
298
[email protected]2d2697f92009-02-18 21:00:32299 bool keep_alive = false;
[email protected]0877e3d2009-10-17 22:29:57300 // Even if the server says the connection is keep-alive, we have to be
301 // able to find the end of each response in order to reuse the connection.
302 if (GetResponseHeaders()->IsKeepAlive() &&
[email protected]351ab642010-08-05 16:55:31303 stream_->CanFindEndOfResponse()) {
[email protected]0877e3d2009-10-17 22:29:57304 // If the response body hasn't been completely read, we need to drain
305 // it first.
[email protected]351ab642010-08-05 16:55:31306 if (!stream_->IsResponseBodyComplete()) {
[email protected]2d2697f92009-02-18 21:00:32307 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
[email protected]0877e3d2009-10-17 22:29:57308 read_buf_ = new IOBuffer(kDrainBodyBufferSize); // A bit bucket.
[email protected]2d2697f92009-02-18 21:00:32309 read_buf_len_ = kDrainBodyBufferSize;
310 return;
311 }
[email protected]0877e3d2009-10-17 22:29:57312 keep_alive = true;
[email protected]37832c6d2009-06-05 19:44:09313 }
314
[email protected]2d2697f92009-02-18 21:00:32315 // We don't need to drain the response body, so we act as if we had drained
316 // the response body.
317 DidDrainBodyForAuthRestart(keep_alive);
318}
319
320void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) {
[email protected]8e6441ca2010-08-19 05:56:38321 DCHECK(!stream_request_.get());
322
323 if (stream_.get()) {
324 if (keep_alive) {
325 // We should call connection_->set_idle_time(), but this doesn't occur
326 // often enough to be worth the trouble.
327 stream_->SetConnectionReused();
328 }
329 stream_->Close(!keep_alive);
[email protected]82918cc2010-08-25 17:24:50330 next_state_ = STATE_CREATE_STREAM;
[email protected]2d2697f92009-02-18 21:00:32331 }
[email protected]f9ee6b52008-11-08 06:46:23332
333 // Reset the other member variables.
334 ResetStateForRestart();
335}
336
[email protected]8e6441ca2010-08-19 05:56:38337bool HttpNetworkTransaction::IsReadyToRestartForAuth() {
338 return pending_auth_target_ != HttpAuth::AUTH_NONE &&
339 HaveAuth(pending_auth_target_);
340}
341
[email protected]9dea9e1f2009-01-29 00:30:47342int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len,
[email protected]96d570e42008-08-05 22:43:04343 CompletionCallback* callback) {
[email protected]96d570e42008-08-05 22:43:04344 DCHECK(buf);
[email protected]e0c27be2009-07-15 13:09:35345 DCHECK_LT(0, buf_len);
[email protected]96d570e42008-08-05 22:43:04346
[email protected]1f14a912009-12-21 20:32:44347 State next_state = STATE_NONE;
[email protected]96d570e42008-08-05 22:43:04348
[email protected]8a1f3312010-05-25 19:25:04349 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
[email protected]8e6441ca2010-08-19 05:56:38350 if (headers_valid_ && headers.get() && stream_request_.get()) {
[email protected]8a1f3312010-05-25 19:25:04351 // We're trying to read the body of the response but we're still trying
352 // to establish an SSL tunnel through the proxy. We can't read these
353 // bytes when establishing a tunnel because they might be controlled by
354 // an active network attacker. We don't worry about this for HTTP
355 // because an active network attacker can already control HTTP sessions.
356 // We reach this case when the user cancels a 407 proxy auth prompt.
357 // See http://crbug.com/8473.
[email protected]2df19bb2010-08-25 20:13:46358 DCHECK(proxy_info_.is_http() || proxy_info_.is_https());
[email protected]a7ea8832010-07-12 17:54:54359 DCHECK_EQ(headers->response_code(), 407);
360 LOG(WARNING) << "Blocked proxy response with status "
361 << headers->response_code() << " to CONNECT request for "
362 << GetHostAndPort(request_->url) << ".";
[email protected]8a1f3312010-05-25 19:25:04363 return ERR_TUNNEL_CONNECTION_FAILED;
[email protected]a8e9b162009-03-12 00:06:44364 }
365
[email protected]e60e47a2010-07-14 03:37:18366 // Are we using SPDY or HTTP?
[email protected]351ab642010-08-05 16:55:31367 next_state = STATE_READ_BODY;
368 DCHECK(stream_->GetResponseInfo()->headers);
[email protected]e60e47a2010-07-14 03:37:18369
[email protected]96d570e42008-08-05 22:43:04370 read_buf_ = buf;
371 read_buf_len_ = buf_len;
372
[email protected]1f14a912009-12-21 20:32:44373 next_state_ = next_state;
[email protected]96d570e42008-08-05 22:43:04374 int rv = DoLoop(OK);
375 if (rv == ERR_IO_PENDING)
376 user_callback_ = callback;
377 return rv;
378}
379
380const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const {
[email protected]a7e41312009-12-16 23:18:14381 return ((headers_valid_ && response_.headers) || response_.ssl_info.cert ||
382 response_.cert_request_info) ? &response_ : NULL;
[email protected]96d570e42008-08-05 22:43:04383}
384
385LoadState HttpNetworkTransaction::GetLoadState() const {
386 // TODO(wtc): Define a new LoadState value for the
387 // STATE_INIT_CONNECTION_COMPLETE state, which delays the HTTP request.
388 switch (next_state_) {
[email protected]82918cc2010-08-25 17:24:50389 case STATE_CREATE_STREAM_COMPLETE:
[email protected]8e6441ca2010-08-19 05:56:38390 return stream_request_->GetLoadState();
[email protected]044de0642010-06-17 10:42:15391 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE:
392 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE:
[email protected]0877e3d2009-10-17 22:29:57393 case STATE_SEND_REQUEST_COMPLETE:
[email protected]96d570e42008-08-05 22:43:04394 return LOAD_STATE_SENDING_REQUEST;
395 case STATE_READ_HEADERS_COMPLETE:
396 return LOAD_STATE_WAITING_FOR_RESPONSE;
397 case STATE_READ_BODY_COMPLETE:
398 return LOAD_STATE_READING_RESPONSE;
399 default:
400 return LOAD_STATE_IDLE;
401 }
402}
403
404uint64 HttpNetworkTransaction::GetUploadProgress() const {
[email protected]351ab642010-08-05 16:55:31405 if (!stream_.get())
[email protected]96d570e42008-08-05 22:43:04406 return 0;
407
[email protected]351ab642010-08-05 16:55:31408 return stream_->GetUploadProgress();
[email protected]96d570e42008-08-05 22:43:04409}
410
[email protected]8e6441ca2010-08-19 05:56:38411void HttpNetworkTransaction::OnStreamReady(HttpStreamHandle* stream) {
[email protected]82918cc2010-08-25 17:24:50412 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38413 DCHECK(stream_request_.get());
414
415 stream_.reset(stream);
416 response_.was_alternate_protocol_available =
417 stream_request_->was_alternate_protocol_available();
418 response_.was_npn_negotiated = stream_request_->was_npn_negotiated();
419 response_.was_fetched_via_spdy = stream_request_->using_spdy();
420 response_.was_fetched_via_proxy = !proxy_info_.is_direct();
[email protected]8e6441ca2010-08-19 05:56:38421
422 OnIOComplete(OK);
423}
424
425void HttpNetworkTransaction::OnStreamFailed(int result) {
[email protected]82918cc2010-08-25 17:24:50426 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38427 DCHECK_NE(OK, result);
428 DCHECK(stream_request_.get());
429 DCHECK(!stream_.get());
430
431 OnIOComplete(result);
432}
433
434void HttpNetworkTransaction::OnCertificateError(int result,
435 const SSLInfo& ssl_info) {
[email protected]82918cc2010-08-25 17:24:50436 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38437 DCHECK_NE(OK, result);
438 DCHECK(stream_request_.get());
439 DCHECK(!stream_.get());
440
441 response_.ssl_info = ssl_info;
442
443 // TODO(mbelshe): For now, we're going to pass the error through, and that
444 // will close the stream_request in all cases. This means that we're always
[email protected]82918cc2010-08-25 17:24:50445 // going to restart an entire STATE_CREATE_STREAM, even if the connection is
446 // good and the user chooses to ignore the error. This is not ideal, but not
447 // the end of the world either.
[email protected]8e6441ca2010-08-19 05:56:38448
449 OnIOComplete(result);
450}
451
452void HttpNetworkTransaction::OnNeedsProxyAuth(
[email protected]6dc476da2010-09-01 04:43:50453 const HttpResponseInfo& proxy_response,
454 HttpAuthController* auth_controller) {
[email protected]8e6441ca2010-08-19 05:56:38455 DCHECK(stream_request_.get());
[email protected]82918cc2010-08-25 17:24:50456 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38457
458 establishing_tunnel_ = true;
459 response_.headers = proxy_response.headers;
460 response_.auth_challenge = proxy_response.auth_challenge;
461 headers_valid_ = true;
462
463 auth_controllers_[HttpAuth::AUTH_PROXY] = auth_controller;
464 pending_auth_target_ = HttpAuth::AUTH_PROXY;
465
466 DoCallback(OK);
467}
468
469void HttpNetworkTransaction::OnNeedsClientAuth(
[email protected]6dc476da2010-09-01 04:43:50470 SSLCertRequestInfo* cert_info) {
[email protected]82918cc2010-08-25 17:24:50471 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38472
473 response_.cert_request_info = cert_info;
[email protected]65a3b912010-08-21 05:46:58474 OnIOComplete(ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]8e6441ca2010-08-19 05:56:38475}
476
[email protected]8e6441ca2010-08-19 05:56:38477bool HttpNetworkTransaction::is_https_request() const {
478 return request_->url.SchemeIs("https");
initial.commit586acc5fe2008-07-26 22:42:52479}
480
initial.commit586acc5fe2008-07-26 22:42:52481void HttpNetworkTransaction::DoCallback(int rv) {
[email protected]0b0bf032010-09-21 18:08:50482 DCHECK_NE(rv, ERR_IO_PENDING);
initial.commit586acc5fe2008-07-26 22:42:52483 DCHECK(user_callback_);
484
[email protected]96d570e42008-08-05 22:43:04485 // Since Run may result in Read being called, clear user_callback_ up front.
initial.commit586acc5fe2008-07-26 22:42:52486 CompletionCallback* c = user_callback_;
487 user_callback_ = NULL;
488 c->Run(rv);
489}
490
491void HttpNetworkTransaction::OnIOComplete(int result) {
492 int rv = DoLoop(result);
493 if (rv != ERR_IO_PENDING)
494 DoCallback(rv);
495}
496
497int HttpNetworkTransaction::DoLoop(int result) {
498 DCHECK(next_state_ != STATE_NONE);
499
500 int rv = result;
501 do {
502 State state = next_state_;
503 next_state_ = STATE_NONE;
504 switch (state) {
[email protected]82918cc2010-08-25 17:24:50505 case STATE_CREATE_STREAM:
506 DCHECK_EQ(OK, rv);
507 rv = DoCreateStream();
508 break;
509 case STATE_CREATE_STREAM_COMPLETE:
510 rv = DoCreateStreamComplete(rv);
511 break;
[email protected]351ab642010-08-05 16:55:31512 case STATE_INIT_STREAM:
513 DCHECK_EQ(OK, rv);
514 rv = DoInitStream();
515 break;
516 case STATE_INIT_STREAM_COMPLETE:
517 rv = DoInitStreamComplete(rv);
518 break;
[email protected]044de0642010-06-17 10:42:15519 case STATE_GENERATE_PROXY_AUTH_TOKEN:
520 DCHECK_EQ(OK, rv);
521 rv = DoGenerateProxyAuthToken();
522 break;
523 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE:
524 rv = DoGenerateProxyAuthTokenComplete(rv);
525 break;
526 case STATE_GENERATE_SERVER_AUTH_TOKEN:
527 DCHECK_EQ(OK, rv);
528 rv = DoGenerateServerAuthToken();
529 break;
530 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE:
531 rv = DoGenerateServerAuthTokenComplete(rv);
532 break;
[email protected]0877e3d2009-10-17 22:29:57533 case STATE_SEND_REQUEST:
[email protected]725355a2009-03-25 20:42:55534 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09535 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, NULL);
[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]ec11be62010-04-28 19:28:09540 net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, NULL);
initial.commit586acc5fe2008-07-26 22:42:52541 break;
542 case STATE_READ_HEADERS:
[email protected]725355a2009-03-25 20:42:55543 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09544 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, NULL);
initial.commit586acc5fe2008-07-26 22:42:52545 rv = DoReadHeaders();
546 break;
547 case STATE_READ_HEADERS_COMPLETE:
548 rv = DoReadHeadersComplete(rv);
[email protected]ec11be62010-04-28 19:28:09549 net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, NULL);
initial.commit586acc5fe2008-07-26 22:42:52550 break;
551 case STATE_READ_BODY:
[email protected]725355a2009-03-25 20:42:55552 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09553 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, NULL);
initial.commit586acc5fe2008-07-26 22:42:52554 rv = DoReadBody();
555 break;
556 case STATE_READ_BODY_COMPLETE:
557 rv = DoReadBodyComplete(rv);
[email protected]ec11be62010-04-28 19:28:09558 net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, NULL);
initial.commit586acc5fe2008-07-26 22:42:52559 break;
[email protected]2d2697f92009-02-18 21:00:32560 case STATE_DRAIN_BODY_FOR_AUTH_RESTART:
[email protected]725355a2009-03-25 20:42:55561 DCHECK_EQ(OK, rv);
[email protected]9e743cd2010-03-16 07:03:53562 net_log_.BeginEvent(
[email protected]ec11be62010-04-28 19:28:09563 NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART, NULL);
[email protected]2d2697f92009-02-18 21:00:32564 rv = DoDrainBodyForAuthRestart();
565 break;
566 case STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE:
567 rv = DoDrainBodyForAuthRestartComplete(rv);
[email protected]9e743cd2010-03-16 07:03:53568 net_log_.EndEvent(
[email protected]ec11be62010-04-28 19:28:09569 NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART, NULL);
[email protected]2d2697f92009-02-18 21:00:32570 break;
initial.commit586acc5fe2008-07-26 22:42:52571 default:
572 NOTREACHED() << "bad state";
573 rv = ERR_FAILED;
[email protected]96d570e42008-08-05 22:43:04574 break;
initial.commit586acc5fe2008-07-26 22:42:52575 }
576 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
577
578 return rv;
579}
580
[email protected]82918cc2010-08-25 17:24:50581int HttpNetworkTransaction::DoCreateStream() {
582 next_state_ = STATE_CREATE_STREAM_COMPLETE;
[email protected]351ab642010-08-05 16:55:31583
[email protected]8e6441ca2010-08-19 05:56:38584 session_->http_stream_factory()->RequestStream(request_,
585 &ssl_config_,
586 &proxy_info_,
587 this,
588 net_log_,
589 session_,
590 &stream_request_);
591 return ERR_IO_PENDING;
[email protected]351ab642010-08-05 16:55:31592}
593
[email protected]82918cc2010-08-25 17:24:50594int HttpNetworkTransaction::DoCreateStreamComplete(int result) {
[email protected]394816e92010-08-03 07:38:59595 if (result == OK) {
[email protected]82918cc2010-08-25 17:24:50596 next_state_ = STATE_INIT_STREAM;
[email protected]8e6441ca2010-08-19 05:56:38597 DCHECK(stream_.get());
[email protected]394816e92010-08-03 07:38:59598 }
599
[email protected]8e6441ca2010-08-19 05:56:38600 // At this point we are done with the stream_request_.
601 stream_request_ = NULL;
602 return result;
[email protected]394816e92010-08-03 07:38:59603}
604
[email protected]82918cc2010-08-25 17:24:50605int HttpNetworkTransaction::DoInitStream() {
606 DCHECK(stream_.get());
607 next_state_ = STATE_INIT_STREAM_COMPLETE;
608 return stream_->InitializeStream(request_, net_log_, &io_callback_);
609}
610
611int HttpNetworkTransaction::DoInitStreamComplete(int result) {
612 if (result == OK) {
613 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
614
[email protected]82918cc2010-08-25 17:24:50615 if (is_https_request())
616 stream_->GetSSLInfo(&response_.ssl_info);
617 } else {
618 if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED)
619 result = HandleCertificateRequest(result);
620
621 if (result < 0)
[email protected]044dcc52010-09-17 15:44:26622 result = HandleIOError(result);
623
624 // The stream initialization failed, so this stream will never be useful.
625 stream_.reset();
[email protected]82918cc2010-08-25 17:24:50626 }
627
628 return result;
629}
630
[email protected]044de0642010-06-17 10:42:15631int HttpNetworkTransaction::DoGenerateProxyAuthToken() {
632 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE;
633 if (!ShouldApplyProxyAuth())
634 return OK;
[email protected]394816e92010-08-03 07:38:59635 HttpAuth::Target target = HttpAuth::AUTH_PROXY;
636 if (!auth_controllers_[target].get())
[email protected]3598c6022010-09-17 23:13:09637 auth_controllers_[target] =
638 new HttpAuthController(target,
639 AuthURL(target),
640 session_->auth_cache(),
641 session_->http_auth_handler_factory());
[email protected]394816e92010-08-03 07:38:59642 return auth_controllers_[target]->MaybeGenerateAuthToken(request_,
643 &io_callback_,
644 net_log_);
[email protected]044de0642010-06-17 10:42:15645}
646
647int HttpNetworkTransaction::DoGenerateProxyAuthTokenComplete(int rv) {
648 DCHECK_NE(ERR_IO_PENDING, rv);
649 if (rv == OK)
650 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN;
651 return rv;
652}
653
654int HttpNetworkTransaction::DoGenerateServerAuthToken() {
655 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE;
[email protected]394816e92010-08-03 07:38:59656 HttpAuth::Target target = HttpAuth::AUTH_SERVER;
657 if (!auth_controllers_[target].get())
[email protected]3598c6022010-09-17 23:13:09658 auth_controllers_[target] =
659 new HttpAuthController(target,
660 AuthURL(target),
661 session_->auth_cache(),
662 session_->http_auth_handler_factory());
[email protected]044de0642010-06-17 10:42:15663 if (!ShouldApplyServerAuth())
664 return OK;
[email protected]394816e92010-08-03 07:38:59665 return auth_controllers_[target]->MaybeGenerateAuthToken(request_,
666 &io_callback_,
667 net_log_);
[email protected]044de0642010-06-17 10:42:15668}
669
670int HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) {
671 DCHECK_NE(ERR_IO_PENDING, rv);
672 if (rv == OK)
[email protected]8e6441ca2010-08-19 05:56:38673 next_state_ = STATE_SEND_REQUEST;
[email protected]044de0642010-06-17 10:42:15674 return rv;
675}
676
[email protected]0877e3d2009-10-17 22:29:57677int HttpNetworkTransaction::DoSendRequest() {
678 next_state_ = STATE_SEND_REQUEST_COMPLETE;
679
680 UploadDataStream* request_body = NULL;
[email protected]8a1f3312010-05-25 19:25:04681 if (request_->upload_data) {
[email protected]7a6db4022010-03-24 23:37:50682 int error_code;
683 request_body = UploadDataStream::Create(request_->upload_data, &error_code);
684 if (!request_body)
685 return error_code;
686 }
initial.commit586acc5fe2008-07-26 22:42:52687
688 // This is constructed lazily (instead of within our Start method), so that
689 // we have proxy info available.
[email protected]8e6441ca2010-08-19 05:56:38690 if (request_headers_.empty() && !response_.was_fetched_via_spdy) {
[email protected]1c773ea12009-04-28 19:58:42691 // Figure out if we can/should add Proxy-Authentication & Authentication
692 // headers.
[email protected]270c6412010-03-29 22:02:47693 HttpRequestHeaders authorization_headers;
[email protected]044de0642010-06-17 10:42:15694 bool have_proxy_auth = (ShouldApplyProxyAuth() &&
695 HaveAuth(HttpAuth::AUTH_PROXY));
696 bool have_server_auth = (ShouldApplyServerAuth() &&
697 HaveAuth(HttpAuth::AUTH_SERVER));
[email protected]1c773ea12009-04-28 19:58:42698 if (have_proxy_auth)
[email protected]228404f2010-06-24 04:31:41699 auth_controllers_[HttpAuth::AUTH_PROXY]->AddAuthorizationHeader(
700 &authorization_headers);
[email protected]1c773ea12009-04-28 19:58:42701 if (have_server_auth)
[email protected]228404f2010-06-24 04:31:41702 auth_controllers_[HttpAuth::AUTH_SERVER]->AddAuthorizationHeader(
703 &authorization_headers);
[email protected]044de0642010-06-17 10:42:15704 std::string request_line;
705 HttpRequestHeaders request_headers;
[email protected]8e6441ca2010-08-19 05:56:38706
[email protected]8a1f3312010-05-25 19:25:04707 BuildRequestHeaders(request_, authorization_headers, request_body,
[email protected]2df19bb2010-08-25 20:13:46708 !is_https_request() && (proxy_info_.is_http() ||
709 proxy_info_.is_https()),
[email protected]8e6441ca2010-08-19 05:56:38710 &request_line, &request_headers);
[email protected]ac039522010-06-15 16:39:44711
712 if (session_->network_delegate())
713 session_->network_delegate()->OnSendHttpRequest(&request_headers);
714
[email protected]095c7cf2010-08-31 21:07:33715 if (net_log_.IsLoggingAll()) {
[email protected]8a1f3312010-05-25 19:25:04716 net_log_.AddEvent(
717 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
[email protected]a7ea8832010-07-12 17:54:54718 new NetLogHttpRequestParameter(request_line, request_headers));
[email protected]6b9833e2008-09-10 20:32:25719 }
[email protected]ac039522010-06-15 16:39:44720
[email protected]8c76ae22010-04-20 22:15:43721 request_headers_ = request_line + request_headers.ToString();
[email protected]490937a2010-09-01 07:57:35722 } else {
723 if (net_log_.IsLoggingAll()) {
724 net_log_.AddEvent(
725 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
726 new NetLogHttpRequestParameter(request_->url.spec(),
727 request_->extra_headers));
728 }
[email protected]6b9833e2008-09-10 20:32:25729 }
initial.commit586acc5fe2008-07-26 22:42:52730
[email protected]1f14a912009-12-21 20:32:44731 headers_valid_ = false;
[email protected]351ab642010-08-05 16:55:31732 return stream_->SendRequest(request_headers_, request_body, &response_,
733 &io_callback_);
initial.commit586acc5fe2008-07-26 22:42:52734}
735
[email protected]0877e3d2009-10-17 22:29:57736int HttpNetworkTransaction::DoSendRequestComplete(int result) {
initial.commit586acc5fe2008-07-26 22:42:52737 if (result < 0)
738 return HandleIOError(result);
[email protected]0877e3d2009-10-17 22:29:57739 next_state_ = STATE_READ_HEADERS;
initial.commit586acc5fe2008-07-26 22:42:52740 return OK;
741}
742
743int HttpNetworkTransaction::DoReadHeaders() {
744 next_state_ = STATE_READ_HEADERS_COMPLETE;
[email protected]351ab642010-08-05 16:55:31745 return stream_->ReadResponseHeaders(&io_callback_);
initial.commit586acc5fe2008-07-26 22:42:52746}
747
[email protected]0e75a732008-10-16 20:36:09748int HttpNetworkTransaction::HandleConnectionClosedBeforeEndOfHeaders() {
[email protected]8e6441ca2010-08-19 05:56:38749 if (!response_.headers && !stream_->IsConnectionReused()) {
[email protected]0e75a732008-10-16 20:36:09750 // The connection was closed before any data was sent. Likely an error
751 // rather than empty HTTP/0.9 response.
[email protected]aecfbf22008-10-16 02:02:47752 return ERR_EMPTY_RESPONSE;
753 }
754
[email protected]aecfbf22008-10-16 02:02:47755 return OK;
756}
757
initial.commit586acc5fe2008-07-26 22:42:52758int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
[email protected]0b45559b2009-06-12 21:45:11759 // We can get a certificate error or ERR_SSL_CLIENT_AUTH_CERT_NEEDED here
760 // due to SSL renegotiation.
[email protected]8e6441ca2010-08-19 05:56:38761 if (IsCertificateError(result)) {
762 // We don't handle a certificate error during SSL renegotiation, so we
763 // have to return an error that's not in the certificate error range
764 // (-2xx).
765 LOG(ERROR) << "Got a server certificate with error " << result
766 << " during SSL renegotiation";
767 result = ERR_CERT_ERROR_IN_SSL_RENEGOTIATION;
768 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
769 // TODO(wtc): Need a test case for this code path!
770 DCHECK(stream_.get());
771 DCHECK(is_https_request());
772 response_.cert_request_info = new SSLCertRequestInfo;
773 stream_->GetSSLCertRequestInfo(response_.cert_request_info);
774 result = HandleCertificateRequest(result);
775 if (result == OK)
776 return result;
777 } else if ((result == ERR_SSL_DECOMPRESSION_FAILURE_ALERT ||
778 result == ERR_SSL_BAD_RECORD_MAC_ALERT) &&
779 ssl_config_.tls1_enabled &&
780 !SSLConfigService::IsKnownStrictTLSServer(request_->url.host())) {
781 // Some buggy servers select DEFLATE compression when offered and then
782 // fail to ever decompress anything. They will send a fatal alert telling
783 // us this. Normally we would pick this up during the handshake because
784 // our Finished message is compressed and we'll never get the server's
785 // Finished if it fails to process ours.
786 //
787 // However, with False Start, we'll believe that the handshake is
788 // complete as soon as we've /sent/ our Finished message. In this case,
789 // we only find out that the server is buggy here, when we try to read
790 // the initial reply.
791 session_->http_stream_factory()->AddTLSIntolerantServer(request_->url);
792 ResetConnectionAndRequestForResend();
793 return OK;
[email protected]2181ea002009-06-09 01:37:27794 }
795
[email protected]0877e3d2009-10-17 22:29:57796 if (result < 0 && result != ERR_CONNECTION_CLOSED)
initial.commit586acc5fe2008-07-26 22:42:52797 return HandleIOError(result);
798
[email protected]0877e3d2009-10-17 22:29:57799 if (result == ERR_CONNECTION_CLOSED && ShouldResendRequest(result)) {
[email protected]1c773ea12009-04-28 19:58:42800 ResetConnectionAndRequestForResend();
[email protected]0877e3d2009-10-17 22:29:57801 return OK;
[email protected]1c773ea12009-04-28 19:58:42802 }
[email protected]2a5c76b2008-09-25 22:15:16803
[email protected]0877e3d2009-10-17 22:29:57804 // After we call RestartWithAuth a new response_time will be recorded, and
805 // we need to be cautious about incorrectly logging the duration across the
806 // authentication activity.
[email protected]8e6441ca2010-08-19 05:56:38807 if (result == OK)
808 LogTransactionConnectedMetrics();
initial.commit586acc5fe2008-07-26 22:42:52809
[email protected]0877e3d2009-10-17 22:29:57810 if (result == ERR_CONNECTION_CLOSED) {
[email protected]02c92c492010-03-08 21:28:14811 // For now, if we get at least some data, we do the best we can to make
[email protected]9492e4a2010-02-24 00:58:46812 // sense of it and send it back up the stack.
[email protected]0e75a732008-10-16 20:36:09813 int rv = HandleConnectionClosedBeforeEndOfHeaders();
[email protected]aecfbf22008-10-16 02:02:47814 if (rv != OK)
815 return rv;
[email protected]0877e3d2009-10-17 22:29:57816 }
initial.commit586acc5fe2008-07-26 22:42:52817
[email protected]095c7cf2010-08-31 21:07:33818 if (net_log_.IsLoggingAll()) {
[email protected]8a1f3312010-05-25 19:25:04819 net_log_.AddEvent(
820 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
821 new NetLogHttpResponseParameter(response_.headers));
[email protected]dbb83db2010-05-11 18:13:39822 }
823
[email protected]a7e41312009-12-16 23:18:14824 if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0)) {
[email protected]0877e3d2009-10-17 22:29:57825 // HTTP/0.9 doesn't support the PUT method, so lack of response headers
826 // indicates a buggy server. See:
827 // https://bugzilla.mozilla.org/show_bug.cgi?id=193921
828 if (request_->method == "PUT")
829 return ERR_METHOD_NOT_SUPPORTED;
830 }
[email protected]4ddaf2502008-10-23 18:26:19831
[email protected]0877e3d2009-10-17 22:29:57832 // Check for an intermediate 100 Continue response. An origin server is
833 // allowed to send this response even if we didn't ask for it, so we just
834 // need to skip over it.
835 // We treat any other 1xx in this same way (although in practice getting
836 // a 1xx that isn't a 100 is rare).
[email protected]a7e41312009-12-16 23:18:14837 if (response_.headers->response_code() / 100 == 1) {
[email protected]ee9410e72010-01-07 01:42:38838 response_.headers = new HttpResponseHeaders("");
[email protected]0877e3d2009-10-17 22:29:57839 next_state_ = STATE_READ_HEADERS;
840 return OK;
841 }
842
[email protected]8e6441ca2010-08-19 05:56:38843 HostPortPair endpoint = HostPortPair(request_->url.HostNoBrackets(),
844 request_->url.EffectiveIntPort());
845 ProcessAlternateProtocol(session_->http_stream_factory(),
846 session_->mutable_alternate_protocols(),
847 *response_.headers,
848 endpoint);
[email protected]564b4912010-03-09 16:30:42849
[email protected]e772db3f2010-07-12 18:11:13850 int rv = HandleAuthChallenge();
[email protected]0877e3d2009-10-17 22:29:57851 if (rv != OK)
852 return rv;
853
[email protected]0877e3d2009-10-17 22:29:57854 headers_valid_ = true;
855 return OK;
initial.commit586acc5fe2008-07-26 22:42:52856}
857
858int HttpNetworkTransaction::DoReadBody() {
859 DCHECK(read_buf_);
[email protected]6501bc02009-06-25 20:55:13860 DCHECK_GT(read_buf_len_, 0);
[email protected]8e6441ca2010-08-19 05:56:38861 DCHECK(stream_ != NULL);
initial.commit586acc5fe2008-07-26 22:42:52862
863 next_state_ = STATE_READ_BODY_COMPLETE;
[email protected]351ab642010-08-05 16:55:31864 return stream_->ReadResponseBody(read_buf_, read_buf_len_, &io_callback_);
initial.commit586acc5fe2008-07-26 22:42:52865}
866
867int HttpNetworkTransaction::DoReadBodyComplete(int result) {
868 // We are done with the Read call.
[email protected]8e6441ca2010-08-19 05:56:38869 bool done = false;
870 if (result <= 0) {
871 DCHECK_NE(ERR_IO_PENDING, result);
initial.commit586acc5fe2008-07-26 22:42:52872 done = true;
[email protected]8e6441ca2010-08-19 05:56:38873 }
[email protected]9492e4a2010-02-24 00:58:46874
[email protected]8e6441ca2010-08-19 05:56:38875 bool keep_alive = false;
[email protected]351ab642010-08-05 16:55:31876 if (stream_->IsResponseBodyComplete()) {
[email protected]8e6441ca2010-08-19 05:56:38877 // Note: Just because IsResponseBodyComplete is true, we're not
878 // necessarily "done". We're only "done" when it is the last
879 // read on this HttpNetworkTransaction, which will be signified
880 // by a zero-length read.
881 // TODO(mbelshe): The keepalive property is really a property of
882 // the stream. No need to compute it here just to pass back
883 // to the stream's Close function.
[email protected]351ab642010-08-05 16:55:31884 if (stream_->CanFindEndOfResponse())
[email protected]02c92c492010-03-08 21:28:14885 keep_alive = GetResponseHeaders()->IsKeepAlive();
initial.commit586acc5fe2008-07-26 22:42:52886 }
887
[email protected]8e6441ca2010-08-19 05:56:38888 // Clean up connection if we are done.
initial.commit586acc5fe2008-07-26 22:42:52889 if (done) {
[email protected]56300172008-11-06 18:42:55890 LogTransactionMetrics();
[email protected]8e6441ca2010-08-19 05:56:38891 stream_->Close(!keep_alive);
[email protected]e2a915a2010-08-19 07:55:01892 // Note: we don't reset the stream here. We've closed it, but we still
893 // need it around so that callers can call methods such as
894 // GetUploadProgress() and have them be meaningful.
895 // TODO(mbelshe): This means we closed the stream here, and we close it
896 // again in ~HttpNetworkTransaction. Clean that up.
897
[email protected]8e6441ca2010-08-19 05:56:38898 // The next Read call will return 0 (EOF).
initial.commit586acc5fe2008-07-26 22:42:52899 }
900
901 // Clear these to avoid leaving around old state.
902 read_buf_ = NULL;
903 read_buf_len_ = 0;
904
905 return result;
906}
907
[email protected]2d2697f92009-02-18 21:00:32908int HttpNetworkTransaction::DoDrainBodyForAuthRestart() {
909 // This method differs from DoReadBody only in the next_state_. So we just
910 // call DoReadBody and override the next_state_. Perhaps there is a more
911 // elegant way for these two methods to share code.
912 int rv = DoReadBody();
913 DCHECK(next_state_ == STATE_READ_BODY_COMPLETE);
914 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE;
915 return rv;
916}
917
[email protected]0877e3d2009-10-17 22:29:57918// TODO(wtc): This method and the DoReadBodyComplete method are almost
919// the same. Figure out a good way for these two methods to share code.
[email protected]2d2697f92009-02-18 21:00:32920int HttpNetworkTransaction::DoDrainBodyForAuthRestartComplete(int result) {
[email protected]68873ba2009-06-04 21:49:23921 // keep_alive defaults to true because the very reason we're draining the
922 // response body is to reuse the connection for auth restart.
923 bool done = false, keep_alive = true;
[email protected]2d2697f92009-02-18 21:00:32924 if (result < 0) {
[email protected]0877e3d2009-10-17 22:29:57925 // Error or closed connection while reading the socket.
[email protected]2d2697f92009-02-18 21:00:32926 done = true;
[email protected]68873ba2009-06-04 21:49:23927 keep_alive = false;
[email protected]351ab642010-08-05 16:55:31928 } else if (stream_->IsResponseBodyComplete()) {
[email protected]0877e3d2009-10-17 22:29:57929 done = true;
[email protected]2d2697f92009-02-18 21:00:32930 }
931
932 if (done) {
933 DidDrainBodyForAuthRestart(keep_alive);
934 } else {
935 // Keep draining.
936 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
937 }
938
939 return OK;
940}
941
[email protected]8e3d2d32010-06-13 18:46:23942void HttpNetworkTransaction::LogTransactionConnectedMetrics() {
943 if (logged_response_time_)
944 return;
945
946 logged_response_time_ = true;
947
[email protected]a7e41312009-12-16 23:18:14948 base::TimeDelta total_duration = response_.response_time - start_time_;
[email protected]9a0a55f2009-04-13 23:23:03949
[email protected]510e854f2009-04-20 18:39:08950 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:58951 "Net.Transaction_Connected_Under_10",
[email protected]510e854f2009-04-20 18:39:08952 total_duration,
[email protected]9a0a55f2009-04-13 23:23:03953 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
954 100);
[email protected]1fa47592009-07-27 22:45:00955
[email protected]c38ec5a2010-08-25 23:32:38956 bool reused_socket = stream_->IsConnectionReused();
957 if (!reused_socket) {
[email protected]b01998a2009-04-21 01:01:11958 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:58959 "Net.Transaction_Connected_New",
[email protected]b01998a2009-04-21 01:01:11960 total_duration,
961 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
962 100);
[email protected]d068f7a2010-06-07 15:12:59963
964 static bool use_conn_impact_histogram(
965 FieldTrialList::Find("ConnCountImpact") &&
966 !FieldTrialList::Find("ConnCountImpact")->group_name().empty());
967 if (use_conn_impact_histogram) {
968 UMA_HISTOGRAM_CLIPPED_TIMES(
969 FieldTrial::MakeName("Net.Transaction_Connected_New",
970 "ConnCountImpact"),
971 total_duration,
972 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
973 100);
974 }
[email protected]0310d432009-08-25 07:49:52975 }
976
[email protected]8e3d2d32010-06-13 18:46:23977 static bool use_spdy_histogram(FieldTrialList::Find("SpdyImpact") &&
978 !FieldTrialList::Find("SpdyImpact")->group_name().empty());
979 if (use_spdy_histogram && response_.was_npn_negotiated) {
980 UMA_HISTOGRAM_CLIPPED_TIMES(
981 FieldTrial::MakeName("Net.Transaction_Connected_Under_10", "SpdyImpact"),
982 total_duration, base::TimeDelta::FromMilliseconds(1),
983 base::TimeDelta::FromMinutes(10), 100);
984
[email protected]c38ec5a2010-08-25 23:32:38985 if (!reused_socket) {
[email protected]8e3d2d32010-06-13 18:46:23986 UMA_HISTOGRAM_CLIPPED_TIMES(
987 FieldTrial::MakeName("Net.Transaction_Connected_New", "SpdyImpact"),
988 total_duration, base::TimeDelta::FromMilliseconds(1),
989 base::TimeDelta::FromMinutes(10), 100);
990 }
991 }
992
[email protected]510e854f2009-04-20 18:39:08993 // Currently, non-zero priority requests are frame or sub-frame resource
994 // types. This will change when we also prioritize certain subresources like
995 // css, js, etc.
996 if (request_->priority) {
997 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:58998 "Net.Priority_High_Latency",
[email protected]510e854f2009-04-20 18:39:08999 total_duration,
1000 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1001 100);
1002 } else {
1003 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:581004 "Net.Priority_Low_Latency",
[email protected]510e854f2009-04-20 18:39:081005 total_duration,
1006 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1007 100);
1008 }
[email protected]9a0a55f2009-04-13 23:23:031009}
1010
[email protected]56300172008-11-06 18:42:551011void HttpNetworkTransaction::LogTransactionMetrics() const {
[email protected]0877e3d2009-10-17 22:29:571012 base::TimeDelta duration = base::Time::Now() -
[email protected]2227c692010-05-04 15:36:111013 response_.request_time;
[email protected]56300172008-11-06 18:42:551014 if (60 < duration.InMinutes())
1015 return;
[email protected]0b48db42009-03-23 02:45:111016
[email protected]21b316a2009-03-23 18:25:061017 base::TimeDelta total_duration = base::Time::Now() - start_time_;
1018
[email protected]f929f2f22009-06-12 16:56:581019 UMA_HISTOGRAM_LONG_TIMES("Net.Transaction_Latency", duration);
1020 UMA_HISTOGRAM_CLIPPED_TIMES("Net.Transaction_Latency_Under_10", duration,
[email protected]2227c692010-05-04 15:36:111021 base::TimeDelta::FromMilliseconds(1),
1022 base::TimeDelta::FromMinutes(10),
1023 100);
[email protected]f929f2f22009-06-12 16:56:581024 UMA_HISTOGRAM_CLIPPED_TIMES("Net.Transaction_Latency_Total_Under_10",
[email protected]2227c692010-05-04 15:36:111025 total_duration,
1026 base::TimeDelta::FromMilliseconds(1),
1027 base::TimeDelta::FromMinutes(10), 100);
[email protected]c38ec5a2010-08-25 23:32:381028 if (!stream_->IsConnectionReused()) {
[email protected]f929f2f22009-06-12 16:56:581029 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]808f6402009-03-30 20:02:071030 "Net.Transaction_Latency_Total_New_Connection_Under_10",
[email protected]808f6402009-03-30 20:02:071031 total_duration, base::TimeDelta::FromMilliseconds(1),
1032 base::TimeDelta::FromMinutes(10), 100);
1033 }
[email protected]56300172008-11-06 18:42:551034}
1035
[email protected]5e363962009-06-19 19:57:011036int HttpNetworkTransaction::HandleCertificateRequest(int error) {
[email protected]8e6441ca2010-08-19 05:56:381037 // There are two paths through which the server can request a certificate
1038 // from us. The first is during the initial handshake, the second is
1039 // during SSL renegotiation.
1040 //
1041 // In both cases, we want to close the connection before proceeding.
1042 // We do this for two reasons:
1043 // First, we don't want to keep the connection to the server hung for a
1044 // long time while the user selects a certificate.
1045 // Second, even if we did keep the connection open, NSS has a bug where
1046 // restarting the handshake for ClientAuth is currently broken.
[email protected]65a3b912010-08-21 05:46:581047 DCHECK_EQ(error, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]8e6441ca2010-08-19 05:56:381048
1049 if (stream_.get()) {
1050 // Since we already have a stream, we're being called as part of SSL
1051 // renegotiation.
1052 DCHECK(!stream_request_.get());
1053 stream_->Close(true);
1054 stream_.reset();
1055 }
1056
1057 if (stream_request_.get()) {
1058 // The server is asking for a client certificate during the initial
1059 // handshake.
[email protected]8e6441ca2010-08-19 05:56:381060 stream_request_->Cancel();
1061 stream_request_ = NULL;
[email protected]8e6441ca2010-08-19 05:56:381062 }
[email protected]5e363962009-06-19 19:57:011063
1064 // If the user selected one of the certificate in client_certs for this
1065 // server before, use it automatically.
1066 X509Certificate* client_cert = session_->ssl_client_auth_cache()->
[email protected]2227c692010-05-04 15:36:111067 Lookup(GetHostAndPort(request_->url));
[email protected]5e363962009-06-19 19:57:011068 if (client_cert) {
1069 const std::vector<scoped_refptr<X509Certificate> >& client_certs =
[email protected]a7e41312009-12-16 23:18:141070 response_.cert_request_info->client_certs;
[email protected]5e363962009-06-19 19:57:011071 for (size_t i = 0; i < client_certs.size(); ++i) {
[email protected]bd0b7432009-06-23 21:03:421072 if (client_cert->fingerprint().Equals(client_certs[i]->fingerprint())) {
[email protected]65a3b912010-08-21 05:46:581073 // TODO(davidben): Add a unit test which covers this path; we need to be
1074 // able to send a legitimate certificate and also bypass/clear the
1075 // SSL session cache.
[email protected]5e363962009-06-19 19:57:011076 ssl_config_.client_cert = client_cert;
1077 ssl_config_.send_client_cert = true;
[email protected]82918cc2010-08-25 17:24:501078 next_state_ = STATE_CREATE_STREAM;
[email protected]5e363962009-06-19 19:57:011079 // Reset the other member variables.
1080 // Note: this is necessary only with SSL renegotiation.
1081 ResetStateForRestart();
1082 return OK;
1083 }
1084 }
1085 }
1086 return error;
[email protected]0b45559b2009-06-12 21:45:111087}
1088
[email protected]96d570e42008-08-05 22:43:041089// This method determines whether it is safe to resend the request after an
1090// IO error. It can only be called in response to request header or body
1091// write errors or response header read errors. It should not be used in
1092// other cases, such as a Connect error.
initial.commit586acc5fe2008-07-26 22:42:521093int HttpNetworkTransaction::HandleIOError(int error) {
1094 switch (error) {
1095 // If we try to reuse a connection that the server is in the process of
1096 // closing, we may end up successfully writing out our request (or a
1097 // portion of our request) only to find a connection error when we try to
1098 // read from (or finish writing to) the socket.
1099 case ERR_CONNECTION_RESET:
1100 case ERR_CONNECTION_CLOSED:
1101 case ERR_CONNECTION_ABORTED:
[email protected]a19f1c602009-08-24 21:35:281102 if (ShouldResendRequest(error)) {
[email protected]1c773ea12009-04-28 19:58:421103 ResetConnectionAndRequestForResend();
initial.commit586acc5fe2008-07-26 22:42:521104 error = OK;
[email protected]1c773ea12009-04-28 19:58:421105 }
initial.commit586acc5fe2008-07-26 22:42:521106 break;
1107 }
1108 return error;
1109}
1110
[email protected]c3b35c22008-09-27 03:19:421111void HttpNetworkTransaction::ResetStateForRestart() {
[email protected]0757e7702009-03-27 04:00:221112 pending_auth_target_ = HttpAuth::AUTH_NONE;
[email protected]c3b35c22008-09-27 03:19:421113 read_buf_ = NULL;
1114 read_buf_len_ = 0;
[email protected]351ab642010-08-05 16:55:311115 stream_.reset();
[email protected]0877e3d2009-10-17 22:29:571116 headers_valid_ = false;
1117 request_headers_.clear();
[email protected]a7e41312009-12-16 23:18:141118 response_ = HttpResponseInfo();
[email protected]8e6441ca2010-08-19 05:56:381119 establishing_tunnel_ = false;
[email protected]0877e3d2009-10-17 22:29:571120}
1121
1122HttpResponseHeaders* HttpNetworkTransaction::GetResponseHeaders() const {
[email protected]a7e41312009-12-16 23:18:141123 return response_.headers;
[email protected]c3b35c22008-09-27 03:19:421124}
1125
[email protected]a19f1c602009-08-24 21:35:281126bool HttpNetworkTransaction::ShouldResendRequest(int error) const {
[email protected]8e6441ca2010-08-19 05:56:381127 bool connection_is_proven = stream_->IsConnectionReused();
1128 bool has_received_headers = GetResponseHeaders() != NULL;
[email protected]58cebf8f2010-07-31 19:20:161129
[email protected]2a5c76b2008-09-25 22:15:161130 // NOTE: we resend a request only if we reused a keep-alive connection.
1131 // This automatically prevents an infinite resend loop because we'll run
1132 // out of the cached keep-alive connections eventually.
[email protected]8e6441ca2010-08-19 05:56:381133 if (connection_is_proven && !has_received_headers)
1134 return true;
1135 return false;
[email protected]1c773ea12009-04-28 19:58:421136}
1137
1138void HttpNetworkTransaction::ResetConnectionAndRequestForResend() {
[email protected]8e6441ca2010-08-19 05:56:381139 if (stream_.get()) {
1140 stream_->Close(true);
1141 stream_.reset();
[email protected]58cebf8f2010-07-31 19:20:161142 }
1143
[email protected]0877e3d2009-10-17 22:29:571144 // We need to clear request_headers_ because it contains the real request
1145 // headers, but we may need to resend the CONNECT request first to recreate
1146 // the SSL tunnel.
1147 request_headers_.clear();
[email protected]82918cc2010-08-25 17:24:501148 next_state_ = STATE_CREATE_STREAM; // Resend the request.
[email protected]86ec30d2008-09-29 21:53:541149}
1150
[email protected]1c773ea12009-04-28 19:58:421151bool HttpNetworkTransaction::ShouldApplyProxyAuth() const {
[email protected]2df19bb2010-08-25 20:13:461152 return !is_https_request() &&
1153 (proxy_info_.is_https() || proxy_info_.is_http());
[email protected]1c773ea12009-04-28 19:58:421154}
license.botbf09a502008-08-24 00:55:551155
[email protected]1c773ea12009-04-28 19:58:421156bool HttpNetworkTransaction::ShouldApplyServerAuth() const {
[email protected]8a1f3312010-05-25 19:25:041157 return !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA);
[email protected]1c773ea12009-04-28 19:58:421158}
1159
[email protected]e772db3f2010-07-12 18:11:131160int HttpNetworkTransaction::HandleAuthChallenge() {
[email protected]0877e3d2009-10-17 22:29:571161 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
1162 DCHECK(headers);
[email protected]c3b35c22008-09-27 03:19:421163
[email protected]0877e3d2009-10-17 22:29:571164 int status = headers->response_code();
[email protected]c3b35c22008-09-27 03:19:421165 if (status != 401 && status != 407)
1166 return OK;
1167 HttpAuth::Target target = status == 407 ?
[email protected]2227c692010-05-04 15:36:111168 HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER;
[email protected]038e9a32008-10-08 22:40:161169 if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct())
1170 return ERR_UNEXPECTED_PROXY_AUTH;
[email protected]c3b35c22008-09-27 03:19:421171
[email protected]a7ea8832010-07-12 17:54:541172 int rv = auth_controllers_[target]->HandleAuthChallenge(
[email protected]560c0432010-07-13 20:45:311173 headers, (request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA) != 0, false,
1174 net_log_);
[email protected]228404f2010-06-24 04:31:411175 if (auth_controllers_[target]->HaveAuthHandler())
1176 pending_auth_target_ = target;
1177
1178 scoped_refptr<AuthChallengeInfo> auth_info =
1179 auth_controllers_[target]->auth_info();
1180 if (auth_info.get())
1181 response_.auth_challenge = auth_info;
1182
[email protected]228404f2010-06-24 04:31:411183 return rv;
[email protected]f9ee6b52008-11-08 06:46:231184}
1185
[email protected]8e6441ca2010-08-19 05:56:381186bool HttpNetworkTransaction::HaveAuth(HttpAuth::Target target) const {
1187 return auth_controllers_[target].get() &&
1188 auth_controllers_[target]->HaveAuth();
1189}
1190
1191
[email protected]228404f2010-06-24 04:31:411192GURL HttpNetworkTransaction::AuthURL(HttpAuth::Target target) const {
1193 switch (target) {
[email protected]2df19bb2010-08-25 20:13:461194 case HttpAuth::AUTH_PROXY: {
[email protected]228404f2010-06-24 04:31:411195 if (!proxy_info_.proxy_server().is_valid() ||
1196 proxy_info_.proxy_server().is_direct()) {
1197 return GURL(); // There is no proxy server.
1198 }
[email protected]2df19bb2010-08-25 20:13:461199 const char* scheme = proxy_info_.is_https() ? "https://" : "http://";
1200 return GURL(scheme +
[email protected]2fbaecf22010-07-22 22:20:351201 proxy_info_.proxy_server().host_port_pair().ToString());
[email protected]2df19bb2010-08-25 20:13:461202 }
[email protected]228404f2010-06-24 04:31:411203 case HttpAuth::AUTH_SERVER:
1204 return request_->url;
1205 default:
1206 return GURL();
1207 }
[email protected]c3b35c22008-09-27 03:19:421208}
1209
[email protected]aef04272010-06-28 18:03:041210#define STATE_CASE(s) case s: \
1211 description = StringPrintf("%s (0x%08X)", #s, s); \
1212 break
1213
1214std::string HttpNetworkTransaction::DescribeState(State state) {
1215 std::string description;
1216 switch (state) {
[email protected]82918cc2010-08-25 17:24:501217 STATE_CASE(STATE_CREATE_STREAM);
1218 STATE_CASE(STATE_CREATE_STREAM_COMPLETE);
[email protected]aef04272010-06-28 18:03:041219 STATE_CASE(STATE_SEND_REQUEST);
1220 STATE_CASE(STATE_SEND_REQUEST_COMPLETE);
1221 STATE_CASE(STATE_READ_HEADERS);
1222 STATE_CASE(STATE_READ_HEADERS_COMPLETE);
[email protected]aef04272010-06-28 18:03:041223 STATE_CASE(STATE_READ_BODY);
1224 STATE_CASE(STATE_READ_BODY_COMPLETE);
1225 STATE_CASE(STATE_DRAIN_BODY_FOR_AUTH_RESTART);
1226 STATE_CASE(STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE);
[email protected]aef04272010-06-28 18:03:041227 STATE_CASE(STATE_NONE);
1228 default:
1229 description = StringPrintf("Unknown state 0x%08X (%u)", state, state);
1230 break;
1231 }
1232 return description;
1233}
1234
[email protected]c9c6f5c2010-07-31 01:30:031235// TODO(gavinp): re-adjust this once SPDY v3 has three priority bits,
1236// eliminating the need for this folding.
1237int ConvertRequestPriorityToSpdyPriority(const RequestPriority priority) {
1238 DCHECK(HIGHEST <= priority && priority < NUM_PRIORITIES);
1239 switch (priority) {
1240 case LOWEST:
1241 return SPDY_PRIORITY_LOWEST-1;
1242 case IDLE:
1243 return SPDY_PRIORITY_LOWEST;
1244 default:
1245 return priority;
1246 }
1247}
1248
1249
1250
[email protected]aef04272010-06-28 18:03:041251#undef STATE_CASE
1252
[email protected]c3b35c22008-09-27 03:19:421253} // namespace net