// 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/services/html_viewer/blink_platform_impl.h" #include #include "base/rand_util.h" #include "base/stl_util.h" #include "base/synchronization/waitable_event.h" #include "base/threading/platform_thread.h" #include "base/time/time.h" #include "mojo/services/html_viewer/blink_resource_constants.h" #include "mojo/services/html_viewer/webthread_impl.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 html_viewer { 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 impl_; DISALLOW_COPY_AND_ASSIGN(WebWaitableEventImpl); }; } // namespace BlinkPlatformImpl::BlinkPlatformImpl() : 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) { } BlinkPlatformImpl::~BlinkPlatformImpl() { } blink::WebMimeRegistry* BlinkPlatformImpl::mimeRegistry() { return &mime_registry_; } blink::WebThemeEngine* BlinkPlatformImpl::themeEngine() { return &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(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( 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)); } bool BlinkPlatformImpl::isThreadedCompositingEnabled() { return true; } blink::WebCompositorSupport* BlinkPlatformImpl::compositorSupport() { return &compositor_support_; } blink::WebScrollbarBehavior* BlinkPlatformImpl::scrollbarBehavior() { return &scrollbar_behavior_; } const unsigned char* BlinkPlatformImpl::getTraceCategoryEnabledFlag( const char* category_name) { static const unsigned char buf[] = "*"; return buf; } blink::WebData BlinkPlatformImpl::loadResource(const char* resource) { for (size_t i = 0; i < arraysize(kDataResources); ++i) { if (!strcmp(resource, kDataResources[i].name)) { int length; const char* data = blink_resource_map_.GetResource(kDataResources[i].id, &length); CHECK(data != nullptr && length > 0); return blink::WebData(data, length); } } NOTREACHED() << "Requested resource is unavailable!"; return blink::WebData(); } blink::WebURLLoader* BlinkPlatformImpl::createURLLoader() { return NULL; } blink::WebSocketHandle* BlinkPlatformImpl::createWebSocketHandle() { return NULL; } 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(current_thread_slot_.Get()); if (thread) return (thread); scoped_refptr message_loop = base::MessageLoopProxy::current(); if (!message_loop.get()) return NULL; thread = new WebThreadImplForMessageLoop(message_loop.get()); current_thread_slot_.Set(thread); return thread; } void BlinkPlatformImpl::yieldCurrentThread() { base::PlatformThread::YieldCurrentThread(); } blink::WebWaitableEvent* BlinkPlatformImpl::createWaitableEvent() { return new WebWaitableEventImpl(); } blink::WebWaitableEvent* BlinkPlatformImpl::waitMultipleEvents( const blink::WebVector& web_events) { std::vector events; for (size_t i = 0; i < web_events.size(); ++i) events.push_back(static_cast(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(thread); delete impl; } } // namespace html_viewer