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 88fdce8dd4ea5b8a42842547b1fd2247fc7f4468..fe490ab36933037c00c3cd779a3bc4eb1be7334f 100644 |
--- a/mojo/services/network/url_loader_impl.cc |
+++ b/mojo/services/network/url_loader_impl.cc |
@@ -46,6 +46,13 @@ URLResponsePtr MakeURLResponse(const net::URLRequest* url_request) { |
return response.Pass(); |
} |
+NetworkErrorPtr MakeNetworkError(int error_code) { |
+ NetworkErrorPtr error = NetworkError::New(); |
+ error->code = error_code; |
+ error->description = net::ErrorToString(error_code); |
+ return error.Pass(); |
+} |
+ |
} // namespace |
// Keeps track of a pending two-phase write on a DataPipeProducerHandle. |
@@ -103,6 +110,7 @@ class URLLoaderImpl::DependentIOBuffer : public net::WrappedIOBuffer { |
URLLoaderImpl::URLLoaderImpl(NetworkContext* context) |
: context_(context), |
+ response_body_buffer_size_(0), |
auto_follow_redirects_(true), |
weak_ptr_factory_(this) { |
} |
@@ -115,25 +123,19 @@ void URLLoaderImpl::OnConnectionError() { |
} |
void URLLoaderImpl::Start(URLRequestPtr request, |
- ScopedDataPipeProducerHandle response_body_stream) { |
- // Do not allow starting another request. |
+ const Callback<void(URLResponsePtr)>& callback) { |
if (url_request_) { |
- SendError(net::ERR_UNEXPECTED); |
- url_request_.reset(); |
- response_body_stream_.reset(); |
+ SendError(net::ERR_UNEXPECTED, callback); |
return; |
} |
if (!request) { |
- SendError(net::ERR_INVALID_ARGUMENT); |
+ SendError(net::ERR_INVALID_ARGUMENT, callback); |
return; |
} |
- response_body_stream_ = response_body_stream.Pass(); |
- |
- GURL url(request->url); |
url_request_.reset( |
- new net::URLRequest(url, |
+ new net::URLRequest(GURL(request->url), |
net::DEFAULT_PRIORITY, |
this, |
context_->url_request_context())); |
@@ -148,18 +150,42 @@ void URLLoaderImpl::Start(URLRequestPtr request, |
url_request_->SetLoadFlags(net::LOAD_BYPASS_CACHE); |
// TODO(darin): Handle request body. |
+ callback_ = callback; |
+ response_body_buffer_size_ = request->response_body_buffer_size; |
auto_follow_redirects_ = request->auto_follow_redirects; |
url_request_->Start(); |
} |
-void URLLoaderImpl::FollowRedirect() { |
+void URLLoaderImpl::FollowRedirect( |
+ const Callback<void(URLResponsePtr)>& callback) { |
+ if (!url_request_) { |
+ SendError(net::ERR_UNEXPECTED, callback); |
+ return; |
+ } |
+ |
if (auto_follow_redirects_) { |
DLOG(ERROR) << "Spurious call to FollowRedirect"; |
+ SendError(net::ERR_UNEXPECTED, callback); |
+ return; |
+ } |
+ |
+ // TODO(darin): Verify that it makes sense to call FollowDeferredRedirect. |
+ url_request_->FollowDeferredRedirect(); |
+} |
+ |
+void URLLoaderImpl::QueryStatus( |
+ const Callback<void(URLLoaderStatusPtr)>& callback) { |
+ URLLoaderStatusPtr status(URLLoaderStatus::New()); |
+ if (url_request_) { |
+ status->is_loading = url_request_->is_pending(); |
+ if (!url_request_->status().is_success()) |
+ status->error = MakeNetworkError(url_request_->status().error()); |
} else { |
- if (url_request_) |
- url_request_->FollowDeferredRedirect(); |
+ status->is_loading = false; |
} |
+ // TODO(darin): Populate more status fields. |
+ callback.Run(status.Pass()); |
} |
void URLLoaderImpl::OnReceivedRedirect(net::URLRequest* url_request, |
@@ -168,27 +194,41 @@ void URLLoaderImpl::OnReceivedRedirect(net::URLRequest* url_request, |
DCHECK(url_request == url_request_.get()); |
DCHECK(url_request->status().is_success()); |
+ if (auto_follow_redirects_) |
+ return; |
+ |
+ // Send the redirect response to the client, allowing them to inspect it and |
+ // optionally follow the redirect. |
+ *defer_redirect = true; |
+ |
URLResponsePtr response = MakeURLResponse(url_request); |
- std::string redirect_method = |
+ response->redirect_method = |
net::URLRequest::ComputeMethodForRedirect(url_request->method(), |
response->status_code); |
- client()->OnReceivedRedirect( |
- response.Pass(), new_url.spec(), redirect_method); |
+ response->redirect_url = new_url.spec(); |
- *defer_redirect = !auto_follow_redirects_; |
+ SendResponse(response.Pass()); |
} |
void URLLoaderImpl::OnResponseStarted(net::URLRequest* url_request) { |
DCHECK(url_request == url_request_.get()); |
if (!url_request->status().is_success()) { |
- SendError(url_request->status().error()); |
+ SendError(url_request->status().error(), callback_); |
+ callback_ = Callback<void(URLResponsePtr)>(); |
return; |
} |
// TODO(darin): Add support for optional MIME sniffing. |
- client()->OnReceivedResponse(MakeURLResponse(url_request)); |
+ DataPipe data_pipe; |
+ // TODO(darin): Honor given buffer size. |
+ |
+ URLResponsePtr response = MakeURLResponse(url_request); |
+ response->body = data_pipe.consumer_handle.Pass(); |
+ response_body_stream_ = data_pipe.producer_handle.Pass(); |
+ |
+ SendResponse(response.Pass()); |
// Start reading... |
ReadMore(); |
@@ -196,19 +236,29 @@ void URLLoaderImpl::OnResponseStarted(net::URLRequest* url_request) { |
void URLLoaderImpl::OnReadCompleted(net::URLRequest* url_request, |
int bytes_read) { |
+ DCHECK(url_request == url_request_.get()); |
+ |
if (url_request->status().is_success()) { |
DidRead(static_cast<uint32_t>(bytes_read), false); |
} else { |
pending_write_ = NULL; // This closes the data pipe. |
- // TODO(darin): Perhaps we should communicate this error to our client. |
} |
} |
-void URLLoaderImpl::SendError(int error_code) { |
- NetworkErrorPtr error(NetworkError::New()); |
- error->code = error_code; |
- error->description = net::ErrorToString(error_code); |
- client()->OnReceivedError(error.Pass()); |
+void URLLoaderImpl::SendError( |
+ int error_code, |
+ const Callback<void(URLResponsePtr)>& callback) { |
+ URLResponsePtr response(URLResponse::New()); |
+ if (url_request_) |
+ response->url = url_request_->url().spec(); |
+ response->error = MakeNetworkError(error_code); |
+ callback.Run(response.Pass()); |
+} |
+ |
+void URLLoaderImpl::SendResponse(URLResponsePtr response) { |
+ Callback<void(URLResponsePtr)> callback; |
+ std::swap(callback_, callback); |
+ callback.Run(response.Pass()); |
} |
void URLLoaderImpl::OnResponseBodyStreamReady(MojoResult result) { |
@@ -260,12 +310,6 @@ void URLLoaderImpl::ReadMore() { |
} else { |
pending_write_->Complete(0); |
pending_write_ = NULL; // This closes the data pipe. |
- if (bytes_read == 0) { |
- client()->OnReceivedEndOfResponseBody(); |
- } else { |
- DCHECK(!url_request_->status().is_success()); |
- SendError(url_request_->status().error()); |
- } |
} |
} |