Save errno for logging before potentially overwriting it.
[chromium-blink-merge.git] / content / browser / renderer_host / render_process_host_impl.cc
blob4684d0ee067b7553ad0216341afb5addeaa2e000
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"
10 #include <algorithm>
11 #include <limits>
12 #include <vector>
14 #if defined(OS_POSIX)
15 #include <utility> // for pair<>
16 #endif
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"
133 #if defined(OS_WIN)
134 #include "base/win/scoped_com_initializer.h"
135 #include "content/common/font_cache_dispatcher_win.h"
136 #include "content/common/sandbox_win.h"
137 #include "content/public/common/sandboxed_process_launcher_delegate.h"
138 #endif
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";
146 namespace content {
147 namespace {
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);
159 } // namespace
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 {
164 public:
165 explicit RendererMainThread(const std::string& channel_id)
166 : Thread("Chrome_InProcRendererThread"),
167 channel_id_(channel_id) {
170 virtual ~RendererMainThread() {
171 Stop();
174 protected:
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);
197 private:
198 std::string channel_id_;
199 scoped_ptr<RenderProcess> render_process_;
201 DISALLOW_COPY_AND_ASSIGN(RendererMainThread);
204 namespace {
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 {
210 public:
211 RendererURLRequestContextSelector(BrowserContext* browser_context,
212 int render_child_id)
213 : request_context_(browser_context->GetRequestContextForRenderProcess(
214 render_child_id)),
215 media_request_context_(
216 browser_context->GetMediaRequestContextForRenderProcess(
217 render_child_id)) {
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();
231 private:
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 {
248 public:
249 typedef base::hash_map<std::string, RenderProcessHost*> SiteToProcessMap;
250 SiteProcessMap() {}
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);
258 if (i != map_.end())
259 return i->second;
260 return NULL;
263 void RemoveProcess(RenderProcessHost* host) {
264 // Find all instances of this process in the map, then separately remove
265 // them.
266 std::set<std::string> sites;
267 for (SiteToProcessMap::const_iterator i = map_.begin();
268 i != map_.end();
269 i++) {
270 if (i->second == host)
271 sites.insert(i->first);
273 for (std::set<std::string>::iterator i = sites.begin();
274 i != sites.end();
275 i++) {
276 SiteToProcessMap::iterator iter = map_.find(*i);
277 if (iter != map_.end()) {
278 DCHECK_EQ(iter->second, host);
279 map_.erase(iter);
284 private:
285 SiteToProcessMap map_;
288 // Find the SiteProcessMap specific to the given context.
289 SiteProcessMap* GetSiteProcessMapForBrowserContext(BrowserContext* context) {
290 DCHECK(context);
291 SiteProcessMap* map = static_cast<SiteProcessMap*>(
292 context->GetUserData(kSiteProcessMapKeyName));
293 if (!map) {
294 map = new SiteProcessMap();
295 context->SetUserData(kSiteProcessMapKeyName, map);
297 return map;
300 #if defined(OS_WIN)
301 // NOTE: changes to this class need to be reviewed by the security team.
302 class RendererSandboxedProcessLauncherDelegate
303 : public content::SandboxedProcessLauncherDelegate {
304 public:
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)) {
312 *in_sandbox = false;
314 #endif
317 virtual void PreSpawnTarget(sandbox::TargetPolicy* policy,
318 bool* success) {
319 AddBaseHandleClosePolicy(policy);
320 GetContentClient()->browser()->PreSpawnRenderer(policy, success);
323 #endif // OS_WIN
325 } // namespace
327 // Stores the maximum number of renderer processes the content module can
328 // create.
329 static size_t g_max_renderer_count_override = 0;
331 // static
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:
346 // 128 MB -> 3
347 // 512 MB -> 6
348 // 1024 MB -> 12
349 // 4096 MB -> 51
350 // 16384 MB -> 82 (kMaxRendererProcessCount)
352 static size_t max_count = 0;
353 if (!max_count) {
354 const size_t kEstimatedWebContentsMemoryUsage =
355 #if defined(ARCH_CPU_64_BITS)
356 60; // In MB
357 #else
358 40; // In MB
359 #endif
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);
367 return max_count;
370 // static
371 bool g_run_renderer_in_process_ = false;
373 // static
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,
382 bool is_guest)
383 : fast_shutdown_started_(false),
384 deleting_soon_(false),
385 pending_views_(0),
386 visible_widgets_(0),
387 backgrounded_(true),
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),
398 is_guest_(is_guest),
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
421 // creation.
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.
434 channel_.reset();
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
457 if (channel_)
458 return true;
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();
465 renderer_prefix =
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;
472 #else
473 int flags = ChildProcessHost::CHILD_NORMAL;
474 #endif
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())
480 return false;
482 // Setup the IPC channel.
483 const std::string channel_id =
484 IPC::Channel::GenerateVerifiedChannelID(std::string());
485 channel_.reset(
486 new IPC::ChannelProxy(channel_id,
487 IPC::Channel::MODE_SERVER,
488 this,
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;
512 #else
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;
516 #endif
517 in_process_renderer_->StartWithOptions(options);
519 OnProcessLaunched(); // Fake a callback that the process is ready.
520 } else
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
533 // at this stage.
534 child_process_launcher_.reset(new ChildProcessLauncher(
535 #if defined(OS_WIN)
536 new RendererSandboxedProcessLauncherDelegate,
537 #elif defined(OS_POSIX)
538 renderer_prefix.empty(),
539 base::EnvironmentVector(),
540 channel_->TakeClientFileDescriptor(),
541 #endif
542 cmd_line,
543 GetID(),
544 this));
546 fast_shutdown_started_ = false;
549 if (!gpu_observer_registered_) {
550 gpu_observer_registered_ = true;
551 GpuDataManagerImpl::GetInstance()->AddObserver(this);
554 is_initialized_ = true;
555 return 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
565 // from guests.
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(
574 GetID(),
575 #if defined(ENABLE_PLUGINS)
576 PluginServiceImpl::GetInstance(),
577 #else
578 NULL,
579 #endif
580 GetBrowserContext(),
581 GetBrowserContext()->GetRequestContextForRenderProcess(GetID()),
582 widget_helper_.get(),
583 audio_manager,
584 media_internals,
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(
601 audio_manager,
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));
608 channel_->AddFilter(
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(),
613 GetID()));
614 channel_->AddFilter(new ClipboardMessageFilter);
615 channel_->AddFilter(new DOMStorageMessageFilter(
616 GetID(),
617 storage_partition_impl_->GetDOMStorageContext()));
618 channel_->AddFilter(new IndexedDBDispatcherHost(
619 GetID(),
620 storage_partition_impl_->GetIndexedDBContext()));
621 if (IsGuest()) {
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()));
628 } else {
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));
639 #endif
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);
644 #endif
645 #if defined(ENABLE_INPUT_SPEECH)
646 channel_->AddFilter(new InputTagSpeechDispatcherHost(
647 IsGuest(), GetID(), storage_partition_impl_->GetURLRequestContext(),
648 browser_context->GetSpeechRecognitionPreferences()));
649 #endif
650 channel_->AddFilter(new SpeechRecognitionDispatcherHost(
651 GetID(), storage_partition_impl_->GetURLRequestContext(),
652 browser_context->GetSpeechRecognitionPreferences()));
653 channel_->AddFilter(new FileAPIMessageFilter(
654 GetID(),
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());
667 #endif
669 SocketStreamDispatcherHost* socket_stream_dispatcher_host =
670 new SocketStreamDispatcherHost(GetID(),
671 new RendererURLRequestContextSelector(browser_context, GetID()),
672 resource_context);
673 channel_->AddFilter(socket_stream_dispatcher_host);
675 channel_->AddFilter(new WorkerMessageFilter(
676 GetID(),
677 resource_context,
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(
691 resource_context,
692 browser_context->GetRequestContextForRenderProcess(GetID())));
693 #endif
695 channel_->AddFilter(new TraceMessageFilter());
696 channel_->AddFilter(new ResolveProxyMsgHelper(
697 browser_context->GetRequestContextForRenderProcess(GetID())));
698 channel_->AddFilter(new QuotaDispatcherHost(
699 GetID(),
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());
710 #endif
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(
724 int32 routing_id,
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);
733 #if defined(OS_WIN)
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)) {
739 DumpHandles();
741 // We wait to close the channels until the child process has finished
742 // dumping handles and sends us ChildProcessHostMsg_DumpHandlesDone.
743 return;
745 #endif
746 // Keep the one renderer thread around forever in single process mode.
747 if (!run_renderer_in_process())
748 Cleanup();
751 bool RenderProcessHostImpl::WaitForBackingStoreMsg(
752 int render_widget_id,
753 const base::TimeDelta& max_delay,
754 IPC::Message* msg) {
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())
758 return false;
760 return widget_helper_->WaitForBackingStoreMsg(render_widget_id,
761 max_delay, msg);
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
767 // crash.
768 CHECK(false);
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,
773 false);
776 void RenderProcessHostImpl::WidgetRestored() {
777 // Verify we were properly backgrounded.
778 DCHECK_EQ(backgrounded_, (visible_widgets_ == 0));
779 visible_widgets_++;
780 SetBackgrounded(false);
783 void RenderProcessHostImpl::WidgetHidden() {
784 // On startup, the browser will call Hide
785 if (backgrounded_)
786 return;
788 DCHECK_EQ(backgrounded_, (visible_widgets_ == 0));
789 visible_widgets_--;
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 {
802 return is_guest_;
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,
831 field_trial_states);
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,
880 #endif
881 switches::kDisableWebAudio,
882 #if defined(ENABLE_WEBRTC)
883 switches::kEnableSCTPDataChannels,
884 #endif
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,
914 #endif
915 #if defined(ANDROID) && !defined(GOOGLE_TV)
916 switches::kEnableWebKitMediaSource,
917 #else
918 switches::kDisableWebKitMediaSource,
919 #endif
920 switches::kEnableOverscrollNotifications,
921 switches::kEnableStrictSiteIsolation,
922 switches::kDisableFullScreen,
923 switches::kEnableNewDialogStyle,
924 #if defined(ENABLE_PLUGINS)
925 switches::kEnablePepperTesting,
926 switches::kDisablePepper3d,
927 #endif
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,
935 #endif
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,
968 #endif
969 #if defined(GOOGLE_TV)
970 switches::kUseExternalVideoSurfaceThresholdInPixels,
971 #endif
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,
980 #endif
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.
990 switches::kUseGL,
991 switches::kUseMobileUserAgent,
992 switches::kUserAgent,
993 switches::kV,
994 switches::kVideoThreads,
995 switches::kVModule,
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);
1040 #endif
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())
1064 return false;
1066 if (!child_process_launcher_.get() ||
1067 child_process_launcher_->IsStarting() ||
1068 !GetHandle())
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())
1077 return false;
1079 ProcessDied(false /* already_dead */);
1080 fast_shutdown_started_ = true;
1081 return true;
1084 void RenderProcessHostImpl::DumpHandles() {
1085 #if defined(OS_WIN)
1086 Send(new ChildProcessMsg_DumpHandles());
1087 return;
1088 #endif
1090 NOTIMPLEMENTED();
1093 // This is a platform specific function for mapping a transport DIB given its id
1094 TransportDIB* RenderProcessHostImpl::MapTransportDIB(
1095 TransportDIB::Id dib_id) {
1096 #if defined(OS_WIN)
1097 // On Windows we need to duplicate the handle from the remote process
1098 HANDLE section;
1099 DuplicateHandle(GetHandle(), dib_id.handle, GetCurrentProcess(), &section,
1100 STANDARD_RIGHTS_REQUIRED | FILE_MAP_READ | FILE_MAP_WRITE,
1101 FALSE, 0);
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);
1107 #else
1108 // On POSIX, the browser allocates all DIBs and keeps a file descriptor around
1109 // for each.
1110 return widget_helper_->MapTransportDIB(dib_id);
1111 #endif
1114 TransportDIB* RenderProcessHostImpl::GetTransportDIB(
1115 TransportDIB::Id dib_id) {
1116 if (!TransportDIB::is_valid_id(dib_id))
1117 return NULL;
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();
1123 return i->second;
1126 TransportDIB* dib = MapTransportDIB(dib_id);
1127 if (!dib)
1128 return NULL;
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();
1145 #else
1146 delete smallest_iterator->second;
1147 #endif
1148 cached_dibs_.erase(smallest_iterator);
1151 cached_dibs_[dib_id] = dib;
1152 cached_dibs_cleaner_.Reset();
1153 return dib;
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();
1162 #else
1163 STLDeleteContainerPairSecondPointers(
1164 cached_dibs_.begin(), cached_dibs_.end());
1165 #endif
1166 cached_dibs_.clear();
1169 bool RenderProcessHostImpl::Send(IPC::Message* msg) {
1170 if (!channel_) {
1171 if (!is_initialized_) {
1172 queued_messages_.push(msg);
1173 return true;
1174 } else {
1175 delete msg;
1176 return false;
1180 if (child_process_launcher_.get() && child_process_launcher_->IsStarting()) {
1181 queued_messages_.push(msg);
1182 return true;
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_)
1193 return false;
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,
1201 OnShutdownRequest)
1202 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_DumpHandlesDone,
1203 OnDumpHandlesDone)
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()
1215 if (!msg_is_ok) {
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();
1222 return true;
1225 // Dispatch incoming messages to the appropriate IPC::Listener.
1226 IPC::Listener* listener = listeners_.Lookup(msg.routing_id());
1227 if (!listener) {
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();
1233 Send(reply);
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()
1243 return true;
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()));
1252 #endif
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 {
1273 return id_;
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.
1304 channel_.reset();
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() {
1314 pending_views_++;
1317 void RenderProcessHostImpl::RemovePendingView() {
1318 DCHECK(pending_views_);
1319 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_)
1336 return;
1337 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
1338 &GpuMessageFilter::SurfaceUpdated,
1339 gpu_message_filter_,
1340 surface_id));
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();
1354 return false;
1357 bool RenderProcessHostImpl::FastShutdownStarted() const {
1358 return fast_shutdown_started_;
1361 // static
1362 void RenderProcessHostImpl::RegisterHost(int host_id, RenderProcessHost* host) {
1363 g_all_hosts.Get().AddWithID(host, host_id);
1366 // static
1367 void RenderProcessHostImpl::UnregisterHost(int host_id) {
1368 RenderProcessHost* host = g_all_hosts.Get().Lookup(host_id);
1369 if (!host)
1370 return;
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);
1382 // static
1383 bool RenderProcessHostImpl::IsSuitableHost(
1384 RenderProcessHost* host,
1385 BrowserContext* browser_context,
1386 const GURL& site_url) {
1387 if (run_renderer_in_process())
1388 return true;
1390 if (host->GetBrowserContext() != browser_context)
1391 return false;
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
1396 // isolated sites.
1397 StoragePartition* dest_partition =
1398 BrowserContext::GetStoragePartitionForSite(browser_context, site_url);
1399 if (!host->InSameStoragePartition(dest_partition))
1400 return false;
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())
1407 return true;
1409 if (!host->IsGuest() && site_url.SchemeIs(chrome::kGuestScheme))
1410 return false;
1412 if (ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1413 host->GetID()) !=
1414 WebUIControllerFactoryRegistry::GetInstance()->UseWebUIBindingsForURL(
1415 browser_context, site_url)) {
1416 return false;
1419 return GetContentClient()->browser()->IsSuitableHost(host, site_url);
1422 // static
1423 bool RenderProcessHost::run_renderer_in_process() {
1424 return g_run_renderer_in_process_;
1427 // static
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());
1446 // static
1447 RenderProcessHost* RenderProcessHost::FromID(int render_process_id) {
1448 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1449 return g_all_hosts.Get().Lookup(render_process_id);
1452 // static
1453 bool RenderProcessHost::ShouldTryToUseExistingProcessHost(
1454 BrowserContext* browser_context, const GURL& url) {
1455 // Experimental:
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))
1464 return false;
1466 if (run_renderer_in_process())
1467 return true;
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())
1475 return true;
1477 return GetContentClient()->browser()->
1478 ShouldTryToUseExistingProcessHost(browser_context, url);
1481 // static
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());
1496 iter.Advance();
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];
1506 return NULL;
1509 // static
1510 bool RenderProcessHost::ShouldUseProcessPerSite(
1511 BrowserContext* browser_context,
1512 const GURL& url) {
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))
1519 return true;
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)) {
1527 return true;
1530 // Otherwise let the content client decide, defaulting to false.
1531 return GetContentClient()->browser()->ShouldUseProcessPerSite(browser_context,
1532 url);
1535 // static
1536 RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSite(
1537 BrowserContext* browser_context,
1538 const GURL& url) {
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);
1553 host = NULL;
1556 return host;
1559 void RenderProcessHostImpl::RegisterProcessHostForSite(
1560 BrowserContext* browser_context,
1561 RenderProcessHost* process,
1562 const GURL& url) {
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();
1572 if (!site.empty())
1573 map->RegisterProcess(site, process);
1576 base::MessageLoop*
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.
1590 int exit_code = 0;
1591 base::TerminationStatus status =
1592 child_process_launcher_.get() ?
1593 child_process_launcher_->GetChildTerminationStatus(already_dead,
1594 &exit_code) :
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();
1604 channel_.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())
1610 continue;
1611 RenderWidgetHostImpl::From(widgets[i])->OnMessageReceived(
1612 ViewHostMsg_RenderViewGone(widgets[i]->GetRoutingID(),
1613 static_cast<int>(status),
1614 exit_code));
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())
1629 continue;
1631 // All RenderWidgetHosts are swapped in.
1632 if (!widgets[i]->IsRenderView()) {
1633 num_active_views++;
1634 continue;
1637 // Don't count swapped out views.
1638 RenderViewHost* rvh = RenderViewHost::From(widgets[i]);
1639 if (!static_cast<RenderViewHostImpl*>(rvh)->is_swapped_out())
1640 num_active_views++;
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(
1648 int route_id,
1649 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
1650 if (!gpu_message_filter_)
1651 return;
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_)
1660 return;
1661 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
1662 &GpuMessageFilter::EndFrameSubscription,
1663 gpu_message_filter_,
1664 route_id));
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())
1673 return;
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() {
1690 Cleanup();
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())
1699 return;
1701 #if defined(OS_WIN)
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"))
1709 return;
1710 #endif // OS_WIN
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.
1720 if (deleting_soon_)
1721 return;
1723 if (child_process_launcher_) {
1724 if (!child_process_launcher_->GetHandle()) {
1725 OnChannelError();
1726 return;
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
1738 // happens.
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,
1767 ack_params);
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())
1774 continue;
1776 // Skip widgets in other processes.
1777 if (widgets[i]->GetProcess()->GetID() != GetID())
1778 continue;
1780 RenderViewHost* rvh = RenderViewHost::From(widgets[i]);
1781 rvh->UpdateWebkitPreferences(rvh->GetWebkitPreferences());
1785 } // namespace content