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 25namespace mojo { 26namespace { 27 28// TODO(darin): Figure out what our UA should really be. 29const 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 33class 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 52BlinkPlatformImpl::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 70BlinkPlatformImpl::~BlinkPlatformImpl() { 71} 72 73blink::WebCookieJar* BlinkPlatformImpl::cookieJar() { 74 return cookie_jar_.get(); 75} 76 77blink::WebClipboard* BlinkPlatformImpl::clipboard() { 78 return clipboard_.get(); 79} 80 81blink::WebMimeRegistry* BlinkPlatformImpl::mimeRegistry() { 82 return &mime_registry_; 83} 84 85blink::WebThemeEngine* BlinkPlatformImpl::themeEngine() { 86 return &theme_engine_; 87} 88 89blink::WebString BlinkPlatformImpl::defaultLocale() { 90 return blink::WebString::fromUTF8("en-US"); 91} 92 93double BlinkPlatformImpl::currentTime() { 94 return base::Time::Now().ToDoubleT(); 95} 96 97double BlinkPlatformImpl::monotonicallyIncreasingTime() { 98 return base::TimeTicks::Now().ToInternalValue() / 99 static_cast<double>(base::Time::kMicrosecondsPerSecond); 100} 101 102void BlinkPlatformImpl::cryptographicallyRandomValues(unsigned char* buffer, 103 size_t length) { 104 base::RandBytes(buffer, length); 105} 106 107void BlinkPlatformImpl::setSharedTimerFiredFunction(void (*func)()) { 108 shared_timer_func_ = func; 109} 110 111void 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 141void BlinkPlatformImpl::stopSharedTimer() { 142 shared_timer_.Stop(); 143} 144 145void BlinkPlatformImpl::callOnMainThread( 146 void (*func)(void*), void* context) { 147 main_loop_->PostTask(FROM_HERE, base::Bind(func, context)); 148} 149 150bool BlinkPlatformImpl::isThreadedCompositingEnabled() { 151 return true; 152} 153 154blink::WebCompositorSupport* BlinkPlatformImpl::compositorSupport() { 155 return &compositor_support_; 156} 157 158blink::WebScrollbarBehavior* BlinkPlatformImpl::scrollbarBehavior() { 159 return &scrollbar_behavior_; 160} 161 162const unsigned char* BlinkPlatformImpl::getTraceCategoryEnabledFlag( 163 const char* category_name) { 164 static const unsigned char buf[] = "*"; 165 return buf; 166} 167 168blink::WebURLLoader* BlinkPlatformImpl::createURLLoader() { 169 return new WebURLLoaderImpl(network_service_.get()); 170} 171 172blink::WebSocketHandle* BlinkPlatformImpl::createWebSocketHandle() { 173 return new WebSocketHandleImpl(network_service_.get()); 174} 175 176blink::WebString BlinkPlatformImpl::userAgent() { 177 return blink::WebString::fromUTF8(kUserAgentString); 178} 179 180blink::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 194blink::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 205blink::WebThread* BlinkPlatformImpl::createThread(const char* name) { 206 return new WebThreadImpl(name); 207} 208 209blink::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 225void BlinkPlatformImpl::yieldCurrentThread() { 226 base::PlatformThread::YieldCurrentThread(); 227} 228 229blink::WebWaitableEvent* BlinkPlatformImpl::createWaitableEvent() { 230 return new WebWaitableEventImpl(); 231} 232 233blink::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 245void BlinkPlatformImpl::DestroyCurrentThread(void* thread) { 246 WebThreadImplForMessageLoop* impl = 247 static_cast<WebThreadImplForMessageLoop*>(thread); 248 delete impl; 249} 250 251} // namespace mojo 252