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