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