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