// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "mojo/examples/html_viewer/weburlloader_impl.h" #include "base/bind.h" #include "base/logging.h" #include "mojo/services/public/interfaces/network/network_service.mojom.h" #include "third_party/WebKit/public/platform/WebURLError.h" #include "third_party/WebKit/public/platform/WebURLLoaderClient.h" #include "third_party/WebKit/public/platform/WebURLRequest.h" #include "third_party/WebKit/public/platform/WebURLResponse.h" namespace mojo { namespace examples { namespace { blink::WebURLResponse ToWebURLResponse(const URLResponsePtr& url_response) { blink::WebURLResponse result; result.initialize(); result.setURL(GURL(url_response->url)); // TODO(darin): Copy other fields. return result; } } // namespace WebURLLoaderImpl::WebURLLoaderImpl(NetworkService* network_service) : client_(NULL), weak_factory_(this) { network_service->CreateURLLoader(Get(&url_loader_)); url_loader_.set_client(this); } WebURLLoaderImpl::~WebURLLoaderImpl() { } void WebURLLoaderImpl::loadSynchronously( const blink::WebURLRequest& request, blink::WebURLResponse& response, blink::WebURLError& error, blink::WebData& data) { NOTIMPLEMENTED(); } void WebURLLoaderImpl::loadAsynchronously(const blink::WebURLRequest& request, blink::WebURLLoaderClient* client) { client_ = client; URLRequestPtr url_request(URLRequest::New()); url_request->url = request.url().spec(); url_request->auto_follow_redirects = false; // TODO(darin): Copy other fields. DataPipe pipe; url_loader_->Start(url_request.Pass(), pipe.producer_handle.Pass()); response_body_stream_ = pipe.consumer_handle.Pass(); } void WebURLLoaderImpl::cancel() { url_loader_.reset(); response_body_stream_.reset(); // TODO(darin): Need to asynchronously call didFail. } void WebURLLoaderImpl::setDefersLoading(bool defers_loading) { NOTIMPLEMENTED(); } void WebURLLoaderImpl::OnReceivedRedirect(URLResponsePtr url_response, const String& new_url, const String& new_method) { blink::WebURLRequest new_request; new_request.initialize(); new_request.setURL(GURL(new_url)); client_->willSendRequest(this, new_request, ToWebURLResponse(url_response)); // TODO(darin): Check if new_request was rejected. url_loader_->FollowRedirect(); } void WebURLLoaderImpl::OnReceivedResponse(URLResponsePtr url_response) { client_->didReceiveResponse(this, ToWebURLResponse(url_response)); // Start streaming data ReadMore(); } void WebURLLoaderImpl::OnReceivedError(NetworkErrorPtr error) { // TODO(darin): Construct a meaningful WebURLError. client_->didFail(this, blink::WebURLError()); } void WebURLLoaderImpl::OnReceivedEndOfResponseBody() { // This is the signal that the response body was not truncated. } void WebURLLoaderImpl::ReadMore() { const void* buf; uint32_t buf_size; MojoResult rv = BeginReadDataRaw(response_body_stream_.get(), &buf, &buf_size, MOJO_READ_DATA_FLAG_NONE); if (rv == MOJO_RESULT_OK) { client_->didReceiveData(this, static_cast<const char*>(buf), buf_size, -1); EndReadDataRaw(response_body_stream_.get(), buf_size); WaitToReadMore(); } else if (rv == MOJO_RESULT_SHOULD_WAIT) { WaitToReadMore(); } else if (rv == MOJO_RESULT_FAILED_PRECONDITION) { // We reached end-of-file. double finish_time = base::Time::Now().ToDoubleT(); client_->didFinishLoading( this, finish_time, blink::WebURLLoaderClient::kUnknownEncodedDataLength); } else { // TODO(darin): Oops! } } void WebURLLoaderImpl::WaitToReadMore() { handle_watcher_.Start( response_body_stream_.get(), MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, base::Bind(&WebURLLoaderImpl::OnResponseBodyStreamReady, weak_factory_.GetWeakPtr())); } void WebURLLoaderImpl::OnResponseBodyStreamReady(MojoResult result) { ReadMore(); } } // namespace examples } // namespace mojo