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