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