summaryrefslogtreecommitdiffstats
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
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
-rw-r--r--chrome/browser/chrome_plugin_host.cc3
-rw-r--r--chrome/browser/net/url_fetcher.cc2
-rw-r--r--chrome/browser/plugin_process_host.cc6
-rw-r--r--chrome/browser/renderer_host/resource_dispatcher_host.cc3
-rw-r--r--chrome/browser/renderer_host/resource_dispatcher_host.h3
-rw-r--r--chrome/common/chrome_plugin_unittest.cc2
-rw-r--r--net/proxy/proxy_script_fetcher.cc7
-rw-r--r--net/tools/testserver/testserver.py4
-rw-r--r--net/url_request/url_request.cc16
-rw-r--r--net/url_request/url_request.h21
-rw-r--r--net/url_request/url_request_job.cc52
-rw-r--r--net/url_request/url_request_job.h8
-rw-r--r--net/url_request/url_request_unittest.cc82
-rw-r--r--net/url_request/url_request_unittest.h12
-rw-r--r--webkit/tools/test_shell/simple_resource_loader_bridge.cc3
15 files changed, 166 insertions, 58 deletions
diff --git a/chrome/browser/chrome_plugin_host.cc b/chrome/browser/chrome_plugin_host.cc
index 4772769..75a2fc3 100644
--- a/chrome/browser/chrome_plugin_host.cc
+++ b/chrome/browser/chrome_plugin_host.cc
@@ -189,7 +189,8 @@ class PluginRequestHandler : public PluginHelper, public URLRequest::Delegate {
}
// URLRequest::Delegate
- virtual void OnReceivedRedirect(URLRequest* request, const GURL& new_url) {
+ virtual void OnReceivedRedirect(URLRequest* request, const GURL& new_url,
+ bool* defer_redirect) {
plugin_->functions().response_funcs->received_redirect(
cprequest_.get(), new_url.spec().c_str());
}
diff --git a/chrome/browser/net/url_fetcher.cc b/chrome/browser/net/url_fetcher.cc
index 4783aea8..03586eb 100644
--- a/chrome/browser/net/url_fetcher.cc
+++ b/chrome/browser/net/url_fetcher.cc
@@ -44,8 +44,6 @@ class URLFetcher::Core
void Stop();
// URLRequest::Delegate implementations
- virtual void OnReceivedRedirect(URLRequest* request,
- const GURL& new_url) { }
virtual void OnResponseStarted(URLRequest* request);
virtual void OnReadCompleted(URLRequest* request, int bytes_read);
diff --git a/chrome/browser/plugin_process_host.cc b/chrome/browser/plugin_process_host.cc
index fe9addf..f03b42f 100644
--- a/chrome/browser/plugin_process_host.cc
+++ b/chrome/browser/plugin_process_host.cc
@@ -82,8 +82,6 @@ class PluginDownloadUrlHelper : public URLRequest::Delegate {
void InitiateDownload();
// URLRequest::Delegate
- virtual void OnReceivedRedirect(URLRequest* request,
- const GURL& new_url);
virtual void OnAuthRequired(URLRequest* request,
net::AuthChallengeInfo* auth_info);
virtual void OnSSLCertificateError(URLRequest* request,
@@ -143,10 +141,6 @@ void PluginDownloadUrlHelper::InitiateDownload() {
download_file_request_->Start();
}
-void PluginDownloadUrlHelper::OnReceivedRedirect(URLRequest* request,
- const GURL& new_url) {
-}
-
void PluginDownloadUrlHelper::OnAuthRequired(
URLRequest* request,
net::AuthChallengeInfo* auth_info) {
diff --git a/chrome/browser/renderer_host/resource_dispatcher_host.cc b/chrome/browser/renderer_host/resource_dispatcher_host.cc
index 9ac5b7f..5e46a8a 100644
--- a/chrome/browser/renderer_host/resource_dispatcher_host.cc
+++ b/chrome/browser/renderer_host/resource_dispatcher_host.cc
@@ -889,7 +889,8 @@ void ResourceDispatcherHost::RemovePendingRequest(
// URLRequest::Delegate -------------------------------------------------------
void ResourceDispatcherHost::OnReceivedRedirect(URLRequest* request,
- const GURL& new_url) {
+ const GURL& new_url,
+ bool* defer_redirect) {
RESOURCE_LOG("OnReceivedRedirect: " << request->url().spec());
ExtraRequestInfo* info = ExtraInfoForRequest(request);
diff --git a/chrome/browser/renderer_host/resource_dispatcher_host.h b/chrome/browser/renderer_host/resource_dispatcher_host.h
index 7a0d4220..70ca89f 100644
--- a/chrome/browser/renderer_host/resource_dispatcher_host.h
+++ b/chrome/browser/renderer_host/resource_dispatcher_host.h
@@ -309,7 +309,8 @@ class ResourceDispatcherHost : public URLRequest::Delegate {
// URLRequest::Delegate
virtual void OnReceivedRedirect(URLRequest* request,
- const GURL& new_url);
+ const GURL& new_url,
+ bool* defer_redirect);
virtual void OnAuthRequired(URLRequest* request,
net::AuthChallengeInfo* auth_info);
virtual void OnCertificateRequested(
diff --git a/chrome/common/chrome_plugin_unittest.cc b/chrome/common/chrome_plugin_unittest.cc
index 8a884a6..521552b 100644
--- a/chrome/common/chrome_plugin_unittest.cc
+++ b/chrome/common/chrome_plugin_unittest.cc
@@ -41,8 +41,6 @@ class ChromePluginTest : public testing::Test, public URLRequest::Delegate {
void RunTest(const GURL& url, const TestResponsePayload* expected_payload);
// URLRequest::Delegate implementations
- virtual void OnReceivedRedirect(URLRequest* request,
- const GURL& new_url) { }
virtual void OnResponseStarted(URLRequest* request);
virtual void OnReadCompleted(URLRequest* request, int bytes_read);
diff --git a/net/proxy/proxy_script_fetcher.cc b/net/proxy/proxy_script_fetcher.cc
index ec0c8b1..eecff19 100644
--- a/net/proxy/proxy_script_fetcher.cc
+++ b/net/proxy/proxy_script_fetcher.cc
@@ -67,7 +67,6 @@ class ProxyScriptFetcherImpl : public ProxyScriptFetcher,
AuthChallengeInfo* auth_info);
virtual void OnSSLCertificateError(URLRequest* request, int cert_error,
X509Certificate* cert);
- virtual void OnReceivedRedirect(URLRequest* request, const GURL& to_url);
virtual void OnResponseStarted(URLRequest* request);
virtual void OnReadCompleted(URLRequest* request, int num_bytes);
virtual void OnResponseCompleted(URLRequest* request);
@@ -199,12 +198,6 @@ void ProxyScriptFetcherImpl::OnSSLCertificateError(URLRequest* request,
request->Cancel();
}
-void ProxyScriptFetcherImpl::OnReceivedRedirect(URLRequest* request,
- const GURL& to_url) {
- DCHECK(request == cur_request_.get());
- // OK, thanks for telling.
-}
-
void ProxyScriptFetcherImpl::OnResponseStarted(URLRequest* request) {
DCHECK(request == cur_request_.get());
diff --git a/net/tools/testserver/testserver.py b/net/tools/testserver/testserver.py
index 06bcfad..14ae182 100644
--- a/net/tools/testserver/testserver.py
+++ b/net/tools/testserver/testserver.py
@@ -570,6 +570,10 @@ class TestPageHandler(BaseHTTPServer.BaseHTTPRequestHandler):
if not self.path.startswith(prefix):
return False
+ # Consume a request body if present.
+ if self.command == 'POST':
+ self.rfile.read(int(self.headers.getheader('content-length')))
+
file = self.path[len(prefix):]
entries = file.split('/');
path = os.path.join(self.server.data_dir, *entries)
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc
index 7bccf6d..18437ad 100644
--- a/net/url_request/url_request.cc
+++ b/net/url_request/url_request.cc
@@ -252,6 +252,7 @@ void URLRequest::StartJob(URLRequestJob* job) {
job_->SetUpload(upload_.get());
is_pending_ = true;
+
response_info_.request_time = Time::Now();
response_info_.was_cached = false;
@@ -270,6 +271,7 @@ void URLRequest::Restart() {
void URLRequest::RestartWithJob(URLRequestJob *job) {
DCHECK(job->request() == this);
+ job_->Kill();
OrphanJob();
status_ = URLRequestStatus();
is_pending_ = false;
@@ -335,12 +337,12 @@ bool URLRequest::Read(net::IOBuffer* dest, int dest_size, int *bytes_read) {
return job_->Read(dest, dest_size, bytes_read);
}
-void URLRequest::ReceivedRedirect(const GURL& location) {
+void URLRequest::ReceivedRedirect(const GURL& location, bool* defer_redirect) {
URLRequestJob* job = GetJobManager()->MaybeInterceptRedirect(this, location);
if (job) {
RestartWithJob(job);
} else if (delegate_) {
- delegate_->OnReceivedRedirect(this, location);
+ delegate_->OnReceivedRedirect(this, location, defer_redirect);
}
}
@@ -353,6 +355,12 @@ void URLRequest::ResponseStarted() {
}
}
+void URLRequest::FollowDeferredRedirect() {
+ DCHECK(job_);
+
+ job_->FollowDeferredRedirect();
+}
+
void URLRequest::SetAuth(const wstring& username, const wstring& password) {
DCHECK(job_);
DCHECK(job_->NeedsAuth());
@@ -380,6 +388,7 @@ void URLRequest::ContinueDespiteLastError() {
}
void URLRequest::OrphanJob() {
+ job_->Kill();
job_->DetachRequest(); // ensures that the job will not call us again
job_ = NULL;
}
@@ -423,7 +432,6 @@ int URLRequest::Redirect(const GURL& location, int http_status_code) {
}
url_ = location;
upload_ = NULL;
- status_ = URLRequestStatus();
--redirect_limit_;
if (strip_post_specific_headers) {
@@ -442,8 +450,10 @@ int URLRequest::Redirect(const GURL& location, int http_status_code) {
final_upload_progress_ = job_->GetUploadProgress();
}
+ job_->Kill();
OrphanJob();
+ status_ = URLRequestStatus();
is_pending_ = false;
Start();
return net::OK;
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h
index 5ffec08..84da0cc 100644
--- a/net/url_request/url_request.h
+++ b/net/url_request/url_request.h
@@ -135,10 +135,19 @@ class URLRequest {
//
// When this function is called, the request will still contain the
// original URL, the destination of the redirect is provided in 'new_url'.
- // If the request is not canceled the redirect will be followed and the
- // request's URL will be changed to the new URL.
+ // If the delegate does not cancel the request and |*defer_redirect| is
+ // false, then the redirect will be followed, and the request's URL will be
+ // changed to the new URL. Otherwise if the delegate does not cancel the
+ // request and |*defer_redirect| is true, then the redirect will be
+ // followed once FollowDeferredRedirect is called on the URLRequest.
+ //
+ // The caller must set |*defer_redirect| to false, so that delegates do not
+ // need to set it if they are happy with the default behavior of not
+ // deferring redirect.
virtual void OnReceivedRedirect(URLRequest* request,
- const GURL& new_url) = 0;
+ const GURL& new_url,
+ bool* defer_redirect) {
+ }
// Called when we receive an authentication failure. The delegate should
// call request->SetAuth() with the user's credentials once it obtains them,
@@ -436,6 +445,10 @@ class URLRequest {
// will be set to an error.
bool Read(net::IOBuffer* buf, int max_bytes, int *bytes_read);
+ // This method may be called to follow a redirect that was deferred in
+ // response to an OnReceivedRedirect call.
+ void FollowDeferredRedirect();
+
// One of the following two methods should be called in response to an
// OnAuthRequired() callback (and only then).
// SetAuth will reissue the request with the given credentials.
@@ -494,7 +507,7 @@ class URLRequest {
int Redirect(const GURL& location, int http_status_code);
// Called by URLRequestJob to allow interception when a redirect occurs.
- void ReceivedRedirect(const GURL& location);
+ void ReceivedRedirect(const GURL& location, bool* defer_redirect);
// Called by URLRequestJob to allow interception when the final response
// occurs.
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_);
diff --git a/net/url_request/url_request_job.h b/net/url_request/url_request_job.h
index 558d9ad..8e56bea 100644
--- a/net/url_request/url_request_job.h
+++ b/net/url_request/url_request_job.h
@@ -11,6 +11,7 @@
#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
#include "base/time.h"
+#include "googleurl/src/gurl.h"
#include "net/base/filter.h"
#include "net/base/load_states.h"
@@ -22,7 +23,6 @@ class UploadData;
class X509Certificate;
}
-class GURL;
class URLRequest;
class URLRequestStatus;
class URLRequestJobMetrics;
@@ -182,6 +182,8 @@ class URLRequestJob : public base::RefCountedThreadSafe<URLRequestJob>,
// Continue processing the request ignoring the last error.
virtual void ContinueDespiteLastError();
+ void FollowDeferredRedirect();
+
// Returns true if the Job is done producing response data and has called
// NotifyDone on the request.
bool is_done() const { return done_; }
@@ -348,6 +350,10 @@ class URLRequestJob : public base::RefCountedThreadSafe<URLRequestJob>,
// Expected content size
int64 expected_content_size_;
+ // Set when a redirect is deferred.
+ GURL deferred_redirect_url_;
+ int deferred_redirect_status_code_;
+
//----------------------------------------------------------------------------
// Data used for statistics gathering in some instances. This data is only
// used for histograms etc., and is not required. It is optionally gathered
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 167e7e4..084206d 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -27,6 +27,7 @@
#include "net/base/net_errors.h"
#include "net/base/net_module.h"
#include "net/base/net_util.h"
+#include "net/base/upload_data.h"
#include "net/disk_cache/disk_cache.h"
#include "net/http/http_cache.h"
#include "net/http/http_network_layer.h"
@@ -100,6 +101,12 @@ void FillBuffer(char* buffer, size_t len) {
}
}
+scoped_refptr<net::UploadData> CreateSimpleUploadData(const char* data) {
+ scoped_refptr<net::UploadData> upload = new net::UploadData;
+ upload->AppendBytes(data, strlen(data));
+ return upload;
+}
+
} // namespace
// Inherit PlatformTest since we require the autorelease pool on Mac OS X.f
@@ -1071,6 +1078,64 @@ TEST_F(URLRequestTest, CancelRedirect) {
}
}
+TEST_F(URLRequestTest, DeferredRedirect) {
+ scoped_refptr<HTTPTestServer> server =
+ HTTPTestServer::CreateServer(L"net/data/url_request_unittest", NULL);
+ ASSERT_TRUE(NULL != server.get());
+ TestDelegate d;
+ {
+ d.set_quit_on_redirect(true);
+ TestURLRequest req(server->TestServerPage(
+ "files/redirect-test.html"), &d);
+ req.Start();
+ MessageLoop::current()->Run();
+
+ EXPECT_EQ(1, d.received_redirect_count());
+
+ req.FollowDeferredRedirect();
+ MessageLoop::current()->Run();
+
+ EXPECT_EQ(1, d.response_started_count());
+ EXPECT_FALSE(d.received_data_before_response());
+ EXPECT_EQ(URLRequestStatus::SUCCESS, req.status().status());
+
+ FilePath path;
+ PathService::Get(base::DIR_SOURCE_ROOT, &path);
+ path = path.Append(FILE_PATH_LITERAL("net"));
+ path = path.Append(FILE_PATH_LITERAL("data"));
+ path = path.Append(FILE_PATH_LITERAL("url_request_unittest"));
+ path = path.Append(FILE_PATH_LITERAL("with-headers.html"));
+
+ std::string contents;
+ EXPECT_TRUE(file_util::ReadFileToString(path, &contents));
+ EXPECT_EQ(contents, d.data_received());
+ }
+}
+
+TEST_F(URLRequestTest, CancelDeferredRedirect) {
+ scoped_refptr<HTTPTestServer> server =
+ HTTPTestServer::CreateServer(L"net/data/url_request_unittest", NULL);
+ ASSERT_TRUE(NULL != server.get());
+ TestDelegate d;
+ {
+ d.set_quit_on_redirect(true);
+ TestURLRequest req(server->TestServerPage(
+ "files/redirect-test.html"), &d);
+ req.Start();
+ MessageLoop::current()->Run();
+
+ EXPECT_EQ(1, d.received_redirect_count());
+
+ req.Cancel();
+ MessageLoop::current()->Run();
+
+ EXPECT_EQ(1, d.response_started_count());
+ EXPECT_EQ(0, d.bytes_received());
+ EXPECT_FALSE(d.received_data_before_response());
+ EXPECT_EQ(URLRequestStatus::CANCELED, req.status().status());
+ }
+}
+
TEST_F(URLRequestTest, VaryHeader) {
scoped_refptr<HTTPTestServer> server =
HTTPTestServer::CreateServer(L"net/data/url_request_unittest", NULL);
@@ -1236,15 +1301,16 @@ TEST_F(URLRequestTest, BasicAuthWithCookies) {
// Content-Type header.
// http://code.google.com/p/chromium/issues/detail?id=843
TEST_F(URLRequestTest, Post302RedirectGet) {
+ const char kData[] = "hello world";
scoped_refptr<HTTPTestServer> server =
HTTPTestServer::CreateServer(L"net/data/url_request_unittest", NULL);
ASSERT_TRUE(NULL != server.get());
TestDelegate d;
TestURLRequest req(server->TestServerPage("files/redirect-to-echoall"), &d);
req.set_method("POST");
+ req.set_upload(CreateSimpleUploadData(kData));
// Set headers (some of which are specific to the POST).
- // ("Content-Length: 10" is just a junk value to make sure it gets stripped).
req.SetExtraRequestHeaders(
"Content-Type: multipart/form-data; "
"boundary=----WebKitFormBoundaryAADeAA+NAAWMAAwZ\r\n"
@@ -1252,7 +1318,7 @@ TEST_F(URLRequestTest, Post302RedirectGet) {
"text/plain;q=0.8,image/png,*/*;q=0.5\r\n"
"Accept-Language: en-US,en\r\n"
"Accept-Charset: ISO-8859-1,*,utf-8\r\n"
- "Content-Length: 10\r\n"
+ "Content-Length: 11\r\n"
"Origin: http://localhost:1337/");
req.Start();
MessageLoop::current()->Run();
@@ -1274,17 +1340,23 @@ TEST_F(URLRequestTest, Post302RedirectGet) {
EXPECT_TRUE(ContainsString(data, "Accept-Charset:"));
}
-TEST_F(URLRequestTest, Post307RedirectPost) {
+// TODO(darin): Re-enable this test once bug 16832 is fixed.
+TEST_F(URLRequestTest, DISABLED_Post307RedirectPost) {
+ const char kData[] = "hello world";
scoped_refptr<HTTPTestServer> server =
HTTPTestServer::CreateServer(L"net/data/url_request_unittest", NULL);
ASSERT_TRUE(NULL != server.get());
TestDelegate d;
- TestURLRequest req(server->TestServerPage("files/redirect307-to-echoall"),
+ TestURLRequest req(server->TestServerPage("files/redirect307-to-echo"),
&d);
req.set_method("POST");
+ req.set_upload(CreateSimpleUploadData(kData).get());
+ req.SetExtraRequestHeaders(
+ "Content-Length: " + UintToString(sizeof(kData) - 1));
req.Start();
MessageLoop::current()->Run();
- EXPECT_EQ(req.method(), "POST");
+ EXPECT_EQ("POST", req.method());
+ EXPECT_EQ(kData, d.data_received());
}
// Custom URLRequestJobs for use with interceptor tests
diff --git a/net/url_request/url_request_unittest.h b/net/url_request/url_request_unittest.h
index 61a1712..763389f 100644
--- a/net/url_request/url_request_unittest.h
+++ b/net/url_request/url_request_unittest.h
@@ -74,6 +74,7 @@ class TestDelegate : public URLRequest::Delegate {
cancel_in_rd_(false),
cancel_in_rd_pending_(false),
quit_on_complete_(true),
+ quit_on_redirect_(false),
allow_certificate_errors_(false),
response_started_count_(0),
received_bytes_count_(0),
@@ -84,10 +85,15 @@ class TestDelegate : public URLRequest::Delegate {
buf_(new net::IOBuffer(kBufferSize)) {
}
- virtual void OnReceivedRedirect(URLRequest* request, const GURL& new_url) {
+ virtual void OnReceivedRedirect(URLRequest* request, const GURL& new_url,
+ bool* defer_redirect) {
received_redirect_count_++;
- if (cancel_in_rr_)
+ if (quit_on_redirect_) {
+ *defer_redirect = true;
+ MessageLoop::current()->Quit();
+ } else if (cancel_in_rr_) {
request->Cancel();
+ }
}
virtual void OnResponseStarted(URLRequest* request) {
@@ -182,6 +188,7 @@ class TestDelegate : public URLRequest::Delegate {
cancel_in_rd_pending_ = val;
}
void set_quit_on_complete(bool val) { quit_on_complete_ = val; }
+ void set_quit_on_redirect(bool val) { quit_on_redirect_ = val; }
void set_allow_certificate_errors(bool val) {
allow_certificate_errors_ = val;
}
@@ -207,6 +214,7 @@ class TestDelegate : public URLRequest::Delegate {
bool cancel_in_rd_;
bool cancel_in_rd_pending_;
bool quit_on_complete_;
+ bool quit_on_redirect_;
bool allow_certificate_errors_;
std::wstring username_;
diff --git a/webkit/tools/test_shell/simple_resource_loader_bridge.cc b/webkit/tools/test_shell/simple_resource_loader_bridge.cc
index 88e6244..a47abc30 100644
--- a/webkit/tools/test_shell/simple_resource_loader_bridge.cc
+++ b/webkit/tools/test_shell/simple_resource_loader_bridge.cc
@@ -280,7 +280,8 @@ class RequestProxy : public URLRequest::Delegate,
// URLRequest::Delegate implementation:
virtual void OnReceivedRedirect(URLRequest* request,
- const GURL& new_url) {
+ const GURL& new_url,
+ bool* defer_redirect) {
DCHECK(request->status().is_success());
OnReceivedRedirect(new_url);
}