render_process_host_impl.cc revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
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// Represents the browser side of the browser <--> renderer communication
6// channel. There will be one RenderProcessHost per renderer process.
7
8#include "content/browser/renderer_host/render_process_host_impl.h"
9
10#include <algorithm>
11#include <limits>
12#include <vector>
13
14#if defined(OS_POSIX)
15#include <utility>  // for pair<>
16#endif
17
18#include "base/base_switches.h"
19#include "base/bind.h"
20#include "base/bind_helpers.h"
21#include "base/callback.h"
22#include "base/command_line.h"
23#include "base/debug/trace_event.h"
24#include "base/lazy_instance.h"
25#include "base/logging.h"
26#include "base/metrics/field_trial.h"
27#include "base/metrics/histogram.h"
28#include "base/path_service.h"
29#include "base/platform_file.h"
30#include "base/process_util.h"
31#include "base/rand_util.h"
32#include "base/stl_util.h"
33#include "base/strings/string_util.h"
34#include "base/supports_user_data.h"
35#include "base/sys_info.h"
36#include "base/threading/thread.h"
37#include "base/threading/thread_restrictions.h"
38#include "base/tracked_objects.h"
39#include "cc/base/switches.h"
40#include "content/browser/appcache/appcache_dispatcher_host.h"
41#include "content/browser/appcache/chrome_appcache_service.h"
42#include "content/browser/browser_main.h"
43#include "content/browser/browser_main_loop.h"
44#include "content/browser/browser_plugin/browser_plugin_geolocation_permission_context.h"
45#include "content/browser/browser_plugin/browser_plugin_message_filter.h"
46#include "content/browser/child_process_security_policy_impl.h"
47#include "content/browser/device_orientation/orientation_message_filter.h"
48#include "content/browser/dom_storage/dom_storage_context_impl.h"
49#include "content/browser/dom_storage/dom_storage_message_filter.h"
50#include "content/browser/download/mhtml_generation_manager.h"
51#include "content/browser/fileapi/chrome_blob_storage_context.h"
52#include "content/browser/fileapi/fileapi_message_filter.h"
53#include "content/browser/geolocation/geolocation_dispatcher_host.h"
54#include "content/browser/gpu/gpu_data_manager_impl.h"
55#include "content/browser/gpu/gpu_process_host.h"
56#include "content/browser/gpu/shader_disk_cache.h"
57#include "content/browser/histogram_message_filter.h"
58#include "content/browser/hyphenator/hyphenator_message_filter.h"
59#include "content/browser/in_process_webkit/indexed_db_dispatcher_host.h"
60#include "content/browser/indexed_db/indexed_db_context_impl.h"
61#include "content/browser/loader/resource_message_filter.h"
62#include "content/browser/loader/resource_scheduler_filter.h"
63#include "content/browser/media/media_internals.h"
64#include "content/browser/mime_registry_message_filter.h"
65#include "content/browser/plugin_service_impl.h"
66#include "content/browser/profiler_message_filter.h"
67#include "content/browser/renderer_host/clipboard_message_filter.h"
68#include "content/browser/renderer_host/database_message_filter.h"
69#include "content/browser/renderer_host/file_utilities_message_filter.h"
70#include "content/browser/renderer_host/gamepad_browser_message_filter.h"
71#include "content/browser/renderer_host/gpu_message_filter.h"
72#include "content/browser/renderer_host/media/audio_input_renderer_host.h"
73#include "content/browser/renderer_host/media/audio_mirroring_manager.h"
74#include "content/browser/renderer_host/media/audio_renderer_host.h"
75#include "content/browser/renderer_host/media/media_stream_dispatcher_host.h"
76#include "content/browser/renderer_host/media/peer_connection_tracker_host.h"
77#include "content/browser/renderer_host/media/video_capture_host.h"
78#include "content/browser/renderer_host/memory_benchmark_message_filter.h"
79#include "content/browser/renderer_host/p2p/socket_dispatcher_host.h"
80#include "content/browser/renderer_host/pepper/pepper_message_filter.h"
81#include "content/browser/renderer_host/pepper/pepper_renderer_connection.h"
82#include "content/browser/renderer_host/quota_dispatcher_host.h"
83#include "content/browser/renderer_host/render_message_filter.h"
84#include "content/browser/renderer_host/render_view_host_delegate.h"
85#include "content/browser/renderer_host/render_view_host_impl.h"
86#include "content/browser/renderer_host/render_widget_helper.h"
87#include "content/browser/renderer_host/socket_stream_dispatcher_host.h"
88#include "content/browser/renderer_host/text_input_client_message_filter.h"
89#include "content/browser/resolve_proxy_msg_helper.h"
90#include "content/browser/speech/input_tag_speech_dispatcher_host.h"
91#include "content/browser/speech/speech_recognition_dispatcher_host.h"
92#include "content/browser/storage_partition_impl.h"
93#include "content/browser/tracing/trace_message_filter.h"
94#include "content/browser/webui/web_ui_controller_factory_registry.h"
95#include "content/browser/worker_host/worker_message_filter.h"
96#include "content/browser/worker_host/worker_storage_partition.h"
97#include "content/common/child_process_host_impl.h"
98#include "content/common/child_process_messages.h"
99#include "content/common/gpu/gpu_messages.h"
100#include "content/common/resource_messages.h"
101#include "content/common/view_messages.h"
102#include "content/port/browser/render_widget_host_view_frame_subscriber.h"
103#include "content/public/browser/browser_context.h"
104#include "content/public/browser/content_browser_client.h"
105#include "content/public/browser/notification_service.h"
106#include "content/public/browser/notification_types.h"
107#include "content/public/browser/render_process_host_factory.h"
108#include "content/public/browser/resource_context.h"
109#include "content/public/browser/user_metrics.h"
110#include "content/public/common/content_constants.h"
111#include "content/public/common/content_switches.h"
112#include "content/public/common/process_type.h"
113#include "content/public/common/result_codes.h"
114#include "content/public/common/url_constants.h"
115#include "content/renderer/render_process_impl.h"
116#include "content/renderer/render_thread_impl.h"
117#include "gpu/command_buffer/service/gpu_switches.h"
118#include "ipc/ipc_channel.h"
119#include "ipc/ipc_logging.h"
120#include "ipc/ipc_platform_file.h"
121#include "ipc/ipc_switches.h"
122#include "media/base/media_switches.h"
123#include "net/url_request/url_request_context_getter.h"
124#include "ppapi/shared_impl/ppapi_switches.h"
125#include "ui/base/ui_base_switches.h"
126#include "ui/gl/gl_switches.h"
127#include "webkit/browser/fileapi/sandbox_mount_point_provider.h"
128#include "webkit/glue/resource_type.h"
129#include "webkit/plugins/plugin_switches.h"
130
131#if defined(OS_WIN)
132#include "base/win/scoped_com_initializer.h"
133#include "content/common/font_cache_dispatcher_win.h"
134#include "content/common/sandbox_win.h"
135#include "content/public/common/sandboxed_process_launcher_delegate.h"
136#endif
137
138#include "third_party/skia/include/core/SkBitmap.h"
139
140extern bool g_exited_main_message_loop;
141
142static const char* kSiteProcessMapKeyName = "content_site_process_map";
143
144namespace content {
145namespace {
146
147base::MessageLoop* g_in_process_thread;
148
149void CacheShaderInfo(int32 id, base::FilePath path) {
150  ShaderCacheFactory::GetInstance()->SetCacheInfo(id, path);
151}
152
153void RemoveShaderInfo(int32 id) {
154  ShaderCacheFactory::GetInstance()->RemoveCacheInfo(id);
155}
156
157}  // namespace
158
159// This class creates the IO thread for the renderer when running in
160// single-process mode.  It's not used in multi-process mode.
161class RendererMainThread : public base::Thread {
162 public:
163  explicit RendererMainThread(const std::string& channel_id)
164      : Thread("Chrome_InProcRendererThread"),
165        channel_id_(channel_id) {
166  }
167
168  virtual ~RendererMainThread() {
169    Stop();
170  }
171
172 protected:
173  virtual void Init() OVERRIDE {
174    render_process_.reset(new RenderProcessImpl());
175    new RenderThreadImpl(channel_id_);
176    g_in_process_thread = message_loop();
177  }
178
179  virtual void CleanUp() OVERRIDE {
180    g_in_process_thread = NULL;
181    render_process_.reset();
182
183    // It's a little lame to manually set this flag.  But the single process
184    // RendererThread will receive the WM_QUIT.  We don't need to assert on
185    // this thread, so just force the flag manually.
186    // If we want to avoid this, we could create the InProcRendererThread
187    // directly with _beginthreadex() rather than using the Thread class.
188    // We used to set this flag in the Init function above. However there
189    // other threads like WebThread which are created by this thread
190    // which resets this flag. Please see Thread::StartWithOptions. Setting
191    // this flag to true in Cleanup works around these problems.
192    SetThreadWasQuitProperly(true);
193  }
194
195 private:
196  std::string channel_id_;
197  scoped_ptr<RenderProcess> render_process_;
198
199  DISALLOW_COPY_AND_ASSIGN(RendererMainThread);
200};
201
202namespace {
203
204// Helper class that we pass to ResourceMessageFilter so that it can find the
205// right net::URLRequestContext for a request.
206class RendererURLRequestContextSelector
207    : public ResourceMessageFilter::URLRequestContextSelector {
208 public:
209  RendererURLRequestContextSelector(BrowserContext* browser_context,
210                                    int render_child_id)
211      : request_context_(browser_context->GetRequestContextForRenderProcess(
212                             render_child_id)),
213        media_request_context_(
214            browser_context->GetMediaRequestContextForRenderProcess(
215                render_child_id)) {
216  }
217
218  virtual net::URLRequestContext* GetRequestContext(
219      ResourceType::Type resource_type) OVERRIDE {
220    net::URLRequestContextGetter* request_context = request_context_.get();
221    // If the request has resource type of ResourceType::MEDIA, we use a request
222    // context specific to media for handling it because these resources have
223    // specific needs for caching.
224    if (resource_type == ResourceType::MEDIA)
225      request_context = media_request_context_.get();
226    return request_context->GetURLRequestContext();
227  }
228
229 private:
230  virtual ~RendererURLRequestContextSelector() {}
231
232  scoped_refptr<net::URLRequestContextGetter> request_context_;
233  scoped_refptr<net::URLRequestContextGetter> media_request_context_;
234};
235
236// the global list of all renderer processes
237base::LazyInstance<IDMap<RenderProcessHost> >::Leaky
238    g_all_hosts = LAZY_INSTANCE_INITIALIZER;
239
240base::LazyInstance<scoped_refptr<BrowserPluginGeolocationPermissionContext> >
241    g_browser_plugin_geolocation_context = LAZY_INSTANCE_INITIALIZER;
242
243// Map of site to process, to ensure we only have one RenderProcessHost per
244// site in process-per-site mode.  Each map is specific to a BrowserContext.
245class SiteProcessMap : public base::SupportsUserData::Data {
246 public:
247  typedef base::hash_map<std::string, RenderProcessHost*> SiteToProcessMap;
248  SiteProcessMap() {}
249
250  void RegisterProcess(const std::string& site, RenderProcessHost* process) {
251    map_[site] = process;
252  }
253
254  RenderProcessHost* FindProcess(const std::string& site) {
255    SiteToProcessMap::iterator i = map_.find(site);
256    if (i != map_.end())
257      return i->second;
258    return NULL;
259  }
260
261  void RemoveProcess(RenderProcessHost* host) {
262    // Find all instances of this process in the map, then separately remove
263    // them.
264    std::set<std::string> sites;
265    for (SiteToProcessMap::const_iterator i = map_.begin();
266         i != map_.end();
267         i++) {
268      if (i->second == host)
269        sites.insert(i->first);
270    }
271    for (std::set<std::string>::iterator i = sites.begin();
272         i != sites.end();
273         i++) {
274      SiteToProcessMap::iterator iter = map_.find(*i);
275      if (iter != map_.end()) {
276        DCHECK_EQ(iter->second, host);
277        map_.erase(iter);
278      }
279    }
280  }
281
282 private:
283  SiteToProcessMap map_;
284};
285
286// Find the SiteProcessMap specific to the given context.
287SiteProcessMap* GetSiteProcessMapForBrowserContext(BrowserContext* context) {
288  DCHECK(context);
289  SiteProcessMap* map = static_cast<SiteProcessMap*>(
290      context->GetUserData(kSiteProcessMapKeyName));
291  if (!map) {
292    map = new SiteProcessMap();
293    context->SetUserData(kSiteProcessMapKeyName, map);
294  }
295  return map;
296}
297
298#if defined(OS_WIN)
299// NOTE: changes to this class need to be reviewed by the security team.
300class RendererSandboxedProcessLauncherDelegate
301    : public content::SandboxedProcessLauncherDelegate {
302 public:
303  RendererSandboxedProcessLauncherDelegate() {}
304  virtual ~RendererSandboxedProcessLauncherDelegate() {}
305
306  virtual void ShouldSandbox(bool* in_sandbox) OVERRIDE {
307#if !defined (GOOGLE_CHROME_BUILD)
308    if (CommandLine::ForCurrentProcess()->HasSwitch(
309        switches::kInProcessPlugins)) {
310      *in_sandbox = false;
311    }
312#endif
313  }
314
315  virtual void PreSpawnTarget(sandbox::TargetPolicy* policy,
316                              bool* success) {
317    AddBaseHandleClosePolicy(policy);
318    GetContentClient()->browser()->PreSpawnRenderer(policy, success);
319  }
320};
321#endif  // OS_WIN
322
323}  // namespace
324
325// Stores the maximum number of renderer processes the content module can
326// create.
327static size_t g_max_renderer_count_override = 0;
328
329// static
330size_t RenderProcessHost::GetMaxRendererProcessCount() {
331  if (g_max_renderer_count_override)
332    return g_max_renderer_count_override;
333
334  // Defines the maximum number of renderer processes according to the
335  // amount of installed memory as reported by the OS. The calculation
336  // assumes that you want the renderers to use half of the installed
337  // RAM and assuming that each WebContents uses ~40MB.
338  // If you modify this assumption, you need to adjust the
339  // ThirtyFourTabs test to match the expected number of processes.
340  //
341  // With the given amounts of installed memory below on a 32-bit CPU,
342  // the maximum renderer count will roughly be as follows:
343  //
344  //   128 MB -> 3
345  //   512 MB -> 6
346  //  1024 MB -> 12
347  //  4096 MB -> 51
348  // 16384 MB -> 82 (kMaxRendererProcessCount)
349
350  static size_t max_count = 0;
351  if (!max_count) {
352    const size_t kEstimatedWebContentsMemoryUsage =
353#if defined(ARCH_CPU_64_BITS)
354        60;  // In MB
355#else
356        40;  // In MB
357#endif
358    max_count = base::SysInfo::AmountOfPhysicalMemoryMB() / 2;
359    max_count /= kEstimatedWebContentsMemoryUsage;
360
361    const size_t kMinRendererProcessCount = 3;
362    max_count = std::max(max_count, kMinRendererProcessCount);
363    max_count = std::min(max_count, kMaxRendererProcessCount);
364  }
365  return max_count;
366}
367
368// static
369bool g_run_renderer_in_process_ = false;
370
371// static
372void RenderProcessHost::SetMaxRendererProcessCount(size_t count) {
373  g_max_renderer_count_override = count;
374}
375
376RenderProcessHostImpl::RenderProcessHostImpl(
377    BrowserContext* browser_context,
378    StoragePartitionImpl* storage_partition_impl,
379    bool supports_browser_plugin,
380    bool is_guest)
381        : fast_shutdown_started_(false),
382          deleting_soon_(false),
383          pending_views_(0),
384          visible_widgets_(0),
385          backgrounded_(true),
386          cached_dibs_cleaner_(
387              FROM_HERE, base::TimeDelta::FromSeconds(5),
388              this, &RenderProcessHostImpl::ClearTransportDIBCache),
389          is_initialized_(false),
390          id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()),
391          browser_context_(browser_context),
392          storage_partition_impl_(storage_partition_impl),
393          sudden_termination_allowed_(true),
394          ignore_input_events_(false),
395          supports_browser_plugin_(supports_browser_plugin),
396          is_guest_(is_guest),
397          gpu_observer_registered_(false) {
398  widget_helper_ = new RenderWidgetHelper();
399
400  ChildProcessSecurityPolicyImpl::GetInstance()->Add(GetID());
401
402  CHECK(!g_exited_main_message_loop);
403  RegisterHost(GetID(), this);
404  g_all_hosts.Get().set_check_on_null_data(true);
405  // Initialize |child_process_activity_time_| to a reasonable value.
406  mark_child_process_activity_time();
407
408  if (!GetBrowserContext()->IsOffTheRecord() &&
409      !CommandLine::ForCurrentProcess()->HasSwitch(
410          switches::kDisableGpuShaderDiskCache)) {
411    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
412                            base::Bind(&CacheShaderInfo, GetID(),
413                                       storage_partition_impl_->GetPath()));
414  }
415
416  // Note: When we create the RenderProcessHostImpl, it's technically
417  //       backgrounded, because it has no visible listeners.  But the process
418  //       doesn't actually exist yet, so we'll Background it later, after
419  //       creation.
420}
421
422RenderProcessHostImpl::~RenderProcessHostImpl() {
423  DCHECK(!run_renderer_in_process());
424  ChildProcessSecurityPolicyImpl::GetInstance()->Remove(GetID());
425
426  if (gpu_observer_registered_) {
427    GpuDataManagerImpl::GetInstance()->RemoveObserver(this);
428    gpu_observer_registered_ = false;
429  }
430
431  // We may have some unsent messages at this point, but that's OK.
432  channel_.reset();
433  while (!queued_messages_.empty()) {
434    delete queued_messages_.front();
435    queued_messages_.pop();
436  }
437
438  ClearTransportDIBCache();
439  UnregisterHost(GetID());
440
441  if (!CommandLine::ForCurrentProcess()->HasSwitch(
442      switches::kDisableGpuShaderDiskCache)) {
443    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
444                            base::Bind(&RemoveShaderInfo, GetID()));
445  }
446}
447
448void RenderProcessHostImpl::EnableSendQueue() {
449  is_initialized_ = false;
450}
451
452bool RenderProcessHostImpl::Init() {
453  // calling Init() more than once does nothing, this makes it more convenient
454  // for the view host which may not be sure in some cases
455  if (channel_)
456    return true;
457
458  CommandLine::StringType renderer_prefix;
459#if defined(OS_POSIX)
460  // A command prefix is something prepended to the command line of the spawned
461  // process. It is supported only on POSIX systems.
462  const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
463  renderer_prefix =
464      browser_command_line.GetSwitchValueNative(switches::kRendererCmdPrefix);
465#endif  // defined(OS_POSIX)
466
467#if defined(OS_LINUX)
468  int flags = renderer_prefix.empty() ? ChildProcessHost::CHILD_ALLOW_SELF :
469                                        ChildProcessHost::CHILD_NORMAL;
470#else
471  int flags = ChildProcessHost::CHILD_NORMAL;
472#endif
473
474  // Find the renderer before creating the channel so if this fails early we
475  // return without creating the channel.
476  base::FilePath renderer_path = ChildProcessHost::GetChildPath(flags);
477  if (renderer_path.empty())
478    return false;
479
480  // Setup the IPC channel.
481  const std::string channel_id =
482      IPC::Channel::GenerateVerifiedChannelID(std::string());
483  channel_.reset(
484          new IPC::ChannelProxy(channel_id,
485                                IPC::Channel::MODE_SERVER,
486                                this,
487                                BrowserThread::GetMessageLoopProxyForThread(
488                                    BrowserThread::IO).get()));
489
490  // Call the embedder first so that their IPC filters have priority.
491  GetContentClient()->browser()->RenderProcessHostCreated(this);
492
493  CreateMessageFilters();
494
495  // Single-process mode not supported in split-dll mode.
496#if !defined(CHROME_SPLIT_DLL)
497  if (run_renderer_in_process()) {
498    // Crank up a thread and run the initialization there.  With the way that
499    // messages flow between the browser and renderer, this thread is required
500    // to prevent a deadlock in single-process mode.  Since the primordial
501    // thread in the renderer process runs the WebKit code and can sometimes
502    // make blocking calls to the UI thread (i.e. this thread), they need to run
503    // on separate threads.
504    in_process_renderer_.reset(new RendererMainThread(channel_id));
505
506    base::Thread::Options options;
507#if defined(OS_WIN) && !defined(OS_MACOSX)
508    // In-process plugins require this to be a UI message loop.
509    options.message_loop_type = base::MessageLoop::TYPE_UI;
510#else
511    // We can't have multiple UI loops on Linux and Android, so we don't support
512    // in-process plugins.
513    options.message_loop_type = base::MessageLoop::TYPE_DEFAULT;
514#endif
515    in_process_renderer_->StartWithOptions(options);
516
517    OnProcessLaunched();  // Fake a callback that the process is ready.
518  } else
519#endif  // !CHROME_SPLIT_DLL
520  {
521    // Build command line for renderer.  We call AppendRendererCommandLine()
522    // first so the process type argument will appear first.
523    CommandLine* cmd_line = new CommandLine(renderer_path);
524    if (!renderer_prefix.empty())
525      cmd_line->PrependWrapper(renderer_prefix);
526    AppendRendererCommandLine(cmd_line);
527    cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
528
529    // Spawn the child process asynchronously to avoid blocking the UI thread.
530    // As long as there's no renderer prefix, we can use the zygote process
531    // at this stage.
532    child_process_launcher_.reset(new ChildProcessLauncher(
533#if defined(OS_WIN)
534        new RendererSandboxedProcessLauncherDelegate,
535#elif defined(OS_POSIX)
536        renderer_prefix.empty(),
537        base::EnvironmentVector(),
538        channel_->TakeClientFileDescriptor(),
539#endif
540        cmd_line,
541        GetID(),
542        this));
543
544    fast_shutdown_started_ = false;
545  }
546
547  if (!gpu_observer_registered_) {
548    gpu_observer_registered_ = true;
549    GpuDataManagerImpl::GetInstance()->AddObserver(this);
550  }
551
552  is_initialized_ = true;
553  return true;
554}
555
556void RenderProcessHostImpl::CreateMessageFilters() {
557  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
558  channel_->AddFilter(new ResourceSchedulerFilter(GetID()));
559  MediaInternals* media_internals = MediaInternals::GetInstance();;
560  // Add BrowserPluginMessageFilter to ensure it gets the first stab at messages
561  // from guests.
562  if (supports_browser_plugin_) {
563    scoped_refptr<BrowserPluginMessageFilter> bp_message_filter(
564        new BrowserPluginMessageFilter(GetID(), IsGuest()));
565    channel_->AddFilter(bp_message_filter.get());
566  }
567
568  scoped_refptr<RenderMessageFilter> render_message_filter(
569      new RenderMessageFilter(
570          GetID(),
571#if defined(ENABLE_PLUGINS)
572          PluginServiceImpl::GetInstance(),
573#else
574          NULL,
575#endif
576          GetBrowserContext(),
577          GetBrowserContext()->GetRequestContextForRenderProcess(GetID()),
578          widget_helper_.get(),
579          media_internals,
580          storage_partition_impl_->GetDOMStorageContext()));
581  channel_->AddFilter(render_message_filter.get());
582  BrowserContext* browser_context = GetBrowserContext();
583  ResourceContext* resource_context = browser_context->GetResourceContext();
584
585  ResourceMessageFilter* resource_message_filter = new ResourceMessageFilter(
586      GetID(), PROCESS_TYPE_RENDERER, resource_context,
587      storage_partition_impl_->GetAppCacheService(),
588      ChromeBlobStorageContext::GetFor(browser_context),
589      storage_partition_impl_->GetFileSystemContext(),
590      new RendererURLRequestContextSelector(browser_context, GetID()));
591
592  channel_->AddFilter(resource_message_filter);
593  media::AudioManager* audio_manager = BrowserMainLoop::GetAudioManager();
594  MediaStreamManager* media_stream_manager =
595      BrowserMainLoop::GetMediaStreamManager();
596  channel_->AddFilter(new AudioInputRendererHost(audio_manager,
597                                                 media_stream_manager));
598  channel_->AddFilter(new AudioRendererHost(
599      GetID(), audio_manager, BrowserMainLoop::GetAudioMirroringManager(),
600      media_internals, media_stream_manager));
601  channel_->AddFilter(new VideoCaptureHost());
602  channel_->AddFilter(new AppCacheDispatcherHost(
603      storage_partition_impl_->GetAppCacheService(),
604      GetID()));
605  channel_->AddFilter(new ClipboardMessageFilter);
606  channel_->AddFilter(
607      new DOMStorageMessageFilter(
608          GetID(),
609          storage_partition_impl_->GetDOMStorageContext()));
610  channel_->AddFilter(
611      new IndexedDBDispatcherHost(
612          GetID(),
613          storage_partition_impl_->GetIndexedDBContext()));
614  if (IsGuest()) {
615    if (!g_browser_plugin_geolocation_context.Get().get()) {
616      g_browser_plugin_geolocation_context.Get() =
617          new BrowserPluginGeolocationPermissionContext();
618    }
619    channel_->AddFilter(GeolocationDispatcherHost::New(
620        GetID(), g_browser_plugin_geolocation_context.Get().get()));
621  } else {
622    channel_->AddFilter(GeolocationDispatcherHost::New(
623        GetID(), browser_context->GetGeolocationPermissionContext()));
624  }
625  gpu_message_filter_ = new GpuMessageFilter(GetID(), widget_helper_.get());
626  channel_->AddFilter(gpu_message_filter_);
627#if defined(ENABLE_WEBRTC)
628  peer_connection_tracker_host_ = new PeerConnectionTrackerHost(GetID());
629  channel_->AddFilter(peer_connection_tracker_host_.get());
630  channel_->AddFilter(new MediaStreamDispatcherHost(GetID()));
631#endif
632#if defined(ENABLE_PLUGINS)
633  // TODO(raymes): PepperMessageFilter should be removed from here.
634  channel_->AddFilter(new PepperMessageFilter(GetID(), browser_context));
635  channel_->AddFilter(new PepperRendererConnection);
636#endif
637#if defined(ENABLE_INPUT_SPEECH)
638  channel_->AddFilter(new InputTagSpeechDispatcherHost(
639      IsGuest(), GetID(), storage_partition_impl_->GetURLRequestContext(),
640      browser_context->GetSpeechRecognitionPreferences()));
641#endif
642  channel_->AddFilter(new SpeechRecognitionDispatcherHost(
643      GetID(), storage_partition_impl_->GetURLRequestContext(),
644      browser_context->GetSpeechRecognitionPreferences()));
645  channel_->AddFilter(new FileAPIMessageFilter(
646      GetID(),
647      storage_partition_impl_->GetURLRequestContext(),
648      storage_partition_impl_->GetFileSystemContext(),
649      ChromeBlobStorageContext::GetFor(browser_context)));
650  channel_->AddFilter(new OrientationMessageFilter());
651  channel_->AddFilter(new FileUtilitiesMessageFilter(GetID()));
652  channel_->AddFilter(new MimeRegistryMessageFilter());
653  channel_->AddFilter(new DatabaseMessageFilter(
654      storage_partition_impl_->GetDatabaseTracker()));
655#if defined(OS_MACOSX)
656  channel_->AddFilter(new TextInputClientMessageFilter(GetID()));
657#elif defined(OS_WIN)
658  channel_->AddFilter(new FontCacheDispatcher());
659#endif
660
661  SocketStreamDispatcherHost* socket_stream_dispatcher_host =
662      new SocketStreamDispatcherHost(GetID(),
663          new RendererURLRequestContextSelector(browser_context, GetID()),
664          resource_context);
665  channel_->AddFilter(socket_stream_dispatcher_host);
666
667  channel_->AddFilter(
668      new WorkerMessageFilter(
669          GetID(),
670          resource_context,
671          WorkerStoragePartition(
672              storage_partition_impl_->GetURLRequestContext(),
673              storage_partition_impl_->GetMediaURLRequestContext(),
674              storage_partition_impl_->GetAppCacheService(),
675              storage_partition_impl_->GetQuotaManager(),
676              storage_partition_impl_->GetFileSystemContext(),
677              storage_partition_impl_->GetDatabaseTracker(),
678              storage_partition_impl_->GetIndexedDBContext()),
679          base::Bind(&RenderWidgetHelper::GetNextRoutingID,
680                     base::Unretained(widget_helper_.get()))));
681
682#if defined(ENABLE_WEBRTC)
683  channel_->AddFilter(new P2PSocketDispatcherHost(resource_context));
684#endif
685
686  channel_->AddFilter(new TraceMessageFilter());
687  channel_->AddFilter(new ResolveProxyMsgHelper(
688      browser_context->GetRequestContextForRenderProcess(GetID())));
689  channel_->AddFilter(new QuotaDispatcherHost(
690      GetID(),
691      storage_partition_impl_->GetQuotaManager(),
692      GetContentClient()->browser()->CreateQuotaPermissionContext()));
693  channel_->AddFilter(new GamepadBrowserMessageFilter());
694  channel_->AddFilter(new ProfilerMessageFilter(PROCESS_TYPE_RENDERER));
695  channel_->AddFilter(new HistogramMessageFilter());
696  channel_->AddFilter(new HyphenatorMessageFilter(this));
697#if defined(USE_TCMALLOC) && (defined(OS_LINUX) || defined(OS_ANDROID))
698  if (CommandLine::ForCurrentProcess()->HasSwitch(
699      switches::kEnableMemoryBenchmarking))
700    channel_->AddFilter(new MemoryBenchmarkMessageFilter());
701#endif
702}
703
704int RenderProcessHostImpl::GetNextRoutingID() {
705  return widget_helper_->GetNextRoutingID();
706}
707
708void RenderProcessHostImpl::ResumeDeferredNavigation(
709    const GlobalRequestID& request_id) {
710  widget_helper_->ResumeDeferredNavigation(request_id);
711}
712
713bool RenderProcessHostImpl::WaitForBackingStoreMsg(
714    int render_widget_id,
715    const base::TimeDelta& max_delay,
716    IPC::Message* msg) {
717  // The post task to this thread with the process id could be in queue, and we
718  // don't want to dispatch a message before then since it will need the handle.
719  if (child_process_launcher_.get() && child_process_launcher_->IsStarting())
720    return false;
721
722  return widget_helper_->WaitForBackingStoreMsg(render_widget_id,
723                                                max_delay, msg);
724}
725
726void RenderProcessHostImpl::ReceivedBadMessage() {
727  if (run_renderer_in_process()) {
728    // In single process mode it is better if we don't suicide but just
729    // crash.
730    CHECK(false);
731  }
732  // We kill the renderer but don't include a NOTREACHED, because we want the
733  // browser to try to survive when it gets illegal messages from the renderer.
734  base::KillProcess(GetHandle(), RESULT_CODE_KILLED_BAD_MESSAGE,
735                    false);
736}
737
738void RenderProcessHostImpl::WidgetRestored() {
739  // Verify we were properly backgrounded.
740  DCHECK_EQ(backgrounded_, (visible_widgets_ == 0));
741  visible_widgets_++;
742  SetBackgrounded(false);
743}
744
745void RenderProcessHostImpl::WidgetHidden() {
746  // On startup, the browser will call Hide
747  if (backgrounded_)
748    return;
749
750  DCHECK_EQ(backgrounded_, (visible_widgets_ == 0));
751  visible_widgets_--;
752  DCHECK_GE(visible_widgets_, 0);
753  if (visible_widgets_ == 0) {
754    DCHECK(!backgrounded_);
755    SetBackgrounded(true);
756  }
757}
758
759int RenderProcessHostImpl::VisibleWidgetCount() const {
760  return visible_widgets_;
761}
762
763bool RenderProcessHostImpl::IsGuest() const {
764  return is_guest_;
765}
766
767StoragePartition* RenderProcessHostImpl::GetStoragePartition() const {
768  return storage_partition_impl_;
769}
770
771void RenderProcessHostImpl::AppendRendererCommandLine(
772    CommandLine* command_line) const {
773  // Pass the process type first, so it shows first in process listings.
774  command_line->AppendSwitchASCII(switches::kProcessType,
775                                  switches::kRendererProcess);
776
777  // Now send any options from our own command line we want to propagate.
778  const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
779  PropagateBrowserCommandLineToRenderer(browser_command_line, command_line);
780
781  // Pass on the browser locale.
782  const std::string locale =
783      GetContentClient()->browser()->GetApplicationLocale();
784  command_line->AppendSwitchASCII(switches::kLang, locale);
785
786  // If we run base::FieldTrials, we want to pass to their state to the
787  // renderer so that it can act in accordance with each state, or record
788  // histograms relating to the base::FieldTrial states.
789  std::string field_trial_states;
790  base::FieldTrialList::StatesToString(&field_trial_states);
791  if (!field_trial_states.empty()) {
792    command_line->AppendSwitchASCII(switches::kForceFieldTrials,
793                                    field_trial_states);
794  }
795
796  GetContentClient()->browser()->AppendExtraCommandLineSwitches(
797      command_line, GetID());
798
799  // Appending disable-gpu-feature switches due to software rendering list.
800  GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance();
801  DCHECK(gpu_data_manager);
802  gpu_data_manager->AppendRendererCommandLine(command_line);
803}
804
805void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
806    const CommandLine& browser_cmd,
807    CommandLine* renderer_cmd) const {
808  // Propagate the following switches to the renderer command line (along
809  // with any associated values) if present in the browser command line.
810  static const char* const kSwitchNames[] = {
811    switches::kAudioBufferSize,
812    switches::kAuditAllHandles,
813    switches::kAuditHandles,
814    switches::kDisable3DAPIs,
815    switches::kDisableAcceleratedCompositing,
816    switches::kDisableAcceleratedVideoDecode,
817    switches::kDisableApplicationCache,
818    switches::kDisableAudio,
819    switches::kDisableBreakpad,
820    switches::kDisableDatabases,
821    switches::kDisableDesktopNotifications,
822    switches::kDisableDeviceOrientation,
823    switches::kDisableFileSystem,
824    switches::kDisableGeolocation,
825    switches::kDisableGLMultisampling,
826    switches::kDisableGpuVsync,
827    switches::kDisableGpu,
828    switches::kDisableHistogramCustomizer,
829    switches::kDisableJavaScriptI18NAPI,
830    switches::kDisableLocalStorage,
831    switches::kDisableLogging,
832    switches::kDisableNewDialogStyle,
833    switches::kDisableSeccompFilterSandbox,
834    switches::kDisableSessionStorage,
835    switches::kDisableSharedWorkers,
836    switches::kDisableSpeechInput,
837    switches::kDisableTouchDragDrop,
838    switches::kDisableTouchEditing,
839#if defined(OS_ANDROID)
840    switches::kDisableWebRTC,
841    switches::kEnableSpeechRecognition,
842#endif
843    switches::kDisableWebAudio,
844#if defined(ENABLE_WEBRTC)
845    switches::kEnableSCTPDataChannels,
846#endif
847    switches::kEnableWebMIDI,
848    switches::kEnableExperimentalCanvasFeatures,
849    switches::kEnableExperimentalWebSocket,
850    switches::kDomAutomationController,
851    switches::kEnableAccessibilityLogging,
852    switches::kEnableBeginFrameScheduling,
853    switches::kEnableBrowserInputController,
854    switches::kEnableBrowserPluginForAllViewTypes,
855    switches::kEnableDCHECK,
856    switches::kEnableDelegatedRenderer,
857    switches::kEnableEncryptedMedia,
858    switches::kDisableLegacyEncryptedMedia,
859    switches::kEnableExperimentalWebKitFeatures,
860    switches::kEnableFixedLayout,
861    switches::kEnableDeferredImageDecoding,
862    switches::kEnableGPUServiceLogging,
863    switches::kEnableGPUClientLogging,
864    switches::kEnableGpuClientTracing,
865    switches::kEnableGpuBenchmarking,
866    switches::kEnableMemoryBenchmarking,
867    switches::kEnableSkiaBenchmarking,
868    switches::kEnableLogging,
869    switches::kEnableSpeechSynthesis,
870    switches::kEnableTouchDragDrop,
871    switches::kEnableTouchEditing,
872    switches::kEnableWebPInAcceptHeader,
873#if defined(ENABLE_WEBRTC)
874    switches::kEnableWebRtcAecRecordings,
875#endif
876#if defined(ANDROID) && !defined(GOOGLE_TV)
877    switches::kEnableWebKitMediaSource,
878#else
879    switches::kDisableWebKitMediaSource,
880#endif
881    switches::kEnableOverscrollNotifications,
882    switches::kEnableStrictSiteIsolation,
883    switches::kDisableFullScreen,
884    switches::kEnableNewDialogStyle,
885#if defined(ENABLE_PLUGINS)
886    switches::kEnablePepperTesting,
887    switches::kDisablePepper3d,
888#endif
889    switches::kEnablePreparsedJsCaching,
890    switches::kEnablePruneGpuCommandBuffers,
891    switches::kEnablePinch,
892    switches::kDisablePinch,
893#if defined(OS_MACOSX)
894    // Allow this to be set when invoking the browser and relayed along.
895    switches::kEnableSandboxLogging,
896#endif
897    switches::kEnableSoftwareCompositingGLAdapter,
898    switches::kEnableStatsTable,
899    switches::kEnableThreadedCompositing,
900    switches::kEnableCompositingForFixedPosition,
901    switches::kEnableHighDpiCompositingForFixedPosition,
902    switches::kDisableCompositingForFixedPosition,
903    switches::kEnableCompositingForTransition,
904    switches::kDisableCompositingForTransition,
905    switches::kDisableThreadedCompositing,
906    switches::kDisableTouchAdjustment,
907    switches::kDefaultTileWidth,
908    switches::kDefaultTileHeight,
909    switches::kMaxUntiledLayerWidth,
910    switches::kMaxUntiledLayerHeight,
911    switches::kEnableViewport,
912    switches::kEnableOpusPlayback,
913    switches::kEnableVp8AlphaPlayback,
914    switches::kEnableEac3Playback,
915    switches::kForceDeviceScaleFactor,
916    switches::kFullMemoryCrashReport,
917#if !defined (GOOGLE_CHROME_BUILD)
918    // These are unsupported and not fully tested modes, so don't enable them
919    // for official Google Chrome builds.
920    switches::kInProcessPlugins,
921#endif  // GOOGLE_CHROME_BUILD
922    switches::kJavaScriptFlags,
923    switches::kLoggingLevel,
924    switches::kMemoryMetrics,
925#if defined(OS_ANDROID)
926    switches::kNetworkCountryIso,
927    switches::kDisableGestureRequirementForMediaPlayback,
928#endif
929#if defined(GOOGLE_TV)
930    switches::kUseExternalVideoSurfaceThresholdInPixels,
931#endif
932    switches::kNoReferrers,
933    switches::kNoSandbox,
934    switches::kEnableVtune,
935    switches::kPpapiInProcess,
936    switches::kRegisterPepperPlugins,
937    switches::kRendererAssertTest,
938#if defined(OS_POSIX)
939    switches::kChildCleanExit,
940#endif
941    switches::kRendererStartupDialog,
942    switches::kShowPaintRects,
943    switches::kSitePerProcess,
944    switches::kStatsCollectionController,
945    switches::kTestSandbox,
946    switches::kTouchEvents,
947    switches::kTraceStartup,
948    // This flag needs to be propagated to the renderer process for
949    // --in-process-webgl.
950    switches::kUseGL,
951    switches::kUseMobileUserAgent,
952    switches::kUserAgent,
953    switches::kV,
954    switches::kVideoThreads,
955    switches::kVModule,
956    switches::kWebCoreLogChannels,
957    switches::kEnableWebGLDraftExtensions,
958    // Please keep these in alphabetical order. Compositor switches here should
959    // also be added to chrome/browser/chromeos/login/chrome_restart_request.cc.
960    cc::switches::kBackgroundColorInsteadOfCheckerboard,
961    cc::switches::kCompositeToMailbox,
962    cc::switches::kDisableColorEstimator,
963    cc::switches::kDisableImplSidePainting,
964    cc::switches::kDisableThreadedAnimation,
965    cc::switches::kEnableImplSidePainting,
966    cc::switches::kEnablePartialSwap,
967    cc::switches::kEnablePerTilePainting,
968    cc::switches::kEnablePinchVirtualViewport,
969    cc::switches::kEnableTopControlsPositionCalculation,
970    cc::switches::kForceDirectLayerDrawing,
971    cc::switches::kLowResolutionContentsScaleFactor,
972    cc::switches::kMaxTilesForInterestArea,
973    cc::switches::kMaxUnusedResourceMemoryUsagePercentage,
974    cc::switches::kNumRasterThreads,
975    cc::switches::kShowCompositedLayerBorders,
976    cc::switches::kShowCompositedLayerTree,
977    cc::switches::kShowFPSCounter,
978    cc::switches::kShowNonOccludingRects,
979    cc::switches::kShowOccludingRects,
980    cc::switches::kShowPropertyChangedRects,
981    cc::switches::kShowReplicaScreenSpaceRects,
982    cc::switches::kShowScreenSpaceRects,
983    cc::switches::kShowSurfaceDamageRects,
984    cc::switches::kSlowDownRasterScaleFactor,
985    cc::switches::kStrictLayerPropertyChangeChecking,
986    cc::switches::kTopControlsHeight,
987    cc::switches::kTopControlsHideThreshold,
988    cc::switches::kTopControlsShowThreshold,
989    cc::switches::kTraceOverdraw,
990    cc::switches::kUseMapImage,
991  };
992  renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames,
993                                 arraysize(kSwitchNames));
994
995  // Disable databases in incognito mode.
996  if (GetBrowserContext()->IsOffTheRecord() &&
997      !browser_cmd.HasSwitch(switches::kDisableDatabases)) {
998    renderer_cmd->AppendSwitch(switches::kDisableDatabases);
999#if defined(OS_ANDROID)
1000    renderer_cmd->AppendSwitch(switches::kDisableMediaHistoryLogging);
1001#endif
1002  }
1003
1004  // Enforce the extra command line flags for impl-side painting.
1005  if (cc::switches::IsImplSidePaintingEnabled() &&
1006      !browser_cmd.HasSwitch(switches::kEnableDeferredImageDecoding))
1007    renderer_cmd->AppendSwitch(switches::kEnableDeferredImageDecoding);
1008}
1009
1010base::ProcessHandle RenderProcessHostImpl::GetHandle() const {
1011  if (run_renderer_in_process())
1012    return base::Process::Current().handle();
1013
1014  if (!child_process_launcher_.get() || child_process_launcher_->IsStarting())
1015    return base::kNullProcessHandle;
1016
1017  return child_process_launcher_->GetHandle();
1018}
1019
1020bool RenderProcessHostImpl::FastShutdownIfPossible() {
1021  if (run_renderer_in_process())
1022    return false;  // Single process mode never shutdown the renderer.
1023
1024  if (!GetContentClient()->browser()->IsFastShutdownPossible())
1025    return false;
1026
1027  if (!child_process_launcher_.get() ||
1028      child_process_launcher_->IsStarting() ||
1029      !GetHandle())
1030    return false;  // Render process hasn't started or is probably crashed.
1031
1032  // Test if there's an unload listener.
1033  // NOTE: It's possible that an onunload listener may be installed
1034  // while we're shutting down, so there's a small race here.  Given that
1035  // the window is small, it's unlikely that the web page has much
1036  // state that will be lost by not calling its unload handlers properly.
1037  if (!SuddenTerminationAllowed())
1038    return false;
1039
1040  ProcessDied(false /* already_dead */);
1041  fast_shutdown_started_ = true;
1042  return true;
1043}
1044
1045void RenderProcessHostImpl::DumpHandles() {
1046#if defined(OS_WIN)
1047  Send(new ChildProcessMsg_DumpHandles());
1048  return;
1049#endif
1050
1051  NOTIMPLEMENTED();
1052}
1053
1054// This is a platform specific function for mapping a transport DIB given its id
1055TransportDIB* RenderProcessHostImpl::MapTransportDIB(
1056    TransportDIB::Id dib_id) {
1057#if defined(OS_WIN)
1058  // On Windows we need to duplicate the handle from the remote process
1059  HANDLE section;
1060  DuplicateHandle(GetHandle(), dib_id.handle, GetCurrentProcess(), &section,
1061                  STANDARD_RIGHTS_REQUIRED | FILE_MAP_READ | FILE_MAP_WRITE,
1062                  FALSE, 0);
1063  return TransportDIB::Map(section);
1064#elif defined(TOOLKIT_GTK)
1065  return TransportDIB::Map(dib_id.shmkey);
1066#elif defined(OS_ANDROID)
1067  return TransportDIB::Map(dib_id);
1068#else
1069  // On POSIX, the browser allocates all DIBs and keeps a file descriptor around
1070  // for each.
1071  return widget_helper_->MapTransportDIB(dib_id);
1072#endif
1073}
1074
1075TransportDIB* RenderProcessHostImpl::GetTransportDIB(
1076    TransportDIB::Id dib_id) {
1077  if (!TransportDIB::is_valid_id(dib_id))
1078    return NULL;
1079
1080  const std::map<TransportDIB::Id, TransportDIB*>::iterator
1081      i = cached_dibs_.find(dib_id);
1082  if (i != cached_dibs_.end()) {
1083    cached_dibs_cleaner_.Reset();
1084    return i->second;
1085  }
1086
1087  TransportDIB* dib = MapTransportDIB(dib_id);
1088  if (!dib)
1089    return NULL;
1090
1091  if (cached_dibs_.size() >= MAX_MAPPED_TRANSPORT_DIBS) {
1092    // Clean a single entry from the cache
1093    std::map<TransportDIB::Id, TransportDIB*>::iterator smallest_iterator;
1094    size_t smallest_size = std::numeric_limits<size_t>::max();
1095
1096    for (std::map<TransportDIB::Id, TransportDIB*>::iterator
1097         i = cached_dibs_.begin(); i != cached_dibs_.end(); ++i) {
1098      if (i->second->size() <= smallest_size) {
1099        smallest_iterator = i;
1100        smallest_size = i->second->size();
1101      }
1102    }
1103
1104#if defined(TOOLKIT_GTK)
1105    smallest_iterator->second->Detach();
1106#else
1107    delete smallest_iterator->second;
1108#endif
1109    cached_dibs_.erase(smallest_iterator);
1110  }
1111
1112  cached_dibs_[dib_id] = dib;
1113  cached_dibs_cleaner_.Reset();
1114  return dib;
1115}
1116
1117void RenderProcessHostImpl::ClearTransportDIBCache() {
1118#if defined(TOOLKIT_GTK)
1119  std::map<TransportDIB::Id, TransportDIB*>::const_iterator dib =
1120      cached_dibs_.begin();
1121  for (; dib != cached_dibs_.end(); ++dib)
1122    dib->second->Detach();
1123#else
1124  STLDeleteContainerPairSecondPointers(
1125      cached_dibs_.begin(), cached_dibs_.end());
1126#endif
1127  cached_dibs_.clear();
1128}
1129
1130bool RenderProcessHostImpl::Send(IPC::Message* msg) {
1131  if (!channel_) {
1132    if (!is_initialized_) {
1133      queued_messages_.push(msg);
1134      return true;
1135    } else {
1136      delete msg;
1137      return false;
1138    }
1139  }
1140
1141  if (child_process_launcher_.get() && child_process_launcher_->IsStarting()) {
1142    queued_messages_.push(msg);
1143    return true;
1144  }
1145
1146  return channel_->Send(msg);
1147}
1148
1149bool RenderProcessHostImpl::OnMessageReceived(const IPC::Message& msg) {
1150  // If we're about to be deleted, or have initiated the fast shutdown sequence,
1151  // we ignore incoming messages.
1152
1153  if (deleting_soon_ || fast_shutdown_started_)
1154    return false;
1155
1156  mark_child_process_activity_time();
1157  if (msg.routing_id() == MSG_ROUTING_CONTROL) {
1158    // Dispatch control messages.
1159    bool msg_is_ok = true;
1160    IPC_BEGIN_MESSAGE_MAP_EX(RenderProcessHostImpl, msg, msg_is_ok)
1161      IPC_MESSAGE_HANDLER(ChildProcessHostMsg_ShutdownRequest,
1162                          OnShutdownRequest)
1163      IPC_MESSAGE_HANDLER(ChildProcessHostMsg_DumpHandlesDone,
1164                          OnDumpHandlesDone)
1165      IPC_MESSAGE_HANDLER(ViewHostMsg_SuddenTerminationChanged,
1166                          SuddenTerminationChanged)
1167      IPC_MESSAGE_HANDLER(ViewHostMsg_UserMetricsRecordAction,
1168                          OnUserMetricsRecordAction)
1169      IPC_MESSAGE_HANDLER(ViewHostMsg_SavedPageAsMHTML, OnSavedPageAsMHTML)
1170      // Adding single handlers for your service here is fine, but once your
1171      // service needs more than one handler, please extract them into a new
1172      // message filter and add that filter to CreateMessageFilters().
1173      IPC_MESSAGE_UNHANDLED_ERROR()
1174    IPC_END_MESSAGE_MAP_EX()
1175
1176    if (!msg_is_ok) {
1177      // The message had a handler, but its de-serialization failed.
1178      // We consider this a capital crime. Kill the renderer if we have one.
1179      LOG(ERROR) << "bad message " << msg.type() << " terminating renderer.";
1180      RecordAction(UserMetricsAction("BadMessageTerminate_BRPH"));
1181      ReceivedBadMessage();
1182    }
1183    return true;
1184  }
1185
1186  // Dispatch incoming messages to the appropriate RenderView/WidgetHost.
1187  RenderWidgetHost* rwh = render_widget_hosts_.Lookup(msg.routing_id());
1188  if (!rwh) {
1189    if (msg.is_sync()) {
1190      // The listener has gone away, so we must respond or else the caller will
1191      // hang waiting for a reply.
1192      IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg);
1193      reply->set_reply_error();
1194      Send(reply);
1195    }
1196
1197    // If this is a SwapBuffers, we need to ack it if we're not going to handle
1198    // it so that the GPU process doesn't get stuck in unscheduled state.
1199    bool msg_is_ok = true;
1200    IPC_BEGIN_MESSAGE_MAP_EX(RenderProcessHostImpl, msg, msg_is_ok)
1201      IPC_MESSAGE_HANDLER(ViewHostMsg_CompositorSurfaceBuffersSwapped,
1202                          OnCompositorSurfaceBuffersSwappedNoHost)
1203    IPC_END_MESSAGE_MAP_EX()
1204    return true;
1205  }
1206  return RenderWidgetHostImpl::From(rwh)->OnMessageReceived(msg);
1207}
1208
1209void RenderProcessHostImpl::OnChannelConnected(int32 peer_pid) {
1210#if defined(IPC_MESSAGE_LOG_ENABLED)
1211  Send(new ChildProcessMsg_SetIPCLoggingEnabled(
1212      IPC::Logging::GetInstance()->Enabled()));
1213#endif
1214
1215  tracked_objects::ThreadData::Status status =
1216      tracked_objects::ThreadData::status();
1217  Send(new ChildProcessMsg_SetProfilerStatus(status));
1218}
1219
1220void RenderProcessHostImpl::OnChannelError() {
1221  ProcessDied(true /* already_dead */);
1222}
1223
1224BrowserContext* RenderProcessHostImpl::GetBrowserContext() const {
1225  return browser_context_;
1226}
1227
1228bool RenderProcessHostImpl::InSameStoragePartition(
1229    StoragePartition* partition) const {
1230  return storage_partition_impl_ == partition;
1231}
1232
1233int RenderProcessHostImpl::GetID() const {
1234  return id_;
1235}
1236
1237bool RenderProcessHostImpl::HasConnection() const {
1238  return channel_.get() != NULL;
1239}
1240
1241RenderWidgetHost* RenderProcessHostImpl::GetRenderWidgetHostByID(
1242    int routing_id) {
1243  return render_widget_hosts_.Lookup(routing_id);
1244}
1245
1246void RenderProcessHostImpl::SetIgnoreInputEvents(bool ignore_input_events) {
1247  ignore_input_events_ = ignore_input_events;
1248}
1249
1250bool RenderProcessHostImpl::IgnoreInputEvents() const {
1251  return ignore_input_events_;
1252}
1253
1254void RenderProcessHostImpl::Attach(RenderWidgetHost* host,
1255                                   int routing_id) {
1256  render_widget_hosts_.AddWithID(host, routing_id);
1257}
1258
1259void RenderProcessHostImpl::Release(int routing_id) {
1260  DCHECK(render_widget_hosts_.Lookup(routing_id) != NULL);
1261  render_widget_hosts_.Remove(routing_id);
1262
1263#if defined(OS_WIN)
1264  // Dump the handle table if handle auditing is enabled.
1265  const CommandLine& browser_command_line =
1266      *CommandLine::ForCurrentProcess();
1267  if (browser_command_line.HasSwitch(switches::kAuditHandles) ||
1268      browser_command_line.HasSwitch(switches::kAuditAllHandles)) {
1269    DumpHandles();
1270
1271    // We wait to close the channels until the child process has finished
1272    // dumping handles and sends us ChildProcessHostMsg_DumpHandlesDone.
1273    return;
1274  }
1275#endif
1276  // Keep the one renderer thread around forever in single process mode.
1277  if (!run_renderer_in_process())
1278    Cleanup();
1279}
1280
1281void RenderProcessHostImpl::Cleanup() {
1282  // When no other owners of this object, we can delete ourselves
1283  if (render_widget_hosts_.IsEmpty()) {
1284    DCHECK_EQ(0, pending_views_);
1285    NotificationService::current()->Notify(
1286        NOTIFICATION_RENDERER_PROCESS_TERMINATED,
1287        Source<RenderProcessHost>(this),
1288        NotificationService::NoDetails());
1289
1290    base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
1291    deleting_soon_ = true;
1292    // It's important not to wait for the DeleteTask to delete the channel
1293    // proxy. Kill it off now. That way, in case the profile is going away, the
1294    // rest of the objects attached to this RenderProcessHost start going
1295    // away first, since deleting the channel proxy will post a
1296    // OnChannelClosed() to IPC::ChannelProxy::Context on the IO thread.
1297    channel_.reset();
1298    gpu_message_filter_ = NULL;
1299
1300    // Remove ourself from the list of renderer processes so that we can't be
1301    // reused in between now and when the Delete task runs.
1302    UnregisterHost(GetID());
1303  }
1304}
1305
1306void RenderProcessHostImpl::AddPendingView() {
1307  pending_views_++;
1308}
1309
1310void RenderProcessHostImpl::RemovePendingView() {
1311  DCHECK(pending_views_);
1312  pending_views_--;
1313}
1314
1315void RenderProcessHostImpl::SetSuddenTerminationAllowed(bool enabled) {
1316  sudden_termination_allowed_ = enabled;
1317}
1318
1319bool RenderProcessHostImpl::SuddenTerminationAllowed() const {
1320  return sudden_termination_allowed_;
1321}
1322
1323base::TimeDelta RenderProcessHostImpl::GetChildProcessIdleTime() const {
1324  return base::TimeTicks::Now() - child_process_activity_time_;
1325}
1326
1327void RenderProcessHostImpl::SurfaceUpdated(int32 surface_id) {
1328  if (!gpu_message_filter_)
1329    return;
1330  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
1331      &GpuMessageFilter::SurfaceUpdated,
1332      gpu_message_filter_,
1333      surface_id));
1334}
1335
1336void RenderProcessHostImpl::ResumeRequestsForView(int route_id) {
1337  widget_helper_->ResumeRequestsForView(route_id);
1338}
1339
1340IPC::ChannelProxy* RenderProcessHostImpl::GetChannel() {
1341  return channel_.get();
1342}
1343
1344RenderProcessHost::RenderWidgetHostsIterator
1345    RenderProcessHostImpl::GetRenderWidgetHostsIterator() {
1346  return RenderWidgetHostsIterator(&render_widget_hosts_);
1347}
1348
1349bool RenderProcessHostImpl::FastShutdownForPageCount(size_t count) {
1350  if (render_widget_hosts_.size() == count)
1351    return FastShutdownIfPossible();
1352  return false;
1353}
1354
1355bool RenderProcessHostImpl::FastShutdownStarted() const {
1356  return fast_shutdown_started_;
1357}
1358
1359// static
1360void RenderProcessHostImpl::RegisterHost(int host_id, RenderProcessHost* host) {
1361  g_all_hosts.Get().AddWithID(host, host_id);
1362}
1363
1364// static
1365void RenderProcessHostImpl::UnregisterHost(int host_id) {
1366  RenderProcessHost* host = g_all_hosts.Get().Lookup(host_id);
1367  if (!host)
1368    return;
1369
1370  g_all_hosts.Get().Remove(host_id);
1371
1372  // Look up the map of site to process for the given browser_context,
1373  // in case we need to remove this process from it.  It will be registered
1374  // under any sites it rendered that use process-per-site mode.
1375  SiteProcessMap* map =
1376      GetSiteProcessMapForBrowserContext(host->GetBrowserContext());
1377  map->RemoveProcess(host);
1378}
1379
1380// static
1381bool RenderProcessHostImpl::IsSuitableHost(
1382    RenderProcessHost* host,
1383    BrowserContext* browser_context,
1384    const GURL& site_url) {
1385  if (run_renderer_in_process())
1386    return true;
1387
1388  if (host->GetBrowserContext() != browser_context)
1389    return false;
1390
1391  // Check whether the given host and the intended site_url will be using the
1392  // same StoragePartition, since a RenderProcessHost can only support a single
1393  // StoragePartition.  This is relevant for packaged apps, browser tags, and
1394  // isolated sites.
1395  StoragePartition* dest_partition =
1396      BrowserContext::GetStoragePartitionForSite(browser_context, site_url);
1397  if (!host->InSameStoragePartition(dest_partition))
1398    return false;
1399
1400  // All URLs are suitable if this is associated with a guest renderer process.
1401  // TODO(fsamuel, creis): Further validation is needed to ensure that only
1402  // normal web URLs are permitted in guest processes. We need to investigate
1403  // where this validation should happen.
1404  if (host->IsGuest())
1405    return true;
1406
1407  if (!host->IsGuest() && site_url.SchemeIs(chrome::kGuestScheme))
1408    return false;
1409
1410  if (ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1411          host->GetID()) !=
1412      WebUIControllerFactoryRegistry::GetInstance()->UseWebUIBindingsForURL(
1413          browser_context, site_url)) {
1414    return false;
1415  }
1416
1417  return GetContentClient()->browser()->IsSuitableHost(host, site_url);
1418}
1419
1420// static
1421bool RenderProcessHost::run_renderer_in_process() {
1422  return g_run_renderer_in_process_;
1423}
1424
1425// static
1426void RenderProcessHost::SetRunRendererInProcess(bool value) {
1427  g_run_renderer_in_process_ = value;
1428
1429  CommandLine* command_line = CommandLine::ForCurrentProcess();
1430  if (value && !command_line->HasSwitch(switches::kLang)) {
1431    // Modify the current process' command line to include the browser locale,
1432    // as the renderer expects this flag to be set.
1433    const std::string locale =
1434        GetContentClient()->browser()->GetApplicationLocale();
1435    command_line->AppendSwitchASCII(switches::kLang, locale);
1436  }
1437}
1438
1439RenderProcessHost::iterator RenderProcessHost::AllHostsIterator() {
1440  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1441  return iterator(g_all_hosts.Pointer());
1442}
1443
1444// static
1445RenderProcessHost* RenderProcessHost::FromID(int render_process_id) {
1446  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1447  return g_all_hosts.Get().Lookup(render_process_id);
1448}
1449
1450// static
1451bool RenderProcessHost::ShouldTryToUseExistingProcessHost(
1452    BrowserContext* browser_context, const GURL& url) {
1453  // Experimental:
1454  // If --enable-strict-site-isolation or --site-per-process is enabled, do not
1455  // try to reuse renderer processes when over the limit.  (We could allow pages
1456  // from the same site to share, if we knew what the given process was
1457  // dedicated to.  Allowing no sharing is simpler for now.)  This may cause
1458  // resource exhaustion issues if too many sites are open at once.
1459  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1460  if (command_line.HasSwitch(switches::kEnableStrictSiteIsolation) ||
1461      command_line.HasSwitch(switches::kSitePerProcess))
1462    return false;
1463
1464  if (run_renderer_in_process())
1465    return true;
1466
1467  // NOTE: Sometimes it's necessary to create more render processes than
1468  //       GetMaxRendererProcessCount(), for instance when we want to create
1469  //       a renderer process for a browser context that has no existing
1470  //       renderers. This is OK in moderation, since the
1471  //       GetMaxRendererProcessCount() is conservative.
1472  if (g_all_hosts.Get().size() >= GetMaxRendererProcessCount())
1473    return true;
1474
1475  return GetContentClient()->browser()->
1476      ShouldTryToUseExistingProcessHost(browser_context, url);
1477}
1478
1479// static
1480RenderProcessHost* RenderProcessHost::GetExistingProcessHost(
1481    BrowserContext* browser_context,
1482    const GURL& site_url) {
1483  // First figure out which existing renderers we can use.
1484  std::vector<RenderProcessHost*> suitable_renderers;
1485  suitable_renderers.reserve(g_all_hosts.Get().size());
1486
1487  iterator iter(AllHostsIterator());
1488  while (!iter.IsAtEnd()) {
1489    if (RenderProcessHostImpl::IsSuitableHost(
1490            iter.GetCurrentValue(),
1491            browser_context, site_url))
1492      suitable_renderers.push_back(iter.GetCurrentValue());
1493
1494    iter.Advance();
1495  }
1496
1497  // Now pick a random suitable renderer, if we have any.
1498  if (!suitable_renderers.empty()) {
1499    int suitable_count = static_cast<int>(suitable_renderers.size());
1500    int random_index = base::RandInt(0, suitable_count - 1);
1501    return suitable_renderers[random_index];
1502  }
1503
1504  return NULL;
1505}
1506
1507// static
1508bool RenderProcessHost::ShouldUseProcessPerSite(
1509    BrowserContext* browser_context,
1510    const GURL& url) {
1511  // Returns true if we should use the process-per-site model.  This will be
1512  // the case if the --process-per-site switch is specified, or in
1513  // process-per-site-instance for particular sites (e.g., WebUI).
1514  // Note that --single-process is handled in ShouldTryToUseExistingProcessHost.
1515  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1516  if (command_line.HasSwitch(switches::kProcessPerSite))
1517    return true;
1518
1519  // We want to consolidate particular sites like WebUI even when we are using
1520  // the process-per-tab or process-per-site-instance models.
1521  // Note: DevTools pages have WebUI type but should not reuse the same host.
1522  if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL(
1523          browser_context, url) &&
1524      !url.SchemeIs(chrome::kChromeDevToolsScheme)) {
1525    return true;
1526  }
1527
1528  // Otherwise let the content client decide, defaulting to false.
1529  return GetContentClient()->browser()->ShouldUseProcessPerSite(browser_context,
1530                                                                url);
1531}
1532
1533// static
1534RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSite(
1535    BrowserContext* browser_context,
1536    const GURL& url) {
1537  // Look up the map of site to process for the given browser_context.
1538  SiteProcessMap* map =
1539      GetSiteProcessMapForBrowserContext(browser_context);
1540
1541  // See if we have an existing process with appropriate bindings for this site.
1542  // If not, the caller should create a new process and register it.
1543  std::string site = SiteInstance::GetSiteForURL(browser_context, url)
1544      .possibly_invalid_spec();
1545  RenderProcessHost* host = map->FindProcess(site);
1546  if (host && !IsSuitableHost(host, browser_context, url)) {
1547    // The registered process does not have an appropriate set of bindings for
1548    // the url.  Remove it from the map so we can register a better one.
1549    RecordAction(UserMetricsAction("BindingsMismatch_GetProcessHostPerSite"));
1550    map->RemoveProcess(host);
1551    host = NULL;
1552  }
1553
1554  return host;
1555}
1556
1557void RenderProcessHostImpl::RegisterProcessHostForSite(
1558    BrowserContext* browser_context,
1559    RenderProcessHost* process,
1560    const GURL& url) {
1561  // Look up the map of site to process for the given browser_context.
1562  SiteProcessMap* map =
1563      GetSiteProcessMapForBrowserContext(browser_context);
1564
1565  // Only register valid, non-empty sites.  Empty or invalid sites will not
1566  // use process-per-site mode.  We cannot check whether the process has
1567  // appropriate bindings here, because the bindings have not yet been granted.
1568  std::string site = SiteInstance::GetSiteForURL(browser_context, url)
1569      .possibly_invalid_spec();
1570  if (!site.empty())
1571    map->RegisterProcess(site, process);
1572}
1573
1574base::MessageLoop*
1575    RenderProcessHostImpl::GetInProcessRendererThreadForTesting() {
1576  return g_in_process_thread;
1577}
1578
1579void RenderProcessHostImpl::ProcessDied(bool already_dead) {
1580  // Our child process has died.  If we didn't expect it, it's a crash.
1581  // In any case, we need to let everyone know it's gone.
1582  // The OnChannelError notification can fire multiple times due to nested sync
1583  // calls to a renderer. If we don't have a valid channel here it means we
1584  // already handled the error.
1585
1586  // child_process_launcher_ can be NULL in single process mode or if fast
1587  // termination happened.
1588  int exit_code = 0;
1589  base::TerminationStatus status =
1590      child_process_launcher_.get() ?
1591      child_process_launcher_->GetChildTerminationStatus(already_dead,
1592                                                         &exit_code) :
1593      base::TERMINATION_STATUS_NORMAL_TERMINATION;
1594
1595  RendererClosedDetails details(GetHandle(), status, exit_code);
1596  NotificationService::current()->Notify(
1597      NOTIFICATION_RENDERER_PROCESS_CLOSED,
1598      Source<RenderProcessHost>(this),
1599      Details<RendererClosedDetails>(&details));
1600
1601  child_process_launcher_.reset();
1602  channel_.reset();
1603  gpu_message_filter_ = NULL;
1604
1605  IDMap<RenderWidgetHost>::iterator iter(&render_widget_hosts_);
1606  while (!iter.IsAtEnd()) {
1607    RenderWidgetHostImpl::From(iter.GetCurrentValue())->OnMessageReceived(
1608        ViewHostMsg_RenderViewGone(iter.GetCurrentKey(),
1609                                   static_cast<int>(status),
1610                                   exit_code));
1611    iter.Advance();
1612  }
1613
1614  ClearTransportDIBCache();
1615
1616  // this object is not deleted at this point and may be reused later.
1617  // TODO(darin): clean this up
1618}
1619
1620int RenderProcessHostImpl::GetActiveViewCount() {
1621  int num_active_views = 0;
1622  for (RenderWidgetHostsIterator iter = GetRenderWidgetHostsIterator();
1623       !iter.IsAtEnd();
1624       iter.Advance()) {
1625    const RenderWidgetHost* widget = iter.GetCurrentValue();
1626    DCHECK(widget);
1627    if (!widget)
1628      continue;
1629
1630    // All RenderWidgetHosts are swapped in.
1631    if (!widget->IsRenderView()) {
1632      num_active_views++;
1633      continue;
1634    }
1635
1636    // Don't count swapped out views.
1637    RenderViewHost* rvh =
1638        RenderViewHost::From(const_cast<RenderWidgetHost*>(widget));
1639    if (!static_cast<RenderViewHostImpl*>(rvh)->is_swapped_out())
1640      num_active_views++;
1641  }
1642  return num_active_views;
1643}
1644
1645// Frame subscription API for this class is for accelerated composited path
1646// only. These calls are redirected to GpuMessageFilter.
1647void RenderProcessHostImpl::BeginFrameSubscription(
1648    int route_id,
1649    scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
1650  if (!gpu_message_filter_)
1651    return;
1652  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
1653      &GpuMessageFilter::BeginFrameSubscription,
1654      gpu_message_filter_,
1655      route_id, base::Passed(&subscriber)));
1656}
1657
1658void RenderProcessHostImpl::EndFrameSubscription(int route_id) {
1659  if (!gpu_message_filter_)
1660    return;
1661  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
1662      &GpuMessageFilter::EndFrameSubscription,
1663      gpu_message_filter_,
1664      route_id));
1665}
1666
1667void RenderProcessHostImpl::OnShutdownRequest() {
1668  // Don't shut down if there are active RenderViews, or if there are pending
1669  // RenderViews being swapped back in.
1670  // In single process mode, we never shutdown the renderer.
1671  int num_active_views = GetActiveViewCount();
1672  if (pending_views_ || num_active_views > 0 || run_renderer_in_process())
1673    return;
1674
1675  // Notify any contents that might have swapped out renderers from this
1676  // process. They should not attempt to swap them back in.
1677  NotificationService::current()->Notify(
1678      NOTIFICATION_RENDERER_PROCESS_CLOSING,
1679      Source<RenderProcessHost>(this),
1680      NotificationService::NoDetails());
1681
1682  Send(new ChildProcessMsg_Shutdown());
1683}
1684
1685void RenderProcessHostImpl::SuddenTerminationChanged(bool enabled) {
1686  SetSuddenTerminationAllowed(enabled);
1687}
1688
1689void RenderProcessHostImpl::OnDumpHandlesDone() {
1690  Cleanup();
1691}
1692
1693void RenderProcessHostImpl::SetBackgrounded(bool backgrounded) {
1694  // Note: we always set the backgrounded_ value.  If the process is NULL
1695  // (and hence hasn't been created yet), we will set the process priority
1696  // later when we create the process.
1697  backgrounded_ = backgrounded;
1698  if (!child_process_launcher_.get() || child_process_launcher_->IsStarting())
1699    return;
1700
1701#if defined(OS_WIN)
1702  // The cbstext.dll loads as a global GetMessage hook in the browser process
1703  // and intercepts/unintercepts the kernel32 API SetPriorityClass in a
1704  // background thread. If the UI thread invokes this API just when it is
1705  // intercepted the stack is messed up on return from the interceptor
1706  // which causes random crashes in the browser process. Our hack for now
1707  // is to not invoke the SetPriorityClass API if the dll is loaded.
1708  if (GetModuleHandle(L"cbstext.dll"))
1709    return;
1710#endif  // OS_WIN
1711
1712  child_process_launcher_->SetProcessBackgrounded(backgrounded);
1713}
1714
1715void RenderProcessHostImpl::OnProcessLaunched() {
1716  // No point doing anything, since this object will be destructed soon.  We
1717  // especially don't want to send the RENDERER_PROCESS_CREATED notification,
1718  // since some clients might expect a RENDERER_PROCESS_TERMINATED afterwards to
1719  // properly cleanup.
1720  if (deleting_soon_)
1721    return;
1722
1723  if (child_process_launcher_) {
1724    if (!child_process_launcher_->GetHandle()) {
1725      OnChannelError();
1726      return;
1727    }
1728
1729    child_process_launcher_->SetProcessBackgrounded(backgrounded_);
1730  }
1731
1732  // NOTE: This needs to be before sending queued messages because
1733  // ExtensionService uses this notification to initialize the renderer process
1734  // with state that must be there before any JavaScript executes.
1735  //
1736  // The queued messages contain such things as "navigate". If this notification
1737  // was after, we can end up executing JavaScript before the initialization
1738  // happens.
1739  NotificationService::current()->Notify(
1740      NOTIFICATION_RENDERER_PROCESS_CREATED,
1741      Source<RenderProcessHost>(this),
1742      NotificationService::NoDetails());
1743
1744  while (!queued_messages_.empty()) {
1745    Send(queued_messages_.front());
1746    queued_messages_.pop();
1747  }
1748}
1749
1750void RenderProcessHostImpl::OnUserMetricsRecordAction(
1751    const std::string& action) {
1752  RecordComputedAction(action);
1753}
1754
1755void RenderProcessHostImpl::OnSavedPageAsMHTML(int job_id, int64 data_size) {
1756  MHTMLGenerationManager::GetInstance()->MHTMLGenerated(job_id, data_size);
1757}
1758
1759void RenderProcessHostImpl::OnCompositorSurfaceBuffersSwappedNoHost(
1760      const ViewHostMsg_CompositorSurfaceBuffersSwapped_Params& params) {
1761  TRACE_EVENT0("renderer_host",
1762               "RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwappedNoHost");
1763  AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
1764  ack_params.sync_point = 0;
1765  RenderWidgetHostImpl::AcknowledgeBufferPresent(params.route_id,
1766                                                 params.gpu_process_host_id,
1767                                                 ack_params);
1768}
1769
1770void RenderProcessHostImpl::OnGpuSwitching() {
1771  for (RenderWidgetHostsIterator iter = GetRenderWidgetHostsIterator();
1772       !iter.IsAtEnd();
1773       iter.Advance()) {
1774    const RenderWidgetHost* widget = iter.GetCurrentValue();
1775    DCHECK(widget);
1776    if (!widget || !widget->IsRenderView())
1777      continue;
1778
1779    RenderViewHost* rvh =
1780        RenderViewHost::From(const_cast<RenderWidgetHost*>(widget));
1781
1782    rvh->UpdateWebkitPreferences(rvh->GetWebkitPreferences());
1783  }
1784}
1785
1786}  // namespace content
1787