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