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