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.
5 #include "components/html_viewer/blink_platform_impl.h"
9 #include "base/command_line.h"
10 #include "base/rand_util.h"
11 #include "base/stl_util.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "base/threading/platform_thread.h"
15 #include "base/time/time.h"
16 #include "components/html_viewer/blink_resource_constants.h"
17 #include "components/html_viewer/web_clipboard_impl.h"
18 #include "components/html_viewer/web_cookie_jar_impl.h"
19 #include "components/html_viewer/web_message_port_channel_impl.h"
20 #include "components/html_viewer/web_socket_handle_impl.h"
21 #include "components/html_viewer/web_url_loader_impl.h"
22 #include "components/mime_util/mime_util.h"
23 #include "components/scheduler/child/webthread_impl_for_worker_scheduler.h"
24 #include "components/scheduler/renderer/renderer_scheduler.h"
25 #include "components/scheduler/renderer/webthread_impl_for_renderer_scheduler.h"
26 #include "mojo/application/public/cpp/application_impl.h"
27 #include "mojo/application/public/cpp/connect.h"
28 #include "mojo/common/user_agent.h"
29 #include "net/base/data_url.h"
30 #include "net/base/net_errors.h"
31 #include "net/base/net_util.h"
32 #include "third_party/WebKit/public/platform/WebWaitableEvent.h"
33 #include "ui/events/gestures/blink/web_gesture_curve_impl.h"
35 namespace html_viewer
{
38 // Allows overriding user agent scring.
39 const char kUserAgentSwitch
[] = "user-agent";
41 class WebWaitableEventImpl
: public blink::WebWaitableEvent
{
43 WebWaitableEventImpl() : impl_(new base::WaitableEvent(false, false)) {}
44 ~WebWaitableEventImpl() override
{}
46 void wait() override
{ impl_
->Wait(); }
47 void signal() override
{ impl_
->Signal(); }
49 base::WaitableEvent
* impl() {
54 scoped_ptr
<base::WaitableEvent
> impl_
;
55 DISALLOW_COPY_AND_ASSIGN(WebWaitableEventImpl
);
60 BlinkPlatformImpl::BlinkPlatformImpl(
61 mojo::ApplicationImpl
* app
,
62 scheduler::RendererScheduler
* renderer_scheduler
)
63 : main_thread_task_runner_(renderer_scheduler
->DefaultTaskRunner()),
65 new scheduler::WebThreadImplForRendererScheduler(renderer_scheduler
)),
66 shared_timer_func_(NULL
),
67 shared_timer_fire_time_(0.0),
68 shared_timer_fire_time_was_set_while_suspended_(false),
69 shared_timer_suspended_(0) {
71 mojo::URLRequestPtr
request(mojo::URLRequest::New());
72 request
->url
= mojo::String::From("mojo:network_service");
73 app
->ConnectToService(request
.Pass(), &network_service_
);
75 mojo::CookieStorePtr cookie_store
;
76 network_service_
->GetCookieStore(GetProxy(&cookie_store
));
77 cookie_jar_
.reset(new WebCookieJarImpl(cookie_store
.Pass()));
79 mojo::ClipboardPtr clipboard
;
80 mojo::URLRequestPtr
request2(mojo::URLRequest::New());
81 request2
->url
= mojo::String::From("mojo:clipboard");
82 app
->ConnectToService(request2
.Pass(), &clipboard
);
83 clipboard_
.reset(new WebClipboardImpl(clipboard
.Pass()));
85 shared_timer_
.SetTaskRunner(main_thread_task_runner_
);
88 BlinkPlatformImpl::~BlinkPlatformImpl() {
91 blink::WebCookieJar
* BlinkPlatformImpl::cookieJar() {
92 return cookie_jar_
.get();
95 blink::WebClipboard
* BlinkPlatformImpl::clipboard() {
96 return clipboard_
.get();
99 blink::WebMimeRegistry
* BlinkPlatformImpl::mimeRegistry() {
100 return &mime_registry_
;
103 blink::WebThemeEngine
* BlinkPlatformImpl::themeEngine() {
104 return &theme_engine_
;
107 blink::WebString
BlinkPlatformImpl::defaultLocale() {
108 return blink::WebString::fromUTF8("en-US");
111 blink::WebBlobRegistry
* BlinkPlatformImpl::blobRegistry() {
112 return &blob_registry_
;
115 double BlinkPlatformImpl::currentTime() {
116 return base::Time::Now().ToDoubleT();
119 double BlinkPlatformImpl::monotonicallyIncreasingTime() {
120 return base::TimeTicks::Now().ToInternalValue() /
121 static_cast<double>(base::Time::kMicrosecondsPerSecond
);
124 void BlinkPlatformImpl::cryptographicallyRandomValues(unsigned char* buffer
,
126 base::RandBytes(buffer
, length
);
129 void BlinkPlatformImpl::setSharedTimerFiredFunction(void (*func
)()) {
130 shared_timer_func_
= func
;
133 void BlinkPlatformImpl::setSharedTimerFireInterval(
134 double interval_seconds
) {
135 shared_timer_fire_time_
= interval_seconds
+ monotonicallyIncreasingTime();
136 if (shared_timer_suspended_
) {
137 shared_timer_fire_time_was_set_while_suspended_
= true;
141 // By converting between double and int64 representation, we run the risk
142 // of losing precision due to rounding errors. Performing computations in
143 // microseconds reduces this risk somewhat. But there still is the potential
144 // of us computing a fire time for the timer that is shorter than what we
146 // As the event loop will check event deadlines prior to actually firing
147 // them, there is a risk of needlessly rescheduling events and of
148 // needlessly looping if sleep times are too short even by small amounts.
149 // This results in measurable performance degradation unless we use ceil() to
150 // always round up the sleep times.
151 int64 interval
= static_cast<int64
>(
152 ceil(interval_seconds
* base::Time::kMillisecondsPerSecond
)
153 * base::Time::kMicrosecondsPerMillisecond
);
158 shared_timer_
.Stop();
159 shared_timer_
.Start(FROM_HERE
, base::TimeDelta::FromMicroseconds(interval
),
160 this, &BlinkPlatformImpl::DoTimeout
);
163 void BlinkPlatformImpl::stopSharedTimer() {
164 shared_timer_
.Stop();
167 bool BlinkPlatformImpl::isThreadedCompositingEnabled() {
171 blink::WebCompositorSupport
* BlinkPlatformImpl::compositorSupport() {
172 return &compositor_support_
;
175 void BlinkPlatformImpl::createMessageChannel(
176 blink::WebMessagePortChannel
** channel1
,
177 blink::WebMessagePortChannel
** channel2
) {
178 WebMessagePortChannelImpl::CreatePair(channel1
, channel2
);
181 blink::WebScrollbarBehavior
* BlinkPlatformImpl::scrollbarBehavior() {
182 return &scrollbar_behavior_
;
185 const unsigned char* BlinkPlatformImpl::getTraceCategoryEnabledFlag(
186 const char* category_name
) {
187 static const unsigned char buf
[] = "*";
191 blink::WebData
BlinkPlatformImpl::loadResource(const char* resource
) {
192 for (size_t i
= 0; i
< arraysize(kDataResources
); ++i
) {
193 if (!strcmp(resource
, kDataResources
[i
].name
)) {
195 const unsigned char* data
=
196 blink_resource_map_
.GetResource(kDataResources
[i
].id
, &length
);
197 CHECK(data
!= nullptr && length
> 0);
198 return blink::WebData(reinterpret_cast<const char*>(data
), length
);
201 NOTREACHED() << "Requested resource is unavailable: " << resource
;
202 return blink::WebData();
205 blink::WebURLLoader
* BlinkPlatformImpl::createURLLoader() {
206 return new WebURLLoaderImpl(network_service_
.get(), &blob_registry_
);
209 blink::WebSocketHandle
* BlinkPlatformImpl::createWebSocketHandle() {
210 return new WebSocketHandleImpl(network_service_
.get());
213 blink::WebString
BlinkPlatformImpl::userAgent() {
214 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
215 if (command_line
->HasSwitch(kUserAgentSwitch
)) {
216 return blink::WebString::fromUTF8(
217 command_line
->GetSwitchValueASCII(kUserAgentSwitch
));
219 return blink::WebString::fromUTF8(mojo::common::GetUserAgent());
222 blink::WebData
BlinkPlatformImpl::parseDataURL(
223 const blink::WebURL
& url
,
224 blink::WebString
& mimetype_out
,
225 blink::WebString
& charset_out
) {
226 std::string mimetype
, charset
, data
;
227 if (net::DataURL::Parse(url
, &mimetype
, &charset
, &data
) &&
228 mime_util::IsSupportedMimeType(mimetype
)) {
229 mimetype_out
= blink::WebString::fromUTF8(mimetype
);
230 charset_out
= blink::WebString::fromUTF8(charset
);
233 return blink::WebData();
236 blink::WebURLError
BlinkPlatformImpl::cancelledError(const blink::WebURL
& url
)
238 blink::WebURLError error
;
239 error
.domain
= blink::WebString::fromUTF8(net::kErrorDomain
);
240 error
.reason
= net::ERR_ABORTED
;
241 error
.unreachableURL
= url
;
242 error
.staleCopyInCache
= false;
243 error
.isCancellation
= true;
247 bool BlinkPlatformImpl::isReservedIPAddress(
248 const blink::WebString
& host
) const {
249 net::IPAddressNumber address
;
250 if (!net::ParseURLHostnameToNumber(host
.utf8(), &address
))
252 return net::IsIPAddressReserved(address
);
255 blink::WebThread
* BlinkPlatformImpl::createThread(const char* name
) {
256 scheduler::WebThreadImplForWorkerScheduler
* thread
=
257 new scheduler::WebThreadImplForWorkerScheduler(name
);
258 thread
->TaskRunner()->PostTask(
259 FROM_HERE
, base::Bind(&BlinkPlatformImpl::UpdateWebThreadTLS
,
260 base::Unretained(this), thread
));
264 blink::WebThread
* BlinkPlatformImpl::currentThread() {
265 if (main_thread_
->isCurrentThread())
266 return main_thread_
.get();
267 return static_cast<blink::WebThread
*>(current_thread_slot_
.Get());
270 void BlinkPlatformImpl::yieldCurrentThread() {
271 base::PlatformThread::YieldCurrentThread();
274 blink::WebWaitableEvent
* BlinkPlatformImpl::createWaitableEvent() {
275 return new WebWaitableEventImpl();
278 blink::WebWaitableEvent
* BlinkPlatformImpl::waitMultipleEvents(
279 const blink::WebVector
<blink::WebWaitableEvent
*>& web_events
) {
280 std::vector
<base::WaitableEvent
*> events
;
281 for (size_t i
= 0; i
< web_events
.size(); ++i
)
282 events
.push_back(static_cast<WebWaitableEventImpl
*>(web_events
[i
])->impl());
283 size_t idx
= base::WaitableEvent::WaitMany(
284 vector_as_array(&events
), events
.size());
285 DCHECK_LT(idx
, web_events
.size());
286 return web_events
[idx
];
289 blink::WebGestureCurve
* BlinkPlatformImpl::createFlingAnimationCurve(
290 blink::WebGestureDevice device_source
,
291 const blink::WebFloatPoint
& velocity
,
292 const blink::WebSize
& cumulative_scroll
) {
293 const bool is_main_thread
= true;
294 return ui::WebGestureCurveImpl::CreateFromDefaultPlatformCurve(
295 gfx::Vector2dF(velocity
.x
, velocity
.y
),
296 gfx::Vector2dF(cumulative_scroll
.width
, cumulative_scroll
.height
),
297 is_main_thread
).release();
300 blink::WebCrypto
* BlinkPlatformImpl::crypto() {
304 blink::WebNotificationManager
*
305 BlinkPlatformImpl::notificationManager() {
306 return &web_notification_manager_
;
309 void BlinkPlatformImpl::UpdateWebThreadTLS(blink::WebThread
* thread
) {
310 DCHECK(!current_thread_slot_
.Get());
311 current_thread_slot_
.Set(thread
);
314 } // namespace html_viewer