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(), §ion,
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