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.
5 // Represents the browser side of the browser <--> renderer communication
6 // channel. There will be one RenderProcessHost per renderer process.
8 #include "content/browser/renderer_host/render_process_host_impl.h"
15 #include <utility> // for pair<>
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/process_util.h"
31 #include "base/rand_util.h"
32 #include "base/stl_util.h"
33 #include "base/strings/string_util.h"
34 #include "base/supports_user_data.h"
35 #include "base/sys_info.h"
36 #include "base/threading/thread.h"
37 #include "base/threading/thread_restrictions.h"
38 #include "base/tracked_objects.h"
39 #include "cc/base/switches.h"
40 #include "content/browser/appcache/appcache_dispatcher_host.h"
41 #include "content/browser/appcache/chrome_appcache_service.h"
42 #include "content/browser/browser_main.h"
43 #include "content/browser/browser_main_loop.h"
44 #include "content/browser/browser_plugin/browser_plugin_geolocation_permission_context.h"
45 #include "content/browser/browser_plugin/browser_plugin_message_filter.h"
46 #include "content/browser/child_process_security_policy_impl.h"
47 #include "content/browser/device_orientation/orientation_message_filter.h"
48 #include "content/browser/dom_storage/dom_storage_context_impl.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/geolocation/geolocation_dispatcher_host.h"
54 #include "content/browser/gpu/gpu_data_manager_impl.h"
55 #include "content/browser/gpu/gpu_process_host.h"
56 #include "content/browser/gpu/shader_disk_cache.h"
57 #include "content/browser/histogram_message_filter.h"
58 #include "content/browser/hyphenator/hyphenator_message_filter.h"
59 #include "content/browser/in_process_webkit/indexed_db_dispatcher_host.h"
60 #include "content/browser/indexed_db/indexed_db_context_impl.h"
61 #include "content/browser/loader/resource_message_filter.h"
62 #include "content/browser/loader/resource_scheduler_filter.h"
63 #include "content/browser/media/media_internals.h"
64 #include "content/browser/mime_registry_message_filter.h"
65 #include "content/browser/plugin_service_impl.h"
66 #include "content/browser/profiler_message_filter.h"
67 #include "content/browser/renderer_host/clipboard_message_filter.h"
68 #include "content/browser/renderer_host/database_message_filter.h"
69 #include "content/browser/renderer_host/file_utilities_message_filter.h"
70 #include "content/browser/renderer_host/gamepad_browser_message_filter.h"
71 #include "content/browser/renderer_host/gpu_message_filter.h"
72 #include "content/browser/renderer_host/media/audio_input_renderer_host.h"
73 #include "content/browser/renderer_host/media/audio_mirroring_manager.h"
74 #include "content/browser/renderer_host/media/audio_renderer_host.h"
75 #include "content/browser/renderer_host/media/media_stream_dispatcher_host.h"
76 #include "content/browser/renderer_host/media/midi_host.h"
77 #include "content/browser/renderer_host/media/peer_connection_tracker_host.h"
78 #include "content/browser/renderer_host/media/video_capture_host.h"
79 #include "content/browser/renderer_host/memory_benchmark_message_filter.h"
80 #include "content/browser/renderer_host/p2p/socket_dispatcher_host.h"
81 #include "content/browser/renderer_host/pepper/pepper_message_filter.h"
82 #include "content/browser/renderer_host/pepper/pepper_renderer_connection.h"
83 #include "content/browser/renderer_host/quota_dispatcher_host.h"
84 #include "content/browser/renderer_host/render_message_filter.h"
85 #include "content/browser/renderer_host/render_view_host_delegate.h"
86 #include "content/browser/renderer_host/render_view_host_impl.h"
87 #include "content/browser/renderer_host/render_widget_helper.h"
88 #include "content/browser/renderer_host/socket_stream_dispatcher_host.h"
89 #include "content/browser/renderer_host/text_input_client_message_filter.h"
90 #include "content/browser/resolve_proxy_msg_helper.h"
91 #include "content/browser/speech/input_tag_speech_dispatcher_host.h"
92 #include "content/browser/speech/speech_recognition_dispatcher_host.h"
93 #include "content/browser/storage_partition_impl.h"
94 #include "content/browser/tracing/trace_message_filter.h"
95 #include "content/browser/webui/web_ui_controller_factory_registry.h"
96 #include "content/browser/worker_host/worker_message_filter.h"
97 #include "content/browser/worker_host/worker_storage_partition.h"
98 #include "content/common/child_process_host_impl.h"
99 #include "content/common/child_process_messages.h"
100 #include "content/common/gpu/gpu_messages.h"
101 #include "content/common/resource_messages.h"
102 #include "content/common/view_messages.h"
103 #include "content/port/browser/render_widget_host_view_frame_subscriber.h"
104 #include "content/public/browser/browser_context.h"
105 #include "content/public/browser/content_browser_client.h"
106 #include "content/public/browser/notification_service.h"
107 #include "content/public/browser/notification_types.h"
108 #include "content/public/browser/render_process_host_factory.h"
109 #include "content/public/browser/render_widget_host.h"
110 #include "content/public/browser/resource_context.h"
111 #include "content/public/browser/user_metrics.h"
112 #include "content/public/common/content_constants.h"
113 #include "content/public/common/content_switches.h"
114 #include "content/public/common/process_type.h"
115 #include "content/public/common/result_codes.h"
116 #include "content/public/common/url_constants.h"
117 #include "content/renderer/render_process_impl.h"
118 #include "content/renderer/render_thread_impl.h"
119 #include "gpu/command_buffer/service/gpu_switches.h"
120 #include "ipc/ipc_channel.h"
121 #include "ipc/ipc_logging.h"
122 #include "ipc/ipc_platform_file.h"
123 #include "ipc/ipc_switches.h"
124 #include "media/base/media_switches.h"
125 #include "net/url_request/url_request_context_getter.h"
126 #include "ppapi/shared_impl/ppapi_switches.h"
127 #include "ui/base/ui_base_switches.h"
128 #include "ui/gl/gl_switches.h"
129 #include "webkit/browser/fileapi/sandbox_mount_point_provider.h"
130 #include "webkit/glue/resource_type.h"
131 #include "webkit/plugins/plugin_switches.h"
134 #include "base/win/scoped_com_initializer.h"
135 #include "content/common/font_cache_dispatcher_win.h"
136 #include "content/common/sandbox_win.h"
137 #include "content/public/common/sandboxed_process_launcher_delegate.h"
140 #include "third_party/skia/include/core/SkBitmap.h"
142 extern bool g_exited_main_message_loop
;
144 static const char* kSiteProcessMapKeyName
= "content_site_process_map";
149 base::MessageLoop
* g_in_process_thread
;
151 void CacheShaderInfo(int32 id
, base::FilePath path
) {
152 ShaderCacheFactory::GetInstance()->SetCacheInfo(id
, path
);
155 void RemoveShaderInfo(int32 id
) {
156 ShaderCacheFactory::GetInstance()->RemoveCacheInfo(id
);
161 // This class creates the IO thread for the renderer when running in
162 // single-process mode. It's not used in multi-process mode.
163 class RendererMainThread
: public base::Thread
{
165 explicit RendererMainThread(const std::string
& channel_id
)
166 : Thread("Chrome_InProcRendererThread"),
167 channel_id_(channel_id
) {
170 virtual ~RendererMainThread() {
175 virtual void Init() OVERRIDE
{
176 render_process_
.reset(new RenderProcessImpl());
177 new RenderThreadImpl(channel_id_
);
178 g_in_process_thread
= message_loop();
181 virtual void CleanUp() OVERRIDE
{
182 g_in_process_thread
= NULL
;
183 render_process_
.reset();
185 // It's a little lame to manually set this flag. But the single process
186 // RendererThread will receive the WM_QUIT. We don't need to assert on
187 // this thread, so just force the flag manually.
188 // If we want to avoid this, we could create the InProcRendererThread
189 // directly with _beginthreadex() rather than using the Thread class.
190 // We used to set this flag in the Init function above. However there
191 // other threads like WebThread which are created by this thread
192 // which resets this flag. Please see Thread::StartWithOptions. Setting
193 // this flag to true in Cleanup works around these problems.
194 SetThreadWasQuitProperly(true);
198 std::string channel_id_
;
199 scoped_ptr
<RenderProcess
> render_process_
;
201 DISALLOW_COPY_AND_ASSIGN(RendererMainThread
);
206 // Helper class that we pass to ResourceMessageFilter so that it can find the
207 // right net::URLRequestContext for a request.
208 class RendererURLRequestContextSelector
209 : public ResourceMessageFilter::URLRequestContextSelector
{
211 RendererURLRequestContextSelector(BrowserContext
* browser_context
,
213 : request_context_(browser_context
->GetRequestContextForRenderProcess(
215 media_request_context_(
216 browser_context
->GetMediaRequestContextForRenderProcess(
220 virtual net::URLRequestContext
* GetRequestContext(
221 ResourceType::Type resource_type
) OVERRIDE
{
222 net::URLRequestContextGetter
* request_context
= request_context_
.get();
223 // If the request has resource type of ResourceType::MEDIA, we use a request
224 // context specific to media for handling it because these resources have
225 // specific needs for caching.
226 if (resource_type
== ResourceType::MEDIA
)
227 request_context
= media_request_context_
.get();
228 return request_context
->GetURLRequestContext();
232 virtual ~RendererURLRequestContextSelector() {}
234 scoped_refptr
<net::URLRequestContextGetter
> request_context_
;
235 scoped_refptr
<net::URLRequestContextGetter
> media_request_context_
;
238 // the global list of all renderer processes
239 base::LazyInstance
<IDMap
<RenderProcessHost
> >::Leaky
240 g_all_hosts
= LAZY_INSTANCE_INITIALIZER
;
242 base::LazyInstance
<scoped_refptr
<BrowserPluginGeolocationPermissionContext
> >
243 g_browser_plugin_geolocation_context
= LAZY_INSTANCE_INITIALIZER
;
245 // Map of site to process, to ensure we only have one RenderProcessHost per
246 // site in process-per-site mode. Each map is specific to a BrowserContext.
247 class SiteProcessMap
: public base::SupportsUserData::Data
{
249 typedef base::hash_map
<std::string
, RenderProcessHost
*> SiteToProcessMap
;
252 void RegisterProcess(const std::string
& site
, RenderProcessHost
* process
) {
253 map_
[site
] = process
;
256 RenderProcessHost
* FindProcess(const std::string
& site
) {
257 SiteToProcessMap::iterator i
= map_
.find(site
);
263 void RemoveProcess(RenderProcessHost
* host
) {
264 // Find all instances of this process in the map, then separately remove
266 std::set
<std::string
> sites
;
267 for (SiteToProcessMap::const_iterator i
= map_
.begin();
270 if (i
->second
== host
)
271 sites
.insert(i
->first
);
273 for (std::set
<std::string
>::iterator i
= sites
.begin();
276 SiteToProcessMap::iterator iter
= map_
.find(*i
);
277 if (iter
!= map_
.end()) {
278 DCHECK_EQ(iter
->second
, host
);
285 SiteToProcessMap map_
;
288 // Find the SiteProcessMap specific to the given context.
289 SiteProcessMap
* GetSiteProcessMapForBrowserContext(BrowserContext
* context
) {
291 SiteProcessMap
* map
= static_cast<SiteProcessMap
*>(
292 context
->GetUserData(kSiteProcessMapKeyName
));
294 map
= new SiteProcessMap();
295 context
->SetUserData(kSiteProcessMapKeyName
, map
);
301 // NOTE: changes to this class need to be reviewed by the security team.
302 class RendererSandboxedProcessLauncherDelegate
303 : public content::SandboxedProcessLauncherDelegate
{
305 RendererSandboxedProcessLauncherDelegate() {}
306 virtual ~RendererSandboxedProcessLauncherDelegate() {}
308 virtual void ShouldSandbox(bool* in_sandbox
) OVERRIDE
{
309 #if !defined (GOOGLE_CHROME_BUILD)
310 if (CommandLine::ForCurrentProcess()->HasSwitch(
311 switches::kInProcessPlugins
)) {
317 virtual void PreSpawnTarget(sandbox::TargetPolicy
* policy
,
319 AddBaseHandleClosePolicy(policy
);
320 GetContentClient()->browser()->PreSpawnRenderer(policy
, success
);
327 // Stores the maximum number of renderer processes the content module can
329 static size_t g_max_renderer_count_override
= 0;
332 size_t RenderProcessHost::GetMaxRendererProcessCount() {
333 if (g_max_renderer_count_override
)
334 return g_max_renderer_count_override
;
336 // Defines the maximum number of renderer processes according to the
337 // amount of installed memory as reported by the OS. The calculation
338 // assumes that you want the renderers to use half of the installed
339 // RAM and assuming that each WebContents uses ~40MB.
340 // If you modify this assumption, you need to adjust the
341 // ThirtyFourTabs test to match the expected number of processes.
343 // With the given amounts of installed memory below on a 32-bit CPU,
344 // the maximum renderer count will roughly be as follows:
350 // 16384 MB -> 82 (kMaxRendererProcessCount)
352 static size_t max_count
= 0;
354 const size_t kEstimatedWebContentsMemoryUsage
=
355 #if defined(ARCH_CPU_64_BITS)
360 max_count
= base::SysInfo::AmountOfPhysicalMemoryMB() / 2;
361 max_count
/= kEstimatedWebContentsMemoryUsage
;
363 const size_t kMinRendererProcessCount
= 3;
364 max_count
= std::max(max_count
, kMinRendererProcessCount
);
365 max_count
= std::min(max_count
, kMaxRendererProcessCount
);
371 bool g_run_renderer_in_process_
= false;
374 void RenderProcessHost::SetMaxRendererProcessCount(size_t count
) {
375 g_max_renderer_count_override
= count
;
378 RenderProcessHostImpl::RenderProcessHostImpl(
379 BrowserContext
* browser_context
,
380 StoragePartitionImpl
* storage_partition_impl
,
381 bool supports_browser_plugin
,
383 : fast_shutdown_started_(false),
384 deleting_soon_(false),
388 cached_dibs_cleaner_(
389 FROM_HERE
, base::TimeDelta::FromSeconds(5),
390 this, &RenderProcessHostImpl::ClearTransportDIBCache
),
391 is_initialized_(false),
392 id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()),
393 browser_context_(browser_context
),
394 storage_partition_impl_(storage_partition_impl
),
395 sudden_termination_allowed_(true),
396 ignore_input_events_(false),
397 supports_browser_plugin_(supports_browser_plugin
),
399 gpu_observer_registered_(false) {
400 widget_helper_
= new RenderWidgetHelper();
402 ChildProcessSecurityPolicyImpl::GetInstance()->Add(GetID());
404 CHECK(!g_exited_main_message_loop
);
405 RegisterHost(GetID(), this);
406 g_all_hosts
.Get().set_check_on_null_data(true);
407 // Initialize |child_process_activity_time_| to a reasonable value.
408 mark_child_process_activity_time();
410 if (!GetBrowserContext()->IsOffTheRecord() &&
411 !CommandLine::ForCurrentProcess()->HasSwitch(
412 switches::kDisableGpuShaderDiskCache
)) {
413 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
414 base::Bind(&CacheShaderInfo
, GetID(),
415 storage_partition_impl_
->GetPath()));
418 // Note: When we create the RenderProcessHostImpl, it's technically
419 // backgrounded, because it has no visible listeners. But the process
420 // doesn't actually exist yet, so we'll Background it later, after
424 RenderProcessHostImpl::~RenderProcessHostImpl() {
425 DCHECK(!run_renderer_in_process());
426 ChildProcessSecurityPolicyImpl::GetInstance()->Remove(GetID());
428 if (gpu_observer_registered_
) {
429 GpuDataManagerImpl::GetInstance()->RemoveObserver(this);
430 gpu_observer_registered_
= false;
433 // We may have some unsent messages at this point, but that's OK.
435 while (!queued_messages_
.empty()) {
436 delete queued_messages_
.front();
437 queued_messages_
.pop();
440 ClearTransportDIBCache();
441 UnregisterHost(GetID());
443 if (!CommandLine::ForCurrentProcess()->HasSwitch(
444 switches::kDisableGpuShaderDiskCache
)) {
445 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
446 base::Bind(&RemoveShaderInfo
, GetID()));
450 void RenderProcessHostImpl::EnableSendQueue() {
451 is_initialized_
= false;
454 bool RenderProcessHostImpl::Init() {
455 // calling Init() more than once does nothing, this makes it more convenient
456 // for the view host which may not be sure in some cases
460 CommandLine::StringType renderer_prefix
;
461 #if defined(OS_POSIX)
462 // A command prefix is something prepended to the command line of the spawned
463 // process. It is supported only on POSIX systems.
464 const CommandLine
& browser_command_line
= *CommandLine::ForCurrentProcess();
466 browser_command_line
.GetSwitchValueNative(switches::kRendererCmdPrefix
);
467 #endif // defined(OS_POSIX)
469 #if defined(OS_LINUX)
470 int flags
= renderer_prefix
.empty() ? ChildProcessHost::CHILD_ALLOW_SELF
:
471 ChildProcessHost::CHILD_NORMAL
;
473 int flags
= ChildProcessHost::CHILD_NORMAL
;
476 // Find the renderer before creating the channel so if this fails early we
477 // return without creating the channel.
478 base::FilePath renderer_path
= ChildProcessHost::GetChildPath(flags
);
479 if (renderer_path
.empty())
482 // Setup the IPC channel.
483 const std::string channel_id
=
484 IPC::Channel::GenerateVerifiedChannelID(std::string());
486 new IPC::ChannelProxy(channel_id
,
487 IPC::Channel::MODE_SERVER
,
489 BrowserThread::GetMessageLoopProxyForThread(
490 BrowserThread::IO
).get()));
492 // Call the embedder first so that their IPC filters have priority.
493 GetContentClient()->browser()->RenderProcessHostCreated(this);
495 CreateMessageFilters();
497 // Single-process mode not supported in split-dll mode.
498 #if !defined(CHROME_SPLIT_DLL)
499 if (run_renderer_in_process()) {
500 // Crank up a thread and run the initialization there. With the way that
501 // messages flow between the browser and renderer, this thread is required
502 // to prevent a deadlock in single-process mode. Since the primordial
503 // thread in the renderer process runs the WebKit code and can sometimes
504 // make blocking calls to the UI thread (i.e. this thread), they need to run
505 // on separate threads.
506 in_process_renderer_
.reset(new RendererMainThread(channel_id
));
508 base::Thread::Options options
;
509 #if defined(OS_WIN) && !defined(OS_MACOSX)
510 // In-process plugins require this to be a UI message loop.
511 options
.message_loop_type
= base::MessageLoop::TYPE_UI
;
513 // We can't have multiple UI loops on Linux and Android, so we don't support
514 // in-process plugins.
515 options
.message_loop_type
= base::MessageLoop::TYPE_DEFAULT
;
517 in_process_renderer_
->StartWithOptions(options
);
519 OnProcessLaunched(); // Fake a callback that the process is ready.
521 #endif // !CHROME_SPLIT_DLL
523 // Build command line for renderer. We call AppendRendererCommandLine()
524 // first so the process type argument will appear first.
525 CommandLine
* cmd_line
= new CommandLine(renderer_path
);
526 if (!renderer_prefix
.empty())
527 cmd_line
->PrependWrapper(renderer_prefix
);
528 AppendRendererCommandLine(cmd_line
);
529 cmd_line
->AppendSwitchASCII(switches::kProcessChannelID
, channel_id
);
531 // Spawn the child process asynchronously to avoid blocking the UI thread.
532 // As long as there's no renderer prefix, we can use the zygote process
534 child_process_launcher_
.reset(new ChildProcessLauncher(
536 new RendererSandboxedProcessLauncherDelegate
,
537 #elif defined(OS_POSIX)
538 renderer_prefix
.empty(),
539 base::EnvironmentVector(),
540 channel_
->TakeClientFileDescriptor(),
546 fast_shutdown_started_
= false;
549 if (!gpu_observer_registered_
) {
550 gpu_observer_registered_
= true;
551 GpuDataManagerImpl::GetInstance()->AddObserver(this);
554 is_initialized_
= true;
558 void RenderProcessHostImpl::CreateMessageFilters() {
559 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
560 channel_
->AddFilter(new ResourceSchedulerFilter(GetID()));
561 MediaInternals
* media_internals
= MediaInternals::GetInstance();;
562 media::AudioManager
* audio_manager
=
563 BrowserMainLoop::GetInstance()->audio_manager();
564 // Add BrowserPluginMessageFilter to ensure it gets the first stab at messages
566 if (supports_browser_plugin_
) {
567 scoped_refptr
<BrowserPluginMessageFilter
> bp_message_filter(
568 new BrowserPluginMessageFilter(GetID(), IsGuest()));
569 channel_
->AddFilter(bp_message_filter
.get());
572 scoped_refptr
<RenderMessageFilter
> render_message_filter(
573 new RenderMessageFilter(
575 #if defined(ENABLE_PLUGINS)
576 PluginServiceImpl::GetInstance(),
581 GetBrowserContext()->GetRequestContextForRenderProcess(GetID()),
582 widget_helper_
.get(),
585 storage_partition_impl_
->GetDOMStorageContext()));
586 channel_
->AddFilter(render_message_filter
.get());
587 BrowserContext
* browser_context
= GetBrowserContext();
588 ResourceContext
* resource_context
= browser_context
->GetResourceContext();
590 ResourceMessageFilter
* resource_message_filter
= new ResourceMessageFilter(
591 GetID(), PROCESS_TYPE_RENDERER
, resource_context
,
592 storage_partition_impl_
->GetAppCacheService(),
593 ChromeBlobStorageContext::GetFor(browser_context
),
594 storage_partition_impl_
->GetFileSystemContext(),
595 new RendererURLRequestContextSelector(browser_context
, GetID()));
597 channel_
->AddFilter(resource_message_filter
);
598 MediaStreamManager
* media_stream_manager
=
599 BrowserMainLoop::GetInstance()->media_stream_manager();
600 channel_
->AddFilter(new AudioInputRendererHost(
602 media_stream_manager
,
603 BrowserMainLoop::GetInstance()->audio_mirroring_manager()));
604 channel_
->AddFilter(new AudioRendererHost(
605 GetID(), audio_manager
,
606 BrowserMainLoop::GetInstance()->audio_mirroring_manager(),
607 media_internals
, media_stream_manager
));
609 new MIDIHost(BrowserMainLoop::GetInstance()->midi_manager()));
610 channel_
->AddFilter(new VideoCaptureHost(media_stream_manager
));
611 channel_
->AddFilter(new AppCacheDispatcherHost(
612 storage_partition_impl_
->GetAppCacheService(),
614 channel_
->AddFilter(new ClipboardMessageFilter
);
615 channel_
->AddFilter(new DOMStorageMessageFilter(
617 storage_partition_impl_
->GetDOMStorageContext()));
618 channel_
->AddFilter(new IndexedDBDispatcherHost(
620 storage_partition_impl_
->GetIndexedDBContext()));
622 if (!g_browser_plugin_geolocation_context
.Get().get()) {
623 g_browser_plugin_geolocation_context
.Get() =
624 new BrowserPluginGeolocationPermissionContext();
626 channel_
->AddFilter(GeolocationDispatcherHost::New(
627 GetID(), g_browser_plugin_geolocation_context
.Get().get()));
629 channel_
->AddFilter(GeolocationDispatcherHost::New(
630 GetID(), browser_context
->GetGeolocationPermissionContext()));
632 gpu_message_filter_
= new GpuMessageFilter(GetID(), widget_helper_
.get());
633 channel_
->AddFilter(gpu_message_filter_
);
634 #if defined(ENABLE_WEBRTC)
635 peer_connection_tracker_host_
= new PeerConnectionTrackerHost(GetID());
636 channel_
->AddFilter(peer_connection_tracker_host_
.get());
637 channel_
->AddFilter(new MediaStreamDispatcherHost(
638 GetID(), media_stream_manager
));
640 #if defined(ENABLE_PLUGINS)
641 // TODO(raymes): PepperMessageFilter should be removed from here.
642 channel_
->AddFilter(new PepperMessageFilter(GetID(), browser_context
));
643 channel_
->AddFilter(new PepperRendererConnection
);
645 #if defined(ENABLE_INPUT_SPEECH)
646 channel_
->AddFilter(new InputTagSpeechDispatcherHost(
647 IsGuest(), GetID(), storage_partition_impl_
->GetURLRequestContext(),
648 browser_context
->GetSpeechRecognitionPreferences()));
650 channel_
->AddFilter(new SpeechRecognitionDispatcherHost(
651 GetID(), storage_partition_impl_
->GetURLRequestContext(),
652 browser_context
->GetSpeechRecognitionPreferences()));
653 channel_
->AddFilter(new FileAPIMessageFilter(
655 storage_partition_impl_
->GetURLRequestContext(),
656 storage_partition_impl_
->GetFileSystemContext(),
657 ChromeBlobStorageContext::GetFor(browser_context
)));
658 channel_
->AddFilter(new OrientationMessageFilter());
659 channel_
->AddFilter(new FileUtilitiesMessageFilter(GetID()));
660 channel_
->AddFilter(new MimeRegistryMessageFilter());
661 channel_
->AddFilter(new DatabaseMessageFilter(
662 storage_partition_impl_
->GetDatabaseTracker()));
663 #if defined(OS_MACOSX)
664 channel_
->AddFilter(new TextInputClientMessageFilter(GetID()));
665 #elif defined(OS_WIN)
666 channel_
->AddFilter(new FontCacheDispatcher());
669 SocketStreamDispatcherHost
* socket_stream_dispatcher_host
=
670 new SocketStreamDispatcherHost(GetID(),
671 new RendererURLRequestContextSelector(browser_context
, GetID()),
673 channel_
->AddFilter(socket_stream_dispatcher_host
);
675 channel_
->AddFilter(new WorkerMessageFilter(
678 WorkerStoragePartition(
679 storage_partition_impl_
->GetURLRequestContext(),
680 storage_partition_impl_
->GetMediaURLRequestContext(),
681 storage_partition_impl_
->GetAppCacheService(),
682 storage_partition_impl_
->GetQuotaManager(),
683 storage_partition_impl_
->GetFileSystemContext(),
684 storage_partition_impl_
->GetDatabaseTracker(),
685 storage_partition_impl_
->GetIndexedDBContext()),
686 base::Bind(&RenderWidgetHelper::GetNextRoutingID
,
687 base::Unretained(widget_helper_
.get()))));
689 #if defined(ENABLE_WEBRTC)
690 channel_
->AddFilter(new P2PSocketDispatcherHost(
692 browser_context
->GetRequestContextForRenderProcess(GetID())));
695 channel_
->AddFilter(new TraceMessageFilter());
696 channel_
->AddFilter(new ResolveProxyMsgHelper(
697 browser_context
->GetRequestContextForRenderProcess(GetID())));
698 channel_
->AddFilter(new QuotaDispatcherHost(
700 storage_partition_impl_
->GetQuotaManager(),
701 GetContentClient()->browser()->CreateQuotaPermissionContext()));
702 channel_
->AddFilter(new GamepadBrowserMessageFilter());
703 channel_
->AddFilter(new ProfilerMessageFilter(PROCESS_TYPE_RENDERER
));
704 channel_
->AddFilter(new HistogramMessageFilter());
705 channel_
->AddFilter(new HyphenatorMessageFilter(this));
706 #if defined(USE_TCMALLOC) && (defined(OS_LINUX) || defined(OS_ANDROID))
707 if (CommandLine::ForCurrentProcess()->HasSwitch(
708 switches::kEnableMemoryBenchmarking
))
709 channel_
->AddFilter(new MemoryBenchmarkMessageFilter());
713 int RenderProcessHostImpl::GetNextRoutingID() {
714 return widget_helper_
->GetNextRoutingID();
718 void RenderProcessHostImpl::ResumeDeferredNavigation(
719 const GlobalRequestID
& request_id
) {
720 widget_helper_
->ResumeDeferredNavigation(request_id
);
723 void RenderProcessHostImpl::AddRoute(
725 IPC::Listener
* listener
) {
726 listeners_
.AddWithID(listener
, routing_id
);
729 void RenderProcessHostImpl::RemoveRoute(int32 routing_id
) {
730 DCHECK(listeners_
.Lookup(routing_id
) != NULL
);
731 listeners_
.Remove(routing_id
);
734 // Dump the handle table if handle auditing is enabled.
735 const CommandLine
& browser_command_line
=
736 *CommandLine::ForCurrentProcess();
737 if (browser_command_line
.HasSwitch(switches::kAuditHandles
) ||
738 browser_command_line
.HasSwitch(switches::kAuditAllHandles
)) {
741 // We wait to close the channels until the child process has finished
742 // dumping handles and sends us ChildProcessHostMsg_DumpHandlesDone.
746 // Keep the one renderer thread around forever in single process mode.
747 if (!run_renderer_in_process())
751 bool RenderProcessHostImpl::WaitForBackingStoreMsg(
752 int render_widget_id
,
753 const base::TimeDelta
& max_delay
,
755 // The post task to this thread with the process id could be in queue, and we
756 // don't want to dispatch a message before then since it will need the handle.
757 if (child_process_launcher_
.get() && child_process_launcher_
->IsStarting())
760 return widget_helper_
->WaitForBackingStoreMsg(render_widget_id
,
764 void RenderProcessHostImpl::ReceivedBadMessage() {
765 if (run_renderer_in_process()) {
766 // In single process mode it is better if we don't suicide but just
770 // We kill the renderer but don't include a NOTREACHED, because we want the
771 // browser to try to survive when it gets illegal messages from the renderer.
772 base::KillProcess(GetHandle(), RESULT_CODE_KILLED_BAD_MESSAGE
,
776 void RenderProcessHostImpl::WidgetRestored() {
777 // Verify we were properly backgrounded.
778 DCHECK_EQ(backgrounded_
, (visible_widgets_
== 0));
780 SetBackgrounded(false);
783 void RenderProcessHostImpl::WidgetHidden() {
784 // On startup, the browser will call Hide
788 DCHECK_EQ(backgrounded_
, (visible_widgets_
== 0));
790 DCHECK_GE(visible_widgets_
, 0);
791 if (visible_widgets_
== 0) {
792 DCHECK(!backgrounded_
);
793 SetBackgrounded(true);
797 int RenderProcessHostImpl::VisibleWidgetCount() const {
798 return visible_widgets_
;
801 bool RenderProcessHostImpl::IsGuest() const {
805 StoragePartition
* RenderProcessHostImpl::GetStoragePartition() const {
806 return storage_partition_impl_
;
809 void RenderProcessHostImpl::AppendRendererCommandLine(
810 CommandLine
* command_line
) const {
811 // Pass the process type first, so it shows first in process listings.
812 command_line
->AppendSwitchASCII(switches::kProcessType
,
813 switches::kRendererProcess
);
815 // Now send any options from our own command line we want to propagate.
816 const CommandLine
& browser_command_line
= *CommandLine::ForCurrentProcess();
817 PropagateBrowserCommandLineToRenderer(browser_command_line
, command_line
);
819 // Pass on the browser locale.
820 const std::string locale
=
821 GetContentClient()->browser()->GetApplicationLocale();
822 command_line
->AppendSwitchASCII(switches::kLang
, locale
);
824 // If we run base::FieldTrials, we want to pass to their state to the
825 // renderer so that it can act in accordance with each state, or record
826 // histograms relating to the base::FieldTrial states.
827 std::string field_trial_states
;
828 base::FieldTrialList::StatesToString(&field_trial_states
);
829 if (!field_trial_states
.empty()) {
830 command_line
->AppendSwitchASCII(switches::kForceFieldTrials
,
834 GetContentClient()->browser()->AppendExtraCommandLineSwitches(
835 command_line
, GetID());
837 // Appending disable-gpu-feature switches due to software rendering list.
838 GpuDataManagerImpl
* gpu_data_manager
= GpuDataManagerImpl::GetInstance();
839 DCHECK(gpu_data_manager
);
840 gpu_data_manager
->AppendRendererCommandLine(command_line
);
843 void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
844 const CommandLine
& browser_cmd
,
845 CommandLine
* renderer_cmd
) const {
846 // Propagate the following switches to the renderer command line (along
847 // with any associated values) if present in the browser command line.
848 static const char* const kSwitchNames
[] = {
849 switches::kAudioBufferSize
,
850 switches::kAuditAllHandles
,
851 switches::kAuditHandles
,
852 switches::kDisable3DAPIs
,
853 switches::kDisableAcceleratedCompositing
,
854 switches::kDisableAcceleratedVideoDecode
,
855 switches::kDisableApplicationCache
,
856 switches::kDisableAudio
,
857 switches::kDisableBreakpad
,
858 switches::kDisableDatabases
,
859 switches::kDisableDesktopNotifications
,
860 switches::kDisableDeviceOrientation
,
861 switches::kDisableFileSystem
,
862 switches::kDisableGeolocation
,
863 switches::kDisableGLMultisampling
,
864 switches::kDisableGpuVsync
,
865 switches::kDisableGpu
,
866 switches::kDisableHistogramCustomizer
,
867 switches::kDisableJavaScriptI18NAPI
,
868 switches::kDisableLocalStorage
,
869 switches::kDisableLogging
,
870 switches::kDisableNewDialogStyle
,
871 switches::kDisableSeccompFilterSandbox
,
872 switches::kDisableSessionStorage
,
873 switches::kDisableSharedWorkers
,
874 switches::kDisableSpeechInput
,
875 switches::kDisableTouchDragDrop
,
876 switches::kDisableTouchEditing
,
877 #if defined(OS_ANDROID)
878 switches::kDisableWebRTC
,
879 switches::kEnableSpeechRecognition
,
881 switches::kDisableWebAudio
,
882 #if defined(ENABLE_WEBRTC)
883 switches::kEnableSCTPDataChannels
,
885 switches::kEnableWebMIDI
,
886 switches::kEnableExperimentalCanvasFeatures
,
887 switches::kEnableExperimentalWebSocket
,
888 switches::kDomAutomationController
,
889 switches::kEnableAccessibilityLogging
,
890 switches::kEnableBeginFrameScheduling
,
891 switches::kEnableBrowserInputController
,
892 switches::kEnableBrowserPluginForAllViewTypes
,
893 switches::kEnableDCHECK
,
894 switches::kEnableDelegatedRenderer
,
895 switches::kEnableEncryptedMedia
,
896 switches::kDisableLegacyEncryptedMedia
,
897 switches::kOverrideEncryptedMediaCanPlayType
,
898 switches::kEnableExperimentalWebKitFeatures
,
899 switches::kEnableFixedLayout
,
900 switches::kEnableDeferredImageDecoding
,
901 switches::kEnableGPUServiceLogging
,
902 switches::kEnableGPUClientLogging
,
903 switches::kEnableGpuClientTracing
,
904 switches::kEnableGpuBenchmarking
,
905 switches::kEnableMemoryBenchmarking
,
906 switches::kEnableSkiaBenchmarking
,
907 switches::kEnableLogging
,
908 switches::kEnableSpeechSynthesis
,
909 switches::kEnableTouchDragDrop
,
910 switches::kEnableTouchEditing
,
911 #if defined(ENABLE_WEBRTC)
912 switches::kEnableWebRtcAecRecordings
,
913 switches::kEnableWebRtcTcpServerSocket
,
915 #if defined(ANDROID) && !defined(GOOGLE_TV)
916 switches::kEnableWebKitMediaSource
,
918 switches::kDisableWebKitMediaSource
,
920 switches::kEnableOverscrollNotifications
,
921 switches::kEnableStrictSiteIsolation
,
922 switches::kDisableFullScreen
,
923 switches::kEnableNewDialogStyle
,
924 #if defined(ENABLE_PLUGINS)
925 switches::kEnablePepperTesting
,
926 switches::kDisablePepper3d
,
928 switches::kEnablePreparsedJsCaching
,
929 switches::kEnablePruneGpuCommandBuffers
,
930 switches::kEnablePinch
,
931 switches::kDisablePinch
,
932 #if defined(OS_MACOSX)
933 // Allow this to be set when invoking the browser and relayed along.
934 switches::kEnableSandboxLogging
,
936 switches::kEnableSoftwareCompositingGLAdapter
,
937 switches::kEnableStatsTable
,
938 switches::kEnableThreadedCompositing
,
939 switches::kEnableCompositingForFixedPosition
,
940 switches::kEnableHighDpiCompositingForFixedPosition
,
941 switches::kDisableCompositingForFixedPosition
,
942 switches::kEnableCompositingForTransition
,
943 switches::kDisableCompositingForTransition
,
944 switches::kDisableThreadedCompositing
,
945 switches::kDisableTouchAdjustment
,
946 switches::kDefaultTileWidth
,
947 switches::kDefaultTileHeight
,
948 switches::kMaxUntiledLayerWidth
,
949 switches::kMaxUntiledLayerHeight
,
950 switches::kEnableViewport
,
951 switches::kEnableOpusPlayback
,
952 switches::kEnableVp8AlphaPlayback
,
953 switches::kEnableEac3Playback
,
954 switches::kForceDeviceScaleFactor
,
955 switches::kFullMemoryCrashReport
,
956 #if !defined (GOOGLE_CHROME_BUILD)
957 // These are unsupported and not fully tested modes, so don't enable them
958 // for official Google Chrome builds.
959 switches::kInProcessPlugins
,
960 #endif // GOOGLE_CHROME_BUILD
961 switches::kJavaScriptFlags
,
962 switches::kLoggingLevel
,
963 switches::kMemoryMetrics
,
964 #if defined(OS_ANDROID)
965 switches::kNetworkCountryIso
,
966 switches::kDisableGestureRequirementForMediaPlayback
,
967 switches::kRetainVideoPlaybackOnLostFocus
,
969 #if defined(GOOGLE_TV)
970 switches::kUseExternalVideoSurfaceThresholdInPixels
,
972 switches::kNoReferrers
,
973 switches::kNoSandbox
,
974 switches::kEnableVtune
,
975 switches::kPpapiInProcess
,
976 switches::kRegisterPepperPlugins
,
977 switches::kRendererAssertTest
,
978 #if defined(OS_POSIX)
979 switches::kChildCleanExit
,
981 switches::kRendererStartupDialog
,
982 switches::kShowPaintRects
,
983 switches::kSitePerProcess
,
984 switches::kStatsCollectionController
,
985 switches::kTestSandbox
,
986 switches::kTouchEvents
,
987 switches::kTraceStartup
,
988 // This flag needs to be propagated to the renderer process for
989 // --in-process-webgl.
991 switches::kUseMobileUserAgent
,
992 switches::kUserAgent
,
994 switches::kVideoThreads
,
996 switches::kWebCoreLogChannels
,
997 switches::kEnableWebGLDraftExtensions
,
998 // Please keep these in alphabetical order. Compositor switches here should
999 // also be added to chrome/browser/chromeos/login/chrome_restart_request.cc.
1000 cc::switches::kBackgroundColorInsteadOfCheckerboard
,
1001 cc::switches::kCompositeToMailbox
,
1002 cc::switches::kDisableColorEstimator
,
1003 cc::switches::kDisableImplSidePainting
,
1004 cc::switches::kDisableThreadedAnimation
,
1005 cc::switches::kEnableImplSidePainting
,
1006 cc::switches::kEnablePartialSwap
,
1007 cc::switches::kEnablePerTilePainting
,
1008 cc::switches::kEnablePinchVirtualViewport
,
1009 cc::switches::kEnableTopControlsPositionCalculation
,
1010 cc::switches::kForceDirectLayerDrawing
,
1011 cc::switches::kLowResolutionContentsScaleFactor
,
1012 cc::switches::kMaxTilesForInterestArea
,
1013 cc::switches::kMaxUnusedResourceMemoryUsagePercentage
,
1014 cc::switches::kNumRasterThreads
,
1015 cc::switches::kShowCompositedLayerBorders
,
1016 cc::switches::kShowFPSCounter
,
1017 cc::switches::kShowNonOccludingRects
,
1018 cc::switches::kShowOccludingRects
,
1019 cc::switches::kShowPropertyChangedRects
,
1020 cc::switches::kShowReplicaScreenSpaceRects
,
1021 cc::switches::kShowScreenSpaceRects
,
1022 cc::switches::kShowSurfaceDamageRects
,
1023 cc::switches::kSlowDownRasterScaleFactor
,
1024 cc::switches::kStrictLayerPropertyChangeChecking
,
1025 cc::switches::kTopControlsHeight
,
1026 cc::switches::kTopControlsHideThreshold
,
1027 cc::switches::kTopControlsShowThreshold
,
1028 cc::switches::kTraceOverdraw
,
1029 cc::switches::kUseMapImage
,
1031 renderer_cmd
->CopySwitchesFrom(browser_cmd
, kSwitchNames
,
1032 arraysize(kSwitchNames
));
1034 // Disable databases in incognito mode.
1035 if (GetBrowserContext()->IsOffTheRecord() &&
1036 !browser_cmd
.HasSwitch(switches::kDisableDatabases
)) {
1037 renderer_cmd
->AppendSwitch(switches::kDisableDatabases
);
1038 #if defined(OS_ANDROID)
1039 renderer_cmd
->AppendSwitch(switches::kDisableMediaHistoryLogging
);
1043 // Enforce the extra command line flags for impl-side painting.
1044 if (cc::switches::IsImplSidePaintingEnabled() &&
1045 !browser_cmd
.HasSwitch(switches::kEnableDeferredImageDecoding
))
1046 renderer_cmd
->AppendSwitch(switches::kEnableDeferredImageDecoding
);
1049 base::ProcessHandle
RenderProcessHostImpl::GetHandle() const {
1050 if (run_renderer_in_process())
1051 return base::Process::Current().handle();
1053 if (!child_process_launcher_
.get() || child_process_launcher_
->IsStarting())
1054 return base::kNullProcessHandle
;
1056 return child_process_launcher_
->GetHandle();
1059 bool RenderProcessHostImpl::FastShutdownIfPossible() {
1060 if (run_renderer_in_process())
1061 return false; // Single process mode never shutdown the renderer.
1063 if (!GetContentClient()->browser()->IsFastShutdownPossible())
1066 if (!child_process_launcher_
.get() ||
1067 child_process_launcher_
->IsStarting() ||
1069 return false; // Render process hasn't started or is probably crashed.
1071 // Test if there's an unload listener.
1072 // NOTE: It's possible that an onunload listener may be installed
1073 // while we're shutting down, so there's a small race here. Given that
1074 // the window is small, it's unlikely that the web page has much
1075 // state that will be lost by not calling its unload handlers properly.
1076 if (!SuddenTerminationAllowed())
1079 ProcessDied(false /* already_dead */);
1080 fast_shutdown_started_
= true;
1084 void RenderProcessHostImpl::DumpHandles() {
1086 Send(new ChildProcessMsg_DumpHandles());
1093 // This is a platform specific function for mapping a transport DIB given its id
1094 TransportDIB
* RenderProcessHostImpl::MapTransportDIB(
1095 TransportDIB::Id dib_id
) {
1097 // On Windows we need to duplicate the handle from the remote process
1099 DuplicateHandle(GetHandle(), dib_id
.handle
, GetCurrentProcess(), §ion
,
1100 STANDARD_RIGHTS_REQUIRED
| FILE_MAP_READ
| FILE_MAP_WRITE
,
1102 return TransportDIB::Map(section
);
1103 #elif defined(TOOLKIT_GTK)
1104 return TransportDIB::Map(dib_id
.shmkey
);
1105 #elif defined(OS_ANDROID)
1106 return TransportDIB::Map(dib_id
);
1108 // On POSIX, the browser allocates all DIBs and keeps a file descriptor around
1110 return widget_helper_
->MapTransportDIB(dib_id
);
1114 TransportDIB
* RenderProcessHostImpl::GetTransportDIB(
1115 TransportDIB::Id dib_id
) {
1116 if (!TransportDIB::is_valid_id(dib_id
))
1119 const std::map
<TransportDIB::Id
, TransportDIB
*>::iterator
1120 i
= cached_dibs_
.find(dib_id
);
1121 if (i
!= cached_dibs_
.end()) {
1122 cached_dibs_cleaner_
.Reset();
1126 TransportDIB
* dib
= MapTransportDIB(dib_id
);
1130 if (cached_dibs_
.size() >= MAX_MAPPED_TRANSPORT_DIBS
) {
1131 // Clean a single entry from the cache
1132 std::map
<TransportDIB::Id
, TransportDIB
*>::iterator smallest_iterator
;
1133 size_t smallest_size
= std::numeric_limits
<size_t>::max();
1135 for (std::map
<TransportDIB::Id
, TransportDIB
*>::iterator
1136 i
= cached_dibs_
.begin(); i
!= cached_dibs_
.end(); ++i
) {
1137 if (i
->second
->size() <= smallest_size
) {
1138 smallest_iterator
= i
;
1139 smallest_size
= i
->second
->size();
1143 #if defined(TOOLKIT_GTK)
1144 smallest_iterator
->second
->Detach();
1146 delete smallest_iterator
->second
;
1148 cached_dibs_
.erase(smallest_iterator
);
1151 cached_dibs_
[dib_id
] = dib
;
1152 cached_dibs_cleaner_
.Reset();
1156 void RenderProcessHostImpl::ClearTransportDIBCache() {
1157 #if defined(TOOLKIT_GTK)
1158 std::map
<TransportDIB::Id
, TransportDIB
*>::const_iterator dib
=
1159 cached_dibs_
.begin();
1160 for (; dib
!= cached_dibs_
.end(); ++dib
)
1161 dib
->second
->Detach();
1163 STLDeleteContainerPairSecondPointers(
1164 cached_dibs_
.begin(), cached_dibs_
.end());
1166 cached_dibs_
.clear();
1169 bool RenderProcessHostImpl::Send(IPC::Message
* msg
) {
1171 if (!is_initialized_
) {
1172 queued_messages_
.push(msg
);
1180 if (child_process_launcher_
.get() && child_process_launcher_
->IsStarting()) {
1181 queued_messages_
.push(msg
);
1185 return channel_
->Send(msg
);
1188 bool RenderProcessHostImpl::OnMessageReceived(const IPC::Message
& msg
) {
1189 // If we're about to be deleted, or have initiated the fast shutdown sequence,
1190 // we ignore incoming messages.
1192 if (deleting_soon_
|| fast_shutdown_started_
)
1195 mark_child_process_activity_time();
1196 if (msg
.routing_id() == MSG_ROUTING_CONTROL
) {
1197 // Dispatch control messages.
1198 bool msg_is_ok
= true;
1199 IPC_BEGIN_MESSAGE_MAP_EX(RenderProcessHostImpl
, msg
, msg_is_ok
)
1200 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_ShutdownRequest
,
1202 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_DumpHandlesDone
,
1204 IPC_MESSAGE_HANDLER(ViewHostMsg_SuddenTerminationChanged
,
1205 SuddenTerminationChanged
)
1206 IPC_MESSAGE_HANDLER(ViewHostMsg_UserMetricsRecordAction
,
1207 OnUserMetricsRecordAction
)
1208 IPC_MESSAGE_HANDLER(ViewHostMsg_SavedPageAsMHTML
, OnSavedPageAsMHTML
)
1209 // Adding single handlers for your service here is fine, but once your
1210 // service needs more than one handler, please extract them into a new
1211 // message filter and add that filter to CreateMessageFilters().
1212 IPC_MESSAGE_UNHANDLED_ERROR()
1213 IPC_END_MESSAGE_MAP_EX()
1216 // The message had a handler, but its de-serialization failed.
1217 // We consider this a capital crime. Kill the renderer if we have one.
1218 LOG(ERROR
) << "bad message " << msg
.type() << " terminating renderer.";
1219 RecordAction(UserMetricsAction("BadMessageTerminate_BRPH"));
1220 ReceivedBadMessage();
1225 // Dispatch incoming messages to the appropriate IPC::Listener.
1226 IPC::Listener
* listener
= listeners_
.Lookup(msg
.routing_id());
1228 if (msg
.is_sync()) {
1229 // The listener has gone away, so we must respond or else the caller will
1230 // hang waiting for a reply.
1231 IPC::Message
* reply
= IPC::SyncMessage::GenerateReply(&msg
);
1232 reply
->set_reply_error();
1236 // If this is a SwapBuffers, we need to ack it if we're not going to handle
1237 // it so that the GPU process doesn't get stuck in unscheduled state.
1238 bool msg_is_ok
= true;
1239 IPC_BEGIN_MESSAGE_MAP_EX(RenderProcessHostImpl
, msg
, msg_is_ok
)
1240 IPC_MESSAGE_HANDLER(ViewHostMsg_CompositorSurfaceBuffersSwapped
,
1241 OnCompositorSurfaceBuffersSwappedNoHost
)
1242 IPC_END_MESSAGE_MAP_EX()
1245 return listener
->OnMessageReceived(msg
);
1248 void RenderProcessHostImpl::OnChannelConnected(int32 peer_pid
) {
1249 #if defined(IPC_MESSAGE_LOG_ENABLED)
1250 Send(new ChildProcessMsg_SetIPCLoggingEnabled(
1251 IPC::Logging::GetInstance()->Enabled()));
1254 tracked_objects::ThreadData::Status status
=
1255 tracked_objects::ThreadData::status();
1256 Send(new ChildProcessMsg_SetProfilerStatus(status
));
1259 void RenderProcessHostImpl::OnChannelError() {
1260 ProcessDied(true /* already_dead */);
1263 BrowserContext
* RenderProcessHostImpl::GetBrowserContext() const {
1264 return browser_context_
;
1267 bool RenderProcessHostImpl::InSameStoragePartition(
1268 StoragePartition
* partition
) const {
1269 return storage_partition_impl_
== partition
;
1272 int RenderProcessHostImpl::GetID() const {
1276 bool RenderProcessHostImpl::HasConnection() const {
1277 return channel_
.get() != NULL
;
1280 void RenderProcessHostImpl::SetIgnoreInputEvents(bool ignore_input_events
) {
1281 ignore_input_events_
= ignore_input_events
;
1284 bool RenderProcessHostImpl::IgnoreInputEvents() const {
1285 return ignore_input_events_
;
1288 void RenderProcessHostImpl::Cleanup() {
1289 // When no other owners of this object, we can delete ourselves
1290 if (listeners_
.IsEmpty()) {
1291 DCHECK_EQ(0, pending_views_
);
1292 NotificationService::current()->Notify(
1293 NOTIFICATION_RENDERER_PROCESS_TERMINATED
,
1294 Source
<RenderProcessHost
>(this),
1295 NotificationService::NoDetails());
1297 base::MessageLoop::current()->DeleteSoon(FROM_HERE
, this);
1298 deleting_soon_
= true;
1299 // It's important not to wait for the DeleteTask to delete the channel
1300 // proxy. Kill it off now. That way, in case the profile is going away, the
1301 // rest of the objects attached to this RenderProcessHost start going
1302 // away first, since deleting the channel proxy will post a
1303 // OnChannelClosed() to IPC::ChannelProxy::Context on the IO thread.
1305 gpu_message_filter_
= NULL
;
1307 // Remove ourself from the list of renderer processes so that we can't be
1308 // reused in between now and when the Delete task runs.
1309 UnregisterHost(GetID());
1313 void RenderProcessHostImpl::AddPendingView() {
1317 void RenderProcessHostImpl::RemovePendingView() {
1318 DCHECK(pending_views_
);
1322 void RenderProcessHostImpl::SetSuddenTerminationAllowed(bool enabled
) {
1323 sudden_termination_allowed_
= enabled
;
1326 bool RenderProcessHostImpl::SuddenTerminationAllowed() const {
1327 return sudden_termination_allowed_
;
1330 base::TimeDelta
RenderProcessHostImpl::GetChildProcessIdleTime() const {
1331 return base::TimeTicks::Now() - child_process_activity_time_
;
1334 void RenderProcessHostImpl::SurfaceUpdated(int32 surface_id
) {
1335 if (!gpu_message_filter_
)
1337 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
, base::Bind(
1338 &GpuMessageFilter::SurfaceUpdated
,
1339 gpu_message_filter_
,
1343 void RenderProcessHostImpl::ResumeRequestsForView(int route_id
) {
1344 widget_helper_
->ResumeRequestsForView(route_id
);
1347 IPC::ChannelProxy
* RenderProcessHostImpl::GetChannel() {
1348 return channel_
.get();
1351 bool RenderProcessHostImpl::FastShutdownForPageCount(size_t count
) {
1352 if (static_cast<size_t>(GetActiveViewCount()) == count
)
1353 return FastShutdownIfPossible();
1357 bool RenderProcessHostImpl::FastShutdownStarted() const {
1358 return fast_shutdown_started_
;
1362 void RenderProcessHostImpl::RegisterHost(int host_id
, RenderProcessHost
* host
) {
1363 g_all_hosts
.Get().AddWithID(host
, host_id
);
1367 void RenderProcessHostImpl::UnregisterHost(int host_id
) {
1368 RenderProcessHost
* host
= g_all_hosts
.Get().Lookup(host_id
);
1372 g_all_hosts
.Get().Remove(host_id
);
1374 // Look up the map of site to process for the given browser_context,
1375 // in case we need to remove this process from it. It will be registered
1376 // under any sites it rendered that use process-per-site mode.
1377 SiteProcessMap
* map
=
1378 GetSiteProcessMapForBrowserContext(host
->GetBrowserContext());
1379 map
->RemoveProcess(host
);
1383 bool RenderProcessHostImpl::IsSuitableHost(
1384 RenderProcessHost
* host
,
1385 BrowserContext
* browser_context
,
1386 const GURL
& site_url
) {
1387 if (run_renderer_in_process())
1390 if (host
->GetBrowserContext() != browser_context
)
1393 // Check whether the given host and the intended site_url will be using the
1394 // same StoragePartition, since a RenderProcessHost can only support a single
1395 // StoragePartition. This is relevant for packaged apps, browser tags, and
1397 StoragePartition
* dest_partition
=
1398 BrowserContext::GetStoragePartitionForSite(browser_context
, site_url
);
1399 if (!host
->InSameStoragePartition(dest_partition
))
1402 // All URLs are suitable if this is associated with a guest renderer process.
1403 // TODO(fsamuel, creis): Further validation is needed to ensure that only
1404 // normal web URLs are permitted in guest processes. We need to investigate
1405 // where this validation should happen.
1406 if (host
->IsGuest())
1409 if (!host
->IsGuest() && site_url
.SchemeIs(chrome::kGuestScheme
))
1412 if (ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1414 WebUIControllerFactoryRegistry::GetInstance()->UseWebUIBindingsForURL(
1415 browser_context
, site_url
)) {
1419 return GetContentClient()->browser()->IsSuitableHost(host
, site_url
);
1423 bool RenderProcessHost::run_renderer_in_process() {
1424 return g_run_renderer_in_process_
;
1428 void RenderProcessHost::SetRunRendererInProcess(bool value
) {
1429 g_run_renderer_in_process_
= value
;
1431 CommandLine
* command_line
= CommandLine::ForCurrentProcess();
1432 if (value
&& !command_line
->HasSwitch(switches::kLang
)) {
1433 // Modify the current process' command line to include the browser locale,
1434 // as the renderer expects this flag to be set.
1435 const std::string locale
=
1436 GetContentClient()->browser()->GetApplicationLocale();
1437 command_line
->AppendSwitchASCII(switches::kLang
, locale
);
1441 RenderProcessHost::iterator
RenderProcessHost::AllHostsIterator() {
1442 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
1443 return iterator(g_all_hosts
.Pointer());
1447 RenderProcessHost
* RenderProcessHost::FromID(int render_process_id
) {
1448 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
1449 return g_all_hosts
.Get().Lookup(render_process_id
);
1453 bool RenderProcessHost::ShouldTryToUseExistingProcessHost(
1454 BrowserContext
* browser_context
, const GURL
& url
) {
1456 // If --enable-strict-site-isolation or --site-per-process is enabled, do not
1457 // try to reuse renderer processes when over the limit. (We could allow pages
1458 // from the same site to share, if we knew what the given process was
1459 // dedicated to. Allowing no sharing is simpler for now.) This may cause
1460 // resource exhaustion issues if too many sites are open at once.
1461 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
1462 if (command_line
.HasSwitch(switches::kEnableStrictSiteIsolation
) ||
1463 command_line
.HasSwitch(switches::kSitePerProcess
))
1466 if (run_renderer_in_process())
1469 // NOTE: Sometimes it's necessary to create more render processes than
1470 // GetMaxRendererProcessCount(), for instance when we want to create
1471 // a renderer process for a browser context that has no existing
1472 // renderers. This is OK in moderation, since the
1473 // GetMaxRendererProcessCount() is conservative.
1474 if (g_all_hosts
.Get().size() >= GetMaxRendererProcessCount())
1477 return GetContentClient()->browser()->
1478 ShouldTryToUseExistingProcessHost(browser_context
, url
);
1482 RenderProcessHost
* RenderProcessHost::GetExistingProcessHost(
1483 BrowserContext
* browser_context
,
1484 const GURL
& site_url
) {
1485 // First figure out which existing renderers we can use.
1486 std::vector
<RenderProcessHost
*> suitable_renderers
;
1487 suitable_renderers
.reserve(g_all_hosts
.Get().size());
1489 iterator
iter(AllHostsIterator());
1490 while (!iter
.IsAtEnd()) {
1491 if (RenderProcessHostImpl::IsSuitableHost(
1492 iter
.GetCurrentValue(),
1493 browser_context
, site_url
))
1494 suitable_renderers
.push_back(iter
.GetCurrentValue());
1499 // Now pick a random suitable renderer, if we have any.
1500 if (!suitable_renderers
.empty()) {
1501 int suitable_count
= static_cast<int>(suitable_renderers
.size());
1502 int random_index
= base::RandInt(0, suitable_count
- 1);
1503 return suitable_renderers
[random_index
];
1510 bool RenderProcessHost::ShouldUseProcessPerSite(
1511 BrowserContext
* browser_context
,
1513 // Returns true if we should use the process-per-site model. This will be
1514 // the case if the --process-per-site switch is specified, or in
1515 // process-per-site-instance for particular sites (e.g., WebUI).
1516 // Note that --single-process is handled in ShouldTryToUseExistingProcessHost.
1517 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
1518 if (command_line
.HasSwitch(switches::kProcessPerSite
))
1521 // We want to consolidate particular sites like WebUI even when we are using
1522 // the process-per-tab or process-per-site-instance models.
1523 // Note: DevTools pages have WebUI type but should not reuse the same host.
1524 if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL(
1525 browser_context
, url
) &&
1526 !url
.SchemeIs(chrome::kChromeDevToolsScheme
)) {
1530 // Otherwise let the content client decide, defaulting to false.
1531 return GetContentClient()->browser()->ShouldUseProcessPerSite(browser_context
,
1536 RenderProcessHost
* RenderProcessHostImpl::GetProcessHostForSite(
1537 BrowserContext
* browser_context
,
1539 // Look up the map of site to process for the given browser_context.
1540 SiteProcessMap
* map
=
1541 GetSiteProcessMapForBrowserContext(browser_context
);
1543 // See if we have an existing process with appropriate bindings for this site.
1544 // If not, the caller should create a new process and register it.
1545 std::string site
= SiteInstance::GetSiteForURL(browser_context
, url
)
1546 .possibly_invalid_spec();
1547 RenderProcessHost
* host
= map
->FindProcess(site
);
1548 if (host
&& !IsSuitableHost(host
, browser_context
, url
)) {
1549 // The registered process does not have an appropriate set of bindings for
1550 // the url. Remove it from the map so we can register a better one.
1551 RecordAction(UserMetricsAction("BindingsMismatch_GetProcessHostPerSite"));
1552 map
->RemoveProcess(host
);
1559 void RenderProcessHostImpl::RegisterProcessHostForSite(
1560 BrowserContext
* browser_context
,
1561 RenderProcessHost
* process
,
1563 // Look up the map of site to process for the given browser_context.
1564 SiteProcessMap
* map
=
1565 GetSiteProcessMapForBrowserContext(browser_context
);
1567 // Only register valid, non-empty sites. Empty or invalid sites will not
1568 // use process-per-site mode. We cannot check whether the process has
1569 // appropriate bindings here, because the bindings have not yet been granted.
1570 std::string site
= SiteInstance::GetSiteForURL(browser_context
, url
)
1571 .possibly_invalid_spec();
1573 map
->RegisterProcess(site
, process
);
1577 RenderProcessHostImpl::GetInProcessRendererThreadForTesting() {
1578 return g_in_process_thread
;
1581 void RenderProcessHostImpl::ProcessDied(bool already_dead
) {
1582 // Our child process has died. If we didn't expect it, it's a crash.
1583 // In any case, we need to let everyone know it's gone.
1584 // The OnChannelError notification can fire multiple times due to nested sync
1585 // calls to a renderer. If we don't have a valid channel here it means we
1586 // already handled the error.
1588 // child_process_launcher_ can be NULL in single process mode or if fast
1589 // termination happened.
1591 base::TerminationStatus status
=
1592 child_process_launcher_
.get() ?
1593 child_process_launcher_
->GetChildTerminationStatus(already_dead
,
1595 base::TERMINATION_STATUS_NORMAL_TERMINATION
;
1597 RendererClosedDetails
details(GetHandle(), status
, exit_code
);
1598 NotificationService::current()->Notify(
1599 NOTIFICATION_RENDERER_PROCESS_CLOSED
,
1600 Source
<RenderProcessHost
>(this),
1601 Details
<RendererClosedDetails
>(&details
));
1603 child_process_launcher_
.reset();
1605 gpu_message_filter_
= NULL
;
1607 RenderWidgetHost::List widgets
= RenderWidgetHost::GetRenderWidgetHosts();
1608 for (size_t i
= 0; i
< widgets
.size(); ++i
) {
1609 if (widgets
[i
]->GetProcess()->GetID() != GetID())
1611 RenderWidgetHostImpl::From(widgets
[i
])->OnMessageReceived(
1612 ViewHostMsg_RenderViewGone(widgets
[i
]->GetRoutingID(),
1613 static_cast<int>(status
),
1617 ClearTransportDIBCache();
1619 // this object is not deleted at this point and may be reused later.
1620 // TODO(darin): clean this up
1623 int RenderProcessHostImpl::GetActiveViewCount() {
1624 int num_active_views
= 0;
1625 RenderWidgetHost::List widgets
= RenderWidgetHost::GetRenderWidgetHosts();
1626 for (size_t i
= 0; i
< widgets
.size(); ++i
) {
1627 // Count only RenderWidgetHosts in this process.
1628 if (widgets
[i
]->GetProcess()->GetID() != GetID())
1631 // All RenderWidgetHosts are swapped in.
1632 if (!widgets
[i
]->IsRenderView()) {
1637 // Don't count swapped out views.
1638 RenderViewHost
* rvh
= RenderViewHost::From(widgets
[i
]);
1639 if (!static_cast<RenderViewHostImpl
*>(rvh
)->is_swapped_out())
1642 return num_active_views
;
1645 // Frame subscription API for this class is for accelerated composited path
1646 // only. These calls are redirected to GpuMessageFilter.
1647 void RenderProcessHostImpl::BeginFrameSubscription(
1649 scoped_ptr
<RenderWidgetHostViewFrameSubscriber
> subscriber
) {
1650 if (!gpu_message_filter_
)
1652 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
, base::Bind(
1653 &GpuMessageFilter::BeginFrameSubscription
,
1654 gpu_message_filter_
,
1655 route_id
, base::Passed(&subscriber
)));
1658 void RenderProcessHostImpl::EndFrameSubscription(int route_id
) {
1659 if (!gpu_message_filter_
)
1661 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
, base::Bind(
1662 &GpuMessageFilter::EndFrameSubscription
,
1663 gpu_message_filter_
,
1667 void RenderProcessHostImpl::OnShutdownRequest() {
1668 // Don't shut down if there are active RenderViews, or if there are pending
1669 // RenderViews being swapped back in.
1670 // In single process mode, we never shutdown the renderer.
1671 int num_active_views
= GetActiveViewCount();
1672 if (pending_views_
|| num_active_views
> 0 || run_renderer_in_process())
1675 // Notify any contents that might have swapped out renderers from this
1676 // process. They should not attempt to swap them back in.
1677 NotificationService::current()->Notify(
1678 NOTIFICATION_RENDERER_PROCESS_CLOSING
,
1679 Source
<RenderProcessHost
>(this),
1680 NotificationService::NoDetails());
1682 Send(new ChildProcessMsg_Shutdown());
1685 void RenderProcessHostImpl::SuddenTerminationChanged(bool enabled
) {
1686 SetSuddenTerminationAllowed(enabled
);
1689 void RenderProcessHostImpl::OnDumpHandlesDone() {
1693 void RenderProcessHostImpl::SetBackgrounded(bool backgrounded
) {
1694 // Note: we always set the backgrounded_ value. If the process is NULL
1695 // (and hence hasn't been created yet), we will set the process priority
1696 // later when we create the process.
1697 backgrounded_
= backgrounded
;
1698 if (!child_process_launcher_
.get() || child_process_launcher_
->IsStarting())
1702 // The cbstext.dll loads as a global GetMessage hook in the browser process
1703 // and intercepts/unintercepts the kernel32 API SetPriorityClass in a
1704 // background thread. If the UI thread invokes this API just when it is
1705 // intercepted the stack is messed up on return from the interceptor
1706 // which causes random crashes in the browser process. Our hack for now
1707 // is to not invoke the SetPriorityClass API if the dll is loaded.
1708 if (GetModuleHandle(L
"cbstext.dll"))
1712 child_process_launcher_
->SetProcessBackgrounded(backgrounded
);
1715 void RenderProcessHostImpl::OnProcessLaunched() {
1716 // No point doing anything, since this object will be destructed soon. We
1717 // especially don't want to send the RENDERER_PROCESS_CREATED notification,
1718 // since some clients might expect a RENDERER_PROCESS_TERMINATED afterwards to
1719 // properly cleanup.
1723 if (child_process_launcher_
) {
1724 if (!child_process_launcher_
->GetHandle()) {
1729 child_process_launcher_
->SetProcessBackgrounded(backgrounded_
);
1732 // NOTE: This needs to be before sending queued messages because
1733 // ExtensionService uses this notification to initialize the renderer process
1734 // with state that must be there before any JavaScript executes.
1736 // The queued messages contain such things as "navigate". If this notification
1737 // was after, we can end up executing JavaScript before the initialization
1739 NotificationService::current()->Notify(
1740 NOTIFICATION_RENDERER_PROCESS_CREATED
,
1741 Source
<RenderProcessHost
>(this),
1742 NotificationService::NoDetails());
1744 while (!queued_messages_
.empty()) {
1745 Send(queued_messages_
.front());
1746 queued_messages_
.pop();
1750 void RenderProcessHostImpl::OnUserMetricsRecordAction(
1751 const std::string
& action
) {
1752 RecordComputedAction(action
);
1755 void RenderProcessHostImpl::OnSavedPageAsMHTML(int job_id
, int64 data_size
) {
1756 MHTMLGenerationManager::GetInstance()->MHTMLGenerated(job_id
, data_size
);
1759 void RenderProcessHostImpl::OnCompositorSurfaceBuffersSwappedNoHost(
1760 const ViewHostMsg_CompositorSurfaceBuffersSwapped_Params
& params
) {
1761 TRACE_EVENT0("renderer_host",
1762 "RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwappedNoHost");
1763 AcceleratedSurfaceMsg_BufferPresented_Params ack_params
;
1764 ack_params
.sync_point
= 0;
1765 RenderWidgetHostImpl::AcknowledgeBufferPresent(params
.route_id
,
1766 params
.gpu_process_host_id
,
1770 void RenderProcessHostImpl::OnGpuSwitching() {
1771 RenderWidgetHost::List widgets
= RenderWidgetHost::GetRenderWidgetHosts();
1772 for (size_t i
= 0; i
< widgets
.size(); ++i
) {
1773 if (!widgets
[i
]->IsRenderView())
1776 // Skip widgets in other processes.
1777 if (widgets
[i
]->GetProcess()->GetID() != GetID())
1780 RenderViewHost
* rvh
= RenderViewHost::From(widgets
[i
]);
1781 rvh
->UpdateWebkitPreferences(rvh
->GetWebkitPreferences());
1785 } // namespace content