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