Index: net/url_request/url_request_unittest.cc |
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc |
index 63e7c757244ddf6c31f28adcd369cd86c2a0ef48..7e197b760931c8e060cf20384aa368b7ec45bd7a 100644 |
--- a/net/url_request/url_request_unittest.cc |
+++ b/net/url_request/url_request_unittest.cc |
@@ -338,6 +338,9 @@ class BlockingNetworkDelegate : public TestNetworkDelegate { |
void set_redirect_url(const GURL& url) { |
redirect_url_ = url; |
} |
+ void set_redirect_url_on_headers_received(const GURL& url) { |
+ redirect_url_on_headers_received_ = url; |
+ } |
void set_block_on(int block_on) { |
block_on_ = block_on; |
@@ -366,6 +369,7 @@ class BlockingNetworkDelegate : public TestNetworkDelegate { |
virtual int OnHeadersReceived( |
URLRequest* request, |
const CompletionCallback& callback, |
+ GURL* new_url, |
const HttpResponseHeaders* original_response_headers, |
scoped_refptr<HttpResponseHeaders>* override_response_headers) OVERRIDE; |
@@ -390,7 +394,8 @@ class BlockingNetworkDelegate : public TestNetworkDelegate { |
int retval_; // To be returned in non-auth stages. |
AuthRequiredResponse auth_retval_; |
- GURL redirect_url_; // Used if non-empty. |
+ GURL redirect_url_; // Used if non-empty during OnBeforeURLRequest. |
+ GURL redirect_url_on_headers_received_; // Used if non-empty. |
int block_on_; // Bit mask: in which stages to block. |
// |auth_credentials_| will be copied to |*target_auth_credential_| on |
@@ -481,12 +486,19 @@ int BlockingNetworkDelegate::OnBeforeSendHeaders( |
int BlockingNetworkDelegate::OnHeadersReceived( |
URLRequest* request, |
const CompletionCallback& callback, |
+ GURL* new_url, |
const HttpResponseHeaders* original_response_headers, |
scoped_refptr<HttpResponseHeaders>* override_response_headers) { |
TestNetworkDelegate::OnHeadersReceived( |
- request, callback, original_response_headers, |
+ request, callback, new_url, original_response_headers, |
override_response_headers); |
+ // Redirects to the same URL are allowed, but for simplicity, assume that |
+ // the tests only redirect to a different URL. |
+ if (!redirect_url_on_headers_received_.is_empty() && |
+ redirect_url_on_headers_received_ != request->url()) |
+ *new_url = redirect_url_on_headers_received_; |
+ |
return MaybeBlockStage(ON_HEADERS_RECEIVED, callback); |
} |
@@ -2415,6 +2427,7 @@ class FixedDateNetworkDelegate : public TestNetworkDelegate { |
virtual int OnHeadersReceived( |
net::URLRequest* request, |
const net::CompletionCallback& callback, |
+ GURL* new_url, |
const net::HttpResponseHeaders* original_response_headers, |
scoped_refptr<net::HttpResponseHeaders>* override_response_headers) |
OVERRIDE; |
@@ -2428,6 +2441,7 @@ class FixedDateNetworkDelegate : public TestNetworkDelegate { |
int FixedDateNetworkDelegate::OnHeadersReceived( |
net::URLRequest* request, |
const net::CompletionCallback& callback, |
+ GURL* new_url, |
const net::HttpResponseHeaders* original_response_headers, |
scoped_refptr<net::HttpResponseHeaders>* override_response_headers) { |
net::HttpResponseHeaders* new_response_headers = |
@@ -2439,6 +2453,7 @@ int FixedDateNetworkDelegate::OnHeadersReceived( |
*override_response_headers = new_response_headers; |
return TestNetworkDelegate::OnHeadersReceived(request, |
callback, |
+ new_url, |
original_response_headers, |
override_response_headers); |
} |
@@ -3007,6 +3022,83 @@ TEST_F(URLRequestTestHTTP, NetworkDelegateRedirectRequestPost) { |
EXPECT_EQ(1, network_delegate.destroyed_requests()); |
} |
+// Tests that the network delegate can block and redirect a request to a new |
+// URL during OnHeadersReceived. |
+TEST_F(URLRequestTestHTTP, NetworkDelegateRedirectRequestOnHeadersReceived) { |
+ ASSERT_TRUE(test_server_.Start()); |
+ |
+ TestDelegate d; |
+ BlockingNetworkDelegate network_delegate( |
+ BlockingNetworkDelegate::AUTO_CALLBACK); |
+ network_delegate.set_block_on(BlockingNetworkDelegate::ON_HEADERS_RECEIVED); |
+ GURL redirect_url(test_server_.GetURL("simple.html")); |
+ network_delegate.set_redirect_url_on_headers_received(redirect_url); |
+ |
+ TestURLRequestContextWithProxy context( |
+ test_server_.host_port_pair().ToString(), &network_delegate); |
+ |
+ { |
+ GURL original_url(test_server_.GetURL("empty.html")); |
+ URLRequest r(original_url, DEFAULT_PRIORITY, &d, &context); |
+ |
+ r.Start(); |
+ base::RunLoop().Run(); |
+ |
+ EXPECT_EQ(URLRequestStatus::SUCCESS, r.status().status()); |
+ EXPECT_EQ(0, r.status().error()); |
+ EXPECT_EQ(redirect_url, r.url()); |
+ EXPECT_EQ(original_url, r.original_url()); |
+ EXPECT_EQ(2U, r.url_chain().size()); |
+ EXPECT_EQ(2, network_delegate.created_requests()); |
+ EXPECT_EQ(0, network_delegate.destroyed_requests()); |
+ } |
+ EXPECT_EQ(1, network_delegate.destroyed_requests()); |
battre
2014/02/13 15:30:33
This looks suspicious. Shouldn't there be
a) only
|
+} |
+ |
+// Tests that redirects caused by the network delegate during OnHeadersReceived |
+// preserve POST data. |
+TEST_F(URLRequestTestHTTP, |
+ NetworkDelegateRedirectRequestOnHeadersReceivedPost) { |
+ ASSERT_TRUE(test_server_.Start()); |
+ |
+ const char kData[] = "hello world"; |
+ |
+ TestDelegate d; |
+ BlockingNetworkDelegate network_delegate( |
+ BlockingNetworkDelegate::AUTO_CALLBACK); |
+ network_delegate.set_block_on(BlockingNetworkDelegate::ON_HEADERS_RECEIVED); |
+ GURL redirect_url(test_server_.GetURL("echo")); |
+ network_delegate.set_redirect_url_on_headers_received(redirect_url); |
+ |
+ TestURLRequestContext context(true); |
+ context.set_network_delegate(&network_delegate); |
+ context.Init(); |
+ |
+ { |
+ GURL original_url(test_server_.GetURL("empty.html")); |
+ URLRequest r(original_url, DEFAULT_PRIORITY, &d, &context); |
+ r.set_method("POST"); |
+ r.set_upload(make_scoped_ptr(CreateSimpleUploadData(kData))); |
+ HttpRequestHeaders headers; |
+ headers.SetHeader(HttpRequestHeaders::kContentLength, |
+ base::UintToString(arraysize(kData) - 1)); |
+ r.SetExtraRequestHeaders(headers); |
+ r.Start(); |
+ base::RunLoop().Run(); |
+ |
+ EXPECT_EQ(URLRequestStatus::SUCCESS, r.status().status()); |
+ EXPECT_EQ(0, r.status().error()); |
+ EXPECT_EQ(redirect_url, r.url()); |
+ EXPECT_EQ(original_url, r.original_url()); |
+ EXPECT_EQ(2U, r.url_chain().size()); |
+ EXPECT_EQ(2, network_delegate.created_requests()); |
+ EXPECT_EQ(0, network_delegate.destroyed_requests()); |
+ EXPECT_EQ("POST", r.method()); |
+ EXPECT_EQ(kData, d.data_received()); |
+ } |
+ EXPECT_EQ(1, network_delegate.destroyed_requests()); |
+} |
+ |
// Tests that the network delegate can synchronously complete OnAuthRequired |
// by taking no action. This indicates that the NetworkDelegate does not want to |
// handle the challenge, and is passing the buck along to the |
@@ -3918,9 +4010,10 @@ class AsyncLoggingNetworkDelegate : public TestNetworkDelegate { |
virtual int OnHeadersReceived( |
URLRequest* request, |
const CompletionCallback& callback, |
+ GURL* new_url, |
const HttpResponseHeaders* original_response_headers, |
scoped_refptr<HttpResponseHeaders>* override_response_headers) OVERRIDE { |
- TestNetworkDelegate::OnHeadersReceived(request, callback, |
+ TestNetworkDelegate::OnHeadersReceived(request, callback, new_url, |
original_response_headers, |
override_response_headers); |
return RunCallbackAsynchronously(request, callback); |