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/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 
    105 using WebKit::WebAudioDevice;
    106 using WebKit::WebBlobRegistry;
    107 using WebKit::WebFileInfo;
    108 using WebKit::WebFileSystem;
    109 using WebKit::WebFrame;
    110 using WebKit::WebGamepads;
    111 using WebKit::WebIDBFactory;
    112 using WebKit::WebMIDIAccessor;
    113 using WebKit::Platform;
    114 using WebKit::WebMediaStreamCenter;
    115 using WebKit::WebMediaStreamCenterClient;
    116 using WebKit::WebMimeRegistry;
    117 using WebKit::WebRTCPeerConnectionHandler;
    118 using WebKit::WebRTCPeerConnectionHandlerClient;
    119 using WebKit::WebStorageNamespace;
    120 using WebKit::WebString;
    121 using WebKit::WebURL;
    122 using WebKit::WebVector;
    123 
    124 namespace content {
    125 
    126 static bool g_sandbox_enabled = true;
    127 base::LazyInstance<WebGamepads>::Leaky g_test_gamepads =
    128     LAZY_INSTANCE_INITIALIZER;
    129 base::LazyInstance<WebKit::WebDeviceMotionData>::Leaky
    130     g_test_device_motion_data = LAZY_INSTANCE_INITIALIZER;
    131 
    132 //------------------------------------------------------------------------------
    133 
    134 class 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 
    155 class 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.
    169 class RendererWebKitPlatformSupportImpl::SandboxSupport {
    170 };
    171 #else
    172 class 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 
    204 RendererWebKitPlatformSupportImpl::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 
    227 RendererWebKitPlatformSupportImpl::~RendererWebKitPlatformSupportImpl() {
    228 }
    229 
    230 //------------------------------------------------------------------------------
    231 
    232 WebKit::WebClipboard* RendererWebKitPlatformSupportImpl::clipboard() {
    233   WebKit::WebClipboard* clipboard =
    234       GetContentClient()->renderer()->OverrideWebClipboard();
    235   if (clipboard)
    236     return clipboard;
    237   return clipboard_.get();
    238 }
    239 
    240 WebKit::WebMimeRegistry* RendererWebKitPlatformSupportImpl::mimeRegistry() {
    241   return mime_registry_.get();
    242 }
    243 
    244 WebKit::WebFileUtilities*
    245 RendererWebKitPlatformSupportImpl::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 
    253 WebKit::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 
    262 WebKit::WebCookieJar* RendererWebKitPlatformSupportImpl::cookieJar() {
    263   NOTREACHED() << "Use WebFrameClient::cookieJar() instead!";
    264   return NULL;
    265 }
    266 
    267 WebKit::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 
    275 bool 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 
    286 unsigned long long RendererWebKitPlatformSupportImpl::visitedLinkHash(
    287     const char* canonical_url,
    288     size_t length) {
    289   return GetContentClient()->renderer()->VisitedLinkHash(canonical_url, length);
    290 }
    291 
    292 bool RendererWebKitPlatformSupportImpl::isLinkVisited(
    293     unsigned long long link_hash) {
    294   return GetContentClient()->renderer()->IsLinkVisited(link_hash);
    295 }
    296 
    297 WebKit::WebMessagePortChannel*
    298 RendererWebKitPlatformSupportImpl::createMessagePortChannel() {
    299   return new WebMessagePortChannelImpl(child_thread_loop_.get());
    300 }
    301 
    302 WebKit::WebPrescientNetworking*
    303 RendererWebKitPlatformSupportImpl::prescientNetworking() {
    304   return GetContentClient()->renderer()->GetPrescientNetworking();
    305 }
    306 
    307 bool
    308 RendererWebKitPlatformSupportImpl::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 
    319 void 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 
    335 WebString RendererWebKitPlatformSupportImpl::defaultLocale() {
    336   return ASCIIToUTF16(RenderThread::Get()->GetLocale());
    337 }
    338 
    339 void 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 
    359 WebStorageNamespace*
    360 RendererWebKitPlatformSupportImpl::createLocalStorageNamespace() {
    361   return new WebStorageNamespaceImpl();
    362 }
    363 
    364 
    365 //------------------------------------------------------------------------------
    366 
    367 WebIDBFactory* 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 
    376 WebFileSystem* 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 
    384 WebMimeRegistry::SupportsType
    385 RendererWebKitPlatformSupportImpl::MimeRegistry::supportsMediaMIMEType(
    386     const WebString& mime_type,
    387     const WebString& codecs) {
    388   return supportsMediaMIMEType(mime_type, codecs, WebString());
    389 }
    390 
    391 WebMimeRegistry::SupportsType
    392 RendererWebKitPlatformSupportImpl::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 
    445 bool
    446 RendererWebKitPlatformSupportImpl::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 
    458 WebString
    459 RendererWebKitPlatformSupportImpl::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 
    473 WebString 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 
    487 WebString
    488 RendererWebKitPlatformSupportImpl::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 
    504 bool 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 
    519 bool RendererWebKitPlatformSupportImpl::FileUtilities::
    520 SendSyncMessageFromAnyThread(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 
    532 bool 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 
    542 bool 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 
    578 void
    579 RendererWebKitPlatformSupportImpl::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 
    597 void
    598 RendererWebKitPlatformSupportImpl::SandboxSupport::getRenderStyleForStrike(
    599     const char* family, int sizeAndStyle, WebKit::WebFontRenderStyle* out) {
    600   GetRenderStyleForStrike(family, sizeAndStyle, out);
    601 }
    602 
    603 #endif
    604 
    605 //------------------------------------------------------------------------------
    606 
    607 Platform::FileHandle
    608 RendererWebKitPlatformSupportImpl::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 
    614 int 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 
    620 long RendererWebKitPlatformSupportImpl::databaseGetFileAttributes(
    621     const WebString& vfs_file_name) {
    622   return DatabaseUtil::DatabaseGetFileAttributes(vfs_file_name,
    623                                                  sync_message_filter_.get());
    624 }
    625 
    626 long long RendererWebKitPlatformSupportImpl::databaseGetFileSize(
    627     const WebString& vfs_file_name) {
    628   return DatabaseUtil::DatabaseGetFileSize(vfs_file_name,
    629                                            sync_message_filter_.get());
    630 }
    631 
    632 long long RendererWebKitPlatformSupportImpl::databaseGetSpaceAvailableForOrigin(
    633     const WebString& origin_identifier) {
    634   return DatabaseUtil::DatabaseGetSpaceAvailable(origin_identifier,
    635                                                  sync_message_filter_.get());
    636 }
    637 
    638 WebKit::WebSharedWorkerRepository*
    639 RendererWebKitPlatformSupportImpl::sharedWorkerRepository() {
    640   if (!CommandLine::ForCurrentProcess()->HasSwitch(
    641           switches::kDisableSharedWorkers)) {
    642     return shared_worker_repository_.get();
    643   } else {
    644     return NULL;
    645   }
    646 }
    647 
    648 bool 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 
    662 bool RendererWebKitPlatformSupportImpl::isThreadedCompositingEnabled() {
    663   return !!RenderThreadImpl::current()->compositor_message_loop_proxy().get();
    664 }
    665 
    666 double RendererWebKitPlatformSupportImpl::audioHardwareSampleRate() {
    667   RenderThreadImpl* thread = RenderThreadImpl::current();
    668   return thread->GetAudioHardwareConfig()->GetOutputSampleRate();
    669 }
    670 
    671 size_t RendererWebKitPlatformSupportImpl::audioHardwareBufferSize() {
    672   RenderThreadImpl* thread = RenderThreadImpl::current();
    673   return thread->GetAudioHardwareConfig()->GetOutputBufferSize();
    674 }
    675 
    676 unsigned 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.
    682 WebAudioDevice*
    683 RendererWebKitPlatformSupportImpl::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.
    693 WebAudioDevice*
    694 RendererWebKitPlatformSupportImpl::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 
    704 WebAudioDevice*
    705 RendererWebKitPlatformSupportImpl::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)
    771 bool 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
    781 bool 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 
    791 WebKit::WebContentDecryptionModule*
    792 RendererWebKitPlatformSupportImpl::createContentDecryptionModule(
    793     const WebKit::WebString& key_system) {
    794   return WebContentDecryptionModuleImpl::Create(key_system);
    795 }
    796 
    797 //------------------------------------------------------------------------------
    798 
    799 WebKit::WebMIDIAccessor*
    800 RendererWebKitPlatformSupportImpl::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 
    810 void 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 
    843 WebKit::WebString
    844 RendererWebKitPlatformSupportImpl::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 
    859 void 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 
    869 WebBlobRegistry* 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 
    878 void 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 
    886 WebKit::WebString RendererWebKitPlatformSupportImpl::userAgent(
    887     const WebKit::WebURL& url) {
    888   return WebKitPlatformSupportImpl::userAgent(url);
    889 }
    890 
    891 //------------------------------------------------------------------------------
    892 
    893 WebRTCPeerConnectionHandler*
    894 RendererWebKitPlatformSupportImpl::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 
    918 WebMediaStreamCenter*
    919 RendererWebKitPlatformSupportImpl::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
    929 bool 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
    937 void RendererWebKitPlatformSupportImpl::SetMockGamepadsForTesting(
    938     const WebGamepads& pads) {
    939   g_test_gamepads.Get() = pads;
    940 }
    941 
    942 //------------------------------------------------------------------------------
    943 
    944 WebKit::WebSpeechSynthesizer*
    945 RendererWebKitPlatformSupportImpl::createSpeechSynthesizer(
    946     WebKit::WebSpeechSynthesizerClient* client) {
    947   return GetContentClient()->renderer()->OverrideSpeechSynthesizer(client);
    948 }
    949 
    950 //------------------------------------------------------------------------------
    951 
    952 bool 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 
    961 WebKit::WebGraphicsContext3D*
    962 RendererWebKitPlatformSupportImpl::createOffscreenGraphicsContext3D(
    963     const WebKit::WebGraphicsContext3D::Attributes& attributes) {
    964   return WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
    965       RenderThreadImpl::current(),
    966       attributes,
    967       GURL(attributes.topDocumentURL));
    968 }
    969 
    970 //------------------------------------------------------------------------------
    971 
    972 WebKit::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 
    987 WebKit::WebCompositorSupport*
    988 RendererWebKitPlatformSupportImpl::compositorSupport() {
    989   return &compositor_support_;
    990 }
    991 
    992 //------------------------------------------------------------------------------
    993 
    994 WebKit::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 
   1002 void 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
   1021 void RendererWebKitPlatformSupportImpl::SetMockDeviceMotionDataForTesting(
   1022     const WebKit::WebDeviceMotionData& data) {
   1023   g_test_device_motion_data.Get() = data;
   1024 }
   1025 
   1026 //------------------------------------------------------------------------------
   1027 
   1028 void 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 
   1039 WebKit::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)
   1055 void RendererWebKitPlatformSupportImpl::vibrate(unsigned int milliseconds) {
   1056   RenderThread::Get()->Send(
   1057       new ViewHostMsg_Vibrate(base::checked_numeric_cast<int64>(milliseconds)));
   1058 }
   1059 
   1060 void RendererWebKitPlatformSupportImpl::cancelVibration() {
   1061   RenderThread::Get()->Send(new ViewHostMsg_CancelVibration());
   1062 }
   1063 #endif  // defined(OS_ANDROID)
   1064 
   1065 //------------------------------------------------------------------------------
   1066 
   1067 void 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