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