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