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