| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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), |
| 33 filter_input_byte_count_(0) { | 32 filter_input_byte_count_(0) , |
| 33 deferred_redirect_status_code_(-1) { |
| 34 load_flags_ = request_->load_flags(); | 34 load_flags_ = request_->load_flags(); |
| 35 is_profiling_ = request->enable_profiling(); | 35 is_profiling_ = request->enable_profiling(); |
| 36 if (is_profiling()) { | 36 if (is_profiling()) { |
| 37 metrics_.reset(new URLRequestJobMetrics()); | 37 metrics_.reset(new URLRequestJobMetrics()); |
| 38 metrics_->start_time_ = TimeTicks::Now(); | 38 metrics_->start_time_ = TimeTicks::Now(); |
| 39 } | 39 } |
| 40 g_url_request_job_tracker.AddNewJob(this); | 40 g_url_request_job_tracker.AddNewJob(this); |
| 41 } | 41 } |
| 42 | 42 |
| 43 URLRequestJob::~URLRequestJob() { | 43 URLRequestJob::~URLRequestJob() { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 NOTREACHED(); | 86 NOTREACHED(); |
| 87 } | 87 } |
| 88 | 88 |
| 89 void URLRequestJob::ContinueDespiteLastError() { | 89 void URLRequestJob::ContinueDespiteLastError() { |
| 90 // Implementations should know how to recover from errors they generate. | 90 // Implementations should know how to recover from errors they generate. |
| 91 // If this code was reached, we are trying to recover from an error that | 91 // If this code was reached, we are trying to recover from an error that |
| 92 // we don't know how to recover from. | 92 // we don't know how to recover from. |
| 93 NOTREACHED(); | 93 NOTREACHED(); |
| 94 } | 94 } |
| 95 | 95 |
| 96 void URLRequestJob::FollowDeferredRedirect() { |
| 97 DCHECK(deferred_redirect_status_code_ != -1); |
| 98 // NOTE: deferred_redirect_url_ may be invalid, and attempting to redirect to |
| 99 // such an URL will fail inside FollowRedirect. The DCHECK above asserts |
| 100 // that we called OnReceivedRedirect. |
| 101 |
| 102 FollowRedirect(deferred_redirect_url_, deferred_redirect_status_code_); |
| 103 deferred_redirect_url_ = GURL(); |
| 104 deferred_redirect_status_code_ = -1; |
| 105 } |
| 106 |
| 96 int64 URLRequestJob::GetByteReadCount() const { | 107 int64 URLRequestJob::GetByteReadCount() const { |
| 97 return filter_input_byte_count_ ; | 108 return filter_input_byte_count_ ; |
| 98 } | 109 } |
| 99 | 110 |
| 100 bool URLRequestJob::GetURL(GURL* gurl) const { | 111 bool URLRequestJob::GetURL(GURL* gurl) const { |
| 101 if (!request_) | 112 if (!request_) |
| 102 return false; | 113 return false; |
| 103 *gurl = request_->url(); | 114 *gurl = request_->url(); |
| 104 return true; | 115 return true; |
| 105 } | 116 } |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 if (!filter_->stream_data_len() && !is_done()) { | 175 if (!filter_->stream_data_len() && !is_done()) { |
| 165 net::IOBuffer* stream_buffer = filter_->stream_buffer(); | 176 net::IOBuffer* stream_buffer = filter_->stream_buffer(); |
| 166 int stream_buffer_size = filter_->stream_buffer_size(); | 177 int stream_buffer_size = filter_->stream_buffer_size(); |
| 167 rv = ReadRawData(stream_buffer, stream_buffer_size, bytes_read); | 178 rv = ReadRawData(stream_buffer, stream_buffer_size, bytes_read); |
| 168 if (rv && *bytes_read > 0) | 179 if (rv && *bytes_read > 0) |
| 169 RecordBytesRead(*bytes_read); | 180 RecordBytesRead(*bytes_read); |
| 170 } | 181 } |
| 171 return rv; | 182 return rv; |
| 172 } | 183 } |
| 173 | 184 |
| 185 void URLRequestJob::FollowRedirect(const GURL& location, int http_status_code) { |
| 186 g_url_request_job_tracker.OnJobRedirect(this, location, http_status_code); |
| 187 |
| 188 int rv = request_->Redirect(location, http_status_code); |
| 189 if (rv != net::OK) |
| 190 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); |
| 191 } |
| 192 |
| 174 void URLRequestJob::FilteredDataRead(int bytes_read) { | 193 void URLRequestJob::FilteredDataRead(int bytes_read) { |
| 175 DCHECK(filter_.get()); // don't add data if there is no filter | 194 DCHECK(filter_.get()); // don't add data if there is no filter |
| 176 filter_->FlushStreamBuffer(bytes_read); | 195 filter_->FlushStreamBuffer(bytes_read); |
| 177 } | 196 } |
| 178 | 197 |
| 179 bool URLRequestJob::ReadFilteredData(int *bytes_read) { | 198 bool URLRequestJob::ReadFilteredData(int *bytes_read) { |
| 180 DCHECK(filter_.get()); // don't add data if there is no filter | 199 DCHECK(filter_.get()); // don't add data if there is no filter |
| 181 DCHECK(read_buffer_ != NULL); // we need to have a buffer to fill | 200 DCHECK(read_buffer_ != NULL); // we need to have a buffer to fill |
| 182 DCHECK(read_buffer_len_ > 0); // sanity check | 201 DCHECK(read_buffer_len_ > 0); // sanity check |
| 183 DCHECK(read_buffer_len_ < 1000000); // sanity check | 202 DCHECK(read_buffer_len_ < 1000000); // sanity check |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 request_->response_info_.response_time = Time::Now(); | 330 request_->response_info_.response_time = Time::Now(); |
| 312 GetResponseInfo(&request_->response_info_); | 331 GetResponseInfo(&request_->response_info_); |
| 313 | 332 |
| 314 // When notifying the delegate, the delegate can release the request | 333 // When notifying the delegate, the delegate can release the request |
| 315 // (and thus release 'this'). After calling to the delgate, we must | 334 // (and thus release 'this'). After calling to the delgate, we must |
| 316 // check the request pointer to see if it still exists, and return | 335 // check the request pointer to see if it still exists, and return |
| 317 // immediately if it has been destroyed. self_preservation ensures our | 336 // immediately if it has been destroyed. self_preservation ensures our |
| 318 // survival until we can get out of this method. | 337 // survival until we can get out of this method. |
| 319 scoped_refptr<URLRequestJob> self_preservation = this; | 338 scoped_refptr<URLRequestJob> self_preservation = this; |
| 320 | 339 |
| 340 GURL new_location; |
| 321 int http_status_code; | 341 int http_status_code; |
| 322 GURL new_location; | |
| 323 if (IsRedirectResponse(&new_location, &http_status_code)) { | 342 if (IsRedirectResponse(&new_location, &http_status_code)) { |
| 324 const GURL& url = request_->url(); | 343 const GURL& url = request_->url(); |
| 325 | 344 |
| 326 // Move the reference fragment of the old location to the new one if the | 345 // Move the reference fragment of the old location to the new one if the |
| 327 // new one has none. This duplicates mozilla's behavior. | 346 // new one has none. This duplicates mozilla's behavior. |
| 328 if (url.is_valid() && url.has_ref() && !new_location.has_ref()) { | 347 if (url.is_valid() && url.has_ref() && !new_location.has_ref()) { |
| 329 GURL::Replacements replacements; | 348 GURL::Replacements replacements; |
| 330 // Reference the |ref| directly out of the original URL to avoid a | 349 // Reference the |ref| directly out of the original URL to avoid a |
| 331 // malloc. | 350 // malloc. |
| 332 replacements.SetRef(url.spec().data(), | 351 replacements.SetRef(url.spec().data(), |
| 333 url.parsed_for_possibly_invalid_spec().ref); | 352 url.parsed_for_possibly_invalid_spec().ref); |
| 334 new_location = new_location.ReplaceComponents(replacements); | 353 new_location = new_location.ReplaceComponents(replacements); |
| 335 } | 354 } |
| 336 | 355 |
| 337 // Toggle this flag to true so the consumer can access response headers. | 356 bool defer_redirect = false; |
| 338 // Then toggle it back if we choose to follow the redirect. | 357 request_->ReceivedRedirect(new_location, &defer_redirect); |
| 339 has_handled_response_ = true; | |
| 340 request_->delegate()->OnReceivedRedirect(request_, new_location); | |
| 341 | 358 |
| 342 // Ensure that the request wasn't destroyed in OnReceivedRedirect | 359 // Ensure that the request wasn't destroyed in OnReceivedRedirect |
| 343 if (!request_ || !request_->delegate()) | 360 if (!request_ || !request_->delegate()) |
| 344 return; | 361 return; |
| 345 | 362 |
| 346 // If we were not cancelled, then follow the redirect. | 363 // If we were not cancelled, then maybe follow the redirect. |
| 347 if (request_->status().is_success()) { | 364 if (request_->status().is_success()) { |
| 348 has_handled_response_ = false; | 365 if (defer_redirect) { |
| 349 FollowRedirect(new_location, http_status_code); | 366 deferred_redirect_url_ = new_location; |
| 367 deferred_redirect_status_code_ = http_status_code; |
| 368 } else { |
| 369 FollowRedirect(new_location, http_status_code); |
| 370 } |
| 350 return; | 371 return; |
| 351 } | 372 } |
| 352 } else if (NeedsAuth()) { | 373 } else if (NeedsAuth()) { |
| 353 scoped_refptr<net::AuthChallengeInfo> auth_info; | 374 scoped_refptr<net::AuthChallengeInfo> auth_info; |
| 354 GetAuthChallengeInfo(&auth_info); | 375 GetAuthChallengeInfo(&auth_info); |
| 355 // Need to check for a NULL auth_info because the server may have failed | 376 // Need to check for a NULL auth_info because the server may have failed |
| 356 // to send a challenge with the 401 response. | 377 // to send a challenge with the 401 response. |
| 357 if (auth_info) { | 378 if (auth_info) { |
| 358 request_->delegate()->OnAuthRequired(request_, auth_info); | 379 request_->delegate()->OnAuthRequired(request_, auth_info); |
| 359 // Wait for SetAuth or CancelAuth to be called. | 380 // Wait for SetAuth or CancelAuth to be called. |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 491 if (!done_) { | 512 if (!done_) { |
| 492 NotifyDone(URLRequestStatus(URLRequestStatus::CANCELED, | 513 NotifyDone(URLRequestStatus(URLRequestStatus::CANCELED, |
| 493 net::ERR_ABORTED)); | 514 net::ERR_ABORTED)); |
| 494 } | 515 } |
| 495 } | 516 } |
| 496 | 517 |
| 497 bool URLRequestJob::FilterHasData() { | 518 bool URLRequestJob::FilterHasData() { |
| 498 return filter_.get() && filter_->stream_data_len(); | 519 return filter_.get() && filter_->stream_data_len(); |
| 499 } | 520 } |
| 500 | 521 |
| 501 void URLRequestJob::FollowRedirect(const GURL& location, | |
| 502 int http_status_code) { | |
| 503 g_url_request_job_tracker.OnJobRedirect(this, location, http_status_code); | |
| 504 Kill(); | |
| 505 // Kill could have notified the Delegate and destroyed the request. | |
| 506 if (!request_) | |
| 507 return; | |
| 508 | |
| 509 int rv = request_->Redirect(location, http_status_code); | |
| 510 if (rv != net::OK) | |
| 511 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, rv)); | |
| 512 } | |
| 513 | |
| 514 void URLRequestJob::RecordBytesRead(int bytes_read) { | 522 void URLRequestJob::RecordBytesRead(int bytes_read) { |
| 515 if (is_profiling()) { | 523 if (is_profiling()) { |
| 516 ++(metrics_->number_of_read_IO_); | 524 ++(metrics_->number_of_read_IO_); |
| 517 metrics_->total_bytes_read_ += bytes_read; | 525 metrics_->total_bytes_read_ += bytes_read; |
| 518 } | 526 } |
| 519 filter_input_byte_count_ += bytes_read; | 527 filter_input_byte_count_ += bytes_read; |
| 520 g_url_request_job_tracker.OnBytesRead(this, bytes_read); | 528 g_url_request_job_tracker.OnBytesRead(this, bytes_read); |
| 521 } | 529 } |
| 522 | 530 |
| 523 const URLRequestStatus URLRequestJob::GetStatus() { | 531 const URLRequestStatus URLRequestJob::GetStatus() { |
| 524 if (request_) | 532 if (request_) |
| 525 return request_->status(); | 533 return request_->status(); |
| 526 // If the request is gone, we must be cancelled. | 534 // If the request is gone, we must be cancelled. |
| 527 return URLRequestStatus(URLRequestStatus::CANCELED, | 535 return URLRequestStatus(URLRequestStatus::CANCELED, |
| 528 net::ERR_ABORTED); | 536 net::ERR_ABORTED); |
| 529 } | 537 } |
| 530 | 538 |
| 531 void URLRequestJob::SetStatus(const URLRequestStatus &status) { | 539 void URLRequestJob::SetStatus(const URLRequestStatus &status) { |
| 532 if (request_) | 540 if (request_) |
| 533 request_->set_status(status); | 541 request_->set_status(status); |
| 534 } | 542 } |
| OLD | NEW |