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