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/browser/renderer_host/render_message_filter.h" 6 7 #include <map> 8 9 #include "base/bind.h" 10 #include "base/bind_helpers.h" 11 #include "base/command_line.h" 12 #include "base/debug/alias.h" 13 #include "base/strings/sys_string_conversions.h" 14 #include "base/strings/utf_string_conversions.h" 15 #include "base/threading/thread.h" 16 #include "base/threading/worker_pool.h" 17 #include "content/browser/browser_main_loop.h" 18 #include "content/browser/child_process_security_policy_impl.h" 19 #include "content/browser/dom_storage/dom_storage_context_wrapper.h" 20 #include "content/browser/dom_storage/session_storage_namespace_impl.h" 21 #include "content/browser/download/download_stats.h" 22 #include "content/browser/gpu/gpu_data_manager_impl.h" 23 #include "content/browser/loader/resource_dispatcher_host_impl.h" 24 #include "content/browser/media/media_internals.h" 25 #include "content/browser/plugin_process_host.h" 26 #include "content/browser/plugin_service_impl.h" 27 #include "content/browser/ppapi_plugin_process_host.h" 28 #include "content/browser/renderer_host/pepper/pepper_security_helper.h" 29 #include "content/browser/renderer_host/render_process_host_impl.h" 30 #include "content/browser/renderer_host/render_view_host_delegate.h" 31 #include "content/browser/renderer_host/render_widget_helper.h" 32 #include "content/common/child_process_host_impl.h" 33 #include "content/common/child_process_messages.h" 34 #include "content/common/cookie_data.h" 35 #include "content/common/desktop_notification_messages.h" 36 #include "content/common/media/media_param_traits.h" 37 #include "content/common/view_messages.h" 38 #include "content/public/browser/browser_child_process_host.h" 39 #include "content/public/browser/browser_context.h" 40 #include "content/public/browser/browser_thread.h" 41 #include "content/public/browser/content_browser_client.h" 42 #include "content/public/browser/download_save_info.h" 43 #include "content/public/browser/plugin_service_filter.h" 44 #include "content/public/browser/resource_context.h" 45 #include "content/public/browser/user_metrics.h" 46 #include "content/public/common/content_constants.h" 47 #include "content/public/common/content_switches.h" 48 #include "content/public/common/context_menu_params.h" 49 #include "content/public/common/url_constants.h" 50 #include "content/public/common/webplugininfo.h" 51 #include "ipc/ipc_channel_handle.h" 52 #include "ipc/ipc_platform_file.h" 53 #include "media/audio/audio_manager.h" 54 #include "media/audio/audio_manager_base.h" 55 #include "media/audio/audio_parameters.h" 56 #include "media/base/media_log_event.h" 57 #include "net/base/io_buffer.h" 58 #include "net/base/keygen_handler.h" 59 #include "net/base/mime_util.h" 60 #include "net/base/request_priority.h" 61 #include "net/cookies/canonical_cookie.h" 62 #include "net/cookies/cookie_monster.h" 63 #include "net/http/http_cache.h" 64 #include "net/url_request/url_request_context.h" 65 #include "net/url_request/url_request_context_getter.h" 66 #include "ppapi/shared_impl/file_type_conversion.h" 67 #include "third_party/WebKit/public/web/WebNotificationPresenter.h" 68 #include "ui/gfx/color_profile.h" 69 70 #if defined(OS_MACOSX) 71 #include "content/common/mac/font_descriptor.h" 72 #else 73 #include "gpu/GLES2/gl2extchromium.h" 74 #include "third_party/khronos/GLES2/gl2.h" 75 #include "third_party/khronos/GLES2/gl2ext.h" 76 #endif 77 #if defined(OS_POSIX) 78 #include "base/file_descriptor_posix.h" 79 #endif 80 #if defined(OS_WIN) 81 #include "content/browser/renderer_host/backing_store_win.h" 82 #include "content/common/font_cache_dispatcher_win.h" 83 #endif 84 #if defined(OS_ANDROID) 85 #include "media/base/android/webaudio_media_codec_bridge.h" 86 #endif 87 88 using net::CookieStore; 89 90 namespace content { 91 namespace { 92 93 const int kPluginsRefreshThresholdInSeconds = 3; 94 95 // When two CPU usage queries arrive within this interval, we sample the CPU 96 // usage only once and send it as a response for both queries. 97 static const int64 kCPUUsageSampleIntervalMs = 900; 98 99 // On Windows, |g_color_profile| can run on an arbitrary background thread. 100 // We avoid races by using LazyInstance's constructor lock to initialize the 101 // object. 102 base::LazyInstance<gfx::ColorProfile>::Leaky g_color_profile = 103 LAZY_INSTANCE_INITIALIZER; 104 105 // Common functionality for converting a sync renderer message to a callback 106 // function in the browser. Derive from this, create it on the heap when 107 // issuing your callback. When done, write your reply parameters into 108 // reply_msg(), and then call SendReplyAndDeleteThis(). 109 class RenderMessageCompletionCallback { 110 public: 111 RenderMessageCompletionCallback(RenderMessageFilter* filter, 112 IPC::Message* reply_msg) 113 : filter_(filter), 114 reply_msg_(reply_msg) { 115 } 116 117 virtual ~RenderMessageCompletionCallback() { 118 } 119 120 RenderMessageFilter* filter() { return filter_.get(); } 121 IPC::Message* reply_msg() { return reply_msg_; } 122 123 void SendReplyAndDeleteThis() { 124 filter_->Send(reply_msg_); 125 delete this; 126 } 127 128 private: 129 scoped_refptr<RenderMessageFilter> filter_; 130 IPC::Message* reply_msg_; 131 }; 132 133 class OpenChannelToPpapiPluginCallback 134 : public RenderMessageCompletionCallback, 135 public PpapiPluginProcessHost::PluginClient { 136 public: 137 OpenChannelToPpapiPluginCallback(RenderMessageFilter* filter, 138 ResourceContext* context, 139 IPC::Message* reply_msg) 140 : RenderMessageCompletionCallback(filter, reply_msg), 141 context_(context) { 142 } 143 144 virtual void GetPpapiChannelInfo(base::ProcessHandle* renderer_handle, 145 int* renderer_id) OVERRIDE { 146 *renderer_handle = filter()->PeerHandle(); 147 *renderer_id = filter()->render_process_id(); 148 } 149 150 virtual void OnPpapiChannelOpened(const IPC::ChannelHandle& channel_handle, 151 base::ProcessId plugin_pid, 152 int plugin_child_id) OVERRIDE { 153 ViewHostMsg_OpenChannelToPepperPlugin::WriteReplyParams( 154 reply_msg(), channel_handle, plugin_pid, plugin_child_id); 155 SendReplyAndDeleteThis(); 156 } 157 158 virtual bool OffTheRecord() OVERRIDE { 159 return filter()->OffTheRecord(); 160 } 161 162 virtual ResourceContext* GetResourceContext() OVERRIDE { 163 return context_; 164 } 165 166 private: 167 ResourceContext* context_; 168 }; 169 170 class OpenChannelToPpapiBrokerCallback 171 : public PpapiPluginProcessHost::BrokerClient { 172 public: 173 OpenChannelToPpapiBrokerCallback(RenderMessageFilter* filter, 174 int routing_id) 175 : filter_(filter), 176 routing_id_(routing_id) { 177 } 178 179 virtual ~OpenChannelToPpapiBrokerCallback() {} 180 181 virtual void GetPpapiChannelInfo(base::ProcessHandle* renderer_handle, 182 int* renderer_id) OVERRIDE { 183 *renderer_handle = filter_->PeerHandle(); 184 *renderer_id = filter_->render_process_id(); 185 } 186 187 virtual void OnPpapiChannelOpened(const IPC::ChannelHandle& channel_handle, 188 base::ProcessId plugin_pid, 189 int /* plugin_child_id */) OVERRIDE { 190 filter_->Send(new ViewMsg_PpapiBrokerChannelCreated(routing_id_, 191 plugin_pid, 192 channel_handle)); 193 delete this; 194 } 195 196 virtual bool OffTheRecord() OVERRIDE { 197 return filter_->OffTheRecord(); 198 } 199 200 private: 201 scoped_refptr<RenderMessageFilter> filter_; 202 int routing_id_; 203 }; 204 205 } // namespace 206 207 class RenderMessageFilter::OpenChannelToNpapiPluginCallback 208 : public RenderMessageCompletionCallback, 209 public PluginProcessHost::Client { 210 public: 211 OpenChannelToNpapiPluginCallback(RenderMessageFilter* filter, 212 ResourceContext* context, 213 IPC::Message* reply_msg) 214 : RenderMessageCompletionCallback(filter, reply_msg), 215 context_(context), 216 host_(NULL), 217 sent_plugin_channel_request_(false) { 218 } 219 220 virtual int ID() OVERRIDE { 221 return filter()->render_process_id(); 222 } 223 224 virtual ResourceContext* GetResourceContext() OVERRIDE { 225 return context_; 226 } 227 228 virtual bool OffTheRecord() OVERRIDE { 229 if (filter()->OffTheRecord()) 230 return true; 231 if (GetContentClient()->browser()->AllowSaveLocalState(context_)) 232 return false; 233 234 // For now, only disallow storing data for Flash <http://crbug.com/97319>. 235 for (size_t i = 0; i < info_.mime_types.size(); ++i) { 236 if (info_.mime_types[i].mime_type == kFlashPluginSwfMimeType) 237 return true; 238 } 239 return false; 240 } 241 242 virtual void SetPluginInfo(const WebPluginInfo& info) OVERRIDE { 243 info_ = info; 244 } 245 246 virtual void OnFoundPluginProcessHost(PluginProcessHost* host) OVERRIDE { 247 DCHECK(host); 248 host_ = host; 249 } 250 251 virtual void OnSentPluginChannelRequest() OVERRIDE { 252 sent_plugin_channel_request_ = true; 253 } 254 255 virtual void OnChannelOpened(const IPC::ChannelHandle& handle) OVERRIDE { 256 WriteReplyAndDeleteThis(handle); 257 } 258 259 virtual void OnError() OVERRIDE { 260 WriteReplyAndDeleteThis(IPC::ChannelHandle()); 261 } 262 263 PluginProcessHost* host() const { 264 return host_; 265 } 266 267 bool sent_plugin_channel_request() const { 268 return sent_plugin_channel_request_; 269 } 270 271 void Cancel() { 272 delete this; 273 } 274 275 private: 276 void WriteReplyAndDeleteThis(const IPC::ChannelHandle& handle) { 277 ViewHostMsg_OpenChannelToPlugin::WriteReplyParams(reply_msg(), 278 handle, info_); 279 filter()->OnCompletedOpenChannelToNpapiPlugin(this); 280 SendReplyAndDeleteThis(); 281 } 282 283 ResourceContext* context_; 284 WebPluginInfo info_; 285 PluginProcessHost* host_; 286 bool sent_plugin_channel_request_; 287 }; 288 289 RenderMessageFilter::RenderMessageFilter( 290 int render_process_id, 291 bool is_guest, 292 PluginServiceImpl* plugin_service, 293 BrowserContext* browser_context, 294 net::URLRequestContextGetter* request_context, 295 RenderWidgetHelper* render_widget_helper, 296 media::AudioManager* audio_manager, 297 MediaInternals* media_internals, 298 DOMStorageContextWrapper* dom_storage_context) 299 : resource_dispatcher_host_(ResourceDispatcherHostImpl::Get()), 300 plugin_service_(plugin_service), 301 profile_data_directory_(browser_context->GetPath()), 302 request_context_(request_context), 303 resource_context_(browser_context->GetResourceContext()), 304 render_widget_helper_(render_widget_helper), 305 incognito_(browser_context->IsOffTheRecord()), 306 dom_storage_context_(dom_storage_context), 307 render_process_id_(render_process_id), 308 is_guest_(is_guest), 309 cpu_usage_(0), 310 audio_manager_(audio_manager), 311 media_internals_(media_internals) { 312 DCHECK(request_context_.get()); 313 314 render_widget_helper_->Init(render_process_id_, resource_dispatcher_host_); 315 } 316 317 RenderMessageFilter::~RenderMessageFilter() { 318 // This function should be called on the IO thread. 319 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 320 DCHECK(plugin_host_clients_.empty()); 321 } 322 323 void RenderMessageFilter::OnChannelClosing() { 324 BrowserMessageFilter::OnChannelClosing(); 325 #if defined(ENABLE_PLUGINS) 326 for (std::set<OpenChannelToNpapiPluginCallback*>::iterator it = 327 plugin_host_clients_.begin(); it != plugin_host_clients_.end(); ++it) { 328 OpenChannelToNpapiPluginCallback* client = *it; 329 if (client->host()) { 330 if (client->sent_plugin_channel_request()) { 331 client->host()->CancelSentRequest(client); 332 } else { 333 client->host()->CancelPendingRequest(client); 334 } 335 } else { 336 plugin_service_->CancelOpenChannelToNpapiPlugin(client); 337 } 338 client->Cancel(); 339 } 340 #endif // defined(ENABLE_PLUGINS) 341 plugin_host_clients_.clear(); 342 } 343 344 void RenderMessageFilter::OnChannelConnected(int32 peer_id) { 345 BrowserMessageFilter::OnChannelConnected(peer_id); 346 base::ProcessHandle handle = PeerHandle(); 347 #if defined(OS_MACOSX) 348 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle, 349 NULL)); 350 #else 351 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle)); 352 #endif 353 cpu_usage_ = process_metrics_->GetCPUUsage(); // Initialize CPU usage counters 354 cpu_usage_sample_time_ = base::TimeTicks::Now(); 355 } 356 357 bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message, 358 bool* message_was_ok) { 359 bool handled = true; 360 IPC_BEGIN_MESSAGE_MAP_EX(RenderMessageFilter, message, *message_was_ok) 361 #if defined(OS_WIN) 362 IPC_MESSAGE_HANDLER(ViewHostMsg_PreCacheFontCharacters, 363 OnPreCacheFontCharacters) 364 #endif 365 IPC_MESSAGE_HANDLER(ViewHostMsg_GetProcessMemorySizes, 366 OnGetProcessMemorySizes) 367 IPC_MESSAGE_HANDLER(ViewHostMsg_GenerateRoutingID, OnGenerateRoutingID) 368 IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWindow, OnCreateWindow) 369 IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidget, OnCreateWidget) 370 IPC_MESSAGE_HANDLER(ViewHostMsg_CreateFullscreenWidget, 371 OnCreateFullscreenWidget) 372 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCookie, OnSetCookie) 373 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetCookies, OnGetCookies) 374 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetRawCookies, OnGetRawCookies) 375 IPC_MESSAGE_HANDLER(ViewHostMsg_DeleteCookie, OnDeleteCookie) 376 IPC_MESSAGE_HANDLER(ViewHostMsg_CookiesEnabled, OnCookiesEnabled) 377 #if defined(OS_MACOSX) 378 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_LoadFont, OnLoadFont) 379 #endif 380 IPC_MESSAGE_HANDLER(ViewHostMsg_DownloadUrl, OnDownloadUrl) 381 #if defined(ENABLE_PLUGINS) 382 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetPlugins, OnGetPlugins) 383 IPC_MESSAGE_HANDLER(ViewHostMsg_GetPluginInfo, OnGetPluginInfo) 384 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPlugin, 385 OnOpenChannelToPlugin) 386 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPepperPlugin, 387 OnOpenChannelToPepperPlugin) 388 IPC_MESSAGE_HANDLER(ViewHostMsg_DidCreateOutOfProcessPepperInstance, 389 OnDidCreateOutOfProcessPepperInstance) 390 IPC_MESSAGE_HANDLER(ViewHostMsg_DidDeleteOutOfProcessPepperInstance, 391 OnDidDeleteOutOfProcessPepperInstance) 392 IPC_MESSAGE_HANDLER(ViewHostMsg_OpenChannelToPpapiBroker, 393 OnOpenChannelToPpapiBroker) 394 IPC_MESSAGE_HANDLER(ViewHostMsg_AsyncOpenPepperFile, OnAsyncOpenPepperFile) 395 #endif 396 IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_UpdateRect, 397 render_widget_helper_->DidReceiveBackingStoreMsg(message)) 398 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateIsDelayed, OnUpdateIsDelayed) 399 IPC_MESSAGE_HANDLER(DesktopNotificationHostMsg_CheckPermission, 400 OnCheckNotificationPermission) 401 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateSharedMemory, 402 OnAllocateSharedMemory) 403 #if defined(OS_POSIX) && !defined(TOOLKIT_GTK) && !defined(OS_ANDROID) 404 IPC_MESSAGE_HANDLER(ViewHostMsg_AllocTransportDIB, OnAllocTransportDIB) 405 IPC_MESSAGE_HANDLER(ViewHostMsg_FreeTransportDIB, OnFreeTransportDIB) 406 #endif 407 IPC_MESSAGE_HANDLER(ViewHostMsg_DidGenerateCacheableMetadata, 408 OnCacheableMetadataAvailable) 409 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_Keygen, OnKeygen) 410 IPC_MESSAGE_HANDLER(ViewHostMsg_GetCPUUsage, OnGetCPUUsage) 411 IPC_MESSAGE_HANDLER(ViewHostMsg_GetAudioHardwareConfig, 412 OnGetAudioHardwareConfig) 413 IPC_MESSAGE_HANDLER(ViewHostMsg_GetMonitorColorProfile, 414 OnGetMonitorColorProfile) 415 IPC_MESSAGE_HANDLER(ViewHostMsg_MediaLogEvents, OnMediaLogEvents) 416 IPC_MESSAGE_HANDLER(ViewHostMsg_Are3DAPIsBlocked, OnAre3DAPIsBlocked) 417 IPC_MESSAGE_HANDLER(ViewHostMsg_DidLose3DContext, OnDidLose3DContext) 418 #if defined(OS_ANDROID) 419 IPC_MESSAGE_HANDLER(ViewHostMsg_RunWebAudioMediaCodec, OnWebAudioMediaCodec) 420 #endif 421 IPC_MESSAGE_UNHANDLED(handled = false) 422 IPC_END_MESSAGE_MAP_EX() 423 424 return handled; 425 } 426 427 void RenderMessageFilter::OnDestruct() const { 428 BrowserThread::DeleteOnIOThread::Destruct(this); 429 } 430 431 base::TaskRunner* RenderMessageFilter::OverrideTaskRunnerForMessage( 432 const IPC::Message& message) { 433 #if defined(OS_WIN) 434 // Windows monitor profile must be read from a file. 435 if (message.type() == ViewHostMsg_GetMonitorColorProfile::ID) 436 return BrowserThread::GetBlockingPool(); 437 #endif 438 #if defined(OS_MACOSX) 439 // OSX CoreAudio calls must all happen on the main thread. 440 if (message.type() == ViewHostMsg_GetAudioHardwareConfig::ID) 441 return audio_manager_->GetMessageLoop().get(); 442 #endif 443 if (message.type() == ViewHostMsg_AsyncOpenPepperFile::ID) 444 return BrowserThread::GetBlockingPool(); 445 return NULL; 446 } 447 448 bool RenderMessageFilter::OffTheRecord() const { 449 return incognito_; 450 } 451 452 void RenderMessageFilter::OnCreateWindow( 453 const ViewHostMsg_CreateWindow_Params& params, 454 int* route_id, 455 int* main_frame_route_id, 456 int* surface_id, 457 int64* cloned_session_storage_namespace_id) { 458 bool no_javascript_access; 459 bool can_create_window = 460 GetContentClient()->browser()->CanCreateWindow( 461 params.opener_url, 462 params.opener_top_level_frame_url, 463 params.opener_security_origin, 464 params.window_container_type, 465 params.target_url, 466 params.referrer, 467 params.disposition, 468 params.features, 469 params.user_gesture, 470 params.opener_suppressed, 471 resource_context_, 472 render_process_id_, 473 is_guest_, 474 params.opener_id, 475 &no_javascript_access); 476 477 if (!can_create_window) { 478 *route_id = MSG_ROUTING_NONE; 479 *main_frame_route_id = MSG_ROUTING_NONE; 480 *surface_id = 0; 481 return; 482 } 483 484 // This will clone the sessionStorage for namespace_id_to_clone. 485 scoped_refptr<SessionStorageNamespaceImpl> cloned_namespace = 486 new SessionStorageNamespaceImpl(dom_storage_context_.get(), 487 params.session_storage_namespace_id); 488 *cloned_session_storage_namespace_id = cloned_namespace->id(); 489 490 render_widget_helper_->CreateNewWindow(params, 491 no_javascript_access, 492 PeerHandle(), 493 route_id, 494 main_frame_route_id, 495 surface_id, 496 cloned_namespace.get()); 497 } 498 499 void RenderMessageFilter::OnCreateWidget(int opener_id, 500 WebKit::WebPopupType popup_type, 501 int* route_id, 502 int* surface_id) { 503 render_widget_helper_->CreateNewWidget( 504 opener_id, popup_type, route_id, surface_id); 505 } 506 507 void RenderMessageFilter::OnCreateFullscreenWidget(int opener_id, 508 int* route_id, 509 int* surface_id) { 510 render_widget_helper_->CreateNewFullscreenWidget( 511 opener_id, route_id, surface_id); 512 } 513 514 void RenderMessageFilter::OnGetProcessMemorySizes(size_t* private_bytes, 515 size_t* shared_bytes) { 516 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 517 using base::ProcessMetrics; 518 #if !defined(OS_MACOSX) || defined(OS_IOS) 519 scoped_ptr<ProcessMetrics> metrics(ProcessMetrics::CreateProcessMetrics( 520 PeerHandle())); 521 #else 522 scoped_ptr<ProcessMetrics> metrics(ProcessMetrics::CreateProcessMetrics( 523 PeerHandle(), content::BrowserChildProcessHost::GetPortProvider())); 524 #endif 525 if (!metrics->GetMemoryBytes(private_bytes, shared_bytes)) { 526 *private_bytes = 0; 527 *shared_bytes = 0; 528 } 529 } 530 531 void RenderMessageFilter::OnSetCookie(const IPC::Message& message, 532 const GURL& url, 533 const GURL& first_party_for_cookies, 534 const std::string& cookie) { 535 ChildProcessSecurityPolicyImpl* policy = 536 ChildProcessSecurityPolicyImpl::GetInstance(); 537 if (!policy->CanAccessCookiesForOrigin(render_process_id_, url)) 538 return; 539 540 net::CookieOptions options; 541 if (GetContentClient()->browser()->AllowSetCookie( 542 url, first_party_for_cookies, cookie, 543 resource_context_, render_process_id_, message.routing_id(), 544 &options)) { 545 net::URLRequestContext* context = GetRequestContextForURL(url); 546 // Pass a null callback since we don't care about when the 'set' completes. 547 context->cookie_store()->SetCookieWithOptionsAsync( 548 url, cookie, options, net::CookieMonster::SetCookiesCallback()); 549 } 550 } 551 552 void RenderMessageFilter::OnGetCookies(const GURL& url, 553 const GURL& first_party_for_cookies, 554 IPC::Message* reply_msg) { 555 ChildProcessSecurityPolicyImpl* policy = 556 ChildProcessSecurityPolicyImpl::GetInstance(); 557 if (!policy->CanAccessCookiesForOrigin(render_process_id_, url)) { 558 SendGetCookiesResponse(reply_msg, std::string()); 559 return; 560 } 561 562 // If we crash here, figure out what URL the renderer was requesting. 563 // http://crbug.com/99242 564 char url_buf[128]; 565 base::strlcpy(url_buf, url.spec().c_str(), arraysize(url_buf)); 566 base::debug::Alias(url_buf); 567 568 net::URLRequestContext* context = GetRequestContextForURL(url); 569 net::CookieMonster* cookie_monster = 570 context->cookie_store()->GetCookieMonster(); 571 cookie_monster->GetAllCookiesForURLAsync( 572 url, base::Bind(&RenderMessageFilter::CheckPolicyForCookies, this, url, 573 first_party_for_cookies, reply_msg)); 574 } 575 576 void RenderMessageFilter::OnGetRawCookies( 577 const GURL& url, 578 const GURL& first_party_for_cookies, 579 IPC::Message* reply_msg) { 580 ChildProcessSecurityPolicyImpl* policy = 581 ChildProcessSecurityPolicyImpl::GetInstance(); 582 // Only return raw cookies to trusted renderers or if this request is 583 // not targeted to an an external host like ChromeFrame. 584 // TODO(ananta) We need to support retreiving raw cookies from external 585 // hosts. 586 if (!policy->CanReadRawCookies(render_process_id_) || 587 !policy->CanAccessCookiesForOrigin(render_process_id_, url)) { 588 SendGetRawCookiesResponse(reply_msg, net::CookieList()); 589 return; 590 } 591 592 // We check policy here to avoid sending back cookies that would not normally 593 // be applied to outbound requests for the given URL. Since this cookie info 594 // is visible in the developer tools, it is helpful to make it match reality. 595 net::URLRequestContext* context = GetRequestContextForURL(url); 596 net::CookieMonster* cookie_monster = 597 context->cookie_store()->GetCookieMonster(); 598 cookie_monster->GetAllCookiesForURLAsync( 599 url, base::Bind(&RenderMessageFilter::SendGetRawCookiesResponse, 600 this, reply_msg)); 601 } 602 603 void RenderMessageFilter::OnDeleteCookie(const GURL& url, 604 const std::string& cookie_name) { 605 ChildProcessSecurityPolicyImpl* policy = 606 ChildProcessSecurityPolicyImpl::GetInstance(); 607 if (!policy->CanAccessCookiesForOrigin(render_process_id_, url)) 608 return; 609 610 net::URLRequestContext* context = GetRequestContextForURL(url); 611 context->cookie_store()->DeleteCookieAsync(url, cookie_name, base::Closure()); 612 } 613 614 void RenderMessageFilter::OnCookiesEnabled( 615 const GURL& url, 616 const GURL& first_party_for_cookies, 617 bool* cookies_enabled) { 618 // TODO(ananta): If this render view is associated with an automation channel, 619 // aka ChromeFrame then we need to retrieve cookie settings from the external 620 // host. 621 *cookies_enabled = GetContentClient()->browser()->AllowGetCookie( 622 url, first_party_for_cookies, net::CookieList(), resource_context_, 623 render_process_id_, MSG_ROUTING_CONTROL); 624 } 625 626 #if defined(OS_MACOSX) 627 void RenderMessageFilter::OnLoadFont(const FontDescriptor& font, 628 IPC::Message* reply_msg) { 629 FontLoader::Result* result = new FontLoader::Result; 630 631 BrowserThread::PostTaskAndReply( 632 BrowserThread::FILE, FROM_HERE, 633 base::Bind(&FontLoader::LoadFont, font, result), 634 base::Bind(&RenderMessageFilter::SendLoadFontReply, this, reply_msg, 635 base::Owned(result))); 636 } 637 638 void RenderMessageFilter::SendLoadFontReply(IPC::Message* reply, 639 FontLoader::Result* result) { 640 base::SharedMemoryHandle handle; 641 if (result->font_data_size == 0 || result->font_id == 0) { 642 result->font_data_size = 0; 643 result->font_id = 0; 644 handle = base::SharedMemory::NULLHandle(); 645 } else { 646 result->font_data.GiveToProcess(base::GetCurrentProcessHandle(), &handle); 647 } 648 ViewHostMsg_LoadFont::WriteReplyParams( 649 reply, result->font_data_size, handle, result->font_id); 650 Send(reply); 651 } 652 #endif // OS_MACOSX 653 654 void RenderMessageFilter::OnGetPlugins( 655 bool refresh, 656 IPC::Message* reply_msg) { 657 // Don't refresh if the specified threshold has not been passed. Note that 658 // this check is performed before off-loading to the file thread. The reason 659 // we do this is that some pages tend to request that the list of plugins be 660 // refreshed at an excessive rate. This instigates disk scanning, as the list 661 // is accumulated by doing multiple reads from disk. This effect is 662 // multiplied when we have several pages requesting this operation. 663 if (refresh) { 664 const base::TimeDelta threshold = base::TimeDelta::FromSeconds( 665 kPluginsRefreshThresholdInSeconds); 666 const base::TimeTicks now = base::TimeTicks::Now(); 667 if (now - last_plugin_refresh_time_ >= threshold) { 668 // Only refresh if the threshold hasn't been exceeded yet. 669 PluginServiceImpl::GetInstance()->RefreshPlugins(); 670 last_plugin_refresh_time_ = now; 671 } 672 } 673 674 PluginServiceImpl::GetInstance()->GetPlugins( 675 base::Bind(&RenderMessageFilter::GetPluginsCallback, this, reply_msg)); 676 } 677 678 void RenderMessageFilter::GetPluginsCallback( 679 IPC::Message* reply_msg, 680 const std::vector<WebPluginInfo>& all_plugins) { 681 // Filter the plugin list. 682 PluginServiceFilter* filter = PluginServiceImpl::GetInstance()->GetFilter(); 683 std::vector<WebPluginInfo> plugins; 684 685 int child_process_id = -1; 686 int routing_id = MSG_ROUTING_NONE; 687 for (size_t i = 0; i < all_plugins.size(); ++i) { 688 // Copy because the filter can mutate. 689 WebPluginInfo plugin(all_plugins[i]); 690 if (!filter || filter->IsPluginAvailable(child_process_id, 691 routing_id, 692 resource_context_, 693 GURL(), 694 GURL(), 695 &plugin)) { 696 plugins.push_back(plugin); 697 } 698 } 699 700 ViewHostMsg_GetPlugins::WriteReplyParams(reply_msg, plugins); 701 Send(reply_msg); 702 } 703 704 void RenderMessageFilter::OnGetPluginInfo( 705 int routing_id, 706 const GURL& url, 707 const GURL& page_url, 708 const std::string& mime_type, 709 bool* found, 710 WebPluginInfo* info, 711 std::string* actual_mime_type) { 712 bool allow_wildcard = true; 713 *found = plugin_service_->GetPluginInfo( 714 render_process_id_, routing_id, resource_context_, 715 url, page_url, mime_type, allow_wildcard, 716 NULL, info, actual_mime_type); 717 } 718 719 void RenderMessageFilter::OnOpenChannelToPlugin(int routing_id, 720 const GURL& url, 721 const GURL& policy_url, 722 const std::string& mime_type, 723 IPC::Message* reply_msg) { 724 OpenChannelToNpapiPluginCallback* client = 725 new OpenChannelToNpapiPluginCallback(this, resource_context_, reply_msg); 726 DCHECK(!ContainsKey(plugin_host_clients_, client)); 727 plugin_host_clients_.insert(client); 728 plugin_service_->OpenChannelToNpapiPlugin( 729 render_process_id_, routing_id, 730 url, policy_url, mime_type, client); 731 } 732 733 void RenderMessageFilter::OnOpenChannelToPepperPlugin( 734 const base::FilePath& path, 735 IPC::Message* reply_msg) { 736 plugin_service_->OpenChannelToPpapiPlugin( 737 render_process_id_, 738 path, 739 profile_data_directory_, 740 new OpenChannelToPpapiPluginCallback(this, resource_context_, reply_msg)); 741 } 742 743 void RenderMessageFilter::OnDidCreateOutOfProcessPepperInstance( 744 int plugin_child_id, 745 int32 pp_instance, 746 PepperRendererInstanceData instance_data, 747 bool is_external) { 748 // It's important that we supply the render process ID ourselves based on the 749 // channel the message arrived on. We use the 750 // PP_Instance -> (process id, view id) 751 // mapping to decide how to handle messages received from the (untrusted) 752 // plugin, so an exploited renderer must not be able to insert fake mappings 753 // that may allow it access to other render processes. 754 DCHECK_EQ(0, instance_data.render_process_id); 755 instance_data.render_process_id = render_process_id_; 756 if (is_external) { 757 // We provide the BrowserPpapiHost to the embedder, so it's safe to cast. 758 BrowserPpapiHostImpl* host = static_cast<BrowserPpapiHostImpl*>( 759 GetContentClient()->browser()->GetExternalBrowserPpapiHost( 760 plugin_child_id)); 761 if (host) 762 host->AddInstance(pp_instance, instance_data); 763 } else { 764 PpapiPluginProcessHost::DidCreateOutOfProcessInstance( 765 plugin_child_id, pp_instance, instance_data); 766 } 767 } 768 769 void RenderMessageFilter::OnDidDeleteOutOfProcessPepperInstance( 770 int plugin_child_id, 771 int32 pp_instance, 772 bool is_external) { 773 if (is_external) { 774 // We provide the BrowserPpapiHost to the embedder, so it's safe to cast. 775 BrowserPpapiHostImpl* host = static_cast<BrowserPpapiHostImpl*>( 776 GetContentClient()->browser()->GetExternalBrowserPpapiHost( 777 plugin_child_id)); 778 if (host) 779 host->DeleteInstance(pp_instance); 780 } else { 781 PpapiPluginProcessHost::DidDeleteOutOfProcessInstance( 782 plugin_child_id, pp_instance); 783 } 784 } 785 786 void RenderMessageFilter::OnOpenChannelToPpapiBroker( 787 int routing_id, 788 const base::FilePath& path) { 789 plugin_service_->OpenChannelToPpapiBroker( 790 render_process_id_, 791 path, 792 new OpenChannelToPpapiBrokerCallback(this, routing_id)); 793 } 794 795 void RenderMessageFilter::OnGenerateRoutingID(int* route_id) { 796 *route_id = render_widget_helper_->GetNextRoutingID(); 797 } 798 799 void RenderMessageFilter::OnGetCPUUsage(int* cpu_usage) { 800 base::TimeTicks now = base::TimeTicks::Now(); 801 int64 since_last_sample_ms = (now - cpu_usage_sample_time_).InMilliseconds(); 802 if (since_last_sample_ms > kCPUUsageSampleIntervalMs) { 803 cpu_usage_sample_time_ = now; 804 cpu_usage_ = static_cast<int>(process_metrics_->GetCPUUsage()); 805 } 806 *cpu_usage = cpu_usage_; 807 } 808 809 void RenderMessageFilter::OnGetAudioHardwareConfig( 810 media::AudioParameters* input_params, 811 media::AudioParameters* output_params) { 812 DCHECK(input_params); 813 DCHECK(output_params); 814 *output_params = audio_manager_->GetDefaultOutputStreamParameters(); 815 816 // TODO(henrika): add support for all available input devices. 817 *input_params = audio_manager_->GetInputStreamParameters( 818 media::AudioManagerBase::kDefaultDeviceId); 819 } 820 821 void RenderMessageFilter::OnGetMonitorColorProfile(std::vector<char>* profile) { 822 #if defined(OS_WIN) 823 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO)); 824 if (BackingStoreWin::ColorManagementEnabled()) 825 return; 826 #endif 827 *profile = g_color_profile.Get().profile(); 828 } 829 830 void RenderMessageFilter::OnDownloadUrl(const IPC::Message& message, 831 const GURL& url, 832 const Referrer& referrer, 833 const string16& suggested_name) { 834 scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo()); 835 save_info->suggested_name = suggested_name; 836 scoped_ptr<net::URLRequest> request( 837 resource_context_->GetRequestContext()->CreateRequest(url, NULL)); 838 RecordDownloadSource(INITIATED_BY_RENDERER); 839 resource_dispatcher_host_->BeginDownload( 840 request.Pass(), 841 referrer, 842 true, // is_content_initiated 843 resource_context_, 844 render_process_id_, 845 message.routing_id(), 846 false, 847 save_info.Pass(), 848 content::DownloadItem::kInvalidId, 849 ResourceDispatcherHostImpl::DownloadStartedCallback()); 850 } 851 852 void RenderMessageFilter::OnCheckNotificationPermission( 853 const GURL& source_origin, int* result) { 854 #if defined(ENABLE_NOTIFICATIONS) 855 *result = GetContentClient()->browser()-> 856 CheckDesktopNotificationPermission(source_origin, resource_context_, 857 render_process_id_); 858 #else 859 *result = WebKit::WebNotificationPresenter::PermissionAllowed; 860 #endif 861 } 862 863 void RenderMessageFilter::OnAllocateSharedMemory( 864 uint32 buffer_size, 865 base::SharedMemoryHandle* handle) { 866 ChildProcessHostImpl::AllocateSharedMemory( 867 buffer_size, PeerHandle(), handle); 868 } 869 870 net::URLRequestContext* RenderMessageFilter::GetRequestContextForURL( 871 const GURL& url) { 872 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 873 874 net::URLRequestContext* context = 875 GetContentClient()->browser()->OverrideRequestContextForURL( 876 url, resource_context_); 877 if (!context) 878 context = request_context_->GetURLRequestContext(); 879 880 return context; 881 } 882 883 #if defined(OS_POSIX) && !defined(TOOLKIT_GTK) && !defined(OS_ANDROID) 884 void RenderMessageFilter::OnAllocTransportDIB( 885 uint32 size, bool cache_in_browser, TransportDIB::Handle* handle) { 886 render_widget_helper_->AllocTransportDIB(size, cache_in_browser, handle); 887 } 888 889 void RenderMessageFilter::OnFreeTransportDIB( 890 TransportDIB::Id dib_id) { 891 render_widget_helper_->FreeTransportDIB(dib_id); 892 } 893 #endif 894 895 bool RenderMessageFilter::CheckPreparsedJsCachingEnabled() const { 896 static bool checked = false; 897 static bool result = false; 898 if (!checked) { 899 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 900 result = command_line.HasSwitch(switches::kEnablePreparsedJsCaching); 901 checked = true; 902 } 903 return result; 904 } 905 906 void RenderMessageFilter::OnCacheableMetadataAvailable( 907 const GURL& url, 908 double expected_response_time, 909 const std::vector<char>& data) { 910 if (!CheckPreparsedJsCachingEnabled()) 911 return; 912 913 net::HttpCache* cache = request_context_->GetURLRequestContext()-> 914 http_transaction_factory()->GetCache(); 915 DCHECK(cache); 916 917 // Use the same priority for the metadata write as for script 918 // resources (see defaultPriorityForResourceType() in WebKit's 919 // CachedResource.cpp). Note that WebURLRequest::PriorityMedium 920 // corresponds to net::LOW (see ConvertWebKitPriorityToNetPriority() 921 // in weburlloader_impl.cc). 922 const net::RequestPriority kPriority = net::LOW; 923 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(data.size())); 924 memcpy(buf->data(), &data.front(), data.size()); 925 cache->WriteMetadata(url, 926 kPriority, 927 base::Time::FromDoubleT(expected_response_time), 928 buf.get(), 929 data.size()); 930 } 931 932 void RenderMessageFilter::OnKeygen(uint32 key_size_index, 933 const std::string& challenge_string, 934 const GURL& url, 935 IPC::Message* reply_msg) { 936 // Map displayed strings indicating level of keysecurity in the <keygen> 937 // menu to the key size in bits. (See SSLKeyGeneratorChromium.cpp in WebCore.) 938 int key_size_in_bits; 939 switch (key_size_index) { 940 case 0: 941 key_size_in_bits = 2048; 942 break; 943 case 1: 944 key_size_in_bits = 1024; 945 break; 946 default: 947 DCHECK(false) << "Illegal key_size_index " << key_size_index; 948 ViewHostMsg_Keygen::WriteReplyParams(reply_msg, std::string()); 949 Send(reply_msg); 950 return; 951 } 952 953 VLOG(1) << "Dispatching keygen task to worker pool."; 954 // Dispatch to worker pool, so we do not block the IO thread. 955 if (!base::WorkerPool::PostTask( 956 FROM_HERE, 957 base::Bind( 958 &RenderMessageFilter::OnKeygenOnWorkerThread, this, 959 key_size_in_bits, challenge_string, url, reply_msg), 960 true)) { 961 NOTREACHED() << "Failed to dispatch keygen task to worker pool"; 962 ViewHostMsg_Keygen::WriteReplyParams(reply_msg, std::string()); 963 Send(reply_msg); 964 return; 965 } 966 } 967 968 void RenderMessageFilter::OnKeygenOnWorkerThread( 969 int key_size_in_bits, 970 const std::string& challenge_string, 971 const GURL& url, 972 IPC::Message* reply_msg) { 973 DCHECK(reply_msg); 974 975 // Generate a signed public key and challenge, then send it back. 976 net::KeygenHandler keygen_handler(key_size_in_bits, challenge_string, url); 977 978 #if defined(USE_NSS) 979 // Attach a password delegate so we can authenticate. 980 keygen_handler.set_crypto_module_password_delegate( 981 GetContentClient()->browser()->GetCryptoPasswordDelegate(url)); 982 #endif // defined(USE_NSS) 983 984 ViewHostMsg_Keygen::WriteReplyParams( 985 reply_msg, 986 keygen_handler.GenKeyAndSignChallenge()); 987 Send(reply_msg); 988 } 989 990 void RenderMessageFilter::OnAsyncOpenPepperFile(int routing_id, 991 const base::FilePath& path, 992 int pp_open_flags, 993 int message_id) { 994 int platform_file_flags = 0; 995 if (!CanOpenWithPepperFlags(pp_open_flags, render_process_id_, path) || 996 !ppapi::PepperFileOpenFlagsToPlatformFileFlags( 997 pp_open_flags, &platform_file_flags)) { 998 DLOG(ERROR) << 999 "Bad pp_open_flags in ViewMsgHost_AsyncOpenPepperFile message: " << 1000 pp_open_flags; 1001 RecordAction(UserMetricsAction("BadMessageTerminate_AOF")); 1002 BadMessageReceived(); 1003 return; 1004 } 1005 1006 base::PlatformFileError error_code = base::PLATFORM_FILE_OK; 1007 base::PlatformFile file = base::CreatePlatformFile( 1008 path, platform_file_flags, NULL, &error_code); 1009 IPC::PlatformFileForTransit file_for_transit = 1010 file != base::kInvalidPlatformFileValue ? 1011 IPC::GetFileHandleForProcess(file, PeerHandle(), true) : 1012 IPC::InvalidPlatformFileForTransit(); 1013 1014 Send(new ViewMsg_AsyncOpenPepperFile_ACK( 1015 routing_id, error_code, file_for_transit, message_id)); 1016 } 1017 1018 void RenderMessageFilter::OnMediaLogEvents( 1019 const std::vector<media::MediaLogEvent>& events) { 1020 if (media_internals_) 1021 media_internals_->OnMediaEvents(render_process_id_, events); 1022 } 1023 1024 void RenderMessageFilter::CheckPolicyForCookies( 1025 const GURL& url, 1026 const GURL& first_party_for_cookies, 1027 IPC::Message* reply_msg, 1028 const net::CookieList& cookie_list) { 1029 net::URLRequestContext* context = GetRequestContextForURL(url); 1030 // Check the policy for get cookies, and pass cookie_list to the 1031 // TabSpecificContentSetting for logging purpose. 1032 if (GetContentClient()->browser()->AllowGetCookie( 1033 url, first_party_for_cookies, cookie_list, resource_context_, 1034 render_process_id_, reply_msg->routing_id())) { 1035 // Gets the cookies from cookie store if allowed. 1036 context->cookie_store()->GetCookiesWithOptionsAsync( 1037 url, net::CookieOptions(), 1038 base::Bind(&RenderMessageFilter::SendGetCookiesResponse, 1039 this, reply_msg)); 1040 } else { 1041 SendGetCookiesResponse(reply_msg, std::string()); 1042 } 1043 } 1044 1045 void RenderMessageFilter::SendGetCookiesResponse(IPC::Message* reply_msg, 1046 const std::string& cookies) { 1047 ViewHostMsg_GetCookies::WriteReplyParams(reply_msg, cookies); 1048 Send(reply_msg); 1049 } 1050 1051 void RenderMessageFilter::SendGetRawCookiesResponse( 1052 IPC::Message* reply_msg, 1053 const net::CookieList& cookie_list) { 1054 std::vector<CookieData> cookies; 1055 for (size_t i = 0; i < cookie_list.size(); ++i) 1056 cookies.push_back(CookieData(cookie_list[i])); 1057 ViewHostMsg_GetRawCookies::WriteReplyParams(reply_msg, cookies); 1058 Send(reply_msg); 1059 } 1060 1061 void RenderMessageFilter::OnCompletedOpenChannelToNpapiPlugin( 1062 OpenChannelToNpapiPluginCallback* client) { 1063 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1064 DCHECK(ContainsKey(plugin_host_clients_, client)); 1065 plugin_host_clients_.erase(client); 1066 } 1067 1068 void RenderMessageFilter::OnUpdateIsDelayed(const IPC::Message& msg) { 1069 // When not in accelerated compositing mode, in certain cases (e.g. waiting 1070 // for a resize or if no backing store) the RenderWidgetHost is blocking the 1071 // UI thread for some time, waiting for an UpdateRect from the renderer. If we 1072 // are going to switch to accelerated compositing, the GPU process may need 1073 // round-trips to the UI thread before finishing the frame, causing deadlocks 1074 // if we delay the UpdateRect until we receive the OnSwapBuffersComplete. So 1075 // the renderer sent us this message, so that we can unblock the UI thread. 1076 // We will simply re-use the UpdateRect unblock mechanism, just with a 1077 // different message. 1078 render_widget_helper_->DidReceiveBackingStoreMsg(msg); 1079 } 1080 1081 void RenderMessageFilter::OnAre3DAPIsBlocked(int render_view_id, 1082 const GURL& top_origin_url, 1083 ThreeDAPIType requester, 1084 bool* blocked) { 1085 *blocked = GpuDataManagerImpl::GetInstance()->Are3DAPIsBlocked( 1086 top_origin_url, render_process_id_, render_view_id, requester); 1087 } 1088 1089 void RenderMessageFilter::OnDidLose3DContext( 1090 const GURL& top_origin_url, 1091 ThreeDAPIType /* unused */, 1092 int arb_robustness_status_code) { 1093 #if defined(OS_MACOSX) 1094 // TODO(kbr): this file indirectly includes npapi.h, which on Mac 1095 // OS pulls in the system OpenGL headers. For some 1096 // not-yet-investigated reason this breaks the build with the 10.6 1097 // SDK but not 10.7. For now work around this in a way compatible 1098 // with the Khronos headers. 1099 #ifndef GL_GUILTY_CONTEXT_RESET_ARB 1100 #define GL_GUILTY_CONTEXT_RESET_ARB 0x8253 1101 #endif 1102 #ifndef GL_INNOCENT_CONTEXT_RESET_ARB 1103 #define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254 1104 #endif 1105 #ifndef GL_UNKNOWN_CONTEXT_RESET_ARB 1106 #define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255 1107 #endif 1108 1109 #endif 1110 GpuDataManagerImpl::DomainGuilt guilt; 1111 switch (arb_robustness_status_code) { 1112 case GL_GUILTY_CONTEXT_RESET_ARB: 1113 guilt = GpuDataManagerImpl::DOMAIN_GUILT_KNOWN; 1114 break; 1115 case GL_UNKNOWN_CONTEXT_RESET_ARB: 1116 guilt = GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN; 1117 break; 1118 default: 1119 // Ignore lost contexts known to be innocent. 1120 return; 1121 } 1122 1123 GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs( 1124 top_origin_url, guilt); 1125 } 1126 1127 #if defined(OS_WIN) 1128 void RenderMessageFilter::OnPreCacheFontCharacters(const LOGFONT& font, 1129 const string16& str) { 1130 // First, comments from FontCacheDispatcher::OnPreCacheFont do apply here too. 1131 // Except that for True Type fonts, 1132 // GetTextMetrics will not load the font in memory. 1133 // The only way windows seem to load properly, it is to create a similar 1134 // device (like the one in which we print), then do an ExtTextOut, 1135 // as we do in the printing thread, which is sandboxed. 1136 HDC hdc = CreateEnhMetaFile(NULL, NULL, NULL, NULL); 1137 HFONT font_handle = CreateFontIndirect(&font); 1138 DCHECK(NULL != font_handle); 1139 1140 HGDIOBJ old_font = SelectObject(hdc, font_handle); 1141 DCHECK(NULL != old_font); 1142 1143 ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, 0, str.c_str(), str.length(), NULL); 1144 1145 SelectObject(hdc, old_font); 1146 DeleteObject(font_handle); 1147 1148 HENHMETAFILE metafile = CloseEnhMetaFile(hdc); 1149 1150 if (metafile) { 1151 DeleteEnhMetaFile(metafile); 1152 } 1153 } 1154 #endif 1155 1156 #if defined(OS_ANDROID) 1157 void RenderMessageFilter::OnWebAudioMediaCodec( 1158 base::SharedMemoryHandle encoded_data_handle, 1159 base::FileDescriptor pcm_output, 1160 uint32_t data_size) { 1161 // Let a WorkerPool handle this request since the WebAudio 1162 // MediaCodec bridge is slow and can block while sending the data to 1163 // the renderer. 1164 base::WorkerPool::PostTask( 1165 FROM_HERE, 1166 base::Bind(&media::WebAudioMediaCodecBridge::RunWebAudioMediaCodec, 1167 encoded_data_handle, pcm_output, data_size), 1168 true); 1169 } 1170 #endif 1171 } // namespace content 1172