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