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