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