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