blob: 6dd62fd052f5304614eb0c5c0ff745d29ff4133d [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_request.h"
initial.commit586acc5fe2008-07-26 22:42:5243#include "net/http/http_util.h"
[email protected]d7f16632010-03-29 18:02:3644#include "net/http/url_security_manager.h"
[email protected]f7984fc62009-06-22 23:26:4445#include "net/socket/client_socket_factory.h"
[email protected]a796bcec2010-03-22 17:17:2646#include "net/socket/socks_client_socket_pool.h"
[email protected]f7984fc62009-06-22 23:26:4447#include "net/socket/ssl_client_socket.h"
[email protected]e60e47a2010-07-14 03:37:1848#include "net/socket/ssl_client_socket_pool.h"
[email protected]7fc5b09a2010-02-27 00:07:3849#include "net/socket/tcp_client_socket_pool.h"
[email protected]65d56aa2010-06-14 04:13:4050#include "net/spdy/spdy_http_stream.h"
[email protected]dab9c7d2010-02-06 21:44:3251#include "net/spdy/spdy_session.h"
52#include "net/spdy/spdy_session_pool.h"
initial.commit586acc5fe2008-07-26 22:42:5253
[email protected]e1acf6f2008-10-27 20:43:3354using base::Time;
55
initial.commit586acc5fe2008-07-26 22:42:5256namespace net {
57
[email protected]1c773ea12009-04-28 19:58:4258namespace {
59
60void BuildRequestHeaders(const HttpRequestInfo* request_info,
[email protected]270c6412010-03-29 22:02:4761 const HttpRequestHeaders& authorization_headers,
[email protected]1c773ea12009-04-28 19:58:4262 const UploadDataStream* upload_data_stream,
63 bool using_proxy,
[email protected]8c76ae22010-04-20 22:15:4364 std::string* request_line,
[email protected]270c6412010-03-29 22:02:4765 HttpRequestHeaders* request_headers) {
66 const std::string path = using_proxy ?
[email protected]2227c692010-05-04 15:36:1167 HttpUtil::SpecForRequest(request_info->url) :
68 HttpUtil::PathForRequest(request_info->url);
[email protected]8c76ae22010-04-20 22:15:4369 *request_line = StringPrintf(
70 "%s %s HTTP/1.1\r\n", request_info->method.c_str(), path.c_str());
[email protected]270c6412010-03-29 22:02:4771 request_headers->SetHeader(HttpRequestHeaders::kHost,
72 GetHostAndOptionalPort(request_info->url));
73
74 // For compat with HTTP/1.0 servers and proxies:
75 if (using_proxy) {
76 request_headers->SetHeader(HttpRequestHeaders::kProxyConnection,
77 "keep-alive");
78 } else {
79 request_headers->SetHeader(HttpRequestHeaders::kConnection, "keep-alive");
80 }
81
[email protected]270c6412010-03-29 22:02:4782 // Our consumer should have made sure that this is a safe referrer. See for
83 // instance WebCore::FrameLoader::HideReferrer.
84 if (request_info->referrer.is_valid()) {
85 request_headers->SetHeader(HttpRequestHeaders::kReferer,
86 request_info->referrer.spec());
87 }
88
89 // Add a content length header?
90 if (upload_data_stream) {
91 request_headers->SetHeader(
92 HttpRequestHeaders::kContentLength,
[email protected]e83326f2010-07-31 17:29:2593 base::Uint64ToString(upload_data_stream->size()));
[email protected]270c6412010-03-29 22:02:4794 } else if (request_info->method == "POST" || request_info->method == "PUT" ||
95 request_info->method == "HEAD") {
96 // An empty POST/PUT request still needs a content length. As for HEAD,
97 // IE and Safari also add a content length header. Presumably it is to
98 // support sending a HEAD request to an URL that only expects to be sent a
99 // POST or some other method that normally would have a message body.
100 request_headers->SetHeader(HttpRequestHeaders::kContentLength, "0");
101 }
102
103 // Honor load flags that impact proxy caches.
104 if (request_info->load_flags & LOAD_BYPASS_CACHE) {
105 request_headers->SetHeader(HttpRequestHeaders::kPragma, "no-cache");
106 request_headers->SetHeader(HttpRequestHeaders::kCacheControl, "no-cache");
107 } else if (request_info->load_flags & LOAD_VALIDATE_CACHE) {
108 request_headers->SetHeader(HttpRequestHeaders::kCacheControl, "max-age=0");
109 }
110
111 request_headers->MergeFrom(authorization_headers);
112
[email protected]860c85d2010-02-10 07:22:40113 // Headers that will be stripped from request_info->extra_headers to prevent,
114 // e.g., plugins from overriding headers that are controlled using other
115 // means. Otherwise a plugin could set a referrer although sending the
116 // referrer is inhibited.
117 // TODO(jochen): check whether also other headers should be stripped.
118 static const char* const kExtraHeadersToBeStripped[] = {
119 "Referer"
120 };
121
[email protected]8c76ae22010-04-20 22:15:43122 HttpRequestHeaders stripped_extra_headers;
123 stripped_extra_headers.CopyFrom(request_info->extra_headers);
[email protected]2227c692010-05-04 15:36:11124 for (size_t i = 0; i < arraysize(kExtraHeadersToBeStripped); ++i)
125 stripped_extra_headers.RemoveHeader(kExtraHeadersToBeStripped[i]);
[email protected]8c76ae22010-04-20 22:15:43126 request_headers->MergeFrom(stripped_extra_headers);
[email protected]1c773ea12009-04-28 19:58:42127}
128
[email protected]8e6441ca2010-08-19 05:56:38129void ProcessAlternateProtocol(HttpStreamFactory* factory,
130 HttpAlternateProtocols* alternate_protocols,
131 const HttpResponseHeaders& headers,
132 const HostPortPair& http_host_port_pair) {
[email protected]564b4912010-03-09 16:30:42133 std::string alternate_protocol_str;
[email protected]8e6441ca2010-08-19 05:56:38134
[email protected]564b4912010-03-09 16:30:42135 if (!headers.EnumerateHeader(NULL, HttpAlternateProtocols::kHeader,
136 &alternate_protocol_str)) {
137 // Header is not present.
138 return;
139 }
140
[email protected]8e6441ca2010-08-19 05:56:38141 factory->ProcessAlternateProtocol(alternate_protocols,
142 alternate_protocol_str,
143 http_host_port_pair);
[email protected]f45c1ee2010-08-03 00:54:30144}
145
[email protected]1c773ea12009-04-28 19:58:42146} // namespace
147
initial.commit586acc5fe2008-07-26 22:42:52148//-----------------------------------------------------------------------------
149
[email protected]5695b8c2009-09-30 21:36:43150HttpNetworkTransaction::HttpNetworkTransaction(HttpNetworkSession* session)
[email protected]0757e7702009-03-27 04:00:22151 : pending_auth_target_(HttpAuth::AUTH_NONE),
152 ALLOW_THIS_IN_INITIALIZER_LIST(
[email protected]68bf9152008-09-25 19:47:30153 io_callback_(this, &HttpNetworkTransaction::OnIOComplete)),
initial.commit586acc5fe2008-07-26 22:42:52154 user_callback_(NULL),
155 session_(session),
156 request_(NULL),
[email protected]0877e3d2009-10-17 22:29:57157 headers_valid_(false),
[email protected]8e3d2d32010-06-13 18:46:23158 logged_response_time_(false),
initial.commit586acc5fe2008-07-26 22:42:52159 read_buf_len_(0),
[email protected]a7ea8832010-07-12 17:54:54160 next_state_(STATE_NONE),
161 establishing_tunnel_(false) {
[email protected]2cd713f2008-10-21 17:54:28162 session->ssl_config_service()->GetSSLConfig(&ssl_config_);
[email protected]8e6441ca2010-08-19 05:56:38163 if (session->http_stream_factory()->next_protos())
164 ssl_config_.next_protos = *session->http_stream_factory()->next_protos();
[email protected]1f14a912009-12-21 20:32:44165
[email protected]3ce7df0f2010-03-03 00:30:50166}
167
[email protected]0b0bf032010-09-21 18:08:50168HttpNetworkTransaction::~HttpNetworkTransaction() {
169 if (stream_.get()) {
170 HttpResponseHeaders* headers = GetResponseHeaders();
171 // TODO(mbelshe): The stream_ should be able to compute whether or not the
172 // stream should be kept alive. No reason to compute here
173 // and pass it in.
174 bool try_to_keep_alive =
175 next_state_ == STATE_NONE &&
176 stream_->CanFindEndOfResponse() &&
177 (!headers || headers->IsKeepAlive());
178 if (!try_to_keep_alive) {
179 stream_->Close(true /* not reusable */);
180 } else {
181 if (stream_->IsResponseBodyComplete()) {
182 // If the response body is complete, we can just reuse the socket.
183 stream_->Close(false /* reusable */);
184 } else {
185 // Otherwise, we try to drain the response body.
186 // TODO(willchan): Consider moving this response body draining to the
187 // stream implementation. For SPDY, there's clearly no point. For
188 // HTTP, it can vary depending on whether or not we're pipelining. It's
189 // stream dependent, so the different subtypes should be implementing
190 // their solutions.
191 HttpUtil::DrainStreamBodyAndClose(stream_.release());
192 }
193 }
194 }
195
196 if (stream_request_.get()) {
197 stream_request_->Cancel();
198 stream_request_ = NULL;
199 }
200}
201
[email protected]684970b2009-08-14 04:54:46202int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info,
203 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53204 const BoundNetLog& net_log) {
[email protected]5e2e6c77d12009-12-24 21:57:16205 SIMPLE_STATS_COUNTER("HttpNetworkTransaction.Count");
[email protected]5d0153c512009-01-12 19:08:36206
[email protected]9e743cd2010-03-16 07:03:53207 net_log_ = net_log;
[email protected]96d570e42008-08-05 22:43:04208 request_ = request_info;
[email protected]21b316a2009-03-23 18:25:06209 start_time_ = base::Time::Now();
[email protected]96d570e42008-08-05 22:43:04210
[email protected]82918cc2010-08-25 17:24:50211 next_state_ = STATE_CREATE_STREAM;
[email protected]96d570e42008-08-05 22:43:04212 int rv = DoLoop(OK);
213 if (rv == ERR_IO_PENDING)
214 user_callback_ = callback;
215 return rv;
216}
217
218int HttpNetworkTransaction::RestartIgnoringLastError(
219 CompletionCallback* callback) {
[email protected]8e6441ca2010-08-19 05:56:38220 DCHECK(!stream_.get());
221 DCHECK(!stream_request_.get());
222 DCHECK_EQ(STATE_NONE, next_state_);
223
[email protected]82918cc2010-08-25 17:24:50224 next_state_ = STATE_CREATE_STREAM;
[email protected]8e6441ca2010-08-19 05:56:38225
[email protected]ccb40e52008-09-17 20:54:40226 int rv = DoLoop(OK);
227 if (rv == ERR_IO_PENDING)
228 user_callback_ = callback;
[email protected]aaead502008-10-15 00:20:11229 return rv;
[email protected]96d570e42008-08-05 22:43:04230}
231
[email protected]0b45559b2009-06-12 21:45:11232int HttpNetworkTransaction::RestartWithCertificate(
233 X509Certificate* client_cert,
234 CompletionCallback* callback) {
[email protected]8e6441ca2010-08-19 05:56:38235 // In HandleCertificateRequest(), we always tear down existing stream
236 // requests to force a new connection. So we shouldn't have one here.
237 DCHECK(!stream_request_.get());
238 DCHECK(!stream_.get());
239 DCHECK_EQ(STATE_NONE, next_state_);
240
[email protected]0b45559b2009-06-12 21:45:11241 ssl_config_.client_cert = client_cert;
[email protected]5e363962009-06-19 19:57:01242 if (client_cert) {
243 session_->ssl_client_auth_cache()->Add(GetHostAndPort(request_->url),
244 client_cert);
245 }
[email protected]0b45559b2009-06-12 21:45:11246 ssl_config_.send_client_cert = true;
[email protected]0b45559b2009-06-12 21:45:11247 // Reset the other member variables.
248 // Note: this is necessary only with SSL renegotiation.
249 ResetStateForRestart();
[email protected]82918cc2010-08-25 17:24:50250 next_state_ = STATE_CREATE_STREAM;
[email protected]0b45559b2009-06-12 21:45:11251 int rv = DoLoop(OK);
252 if (rv == ERR_IO_PENDING)
253 user_callback_ = callback;
254 return rv;
255}
256
[email protected]96d570e42008-08-05 22:43:04257int HttpNetworkTransaction::RestartWithAuth(
[email protected]13c8a092010-07-29 06:15:44258 const string16& username,
259 const string16& password,
[email protected]96d570e42008-08-05 22:43:04260 CompletionCallback* callback) {
[email protected]0757e7702009-03-27 04:00:22261 HttpAuth::Target target = pending_auth_target_;
262 if (target == HttpAuth::AUTH_NONE) {
263 NOTREACHED();
264 return ERR_UNEXPECTED;
265 }
[email protected]0757e7702009-03-27 04:00:22266 pending_auth_target_ = HttpAuth::AUTH_NONE;
[email protected]c3b35c22008-09-27 03:19:42267
[email protected]e772db3f2010-07-12 18:11:13268 auth_controllers_[target]->ResetAuth(username, password);
269
[email protected]8e6441ca2010-08-19 05:56:38270 DCHECK(user_callback_ == NULL);
271
272 int rv = OK;
273 if (target == HttpAuth::AUTH_PROXY && establishing_tunnel_) {
274 // In this case, we've gathered credentials for use with proxy
275 // authentication of a tunnel.
[email protected]82918cc2010-08-25 17:24:50276 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38277 DCHECK(stream_request_ != NULL);
[email protected]394816e92010-08-03 07:38:59278 auth_controllers_[target] = NULL;
[email protected]a7ea8832010-07-12 17:54:54279 ResetStateForRestart();
[email protected]8e6441ca2010-08-19 05:56:38280 rv = stream_request_->RestartTunnelWithProxyAuth(username, password);
[email protected]a7ea8832010-07-12 17:54:54281 } else {
[email protected]8e6441ca2010-08-19 05:56:38282 // In this case, we've gathered credentials for the server or the proxy
283 // but it is not during the tunneling phase.
284 DCHECK(stream_request_ == NULL);
[email protected]a7ea8832010-07-12 17:54:54285 PrepareForAuthRestart(target);
[email protected]8e6441ca2010-08-19 05:56:38286 rv = DoLoop(OK);
[email protected]a7ea8832010-07-12 17:54:54287 }
[email protected]c3b35c22008-09-27 03:19:42288
[email protected]c3b35c22008-09-27 03:19:42289 if (rv == ERR_IO_PENDING)
290 user_callback_ = callback;
[email protected]c3b35c22008-09-27 03:19:42291 return rv;
[email protected]96d570e42008-08-05 22:43:04292}
293
[email protected]f9ee6b52008-11-08 06:46:23294void HttpNetworkTransaction::PrepareForAuthRestart(HttpAuth::Target target) {
295 DCHECK(HaveAuth(target));
[email protected]8e6441ca2010-08-19 05:56:38296 DCHECK(!stream_request_.get());
297
[email protected]2d2697f92009-02-18 21:00:32298 bool keep_alive = false;
[email protected]0877e3d2009-10-17 22:29:57299 // Even if the server says the connection is keep-alive, we have to be
300 // able to find the end of each response in order to reuse the connection.
301 if (GetResponseHeaders()->IsKeepAlive() &&
[email protected]351ab642010-08-05 16:55:31302 stream_->CanFindEndOfResponse()) {
[email protected]0877e3d2009-10-17 22:29:57303 // If the response body hasn't been completely read, we need to drain
304 // it first.
[email protected]351ab642010-08-05 16:55:31305 if (!stream_->IsResponseBodyComplete()) {
[email protected]2d2697f92009-02-18 21:00:32306 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
[email protected]0877e3d2009-10-17 22:29:57307 read_buf_ = new IOBuffer(kDrainBodyBufferSize); // A bit bucket.
[email protected]2d2697f92009-02-18 21:00:32308 read_buf_len_ = kDrainBodyBufferSize;
309 return;
310 }
[email protected]0877e3d2009-10-17 22:29:57311 keep_alive = true;
[email protected]37832c6d2009-06-05 19:44:09312 }
313
[email protected]2d2697f92009-02-18 21:00:32314 // We don't need to drain the response body, so we act as if we had drained
315 // the response body.
316 DidDrainBodyForAuthRestart(keep_alive);
317}
318
319void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) {
[email protected]8e6441ca2010-08-19 05:56:38320 DCHECK(!stream_request_.get());
321
322 if (stream_.get()) {
323 if (keep_alive) {
324 // We should call connection_->set_idle_time(), but this doesn't occur
325 // often enough to be worth the trouble.
326 stream_->SetConnectionReused();
327 }
328 stream_->Close(!keep_alive);
[email protected]82918cc2010-08-25 17:24:50329 next_state_ = STATE_CREATE_STREAM;
[email protected]2d2697f92009-02-18 21:00:32330 }
[email protected]f9ee6b52008-11-08 06:46:23331
332 // Reset the other member variables.
333 ResetStateForRestart();
334}
335
[email protected]8e6441ca2010-08-19 05:56:38336bool HttpNetworkTransaction::IsReadyToRestartForAuth() {
337 return pending_auth_target_ != HttpAuth::AUTH_NONE &&
338 HaveAuth(pending_auth_target_);
339}
340
[email protected]9dea9e1f2009-01-29 00:30:47341int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len,
[email protected]96d570e42008-08-05 22:43:04342 CompletionCallback* callback) {
[email protected]96d570e42008-08-05 22:43:04343 DCHECK(buf);
[email protected]e0c27be2009-07-15 13:09:35344 DCHECK_LT(0, buf_len);
[email protected]96d570e42008-08-05 22:43:04345
[email protected]1f14a912009-12-21 20:32:44346 State next_state = STATE_NONE;
[email protected]96d570e42008-08-05 22:43:04347
[email protected]8a1f3312010-05-25 19:25:04348 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
[email protected]8e6441ca2010-08-19 05:56:38349 if (headers_valid_ && headers.get() && stream_request_.get()) {
[email protected]8a1f3312010-05-25 19:25:04350 // We're trying to read the body of the response but we're still trying
351 // to establish an SSL tunnel through the proxy. We can't read these
352 // bytes when establishing a tunnel because they might be controlled by
353 // an active network attacker. We don't worry about this for HTTP
354 // because an active network attacker can already control HTTP sessions.
355 // We reach this case when the user cancels a 407 proxy auth prompt.
356 // See http://crbug.com/8473.
[email protected]2df19bb2010-08-25 20:13:46357 DCHECK(proxy_info_.is_http() || proxy_info_.is_https());
[email protected]a7ea8832010-07-12 17:54:54358 DCHECK_EQ(headers->response_code(), 407);
359 LOG(WARNING) << "Blocked proxy response with status "
360 << headers->response_code() << " to CONNECT request for "
361 << GetHostAndPort(request_->url) << ".";
[email protected]8a1f3312010-05-25 19:25:04362 return ERR_TUNNEL_CONNECTION_FAILED;
[email protected]a8e9b162009-03-12 00:06:44363 }
364
[email protected]e60e47a2010-07-14 03:37:18365 // Are we using SPDY or HTTP?
[email protected]351ab642010-08-05 16:55:31366 next_state = STATE_READ_BODY;
367 DCHECK(stream_->GetResponseInfo()->headers);
[email protected]e60e47a2010-07-14 03:37:18368
[email protected]96d570e42008-08-05 22:43:04369 read_buf_ = buf;
370 read_buf_len_ = buf_len;
371
[email protected]1f14a912009-12-21 20:32:44372 next_state_ = next_state;
[email protected]96d570e42008-08-05 22:43:04373 int rv = DoLoop(OK);
374 if (rv == ERR_IO_PENDING)
375 user_callback_ = callback;
376 return rv;
377}
378
379const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const {
[email protected]a7e41312009-12-16 23:18:14380 return ((headers_valid_ && response_.headers) || response_.ssl_info.cert ||
381 response_.cert_request_info) ? &response_ : NULL;
[email protected]96d570e42008-08-05 22:43:04382}
383
384LoadState HttpNetworkTransaction::GetLoadState() const {
385 // TODO(wtc): Define a new LoadState value for the
386 // STATE_INIT_CONNECTION_COMPLETE state, which delays the HTTP request.
387 switch (next_state_) {
[email protected]82918cc2010-08-25 17:24:50388 case STATE_CREATE_STREAM_COMPLETE:
[email protected]8e6441ca2010-08-19 05:56:38389 return stream_request_->GetLoadState();
[email protected]044de0642010-06-17 10:42:15390 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE:
391 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE:
[email protected]0877e3d2009-10-17 22:29:57392 case STATE_SEND_REQUEST_COMPLETE:
[email protected]96d570e42008-08-05 22:43:04393 return LOAD_STATE_SENDING_REQUEST;
394 case STATE_READ_HEADERS_COMPLETE:
395 return LOAD_STATE_WAITING_FOR_RESPONSE;
396 case STATE_READ_BODY_COMPLETE:
397 return LOAD_STATE_READING_RESPONSE;
398 default:
399 return LOAD_STATE_IDLE;
400 }
401}
402
403uint64 HttpNetworkTransaction::GetUploadProgress() const {
[email protected]351ab642010-08-05 16:55:31404 if (!stream_.get())
[email protected]96d570e42008-08-05 22:43:04405 return 0;
406
[email protected]351ab642010-08-05 16:55:31407 return stream_->GetUploadProgress();
[email protected]96d570e42008-08-05 22:43:04408}
409
[email protected]4d4a5162010-09-21 22:44:04410void HttpNetworkTransaction::OnStreamReady(HttpStream* stream) {
[email protected]82918cc2010-08-25 17:24:50411 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38412 DCHECK(stream_request_.get());
413
414 stream_.reset(stream);
415 response_.was_alternate_protocol_available =
416 stream_request_->was_alternate_protocol_available();
417 response_.was_npn_negotiated = stream_request_->was_npn_negotiated();
418 response_.was_fetched_via_spdy = stream_request_->using_spdy();
419 response_.was_fetched_via_proxy = !proxy_info_.is_direct();
[email protected]8e6441ca2010-08-19 05:56:38420
421 OnIOComplete(OK);
422}
423
424void HttpNetworkTransaction::OnStreamFailed(int result) {
[email protected]82918cc2010-08-25 17:24:50425 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38426 DCHECK_NE(OK, result);
427 DCHECK(stream_request_.get());
428 DCHECK(!stream_.get());
429
430 OnIOComplete(result);
431}
432
433void HttpNetworkTransaction::OnCertificateError(int result,
434 const SSLInfo& ssl_info) {
[email protected]82918cc2010-08-25 17:24:50435 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38436 DCHECK_NE(OK, result);
437 DCHECK(stream_request_.get());
438 DCHECK(!stream_.get());
439
440 response_.ssl_info = ssl_info;
441
442 // TODO(mbelshe): For now, we're going to pass the error through, and that
443 // will close the stream_request in all cases. This means that we're always
[email protected]82918cc2010-08-25 17:24:50444 // going to restart an entire STATE_CREATE_STREAM, even if the connection is
445 // good and the user chooses to ignore the error. This is not ideal, but not
446 // the end of the world either.
[email protected]8e6441ca2010-08-19 05:56:38447
448 OnIOComplete(result);
449}
450
451void HttpNetworkTransaction::OnNeedsProxyAuth(
[email protected]6dc476da2010-09-01 04:43:50452 const HttpResponseInfo& proxy_response,
453 HttpAuthController* auth_controller) {
[email protected]8e6441ca2010-08-19 05:56:38454 DCHECK(stream_request_.get());
[email protected]82918cc2010-08-25 17:24:50455 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38456
457 establishing_tunnel_ = true;
458 response_.headers = proxy_response.headers;
459 response_.auth_challenge = proxy_response.auth_challenge;
460 headers_valid_ = true;
461
462 auth_controllers_[HttpAuth::AUTH_PROXY] = auth_controller;
463 pending_auth_target_ = HttpAuth::AUTH_PROXY;
464
465 DoCallback(OK);
466}
467
468void HttpNetworkTransaction::OnNeedsClientAuth(
[email protected]6dc476da2010-09-01 04:43:50469 SSLCertRequestInfo* cert_info) {
[email protected]82918cc2010-08-25 17:24:50470 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38471
472 response_.cert_request_info = cert_info;
[email protected]65a3b912010-08-21 05:46:58473 OnIOComplete(ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]8e6441ca2010-08-19 05:56:38474}
475
[email protected]8e6441ca2010-08-19 05:56:38476bool HttpNetworkTransaction::is_https_request() const {
477 return request_->url.SchemeIs("https");
initial.commit586acc5fe2008-07-26 22:42:52478}
479
initial.commit586acc5fe2008-07-26 22:42:52480void HttpNetworkTransaction::DoCallback(int rv) {
[email protected]0b0bf032010-09-21 18:08:50481 DCHECK_NE(rv, ERR_IO_PENDING);
initial.commit586acc5fe2008-07-26 22:42:52482 DCHECK(user_callback_);
483
[email protected]96d570e42008-08-05 22:43:04484 // Since Run may result in Read being called, clear user_callback_ up front.
initial.commit586acc5fe2008-07-26 22:42:52485 CompletionCallback* c = user_callback_;
486 user_callback_ = NULL;
487 c->Run(rv);
488}
489
490void HttpNetworkTransaction::OnIOComplete(int result) {
491 int rv = DoLoop(result);
492 if (rv != ERR_IO_PENDING)
493 DoCallback(rv);
494}
495
496int HttpNetworkTransaction::DoLoop(int result) {
497 DCHECK(next_state_ != STATE_NONE);
498
499 int rv = result;
500 do {
501 State state = next_state_;
502 next_state_ = STATE_NONE;
503 switch (state) {
[email protected]82918cc2010-08-25 17:24:50504 case STATE_CREATE_STREAM:
505 DCHECK_EQ(OK, rv);
506 rv = DoCreateStream();
507 break;
508 case STATE_CREATE_STREAM_COMPLETE:
509 rv = DoCreateStreamComplete(rv);
510 break;
[email protected]351ab642010-08-05 16:55:31511 case STATE_INIT_STREAM:
512 DCHECK_EQ(OK, rv);
513 rv = DoInitStream();
514 break;
515 case STATE_INIT_STREAM_COMPLETE:
516 rv = DoInitStreamComplete(rv);
517 break;
[email protected]044de0642010-06-17 10:42:15518 case STATE_GENERATE_PROXY_AUTH_TOKEN:
519 DCHECK_EQ(OK, rv);
520 rv = DoGenerateProxyAuthToken();
521 break;
522 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE:
523 rv = DoGenerateProxyAuthTokenComplete(rv);
524 break;
525 case STATE_GENERATE_SERVER_AUTH_TOKEN:
526 DCHECK_EQ(OK, rv);
527 rv = DoGenerateServerAuthToken();
528 break;
529 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE:
530 rv = DoGenerateServerAuthTokenComplete(rv);
531 break;
[email protected]0877e3d2009-10-17 22:29:57532 case STATE_SEND_REQUEST:
[email protected]725355a2009-03-25 20:42:55533 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09534 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, NULL);
[email protected]0877e3d2009-10-17 22:29:57535 rv = DoSendRequest();
initial.commit586acc5fe2008-07-26 22:42:52536 break;
[email protected]0877e3d2009-10-17 22:29:57537 case STATE_SEND_REQUEST_COMPLETE:
538 rv = DoSendRequestComplete(rv);
[email protected]ec11be62010-04-28 19:28:09539 net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, NULL);
initial.commit586acc5fe2008-07-26 22:42:52540 break;
541 case STATE_READ_HEADERS:
[email protected]725355a2009-03-25 20:42:55542 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09543 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, NULL);
initial.commit586acc5fe2008-07-26 22:42:52544 rv = DoReadHeaders();
545 break;
546 case STATE_READ_HEADERS_COMPLETE:
547 rv = DoReadHeadersComplete(rv);
[email protected]ec11be62010-04-28 19:28:09548 net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, NULL);
initial.commit586acc5fe2008-07-26 22:42:52549 break;
550 case STATE_READ_BODY:
[email protected]725355a2009-03-25 20:42:55551 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09552 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, NULL);
initial.commit586acc5fe2008-07-26 22:42:52553 rv = DoReadBody();
554 break;
555 case STATE_READ_BODY_COMPLETE:
556 rv = DoReadBodyComplete(rv);
[email protected]ec11be62010-04-28 19:28:09557 net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, NULL);
initial.commit586acc5fe2008-07-26 22:42:52558 break;
[email protected]2d2697f92009-02-18 21:00:32559 case STATE_DRAIN_BODY_FOR_AUTH_RESTART:
[email protected]725355a2009-03-25 20:42:55560 DCHECK_EQ(OK, rv);
[email protected]9e743cd2010-03-16 07:03:53561 net_log_.BeginEvent(
[email protected]ec11be62010-04-28 19:28:09562 NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART, NULL);
[email protected]2d2697f92009-02-18 21:00:32563 rv = DoDrainBodyForAuthRestart();
564 break;
565 case STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE:
566 rv = DoDrainBodyForAuthRestartComplete(rv);
[email protected]9e743cd2010-03-16 07:03:53567 net_log_.EndEvent(
[email protected]ec11be62010-04-28 19:28:09568 NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART, NULL);
[email protected]2d2697f92009-02-18 21:00:32569 break;
initial.commit586acc5fe2008-07-26 22:42:52570 default:
571 NOTREACHED() << "bad state";
572 rv = ERR_FAILED;
[email protected]96d570e42008-08-05 22:43:04573 break;
initial.commit586acc5fe2008-07-26 22:42:52574 }
575 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
576
577 return rv;
578}
579
[email protected]82918cc2010-08-25 17:24:50580int HttpNetworkTransaction::DoCreateStream() {
581 next_state_ = STATE_CREATE_STREAM_COMPLETE;
[email protected]351ab642010-08-05 16:55:31582
[email protected]8e6441ca2010-08-19 05:56:38583 session_->http_stream_factory()->RequestStream(request_,
584 &ssl_config_,
585 &proxy_info_,
586 this,
587 net_log_,
588 session_,
589 &stream_request_);
590 return ERR_IO_PENDING;
[email protected]351ab642010-08-05 16:55:31591}
592
[email protected]82918cc2010-08-25 17:24:50593int HttpNetworkTransaction::DoCreateStreamComplete(int result) {
[email protected]394816e92010-08-03 07:38:59594 if (result == OK) {
[email protected]82918cc2010-08-25 17:24:50595 next_state_ = STATE_INIT_STREAM;
[email protected]8e6441ca2010-08-19 05:56:38596 DCHECK(stream_.get());
[email protected]394816e92010-08-03 07:38:59597 }
598
[email protected]8e6441ca2010-08-19 05:56:38599 // At this point we are done with the stream_request_.
600 stream_request_ = NULL;
601 return result;
[email protected]394816e92010-08-03 07:38:59602}
603
[email protected]82918cc2010-08-25 17:24:50604int HttpNetworkTransaction::DoInitStream() {
605 DCHECK(stream_.get());
606 next_state_ = STATE_INIT_STREAM_COMPLETE;
607 return stream_->InitializeStream(request_, net_log_, &io_callback_);
608}
609
610int HttpNetworkTransaction::DoInitStreamComplete(int result) {
611 if (result == OK) {
612 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
613
[email protected]82918cc2010-08-25 17:24:50614 if (is_https_request())
615 stream_->GetSSLInfo(&response_.ssl_info);
616 } else {
617 if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED)
618 result = HandleCertificateRequest(result);
619
620 if (result < 0)
[email protected]044dcc52010-09-17 15:44:26621 result = HandleIOError(result);
622
623 // The stream initialization failed, so this stream will never be useful.
624 stream_.reset();
[email protected]82918cc2010-08-25 17:24:50625 }
626
627 return result;
628}
629
[email protected]044de0642010-06-17 10:42:15630int HttpNetworkTransaction::DoGenerateProxyAuthToken() {
631 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE;
632 if (!ShouldApplyProxyAuth())
633 return OK;
[email protected]394816e92010-08-03 07:38:59634 HttpAuth::Target target = HttpAuth::AUTH_PROXY;
635 if (!auth_controllers_[target].get())
[email protected]3598c6022010-09-17 23:13:09636 auth_controllers_[target] =
637 new HttpAuthController(target,
638 AuthURL(target),
639 session_->auth_cache(),
640 session_->http_auth_handler_factory());
[email protected]394816e92010-08-03 07:38:59641 return auth_controllers_[target]->MaybeGenerateAuthToken(request_,
642 &io_callback_,
643 net_log_);
[email protected]044de0642010-06-17 10:42:15644}
645
646int HttpNetworkTransaction::DoGenerateProxyAuthTokenComplete(int rv) {
647 DCHECK_NE(ERR_IO_PENDING, rv);
648 if (rv == OK)
649 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN;
650 return rv;
651}
652
653int HttpNetworkTransaction::DoGenerateServerAuthToken() {
654 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE;
[email protected]394816e92010-08-03 07:38:59655 HttpAuth::Target target = HttpAuth::AUTH_SERVER;
656 if (!auth_controllers_[target].get())
[email protected]3598c6022010-09-17 23:13:09657 auth_controllers_[target] =
658 new HttpAuthController(target,
659 AuthURL(target),
660 session_->auth_cache(),
661 session_->http_auth_handler_factory());
[email protected]044de0642010-06-17 10:42:15662 if (!ShouldApplyServerAuth())
663 return OK;
[email protected]394816e92010-08-03 07:38:59664 return auth_controllers_[target]->MaybeGenerateAuthToken(request_,
665 &io_callback_,
666 net_log_);
[email protected]044de0642010-06-17 10:42:15667}
668
669int HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) {
670 DCHECK_NE(ERR_IO_PENDING, rv);
671 if (rv == OK)
[email protected]8e6441ca2010-08-19 05:56:38672 next_state_ = STATE_SEND_REQUEST;
[email protected]044de0642010-06-17 10:42:15673 return rv;
674}
675
[email protected]0877e3d2009-10-17 22:29:57676int HttpNetworkTransaction::DoSendRequest() {
677 next_state_ = STATE_SEND_REQUEST_COMPLETE;
678
679 UploadDataStream* request_body = NULL;
[email protected]8a1f3312010-05-25 19:25:04680 if (request_->upload_data) {
[email protected]7a6db4022010-03-24 23:37:50681 int error_code;
682 request_body = UploadDataStream::Create(request_->upload_data, &error_code);
683 if (!request_body)
684 return error_code;
685 }
initial.commit586acc5fe2008-07-26 22:42:52686
687 // This is constructed lazily (instead of within our Start method), so that
688 // we have proxy info available.
[email protected]8e6441ca2010-08-19 05:56:38689 if (request_headers_.empty() && !response_.was_fetched_via_spdy) {
[email protected]1c773ea12009-04-28 19:58:42690 // Figure out if we can/should add Proxy-Authentication & Authentication
691 // headers.
[email protected]270c6412010-03-29 22:02:47692 HttpRequestHeaders authorization_headers;
[email protected]044de0642010-06-17 10:42:15693 bool have_proxy_auth = (ShouldApplyProxyAuth() &&
694 HaveAuth(HttpAuth::AUTH_PROXY));
695 bool have_server_auth = (ShouldApplyServerAuth() &&
696 HaveAuth(HttpAuth::AUTH_SERVER));
[email protected]1c773ea12009-04-28 19:58:42697 if (have_proxy_auth)
[email protected]228404f2010-06-24 04:31:41698 auth_controllers_[HttpAuth::AUTH_PROXY]->AddAuthorizationHeader(
699 &authorization_headers);
[email protected]1c773ea12009-04-28 19:58:42700 if (have_server_auth)
[email protected]228404f2010-06-24 04:31:41701 auth_controllers_[HttpAuth::AUTH_SERVER]->AddAuthorizationHeader(
702 &authorization_headers);
[email protected]044de0642010-06-17 10:42:15703 std::string request_line;
704 HttpRequestHeaders request_headers;
[email protected]8e6441ca2010-08-19 05:56:38705
[email protected]8a1f3312010-05-25 19:25:04706 BuildRequestHeaders(request_, authorization_headers, request_body,
[email protected]2df19bb2010-08-25 20:13:46707 !is_https_request() && (proxy_info_.is_http() ||
708 proxy_info_.is_https()),
[email protected]8e6441ca2010-08-19 05:56:38709 &request_line, &request_headers);
[email protected]ac039522010-06-15 16:39:44710
711 if (session_->network_delegate())
712 session_->network_delegate()->OnSendHttpRequest(&request_headers);
713
[email protected]095c7cf2010-08-31 21:07:33714 if (net_log_.IsLoggingAll()) {
[email protected]8a1f3312010-05-25 19:25:04715 net_log_.AddEvent(
716 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
[email protected]a7ea8832010-07-12 17:54:54717 new NetLogHttpRequestParameter(request_line, request_headers));
[email protected]6b9833e2008-09-10 20:32:25718 }
[email protected]ac039522010-06-15 16:39:44719
[email protected]8c76ae22010-04-20 22:15:43720 request_headers_ = request_line + request_headers.ToString();
[email protected]490937a2010-09-01 07:57:35721 } else {
722 if (net_log_.IsLoggingAll()) {
723 net_log_.AddEvent(
724 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
725 new NetLogHttpRequestParameter(request_->url.spec(),
726 request_->extra_headers));
727 }
[email protected]6b9833e2008-09-10 20:32:25728 }
initial.commit586acc5fe2008-07-26 22:42:52729
[email protected]1f14a912009-12-21 20:32:44730 headers_valid_ = false;
[email protected]351ab642010-08-05 16:55:31731 return stream_->SendRequest(request_headers_, request_body, &response_,
732 &io_callback_);
initial.commit586acc5fe2008-07-26 22:42:52733}
734
[email protected]0877e3d2009-10-17 22:29:57735int HttpNetworkTransaction::DoSendRequestComplete(int result) {
initial.commit586acc5fe2008-07-26 22:42:52736 if (result < 0)
737 return HandleIOError(result);
[email protected]0877e3d2009-10-17 22:29:57738 next_state_ = STATE_READ_HEADERS;
initial.commit586acc5fe2008-07-26 22:42:52739 return OK;
740}
741
742int HttpNetworkTransaction::DoReadHeaders() {
743 next_state_ = STATE_READ_HEADERS_COMPLETE;
[email protected]351ab642010-08-05 16:55:31744 return stream_->ReadResponseHeaders(&io_callback_);
initial.commit586acc5fe2008-07-26 22:42:52745}
746
[email protected]0e75a732008-10-16 20:36:09747int HttpNetworkTransaction::HandleConnectionClosedBeforeEndOfHeaders() {
[email protected]8e6441ca2010-08-19 05:56:38748 if (!response_.headers && !stream_->IsConnectionReused()) {
[email protected]0e75a732008-10-16 20:36:09749 // The connection was closed before any data was sent. Likely an error
750 // rather than empty HTTP/0.9 response.
[email protected]aecfbf22008-10-16 02:02:47751 return ERR_EMPTY_RESPONSE;
752 }
753
[email protected]aecfbf22008-10-16 02:02:47754 return OK;
755}
756
initial.commit586acc5fe2008-07-26 22:42:52757int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
[email protected]0b45559b2009-06-12 21:45:11758 // We can get a certificate error or ERR_SSL_CLIENT_AUTH_CERT_NEEDED here
759 // due to SSL renegotiation.
[email protected]8e6441ca2010-08-19 05:56:38760 if (IsCertificateError(result)) {
761 // We don't handle a certificate error during SSL renegotiation, so we
762 // have to return an error that's not in the certificate error range
763 // (-2xx).
764 LOG(ERROR) << "Got a server certificate with error " << result
765 << " during SSL renegotiation";
766 result = ERR_CERT_ERROR_IN_SSL_RENEGOTIATION;
767 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
768 // TODO(wtc): Need a test case for this code path!
769 DCHECK(stream_.get());
770 DCHECK(is_https_request());
771 response_.cert_request_info = new SSLCertRequestInfo;
772 stream_->GetSSLCertRequestInfo(response_.cert_request_info);
773 result = HandleCertificateRequest(result);
774 if (result == OK)
775 return result;
776 } else if ((result == ERR_SSL_DECOMPRESSION_FAILURE_ALERT ||
777 result == ERR_SSL_BAD_RECORD_MAC_ALERT) &&
778 ssl_config_.tls1_enabled &&
779 !SSLConfigService::IsKnownStrictTLSServer(request_->url.host())) {
780 // Some buggy servers select DEFLATE compression when offered and then
781 // fail to ever decompress anything. They will send a fatal alert telling
782 // us this. Normally we would pick this up during the handshake because
783 // our Finished message is compressed and we'll never get the server's
784 // Finished if it fails to process ours.
785 //
786 // However, with False Start, we'll believe that the handshake is
787 // complete as soon as we've /sent/ our Finished message. In this case,
788 // we only find out that the server is buggy here, when we try to read
789 // the initial reply.
790 session_->http_stream_factory()->AddTLSIntolerantServer(request_->url);
791 ResetConnectionAndRequestForResend();
792 return OK;
[email protected]2181ea002009-06-09 01:37:27793 }
794
[email protected]0877e3d2009-10-17 22:29:57795 if (result < 0 && result != ERR_CONNECTION_CLOSED)
initial.commit586acc5fe2008-07-26 22:42:52796 return HandleIOError(result);
797
[email protected]0877e3d2009-10-17 22:29:57798 if (result == ERR_CONNECTION_CLOSED && ShouldResendRequest(result)) {
[email protected]1c773ea12009-04-28 19:58:42799 ResetConnectionAndRequestForResend();
[email protected]0877e3d2009-10-17 22:29:57800 return OK;
[email protected]1c773ea12009-04-28 19:58:42801 }
[email protected]2a5c76b2008-09-25 22:15:16802
[email protected]0877e3d2009-10-17 22:29:57803 // After we call RestartWithAuth a new response_time will be recorded, and
804 // we need to be cautious about incorrectly logging the duration across the
805 // authentication activity.
[email protected]8e6441ca2010-08-19 05:56:38806 if (result == OK)
807 LogTransactionConnectedMetrics();
initial.commit586acc5fe2008-07-26 22:42:52808
[email protected]0877e3d2009-10-17 22:29:57809 if (result == ERR_CONNECTION_CLOSED) {
[email protected]02c92c492010-03-08 21:28:14810 // For now, if we get at least some data, we do the best we can to make
[email protected]9492e4a2010-02-24 00:58:46811 // sense of it and send it back up the stack.
[email protected]0e75a732008-10-16 20:36:09812 int rv = HandleConnectionClosedBeforeEndOfHeaders();
[email protected]aecfbf22008-10-16 02:02:47813 if (rv != OK)
814 return rv;
[email protected]0877e3d2009-10-17 22:29:57815 }
initial.commit586acc5fe2008-07-26 22:42:52816
[email protected]095c7cf2010-08-31 21:07:33817 if (net_log_.IsLoggingAll()) {
[email protected]8a1f3312010-05-25 19:25:04818 net_log_.AddEvent(
819 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
820 new NetLogHttpResponseParameter(response_.headers));
[email protected]dbb83db2010-05-11 18:13:39821 }
822
[email protected]a7e41312009-12-16 23:18:14823 if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0)) {
[email protected]0877e3d2009-10-17 22:29:57824 // HTTP/0.9 doesn't support the PUT method, so lack of response headers
825 // indicates a buggy server. See:
826 // https://bugzilla.mozilla.org/show_bug.cgi?id=193921
827 if (request_->method == "PUT")
828 return ERR_METHOD_NOT_SUPPORTED;
829 }
[email protected]4ddaf2502008-10-23 18:26:19830
[email protected]0877e3d2009-10-17 22:29:57831 // Check for an intermediate 100 Continue response. An origin server is
832 // allowed to send this response even if we didn't ask for it, so we just
833 // need to skip over it.
834 // We treat any other 1xx in this same way (although in practice getting
835 // a 1xx that isn't a 100 is rare).
[email protected]a7e41312009-12-16 23:18:14836 if (response_.headers->response_code() / 100 == 1) {
[email protected]ee9410e72010-01-07 01:42:38837 response_.headers = new HttpResponseHeaders("");
[email protected]0877e3d2009-10-17 22:29:57838 next_state_ = STATE_READ_HEADERS;
839 return OK;
840 }
841
[email protected]8e6441ca2010-08-19 05:56:38842 HostPortPair endpoint = HostPortPair(request_->url.HostNoBrackets(),
843 request_->url.EffectiveIntPort());
844 ProcessAlternateProtocol(session_->http_stream_factory(),
845 session_->mutable_alternate_protocols(),
846 *response_.headers,
847 endpoint);
[email protected]564b4912010-03-09 16:30:42848
[email protected]e772db3f2010-07-12 18:11:13849 int rv = HandleAuthChallenge();
[email protected]0877e3d2009-10-17 22:29:57850 if (rv != OK)
851 return rv;
852
[email protected]0877e3d2009-10-17 22:29:57853 headers_valid_ = true;
854 return OK;
initial.commit586acc5fe2008-07-26 22:42:52855}
856
857int HttpNetworkTransaction::DoReadBody() {
858 DCHECK(read_buf_);
[email protected]6501bc02009-06-25 20:55:13859 DCHECK_GT(read_buf_len_, 0);
[email protected]8e6441ca2010-08-19 05:56:38860 DCHECK(stream_ != NULL);
initial.commit586acc5fe2008-07-26 22:42:52861
862 next_state_ = STATE_READ_BODY_COMPLETE;
[email protected]351ab642010-08-05 16:55:31863 return stream_->ReadResponseBody(read_buf_, read_buf_len_, &io_callback_);
initial.commit586acc5fe2008-07-26 22:42:52864}
865
866int HttpNetworkTransaction::DoReadBodyComplete(int result) {
867 // We are done with the Read call.
[email protected]8e6441ca2010-08-19 05:56:38868 bool done = false;
869 if (result <= 0) {
870 DCHECK_NE(ERR_IO_PENDING, result);
initial.commit586acc5fe2008-07-26 22:42:52871 done = true;
[email protected]8e6441ca2010-08-19 05:56:38872 }
[email protected]9492e4a2010-02-24 00:58:46873
[email protected]8e6441ca2010-08-19 05:56:38874 bool keep_alive = false;
[email protected]351ab642010-08-05 16:55:31875 if (stream_->IsResponseBodyComplete()) {
[email protected]8e6441ca2010-08-19 05:56:38876 // Note: Just because IsResponseBodyComplete is true, we're not
877 // necessarily "done". We're only "done" when it is the last
878 // read on this HttpNetworkTransaction, which will be signified
879 // by a zero-length read.
880 // TODO(mbelshe): The keepalive property is really a property of
881 // the stream. No need to compute it here just to pass back
882 // to the stream's Close function.
[email protected]351ab642010-08-05 16:55:31883 if (stream_->CanFindEndOfResponse())
[email protected]02c92c492010-03-08 21:28:14884 keep_alive = GetResponseHeaders()->IsKeepAlive();
initial.commit586acc5fe2008-07-26 22:42:52885 }
886
[email protected]8e6441ca2010-08-19 05:56:38887 // Clean up connection if we are done.
initial.commit586acc5fe2008-07-26 22:42:52888 if (done) {
[email protected]56300172008-11-06 18:42:55889 LogTransactionMetrics();
[email protected]8e6441ca2010-08-19 05:56:38890 stream_->Close(!keep_alive);
[email protected]e2a915a2010-08-19 07:55:01891 // Note: we don't reset the stream here. We've closed it, but we still
892 // need it around so that callers can call methods such as
893 // GetUploadProgress() and have them be meaningful.
894 // TODO(mbelshe): This means we closed the stream here, and we close it
895 // again in ~HttpNetworkTransaction. Clean that up.
896
[email protected]8e6441ca2010-08-19 05:56:38897 // The next Read call will return 0 (EOF).
initial.commit586acc5fe2008-07-26 22:42:52898 }
899
900 // Clear these to avoid leaving around old state.
901 read_buf_ = NULL;
902 read_buf_len_ = 0;
903
904 return result;
905}
906
[email protected]2d2697f92009-02-18 21:00:32907int HttpNetworkTransaction::DoDrainBodyForAuthRestart() {
908 // This method differs from DoReadBody only in the next_state_. So we just
909 // call DoReadBody and override the next_state_. Perhaps there is a more
910 // elegant way for these two methods to share code.
911 int rv = DoReadBody();
912 DCHECK(next_state_ == STATE_READ_BODY_COMPLETE);
913 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE;
914 return rv;
915}
916
[email protected]0877e3d2009-10-17 22:29:57917// TODO(wtc): This method and the DoReadBodyComplete method are almost
918// the same. Figure out a good way for these two methods to share code.
[email protected]2d2697f92009-02-18 21:00:32919int HttpNetworkTransaction::DoDrainBodyForAuthRestartComplete(int result) {
[email protected]68873ba2009-06-04 21:49:23920 // keep_alive defaults to true because the very reason we're draining the
921 // response body is to reuse the connection for auth restart.
922 bool done = false, keep_alive = true;
[email protected]2d2697f92009-02-18 21:00:32923 if (result < 0) {
[email protected]0877e3d2009-10-17 22:29:57924 // Error or closed connection while reading the socket.
[email protected]2d2697f92009-02-18 21:00:32925 done = true;
[email protected]68873ba2009-06-04 21:49:23926 keep_alive = false;
[email protected]351ab642010-08-05 16:55:31927 } else if (stream_->IsResponseBodyComplete()) {
[email protected]0877e3d2009-10-17 22:29:57928 done = true;
[email protected]2d2697f92009-02-18 21:00:32929 }
930
931 if (done) {
932 DidDrainBodyForAuthRestart(keep_alive);
933 } else {
934 // Keep draining.
935 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
936 }
937
938 return OK;
939}
940
[email protected]8e3d2d32010-06-13 18:46:23941void HttpNetworkTransaction::LogTransactionConnectedMetrics() {
942 if (logged_response_time_)
943 return;
944
945 logged_response_time_ = true;
946
[email protected]a7e41312009-12-16 23:18:14947 base::TimeDelta total_duration = response_.response_time - start_time_;
[email protected]9a0a55f2009-04-13 23:23:03948
[email protected]510e854f2009-04-20 18:39:08949 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:58950 "Net.Transaction_Connected_Under_10",
[email protected]510e854f2009-04-20 18:39:08951 total_duration,
[email protected]9a0a55f2009-04-13 23:23:03952 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
953 100);
[email protected]1fa47592009-07-27 22:45:00954
[email protected]c38ec5a2010-08-25 23:32:38955 bool reused_socket = stream_->IsConnectionReused();
956 if (!reused_socket) {
[email protected]b01998a2009-04-21 01:01:11957 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:58958 "Net.Transaction_Connected_New",
[email protected]b01998a2009-04-21 01:01:11959 total_duration,
960 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
961 100);
[email protected]d068f7a2010-06-07 15:12:59962
963 static bool use_conn_impact_histogram(
964 FieldTrialList::Find("ConnCountImpact") &&
965 !FieldTrialList::Find("ConnCountImpact")->group_name().empty());
966 if (use_conn_impact_histogram) {
967 UMA_HISTOGRAM_CLIPPED_TIMES(
968 FieldTrial::MakeName("Net.Transaction_Connected_New",
969 "ConnCountImpact"),
970 total_duration,
971 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
972 100);
973 }
[email protected]0310d432009-08-25 07:49:52974 }
975
[email protected]8e3d2d32010-06-13 18:46:23976 static bool use_spdy_histogram(FieldTrialList::Find("SpdyImpact") &&
977 !FieldTrialList::Find("SpdyImpact")->group_name().empty());
978 if (use_spdy_histogram && response_.was_npn_negotiated) {
979 UMA_HISTOGRAM_CLIPPED_TIMES(
980 FieldTrial::MakeName("Net.Transaction_Connected_Under_10", "SpdyImpact"),
981 total_duration, base::TimeDelta::FromMilliseconds(1),
982 base::TimeDelta::FromMinutes(10), 100);
983
[email protected]c38ec5a2010-08-25 23:32:38984 if (!reused_socket) {
[email protected]8e3d2d32010-06-13 18:46:23985 UMA_HISTOGRAM_CLIPPED_TIMES(
986 FieldTrial::MakeName("Net.Transaction_Connected_New", "SpdyImpact"),
987 total_duration, base::TimeDelta::FromMilliseconds(1),
988 base::TimeDelta::FromMinutes(10), 100);
989 }
990 }
991
[email protected]510e854f2009-04-20 18:39:08992 // Currently, non-zero priority requests are frame or sub-frame resource
993 // types. This will change when we also prioritize certain subresources like
994 // css, js, etc.
995 if (request_->priority) {
996 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:58997 "Net.Priority_High_Latency",
[email protected]510e854f2009-04-20 18:39:08998 total_duration,
999 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1000 100);
1001 } else {
1002 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:581003 "Net.Priority_Low_Latency",
[email protected]510e854f2009-04-20 18:39:081004 total_duration,
1005 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1006 100);
1007 }
[email protected]9a0a55f2009-04-13 23:23:031008}
1009
[email protected]56300172008-11-06 18:42:551010void HttpNetworkTransaction::LogTransactionMetrics() const {
[email protected]0877e3d2009-10-17 22:29:571011 base::TimeDelta duration = base::Time::Now() -
[email protected]2227c692010-05-04 15:36:111012 response_.request_time;
[email protected]56300172008-11-06 18:42:551013 if (60 < duration.InMinutes())
1014 return;
[email protected]0b48db42009-03-23 02:45:111015
[email protected]21b316a2009-03-23 18:25:061016 base::TimeDelta total_duration = base::Time::Now() - start_time_;
1017
[email protected]f929f2f22009-06-12 16:56:581018 UMA_HISTOGRAM_LONG_TIMES("Net.Transaction_Latency", duration);
1019 UMA_HISTOGRAM_CLIPPED_TIMES("Net.Transaction_Latency_Under_10", duration,
[email protected]2227c692010-05-04 15:36:111020 base::TimeDelta::FromMilliseconds(1),
1021 base::TimeDelta::FromMinutes(10),
1022 100);
[email protected]f929f2f22009-06-12 16:56:581023 UMA_HISTOGRAM_CLIPPED_TIMES("Net.Transaction_Latency_Total_Under_10",
[email protected]2227c692010-05-04 15:36:111024 total_duration,
1025 base::TimeDelta::FromMilliseconds(1),
1026 base::TimeDelta::FromMinutes(10), 100);
[email protected]c38ec5a2010-08-25 23:32:381027 if (!stream_->IsConnectionReused()) {
[email protected]f929f2f22009-06-12 16:56:581028 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]808f6402009-03-30 20:02:071029 "Net.Transaction_Latency_Total_New_Connection_Under_10",
[email protected]808f6402009-03-30 20:02:071030 total_duration, base::TimeDelta::FromMilliseconds(1),
1031 base::TimeDelta::FromMinutes(10), 100);
1032 }
[email protected]56300172008-11-06 18:42:551033}
1034
[email protected]5e363962009-06-19 19:57:011035int HttpNetworkTransaction::HandleCertificateRequest(int error) {
[email protected]8e6441ca2010-08-19 05:56:381036 // There are two paths through which the server can request a certificate
1037 // from us. The first is during the initial handshake, the second is
1038 // during SSL renegotiation.
1039 //
1040 // In both cases, we want to close the connection before proceeding.
1041 // We do this for two reasons:
1042 // First, we don't want to keep the connection to the server hung for a
1043 // long time while the user selects a certificate.
1044 // Second, even if we did keep the connection open, NSS has a bug where
1045 // restarting the handshake for ClientAuth is currently broken.
[email protected]65a3b912010-08-21 05:46:581046 DCHECK_EQ(error, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]8e6441ca2010-08-19 05:56:381047
1048 if (stream_.get()) {
1049 // Since we already have a stream, we're being called as part of SSL
1050 // renegotiation.
1051 DCHECK(!stream_request_.get());
1052 stream_->Close(true);
1053 stream_.reset();
1054 }
1055
1056 if (stream_request_.get()) {
1057 // The server is asking for a client certificate during the initial
1058 // handshake.
[email protected]8e6441ca2010-08-19 05:56:381059 stream_request_->Cancel();
1060 stream_request_ = NULL;
[email protected]8e6441ca2010-08-19 05:56:381061 }
[email protected]5e363962009-06-19 19:57:011062
1063 // If the user selected one of the certificate in client_certs for this
1064 // server before, use it automatically.
1065 X509Certificate* client_cert = session_->ssl_client_auth_cache()->
[email protected]2227c692010-05-04 15:36:111066 Lookup(GetHostAndPort(request_->url));
[email protected]5e363962009-06-19 19:57:011067 if (client_cert) {
1068 const std::vector<scoped_refptr<X509Certificate> >& client_certs =
[email protected]a7e41312009-12-16 23:18:141069 response_.cert_request_info->client_certs;
[email protected]5e363962009-06-19 19:57:011070 for (size_t i = 0; i < client_certs.size(); ++i) {
[email protected]bd0b7432009-06-23 21:03:421071 if (client_cert->fingerprint().Equals(client_certs[i]->fingerprint())) {
[email protected]65a3b912010-08-21 05:46:581072 // TODO(davidben): Add a unit test which covers this path; we need to be
1073 // able to send a legitimate certificate and also bypass/clear the
1074 // SSL session cache.
[email protected]5e363962009-06-19 19:57:011075 ssl_config_.client_cert = client_cert;
1076 ssl_config_.send_client_cert = true;
[email protected]82918cc2010-08-25 17:24:501077 next_state_ = STATE_CREATE_STREAM;
[email protected]5e363962009-06-19 19:57:011078 // Reset the other member variables.
1079 // Note: this is necessary only with SSL renegotiation.
1080 ResetStateForRestart();
1081 return OK;
1082 }
1083 }
1084 }
1085 return error;
[email protected]0b45559b2009-06-12 21:45:111086}
1087
[email protected]96d570e42008-08-05 22:43:041088// This method determines whether it is safe to resend the request after an
1089// IO error. It can only be called in response to request header or body
1090// write errors or response header read errors. It should not be used in
1091// other cases, such as a Connect error.
initial.commit586acc5fe2008-07-26 22:42:521092int HttpNetworkTransaction::HandleIOError(int error) {
1093 switch (error) {
1094 // If we try to reuse a connection that the server is in the process of
1095 // closing, we may end up successfully writing out our request (or a
1096 // portion of our request) only to find a connection error when we try to
1097 // read from (or finish writing to) the socket.
1098 case ERR_CONNECTION_RESET:
1099 case ERR_CONNECTION_CLOSED:
1100 case ERR_CONNECTION_ABORTED:
[email protected]a19f1c602009-08-24 21:35:281101 if (ShouldResendRequest(error)) {
[email protected]1c773ea12009-04-28 19:58:421102 ResetConnectionAndRequestForResend();
initial.commit586acc5fe2008-07-26 22:42:521103 error = OK;
[email protected]1c773ea12009-04-28 19:58:421104 }
initial.commit586acc5fe2008-07-26 22:42:521105 break;
1106 }
1107 return error;
1108}
1109
[email protected]c3b35c22008-09-27 03:19:421110void HttpNetworkTransaction::ResetStateForRestart() {
[email protected]0757e7702009-03-27 04:00:221111 pending_auth_target_ = HttpAuth::AUTH_NONE;
[email protected]c3b35c22008-09-27 03:19:421112 read_buf_ = NULL;
1113 read_buf_len_ = 0;
[email protected]351ab642010-08-05 16:55:311114 stream_.reset();
[email protected]0877e3d2009-10-17 22:29:571115 headers_valid_ = false;
1116 request_headers_.clear();
[email protected]a7e41312009-12-16 23:18:141117 response_ = HttpResponseInfo();
[email protected]8e6441ca2010-08-19 05:56:381118 establishing_tunnel_ = false;
[email protected]0877e3d2009-10-17 22:29:571119}
1120
1121HttpResponseHeaders* HttpNetworkTransaction::GetResponseHeaders() const {
[email protected]a7e41312009-12-16 23:18:141122 return response_.headers;
[email protected]c3b35c22008-09-27 03:19:421123}
1124
[email protected]a19f1c602009-08-24 21:35:281125bool HttpNetworkTransaction::ShouldResendRequest(int error) const {
[email protected]8e6441ca2010-08-19 05:56:381126 bool connection_is_proven = stream_->IsConnectionReused();
1127 bool has_received_headers = GetResponseHeaders() != NULL;
[email protected]58cebf8f2010-07-31 19:20:161128
[email protected]2a5c76b2008-09-25 22:15:161129 // NOTE: we resend a request only if we reused a keep-alive connection.
1130 // This automatically prevents an infinite resend loop because we'll run
1131 // out of the cached keep-alive connections eventually.
[email protected]8e6441ca2010-08-19 05:56:381132 if (connection_is_proven && !has_received_headers)
1133 return true;
1134 return false;
[email protected]1c773ea12009-04-28 19:58:421135}
1136
1137void HttpNetworkTransaction::ResetConnectionAndRequestForResend() {
[email protected]8e6441ca2010-08-19 05:56:381138 if (stream_.get()) {
1139 stream_->Close(true);
1140 stream_.reset();
[email protected]58cebf8f2010-07-31 19:20:161141 }
1142
[email protected]0877e3d2009-10-17 22:29:571143 // We need to clear request_headers_ because it contains the real request
1144 // headers, but we may need to resend the CONNECT request first to recreate
1145 // the SSL tunnel.
1146 request_headers_.clear();
[email protected]82918cc2010-08-25 17:24:501147 next_state_ = STATE_CREATE_STREAM; // Resend the request.
[email protected]86ec30d2008-09-29 21:53:541148}
1149
[email protected]1c773ea12009-04-28 19:58:421150bool HttpNetworkTransaction::ShouldApplyProxyAuth() const {
[email protected]2df19bb2010-08-25 20:13:461151 return !is_https_request() &&
1152 (proxy_info_.is_https() || proxy_info_.is_http());
[email protected]1c773ea12009-04-28 19:58:421153}
license.botbf09a502008-08-24 00:55:551154
[email protected]1c773ea12009-04-28 19:58:421155bool HttpNetworkTransaction::ShouldApplyServerAuth() const {
[email protected]8a1f3312010-05-25 19:25:041156 return !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA);
[email protected]1c773ea12009-04-28 19:58:421157}
1158
[email protected]e772db3f2010-07-12 18:11:131159int HttpNetworkTransaction::HandleAuthChallenge() {
[email protected]0877e3d2009-10-17 22:29:571160 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
1161 DCHECK(headers);
[email protected]c3b35c22008-09-27 03:19:421162
[email protected]0877e3d2009-10-17 22:29:571163 int status = headers->response_code();
[email protected]c3b35c22008-09-27 03:19:421164 if (status != 401 && status != 407)
1165 return OK;
1166 HttpAuth::Target target = status == 407 ?
[email protected]2227c692010-05-04 15:36:111167 HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER;
[email protected]038e9a32008-10-08 22:40:161168 if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct())
1169 return ERR_UNEXPECTED_PROXY_AUTH;
[email protected]c3b35c22008-09-27 03:19:421170
[email protected]a7ea8832010-07-12 17:54:541171 int rv = auth_controllers_[target]->HandleAuthChallenge(
[email protected]560c0432010-07-13 20:45:311172 headers, (request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA) != 0, false,
1173 net_log_);
[email protected]228404f2010-06-24 04:31:411174 if (auth_controllers_[target]->HaveAuthHandler())
1175 pending_auth_target_ = target;
1176
1177 scoped_refptr<AuthChallengeInfo> auth_info =
1178 auth_controllers_[target]->auth_info();
1179 if (auth_info.get())
1180 response_.auth_challenge = auth_info;
1181
[email protected]228404f2010-06-24 04:31:411182 return rv;
[email protected]f9ee6b52008-11-08 06:46:231183}
1184
[email protected]8e6441ca2010-08-19 05:56:381185bool HttpNetworkTransaction::HaveAuth(HttpAuth::Target target) const {
1186 return auth_controllers_[target].get() &&
1187 auth_controllers_[target]->HaveAuth();
1188}
1189
1190
[email protected]228404f2010-06-24 04:31:411191GURL HttpNetworkTransaction::AuthURL(HttpAuth::Target target) const {
1192 switch (target) {
[email protected]2df19bb2010-08-25 20:13:461193 case HttpAuth::AUTH_PROXY: {
[email protected]228404f2010-06-24 04:31:411194 if (!proxy_info_.proxy_server().is_valid() ||
1195 proxy_info_.proxy_server().is_direct()) {
1196 return GURL(); // There is no proxy server.
1197 }
[email protected]2df19bb2010-08-25 20:13:461198 const char* scheme = proxy_info_.is_https() ? "https://" : "http://";
1199 return GURL(scheme +
[email protected]2fbaecf22010-07-22 22:20:351200 proxy_info_.proxy_server().host_port_pair().ToString());
[email protected]2df19bb2010-08-25 20:13:461201 }
[email protected]228404f2010-06-24 04:31:411202 case HttpAuth::AUTH_SERVER:
1203 return request_->url;
1204 default:
1205 return GURL();
1206 }
[email protected]c3b35c22008-09-27 03:19:421207}
1208
[email protected]aef04272010-06-28 18:03:041209#define STATE_CASE(s) case s: \
1210 description = StringPrintf("%s (0x%08X)", #s, s); \
1211 break
1212
1213std::string HttpNetworkTransaction::DescribeState(State state) {
1214 std::string description;
1215 switch (state) {
[email protected]82918cc2010-08-25 17:24:501216 STATE_CASE(STATE_CREATE_STREAM);
1217 STATE_CASE(STATE_CREATE_STREAM_COMPLETE);
[email protected]aef04272010-06-28 18:03:041218 STATE_CASE(STATE_SEND_REQUEST);
1219 STATE_CASE(STATE_SEND_REQUEST_COMPLETE);
1220 STATE_CASE(STATE_READ_HEADERS);
1221 STATE_CASE(STATE_READ_HEADERS_COMPLETE);
[email protected]aef04272010-06-28 18:03:041222 STATE_CASE(STATE_READ_BODY);
1223 STATE_CASE(STATE_READ_BODY_COMPLETE);
1224 STATE_CASE(STATE_DRAIN_BODY_FOR_AUTH_RESTART);
1225 STATE_CASE(STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE);
[email protected]aef04272010-06-28 18:03:041226 STATE_CASE(STATE_NONE);
1227 default:
1228 description = StringPrintf("Unknown state 0x%08X (%u)", state, state);
1229 break;
1230 }
1231 return description;
1232}
1233
[email protected]c9c6f5c2010-07-31 01:30:031234// TODO(gavinp): re-adjust this once SPDY v3 has three priority bits,
1235// eliminating the need for this folding.
1236int ConvertRequestPriorityToSpdyPriority(const RequestPriority priority) {
1237 DCHECK(HIGHEST <= priority && priority < NUM_PRIORITIES);
1238 switch (priority) {
1239 case LOWEST:
1240 return SPDY_PRIORITY_LOWEST-1;
1241 case IDLE:
1242 return SPDY_PRIORITY_LOWEST;
1243 default:
1244 return priority;
1245 }
1246}
1247
1248
1249
[email protected]aef04272010-06-28 18:03:041250#undef STATE_CASE
1251
[email protected]c3b35c22008-09-27 03:19:421252} // namespace net