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