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