diff options
-rw-r--r-- | mojo/examples/html_viewer/DEPS | 6 | ||||
-rw-r--r-- | mojo/examples/html_viewer/blink_platform_impl.cc | 213 | ||||
-rw-r--r-- | mojo/examples/html_viewer/blink_platform_impl.h | 78 | ||||
-rw-r--r-- | mojo/examples/html_viewer/html_document_view.cc | 140 | ||||
-rw-r--r-- | mojo/examples/html_viewer/html_document_view.h | 62 | ||||
-rw-r--r-- | mojo/examples/html_viewer/html_viewer.cc | 82 | ||||
-rw-r--r-- | mojo/examples/html_viewer/webmimeregistry_impl.cc | 97 | ||||
-rw-r--r-- | mojo/examples/html_viewer/webmimeregistry_impl.h | 50 | ||||
-rw-r--r-- | mojo/examples/html_viewer/webthread_impl.cc | 133 | ||||
-rw-r--r-- | mojo/examples/html_viewer/webthread_impl.h | 75 | ||||
-rw-r--r-- | mojo/examples/html_viewer/weburlloader_impl.cc | 139 | ||||
-rw-r--r-- | mojo/examples/html_viewer/weburlloader_impl.h | 60 | ||||
-rw-r--r-- | mojo/mojo_examples.gypi | 16 | ||||
-rw-r--r-- | mojo/services/network/url_loader_impl.cc | 2 |
14 files changed, 1113 insertions, 40 deletions
diff --git a/mojo/examples/html_viewer/DEPS b/mojo/examples/html_viewer/DEPS new file mode 100644 index 0000000..83af040 --- /dev/null +++ b/mojo/examples/html_viewer/DEPS @@ -0,0 +1,6 @@ +include_rules = [ + "+skia", + "+net/base", + "+third_party/skia/include", + "+third_party/WebKit/public", +] diff --git a/mojo/examples/html_viewer/blink_platform_impl.cc b/mojo/examples/html_viewer/blink_platform_impl.cc new file mode 100644 index 0000000..3128d43 --- /dev/null +++ b/mojo/examples/html_viewer/blink_platform_impl.cc @@ -0,0 +1,213 @@ +// 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/blink_platform_impl.h" + +#include <cmath> + +#include "base/rand_util.h" +#include "base/stl_util.h" +#include "base/synchronization/waitable_event.h" +#include "base/time/time.h" +#include "mojo/examples/html_viewer/webthread_impl.h" +#include "mojo/examples/html_viewer/weburlloader_impl.h" +#include "mojo/public/cpp/application/application.h" +#include "net/base/data_url.h" +#include "net/base/mime_util.h" +#include "net/base/net_errors.h" +#include "third_party/WebKit/public/platform/WebWaitableEvent.h" + +namespace mojo { +namespace examples { +namespace { + +// TODO(darin): Figure out what our UA should really be. +const char kUserAgentString[] = + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/35.0.1916.153 Safari/537.36"; + +class WebWaitableEventImpl : public blink::WebWaitableEvent { + public: + WebWaitableEventImpl() : impl_(new base::WaitableEvent(false, false)) {} + virtual ~WebWaitableEventImpl() {} + + virtual void wait() { impl_->Wait(); } + virtual void signal() { impl_->Signal(); } + + base::WaitableEvent* impl() { + return impl_.get(); + } + + private: + scoped_ptr<base::WaitableEvent> impl_; + DISALLOW_COPY_AND_ASSIGN(WebWaitableEventImpl); +}; + +} // namespace + +BlinkPlatformImpl::BlinkPlatformImpl(Application* app) + : main_loop_(base::MessageLoop::current()), + shared_timer_func_(NULL), + shared_timer_fire_time_(0.0), + shared_timer_fire_time_was_set_while_suspended_(false), + shared_timer_suspended_(0), + current_thread_slot_(&DestroyCurrentThread) { + app->ConnectTo("mojo:mojo_network_service", &network_service_); +} + +BlinkPlatformImpl::~BlinkPlatformImpl() { +} + +blink::WebMimeRegistry* BlinkPlatformImpl::mimeRegistry() { + return &mime_registry_; +} + +blink::WebThemeEngine* BlinkPlatformImpl::themeEngine() { + return &dummy_theme_engine_; +} + +blink::WebString BlinkPlatformImpl::defaultLocale() { + return blink::WebString::fromUTF8("en-US"); +} + +double BlinkPlatformImpl::currentTime() { + return base::Time::Now().ToDoubleT(); +} + +double BlinkPlatformImpl::monotonicallyIncreasingTime() { + return base::TimeTicks::Now().ToInternalValue() / + static_cast<double>(base::Time::kMicrosecondsPerSecond); +} + +void BlinkPlatformImpl::cryptographicallyRandomValues(unsigned char* buffer, + size_t length) { + base::RandBytes(buffer, length); +} + +void BlinkPlatformImpl::setSharedTimerFiredFunction(void (*func)()) { + shared_timer_func_ = func; +} + +void BlinkPlatformImpl::setSharedTimerFireInterval( + double interval_seconds) { + shared_timer_fire_time_ = interval_seconds + monotonicallyIncreasingTime(); + if (shared_timer_suspended_) { + shared_timer_fire_time_was_set_while_suspended_ = true; + return; + } + + // By converting between double and int64 representation, we run the risk + // of losing precision due to rounding errors. Performing computations in + // microseconds reduces this risk somewhat. But there still is the potential + // of us computing a fire time for the timer that is shorter than what we + // need. + // As the event loop will check event deadlines prior to actually firing + // them, there is a risk of needlessly rescheduling events and of + // needlessly looping if sleep times are too short even by small amounts. + // This results in measurable performance degradation unless we use ceil() to + // always round up the sleep times. + int64 interval = static_cast<int64>( + ceil(interval_seconds * base::Time::kMillisecondsPerSecond) + * base::Time::kMicrosecondsPerMillisecond); + + if (interval < 0) + interval = 0; + + shared_timer_.Stop(); + shared_timer_.Start(FROM_HERE, base::TimeDelta::FromMicroseconds(interval), + this, &BlinkPlatformImpl::DoTimeout); +} + +void BlinkPlatformImpl::stopSharedTimer() { + shared_timer_.Stop(); +} + +void BlinkPlatformImpl::callOnMainThread( + void (*func)(void*), void* context) { + main_loop_->PostTask(FROM_HERE, base::Bind(func, context)); +} + +const unsigned char* BlinkPlatformImpl::getTraceCategoryEnabledFlag( + const char* category_name) { + static const unsigned char buf[] = "*"; + return buf; +} + +blink::WebURLLoader* BlinkPlatformImpl::createURLLoader() { + return new WebURLLoaderImpl(network_service_.get()); +} + +blink::WebString BlinkPlatformImpl::userAgent() { + return blink::WebString::fromUTF8(kUserAgentString); +} + +blink::WebData BlinkPlatformImpl::parseDataURL( + const blink::WebURL& url, + blink::WebString& mimetype_out, + blink::WebString& charset_out) { + std::string mimetype, charset, data; + if (net::DataURL::Parse(url, &mimetype, &charset, &data) + && net::IsSupportedMimeType(mimetype)) { + mimetype_out = blink::WebString::fromUTF8(mimetype); + charset_out = blink::WebString::fromUTF8(charset); + return data; + } + return blink::WebData(); +} + +blink::WebURLError BlinkPlatformImpl::cancelledError(const blink::WebURL& url) + const { + blink::WebURLError error; + error.domain = blink::WebString::fromUTF8(net::kErrorDomain); + error.reason = net::ERR_ABORTED; + error.unreachableURL = url; + error.staleCopyInCache = false; + error.isCancellation = true; + return error; +} + +blink::WebThread* BlinkPlatformImpl::createThread(const char* name) { + return new WebThreadImpl(name); +} + +blink::WebThread* BlinkPlatformImpl::currentThread() { + WebThreadImplForMessageLoop* thread = + static_cast<WebThreadImplForMessageLoop*>(current_thread_slot_.Get()); + if (thread) + return (thread); + + scoped_refptr<base::MessageLoopProxy> message_loop = + base::MessageLoopProxy::current(); + if (!message_loop.get()) + return NULL; + + thread = new WebThreadImplForMessageLoop(message_loop.get()); + current_thread_slot_.Set(thread); + return thread; +} + +blink::WebWaitableEvent* BlinkPlatformImpl::createWaitableEvent() { + return new WebWaitableEventImpl(); +} + +blink::WebWaitableEvent* BlinkPlatformImpl::waitMultipleEvents( + const blink::WebVector<blink::WebWaitableEvent*>& web_events) { + std::vector<base::WaitableEvent*> events; + for (size_t i = 0; i < web_events.size(); ++i) + events.push_back(static_cast<WebWaitableEventImpl*>(web_events[i])->impl()); + size_t idx = base::WaitableEvent::WaitMany( + vector_as_array(&events), events.size()); + DCHECK_LT(idx, web_events.size()); + return web_events[idx]; +} + +// static +void BlinkPlatformImpl::DestroyCurrentThread(void* thread) { + WebThreadImplForMessageLoop* impl = + static_cast<WebThreadImplForMessageLoop*>(thread); + delete impl; +} + +} // namespace examples +} // namespace mojo diff --git a/mojo/examples/html_viewer/blink_platform_impl.h b/mojo/examples/html_viewer/blink_platform_impl.h new file mode 100644 index 0000000..dfe7744 --- /dev/null +++ b/mojo/examples/html_viewer/blink_platform_impl.h @@ -0,0 +1,78 @@ +// 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. + +#ifndef MOJO_EXAMPLE_HTML_VIEWER_BLINK_PLATFORM_IMPL_H_ +#define MOJO_EXAMPLE_HTML_VIEWER_BLINK_PLATFORM_IMPL_H_ + +#include "base/message_loop/message_loop.h" +#include "base/threading/thread_local_storage.h" +#include "base/timer/timer.h" +#include "mojo/examples/html_viewer/webmimeregistry_impl.h" +#include "mojo/services/public/interfaces/network/network_service.mojom.h" +#include "third_party/WebKit/public/platform/Platform.h" +#include "third_party/WebKit/public/platform/WebThemeEngine.h" + +namespace mojo { +class Application; + +namespace examples { + +class BlinkPlatformImpl : public blink::Platform { + public: + explicit BlinkPlatformImpl(Application* app); + virtual ~BlinkPlatformImpl(); + + // blink::Platform methods: + virtual blink::WebMimeRegistry* mimeRegistry(); + virtual blink::WebThemeEngine* themeEngine(); + virtual blink::WebString defaultLocale(); + virtual double currentTime(); + virtual double monotonicallyIncreasingTime(); + virtual void cryptographicallyRandomValues( + unsigned char* buffer, size_t length); + virtual void setSharedTimerFiredFunction(void (*func)()); + virtual void setSharedTimerFireInterval(double interval_seconds); + virtual void stopSharedTimer(); + virtual void callOnMainThread(void (*func)(void*), void* context); + virtual blink::WebURLLoader* createURLLoader(); + virtual blink::WebString userAgent(); + virtual blink::WebData parseDataURL( + const blink::WebURL& url, blink::WebString& mime_type, + blink::WebString& charset); + virtual blink::WebURLError cancelledError(const blink::WebURL& url) const; + virtual blink::WebThread* createThread(const char* name); + virtual blink::WebThread* currentThread(); + virtual blink::WebWaitableEvent* createWaitableEvent(); + virtual blink::WebWaitableEvent* waitMultipleEvents( + const blink::WebVector<blink::WebWaitableEvent*>& events); + virtual const unsigned char* getTraceCategoryEnabledFlag( + const char* category_name); + + private: + void SuspendSharedTimer(); + void ResumeSharedTimer(); + + void DoTimeout() { + if (shared_timer_func_ && !shared_timer_suspended_) + shared_timer_func_(); + } + + static void DestroyCurrentThread(void*); + + NetworkServicePtr network_service_; + base::MessageLoop* main_loop_; + base::OneShotTimer<BlinkPlatformImpl> shared_timer_; + void (*shared_timer_func_)(); + double shared_timer_fire_time_; + bool shared_timer_fire_time_was_set_while_suspended_; + int shared_timer_suspended_; // counter + base::ThreadLocalStorage::Slot current_thread_slot_; + blink::WebThemeEngine dummy_theme_engine_; + WebMimeRegistryImpl mime_registry_; +}; + +} // namespace examples +} // namespace mojo + +#endif // MOJO_EXAMPLE_HTML_VIEWER_BLINK_PLATFORM_IMPL_H_ diff --git a/mojo/examples/html_viewer/html_document_view.cc b/mojo/examples/html_viewer/html_document_view.cc new file mode 100644 index 0000000..868230c2 --- /dev/null +++ b/mojo/examples/html_viewer/html_document_view.cc @@ -0,0 +1,140 @@ +// 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/html_document_view.h" + +#include "base/bind.h" +#include "base/location.h" +#include "base/single_thread_task_runner.h" +#include "base/thread_task_runner_handle.h" +#include "mojo/services/public/cpp/view_manager/node.h" +#include "mojo/services/public/cpp/view_manager/view.h" +#include "skia/ext/refptr.h" +#include "third_party/WebKit/public/web/WebConsoleMessage.h" +#include "third_party/WebKit/public/web/WebDocument.h" +#include "third_party/WebKit/public/web/WebElement.h" +#include "third_party/WebKit/public/web/WebLocalFrame.h" +#include "third_party/WebKit/public/web/WebScriptSource.h" +#include "third_party/WebKit/public/web/WebSettings.h" +#include "third_party/WebKit/public/web/WebView.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkColor.h" +#include "third_party/skia/include/core/SkDevice.h" + +namespace mojo { +namespace examples { +namespace { + +blink::WebData CopyToWebData(DataPipeConsumerHandle handle) { + std::vector<char> data; + for (;;) { + char buf[4096]; + uint32_t num_bytes = sizeof(buf); + MojoResult result = ReadDataRaw( + handle, + buf, + &num_bytes, + MOJO_READ_DATA_FLAG_NONE); + if (result == MOJO_RESULT_SHOULD_WAIT) { + Wait(handle, + MOJO_HANDLE_SIGNAL_READABLE, + MOJO_DEADLINE_INDEFINITE); + } else if (result == MOJO_RESULT_OK) { + data.insert(data.end(), buf, buf + num_bytes); + } else { + break; + } + } + return blink::WebData(data); +} + +void ConfigureSettings(blink::WebSettings* settings) { + settings->setAcceleratedCompositingEnabled(false); + settings->setLoadsImagesAutomatically(true); + settings->setJavaScriptEnabled(true); +} + +} // namespace + +HTMLDocumentView::HTMLDocumentView(view_manager::ViewManager* view_manager) + : view_manager_(view_manager), + view_(view_manager::View::Create(view_manager_)), + web_view_(NULL), + repaint_pending_(false), + weak_factory_(this) { +} + +HTMLDocumentView::~HTMLDocumentView() { + if (web_view_) + web_view_->close(); +} + +void HTMLDocumentView::AttachToNode(view_manager::Node* node) { + node->SetActiveView(view_); + view_->SetColor(SK_ColorCYAN); // Dummy background color. + + web_view_ = blink::WebView::create(this); + ConfigureSettings(web_view_->settings()); + web_view_->setMainFrame(blink::WebLocalFrame::create(this)); + + // TODO(darin): Track size of view_manager::Node. + web_view_->resize(gfx::Size(800, 600)); +} + +void HTMLDocumentView::Load(URLResponsePtr response, + ScopedDataPipeConsumerHandle response_body_stream) { + DCHECK(web_view_); + + // TODO(darin): A better solution would be to use loadRequest, but intercept + // the network request and connect it to the response we already have. + blink::WebData data = CopyToWebData(response_body_stream.get()); + web_view_->mainFrame()->loadHTMLString( + data, GURL(response->url), GURL(response->url)); +} + +void HTMLDocumentView::didInvalidateRect(const blink::WebRect& rect) { + if (!repaint_pending_) { + repaint_pending_ = true; + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(&HTMLDocumentView::Repaint, weak_factory_.GetWeakPtr())); + } +} + +bool HTMLDocumentView::allowsBrokenNullLayerTreeView() const { + // TODO(darin): Switch to using compositor bindings. + // + // NOTE: Note to Blink maintainers, feel free to just break this code if it + // is the last using compositor bindings and you want to delete the old path. + // + return true; +} + +void HTMLDocumentView::didAddMessageToConsole( + const blink::WebConsoleMessage& message, + const blink::WebString& source_name, + unsigned source_line, + const blink::WebString& stack_trace) { + printf("### console: %s\n", std::string(message.text.utf8()).c_str()); +} + +void HTMLDocumentView::Repaint() { + repaint_pending_ = false; + + web_view_->animate(0.0); + web_view_->layout(); + + int width = web_view_->size().width; + int height = web_view_->size().height; + + skia::RefPtr<SkCanvas> canvas = skia::AdoptRef(SkCanvas::NewRaster( + SkImageInfo::MakeN32(width, height, kOpaque_SkAlphaType))); + + web_view_->paint(canvas.get(), gfx::Rect(0, 0, width, height)); + + view_->SetContents(canvas->getDevice()->accessBitmap(false)); +} + +} // namespace examples +} // namespace mojo diff --git a/mojo/examples/html_viewer/html_document_view.h b/mojo/examples/html_viewer/html_document_view.h new file mode 100644 index 0000000..9ad76e4 --- /dev/null +++ b/mojo/examples/html_viewer/html_document_view.h @@ -0,0 +1,62 @@ +// 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. + +#ifndef MOJO_EXAMPLES_HTML_VIEWER_HTML_DOCUMENT_VIEW_H_ +#define MOJO_EXAMPLES_HTML_VIEWER_HTML_DOCUMENT_VIEW_H_ + +#include "base/memory/weak_ptr.h" +#include "mojo/services/public/interfaces/network/url_loader.mojom.h" +#include "third_party/WebKit/public/web/WebFrameClient.h" +#include "third_party/WebKit/public/web/WebViewClient.h" + +namespace mojo { + +namespace view_manager { +class Node; +class ViewManager; +class View; +} + +namespace examples { + +// A view for a single HTML document. +class HTMLDocumentView : public blink::WebViewClient, + public blink::WebFrameClient { + public: + explicit HTMLDocumentView(view_manager::ViewManager* view_manager); + virtual ~HTMLDocumentView(); + + void AttachToNode(view_manager::Node* node); + + void Load(URLResponsePtr response, + ScopedDataPipeConsumerHandle response_body_stream); + + private: + // WebWidgetClient methods: + virtual void didInvalidateRect(const blink::WebRect& rect); + virtual bool allowsBrokenNullLayerTreeView() const; + + // WebFrameClient methods: + virtual void didAddMessageToConsole( + const blink::WebConsoleMessage& message, + const blink::WebString& source_name, + unsigned source_line, + const blink::WebString& stack_trace); + + void Repaint(); + + view_manager::ViewManager* view_manager_; + view_manager::View* view_; + blink::WebView* web_view_; + bool repaint_pending_; + + base::WeakPtrFactory<HTMLDocumentView> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(HTMLDocumentView); +}; + +} // namespace examples +} // namespace mojo + +#endif // MOJO_EXAMPLES_HTML_VIEWER_HTML_DOCUMENT_VIEW_H_ diff --git a/mojo/examples/html_viewer/html_viewer.cc b/mojo/examples/html_viewer/html_viewer.cc index 8509ed1..05bd7b5 100644 --- a/mojo/examples/html_viewer/html_viewer.cc +++ b/mojo/examples/html_viewer/html_viewer.cc @@ -2,6 +2,8 @@ // 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/blink_platform_impl.h" +#include "mojo/examples/html_viewer/html_document_view.h" #include "mojo/public/cpp/application/application.h" #include "mojo/services/public/cpp/view_manager/node.h" #include "mojo/services/public/cpp/view_manager/types.h" @@ -9,6 +11,7 @@ #include "mojo/services/public/cpp/view_manager/view_manager.h" #include "mojo/services/public/cpp/view_manager/view_manager_delegate.h" #include "mojo/services/public/interfaces/navigation/navigation.mojom.h" +#include "third_party/WebKit/public/web/WebKit.h" namespace mojo { namespace examples { @@ -25,34 +28,7 @@ class NavigatorImpl : public InterfaceImpl<navigation::Navigator> { virtual void Navigate( uint32_t node_id, navigation::NavigationDetailsPtr navigation_details, - navigation::ResponseDetailsPtr response_details) OVERRIDE { - printf("In HTMLViewer, rendering url: %s\n", - response_details->response->url.data()); - printf("HTML: \n"); - for (;;) { - char buf[512]; - uint32_t num_bytes = sizeof(buf); - MojoResult result = ReadDataRaw( - response_details->response_body_stream.get(), - buf, - &num_bytes, - MOJO_READ_DATA_FLAG_NONE); - if (result == MOJO_RESULT_SHOULD_WAIT) { - Wait(response_details->response_body_stream.get(), - MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE); - } else if (result == MOJO_RESULT_OK) { - fwrite(buf, num_bytes, 1, stdout); - } else { - break; - } - } - printf("\n>>>> EOF <<<<\n\n"); - - UpdateView(); - } - - void UpdateView(); + navigation::ResponseDetailsPtr response_details) OVERRIDE; HTMLViewer* viewer_; @@ -60,16 +36,28 @@ class NavigatorImpl : public InterfaceImpl<navigation::Navigator> { }; class HTMLViewer : public Application, - public view_manager::ViewManagerDelegate { + public view_manager::ViewManagerDelegate { public: - HTMLViewer() : content_view_(NULL) {} - virtual ~HTMLViewer() {} + HTMLViewer() : document_view_(NULL) { + } + virtual ~HTMLViewer() { + blink::shutdown(); + } - private: - friend class NavigatorImpl; + void Load(URLResponsePtr response, + ScopedDataPipeConsumerHandle response_body_stream) { + // Need to wait for OnRootAdded. + response_ = response.Pass(); + response_body_stream_ = response_body_stream.Pass(); + MaybeLoad(); + } + private: // Overridden from Application: virtual void Initialize() OVERRIDE { + blink_platform_impl_.reset(new BlinkPlatformImpl(this)); + blink::initialize(blink_platform_impl_.get()); + AddService<NavigatorImpl>(this); view_manager::ViewManager::Create(this, this); } @@ -77,18 +65,34 @@ class HTMLViewer : public Application, // Overridden from view_manager::ViewManagerDelegate: virtual void OnRootAdded(view_manager::ViewManager* view_manager, view_manager::Node* root) OVERRIDE { - content_view_ = view_manager::View::Create(view_manager); - root->SetActiveView(content_view_); - content_view_->SetColor(SK_ColorRED); + document_view_ = new HTMLDocumentView(view_manager); + document_view_->AttachToNode(root); + MaybeLoad(); } - view_manager::View* content_view_; + void MaybeLoad() { + if (document_view_ && response_.get()) + document_view_->Load(response_.Pass(), response_body_stream_.Pass()); + } + + scoped_ptr<BlinkPlatformImpl> blink_platform_impl_; + + // TODO(darin): Figure out proper ownership of this instance. + HTMLDocumentView* document_view_; + URLResponsePtr response_; + ScopedDataPipeConsumerHandle response_body_stream_; DISALLOW_COPY_AND_ASSIGN(HTMLViewer); }; -void NavigatorImpl::UpdateView() { - viewer_->content_view_->SetColor(SK_ColorGREEN); +void NavigatorImpl::Navigate( + uint32_t node_id, + navigation::NavigationDetailsPtr navigation_details, + navigation::ResponseDetailsPtr response_details) { + printf("In HTMLViewer, rendering url: %s\n", + response_details->response->url.data()); + viewer_->Load(response_details->response.Pass(), + response_details->response_body_stream.Pass()); } } diff --git a/mojo/examples/html_viewer/webmimeregistry_impl.cc b/mojo/examples/html_viewer/webmimeregistry_impl.cc new file mode 100644 index 0000000..4f4bbed --- /dev/null +++ b/mojo/examples/html_viewer/webmimeregistry_impl.cc @@ -0,0 +1,97 @@ +// 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/webmimeregistry_impl.h" + +#include "base/files/file_path.h" +#include "base/strings/string_util.h" +#include "base/strings/sys_string_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "net/base/mime_util.h" +#include "third_party/WebKit/public/platform/WebString.h" + +namespace mojo { +namespace examples { +namespace { + +std::string ToASCIIOrEmpty(const blink::WebString& string) { + return base::IsStringASCII(string) ? base::UTF16ToASCII(string) + : std::string(); +} + +} // namespace + +blink::WebMimeRegistry::SupportsType WebMimeRegistryImpl::supportsMIMEType( + const blink::WebString& mime_type) { + return net::IsSupportedMimeType(ToASCIIOrEmpty(mime_type)) ? + blink::WebMimeRegistry::IsSupported : + blink::WebMimeRegistry::IsNotSupported; +} + +blink::WebMimeRegistry::SupportsType WebMimeRegistryImpl::supportsImageMIMEType( + const blink::WebString& mime_type) { + return net::IsSupportedImageMimeType(ToASCIIOrEmpty(mime_type)) ? + blink::WebMimeRegistry::IsSupported : + blink::WebMimeRegistry::IsNotSupported; +} + +blink::WebMimeRegistry::SupportsType + WebMimeRegistryImpl::supportsJavaScriptMIMEType( + const blink::WebString& mime_type) { + return net::IsSupportedJavascriptMimeType(ToASCIIOrEmpty(mime_type)) ? + blink::WebMimeRegistry::IsSupported : + blink::WebMimeRegistry::IsNotSupported; +} + +blink::WebMimeRegistry::SupportsType WebMimeRegistryImpl::supportsMediaMIMEType( + const blink::WebString& mime_type, + const blink::WebString& codecs, + const blink::WebString& key_system) { + NOTIMPLEMENTED(); + return IsNotSupported; +} + +bool WebMimeRegistryImpl::supportsMediaSourceMIMEType( + const blink::WebString& mime_type, + const blink::WebString& codecs) { + NOTIMPLEMENTED(); + return false; +} + +bool WebMimeRegistryImpl::supportsEncryptedMediaMIMEType( + const blink::WebString& key_system, + const blink::WebString& mime_type, + const blink::WebString& codecs) { + NOTIMPLEMENTED(); + return false; +} + +blink::WebMimeRegistry::SupportsType + WebMimeRegistryImpl::supportsNonImageMIMEType( + const blink::WebString& mime_type) { + return net::IsSupportedNonImageMimeType(ToASCIIOrEmpty(mime_type)) ? + blink::WebMimeRegistry::IsSupported : + blink::WebMimeRegistry::IsNotSupported; +} + +blink::WebString WebMimeRegistryImpl::mimeTypeForExtension( + const blink::WebString& file_extension) { + NOTIMPLEMENTED(); + return blink::WebString(); +} + +blink::WebString WebMimeRegistryImpl::wellKnownMimeTypeForExtension( + const blink::WebString& file_extension) { + NOTIMPLEMENTED(); + return blink::WebString(); +} + +blink::WebString WebMimeRegistryImpl::mimeTypeFromFile( + const blink::WebString& file_path) { + NOTIMPLEMENTED(); + return blink::WebString(); +} + +} // namespace examples +} // namespace mojo diff --git a/mojo/examples/html_viewer/webmimeregistry_impl.h b/mojo/examples/html_viewer/webmimeregistry_impl.h new file mode 100644 index 0000000..ec7b577 --- /dev/null +++ b/mojo/examples/html_viewer/webmimeregistry_impl.h @@ -0,0 +1,50 @@ +// 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. + +#ifndef MOJO_EXAMPLES_HTML_VIEWER_WEBMIMEREGISTRY_IMPL_H_ +#define MOJO_EXAMPLES_HTML_VIEWER_WEBMIMEREGISTRY_IMPL_H_ + +#include "base/compiler_specific.h" +#include "third_party/WebKit/public/platform/WebMimeRegistry.h" + +namespace mojo { +namespace examples { + +class WebMimeRegistryImpl : public blink::WebMimeRegistry { + public: + WebMimeRegistryImpl() {} + virtual ~WebMimeRegistryImpl() {} + + // WebMimeRegistry methods: + virtual blink::WebMimeRegistry::SupportsType supportsMIMEType( + const blink::WebString& mime_type); + virtual blink::WebMimeRegistry::SupportsType supportsImageMIMEType( + const blink::WebString& mime_type); + virtual blink::WebMimeRegistry::SupportsType supportsJavaScriptMIMEType( + const blink::WebString& mime_type); + virtual blink::WebMimeRegistry::SupportsType supportsMediaMIMEType( + const blink::WebString& mime_type, + const blink::WebString& codecs, + const blink::WebString& key_system); + virtual bool supportsMediaSourceMIMEType( + const blink::WebString& mime_type, + const blink::WebString& codecs); + virtual bool supportsEncryptedMediaMIMEType( + const blink::WebString& key_system, + const blink::WebString& mime_type, + const blink::WebString& codecs); + virtual blink::WebMimeRegistry::SupportsType supportsNonImageMIMEType( + const blink::WebString& mime_type); + virtual blink::WebString mimeTypeForExtension( + const blink::WebString& extension); + virtual blink::WebString wellKnownMimeTypeForExtension( + const blink::WebString& extension); + virtual blink::WebString mimeTypeFromFile( + const blink::WebString& path); +}; + +} // namespace examples +} // namespace mojo + +#endif // MOJO_EXAMPLES_HTML_VIEWER_WEBMIMEREGISTRY_IMPL_H_ diff --git a/mojo/examples/html_viewer/webthread_impl.cc b/mojo/examples/html_viewer/webthread_impl.cc new file mode 100644 index 0000000..1173a25 --- /dev/null +++ b/mojo/examples/html_viewer/webthread_impl.cc @@ -0,0 +1,133 @@ +// 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. + +// An implementation of WebThread in terms of base::MessageLoop and +// base::Thread + +#include "mojo/examples/html_viewer/webthread_impl.h" + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/message_loop/message_loop.h" +#include "base/pending_task.h" +#include "base/threading/platform_thread.h" + +namespace mojo { +namespace examples { + +WebThreadBase::WebThreadBase() {} +WebThreadBase::~WebThreadBase() {} + +class WebThreadBase::TaskObserverAdapter + : public base::MessageLoop::TaskObserver { + public: + TaskObserverAdapter(WebThread::TaskObserver* observer) + : observer_(observer) {} + + virtual void WillProcessTask(const base::PendingTask& pending_task) OVERRIDE { + observer_->willProcessTask(); + } + + virtual void DidProcessTask(const base::PendingTask& pending_task) OVERRIDE { + observer_->didProcessTask(); + } + +private: + WebThread::TaskObserver* observer_; +}; + +void WebThreadBase::addTaskObserver(TaskObserver* observer) { + CHECK(isCurrentThread()); + std::pair<TaskObserverMap::iterator, bool> result = task_observer_map_.insert( + std::make_pair(observer, static_cast<TaskObserverAdapter*>(NULL))); + if (result.second) + result.first->second = new TaskObserverAdapter(observer); + base::MessageLoop::current()->AddTaskObserver(result.first->second); +} + +void WebThreadBase::removeTaskObserver(TaskObserver* observer) { + CHECK(isCurrentThread()); + TaskObserverMap::iterator iter = task_observer_map_.find(observer); + if (iter == task_observer_map_.end()) + return; + base::MessageLoop::current()->RemoveTaskObserver(iter->second); + delete iter->second; + task_observer_map_.erase(iter); +} + +WebThreadImpl::WebThreadImpl(const char* name) + : thread_(new base::Thread(name)) { + thread_->Start(); +} + +void WebThreadImpl::postTask(Task* task) { + thread_->message_loop()->PostTask( + FROM_HERE, base::Bind(&blink::WebThread::Task::run, base::Owned(task))); +} + +void WebThreadImpl::postDelayedTask(Task* task, long long delay_ms) { + thread_->message_loop()->PostDelayedTask( + FROM_HERE, + base::Bind(&blink::WebThread::Task::run, base::Owned(task)), + base::TimeDelta::FromMilliseconds(delay_ms)); +} + +void WebThreadImpl::enterRunLoop() { + CHECK(isCurrentThread()); + CHECK(!thread_->message_loop()->is_running()); // We don't support nesting. + thread_->message_loop()->Run(); +} + +void WebThreadImpl::exitRunLoop() { + CHECK(isCurrentThread()); + CHECK(thread_->message_loop()->is_running()); + thread_->message_loop()->Quit(); +} + +bool WebThreadImpl::isCurrentThread() const { + return thread_->thread_id() == base::PlatformThread::CurrentId(); +} + +WebThreadImpl::~WebThreadImpl() { + thread_->Stop(); +} + +WebThreadImplForMessageLoop::WebThreadImplForMessageLoop( + base::MessageLoopProxy* message_loop) + : message_loop_(message_loop) {} + +void WebThreadImplForMessageLoop::postTask(Task* task) { + message_loop_->PostTask( + FROM_HERE, base::Bind(&blink::WebThread::Task::run, base::Owned(task))); +} + +void WebThreadImplForMessageLoop::postDelayedTask(Task* task, + long long delay_ms) { + message_loop_->PostDelayedTask( + FROM_HERE, + base::Bind(&blink::WebThread::Task::run, base::Owned(task)), + base::TimeDelta::FromMilliseconds(delay_ms)); +} + +void WebThreadImplForMessageLoop::enterRunLoop() { + CHECK(isCurrentThread()); + // We don't support nesting. + CHECK(!base::MessageLoop::current()->is_running()); + base::MessageLoop::current()->Run(); +} + +void WebThreadImplForMessageLoop::exitRunLoop() { + CHECK(isCurrentThread()); + CHECK(base::MessageLoop::current()->is_running()); + base::MessageLoop::current()->Quit(); +} + +bool WebThreadImplForMessageLoop::isCurrentThread() const { + return message_loop_->BelongsToCurrentThread(); +} + +WebThreadImplForMessageLoop::~WebThreadImplForMessageLoop() {} + +} // namespace examples +} // namespace mojo diff --git a/mojo/examples/html_viewer/webthread_impl.h b/mojo/examples/html_viewer/webthread_impl.h new file mode 100644 index 0000000..ea068cc --- /dev/null +++ b/mojo/examples/html_viewer/webthread_impl.h @@ -0,0 +1,75 @@ +// 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. + +#ifndef MOJO_EXAMPLES_HTML_VIEWER_WEBTHREAD_IMPL_H_ +#define MOJO_EXAMPLES_HTML_VIEWER_WEBTHREAD_IMPL_H_ + +#include <map> + +#include "base/memory/scoped_ptr.h" +#include "base/threading/thread.h" +#include "third_party/WebKit/public/platform/WebThread.h" + +namespace mojo { +namespace examples { + +class WebThreadBase : public blink::WebThread { + public: + virtual ~WebThreadBase(); + + virtual void addTaskObserver(TaskObserver* observer); + virtual void removeTaskObserver(TaskObserver* observer); + + virtual bool isCurrentThread() const = 0; + + protected: + WebThreadBase(); + + private: + class TaskObserverAdapter; + + typedef std::map<TaskObserver*, TaskObserverAdapter*> TaskObserverMap; + TaskObserverMap task_observer_map_; +}; + +class WebThreadImpl : public WebThreadBase { + public: + explicit WebThreadImpl(const char* name); + virtual ~WebThreadImpl(); + + virtual void postTask(Task* task); + virtual void postDelayedTask(Task* task, long long delay_ms); + + virtual void enterRunLoop(); + virtual void exitRunLoop(); + + base::MessageLoop* message_loop() const { return thread_->message_loop(); } + + virtual bool isCurrentThread() const; + + private: + scoped_ptr<base::Thread> thread_; +}; + +class WebThreadImplForMessageLoop : public WebThreadBase { + public: + explicit WebThreadImplForMessageLoop( + base::MessageLoopProxy* message_loop); + virtual ~WebThreadImplForMessageLoop(); + + virtual void postTask(Task* task); + virtual void postDelayedTask(Task* task, long long delay_ms); + + virtual void enterRunLoop(); + virtual void exitRunLoop(); + + private: + virtual bool isCurrentThread() const; + scoped_refptr<base::MessageLoopProxy> message_loop_; +}; + +} // namespace examples +} // namespace mojo + +#endif // MOJO_EXAMPLES_HTML_VIEWER_WEBTHREAD_IMPL_H_ diff --git a/mojo/examples/html_viewer/weburlloader_impl.cc b/mojo/examples/html_viewer/weburlloader_impl.cc new file mode 100644 index 0000000..fa57e91 --- /dev/null +++ b/mojo/examples/html_viewer/weburlloader_impl.cc @@ -0,0 +1,139 @@ +// 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 diff --git a/mojo/examples/html_viewer/weburlloader_impl.h b/mojo/examples/html_viewer/weburlloader_impl.h new file mode 100644 index 0000000..3d2a570 --- /dev/null +++ b/mojo/examples/html_viewer/weburlloader_impl.h @@ -0,0 +1,60 @@ +// 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. + +#ifndef MOJO_EXAMPLE_HTML_VIEWER_WEBURLLOADER_IMPL_H_ +#define MOJO_EXAMPLE_HTML_VIEWER_WEBURLLOADER_IMPL_H_ + +#include "base/memory/weak_ptr.h" +#include "mojo/common/handle_watcher.h" +#include "mojo/services/public/interfaces/network/url_loader.mojom.h" +#include "third_party/WebKit/public/platform/WebURLLoader.h" + +namespace mojo { +class NetworkService; + +namespace examples { + +class WebURLLoaderImpl : public blink::WebURLLoader, + public URLLoaderClient { + public: + explicit WebURLLoaderImpl(NetworkService* network_service); + + private: + virtual ~WebURLLoaderImpl(); + + // blink::WebURLLoader methods: + virtual void loadSynchronously( + const blink::WebURLRequest& request, blink::WebURLResponse& response, + blink::WebURLError& error, blink::WebData& data) OVERRIDE; + virtual void loadAsynchronously( + const blink::WebURLRequest&, blink::WebURLLoaderClient* client) OVERRIDE; + virtual void cancel() OVERRIDE; + virtual void setDefersLoading(bool defers_loading) OVERRIDE; + + // URLLoaderClient methods: + virtual void OnReceivedRedirect(URLResponsePtr response, + const String& new_url, + const String& new_method) OVERRIDE; + virtual void OnReceivedResponse(URLResponsePtr response) OVERRIDE; + virtual void OnReceivedError(NetworkErrorPtr error) OVERRIDE; + virtual void OnReceivedEndOfResponseBody() OVERRIDE; + + void ReadMore(); + void WaitToReadMore(); + void OnResponseBodyStreamReady(MojoResult result); + + URLLoaderPtr url_loader_; + blink::WebURLLoaderClient* client_; + ScopedDataPipeConsumerHandle response_body_stream_; + common::HandleWatcher handle_watcher_; + + base::WeakPtrFactory<WebURLLoaderImpl> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(WebURLLoaderImpl); +}; + +} // namespace examples +} // namespace mojo + +#endif // MOJO_EXAMPLE_HTML_VIEWER_WEBURLLOADER_IMPL_H_ diff --git a/mojo/mojo_examples.gypi b/mojo/mojo_examples.gypi index 0f8d3f9..254d5fa 100644 --- a/mojo/mojo_examples.gypi +++ b/mojo/mojo_examples.gypi @@ -95,7 +95,10 @@ 'target_name': 'mojo_html_viewer', 'type': 'shared_library', 'dependencies': [ + '../net/net.gyp:net', '../skia/skia.gyp:skia', + '../third_party/WebKit/public/blink.gyp:blink', + '../url/url.gyp:url_lib', 'mojo_application', 'mojo_cpp_bindings', 'mojo_environment_chromium', @@ -106,8 +109,21 @@ 'mojo_utility', 'mojo_view_manager_lib', ], + 'include_dirs': [ + 'third_party/WebKit' + ], 'sources': [ + 'examples/html_viewer/blink_platform_impl.cc', + 'examples/html_viewer/blink_platform_impl.h', 'examples/html_viewer/html_viewer.cc', + 'examples/html_viewer/html_document_view.cc', + 'examples/html_viewer/html_document_view.h', + 'examples/html_viewer/webmimeregistry_impl.cc', + 'examples/html_viewer/webmimeregistry_impl.h', + 'examples/html_viewer/webthread_impl.cc', + 'examples/html_viewer/webthread_impl.h', + 'examples/html_viewer/weburlloader_impl.cc', + 'examples/html_viewer/weburlloader_impl.h', 'public/cpp/application/lib/mojo_main_chromium.cc', ], }, diff --git a/mojo/services/network/url_loader_impl.cc b/mojo/services/network/url_loader_impl.cc index 7ce2d52..9b0cce9 100644 --- a/mojo/services/network/url_loader_impl.cc +++ b/mojo/services/network/url_loader_impl.cc @@ -207,7 +207,7 @@ void URLLoaderImpl::ReadMore() { uint32_t num_bytes; if (!pending_write_->BeginWrite(&num_bytes)) - CHECK(false); // Oops! + CHECK(false); // Oops! TODO(darin): crbug/386877: The pipe might be full! if (num_bytes > static_cast<uint32_t>(std::numeric_limits<int>::max())) CHECK(false); // Oops! |