render_process_host_impl.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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/files/file.h" 25#include "base/lazy_instance.h" 26#include "base/logging.h" 27#include "base/metrics/field_trial.h" 28#include "base/metrics/histogram.h" 29#include "base/numerics/safe_math.h" 30#include "base/path_service.h" 31#include "base/rand_util.h" 32#include "base/stl_util.h" 33#include "base/strings/string_number_conversions.h" 34#include "base/strings/string_util.h" 35#include "base/supports_user_data.h" 36#include "base/sys_info.h" 37#include "base/threading/thread.h" 38#include "base/threading/thread_restrictions.h" 39#include "base/tracked_objects.h" 40#include "cc/base/switches.h" 41#include "content/browser/appcache/appcache_dispatcher_host.h" 42#include "content/browser/appcache/chrome_appcache_service.h" 43#include "content/browser/battery_status/battery_status_message_filter.h" 44#include "content/browser/browser_child_process_host_impl.h" 45#include "content/browser/browser_main.h" 46#include "content/browser/browser_main_loop.h" 47#include "content/browser/browser_plugin/browser_plugin_message_filter.h" 48#include "content/browser/child_process_security_policy_impl.h" 49#include "content/browser/device_sensors/device_motion_message_filter.h" 50#include "content/browser/device_sensors/device_orientation_message_filter.h" 51#include "content/browser/dom_storage/dom_storage_context_wrapper.h" 52#include "content/browser/dom_storage/dom_storage_message_filter.h" 53#include "content/browser/download/mhtml_generation_manager.h" 54#include "content/browser/fileapi/chrome_blob_storage_context.h" 55#include "content/browser/fileapi/fileapi_message_filter.h" 56#include "content/browser/frame_host/render_frame_message_filter.h" 57#include "content/browser/gpu/compositor_util.h" 58#include "content/browser/gpu/gpu_data_manager_impl.h" 59#include "content/browser/gpu/gpu_process_host.h" 60#include "content/browser/gpu/shader_disk_cache.h" 61#include "content/browser/histogram_message_filter.h" 62#include "content/browser/indexed_db/indexed_db_context_impl.h" 63#include "content/browser/indexed_db/indexed_db_dispatcher_host.h" 64#include "content/browser/loader/resource_message_filter.h" 65#include "content/browser/loader/resource_scheduler_filter.h" 66#include "content/browser/media/capture/audio_mirroring_manager.h" 67#include "content/browser/media/media_internals.h" 68#include "content/browser/media/midi_host.h" 69#include "content/browser/message_port_message_filter.h" 70#include "content/browser/mime_registry_message_filter.h" 71#include "content/browser/mojo/mojo_application_host.h" 72#include "content/browser/plugin_service_impl.h" 73#include "content/browser/profiler_message_filter.h" 74#include "content/browser/push_messaging_message_filter.h" 75#include "content/browser/quota_dispatcher_host.h" 76#include "content/browser/renderer_host/clipboard_message_filter.h" 77#include "content/browser/renderer_host/database_message_filter.h" 78#include "content/browser/renderer_host/file_utilities_message_filter.h" 79#include "content/browser/renderer_host/gamepad_browser_message_filter.h" 80#include "content/browser/renderer_host/gpu_message_filter.h" 81#include "content/browser/renderer_host/media/audio_input_renderer_host.h" 82#include "content/browser/renderer_host/media/audio_renderer_host.h" 83#include "content/browser/renderer_host/media/device_request_message_filter.h" 84#include "content/browser/renderer_host/media/media_stream_dispatcher_host.h" 85#include "content/browser/renderer_host/media/peer_connection_tracker_host.h" 86#include "content/browser/renderer_host/media/video_capture_host.h" 87#include "content/browser/renderer_host/memory_benchmark_message_filter.h" 88#include "content/browser/renderer_host/p2p/socket_dispatcher_host.h" 89#include "content/browser/renderer_host/pepper/pepper_message_filter.h" 90#include "content/browser/renderer_host/pepper/pepper_renderer_connection.h" 91#include "content/browser/renderer_host/render_message_filter.h" 92#include "content/browser/renderer_host/render_view_host_delegate.h" 93#include "content/browser/renderer_host/render_view_host_impl.h" 94#include "content/browser/renderer_host/render_widget_helper.h" 95#include "content/browser/renderer_host/render_widget_host_impl.h" 96#include "content/browser/renderer_host/socket_stream_dispatcher_host.h" 97#include "content/browser/renderer_host/text_input_client_message_filter.h" 98#include "content/browser/renderer_host/websocket_dispatcher_host.h" 99#include "content/browser/resolve_proxy_msg_helper.h" 100#include "content/browser/service_worker/service_worker_context_wrapper.h" 101#include "content/browser/service_worker/service_worker_dispatcher_host.h" 102#include "content/browser/shared_worker/shared_worker_message_filter.h" 103#include "content/browser/speech/speech_recognition_dispatcher_host.h" 104#include "content/browser/storage_partition_impl.h" 105#include "content/browser/streams/stream_context.h" 106#include "content/browser/tracing/trace_message_filter.h" 107#include "content/browser/vibration/vibration_message_filter.h" 108#include "content/browser/webui/web_ui_controller_factory_registry.h" 109#include "content/browser/worker_host/worker_message_filter.h" 110#include "content/browser/worker_host/worker_storage_partition.h" 111#include "content/common/child_process_host_impl.h" 112#include "content/common/child_process_messages.h" 113#include "content/common/content_switches_internal.h" 114#include "content/common/gpu/client/gpu_memory_buffer_impl.h" 115#include "content/common/gpu/client/gpu_memory_buffer_impl_shm.h" 116#include "content/common/gpu/gpu_messages.h" 117#include "content/common/mojo/mojo_messages.h" 118#include "content/common/resource_messages.h" 119#include "content/common/view_messages.h" 120#include "content/public/browser/browser_context.h" 121#include "content/public/browser/content_browser_client.h" 122#include "content/public/browser/notification_service.h" 123#include "content/public/browser/notification_types.h" 124#include "content/public/browser/render_process_host_factory.h" 125#include "content/public/browser/render_process_host_observer.h" 126#include "content/public/browser/render_widget_host.h" 127#include "content/public/browser/render_widget_host_iterator.h" 128#include "content/public/browser/render_widget_host_view_frame_subscriber.h" 129#include "content/public/browser/resource_context.h" 130#include "content/public/browser/user_metrics.h" 131#include "content/public/browser/worker_service.h" 132#include "content/public/common/content_constants.h" 133#include "content/public/common/content_switches.h" 134#include "content/public/common/process_type.h" 135#include "content/public/common/result_codes.h" 136#include "content/public/common/sandboxed_process_launcher_delegate.h" 137#include "content/public/common/url_constants.h" 138#include "gpu/command_buffer/service/gpu_switches.h" 139#include "ipc/ipc_channel.h" 140#include "ipc/ipc_logging.h" 141#include "ipc/ipc_switches.h" 142#include "media/base/media_switches.h" 143#include "mojo/common/common_type_converters.h" 144#include "net/url_request/url_request_context_getter.h" 145#include "ppapi/shared_impl/ppapi_switches.h" 146#include "third_party/skia/include/core/SkBitmap.h" 147#include "ui/base/ui_base_switches.h" 148#include "ui/events/event_switches.h" 149#include "ui/gfx/switches.h" 150#include "ui/gl/gl_switches.h" 151#include "ui/native_theme/native_theme_switches.h" 152#include "webkit/browser/fileapi/sandbox_file_system_backend.h" 153#include "webkit/common/resource_type.h" 154 155#if defined(OS_ANDROID) 156#include "content/browser/media/android/browser_demuxer_android.h" 157#include "content/browser/renderer_host/compositor_impl_android.h" 158#include "content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.h" 159#endif 160 161#if defined(OS_MACOSX) 162#include "content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h" 163#endif 164 165#if defined(OS_WIN) 166#include "base/strings/string_number_conversions.h" 167#include "base/win/scoped_com_initializer.h" 168#include "content/common/font_cache_dispatcher_win.h" 169#include "content/common/sandbox_win.h" 170#include "ui/gfx/win/dpi.h" 171#endif 172 173#if defined(ENABLE_WEBRTC) 174#include "content/browser/media/webrtc_internals.h" 175#include "content/browser/renderer_host/media/media_stream_track_metrics_host.h" 176#include "content/browser/renderer_host/media/webrtc_identity_service_host.h" 177#include "content/common/media/aec_dump_messages.h" 178#include "content/common/media/media_stream_messages.h" 179#endif 180 181extern bool g_exited_main_message_loop; 182 183static const char* kSiteProcessMapKeyName = "content_site_process_map"; 184 185namespace content { 186namespace { 187 188void CacheShaderInfo(int32 id, base::FilePath path) { 189 ShaderCacheFactory::GetInstance()->SetCacheInfo(id, path); 190} 191 192void RemoveShaderInfo(int32 id) { 193 ShaderCacheFactory::GetInstance()->RemoveCacheInfo(id); 194} 195 196net::URLRequestContext* GetRequestContext( 197 scoped_refptr<net::URLRequestContextGetter> request_context, 198 scoped_refptr<net::URLRequestContextGetter> media_request_context, 199 ResourceType::Type resource_type) { 200 // If the request has resource type of ResourceType::MEDIA, we use a request 201 // context specific to media for handling it because these resources have 202 // specific needs for caching. 203 if (resource_type == ResourceType::MEDIA) 204 return media_request_context->GetURLRequestContext(); 205 return request_context->GetURLRequestContext(); 206} 207 208void GetContexts( 209 ResourceContext* resource_context, 210 scoped_refptr<net::URLRequestContextGetter> request_context, 211 scoped_refptr<net::URLRequestContextGetter> media_request_context, 212 const ResourceHostMsg_Request& request, 213 ResourceContext** resource_context_out, 214 net::URLRequestContext** request_context_out) { 215 *resource_context_out = resource_context; 216 *request_context_out = 217 GetRequestContext(request_context, media_request_context, 218 request.resource_type); 219} 220 221#if defined(ENABLE_WEBRTC) 222// Creates a file used for diagnostic echo canceller recordings for handing 223// over to the renderer. 224IPC::PlatformFileForTransit CreateAecDumpFileForProcess( 225 base::FilePath file_path, 226 base::ProcessHandle process) { 227 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 228 base::File dump_file(file_path, 229 base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_APPEND); 230 if (!dump_file.IsValid()) { 231 VLOG(1) << "Could not open AEC dump file, error=" << 232 dump_file.error_details(); 233 return IPC::InvalidPlatformFileForTransit(); 234 } 235 return IPC::TakeFileHandleForProcess(dump_file.Pass(), process); 236} 237 238// Does nothing. Just to avoid races between enable and disable. 239void DisableAecDumpOnFileThread() { 240 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 241} 242#endif 243 244// the global list of all renderer processes 245base::LazyInstance<IDMap<RenderProcessHost> >::Leaky 246 g_all_hosts = LAZY_INSTANCE_INITIALIZER; 247 248// Map of site to process, to ensure we only have one RenderProcessHost per 249// site in process-per-site mode. Each map is specific to a BrowserContext. 250class SiteProcessMap : public base::SupportsUserData::Data { 251 public: 252 typedef base::hash_map<std::string, RenderProcessHost*> SiteToProcessMap; 253 SiteProcessMap() {} 254 255 void RegisterProcess(const std::string& site, RenderProcessHost* process) { 256 map_[site] = process; 257 } 258 259 RenderProcessHost* FindProcess(const std::string& site) { 260 SiteToProcessMap::iterator i = map_.find(site); 261 if (i != map_.end()) 262 return i->second; 263 return NULL; 264 } 265 266 void RemoveProcess(RenderProcessHost* host) { 267 // Find all instances of this process in the map, then separately remove 268 // them. 269 std::set<std::string> sites; 270 for (SiteToProcessMap::const_iterator i = map_.begin(); 271 i != map_.end(); 272 i++) { 273 if (i->second == host) 274 sites.insert(i->first); 275 } 276 for (std::set<std::string>::iterator i = sites.begin(); 277 i != sites.end(); 278 i++) { 279 SiteToProcessMap::iterator iter = map_.find(*i); 280 if (iter != map_.end()) { 281 DCHECK_EQ(iter->second, host); 282 map_.erase(iter); 283 } 284 } 285 } 286 287 private: 288 SiteToProcessMap map_; 289}; 290 291// Find the SiteProcessMap specific to the given context. 292SiteProcessMap* GetSiteProcessMapForBrowserContext(BrowserContext* context) { 293 DCHECK(context); 294 SiteProcessMap* map = static_cast<SiteProcessMap*>( 295 context->GetUserData(kSiteProcessMapKeyName)); 296 if (!map) { 297 map = new SiteProcessMap(); 298 context->SetUserData(kSiteProcessMapKeyName, map); 299 } 300 return map; 301} 302 303// NOTE: changes to this class need to be reviewed by the security team. 304class RendererSandboxedProcessLauncherDelegate 305 : public content::SandboxedProcessLauncherDelegate { 306 public: 307 RendererSandboxedProcessLauncherDelegate(IPC::ChannelProxy* channel) 308#if defined(OS_POSIX) 309 : ipc_fd_(channel->TakeClientFileDescriptor()) 310#endif // OS_POSIX 311 {} 312 313 virtual ~RendererSandboxedProcessLauncherDelegate() {} 314 315#if defined(OS_WIN) 316 virtual void PreSpawnTarget(sandbox::TargetPolicy* policy, 317 bool* success) { 318 AddBaseHandleClosePolicy(policy); 319 GetContentClient()->browser()->PreSpawnRenderer(policy, success); 320 } 321 322#elif defined(OS_POSIX) 323 virtual bool ShouldUseZygote() OVERRIDE { 324 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); 325 CommandLine::StringType renderer_prefix = 326 browser_command_line.GetSwitchValueNative(switches::kRendererCmdPrefix); 327 return renderer_prefix.empty(); 328 } 329 virtual int GetIpcFd() OVERRIDE { 330 return ipc_fd_; 331 } 332#endif // OS_WIN 333 334 private: 335#if defined(OS_POSIX) 336 int ipc_fd_; 337#endif // OS_POSIX 338}; 339 340#if defined(OS_MACOSX) 341void AddBooleanValue(CFMutableDictionaryRef dictionary, 342 const CFStringRef key, 343 bool value) { 344 CFDictionaryAddValue( 345 dictionary, key, value ? kCFBooleanTrue : kCFBooleanFalse); 346} 347 348void AddIntegerValue(CFMutableDictionaryRef dictionary, 349 const CFStringRef key, 350 int32 value) { 351 base::ScopedCFTypeRef<CFNumberRef> number( 352 CFNumberCreate(NULL, kCFNumberSInt32Type, &value)); 353 CFDictionaryAddValue(dictionary, key, number.get()); 354} 355#endif 356 357const char kSessionStorageHolderKey[] = "kSessionStorageHolderKey"; 358 359class SessionStorageHolder : public base::SupportsUserData::Data { 360 public: 361 SessionStorageHolder() {} 362 virtual ~SessionStorageHolder() {} 363 364 void Hold(const SessionStorageNamespaceMap& sessions, int view_route_id) { 365 session_storage_namespaces_awaiting_close_[view_route_id] = sessions; 366 } 367 368 void Release(int old_route_id) { 369 session_storage_namespaces_awaiting_close_.erase(old_route_id); 370 } 371 372 private: 373 std::map<int, SessionStorageNamespaceMap > 374 session_storage_namespaces_awaiting_close_; 375 DISALLOW_COPY_AND_ASSIGN(SessionStorageHolder); 376}; 377 378} // namespace 379 380RendererMainThreadFactoryFunction g_renderer_main_thread_factory = NULL; 381 382base::MessageLoop* g_in_process_thread; 383 384base::MessageLoop* 385 RenderProcessHostImpl::GetInProcessRendererThreadForTesting() { 386 return g_in_process_thread; 387} 388 389// Stores the maximum number of renderer processes the content module can 390// create. 391static size_t g_max_renderer_count_override = 0; 392 393// static 394size_t RenderProcessHost::GetMaxRendererProcessCount() { 395 if (g_max_renderer_count_override) 396 return g_max_renderer_count_override; 397 398 // Defines the maximum number of renderer processes according to the 399 // amount of installed memory as reported by the OS. The calculation 400 // assumes that you want the renderers to use half of the installed 401 // RAM and assuming that each WebContents uses ~40MB. 402 // If you modify this assumption, you need to adjust the 403 // ThirtyFourTabs test to match the expected number of processes. 404 // 405 // With the given amounts of installed memory below on a 32-bit CPU, 406 // the maximum renderer count will roughly be as follows: 407 // 408 // 128 MB -> 3 409 // 512 MB -> 6 410 // 1024 MB -> 12 411 // 4096 MB -> 51 412 // 16384 MB -> 82 (kMaxRendererProcessCount) 413 414 static size_t max_count = 0; 415 if (!max_count) { 416 const size_t kEstimatedWebContentsMemoryUsage = 417#if defined(ARCH_CPU_64_BITS) 418 60; // In MB 419#else 420 40; // In MB 421#endif 422 max_count = base::SysInfo::AmountOfPhysicalMemoryMB() / 2; 423 max_count /= kEstimatedWebContentsMemoryUsage; 424 425 const size_t kMinRendererProcessCount = 3; 426 max_count = std::max(max_count, kMinRendererProcessCount); 427 max_count = std::min(max_count, kMaxRendererProcessCount); 428 } 429 return max_count; 430} 431 432// static 433bool g_run_renderer_in_process_ = false; 434 435// static 436void RenderProcessHost::SetMaxRendererProcessCount(size_t count) { 437 g_max_renderer_count_override = count; 438} 439 440RenderProcessHostImpl::RenderProcessHostImpl( 441 BrowserContext* browser_context, 442 StoragePartitionImpl* storage_partition_impl, 443 bool is_isolated_guest) 444 : fast_shutdown_started_(false), 445 deleting_soon_(false), 446#ifndef NDEBUG 447 is_self_deleted_(false), 448#endif 449 pending_views_(0), 450 mojo_activation_required_(false), 451 visible_widgets_(0), 452 backgrounded_(true), 453 is_initialized_(false), 454 id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()), 455 browser_context_(browser_context), 456 storage_partition_impl_(storage_partition_impl), 457 sudden_termination_allowed_(true), 458 ignore_input_events_(false), 459 is_isolated_guest_(is_isolated_guest), 460 gpu_observer_registered_(false), 461 delayed_cleanup_needed_(false), 462 within_process_died_observer_(false), 463 power_monitor_broadcaster_(this), 464 worker_ref_count_(0), 465 weak_factory_(this) { 466 widget_helper_ = new RenderWidgetHelper(); 467 468 ChildProcessSecurityPolicyImpl::GetInstance()->Add(GetID()); 469 470 CHECK(!g_exited_main_message_loop); 471 RegisterHost(GetID(), this); 472 g_all_hosts.Get().set_check_on_null_data(true); 473 // Initialize |child_process_activity_time_| to a reasonable value. 474 mark_child_process_activity_time(); 475 476 if (!GetBrowserContext()->IsOffTheRecord() && 477 !CommandLine::ForCurrentProcess()->HasSwitch( 478 switches::kDisableGpuShaderDiskCache)) { 479 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 480 base::Bind(&CacheShaderInfo, GetID(), 481 storage_partition_impl_->GetPath())); 482 } 483 484 // Note: When we create the RenderProcessHostImpl, it's technically 485 // backgrounded, because it has no visible listeners. But the process 486 // doesn't actually exist yet, so we'll Background it later, after 487 // creation. 488} 489 490// static 491void RenderProcessHostImpl::ShutDownInProcessRenderer() { 492 DCHECK(g_run_renderer_in_process_); 493 494 switch (g_all_hosts.Pointer()->size()) { 495 case 0: 496 return; 497 case 1: { 498 RenderProcessHostImpl* host = static_cast<RenderProcessHostImpl*>( 499 AllHostsIterator().GetCurrentValue()); 500 FOR_EACH_OBSERVER(RenderProcessHostObserver, 501 host->observers_, 502 RenderProcessHostDestroyed(host)); 503#ifndef NDEBUG 504 host->is_self_deleted_ = true; 505#endif 506 delete host; 507 return; 508 } 509 default: 510 NOTREACHED() << "There should be only one RenderProcessHost when running " 511 << "in-process."; 512 } 513} 514 515void RenderProcessHostImpl::RegisterRendererMainThreadFactory( 516 RendererMainThreadFactoryFunction create) { 517 g_renderer_main_thread_factory = create; 518} 519 520RenderProcessHostImpl::~RenderProcessHostImpl() { 521#ifndef NDEBUG 522 DCHECK(is_self_deleted_) 523 << "RenderProcessHostImpl is destroyed by something other than itself"; 524#endif 525 526 // Make sure to clean up the in-process renderer before the channel, otherwise 527 // it may still run and have its IPCs fail, causing asserts. 528 in_process_renderer_.reset(); 529 530 ChildProcessSecurityPolicyImpl::GetInstance()->Remove(GetID()); 531 532 if (gpu_observer_registered_) { 533 GpuDataManagerImpl::GetInstance()->RemoveObserver(this); 534 gpu_observer_registered_ = false; 535 } 536 537 // We may have some unsent messages at this point, but that's OK. 538 channel_.reset(); 539 while (!queued_messages_.empty()) { 540 delete queued_messages_.front(); 541 queued_messages_.pop(); 542 } 543 544 UnregisterHost(GetID()); 545 546 if (!CommandLine::ForCurrentProcess()->HasSwitch( 547 switches::kDisableGpuShaderDiskCache)) { 548 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 549 base::Bind(&RemoveShaderInfo, GetID())); 550 } 551 552#if defined(OS_ANDROID) 553 CompositorImpl::DestroyAllSurfaceTextures(GetID()); 554#endif 555} 556 557void RenderProcessHostImpl::EnableSendQueue() { 558 is_initialized_ = false; 559} 560 561bool RenderProcessHostImpl::Init() { 562 // calling Init() more than once does nothing, this makes it more convenient 563 // for the view host which may not be sure in some cases 564 if (channel_) 565 return true; 566 567 CommandLine::StringType renderer_prefix; 568#if defined(OS_POSIX) 569 // A command prefix is something prepended to the command line of the spawned 570 // process. It is supported only on POSIX systems. 571 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); 572 renderer_prefix = 573 browser_command_line.GetSwitchValueNative(switches::kRendererCmdPrefix); 574#endif // defined(OS_POSIX) 575 576#if defined(OS_LINUX) 577 int flags = renderer_prefix.empty() ? ChildProcessHost::CHILD_ALLOW_SELF : 578 ChildProcessHost::CHILD_NORMAL; 579#else 580 int flags = ChildProcessHost::CHILD_NORMAL; 581#endif 582 583 // Find the renderer before creating the channel so if this fails early we 584 // return without creating the channel. 585 base::FilePath renderer_path = ChildProcessHost::GetChildPath(flags); 586 if (renderer_path.empty()) 587 return false; 588 589 // Setup the IPC channel. 590 const std::string channel_id = 591 IPC::Channel::GenerateVerifiedChannelID(std::string()); 592 channel_ = IPC::ChannelProxy::Create( 593 channel_id, 594 IPC::Channel::MODE_SERVER, 595 this, 596 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get()); 597 598 // Setup the Mojo channel. 599 mojo_application_host_.reset(new MojoApplicationHost()); 600 mojo_application_host_->Init(); 601 602 // Call the embedder first so that their IPC filters have priority. 603 GetContentClient()->browser()->RenderProcessWillLaunch(this); 604 605 CreateMessageFilters(); 606 607 if (run_renderer_in_process()) { 608 DCHECK(g_renderer_main_thread_factory); 609 // Crank up a thread and run the initialization there. With the way that 610 // messages flow between the browser and renderer, this thread is required 611 // to prevent a deadlock in single-process mode. Since the primordial 612 // thread in the renderer process runs the WebKit code and can sometimes 613 // make blocking calls to the UI thread (i.e. this thread), they need to run 614 // on separate threads. 615 in_process_renderer_.reset(g_renderer_main_thread_factory(channel_id)); 616 617 base::Thread::Options options; 618#if defined(OS_WIN) && !defined(OS_MACOSX) 619 // In-process plugins require this to be a UI message loop. 620 options.message_loop_type = base::MessageLoop::TYPE_UI; 621#else 622 // We can't have multiple UI loops on Linux and Android, so we don't support 623 // in-process plugins. 624 options.message_loop_type = base::MessageLoop::TYPE_DEFAULT; 625#endif 626 in_process_renderer_->StartWithOptions(options); 627 628 g_in_process_thread = in_process_renderer_->message_loop(); 629 630 OnProcessLaunched(); // Fake a callback that the process is ready. 631 } else { 632 // Build command line for renderer. We call AppendRendererCommandLine() 633 // first so the process type argument will appear first. 634 CommandLine* cmd_line = new CommandLine(renderer_path); 635 if (!renderer_prefix.empty()) 636 cmd_line->PrependWrapper(renderer_prefix); 637 AppendRendererCommandLine(cmd_line); 638 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id); 639 640 // Spawn the child process asynchronously to avoid blocking the UI thread. 641 // As long as there's no renderer prefix, we can use the zygote process 642 // at this stage. 643 child_process_launcher_.reset(new ChildProcessLauncher( 644 new RendererSandboxedProcessLauncherDelegate(channel_.get()), 645 cmd_line, 646 GetID(), 647 this)); 648 649 fast_shutdown_started_ = false; 650 } 651 652 if (!gpu_observer_registered_) { 653 gpu_observer_registered_ = true; 654 GpuDataManagerImpl::GetInstance()->AddObserver(this); 655 } 656 657 is_initialized_ = true; 658 return true; 659} 660 661void RenderProcessHostImpl::MaybeActivateMojo() { 662 // TODO(darin): Following security review, we can unconditionally initialize 663 // Mojo in all renderers. We will then be able to directly call Activate() 664 // from OnProcessLaunched. 665 if (!mojo_activation_required_) 666 return; // Waiting on someone to require Mojo. 667 668 if (!GetHandle()) 669 return; // Waiting on renderer startup. 670 671 if (!mojo_application_host_->did_activate()) 672 mojo_application_host_->Activate(this, GetHandle()); 673} 674 675void RenderProcessHostImpl::CreateMessageFilters() { 676 DCHECK_CURRENTLY_ON(BrowserThread::UI); 677 AddFilter(new ResourceSchedulerFilter(GetID())); 678 MediaInternals* media_internals = MediaInternals::GetInstance(); 679 media::AudioManager* audio_manager = 680 BrowserMainLoop::GetInstance()->audio_manager(); 681 // Add BrowserPluginMessageFilter to ensure it gets the first stab at messages 682 // from guests. 683 scoped_refptr<BrowserPluginMessageFilter> bp_message_filter( 684 new BrowserPluginMessageFilter(GetID())); 685 AddFilter(bp_message_filter.get()); 686 687 scoped_refptr<RenderMessageFilter> render_message_filter( 688 new RenderMessageFilter( 689 GetID(), 690#if defined(ENABLE_PLUGINS) 691 PluginServiceImpl::GetInstance(), 692#else 693 NULL, 694#endif 695 GetBrowserContext(), 696 GetBrowserContext()->GetRequestContextForRenderProcess(GetID()), 697 widget_helper_.get(), 698 audio_manager, 699 media_internals, 700 storage_partition_impl_->GetDOMStorageContext())); 701 AddFilter(render_message_filter.get()); 702 AddFilter( 703 new RenderFrameMessageFilter(GetID(), widget_helper_.get())); 704 BrowserContext* browser_context = GetBrowserContext(); 705 ResourceContext* resource_context = browser_context->GetResourceContext(); 706 707 scoped_refptr<net::URLRequestContextGetter> request_context( 708 browser_context->GetRequestContextForRenderProcess(GetID())); 709 scoped_refptr<net::URLRequestContextGetter> media_request_context( 710 browser_context->GetMediaRequestContextForRenderProcess(GetID())); 711 712 ResourceMessageFilter::GetContextsCallback get_contexts_callback( 713 base::Bind(&GetContexts, browser_context->GetResourceContext(), 714 request_context, media_request_context)); 715 716 ResourceMessageFilter* resource_message_filter = new ResourceMessageFilter( 717 GetID(), PROCESS_TYPE_RENDERER, 718 storage_partition_impl_->GetAppCacheService(), 719 ChromeBlobStorageContext::GetFor(browser_context), 720 storage_partition_impl_->GetFileSystemContext(), 721 storage_partition_impl_->GetServiceWorkerContext(), 722 get_contexts_callback); 723 724 AddFilter(resource_message_filter); 725 MediaStreamManager* media_stream_manager = 726 BrowserMainLoop::GetInstance()->media_stream_manager(); 727 AddFilter(new AudioInputRendererHost( 728 audio_manager, 729 media_stream_manager, 730 BrowserMainLoop::GetInstance()->audio_mirroring_manager(), 731 BrowserMainLoop::GetInstance()->user_input_monitor())); 732 // The AudioRendererHost needs to be available for lookup, so it's 733 // stashed in a member variable. 734 audio_renderer_host_ = new AudioRendererHost( 735 GetID(), 736 audio_manager, 737 BrowserMainLoop::GetInstance()->audio_mirroring_manager(), 738 media_internals, 739 media_stream_manager); 740 AddFilter(audio_renderer_host_); 741 AddFilter( 742 new MidiHost(GetID(), BrowserMainLoop::GetInstance()->midi_manager())); 743 AddFilter(new VideoCaptureHost(media_stream_manager)); 744 AddFilter(new AppCacheDispatcherHost( 745 storage_partition_impl_->GetAppCacheService(), 746 GetID())); 747 AddFilter(new ClipboardMessageFilter); 748 AddFilter(new DOMStorageMessageFilter( 749 GetID(), 750 storage_partition_impl_->GetDOMStorageContext())); 751 AddFilter(new IndexedDBDispatcherHost( 752 GetID(), 753 storage_partition_impl_->GetURLRequestContext(), 754 storage_partition_impl_->GetIndexedDBContext(), 755 ChromeBlobStorageContext::GetFor(browser_context))); 756 757 gpu_message_filter_ = new GpuMessageFilter(GetID(), widget_helper_.get()); 758 AddFilter(gpu_message_filter_); 759#if defined(ENABLE_WEBRTC) 760 AddFilter(new WebRTCIdentityServiceHost( 761 GetID(), storage_partition_impl_->GetWebRTCIdentityStore())); 762 peer_connection_tracker_host_ = new PeerConnectionTrackerHost(GetID()); 763 AddFilter(peer_connection_tracker_host_.get()); 764 AddFilter(new MediaStreamDispatcherHost( 765 GetID(), 766 browser_context->GetResourceContext()->GetMediaDeviceIDSalt(), 767 media_stream_manager, 768 resource_context)); 769 AddFilter(new DeviceRequestMessageFilter( 770 resource_context, media_stream_manager, GetID())); 771 AddFilter(new MediaStreamTrackMetricsHost()); 772#endif 773#if defined(ENABLE_PLUGINS) 774 AddFilter(new PepperRendererConnection(GetID())); 775#endif 776 AddFilter(new SpeechRecognitionDispatcherHost( 777 GetID(), storage_partition_impl_->GetURLRequestContext())); 778 AddFilter(new FileAPIMessageFilter( 779 GetID(), 780 storage_partition_impl_->GetURLRequestContext(), 781 storage_partition_impl_->GetFileSystemContext(), 782 ChromeBlobStorageContext::GetFor(browser_context), 783 StreamContext::GetFor(browser_context))); 784 AddFilter(new FileUtilitiesMessageFilter(GetID())); 785 AddFilter(new MimeRegistryMessageFilter()); 786 AddFilter(new DatabaseMessageFilter( 787 storage_partition_impl_->GetDatabaseTracker())); 788#if defined(OS_MACOSX) 789 AddFilter(new TextInputClientMessageFilter(GetID())); 790#elif defined(OS_WIN) 791 // The FontCacheDispatcher is required only when we're using GDI rendering. 792 // TODO(scottmg): pdf/ppapi still require the renderer to be able to precache 793 // GDI fonts (http://crbug.com/383227), even when using DirectWrite. This 794 // should eventually be if (!ShouldUseDirectWrite()) guarded. 795 channel_->AddFilter(new FontCacheDispatcher()); 796#elif defined(OS_ANDROID) 797 browser_demuxer_android_ = new BrowserDemuxerAndroid(); 798 AddFilter(browser_demuxer_android_); 799#endif 800 801 SocketStreamDispatcherHost::GetRequestContextCallback 802 request_context_callback( 803 base::Bind(&GetRequestContext, request_context, 804 media_request_context)); 805 806 SocketStreamDispatcherHost* socket_stream_dispatcher_host = 807 new SocketStreamDispatcherHost( 808 GetID(), request_context_callback, resource_context); 809 AddFilter(socket_stream_dispatcher_host); 810 811 WebSocketDispatcherHost::GetRequestContextCallback 812 websocket_request_context_callback( 813 base::Bind(&GetRequestContext, request_context, 814 media_request_context, ResourceType::SUB_RESOURCE)); 815 816 AddFilter( 817 new WebSocketDispatcherHost(GetID(), websocket_request_context_callback)); 818 819 message_port_message_filter_ = new MessagePortMessageFilter( 820 base::Bind(&RenderWidgetHelper::GetNextRoutingID, 821 base::Unretained(widget_helper_.get()))); 822 AddFilter(message_port_message_filter_); 823 824 scoped_refptr<ServiceWorkerDispatcherHost> service_worker_filter = 825 new ServiceWorkerDispatcherHost(GetID(), message_port_message_filter_); 826 service_worker_filter->Init( 827 storage_partition_impl_->GetServiceWorkerContext()); 828 AddFilter(service_worker_filter); 829 830 // If "--enable-embedded-shared-worker" is set, we use 831 // SharedWorkerMessageFilter in stead of WorkerMessageFilter. 832 if (WorkerService::EmbeddedSharedWorkerEnabled()) { 833 AddFilter(new SharedWorkerMessageFilter( 834 GetID(), 835 resource_context, 836 WorkerStoragePartition( 837 storage_partition_impl_->GetURLRequestContext(), 838 storage_partition_impl_->GetMediaURLRequestContext(), 839 storage_partition_impl_->GetAppCacheService(), 840 storage_partition_impl_->GetQuotaManager(), 841 storage_partition_impl_->GetFileSystemContext(), 842 storage_partition_impl_->GetDatabaseTracker(), 843 storage_partition_impl_->GetIndexedDBContext(), 844 storage_partition_impl_->GetServiceWorkerContext()), 845 message_port_message_filter_)); 846 } else { 847 AddFilter(new WorkerMessageFilter( 848 GetID(), 849 resource_context, 850 WorkerStoragePartition( 851 storage_partition_impl_->GetURLRequestContext(), 852 storage_partition_impl_->GetMediaURLRequestContext(), 853 storage_partition_impl_->GetAppCacheService(), 854 storage_partition_impl_->GetQuotaManager(), 855 storage_partition_impl_->GetFileSystemContext(), 856 storage_partition_impl_->GetDatabaseTracker(), 857 storage_partition_impl_->GetIndexedDBContext(), 858 storage_partition_impl_->GetServiceWorkerContext()), 859 message_port_message_filter_)); 860 } 861 862#if defined(ENABLE_WEBRTC) 863 p2p_socket_dispatcher_host_ = new P2PSocketDispatcherHost( 864 resource_context, 865 browser_context->GetRequestContextForRenderProcess(GetID())); 866 AddFilter(p2p_socket_dispatcher_host_); 867#endif 868 869 AddFilter(new TraceMessageFilter()); 870 AddFilter(new ResolveProxyMsgHelper( 871 browser_context->GetRequestContextForRenderProcess(GetID()))); 872 AddFilter(new QuotaDispatcherHost( 873 GetID(), 874 storage_partition_impl_->GetQuotaManager(), 875 GetContentClient()->browser()->CreateQuotaPermissionContext())); 876 AddFilter(new GamepadBrowserMessageFilter()); 877 AddFilter(new DeviceMotionMessageFilter()); 878 AddFilter(new DeviceOrientationMessageFilter()); 879 AddFilter(new ProfilerMessageFilter(PROCESS_TYPE_RENDERER)); 880 AddFilter(new HistogramMessageFilter()); 881#if defined(USE_TCMALLOC) && (defined(OS_LINUX) || defined(OS_ANDROID)) 882 if (CommandLine::ForCurrentProcess()->HasSwitch( 883 switches::kEnableMemoryBenchmarking)) 884 AddFilter(new MemoryBenchmarkMessageFilter()); 885#endif 886 AddFilter(new VibrationMessageFilter()); 887 AddFilter(new PushMessagingMessageFilter(GetID())); 888 AddFilter(new BatteryStatusMessageFilter()); 889} 890 891int RenderProcessHostImpl::GetNextRoutingID() { 892 return widget_helper_->GetNextRoutingID(); 893} 894 895 896void RenderProcessHostImpl::ResumeDeferredNavigation( 897 const GlobalRequestID& request_id) { 898 widget_helper_->ResumeDeferredNavigation(request_id); 899} 900 901void RenderProcessHostImpl::NotifyTimezoneChange() { 902 Send(new ViewMsg_TimezoneChange()); 903} 904 905void RenderProcessHostImpl::AddRoute( 906 int32 routing_id, 907 IPC::Listener* listener) { 908 listeners_.AddWithID(listener, routing_id); 909} 910 911void RenderProcessHostImpl::RemoveRoute(int32 routing_id) { 912 DCHECK(listeners_.Lookup(routing_id) != NULL); 913 listeners_.Remove(routing_id); 914 915#if defined(OS_WIN) 916 // Dump the handle table if handle auditing is enabled. 917 const CommandLine& browser_command_line = 918 *CommandLine::ForCurrentProcess(); 919 if (browser_command_line.HasSwitch(switches::kAuditHandles) || 920 browser_command_line.HasSwitch(switches::kAuditAllHandles)) { 921 DumpHandles(); 922 923 // We wait to close the channels until the child process has finished 924 // dumping handles and sends us ChildProcessHostMsg_DumpHandlesDone. 925 return; 926 } 927#endif 928 // Keep the one renderer thread around forever in single process mode. 929 if (!run_renderer_in_process()) 930 Cleanup(); 931} 932 933void RenderProcessHostImpl::AddObserver(RenderProcessHostObserver* observer) { 934 observers_.AddObserver(observer); 935} 936 937void RenderProcessHostImpl::RemoveObserver( 938 RenderProcessHostObserver* observer) { 939 observers_.RemoveObserver(observer); 940} 941 942bool RenderProcessHostImpl::WaitForBackingStoreMsg( 943 int render_widget_id, 944 const base::TimeDelta& max_delay, 945 IPC::Message* msg) { 946 // The post task to this thread with the process id could be in queue, and we 947 // don't want to dispatch a message before then since it will need the handle. 948 if (child_process_launcher_.get() && child_process_launcher_->IsStarting()) 949 return false; 950 951 return widget_helper_->WaitForBackingStoreMsg(render_widget_id, 952 max_delay, msg); 953} 954 955void RenderProcessHostImpl::ReceivedBadMessage() { 956 CommandLine* command_line = CommandLine::ForCurrentProcess(); 957 if (command_line->HasSwitch(switches::kDisableKillAfterBadIPC)) 958 return; 959 960 if (run_renderer_in_process()) { 961 // In single process mode it is better if we don't suicide but just 962 // crash. 963 CHECK(false); 964 } 965 // We kill the renderer but don't include a NOTREACHED, because we want the 966 // browser to try to survive when it gets illegal messages from the renderer. 967 base::KillProcess(GetHandle(), RESULT_CODE_KILLED_BAD_MESSAGE, 968 false); 969} 970 971void RenderProcessHostImpl::WidgetRestored() { 972 // Verify we were properly backgrounded. 973 DCHECK_EQ(backgrounded_, (visible_widgets_ == 0)); 974 visible_widgets_++; 975 SetBackgrounded(false); 976} 977 978void RenderProcessHostImpl::WidgetHidden() { 979 // On startup, the browser will call Hide 980 if (backgrounded_) 981 return; 982 983 DCHECK_EQ(backgrounded_, (visible_widgets_ == 0)); 984 visible_widgets_--; 985 DCHECK_GE(visible_widgets_, 0); 986 if (visible_widgets_ == 0) { 987 DCHECK(!backgrounded_); 988 SetBackgrounded(true); 989 } 990} 991 992int RenderProcessHostImpl::VisibleWidgetCount() const { 993 return visible_widgets_; 994} 995 996bool RenderProcessHostImpl::IsIsolatedGuest() const { 997 return is_isolated_guest_; 998} 999 1000StoragePartition* RenderProcessHostImpl::GetStoragePartition() const { 1001 return storage_partition_impl_; 1002} 1003 1004static void AppendCompositorCommandLineFlags(CommandLine* command_line) { 1005 if (IsPinchVirtualViewportEnabled()) 1006 command_line->AppendSwitch(cc::switches::kEnablePinchVirtualViewport); 1007 1008 if (IsThreadedCompositingEnabled()) 1009 command_line->AppendSwitch(switches::kEnableThreadedCompositing); 1010 1011 if (IsDelegatedRendererEnabled()) 1012 command_line->AppendSwitch(switches::kEnableDelegatedRenderer); 1013 1014 if (IsImplSidePaintingEnabled()) 1015 command_line->AppendSwitch(switches::kEnableImplSidePainting); 1016 1017 if (content::IsGpuRasterizationEnabled()) 1018 command_line->AppendSwitch(switches::kEnableGpuRasterization); 1019 1020 if (content::IsForceGpuRasterizationEnabled()) 1021 command_line->AppendSwitch(switches::kForceGpuRasterization); 1022 1023 // Appending disable-gpu-feature switches due to software rendering list. 1024 GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance(); 1025 DCHECK(gpu_data_manager); 1026 gpu_data_manager->AppendRendererCommandLine(command_line); 1027} 1028 1029void RenderProcessHostImpl::AppendRendererCommandLine( 1030 CommandLine* command_line) const { 1031 // Pass the process type first, so it shows first in process listings. 1032 command_line->AppendSwitchASCII(switches::kProcessType, 1033 switches::kRendererProcess); 1034 1035 // Now send any options from our own command line we want to propagate. 1036 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); 1037 PropagateBrowserCommandLineToRenderer(browser_command_line, command_line); 1038 1039 // Pass on the browser locale. 1040 const std::string locale = 1041 GetContentClient()->browser()->GetApplicationLocale(); 1042 command_line->AppendSwitchASCII(switches::kLang, locale); 1043 1044 // If we run base::FieldTrials, we want to pass to their state to the 1045 // renderer so that it can act in accordance with each state, or record 1046 // histograms relating to the base::FieldTrial states. 1047 std::string field_trial_states; 1048 base::FieldTrialList::StatesToString(&field_trial_states); 1049 if (!field_trial_states.empty()) { 1050 command_line->AppendSwitchASCII(switches::kForceFieldTrials, 1051 field_trial_states); 1052 } 1053 1054 GetContentClient()->browser()->AppendExtraCommandLineSwitches( 1055 command_line, GetID()); 1056 1057 if (content::IsPinchToZoomEnabled()) 1058 command_line->AppendSwitch(switches::kEnablePinch); 1059 1060#if defined(OS_WIN) 1061 command_line->AppendSwitchASCII(switches::kDeviceScaleFactor, 1062 base::DoubleToString(gfx::GetDPIScale())); 1063#endif 1064 1065 AppendCompositorCommandLineFlags(command_line); 1066} 1067 1068void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( 1069 const CommandLine& browser_cmd, 1070 CommandLine* renderer_cmd) const { 1071 // Propagate the following switches to the renderer command line (along 1072 // with any associated values) if present in the browser command line. 1073 static const char* const kSwitchNames[] = { 1074 switches::kAllowInsecureWebSocketFromHttpsOrigin, 1075 switches::kAllowLoopbackInPeerConnection, 1076 switches::kAudioBufferSize, 1077 switches::kAuditAllHandles, 1078 switches::kAuditHandles, 1079 switches::kBlinkPlatformLogChannels, 1080 switches::kBlockCrossSiteDocuments, 1081 switches::kDefaultTileWidth, 1082 switches::kDefaultTileHeight, 1083 switches::kDisable3DAPIs, 1084 switches::kDisableAcceleratedFixedRootBackground, 1085 switches::kDisableAcceleratedOverflowScroll, 1086 switches::kDisableAcceleratedVideoDecode, 1087 switches::kDisableApplicationCache, 1088 switches::kDisableBreakpad, 1089 switches::kDisableCompositingForFixedPosition, 1090 switches::kDisableCompositingForTransition, 1091 switches::kDisableDatabases, 1092 switches::kDisableDesktopNotifications, 1093 switches::kDisableDirectNPAPIRequests, 1094 switches::kDisableDistanceFieldText, 1095 switches::kDisableFastTextAutosizing, 1096 switches::kDisableFileSystem, 1097 switches::kDisableGpuCompositing, 1098 switches::kDisableGpuVsync, 1099 switches::kDisableLowResTiling, 1100 switches::kDisableHistogramCustomizer, 1101 switches::kDisableLCDText, 1102 switches::kDisableLayerSquashing, 1103 switches::kDisableLocalStorage, 1104 switches::kDisableLogging, 1105 switches::kDisableMediaSource, 1106 switches::kDisableOverlayScrollbar, 1107 switches::kDisablePinch, 1108 switches::kDisablePrefixedEncryptedMedia, 1109 switches::kDisableRepaintAfterLayout, 1110 switches::kDisableSeccompFilterSandbox, 1111 switches::kDisableSessionStorage, 1112 switches::kDisableSharedWorkers, 1113 switches::kDisableTouchAdjustment, 1114 switches::kDisableTouchDragDrop, 1115 switches::kDisableTouchEditing, 1116 switches::kDisableZeroCopy, 1117 switches::kDomAutomationController, 1118 switches::kEnableAcceleratedFixedRootBackground, 1119 switches::kEnableAcceleratedOverflowScroll, 1120 switches::kEnableBeginFrameScheduling, 1121 switches::kEnableBleedingEdgeRenderingFastPaths, 1122 switches::kEnableCompositingForFixedPosition, 1123 switches::kEnableCompositingForTransition, 1124 switches::kEnableDeferredImageDecoding, 1125 switches::kEnableDistanceFieldText, 1126 switches::kEnableEncryptedMedia, 1127 switches::kEnableExperimentalCanvasFeatures, 1128 switches::kEnableExperimentalWebPlatformFeatures, 1129 switches::kEnableFastTextAutosizing, 1130 switches::kEnableGPUClientLogging, 1131 switches::kEnableGpuClientTracing, 1132 switches::kEnableGPUServiceLogging, 1133 switches::kEnableHighDpiCompositingForFixedPosition, 1134 switches::kEnableLowResTiling, 1135 switches::kEnableInbandTextTracks, 1136 switches::kEnableLCDText, 1137 switches::kEnableLayerSquashing, 1138 switches::kEnableLogging, 1139 switches::kEnableMemoryBenchmarking, 1140 switches::kEnableOneCopy, 1141 switches::kEnableOverlayFullscreenVideo, 1142 switches::kEnableOverlayScrollbar, 1143 switches::kEnableOverscrollNotifications, 1144 switches::kEnablePinch, 1145 switches::kEnablePreciseMemoryInfo, 1146 switches::kEnablePreparsedJsCaching, 1147 switches::kEnableRepaintAfterLayout, 1148 switches::kEnableSeccompFilterSandbox, 1149 switches::kEnableServiceWorker, 1150 switches::kEnableSkiaBenchmarking, 1151 switches::kEnableSpeechSynthesis, 1152 switches::kEnableStatsTable, 1153 switches::kEnableStrictSiteIsolation, 1154 switches::kEnableTargetedStyleRecalc, 1155 switches::kEnableTouchDragDrop, 1156 switches::kEnableTouchEditing, 1157 switches::kEnableViewport, 1158 switches::kEnableViewportMeta, 1159 switches::kMainFrameResizesAreOrientationChanges, 1160 switches::kEnableVtune, 1161 switches::kEnableWebAnimationsSVG, 1162 switches::kEnableWebGLDraftExtensions, 1163 switches::kEnableWebGLImageChromium, 1164 switches::kEnableWebMIDI, 1165 switches::kEnableZeroCopy, 1166 switches::kForceDeviceScaleFactor, 1167 switches::kFullMemoryCrashReport, 1168 switches::kIgnoreResolutionLimitsForAcceleratedVideoDecode, 1169 switches::kJavaScriptFlags, 1170 switches::kLoggingLevel, 1171 switches::kMaxUntiledLayerWidth, 1172 switches::kMaxUntiledLayerHeight, 1173 switches::kMemoryMetrics, 1174 switches::kNoReferrers, 1175 switches::kNoSandbox, 1176 switches::kNumRasterThreads, 1177 switches::kPpapiInProcess, 1178 switches::kProfilerTiming, 1179 switches::kReduceSecurityForTesting, 1180 switches::kRegisterPepperPlugins, 1181 switches::kRendererAssertTest, 1182 switches::kRendererStartupDialog, 1183 switches::kShowPaintRects, 1184 switches::kSitePerProcess, 1185 switches::kStatsCollectionController, 1186 switches::kTestType, 1187 switches::kTouchEvents, 1188 switches::kTraceToConsole, 1189 switches::kUseDiscardableMemory, 1190 // This flag needs to be propagated to the renderer process for 1191 // --in-process-webgl. 1192 switches::kUseGL, 1193 switches::kUseMobileUserAgent, 1194 switches::kV, 1195 switches::kVideoThreads, 1196 switches::kVModule, 1197 // Please keep these in alphabetical order. Compositor switches here should 1198 // also be added to chrome/browser/chromeos/login/chrome_restart_request.cc. 1199 cc::switches::kCompositeToMailbox, 1200 cc::switches::kDisableCompositedAntialiasing, 1201 cc::switches::kDisableCompositorTouchHitTesting, 1202 cc::switches::kDisableMainFrameBeforeActivation, 1203 cc::switches::kDisableMainFrameBeforeDraw, 1204 cc::switches::kDisableThreadedAnimation, 1205 cc::switches::kEnableGpuBenchmarking, 1206 cc::switches::kEnableMainFrameBeforeActivation, 1207 cc::switches::kEnableTopControlsPositionCalculation, 1208 cc::switches::kMaxTilesForInterestArea, 1209 cc::switches::kMaxUnusedResourceMemoryUsagePercentage, 1210 cc::switches::kShowCompositedLayerBorders, 1211 cc::switches::kShowFPSCounter, 1212 cc::switches::kShowLayerAnimationBounds, 1213 cc::switches::kShowNonOccludingRects, 1214 cc::switches::kShowOccludingRects, 1215 cc::switches::kShowPropertyChangedRects, 1216 cc::switches::kShowReplicaScreenSpaceRects, 1217 cc::switches::kShowScreenSpaceRects, 1218 cc::switches::kShowSurfaceDamageRects, 1219 cc::switches::kSlowDownRasterScaleFactor, 1220 cc::switches::kStrictLayerPropertyChangeChecking, 1221 cc::switches::kTopControlsHeight, 1222 cc::switches::kTopControlsHideThreshold, 1223 cc::switches::kTopControlsShowThreshold, 1224#if defined(ENABLE_PLUGINS) 1225 switches::kEnablePepperTesting, 1226#endif 1227#if defined(ENABLE_WEBRTC) 1228 switches::kDisableAudioTrackProcessing, 1229 switches::kDisableDeviceEnumeration, 1230 switches::kDisableWebRtcHWDecoding, 1231 switches::kDisableWebRtcHWEncoding, 1232 switches::kEnableWebRtcHWVp8Encoding, 1233#endif 1234#if defined(OS_ANDROID) 1235 switches::kDisableGestureRequirementForMediaPlayback, 1236 switches::kDisableLowEndDeviceMode, 1237 switches::kDisableWebRTC, 1238 switches::kEnableLowEndDeviceMode, 1239 switches::kEnableSpeechRecognition, 1240 switches::kMediaDrmEnableNonCompositing, 1241 switches::kNetworkCountryIso, 1242 switches::kDisableWebAudio, 1243#endif 1244#if defined(OS_MACOSX) 1245 // Allow this to be set when invoking the browser and relayed along. 1246 switches::kEnableSandboxLogging, 1247#endif 1248#if defined(OS_WIN) 1249 switches::kDisableDirectWrite, 1250 switches::kEnableHighResolutionTime, 1251#endif 1252 }; 1253 renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames, 1254 arraysize(kSwitchNames)); 1255 1256 if (browser_cmd.HasSwitch(switches::kTraceStartup) && 1257 BrowserMainLoop::GetInstance()->is_tracing_startup()) { 1258 // Pass kTraceStartup switch to renderer only if startup tracing has not 1259 // finished. 1260 renderer_cmd->AppendSwitchASCII( 1261 switches::kTraceStartup, 1262 browser_cmd.GetSwitchValueASCII(switches::kTraceStartup)); 1263 } 1264 1265 // Disable databases in incognito mode. 1266 if (GetBrowserContext()->IsOffTheRecord() && 1267 !browser_cmd.HasSwitch(switches::kDisableDatabases)) { 1268 renderer_cmd->AppendSwitch(switches::kDisableDatabases); 1269 } 1270 1271 // Enforce the extra command line flags for impl-side painting. 1272 if (IsImplSidePaintingEnabled() && 1273 !browser_cmd.HasSwitch(switches::kEnableDeferredImageDecoding)) 1274 renderer_cmd->AppendSwitch(switches::kEnableDeferredImageDecoding); 1275} 1276 1277base::ProcessHandle RenderProcessHostImpl::GetHandle() const { 1278 if (run_renderer_in_process()) 1279 return base::Process::Current().handle(); 1280 1281 if (!child_process_launcher_.get() || child_process_launcher_->IsStarting()) 1282 return base::kNullProcessHandle; 1283 1284 return child_process_launcher_->GetHandle(); 1285} 1286 1287bool RenderProcessHostImpl::FastShutdownIfPossible() { 1288 if (run_renderer_in_process()) 1289 return false; // Single process mode never shutdown the renderer. 1290 1291 if (!GetContentClient()->browser()->IsFastShutdownPossible()) 1292 return false; 1293 1294 if (!child_process_launcher_.get() || 1295 child_process_launcher_->IsStarting() || 1296 !GetHandle()) 1297 return false; // Render process hasn't started or is probably crashed. 1298 1299 // Test if there's an unload listener. 1300 // NOTE: It's possible that an onunload listener may be installed 1301 // while we're shutting down, so there's a small race here. Given that 1302 // the window is small, it's unlikely that the web page has much 1303 // state that will be lost by not calling its unload handlers properly. 1304 if (!SuddenTerminationAllowed()) 1305 return false; 1306 1307 if (worker_ref_count_ != 0) { 1308 if (survive_for_worker_start_time_.is_null()) 1309 survive_for_worker_start_time_ = base::TimeTicks::Now(); 1310 return false; 1311 } 1312 1313 // Set this before ProcessDied() so observers can tell if the render process 1314 // died due to fast shutdown versus another cause. 1315 fast_shutdown_started_ = true; 1316 1317 ProcessDied(false /* already_dead */); 1318 return true; 1319} 1320 1321void RenderProcessHostImpl::DumpHandles() { 1322#if defined(OS_WIN) 1323 Send(new ChildProcessMsg_DumpHandles()); 1324#else 1325 NOTIMPLEMENTED(); 1326#endif 1327} 1328 1329bool RenderProcessHostImpl::Send(IPC::Message* msg) { 1330 TRACE_EVENT0("renderer_host", "RenderProcessHostImpl::Send"); 1331 if (!channel_) { 1332 if (!is_initialized_) { 1333 queued_messages_.push(msg); 1334 return true; 1335 } else { 1336 delete msg; 1337 return false; 1338 } 1339 } 1340 1341 if (child_process_launcher_.get() && child_process_launcher_->IsStarting()) { 1342 queued_messages_.push(msg); 1343 return true; 1344 } 1345 1346 return channel_->Send(msg); 1347} 1348 1349bool RenderProcessHostImpl::OnMessageReceived(const IPC::Message& msg) { 1350 // If we're about to be deleted, or have initiated the fast shutdown sequence, 1351 // we ignore incoming messages. 1352 1353 if (deleting_soon_ || fast_shutdown_started_) 1354 return false; 1355 1356 mark_child_process_activity_time(); 1357 if (msg.routing_id() == MSG_ROUTING_CONTROL) { 1358 // Dispatch control messages. 1359 IPC_BEGIN_MESSAGE_MAP(RenderProcessHostImpl, msg) 1360 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_ShutdownRequest, 1361 OnShutdownRequest) 1362 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_DumpHandlesDone, 1363 OnDumpHandlesDone) 1364 IPC_MESSAGE_HANDLER(ViewHostMsg_SuddenTerminationChanged, 1365 SuddenTerminationChanged) 1366 IPC_MESSAGE_HANDLER(ViewHostMsg_UserMetricsRecordAction, 1367 OnUserMetricsRecordAction) 1368 IPC_MESSAGE_HANDLER(ViewHostMsg_SavedPageAsMHTML, OnSavedPageAsMHTML) 1369 IPC_MESSAGE_HANDLER_DELAY_REPLY( 1370 ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer, 1371 OnAllocateGpuMemoryBuffer) 1372 IPC_MESSAGE_HANDLER(ViewHostMsg_Close_ACK, OnCloseACK) 1373#if defined(ENABLE_WEBRTC) 1374 IPC_MESSAGE_HANDLER(AecDumpMsg_RegisterAecDumpConsumer, 1375 OnRegisterAecDumpConsumer) 1376 IPC_MESSAGE_HANDLER(AecDumpMsg_UnregisterAecDumpConsumer, 1377 OnUnregisterAecDumpConsumer) 1378#endif 1379 // Adding single handlers for your service here is fine, but once your 1380 // service needs more than one handler, please extract them into a new 1381 // message filter and add that filter to CreateMessageFilters(). 1382 IPC_END_MESSAGE_MAP() 1383 1384 return true; 1385 } 1386 1387 // Dispatch incoming messages to the appropriate IPC::Listener. 1388 IPC::Listener* listener = listeners_.Lookup(msg.routing_id()); 1389 if (!listener) { 1390 if (msg.is_sync()) { 1391 // The listener has gone away, so we must respond or else the caller will 1392 // hang waiting for a reply. 1393 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg); 1394 reply->set_reply_error(); 1395 Send(reply); 1396 } 1397 1398 // If this is a SwapBuffers, we need to ack it if we're not going to handle 1399 // it so that the GPU process doesn't get stuck in unscheduled state. 1400 IPC_BEGIN_MESSAGE_MAP(RenderProcessHostImpl, msg) 1401 IPC_MESSAGE_HANDLER(ViewHostMsg_CompositorSurfaceBuffersSwapped, 1402 OnCompositorSurfaceBuffersSwappedNoHost) 1403 IPC_END_MESSAGE_MAP() 1404 return true; 1405 } 1406 return listener->OnMessageReceived(msg); 1407} 1408 1409void RenderProcessHostImpl::OnChannelConnected(int32 peer_pid) { 1410#if defined(IPC_MESSAGE_LOG_ENABLED) 1411 Send(new ChildProcessMsg_SetIPCLoggingEnabled( 1412 IPC::Logging::GetInstance()->Enabled())); 1413#endif 1414 1415 tracked_objects::ThreadData::Status status = 1416 tracked_objects::ThreadData::status(); 1417 Send(new ChildProcessMsg_SetProfilerStatus(status)); 1418} 1419 1420void RenderProcessHostImpl::OnChannelError() { 1421 ProcessDied(true /* already_dead */); 1422} 1423 1424void RenderProcessHostImpl::OnBadMessageReceived(const IPC::Message& message) { 1425 // Message de-serialization failed. We consider this a capital crime. Kill the 1426 // renderer if we have one. 1427 LOG(ERROR) << "bad message " << message.type() << " terminating renderer."; 1428 BrowserChildProcessHostImpl::HistogramBadMessageTerminated( 1429 PROCESS_TYPE_RENDERER); 1430 ReceivedBadMessage(); 1431} 1432 1433BrowserContext* RenderProcessHostImpl::GetBrowserContext() const { 1434 return browser_context_; 1435} 1436 1437bool RenderProcessHostImpl::InSameStoragePartition( 1438 StoragePartition* partition) const { 1439 return storage_partition_impl_ == partition; 1440} 1441 1442int RenderProcessHostImpl::GetID() const { 1443 return id_; 1444} 1445 1446bool RenderProcessHostImpl::HasConnection() const { 1447 return channel_.get() != NULL; 1448} 1449 1450void RenderProcessHostImpl::SetIgnoreInputEvents(bool ignore_input_events) { 1451 ignore_input_events_ = ignore_input_events; 1452} 1453 1454bool RenderProcessHostImpl::IgnoreInputEvents() const { 1455 return ignore_input_events_; 1456} 1457 1458void RenderProcessHostImpl::Cleanup() { 1459 // If within_process_died_observer_ is true, one of our observers performed an 1460 // action that caused us to die (e.g. http://crbug.com/339504). Therefore, 1461 // delay the destruction until all of the observer callbacks have been made, 1462 // and guarantee that the RenderProcessHostDestroyed observer callback is 1463 // always the last callback fired. 1464 if (within_process_died_observer_) { 1465 delayed_cleanup_needed_ = true; 1466 return; 1467 } 1468 delayed_cleanup_needed_ = false; 1469 1470 // Records the time when the process starts surviving for workers for UMA. 1471 if (listeners_.IsEmpty() && worker_ref_count_ > 0 && 1472 survive_for_worker_start_time_.is_null()) { 1473 survive_for_worker_start_time_ = base::TimeTicks::Now(); 1474 } 1475 1476 // When there are no other owners of this object, we can delete ourselves. 1477 if (listeners_.IsEmpty() && worker_ref_count_ == 0) { 1478 if (!survive_for_worker_start_time_.is_null()) { 1479 UMA_HISTOGRAM_LONG_TIMES( 1480 "SharedWorker.RendererSurviveForWorkerTime", 1481 base::TimeTicks::Now() - survive_for_worker_start_time_); 1482 } 1483 // We cannot clean up twice; if this fails, there is an issue with our 1484 // control flow. 1485 DCHECK(!deleting_soon_); 1486 1487 DCHECK_EQ(0, pending_views_); 1488 FOR_EACH_OBSERVER(RenderProcessHostObserver, 1489 observers_, 1490 RenderProcessHostDestroyed(this)); 1491 NotificationService::current()->Notify( 1492 NOTIFICATION_RENDERER_PROCESS_TERMINATED, 1493 Source<RenderProcessHost>(this), 1494 NotificationService::NoDetails()); 1495 1496#ifndef NDEBUG 1497 is_self_deleted_ = true; 1498#endif 1499 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); 1500 deleting_soon_ = true; 1501 // It's important not to wait for the DeleteTask to delete the channel 1502 // proxy. Kill it off now. That way, in case the profile is going away, the 1503 // rest of the objects attached to this RenderProcessHost start going 1504 // away first, since deleting the channel proxy will post a 1505 // OnChannelClosed() to IPC::ChannelProxy::Context on the IO thread. 1506 channel_.reset(); 1507 gpu_message_filter_ = NULL; 1508 message_port_message_filter_ = NULL; 1509 RemoveUserData(kSessionStorageHolderKey); 1510 1511 // Remove ourself from the list of renderer processes so that we can't be 1512 // reused in between now and when the Delete task runs. 1513 UnregisterHost(GetID()); 1514 } 1515} 1516 1517void RenderProcessHostImpl::AddPendingView() { 1518 pending_views_++; 1519} 1520 1521void RenderProcessHostImpl::RemovePendingView() { 1522 DCHECK(pending_views_); 1523 pending_views_--; 1524} 1525 1526void RenderProcessHostImpl::SetSuddenTerminationAllowed(bool enabled) { 1527 sudden_termination_allowed_ = enabled; 1528} 1529 1530bool RenderProcessHostImpl::SuddenTerminationAllowed() const { 1531 return sudden_termination_allowed_; 1532} 1533 1534base::TimeDelta RenderProcessHostImpl::GetChildProcessIdleTime() const { 1535 return base::TimeTicks::Now() - child_process_activity_time_; 1536} 1537 1538void RenderProcessHostImpl::ResumeRequestsForView(int route_id) { 1539 widget_helper_->ResumeRequestsForView(route_id); 1540} 1541 1542void RenderProcessHostImpl::FilterURL(bool empty_allowed, GURL* url) { 1543 FilterURL(this, empty_allowed, url); 1544} 1545 1546#if defined(ENABLE_WEBRTC) 1547void RenderProcessHostImpl::EnableAecDump(const base::FilePath& file) { 1548 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1549 // Enable AEC dump for each registered consumer. 1550 for (std::vector<int>::iterator it = aec_dump_consumers_.begin(); 1551 it != aec_dump_consumers_.end(); ++it) { 1552 EnableAecDumpForId(file, *it); 1553 } 1554} 1555 1556void RenderProcessHostImpl::DisableAecDump() { 1557 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1558 // Posting on the FILE thread and then replying back on the UI thread is only 1559 // for avoiding races between enable and disable. Nothing is done on the FILE 1560 // thread. 1561 BrowserThread::PostTaskAndReply( 1562 BrowserThread::FILE, FROM_HERE, 1563 base::Bind(&DisableAecDumpOnFileThread), 1564 base::Bind(&RenderProcessHostImpl::SendDisableAecDumpToRenderer, 1565 weak_factory_.GetWeakPtr())); 1566} 1567 1568void RenderProcessHostImpl::SetWebRtcLogMessageCallback( 1569 base::Callback<void(const std::string&)> callback) { 1570 webrtc_log_message_callback_ = callback; 1571} 1572 1573RenderProcessHostImpl::WebRtcStopRtpDumpCallback 1574RenderProcessHostImpl::StartRtpDump( 1575 bool incoming, 1576 bool outgoing, 1577 const WebRtcRtpPacketCallback& packet_callback) { 1578 if (!p2p_socket_dispatcher_host_) 1579 return WebRtcStopRtpDumpCallback(); 1580 1581 BrowserThread::PostTask(BrowserThread::IO, 1582 FROM_HERE, 1583 base::Bind(&P2PSocketDispatcherHost::StartRtpDump, 1584 p2p_socket_dispatcher_host_, 1585 incoming, 1586 outgoing, 1587 packet_callback)); 1588 1589 if (stop_rtp_dump_callback_.is_null()) { 1590 stop_rtp_dump_callback_ = 1591 base::Bind(&P2PSocketDispatcherHost::StopRtpDumpOnUIThread, 1592 p2p_socket_dispatcher_host_); 1593 } 1594 return stop_rtp_dump_callback_; 1595} 1596#endif 1597 1598IPC::ChannelProxy* RenderProcessHostImpl::GetChannel() { 1599 return channel_.get(); 1600} 1601 1602void RenderProcessHostImpl::AddFilter(BrowserMessageFilter* filter) { 1603 channel_->AddFilter(filter->GetFilter()); 1604} 1605 1606bool RenderProcessHostImpl::FastShutdownForPageCount(size_t count) { 1607 if (static_cast<size_t>(GetActiveViewCount()) == count) 1608 return FastShutdownIfPossible(); 1609 return false; 1610} 1611 1612bool RenderProcessHostImpl::FastShutdownStarted() const { 1613 return fast_shutdown_started_; 1614} 1615 1616// static 1617void RenderProcessHostImpl::RegisterHost(int host_id, RenderProcessHost* host) { 1618 g_all_hosts.Get().AddWithID(host, host_id); 1619} 1620 1621// static 1622void RenderProcessHostImpl::UnregisterHost(int host_id) { 1623 RenderProcessHost* host = g_all_hosts.Get().Lookup(host_id); 1624 if (!host) 1625 return; 1626 1627 g_all_hosts.Get().Remove(host_id); 1628 1629 // Look up the map of site to process for the given browser_context, 1630 // in case we need to remove this process from it. It will be registered 1631 // under any sites it rendered that use process-per-site mode. 1632 SiteProcessMap* map = 1633 GetSiteProcessMapForBrowserContext(host->GetBrowserContext()); 1634 map->RemoveProcess(host); 1635} 1636 1637// static 1638void RenderProcessHostImpl::FilterURL(RenderProcessHost* rph, 1639 bool empty_allowed, 1640 GURL* url) { 1641 ChildProcessSecurityPolicyImpl* policy = 1642 ChildProcessSecurityPolicyImpl::GetInstance(); 1643 1644 if (empty_allowed && url->is_empty()) 1645 return; 1646 1647 // The browser process should never hear the swappedout:// URL from any 1648 // of the renderer's messages. Check for this in debug builds, but don't 1649 // let it crash a release browser. 1650 DCHECK(GURL(kSwappedOutURL) != *url); 1651 1652 if (!url->is_valid()) { 1653 // Have to use about:blank for the denied case, instead of an empty GURL. 1654 // This is because the browser treats navigation to an empty GURL as a 1655 // navigation to the home page. This is often a privileged page 1656 // (chrome://newtab/) which is exactly what we don't want. 1657 *url = GURL(url::kAboutBlankURL); 1658 RecordAction(base::UserMetricsAction("FilterURLTermiate_Invalid")); 1659 return; 1660 } 1661 1662 if (url->SchemeIs(url::kAboutScheme)) { 1663 // The renderer treats all URLs in the about: scheme as being about:blank. 1664 // Canonicalize about: URLs to about:blank. 1665 *url = GURL(url::kAboutBlankURL); 1666 RecordAction(base::UserMetricsAction("FilterURLTermiate_About")); 1667 } 1668 1669 // Do not allow browser plugin guests to navigate to non-web URLs, since they 1670 // cannot swap processes or grant bindings. 1671 bool non_web_url_in_guest = rph->IsIsolatedGuest() && 1672 !(url->is_valid() && policy->IsWebSafeScheme(url->scheme())); 1673 1674 if (non_web_url_in_guest || !policy->CanRequestURL(rph->GetID(), *url)) { 1675 // If this renderer is not permitted to request this URL, we invalidate the 1676 // URL. This prevents us from storing the blocked URL and becoming confused 1677 // later. 1678 VLOG(1) << "Blocked URL " << url->spec(); 1679 *url = GURL(url::kAboutBlankURL); 1680 RecordAction(base::UserMetricsAction("FilterURLTermiate_Blocked")); 1681 } 1682} 1683 1684// static 1685bool RenderProcessHostImpl::IsSuitableHost( 1686 RenderProcessHost* host, 1687 BrowserContext* browser_context, 1688 const GURL& site_url) { 1689 if (run_renderer_in_process()) 1690 return true; 1691 1692 if (host->GetBrowserContext() != browser_context) 1693 return false; 1694 1695 // Do not allow sharing of guest hosts. This is to prevent bugs where guest 1696 // and non-guest storage gets mixed. In the future, we might consider enabling 1697 // the sharing of guests, in this case this check should be removed and 1698 // InSameStoragePartition should handle the possible sharing. 1699 if (host->IsIsolatedGuest()) 1700 return false; 1701 1702 // Check whether the given host and the intended site_url will be using the 1703 // same StoragePartition, since a RenderProcessHost can only support a single 1704 // StoragePartition. This is relevant for packaged apps and isolated sites. 1705 StoragePartition* dest_partition = 1706 BrowserContext::GetStoragePartitionForSite(browser_context, site_url); 1707 if (!host->InSameStoragePartition(dest_partition)) 1708 return false; 1709 1710 if (ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( 1711 host->GetID()) != 1712 WebUIControllerFactoryRegistry::GetInstance()->UseWebUIBindingsForURL( 1713 browser_context, site_url)) { 1714 return false; 1715 } 1716 1717 return GetContentClient()->browser()->IsSuitableHost(host, site_url); 1718} 1719 1720// static 1721bool RenderProcessHost::run_renderer_in_process() { 1722 return g_run_renderer_in_process_; 1723} 1724 1725// static 1726void RenderProcessHost::SetRunRendererInProcess(bool value) { 1727 g_run_renderer_in_process_ = value; 1728 1729 CommandLine* command_line = CommandLine::ForCurrentProcess(); 1730 if (value) { 1731 if (!command_line->HasSwitch(switches::kLang)) { 1732 // Modify the current process' command line to include the browser locale, 1733 // as the renderer expects this flag to be set. 1734 const std::string locale = 1735 GetContentClient()->browser()->GetApplicationLocale(); 1736 command_line->AppendSwitchASCII(switches::kLang, locale); 1737 } 1738 // TODO(piman): we should really send configuration through bools rather 1739 // than by parsing strings, i.e. sending an IPC rather than command line 1740 // args. crbug.com/314909 1741 AppendCompositorCommandLineFlags(command_line); 1742 } 1743} 1744 1745// static 1746RenderProcessHost::iterator RenderProcessHost::AllHostsIterator() { 1747 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1748 return iterator(g_all_hosts.Pointer()); 1749} 1750 1751// static 1752RenderProcessHost* RenderProcessHost::FromID(int render_process_id) { 1753 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1754 return g_all_hosts.Get().Lookup(render_process_id); 1755} 1756 1757// static 1758bool RenderProcessHost::ShouldTryToUseExistingProcessHost( 1759 BrowserContext* browser_context, const GURL& url) { 1760 // Experimental: 1761 // If --enable-strict-site-isolation or --site-per-process is enabled, do not 1762 // try to reuse renderer processes when over the limit. (We could allow pages 1763 // from the same site to share, if we knew what the given process was 1764 // dedicated to. Allowing no sharing is simpler for now.) This may cause 1765 // resource exhaustion issues if too many sites are open at once. 1766 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 1767 if (command_line.HasSwitch(switches::kEnableStrictSiteIsolation) || 1768 command_line.HasSwitch(switches::kSitePerProcess)) 1769 return false; 1770 1771 if (run_renderer_in_process()) 1772 return true; 1773 1774 // NOTE: Sometimes it's necessary to create more render processes than 1775 // GetMaxRendererProcessCount(), for instance when we want to create 1776 // a renderer process for a browser context that has no existing 1777 // renderers. This is OK in moderation, since the 1778 // GetMaxRendererProcessCount() is conservative. 1779 if (g_all_hosts.Get().size() >= GetMaxRendererProcessCount()) 1780 return true; 1781 1782 return GetContentClient()->browser()-> 1783 ShouldTryToUseExistingProcessHost(browser_context, url); 1784} 1785 1786// static 1787RenderProcessHost* RenderProcessHost::GetExistingProcessHost( 1788 BrowserContext* browser_context, 1789 const GURL& site_url) { 1790 // First figure out which existing renderers we can use. 1791 std::vector<RenderProcessHost*> suitable_renderers; 1792 suitable_renderers.reserve(g_all_hosts.Get().size()); 1793 1794 iterator iter(AllHostsIterator()); 1795 while (!iter.IsAtEnd()) { 1796 if (GetContentClient()->browser()->MayReuseHost(iter.GetCurrentValue()) && 1797 RenderProcessHostImpl::IsSuitableHost( 1798 iter.GetCurrentValue(), 1799 browser_context, site_url)) { 1800 suitable_renderers.push_back(iter.GetCurrentValue()); 1801 } 1802 iter.Advance(); 1803 } 1804 1805 // Now pick a random suitable renderer, if we have any. 1806 if (!suitable_renderers.empty()) { 1807 int suitable_count = static_cast<int>(suitable_renderers.size()); 1808 int random_index = base::RandInt(0, suitable_count - 1); 1809 return suitable_renderers[random_index]; 1810 } 1811 1812 return NULL; 1813} 1814 1815// static 1816bool RenderProcessHost::ShouldUseProcessPerSite( 1817 BrowserContext* browser_context, 1818 const GURL& url) { 1819 // Returns true if we should use the process-per-site model. This will be 1820 // the case if the --process-per-site switch is specified, or in 1821 // process-per-site-instance for particular sites (e.g., WebUI). 1822 // Note that --single-process is handled in ShouldTryToUseExistingProcessHost. 1823 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 1824 if (command_line.HasSwitch(switches::kProcessPerSite)) 1825 return true; 1826 1827 // We want to consolidate particular sites like WebUI even when we are using 1828 // the process-per-tab or process-per-site-instance models. 1829 // Note: DevTools pages have WebUI type but should not reuse the same host. 1830 if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL( 1831 browser_context, url) && 1832 !url.SchemeIs(kChromeDevToolsScheme)) { 1833 return true; 1834 } 1835 1836 // Otherwise let the content client decide, defaulting to false. 1837 return GetContentClient()->browser()->ShouldUseProcessPerSite(browser_context, 1838 url); 1839} 1840 1841// static 1842RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSite( 1843 BrowserContext* browser_context, 1844 const GURL& url) { 1845 // Look up the map of site to process for the given browser_context. 1846 SiteProcessMap* map = 1847 GetSiteProcessMapForBrowserContext(browser_context); 1848 1849 // See if we have an existing process with appropriate bindings for this site. 1850 // If not, the caller should create a new process and register it. 1851 std::string site = SiteInstance::GetSiteForURL(browser_context, url) 1852 .possibly_invalid_spec(); 1853 RenderProcessHost* host = map->FindProcess(site); 1854 if (host && (!GetContentClient()->browser()->MayReuseHost(host) || 1855 !IsSuitableHost(host, browser_context, url))) { 1856 // The registered process does not have an appropriate set of bindings for 1857 // the url. Remove it from the map so we can register a better one. 1858 RecordAction( 1859 base::UserMetricsAction("BindingsMismatch_GetProcessHostPerSite")); 1860 map->RemoveProcess(host); 1861 host = NULL; 1862 } 1863 1864 return host; 1865} 1866 1867void RenderProcessHostImpl::RegisterProcessHostForSite( 1868 BrowserContext* browser_context, 1869 RenderProcessHost* process, 1870 const GURL& url) { 1871 // Look up the map of site to process for the given browser_context. 1872 SiteProcessMap* map = 1873 GetSiteProcessMapForBrowserContext(browser_context); 1874 1875 // Only register valid, non-empty sites. Empty or invalid sites will not 1876 // use process-per-site mode. We cannot check whether the process has 1877 // appropriate bindings here, because the bindings have not yet been granted. 1878 std::string site = SiteInstance::GetSiteForURL(browser_context, url) 1879 .possibly_invalid_spec(); 1880 if (!site.empty()) 1881 map->RegisterProcess(site, process); 1882} 1883 1884void RenderProcessHostImpl::ProcessDied(bool already_dead) { 1885 // Our child process has died. If we didn't expect it, it's a crash. 1886 // In any case, we need to let everyone know it's gone. 1887 // The OnChannelError notification can fire multiple times due to nested sync 1888 // calls to a renderer. If we don't have a valid channel here it means we 1889 // already handled the error. 1890 1891 // It should not be possible for us to be called re-entrantly. 1892 DCHECK(!within_process_died_observer_); 1893 1894 // It should not be possible for a process death notification to come in while 1895 // we are dying. 1896 DCHECK(!deleting_soon_); 1897 1898 // child_process_launcher_ can be NULL in single process mode or if fast 1899 // termination happened. 1900 int exit_code = 0; 1901 base::TerminationStatus status = 1902 child_process_launcher_.get() ? 1903 child_process_launcher_->GetChildTerminationStatus(already_dead, 1904 &exit_code) : 1905 base::TERMINATION_STATUS_NORMAL_TERMINATION; 1906 1907 RendererClosedDetails details(GetHandle(), status, exit_code); 1908 within_process_died_observer_ = true; 1909 NotificationService::current()->Notify( 1910 NOTIFICATION_RENDERER_PROCESS_CLOSED, 1911 Source<RenderProcessHost>(this), 1912 Details<RendererClosedDetails>(&details)); 1913 FOR_EACH_OBSERVER(RenderProcessHostObserver, 1914 observers_, 1915 RenderProcessExited(this, GetHandle(), status, exit_code)); 1916 within_process_died_observer_ = false; 1917 1918 child_process_launcher_.reset(); 1919 channel_.reset(); 1920 gpu_message_filter_ = NULL; 1921 message_port_message_filter_ = NULL; 1922 RemoveUserData(kSessionStorageHolderKey); 1923 1924 IDMap<IPC::Listener>::iterator iter(&listeners_); 1925 while (!iter.IsAtEnd()) { 1926 iter.GetCurrentValue()->OnMessageReceived( 1927 ViewHostMsg_RenderProcessGone(iter.GetCurrentKey(), 1928 static_cast<int>(status), 1929 exit_code)); 1930 iter.Advance(); 1931 } 1932 1933 mojo_application_host_.reset(); 1934 1935 // It's possible that one of the calls out to the observers might have caused 1936 // this object to be no longer needed. 1937 if (delayed_cleanup_needed_) 1938 Cleanup(); 1939 1940 // This object is not deleted at this point and might be reused later. 1941 // TODO(darin): clean this up 1942} 1943 1944int RenderProcessHostImpl::GetActiveViewCount() { 1945 int num_active_views = 0; 1946 scoped_ptr<RenderWidgetHostIterator> widgets( 1947 RenderWidgetHost::GetRenderWidgetHosts()); 1948 while (RenderWidgetHost* widget = widgets->GetNextHost()) { 1949 // Count only RenderWidgetHosts in this process. 1950 if (widget->GetProcess()->GetID() == GetID()) 1951 num_active_views++; 1952 } 1953 return num_active_views; 1954} 1955 1956// Frame subscription API for this class is for accelerated composited path 1957// only. These calls are redirected to GpuMessageFilter. 1958void RenderProcessHostImpl::BeginFrameSubscription( 1959 int route_id, 1960 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) { 1961 if (!gpu_message_filter_) 1962 return; 1963 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind( 1964 &GpuMessageFilter::BeginFrameSubscription, 1965 gpu_message_filter_, 1966 route_id, base::Passed(&subscriber))); 1967} 1968 1969void RenderProcessHostImpl::EndFrameSubscription(int route_id) { 1970 if (!gpu_message_filter_) 1971 return; 1972 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind( 1973 &GpuMessageFilter::EndFrameSubscription, 1974 gpu_message_filter_, 1975 route_id)); 1976} 1977 1978#if defined(ENABLE_WEBRTC) 1979void RenderProcessHostImpl::WebRtcLogMessage(const std::string& message) { 1980 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1981 if (!webrtc_log_message_callback_.is_null()) 1982 webrtc_log_message_callback_.Run(message); 1983} 1984#endif 1985 1986void RenderProcessHostImpl::ReleaseOnCloseACK( 1987 RenderProcessHost* host, 1988 const SessionStorageNamespaceMap& sessions, 1989 int view_route_id) { 1990 DCHECK(host); 1991 if (sessions.empty()) 1992 return; 1993 SessionStorageHolder* holder = static_cast<SessionStorageHolder*> 1994 (host->GetUserData(kSessionStorageHolderKey)); 1995 if (!holder) { 1996 holder = new SessionStorageHolder(); 1997 host->SetUserData( 1998 kSessionStorageHolderKey, 1999 holder); 2000 } 2001 holder->Hold(sessions, view_route_id); 2002} 2003 2004void RenderProcessHostImpl::OnShutdownRequest() { 2005 // Don't shut down if there are active RenderViews, or if there are pending 2006 // RenderViews being swapped back in. 2007 // In single process mode, we never shutdown the renderer. 2008 int num_active_views = GetActiveViewCount(); 2009 if (pending_views_ || num_active_views > 0 || run_renderer_in_process()) 2010 return; 2011 2012 // Notify any contents that might have swapped out renderers from this 2013 // process. They should not attempt to swap them back in. 2014 NotificationService::current()->Notify( 2015 NOTIFICATION_RENDERER_PROCESS_CLOSING, 2016 Source<RenderProcessHost>(this), 2017 NotificationService::NoDetails()); 2018 2019 Send(new ChildProcessMsg_Shutdown()); 2020} 2021 2022void RenderProcessHostImpl::SuddenTerminationChanged(bool enabled) { 2023 SetSuddenTerminationAllowed(enabled); 2024} 2025 2026void RenderProcessHostImpl::OnDumpHandlesDone() { 2027 Cleanup(); 2028} 2029 2030void RenderProcessHostImpl::SetBackgrounded(bool backgrounded) { 2031 // Note: we always set the backgrounded_ value. If the process is NULL 2032 // (and hence hasn't been created yet), we will set the process priority 2033 // later when we create the process. 2034 backgrounded_ = backgrounded; 2035 if (!child_process_launcher_.get() || child_process_launcher_->IsStarting()) 2036 return; 2037 2038 // Don't background processes which have active audio streams. 2039 if (backgrounded_ && audio_renderer_host_->HasActiveAudio()) 2040 return; 2041 2042#if defined(OS_WIN) 2043 // The cbstext.dll loads as a global GetMessage hook in the browser process 2044 // and intercepts/unintercepts the kernel32 API SetPriorityClass in a 2045 // background thread. If the UI thread invokes this API just when it is 2046 // intercepted the stack is messed up on return from the interceptor 2047 // which causes random crashes in the browser process. Our hack for now 2048 // is to not invoke the SetPriorityClass API if the dll is loaded. 2049 if (GetModuleHandle(L"cbstext.dll")) 2050 return; 2051#endif // OS_WIN 2052 2053 // Notify the child process of background state. 2054 Send(new ChildProcessMsg_SetProcessBackgrounded(backgrounded)); 2055 2056#if !defined(OS_WIN) 2057 // Backgrounding may require elevated privileges not available to renderer 2058 // processes, so control backgrounding from the process host. 2059 2060 // Windows Vista+ has a fancy process backgrounding mode that can only be set 2061 // from within the process. 2062 child_process_launcher_->SetProcessBackgrounded(backgrounded); 2063#endif // !OS_WIN 2064} 2065 2066void RenderProcessHostImpl::OnProcessLaunched() { 2067 // No point doing anything, since this object will be destructed soon. We 2068 // especially don't want to send the RENDERER_PROCESS_CREATED notification, 2069 // since some clients might expect a RENDERER_PROCESS_TERMINATED afterwards to 2070 // properly cleanup. 2071 if (deleting_soon_) 2072 return; 2073 2074 if (child_process_launcher_) { 2075 if (!child_process_launcher_->GetHandle()) { 2076 OnChannelError(); 2077 return; 2078 } 2079 2080 SetBackgrounded(backgrounded_); 2081 } 2082 2083 // NOTE: This needs to be before sending queued messages because 2084 // ExtensionService uses this notification to initialize the renderer process 2085 // with state that must be there before any JavaScript executes. 2086 // 2087 // The queued messages contain such things as "navigate". If this notification 2088 // was after, we can end up executing JavaScript before the initialization 2089 // happens. 2090 NotificationService::current()->Notify( 2091 NOTIFICATION_RENDERER_PROCESS_CREATED, 2092 Source<RenderProcessHost>(this), 2093 NotificationService::NoDetails()); 2094 2095 // Allow Mojo to be setup before the renderer sees any Chrome IPC messages. 2096 // This way, Mojo can be safely used from the renderer in response to any 2097 // Chrome IPC message. 2098 MaybeActivateMojo(); 2099 2100 while (!queued_messages_.empty()) { 2101 Send(queued_messages_.front()); 2102 queued_messages_.pop(); 2103 } 2104 2105#if defined(ENABLE_WEBRTC) 2106 if (WebRTCInternals::GetInstance()->aec_dump_enabled()) 2107 EnableAecDump(WebRTCInternals::GetInstance()->aec_dump_file_path()); 2108#endif 2109} 2110 2111scoped_refptr<AudioRendererHost> 2112RenderProcessHostImpl::audio_renderer_host() const { 2113 return audio_renderer_host_; 2114} 2115 2116void RenderProcessHostImpl::OnUserMetricsRecordAction( 2117 const std::string& action) { 2118 RecordComputedAction(action); 2119} 2120 2121void RenderProcessHostImpl::OnCloseACK(int old_route_id) { 2122 SessionStorageHolder* holder = static_cast<SessionStorageHolder*> 2123 (GetUserData(kSessionStorageHolderKey)); 2124 if (!holder) 2125 return; 2126 holder->Release(old_route_id); 2127} 2128 2129void RenderProcessHostImpl::OnSavedPageAsMHTML(int job_id, int64 data_size) { 2130 MHTMLGenerationManager::GetInstance()->MHTMLGenerated(job_id, data_size); 2131} 2132 2133void RenderProcessHostImpl::OnCompositorSurfaceBuffersSwappedNoHost( 2134 const ViewHostMsg_CompositorSurfaceBuffersSwapped_Params& params) { 2135 TRACE_EVENT0("renderer_host", 2136 "RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwappedNoHost"); 2137 if (!ui::LatencyInfo::Verify(params.latency_info, 2138 "ViewHostMsg_CompositorSurfaceBuffersSwapped")) 2139 return; 2140 AcceleratedSurfaceMsg_BufferPresented_Params ack_params; 2141 ack_params.sync_point = 0; 2142 RenderWidgetHostImpl::AcknowledgeBufferPresent(params.route_id, 2143 params.gpu_process_host_id, 2144 ack_params); 2145} 2146 2147void RenderProcessHostImpl::OnGpuSwitching() { 2148 // We are updating all widgets including swapped out ones. 2149 scoped_ptr<RenderWidgetHostIterator> widgets( 2150 RenderWidgetHostImpl::GetAllRenderWidgetHosts()); 2151 while (RenderWidgetHost* widget = widgets->GetNextHost()) { 2152 if (!widget->IsRenderView()) 2153 continue; 2154 2155 // Skip widgets in other processes. 2156 if (widget->GetProcess()->GetID() != GetID()) 2157 continue; 2158 2159 RenderViewHost* rvh = RenderViewHost::From(widget); 2160 rvh->UpdateWebkitPreferences(rvh->GetWebkitPreferences()); 2161 } 2162} 2163 2164#if defined(ENABLE_WEBRTC) 2165void RenderProcessHostImpl::OnRegisterAecDumpConsumer(int id) { 2166 BrowserThread::PostTask( 2167 BrowserThread::UI, 2168 FROM_HERE, 2169 base::Bind( 2170 &RenderProcessHostImpl::RegisterAecDumpConsumerOnUIThread, 2171 weak_factory_.GetWeakPtr(), 2172 id)); 2173} 2174 2175void RenderProcessHostImpl::OnUnregisterAecDumpConsumer(int id) { 2176 BrowserThread::PostTask( 2177 BrowserThread::UI, 2178 FROM_HERE, 2179 base::Bind( 2180 &RenderProcessHostImpl::UnregisterAecDumpConsumerOnUIThread, 2181 weak_factory_.GetWeakPtr(), 2182 id)); 2183} 2184 2185void RenderProcessHostImpl::RegisterAecDumpConsumerOnUIThread(int id) { 2186 DCHECK_CURRENTLY_ON(BrowserThread::UI); 2187 aec_dump_consumers_.push_back(id); 2188 if (WebRTCInternals::GetInstance()->aec_dump_enabled()) { 2189 EnableAecDumpForId(WebRTCInternals::GetInstance()->aec_dump_file_path(), 2190 id); 2191 } 2192} 2193 2194void RenderProcessHostImpl::UnregisterAecDumpConsumerOnUIThread(int id) { 2195 DCHECK_CURRENTLY_ON(BrowserThread::UI); 2196 for (std::vector<int>::iterator it = aec_dump_consumers_.begin(); 2197 it != aec_dump_consumers_.end(); ++it) { 2198 if (*it == id) { 2199 aec_dump_consumers_.erase(it); 2200 break; 2201 } 2202 } 2203} 2204 2205#if defined(OS_WIN) 2206#define IntToStringType base::IntToString16 2207#else 2208#define IntToStringType base::IntToString 2209#endif 2210 2211void RenderProcessHostImpl::EnableAecDumpForId(const base::FilePath& file, 2212 int id) { 2213 DCHECK_CURRENTLY_ON(BrowserThread::UI); 2214 base::FilePath unique_file = 2215 file.AddExtension(IntToStringType(GetID())) 2216 .AddExtension(IntToStringType(id)); 2217 BrowserThread::PostTaskAndReplyWithResult( 2218 BrowserThread::FILE, FROM_HERE, 2219 base::Bind(&CreateAecDumpFileForProcess, unique_file, GetHandle()), 2220 base::Bind(&RenderProcessHostImpl::SendAecDumpFileToRenderer, 2221 weak_factory_.GetWeakPtr(), 2222 id)); 2223} 2224 2225#undef IntToStringType 2226 2227void RenderProcessHostImpl::SendAecDumpFileToRenderer( 2228 int id, 2229 IPC::PlatformFileForTransit file_for_transit) { 2230 if (file_for_transit == IPC::InvalidPlatformFileForTransit()) 2231 return; 2232 Send(new AecDumpMsg_EnableAecDump(id, file_for_transit)); 2233} 2234 2235void RenderProcessHostImpl::SendDisableAecDumpToRenderer() { 2236 Send(new AecDumpMsg_DisableAecDump()); 2237} 2238#endif 2239 2240void RenderProcessHostImpl::IncrementWorkerRefCount() { 2241 DCHECK_CURRENTLY_ON(BrowserThread::UI); 2242 ++worker_ref_count_; 2243} 2244 2245void RenderProcessHostImpl::DecrementWorkerRefCount() { 2246 DCHECK_CURRENTLY_ON(BrowserThread::UI); 2247 DCHECK_GT(worker_ref_count_, 0); 2248 --worker_ref_count_; 2249 if (worker_ref_count_ == 0) 2250 Cleanup(); 2251} 2252 2253void RenderProcessHostImpl::ConnectTo( 2254 const base::StringPiece& service_name, 2255 mojo::ScopedMessagePipeHandle handle) { 2256 mojo_activation_required_ = true; 2257 MaybeActivateMojo(); 2258 2259 mojo_application_host_->service_provider()->ConnectToService( 2260 mojo::String::From(service_name), 2261 std::string(), 2262 handle.Pass(), 2263 mojo::String()); 2264} 2265 2266void RenderProcessHostImpl::OnAllocateGpuMemoryBuffer(uint32 width, 2267 uint32 height, 2268 uint32 internalformat, 2269 uint32 usage, 2270 IPC::Message* reply) { 2271 DCHECK_CURRENTLY_ON(BrowserThread::UI); 2272 if (!GpuMemoryBufferImpl::IsFormatValid(internalformat) || 2273 !GpuMemoryBufferImpl::IsUsageValid(usage)) { 2274 GpuMemoryBufferAllocated(reply, gfx::GpuMemoryBufferHandle()); 2275 return; 2276 } 2277 base::CheckedNumeric<int> size = width; 2278 size *= height; 2279 if (!size.IsValid()) { 2280 GpuMemoryBufferAllocated(reply, gfx::GpuMemoryBufferHandle()); 2281 return; 2282 } 2283 2284#if defined(OS_MACOSX) 2285 // TODO(reveman): This should be moved to 2286 // GpuMemoryBufferImpl::AllocateForChildProcess and 2287 // GpuMemoryBufferImplIOSurface. crbug.com/325045, crbug.com/323304 2288 if (GpuMemoryBufferImplIOSurface::IsConfigurationSupported(internalformat, 2289 usage)) { 2290 base::ScopedCFTypeRef<CFMutableDictionaryRef> properties; 2291 properties.reset( 2292 CFDictionaryCreateMutable(kCFAllocatorDefault, 2293 0, 2294 &kCFTypeDictionaryKeyCallBacks, 2295 &kCFTypeDictionaryValueCallBacks)); 2296 AddIntegerValue(properties, kIOSurfaceWidth, width); 2297 AddIntegerValue(properties, kIOSurfaceHeight, height); 2298 AddIntegerValue(properties, 2299 kIOSurfaceBytesPerElement, 2300 GpuMemoryBufferImpl::BytesPerPixel(internalformat)); 2301 AddIntegerValue( 2302 properties, 2303 kIOSurfacePixelFormat, 2304 GpuMemoryBufferImplIOSurface::PixelFormat(internalformat)); 2305 // TODO(reveman): Remove this when using a mach_port_t to transfer 2306 // IOSurface to renderer process. crbug.com/323304 2307 AddBooleanValue( 2308 properties, kIOSurfaceIsGlobal, true); 2309 2310 base::ScopedCFTypeRef<IOSurfaceRef> io_surface(IOSurfaceCreate(properties)); 2311 if (io_surface) { 2312 gfx::GpuMemoryBufferHandle handle; 2313 handle.type = gfx::IO_SURFACE_BUFFER; 2314 handle.io_surface_id = IOSurfaceGetID(io_surface); 2315 2316 // TODO(reveman): This makes the assumption that the renderer will 2317 // grab a reference to the surface before sending another message. 2318 // crbug.com/325045 2319 last_io_surface_ = io_surface; 2320 GpuMemoryBufferAllocated(reply, handle); 2321 return; 2322 } 2323 } 2324#endif 2325 2326#if defined(OS_ANDROID) 2327 // TODO(reveman): This should be moved to 2328 // GpuMemoryBufferImpl::AllocateForChildProcess and 2329 // GpuMemoryBufferImplSurfaceTexture when adding support for out-of-process 2330 // GPU service. crbug.com/368716 2331 if (GpuMemoryBufferImplSurfaceTexture::IsConfigurationSupported( 2332 internalformat, usage)) { 2333 // Each surface texture is associated with a render process id. This allows 2334 // the GPU service and Java Binder IPC to verify that a renderer is not 2335 // trying to use a surface texture it doesn't own. 2336 int surface_texture_id = CompositorImpl::CreateSurfaceTexture(GetID()); 2337 if (surface_texture_id != -1) { 2338 gfx::GpuMemoryBufferHandle handle; 2339 handle.type = gfx::SURFACE_TEXTURE_BUFFER; 2340 handle.surface_texture_id = 2341 gfx::SurfaceTextureId(surface_texture_id, GetID()); 2342 GpuMemoryBufferAllocated(reply, handle); 2343 return; 2344 } 2345 } 2346#endif 2347 2348 GpuMemoryBufferImpl::AllocateForChildProcess( 2349 gfx::Size(width, height), 2350 internalformat, 2351 usage, 2352 GetHandle(), 2353 base::Bind(&RenderProcessHostImpl::GpuMemoryBufferAllocated, 2354 weak_factory_.GetWeakPtr(), 2355 reply)); 2356} 2357 2358void RenderProcessHostImpl::GpuMemoryBufferAllocated( 2359 IPC::Message* reply, 2360 const gfx::GpuMemoryBufferHandle& handle) { 2361 DCHECK_CURRENTLY_ON(BrowserThread::UI); 2362 ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer::WriteReplyParams(reply, 2363 handle); 2364 Send(reply); 2365} 2366 2367} // namespace content 2368