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