OLD | NEW |
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/url_request/url_request_job.h" | 5 #include "net/url_request/url_request_job.h" |
6 | 6 |
7 #include "base/message_loop.h" | 7 #include "base/message_loop.h" |
8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
9 #include "googleurl/src/gurl.h" | |
10 #include "net/base/auth.h" | 9 #include "net/base/auth.h" |
11 #include "net/base/io_buffer.h" | 10 #include "net/base/io_buffer.h" |
12 #include "net/base/load_flags.h" | 11 #include "net/base/load_flags.h" |
13 #include "net/base/net_errors.h" | 12 #include "net/base/net_errors.h" |
14 #include "net/url_request/url_request.h" | 13 #include "net/url_request/url_request.h" |
15 #include "net/url_request/url_request_job_metrics.h" | 14 #include "net/url_request/url_request_job_metrics.h" |
16 #include "net/url_request/url_request_job_tracker.h" | 15 #include "net/url_request/url_request_job_tracker.h" |
17 | 16 |
18 using base::Time; | 17 using base::Time; |
19 using base::TimeTicks; | 18 using base::TimeTicks; |
20 | 19 |
21 // Buffer size allocated when de-compressing data. | 20 // Buffer size allocated when de-compressing data. |
22 // static | 21 // static |
23 const int URLRequestJob::kFilterBufSize = 32 * 1024; | 22 const int URLRequestJob::kFilterBufSize = 32 * 1024; |
24 | 23 |
25 URLRequestJob::URLRequestJob(URLRequest* request) | 24 URLRequestJob::URLRequestJob(URLRequest* request) |
26 : request_(request), | 25 : request_(request), |
27 done_(false), | 26 done_(false), |
28 filter_needs_more_output_space_(false), | 27 filter_needs_more_output_space_(false), |
29 read_buffer_(NULL), | 28 read_buffer_(NULL), |
30 read_buffer_len_(0), | 29 read_buffer_len_(0), |
31 has_handled_response_(false), | 30 has_handled_response_(false), |
32 expected_content_size_(-1), | 31 expected_content_size_(-1), |
| 32 deferred_redirect_status_code_(-1), |
33 packet_timing_enabled_(false), | 33 packet_timing_enabled_(false), |
34 filter_input_byte_count_(0), | 34 filter_input_byte_count_(0), |
35 bytes_observed_in_packets_(0), | 35 bytes_observed_in_packets_(0), |
36 max_packets_timed_(0), | 36 max_packets_timed_(0), |
37 observed_packet_count_(0) { | 37 observed_packet_count_(0) { |
38 load_flags_ = request_->load_flags(); | 38 load_flags_ = request_->load_flags(); |
39 is_profiling_ = request->enable_profiling(); | 39 is_profiling_ = request->enable_profiling(); |
40 if (is_profiling()) { | 40 if (is_profiling()) { |
41 metrics_.reset(new URLRequestJobMetrics()); | 41 metrics_.reset(new URLRequestJobMetrics()); |
42 metrics_->start_time_ = TimeTicks::Now(); | 42 metrics_->start_time_ = TimeTicks::Now(); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 NOTREACHED(); | 96 NOTREACHED(); |
97 } | 97 } |
98 | 98 |
99 void URLRequestJob::ContinueDespiteLastError() { | 99 void URLRequestJob::ContinueDespiteLastError() { |
100 // Implementations should know how to recover from errors they generate. | 100 // Implementations should know how to recover from errors they generate. |
101 // If this code was reached, we are trying to recover from an error that | 101 // If this code was reached, we are trying to recover from an error that |
102 // we don't know how to recover from. | 102 // we don't know how to recover from. |
103 NOTREACHED(); | 103 NOTREACHED(); |
104 } | 104 } |
105 | 105 |
| 106 void URLRequestJob::FollowDeferredRedirect() { |
| 107 DCHECK(deferred_redirect_status_code_ != -1); |
| 108 // NOTE: deferred_redirect_url_ may be invalid, and attempting to redirect to |
| 109 // such an URL will fail inside FollowRedirect. The DCHECK above asserts |
| 110 // that we called OnReceivedRedirect. |
| 111 |
| 112 FollowRedirect(deferred_redirect_url_, deferred_redirect_status_code_); |
| 113 deferred_redirect_url_ = GURL(); |
| 114 deferred_redirect_status_code_ = -1; |
| 115 } |
| 116 |
106 int64 URLRequestJob::GetByteReadCount() const { | 117 int64 URLRequestJob::GetByteReadCount() const { |
107 return filter_input_byte_count_; | 118 return filter_input_byte_count_; |
108 } | 119 } |
109 | 120 |
110 bool URLRequestJob::GetURL(GURL* gurl) const { | 121 bool URLRequestJob::GetURL(GURL* gurl) const { |
111 if (!request_) | 122 if (!request_) |
112 return false; | 123 return false; |
113 *gurl = request_->url(); | 124 *gurl = request_->url(); |
114 return true; | 125 return true; |
115 } | 126 } |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 request_->response_info_.response_time = Time::Now(); | 326 request_->response_info_.response_time = Time::Now(); |
316 GetResponseInfo(&request_->response_info_); | 327 GetResponseInfo(&request_->response_info_); |
317 | 328 |
318 // When notifying the delegate, the delegate can release the request | 329 // When notifying the delegate, the delegate can release the request |
319 // (and thus release 'this'). After calling to the delgate, we must | 330 // (and thus release 'this'). After calling to the delgate, we must |
320 // check the request pointer to see if it still exists, and return | 331 // check the request pointer to see if it still exists, and return |
321 // immediately if it has been destroyed. self_preservation ensures our | 332 // immediately if it has been destroyed. self_preservation ensures our |
322 // survival until we can get out of this method. | 333 // survival until we can get out of this method. |
323 scoped_refptr<URLRequestJob> self_preservation = this; | 334 scoped_refptr<URLRequestJob> self_preservation = this; |
324 | 335 |
| 336 GURL new_location; |
325 int http_status_code; | 337 int http_status_code; |
326 GURL new_location; | |
327 if (IsRedirectResponse(&new_location, &http_status_code)) { | 338 if (IsRedirectResponse(&new_location, &http_status_code)) { |
328 const GURL& url = request_->url(); | 339 const GURL& url = request_->url(); |
329 | 340 |
330 // Move the reference fragment of the old location to the new one if the | 341 // Move the reference fragment of the old location to the new one if the |
331 // new one has none. This duplicates mozilla's behavior. | 342 // new one has none. This duplicates mozilla's behavior. |
332 if (url.is_valid() && url.has_ref() && !new_location.has_ref()) { | 343 if (url.is_valid() && url.has_ref() && !new_location.has_ref()) { |
333 GURL::Replacements replacements; | 344 GURL::Replacements replacements; |
334 // Reference the |ref| directly out of the original URL to avoid a | 345 // Reference the |ref| directly out of the original URL to avoid a |
335 // malloc. | 346 // malloc. |
336 replacements.SetRef(url.spec().data(), | 347 replacements.SetRef(url.spec().data(), |
337 url.parsed_for_possibly_invalid_spec().ref); | 348 url.parsed_for_possibly_invalid_spec().ref); |
338 new_location = new_location.ReplaceComponents(replacements); | 349 new_location = new_location.ReplaceComponents(replacements); |
339 } | 350 } |
340 | 351 |
341 // Toggle this flag to true so the consumer can access response headers. | 352 bool defer_redirect = false; |
342 // Then toggle it back if we choose to follow the redirect. | 353 request_->ReceivedRedirect(new_location, &defer_redirect); |
343 has_handled_response_ = true; | |
344 request_->ReceivedRedirect(new_location); | |
345 | 354 |
346 // Ensure that the request wasn't detached or destroyed in ReceivedRedirect | 355 // Ensure that the request wasn't detached or destroyed in ReceivedRedirect |
347 if (!request_ || !request_->delegate()) | 356 if (!request_ || !request_->delegate()) |
348 return; | 357 return; |
349 | 358 |
350 // If we were not cancelled, then follow the redirect. | 359 // If we were not cancelled, then maybe follow the redirect. |
351 if (request_->status().is_success()) { | 360 if (request_->status().is_success()) { |
352 has_handled_response_ = false; | 361 if (defer_redirect) { |
353 FollowRedirect(new_location, http_status_code); | 362 deferred_redirect_url_ = new_location; |
| 363 deferred_redirect_status_code_ = http_status_code; |
| 364 } else { |
| 365 FollowRedirect(new_location, http_status_code); |
| 366 } |
354 return; | 367 return; |
355 } | 368 } |
356 } else if (NeedsAuth()) { | 369 } else if (NeedsAuth()) { |
357 scoped_refptr<net::AuthChallengeInfo> auth_info; | 370 scoped_refptr<net::AuthChallengeInfo> auth_info; |
358 GetAuthChallengeInfo(&auth_info); | 371 GetAuthChallengeInfo(&auth_info); |
359 // Need to check for a NULL auth_info because the server may have failed | 372 // Need to check for a NULL auth_info because the server may have failed |
360 // to send a challenge with the 401 response. | 373 // to send a challenge with the 401 response. |
361 if (auth_info) { | 374 if (auth_info) { |
362 request_->delegate()->OnAuthRequired(request_, auth_info); | 375 request_->delegate()->OnAuthRequired(request_, auth_info); |
363 // Wait for SetAuth or CancelAuth to be called. | 376 // Wait for SetAuth or CancelAuth to be called. |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
500 void URLRequestJob::NotifyRestartRequired() { | 513 void URLRequestJob::NotifyRestartRequired() { |
501 DCHECK(!has_handled_response_); | 514 DCHECK(!has_handled_response_); |
502 if (GetStatus().status() != URLRequestStatus::CANCELED) | 515 if (GetStatus().status() != URLRequestStatus::CANCELED) |
503 request_->Restart(); | 516 request_->Restart(); |
504 } | 517 } |
505 | 518 |
506 bool URLRequestJob::FilterHasData() { | 519 bool URLRequestJob::FilterHasData() { |
507 return filter_.get() && filter_->stream_data_len(); | 520 return filter_.get() && filter_->stream_data_len(); |
508 } | 521 } |
509 | 522 |
510 void URLRequestJob::FollowRedirect(const GURL& location, | |
511 int http_status_code) { | |
512 g_url_request_job_tracker.OnJobRedirect(this, location, http_status_code); | |
513 Kill(); | |
514 // Kill could have notified the Delegate and destroyed the request. | |
515 if (!request_) | |
516 return; | |
517 | |
518 int rv = request_->Redirect(location, http_status_code); | |
519 if (rv != net::OK) | |
520 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, rv)); | |
521 } | |
522 | |
523 void URLRequestJob::RecordBytesRead(int bytes_read) { | 523 void URLRequestJob::RecordBytesRead(int bytes_read) { |
524 if (is_profiling()) { | 524 if (is_profiling()) { |
525 ++(metrics_->number_of_read_IO_); | 525 ++(metrics_->number_of_read_IO_); |
526 metrics_->total_bytes_read_ += bytes_read; | 526 metrics_->total_bytes_read_ += bytes_read; |
527 } | 527 } |
528 filter_input_byte_count_ += bytes_read; | 528 filter_input_byte_count_ += bytes_read; |
529 UpdatePacketReadTimes(); // Facilitate stats recording if it is active. | 529 UpdatePacketReadTimes(); // Facilitate stats recording if it is active. |
530 g_url_request_job_tracker.OnBytesRead(this, bytes_read); | 530 g_url_request_job_tracker.OnBytesRead(this, bytes_read); |
531 } | 531 } |
532 | 532 |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
703 packet_times_[4] - packet_times_[3], | 703 packet_times_[4] - packet_times_[3], |
704 base::TimeDelta::FromMilliseconds(1), | 704 base::TimeDelta::FromMilliseconds(1), |
705 base::TimeDelta::FromSeconds(10), 100); | 705 base::TimeDelta::FromSeconds(10), 100); |
706 return; | 706 return; |
707 } | 707 } |
708 default: | 708 default: |
709 NOTREACHED(); | 709 NOTREACHED(); |
710 return; | 710 return; |
711 } | 711 } |
712 } | 712 } |
| 713 |
| 714 void URLRequestJob::FollowRedirect(const GURL& location, int http_status_code) { |
| 715 g_url_request_job_tracker.OnJobRedirect(this, location, http_status_code); |
| 716 |
| 717 int rv = request_->Redirect(location, http_status_code); |
| 718 if (rv != net::OK) |
| 719 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); |
| 720 } |
OLD | NEW |