summaryrefslogtreecommitdiffstats
path: root/net/url_request/url_request_job.cc
diff options
context:
space:
mode:
authordarin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-23 19:10:23 +0000
committerdarin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-23 19:10:23 +0000
commit195e77d6f2d2f615c2a5138750db124853c0a093 (patch)
treee1ea14d75832faa10ca8951e82c44a1e4b1a03ab /net/url_request/url_request_job.cc
parent35350e871b173b3daa1e6e9921e1930ecc9331c4 (diff)
downloadchromium_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.cc52
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_);