Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(30)

Side by Side Diff: net/http/http_stream_parser.cc

Issue 249031: Refactor HttpNetworkTransaction: Parse stream in HttpStream (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/http/http_stream_parser.h ('k') | net/net.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:mergeinfo
Merged /branches/chrome_webkit_merge_branch/net/http/http_network_transaction.cc:r69-2775
OLDNEW
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/http/http_network_transaction.h" 5 #include "net/http/http_stream_parser.h"
6 6
7 #include "base/scoped_ptr.h"
8 #include "base/compiler_specific.h" 7 #include "base/compiler_specific.h"
9 #include "base/field_trial.h"
10 #include "base/histogram.h"
11 #include "base/string_util.h"
12 #include "base/trace_event.h" 8 #include "base/trace_event.h"
13 #include "build/build_config.h"
14 #include "net/base/connection_type_histograms.h"
15 #include "net/base/io_buffer.h" 9 #include "net/base/io_buffer.h"
16 #include "net/base/load_flags.h"
17 #include "net/base/net_errors.h"
18 #include "net/base/net_util.h"
19 #include "net/base/ssl_cert_request_info.h"
20 #include "net/base/upload_data_stream.h"
21 #include "net/http/http_auth.h"
22 #include "net/http/http_auth_handler.h"
23 #include "net/http/http_basic_stream.h"
24 #include "net/http/http_chunked_decoder.h"
25 #include "net/http/http_network_session.h"
26 #include "net/http/http_request_info.h" 10 #include "net/http/http_request_info.h"
27 #include "net/http/http_response_headers.h" 11 #include "net/http/http_response_headers.h"
28 #include "net/http/http_util.h" 12 #include "net/http/http_util.h"
29 #include "net/socket/client_socket_factory.h"
30 #include "net/socket/socks5_client_socket.h"
31 #include "net/socket/socks_client_socket.h"
32 #include "net/socket/ssl_client_socket.h"
33
34 using base::Time;
35 13
36 namespace net { 14 namespace net {
37 15
38 void HttpNetworkTransaction::ResponseHeaders::Realloc(size_t new_size) { 16 HttpStreamParser::HttpStreamParser(ClientSocketHandle* connection,
39 headers_.reset(static_cast<char*>(realloc(headers_.release(), new_size))); 17 GrowableIOBuffer* read_buffer)
40 } 18 : io_state_(STATE_NONE),
41 19 request_(NULL),
42 namespace { 20 request_headers_(NULL),
43 21 request_body_(NULL),
44 void BuildRequestHeaders(const HttpRequestInfo* request_info, 22 read_buf_(read_buffer),
45 const std::string& authorization_headers, 23 read_buf_unused_offset_(0),
46 const UploadDataStream* upload_data_stream, 24 response_header_start_offset_(-1),
47 bool using_proxy, 25 response_body_length_(-1),
48 std::string* request_headers) { 26 response_body_read_(0),
49 const std::string path = using_proxy ? 27 chunked_decoder_(NULL),
50 HttpUtil::SpecForRequest(request_info->url) : 28 user_read_buf_(NULL),
51 HttpUtil::PathForRequest(request_info->url); 29 user_read_buf_len_(0),
52 *request_headers = 30 user_callback_(NULL),
53 StringPrintf("%s %s HTTP/1.1\r\nHost: %s\r\n", 31 connection_(connection),
54 request_info->method.c_str(), path.c_str(),
55 GetHostAndOptionalPort(request_info->url).c_str());
56
57 // For compat with HTTP/1.0 servers and proxies:
58 if (using_proxy)
59 *request_headers += "Proxy-";
60 *request_headers += "Connection: keep-alive\r\n";
61
62 if (!request_info->user_agent.empty()) {
63 StringAppendF(request_headers, "User-Agent: %s\r\n",
64 request_info->user_agent.c_str());
65 }
66
67 // Our consumer should have made sure that this is a safe referrer. See for
68 // instance WebCore::FrameLoader::HideReferrer.
69 if (request_info->referrer.is_valid())
70 StringAppendF(request_headers, "Referer: %s\r\n",
71 request_info->referrer.spec().c_str());
72
73 // Add a content length header?
74 if (upload_data_stream) {
75 StringAppendF(request_headers, "Content-Length: %llu\r\n",
76 upload_data_stream->size());
77 } else if (request_info->method == "POST" || request_info->method == "PUT" ||
78 request_info->method == "HEAD") {
79 // An empty POST/PUT request still needs a content length. As for HEAD,
80 // IE and Safari also add a content length header. Presumably it is to
81 // support sending a HEAD request to an URL that only expects to be sent a
82 // POST or some other method that normally would have a message body.
83 *request_headers += "Content-Length: 0\r\n";
84 }
85
86 // Honor load flags that impact proxy caches.
87 if (request_info->load_flags & LOAD_BYPASS_CACHE) {
88 *request_headers += "Pragma: no-cache\r\nCache-Control: no-cache\r\n";
89 } else if (request_info->load_flags & LOAD_VALIDATE_CACHE) {
90 *request_headers += "Cache-Control: max-age=0\r\n";
91 }
92
93 if (!authorization_headers.empty()) {
94 *request_headers += authorization_headers;
95 }
96
97 // TODO(darin): Need to prune out duplicate headers.
98
99 *request_headers += request_info->extra_headers;
100 *request_headers += "\r\n";
101 }
102
103 // The HTTP CONNECT method for establishing a tunnel connection is documented
104 // in draft-luotonen-web-proxy-tunneling-01.txt and RFC 2817, Sections 5.2 and
105 // 5.3.
106 void BuildTunnelRequest(const HttpRequestInfo* request_info,
107 const std::string& authorization_headers,
108 std::string* request_headers) {
109 // RFC 2616 Section 9 says the Host request-header field MUST accompany all
110 // HTTP/1.1 requests. Add "Proxy-Connection: keep-alive" for compat with
111 // HTTP/1.0 proxies such as Squid (required for NTLM authentication).
112 *request_headers = StringPrintf(
113 "CONNECT %s HTTP/1.1\r\nHost: %s\r\nProxy-Connection: keep-alive\r\n",
114 GetHostAndPort(request_info->url).c_str(),
115 GetHostAndOptionalPort(request_info->url).c_str());
116
117 if (!request_info->user_agent.empty())
118 StringAppendF(request_headers, "User-Agent: %s\r\n",
119 request_info->user_agent.c_str());
120
121 if (!authorization_headers.empty()) {
122 *request_headers += authorization_headers;
123 }
124
125 *request_headers += "\r\n";
126 }
127
128 } // namespace
129
130 //-----------------------------------------------------------------------------
131
132 HttpNetworkTransaction::HttpNetworkTransaction(HttpNetworkSession* session)
133 : pending_auth_target_(HttpAuth::AUTH_NONE),
134 ALLOW_THIS_IN_INITIALIZER_LIST( 32 ALLOW_THIS_IN_INITIALIZER_LIST(
135 io_callback_(this, &HttpNetworkTransaction::OnIOComplete)), 33 io_callback_(this, &HttpStreamParser::OnIOComplete)) {
136 user_callback_(NULL), 34 DCHECK_EQ(0, read_buffer->offset());
137 session_(session), 35 }
138 request_(NULL), 36
139 pac_request_(NULL), 37 int HttpStreamParser::SendRequest(const HttpRequestInfo* request,
140 reused_socket_(false), 38 const std::string& headers,
141 using_ssl_(false), 39 UploadDataStream* request_body,
142 proxy_mode_(kDirectConnection), 40 CompletionCallback* callback) {
143 establishing_tunnel_(false), 41 DCHECK_EQ(STATE_NONE, io_state_);
144 reading_body_from_socket_(false), 42 DCHECK(!user_callback_);
145 embedded_identity_used_(false), 43 DCHECK(callback);
146 request_headers_(new RequestHeaders()), 44
147 request_headers_bytes_sent_(0), 45 request_ = request;
148 header_buf_(new ResponseHeaders()), 46 scoped_refptr<StringIOBuffer> headers_io_buf = new StringIOBuffer(headers);
149 header_buf_capacity_(0), 47 request_headers_ = new DrainableIOBuffer(headers_io_buf,
150 header_buf_len_(0), 48 headers_io_buf->size());
151 header_buf_body_offset_(-1), 49 request_body_.reset(request_body);
152 header_buf_http_offset_(-1), 50
153 response_body_length_(-1), // -1 means unspecified. 51 io_state_ = STATE_SENDING_HEADERS;
154 response_body_read_(0), 52 int result = DoLoop(OK);
155 read_buf_len_(0), 53 if (result == ERR_IO_PENDING)
156 next_state_(STATE_NONE) {
157 session->ssl_config_service()->GetSSLConfig(&ssl_config_);
158 }
159
160 int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info,
161 CompletionCallback* callback,
162 LoadLog* load_log) {
163 UpdateConnectionTypeHistograms(CONNECTION_ANY);
164
165 load_log_ = load_log;
166 request_ = request_info;
167 start_time_ = base::Time::Now();
168
169 next_state_ = STATE_RESOLVE_PROXY;
170 int rv = DoLoop(OK);
171 if (rv == ERR_IO_PENDING)
172 user_callback_ = callback; 54 user_callback_ = callback;
173 return rv; 55
174 } 56 return result > 0 ? OK : result;
175 57 }
176 int HttpNetworkTransaction::RestartIgnoringLastError( 58
177 CompletionCallback* callback) { 59 int HttpStreamParser::ReadResponseHeaders(CompletionCallback* callback) {
178 if (connection_.socket()->IsConnected()) { 60 DCHECK_EQ(STATE_REQUEST_SENT, io_state_);
179 next_state_ = STATE_WRITE_HEADERS; 61 DCHECK(!user_callback_);
62 DCHECK(callback);
63
64 int result = OK;
65 io_state_ = STATE_READ_HEADERS;
66
67 if (read_buf_->offset() > 0) {
68 // Simulate the state where the data was just read from the socket.
69 result = read_buf_->offset() - read_buf_unused_offset_;
70 read_buf_->set_offset(read_buf_unused_offset_);
71 }
72 if (result > 0)
73 io_state_ = STATE_READ_HEADERS_COMPLETE;
74
75 result = DoLoop(result);
76 if (result == ERR_IO_PENDING)
77 user_callback_ = callback;
78
79 return result > 0 ? OK : result;
80 }
81
82 int HttpStreamParser::ReadResponseBody(IOBuffer* buf, int buf_len,
83 CompletionCallback* callback) {
84 DCHECK(io_state_ == STATE_BODY_PENDING || io_state_ == STATE_DONE);
85 DCHECK(!user_callback_);
86 DCHECK(callback);
87
88 if (io_state_ == STATE_DONE)
89 return OK;
90
91 user_read_buf_ = buf;
92 user_read_buf_len_ = buf_len;
93 io_state_ = STATE_READ_BODY;
94
95 int result = DoLoop(OK);
96 if (result == ERR_IO_PENDING)
97 user_callback_ = callback;
98
99 return result;
100 }
101
102 void HttpStreamParser::OnIOComplete(int result) {
103 result = DoLoop(result);
104
105 // The client callback can do anything, including destroying this class,
106 // so any pending callback must be issued after everything else is done.
107 if (result != ERR_IO_PENDING && user_callback_) {
108 CompletionCallback* c = user_callback_;
109 user_callback_ = NULL;
110 c->Run(result);
111 }
112 }
113
114 int HttpStreamParser::DoLoop(int result) {
115 bool can_do_more = true;
116 do {
117 switch (io_state_) {
118 case STATE_SENDING_HEADERS:
119 TRACE_EVENT_BEGIN("http.write_headers", request_, request_->url.spec());
120 if (result < 0)
121 can_do_more = false;
122 else
123 result = DoSendHeaders(result);
124 TRACE_EVENT_END("http.write_headers", request_, request_->url.spec());
125 break;
126 case STATE_SENDING_BODY:
127 TRACE_EVENT_BEGIN("http.write_body", request_, request_->url.spec());
128 if (result < 0)
129 can_do_more = false;
130 else
131 result = DoSendBody(result);
132 TRACE_EVENT_END("http.write_body", request_, request_->url.spec());
133 break;
134 case STATE_REQUEST_SENT:
135 DCHECK(result != ERR_IO_PENDING);
136 can_do_more = false;
137 break;
138 case STATE_READ_HEADERS:
139 TRACE_EVENT_BEGIN("http.read_headers", request_, request_->url.spec());
140 result = DoReadHeaders();
141 break;
142 case STATE_READ_HEADERS_COMPLETE:
143 result = DoReadHeadersComplete(result);
144 TRACE_EVENT_END("http.read_headers", request_, request_->url.spec());
145 break;
146 case STATE_BODY_PENDING:
147 DCHECK(result != ERR_IO_PENDING);
148 can_do_more = false;
149 break;
150 case STATE_READ_BODY:
151 TRACE_EVENT_BEGIN("http.read_body", request_, request_->url.spec());
152 result = DoReadBody();
153 // DoReadBodyComplete handles error conditions.
154 break;
155 case STATE_READ_BODY_COMPLETE:
156 result = DoReadBodyComplete(result);
157 TRACE_EVENT_END("http.read_body", request_, request_->url.spec());
158 break;
159 case STATE_DONE:
160 DCHECK(result != ERR_IO_PENDING);
161 can_do_more = false;
162 break;
163 default:
164 NOTREACHED();
165 can_do_more = false;
166 break;
167 }
168 } while (result != ERR_IO_PENDING && can_do_more);
169
170 return result;
171 }
172
173 int HttpStreamParser::DoSendHeaders(int result) {
174 request_headers_->DidConsume(result);
175
176 if (request_headers_->BytesRemaining() > 0) {
177 // Record our best estimate of the 'request time' as the time when we send
178 // out the first bytes of the request headers.
179 if (request_headers_->BytesRemaining() == request_headers_->size()) {
180 response_.request_time = base::Time::Now();
181 }
182 result = connection_->socket()->Write(request_headers_,
183 request_headers_->BytesRemaining(),
184 &io_callback_);
185 } else if (request_body_ != NULL && request_body_->size()) {
186 io_state_ = STATE_SENDING_BODY;
187 result = OK;
180 } else { 188 } else {
181 connection_.socket()->Disconnect(); 189 io_state_ = STATE_REQUEST_SENT;
182 connection_.Reset(); 190 }
183 next_state_ = STATE_INIT_CONNECTION; 191 return result;
184 } 192 }
185 int rv = DoLoop(OK); 193
186 if (rv == ERR_IO_PENDING) 194 int HttpStreamParser::DoSendBody(int result) {
187 user_callback_ = callback; 195 request_body_->DidConsume(result);
188 return rv; 196
189 } 197 if (request_body_->position() < request_body_->size()) {
190 198 int buf_len = static_cast<int>(request_body_->buf_len());
191 int HttpNetworkTransaction::RestartWithCertificate( 199 result = connection_->socket()->Write(request_body_->buf(), buf_len,
192 X509Certificate* client_cert, 200 &io_callback_);
193 CompletionCallback* callback) {
194 ssl_config_.client_cert = client_cert;
195 if (client_cert) {
196 session_->ssl_client_auth_cache()->Add(GetHostAndPort(request_->url),
197 client_cert);
198 }
199 ssl_config_.send_client_cert = true;
200 next_state_ = STATE_INIT_CONNECTION;
201 // Reset the other member variables.
202 // Note: this is necessary only with SSL renegotiation.
203 ResetStateForRestart();
204 int rv = DoLoop(OK);
205 if (rv == ERR_IO_PENDING)
206 user_callback_ = callback;
207 return rv;
208 }
209
210 int HttpNetworkTransaction::RestartWithAuth(
211 const std::wstring& username,
212 const std::wstring& password,
213 CompletionCallback* callback) {
214 HttpAuth::Target target = pending_auth_target_;
215 if (target == HttpAuth::AUTH_NONE) {
216 NOTREACHED();
217 return ERR_UNEXPECTED;
218 }
219
220 pending_auth_target_ = HttpAuth::AUTH_NONE;
221
222 DCHECK(auth_identity_[target].invalid ||
223 (username.empty() && password.empty()));
224
225 if (auth_identity_[target].invalid) {
226 // Update the username/password.
227 auth_identity_[target].source = HttpAuth::IDENT_SRC_EXTERNAL;
228 auth_identity_[target].invalid = false;
229 auth_identity_[target].username = username;
230 auth_identity_[target].password = password;
231 }
232
233 PrepareForAuthRestart(target);
234
235 DCHECK(user_callback_ == NULL);
236 int rv = DoLoop(OK);
237 if (rv == ERR_IO_PENDING)
238 user_callback_ = callback;
239
240 return rv;
241 }
242
243 void HttpNetworkTransaction::PrepareForAuthRestart(HttpAuth::Target target) {
244 DCHECK(HaveAuth(target));
245 DCHECK(auth_identity_[target].source != HttpAuth::IDENT_SRC_PATH_LOOKUP);
246
247 // Add the auth entry to the cache before restarting. We don't know whether
248 // the identity is valid yet, but if it is valid we want other transactions
249 // to know about it. If an entry for (origin, handler->realm()) already
250 // exists, we update it.
251 //
252 // If auth_identity_[target].source is HttpAuth::IDENT_SRC_NONE,
253 // auth_identity_[target] contains no identity because identity is not
254 // required yet.
255 //
256 // TODO(wtc): For NTLM_SSPI, we add the same auth entry to the cache in
257 // round 1 and round 2, which is redundant but correct. It would be nice
258 // to add an auth entry to the cache only once, preferrably in round 1.
259 // See http://crbug.com/21015.
260 bool has_auth_identity =
261 auth_identity_[target].source != HttpAuth::IDENT_SRC_NONE;
262 if (has_auth_identity) {
263 session_->auth_cache()->Add(AuthOrigin(target), auth_handler_[target],
264 auth_identity_[target].username, auth_identity_[target].password,
265 AuthPath(target));
266 }
267
268 bool keep_alive = false;
269 if (response_.headers->IsKeepAlive()) {
270 // If there is a response body of known length, we need to drain it first.
271 if (response_body_length_ > 0 || chunked_decoder_.get()) {
272 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
273 read_buf_ = new IOBuffer(kDrainBodyBufferSize); // A bit bucket
274 read_buf_len_ = kDrainBodyBufferSize;
275 return;
276 }
277 if (response_body_length_ == 0) // No response body to drain.
278 keep_alive = true;
279 // response_body_length_ is -1 and we're not using chunked encoding. We
280 // don't know the length of the response body, so we can't reuse this
281 // connection even though the server says it's keep-alive.
282 }
283
284 // We don't need to drain the response body, so we act as if we had drained
285 // the response body.
286 DidDrainBodyForAuthRestart(keep_alive);
287 }
288
289 void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) {
290 if (keep_alive) {
291 next_state_ = STATE_WRITE_HEADERS;
292 reused_socket_ = true;
293 } else { 201 } else {
294 next_state_ = STATE_INIT_CONNECTION; 202 io_state_ = STATE_REQUEST_SENT;
295 connection_.socket()->Disconnect(); 203 }
296 connection_.Reset(); 204 return result;
297 } 205 }
298 206
299 // Reset the other member variables. 207 int HttpStreamParser::DoReadHeaders() {
300 ResetStateForRestart(); 208 io_state_ = STATE_READ_HEADERS_COMPLETE;
301 } 209
302 210 // Grow the read buffer if necessary.
303 int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len, 211 if (read_buf_->RemainingCapacity() == 0)
304 CompletionCallback* callback) { 212 read_buf_->set_capacity(read_buf_->capacity() + kHeaderBufInitialSize);
305 DCHECK(response_.headers);
306 DCHECK(buf);
307 DCHECK_LT(0, buf_len);
308
309 if (!connection_.is_initialized())
310 return 0; // connection_ has been reset. Treat like EOF.
311
312 if (establishing_tunnel_) {
313 // We're trying to read the body of the response but we're still trying to
314 // establish an SSL tunnel through the proxy. We can't read these bytes
315 // when establishing a tunnel because they might be controlled by an active
316 // network attacker. We don't worry about this for HTTP because an active
317 // network attacker can already control HTTP sessions.
318 // We reach this case when the user cancels a 407 proxy auth prompt.
319 // See http://crbug.com/8473
320 DCHECK_EQ(407, response_.headers->response_code());
321 LogBlockedTunnelResponse(response_.headers->response_code());
322 return ERR_TUNNEL_CONNECTION_FAILED;
323 }
324 213
325 // http://crbug.com/16371: We're seeing |user_buf_->data()| return NULL. 214 // http://crbug.com/16371: We're seeing |user_buf_->data()| return NULL.
326 // See if the user is passing in an IOBuffer with a NULL |data_|. 215 // See if the user is passing in an IOBuffer with a NULL |data_|.
327 CHECK(buf); 216 CHECK(read_buf_->data());
328 CHECK(buf->data()); 217
329 218 int bytes_read = connection_->socket()->Read(read_buf_,
330 read_buf_ = buf; 219 read_buf_->RemainingCapacity(),
331 read_buf_len_ = buf_len; 220 &io_callback_);
332 221 if (bytes_read == 0)
333 next_state_ = STATE_READ_BODY; 222 bytes_read = ERR_CONNECTION_CLOSED;
334 int rv = DoLoop(OK); 223
335 if (rv == ERR_IO_PENDING) 224 return bytes_read;
336 user_callback_ = callback; 225 }
337 return rv; 226
338 } 227 int HttpStreamParser::DoReadHeadersComplete(int result) {
339 228 if (result < 0 && result != ERR_CONNECTION_CLOSED) {
340 const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const { 229 io_state_ = STATE_DONE;
341 return (response_.headers || response_.ssl_info.cert || 230 return result;
342 response_.cert_request_info) ? &response_ : NULL; 231 }
343 } 232 if (result == ERR_CONNECTION_CLOSED && read_buf_->offset() == 0 &&
344 233 connection_->ShouldResendFailedRequest(result)) {
345 LoadState HttpNetworkTransaction::GetLoadState() const { 234 io_state_ = STATE_DONE;
346 // TODO(wtc): Define a new LoadState value for the
347 // STATE_INIT_CONNECTION_COMPLETE state, which delays the HTTP request.
348 switch (next_state_) {
349 case STATE_RESOLVE_PROXY_COMPLETE:
350 return LOAD_STATE_RESOLVING_PROXY_FOR_URL;
351 case STATE_INIT_CONNECTION_COMPLETE:
352 return connection_.GetLoadState();
353 case STATE_WRITE_HEADERS_COMPLETE:
354 case STATE_WRITE_BODY_COMPLETE:
355 return LOAD_STATE_SENDING_REQUEST;
356 case STATE_READ_HEADERS_COMPLETE:
357 return LOAD_STATE_WAITING_FOR_RESPONSE;
358 case STATE_READ_BODY_COMPLETE:
359 return LOAD_STATE_READING_RESPONSE;
360 default:
361 return LOAD_STATE_IDLE;
362 }
363 }
364
365 uint64 HttpNetworkTransaction::GetUploadProgress() const {
366 if (!request_body_stream_.get())
367 return 0;
368
369 return request_body_stream_->position();
370 }
371
372 HttpNetworkTransaction::~HttpNetworkTransaction() {
373 // If we still have an open socket, then make sure to disconnect it so it
374 // won't call us back and we don't try to reuse it later on.
375 if (connection_.is_initialized())
376 connection_.socket()->Disconnect();
377
378 if (pac_request_)
379 session_->proxy_service()->CancelPacRequest(pac_request_);
380 }
381
382 void HttpNetworkTransaction::DoCallback(int rv) {
383 DCHECK(rv != ERR_IO_PENDING);
384 DCHECK(user_callback_);
385
386 // Since Run may result in Read being called, clear user_callback_ up front.
387 CompletionCallback* c = user_callback_;
388 user_callback_ = NULL;
389 c->Run(rv);
390 }
391
392 void HttpNetworkTransaction::OnIOComplete(int result) {
393 int rv = DoLoop(result);
394 if (rv != ERR_IO_PENDING)
395 DoCallback(rv);
396 }
397
398 int HttpNetworkTransaction::DoLoop(int result) {
399 DCHECK(next_state_ != STATE_NONE);
400
401 int rv = result;
402 do {
403 State state = next_state_;
404 next_state_ = STATE_NONE;
405 switch (state) {
406 case STATE_RESOLVE_PROXY:
407 DCHECK_EQ(OK, rv);
408 TRACE_EVENT_BEGIN("http.resolve_proxy", request_, request_->url.spec());
409 rv = DoResolveProxy();
410 break;
411 case STATE_RESOLVE_PROXY_COMPLETE:
412 rv = DoResolveProxyComplete(rv);
413 TRACE_EVENT_END("http.resolve_proxy", request_, request_->url.spec());
414 break;
415 case STATE_INIT_CONNECTION:
416 DCHECK_EQ(OK, rv);
417 TRACE_EVENT_BEGIN("http.init_conn", request_, request_->url.spec());
418 rv = DoInitConnection();
419 break;
420 case STATE_INIT_CONNECTION_COMPLETE:
421 rv = DoInitConnectionComplete(rv);
422 TRACE_EVENT_END("http.init_conn", request_, request_->url.spec());
423 break;
424 case STATE_SOCKS_CONNECT:
425 DCHECK_EQ(OK, rv);
426 TRACE_EVENT_BEGIN("http.socks_connect", request_, request_->url.spec());
427 rv = DoSOCKSConnect();
428 break;
429 case STATE_SOCKS_CONNECT_COMPLETE:
430 rv = DoSOCKSConnectComplete(rv);
431 TRACE_EVENT_END("http.socks_connect", request_, request_->url.spec());
432 break;
433 case STATE_SSL_CONNECT:
434 DCHECK_EQ(OK, rv);
435 TRACE_EVENT_BEGIN("http.ssl_connect", request_, request_->url.spec());
436 rv = DoSSLConnect();
437 break;
438 case STATE_SSL_CONNECT_COMPLETE:
439 rv = DoSSLConnectComplete(rv);
440 TRACE_EVENT_END("http.ssl_connect", request_, request_->url.spec());
441 break;
442 case STATE_WRITE_HEADERS:
443 DCHECK_EQ(OK, rv);
444 TRACE_EVENT_BEGIN("http.write_headers", request_, request_->url.spec());
445 rv = DoWriteHeaders();
446 break;
447 case STATE_WRITE_HEADERS_COMPLETE:
448 rv = DoWriteHeadersComplete(rv);
449 TRACE_EVENT_END("http.write_headers", request_, request_->url.spec());
450 break;
451 case STATE_WRITE_BODY:
452 DCHECK_EQ(OK, rv);
453 TRACE_EVENT_BEGIN("http.write_body", request_, request_->url.spec());
454 rv = DoWriteBody();
455 break;
456 case STATE_WRITE_BODY_COMPLETE:
457 rv = DoWriteBodyComplete(rv);
458 TRACE_EVENT_END("http.write_body", request_, request_->url.spec());
459 break;
460 case STATE_READ_HEADERS:
461 DCHECK_EQ(OK, rv);
462 TRACE_EVENT_BEGIN("http.read_headers", request_, request_->url.spec());
463 rv = DoReadHeaders();
464 break;
465 case STATE_READ_HEADERS_COMPLETE:
466 rv = DoReadHeadersComplete(rv);
467 TRACE_EVENT_END("http.read_headers", request_, request_->url.spec());
468 break;
469 case STATE_READ_BODY:
470 DCHECK_EQ(OK, rv);
471 TRACE_EVENT_BEGIN("http.read_body", request_, request_->url.spec());
472 rv = DoReadBody();
473 break;
474 case STATE_READ_BODY_COMPLETE:
475 rv = DoReadBodyComplete(rv);
476 TRACE_EVENT_END("http.read_body", request_, request_->url.spec());
477 break;
478 case STATE_DRAIN_BODY_FOR_AUTH_RESTART:
479 DCHECK_EQ(OK, rv);
480 TRACE_EVENT_BEGIN("http.drain_body_for_auth_restart",
481 request_, request_->url.spec());
482 rv = DoDrainBodyForAuthRestart();
483 break;
484 case STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE:
485 rv = DoDrainBodyForAuthRestartComplete(rv);
486 TRACE_EVENT_END("http.drain_body_for_auth_restart",
487 request_, request_->url.spec());
488 break;
489 default:
490 NOTREACHED() << "bad state";
491 rv = ERR_FAILED;
492 break;
493 }
494 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
495
496 return rv;
497 }
498
499 int HttpNetworkTransaction::DoResolveProxy() {
500 DCHECK(!pac_request_);
501
502 next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
503
504 if (request_->load_flags & LOAD_BYPASS_PROXY) {
505 proxy_info_.UseDirect();
506 return OK;
507 }
508
509 return session_->proxy_service()->ResolveProxy(
510 request_->url, &proxy_info_, &io_callback_, &pac_request_, load_log_);
511 }
512
513 int HttpNetworkTransaction::DoResolveProxyComplete(int result) {
514 next_state_ = STATE_INIT_CONNECTION;
515
516 // Remove unsupported proxies from the list.
517 proxy_info_.RemoveProxiesWithoutScheme(
518 ProxyServer::SCHEME_DIRECT | ProxyServer::SCHEME_HTTP |
519 ProxyServer::SCHEME_SOCKS4 | ProxyServer::SCHEME_SOCKS5);
520
521 pac_request_ = NULL;
522
523 if (result != OK) {
524 DLOG(ERROR) << "Failed to resolve proxy: " << result;
525 proxy_info_.UseDirect();
526 }
527 return OK;
528 }
529
530 int HttpNetworkTransaction::DoInitConnection() {
531 DCHECK(!connection_.is_initialized());
532
533 next_state_ = STATE_INIT_CONNECTION_COMPLETE;
534
535 using_ssl_ = request_->url.SchemeIs("https");
536
537 if (proxy_info_.is_direct())
538 proxy_mode_ = kDirectConnection;
539 else if (proxy_info_.proxy_server().is_socks())
540 proxy_mode_ = kSOCKSProxy;
541 else if (using_ssl_)
542 proxy_mode_ = kHTTPProxyUsingTunnel;
543 else
544 proxy_mode_ = kHTTPProxy;
545
546 // Build the string used to uniquely identify connections of this type.
547 // Determine the host and port to connect to.
548 std::string connection_group;
549 std::string host;
550 int port;
551 if (proxy_mode_ != kDirectConnection) {
552 ProxyServer proxy_server = proxy_info_.proxy_server();
553 connection_group = "proxy/" + proxy_server.ToURI() + "/";
554 host = proxy_server.HostNoBrackets();
555 port = proxy_server.port();
556 } else {
557 host = request_->url.HostNoBrackets();
558 port = request_->url.EffectiveIntPort();
559 }
560
561 // For a connection via HTTP proxy not using CONNECT, the connection
562 // is to the proxy server only. For all other cases
563 // (direct, HTTP proxy CONNECT, SOCKS), the connection is upto the
564 // url endpoint. Hence we append the url data into the connection_group.
565 if (proxy_mode_ != kHTTPProxy)
566 connection_group.append(request_->url.GetOrigin().spec());
567
568 // TODO(willchan): Downgrade this back to a DCHECK after closing
569 // http://crbug.com/15374.
570 if (connection_group.empty()) {
571 char url_debug[4096];
572 base::strlcpy(url_debug,
573 request_->url.possibly_invalid_spec().c_str(),
574 arraysize(url_debug));
575 char url_origin_debug[4096];
576 base::strlcpy(url_origin_debug,
577 request_->url.GetOrigin().possibly_invalid_spec().c_str(),
578 arraysize(url_origin_debug));
579 CHECK(false) << "URL: " << url_debug << ", Origin: " << url_origin_debug;
580 }
581
582 HostResolver::RequestInfo resolve_info(host, port);
583
584 // The referrer is used by the DNS prefetch system to corellate resolutions
585 // with the page that triggered them. It doesn't impact the actual addresses
586 // that we resolve to.
587 resolve_info.set_referrer(request_->referrer);
588
589 // If the user is refreshing the page, bypass the host cache.
590 if (request_->load_flags & LOAD_BYPASS_CACHE ||
591 request_->load_flags & LOAD_DISABLE_CACHE) {
592 resolve_info.set_allow_cached_response(false);
593 }
594
595 int rv = connection_.Init(connection_group, resolve_info, request_->priority,
596 &io_callback_, session_->tcp_socket_pool(),
597 load_log_);
598 return rv;
599 }
600
601 int HttpNetworkTransaction::DoInitConnectionComplete(int result) {
602 if (result < 0)
603 return ReconsiderProxyAfterError(result);
604
605 DCHECK(connection_.is_initialized());
606
607 LogTCPConnectedMetrics(connection_);
608
609 // Set the reused_socket_ flag to indicate that we are using a keep-alive
610 // connection. This flag is used to handle errors that occur while we are
611 // trying to reuse a keep-alive connection.
612 reused_socket_ = connection_.is_reused();
613 if (reused_socket_) {
614 next_state_ = STATE_WRITE_HEADERS;
615 } else {
616 // Now we have a TCP connected socket. Perform other connection setup as
617 // needed.
618 if (proxy_mode_ == kSOCKSProxy)
619 next_state_ = STATE_SOCKS_CONNECT;
620 else if (using_ssl_ && proxy_mode_ == kDirectConnection) {
621 next_state_ = STATE_SSL_CONNECT;
622 } else {
623 next_state_ = STATE_WRITE_HEADERS;
624 if (proxy_mode_ == kHTTPProxyUsingTunnel)
625 establishing_tunnel_ = true;
626 }
627 }
628 http_stream_.reset(new HttpBasicStream(&connection_));
629 return OK;
630 }
631
632 int HttpNetworkTransaction::DoSOCKSConnect() {
633 DCHECK_EQ(kSOCKSProxy, proxy_mode_);
634
635 next_state_ = STATE_SOCKS_CONNECT_COMPLETE;
636
637 // Add a SOCKS connection on top of our existing transport socket.
638 ClientSocket* s = connection_.release_socket();
639 HostResolver::RequestInfo req_info(request_->url.HostNoBrackets(),
640 request_->url.EffectiveIntPort());
641 req_info.set_referrer(request_->referrer);
642
643 if (proxy_info_.proxy_server().scheme() == ProxyServer::SCHEME_SOCKS5)
644 s = new SOCKS5ClientSocket(s, req_info, session_->host_resolver());
645 else
646 s = new SOCKSClientSocket(s, req_info, session_->host_resolver());
647 connection_.set_socket(s);
648 return connection_.socket()->Connect(&io_callback_);
649 }
650
651 int HttpNetworkTransaction::DoSOCKSConnectComplete(int result) {
652 DCHECK_EQ(kSOCKSProxy, proxy_mode_);
653
654 if (result == OK) {
655 if (using_ssl_) {
656 next_state_ = STATE_SSL_CONNECT;
657 } else {
658 next_state_ = STATE_WRITE_HEADERS;
659 }
660 } else {
661 result = ReconsiderProxyAfterError(result);
662 }
663 return result;
664 }
665
666 int HttpNetworkTransaction::DoSSLConnect() {
667 next_state_ = STATE_SSL_CONNECT_COMPLETE;
668
669 if (request_->load_flags & LOAD_VERIFY_EV_CERT)
670 ssl_config_.verify_ev_cert = true;
671
672 ssl_connect_start_time_ = base::TimeTicks::Now();
673
674 // Add a SSL socket on top of our existing transport socket.
675 ClientSocket* s = connection_.release_socket();
676 s = session_->socket_factory()->CreateSSLClientSocket(
677 s, request_->url.HostNoBrackets(), ssl_config_);
678 connection_.set_socket(s);
679 return connection_.socket()->Connect(&io_callback_);
680 }
681
682 int HttpNetworkTransaction::DoSSLConnectComplete(int result) {
683 if (IsCertificateError(result))
684 result = HandleCertificateError(result);
685
686 if (result == OK) {
687 DCHECK(ssl_connect_start_time_ != base::TimeTicks());
688 base::TimeDelta connect_duration =
689 base::TimeTicks::Now() - ssl_connect_start_time_;
690
691 UMA_HISTOGRAM_CLIPPED_TIMES("Net.SSL_Connection_Latency",
692 connect_duration,
693 base::TimeDelta::FromMilliseconds(1),
694 base::TimeDelta::FromMinutes(10),
695 100);
696
697 next_state_ = STATE_WRITE_HEADERS;
698 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
699 result = HandleCertificateRequest(result);
700 } else {
701 result = HandleSSLHandshakeError(result);
702 }
703 return result;
704 }
705
706 int HttpNetworkTransaction::DoWriteHeaders() {
707 next_state_ = STATE_WRITE_HEADERS_COMPLETE;
708
709 // This is constructed lazily (instead of within our Start method), so that
710 // we have proxy info available.
711 if (request_headers_->headers_.empty()) {
712 // Figure out if we can/should add Proxy-Authentication & Authentication
713 // headers.
714 bool have_proxy_auth =
715 ShouldApplyProxyAuth() &&
716 (HaveAuth(HttpAuth::AUTH_PROXY) ||
717 SelectPreemptiveAuth(HttpAuth::AUTH_PROXY));
718 bool have_server_auth =
719 ShouldApplyServerAuth() &&
720 (HaveAuth(HttpAuth::AUTH_SERVER) ||
721 SelectPreemptiveAuth(HttpAuth::AUTH_SERVER));
722
723 std::string authorization_headers;
724
725 // TODO(wtc): If BuildAuthorizationHeader fails (returns an authorization
726 // header with no credentials), we should return an error to prevent
727 // entering an infinite auth restart loop. See http://crbug.com/21050.
728 if (have_proxy_auth)
729 authorization_headers.append(
730 BuildAuthorizationHeader(HttpAuth::AUTH_PROXY));
731 if (have_server_auth)
732 authorization_headers.append(
733 BuildAuthorizationHeader(HttpAuth::AUTH_SERVER));
734
735 if (establishing_tunnel_) {
736 BuildTunnelRequest(request_, authorization_headers,
737 &request_headers_->headers_);
738 } else {
739 if (request_->upload_data)
740 request_body_stream_.reset(new UploadDataStream(request_->upload_data));
741 BuildRequestHeaders(request_, authorization_headers,
742 request_body_stream_.get(),
743 proxy_mode_ == kHTTPProxy,
744 &request_headers_->headers_);
745 }
746 }
747
748 // Record our best estimate of the 'request time' as the time when we send
749 // out the first bytes of the request headers.
750 if (request_headers_bytes_sent_ == 0) {
751 response_.request_time = Time::Now();
752 }
753
754 request_headers_->SetDataOffset(request_headers_bytes_sent_);
755 int buf_len = static_cast<int>(request_headers_->headers_.size() -
756 request_headers_bytes_sent_);
757 DCHECK_GT(buf_len, 0);
758
759 return http_stream_->Write(request_headers_, buf_len, &io_callback_);
760 }
761
762 int HttpNetworkTransaction::DoWriteHeadersComplete(int result) {
763 if (result < 0)
764 return HandleIOError(result);
765
766 request_headers_bytes_sent_ += result;
767 if (request_headers_bytes_sent_ < request_headers_->headers_.size()) {
768 next_state_ = STATE_WRITE_HEADERS;
769 } else if (!establishing_tunnel_ && request_body_stream_.get() &&
770 request_body_stream_->size()) {
771 next_state_ = STATE_WRITE_BODY;
772 } else {
773 next_state_ = STATE_READ_HEADERS;
774 }
775 return OK;
776 }
777
778 int HttpNetworkTransaction::DoWriteBody() {
779 next_state_ = STATE_WRITE_BODY_COMPLETE;
780
781 DCHECK(request_body_stream_.get());
782 DCHECK(request_body_stream_->size());
783
784 int buf_len = static_cast<int>(request_body_stream_->buf_len());
785
786 return http_stream_->Write(request_body_stream_->buf(), buf_len,
787 &io_callback_);
788 }
789
790 int HttpNetworkTransaction::DoWriteBodyComplete(int result) {
791 if (result < 0)
792 return HandleIOError(result);
793
794 request_body_stream_->DidConsume(result);
795
796 if (request_body_stream_->position() < request_body_stream_->size()) {
797 next_state_ = STATE_WRITE_BODY;
798 } else {
799 next_state_ = STATE_READ_HEADERS;
800 }
801 return OK;
802 }
803
804 int HttpNetworkTransaction::DoReadHeaders() {
805 next_state_ = STATE_READ_HEADERS_COMPLETE;
806
807 // Grow the read buffer if necessary.
808 if (header_buf_len_ == header_buf_capacity_) {
809 header_buf_capacity_ += kHeaderBufInitialSize;
810 header_buf_->Realloc(header_buf_capacity_);
811 }
812
813 int buf_len = header_buf_capacity_ - header_buf_len_;
814 header_buf_->set_data(header_buf_len_);
815
816 // http://crbug.com/16371: We're seeing |user_buf_->data()| return NULL.
817 // See if the user is passing in an IOBuffer with a NULL |data_|.
818 CHECK(header_buf_->data());
819
820 return http_stream_->Read(header_buf_, buf_len, &io_callback_);
821 }
822
823 int HttpNetworkTransaction::HandleConnectionClosedBeforeEndOfHeaders() {
824 if (establishing_tunnel_) {
825 // The connection was closed before the tunnel could be established.
826 return ERR_TUNNEL_CONNECTION_FAILED;
827 }
828
829 if (has_found_status_line_start()) {
830 // Assume EOF is end-of-headers.
831 header_buf_body_offset_ = header_buf_len_;
832 return OK;
833 }
834
835 // No status line was matched yet. Could have been a HTTP/0.9 response, or
836 // a partial HTTP/1.x response.
837
838 if (header_buf_len_ == 0) {
839 // The connection was closed before any data was sent. Likely an error
840 // rather than empty HTTP/0.9 response.
841 return ERR_EMPTY_RESPONSE;
842 }
843
844 // Assume everything else is a HTTP/0.9 response (including responses
845 // of 'h', 'ht', 'htt').
846 header_buf_body_offset_ = 0;
847 return OK;
848 }
849
850 int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
851 // We can get a certificate error or ERR_SSL_CLIENT_AUTH_CERT_NEEDED here
852 // due to SSL renegotiation.
853 if (using_ssl_) {
854 if (IsCertificateError(result)) {
855 // We don't handle a certificate error during SSL renegotiation, so we
856 // have to return an error that's not in the certificate error range
857 // (-2xx).
858 LOG(ERROR) << "Got a server certificate with error " << result
859 << " during SSL renegotiation";
860 result = ERR_CERT_ERROR_IN_SSL_RENEGOTIATION;
861 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
862 result = HandleCertificateRequest(result);
863 if (result == OK)
864 return result;
865 }
866 }
867
868 if (result < 0)
869 return HandleIOError(result);
870
871 if (result == 0 && ShouldResendRequest(result)) {
872 ResetConnectionAndRequestForResend();
873 return result; 235 return result;
874 } 236 }
875 237
876 // Record our best estimate of the 'response time' as the time when we read 238 // Record our best estimate of the 'response time' as the time when we read
877 // the first bytes of the response headers. 239 // the first bytes of the response headers.
878 if (header_buf_len_ == 0) { 240 if (read_buf_->offset() == 0 && result != ERR_CONNECTION_CLOSED)
879 // After we call RestartWithAuth header_buf_len will be zero again, and 241 response_.response_time = base::Time::Now();
880 // we need to be cautious about incorrectly logging the duration across the 242
881 // authentication activitiy. 243 if (result == ERR_CONNECTION_CLOSED) {
882 bool first_response = response_.response_time == Time(); 244 // The connection closed before we detected the end of the headers.
883 response_.response_time = Time::Now(); 245 // parse things as well as we can and let the caller decide what to do.
884 if (first_response) 246 if (read_buf_->offset() == 0) {
885 LogTransactionConnectedMetrics(); 247 // The connection was closed before any data was sent. Likely an error
886 } 248 // rather than empty HTTP/0.9 response.
887 249 io_state_ = STATE_DONE;
888 // The socket was closed before we found end-of-headers. 250 return ERR_EMPTY_RESPONSE;
889 if (result == 0) { 251 } else {
890 int rv = HandleConnectionClosedBeforeEndOfHeaders(); 252 int end_offset;
891 if (rv != OK) 253 if (response_header_start_offset_ >= 0) {
892 return rv; 254 io_state_ = STATE_READ_BODY_COMPLETE;
255 end_offset = read_buf_->offset();
256 } else {
257 io_state_ = STATE_BODY_PENDING;
258 end_offset = 0;
259 }
260 DoParseResponseHeaders(end_offset);
261 return result;
262 }
263 }
264
265 read_buf_->set_offset(read_buf_->offset() + result);
266 DCHECK_LE(read_buf_->offset(), read_buf_->capacity());
267 DCHECK(result >= 0);
268
269 int end_of_header_offset = ParseResponseHeaders();
270 if (end_of_header_offset == -1) {
271 io_state_ = STATE_READ_HEADERS;
272 // Prevent growing the headers buffer indefinitely.
273 if (read_buf_->offset() - read_buf_unused_offset_ >= kMaxHeaderBufSize) {
274 io_state_ = STATE_DONE;
275 return ERR_RESPONSE_HEADERS_TOO_BIG;
276 }
893 } else { 277 } else {
894 header_buf_len_ += result; 278 // Note where the headers stop.
895 DCHECK(header_buf_len_ <= header_buf_capacity_); 279 read_buf_unused_offset_ = end_of_header_offset;
896 280
897 // Look for the start of the status line, if it hasn't been found yet. 281 if (response_.headers->response_code() / 100 == 1) {
898 if (!has_found_status_line_start()) { 282 // After processing a 1xx response, the caller will ask for the next
899 header_buf_http_offset_ = HttpUtil::LocateStartOfStatusLine( 283 // header, so reset state to support that. We don't just skip these
900 header_buf_->headers(), header_buf_len_); 284 // completely because 1xx codes aren't acceptable when establishing a
901 } 285 // tunnel.
902 286 io_state_ = STATE_REQUEST_SENT;
903 if (has_found_status_line_start()) { 287 response_header_start_offset_ = -1;
904 int eoh = HttpUtil::LocateEndOfHeaders( 288 } else {
905 header_buf_->headers(), header_buf_len_, header_buf_http_offset_); 289 io_state_ = STATE_BODY_PENDING;
906 if (eoh == -1) { 290 CalculateResponseBodySize();
907 // Prevent growing the headers buffer indefinitely. 291 // If the body is 0, the caller may not call ReadResponseBody, which
908 if (header_buf_len_ >= kMaxHeaderBufSize) 292 // is where any extra data is copied to read_buf_, so we trigger
909 return ERR_RESPONSE_HEADERS_TOO_BIG; 293 // the progression to DONE here.
910 294 if (response_body_length_ == 0) {
911 // Haven't found the end of headers yet, keep reading. 295 io_state_ = STATE_READ_BODY;
912 next_state_ = STATE_READ_HEADERS; 296 user_read_buf_ = read_buf_;
297 user_read_buf_len_ = read_buf_->capacity();
913 return OK; 298 return OK;
914 } 299 }
915 header_buf_body_offset_ = eoh; 300 }
916 } else if (header_buf_len_ < 8) { 301 }
917 // Not enough data to decide whether this is HTTP/0.9 yet. 302 return result;
918 // 8 bytes = (4 bytes of junk) + "http".length() 303 }
919 next_state_ = STATE_READ_HEADERS; 304
920 return OK; 305 int HttpStreamParser::DoReadBody() {
306 io_state_ = STATE_READ_BODY_COMPLETE;
307
308 int bytes_read;
309 // There may be some data left over from reading the response headers.
310 if (read_buf_->offset()) {
311 int available = read_buf_->offset() - read_buf_unused_offset_;
312 if (available) {
313 bytes_read = std::min(available, user_read_buf_len_);
314 // memmove is used here so that the caller can pass read_buf_
315 // for user_read_buf.
316 memmove(user_read_buf_->data(),
317 read_buf_->StartOfBuffer() + read_buf_unused_offset_,
318 bytes_read);
319 read_buf_unused_offset_ += bytes_read;
320 if (bytes_read == available) {
321 read_buf_->set_capacity(0);
322 read_buf_unused_offset_ = 0;
323 }
324 return bytes_read;
921 } else { 325 } else {
922 // Enough data was read -- there is no status line. 326 read_buf_->set_capacity(0);
923 header_buf_body_offset_ = 0; 327 read_buf_unused_offset_ = 0;
924 } 328 }
925 } 329 }
926 330
927 // And, we are done with the Start or the SSL tunnel CONNECT sequence. 331 // Check to see if we're done reading.
928 return DidReadResponseHeaders(); 332 if (IsResponseBodyComplete())
929 }
930
931 int HttpNetworkTransaction::DoReadBody() {
932 DCHECK(read_buf_);
933 DCHECK_GT(read_buf_len_, 0);
934 DCHECK(connection_.is_initialized());
935 DCHECK(!header_buf_->headers() || header_buf_body_offset_ >= 0);
936
937 next_state_ = STATE_READ_BODY_COMPLETE;
938
939 // We may have already consumed the indicated content length.
940 if (response_body_length_ != -1 &&
941 response_body_read_ >= response_body_length_)
942 return 0; 333 return 0;
943 334
944 // We may have some data remaining in the header buffer. 335 DCHECK_EQ(0, read_buf_->offset());
945 if (header_buf_->headers() && header_buf_body_offset_ < header_buf_len_) { 336 bytes_read = connection_->socket()->Read(user_read_buf_, user_read_buf_len_,
946 int n = std::min(read_buf_len_, header_buf_len_ - header_buf_body_offset_); 337 &io_callback_);
947 memcpy(read_buf_->data(), header_buf_->headers() + header_buf_body_offset_, 338 if (bytes_read == 0)
948 n); 339 bytes_read = ERR_CONNECTION_CLOSED;
949 header_buf_body_offset_ += n; 340
950 if (header_buf_body_offset_ == header_buf_len_) { 341 return bytes_read;
951 header_buf_->Reset(); 342 }
952 header_buf_capacity_ = 0; 343
953 header_buf_len_ = 0; 344 int HttpStreamParser::DoReadBodyComplete(int result) {
954 header_buf_body_offset_ = -1;
955 }
956 return n;
957 }
958
959 reading_body_from_socket_ = true;
960 return http_stream_->Read(read_buf_, read_buf_len_, &io_callback_);
961 }
962
963 int HttpNetworkTransaction::DoReadBodyComplete(int result) {
964 // We are done with the Read call.
965 DCHECK(!establishing_tunnel_) <<
966 "We should never read a response body of a tunnel.";
967
968 bool unfiltered_eof = (result == 0 && reading_body_from_socket_);
969 reading_body_from_socket_ = false;
970
971 // Filter incoming data if appropriate. FilterBuf may return an error. 345 // Filter incoming data if appropriate. FilterBuf may return an error.
972 if (result > 0 && chunked_decoder_.get()) { 346 if (result > 0 && chunked_decoder_.get()) {
973 result = chunked_decoder_->FilterBuf(read_buf_->data(), result); 347 result = chunked_decoder_->FilterBuf(user_read_buf_->data(), result);
974 if (result == 0 && !chunked_decoder_->reached_eof()) { 348 if (result == 0 && !chunked_decoder_->reached_eof()) {
975 // Don't signal completion of the Read call yet or else it'll look like 349 // Don't signal completion of the Read call yet or else it'll look like
976 // we received end-of-file. Wait for more data. 350 // we received end-of-file. Wait for more data.
977 next_state_ = STATE_READ_BODY; 351 io_state_ = STATE_READ_BODY;
978 return OK; 352 return OK;
979 } 353 }
980 } 354 }
981 355
982 bool done = false, keep_alive = false; 356 if (result > 0)
983 if (result < 0) { 357 response_body_read_ += result;
984 // Error while reading the socket. 358
985 done = true; 359 if (result < 0 || IsResponseBodyComplete()) {
360 io_state_ = STATE_DONE;
361
362 // Save the overflow data, which can be in two places. There may be
363 // some left over in |user_read_buf_|, plus there may be more
364 // in |read_buf_|. But the part left over in |user_read_buf_| must have
365 // come from the |read_buf_|, so there's room to put it back at the
366 // start first.
367 int save_amount = 0;
368 int additional_save_amount = read_buf_->offset() - read_buf_unused_offset_;
369 if (chunked_decoder_.get()) {
370 save_amount = chunked_decoder_->bytes_after_eof();
371 } else if (response_body_length_ >= 0) {
372 save_amount = static_cast<int>(response_body_read_ -
373 response_body_length_);
374 if (result > 0)
375 result -= save_amount;
376 }
377 if (save_amount > 0) {
378 if (static_cast<int>(read_buf_->capacity()) < save_amount)
379 read_buf_->set_capacity(save_amount + additional_save_amount);
380 read_buf_->set_offset(save_amount);
381 // memmove is used here so that the caller can pass read_buf_
382 // for body_buf.
383 memmove(read_buf_->StartOfBuffer(), user_read_buf_->data() + result,
384 save_amount);
385 }
386 if (additional_save_amount) {
387 memmove(read_buf_->data(),
388 read_buf_->StartOfBuffer() + read_buf_unused_offset_,
389 additional_save_amount);
390 read_buf_->set_offset(save_amount + additional_save_amount);
391 }
392 read_buf_unused_offset_ = 0;
986 } else { 393 } else {
987 response_body_read_ += result; 394 io_state_ = STATE_BODY_PENDING;
988 if (unfiltered_eof || 395 user_read_buf_ = NULL;
989 (response_body_length_ != -1 && 396 user_read_buf_len_ = 0;
990 response_body_read_ >= response_body_length_) || 397 }
991 (chunked_decoder_.get() && chunked_decoder_->reached_eof())) { 398
992 done = true; 399 return result;
993 keep_alive = response_.headers->IsKeepAlive(); 400 }
994 // We can't reuse the connection if we read more than the advertised 401
995 // content length. 402 int HttpStreamParser::ParseResponseHeaders() {
996 if (unfiltered_eof || 403 int end_offset = -1;
997 (response_body_length_ != -1 && 404
998 response_body_read_ > response_body_length_)) 405 // Look for the start of the status line, if it hasn't been found yet.
999 keep_alive = false; 406 if (response_header_start_offset_ < 0) {
1000 } 407 response_header_start_offset_ = HttpUtil::LocateStartOfStatusLine(
1001 } 408 read_buf_->StartOfBuffer() + read_buf_unused_offset_,
1002 409 read_buf_->offset() - read_buf_unused_offset_);
1003 // Clean up connection_ if we are done. 410 }
1004 if (done) { 411
1005 LogTransactionMetrics(); 412 if (response_header_start_offset_ >= 0) {
1006 if (!keep_alive) 413 end_offset = HttpUtil::LocateEndOfHeaders(
1007 connection_.socket()->Disconnect(); 414 read_buf_->StartOfBuffer() + read_buf_unused_offset_,
1008 connection_.Reset(); 415 read_buf_->offset() - read_buf_unused_offset_,
1009 // The next Read call will return 0 (EOF). 416 response_header_start_offset_);
1010 } 417 } else if (read_buf_->offset() - read_buf_unused_offset_ >= 8) {
1011 418 // Enough data to decide that this is an HTTP/0.9 response.
1012 // Clear these to avoid leaving around old state. 419 // 8 bytes = (4 bytes of junk) + "http".length()
1013 read_buf_ = NULL; 420 end_offset = 0;
1014 read_buf_len_ = 0; 421 }
1015 422
1016 return result; 423 if (end_offset == -1)
1017 } 424 return -1;
1018 425
1019 int HttpNetworkTransaction::DoDrainBodyForAuthRestart() { 426 DoParseResponseHeaders(end_offset);
1020 // This method differs from DoReadBody only in the next_state_. So we just 427 return end_offset + read_buf_unused_offset_;
1021 // call DoReadBody and override the next_state_. Perhaps there is a more 428 }
1022 // elegant way for these two methods to share code. 429
1023 int rv = DoReadBody(); 430 void HttpStreamParser::DoParseResponseHeaders(int end_offset) {
1024 DCHECK(next_state_ == STATE_READ_BODY_COMPLETE); 431 scoped_refptr<HttpResponseHeaders> headers;
1025 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE; 432 if (response_header_start_offset_ >= 0) {
1026 return rv; 433 headers = new HttpResponseHeaders(HttpUtil::AssembleRawHeaders(
1027 } 434 read_buf_->StartOfBuffer() + read_buf_unused_offset_, end_offset));
1028
1029 // TODO(wtc): The first two thirds of this method and the DoReadBodyComplete
1030 // method are almost the same. Figure out a good way for these two methods
1031 // to share code.
1032 int HttpNetworkTransaction::DoDrainBodyForAuthRestartComplete(int result) {
1033 bool unfiltered_eof = (result == 0 && reading_body_from_socket_);
1034 reading_body_from_socket_ = false;
1035
1036 // Filter incoming data if appropriate. FilterBuf may return an error.
1037 if (result > 0 && chunked_decoder_.get()) {
1038 result = chunked_decoder_->FilterBuf(read_buf_->data(), result);
1039 if (result == 0 && !chunked_decoder_->reached_eof()) {
1040 // Don't signal completion of the Read call yet or else it'll look like
1041 // we received end-of-file. Wait for more data.
1042 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
1043 return OK;
1044 }
1045 }
1046
1047 // keep_alive defaults to true because the very reason we're draining the
1048 // response body is to reuse the connection for auth restart.
1049 bool done = false, keep_alive = true;
1050 if (result < 0) {
1051 // Error while reading the socket.
1052 done = true;
1053 keep_alive = false;
1054 } else { 435 } else {
1055 response_body_read_ += result; 436 // Enough data was read -- there is no status line.
1056 if (unfiltered_eof ||
1057 (response_body_length_ != -1 &&
1058 response_body_read_ >= response_body_length_) ||
1059 (chunked_decoder_.get() && chunked_decoder_->reached_eof())) {
1060 done = true;
1061 // We can't reuse the connection if we read more than the advertised
1062 // content length.
1063 if (unfiltered_eof ||
1064 (response_body_length_ != -1 &&
1065 response_body_read_ > response_body_length_))
1066 keep_alive = false;
1067 }
1068 }
1069
1070 if (done) {
1071 DidDrainBodyForAuthRestart(keep_alive);
1072 } else {
1073 // Keep draining.
1074 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
1075 }
1076
1077 return OK;
1078 }
1079
1080 void HttpNetworkTransaction::LogTCPConnectedMetrics(
1081 const ClientSocketHandle& handle) {
1082 const base::TimeDelta time_to_obtain_connected_socket =
1083 base::TimeTicks::Now() - handle.init_time();
1084
1085 static const bool use_late_binding_histogram =
1086 !FieldTrial::MakeName("", "SocketLateBinding").empty();
1087
1088 if (handle.reuse_type() == ClientSocketHandle::UNUSED) {
1089 UMA_HISTOGRAM_CLIPPED_TIMES(
1090 "Net.Dns_Resolution_And_TCP_Connection_Latency",
1091 time_to_obtain_connected_socket,
1092 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1093 100);
1094 }
1095
1096 static LinearHistogram tcp_socket_type_counter(
1097 "Net.TCPSocketType",
1098 0, ClientSocketHandle::NUM_TYPES, ClientSocketHandle::NUM_TYPES + 1);
1099 tcp_socket_type_counter.SetFlags(kUmaTargetedHistogramFlag);
1100 tcp_socket_type_counter.Add(handle.reuse_type());
1101
1102 if (use_late_binding_histogram) {
1103 static LinearHistogram tcp_socket_type_counter2(
1104 FieldTrial::MakeName("Net.TCPSocketType", "SocketLateBinding").data(),
1105 0, ClientSocketHandle::NUM_TYPES, ClientSocketHandle::NUM_TYPES + 1);
1106 tcp_socket_type_counter2.SetFlags(kUmaTargetedHistogramFlag);
1107 tcp_socket_type_counter2.Add(handle.reuse_type());
1108 }
1109
1110 UMA_HISTOGRAM_CLIPPED_TIMES(
1111 "Net.TransportSocketRequestTime",
1112 time_to_obtain_connected_socket,
1113 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1114 100);
1115
1116 if (use_late_binding_histogram) {
1117 UMA_HISTOGRAM_CUSTOM_TIMES(
1118 FieldTrial::MakeName("Net.TransportSocketRequestTime",
1119 "SocketLateBinding").data(),
1120 time_to_obtain_connected_socket,
1121 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1122 100);
1123 }
1124
1125 switch (handle.reuse_type()) {
1126 case ClientSocketHandle::UNUSED:
1127 break;
1128 case ClientSocketHandle::UNUSED_IDLE:
1129 UMA_HISTOGRAM_CUSTOM_TIMES(
1130 "Net.SocketIdleTimeBeforeNextUse_UnusedSocket",
1131 handle.idle_time(), base::TimeDelta::FromMilliseconds(1),
1132 base::TimeDelta::FromMinutes(6), 100);
1133 if (use_late_binding_histogram) {
1134 UMA_HISTOGRAM_CUSTOM_TIMES(
1135 FieldTrial::MakeName("Net.SocketIdleTimeBeforeNextUse_UnusedSocket",
1136 "SocketLateBinding").data(),
1137 handle.idle_time(), base::TimeDelta::FromMilliseconds(1),
1138 base::TimeDelta::FromMinutes(6), 100);
1139 }
1140 break;
1141 case ClientSocketHandle::REUSED_IDLE:
1142 UMA_HISTOGRAM_CUSTOM_TIMES(
1143 "Net.SocketIdleTimeBeforeNextUse_ReusedSocket",
1144 handle.idle_time(), base::TimeDelta::FromMilliseconds(1),
1145 base::TimeDelta::FromMinutes(6), 100);
1146 if (use_late_binding_histogram) {
1147 UMA_HISTOGRAM_CUSTOM_TIMES(
1148 FieldTrial::MakeName("Net.SocketIdleTimeBeforeNextUse_ReusedSocket",
1149 "SocketLateBinding").data(),
1150 handle.idle_time(), base::TimeDelta::FromMilliseconds(1),
1151 base::TimeDelta::FromMinutes(6), 100);
1152 }
1153 break;
1154 default:
1155 NOTREACHED();
1156 break;
1157 }
1158 }
1159
1160 void HttpNetworkTransaction::LogIOErrorMetrics(
1161 const ClientSocketHandle& handle) {
1162 static const bool use_late_binding_histogram =
1163 !FieldTrial::MakeName("", "SocketLateBinding").empty();
1164
1165 static LinearHistogram io_error_socket_type_counter(
1166 "Net.IOError_SocketReuseType",
1167 0, ClientSocketHandle::NUM_TYPES, ClientSocketHandle::NUM_TYPES + 1);
1168 io_error_socket_type_counter.SetFlags(kUmaTargetedHistogramFlag);
1169 io_error_socket_type_counter.Add(handle.reuse_type());
1170
1171 if (use_late_binding_histogram) {
1172 static LinearHistogram io_error_socket_type_counter(
1173 FieldTrial::MakeName("Net.IOError_SocketReuseType",
1174 "SocketLateBinding").data(),
1175 0, ClientSocketHandle::NUM_TYPES, ClientSocketHandle::NUM_TYPES + 1);
1176 io_error_socket_type_counter.SetFlags(kUmaTargetedHistogramFlag);
1177 io_error_socket_type_counter.Add(handle.reuse_type());
1178 }
1179
1180 switch (handle.reuse_type()) {
1181 case ClientSocketHandle::UNUSED:
1182 break;
1183 case ClientSocketHandle::UNUSED_IDLE:
1184 UMA_HISTOGRAM_CUSTOM_TIMES(
1185 "Net.SocketIdleTimeOnIOError2_UnusedSocket",
1186 handle.idle_time(), base::TimeDelta::FromMilliseconds(1),
1187 base::TimeDelta::FromMinutes(6), 100);
1188 if (use_late_binding_histogram) {
1189 UMA_HISTOGRAM_CUSTOM_TIMES(
1190 FieldTrial::MakeName("Net.SocketIdleTimeOnIOError2_UnusedSocket",
1191 "SocketLateBinding").data(),
1192 handle.idle_time(), base::TimeDelta::FromMilliseconds(1),
1193 base::TimeDelta::FromMinutes(6), 100);
1194 }
1195 break;
1196 case ClientSocketHandle::REUSED_IDLE:
1197 UMA_HISTOGRAM_CUSTOM_TIMES(
1198 "Net.SocketIdleTimeOnIOError2_ReusedSocket",
1199 handle.idle_time(), base::TimeDelta::FromMilliseconds(1),
1200 base::TimeDelta::FromMinutes(6), 100);
1201 if (use_late_binding_histogram) {
1202 UMA_HISTOGRAM_CUSTOM_TIMES(
1203 FieldTrial::MakeName("Net.SocketIdleTimeOnIOError2_ReusedSocket",
1204 "SocketLateBinding").data(),
1205 handle.idle_time(), base::TimeDelta::FromMilliseconds(1),
1206 base::TimeDelta::FromMinutes(6), 100);
1207 }
1208 break;
1209 default:
1210 NOTREACHED();
1211 break;
1212 }
1213 }
1214
1215 void HttpNetworkTransaction::LogTransactionConnectedMetrics() const {
1216 base::TimeDelta total_duration = response_.response_time - start_time_;
1217
1218 UMA_HISTOGRAM_CLIPPED_TIMES(
1219 "Net.Transaction_Connected_Under_10",
1220 total_duration,
1221 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1222 100);
1223
1224 static const bool use_late_binding_histogram =
1225 !FieldTrial::MakeName("", "SocketLateBinding").empty();
1226
1227 if (use_late_binding_histogram) {
1228 UMA_HISTOGRAM_CUSTOM_TIMES(
1229 FieldTrial::MakeName("Net.Transaction_Connected_Under_10",
1230 "SocketLateBinding").data(),
1231 total_duration,
1232 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1233 100);
1234 }
1235
1236 if (!reused_socket_) {
1237 UMA_HISTOGRAM_CLIPPED_TIMES(
1238 "Net.Transaction_Connected_New",
1239 total_duration,
1240 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1241 100);
1242
1243 // Also record for our field trial.
1244 static bool use_async_tcp(FieldTrialList::Find("AsyncSlowStart") &&
1245 !FieldTrialList::Find("AsyncSlowStart")->group_name().empty());
1246 if (use_async_tcp) {
1247 UMA_HISTOGRAM_CLIPPED_TIMES(
1248 FieldTrial::MakeName("Net.Transaction_Connected_New",
1249 "AsyncSlowStart").data(),
1250 total_duration,
1251 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1252 100);
1253 }
1254 }
1255
1256 // Currently, non-zero priority requests are frame or sub-frame resource
1257 // types. This will change when we also prioritize certain subresources like
1258 // css, js, etc.
1259 if (request_->priority) {
1260 UMA_HISTOGRAM_CLIPPED_TIMES(
1261 "Net.Priority_High_Latency",
1262 total_duration,
1263 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1264 100);
1265 } else {
1266 UMA_HISTOGRAM_CLIPPED_TIMES(
1267 "Net.Priority_Low_Latency",
1268 total_duration,
1269 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1270 100);
1271 }
1272 }
1273
1274 void HttpNetworkTransaction::LogTransactionMetrics() const {
1275 base::TimeDelta duration = base::Time::Now() - response_.request_time;
1276 if (60 < duration.InMinutes())
1277 return;
1278
1279 base::TimeDelta total_duration = base::Time::Now() - start_time_;
1280
1281 UMA_HISTOGRAM_LONG_TIMES("Net.Transaction_Latency", duration);
1282 UMA_HISTOGRAM_CLIPPED_TIMES("Net.Transaction_Latency_Under_10", duration,
1283 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1284 100);
1285 UMA_HISTOGRAM_CLIPPED_TIMES("Net.Transaction_Latency_Total_Under_10",
1286 total_duration, base::TimeDelta::FromMilliseconds(1),
1287 base::TimeDelta::FromMinutes(10), 100);
1288 if (!reused_socket_) {
1289 UMA_HISTOGRAM_CLIPPED_TIMES(
1290 "Net.Transaction_Latency_Total_New_Connection_Under_10",
1291 total_duration, base::TimeDelta::FromMilliseconds(1),
1292 base::TimeDelta::FromMinutes(10), 100);
1293 }
1294 }
1295
1296 void HttpNetworkTransaction::LogBlockedTunnelResponse(
1297 int response_code) const {
1298 LOG(WARNING) << "Blocked proxy response with status " << response_code
1299 << " to CONNECT request for "
1300 << GetHostAndPort(request_->url) << ".";
1301 }
1302
1303 int HttpNetworkTransaction::DidReadResponseHeaders() {
1304 DCHECK_GE(header_buf_body_offset_, 0);
1305
1306 scoped_refptr<HttpResponseHeaders> headers;
1307 if (has_found_status_line_start()) {
1308 headers = new HttpResponseHeaders(
1309 HttpUtil::AssembleRawHeaders(
1310 header_buf_->headers(), header_buf_body_offset_));
1311 } else {
1312 // Fabricate a status line to to preserve the HTTP/0.9 version.
1313 // (otherwise HttpResponseHeaders will default it to HTTP/1.0).
1314 headers = new HttpResponseHeaders(std::string("HTTP/0.9 200 OK")); 437 headers = new HttpResponseHeaders(std::string("HTTP/0.9 200 OK"));
1315 } 438 }
1316 439
1317 if (headers->GetParsedHttpVersion() < HttpVersion(1, 0)) {
1318 // Require the "HTTP/1.x" status line for SSL CONNECT.
1319 if (establishing_tunnel_)
1320 return ERR_TUNNEL_CONNECTION_FAILED;
1321
1322 // HTTP/0.9 doesn't support the PUT method, so lack of response headers
1323 // indicates a buggy server. See:
1324 // https://bugzilla.mozilla.org/show_bug.cgi?id=193921
1325 if (request_->method == "PUT")
1326 return ERR_METHOD_NOT_SUPPORTED;
1327 }
1328
1329 if (establishing_tunnel_) {
1330 switch (headers->response_code()) {
1331 case 200: // OK
1332 if (header_buf_body_offset_ != header_buf_len_) {
1333 // The proxy sent extraneous data after the headers.
1334 return ERR_TUNNEL_CONNECTION_FAILED;
1335 }
1336 next_state_ = STATE_SSL_CONNECT;
1337 // Reset for the real request and response headers.
1338 request_headers_->headers_.clear();
1339 request_headers_bytes_sent_ = 0;
1340 header_buf_len_ = 0;
1341 header_buf_body_offset_ = -1;
1342 establishing_tunnel_ = false;
1343 return OK;
1344
1345 // We aren't able to CONNECT to the remote host through the proxy. We
1346 // need to be very suspicious about the response because an active network
1347 // attacker can force us into this state by masquerading as the proxy.
1348 // The only safe thing to do here is to fail the connection because our
1349 // client is expecting an SSL protected response.
1350 // See http://crbug.com/7338.
1351 case 407: // Proxy Authentication Required
1352 // We need this status code to allow proxy authentication. Our
1353 // authentication code is smart enough to avoid being tricked by an
1354 // active network attacker.
1355 break;
1356 default:
1357 // For all other status codes, we conservatively fail the CONNECT
1358 // request.
1359 // We lose something by doing this. We have seen proxy 403, 404, and
1360 // 501 response bodies that contain a useful error message. For
1361 // example, Squid uses a 404 response to report the DNS error: "The
1362 // domain name does not exist."
1363 LogBlockedTunnelResponse(headers->response_code());
1364 return ERR_TUNNEL_CONNECTION_FAILED;
1365 }
1366 }
1367
1368 // Check for an intermediate 100 Continue response. An origin server is
1369 // allowed to send this response even if we didn't ask for it, so we just
1370 // need to skip over it.
1371 // We treat any other 1xx in this same way (although in practice getting
1372 // a 1xx that isn't a 100 is rare).
1373 if (headers->response_code() / 100 == 1) {
1374 header_buf_len_ -= header_buf_body_offset_;
1375 // If we've already received some bytes after the 1xx response,
1376 // move them to the beginning of header_buf_.
1377 if (header_buf_len_) {
1378 memmove(header_buf_->headers(),
1379 header_buf_->headers() + header_buf_body_offset_,
1380 header_buf_len_);
1381 }
1382 header_buf_body_offset_ = -1;
1383 next_state_ = STATE_READ_HEADERS;
1384 return OK;
1385 }
1386
1387 response_.headers = headers; 440 response_.headers = headers;
1388 response_.vary_data.Init(*request_, *response_.headers); 441 response_.vary_data.Init(*request_, *response_.headers);
1389 442 }
443
444 void HttpStreamParser::CalculateResponseBodySize() {
1390 // Figure how to determine EOF: 445 // Figure how to determine EOF:
1391 446
1392 // For certain responses, we know the content length is always 0. From 447 // For certain responses, we know the content length is always 0. From
1393 // RFC 2616 Section 4.3 Message Body: 448 // RFC 2616 Section 4.3 Message Body:
1394 // 449 //
1395 // For response messages, whether or not a message-body is included with 450 // For response messages, whether or not a message-body is included with
1396 // a message is dependent on both the request method and the response 451 // a message is dependent on both the request method and the response
1397 // status code (section 6.1.1). All responses to the HEAD request method 452 // status code (section 6.1.1). All responses to the HEAD request method
1398 // MUST NOT include a message-body, even though the presence of entity- 453 // MUST NOT include a message-body, even though the presence of entity-
1399 // header fields might lead one to believe they do. All 1xx 454 // header fields might lead one to believe they do. All 1xx
1400 // (informational), 204 (no content), and 304 (not modified) responses 455 // (informational), 204 (no content), and 304 (not modified) responses
1401 // MUST NOT include a message-body. All other responses do include a 456 // MUST NOT include a message-body. All other responses do include a
1402 // message-body, although it MAY be of zero length. 457 // message-body, although it MAY be of zero length.
1403 switch (response_.headers->response_code()) { 458 switch (response_.headers->response_code()) {
1404 // Note that 1xx was already handled earlier. 459 // Note that 1xx was already handled earlier.
1405 case 204: // No Content 460 case 204: // No Content
1406 case 205: // Reset Content 461 case 205: // Reset Content
1407 case 304: // Not Modified 462 case 304: // Not Modified
1408 response_body_length_ = 0; 463 response_body_length_ = 0;
1409 break; 464 break;
1410 } 465 }
1411 if (request_->method == "HEAD") 466 if (request_->method == "HEAD")
1412 response_body_length_ = 0; 467 response_body_length_ = 0;
1413 468
1414 if (response_body_length_ == -1) { 469 if (response_body_length_ == -1) {
1415 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. 470 // Ignore spurious chunked responses from HTTP/1.0 servers and
1416 // Otherwise "Transfer-Encoding: chunked" trumps "Content-Length: N" 471 // proxies. Otherwise "Transfer-Encoding: chunked" trumps
472 // "Content-Length: N"
1417 if (response_.headers->GetHttpVersion() >= HttpVersion(1, 1) && 473 if (response_.headers->GetHttpVersion() >= HttpVersion(1, 1) &&
1418 response_.headers->HasHeaderValue("Transfer-Encoding", "chunked")) { 474 response_.headers->HasHeaderValue("Transfer-Encoding", "chunked")) {
1419 chunked_decoder_.reset(new HttpChunkedDecoder()); 475 chunked_decoder_.reset(new HttpChunkedDecoder());
1420 } else { 476 } else {
1421 response_body_length_ = response_.headers->GetContentLength(); 477 response_body_length_ = response_.headers->GetContentLength();
1422 // If response_body_length_ is still -1, then we have to wait for the 478 // If response_body_length_ is still -1, then we have to wait
1423 // server to close the connection. 479 // for the server to close the connection.
1424 } 480 }
1425 } 481 }
1426
1427 int rv = HandleAuthChallenge();
1428 if (rv != OK)
1429 return rv;
1430
1431 if (using_ssl_ && !establishing_tunnel_) {
1432 SSLClientSocket* ssl_socket =
1433 reinterpret_cast<SSLClientSocket*>(connection_.socket());
1434 ssl_socket->GetSSLInfo(&response_.ssl_info);
1435 }
1436
1437 return OK;
1438 } 482 }
1439 483
1440 int HttpNetworkTransaction::HandleCertificateError(int error) { 484 uint64 HttpStreamParser::GetUploadProgress() const {
1441 DCHECK(using_ssl_); 485 if (!request_body_.get())
486 return 0;
1442 487
1443 const int kCertFlags = LOAD_IGNORE_CERT_COMMON_NAME_INVALID | 488 return request_body_->position();
1444 LOAD_IGNORE_CERT_DATE_INVALID |
1445 LOAD_IGNORE_CERT_AUTHORITY_INVALID |
1446 LOAD_IGNORE_CERT_WRONG_USAGE;
1447 if (request_->load_flags & kCertFlags) {
1448 switch (error) {
1449 case ERR_CERT_COMMON_NAME_INVALID:
1450 if (request_->load_flags & LOAD_IGNORE_CERT_COMMON_NAME_INVALID)
1451 error = OK;
1452 break;
1453 case ERR_CERT_DATE_INVALID:
1454 if (request_->load_flags & LOAD_IGNORE_CERT_DATE_INVALID)
1455 error = OK;
1456 break;
1457 case ERR_CERT_AUTHORITY_INVALID:
1458 if (request_->load_flags & LOAD_IGNORE_CERT_AUTHORITY_INVALID)
1459 error = OK;
1460 break;
1461 }
1462 }
1463
1464 if (error != OK) {
1465 SSLClientSocket* ssl_socket =
1466 reinterpret_cast<SSLClientSocket*>(connection_.socket());
1467 ssl_socket->GetSSLInfo(&response_.ssl_info);
1468
1469 // Add the bad certificate to the set of allowed certificates in the
1470 // SSL info object. This data structure will be consulted after calling
1471 // RestartIgnoringLastError(). And the user will be asked interactively
1472 // before RestartIgnoringLastError() is ever called.
1473 SSLConfig::CertAndStatus bad_cert;
1474 bad_cert.cert = response_.ssl_info.cert;
1475 bad_cert.cert_status = response_.ssl_info.cert_status;
1476 ssl_config_.allowed_bad_certs.push_back(bad_cert);
1477 }
1478 return error;
1479 } 489 }
1480 490
1481 int HttpNetworkTransaction::HandleCertificateRequest(int error) { 491 HttpResponseInfo* HttpStreamParser::GetResponseInfo() {
1482 // Assert that the socket did not send a client certificate. 492 return &response_;
1483 // Note: If we got a reused socket, it was created with some other
1484 // transaction's ssl_config_, so we need to disable this assertion. We can
1485 // get a certificate request on a reused socket when the server requested
1486 // renegotiation (rehandshake).
1487 // TODO(wtc): add a GetSSLParams method to SSLClientSocket so we can query
1488 // the SSL parameters it was created with and get rid of the reused_socket_
1489 // test.
1490 DCHECK(reused_socket_ || !ssl_config_.send_client_cert);
1491
1492 response_.cert_request_info = new SSLCertRequestInfo;
1493 SSLClientSocket* ssl_socket =
1494 reinterpret_cast<SSLClientSocket*>(connection_.socket());
1495 ssl_socket->GetSSLCertRequestInfo(response_.cert_request_info);
1496
1497 // Close the connection while the user is selecting a certificate to send
1498 // to the server.
1499 connection_.socket()->Disconnect();
1500 connection_.Reset();
1501
1502 // If the user selected one of the certificate in client_certs for this
1503 // server before, use it automatically.
1504 X509Certificate* client_cert = session_->ssl_client_auth_cache()->
1505 Lookup(GetHostAndPort(request_->url));
1506 if (client_cert) {
1507 const std::vector<scoped_refptr<X509Certificate> >& client_certs =
1508 response_.cert_request_info->client_certs;
1509 for (size_t i = 0; i < client_certs.size(); ++i) {
1510 if (client_cert->fingerprint().Equals(client_certs[i]->fingerprint())) {
1511 ssl_config_.client_cert = client_cert;
1512 ssl_config_.send_client_cert = true;
1513 next_state_ = STATE_INIT_CONNECTION;
1514 // Reset the other member variables.
1515 // Note: this is necessary only with SSL renegotiation.
1516 ResetStateForRestart();
1517 return OK;
1518 }
1519 }
1520 }
1521 return error;
1522 } 493 }
1523 494
1524 int HttpNetworkTransaction::HandleSSLHandshakeError(int error) { 495 bool HttpStreamParser::IsResponseBodyComplete() const {
1525 if (ssl_config_.send_client_cert && 496 if (chunked_decoder_.get())
1526 (error == ERR_SSL_PROTOCOL_ERROR || 497 return chunked_decoder_->reached_eof();
1527 error == ERR_BAD_SSL_CLIENT_AUTH_CERT)) { 498 if (response_body_length_ != -1)
1528 session_->ssl_client_auth_cache()->Remove(GetHostAndPort(request_->url)); 499 return response_body_read_ >= response_body_length_;
1529 }
1530 500
1531 switch (error) { 501 return false; // Must read to EOF.
1532 case ERR_SSL_PROTOCOL_ERROR:
1533 case ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
1534 if (ssl_config_.tls1_enabled) {
1535 // This could be a TLS-intolerant server or an SSL 3.0 server that
1536 // chose a TLS-only cipher suite. Turn off TLS 1.0 and retry.
1537 ssl_config_.tls1_enabled = false;
1538 connection_.socket()->Disconnect();
1539 connection_.Reset();
1540 next_state_ = STATE_INIT_CONNECTION;
1541 error = OK;
1542 }
1543 break;
1544 }
1545 return error;
1546 } 502 }
1547 503
1548 // This method determines whether it is safe to resend the request after an 504 bool HttpStreamParser::CanFindEndOfResponse() const {
1549 // IO error. It can only be called in response to request header or body 505 return chunked_decoder_.get() || response_body_length_ >= 0;
1550 // write errors or response header read errors. It should not be used in
1551 // other cases, such as a Connect error.
1552 int HttpNetworkTransaction::HandleIOError(int error) {
1553 switch (error) {
1554 // If we try to reuse a connection that the server is in the process of
1555 // closing, we may end up successfully writing out our request (or a
1556 // portion of our request) only to find a connection error when we try to
1557 // read from (or finish writing to) the socket.
1558 case ERR_CONNECTION_RESET:
1559 case ERR_CONNECTION_CLOSED:
1560 case ERR_CONNECTION_ABORTED:
1561 LogIOErrorMetrics(connection_);
1562 if (ShouldResendRequest(error)) {
1563 ResetConnectionAndRequestForResend();
1564 error = OK;
1565 }
1566 break;
1567 }
1568 return error;
1569 } 506 }
1570 507
1571 void HttpNetworkTransaction::ResetStateForRestart() { 508 bool HttpStreamParser::IsMoreDataBuffered() const {
1572 pending_auth_target_ = HttpAuth::AUTH_NONE; 509 return read_buf_->offset() > read_buf_unused_offset_;
1573 header_buf_->Reset();
1574 header_buf_capacity_ = 0;
1575 header_buf_len_ = 0;
1576 header_buf_body_offset_ = -1;
1577 header_buf_http_offset_ = -1;
1578 response_body_length_ = -1;
1579 response_body_read_ = 0;
1580 read_buf_ = NULL;
1581 read_buf_len_ = 0;
1582 request_headers_->headers_.clear();
1583 request_headers_bytes_sent_ = 0;
1584 chunked_decoder_.reset();
1585 // Reset all the members of response_.
1586 response_ = HttpResponseInfo();
1587 }
1588
1589 bool HttpNetworkTransaction::ShouldResendRequest(int error) const {
1590 // NOTE: we resend a request only if we reused a keep-alive connection.
1591 // This automatically prevents an infinite resend loop because we'll run
1592 // out of the cached keep-alive connections eventually.
1593 if (establishing_tunnel_ ||
1594 // We used a socket that was never idle.
1595 connection_.reuse_type() == ClientSocketHandle::UNUSED ||
1596 // We used an unused, idle socket and got a error that wasn't a TCP RST.
1597 (connection_.reuse_type() == ClientSocketHandle::UNUSED_IDLE &&
1598 (error != OK && error != ERR_CONNECTION_RESET)) ||
1599 header_buf_len_) { // We have received some response headers.
1600 return false;
1601 }
1602 return true;
1603 }
1604
1605 void HttpNetworkTransaction::ResetConnectionAndRequestForResend() {
1606 connection_.socket()->Disconnect();
1607 connection_.Reset();
1608 // There are two reasons we need to clear request_headers_. 1) It contains
1609 // the real request headers, but we may need to resend the CONNECT request
1610 // first to recreate the SSL tunnel. 2) An empty request_headers_ causes
1611 // BuildRequestHeaders to be called, which rewinds request_body_stream_ to
1612 // the beginning of request_->upload_data.
1613 request_headers_->headers_.clear();
1614 request_headers_bytes_sent_ = 0;
1615 next_state_ = STATE_INIT_CONNECTION; // Resend the request.
1616 }
1617
1618 int HttpNetworkTransaction::ReconsiderProxyAfterError(int error) {
1619 DCHECK(!pac_request_);
1620
1621 // A failure to resolve the hostname or any error related to establishing a
1622 // TCP connection could be grounds for trying a new proxy configuration.
1623 //
1624 // Why do this when a hostname cannot be resolved? Some URLs only make sense
1625 // to proxy servers. The hostname in those URLs might fail to resolve if we
1626 // are still using a non-proxy config. We need to check if a proxy config
1627 // now exists that corresponds to a proxy server that could load the URL.
1628 //
1629 switch (error) {
1630 case ERR_NAME_NOT_RESOLVED:
1631 case ERR_INTERNET_DISCONNECTED:
1632 case ERR_ADDRESS_UNREACHABLE:
1633 case ERR_CONNECTION_CLOSED:
1634 case ERR_CONNECTION_RESET:
1635 case ERR_CONNECTION_REFUSED:
1636 case ERR_CONNECTION_ABORTED:
1637 case ERR_TIMED_OUT:
1638 case ERR_TUNNEL_CONNECTION_FAILED:
1639 break;
1640 default:
1641 return error;
1642 }
1643
1644 if (request_->load_flags & LOAD_BYPASS_PROXY) {
1645 return error;
1646 }
1647
1648 int rv = session_->proxy_service()->ReconsiderProxyAfterError(
1649 request_->url, &proxy_info_, &io_callback_, &pac_request_, load_log_);
1650 if (rv == OK || rv == ERR_IO_PENDING) {
1651 // If the error was during connection setup, there is no socket to
1652 // disconnect.
1653 if (connection_.socket())
1654 connection_.socket()->Disconnect();
1655 connection_.Reset();
1656 DCHECK(!request_headers_bytes_sent_);
1657 next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
1658 } else {
1659 rv = error;
1660 }
1661
1662 return rv;
1663 }
1664
1665 bool HttpNetworkTransaction::ShouldApplyProxyAuth() const {
1666 return (proxy_mode_ == kHTTPProxy) || establishing_tunnel_;
1667 }
1668
1669 bool HttpNetworkTransaction::ShouldApplyServerAuth() const {
1670 return !establishing_tunnel_ &&
1671 !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA);
1672 }
1673
1674 std::string HttpNetworkTransaction::BuildAuthorizationHeader(
1675 HttpAuth::Target target) const {
1676 DCHECK(HaveAuth(target));
1677
1678 // Add a Authorization/Proxy-Authorization header line.
1679 std::string credentials = auth_handler_[target]->GenerateCredentials(
1680 auth_identity_[target].username,
1681 auth_identity_[target].password,
1682 request_,
1683 &proxy_info_);
1684
1685 return HttpAuth::GetAuthorizationHeaderName(target) +
1686 ": " + credentials + "\r\n";
1687 }
1688
1689 GURL HttpNetworkTransaction::AuthOrigin(HttpAuth::Target target) const {
1690 return target == HttpAuth::AUTH_PROXY ?
1691 GURL("http://" + proxy_info_.proxy_server().host_and_port()) :
1692 request_->url.GetOrigin();
1693 }
1694
1695 std::string HttpNetworkTransaction::AuthPath(HttpAuth::Target target)
1696 const {
1697 // Proxy authentication realms apply to all paths. So we will use
1698 // empty string in place of an absolute path.
1699 return target == HttpAuth::AUTH_PROXY ?
1700 std::string() : request_->url.path();
1701 }
1702
1703 // static
1704 std::string HttpNetworkTransaction::AuthTargetString(
1705 HttpAuth::Target target) {
1706 return target == HttpAuth::AUTH_PROXY ? "proxy" : "server";
1707 }
1708
1709 void HttpNetworkTransaction::InvalidateRejectedAuthFromCache(
1710 HttpAuth::Target target) {
1711 DCHECK(HaveAuth(target));
1712
1713 // TODO(eroman): this short-circuit can be relaxed. If the realm of
1714 // the preemptively used auth entry matches the realm of the subsequent
1715 // challenge, then we can invalidate the preemptively used entry.
1716 // Otherwise as-is we may send the failed credentials one extra time.
1717 if (auth_identity_[target].source == HttpAuth::IDENT_SRC_PATH_LOOKUP)
1718 return;
1719
1720 // Clear the cache entry for the identity we just failed on.
1721 // Note: we require the username/password to match before invalidating
1722 // since the entry in the cache may be newer than what we used last time.
1723 session_->auth_cache()->Remove(AuthOrigin(target),
1724 auth_handler_[target]->realm(),
1725 auth_identity_[target].username,
1726 auth_identity_[target].password);
1727 }
1728
1729 bool HttpNetworkTransaction::SelectPreemptiveAuth(HttpAuth::Target target) {
1730 DCHECK(!HaveAuth(target));
1731
1732 // Don't do preemptive authorization if the URL contains a username/password,
1733 // since we must first be challenged in order to use the URL's identity.
1734 if (request_->url.has_username())
1735 return false;
1736
1737 // SelectPreemptiveAuth() is on the critical path for each request, so it
1738 // is expected to be fast. LookupByPath() is fast in the common case, since
1739 // the number of http auth cache entries is expected to be very small.
1740 // (For most users in fact, it will be 0.)
1741
1742 HttpAuthCache::Entry* entry = session_->auth_cache()->LookupByPath(
1743 AuthOrigin(target), AuthPath(target));
1744
1745 // We don't support preemptive authentication for connection-based
1746 // authentication schemes because they can't reuse entry->handler().
1747 // Hopefully we can remove this limitation in the future.
1748 if (entry && !entry->handler()->is_connection_based()) {
1749 auth_identity_[target].source = HttpAuth::IDENT_SRC_PATH_LOOKUP;
1750 auth_identity_[target].invalid = false;
1751 auth_identity_[target].username = entry->username();
1752 auth_identity_[target].password = entry->password();
1753 auth_handler_[target] = entry->handler();
1754 return true;
1755 }
1756 return false;
1757 }
1758
1759 bool HttpNetworkTransaction::SelectNextAuthIdentityToTry(
1760 HttpAuth::Target target) {
1761 DCHECK(auth_handler_[target]);
1762 DCHECK(auth_identity_[target].invalid);
1763
1764 // Try to use the username/password encoded into the URL first.
1765 if (target == HttpAuth::AUTH_SERVER && request_->url.has_username() &&
1766 !embedded_identity_used_) {
1767 auth_identity_[target].source = HttpAuth::IDENT_SRC_URL;
1768 auth_identity_[target].invalid = false;
1769 // Extract the username:password from the URL.
1770 GetIdentityFromURL(request_->url,
1771 &auth_identity_[target].username,
1772 &auth_identity_[target].password);
1773 embedded_identity_used_ = true;
1774 // TODO(eroman): If the password is blank, should we also try combining
1775 // with a password from the cache?
1776 return true;
1777 }
1778
1779 // Check the auth cache for a realm entry.
1780 HttpAuthCache::Entry* entry = session_->auth_cache()->LookupByRealm(
1781 AuthOrigin(target), auth_handler_[target]->realm());
1782
1783 if (entry) {
1784 // Disallow re-using of identity if the scheme of the originating challenge
1785 // does not match. This protects against the following situation:
1786 // 1. Browser prompts user to sign into DIGEST realm="Foo".
1787 // 2. Since the auth-scheme is not BASIC, the user is reasured that it
1788 // will not be sent over the wire in clear text. So they use their
1789 // most trusted password.
1790 // 3. Next, the browser receives a challenge for BASIC realm="Foo". This
1791 // is the same realm that we have a cached identity for. However if
1792 // we use that identity, it would get sent over the wire in
1793 // clear text (which isn't what the user agreed to when entering it).
1794 if (entry->handler()->scheme() != auth_handler_[target]->scheme()) {
1795 LOG(WARNING) << "The scheme of realm " << auth_handler_[target]->realm()
1796 << " has changed from " << entry->handler()->scheme()
1797 << " to " << auth_handler_[target]->scheme();
1798 return false;
1799 }
1800
1801 auth_identity_[target].source = HttpAuth::IDENT_SRC_REALM_LOOKUP;
1802 auth_identity_[target].invalid = false;
1803 auth_identity_[target].username = entry->username();
1804 auth_identity_[target].password = entry->password();
1805 return true;
1806 }
1807 return false;
1808 }
1809
1810 std::string HttpNetworkTransaction::AuthChallengeLogMessage() const {
1811 std::string msg;
1812 std::string header_val;
1813 void* iter = NULL;
1814 while (response_.headers->EnumerateHeader(&iter, "proxy-authenticate",
1815 &header_val)) {
1816 msg.append("\n Has header Proxy-Authenticate: ");
1817 msg.append(header_val);
1818 }
1819
1820 iter = NULL;
1821 while (response_.headers->EnumerateHeader(&iter, "www-authenticate",
1822 &header_val)) {
1823 msg.append("\n Has header WWW-Authenticate: ");
1824 msg.append(header_val);
1825 }
1826
1827 // RFC 4559 requires that a proxy indicate its support of NTLM/Negotiate
1828 // authentication with a "Proxy-Support: Session-Based-Authentication"
1829 // response header.
1830 iter = NULL;
1831 while (response_.headers->EnumerateHeader(&iter, "proxy-support",
1832 &header_val)) {
1833 msg.append("\n Has header Proxy-Support: ");
1834 msg.append(header_val);
1835 }
1836
1837 return msg;
1838 }
1839
1840 int HttpNetworkTransaction::HandleAuthChallenge() {
1841 DCHECK(response_.headers);
1842
1843 int status = response_.headers->response_code();
1844 if (status != 401 && status != 407)
1845 return OK;
1846 HttpAuth::Target target = status == 407 ?
1847 HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER;
1848
1849 LOG(INFO) << "The " << AuthTargetString(target) << " "
1850 << AuthOrigin(target) << " requested auth"
1851 << AuthChallengeLogMessage();
1852
1853 if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct())
1854 return ERR_UNEXPECTED_PROXY_AUTH;
1855
1856 // The auth we tried just failed, hence it can't be valid. Remove it from
1857 // the cache so it won't be used again.
1858 // TODO(wtc): IsFinalRound is not the right condition. In a multi-round
1859 // auth sequence, the server may fail the auth in round 1 if our first
1860 // authorization header is broken. We should inspect response_.headers to
1861 // determine if the server already failed the auth or wants us to continue.
1862 // See http://crbug.com/21015.
1863 if (HaveAuth(target) && auth_handler_[target]->IsFinalRound()) {
1864 InvalidateRejectedAuthFromCache(target);
1865 auth_handler_[target] = NULL;
1866 auth_identity_[target] = HttpAuth::Identity();
1867 }
1868
1869 auth_identity_[target].invalid = true;
1870
1871 if (target != HttpAuth::AUTH_SERVER ||
1872 !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA)) {
1873 // Find the best authentication challenge that we support.
1874 HttpAuth::ChooseBestChallenge(response_.headers.get(),
1875 target,
1876 AuthOrigin(target),
1877 &auth_handler_[target]);
1878 }
1879
1880 if (!auth_handler_[target]) {
1881 if (establishing_tunnel_) {
1882 LOG(ERROR) << "Can't perform auth to the " << AuthTargetString(target)
1883 << " " << AuthOrigin(target)
1884 << " when establishing a tunnel"
1885 << AuthChallengeLogMessage();
1886
1887 // We are establishing a tunnel, we can't show the error page because an
1888 // active network attacker could control its contents. Instead, we just
1889 // fail to establish the tunnel.
1890 DCHECK(target == HttpAuth::AUTH_PROXY);
1891 return ERR_PROXY_AUTH_REQUESTED;
1892 }
1893 // We found no supported challenge -- let the transaction continue
1894 // so we end up displaying the error page.
1895 return OK;
1896 }
1897
1898 if (auth_handler_[target]->NeedsIdentity()) {
1899 // Pick a new auth identity to try, by looking to the URL and auth cache.
1900 // If an identity to try is found, it is saved to auth_identity_[target].
1901 SelectNextAuthIdentityToTry(target);
1902 } else {
1903 // Proceed with the existing identity or a null identity.
1904 //
1905 // TODO(wtc): Add a safeguard against infinite transaction restarts, if
1906 // the server keeps returning "NTLM".
1907 auth_identity_[target].invalid = false;
1908 }
1909
1910 // Make a note that we are waiting for auth. This variable is inspected
1911 // when the client calls RestartWithAuth() to pick up where we left off.
1912 pending_auth_target_ = target;
1913
1914 if (auth_identity_[target].invalid) {
1915 // We have exhausted all identity possibilities, all we can do now is
1916 // pass the challenge information back to the client.
1917 PopulateAuthChallenge(target);
1918 }
1919 return OK;
1920 }
1921
1922 void HttpNetworkTransaction::PopulateAuthChallenge(HttpAuth::Target target) {
1923 // Populates response_.auth_challenge with the authentication challenge info.
1924 // This info is consumed by URLRequestHttpJob::GetAuthChallengeInfo().
1925
1926 AuthChallengeInfo* auth_info = new AuthChallengeInfo;
1927 auth_info->is_proxy = target == HttpAuth::AUTH_PROXY;
1928 auth_info->host_and_port = ASCIIToWide(GetHostAndPort(AuthOrigin(target)));
1929 auth_info->scheme = ASCIIToWide(auth_handler_[target]->scheme());
1930 // TODO(eroman): decode realm according to RFC 2047.
1931 auth_info->realm = ASCIIToWide(auth_handler_[target]->realm());
1932 response_.auth_challenge = auth_info;
1933 } 510 }
1934 511
1935 } // namespace net 512 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_stream_parser.h ('k') | net/net.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698