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