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