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