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