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