Allow the NetworkDelegate to synchronously cancel a URLRequest.

BUG=49612
TEST=net_unittests:URLRequestTestHTTP.NetworkDelegateCancelRequestSynchronously


Review URL: http://codereview.chromium.org/7747016

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@98978 0039d316-1c4b-4281-b951-d872f2087c98
parent a8171203
...@@ -403,11 +403,17 @@ void URLRequest::Start() { ...@@ -403,11 +403,17 @@ void URLRequest::Start() {
// Only notify the delegate for the initial request. // Only notify the delegate for the initial request.
if (context_ && context_->network_delegate()) { if (context_ && context_->network_delegate()) {
if (context_->network_delegate()->NotifyBeforeURLRequest( int error = context_->network_delegate()->NotifyBeforeURLRequest(
this, &before_request_callback_, &delegate_redirect_url_) == this, &before_request_callback_, &delegate_redirect_url_);
net::ERR_IO_PENDING) { if (error != net::OK) {
SetBlockedOnDelegate(); if (error == net::ERR_IO_PENDING) {
return; // paused // Paused on the delegate, will invoke |before_request_callback_| later.
SetBlockedOnDelegate();
} else {
// The delegate immediately returned some error code.
BeforeRequestComplete(error);
}
return;
} }
} }
...@@ -420,7 +426,8 @@ void URLRequest::BeforeRequestComplete(int error) { ...@@ -420,7 +426,8 @@ void URLRequest::BeforeRequestComplete(int error) {
DCHECK(!job_); DCHECK(!job_);
DCHECK_NE(ERR_IO_PENDING, error); DCHECK_NE(ERR_IO_PENDING, error);
SetUnblockedOnDelegate(); if (blocked_on_delegate_)
SetUnblockedOnDelegate();
if (error != OK) { if (error != OK) {
net_log_.AddEvent(NetLog::TYPE_CANCELLED, net_log_.AddEvent(NetLog::TYPE_CANCELLED,
make_scoped_refptr(new NetLogStringParameter("source", "delegate"))); make_scoped_refptr(new NetLogStringParameter("source", "delegate")));
......
...@@ -123,9 +123,11 @@ void CheckSSLInfo(const SSLInfo& ssl_info) { ...@@ -123,9 +123,11 @@ void CheckSSLInfo(const SSLInfo& ssl_info) {
class BlockingNetworkDelegate : public TestNetworkDelegate { class BlockingNetworkDelegate : public TestNetworkDelegate {
public: public:
BlockingNetworkDelegate() BlockingNetworkDelegate()
: callback_retval_(net::OK), : retval_(net::ERR_IO_PENDING),
callback_retval_(net::OK),
ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {} ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {}
void set_retval(int retval) { retval_ = retval; }
void set_callback_retval(int retval) { callback_retval_ = retval; } void set_callback_retval(int retval) { callback_retval_ = retval; }
void set_redirect_url(const GURL& url) { redirect_url_ = url; } void set_redirect_url(const GURL& url) { redirect_url_ = url; }
...@@ -143,6 +145,10 @@ class BlockingNetworkDelegate : public TestNetworkDelegate { ...@@ -143,6 +145,10 @@ class BlockingNetworkDelegate : public TestNetworkDelegate {
if (!redirect_url_.is_empty()) if (!redirect_url_.is_empty())
*new_url = redirect_url_; *new_url = redirect_url_;
if (retval_ != net::ERR_IO_PENDING)
return retval_;
MessageLoop::current()->PostTask( MessageLoop::current()->PostTask(
FROM_HERE, FROM_HERE,
method_factory_.NewRunnableMethod(&BlockingNetworkDelegate::DoCallback, method_factory_.NewRunnableMethod(&BlockingNetworkDelegate::DoCallback,
...@@ -154,6 +160,7 @@ class BlockingNetworkDelegate : public TestNetworkDelegate { ...@@ -154,6 +160,7 @@ class BlockingNetworkDelegate : public TestNetworkDelegate {
callback->Run(callback_retval_); callback->Run(callback_retval_);
} }
int retval_;
int callback_retval_; int callback_retval_;
GURL redirect_url_; GURL redirect_url_;
ScopedRunnableMethodFactory<BlockingNetworkDelegate> method_factory_; ScopedRunnableMethodFactory<BlockingNetworkDelegate> method_factory_;
...@@ -343,6 +350,34 @@ TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequest) { ...@@ -343,6 +350,34 @@ TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequest) {
EXPECT_EQ(1, network_delegate.destroyed_requests()); EXPECT_EQ(1, network_delegate.destroyed_requests());
} }
// Tests that the network delegate can cancel a request synchronously.
TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequestSynchronously) {
ASSERT_TRUE(test_server_.Start());
TestDelegate d;
BlockingNetworkDelegate network_delegate;
network_delegate.set_retval(ERR_EMPTY_RESPONSE);
scoped_refptr<TestURLRequestContext> context(new TestURLRequestContext(true));
context->SetProxyFromString(test_server_.host_port_pair().ToString());
context->set_network_delegate(&network_delegate);
context->Init();
{
TestURLRequest r(test_server_.GetURL(""), &d);
r.set_context(context);
r.Start();
MessageLoop::current()->Run();
EXPECT_EQ(URLRequestStatus::FAILED, r.status().status());
EXPECT_EQ(ERR_EMPTY_RESPONSE, r.status().os_error());
EXPECT_EQ(1, network_delegate.created_requests());
EXPECT_EQ(0, network_delegate.destroyed_requests());
}
EXPECT_EQ(1, network_delegate.destroyed_requests());
}
// Tests that the network delegate can block and redirect a request to a new // Tests that the network delegate can block and redirect a request to a new
// URL. // URL.
TEST_F(URLRequestTestHTTP, NetworkDelegateRedirectRequest) { TEST_F(URLRequestTestHTTP, NetworkDelegateRedirectRequest) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment