Index: mojo/services/network/url_loader_impl.cc |
diff --git a/mojo/services/network/url_loader_impl.cc b/mojo/services/network/url_loader_impl.cc |
index 3f263780407b907f7d25da682dcc69719f91e0f0..ccaf4e51c7a156def0bdaf8fcf829801303d55d1 100644 |
--- a/mojo/services/network/url_loader_impl.cc |
+++ b/mojo/services/network/url_loader_impl.cc |
@@ -31,7 +31,7 @@ URLResponsePtr MakeURLResponse(const net::URLRequest* url_request) { |
response->status_line = headers->GetStatusLine(); |
std::vector<String> header_lines; |
- void* iter = NULL; |
+ void* iter = nullptr; |
std::string name, value; |
while (headers->EnumerateHeaderLines(&iter, &name, &value)) |
header_lines.push_back(name + ": " + value); |
@@ -60,7 +60,7 @@ class UploadDataPipeElementReader : public net::UploadElementReader { |
// UploadElementReader overrides: |
int Init(const net::CompletionCallback& callback) override { |
offset_ = 0; |
- ReadDataRaw(pipe_.get(), NULL, &num_bytes_, MOJO_READ_DATA_FLAG_QUERY); |
+ ReadDataRaw(pipe_.get(), nullptr, &num_bytes_, MOJO_READ_DATA_FLAG_QUERY); |
return net::OK; |
} |
uint64 GetContentLength() const override { return num_bytes_; } |
@@ -91,11 +91,15 @@ class UploadDataPipeElementReader : public net::UploadElementReader { |
} // namespace |
-URLLoaderImpl::URLLoaderImpl(NetworkContext* context) |
+URLLoaderImpl::URLLoaderImpl(NetworkContext* context, |
+ InterfaceRequest<URLLoader> request) |
: context_(context), |
response_body_buffer_size_(0), |
auto_follow_redirects_(true), |
+ connected_(true), |
+ binding_(this, request.Pass()), |
weak_ptr_factory_(this) { |
+ binding_.set_error_handler(this); |
} |
URLLoaderImpl::~URLLoaderImpl() { |
@@ -114,10 +118,7 @@ void URLLoaderImpl::Start(URLRequestPtr request, |
} |
url_request_ = context_->url_request_context()->CreateRequest( |
- GURL(request->url), |
- net::DEFAULT_PRIORITY, |
- this, |
- NULL); |
+ GURL(request->url), net::DEFAULT_PRIORITY, this, nullptr); |
url_request_->set_method(request->method); |
if (request->headers) { |
net::HttpRequestHeaders headers; |
@@ -175,6 +176,11 @@ void URLLoaderImpl::QueryStatus( |
callback.Run(status.Pass()); |
} |
+void URLLoaderImpl::OnConnectionError() { |
+ connected_ = false; |
+ DeleteIfNeeded(); |
+} |
+ |
void URLLoaderImpl::OnReceivedRedirect(net::URLRequest* url_request, |
const net::RedirectInfo& redirect_info, |
bool* defer_redirect) { |
@@ -193,6 +199,8 @@ void URLLoaderImpl::OnReceivedRedirect(net::URLRequest* url_request, |
response->redirect_url = String::From(redirect_info.new_url); |
SendResponse(response.Pass()); |
+ |
+ DeleteIfNeeded(); |
} |
void URLLoaderImpl::OnResponseStarted(net::URLRequest* url_request) { |
@@ -201,6 +209,7 @@ void URLLoaderImpl::OnResponseStarted(net::URLRequest* url_request) { |
if (!url_request->status().is_success()) { |
SendError(url_request->status().error(), callback_); |
callback_ = Callback<void(URLResponsePtr)>(); |
+ DeleteIfNeeded(); |
return; |
} |
@@ -212,6 +221,7 @@ void URLLoaderImpl::OnResponseStarted(net::URLRequest* url_request) { |
URLResponsePtr response = MakeURLResponse(url_request); |
response->body = data_pipe.consumer_handle.Pass(); |
response_body_stream_ = data_pipe.producer_handle.Pass(); |
+ ListenForPeerClosed(); |
SendResponse(response.Pass()); |
@@ -226,7 +236,10 @@ void URLLoaderImpl::OnReadCompleted(net::URLRequest* url_request, |
if (url_request->status().is_success()) { |
DidRead(static_cast<uint32_t>(bytes_read), false); |
} else { |
- pending_write_ = NULL; // This closes the data pipe. |
+ handle_watcher_.Stop(); |
+ pending_write_ = nullptr; // This closes the data pipe. |
+ DeleteIfNeeded(); |
+ return; |
} |
} |
@@ -248,9 +261,18 @@ void URLLoaderImpl::SendResponse(URLResponsePtr response) { |
void URLLoaderImpl::OnResponseBodyStreamReady(MojoResult result) { |
// TODO(darin): Handle a bad |result| value. |
+ |
+ // Continue watching the handle in case the peer is closed. |
+ ListenForPeerClosed(); |
ReadMore(); |
} |
+void URLLoaderImpl::OnResponseBodyStreamClosed(MojoResult result) { |
+ response_body_stream_.reset(); |
+ pending_write_ = nullptr; |
+ DeleteIfNeeded(); |
+} |
+ |
void URLLoaderImpl::ReadMore() { |
DCHECK(!pending_write_.get()); |
@@ -261,14 +283,16 @@ void URLLoaderImpl::ReadMore() { |
if (result == MOJO_RESULT_SHOULD_WAIT) { |
// The pipe is full. We need to wait for it to have more space. |
handle_watcher_.Start(response_body_stream_.get(), |
- MOJO_HANDLE_SIGNAL_WRITABLE, |
- MOJO_DEADLINE_INDEFINITE, |
+ MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_DEADLINE_INDEFINITE, |
base::Bind(&URLLoaderImpl::OnResponseBodyStreamReady, |
- weak_ptr_factory_.GetWeakPtr())); |
+ base::Unretained(this))); |
return; |
} else if (result != MOJO_RESULT_OK) { |
// The response body stream is in a bad state. Bail. |
// TODO(darin): How should this be communicated to our client? |
+ handle_watcher_.Stop(); |
+ response_body_stream_.reset(); |
+ DeleteIfNeeded(); |
return; |
} |
CHECK_GT(static_cast<uint32_t>(std::numeric_limits<int>::max()), num_bytes); |
@@ -282,8 +306,11 @@ void URLLoaderImpl::ReadMore() { |
} else if (url_request_->status().is_success() && bytes_read > 0) { |
DidRead(static_cast<uint32_t>(bytes_read), true); |
} else { |
+ handle_watcher_.Stop(); |
pending_write_->Complete(0); |
- pending_write_ = NULL; // This closes the data pipe. |
+ pending_write_ = nullptr; // This closes the data pipe. |
+ DeleteIfNeeded(); |
+ return; |
} |
} |
@@ -291,7 +318,7 @@ void URLLoaderImpl::DidRead(uint32_t num_bytes, bool completed_synchronously) { |
DCHECK(url_request_->status().is_success()); |
response_body_stream_ = pending_write_->Complete(num_bytes); |
- pending_write_ = NULL; |
+ pending_write_ = nullptr; |
if (completed_synchronously) { |
base::MessageLoop::current()->PostTask( |
@@ -302,4 +329,18 @@ void URLLoaderImpl::DidRead(uint32_t num_bytes, bool completed_synchronously) { |
} |
} |
+void URLLoaderImpl::DeleteIfNeeded() { |
+ bool has_data_pipe = pending_write_.get() || response_body_stream_.is_valid(); |
+ if (!connected_ && !has_data_pipe) |
+ delete this; |
+} |
+ |
+void URLLoaderImpl::ListenForPeerClosed() { |
+ handle_watcher_.Start(response_body_stream_.get(), |
+ MOJO_HANDLE_SIGNAL_PEER_CLOSED, |
+ MOJO_DEADLINE_INDEFINITE, |
+ base::Bind(&URLLoaderImpl::OnResponseBodyStreamClosed, |
+ base::Unretained(this))); |
+} |
+ |
} // namespace mojo |