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