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