render_message_filter.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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    PluginServiceImpl* plugin_service,
329    BrowserContext* browser_context,
330    net::URLRequestContextGetter* request_context,
331    RenderWidgetHelper* render_widget_helper,
332    media::AudioManager* audio_manager,
333    MediaInternals* media_internals,
334    DOMStorageContextWrapper* dom_storage_context)
335    : BrowserMessageFilter(
336          kFilteredMessageClasses, arraysize(kFilteredMessageClasses)),
337      resource_dispatcher_host_(ResourceDispatcherHostImpl::Get()),
338      plugin_service_(plugin_service),
339      profile_data_directory_(browser_context->GetPath()),
340      request_context_(request_context),
341      resource_context_(browser_context->GetResourceContext()),
342      render_widget_helper_(render_widget_helper),
343      incognito_(browser_context->IsOffTheRecord()),
344      dom_storage_context_(dom_storage_context),
345      render_process_id_(render_process_id),
346      cpu_usage_(0),
347      audio_manager_(audio_manager),
348      media_internals_(media_internals) {
349  DCHECK(request_context_.get());
350
351  render_widget_helper_->Init(render_process_id_, resource_dispatcher_host_);
352}
353
354RenderMessageFilter::~RenderMessageFilter() {
355  // This function should be called on the IO thread.
356  DCHECK_CURRENTLY_ON(BrowserThread::IO);
357  DCHECK(plugin_host_clients_.empty());
358}
359
360void RenderMessageFilter::OnChannelClosing() {
361  HostSharedBitmapManager::current()->ProcessRemoved(PeerHandle());
362#if defined(ENABLE_PLUGINS)
363  for (std::set<OpenChannelToNpapiPluginCallback*>::iterator it =
364       plugin_host_clients_.begin(); it != plugin_host_clients_.end(); ++it) {
365    OpenChannelToNpapiPluginCallback* client = *it;
366    if (client->host()) {
367      if (client->sent_plugin_channel_request()) {
368        client->host()->CancelSentRequest(client);
369      } else {
370        client->host()->CancelPendingRequest(client);
371      }
372    } else {
373      plugin_service_->CancelOpenChannelToNpapiPlugin(client);
374    }
375    client->Cancel();
376  }
377#endif  // defined(ENABLE_PLUGINS)
378  plugin_host_clients_.clear();
379#if defined(OS_ANDROID)
380  CompositorImpl::DestroyAllSurfaceTextures(render_process_id_);
381#endif
382}
383
384void RenderMessageFilter::OnChannelConnected(int32 peer_id) {
385  base::ProcessHandle handle = PeerHandle();
386#if defined(OS_MACOSX)
387  process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle,
388                                                                    NULL));
389#else
390  process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle));
391#endif
392  cpu_usage_ = process_metrics_->GetCPUUsage(); // Initialize CPU usage counters
393  cpu_usage_sample_time_ = base::TimeTicks::Now();
394}
395
396bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message) {
397  bool handled = true;
398  IPC_BEGIN_MESSAGE_MAP(RenderMessageFilter, message)
399#if defined(OS_WIN)
400    IPC_MESSAGE_HANDLER(ViewHostMsg_PreCacheFontCharacters,
401                        OnPreCacheFontCharacters)
402#endif
403    IPC_MESSAGE_HANDLER(ViewHostMsg_GetProcessMemorySizes,
404                        OnGetProcessMemorySizes)
405    IPC_MESSAGE_HANDLER(ViewHostMsg_GenerateRoutingID, OnGenerateRoutingID)
406    IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWindow, OnCreateWindow)
407    IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidget, OnCreateWidget)
408    IPC_MESSAGE_HANDLER(ViewHostMsg_CreateFullscreenWidget,
409                        OnCreateFullscreenWidget)
410    IPC_MESSAGE_HANDLER(ViewHostMsg_SetCookie, OnSetCookie)
411    IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetCookies, OnGetCookies)
412    IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetRawCookies, OnGetRawCookies)
413    IPC_MESSAGE_HANDLER(ViewHostMsg_DeleteCookie, OnDeleteCookie)
414    IPC_MESSAGE_HANDLER(ViewHostMsg_CookiesEnabled, OnCookiesEnabled)
415#if defined(OS_MACOSX)
416    IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_LoadFont, OnLoadFont)
417#endif
418    IPC_MESSAGE_HANDLER(ViewHostMsg_DownloadUrl, OnDownloadUrl)
419#if defined(ENABLE_PLUGINS)
420    IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetPlugins, OnGetPlugins)
421    IPC_MESSAGE_HANDLER(FrameHostMsg_GetPluginInfo, OnGetPluginInfo)
422    IPC_MESSAGE_HANDLER_DELAY_REPLY(FrameHostMsg_OpenChannelToPlugin,
423                                    OnOpenChannelToPlugin)
424    IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPepperPlugin,
425                                    OnOpenChannelToPepperPlugin)
426    IPC_MESSAGE_HANDLER(ViewHostMsg_DidCreateOutOfProcessPepperInstance,
427                        OnDidCreateOutOfProcessPepperInstance)
428    IPC_MESSAGE_HANDLER(ViewHostMsg_DidDeleteOutOfProcessPepperInstance,
429                        OnDidDeleteOutOfProcessPepperInstance)
430    IPC_MESSAGE_HANDLER(ViewHostMsg_OpenChannelToPpapiBroker,
431                        OnOpenChannelToPpapiBroker)
432#endif
433    IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_SwapCompositorFrame,
434        render_widget_helper_->DidReceiveBackingStoreMsg(message))
435    IPC_MESSAGE_HANDLER(DesktopNotificationHostMsg_CheckPermission,
436                        OnCheckNotificationPermission)
437    IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateSharedMemory,
438                        OnAllocateSharedMemory)
439    IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateSharedBitmap,
440                        OnAllocateSharedBitmap)
441    IPC_MESSAGE_HANDLER_DELAY_REPLY(
442        ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer,
443        OnAllocateGpuMemoryBuffer)
444    IPC_MESSAGE_HANDLER(ChildProcessHostMsg_AllocatedSharedBitmap,
445                        OnAllocatedSharedBitmap)
446    IPC_MESSAGE_HANDLER(ChildProcessHostMsg_DeletedSharedBitmap,
447                        OnDeletedSharedBitmap)
448#if defined(OS_POSIX) && !defined(OS_ANDROID)
449    IPC_MESSAGE_HANDLER(ViewHostMsg_AllocTransportDIB, OnAllocTransportDIB)
450    IPC_MESSAGE_HANDLER(ViewHostMsg_FreeTransportDIB, OnFreeTransportDIB)
451#endif
452    IPC_MESSAGE_HANDLER(ViewHostMsg_DidGenerateCacheableMetadata,
453                        OnCacheableMetadataAvailable)
454    IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_Keygen, OnKeygen)
455    IPC_MESSAGE_HANDLER(ViewHostMsg_GetCPUUsage, OnGetCPUUsage)
456    IPC_MESSAGE_HANDLER(ViewHostMsg_GetAudioHardwareConfig,
457                        OnGetAudioHardwareConfig)
458#if defined(OS_WIN)
459    IPC_MESSAGE_HANDLER(ViewHostMsg_GetMonitorColorProfile,
460                        OnGetMonitorColorProfile)
461#endif
462    IPC_MESSAGE_HANDLER(ViewHostMsg_MediaLogEvents, OnMediaLogEvents)
463    IPC_MESSAGE_HANDLER(ViewHostMsg_Are3DAPIsBlocked, OnAre3DAPIsBlocked)
464    IPC_MESSAGE_HANDLER(ViewHostMsg_DidLose3DContext, OnDidLose3DContext)
465#if defined(OS_ANDROID)
466    IPC_MESSAGE_HANDLER(ViewHostMsg_RunWebAudioMediaCodec, OnWebAudioMediaCodec)
467#endif
468    IPC_MESSAGE_UNHANDLED(handled = false)
469  IPC_END_MESSAGE_MAP()
470
471  return handled;
472}
473
474void RenderMessageFilter::OnDestruct() const {
475  BrowserThread::DeleteOnIOThread::Destruct(this);
476}
477
478base::TaskRunner* RenderMessageFilter::OverrideTaskRunnerForMessage(
479    const IPC::Message& message) {
480#if defined(OS_WIN)
481  // Windows monitor profile must be read from a file.
482  if (message.type() == ViewHostMsg_GetMonitorColorProfile::ID)
483    return BrowserThread::GetBlockingPool();
484#endif
485  // Always query audio device parameters on the audio thread.
486  if (message.type() == ViewHostMsg_GetAudioHardwareConfig::ID)
487    return audio_manager_->GetTaskRunner().get();
488  return NULL;
489}
490
491bool RenderMessageFilter::OffTheRecord() const {
492  return incognito_;
493}
494
495void RenderMessageFilter::OnCreateWindow(
496    const ViewHostMsg_CreateWindow_Params& params,
497    int* route_id,
498    int* main_frame_route_id,
499    int* surface_id,
500    int64* cloned_session_storage_namespace_id) {
501  bool no_javascript_access;
502
503  // Merge the additional features into the WebWindowFeatures struct before we
504  // pass it on.
505  blink::WebVector<blink::WebString> additional_features(
506      params.additional_features.size());
507
508  for (size_t i = 0; i < params.additional_features.size(); ++i)
509    additional_features[i] = blink::WebString(params.additional_features[i]);
510
511  blink::WebWindowFeatures features = params.features;
512  features.additionalFeatures.swap(additional_features);
513
514  bool can_create_window =
515      GetContentClient()->browser()->CanCreateWindow(
516          params.opener_url,
517          params.opener_top_level_frame_url,
518          params.opener_security_origin,
519          params.window_container_type,
520          params.target_url,
521          params.referrer,
522          params.disposition,
523          features,
524          params.user_gesture,
525          params.opener_suppressed,
526          resource_context_,
527          render_process_id_,
528          params.opener_id,
529          &no_javascript_access);
530
531  if (!can_create_window) {
532    *route_id = MSG_ROUTING_NONE;
533    *main_frame_route_id = MSG_ROUTING_NONE;
534    *surface_id = 0;
535    return;
536  }
537
538  // This will clone the sessionStorage for namespace_id_to_clone.
539  scoped_refptr<SessionStorageNamespaceImpl> cloned_namespace =
540      new SessionStorageNamespaceImpl(dom_storage_context_.get(),
541                                      params.session_storage_namespace_id);
542  *cloned_session_storage_namespace_id = cloned_namespace->id();
543
544  render_widget_helper_->CreateNewWindow(params,
545                                         no_javascript_access,
546                                         PeerHandle(),
547                                         route_id,
548                                         main_frame_route_id,
549                                         surface_id,
550                                         cloned_namespace.get());
551}
552
553void RenderMessageFilter::OnCreateWidget(int opener_id,
554                                         blink::WebPopupType popup_type,
555                                         int* route_id,
556                                         int* surface_id) {
557  render_widget_helper_->CreateNewWidget(
558      opener_id, popup_type, route_id, surface_id);
559}
560
561void RenderMessageFilter::OnCreateFullscreenWidget(int opener_id,
562                                                   int* route_id,
563                                                   int* surface_id) {
564  render_widget_helper_->CreateNewFullscreenWidget(
565      opener_id, route_id, surface_id);
566}
567
568void RenderMessageFilter::OnGetProcessMemorySizes(size_t* private_bytes,
569                                                  size_t* shared_bytes) {
570  DCHECK_CURRENTLY_ON(BrowserThread::IO);
571  using base::ProcessMetrics;
572#if !defined(OS_MACOSX) || defined(OS_IOS)
573  scoped_ptr<ProcessMetrics> metrics(ProcessMetrics::CreateProcessMetrics(
574      PeerHandle()));
575#else
576  scoped_ptr<ProcessMetrics> metrics(ProcessMetrics::CreateProcessMetrics(
577      PeerHandle(), content::BrowserChildProcessHost::GetPortProvider()));
578#endif
579  if (!metrics->GetMemoryBytes(private_bytes, shared_bytes)) {
580    *private_bytes = 0;
581    *shared_bytes = 0;
582  }
583}
584
585void RenderMessageFilter::OnSetCookie(int render_frame_id,
586                                      const GURL& url,
587                                      const GURL& first_party_for_cookies,
588                                      const std::string& cookie) {
589  ChildProcessSecurityPolicyImpl* policy =
590      ChildProcessSecurityPolicyImpl::GetInstance();
591  if (!policy->CanAccessCookiesForOrigin(render_process_id_, url))
592    return;
593
594  net::CookieOptions options;
595  if (GetContentClient()->browser()->AllowSetCookie(
596          url, first_party_for_cookies, cookie, resource_context_,
597          render_process_id_, render_frame_id, &options)) {
598    net::CookieStore* cookie_store = GetCookieStoreForURL(url);
599    // Pass a null callback since we don't care about when the 'set' completes.
600    cookie_store->SetCookieWithOptionsAsync(
601        url, cookie, options, net::CookieStore::SetCookiesCallback());
602  }
603}
604
605void RenderMessageFilter::OnGetCookies(int render_frame_id,
606                                       const GURL& url,
607                                       const GURL& first_party_for_cookies,
608                                       IPC::Message* reply_msg) {
609  ChildProcessSecurityPolicyImpl* policy =
610      ChildProcessSecurityPolicyImpl::GetInstance();
611  if (!policy->CanAccessCookiesForOrigin(render_process_id_, url)) {
612    SendGetCookiesResponse(reply_msg, std::string());
613    return;
614  }
615
616  // If we crash here, figure out what URL the renderer was requesting.
617  // http://crbug.com/99242
618  char url_buf[128];
619  base::strlcpy(url_buf, url.spec().c_str(), arraysize(url_buf));
620  base::debug::Alias(url_buf);
621
622  net::CookieStore* cookie_store = GetCookieStoreForURL(url);
623  cookie_store->GetAllCookiesForURLAsync(
624      url, base::Bind(&RenderMessageFilter::CheckPolicyForCookies, this,
625                      render_frame_id, url, first_party_for_cookies,
626                      reply_msg));
627}
628
629void RenderMessageFilter::OnGetRawCookies(
630    const GURL& url,
631    const GURL& first_party_for_cookies,
632    IPC::Message* reply_msg) {
633  ChildProcessSecurityPolicyImpl* policy =
634      ChildProcessSecurityPolicyImpl::GetInstance();
635  // Only return raw cookies to trusted renderers or if this request is
636  // not targeted to an an external host like ChromeFrame.
637  // TODO(ananta) We need to support retreiving raw cookies from external
638  // hosts.
639  if (!policy->CanReadRawCookies(render_process_id_) ||
640      !policy->CanAccessCookiesForOrigin(render_process_id_, url)) {
641    SendGetRawCookiesResponse(reply_msg, net::CookieList());
642    return;
643  }
644
645  // We check policy here to avoid sending back cookies that would not normally
646  // be applied to outbound requests for the given URL.  Since this cookie info
647  // is visible in the developer tools, it is helpful to make it match reality.
648  net::CookieStore* cookie_store = GetCookieStoreForURL(url);
649  cookie_store->GetAllCookiesForURLAsync(
650      url, base::Bind(&RenderMessageFilter::SendGetRawCookiesResponse,
651                      this, reply_msg));
652}
653
654void RenderMessageFilter::OnDeleteCookie(const GURL& url,
655                                         const std::string& cookie_name) {
656  ChildProcessSecurityPolicyImpl* policy =
657      ChildProcessSecurityPolicyImpl::GetInstance();
658  if (!policy->CanAccessCookiesForOrigin(render_process_id_, url))
659    return;
660
661  net::CookieStore* cookie_store = GetCookieStoreForURL(url);
662  cookie_store->DeleteCookieAsync(url, cookie_name, base::Closure());
663}
664
665void RenderMessageFilter::OnCookiesEnabled(
666    int render_frame_id,
667    const GURL& url,
668    const GURL& first_party_for_cookies,
669    bool* cookies_enabled) {
670  // TODO(ananta): If this render view is associated with an automation channel,
671  // aka ChromeFrame then we need to retrieve cookie settings from the external
672  // host.
673  *cookies_enabled = GetContentClient()->browser()->AllowGetCookie(
674      url, first_party_for_cookies, net::CookieList(), resource_context_,
675      render_process_id_, render_frame_id);
676}
677
678#if defined(OS_MACOSX)
679void RenderMessageFilter::OnLoadFont(const FontDescriptor& font,
680                                     IPC::Message* reply_msg) {
681  FontLoader::Result* result = new FontLoader::Result;
682
683  BrowserThread::PostTaskAndReply(
684      BrowserThread::FILE, FROM_HERE,
685      base::Bind(&FontLoader::LoadFont, font, result),
686      base::Bind(&RenderMessageFilter::SendLoadFontReply, this, reply_msg,
687                 base::Owned(result)));
688}
689
690void RenderMessageFilter::SendLoadFontReply(IPC::Message* reply,
691                                            FontLoader::Result* result) {
692  base::SharedMemoryHandle handle;
693  if (result->font_data_size == 0 || result->font_id == 0) {
694    result->font_data_size = 0;
695    result->font_id = 0;
696    handle = base::SharedMemory::NULLHandle();
697  } else {
698    result->font_data.GiveToProcess(base::GetCurrentProcessHandle(), &handle);
699  }
700  ViewHostMsg_LoadFont::WriteReplyParams(
701      reply, result->font_data_size, handle, result->font_id);
702  Send(reply);
703}
704#endif  // OS_MACOSX
705
706#if defined(ENABLE_PLUGINS)
707void RenderMessageFilter::OnGetPlugins(
708    bool refresh,
709    IPC::Message* reply_msg) {
710  // Don't refresh if the specified threshold has not been passed.  Note that
711  // this check is performed before off-loading to the file thread.  The reason
712  // we do this is that some pages tend to request that the list of plugins be
713  // refreshed at an excessive rate.  This instigates disk scanning, as the list
714  // is accumulated by doing multiple reads from disk.  This effect is
715  // multiplied when we have several pages requesting this operation.
716  if (refresh) {
717    const base::TimeDelta threshold = base::TimeDelta::FromSeconds(
718        kPluginsRefreshThresholdInSeconds);
719    const base::TimeTicks now = base::TimeTicks::Now();
720    if (now - last_plugin_refresh_time_ >= threshold) {
721      // Only refresh if the threshold hasn't been exceeded yet.
722      PluginServiceImpl::GetInstance()->RefreshPlugins();
723      last_plugin_refresh_time_ = now;
724    }
725  }
726
727  PluginServiceImpl::GetInstance()->GetPlugins(
728      base::Bind(&RenderMessageFilter::GetPluginsCallback, this, reply_msg));
729}
730
731void RenderMessageFilter::GetPluginsCallback(
732    IPC::Message* reply_msg,
733    const std::vector<WebPluginInfo>& all_plugins) {
734  // Filter the plugin list.
735  PluginServiceFilter* filter = PluginServiceImpl::GetInstance()->GetFilter();
736  std::vector<WebPluginInfo> plugins;
737
738  int child_process_id = -1;
739  int routing_id = MSG_ROUTING_NONE;
740  for (size_t i = 0; i < all_plugins.size(); ++i) {
741    // Copy because the filter can mutate.
742    WebPluginInfo plugin(all_plugins[i]);
743    if (!filter || filter->IsPluginAvailable(child_process_id,
744                                             routing_id,
745                                             resource_context_,
746                                             GURL(),
747                                             GURL(),
748                                             &plugin)) {
749      plugins.push_back(plugin);
750    }
751  }
752
753  ViewHostMsg_GetPlugins::WriteReplyParams(reply_msg, plugins);
754  Send(reply_msg);
755}
756
757void RenderMessageFilter::OnGetPluginInfo(
758    int render_frame_id,
759    const GURL& url,
760    const GURL& page_url,
761    const std::string& mime_type,
762    bool* found,
763    WebPluginInfo* info,
764    std::string* actual_mime_type) {
765  bool allow_wildcard = true;
766  *found = plugin_service_->GetPluginInfo(
767      render_process_id_, render_frame_id, resource_context_,
768      url, page_url, mime_type, allow_wildcard,
769      NULL, info, actual_mime_type);
770}
771
772void RenderMessageFilter::OnOpenChannelToPlugin(int render_frame_id,
773                                                const GURL& url,
774                                                const GURL& policy_url,
775                                                const std::string& mime_type,
776                                                IPC::Message* reply_msg) {
777  OpenChannelToNpapiPluginCallback* client =
778      new OpenChannelToNpapiPluginCallback(this, resource_context_, reply_msg);
779  DCHECK(!ContainsKey(plugin_host_clients_, client));
780  plugin_host_clients_.insert(client);
781  plugin_service_->OpenChannelToNpapiPlugin(
782      render_process_id_, render_frame_id,
783      url, policy_url, mime_type, client);
784}
785
786void RenderMessageFilter::OnOpenChannelToPepperPlugin(
787    const base::FilePath& path,
788    IPC::Message* reply_msg) {
789  plugin_service_->OpenChannelToPpapiPlugin(
790      render_process_id_,
791      path,
792      profile_data_directory_,
793      new OpenChannelToPpapiPluginCallback(this, resource_context_, reply_msg));
794}
795
796void RenderMessageFilter::OnDidCreateOutOfProcessPepperInstance(
797    int plugin_child_id,
798    int32 pp_instance,
799    PepperRendererInstanceData instance_data,
800    bool is_external) {
801  // It's important that we supply the render process ID ourselves based on the
802  // channel the message arrived on. We use the
803  //   PP_Instance -> (process id, view id)
804  // mapping to decide how to handle messages received from the (untrusted)
805  // plugin, so an exploited renderer must not be able to insert fake mappings
806  // that may allow it access to other render processes.
807  DCHECK_EQ(0, instance_data.render_process_id);
808  instance_data.render_process_id = render_process_id_;
809  if (is_external) {
810    // We provide the BrowserPpapiHost to the embedder, so it's safe to cast.
811    BrowserPpapiHostImpl* host = static_cast<BrowserPpapiHostImpl*>(
812        GetContentClient()->browser()->GetExternalBrowserPpapiHost(
813            plugin_child_id));
814    if (host)
815      host->AddInstance(pp_instance, instance_data);
816  } else {
817    PpapiPluginProcessHost::DidCreateOutOfProcessInstance(
818        plugin_child_id, pp_instance, instance_data);
819  }
820}
821
822void RenderMessageFilter::OnDidDeleteOutOfProcessPepperInstance(
823    int plugin_child_id,
824    int32 pp_instance,
825    bool is_external) {
826  if (is_external) {
827    // We provide the BrowserPpapiHost to the embedder, so it's safe to cast.
828    BrowserPpapiHostImpl* host = static_cast<BrowserPpapiHostImpl*>(
829        GetContentClient()->browser()->GetExternalBrowserPpapiHost(
830            plugin_child_id));
831    if (host)
832      host->DeleteInstance(pp_instance);
833  } else {
834    PpapiPluginProcessHost::DidDeleteOutOfProcessInstance(
835        plugin_child_id, pp_instance);
836  }
837}
838
839void RenderMessageFilter::OnOpenChannelToPpapiBroker(
840    int routing_id,
841    const base::FilePath& path) {
842  plugin_service_->OpenChannelToPpapiBroker(
843      render_process_id_,
844      path,
845      new OpenChannelToPpapiBrokerCallback(this, routing_id));
846}
847#endif  // defined(ENABLE_PLUGINS)
848
849void RenderMessageFilter::OnGenerateRoutingID(int* route_id) {
850  *route_id = render_widget_helper_->GetNextRoutingID();
851}
852
853void RenderMessageFilter::OnGetCPUUsage(int* cpu_usage) {
854  base::TimeTicks now = base::TimeTicks::Now();
855  int64 since_last_sample_ms = (now - cpu_usage_sample_time_).InMilliseconds();
856  if (since_last_sample_ms > kCPUUsageSampleIntervalMs) {
857    cpu_usage_sample_time_ = now;
858    cpu_usage_ = static_cast<int>(process_metrics_->GetCPUUsage());
859  }
860  *cpu_usage = cpu_usage_;
861}
862
863void RenderMessageFilter::OnGetAudioHardwareConfig(
864    media::AudioParameters* input_params,
865    media::AudioParameters* output_params) {
866  DCHECK(input_params);
867  DCHECK(output_params);
868  *output_params = audio_manager_->GetDefaultOutputStreamParameters();
869
870  // TODO(henrika): add support for all available input devices.
871  *input_params = audio_manager_->GetInputStreamParameters(
872      media::AudioManagerBase::kDefaultDeviceId);
873}
874
875#if defined(OS_WIN)
876void RenderMessageFilter::OnGetMonitorColorProfile(std::vector<char>* profile) {
877  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
878  *profile = g_color_profile.Get().profile();
879}
880#endif
881
882void RenderMessageFilter::OnDownloadUrl(int render_view_id,
883                                        const GURL& url,
884                                        const Referrer& referrer,
885                                        const base::string16& suggested_name,
886                                        const bool use_prompt) {
887  scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo());
888  save_info->suggested_name = suggested_name;
889  save_info->prompt_for_save_location = use_prompt;
890
891  // There may be a special cookie store that we could use for this download,
892  // rather than the default one. Since this feature is generally only used for
893  // proper render views, and not downloads, we do not need to retrieve the
894  // special cookie store here, but just initialize the request to use the
895  // default cookie store.
896  // TODO(tburkard): retrieve the appropriate special cookie store, if this
897  // is ever to be used for downloads as well.
898  scoped_ptr<net::URLRequest> request(
899      resource_context_->GetRequestContext()->CreateRequest(
900          url, net::DEFAULT_PRIORITY, NULL, NULL));
901  RecordDownloadSource(INITIATED_BY_RENDERER);
902  resource_dispatcher_host_->BeginDownload(
903      request.Pass(),
904      referrer,
905      true,  // is_content_initiated
906      resource_context_,
907      render_process_id_,
908      render_view_id,
909      false,
910      save_info.Pass(),
911      content::DownloadItem::kInvalidId,
912      ResourceDispatcherHostImpl::DownloadStartedCallback());
913}
914
915void RenderMessageFilter::OnCheckNotificationPermission(
916    const GURL& source_origin, int* result) {
917#if defined(ENABLE_NOTIFICATIONS)
918  *result = GetContentClient()->browser()->
919      CheckDesktopNotificationPermission(source_origin, resource_context_,
920                                         render_process_id_);
921#else
922  *result = blink::WebNotificationPresenter::PermissionAllowed;
923#endif
924}
925
926void RenderMessageFilter::OnAllocateSharedMemory(
927    uint32 buffer_size,
928    base::SharedMemoryHandle* handle) {
929  ChildProcessHostImpl::AllocateSharedMemory(
930      buffer_size, PeerHandle(), handle);
931}
932
933void RenderMessageFilter::OnAllocateSharedBitmap(
934    uint32 buffer_size,
935    const cc::SharedBitmapId& id,
936    base::SharedMemoryHandle* handle) {
937  HostSharedBitmapManager::current()->AllocateSharedBitmapForChild(
938      PeerHandle(), buffer_size, id, handle);
939}
940
941void RenderMessageFilter::OnAllocatedSharedBitmap(
942    size_t buffer_size,
943    const base::SharedMemoryHandle& handle,
944    const cc::SharedBitmapId& id) {
945  HostSharedBitmapManager::current()->ChildAllocatedSharedBitmap(
946      buffer_size, handle, PeerHandle(), id);
947}
948
949void RenderMessageFilter::OnDeletedSharedBitmap(const cc::SharedBitmapId& id) {
950  HostSharedBitmapManager::current()->ChildDeletedSharedBitmap(id);
951}
952
953net::CookieStore* RenderMessageFilter::GetCookieStoreForURL(
954    const GURL& url) {
955  DCHECK_CURRENTLY_ON(BrowserThread::IO);
956
957  net::URLRequestContext* context =
958      GetContentClient()->browser()->OverrideRequestContextForURL(
959          url, resource_context_);
960
961  // If we should use a special URLRequestContext rather than the default one,
962  // return the cookie store of that special URLRequestContext.
963  if (context)
964    return context->cookie_store();
965
966  // Otherwise, if there is a special cookie store to be used for this process,
967  // return that cookie store.
968  net::CookieStore* cookie_store =
969      GetContentClient()->browser()->OverrideCookieStoreForRenderProcess(
970          render_process_id_);
971  if (cookie_store)
972    return cookie_store;
973
974  // Otherwise, return the cookie store of the default request context used
975  // for this renderer.
976  return request_context_->GetURLRequestContext()->cookie_store();
977}
978
979#if defined(OS_POSIX) && !defined(OS_ANDROID)
980void RenderMessageFilter::OnAllocTransportDIB(
981    uint32 size, bool cache_in_browser, TransportDIB::Handle* handle) {
982  render_widget_helper_->AllocTransportDIB(size, cache_in_browser, handle);
983}
984
985void RenderMessageFilter::OnFreeTransportDIB(
986    TransportDIB::Id dib_id) {
987  render_widget_helper_->FreeTransportDIB(dib_id);
988}
989#endif
990
991bool RenderMessageFilter::CheckPreparsedJsCachingEnabled() const {
992  static bool checked = false;
993  static bool result = false;
994  if (!checked) {
995    const CommandLine& command_line = *CommandLine::ForCurrentProcess();
996    result = command_line.HasSwitch(switches::kEnablePreparsedJsCaching);
997    checked = true;
998  }
999  return result;
1000}
1001
1002void RenderMessageFilter::OnCacheableMetadataAvailable(
1003    const GURL& url,
1004    double expected_response_time,
1005    const std::vector<char>& data) {
1006  if (!CheckPreparsedJsCachingEnabled())
1007    return;
1008
1009  net::HttpCache* cache = request_context_->GetURLRequestContext()->
1010      http_transaction_factory()->GetCache();
1011  DCHECK(cache);
1012
1013  // Use the same priority for the metadata write as for script
1014  // resources (see defaultPriorityForResourceType() in WebKit's
1015  // CachedResource.cpp). Note that WebURLRequest::PriorityMedium
1016  // corresponds to net::LOW (see ConvertWebKitPriorityToNetPriority()
1017  // in weburlloader_impl.cc).
1018  const net::RequestPriority kPriority = net::LOW;
1019  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(data.size()));
1020  memcpy(buf->data(), &data.front(), data.size());
1021  cache->WriteMetadata(url,
1022                       kPriority,
1023                       base::Time::FromDoubleT(expected_response_time),
1024                       buf.get(),
1025                       data.size());
1026}
1027
1028void RenderMessageFilter::OnKeygen(uint32 key_size_index,
1029                                   const std::string& challenge_string,
1030                                   const GURL& url,
1031                                   IPC::Message* reply_msg) {
1032  // Map displayed strings indicating level of keysecurity in the <keygen>
1033  // menu to the key size in bits. (See SSLKeyGeneratorChromium.cpp in WebCore.)
1034  int key_size_in_bits;
1035  switch (key_size_index) {
1036    case 0:
1037      key_size_in_bits = 2048;
1038      break;
1039    case 1:
1040      key_size_in_bits = 1024;
1041      break;
1042    default:
1043      DCHECK(false) << "Illegal key_size_index " << key_size_index;
1044      ViewHostMsg_Keygen::WriteReplyParams(reply_msg, std::string());
1045      Send(reply_msg);
1046      return;
1047  }
1048
1049  resource_context_->CreateKeygenHandler(
1050      key_size_in_bits,
1051      challenge_string,
1052      url,
1053      base::Bind(
1054          &RenderMessageFilter::PostKeygenToWorkerThread, this, reply_msg));
1055}
1056
1057void RenderMessageFilter::PostKeygenToWorkerThread(
1058    IPC::Message* reply_msg,
1059    scoped_ptr<net::KeygenHandler> keygen_handler) {
1060  VLOG(1) << "Dispatching keygen task to worker pool.";
1061  // Dispatch to worker pool, so we do not block the IO thread.
1062  if (!base::WorkerPool::PostTask(
1063           FROM_HERE,
1064           base::Bind(&RenderMessageFilter::OnKeygenOnWorkerThread,
1065                      this,
1066                      base::Passed(&keygen_handler),
1067                      reply_msg),
1068           true)) {
1069    NOTREACHED() << "Failed to dispatch keygen task to worker pool";
1070    ViewHostMsg_Keygen::WriteReplyParams(reply_msg, std::string());
1071    Send(reply_msg);
1072  }
1073}
1074
1075void RenderMessageFilter::OnKeygenOnWorkerThread(
1076    scoped_ptr<net::KeygenHandler> keygen_handler,
1077    IPC::Message* reply_msg) {
1078  DCHECK(reply_msg);
1079
1080  // Generate a signed public key and challenge, then send it back.
1081  ViewHostMsg_Keygen::WriteReplyParams(
1082      reply_msg,
1083      keygen_handler->GenKeyAndSignChallenge());
1084  Send(reply_msg);
1085}
1086
1087void RenderMessageFilter::OnMediaLogEvents(
1088    const std::vector<media::MediaLogEvent>& events) {
1089  if (media_internals_)
1090    media_internals_->OnMediaEvents(render_process_id_, events);
1091}
1092
1093void RenderMessageFilter::CheckPolicyForCookies(
1094    int render_frame_id,
1095    const GURL& url,
1096    const GURL& first_party_for_cookies,
1097    IPC::Message* reply_msg,
1098    const net::CookieList& cookie_list) {
1099  net::CookieStore* cookie_store = GetCookieStoreForURL(url);
1100  // Check the policy for get cookies, and pass cookie_list to the
1101  // TabSpecificContentSetting for logging purpose.
1102  if (GetContentClient()->browser()->AllowGetCookie(
1103          url, first_party_for_cookies, cookie_list, resource_context_,
1104          render_process_id_, render_frame_id)) {
1105    // Gets the cookies from cookie store if allowed.
1106    cookie_store->GetCookiesWithOptionsAsync(
1107        url, net::CookieOptions(),
1108        base::Bind(&RenderMessageFilter::SendGetCookiesResponse,
1109                   this, reply_msg));
1110  } else {
1111    SendGetCookiesResponse(reply_msg, std::string());
1112  }
1113}
1114
1115void RenderMessageFilter::SendGetCookiesResponse(IPC::Message* reply_msg,
1116                                                 const std::string& cookies) {
1117  ViewHostMsg_GetCookies::WriteReplyParams(reply_msg, cookies);
1118  Send(reply_msg);
1119}
1120
1121void RenderMessageFilter::SendGetRawCookiesResponse(
1122    IPC::Message* reply_msg,
1123    const net::CookieList& cookie_list) {
1124  std::vector<CookieData> cookies;
1125  for (size_t i = 0; i < cookie_list.size(); ++i)
1126    cookies.push_back(CookieData(cookie_list[i]));
1127  ViewHostMsg_GetRawCookies::WriteReplyParams(reply_msg, cookies);
1128  Send(reply_msg);
1129}
1130
1131void RenderMessageFilter::OnCompletedOpenChannelToNpapiPlugin(
1132    OpenChannelToNpapiPluginCallback* client) {
1133  DCHECK_CURRENTLY_ON(BrowserThread::IO);
1134  DCHECK(ContainsKey(plugin_host_clients_, client));
1135  plugin_host_clients_.erase(client);
1136}
1137
1138void RenderMessageFilter::OnAre3DAPIsBlocked(int render_view_id,
1139                                             const GURL& top_origin_url,
1140                                             ThreeDAPIType requester,
1141                                             bool* blocked) {
1142  *blocked = GpuDataManagerImpl::GetInstance()->Are3DAPIsBlocked(
1143      top_origin_url, render_process_id_, render_view_id, requester);
1144}
1145
1146void RenderMessageFilter::OnDidLose3DContext(
1147    const GURL& top_origin_url,
1148    ThreeDAPIType /* unused */,
1149    int arb_robustness_status_code) {
1150#if defined(OS_MACOSX)
1151    // TODO(kbr): this file indirectly includes npapi.h, which on Mac
1152    // OS pulls in the system OpenGL headers. For some
1153    // not-yet-investigated reason this breaks the build with the 10.6
1154    // SDK but not 10.7. For now work around this in a way compatible
1155    // with the Khronos headers.
1156#ifndef GL_GUILTY_CONTEXT_RESET_ARB
1157#define GL_GUILTY_CONTEXT_RESET_ARB 0x8253
1158#endif
1159#ifndef GL_INNOCENT_CONTEXT_RESET_ARB
1160#define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254
1161#endif
1162#ifndef GL_UNKNOWN_CONTEXT_RESET_ARB
1163#define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255
1164#endif
1165
1166#endif
1167  GpuDataManagerImpl::DomainGuilt guilt;
1168  switch (arb_robustness_status_code) {
1169    case GL_GUILTY_CONTEXT_RESET_ARB:
1170      guilt = GpuDataManagerImpl::DOMAIN_GUILT_KNOWN;
1171      break;
1172    case GL_UNKNOWN_CONTEXT_RESET_ARB:
1173      guilt = GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN;
1174      break;
1175    default:
1176      // Ignore lost contexts known to be innocent.
1177      return;
1178  }
1179
1180  GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs(
1181      top_origin_url, guilt);
1182}
1183
1184#if defined(OS_WIN)
1185void RenderMessageFilter::OnPreCacheFontCharacters(const LOGFONT& font,
1186                                                   const base::string16& str) {
1187  // TODO(scottmg): Move this to FontCacheDispatcher, http://crbug.com/356346.
1188  if (!ShouldUseDirectWrite())
1189    return;
1190  // First, comments from FontCacheDispatcher::OnPreCacheFont do apply here too.
1191  // Except that for True Type fonts,
1192  // GetTextMetrics will not load the font in memory.
1193  // The only way windows seem to load properly, it is to create a similar
1194  // device (like the one in which we print), then do an ExtTextOut,
1195  // as we do in the printing thread, which is sandboxed.
1196  HDC hdc = CreateEnhMetaFile(NULL, NULL, NULL, NULL);
1197  HFONT font_handle = CreateFontIndirect(&font);
1198  DCHECK(NULL != font_handle);
1199
1200  HGDIOBJ old_font = SelectObject(hdc, font_handle);
1201  DCHECK(NULL != old_font);
1202
1203  ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, 0, str.c_str(), str.length(), NULL);
1204
1205  SelectObject(hdc, old_font);
1206  DeleteObject(font_handle);
1207
1208  HENHMETAFILE metafile = CloseEnhMetaFile(hdc);
1209
1210  if (metafile) {
1211    DeleteEnhMetaFile(metafile);
1212  }
1213}
1214#endif
1215
1216#if defined(OS_ANDROID)
1217void RenderMessageFilter::OnWebAudioMediaCodec(
1218    base::SharedMemoryHandle encoded_data_handle,
1219    base::FileDescriptor pcm_output,
1220    uint32_t data_size) {
1221  // Let a WorkerPool handle this request since the WebAudio
1222  // MediaCodec bridge is slow and can block while sending the data to
1223  // the renderer.
1224  base::WorkerPool::PostTask(
1225      FROM_HERE,
1226      base::Bind(&media::WebAudioMediaCodecBridge::RunWebAudioMediaCodec,
1227                 encoded_data_handle, pcm_output, data_size),
1228      true);
1229}
1230#endif
1231
1232void RenderMessageFilter::OnAllocateGpuMemoryBuffer(uint32 width,
1233                                                    uint32 height,
1234                                                    uint32 internalformat,
1235                                                    uint32 usage,
1236                                                    IPC::Message* reply) {
1237  if (!GpuMemoryBufferImpl::IsFormatValid(internalformat) ||
1238      !GpuMemoryBufferImpl::IsUsageValid(usage)) {
1239    GpuMemoryBufferAllocated(reply, gfx::GpuMemoryBufferHandle());
1240    return;
1241  }
1242  base::CheckedNumeric<int> size = width;
1243  size *= height;
1244  if (!size.IsValid()) {
1245    GpuMemoryBufferAllocated(reply, gfx::GpuMemoryBufferHandle());
1246    return;
1247  }
1248
1249#if defined(OS_MACOSX)
1250  // TODO(reveman): This should be moved to
1251  // GpuMemoryBufferImpl::AllocateForChildProcess and
1252  // GpuMemoryBufferImplIOSurface. crbug.com/325045, crbug.com/323304
1253  if (GpuMemoryBufferImplIOSurface::IsConfigurationSupported(internalformat,
1254                                                             usage)) {
1255    IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
1256    if (io_surface_support) {
1257      base::ScopedCFTypeRef<CFMutableDictionaryRef> properties;
1258      properties.reset(
1259          CFDictionaryCreateMutable(kCFAllocatorDefault,
1260                                    0,
1261                                    &kCFTypeDictionaryKeyCallBacks,
1262                                    &kCFTypeDictionaryValueCallBacks));
1263      AddIntegerValue(properties,
1264                      io_surface_support->GetKIOSurfaceWidth(),
1265                      width);
1266      AddIntegerValue(properties,
1267                      io_surface_support->GetKIOSurfaceHeight(),
1268                      height);
1269      AddIntegerValue(properties,
1270                      io_surface_support->GetKIOSurfaceBytesPerElement(),
1271                      GpuMemoryBufferImpl::BytesPerPixel(internalformat));
1272      AddIntegerValue(properties,
1273                      io_surface_support->GetKIOSurfacePixelFormat(),
1274                      GpuMemoryBufferImplIOSurface::PixelFormat(
1275                          internalformat));
1276      // TODO(reveman): Remove this when using a mach_port_t to transfer
1277      // IOSurface to renderer process. crbug.com/323304
1278      AddBooleanValue(properties,
1279                      io_surface_support->GetKIOSurfaceIsGlobal(),
1280                      true);
1281
1282      base::ScopedCFTypeRef<CFTypeRef> io_surface(
1283          io_surface_support->IOSurfaceCreate(properties));
1284      if (io_surface) {
1285        gfx::GpuMemoryBufferHandle handle;
1286        handle.type = gfx::IO_SURFACE_BUFFER;
1287        handle.io_surface_id = io_surface_support->IOSurfaceGetID(io_surface);
1288
1289        // TODO(reveman): This makes the assumption that the renderer will
1290        // grab a reference to the surface before sending another message.
1291        // crbug.com/325045
1292        last_io_surface_ = io_surface;
1293        GpuMemoryBufferAllocated(reply, handle);
1294        return;
1295      }
1296    }
1297  }
1298#endif
1299
1300#if defined(OS_ANDROID)
1301  // TODO(reveman): This should be moved to
1302  // GpuMemoryBufferImpl::AllocateForChildProcess and
1303  // GpuMemoryBufferImplSurfaceTexture when adding support for out-of-process
1304  // GPU service. crbug.com/368716
1305  if (GpuMemoryBufferImplSurfaceTexture::IsConfigurationSupported(
1306          internalformat, usage)) {
1307    // Each surface texture is associated with a render process id. This allows
1308    // the GPU service and Java Binder IPC to verify that a renderer is not
1309    // trying to use a surface texture it doesn't own.
1310    int surface_texture_id =
1311        CompositorImpl::CreateSurfaceTexture(render_process_id_);
1312    if (surface_texture_id != -1) {
1313      gfx::GpuMemoryBufferHandle handle;
1314      handle.type = gfx::SURFACE_TEXTURE_BUFFER;
1315      handle.surface_texture_id =
1316          gfx::SurfaceTextureId(surface_texture_id, render_process_id_);
1317      GpuMemoryBufferAllocated(reply, handle);
1318      return;
1319    }
1320  }
1321#endif
1322
1323  GpuMemoryBufferImpl::AllocateForChildProcess(
1324      gfx::Size(width, height),
1325      internalformat,
1326      usage,
1327      PeerHandle(),
1328      base::Bind(&RenderMessageFilter::GpuMemoryBufferAllocated, this, reply));
1329}
1330
1331void RenderMessageFilter::GpuMemoryBufferAllocated(
1332    IPC::Message* reply,
1333    const gfx::GpuMemoryBufferHandle& handle) {
1334  ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer::WriteReplyParams(reply,
1335                                                                    handle);
1336  Send(reply);
1337}
1338
1339}  // namespace content
1340