render_process_host_impl.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
27242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// Use of this source code is governed by a BSD-style license that can be
35267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)// found in the LICENSE file.
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Represents the browser side of the browser <--> renderer communication
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// channel. There will be one RenderProcessHost per renderer process.
75267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "content/browser/renderer_host/render_process_host_impl.h"
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <algorithm>
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <limits>
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <vector>
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if defined(OS_POSIX)
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <utility>  // for pair<>
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/base_switches.h"
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/bind.h"
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/bind_helpers.h"
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/callback.h"
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/command_line.h"
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/debug/trace_event.h"
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/lazy_instance.h"
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/logging.h"
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/metrics/field_trial.h"
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/metrics/histogram.h"
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/path_service.h"
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/platform_file.h"
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/process_util.h"
317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "base/rand_util.h"
327242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "base/stl_util.h"
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/strings/string_util.h"
34c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "base/supports_user_data.h"
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/sys_info.h"
367242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "base/threading/thread.h"
377242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "base/threading/thread_restrictions.h"
387242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "base/tracked_objects.h"
397242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "cc/base/switches.h"
407242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "content/browser/appcache/appcache_dispatcher_host.h"
417242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "content/browser/appcache/chrome_appcache_service.h"
427242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "content/browser/browser_main.h"
435267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "content/browser/browser_main_loop.h"
445267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "content/browser/browser_plugin/browser_plugin_geolocation_permission_context.h"
45926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#include "content/browser/browser_plugin/browser_plugin_message_filter.h"
467242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "content/browser/child_process_security_policy_impl.h"
477242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "content/browser/device_orientation/orientation_message_filter.h"
487242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "content/browser/dom_storage/dom_storage_context_impl.h"
497242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "content/browser/dom_storage/dom_storage_message_filter.h"
507242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "content/browser/download/mhtml_generation_manager.h"
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "content/browser/fileapi/chrome_blob_storage_context.h"
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "content/browser/fileapi/fileapi_message_filter.h"
537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "content/browser/geolocation/geolocation_dispatcher_host.h"
547242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "content/browser/gpu/gpu_data_manager_impl.h"
557242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "content/browser/gpu/gpu_process_host.h"
567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "content/browser/gpu/shader_disk_cache.h"
577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "content/browser/histogram_message_filter.h"
587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "content/browser/hyphenator/hyphenator_message_filter.h"
597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "content/browser/indexed_db/indexed_db_context_impl.h"
607242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "content/browser/loader/resource_message_filter.h"
627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "content/browser/loader/resource_scheduler_filter.h"
63c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "content/browser/media/media_internals.h"
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "content/browser/mime_registry_message_filter.h"
657242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "content/browser/plugin_service_impl.h"
66#include "content/browser/profiler_message_filter.h"
67#include "content/browser/renderer_host/clipboard_message_filter.h"
68#include "content/browser/renderer_host/database_message_filter.h"
69#include "content/browser/renderer_host/file_utilities_message_filter.h"
70#include "content/browser/renderer_host/gamepad_browser_message_filter.h"
71#include "content/browser/renderer_host/gpu_message_filter.h"
72#include "content/browser/renderer_host/media/audio_input_renderer_host.h"
73#include "content/browser/renderer_host/media/audio_mirroring_manager.h"
74#include "content/browser/renderer_host/media/audio_renderer_host.h"
75#include "content/browser/renderer_host/media/media_stream_dispatcher_host.h"
76#include "content/browser/renderer_host/media/midi_host.h"
77#include "content/browser/renderer_host/media/peer_connection_tracker_host.h"
78#include "content/browser/renderer_host/media/video_capture_host.h"
79#include "content/browser/renderer_host/memory_benchmark_message_filter.h"
80#include "content/browser/renderer_host/p2p/socket_dispatcher_host.h"
81#include "content/browser/renderer_host/pepper/pepper_message_filter.h"
82#include "content/browser/renderer_host/pepper/pepper_renderer_connection.h"
83#include "content/browser/renderer_host/quota_dispatcher_host.h"
84#include "content/browser/renderer_host/render_message_filter.h"
85#include "content/browser/renderer_host/render_view_host_delegate.h"
86#include "content/browser/renderer_host/render_view_host_impl.h"
87#include "content/browser/renderer_host/render_widget_helper.h"
88#include "content/browser/renderer_host/socket_stream_dispatcher_host.h"
89#include "content/browser/renderer_host/text_input_client_message_filter.h"
90#include "content/browser/resolve_proxy_msg_helper.h"
91#include "content/browser/speech/input_tag_speech_dispatcher_host.h"
92#include "content/browser/speech/speech_recognition_dispatcher_host.h"
93#include "content/browser/storage_partition_impl.h"
94#include "content/browser/tracing/trace_message_filter.h"
95#include "content/browser/webui/web_ui_controller_factory_registry.h"
96#include "content/browser/worker_host/worker_message_filter.h"
97#include "content/browser/worker_host/worker_storage_partition.h"
98#include "content/common/child_process_host_impl.h"
99#include "content/common/child_process_messages.h"
100#include "content/common/gpu/gpu_messages.h"
101#include "content/common/resource_messages.h"
102#include "content/common/view_messages.h"
103#include "content/port/browser/render_widget_host_view_frame_subscriber.h"
104#include "content/public/browser/browser_context.h"
105#include "content/public/browser/content_browser_client.h"
106#include "content/public/browser/notification_service.h"
107#include "content/public/browser/notification_types.h"
108#include "content/public/browser/render_process_host_factory.h"
109#include "content/public/browser/render_widget_host.h"
110#include "content/public/browser/resource_context.h"
111#include "content/public/browser/user_metrics.h"
112#include "content/public/common/content_constants.h"
113#include "content/public/common/content_switches.h"
114#include "content/public/common/process_type.h"
115#include "content/public/common/result_codes.h"
116#include "content/public/common/url_constants.h"
117#include "content/renderer/render_process_impl.h"
118#include "content/renderer/render_thread_impl.h"
119#include "gpu/command_buffer/service/gpu_switches.h"
120#include "ipc/ipc_channel.h"
121#include "ipc/ipc_logging.h"
122#include "ipc/ipc_platform_file.h"
123#include "ipc/ipc_switches.h"
124#include "media/base/media_switches.h"
125#include "net/url_request/url_request_context_getter.h"
126#include "ppapi/shared_impl/ppapi_switches.h"
127#include "ui/base/ui_base_switches.h"
128#include "ui/gl/gl_switches.h"
129#include "webkit/browser/fileapi/sandbox_mount_point_provider.h"
130#include "webkit/glue/resource_type.h"
131#include "webkit/plugins/plugin_switches.h"
132
133#if defined(OS_WIN)
134#include "base/win/scoped_com_initializer.h"
135#include "content/common/font_cache_dispatcher_win.h"
136#include "content/common/sandbox_win.h"
137#include "content/public/common/sandboxed_process_launcher_delegate.h"
138#endif
139
140#if defined(ENABLE_WEBRTC)
141#include "content/browser/renderer_host/media/webrtc_identity_service_host.h"
142#endif
143
144#include "third_party/skia/include/core/SkBitmap.h"
145
146extern bool g_exited_main_message_loop;
147
148static const char* kSiteProcessMapKeyName = "content_site_process_map";
149
150namespace content {
151namespace {
152
153base::MessageLoop* g_in_process_thread;
154
155void CacheShaderInfo(int32 id, base::FilePath path) {
156  ShaderCacheFactory::GetInstance()->SetCacheInfo(id, path);
157}
158
159void RemoveShaderInfo(int32 id) {
160  ShaderCacheFactory::GetInstance()->RemoveCacheInfo(id);
161}
162
163}  // namespace
164
165// This class creates the IO thread for the renderer when running in
166// single-process mode.  It's not used in multi-process mode.
167class RendererMainThread : public base::Thread {
168 public:
169  explicit RendererMainThread(const std::string& channel_id)
170      : Thread("Chrome_InProcRendererThread"),
171        channel_id_(channel_id) {
172  }
173
174  virtual ~RendererMainThread() {
175    Stop();
176  }
177
178 protected:
179  virtual void Init() OVERRIDE {
180    render_process_.reset(new RenderProcessImpl());
181    new RenderThreadImpl(channel_id_);
182    g_in_process_thread = message_loop();
183  }
184
185  virtual void CleanUp() OVERRIDE {
186    g_in_process_thread = NULL;
187    render_process_.reset();
188
189    // It's a little lame to manually set this flag.  But the single process
190    // RendererThread will receive the WM_QUIT.  We don't need to assert on
191    // this thread, so just force the flag manually.
192    // If we want to avoid this, we could create the InProcRendererThread
193    // directly with _beginthreadex() rather than using the Thread class.
194    // We used to set this flag in the Init function above. However there
195    // other threads like WebThread which are created by this thread
196    // which resets this flag. Please see Thread::StartWithOptions. Setting
197    // this flag to true in Cleanup works around these problems.
198    SetThreadWasQuitProperly(true);
199  }
200
201 private:
202  std::string channel_id_;
203  scoped_ptr<RenderProcess> render_process_;
204
205  DISALLOW_COPY_AND_ASSIGN(RendererMainThread);
206};
207
208namespace {
209
210// Helper class that we pass to ResourceMessageFilter so that it can find the
211// right net::URLRequestContext for a request.
212class RendererURLRequestContextSelector
213    : public ResourceMessageFilter::URLRequestContextSelector {
214 public:
215  RendererURLRequestContextSelector(BrowserContext* browser_context,
216                                    int render_child_id)
217      : request_context_(browser_context->GetRequestContextForRenderProcess(
218                             render_child_id)),
219        media_request_context_(
220            browser_context->GetMediaRequestContextForRenderProcess(
221                render_child_id)) {
222  }
223
224  virtual net::URLRequestContext* GetRequestContext(
225      ResourceType::Type resource_type) OVERRIDE {
226    net::URLRequestContextGetter* request_context = request_context_.get();
227    // If the request has resource type of ResourceType::MEDIA, we use a request
228    // context specific to media for handling it because these resources have
229    // specific needs for caching.
230    if (resource_type == ResourceType::MEDIA)
231      request_context = media_request_context_.get();
232    return request_context->GetURLRequestContext();
233  }
234
235 private:
236  virtual ~RendererURLRequestContextSelector() {}
237
238  scoped_refptr<net::URLRequestContextGetter> request_context_;
239  scoped_refptr<net::URLRequestContextGetter> media_request_context_;
240};
241
242// the global list of all renderer processes
243base::LazyInstance<IDMap<RenderProcessHost> >::Leaky
244    g_all_hosts = LAZY_INSTANCE_INITIALIZER;
245
246base::LazyInstance<scoped_refptr<BrowserPluginGeolocationPermissionContext> >
247    g_browser_plugin_geolocation_context = LAZY_INSTANCE_INITIALIZER;
248
249// Map of site to process, to ensure we only have one RenderProcessHost per
250// site in process-per-site mode.  Each map is specific to a BrowserContext.
251class SiteProcessMap : public base::SupportsUserData::Data {
252 public:
253  typedef base::hash_map<std::string, RenderProcessHost*> SiteToProcessMap;
254  SiteProcessMap() {}
255
256  void RegisterProcess(const std::string& site, RenderProcessHost* process) {
257    map_[site] = process;
258  }
259
260  RenderProcessHost* FindProcess(const std::string& site) {
261    SiteToProcessMap::iterator i = map_.find(site);
262    if (i != map_.end())
263      return i->second;
264    return NULL;
265  }
266
267  void RemoveProcess(RenderProcessHost* host) {
268    // Find all instances of this process in the map, then separately remove
269    // them.
270    std::set<std::string> sites;
271    for (SiteToProcessMap::const_iterator i = map_.begin();
272         i != map_.end();
273         i++) {
274      if (i->second == host)
275        sites.insert(i->first);
276    }
277    for (std::set<std::string>::iterator i = sites.begin();
278         i != sites.end();
279         i++) {
280      SiteToProcessMap::iterator iter = map_.find(*i);
281      if (iter != map_.end()) {
282        DCHECK_EQ(iter->second, host);
283        map_.erase(iter);
284      }
285    }
286  }
287
288 private:
289  SiteToProcessMap map_;
290};
291
292// Find the SiteProcessMap specific to the given context.
293SiteProcessMap* GetSiteProcessMapForBrowserContext(BrowserContext* context) {
294  DCHECK(context);
295  SiteProcessMap* map = static_cast<SiteProcessMap*>(
296      context->GetUserData(kSiteProcessMapKeyName));
297  if (!map) {
298    map = new SiteProcessMap();
299    context->SetUserData(kSiteProcessMapKeyName, map);
300  }
301  return map;
302}
303
304#if defined(OS_WIN)
305// NOTE: changes to this class need to be reviewed by the security team.
306class RendererSandboxedProcessLauncherDelegate
307    : public content::SandboxedProcessLauncherDelegate {
308 public:
309  RendererSandboxedProcessLauncherDelegate() {}
310  virtual ~RendererSandboxedProcessLauncherDelegate() {}
311
312  virtual void ShouldSandbox(bool* in_sandbox) OVERRIDE {
313#if !defined (GOOGLE_CHROME_BUILD)
314    if (CommandLine::ForCurrentProcess()->HasSwitch(
315        switches::kInProcessPlugins)) {
316      *in_sandbox = false;
317    }
318#endif
319  }
320
321  virtual void PreSpawnTarget(sandbox::TargetPolicy* policy,
322                              bool* success) {
323    AddBaseHandleClosePolicy(policy);
324    GetContentClient()->browser()->PreSpawnRenderer(policy, success);
325  }
326};
327#endif  // OS_WIN
328
329}  // namespace
330
331// Stores the maximum number of renderer processes the content module can
332// create.
333static size_t g_max_renderer_count_override = 0;
334
335// static
336size_t RenderProcessHost::GetMaxRendererProcessCount() {
337  if (g_max_renderer_count_override)
338    return g_max_renderer_count_override;
339
340  // Defines the maximum number of renderer processes according to the
341  // amount of installed memory as reported by the OS. The calculation
342  // assumes that you want the renderers to use half of the installed
343  // RAM and assuming that each WebContents uses ~40MB.
344  // If you modify this assumption, you need to adjust the
345  // ThirtyFourTabs test to match the expected number of processes.
346  //
347  // With the given amounts of installed memory below on a 32-bit CPU,
348  // the maximum renderer count will roughly be as follows:
349  //
350  //   128 MB -> 3
351  //   512 MB -> 6
352  //  1024 MB -> 12
353  //  4096 MB -> 51
354  // 16384 MB -> 82 (kMaxRendererProcessCount)
355
356  static size_t max_count = 0;
357  if (!max_count) {
358    const size_t kEstimatedWebContentsMemoryUsage =
359#if defined(ARCH_CPU_64_BITS)
360        60;  // In MB
361#else
362        40;  // In MB
363#endif
364    max_count = base::SysInfo::AmountOfPhysicalMemoryMB() / 2;
365    max_count /= kEstimatedWebContentsMemoryUsage;
366
367    const size_t kMinRendererProcessCount = 3;
368    max_count = std::max(max_count, kMinRendererProcessCount);
369    max_count = std::min(max_count, kMaxRendererProcessCount);
370  }
371  return max_count;
372}
373
374// static
375bool g_run_renderer_in_process_ = false;
376
377// static
378void RenderProcessHost::SetMaxRendererProcessCount(size_t count) {
379  g_max_renderer_count_override = count;
380}
381
382RenderProcessHostImpl::RenderProcessHostImpl(
383    BrowserContext* browser_context,
384    StoragePartitionImpl* storage_partition_impl,
385    bool supports_browser_plugin,
386    bool is_guest)
387        : fast_shutdown_started_(false),
388          deleting_soon_(false),
389          pending_views_(0),
390          visible_widgets_(0),
391          backgrounded_(true),
392          cached_dibs_cleaner_(
393              FROM_HERE, base::TimeDelta::FromSeconds(5),
394              this, &RenderProcessHostImpl::ClearTransportDIBCache),
395          is_initialized_(false),
396          id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()),
397          browser_context_(browser_context),
398          storage_partition_impl_(storage_partition_impl),
399          sudden_termination_allowed_(true),
400          ignore_input_events_(false),
401          supports_browser_plugin_(supports_browser_plugin),
402          is_guest_(is_guest),
403          gpu_observer_registered_(false) {
404  widget_helper_ = new RenderWidgetHelper();
405
406  ChildProcessSecurityPolicyImpl::GetInstance()->Add(GetID());
407
408  CHECK(!g_exited_main_message_loop);
409  RegisterHost(GetID(), this);
410  g_all_hosts.Get().set_check_on_null_data(true);
411  // Initialize |child_process_activity_time_| to a reasonable value.
412  mark_child_process_activity_time();
413
414  if (!GetBrowserContext()->IsOffTheRecord() &&
415      !CommandLine::ForCurrentProcess()->HasSwitch(
416          switches::kDisableGpuShaderDiskCache)) {
417    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
418                            base::Bind(&CacheShaderInfo, GetID(),
419                                       storage_partition_impl_->GetPath()));
420  }
421
422  // Note: When we create the RenderProcessHostImpl, it's technically
423  //       backgrounded, because it has no visible listeners.  But the process
424  //       doesn't actually exist yet, so we'll Background it later, after
425  //       creation.
426}
427
428RenderProcessHostImpl::~RenderProcessHostImpl() {
429  DCHECK(!run_renderer_in_process());
430  ChildProcessSecurityPolicyImpl::GetInstance()->Remove(GetID());
431
432  if (gpu_observer_registered_) {
433    GpuDataManagerImpl::GetInstance()->RemoveObserver(this);
434    gpu_observer_registered_ = false;
435  }
436
437  // We may have some unsent messages at this point, but that's OK.
438  channel_.reset();
439  while (!queued_messages_.empty()) {
440    delete queued_messages_.front();
441    queued_messages_.pop();
442  }
443
444  ClearTransportDIBCache();
445  UnregisterHost(GetID());
446
447  if (!CommandLine::ForCurrentProcess()->HasSwitch(
448      switches::kDisableGpuShaderDiskCache)) {
449    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
450                            base::Bind(&RemoveShaderInfo, GetID()));
451  }
452}
453
454void RenderProcessHostImpl::EnableSendQueue() {
455  is_initialized_ = false;
456}
457
458bool RenderProcessHostImpl::Init() {
459  // calling Init() more than once does nothing, this makes it more convenient
460  // for the view host which may not be sure in some cases
461  if (channel_)
462    return true;
463
464  CommandLine::StringType renderer_prefix;
465#if defined(OS_POSIX)
466  // A command prefix is something prepended to the command line of the spawned
467  // process. It is supported only on POSIX systems.
468  const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
469  renderer_prefix =
470      browser_command_line.GetSwitchValueNative(switches::kRendererCmdPrefix);
471#endif  // defined(OS_POSIX)
472
473#if defined(OS_LINUX)
474  int flags = renderer_prefix.empty() ? ChildProcessHost::CHILD_ALLOW_SELF :
475                                        ChildProcessHost::CHILD_NORMAL;
476#else
477  int flags = ChildProcessHost::CHILD_NORMAL;
478#endif
479
480  // Find the renderer before creating the channel so if this fails early we
481  // return without creating the channel.
482  base::FilePath renderer_path = ChildProcessHost::GetChildPath(flags);
483  if (renderer_path.empty())
484    return false;
485
486  // Setup the IPC channel.
487  const std::string channel_id =
488      IPC::Channel::GenerateVerifiedChannelID(std::string());
489  channel_.reset(
490          new IPC::ChannelProxy(channel_id,
491                                IPC::Channel::MODE_SERVER,
492                                this,
493                                BrowserThread::GetMessageLoopProxyForThread(
494                                    BrowserThread::IO).get()));
495
496  // Call the embedder first so that their IPC filters have priority.
497  GetContentClient()->browser()->RenderProcessHostCreated(this);
498
499  CreateMessageFilters();
500
501  // Single-process mode not supported in split-dll mode.
502#if !defined(CHROME_SPLIT_DLL)
503  if (run_renderer_in_process()) {
504    // Crank up a thread and run the initialization there.  With the way that
505    // messages flow between the browser and renderer, this thread is required
506    // to prevent a deadlock in single-process mode.  Since the primordial
507    // thread in the renderer process runs the WebKit code and can sometimes
508    // make blocking calls to the UI thread (i.e. this thread), they need to run
509    // on separate threads.
510    in_process_renderer_.reset(new RendererMainThread(channel_id));
511
512    base::Thread::Options options;
513#if defined(OS_WIN) && !defined(OS_MACOSX)
514    // In-process plugins require this to be a UI message loop.
515    options.message_loop_type = base::MessageLoop::TYPE_UI;
516#else
517    // We can't have multiple UI loops on Linux and Android, so we don't support
518    // in-process plugins.
519    options.message_loop_type = base::MessageLoop::TYPE_DEFAULT;
520#endif
521    in_process_renderer_->StartWithOptions(options);
522
523    OnProcessLaunched();  // Fake a callback that the process is ready.
524  } else
525#endif  // !CHROME_SPLIT_DLL
526  {
527    // Build command line for renderer.  We call AppendRendererCommandLine()
528    // first so the process type argument will appear first.
529    CommandLine* cmd_line = new CommandLine(renderer_path);
530    if (!renderer_prefix.empty())
531      cmd_line->PrependWrapper(renderer_prefix);
532    AppendRendererCommandLine(cmd_line);
533    cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
534
535    // Spawn the child process asynchronously to avoid blocking the UI thread.
536    // As long as there's no renderer prefix, we can use the zygote process
537    // at this stage.
538    child_process_launcher_.reset(new ChildProcessLauncher(
539#if defined(OS_WIN)
540        new RendererSandboxedProcessLauncherDelegate,
541#elif defined(OS_POSIX)
542        renderer_prefix.empty(),
543        base::EnvironmentVector(),
544        channel_->TakeClientFileDescriptor(),
545#endif
546        cmd_line,
547        GetID(),
548        this));
549
550    fast_shutdown_started_ = false;
551  }
552
553  if (!gpu_observer_registered_) {
554    gpu_observer_registered_ = true;
555    GpuDataManagerImpl::GetInstance()->AddObserver(this);
556  }
557
558  is_initialized_ = true;
559  return true;
560}
561
562void RenderProcessHostImpl::CreateMessageFilters() {
563  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
564  channel_->AddFilter(new ResourceSchedulerFilter(GetID()));
565  MediaInternals* media_internals = MediaInternals::GetInstance();;
566  media::AudioManager* audio_manager =
567      BrowserMainLoop::GetInstance()->audio_manager();
568  // Add BrowserPluginMessageFilter to ensure it gets the first stab at messages
569  // from guests.
570  if (supports_browser_plugin_) {
571    scoped_refptr<BrowserPluginMessageFilter> bp_message_filter(
572        new BrowserPluginMessageFilter(GetID(), IsGuest()));
573    channel_->AddFilter(bp_message_filter.get());
574  }
575
576  scoped_refptr<RenderMessageFilter> render_message_filter(
577      new RenderMessageFilter(
578          GetID(),
579#if defined(ENABLE_PLUGINS)
580          PluginServiceImpl::GetInstance(),
581#else
582          NULL,
583#endif
584          GetBrowserContext(),
585          GetBrowserContext()->GetRequestContextForRenderProcess(GetID()),
586          widget_helper_.get(),
587          audio_manager,
588          media_internals,
589          storage_partition_impl_->GetDOMStorageContext()));
590  channel_->AddFilter(render_message_filter.get());
591  BrowserContext* browser_context = GetBrowserContext();
592  ResourceContext* resource_context = browser_context->GetResourceContext();
593
594  ResourceMessageFilter* resource_message_filter = new ResourceMessageFilter(
595      GetID(), PROCESS_TYPE_RENDERER, resource_context,
596      storage_partition_impl_->GetAppCacheService(),
597      ChromeBlobStorageContext::GetFor(browser_context),
598      storage_partition_impl_->GetFileSystemContext(),
599      new RendererURLRequestContextSelector(browser_context, GetID()));
600
601  channel_->AddFilter(resource_message_filter);
602  MediaStreamManager* media_stream_manager =
603      BrowserMainLoop::GetInstance()->media_stream_manager();
604  channel_->AddFilter(new AudioInputRendererHost(
605      audio_manager,
606      media_stream_manager,
607      BrowserMainLoop::GetInstance()->audio_mirroring_manager()));
608  channel_->AddFilter(new AudioRendererHost(
609      GetID(), audio_manager,
610      BrowserMainLoop::GetInstance()->audio_mirroring_manager(),
611      media_internals, media_stream_manager));
612  channel_->AddFilter(
613      new MIDIHost(BrowserMainLoop::GetInstance()->midi_manager()));
614  channel_->AddFilter(new VideoCaptureHost(media_stream_manager));
615  channel_->AddFilter(new AppCacheDispatcherHost(
616      storage_partition_impl_->GetAppCacheService(),
617      GetID()));
618  channel_->AddFilter(new ClipboardMessageFilter);
619  channel_->AddFilter(new DOMStorageMessageFilter(
620      GetID(),
621      storage_partition_impl_->GetDOMStorageContext()));
622  channel_->AddFilter(new IndexedDBDispatcherHost(
623      GetID(),
624      storage_partition_impl_->GetIndexedDBContext()));
625  if (IsGuest()) {
626    if (!g_browser_plugin_geolocation_context.Get().get()) {
627      g_browser_plugin_geolocation_context.Get() =
628          new BrowserPluginGeolocationPermissionContext();
629    }
630    channel_->AddFilter(GeolocationDispatcherHost::New(
631        GetID(), g_browser_plugin_geolocation_context.Get().get()));
632  } else {
633    channel_->AddFilter(GeolocationDispatcherHost::New(
634        GetID(), browser_context->GetGeolocationPermissionContext()));
635  }
636  gpu_message_filter_ = new GpuMessageFilter(GetID(), widget_helper_.get());
637  channel_->AddFilter(gpu_message_filter_);
638#if defined(ENABLE_WEBRTC)
639  channel_->AddFilter(new WebRTCIdentityServiceHost(
640      storage_partition_impl_->GetWebRTCIdentityStore()));
641  peer_connection_tracker_host_ = new PeerConnectionTrackerHost(GetID());
642  channel_->AddFilter(peer_connection_tracker_host_.get());
643  channel_->AddFilter(new MediaStreamDispatcherHost(
644      GetID(), media_stream_manager));
645#endif
646#if defined(ENABLE_PLUGINS)
647  // TODO(raymes): PepperMessageFilter should be removed from here.
648  channel_->AddFilter(new PepperMessageFilter(GetID(), browser_context));
649  channel_->AddFilter(new PepperRendererConnection);
650#endif
651#if defined(ENABLE_INPUT_SPEECH)
652  channel_->AddFilter(new InputTagSpeechDispatcherHost(
653      IsGuest(), GetID(), storage_partition_impl_->GetURLRequestContext(),
654      browser_context->GetSpeechRecognitionPreferences()));
655#endif
656  channel_->AddFilter(new SpeechRecognitionDispatcherHost(
657      GetID(), storage_partition_impl_->GetURLRequestContext(),
658      browser_context->GetSpeechRecognitionPreferences()));
659  channel_->AddFilter(new FileAPIMessageFilter(
660      GetID(),
661      storage_partition_impl_->GetURLRequestContext(),
662      storage_partition_impl_->GetFileSystemContext(),
663      ChromeBlobStorageContext::GetFor(browser_context)));
664  channel_->AddFilter(new OrientationMessageFilter());
665  channel_->AddFilter(new FileUtilitiesMessageFilter(GetID()));
666  channel_->AddFilter(new MimeRegistryMessageFilter());
667  channel_->AddFilter(new DatabaseMessageFilter(
668      storage_partition_impl_->GetDatabaseTracker()));
669#if defined(OS_MACOSX)
670  channel_->AddFilter(new TextInputClientMessageFilter(GetID()));
671#elif defined(OS_WIN)
672  channel_->AddFilter(new FontCacheDispatcher());
673#endif
674
675  SocketStreamDispatcherHost* socket_stream_dispatcher_host =
676      new SocketStreamDispatcherHost(GetID(),
677          new RendererURLRequestContextSelector(browser_context, GetID()),
678          resource_context);
679  channel_->AddFilter(socket_stream_dispatcher_host);
680
681  channel_->AddFilter(new WorkerMessageFilter(
682      GetID(),
683      resource_context,
684      WorkerStoragePartition(
685          storage_partition_impl_->GetURLRequestContext(),
686          storage_partition_impl_->GetMediaURLRequestContext(),
687          storage_partition_impl_->GetAppCacheService(),
688          storage_partition_impl_->GetQuotaManager(),
689          storage_partition_impl_->GetFileSystemContext(),
690          storage_partition_impl_->GetDatabaseTracker(),
691          storage_partition_impl_->GetIndexedDBContext()),
692      base::Bind(&RenderWidgetHelper::GetNextRoutingID,
693                 base::Unretained(widget_helper_.get()))));
694
695#if defined(ENABLE_WEBRTC)
696  channel_->AddFilter(new P2PSocketDispatcherHost(
697      resource_context,
698      browser_context->GetRequestContextForRenderProcess(GetID())));
699#endif
700
701  channel_->AddFilter(new TraceMessageFilter());
702  channel_->AddFilter(new ResolveProxyMsgHelper(
703      browser_context->GetRequestContextForRenderProcess(GetID())));
704  channel_->AddFilter(new QuotaDispatcherHost(
705      GetID(),
706      storage_partition_impl_->GetQuotaManager(),
707      GetContentClient()->browser()->CreateQuotaPermissionContext()));
708  channel_->AddFilter(new GamepadBrowserMessageFilter());
709  channel_->AddFilter(new ProfilerMessageFilter(PROCESS_TYPE_RENDERER));
710  channel_->AddFilter(new HistogramMessageFilter());
711  channel_->AddFilter(new HyphenatorMessageFilter(this));
712#if defined(USE_TCMALLOC) && (defined(OS_LINUX) || defined(OS_ANDROID))
713  if (CommandLine::ForCurrentProcess()->HasSwitch(
714      switches::kEnableMemoryBenchmarking))
715    channel_->AddFilter(new MemoryBenchmarkMessageFilter());
716#endif
717}
718
719int RenderProcessHostImpl::GetNextRoutingID() {
720  return widget_helper_->GetNextRoutingID();
721}
722
723
724void RenderProcessHostImpl::ResumeDeferredNavigation(
725    const GlobalRequestID& request_id) {
726  widget_helper_->ResumeDeferredNavigation(request_id);
727}
728
729void RenderProcessHostImpl::AddRoute(
730    int32 routing_id,
731    IPC::Listener* listener) {
732  listeners_.AddWithID(listener, routing_id);
733}
734
735void RenderProcessHostImpl::RemoveRoute(int32 routing_id) {
736  DCHECK(listeners_.Lookup(routing_id) != NULL);
737  listeners_.Remove(routing_id);
738
739#if defined(OS_WIN)
740  // Dump the handle table if handle auditing is enabled.
741  const CommandLine& browser_command_line =
742      *CommandLine::ForCurrentProcess();
743  if (browser_command_line.HasSwitch(switches::kAuditHandles) ||
744      browser_command_line.HasSwitch(switches::kAuditAllHandles)) {
745    DumpHandles();
746
747    // We wait to close the channels until the child process has finished
748    // dumping handles and sends us ChildProcessHostMsg_DumpHandlesDone.
749    return;
750  }
751#endif
752  // Keep the one renderer thread around forever in single process mode.
753  if (!run_renderer_in_process())
754    Cleanup();
755}
756
757bool RenderProcessHostImpl::WaitForBackingStoreMsg(
758    int render_widget_id,
759    const base::TimeDelta& max_delay,
760    IPC::Message* msg) {
761  // The post task to this thread with the process id could be in queue, and we
762  // don't want to dispatch a message before then since it will need the handle.
763  if (child_process_launcher_.get() && child_process_launcher_->IsStarting())
764    return false;
765
766  return widget_helper_->WaitForBackingStoreMsg(render_widget_id,
767                                                max_delay, msg);
768}
769
770void RenderProcessHostImpl::ReceivedBadMessage() {
771  if (run_renderer_in_process()) {
772    // In single process mode it is better if we don't suicide but just
773    // crash.
774    CHECK(false);
775  }
776  // We kill the renderer but don't include a NOTREACHED, because we want the
777  // browser to try to survive when it gets illegal messages from the renderer.
778  base::KillProcess(GetHandle(), RESULT_CODE_KILLED_BAD_MESSAGE,
779                    false);
780}
781
782void RenderProcessHostImpl::WidgetRestored() {
783  // Verify we were properly backgrounded.
784  DCHECK_EQ(backgrounded_, (visible_widgets_ == 0));
785  visible_widgets_++;
786  SetBackgrounded(false);
787}
788
789void RenderProcessHostImpl::WidgetHidden() {
790  // On startup, the browser will call Hide
791  if (backgrounded_)
792    return;
793
794  DCHECK_EQ(backgrounded_, (visible_widgets_ == 0));
795  visible_widgets_--;
796  DCHECK_GE(visible_widgets_, 0);
797  if (visible_widgets_ == 0) {
798    DCHECK(!backgrounded_);
799    SetBackgrounded(true);
800  }
801}
802
803int RenderProcessHostImpl::VisibleWidgetCount() const {
804  return visible_widgets_;
805}
806
807bool RenderProcessHostImpl::IsGuest() const {
808  return is_guest_;
809}
810
811StoragePartition* RenderProcessHostImpl::GetStoragePartition() const {
812  return storage_partition_impl_;
813}
814
815void RenderProcessHostImpl::AppendRendererCommandLine(
816    CommandLine* command_line) const {
817  // Pass the process type first, so it shows first in process listings.
818  command_line->AppendSwitchASCII(switches::kProcessType,
819                                  switches::kRendererProcess);
820
821  // Now send any options from our own command line we want to propagate.
822  const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
823  PropagateBrowserCommandLineToRenderer(browser_command_line, command_line);
824
825  // Pass on the browser locale.
826  const std::string locale =
827      GetContentClient()->browser()->GetApplicationLocale();
828  command_line->AppendSwitchASCII(switches::kLang, locale);
829
830  // If we run base::FieldTrials, we want to pass to their state to the
831  // renderer so that it can act in accordance with each state, or record
832  // histograms relating to the base::FieldTrial states.
833  std::string field_trial_states;
834  base::FieldTrialList::StatesToString(&field_trial_states);
835  if (!field_trial_states.empty()) {
836    command_line->AppendSwitchASCII(switches::kForceFieldTrials,
837                                    field_trial_states);
838  }
839
840  GetContentClient()->browser()->AppendExtraCommandLineSwitches(
841      command_line, GetID());
842
843  // Appending disable-gpu-feature switches due to software rendering list.
844  GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance();
845  DCHECK(gpu_data_manager);
846  gpu_data_manager->AppendRendererCommandLine(command_line);
847}
848
849void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
850    const CommandLine& browser_cmd,
851    CommandLine* renderer_cmd) const {
852  // Propagate the following switches to the renderer command line (along
853  // with any associated values) if present in the browser command line.
854  static const char* const kSwitchNames[] = {
855    switches::kAudioBufferSize,
856    switches::kAuditAllHandles,
857    switches::kAuditHandles,
858    switches::kDisable3DAPIs,
859    switches::kDisableAcceleratedCompositing,
860    switches::kDisableAcceleratedVideoDecode,
861    switches::kDisableApplicationCache,
862    switches::kDisableAudio,
863    switches::kDisableBreakpad,
864    switches::kDisableDatabases,
865    switches::kDisableDesktopNotifications,
866    switches::kDisableDeviceOrientation,
867    switches::kDisableFileSystem,
868    switches::kDisableGeolocation,
869    switches::kDisableGLMultisampling,
870    switches::kDisableGpuVsync,
871    switches::kDisableGpu,
872    switches::kDisableHistogramCustomizer,
873    switches::kDisableJavaScriptI18NAPI,
874    switches::kDisableLocalStorage,
875    switches::kDisableLogging,
876    switches::kDisableNewDialogStyle,
877    switches::kDisableSeccompFilterSandbox,
878    switches::kDisableSessionStorage,
879    switches::kDisableSharedWorkers,
880    switches::kDisableSpeechInput,
881    switches::kDisableTouchDragDrop,
882    switches::kDisableTouchEditing,
883#if defined(OS_ANDROID)
884    switches::kDisableWebRTC,
885    switches::kEnableSpeechRecognition,
886#endif
887    switches::kDisableWebAudio,
888#if defined(ENABLE_WEBRTC)
889    switches::kEnableSCTPDataChannels,
890#endif
891    switches::kEnableWebMIDI,
892    switches::kEnableExperimentalCanvasFeatures,
893    switches::kEnableExperimentalWebSocket,
894    switches::kDomAutomationController,
895    switches::kEnableAccessibilityLogging,
896    switches::kEnableBeginFrameScheduling,
897    switches::kEnableBrowserInputController,
898    switches::kEnableBrowserPluginForAllViewTypes,
899    switches::kEnableDCHECK,
900    switches::kEnableDelegatedRenderer,
901    switches::kEnableEncryptedMedia,
902    switches::kDisableLegacyEncryptedMedia,
903    switches::kOverrideEncryptedMediaCanPlayType,
904    switches::kEnableExperimentalWebKitFeatures,
905    switches::kEnableFixedLayout,
906    switches::kEnableDeferredImageDecoding,
907    switches::kEnableGPUServiceLogging,
908    switches::kEnableGPUClientLogging,
909    switches::kEnableGpuClientTracing,
910    switches::kEnableGpuBenchmarking,
911    switches::kEnableMemoryBenchmarking,
912    switches::kEnableSkiaBenchmarking,
913    switches::kEnableLogging,
914    switches::kEnableSpeechSynthesis,
915    switches::kEnableTouchDragDrop,
916    switches::kEnableTouchEditing,
917#if defined(ENABLE_WEBRTC)
918    switches::kEnableWebRtcAecRecordings,
919    switches::kEnableWebRtcTcpServerSocket,
920#endif
921#if defined(ANDROID) && !defined(GOOGLE_TV)
922    switches::kEnableWebKitMediaSource,
923#else
924    switches::kDisableWebKitMediaSource,
925#endif
926    switches::kEnableOverscrollNotifications,
927    switches::kEnableStrictSiteIsolation,
928    switches::kDisableFullScreen,
929    switches::kEnableNewDialogStyle,
930#if defined(ENABLE_PLUGINS)
931    switches::kEnablePepperTesting,
932    switches::kDisablePepper3d,
933#endif
934    switches::kEnablePreparsedJsCaching,
935    switches::kEnablePruneGpuCommandBuffers,
936    switches::kEnablePinch,
937    switches::kDisablePinch,
938#if defined(OS_MACOSX)
939    // Allow this to be set when invoking the browser and relayed along.
940    switches::kEnableSandboxLogging,
941#endif
942    switches::kEnableSoftwareCompositingGLAdapter,
943    switches::kEnableStatsTable,
944    switches::kEnableThreadedCompositing,
945    switches::kEnableCompositingForFixedPosition,
946    switches::kEnableHighDpiCompositingForFixedPosition,
947    switches::kDisableCompositingForFixedPosition,
948    switches::kEnableAcceleratedOverflowScroll,
949    switches::kEnableCompositingForTransition,
950    switches::kDisableCompositingForTransition,
951    switches::kDisableThreadedCompositing,
952    switches::kDisableTouchAdjustment,
953    switches::kDefaultTileWidth,
954    switches::kDefaultTileHeight,
955    switches::kMaxUntiledLayerWidth,
956    switches::kMaxUntiledLayerHeight,
957#if defined(OS_CHROMEOS)
958    switches::kEnableEncodedScreenCapture,
959#endif
960    switches::kEnableViewport,
961    switches::kEnableInbandTextTracks,
962    switches::kEnableOpusPlayback,
963    switches::kEnableVp8AlphaPlayback,
964    switches::kEnableEac3Playback,
965    switches::kForceDeviceScaleFactor,
966    switches::kFullMemoryCrashReport,
967#if !defined (GOOGLE_CHROME_BUILD)
968    // These are unsupported and not fully tested modes, so don't enable them
969    // for official Google Chrome builds.
970    switches::kInProcessPlugins,
971#endif  // GOOGLE_CHROME_BUILD
972    switches::kJavaScriptFlags,
973    switches::kLoggingLevel,
974    switches::kMemoryMetrics,
975#if defined(OS_ANDROID)
976    switches::kNetworkCountryIso,
977    switches::kDisableGestureRequirementForMediaPlayback,
978#endif
979#if defined(GOOGLE_TV)
980    switches::kUseExternalVideoSurfaceThresholdInPixels,
981#endif
982    switches::kNoReferrers,
983    switches::kNoSandbox,
984    switches::kEnableVtune,
985    switches::kPpapiInProcess,
986    switches::kRegisterPepperPlugins,
987    switches::kRendererAssertTest,
988#if defined(OS_POSIX)
989    switches::kChildCleanExit,
990#endif
991    switches::kRendererStartupDialog,
992    switches::kShowPaintRects,
993    switches::kSitePerProcess,
994    switches::kStatsCollectionController,
995    switches::kTestSandbox,
996    switches::kTouchEvents,
997    switches::kTraceStartup,
998    // This flag needs to be propagated to the renderer process for
999    // --in-process-webgl.
1000    switches::kUseGL,
1001    switches::kUseMobileUserAgent,
1002    switches::kUserAgent,
1003    switches::kV,
1004    switches::kVideoThreads,
1005    switches::kVModule,
1006    switches::kWebCoreLogChannels,
1007    switches::kEnableWebGLDraftExtensions,
1008    // Please keep these in alphabetical order. Compositor switches here should
1009    // also be added to chrome/browser/chromeos/login/chrome_restart_request.cc.
1010    cc::switches::kBackgroundColorInsteadOfCheckerboard,
1011    cc::switches::kCompositeToMailbox,
1012    cc::switches::kDisableImplSidePainting,
1013    cc::switches::kDisableThreadedAnimation,
1014    cc::switches::kEnableImplSidePainting,
1015    cc::switches::kEnablePartialSwap,
1016    cc::switches::kEnablePerTilePainting,
1017    cc::switches::kEnablePinchVirtualViewport,
1018    cc::switches::kEnableTopControlsPositionCalculation,
1019    cc::switches::kForceDirectLayerDrawing,
1020    cc::switches::kLowResolutionContentsScaleFactor,
1021    cc::switches::kMaxTilesForInterestArea,
1022    cc::switches::kMaxUnusedResourceMemoryUsagePercentage,
1023    cc::switches::kNumRasterThreads,
1024    cc::switches::kShowCompositedLayerBorders,
1025    cc::switches::kShowFPSCounter,
1026    cc::switches::kShowNonOccludingRects,
1027    cc::switches::kShowOccludingRects,
1028    cc::switches::kShowPropertyChangedRects,
1029    cc::switches::kShowReplicaScreenSpaceRects,
1030    cc::switches::kShowScreenSpaceRects,
1031    cc::switches::kShowSurfaceDamageRects,
1032    cc::switches::kSlowDownRasterScaleFactor,
1033    cc::switches::kStrictLayerPropertyChangeChecking,
1034    cc::switches::kTopControlsHeight,
1035    cc::switches::kTopControlsHideThreshold,
1036    cc::switches::kTopControlsShowThreshold,
1037    cc::switches::kTraceOverdraw,
1038    cc::switches::kUseMapImage,
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
1585base::MessageLoop*
1586    RenderProcessHostImpl::GetInProcessRendererThreadForTesting() {
1587  return g_in_process_thread;
1588}
1589
1590void RenderProcessHostImpl::ProcessDied(bool already_dead) {
1591  // Our child process has died.  If we didn't expect it, it's a crash.
1592  // In any case, we need to let everyone know it's gone.
1593  // The OnChannelError notification can fire multiple times due to nested sync
1594  // calls to a renderer. If we don't have a valid channel here it means we
1595  // already handled the error.
1596
1597  // child_process_launcher_ can be NULL in single process mode or if fast
1598  // termination happened.
1599  int exit_code = 0;
1600  base::TerminationStatus status =
1601      child_process_launcher_.get() ?
1602      child_process_launcher_->GetChildTerminationStatus(already_dead,
1603                                                         &exit_code) :
1604      base::TERMINATION_STATUS_NORMAL_TERMINATION;
1605
1606  RendererClosedDetails details(GetHandle(), status, exit_code);
1607  NotificationService::current()->Notify(
1608      NOTIFICATION_RENDERER_PROCESS_CLOSED,
1609      Source<RenderProcessHost>(this),
1610      Details<RendererClosedDetails>(&details));
1611
1612  child_process_launcher_.reset();
1613  channel_.reset();
1614  gpu_message_filter_ = NULL;
1615
1616  IDMap<IPC::Listener>::iterator iter(&listeners_);
1617  while (!iter.IsAtEnd()) {
1618    iter.GetCurrentValue()->OnMessageReceived(
1619        ViewHostMsg_RenderViewGone(iter.GetCurrentKey(),
1620                                   static_cast<int>(status),
1621                                   exit_code));
1622    iter.Advance();
1623  }
1624
1625  ClearTransportDIBCache();
1626
1627  // this object is not deleted at this point and may be reused later.
1628  // TODO(darin): clean this up
1629}
1630
1631int RenderProcessHostImpl::GetActiveViewCount() {
1632  int num_active_views = 0;
1633  RenderWidgetHost::List widgets = RenderWidgetHost::GetRenderWidgetHosts();
1634  for (size_t i = 0; i < widgets.size(); ++i) {
1635    // Count only RenderWidgetHosts in this process.
1636    if (widgets[i]->GetProcess()->GetID() != GetID())
1637      continue;
1638
1639    // All RenderWidgetHosts are swapped in.
1640    if (!widgets[i]->IsRenderView()) {
1641      num_active_views++;
1642      continue;
1643    }
1644
1645    // Don't count swapped out views.
1646    RenderViewHost* rvh = RenderViewHost::From(widgets[i]);
1647    if (!static_cast<RenderViewHostImpl*>(rvh)->is_swapped_out())
1648      num_active_views++;
1649  }
1650  return num_active_views;
1651}
1652
1653// Frame subscription API for this class is for accelerated composited path
1654// only. These calls are redirected to GpuMessageFilter.
1655void RenderProcessHostImpl::BeginFrameSubscription(
1656    int route_id,
1657    scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
1658  if (!gpu_message_filter_)
1659    return;
1660  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
1661      &GpuMessageFilter::BeginFrameSubscription,
1662      gpu_message_filter_,
1663      route_id, base::Passed(&subscriber)));
1664}
1665
1666void RenderProcessHostImpl::EndFrameSubscription(int route_id) {
1667  if (!gpu_message_filter_)
1668    return;
1669  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
1670      &GpuMessageFilter::EndFrameSubscription,
1671      gpu_message_filter_,
1672      route_id));
1673}
1674
1675void RenderProcessHostImpl::OnShutdownRequest() {
1676  // Don't shut down if there are active RenderViews, or if there are pending
1677  // RenderViews being swapped back in.
1678  // In single process mode, we never shutdown the renderer.
1679  int num_active_views = GetActiveViewCount();
1680  if (pending_views_ || num_active_views > 0 || run_renderer_in_process())
1681    return;
1682
1683  // Notify any contents that might have swapped out renderers from this
1684  // process. They should not attempt to swap them back in.
1685  NotificationService::current()->Notify(
1686      NOTIFICATION_RENDERER_PROCESS_CLOSING,
1687      Source<RenderProcessHost>(this),
1688      NotificationService::NoDetails());
1689
1690  Send(new ChildProcessMsg_Shutdown());
1691}
1692
1693void RenderProcessHostImpl::SuddenTerminationChanged(bool enabled) {
1694  SetSuddenTerminationAllowed(enabled);
1695}
1696
1697void RenderProcessHostImpl::OnDumpHandlesDone() {
1698  Cleanup();
1699}
1700
1701void RenderProcessHostImpl::SetBackgrounded(bool backgrounded) {
1702  // Note: we always set the backgrounded_ value.  If the process is NULL
1703  // (and hence hasn't been created yet), we will set the process priority
1704  // later when we create the process.
1705  backgrounded_ = backgrounded;
1706  if (!child_process_launcher_.get() || child_process_launcher_->IsStarting())
1707    return;
1708
1709#if defined(OS_WIN)
1710  // The cbstext.dll loads as a global GetMessage hook in the browser process
1711  // and intercepts/unintercepts the kernel32 API SetPriorityClass in a
1712  // background thread. If the UI thread invokes this API just when it is
1713  // intercepted the stack is messed up on return from the interceptor
1714  // which causes random crashes in the browser process. Our hack for now
1715  // is to not invoke the SetPriorityClass API if the dll is loaded.
1716  if (GetModuleHandle(L"cbstext.dll"))
1717    return;
1718#endif  // OS_WIN
1719
1720  child_process_launcher_->SetProcessBackgrounded(backgrounded);
1721}
1722
1723void RenderProcessHostImpl::OnProcessLaunched() {
1724  // No point doing anything, since this object will be destructed soon.  We
1725  // especially don't want to send the RENDERER_PROCESS_CREATED notification,
1726  // since some clients might expect a RENDERER_PROCESS_TERMINATED afterwards to
1727  // properly cleanup.
1728  if (deleting_soon_)
1729    return;
1730
1731  if (child_process_launcher_) {
1732    if (!child_process_launcher_->GetHandle()) {
1733      OnChannelError();
1734      return;
1735    }
1736
1737    child_process_launcher_->SetProcessBackgrounded(backgrounded_);
1738  }
1739
1740  // NOTE: This needs to be before sending queued messages because
1741  // ExtensionService uses this notification to initialize the renderer process
1742  // with state that must be there before any JavaScript executes.
1743  //
1744  // The queued messages contain such things as "navigate". If this notification
1745  // was after, we can end up executing JavaScript before the initialization
1746  // happens.
1747  NotificationService::current()->Notify(
1748      NOTIFICATION_RENDERER_PROCESS_CREATED,
1749      Source<RenderProcessHost>(this),
1750      NotificationService::NoDetails());
1751
1752  while (!queued_messages_.empty()) {
1753    Send(queued_messages_.front());
1754    queued_messages_.pop();
1755  }
1756}
1757
1758void RenderProcessHostImpl::OnUserMetricsRecordAction(
1759    const std::string& action) {
1760  RecordComputedAction(action);
1761}
1762
1763void RenderProcessHostImpl::OnSavedPageAsMHTML(int job_id, int64 data_size) {
1764  MHTMLGenerationManager::GetInstance()->MHTMLGenerated(job_id, data_size);
1765}
1766
1767void RenderProcessHostImpl::OnCompositorSurfaceBuffersSwappedNoHost(
1768      const ViewHostMsg_CompositorSurfaceBuffersSwapped_Params& params) {
1769  TRACE_EVENT0("renderer_host",
1770               "RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwappedNoHost");
1771  AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
1772  ack_params.sync_point = 0;
1773  RenderWidgetHostImpl::AcknowledgeBufferPresent(params.route_id,
1774                                                 params.gpu_process_host_id,
1775                                                 ack_params);
1776}
1777
1778void RenderProcessHostImpl::OnGpuSwitching() {
1779  RenderWidgetHost::List widgets = RenderWidgetHost::GetRenderWidgetHosts();
1780  for (size_t i = 0; i < widgets.size(); ++i) {
1781    if (!widgets[i]->IsRenderView())
1782      continue;
1783
1784    // Skip widgets in other processes.
1785    if (widgets[i]->GetProcess()->GetID() != GetID())
1786      continue;
1787
1788    RenderViewHost* rvh = RenderViewHost::From(widgets[i]);
1789    rvh->UpdateWebkitPreferences(rvh->GetWebkitPreferences());
1790  }
1791}
1792
1793}  // namespace content
1794