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