diff options
author | darin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-23 19:10:23 +0000 |
---|---|---|
committer | darin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-23 19:10:23 +0000 |
commit | 195e77d6f2d2f615c2a5138750db124853c0a093 (patch) | |
tree | e1ea14d75832faa10ca8951e82c44a1e4b1a03ab /net/url_request/url_request_job.cc | |
parent | 35350e871b173b3daa1e6e9921e1930ecc9331c4 (diff) | |
download | chromium_src-195e77d6f2d2f615c2a5138750db124853c0a093.zip chromium_src-195e77d6f2d2f615c2a5138750db124853c0a093.tar.gz chromium_src-195e77d6f2d2f615c2a5138750db124853c0a093.tar.bz2 |
Add support to URLRequest for deferring redirects.
I chose to add an out parameter to OnReceivedRedirect because it allows for the
default behavior to remain the same.
I considered adding a ContinueAfterRedirect method that all OnReceivedRedirect
implementations would need to call, but this caused one annoying problem: In
the case of a ChromePlugin, it is possible for the URLRequest to get deleted
inside the handler for the redirect. This would make it hard to subsequently
call a method on the URLRequest since I would need to have a way to determine
if the URLRequest had been deleted.
TEST=covered by unit tests
BUG=16413,6442
R=eroman,wtc
Review URL: http://codereview.chromium.org/155897
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@21417 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/url_request/url_request_job.cc')
-rw-r--r-- | net/url_request/url_request_job.cc | 52 |
1 files changed, 30 insertions, 22 deletions
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc index 797caa6..f9043cc 100644 --- a/net/url_request/url_request_job.cc +++ b/net/url_request/url_request_job.cc @@ -6,7 +6,6 @@ #include "base/message_loop.h" #include "base/string_util.h" -#include "googleurl/src/gurl.h" #include "net/base/auth.h" #include "net/base/io_buffer.h" #include "net/base/load_flags.h" @@ -30,6 +29,7 @@ URLRequestJob::URLRequestJob(URLRequest* request) read_buffer_len_(0), has_handled_response_(false), expected_content_size_(-1), + deferred_redirect_status_code_(-1), packet_timing_enabled_(false), filter_input_byte_count_(0), bytes_observed_in_packets_(0), @@ -103,6 +103,17 @@ void URLRequestJob::ContinueDespiteLastError() { NOTREACHED(); } +void URLRequestJob::FollowDeferredRedirect() { + DCHECK(deferred_redirect_status_code_ != -1); + // NOTE: deferred_redirect_url_ may be invalid, and attempting to redirect to + // such an URL will fail inside FollowRedirect. The DCHECK above asserts + // that we called OnReceivedRedirect. + + FollowRedirect(deferred_redirect_url_, deferred_redirect_status_code_); + deferred_redirect_url_ = GURL(); + deferred_redirect_status_code_ = -1; +} + int64 URLRequestJob::GetByteReadCount() const { return filter_input_byte_count_; } @@ -175,6 +186,14 @@ bool URLRequestJob::ReadRawDataForFilter(int *bytes_read) { return rv; } +void URLRequestJob::FollowRedirect(const GURL& location, int http_status_code) { + g_url_request_job_tracker.OnJobRedirect(this, location, http_status_code); + + int rv = request_->Redirect(location, http_status_code); + if (rv != net::OK) + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); +} + void URLRequestJob::FilteredDataRead(int bytes_read) { DCHECK(filter_.get()); // don't add data if there is no filter filter_->FlushStreamBuffer(bytes_read); @@ -322,8 +341,8 @@ void URLRequestJob::NotifyHeadersComplete() { // survival until we can get out of this method. scoped_refptr<URLRequestJob> self_preservation = this; - int http_status_code; GURL new_location; + int http_status_code; if (IsRedirectResponse(&new_location, &http_status_code)) { const GURL& url = request_->url(); @@ -338,19 +357,21 @@ void URLRequestJob::NotifyHeadersComplete() { new_location = new_location.ReplaceComponents(replacements); } - // Toggle this flag to true so the consumer can access response headers. - // Then toggle it back if we choose to follow the redirect. - has_handled_response_ = true; - request_->ReceivedRedirect(new_location); + bool defer_redirect = false; + request_->ReceivedRedirect(new_location, &defer_redirect); // Ensure that the request wasn't detached or destroyed in ReceivedRedirect if (!request_ || !request_->delegate()) return; - // If we were not cancelled, then follow the redirect. + // If we were not cancelled, then maybe follow the redirect. if (request_->status().is_success()) { - has_handled_response_ = false; - FollowRedirect(new_location, http_status_code); + if (defer_redirect) { + deferred_redirect_url_ = new_location; + deferred_redirect_status_code_ = http_status_code; + } else { + FollowRedirect(new_location, http_status_code); + } return; } } else if (NeedsAuth()) { @@ -507,19 +528,6 @@ bool URLRequestJob::FilterHasData() { return filter_.get() && filter_->stream_data_len(); } -void URLRequestJob::FollowRedirect(const GURL& location, - int http_status_code) { - g_url_request_job_tracker.OnJobRedirect(this, location, http_status_code); - Kill(); - // Kill could have notified the Delegate and destroyed the request. - if (!request_) - return; - - int rv = request_->Redirect(location, http_status_code); - if (rv != net::OK) - NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, rv)); -} - void URLRequestJob::RecordBytesRead(int bytes_read) { if (is_profiling()) { ++(metrics_->number_of_read_IO_); |