render_process_host_impl.cc revision 3551c9c881056c480085172ff9840cab31610854
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(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(new PepperMessageFilter(GetID(), browser_context));
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::kDisable3DAPIs,
844    switches::kDisableAcceleratedCompositing,
845    switches::kDisableAcceleratedVideoDecode,
846    switches::kDisableApplicationCache,
847    switches::kDisableAudio,
848    switches::kDisableBreakpad,
849    switches::kDisableDatabases,
850    switches::kDisableDelegatedRenderer,
851    switches::kDisableDesktopNotifications,
852    switches::kDisableDeviceOrientation,
853    switches::kDisableFileSystem,
854    switches::kDisableGeolocation,
855    switches::kDisableGLMultisampling,
856    switches::kDisableGpuVsync,
857    switches::kDisableGpu,
858    switches::kDisableGpuCompositing,
859    switches::kDisableHistogramCustomizer,
860    switches::kDisableLocalStorage,
861    switches::kDisableLogging,
862    switches::kDisableNewDialogStyle,
863    switches::kDisableSeccompFilterSandbox,
864    switches::kDisableSessionStorage,
865    switches::kDisableSharedWorkers,
866    switches::kDisableSpeechInput,
867    switches::kDisableTouchDragDrop,
868    switches::kDisableTouchEditing,
869#if defined(OS_ANDROID)
870    switches::kDisableWebRTC,
871    switches::kEnableSpeechRecognition,
872#endif
873    switches::kDisableWebAudio,
874#if defined(ENABLE_WEBRTC)
875    switches::kDisableDeviceEnumeration,
876    switches::kEnableSCTPDataChannels,
877#endif
878    switches::kEnableWebAnimationsCSS,
879    switches::kEnableWebAnimationsSVG,
880    switches::kEnableWebMIDI,
881    switches::kEnableExperimentalCanvasFeatures,
882    switches::kEnableExperimentalWebSocket,
883    switches::kDomAutomationController,
884    switches::kEnableAccessibilityLogging,
885    switches::kEnableBeginFrameScheduling,
886    switches::kEnableBrowserInputController,
887    switches::kEnableBrowserPluginForAllViewTypes,
888    switches::kEnableDCHECK,
889    switches::kEnableDelegatedRenderer,
890    switches::kEnableEncryptedMedia,
891    switches::kDisableLegacyEncryptedMedia,
892    switches::kOverrideEncryptedMediaCanPlayType,
893    switches::kEnableExperimentalWebPlatformFeatures,
894    switches::kEnableFixedLayout,
895    switches::kEnableDeferredImageDecoding,
896    switches::kEnableGPUServiceLogging,
897    switches::kEnableGPUClientLogging,
898    switches::kEnableGpuClientTracing,
899    switches::kEnableGpuBenchmarking,
900    switches::kEnableMemoryBenchmarking,
901    switches::kEnableOverlayScrollbars,
902    switches::kEnableSkiaBenchmarking,
903    switches::kEnableLogging,
904    switches::kEnableSpeechSynthesis,
905    switches::kEnableTouchDragDrop,
906    switches::kEnableTouchEditing,
907#if defined(ENABLE_WEBRTC)
908    switches::kEnableWebRtcAecRecordings,
909    switches::kEnableWebRtcTcpServerSocket,
910    switches::kEnableWebRtcHWDecoding,
911    switches::kEnableWebRtcHWEncoding,
912#endif
913    switches::kDisableWebKitMediaSource,
914    switches::kEnableOverscrollNotifications,
915    switches::kEnableStrictSiteIsolation,
916    switches::kDisableFullScreen,
917    switches::kEnableNewDialogStyle,
918#if defined(ENABLE_PLUGINS)
919    switches::kEnablePepperTesting,
920    switches::kDisablePepper3d,
921#endif
922    switches::kEnablePreparsedJsCaching,
923    switches::kEnablePruneGpuCommandBuffers,
924    switches::kEnablePinch,
925    switches::kDisablePinch,
926#if defined(OS_MACOSX)
927    // Allow this to be set when invoking the browser and relayed along.
928    switches::kEnableSandboxLogging,
929#endif
930    switches::kEnableSoftwareCompositing,
931    switches::kEnableStatsTable,
932    switches::kEnableThreadedCompositing,
933    switches::kEnableCompositingForFixedPosition,
934    switches::kEnableHighDpiCompositingForFixedPosition,
935    switches::kDisableCompositingForFixedPosition,
936    switches::kEnableAcceleratedOverflowScroll,
937    switches::kEnableCompositingForTransition,
938    switches::kDisableCompositingForTransition,
939    switches::kEnableAcceleratedFixedRootBackground,
940    switches::kDisableAcceleratedFixedRootBackground,
941    switches::kDisableThreadedCompositing,
942    switches::kDisableTouchAdjustment,
943    switches::kDefaultTileWidth,
944    switches::kDefaultTileHeight,
945    switches::kMaxUntiledLayerWidth,
946    switches::kMaxUntiledLayerHeight,
947    switches::kEnableViewport,
948    switches::kEnableInbandTextTracks,
949    switches::kEnableOpusPlayback,
950    switches::kEnableVp8AlphaPlayback,
951    switches::kEnableEac3Playback,
952    switches::kForceDeviceScaleFactor,
953    switches::kFullMemoryCrashReport,
954#if defined(OS_ANDROID)
955    switches::kHideScrollbars,
956#endif
957#if !defined (GOOGLE_CHROME_BUILD)
958    // These are unsupported and not fully tested modes, so don't enable them
959    // for official Google Chrome builds.
960    switches::kInProcessPlugins,
961#endif  // GOOGLE_CHROME_BUILD
962    switches::kJavaScriptFlags,
963    switches::kLoggingLevel,
964    switches::kMemoryMetrics,
965#if defined(OS_ANDROID)
966    switches::kNetworkCountryIso,
967    switches::kDisableGestureRequirementForMediaPlayback,
968#endif
969#if defined(GOOGLE_TV)
970    switches::kUseExternalVideoSurfaceThresholdInPixels,
971#endif
972    switches::kNoReferrers,
973    switches::kNoSandbox,
974    switches::kEnableVtune,
975    switches::kPpapiInProcess,
976    switches::kRegisterPepperPlugins,
977    switches::kRendererAssertTest,
978#if defined(OS_POSIX)
979    switches::kChildCleanExit,
980#endif
981    switches::kRendererStartupDialog,
982    switches::kShowPaintRects,
983    switches::kSitePerProcess,
984    switches::kStatsCollectionController,
985    switches::kTestSandbox,
986    switches::kTouchEvents,
987    switches::kTraceStartup,
988    // This flag needs to be propagated to the renderer process for
989    // --in-process-webgl.
990    switches::kUseGL,
991    switches::kUseMobileUserAgent,
992    switches::kUserAgent,
993    switches::kV,
994    switches::kVideoThreads,
995    switches::kVModule,
996    switches::kWebCoreLogChannels,
997    switches::kEnableWebGLDraftExtensions,
998    switches::kEnableHTMLImports,
999    switches::kTraceToConsole,
1000    switches::kEnableDeviceMotion,
1001#if defined(OS_ANDROID)
1002    switches::kDisableDeviceMotion,
1003#endif
1004    // Please keep these in alphabetical order. Compositor switches here should
1005    // also be added to chrome/browser/chromeos/login/chrome_restart_request.cc.
1006    cc::switches::kBackgroundColorInsteadOfCheckerboard,
1007    cc::switches::kCompositeToMailbox,
1008    cc::switches::kDisableCompositedAntialiasing,
1009    cc::switches::kDisableImplSidePainting,
1010    cc::switches::kDisableThreadedAnimation,
1011    cc::switches::kEnableImplSidePainting,
1012    cc::switches::kEnablePartialSwap,
1013    cc::switches::kEnablePerTilePainting,
1014    cc::switches::kEnablePinchVirtualViewport,
1015    cc::switches::kEnableTopControlsPositionCalculation,
1016    cc::switches::kForceDirectLayerDrawing,
1017    cc::switches::kLowResolutionContentsScaleFactor,
1018    cc::switches::kMaxTilesForInterestArea,
1019    cc::switches::kMaxUnusedResourceMemoryUsagePercentage,
1020    cc::switches::kNumRasterThreads,
1021    cc::switches::kShowCompositedLayerBorders,
1022    cc::switches::kShowFPSCounter,
1023    cc::switches::kShowNonOccludingRects,
1024    cc::switches::kShowOccludingRects,
1025    cc::switches::kShowPropertyChangedRects,
1026    cc::switches::kShowReplicaScreenSpaceRects,
1027    cc::switches::kShowScreenSpaceRects,
1028    cc::switches::kShowSurfaceDamageRects,
1029    cc::switches::kSlowDownRasterScaleFactor,
1030    cc::switches::kStrictLayerPropertyChangeChecking,
1031    cc::switches::kTopControlsHeight,
1032    cc::switches::kTopControlsHideThreshold,
1033    cc::switches::kTopControlsShowThreshold,
1034    cc::switches::kTraceOverdraw,
1035    cc::switches::kUseMapImage,
1036  };
1037  renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames,
1038                                 arraysize(kSwitchNames));
1039
1040  // Disable databases in incognito mode.
1041  if (GetBrowserContext()->IsOffTheRecord() &&
1042      !browser_cmd.HasSwitch(switches::kDisableDatabases)) {
1043    renderer_cmd->AppendSwitch(switches::kDisableDatabases);
1044#if defined(OS_ANDROID)
1045    renderer_cmd->AppendSwitch(switches::kDisableMediaHistoryLogging);
1046#endif
1047  }
1048
1049  // Enforce the extra command line flags for impl-side painting.
1050  if (cc::switches::IsImplSidePaintingEnabled() &&
1051      !browser_cmd.HasSwitch(switches::kEnableDeferredImageDecoding))
1052    renderer_cmd->AppendSwitch(switches::kEnableDeferredImageDecoding);
1053}
1054
1055base::ProcessHandle RenderProcessHostImpl::GetHandle() const {
1056  if (run_renderer_in_process())
1057    return base::Process::Current().handle();
1058
1059  if (!child_process_launcher_.get() || child_process_launcher_->IsStarting())
1060    return base::kNullProcessHandle;
1061
1062  return child_process_launcher_->GetHandle();
1063}
1064
1065bool RenderProcessHostImpl::FastShutdownIfPossible() {
1066  if (run_renderer_in_process())
1067    return false;  // Single process mode never shutdown the renderer.
1068
1069  if (!GetContentClient()->browser()->IsFastShutdownPossible())
1070    return false;
1071
1072  if (!child_process_launcher_.get() ||
1073      child_process_launcher_->IsStarting() ||
1074      !GetHandle())
1075    return false;  // Render process hasn't started or is probably crashed.
1076
1077  // Test if there's an unload listener.
1078  // NOTE: It's possible that an onunload listener may be installed
1079  // while we're shutting down, so there's a small race here.  Given that
1080  // the window is small, it's unlikely that the web page has much
1081  // state that will be lost by not calling its unload handlers properly.
1082  if (!SuddenTerminationAllowed())
1083    return false;
1084
1085  ProcessDied(false /* already_dead */);
1086  fast_shutdown_started_ = true;
1087  return true;
1088}
1089
1090void RenderProcessHostImpl::DumpHandles() {
1091#if defined(OS_WIN)
1092  Send(new ChildProcessMsg_DumpHandles());
1093  return;
1094#endif
1095
1096  NOTIMPLEMENTED();
1097}
1098
1099// This is a platform specific function for mapping a transport DIB given its id
1100TransportDIB* RenderProcessHostImpl::MapTransportDIB(
1101    TransportDIB::Id dib_id) {
1102#if defined(OS_WIN)
1103  // On Windows we need to duplicate the handle from the remote process
1104  HANDLE section;
1105  DuplicateHandle(GetHandle(), dib_id.handle, GetCurrentProcess(), &section,
1106                  STANDARD_RIGHTS_REQUIRED | FILE_MAP_READ | FILE_MAP_WRITE,
1107                  FALSE, 0);
1108  return TransportDIB::Map(section);
1109#elif defined(TOOLKIT_GTK)
1110  return TransportDIB::Map(dib_id.shmkey);
1111#elif defined(OS_ANDROID)
1112  return TransportDIB::Map(dib_id);
1113#else
1114  // On POSIX, the browser allocates all DIBs and keeps a file descriptor around
1115  // for each.
1116  return widget_helper_->MapTransportDIB(dib_id);
1117#endif
1118}
1119
1120TransportDIB* RenderProcessHostImpl::GetTransportDIB(
1121    TransportDIB::Id dib_id) {
1122  if (!TransportDIB::is_valid_id(dib_id))
1123    return NULL;
1124
1125  const std::map<TransportDIB::Id, TransportDIB*>::iterator
1126      i = cached_dibs_.find(dib_id);
1127  if (i != cached_dibs_.end()) {
1128    cached_dibs_cleaner_.Reset();
1129    return i->second;
1130  }
1131
1132  TransportDIB* dib = MapTransportDIB(dib_id);
1133  if (!dib)
1134    return NULL;
1135
1136  if (cached_dibs_.size() >= MAX_MAPPED_TRANSPORT_DIBS) {
1137    // Clean a single entry from the cache
1138    std::map<TransportDIB::Id, TransportDIB*>::iterator smallest_iterator;
1139    size_t smallest_size = std::numeric_limits<size_t>::max();
1140
1141    for (std::map<TransportDIB::Id, TransportDIB*>::iterator
1142         i = cached_dibs_.begin(); i != cached_dibs_.end(); ++i) {
1143      if (i->second->size() <= smallest_size) {
1144        smallest_iterator = i;
1145        smallest_size = i->second->size();
1146      }
1147    }
1148
1149#if defined(TOOLKIT_GTK)
1150    smallest_iterator->second->Detach();
1151#else
1152    delete smallest_iterator->second;
1153#endif
1154    cached_dibs_.erase(smallest_iterator);
1155  }
1156
1157  cached_dibs_[dib_id] = dib;
1158  cached_dibs_cleaner_.Reset();
1159  return dib;
1160}
1161
1162void RenderProcessHostImpl::ClearTransportDIBCache() {
1163#if defined(TOOLKIT_GTK)
1164  std::map<TransportDIB::Id, TransportDIB*>::const_iterator dib =
1165      cached_dibs_.begin();
1166  for (; dib != cached_dibs_.end(); ++dib)
1167    dib->second->Detach();
1168#else
1169  STLDeleteContainerPairSecondPointers(
1170      cached_dibs_.begin(), cached_dibs_.end());
1171#endif
1172  cached_dibs_.clear();
1173}
1174
1175bool RenderProcessHostImpl::Send(IPC::Message* msg) {
1176  if (!channel_) {
1177    if (!is_initialized_) {
1178      queued_messages_.push(msg);
1179      return true;
1180    } else {
1181      delete msg;
1182      return false;
1183    }
1184  }
1185
1186  if (child_process_launcher_.get() && child_process_launcher_->IsStarting()) {
1187    queued_messages_.push(msg);
1188    return true;
1189  }
1190
1191  return channel_->Send(msg);
1192}
1193
1194bool RenderProcessHostImpl::OnMessageReceived(const IPC::Message& msg) {
1195  // If we're about to be deleted, or have initiated the fast shutdown sequence,
1196  // we ignore incoming messages.
1197
1198  if (deleting_soon_ || fast_shutdown_started_)
1199    return false;
1200
1201  mark_child_process_activity_time();
1202  if (msg.routing_id() == MSG_ROUTING_CONTROL) {
1203    // Dispatch control messages.
1204    bool msg_is_ok = true;
1205    IPC_BEGIN_MESSAGE_MAP_EX(RenderProcessHostImpl, msg, msg_is_ok)
1206      IPC_MESSAGE_HANDLER(ChildProcessHostMsg_ShutdownRequest,
1207                          OnShutdownRequest)
1208      IPC_MESSAGE_HANDLER(ChildProcessHostMsg_DumpHandlesDone,
1209                          OnDumpHandlesDone)
1210      IPC_MESSAGE_HANDLER(ViewHostMsg_SuddenTerminationChanged,
1211                          SuddenTerminationChanged)
1212      IPC_MESSAGE_HANDLER(ViewHostMsg_UserMetricsRecordAction,
1213                          OnUserMetricsRecordAction)
1214      IPC_MESSAGE_HANDLER(ViewHostMsg_SavedPageAsMHTML, OnSavedPageAsMHTML)
1215      // Adding single handlers for your service here is fine, but once your
1216      // service needs more than one handler, please extract them into a new
1217      // message filter and add that filter to CreateMessageFilters().
1218      IPC_MESSAGE_UNHANDLED_ERROR()
1219    IPC_END_MESSAGE_MAP_EX()
1220
1221    if (!msg_is_ok) {
1222      // The message had a handler, but its de-serialization failed.
1223      // We consider this a capital crime. Kill the renderer if we have one.
1224      LOG(ERROR) << "bad message " << msg.type() << " terminating renderer.";
1225      RecordAction(UserMetricsAction("BadMessageTerminate_BRPH"));
1226      ReceivedBadMessage();
1227    }
1228    return true;
1229  }
1230
1231  // Dispatch incoming messages to the appropriate IPC::Listener.
1232  IPC::Listener* listener = listeners_.Lookup(msg.routing_id());
1233  if (!listener) {
1234    if (msg.is_sync()) {
1235      // The listener has gone away, so we must respond or else the caller will
1236      // hang waiting for a reply.
1237      IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg);
1238      reply->set_reply_error();
1239      Send(reply);
1240    }
1241
1242    // If this is a SwapBuffers, we need to ack it if we're not going to handle
1243    // it so that the GPU process doesn't get stuck in unscheduled state.
1244    bool msg_is_ok = true;
1245    IPC_BEGIN_MESSAGE_MAP_EX(RenderProcessHostImpl, msg, msg_is_ok)
1246      IPC_MESSAGE_HANDLER(ViewHostMsg_CompositorSurfaceBuffersSwapped,
1247                          OnCompositorSurfaceBuffersSwappedNoHost)
1248    IPC_END_MESSAGE_MAP_EX()
1249    return true;
1250  }
1251  return listener->OnMessageReceived(msg);
1252}
1253
1254void RenderProcessHostImpl::OnChannelConnected(int32 peer_pid) {
1255#if defined(IPC_MESSAGE_LOG_ENABLED)
1256  Send(new ChildProcessMsg_SetIPCLoggingEnabled(
1257      IPC::Logging::GetInstance()->Enabled()));
1258#endif
1259
1260  tracked_objects::ThreadData::Status status =
1261      tracked_objects::ThreadData::status();
1262  Send(new ChildProcessMsg_SetProfilerStatus(status));
1263}
1264
1265void RenderProcessHostImpl::OnChannelError() {
1266  ProcessDied(true /* already_dead */);
1267}
1268
1269BrowserContext* RenderProcessHostImpl::GetBrowserContext() const {
1270  return browser_context_;
1271}
1272
1273bool RenderProcessHostImpl::InSameStoragePartition(
1274    StoragePartition* partition) const {
1275  return storage_partition_impl_ == partition;
1276}
1277
1278int RenderProcessHostImpl::GetID() const {
1279  return id_;
1280}
1281
1282bool RenderProcessHostImpl::HasConnection() const {
1283  return channel_.get() != NULL;
1284}
1285
1286void RenderProcessHostImpl::SetIgnoreInputEvents(bool ignore_input_events) {
1287  ignore_input_events_ = ignore_input_events;
1288}
1289
1290bool RenderProcessHostImpl::IgnoreInputEvents() const {
1291  return ignore_input_events_;
1292}
1293
1294void RenderProcessHostImpl::Cleanup() {
1295  // When no other owners of this object, we can delete ourselves
1296  if (listeners_.IsEmpty()) {
1297    DCHECK_EQ(0, pending_views_);
1298    NotificationService::current()->Notify(
1299        NOTIFICATION_RENDERER_PROCESS_TERMINATED,
1300        Source<RenderProcessHost>(this),
1301        NotificationService::NoDetails());
1302
1303    base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
1304    deleting_soon_ = true;
1305    // It's important not to wait for the DeleteTask to delete the channel
1306    // proxy. Kill it off now. That way, in case the profile is going away, the
1307    // rest of the objects attached to this RenderProcessHost start going
1308    // away first, since deleting the channel proxy will post a
1309    // OnChannelClosed() to IPC::ChannelProxy::Context on the IO thread.
1310    channel_.reset();
1311    gpu_message_filter_ = NULL;
1312
1313    // Remove ourself from the list of renderer processes so that we can't be
1314    // reused in between now and when the Delete task runs.
1315    UnregisterHost(GetID());
1316  }
1317}
1318
1319void RenderProcessHostImpl::AddPendingView() {
1320  pending_views_++;
1321}
1322
1323void RenderProcessHostImpl::RemovePendingView() {
1324  DCHECK(pending_views_);
1325  pending_views_--;
1326}
1327
1328void RenderProcessHostImpl::SetSuddenTerminationAllowed(bool enabled) {
1329  sudden_termination_allowed_ = enabled;
1330}
1331
1332bool RenderProcessHostImpl::SuddenTerminationAllowed() const {
1333  return sudden_termination_allowed_;
1334}
1335
1336base::TimeDelta RenderProcessHostImpl::GetChildProcessIdleTime() const {
1337  return base::TimeTicks::Now() - child_process_activity_time_;
1338}
1339
1340void RenderProcessHostImpl::SurfaceUpdated(int32 surface_id) {
1341  if (!gpu_message_filter_)
1342    return;
1343  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
1344      &GpuMessageFilter::SurfaceUpdated,
1345      gpu_message_filter_,
1346      surface_id));
1347}
1348
1349void RenderProcessHostImpl::ResumeRequestsForView(int route_id) {
1350  widget_helper_->ResumeRequestsForView(route_id);
1351}
1352
1353IPC::ChannelProxy* RenderProcessHostImpl::GetChannel() {
1354  return channel_.get();
1355}
1356
1357bool RenderProcessHostImpl::FastShutdownForPageCount(size_t count) {
1358  if (static_cast<size_t>(GetActiveViewCount()) == count)
1359    return FastShutdownIfPossible();
1360  return false;
1361}
1362
1363bool RenderProcessHostImpl::FastShutdownStarted() const {
1364  return fast_shutdown_started_;
1365}
1366
1367// static
1368void RenderProcessHostImpl::RegisterHost(int host_id, RenderProcessHost* host) {
1369  g_all_hosts.Get().AddWithID(host, host_id);
1370}
1371
1372// static
1373void RenderProcessHostImpl::UnregisterHost(int host_id) {
1374  RenderProcessHost* host = g_all_hosts.Get().Lookup(host_id);
1375  if (!host)
1376    return;
1377
1378  g_all_hosts.Get().Remove(host_id);
1379
1380  // Look up the map of site to process for the given browser_context,
1381  // in case we need to remove this process from it.  It will be registered
1382  // under any sites it rendered that use process-per-site mode.
1383  SiteProcessMap* map =
1384      GetSiteProcessMapForBrowserContext(host->GetBrowserContext());
1385  map->RemoveProcess(host);
1386}
1387
1388// static
1389bool RenderProcessHostImpl::IsSuitableHost(
1390    RenderProcessHost* host,
1391    BrowserContext* browser_context,
1392    const GURL& site_url) {
1393  if (run_renderer_in_process())
1394    return true;
1395
1396  if (host->GetBrowserContext() != browser_context)
1397    return false;
1398
1399  // Check whether the given host and the intended site_url will be using the
1400  // same StoragePartition, since a RenderProcessHost can only support a single
1401  // StoragePartition.  This is relevant for packaged apps, browser tags, and
1402  // isolated sites.
1403  StoragePartition* dest_partition =
1404      BrowserContext::GetStoragePartitionForSite(browser_context, site_url);
1405  if (!host->InSameStoragePartition(dest_partition))
1406    return false;
1407
1408  // All URLs are suitable if this is associated with a guest renderer process.
1409  // TODO(fsamuel, creis): Further validation is needed to ensure that only
1410  // normal web URLs are permitted in guest processes. We need to investigate
1411  // where this validation should happen.
1412  if (host->IsGuest())
1413    return true;
1414
1415  if (!host->IsGuest() && site_url.SchemeIs(chrome::kGuestScheme))
1416    return false;
1417
1418  if (ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1419          host->GetID()) !=
1420      WebUIControllerFactoryRegistry::GetInstance()->UseWebUIBindingsForURL(
1421          browser_context, site_url)) {
1422    return false;
1423  }
1424
1425  return GetContentClient()->browser()->IsSuitableHost(host, site_url);
1426}
1427
1428// static
1429bool RenderProcessHost::run_renderer_in_process() {
1430  return g_run_renderer_in_process_;
1431}
1432
1433// static
1434void RenderProcessHost::SetRunRendererInProcess(bool value) {
1435  g_run_renderer_in_process_ = value;
1436
1437  CommandLine* command_line = CommandLine::ForCurrentProcess();
1438  if (value && !command_line->HasSwitch(switches::kLang)) {
1439    // Modify the current process' command line to include the browser locale,
1440    // as the renderer expects this flag to be set.
1441    const std::string locale =
1442        GetContentClient()->browser()->GetApplicationLocale();
1443    command_line->AppendSwitchASCII(switches::kLang, locale);
1444  }
1445}
1446
1447RenderProcessHost::iterator RenderProcessHost::AllHostsIterator() {
1448  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1449  return iterator(g_all_hosts.Pointer());
1450}
1451
1452// static
1453RenderProcessHost* RenderProcessHost::FromID(int render_process_id) {
1454  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1455  return g_all_hosts.Get().Lookup(render_process_id);
1456}
1457
1458// static
1459bool RenderProcessHost::ShouldTryToUseExistingProcessHost(
1460    BrowserContext* browser_context, const GURL& url) {
1461  // Experimental:
1462  // If --enable-strict-site-isolation or --site-per-process is enabled, do not
1463  // try to reuse renderer processes when over the limit.  (We could allow pages
1464  // from the same site to share, if we knew what the given process was
1465  // dedicated to.  Allowing no sharing is simpler for now.)  This may cause
1466  // resource exhaustion issues if too many sites are open at once.
1467  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1468  if (command_line.HasSwitch(switches::kEnableStrictSiteIsolation) ||
1469      command_line.HasSwitch(switches::kSitePerProcess))
1470    return false;
1471
1472  if (run_renderer_in_process())
1473    return true;
1474
1475  // NOTE: Sometimes it's necessary to create more render processes than
1476  //       GetMaxRendererProcessCount(), for instance when we want to create
1477  //       a renderer process for a browser context that has no existing
1478  //       renderers. This is OK in moderation, since the
1479  //       GetMaxRendererProcessCount() is conservative.
1480  if (g_all_hosts.Get().size() >= GetMaxRendererProcessCount())
1481    return true;
1482
1483  return GetContentClient()->browser()->
1484      ShouldTryToUseExistingProcessHost(browser_context, url);
1485}
1486
1487// static
1488RenderProcessHost* RenderProcessHost::GetExistingProcessHost(
1489    BrowserContext* browser_context,
1490    const GURL& site_url) {
1491  // First figure out which existing renderers we can use.
1492  std::vector<RenderProcessHost*> suitable_renderers;
1493  suitable_renderers.reserve(g_all_hosts.Get().size());
1494
1495  iterator iter(AllHostsIterator());
1496  while (!iter.IsAtEnd()) {
1497    if (RenderProcessHostImpl::IsSuitableHost(
1498            iter.GetCurrentValue(),
1499            browser_context, site_url))
1500      suitable_renderers.push_back(iter.GetCurrentValue());
1501
1502    iter.Advance();
1503  }
1504
1505  // Now pick a random suitable renderer, if we have any.
1506  if (!suitable_renderers.empty()) {
1507    int suitable_count = static_cast<int>(suitable_renderers.size());
1508    int random_index = base::RandInt(0, suitable_count - 1);
1509    return suitable_renderers[random_index];
1510  }
1511
1512  return NULL;
1513}
1514
1515// static
1516bool RenderProcessHost::ShouldUseProcessPerSite(
1517    BrowserContext* browser_context,
1518    const GURL& url) {
1519  // Returns true if we should use the process-per-site model.  This will be
1520  // the case if the --process-per-site switch is specified, or in
1521  // process-per-site-instance for particular sites (e.g., WebUI).
1522  // Note that --single-process is handled in ShouldTryToUseExistingProcessHost.
1523  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1524  if (command_line.HasSwitch(switches::kProcessPerSite))
1525    return true;
1526
1527  // We want to consolidate particular sites like WebUI even when we are using
1528  // the process-per-tab or process-per-site-instance models.
1529  // Note: DevTools pages have WebUI type but should not reuse the same host.
1530  if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL(
1531          browser_context, url) &&
1532      !url.SchemeIs(chrome::kChromeDevToolsScheme)) {
1533    return true;
1534  }
1535
1536  // Otherwise let the content client decide, defaulting to false.
1537  return GetContentClient()->browser()->ShouldUseProcessPerSite(browser_context,
1538                                                                url);
1539}
1540
1541// static
1542RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSite(
1543    BrowserContext* browser_context,
1544    const GURL& url) {
1545  // Look up the map of site to process for the given browser_context.
1546  SiteProcessMap* map =
1547      GetSiteProcessMapForBrowserContext(browser_context);
1548
1549  // See if we have an existing process with appropriate bindings for this site.
1550  // If not, the caller should create a new process and register it.
1551  std::string site = SiteInstance::GetSiteForURL(browser_context, url)
1552      .possibly_invalid_spec();
1553  RenderProcessHost* host = map->FindProcess(site);
1554  if (host && !IsSuitableHost(host, browser_context, url)) {
1555    // The registered process does not have an appropriate set of bindings for
1556    // the url.  Remove it from the map so we can register a better one.
1557    RecordAction(UserMetricsAction("BindingsMismatch_GetProcessHostPerSite"));
1558    map->RemoveProcess(host);
1559    host = NULL;
1560  }
1561
1562  return host;
1563}
1564
1565void RenderProcessHostImpl::RegisterProcessHostForSite(
1566    BrowserContext* browser_context,
1567    RenderProcessHost* process,
1568    const GURL& url) {
1569  // Look up the map of site to process for the given browser_context.
1570  SiteProcessMap* map =
1571      GetSiteProcessMapForBrowserContext(browser_context);
1572
1573  // Only register valid, non-empty sites.  Empty or invalid sites will not
1574  // use process-per-site mode.  We cannot check whether the process has
1575  // appropriate bindings here, because the bindings have not yet been granted.
1576  std::string site = SiteInstance::GetSiteForURL(browser_context, url)
1577      .possibly_invalid_spec();
1578  if (!site.empty())
1579    map->RegisterProcess(site, process);
1580}
1581
1582void RenderProcessHostImpl::ProcessDied(bool already_dead) {
1583  // Our child process has died.  If we didn't expect it, it's a crash.
1584  // In any case, we need to let everyone know it's gone.
1585  // The OnChannelError notification can fire multiple times due to nested sync
1586  // calls to a renderer. If we don't have a valid channel here it means we
1587  // already handled the error.
1588
1589  // child_process_launcher_ can be NULL in single process mode or if fast
1590  // termination happened.
1591  int exit_code = 0;
1592  base::TerminationStatus status =
1593      child_process_launcher_.get() ?
1594      child_process_launcher_->GetChildTerminationStatus(already_dead,
1595                                                         &exit_code) :
1596      base::TERMINATION_STATUS_NORMAL_TERMINATION;
1597
1598  RendererClosedDetails details(GetHandle(), status, exit_code);
1599  NotificationService::current()->Notify(
1600      NOTIFICATION_RENDERER_PROCESS_CLOSED,
1601      Source<RenderProcessHost>(this),
1602      Details<RendererClosedDetails>(&details));
1603
1604  child_process_launcher_.reset();
1605  channel_.reset();
1606  gpu_message_filter_ = NULL;
1607
1608  IDMap<IPC::Listener>::iterator iter(&listeners_);
1609  while (!iter.IsAtEnd()) {
1610    iter.GetCurrentValue()->OnMessageReceived(
1611        ViewHostMsg_RenderProcessGone(iter.GetCurrentKey(),
1612                                      static_cast<int>(status),
1613                                      exit_code));
1614    iter.Advance();
1615  }
1616
1617  ClearTransportDIBCache();
1618
1619  // this object is not deleted at this point and may be reused later.
1620  // TODO(darin): clean this up
1621}
1622
1623int RenderProcessHostImpl::GetActiveViewCount() {
1624  int num_active_views = 0;
1625  RenderWidgetHost::List widgets = RenderWidgetHost::GetRenderWidgetHosts();
1626  for (size_t i = 0; i < widgets.size(); ++i) {
1627    // Count only RenderWidgetHosts in this process.
1628    if (widgets[i]->GetProcess()->GetID() == GetID())
1629      num_active_views++;
1630  }
1631  return num_active_views;
1632}
1633
1634// Frame subscription API for this class is for accelerated composited path
1635// only. These calls are redirected to GpuMessageFilter.
1636void RenderProcessHostImpl::BeginFrameSubscription(
1637    int route_id,
1638    scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
1639  if (!gpu_message_filter_)
1640    return;
1641  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
1642      &GpuMessageFilter::BeginFrameSubscription,
1643      gpu_message_filter_,
1644      route_id, base::Passed(&subscriber)));
1645}
1646
1647void RenderProcessHostImpl::EndFrameSubscription(int route_id) {
1648  if (!gpu_message_filter_)
1649    return;
1650  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
1651      &GpuMessageFilter::EndFrameSubscription,
1652      gpu_message_filter_,
1653      route_id));
1654}
1655
1656void RenderProcessHostImpl::OnShutdownRequest() {
1657  // Don't shut down if there are active RenderViews, or if there are pending
1658  // RenderViews being swapped back in.
1659  // In single process mode, we never shutdown the renderer.
1660  int num_active_views = GetActiveViewCount();
1661  if (pending_views_ || num_active_views > 0 || run_renderer_in_process())
1662    return;
1663
1664  // Notify any contents that might have swapped out renderers from this
1665  // process. They should not attempt to swap them back in.
1666  NotificationService::current()->Notify(
1667      NOTIFICATION_RENDERER_PROCESS_CLOSING,
1668      Source<RenderProcessHost>(this),
1669      NotificationService::NoDetails());
1670
1671  Send(new ChildProcessMsg_Shutdown());
1672}
1673
1674void RenderProcessHostImpl::SuddenTerminationChanged(bool enabled) {
1675  SetSuddenTerminationAllowed(enabled);
1676}
1677
1678void RenderProcessHostImpl::OnDumpHandlesDone() {
1679  Cleanup();
1680}
1681
1682void RenderProcessHostImpl::SetBackgrounded(bool backgrounded) {
1683  // Note: we always set the backgrounded_ value.  If the process is NULL
1684  // (and hence hasn't been created yet), we will set the process priority
1685  // later when we create the process.
1686  backgrounded_ = backgrounded;
1687  if (!child_process_launcher_.get() || child_process_launcher_->IsStarting())
1688    return;
1689
1690#if defined(OS_WIN)
1691  // The cbstext.dll loads as a global GetMessage hook in the browser process
1692  // and intercepts/unintercepts the kernel32 API SetPriorityClass in a
1693  // background thread. If the UI thread invokes this API just when it is
1694  // intercepted the stack is messed up on return from the interceptor
1695  // which causes random crashes in the browser process. Our hack for now
1696  // is to not invoke the SetPriorityClass API if the dll is loaded.
1697  if (GetModuleHandle(L"cbstext.dll"))
1698    return;
1699#endif  // OS_WIN
1700
1701  child_process_launcher_->SetProcessBackgrounded(backgrounded);
1702}
1703
1704void RenderProcessHostImpl::OnProcessLaunched() {
1705  // No point doing anything, since this object will be destructed soon.  We
1706  // especially don't want to send the RENDERER_PROCESS_CREATED notification,
1707  // since some clients might expect a RENDERER_PROCESS_TERMINATED afterwards to
1708  // properly cleanup.
1709  if (deleting_soon_)
1710    return;
1711
1712  if (child_process_launcher_) {
1713    if (!child_process_launcher_->GetHandle()) {
1714      OnChannelError();
1715      return;
1716    }
1717
1718    child_process_launcher_->SetProcessBackgrounded(backgrounded_);
1719  }
1720
1721  // NOTE: This needs to be before sending queued messages because
1722  // ExtensionService uses this notification to initialize the renderer process
1723  // with state that must be there before any JavaScript executes.
1724  //
1725  // The queued messages contain such things as "navigate". If this notification
1726  // was after, we can end up executing JavaScript before the initialization
1727  // happens.
1728  NotificationService::current()->Notify(
1729      NOTIFICATION_RENDERER_PROCESS_CREATED,
1730      Source<RenderProcessHost>(this),
1731      NotificationService::NoDetails());
1732
1733  while (!queued_messages_.empty()) {
1734    Send(queued_messages_.front());
1735    queued_messages_.pop();
1736  }
1737}
1738
1739void RenderProcessHostImpl::OnUserMetricsRecordAction(
1740    const std::string& action) {
1741  RecordComputedAction(action);
1742}
1743
1744void RenderProcessHostImpl::OnSavedPageAsMHTML(int job_id, int64 data_size) {
1745  MHTMLGenerationManager::GetInstance()->MHTMLGenerated(job_id, data_size);
1746}
1747
1748void RenderProcessHostImpl::OnCompositorSurfaceBuffersSwappedNoHost(
1749      const ViewHostMsg_CompositorSurfaceBuffersSwapped_Params& params) {
1750  TRACE_EVENT0("renderer_host",
1751               "RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwappedNoHost");
1752  AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
1753  ack_params.sync_point = 0;
1754  RenderWidgetHostImpl::AcknowledgeBufferPresent(params.route_id,
1755                                                 params.gpu_process_host_id,
1756                                                 ack_params);
1757}
1758
1759void RenderProcessHostImpl::OnGpuSwitching() {
1760  // We are updating all widgets including swapped out ones.
1761  RenderWidgetHost::List widgets =
1762      RenderWidgetHostImpl::GetAllRenderWidgetHosts();
1763  for (size_t i = 0; i < widgets.size(); ++i) {
1764    if (!widgets[i]->IsRenderView())
1765      continue;
1766
1767    // Skip widgets in other processes.
1768    if (widgets[i]->GetProcess()->GetID() != GetID())
1769      continue;
1770
1771    RenderViewHost* rvh = RenderViewHost::From(widgets[i]);
1772    rvh->UpdateWebkitPreferences(rvh->GetWebkitPreferences());
1773  }
1774}
1775
1776}  // namespace content
1777