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#include "content/renderer/render_thread_impl.h" 6 7#include <algorithm> 8#include <limits> 9#include <map> 10#include <vector> 11 12#include "base/allocator/allocator_extension.h" 13#include "base/command_line.h" 14#include "base/debug/trace_event.h" 15#include "base/lazy_instance.h" 16#include "base/logging.h" 17#include "base/memory/discardable_memory.h" 18#include "base/memory/shared_memory.h" 19#include "base/metrics/field_trial.h" 20#include "base/metrics/histogram.h" 21#include "base/metrics/stats_table.h" 22#include "base/path_service.h" 23#include "base/strings/string16.h" 24#include "base/strings/string_tokenizer.h" 25#include "base/strings/utf_string_conversions.h" 26#include "base/threading/thread_local.h" 27#include "base/threading/thread_restrictions.h" 28#include "base/values.h" 29#include "content/child/appcache/appcache_dispatcher.h" 30#include "content/child/appcache/appcache_frontend_impl.h" 31#include "content/child/child_histogram_message_filter.h" 32#include "content/child/db_message_filter.h" 33#include "content/child/indexed_db/indexed_db_dispatcher.h" 34#include "content/child/indexed_db/indexed_db_message_filter.h" 35#include "content/child/npapi/npobject_util.h" 36#include "content/child/plugin_messages.h" 37#include "content/child/resource_dispatcher.h" 38#include "content/child/runtime_features.h" 39#include "content/child/thread_safe_sender.h" 40#include "content/child/web_database_observer_impl.h" 41#include "content/common/child_process_messages.h" 42#include "content/common/content_constants_internal.h" 43#include "content/common/database_messages.h" 44#include "content/common/dom_storage/dom_storage_messages.h" 45#include "content/common/gpu/client/context_provider_command_buffer.h" 46#include "content/common/gpu/client/gpu_channel_host.h" 47#include "content/common/gpu/client/gpu_memory_buffer_impl.h" 48#include "content/common/gpu/gpu_messages.h" 49#include "content/common/gpu/gpu_process_launch_causes.h" 50#include "content/common/resource_messages.h" 51#include "content/common/view_messages.h" 52#include "content/public/common/content_constants.h" 53#include "content/public/common/content_paths.h" 54#include "content/public/common/content_switches.h" 55#include "content/public/common/renderer_preferences.h" 56#include "content/public/common/url_constants.h" 57#include "content/public/renderer/content_renderer_client.h" 58#include "content/public/renderer/render_process_observer.h" 59#include "content/public/renderer/render_view_visitor.h" 60#include "content/renderer/devtools/devtools_agent_filter.h" 61#include "content/renderer/dom_storage/dom_storage_dispatcher.h" 62#include "content/renderer/dom_storage/webstoragearea_impl.h" 63#include "content/renderer/dom_storage/webstoragenamespace_impl.h" 64#include "content/renderer/gamepad_shared_memory_reader.h" 65#include "content/renderer/gpu/compositor_output_surface.h" 66#include "content/renderer/gpu/gpu_benchmarking_extension.h" 67#include "content/renderer/input/input_event_filter.h" 68#include "content/renderer/input/input_handler_manager.h" 69#include "content/renderer/media/audio_input_message_filter.h" 70#include "content/renderer/media/audio_message_filter.h" 71#include "content/renderer/media/audio_renderer_mixer_manager.h" 72#include "content/renderer/media/media_stream_center.h" 73#include "content/renderer/media/media_stream_dependency_factory.h" 74#include "content/renderer/media/midi_message_filter.h" 75#include "content/renderer/media/peer_connection_tracker.h" 76#include "content/renderer/media/video_capture_impl_manager.h" 77#include "content/renderer/media/video_capture_message_filter.h" 78#include "content/renderer/media/webrtc_identity_service.h" 79#include "content/renderer/memory_benchmarking_extension.h" 80#include "content/renderer/p2p/socket_dispatcher.h" 81#include "content/renderer/render_process_impl.h" 82#include "content/renderer/render_view_impl.h" 83#include "content/renderer/renderer_webkitplatformsupport_impl.h" 84#include "content/renderer/service_worker/embedded_worker_dispatcher.h" 85#include "content/renderer/skia_benchmarking_extension.h" 86#include "grit/content_resources.h" 87#include "ipc/ipc_channel_handle.h" 88#include "ipc/ipc_forwarding_message_filter.h" 89#include "ipc/ipc_platform_file.h" 90#include "media/base/audio_hardware_config.h" 91#include "media/base/media.h" 92#include "media/filters/gpu_video_accelerator_factories.h" 93#include "net/base/net_errors.h" 94#include "net/base/net_util.h" 95#include "third_party/skia/include/core/SkGraphics.h" 96#include "third_party/WebKit/public/platform/WebString.h" 97#include "third_party/WebKit/public/web/WebColorName.h" 98#include "third_party/WebKit/public/web/WebDatabase.h" 99#include "third_party/WebKit/public/web/WebDocument.h" 100#include "third_party/WebKit/public/web/WebFrame.h" 101#include "third_party/WebKit/public/web/WebImageCache.h" 102#include "third_party/WebKit/public/web/WebKit.h" 103#include "third_party/WebKit/public/web/WebNetworkStateNotifier.h" 104#include "third_party/WebKit/public/web/WebPopupMenu.h" 105#include "third_party/WebKit/public/web/WebRuntimeFeatures.h" 106#include "third_party/WebKit/public/web/WebScriptController.h" 107#include "third_party/WebKit/public/web/WebSecurityPolicy.h" 108#include "third_party/WebKit/public/web/WebView.h" 109#include "ui/base/layout.h" 110#include "ui/base/ui_base_switches.h" 111#include "v8/include/v8.h" 112#include "webkit/child/worker_task_runner.h" 113#include "webkit/renderer/compositor_bindings/web_external_bitmap_impl.h" 114 115#if defined(OS_WIN) 116#include <windows.h> 117#include <objbase.h> 118#include "base/win/scoped_com_initializer.h" 119#else 120// TODO(port) 121#include "base/memory/scoped_handle.h" 122#include "content/child/npapi/np_channel_base.h" 123#endif 124 125#if defined(OS_MACOSX) 126#include "third_party/WebKit/public/web/mac/WebScrollbarTheme.h" 127#endif 128 129#if defined(OS_POSIX) 130#include "ipc/ipc_channel_posix.h" 131#endif 132 133#if defined(OS_ANDROID) 134#include <cpu-features.h> 135#include "content/renderer/android/synchronous_compositor_factory.h" 136#include "content/renderer/media/android/renderer_demuxer_android.h" 137#endif 138 139#if defined(ENABLE_PLUGINS) 140#include "content/renderer/npapi/plugin_channel_host.h" 141#endif 142 143using base::ThreadRestrictions; 144using blink::WebDocument; 145using blink::WebFrame; 146using blink::WebNetworkStateNotifier; 147using blink::WebRuntimeFeatures; 148using blink::WebScriptController; 149using blink::WebSecurityPolicy; 150using blink::WebString; 151using blink::WebView; 152 153namespace content { 154 155namespace { 156 157const int64 kInitialIdleHandlerDelayMs = 1000; 158const int64 kShortIdleHandlerDelayMs = 1000; 159const int64 kLongIdleHandlerDelayMs = 30*1000; 160const int kIdleCPUUsageThresholdInPercents = 3; 161 162// Keep the global RenderThreadImpl in a TLS slot so it is impossible to access 163// incorrectly from the wrong thread. 164base::LazyInstance<base::ThreadLocalPointer<RenderThreadImpl> > 165 lazy_tls = LAZY_INSTANCE_INITIALIZER; 166 167class RenderViewZoomer : public RenderViewVisitor { 168 public: 169 RenderViewZoomer(const std::string& scheme, 170 const std::string& host, 171 double zoom_level) : scheme_(scheme), 172 host_(host), 173 zoom_level_(zoom_level) { 174 } 175 176 virtual bool Visit(RenderView* render_view) OVERRIDE { 177 WebView* webview = render_view->GetWebView(); 178 WebDocument document = webview->mainFrame()->document(); 179 180 // Don't set zoom level for full-page plugin since they don't use the same 181 // zoom settings. 182 if (document.isPluginDocument()) 183 return true; 184 GURL url(document.url()); 185 // Empty scheme works as wildcard that matches any scheme, 186 if ((net::GetHostOrSpecFromURL(url) == host_) && 187 (scheme_.empty() || scheme_ == url.scheme())) { 188 webview->setZoomLevel(zoom_level_); 189 } 190 return true; 191 } 192 193 private: 194 const std::string scheme_; 195 const std::string host_; 196 const double zoom_level_; 197 198 DISALLOW_COPY_AND_ASSIGN(RenderViewZoomer); 199}; 200 201std::string HostToCustomHistogramSuffix(const std::string& host) { 202 if (host == "mail.google.com") 203 return ".gmail"; 204 if (host == "docs.google.com" || host == "drive.google.com") 205 return ".docs"; 206 if (host == "plus.google.com") 207 return ".plus"; 208 return std::string(); 209} 210 211void* CreateHistogram( 212 const char *name, int min, int max, size_t buckets) { 213 if (min <= 0) 214 min = 1; 215 std::string histogram_name; 216 RenderThreadImpl* render_thread_impl = RenderThreadImpl::current(); 217 if (render_thread_impl) { // Can be null in tests. 218 histogram_name = render_thread_impl-> 219 histogram_customizer()->ConvertToCustomHistogramName(name); 220 } else { 221 histogram_name = std::string(name); 222 } 223 base::HistogramBase* histogram = base::Histogram::FactoryGet( 224 histogram_name, min, max, buckets, 225 base::Histogram::kUmaTargetedHistogramFlag); 226 return histogram; 227} 228 229void AddHistogramSample(void* hist, int sample) { 230 base::Histogram* histogram = static_cast<base::Histogram*>(hist); 231 histogram->Add(sample); 232} 233 234scoped_ptr<base::SharedMemory> AllocateSharedMemoryFunction(size_t size) { 235 return RenderThreadImpl::Get()->HostAllocateSharedMemoryBuffer(size); 236} 237 238void EnableWebCoreLogChannels(const std::string& channels) { 239 if (channels.empty()) 240 return; 241 base::StringTokenizer t(channels, ", "); 242 while (t.GetNext()) 243 blink::enableLogChannel(t.token().c_str()); 244} 245 246} // namespace 247 248RenderThreadImpl::HistogramCustomizer::HistogramCustomizer() { 249 custom_histograms_.insert("V8.MemoryExternalFragmentationTotal"); 250 custom_histograms_.insert("V8.MemoryHeapSampleTotalCommitted"); 251 custom_histograms_.insert("V8.MemoryHeapSampleTotalUsed"); 252} 253 254RenderThreadImpl::HistogramCustomizer::~HistogramCustomizer() {} 255 256void RenderThreadImpl::HistogramCustomizer::RenderViewNavigatedToHost( 257 const std::string& host, size_t view_count) { 258 if (CommandLine::ForCurrentProcess()->HasSwitch( 259 switches::kDisableHistogramCustomizer)) { 260 return; 261 } 262 // Check if all RenderViews are displaying a page from the same host. If there 263 // is only one RenderView, the common host is this view's host. If there are 264 // many, check if this one shares the common host of the other 265 // RenderViews. It's ok to not detect some cases where the RenderViews share a 266 // common host. This information is only used for producing custom histograms. 267 if (view_count == 1) 268 SetCommonHost(host); 269 else if (host != common_host_) 270 SetCommonHost(std::string()); 271} 272 273std::string RenderThreadImpl::HistogramCustomizer::ConvertToCustomHistogramName( 274 const char* histogram_name) const { 275 std::string name(histogram_name); 276 if (!common_host_histogram_suffix_.empty() && 277 custom_histograms_.find(name) != custom_histograms_.end()) 278 name += common_host_histogram_suffix_; 279 return name; 280} 281 282void RenderThreadImpl::HistogramCustomizer::SetCommonHost( 283 const std::string& host) { 284 if (host != common_host_) { 285 common_host_ = host; 286 common_host_histogram_suffix_ = HostToCustomHistogramSuffix(host); 287 v8::V8::SetCreateHistogramFunction(CreateHistogram); 288 } 289} 290 291RenderThreadImpl* RenderThreadImpl::current() { 292 return lazy_tls.Pointer()->Get(); 293} 294 295// When we run plugins in process, we actually run them on the render thread, 296// which means that we need to make the render thread pump UI events. 297RenderThreadImpl::RenderThreadImpl() { 298 Init(); 299} 300 301RenderThreadImpl::RenderThreadImpl(const std::string& channel_name) 302 : ChildThread(channel_name) { 303 Init(); 304} 305 306void RenderThreadImpl::Init() { 307 TRACE_EVENT_BEGIN_ETW("RenderThreadImpl::Init", 0, ""); 308 309 base::debug::TraceLog::GetInstance()->SetThreadSortIndex( 310 base::PlatformThread::CurrentId(), 311 kTraceEventRendererMainThreadSortIndex); 312 313 v8::V8::SetCounterFunction(base::StatsTable::FindLocation); 314 v8::V8::SetCreateHistogramFunction(CreateHistogram); 315 v8::V8::SetAddHistogramSampleFunction(AddHistogramSample); 316 317#if defined(OS_MACOSX) || defined(OS_ANDROID) 318 // On Mac and Android, the select popups are rendered by the browser. 319 blink::WebView::setUseExternalPopupMenus(true); 320#endif 321 322 lazy_tls.Pointer()->Set(this); 323 324#if defined(OS_WIN) 325 // If you are running plugins in this thread you need COM active but in 326 // the normal case you don't. 327 if (RenderProcessImpl::InProcessPlugins()) 328 initialize_com_.reset(new base::win::ScopedCOMInitializer()); 329#endif 330 331 // Register this object as the main thread. 332 ChildProcess::current()->set_main_thread(this); 333 334 // In single process the single process is all there is. 335 suspend_webkit_shared_timer_ = true; 336 notify_webkit_of_modal_loop_ = true; 337 widget_count_ = 0; 338 hidden_widget_count_ = 0; 339 idle_notification_delay_in_ms_ = kInitialIdleHandlerDelayMs; 340 idle_notifications_to_skip_ = 0; 341 layout_test_mode_ = false; 342 shutdown_event_ = NULL; 343 344 appcache_dispatcher_.reset( 345 new AppCacheDispatcher(Get(), new AppCacheFrontendImpl())); 346 dom_storage_dispatcher_.reset(new DomStorageDispatcher()); 347 main_thread_indexed_db_dispatcher_.reset(new IndexedDBDispatcher( 348 thread_safe_sender())); 349 embedded_worker_dispatcher_.reset(new EmbeddedWorkerDispatcher()); 350 351 media_stream_center_ = NULL; 352 353 db_message_filter_ = new DBMessageFilter(); 354 AddFilter(db_message_filter_.get()); 355 356#if defined(ENABLE_WEBRTC) 357 peer_connection_tracker_.reset(new PeerConnectionTracker()); 358 AddObserver(peer_connection_tracker_.get()); 359 360 p2p_socket_dispatcher_ = 361 new P2PSocketDispatcher(GetIOMessageLoopProxy().get()); 362 AddFilter(p2p_socket_dispatcher_.get()); 363 364 webrtc_identity_service_.reset(new WebRTCIdentityService()); 365#endif // defined(ENABLE_WEBRTC) 366 vc_manager_ = new VideoCaptureImplManager(); 367 AddFilter(vc_manager_->video_capture_message_filter()); 368 369 audio_input_message_filter_ = 370 new AudioInputMessageFilter(GetIOMessageLoopProxy()); 371 AddFilter(audio_input_message_filter_.get()); 372 373 audio_message_filter_ = new AudioMessageFilter(GetIOMessageLoopProxy()); 374 AddFilter(audio_message_filter_.get()); 375 376 midi_message_filter_ = new MIDIMessageFilter(GetIOMessageLoopProxy()); 377 AddFilter(midi_message_filter_.get()); 378 379 AddFilter((new IndexedDBMessageFilter(thread_safe_sender()))->GetFilter()); 380 381 GetContentClient()->renderer()->RenderThreadStarted(); 382 383 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 384 if (command_line.HasSwitch(switches::kEnableGpuBenchmarking)) 385 RegisterExtension(GpuBenchmarkingExtension::Get()); 386 387#if defined(USE_TCMALLOC) && (defined(OS_LINUX) || defined(OS_ANDROID)) 388 if (command_line.HasSwitch(switches::kEnableMemoryBenchmarking)) 389 RegisterExtension(MemoryBenchmarkingExtension::Get()); 390#endif // USE_TCMALLOC 391 392 if (command_line.HasSwitch(switches::kEnableSkiaBenchmarking)) { 393 LOG(WARNING) << "Enabling unsafe Skia benchmarking extension."; 394 RegisterExtension(SkiaBenchmarkingExtension::Get()); 395 } 396 397 // Note that under Linux, the media library will normally already have 398 // been initialized by the Zygote before this instance became a Renderer. 399 base::FilePath media_path; 400 PathService::Get(DIR_MEDIA_LIBS, &media_path); 401 if (!media_path.empty()) 402 media::InitializeMediaLibrary(media_path); 403 404 memory_pressure_listener_.reset(new base::MemoryPressureListener( 405 base::Bind(&RenderThreadImpl::OnMemoryPressure, base::Unretained(this)))); 406 407 renderer_process_id_ = base::kNullProcessId; 408 409 // AllocateGpuMemoryBuffer must be used exclusively on one thread but 410 // it doesn't have to be the same thread RenderThreadImpl is created on. 411 allocate_gpu_memory_buffer_thread_checker_.DetachFromThread(); 412 413 TRACE_EVENT_END_ETW("RenderThreadImpl::Init", 0, ""); 414} 415 416RenderThreadImpl::~RenderThreadImpl() { 417} 418 419void RenderThreadImpl::Shutdown() { 420 FOR_EACH_OBSERVER( 421 RenderProcessObserver, observers_, OnRenderProcessShutdown()); 422 423 ChildThread::Shutdown(); 424 425 // Wait for all databases to be closed. 426 if (webkit_platform_support_) { 427 webkit_platform_support_->web_database_observer_impl()-> 428 WaitForAllDatabasesToClose(); 429 } 430 431 // Shutdown in reverse of the initialization order. 432 if (devtools_agent_message_filter_.get()) { 433 RemoveFilter(devtools_agent_message_filter_.get()); 434 devtools_agent_message_filter_ = NULL; 435 } 436 437 RemoveFilter(audio_input_message_filter_.get()); 438 audio_input_message_filter_ = NULL; 439 440 RemoveFilter(audio_message_filter_.get()); 441 audio_message_filter_ = NULL; 442 443 RemoveFilter(vc_manager_->video_capture_message_filter()); 444 445 RemoveFilter(db_message_filter_.get()); 446 db_message_filter_ = NULL; 447 448 // Shutdown the file thread if it's running. 449 if (file_thread_) 450 file_thread_->Stop(); 451 452 if (compositor_output_surface_filter_.get()) { 453 RemoveFilter(compositor_output_surface_filter_.get()); 454 compositor_output_surface_filter_ = NULL; 455 } 456 457 compositor_thread_.reset(); 458 input_handler_manager_.reset(); 459 if (input_event_filter_.get()) { 460 RemoveFilter(input_event_filter_.get()); 461 input_event_filter_ = NULL; 462 } 463 464 // Ramp down IDB before we ramp down WebKit (and V8), since IDB classes might 465 // hold pointers to V8 objects (e.g., via pending requests). 466 main_thread_indexed_db_dispatcher_.reset(); 467 468 if (webkit_platform_support_) 469 blink::shutdown(); 470 471 lazy_tls.Pointer()->Set(NULL); 472 473 // TODO(port) 474#if defined(OS_WIN) 475 // Clean up plugin channels before this thread goes away. 476 NPChannelBase::CleanupChannels(); 477#endif 478 479 // Leak shared contexts on other threads, as we can not get to the correct 480 // thread to destroy them. 481 if (offscreen_compositor_contexts_.get()) 482 offscreen_compositor_contexts_->set_leak_on_destroy(); 483} 484 485bool RenderThreadImpl::Send(IPC::Message* msg) { 486 // Certain synchronous messages cannot always be processed synchronously by 487 // the browser, e.g., putting up UI and waiting for the user. This could cause 488 // a complete hang of Chrome if a windowed plug-in is trying to communicate 489 // with the renderer thread since the browser's UI thread could be stuck 490 // (within a Windows API call) trying to synchronously communicate with the 491 // plug-in. The remedy is to pump messages on this thread while the browser 492 // is processing this request. This creates an opportunity for re-entrancy 493 // into WebKit, so we need to take care to disable callbacks, timers, and 494 // pending network loads that could trigger such callbacks. 495 bool pumping_events = false; 496 if (msg->is_sync()) { 497 if (msg->is_caller_pumping_messages()) { 498 pumping_events = true; 499 } 500 } 501 502 bool suspend_webkit_shared_timer = true; // default value 503 std::swap(suspend_webkit_shared_timer, suspend_webkit_shared_timer_); 504 505 bool notify_webkit_of_modal_loop = true; // default value 506 std::swap(notify_webkit_of_modal_loop, notify_webkit_of_modal_loop_); 507 508#if defined(ENABLE_PLUGINS) 509 int render_view_id = MSG_ROUTING_NONE; 510#endif 511 512 if (pumping_events) { 513 if (suspend_webkit_shared_timer) 514 webkit_platform_support_->SuspendSharedTimer(); 515 516 if (notify_webkit_of_modal_loop) 517 WebView::willEnterModalLoop(); 518#if defined(ENABLE_PLUGINS) 519 RenderViewImpl* render_view = 520 RenderViewImpl::FromRoutingID(msg->routing_id()); 521 if (render_view) { 522 render_view_id = msg->routing_id(); 523 PluginChannelHost::Broadcast( 524 new PluginMsg_SignalModalDialogEvent(render_view_id)); 525 } 526#endif 527 } 528 529 bool rv = ChildThread::Send(msg); 530 531 if (pumping_events) { 532#if defined(ENABLE_PLUGINS) 533 if (render_view_id != MSG_ROUTING_NONE) { 534 PluginChannelHost::Broadcast( 535 new PluginMsg_ResetModalDialogEvent(render_view_id)); 536 } 537#endif 538 539 if (notify_webkit_of_modal_loop) 540 WebView::didExitModalLoop(); 541 542 if (suspend_webkit_shared_timer) 543 webkit_platform_support_->ResumeSharedTimer(); 544 } 545 546 return rv; 547} 548 549base::MessageLoop* RenderThreadImpl::GetMessageLoop() { 550 return message_loop(); 551} 552 553IPC::SyncChannel* RenderThreadImpl::GetChannel() { 554 return channel(); 555} 556 557std::string RenderThreadImpl::GetLocale() { 558 // The browser process should have passed the locale to the renderer via the 559 // --lang command line flag. 560 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); 561 const std::string& lang = 562 parsed_command_line.GetSwitchValueASCII(switches::kLang); 563 DCHECK(!lang.empty()); 564 return lang; 565} 566 567IPC::SyncMessageFilter* RenderThreadImpl::GetSyncMessageFilter() { 568 return sync_message_filter(); 569} 570 571scoped_refptr<base::MessageLoopProxy> 572 RenderThreadImpl::GetIOMessageLoopProxy() { 573 return ChildProcess::current()->io_message_loop_proxy(); 574} 575 576void RenderThreadImpl::AddRoute(int32 routing_id, IPC::Listener* listener) { 577 widget_count_++; 578 return ChildThread::AddRoute(routing_id, listener); 579} 580 581void RenderThreadImpl::RemoveRoute(int32 routing_id) { 582 widget_count_--; 583 return ChildThread::RemoveRoute(routing_id); 584} 585 586int RenderThreadImpl::GenerateRoutingID() { 587 int routing_id = MSG_ROUTING_NONE; 588 Send(new ViewHostMsg_GenerateRoutingID(&routing_id)); 589 return routing_id; 590} 591 592void RenderThreadImpl::AddFilter(IPC::ChannelProxy::MessageFilter* filter) { 593 channel()->AddFilter(filter); 594} 595 596void RenderThreadImpl::RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) { 597 channel()->RemoveFilter(filter); 598} 599 600void RenderThreadImpl::AddObserver(RenderProcessObserver* observer) { 601 observers_.AddObserver(observer); 602} 603 604void RenderThreadImpl::RemoveObserver(RenderProcessObserver* observer) { 605 observers_.RemoveObserver(observer); 606} 607 608void RenderThreadImpl::SetResourceDispatcherDelegate( 609 ResourceDispatcherDelegate* delegate) { 610 resource_dispatcher()->set_delegate(delegate); 611} 612 613void RenderThreadImpl::WidgetHidden() { 614 DCHECK_LT(hidden_widget_count_, widget_count_); 615 hidden_widget_count_++; 616 617 if (widget_count_ && hidden_widget_count_ == widget_count_) { 618#if !defined(SYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE) 619 // TODO(vollick): Remove this this heavy-handed approach once we're polling 620 // the real system memory pressure. 621 base::MemoryPressureListener::NotifyMemoryPressure( 622 base::MemoryPressureListener::MEMORY_PRESSURE_MODERATE); 623#endif 624 if (GetContentClient()->renderer()->RunIdleHandlerWhenWidgetsHidden()) 625 ScheduleIdleHandler(kInitialIdleHandlerDelayMs); 626 } 627} 628 629void RenderThreadImpl::WidgetRestored() { 630 DCHECK_GT(hidden_widget_count_, 0); 631 hidden_widget_count_--; 632 633 if (!GetContentClient()->renderer()->RunIdleHandlerWhenWidgetsHidden()) { 634 return; 635 } 636 637 ScheduleIdleHandler(kLongIdleHandlerDelayMs); 638} 639 640void RenderThreadImpl::EnsureWebKitInitialized() { 641 if (webkit_platform_support_) 642 return; 643 644 webkit_platform_support_.reset(new RendererWebKitPlatformSupportImpl); 645 blink::initialize(webkit_platform_support_.get()); 646 647 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 648 649 bool enable = command_line.HasSwitch(switches::kEnableThreadedCompositing); 650 if (enable) { 651#if defined(OS_ANDROID) 652 if (SynchronousCompositorFactory* factory = 653 SynchronousCompositorFactory::GetInstance()) 654 compositor_message_loop_proxy_ = 655 factory->GetCompositorMessageLoop(); 656#endif 657 if (!compositor_message_loop_proxy_.get()) { 658 compositor_thread_.reset(new base::Thread("Compositor")); 659 compositor_thread_->Start(); 660#if defined(OS_ANDROID) 661 compositor_thread_->SetPriority(base::kThreadPriority_Display); 662#endif 663 compositor_message_loop_proxy_ = 664 compositor_thread_->message_loop_proxy(); 665 compositor_message_loop_proxy_->PostTask( 666 FROM_HERE, 667 base::Bind(base::IgnoreResult(&ThreadRestrictions::SetIOAllowed), 668 false)); 669 } 670 671 InputHandlerManagerClient* input_handler_manager_client = NULL; 672#if defined(OS_ANDROID) 673 if (SynchronousCompositorFactory* factory = 674 SynchronousCompositorFactory::GetInstance()) { 675 input_handler_manager_client = factory->GetInputHandlerManagerClient(); 676 } 677#endif 678 if (!input_handler_manager_client) { 679 input_event_filter_ = 680 new InputEventFilter(this, compositor_message_loop_proxy_); 681 AddFilter(input_event_filter_.get()); 682 input_handler_manager_client = input_event_filter_.get(); 683 } 684 input_handler_manager_.reset( 685 new InputHandlerManager(compositor_message_loop_proxy_, 686 input_handler_manager_client)); 687 } 688 689 scoped_refptr<base::MessageLoopProxy> output_surface_loop; 690 if (enable) 691 output_surface_loop = compositor_message_loop_proxy_; 692 else 693 output_surface_loop = base::MessageLoopProxy::current(); 694 695 compositor_output_surface_filter_ = 696 CompositorOutputSurface::CreateFilter(output_surface_loop.get()); 697 AddFilter(compositor_output_surface_filter_.get()); 698 699 WebScriptController::enableV8SingleThreadMode(); 700 701 RenderThreadImpl::RegisterSchemes(); 702 703 EnableWebCoreLogChannels( 704 command_line.GetSwitchValueASCII(switches::kWebCoreLogChannels)); 705 706 SetRuntimeFeaturesDefaultsAndUpdateFromArgs(command_line); 707 708 if (!media::IsMediaLibraryInitialized()) { 709 WebRuntimeFeatures::enableMediaPlayer(false); 710 WebRuntimeFeatures::enableWebAudio(false); 711 } 712 713 FOR_EACH_OBSERVER(RenderProcessObserver, observers_, WebKitInitialized()); 714 715 devtools_agent_message_filter_ = new DevToolsAgentFilter(); 716 AddFilter(devtools_agent_message_filter_.get()); 717 718 if (GetContentClient()->renderer()->RunIdleHandlerWhenWidgetsHidden()) 719 ScheduleIdleHandler(kLongIdleHandlerDelayMs); 720 721 webkit::SetSharedMemoryAllocationFunction(AllocateSharedMemoryFunction); 722} 723 724void RenderThreadImpl::RegisterSchemes() { 725 // swappedout: pages should not be accessible, and should also 726 // be treated as empty documents that can commit synchronously. 727 WebString swappedout_scheme(ASCIIToUTF16(kSwappedOutScheme)); 728 WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(swappedout_scheme); 729 WebSecurityPolicy::registerURLSchemeAsEmptyDocument(swappedout_scheme); 730} 731 732void RenderThreadImpl::RecordAction(const UserMetricsAction& action) { 733 Send(new ViewHostMsg_UserMetricsRecordAction(action.str_)); 734} 735 736void RenderThreadImpl::RecordComputedAction(const std::string& action) { 737 Send(new ViewHostMsg_UserMetricsRecordAction(action)); 738} 739 740scoped_ptr<base::SharedMemory> 741 RenderThreadImpl::HostAllocateSharedMemoryBuffer(size_t size) { 742 if (size > static_cast<size_t>(std::numeric_limits<int>::max())) 743 return scoped_ptr<base::SharedMemory>(); 744 745 base::SharedMemoryHandle handle; 746 bool success; 747 IPC::Message* message = 748 new ChildProcessHostMsg_SyncAllocateSharedMemory(size, &handle); 749 750 // Allow calling this from the compositor thread. 751 if (base::MessageLoop::current() == message_loop()) 752 success = ChildThread::Send(message); 753 else 754 success = sync_message_filter()->Send(message); 755 756 if (!success) 757 return scoped_ptr<base::SharedMemory>(); 758 759 if (!base::SharedMemory::IsHandleValid(handle)) 760 return scoped_ptr<base::SharedMemory>(); 761 762 return scoped_ptr<base::SharedMemory>(new base::SharedMemory(handle, false)); 763} 764 765void RenderThreadImpl::RegisterExtension(v8::Extension* extension) { 766 WebScriptController::registerExtension(extension); 767} 768 769void RenderThreadImpl::ScheduleIdleHandler(int64 initial_delay_ms) { 770 idle_notification_delay_in_ms_ = initial_delay_ms; 771 idle_timer_.Stop(); 772 idle_timer_.Start(FROM_HERE, 773 base::TimeDelta::FromMilliseconds(initial_delay_ms), 774 this, &RenderThreadImpl::IdleHandler); 775} 776 777void RenderThreadImpl::IdleHandler() { 778 bool run_in_foreground_tab = (widget_count_ > hidden_widget_count_) && 779 GetContentClient()->renderer()-> 780 RunIdleHandlerWhenWidgetsHidden(); 781 if (run_in_foreground_tab) { 782 IdleHandlerInForegroundTab(); 783 return; 784 } 785 786 base::allocator::ReleaseFreeMemory(); 787 788 v8::V8::IdleNotification(); 789 790 // Schedule next invocation. 791 // Dampen the delay using the algorithm (if delay is in seconds): 792 // delay = delay + 1 / (delay + 2) 793 // Using floor(delay) has a dampening effect such as: 794 // 1s, 1, 1, 2, 2, 2, 2, 3, 3, ... 795 // If the delay is in milliseconds, the above formula is equivalent to: 796 // delay_ms / 1000 = delay_ms / 1000 + 1 / (delay_ms / 1000 + 2) 797 // which is equivalent to 798 // delay_ms = delay_ms + 1000*1000 / (delay_ms + 2000). 799 // Note that idle_notification_delay_in_ms_ would be reset to 800 // kInitialIdleHandlerDelayMs in RenderThreadImpl::WidgetHidden. 801 ScheduleIdleHandler(idle_notification_delay_in_ms_ + 802 1000000 / (idle_notification_delay_in_ms_ + 2000)); 803 804 FOR_EACH_OBSERVER(RenderProcessObserver, observers_, IdleNotification()); 805} 806 807void RenderThreadImpl::IdleHandlerInForegroundTab() { 808 // Increase the delay in the same way as in IdleHandler, 809 // but make it periodic by reseting it once it is too big. 810 int64 new_delay_ms = idle_notification_delay_in_ms_ + 811 1000000 / (idle_notification_delay_in_ms_ + 2000); 812 if (new_delay_ms >= kLongIdleHandlerDelayMs) 813 new_delay_ms = kShortIdleHandlerDelayMs; 814 815 if (idle_notifications_to_skip_ > 0) { 816 idle_notifications_to_skip_--; 817 } else { 818 int cpu_usage = 0; 819 Send(new ViewHostMsg_GetCPUUsage(&cpu_usage)); 820 // Idle notification hint roughly specifies the expected duration of the 821 // idle pause. We set it proportional to the idle timer delay. 822 int idle_hint = static_cast<int>(new_delay_ms / 10); 823 if (cpu_usage < kIdleCPUUsageThresholdInPercents) { 824 base::allocator::ReleaseFreeMemory(); 825 if (v8::V8::IdleNotification(idle_hint)) { 826 // V8 finished collecting garbage. 827 new_delay_ms = kLongIdleHandlerDelayMs; 828 } 829 } 830 } 831 ScheduleIdleHandler(new_delay_ms); 832} 833 834int64 RenderThreadImpl::GetIdleNotificationDelayInMs() const { 835 return idle_notification_delay_in_ms_; 836} 837 838void RenderThreadImpl::SetIdleNotificationDelayInMs( 839 int64 idle_notification_delay_in_ms) { 840 idle_notification_delay_in_ms_ = idle_notification_delay_in_ms; 841} 842 843void RenderThreadImpl::ToggleWebKitSharedTimer(bool suspend) { 844 if (suspend_webkit_shared_timer_) { 845 EnsureWebKitInitialized(); 846 if (suspend) { 847 webkit_platform_support_->SuspendSharedTimer(); 848 } else { 849 webkit_platform_support_->ResumeSharedTimer(); 850 } 851 } 852} 853 854void RenderThreadImpl::UpdateHistograms(int sequence_number) { 855 child_histogram_message_filter()->SendHistograms(sequence_number); 856} 857 858int RenderThreadImpl::PostTaskToAllWebWorkers(const base::Closure& closure) { 859 return webkit_glue::WorkerTaskRunner::Instance()->PostTaskToAllThreads( 860 closure); 861} 862 863bool RenderThreadImpl::ResolveProxy(const GURL& url, std::string* proxy_list) { 864 bool result = false; 865 Send(new ViewHostMsg_ResolveProxy(url, &result, proxy_list)); 866 return result; 867} 868 869void RenderThreadImpl::PostponeIdleNotification() { 870 idle_notifications_to_skip_ = 2; 871} 872 873scoped_refptr<RendererGpuVideoAcceleratorFactories> 874RenderThreadImpl::GetGpuFactories() { 875 DCHECK(IsMainThread()); 876 877 scoped_refptr<GpuChannelHost> gpu_channel_host = GetGpuChannel(); 878 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 879 scoped_refptr<RendererGpuVideoAcceleratorFactories> gpu_factories; 880 if (!cmd_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) { 881 if (!gpu_va_context_provider_ || 882 gpu_va_context_provider_->DestroyedOnMainThread()) { 883 if (!gpu_channel_host) { 884 gpu_channel_host = EstablishGpuChannelSync( 885 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE); 886 } 887 gpu_va_context_provider_ = ContextProviderCommandBuffer::Create( 888 make_scoped_ptr( 889 WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( 890 gpu_channel_host.get(), 891 blink::WebGraphicsContext3D::Attributes(), 892 GURL("chrome://gpu/RenderThreadImpl::GetGpuVDAContext3D"), 893 WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits())), 894 "GPU-VideoAccelerator-Offscreen"); 895 } 896 } 897 if (gpu_channel_host) { 898 gpu_factories = new RendererGpuVideoAcceleratorFactories( 899 gpu_channel_host.get(), gpu_va_context_provider_); 900 } 901 return gpu_factories; 902} 903 904scoped_ptr<WebGraphicsContext3DCommandBufferImpl> 905RenderThreadImpl::CreateOffscreenContext3d() { 906 blink::WebGraphicsContext3D::Attributes attributes; 907 attributes.shareResources = true; 908 attributes.depth = false; 909 attributes.stencil = false; 910 attributes.antialias = false; 911 attributes.noAutomaticFlushes = true; 912 913 scoped_refptr<GpuChannelHost> gpu_channel_host(EstablishGpuChannelSync( 914 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE)); 915 return make_scoped_ptr( 916 WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( 917 gpu_channel_host.get(), 918 attributes, 919 GURL("chrome://gpu/RenderThreadImpl::CreateOffscreenContext3d"), 920 WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits())); 921} 922 923scoped_refptr<cc::ContextProvider> 924RenderThreadImpl::OffscreenCompositorContextProvider() { 925 DCHECK(IsMainThread()); 926 927#if defined(OS_ANDROID) 928 if (SynchronousCompositorFactory* factory = 929 SynchronousCompositorFactory::GetInstance()) { 930 if (compositor_message_loop_proxy_) 931 return factory->GetOffscreenContextProviderForCompositorThread(); 932 return factory->GetOffscreenContextProviderForMainThread(); 933 } 934#endif 935 936 if (!offscreen_compositor_contexts_.get() || 937 offscreen_compositor_contexts_->DestroyedOnMainThread()) { 938 offscreen_compositor_contexts_ = ContextProviderCommandBuffer::Create( 939 CreateOffscreenContext3d(), 940 "Compositor-Offscreen"); 941 } 942 return offscreen_compositor_contexts_; 943} 944 945scoped_refptr<cc::ContextProvider> 946RenderThreadImpl::SharedMainThreadContextProvider() { 947 DCHECK(IsMainThread()); 948#if defined(OS_ANDROID) 949 if (SynchronousCompositorFactory* factory = 950 SynchronousCompositorFactory::GetInstance()) 951 return factory->GetOffscreenContextProviderForMainThread(); 952#endif 953 954 if (!shared_main_thread_contexts_ || 955 shared_main_thread_contexts_->DestroyedOnMainThread()) { 956 if (compositor_message_loop_proxy_) { 957 // In threaded compositing mode, we have to create a new ContextProvider 958 // to bind to the main thread since the compositor's is bound to the 959 // compositor thread. 960 shared_main_thread_contexts_ = 961 ContextProviderCommandBuffer::Create(CreateOffscreenContext3d(), 962 "Offscreen-MainThread"); 963 } else { 964 // In single threaded mode, we can use the same context provider. 965 shared_main_thread_contexts_ = 966 static_cast<ContextProviderCommandBuffer*>( 967 OffscreenCompositorContextProvider().get()); 968 } 969 } 970 if (shared_main_thread_contexts_ && 971 !shared_main_thread_contexts_->BindToCurrentThread()) 972 shared_main_thread_contexts_ = NULL; 973 return shared_main_thread_contexts_; 974} 975 976AudioRendererMixerManager* RenderThreadImpl::GetAudioRendererMixerManager() { 977 if (!audio_renderer_mixer_manager_) { 978 audio_renderer_mixer_manager_.reset(new AudioRendererMixerManager( 979 GetAudioHardwareConfig())); 980 } 981 982 return audio_renderer_mixer_manager_.get(); 983} 984 985media::AudioHardwareConfig* RenderThreadImpl::GetAudioHardwareConfig() { 986 if (!audio_hardware_config_) { 987 media::AudioParameters input_params; 988 media::AudioParameters output_params; 989 Send(new ViewHostMsg_GetAudioHardwareConfig( 990 &input_params, &output_params)); 991 992 audio_hardware_config_.reset(new media::AudioHardwareConfig( 993 input_params, output_params)); 994 audio_message_filter_->SetAudioHardwareConfig(audio_hardware_config_.get()); 995 } 996 997 return audio_hardware_config_.get(); 998} 999 1000#if defined(OS_WIN) 1001void RenderThreadImpl::PreCacheFontCharacters(const LOGFONT& log_font, 1002 const base::string16& str) { 1003 Send(new ViewHostMsg_PreCacheFontCharacters(log_font, str)); 1004} 1005 1006void RenderThreadImpl::PreCacheFont(const LOGFONT& log_font) { 1007 Send(new ChildProcessHostMsg_PreCacheFont(log_font)); 1008} 1009 1010void RenderThreadImpl::ReleaseCachedFonts() { 1011 Send(new ChildProcessHostMsg_ReleaseCachedFonts()); 1012} 1013 1014#endif // OS_WIN 1015 1016bool RenderThreadImpl::IsMainThread() { 1017 return !!current(); 1018} 1019 1020base::MessageLoop* RenderThreadImpl::GetMainLoop() { 1021 return message_loop(); 1022} 1023 1024scoped_refptr<base::MessageLoopProxy> RenderThreadImpl::GetIOLoopProxy() { 1025 return io_message_loop_proxy_; 1026} 1027 1028base::WaitableEvent* RenderThreadImpl::GetShutDownEvent() { 1029 return shutdown_event_; 1030} 1031 1032scoped_ptr<base::SharedMemory> RenderThreadImpl::AllocateSharedMemory( 1033 size_t size) { 1034 return scoped_ptr<base::SharedMemory>( 1035 HostAllocateSharedMemoryBuffer(size)); 1036} 1037 1038int32 RenderThreadImpl::CreateViewCommandBuffer( 1039 int32 surface_id, const GPUCreateCommandBufferConfig& init_params) { 1040 TRACE_EVENT1("gpu", 1041 "RenderThreadImpl::CreateViewCommandBuffer", 1042 "surface_id", 1043 surface_id); 1044 1045 int32 route_id = MSG_ROUTING_NONE; 1046 IPC::Message* message = new GpuHostMsg_CreateViewCommandBuffer( 1047 surface_id, 1048 init_params, 1049 &route_id); 1050 1051 // Allow calling this from the compositor thread. 1052 thread_safe_sender()->Send(message); 1053 1054 return route_id; 1055} 1056 1057void RenderThreadImpl::CreateImage( 1058 gfx::PluginWindowHandle window, 1059 int32 image_id, 1060 const CreateImageCallback& callback) { 1061 NOTREACHED(); 1062} 1063 1064void RenderThreadImpl::DeleteImage(int32 image_id, int32 sync_point) { 1065 NOTREACHED(); 1066} 1067 1068scoped_ptr<gfx::GpuMemoryBuffer> RenderThreadImpl::AllocateGpuMemoryBuffer( 1069 size_t width, 1070 size_t height, 1071 unsigned internalformat) { 1072 DCHECK(allocate_gpu_memory_buffer_thread_checker_.CalledOnValidThread()); 1073 1074 if (!GpuMemoryBufferImpl::IsFormatValid(internalformat)) 1075 return scoped_ptr<gfx::GpuMemoryBuffer>(); 1076 1077 gfx::GpuMemoryBufferHandle handle; 1078 bool success; 1079 IPC::Message* message = 1080 new ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer(width, 1081 height, 1082 internalformat, 1083 &handle); 1084 1085 // Allow calling this from the compositor thread. 1086 if (base::MessageLoop::current() == message_loop()) 1087 success = ChildThread::Send(message); 1088 else 1089 success = sync_message_filter()->Send(message); 1090 1091 if (!success) 1092 return scoped_ptr<gfx::GpuMemoryBuffer>(); 1093 1094 return GpuMemoryBufferImpl::Create( 1095 handle, 1096 gfx::Size(width, height), 1097 internalformat).PassAs<gfx::GpuMemoryBuffer>(); 1098} 1099 1100void RenderThreadImpl::DoNotSuspendWebKitSharedTimer() { 1101 suspend_webkit_shared_timer_ = false; 1102} 1103 1104void RenderThreadImpl::DoNotNotifyWebKitOfModalLoop() { 1105 notify_webkit_of_modal_loop_ = false; 1106} 1107 1108void RenderThreadImpl::OnSetZoomLevelForCurrentURL(const std::string& scheme, 1109 const std::string& host, 1110 double zoom_level) { 1111 RenderViewZoomer zoomer(scheme, host, zoom_level); 1112 RenderView::ForEach(&zoomer); 1113} 1114 1115bool RenderThreadImpl::OnControlMessageReceived(const IPC::Message& msg) { 1116 ObserverListBase<RenderProcessObserver>::Iterator it(observers_); 1117 RenderProcessObserver* observer; 1118 while ((observer = it.GetNext()) != NULL) { 1119 if (observer->OnControlMessageReceived(msg)) 1120 return true; 1121 } 1122 1123 // Some messages are handled by delegates. 1124 if (appcache_dispatcher_->OnMessageReceived(msg) || 1125 dom_storage_dispatcher_->OnMessageReceived(msg) || 1126 embedded_worker_dispatcher_->OnMessageReceived(msg)) { 1127 return true; 1128 } 1129 1130 bool handled = true; 1131 IPC_BEGIN_MESSAGE_MAP(RenderThreadImpl, msg) 1132 IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevelForCurrentURL, 1133 OnSetZoomLevelForCurrentURL) 1134 // TODO(port): removed from render_messages_internal.h; 1135 // is there a new non-windows message I should add here? 1136 IPC_MESSAGE_HANDLER(ViewMsg_New, OnCreateNewView) 1137 IPC_MESSAGE_HANDLER(ViewMsg_PurgePluginListCache, OnPurgePluginListCache) 1138 IPC_MESSAGE_HANDLER(ViewMsg_NetworkStateChanged, OnNetworkStateChanged) 1139 IPC_MESSAGE_HANDLER(ViewMsg_TempCrashWithData, OnTempCrashWithData) 1140 IPC_MESSAGE_HANDLER(ViewMsg_SetRendererProcessID, OnSetRendererProcessID) 1141#if defined(OS_ANDROID) 1142 IPC_MESSAGE_HANDLER(ViewMsg_SetWebKitSharedTimersSuspended, 1143 OnSetWebKitSharedTimersSuspended) 1144#endif 1145#if defined(OS_MACOSX) 1146 IPC_MESSAGE_HANDLER(ViewMsg_UpdateScrollbarTheme, OnUpdateScrollbarTheme) 1147#endif 1148 IPC_MESSAGE_UNHANDLED(handled = false) 1149 IPC_END_MESSAGE_MAP() 1150 return handled; 1151} 1152 1153void RenderThreadImpl::OnCreateNewView(const ViewMsg_New_Params& params) { 1154 EnsureWebKitInitialized(); 1155 // When bringing in render_view, also bring in webkit's glue and jsbindings. 1156 RenderViewImpl::Create( 1157 params.opener_route_id, 1158 params.renderer_preferences, 1159 params.web_preferences, 1160 params.view_id, 1161 params.main_frame_routing_id, 1162 params.surface_id, 1163 params.session_storage_namespace_id, 1164 params.frame_name, 1165 false, 1166 params.swapped_out, 1167 params.hidden, 1168 params.next_page_id, 1169 params.screen_info, 1170 params.accessibility_mode, 1171 params.allow_partial_swap); 1172} 1173 1174GpuChannelHost* RenderThreadImpl::EstablishGpuChannelSync( 1175 CauseForGpuLaunch cause_for_gpu_launch) { 1176 TRACE_EVENT0("gpu", "RenderThreadImpl::EstablishGpuChannelSync"); 1177 1178 if (gpu_channel_.get()) { 1179 // Do nothing if we already have a GPU channel or are already 1180 // establishing one. 1181 if (!gpu_channel_->IsLost()) 1182 return gpu_channel_.get(); 1183 1184 // Recreate the channel if it has been lost. 1185 gpu_channel_ = NULL; 1186 } 1187 1188 // Ask the browser for the channel name. 1189 int client_id = 0; 1190 IPC::ChannelHandle channel_handle; 1191 gpu::GPUInfo gpu_info; 1192 if (!Send(new GpuHostMsg_EstablishGpuChannel(cause_for_gpu_launch, 1193 &client_id, 1194 &channel_handle, 1195 &gpu_info)) || 1196#if defined(OS_POSIX) 1197 channel_handle.socket.fd == -1 || 1198#endif 1199 channel_handle.name.empty()) { 1200 // Otherwise cancel the connection. 1201 return NULL; 1202 } 1203 1204 GetContentClient()->SetGpuInfo(gpu_info); 1205 1206 // Cache some variables that are needed on the compositor thread for our 1207 // implementation of GpuChannelHostFactory. 1208 io_message_loop_proxy_ = ChildProcess::current()->io_message_loop_proxy(); 1209 shutdown_event_ = ChildProcess::current()->GetShutDownEvent(); 1210 1211 gpu_channel_ = GpuChannelHost::Create( 1212 this, 0, gpu_info, channel_handle); 1213 return gpu_channel_.get(); 1214} 1215 1216blink::WebMediaStreamCenter* RenderThreadImpl::CreateMediaStreamCenter( 1217 blink::WebMediaStreamCenterClient* client) { 1218#if defined(OS_ANDROID) 1219 if (CommandLine::ForCurrentProcess()->HasSwitch( 1220 switches::kDisableWebRTC)) 1221 return NULL; 1222#endif 1223 1224#if defined(ENABLE_WEBRTC) 1225 if (!media_stream_center_) { 1226 media_stream_center_ = GetContentClient()->renderer() 1227 ->OverrideCreateWebMediaStreamCenter(client); 1228 if (!media_stream_center_) { 1229 scoped_ptr<MediaStreamCenter> media_stream_center( 1230 new MediaStreamCenter(client, GetMediaStreamDependencyFactory())); 1231 AddObserver(media_stream_center.get()); 1232 media_stream_center_ = media_stream_center.release(); 1233 } 1234 } 1235#endif 1236 return media_stream_center_; 1237} 1238 1239MediaStreamDependencyFactory* 1240RenderThreadImpl::GetMediaStreamDependencyFactory() { 1241#if defined(ENABLE_WEBRTC) 1242 if (!media_stream_factory_) { 1243 media_stream_factory_.reset(new MediaStreamDependencyFactory( 1244 vc_manager_.get(), p2p_socket_dispatcher_.get())); 1245 } 1246#endif 1247 return media_stream_factory_.get(); 1248} 1249 1250GpuChannelHost* RenderThreadImpl::GetGpuChannel() { 1251 if (!gpu_channel_.get()) 1252 return NULL; 1253 1254 if (gpu_channel_->IsLost()) 1255 return NULL; 1256 1257 return gpu_channel_.get(); 1258} 1259 1260void RenderThreadImpl::OnPurgePluginListCache(bool reload_pages) { 1261 EnsureWebKitInitialized(); 1262 // The call below will cause a GetPlugins call with refresh=true, but at this 1263 // point we already know that the browser has refreshed its list, so disable 1264 // refresh temporarily to prevent each renderer process causing the list to be 1265 // regenerated. 1266 webkit_platform_support_->set_plugin_refresh_allowed(false); 1267 blink::resetPluginCache(reload_pages); 1268 webkit_platform_support_->set_plugin_refresh_allowed(true); 1269 1270 FOR_EACH_OBSERVER(RenderProcessObserver, observers_, PluginListChanged()); 1271} 1272 1273void RenderThreadImpl::OnNetworkStateChanged(bool online) { 1274 EnsureWebKitInitialized(); 1275 WebNetworkStateNotifier::setOnLine(online); 1276} 1277 1278void RenderThreadImpl::OnTempCrashWithData(const GURL& data) { 1279 GetContentClient()->SetActiveURL(data); 1280 CHECK(false); 1281} 1282 1283void RenderThreadImpl::OnSetRendererProcessID(base::ProcessId process_id) { 1284 renderer_process_id_ = process_id; 1285} 1286 1287#if defined(OS_ANDROID) 1288void RenderThreadImpl::OnSetWebKitSharedTimersSuspended(bool suspend) { 1289 ToggleWebKitSharedTimer(suspend); 1290} 1291#endif 1292 1293#if defined(OS_MACOSX) 1294void RenderThreadImpl::OnUpdateScrollbarTheme(float initial_button_delay, 1295 float autoscroll_button_delay, 1296 bool jump_on_track_click, 1297 bool redraw) { 1298 blink::WebScrollbarTheme::updateScrollbars(initial_button_delay, 1299 autoscroll_button_delay, 1300 jump_on_track_click, 1301 redraw); 1302} 1303#endif 1304 1305void RenderThreadImpl::OnMemoryPressure( 1306 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { 1307 base::allocator::ReleaseFreeMemory(); 1308 1309 if (memory_pressure_level == 1310 base::MemoryPressureListener::MEMORY_PRESSURE_CRITICAL) { 1311 // Trigger full v8 garbage collection on critical memory notification. 1312 v8::V8::LowMemoryNotification(); 1313 // Clear the image cache. 1314 blink::WebImageCache::clear(); 1315 // Purge Skia font cache, by setting it to 0 and then again to the previous 1316 // limit. 1317 size_t font_cache_limit = SkGraphics::SetFontCacheLimit(0); 1318 SkGraphics::SetFontCacheLimit(font_cache_limit); 1319 } else { 1320 // Otherwise trigger a couple of v8 GCs using IdleNotification. 1321 if (!v8::V8::IdleNotification()) 1322 v8::V8::IdleNotification(); 1323 } 1324} 1325 1326scoped_refptr<base::MessageLoopProxy> 1327RenderThreadImpl::GetFileThreadMessageLoopProxy() { 1328 DCHECK(message_loop() == base::MessageLoop::current()); 1329 if (!file_thread_) { 1330 file_thread_.reset(new base::Thread("Renderer::FILE")); 1331 file_thread_->Start(); 1332 } 1333 return file_thread_->message_loop_proxy(); 1334} 1335 1336scoped_refptr<base::MessageLoopProxy> 1337RenderThreadImpl::GetMediaThreadMessageLoopProxy() { 1338 DCHECK(message_loop() == base::MessageLoop::current()); 1339 if (!media_thread_) { 1340 media_thread_.reset(new base::Thread("Media")); 1341 media_thread_->Start(); 1342 1343#if defined(OS_ANDROID) 1344 renderer_demuxer_ = new RendererDemuxerAndroid(); 1345 AddFilter(renderer_demuxer_.get()); 1346#endif 1347 } 1348 return media_thread_->message_loop_proxy(); 1349} 1350 1351void RenderThreadImpl::SetFlingCurveParameters( 1352 const std::vector<float>& new_touchpad, 1353 const std::vector<float>& new_touchscreen) { 1354 webkit_platform_support_->SetFlingCurveParameters(new_touchpad, 1355 new_touchscreen); 1356 1357} 1358 1359void RenderThreadImpl::SampleGamepads(blink::WebGamepads* data) { 1360 if (!gamepad_shared_memory_reader_) 1361 gamepad_shared_memory_reader_.reset(new GamepadSharedMemoryReader); 1362 gamepad_shared_memory_reader_->SampleGamepads(*data); 1363} 1364 1365base::ProcessId RenderThreadImpl::renderer_process_id() const { 1366 return renderer_process_id_; 1367} 1368 1369} // namespace content 1370