Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / renderer / renderer_webkitplatformsupport_impl.cc
1 // Copyright (c) 2012 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 "content/renderer/renderer_webkitplatformsupport_impl.h"
6
7 #include "base/command_line.h"
8 #include "base/files/file_path.h"
9 #include "base/lazy_instance.h"
10 #include "base/memory/shared_memory.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "base/metrics/histogram.h"
13 #include "base/numerics/safe_conversions.h"
14 #include "base/platform_file.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "content/child/blink_glue.h"
18 #include "content/child/database_util.h"
19 #include "content/child/fileapi/webfilesystem_impl.h"
20 #include "content/child/indexed_db/webidbfactory_impl.h"
21 #include "content/child/npapi/npobject_util.h"
22 #include "content/child/quota_dispatcher.h"
23 #include "content/child/quota_message_filter.h"
24 #include "content/child/simple_webmimeregistry_impl.h"
25 #include "content/child/thread_safe_sender.h"
26 #include "content/child/web_database_observer_impl.h"
27 #include "content/child/webblobregistry_impl.h"
28 #include "content/child/webfileutilities_impl.h"
29 #include "content/child/webmessageportchannel_impl.h"
30 #include "content/common/file_utilities_messages.h"
31 #include "content/common/gpu/client/context_provider_command_buffer.h"
32 #include "content/common/gpu/client/gpu_channel_host.h"
33 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
34 #include "content/common/gpu/gpu_process_launch_causes.h"
35 #include "content/common/mime_registry_messages.h"
36 #include "content/common/screen_orientation_messages.h"
37 #include "content/common/view_messages.h"
38 #include "content/public/common/content_switches.h"
39 #include "content/public/common/webplugininfo.h"
40 #include "content/public/renderer/content_renderer_client.h"
41 #include "content/renderer/device_sensors/device_motion_event_pump.h"
42 #include "content/renderer/device_sensors/device_orientation_event_pump.h"
43 #include "content/renderer/dom_storage/webstoragenamespace_impl.h"
44 #include "content/renderer/gamepad_shared_memory_reader.h"
45 #include "content/renderer/media/audio_decoder.h"
46 #include "content/renderer/media/crypto/key_systems.h"
47 #include "content/renderer/media/media_stream_dependency_factory.h"
48 #include "content/renderer/media/renderer_webaudiodevice_impl.h"
49 #include "content/renderer/media/renderer_webmidiaccessor_impl.h"
50 #include "content/renderer/media/webcontentdecryptionmodule_impl.h"
51 #include "content/renderer/render_thread_impl.h"
52 #include "content/renderer/renderer_clipboard_client.h"
53 #include "content/renderer/screen_orientation/screen_orientation_dispatcher.h"
54 #include "content/renderer/webclipboard_impl.h"
55 #include "content/renderer/webgraphicscontext3d_provider_impl.h"
56 #include "content/renderer/webpublicsuffixlist_impl.h"
57 #include "gpu/config/gpu_info.h"
58 #include "ipc/ipc_sync_message_filter.h"
59 #include "media/audio/audio_output_device.h"
60 #include "media/base/audio_hardware_config.h"
61 #include "media/filters/stream_parser_factory.h"
62 #include "net/base/mime_util.h"
63 #include "net/base/net_util.h"
64 #include "third_party/WebKit/public/platform/WebBlobRegistry.h"
65 #include "third_party/WebKit/public/platform/WebDeviceMotionListener.h"
66 #include "third_party/WebKit/public/platform/WebDeviceOrientationListener.h"
67 #include "third_party/WebKit/public/platform/WebFileInfo.h"
68 #include "third_party/WebKit/public/platform/WebGamepads.h"
69 #include "third_party/WebKit/public/platform/WebMediaStreamCenter.h"
70 #include "third_party/WebKit/public/platform/WebMediaStreamCenterClient.h"
71 #include "third_party/WebKit/public/platform/WebPluginListBuilder.h"
72 #include "third_party/WebKit/public/platform/WebScreenOrientationListener.h"
73 #include "third_party/WebKit/public/platform/WebURL.h"
74 #include "third_party/WebKit/public/platform/WebVector.h"
75 #include "ui/gfx/color_profile.h"
76 #include "url/gurl.h"
77 #include "webkit/common/gpu/context_provider_web_context.h"
78 #include "webkit/common/quota/quota_types.h"
79
80 #if defined(OS_ANDROID)
81 #include "content/renderer/android/synchronous_compositor_factory.h"
82 #include "content/renderer/media/android/audio_decoder_android.h"
83 #endif
84
85 #if defined(OS_MACOSX)
86 #include "content/common/mac/font_descriptor.h"
87 #include "content/common/mac/font_loader.h"
88 #include "content/renderer/webscrollbarbehavior_impl_mac.h"
89 #include "third_party/WebKit/public/platform/mac/WebSandboxSupport.h"
90 #endif
91
92 #if defined(OS_POSIX)
93 #include "base/file_descriptor_posix.h"
94 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
95 #include <map>
96 #include <string>
97
98 #include "base/synchronization/lock.h"
99 #include "content/common/child_process_sandbox_support_impl_linux.h"
100 #include "third_party/WebKit/public/platform/linux/WebFontFamily.h"
101 #include "third_party/WebKit/public/platform/linux/WebSandboxSupport.h"
102 #include "third_party/icu/source/common/unicode/utf16.h"
103 #endif
104 #endif
105
106 #if defined(OS_WIN)
107 #include "content/common/child_process_messages.h"
108 #include "third_party/WebKit/public/platform/win/WebSandboxSupport.h"
109 #endif
110
111 #if defined(USE_AURA)
112 #include "content/renderer/webscrollbarbehavior_impl_gtkoraura.h"
113 #elif !defined(OS_MACOSX)
114 #include "third_party/WebKit/public/platform/WebScrollbarBehavior.h"
115 #define WebScrollbarBehaviorImpl blink::WebScrollbarBehavior
116 #endif
117
118 using blink::Platform;
119 using blink::WebAudioDevice;
120 using blink::WebBlobRegistry;
121 using blink::WebDatabaseObserver;
122 using blink::WebFileInfo;
123 using blink::WebFileSystem;
124 using blink::WebGamepad;
125 using blink::WebGamepads;
126 using blink::WebIDBFactory;
127 using blink::WebMIDIAccessor;
128 using blink::WebMediaStreamCenter;
129 using blink::WebMediaStreamCenterClient;
130 using blink::WebMimeRegistry;
131 using blink::WebRTCPeerConnectionHandler;
132 using blink::WebRTCPeerConnectionHandlerClient;
133 using blink::WebStorageNamespace;
134 using blink::WebString;
135 using blink::WebURL;
136 using blink::WebVector;
137
138 namespace content {
139
140 static bool g_sandbox_enabled = true;
141 static blink::WebGamepadListener* web_gamepad_listener = NULL;
142 base::LazyInstance<WebGamepads>::Leaky g_test_gamepads =
143     LAZY_INSTANCE_INITIALIZER;
144 base::LazyInstance<blink::WebDeviceMotionData>::Leaky
145     g_test_device_motion_data = LAZY_INSTANCE_INITIALIZER;
146 base::LazyInstance<blink::WebDeviceOrientationData>::Leaky
147     g_test_device_orientation_data = LAZY_INSTANCE_INITIALIZER;
148 static blink::WebScreenOrientationListener*
149     g_test_screen_orientation_listener = NULL;
150
151 //------------------------------------------------------------------------------
152
153 class RendererWebKitPlatformSupportImpl::MimeRegistry
154     : public SimpleWebMimeRegistryImpl {
155  public:
156   virtual blink::WebMimeRegistry::SupportsType supportsMediaMIMEType(
157       const blink::WebString& mime_type,
158       const blink::WebString& codecs,
159       const blink::WebString& key_system);
160   virtual bool supportsMediaSourceMIMEType(const blink::WebString& mime_type,
161                                            const blink::WebString& codecs);
162   virtual bool supportsEncryptedMediaMIMEType(const WebString& key_system,
163                                               const WebString& mime_type,
164                                               const WebString& codecs) OVERRIDE;
165   virtual blink::WebString mimeTypeForExtension(
166       const blink::WebString& file_extension);
167   virtual blink::WebString mimeTypeFromFile(
168       const blink::WebString& file_path);
169 };
170
171 class RendererWebKitPlatformSupportImpl::FileUtilities
172     : public WebFileUtilitiesImpl {
173  public:
174   explicit FileUtilities(ThreadSafeSender* sender)
175       : thread_safe_sender_(sender) {}
176   virtual bool getFileInfo(const WebString& path, WebFileInfo& result);
177  private:
178   bool SendSyncMessageFromAnyThread(IPC::SyncMessage* msg) const;
179   scoped_refptr<ThreadSafeSender> thread_safe_sender_;
180 };
181
182 #if defined(OS_ANDROID)
183 // WebKit doesn't use WebSandboxSupport on android so we don't need to
184 // implement anything here.
185 class RendererWebKitPlatformSupportImpl::SandboxSupport {
186 };
187 #else
188 class RendererWebKitPlatformSupportImpl::SandboxSupport
189     : public blink::WebSandboxSupport {
190  public:
191   virtual ~SandboxSupport() {}
192
193 #if defined(OS_WIN)
194   virtual bool ensureFontLoaded(HFONT);
195 #elif defined(OS_MACOSX)
196   virtual bool loadFont(
197       NSFont* src_font,
198       CGFontRef* container,
199       uint32* font_id);
200 #elif defined(OS_POSIX)
201   virtual void getFontFamilyForCharacter(
202       blink::WebUChar32 character,
203       const char* preferred_locale,
204       blink::WebFontFamily* family);
205   virtual void getRenderStyleForStrike(
206       const char* family, int sizeAndStyle, blink::WebFontRenderStyle* out);
207
208  private:
209   // WebKit likes to ask us for the correct font family to use for a set of
210   // unicode code points. It needs this information frequently so we cache it
211   // here.
212   base::Lock unicode_font_families_mutex_;
213   std::map<int32_t, blink::WebFontFamily> unicode_font_families_;
214 #endif
215 };
216 #endif  // defined(OS_ANDROID)
217
218 //------------------------------------------------------------------------------
219
220 RendererWebKitPlatformSupportImpl::RendererWebKitPlatformSupportImpl()
221     : clipboard_client_(new RendererClipboardClient),
222       clipboard_(new WebClipboardImpl(clipboard_client_.get())),
223       mime_registry_(new RendererWebKitPlatformSupportImpl::MimeRegistry),
224       sudden_termination_disables_(0),
225       plugin_refresh_allowed_(true),
226       child_thread_loop_(base::MessageLoopProxy::current()),
227       web_scrollbar_behavior_(new WebScrollbarBehaviorImpl) {
228   if (g_sandbox_enabled && sandboxEnabled()) {
229     sandbox_support_.reset(
230         new RendererWebKitPlatformSupportImpl::SandboxSupport);
231   } else {
232     DVLOG(1) << "Disabling sandbox support for testing.";
233   }
234
235   // ChildThread may not exist in some tests.
236   if (ChildThread::current()) {
237     sync_message_filter_ = ChildThread::current()->sync_message_filter();
238     thread_safe_sender_ = ChildThread::current()->thread_safe_sender();
239     quota_message_filter_ = ChildThread::current()->quota_message_filter();
240     blob_registry_.reset(new WebBlobRegistryImpl(thread_safe_sender_));
241     web_idb_factory_.reset(new WebIDBFactoryImpl(thread_safe_sender_));
242     web_database_observer_impl_.reset(
243         new WebDatabaseObserverImpl(sync_message_filter_));
244   }
245 }
246
247 RendererWebKitPlatformSupportImpl::~RendererWebKitPlatformSupportImpl() {
248   WebFileSystemImpl::DeleteThreadSpecificInstance();
249 }
250
251 //------------------------------------------------------------------------------
252
253 blink::WebClipboard* RendererWebKitPlatformSupportImpl::clipboard() {
254   blink::WebClipboard* clipboard =
255       GetContentClient()->renderer()->OverrideWebClipboard();
256   if (clipboard)
257     return clipboard;
258   return clipboard_.get();
259 }
260
261 blink::WebMimeRegistry* RendererWebKitPlatformSupportImpl::mimeRegistry() {
262   return mime_registry_.get();
263 }
264
265 blink::WebFileUtilities*
266 RendererWebKitPlatformSupportImpl::fileUtilities() {
267   if (!file_utilities_) {
268     file_utilities_.reset(new FileUtilities(thread_safe_sender_.get()));
269     file_utilities_->set_sandbox_enabled(sandboxEnabled());
270   }
271   return file_utilities_.get();
272 }
273
274 blink::WebSandboxSupport* RendererWebKitPlatformSupportImpl::sandboxSupport() {
275 #if defined(OS_ANDROID)
276   // WebKit doesn't use WebSandboxSupport on android.
277   return NULL;
278 #else
279   return sandbox_support_.get();
280 #endif
281 }
282
283 blink::WebCookieJar* RendererWebKitPlatformSupportImpl::cookieJar() {
284   NOTREACHED() << "Use WebFrameClient::cookieJar() instead!";
285   return NULL;
286 }
287
288 blink::WebThemeEngine* RendererWebKitPlatformSupportImpl::themeEngine() {
289   blink::WebThemeEngine* theme_engine =
290       GetContentClient()->renderer()->OverrideThemeEngine();
291   if (theme_engine)
292     return theme_engine;
293   return BlinkPlatformImpl::themeEngine();
294 }
295
296 bool RendererWebKitPlatformSupportImpl::sandboxEnabled() {
297   // As explained in Platform.h, this function is used to decide
298   // whether to allow file system operations to come out of WebKit or not.
299   // Even if the sandbox is disabled, there's no reason why the code should
300   // act any differently...unless we're in single process mode.  In which
301   // case, we have no other choice.  Platform.h discourages using
302   // this switch unless absolutely necessary, so hopefully we won't end up
303   // with too many code paths being different in single-process mode.
304   return !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess);
305 }
306
307 unsigned long long RendererWebKitPlatformSupportImpl::visitedLinkHash(
308     const char* canonical_url,
309     size_t length) {
310   return GetContentClient()->renderer()->VisitedLinkHash(canonical_url, length);
311 }
312
313 bool RendererWebKitPlatformSupportImpl::isLinkVisited(
314     unsigned long long link_hash) {
315   return GetContentClient()->renderer()->IsLinkVisited(link_hash);
316 }
317
318 void RendererWebKitPlatformSupportImpl::createMessageChannel(
319     blink::WebMessagePortChannel** channel1,
320     blink::WebMessagePortChannel** channel2) {
321   WebMessagePortChannelImpl::CreatePair(
322       child_thread_loop_.get(), channel1, channel2);
323 }
324
325 blink::WebPrescientNetworking*
326 RendererWebKitPlatformSupportImpl::prescientNetworking() {
327   return GetContentClient()->renderer()->GetPrescientNetworking();
328 }
329
330 bool
331 RendererWebKitPlatformSupportImpl::CheckPreparsedJsCachingEnabled() const {
332   static bool checked = false;
333   static bool result = false;
334   if (!checked) {
335     const CommandLine& command_line = *CommandLine::ForCurrentProcess();
336     result = command_line.HasSwitch(switches::kEnablePreparsedJsCaching);
337     checked = true;
338   }
339   return result;
340 }
341
342 void RendererWebKitPlatformSupportImpl::cacheMetadata(
343     const blink::WebURL& url,
344     double response_time,
345     const char* data,
346     size_t size) {
347   if (!CheckPreparsedJsCachingEnabled())
348     return;
349
350   // Let the browser know we generated cacheable metadata for this resource. The
351   // browser may cache it and return it on subsequent responses to speed
352   // the processing of this resource.
353   std::vector<char> copy(data, data + size);
354   RenderThread::Get()->Send(
355       new ViewHostMsg_DidGenerateCacheableMetadata(url, response_time, copy));
356 }
357
358 WebString RendererWebKitPlatformSupportImpl::defaultLocale() {
359   return base::ASCIIToUTF16(RenderThread::Get()->GetLocale());
360 }
361
362 void RendererWebKitPlatformSupportImpl::suddenTerminationChanged(bool enabled) {
363   if (enabled) {
364     // We should not get more enables than disables, but we want it to be a
365     // non-fatal error if it does happen.
366     DCHECK_GT(sudden_termination_disables_, 0);
367     sudden_termination_disables_ = std::max(sudden_termination_disables_ - 1,
368                                             0);
369     if (sudden_termination_disables_ != 0)
370       return;
371   } else {
372     sudden_termination_disables_++;
373     if (sudden_termination_disables_ != 1)
374       return;
375   }
376
377   RenderThread* thread = RenderThread::Get();
378   if (thread)  // NULL in unittests.
379     thread->Send(new ViewHostMsg_SuddenTerminationChanged(enabled));
380 }
381
382 WebStorageNamespace*
383 RendererWebKitPlatformSupportImpl::createLocalStorageNamespace() {
384   return new WebStorageNamespaceImpl();
385 }
386
387
388 //------------------------------------------------------------------------------
389
390 WebIDBFactory* RendererWebKitPlatformSupportImpl::idbFactory() {
391   return web_idb_factory_.get();
392 }
393
394 //------------------------------------------------------------------------------
395
396 WebFileSystem* RendererWebKitPlatformSupportImpl::fileSystem() {
397   return WebFileSystemImpl::ThreadSpecificInstance(child_thread_loop_.get());
398 }
399
400 //------------------------------------------------------------------------------
401
402 WebMimeRegistry::SupportsType
403 RendererWebKitPlatformSupportImpl::MimeRegistry::supportsMediaMIMEType(
404     const WebString& mime_type,
405     const WebString& codecs,
406     const WebString& key_system) {
407   const std::string mime_type_ascii = ToASCIIOrEmpty(mime_type);
408   // Not supporting the container is a flat-out no.
409   if (!net::IsSupportedMediaMimeType(mime_type_ascii))
410     return IsNotSupported;
411
412   if (!key_system.isEmpty()) {
413     // Check whether the key system is supported with the mime_type and codecs.
414
415     // Chromium only supports ASCII parameters.
416     if (!base::IsStringASCII(key_system))
417       return IsNotSupported;
418
419     std::string key_system_ascii =
420         GetUnprefixedKeySystemName(base::UTF16ToASCII(key_system));
421     std::vector<std::string> strict_codecs;
422     bool strip_suffix = !net::IsStrictMediaMimeType(mime_type_ascii);
423     net::ParseCodecString(ToASCIIOrEmpty(codecs), &strict_codecs, strip_suffix);
424
425     if (!IsSupportedKeySystemWithMediaMimeType(
426             mime_type_ascii, strict_codecs, key_system_ascii)) {
427       return IsNotSupported;
428     }
429
430     // Continue processing the mime_type and codecs.
431   }
432
433   // Check list of strict codecs to see if it is supported.
434   if (net::IsStrictMediaMimeType(mime_type_ascii)) {
435     // Check if the codecs are a perfect match.
436     std::vector<std::string> strict_codecs;
437     net::ParseCodecString(ToASCIIOrEmpty(codecs), &strict_codecs, false);
438     if (net::IsSupportedStrictMediaMimeType(mime_type_ascii, strict_codecs))
439       return IsSupported;
440
441     // We support the container, but no codecs were specified.
442     if (codecs.isNull())
443       return MayBeSupported;
444
445     return IsNotSupported;
446   }
447
448   // If we don't recognize the codec, it's possible we support it.
449   std::vector<std::string> parsed_codecs;
450   net::ParseCodecString(ToASCIIOrEmpty(codecs), &parsed_codecs, true);
451   if (!net::AreSupportedMediaCodecs(parsed_codecs))
452     return MayBeSupported;
453
454   // Otherwise we have a perfect match.
455   return IsSupported;
456 }
457
458 bool
459 RendererWebKitPlatformSupportImpl::MimeRegistry::supportsMediaSourceMIMEType(
460     const blink::WebString& mime_type,
461     const WebString& codecs) {
462   const std::string mime_type_ascii = ToASCIIOrEmpty(mime_type);
463   std::vector<std::string> parsed_codec_ids;
464   net::ParseCodecString(ToASCIIOrEmpty(codecs), &parsed_codec_ids, false);
465   if (mime_type_ascii.empty())
466     return false;
467   return media::StreamParserFactory::IsTypeSupported(
468       mime_type_ascii, parsed_codec_ids);
469 }
470
471 bool
472 RendererWebKitPlatformSupportImpl::MimeRegistry::supportsEncryptedMediaMIMEType(
473     const WebString& key_system,
474     const WebString& mime_type,
475     const WebString& codecs) {
476   // Chromium only supports ASCII parameters.
477   if (!base::IsStringASCII(key_system) || !base::IsStringASCII(mime_type) ||
478       !base::IsStringASCII(codecs)) {
479     return false;
480   }
481
482   if (key_system.isEmpty())
483     return false;
484
485   const std::string mime_type_ascii = base::UTF16ToASCII(mime_type);
486
487   std::vector<std::string> codec_vector;
488   bool strip_suffix = !net::IsStrictMediaMimeType(mime_type_ascii);
489   net::ParseCodecString(base::UTF16ToASCII(codecs), &codec_vector,
490                         strip_suffix);
491
492   return IsSupportedKeySystemWithMediaMimeType(
493       mime_type_ascii, codec_vector, base::UTF16ToASCII(key_system));
494 }
495
496 WebString
497 RendererWebKitPlatformSupportImpl::MimeRegistry::mimeTypeForExtension(
498     const WebString& file_extension) {
499   if (IsPluginProcess())
500     return SimpleWebMimeRegistryImpl::mimeTypeForExtension(file_extension);
501
502   // The sandbox restricts our access to the registry, so we need to proxy
503   // these calls over to the browser process.
504   std::string mime_type;
505   RenderThread::Get()->Send(
506       new MimeRegistryMsg_GetMimeTypeFromExtension(
507           base::FilePath::FromUTF16Unsafe(file_extension).value(), &mime_type));
508   return base::ASCIIToUTF16(mime_type);
509 }
510
511 WebString RendererWebKitPlatformSupportImpl::MimeRegistry::mimeTypeFromFile(
512     const WebString& file_path) {
513   if (IsPluginProcess())
514     return SimpleWebMimeRegistryImpl::mimeTypeFromFile(file_path);
515
516   // The sandbox restricts our access to the registry, so we need to proxy
517   // these calls over to the browser process.
518   std::string mime_type;
519   RenderThread::Get()->Send(new MimeRegistryMsg_GetMimeTypeFromFile(
520       base::FilePath::FromUTF16Unsafe(file_path),
521       &mime_type));
522   return base::ASCIIToUTF16(mime_type);
523 }
524
525 //------------------------------------------------------------------------------
526
527 bool RendererWebKitPlatformSupportImpl::FileUtilities::getFileInfo(
528     const WebString& path,
529     WebFileInfo& web_file_info) {
530   base::File::Info file_info;
531   base::File::Error status;
532   if (!SendSyncMessageFromAnyThread(new FileUtilitiesMsg_GetFileInfo(
533            base::FilePath::FromUTF16Unsafe(path), &file_info, &status)) ||
534       status != base::File::FILE_OK) {
535     return false;
536   }
537   FileInfoToWebFileInfo(file_info, &web_file_info);
538   web_file_info.platformPath = path;
539   return true;
540 }
541
542 bool RendererWebKitPlatformSupportImpl::FileUtilities::
543 SendSyncMessageFromAnyThread(IPC::SyncMessage* msg) const {
544   base::TimeTicks begin = base::TimeTicks::Now();
545   const bool success = thread_safe_sender_->Send(msg);
546   base::TimeDelta delta = base::TimeTicks::Now() - begin;
547   UMA_HISTOGRAM_TIMES("RendererSyncIPC.ElapsedTime", delta);
548   return success;
549 }
550
551 //------------------------------------------------------------------------------
552
553 #if defined(OS_WIN)
554
555 bool RendererWebKitPlatformSupportImpl::SandboxSupport::ensureFontLoaded(
556     HFONT font) {
557   LOGFONT logfont;
558   GetObject(font, sizeof(LOGFONT), &logfont);
559   RenderThread::Get()->PreCacheFont(logfont);
560   return true;
561 }
562
563 #elif defined(OS_MACOSX)
564
565 bool RendererWebKitPlatformSupportImpl::SandboxSupport::loadFont(
566     NSFont* src_font, CGFontRef* out, uint32* font_id) {
567   uint32 font_data_size;
568   FontDescriptor src_font_descriptor(src_font);
569   base::SharedMemoryHandle font_data;
570   if (!RenderThread::Get()->Send(new ViewHostMsg_LoadFont(
571         src_font_descriptor, &font_data_size, &font_data, font_id))) {
572     *out = NULL;
573     *font_id = 0;
574     return false;
575   }
576
577   if (font_data_size == 0 || font_data == base::SharedMemory::NULLHandle() ||
578       *font_id == 0) {
579     LOG(ERROR) << "Bad response from ViewHostMsg_LoadFont() for " <<
580         src_font_descriptor.font_name;
581     *out = NULL;
582     *font_id = 0;
583     return false;
584   }
585
586   // TODO(jeremy): Need to call back into WebKit to make sure that the font
587   // isn't already activated, based on the font id.  If it's already
588   // activated, don't reactivate it here - crbug.com/72727 .
589
590   return FontLoader::CGFontRefFromBuffer(font_data, font_data_size, out);
591 }
592
593 #elif defined(OS_ANDROID)
594
595 // WebKit doesn't use WebSandboxSupport on android so we don't need to
596 // implement anything here. This is cleaner to support than excluding the
597 // whole class for android.
598
599 #elif defined(OS_POSIX)
600
601 void
602 RendererWebKitPlatformSupportImpl::SandboxSupport::getFontFamilyForCharacter(
603     blink::WebUChar32 character,
604     const char* preferred_locale,
605     blink::WebFontFamily* family) {
606   base::AutoLock lock(unicode_font_families_mutex_);
607   const std::map<int32_t, blink::WebFontFamily>::const_iterator iter =
608       unicode_font_families_.find(character);
609   if (iter != unicode_font_families_.end()) {
610     family->name = iter->second.name;
611     family->isBold = iter->second.isBold;
612     family->isItalic = iter->second.isItalic;
613     return;
614   }
615
616   GetFontFamilyForCharacter(character, preferred_locale, family);
617   unicode_font_families_.insert(std::make_pair(character, *family));
618 }
619
620 void
621 RendererWebKitPlatformSupportImpl::SandboxSupport::getRenderStyleForStrike(
622     const char* family, int sizeAndStyle, blink::WebFontRenderStyle* out) {
623   GetRenderStyleForStrike(family, sizeAndStyle, out);
624 }
625
626 #endif
627
628 //------------------------------------------------------------------------------
629
630 Platform::FileHandle
631 RendererWebKitPlatformSupportImpl::databaseOpenFile(
632     const WebString& vfs_file_name, int desired_flags) {
633   return DatabaseUtil::DatabaseOpenFile(
634       vfs_file_name, desired_flags, sync_message_filter_.get());
635 }
636
637 int RendererWebKitPlatformSupportImpl::databaseDeleteFile(
638     const WebString& vfs_file_name, bool sync_dir) {
639   return DatabaseUtil::DatabaseDeleteFile(
640       vfs_file_name, sync_dir, sync_message_filter_.get());
641 }
642
643 long RendererWebKitPlatformSupportImpl::databaseGetFileAttributes(
644     const WebString& vfs_file_name) {
645   return DatabaseUtil::DatabaseGetFileAttributes(vfs_file_name,
646                                                  sync_message_filter_.get());
647 }
648
649 long long RendererWebKitPlatformSupportImpl::databaseGetFileSize(
650     const WebString& vfs_file_name) {
651   return DatabaseUtil::DatabaseGetFileSize(vfs_file_name,
652                                            sync_message_filter_.get());
653 }
654
655 long long RendererWebKitPlatformSupportImpl::databaseGetSpaceAvailableForOrigin(
656     const WebString& origin_identifier) {
657   return DatabaseUtil::DatabaseGetSpaceAvailable(origin_identifier,
658                                                  sync_message_filter_.get());
659 }
660
661 bool RendererWebKitPlatformSupportImpl::canAccelerate2dCanvas() {
662   RenderThreadImpl* thread = RenderThreadImpl::current();
663   GpuChannelHost* host = thread->EstablishGpuChannelSync(
664       CAUSE_FOR_GPU_LAUNCH_CANVAS_2D);
665   if (!host)
666     return false;
667
668   return host->gpu_info().SupportsAccelerated2dCanvas();
669 }
670
671 bool RendererWebKitPlatformSupportImpl::isThreadedCompositingEnabled() {
672   RenderThreadImpl* thread = RenderThreadImpl::current();
673   // thread can be NULL in tests.
674   return thread && thread->compositor_message_loop_proxy().get();
675 }
676
677 double RendererWebKitPlatformSupportImpl::audioHardwareSampleRate() {
678   RenderThreadImpl* thread = RenderThreadImpl::current();
679   return thread->GetAudioHardwareConfig()->GetOutputSampleRate();
680 }
681
682 size_t RendererWebKitPlatformSupportImpl::audioHardwareBufferSize() {
683   RenderThreadImpl* thread = RenderThreadImpl::current();
684   return thread->GetAudioHardwareConfig()->GetOutputBufferSize();
685 }
686
687 unsigned RendererWebKitPlatformSupportImpl::audioHardwareOutputChannels() {
688   RenderThreadImpl* thread = RenderThreadImpl::current();
689   return thread->GetAudioHardwareConfig()->GetOutputChannels();
690 }
691
692 WebDatabaseObserver* RendererWebKitPlatformSupportImpl::databaseObserver() {
693   return web_database_observer_impl_.get();
694 }
695
696 WebAudioDevice*
697 RendererWebKitPlatformSupportImpl::createAudioDevice(
698     size_t buffer_size,
699     unsigned input_channels,
700     unsigned channels,
701     double sample_rate,
702     WebAudioDevice::RenderCallback* callback,
703     const blink::WebString& input_device_id) {
704   // Use a mock for testing.
705   blink::WebAudioDevice* mock_device =
706       GetContentClient()->renderer()->OverrideCreateAudioDevice(sample_rate);
707   if (mock_device)
708     return mock_device;
709
710   // The |channels| does not exactly identify the channel layout of the
711   // device. The switch statement below assigns a best guess to the channel
712   // layout based on number of channels.
713   // TODO(crogers): WebKit should give the channel layout instead of the hard
714   // channel count.
715   media::ChannelLayout layout = media::CHANNEL_LAYOUT_UNSUPPORTED;
716   switch (channels) {
717     case 1:
718       layout = media::CHANNEL_LAYOUT_MONO;
719       break;
720     case 2:
721       layout = media::CHANNEL_LAYOUT_STEREO;
722       break;
723     case 3:
724       layout = media::CHANNEL_LAYOUT_2_1;
725       break;
726     case 4:
727       layout = media::CHANNEL_LAYOUT_4_0;
728       break;
729     case 5:
730       layout = media::CHANNEL_LAYOUT_5_0;
731       break;
732     case 6:
733       layout = media::CHANNEL_LAYOUT_5_1;
734       break;
735     case 7:
736       layout = media::CHANNEL_LAYOUT_7_0;
737       break;
738     case 8:
739       layout = media::CHANNEL_LAYOUT_7_1;
740       break;
741     default:
742       layout = media::CHANNEL_LAYOUT_STEREO;
743   }
744
745   int session_id = 0;
746   if (input_device_id.isNull() ||
747       !base::StringToInt(base::UTF16ToUTF8(input_device_id), &session_id)) {
748     if (input_channels > 0)
749       DLOG(WARNING) << "createAudioDevice(): request for audio input ignored";
750
751     input_channels = 0;
752   }
753
754   media::AudioParameters params(
755       media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
756       layout, input_channels,
757       static_cast<int>(sample_rate), 16, buffer_size,
758       media::AudioParameters::NO_EFFECTS);
759
760   return new RendererWebAudioDeviceImpl(params, callback, session_id);
761 }
762
763 #if defined(OS_ANDROID)
764 bool RendererWebKitPlatformSupportImpl::loadAudioResource(
765     blink::WebAudioBus* destination_bus, const char* audio_file_data,
766     size_t data_size) {
767   return DecodeAudioFileData(destination_bus,
768                              audio_file_data,
769                              data_size,
770                              thread_safe_sender_);
771 }
772 #else
773 bool RendererWebKitPlatformSupportImpl::loadAudioResource(
774     blink::WebAudioBus* destination_bus, const char* audio_file_data,
775     size_t data_size) {
776   return DecodeAudioFileData(
777       destination_bus, audio_file_data, data_size);
778 }
779 #endif  // defined(OS_ANDROID)
780
781 //------------------------------------------------------------------------------
782
783 blink::WebMIDIAccessor*
784 RendererWebKitPlatformSupportImpl::createMIDIAccessor(
785     blink::WebMIDIAccessorClient* client) {
786   blink::WebMIDIAccessor* accessor =
787       GetContentClient()->renderer()->OverrideCreateMIDIAccessor(client);
788   if (accessor)
789     return accessor;
790
791   return new RendererWebMIDIAccessorImpl(client);
792 }
793
794 void RendererWebKitPlatformSupportImpl::getPluginList(
795     bool refresh,
796     blink::WebPluginListBuilder* builder) {
797 #if defined(ENABLE_PLUGINS)
798   std::vector<WebPluginInfo> plugins;
799   if (!plugin_refresh_allowed_)
800     refresh = false;
801   RenderThread::Get()->Send(
802       new ViewHostMsg_GetPlugins(refresh, &plugins));
803   for (size_t i = 0; i < plugins.size(); ++i) {
804     const WebPluginInfo& plugin = plugins[i];
805
806     builder->addPlugin(
807         plugin.name, plugin.desc,
808         plugin.path.BaseName().AsUTF16Unsafe());
809
810     for (size_t j = 0; j < plugin.mime_types.size(); ++j) {
811       const WebPluginMimeType& mime_type = plugin.mime_types[j];
812
813       builder->addMediaTypeToLastPlugin(
814           WebString::fromUTF8(mime_type.mime_type), mime_type.description);
815
816       for (size_t k = 0; k < mime_type.file_extensions.size(); ++k) {
817         builder->addFileExtensionToLastMediaType(
818             WebString::fromUTF8(mime_type.file_extensions[k]));
819       }
820     }
821   }
822 #endif
823 }
824
825 //------------------------------------------------------------------------------
826
827 blink::WebPublicSuffixList*
828 RendererWebKitPlatformSupportImpl::publicSuffixList() {
829   return &public_suffix_list_;
830 }
831
832 //------------------------------------------------------------------------------
833
834 blink::WebString
835 RendererWebKitPlatformSupportImpl::signedPublicKeyAndChallengeString(
836     unsigned key_size_index,
837     const blink::WebString& challenge,
838     const blink::WebURL& url) {
839   std::string signed_public_key;
840   RenderThread::Get()->Send(new ViewHostMsg_Keygen(
841       static_cast<uint32>(key_size_index),
842       challenge.utf8(),
843       GURL(url),
844       &signed_public_key));
845   return WebString::fromUTF8(signed_public_key);
846 }
847
848 //------------------------------------------------------------------------------
849
850 void RendererWebKitPlatformSupportImpl::screenColorProfile(
851     WebVector<char>* to_profile) {
852 #if defined(OS_WIN)
853   // On Windows screen color profile is only available in the browser.
854   std::vector<char> profile;
855   // This Send() can be called from any impl-side thread. Use a thread
856   // safe send to avoid crashing trying to access RenderThread::Get(),
857   // which is not accessible from arbitrary threads.
858   thread_safe_sender_->Send(
859       new ViewHostMsg_GetMonitorColorProfile(&profile));
860   *to_profile = profile;
861 #else
862   // On other platforms, the primary monitor color profile can be read
863   // directly.
864   gfx::ColorProfile profile;
865   *to_profile = profile.profile();
866 #endif
867 }
868
869 //------------------------------------------------------------------------------
870
871 blink::WebScrollbarBehavior*
872     RendererWebKitPlatformSupportImpl::scrollbarBehavior() {
873   return web_scrollbar_behavior_.get();
874 }
875
876 //------------------------------------------------------------------------------
877
878 WebBlobRegistry* RendererWebKitPlatformSupportImpl::blobRegistry() {
879   // blob_registry_ can be NULL when running some tests.
880   return blob_registry_.get();
881 }
882
883 //------------------------------------------------------------------------------
884
885 void RendererWebKitPlatformSupportImpl::sampleGamepads(WebGamepads& gamepads) {
886   if (g_test_gamepads == 0) {
887     RenderThreadImpl::current()->gamepad_shared_memory_reader()->
888         SampleGamepads(gamepads);
889   } else {
890     gamepads = g_test_gamepads.Get();
891   }
892 }
893
894 void RendererWebKitPlatformSupportImpl::setGamepadListener(
895       blink::WebGamepadListener* listener) {
896   web_gamepad_listener = listener;
897   RenderThreadImpl::current()->gamepad_shared_memory_reader()->
898       SetGamepadListener(listener);
899 }
900
901 //------------------------------------------------------------------------------
902
903 WebRTCPeerConnectionHandler*
904 RendererWebKitPlatformSupportImpl::createRTCPeerConnectionHandler(
905     WebRTCPeerConnectionHandlerClient* client) {
906   RenderThreadImpl* render_thread = RenderThreadImpl::current();
907   DCHECK(render_thread);
908   if (!render_thread)
909     return NULL;
910
911 #if defined(ENABLE_WEBRTC)
912   WebRTCPeerConnectionHandler* peer_connection_handler =
913       GetContentClient()->renderer()->OverrideCreateWebRTCPeerConnectionHandler(
914           client);
915   if (peer_connection_handler)
916     return peer_connection_handler;
917
918   MediaStreamDependencyFactory* rtc_dependency_factory =
919       render_thread->GetMediaStreamDependencyFactory();
920   return rtc_dependency_factory->CreateRTCPeerConnectionHandler(client);
921 #else
922   return NULL;
923 #endif  // defined(ENABLE_WEBRTC)
924 }
925
926 //------------------------------------------------------------------------------
927
928 WebMediaStreamCenter*
929 RendererWebKitPlatformSupportImpl::createMediaStreamCenter(
930     WebMediaStreamCenterClient* client) {
931   RenderThreadImpl* render_thread = RenderThreadImpl::current();
932   DCHECK(render_thread);
933   if (!render_thread)
934     return NULL;
935   return render_thread->CreateMediaStreamCenter(client);
936 }
937
938 // static
939 bool RendererWebKitPlatformSupportImpl::SetSandboxEnabledForTesting(
940     bool enable) {
941   bool was_enabled = g_sandbox_enabled;
942   g_sandbox_enabled = enable;
943   return was_enabled;
944 }
945
946 // static
947 void RendererWebKitPlatformSupportImpl::SetMockGamepadsForTesting(
948     const WebGamepads& pads) {
949   g_test_gamepads.Get() = pads;
950 }
951
952 // static
953 void RendererWebKitPlatformSupportImpl::MockGamepadConnected(
954     int index,
955     const WebGamepad& pad) {
956   if (web_gamepad_listener)
957     web_gamepad_listener->didConnectGamepad(index, pad);
958 }
959
960 // static
961 void RendererWebKitPlatformSupportImpl::MockGamepadDisconnected(
962     int index,
963     const WebGamepad& pad) {
964   if (web_gamepad_listener)
965     web_gamepad_listener->didDisconnectGamepad(index, pad);
966 }
967
968 //------------------------------------------------------------------------------
969
970 blink::WebSpeechSynthesizer*
971 RendererWebKitPlatformSupportImpl::createSpeechSynthesizer(
972     blink::WebSpeechSynthesizerClient* client) {
973   return GetContentClient()->renderer()->OverrideSpeechSynthesizer(client);
974 }
975
976 //------------------------------------------------------------------------------
977
978 bool RendererWebKitPlatformSupportImpl::processMemorySizesInBytes(
979     size_t* private_bytes, size_t* shared_bytes) {
980   content::RenderThread::Get()->Send(
981       new ViewHostMsg_GetProcessMemorySizes(private_bytes, shared_bytes));
982   return true;
983 }
984
985 //------------------------------------------------------------------------------
986
987 blink::WebGraphicsContext3D*
988 RendererWebKitPlatformSupportImpl::createOffscreenGraphicsContext3D(
989     const blink::WebGraphicsContext3D::Attributes& attributes) {
990   return createOffscreenGraphicsContext3D(attributes, NULL);
991 }
992
993 blink::WebGraphicsContext3D*
994 RendererWebKitPlatformSupportImpl::createOffscreenGraphicsContext3D(
995     const blink::WebGraphicsContext3D::Attributes& attributes,
996     blink::WebGraphicsContext3D* share_context) {
997   if (!RenderThreadImpl::current())
998     return NULL;
999
1000 #if defined(OS_ANDROID)
1001   if (SynchronousCompositorFactory* factory =
1002           SynchronousCompositorFactory::GetInstance()) {
1003     return factory->CreateOffscreenGraphicsContext3D(attributes);
1004   }
1005 #endif
1006
1007   scoped_refptr<GpuChannelHost> gpu_channel_host(
1008       RenderThreadImpl::current()->EstablishGpuChannelSync(
1009           CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE));
1010
1011   WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits;
1012
1013   CommandLine* command_line = CommandLine::ForCurrentProcess();
1014   if (command_line->HasSwitch(switches::kWebGLCommandBufferSizeKb)) {
1015     std::string size_string = command_line->GetSwitchValueASCII(
1016         switches::kWebGLCommandBufferSizeKb);
1017     size_t buffer_size_kb;
1018     if (base::StringToSizeT(size_string, &buffer_size_kb)) {
1019       limits.command_buffer_size = buffer_size_kb * 1024;
1020     }
1021   }
1022   bool lose_context_when_out_of_memory = false;
1023   return WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
1024       gpu_channel_host.get(),
1025       attributes,
1026       lose_context_when_out_of_memory,
1027       GURL(attributes.topDocumentURL),
1028       limits,
1029       static_cast<WebGraphicsContext3DCommandBufferImpl*>(share_context));
1030 }
1031
1032 //------------------------------------------------------------------------------
1033
1034 blink::WebGraphicsContext3DProvider* RendererWebKitPlatformSupportImpl::
1035     createSharedOffscreenGraphicsContext3DProvider() {
1036   scoped_refptr<webkit::gpu::ContextProviderWebContext> provider =
1037       RenderThreadImpl::current()->SharedMainThreadContextProvider();
1038   if (!provider)
1039     return NULL;
1040   return new WebGraphicsContext3DProviderImpl(provider);
1041 }
1042
1043 //------------------------------------------------------------------------------
1044
1045 blink::WebCompositorSupport*
1046 RendererWebKitPlatformSupportImpl::compositorSupport() {
1047   return &compositor_support_;
1048 }
1049
1050 //------------------------------------------------------------------------------
1051
1052 blink::WebString RendererWebKitPlatformSupportImpl::convertIDNToUnicode(
1053     const blink::WebString& host,
1054     const blink::WebString& languages) {
1055   return net::IDNToUnicode(host.utf8(), languages.utf8());
1056 }
1057
1058 //------------------------------------------------------------------------------
1059
1060 void RendererWebKitPlatformSupportImpl::setDeviceMotionListener(
1061     blink::WebDeviceMotionListener* listener) {
1062   if (g_test_device_motion_data == 0) {
1063     if (!device_motion_event_pump_) {
1064       device_motion_event_pump_.reset(new DeviceMotionEventPump);
1065       device_motion_event_pump_->Attach(RenderThreadImpl::current());
1066     }
1067     device_motion_event_pump_->SetListener(listener);
1068   } else if (listener) {
1069     // Testing mode: just echo the test data to the listener.
1070     base::MessageLoopProxy::current()->PostTask(
1071         FROM_HERE,
1072         base::Bind(&blink::WebDeviceMotionListener::didChangeDeviceMotion,
1073                    base::Unretained(listener),
1074                    g_test_device_motion_data.Get()));
1075   }
1076 }
1077
1078 // static
1079 void RendererWebKitPlatformSupportImpl::SetMockDeviceMotionDataForTesting(
1080     const blink::WebDeviceMotionData& data) {
1081   g_test_device_motion_data.Get() = data;
1082 }
1083
1084 //------------------------------------------------------------------------------
1085
1086 void RendererWebKitPlatformSupportImpl::setDeviceOrientationListener(
1087     blink::WebDeviceOrientationListener* listener) {
1088   if (g_test_device_orientation_data == 0) {
1089     if (!device_orientation_event_pump_) {
1090       device_orientation_event_pump_.reset(new DeviceOrientationEventPump);
1091       device_orientation_event_pump_->Attach(RenderThreadImpl::current());
1092     }
1093     device_orientation_event_pump_->SetListener(listener);
1094   } else if (listener) {
1095     // Testing mode: just echo the test data to the listener.
1096     base::MessageLoopProxy::current()->PostTask(
1097         FROM_HERE,
1098         base::Bind(
1099             &blink::WebDeviceOrientationListener::didChangeDeviceOrientation,
1100             base::Unretained(listener),
1101             g_test_device_orientation_data.Get()));
1102   }
1103 }
1104
1105 // static
1106 void RendererWebKitPlatformSupportImpl::SetMockDeviceOrientationDataForTesting(
1107     const blink::WebDeviceOrientationData& data) {
1108   g_test_device_orientation_data.Get() = data;
1109 }
1110
1111 //------------------------------------------------------------------------------
1112
1113 void RendererWebKitPlatformSupportImpl::vibrate(unsigned int milliseconds) {
1114   RenderThread::Get()->Send(
1115       new ViewHostMsg_Vibrate(base::checked_cast<int64>(milliseconds)));
1116 }
1117
1118 void RendererWebKitPlatformSupportImpl::cancelVibration() {
1119   RenderThread::Get()->Send(new ViewHostMsg_CancelVibration());
1120 }
1121
1122 //------------------------------------------------------------------------------
1123
1124 void RendererWebKitPlatformSupportImpl::setScreenOrientationListener(
1125     blink::WebScreenOrientationListener* listener) {
1126   if (RenderThreadImpl::current() &&
1127       RenderThreadImpl::current()->layout_test_mode()) {
1128     // If we are in test mode, we want to fully disable the screen orientation
1129     // backend in order to let Blink get tested properly, That means that screen
1130     // orientation updates have to be done manually instead of from signals sent
1131     // by the browser process.
1132     g_test_screen_orientation_listener = listener;
1133     return;
1134   }
1135
1136   if (!screen_orientation_dispatcher_) {
1137     screen_orientation_dispatcher_.reset(
1138         new ScreenOrientationDispatcher(RenderThread::Get()));
1139   }
1140
1141   screen_orientation_dispatcher_->setListener(listener);
1142 }
1143
1144 void RendererWebKitPlatformSupportImpl::lockOrientation(
1145     blink::WebScreenOrientationLockType orientation) {
1146   if (RenderThreadImpl::current() &&
1147       RenderThreadImpl::current()->layout_test_mode()) {
1148     return;
1149   }
1150   RenderThread::Get()->Send(new ScreenOrientationHostMsg_Lock(orientation));
1151 }
1152
1153 void RendererWebKitPlatformSupportImpl::unlockOrientation() {
1154   if (RenderThreadImpl::current() &&
1155       RenderThreadImpl::current()->layout_test_mode()) {
1156     return;
1157   }
1158   RenderThread::Get()->Send(new ScreenOrientationHostMsg_Unlock);
1159 }
1160
1161 // static
1162 void RendererWebKitPlatformSupportImpl::SetMockScreenOrientationForTesting(
1163     blink::WebScreenOrientationType orientation) {
1164   if (!g_test_screen_orientation_listener)
1165     return;
1166   g_test_screen_orientation_listener->didChangeScreenOrientation(orientation);
1167 }
1168
1169 //------------------------------------------------------------------------------
1170
1171 void RendererWebKitPlatformSupportImpl::queryStorageUsageAndQuota(
1172     const blink::WebURL& storage_partition,
1173     blink::WebStorageQuotaType type,
1174     blink::WebStorageQuotaCallbacks callbacks) {
1175   if (!thread_safe_sender_.get() || !quota_message_filter_.get())
1176     return;
1177   QuotaDispatcher::ThreadSpecificInstance(
1178       thread_safe_sender_.get(),
1179       quota_message_filter_.get())->QueryStorageUsageAndQuota(
1180           storage_partition,
1181           static_cast<quota::StorageType>(type),
1182           QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(callbacks));
1183 }
1184
1185 }  // namespace content