Home | History | Annotate | Download | only in html_viewer
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "mojo/services/html_viewer/blink_platform_impl.h"
      6 
      7 #include <cmath>
      8 
      9 #include "base/rand_util.h"
     10 #include "base/stl_util.h"
     11 #include "base/synchronization/waitable_event.h"
     12 #include "base/threading/platform_thread.h"
     13 #include "base/time/time.h"
     14 #include "mojo/public/cpp/application/application_impl.h"
     15 #include "mojo/services/html_viewer/webclipboard_impl.h"
     16 #include "mojo/services/html_viewer/webcookiejar_impl.h"
     17 #include "mojo/services/html_viewer/websockethandle_impl.h"
     18 #include "mojo/services/html_viewer/webthread_impl.h"
     19 #include "mojo/services/html_viewer/weburlloader_impl.h"
     20 #include "net/base/data_url.h"
     21 #include "net/base/mime_util.h"
     22 #include "net/base/net_errors.h"
     23 #include "third_party/WebKit/public/platform/WebWaitableEvent.h"
     24 
     25 namespace mojo {
     26 namespace {
     27 
     28 // TODO(darin): Figure out what our UA should really be.
     29 const char kUserAgentString[] =
     30   "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) "
     31   "Chrome/35.0.1916.153 Safari/537.36";
     32 
     33 class WebWaitableEventImpl : public blink::WebWaitableEvent {
     34  public:
     35   WebWaitableEventImpl() : impl_(new base::WaitableEvent(false, false)) {}
     36   virtual ~WebWaitableEventImpl() {}
     37 
     38   virtual void wait() { impl_->Wait(); }
     39   virtual void signal() { impl_->Signal(); }
     40 
     41   base::WaitableEvent* impl() {
     42     return impl_.get();
     43   }
     44 
     45  private:
     46   scoped_ptr<base::WaitableEvent> impl_;
     47   DISALLOW_COPY_AND_ASSIGN(WebWaitableEventImpl);
     48 };
     49 
     50 }  // namespace
     51 
     52 BlinkPlatformImpl::BlinkPlatformImpl(ApplicationImpl* app)
     53     : main_loop_(base::MessageLoop::current()),
     54       shared_timer_func_(NULL),
     55       shared_timer_fire_time_(0.0),
     56       shared_timer_fire_time_was_set_while_suspended_(false),
     57       shared_timer_suspended_(0),
     58       current_thread_slot_(&DestroyCurrentThread) {
     59   app->ConnectToService("mojo:mojo_network_service", &network_service_);
     60 
     61   CookieStorePtr cookie_store;
     62   network_service_->GetCookieStore(Get(&cookie_store));
     63   cookie_jar_.reset(new WebCookieJarImpl(cookie_store.Pass()));
     64 
     65   ClipboardPtr clipboard;
     66   app->ConnectToService("mojo:mojo_clipboard", &clipboard);
     67   clipboard_.reset(new WebClipboardImpl(clipboard.Pass()));
     68 }
     69 
     70 BlinkPlatformImpl::~BlinkPlatformImpl() {
     71 }
     72 
     73 blink::WebCookieJar* BlinkPlatformImpl::cookieJar() {
     74   return cookie_jar_.get();
     75 }
     76 
     77 blink::WebClipboard* BlinkPlatformImpl::clipboard() {
     78   return clipboard_.get();
     79 }
     80 
     81 blink::WebMimeRegistry* BlinkPlatformImpl::mimeRegistry() {
     82   return &mime_registry_;
     83 }
     84 
     85 blink::WebThemeEngine* BlinkPlatformImpl::themeEngine() {
     86   return &theme_engine_;
     87 }
     88 
     89 blink::WebString BlinkPlatformImpl::defaultLocale() {
     90   return blink::WebString::fromUTF8("en-US");
     91 }
     92 
     93 double BlinkPlatformImpl::currentTime() {
     94   return base::Time::Now().ToDoubleT();
     95 }
     96 
     97 double BlinkPlatformImpl::monotonicallyIncreasingTime() {
     98   return base::TimeTicks::Now().ToInternalValue() /
     99       static_cast<double>(base::Time::kMicrosecondsPerSecond);
    100 }
    101 
    102 void BlinkPlatformImpl::cryptographicallyRandomValues(unsigned char* buffer,
    103                                                       size_t length) {
    104   base::RandBytes(buffer, length);
    105 }
    106 
    107 void BlinkPlatformImpl::setSharedTimerFiredFunction(void (*func)()) {
    108   shared_timer_func_ = func;
    109 }
    110 
    111 void BlinkPlatformImpl::setSharedTimerFireInterval(
    112     double interval_seconds) {
    113   shared_timer_fire_time_ = interval_seconds + monotonicallyIncreasingTime();
    114   if (shared_timer_suspended_) {
    115     shared_timer_fire_time_was_set_while_suspended_ = true;
    116     return;
    117   }
    118 
    119   // By converting between double and int64 representation, we run the risk
    120   // of losing precision due to rounding errors. Performing computations in
    121   // microseconds reduces this risk somewhat. But there still is the potential
    122   // of us computing a fire time for the timer that is shorter than what we
    123   // need.
    124   // As the event loop will check event deadlines prior to actually firing
    125   // them, there is a risk of needlessly rescheduling events and of
    126   // needlessly looping if sleep times are too short even by small amounts.
    127   // This results in measurable performance degradation unless we use ceil() to
    128   // always round up the sleep times.
    129   int64 interval = static_cast<int64>(
    130       ceil(interval_seconds * base::Time::kMillisecondsPerSecond)
    131       * base::Time::kMicrosecondsPerMillisecond);
    132 
    133   if (interval < 0)
    134     interval = 0;
    135 
    136   shared_timer_.Stop();
    137   shared_timer_.Start(FROM_HERE, base::TimeDelta::FromMicroseconds(interval),
    138                       this, &BlinkPlatformImpl::DoTimeout);
    139 }
    140 
    141 void BlinkPlatformImpl::stopSharedTimer() {
    142   shared_timer_.Stop();
    143 }
    144 
    145 void BlinkPlatformImpl::callOnMainThread(
    146     void (*func)(void*), void* context) {
    147   main_loop_->PostTask(FROM_HERE, base::Bind(func, context));
    148 }
    149 
    150 bool BlinkPlatformImpl::isThreadedCompositingEnabled() {
    151   return true;
    152 }
    153 
    154 blink::WebCompositorSupport* BlinkPlatformImpl::compositorSupport() {
    155   return &compositor_support_;
    156 }
    157 
    158 blink::WebScrollbarBehavior* BlinkPlatformImpl::scrollbarBehavior() {
    159   return &scrollbar_behavior_;
    160 }
    161 
    162 const unsigned char* BlinkPlatformImpl::getTraceCategoryEnabledFlag(
    163     const char* category_name) {
    164   static const unsigned char buf[] = "*";
    165   return buf;
    166 }
    167 
    168 blink::WebURLLoader* BlinkPlatformImpl::createURLLoader() {
    169   return new WebURLLoaderImpl(network_service_.get());
    170 }
    171 
    172 blink::WebSocketHandle* BlinkPlatformImpl::createWebSocketHandle() {
    173   return new WebSocketHandleImpl(network_service_.get());
    174 }
    175 
    176 blink::WebString BlinkPlatformImpl::userAgent() {
    177   return blink::WebString::fromUTF8(kUserAgentString);
    178 }
    179 
    180 blink::WebData BlinkPlatformImpl::parseDataURL(
    181     const blink::WebURL& url,
    182     blink::WebString& mimetype_out,
    183     blink::WebString& charset_out) {
    184   std::string mimetype, charset, data;
    185   if (net::DataURL::Parse(url, &mimetype, &charset, &data)
    186       && net::IsSupportedMimeType(mimetype)) {
    187     mimetype_out = blink::WebString::fromUTF8(mimetype);
    188     charset_out = blink::WebString::fromUTF8(charset);
    189     return data;
    190   }
    191   return blink::WebData();
    192 }
    193 
    194 blink::WebURLError BlinkPlatformImpl::cancelledError(const blink::WebURL& url)
    195     const {
    196   blink::WebURLError error;
    197   error.domain = blink::WebString::fromUTF8(net::kErrorDomain);
    198   error.reason = net::ERR_ABORTED;
    199   error.unreachableURL = url;
    200   error.staleCopyInCache = false;
    201   error.isCancellation = true;
    202   return error;
    203 }
    204 
    205 blink::WebThread* BlinkPlatformImpl::createThread(const char* name) {
    206   return new WebThreadImpl(name);
    207 }
    208 
    209 blink::WebThread* BlinkPlatformImpl::currentThread() {
    210   WebThreadImplForMessageLoop* thread =
    211       static_cast<WebThreadImplForMessageLoop*>(current_thread_slot_.Get());
    212   if (thread)
    213     return (thread);
    214 
    215   scoped_refptr<base::MessageLoopProxy> message_loop =
    216       base::MessageLoopProxy::current();
    217   if (!message_loop.get())
    218     return NULL;
    219 
    220   thread = new WebThreadImplForMessageLoop(message_loop.get());
    221   current_thread_slot_.Set(thread);
    222   return thread;
    223 }
    224 
    225 void BlinkPlatformImpl::yieldCurrentThread() {
    226   base::PlatformThread::YieldCurrentThread();
    227 }
    228 
    229 blink::WebWaitableEvent* BlinkPlatformImpl::createWaitableEvent() {
    230   return new WebWaitableEventImpl();
    231 }
    232 
    233 blink::WebWaitableEvent* BlinkPlatformImpl::waitMultipleEvents(
    234     const blink::WebVector<blink::WebWaitableEvent*>& web_events) {
    235   std::vector<base::WaitableEvent*> events;
    236   for (size_t i = 0; i < web_events.size(); ++i)
    237     events.push_back(static_cast<WebWaitableEventImpl*>(web_events[i])->impl());
    238   size_t idx = base::WaitableEvent::WaitMany(
    239       vector_as_array(&events), events.size());
    240   DCHECK_LT(idx, web_events.size());
    241   return web_events[idx];
    242 }
    243 
    244 // static
    245 void BlinkPlatformImpl::DestroyCurrentThread(void* thread) {
    246   WebThreadImplForMessageLoop* impl =
    247       static_cast<WebThreadImplForMessageLoop*>(thread);
    248   delete impl;
    249 }
    250 
    251 }  // namespace mojo
    252