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