render_thread_impl.cc revision 8bcbed890bc3ce4d7a057a8f32cab53fa534672e
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::AddObserver(RenderProcessObserver* observer) { 594 observers_.AddObserver(observer); 595} 596 597void RenderThreadImpl::RemoveObserver(RenderProcessObserver* observer) { 598 observers_.RemoveObserver(observer); 599} 600 601void RenderThreadImpl::SetResourceDispatcherDelegate( 602 ResourceDispatcherDelegate* delegate) { 603 resource_dispatcher()->set_delegate(delegate); 604} 605 606void RenderThreadImpl::WidgetHidden() { 607 DCHECK_LT(hidden_widget_count_, widget_count_); 608 hidden_widget_count_++; 609 610 if (widget_count_ && hidden_widget_count_ == widget_count_) { 611#if !defined(SYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE) 612 // TODO(vollick): Remove this this heavy-handed approach once we're polling 613 // the real system memory pressure. 614 base::MemoryPressureListener::NotifyMemoryPressure( 615 base::MemoryPressureListener::MEMORY_PRESSURE_MODERATE); 616#endif 617 if (GetContentClient()->renderer()->RunIdleHandlerWhenWidgetsHidden()) 618 ScheduleIdleHandler(kInitialIdleHandlerDelayMs); 619 } 620} 621 622void RenderThreadImpl::WidgetRestored() { 623 DCHECK_GT(hidden_widget_count_, 0); 624 hidden_widget_count_--; 625 626 if (!GetContentClient()->renderer()->RunIdleHandlerWhenWidgetsHidden()) { 627 return; 628 } 629 630 ScheduleIdleHandler(kLongIdleHandlerDelayMs); 631} 632 633void RenderThreadImpl::EnsureWebKitInitialized() { 634 if (webkit_platform_support_) 635 return; 636 637 webkit_platform_support_.reset(new RendererWebKitPlatformSupportImpl); 638 WebKit::initialize(webkit_platform_support_.get()); 639 WebKit::setSharedWorkerRepository( 640 webkit_platform_support_.get()->sharedWorkerRepository()); 641 642 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 643 644 bool enable = command_line.HasSwitch(switches::kEnableThreadedCompositing); 645 if (enable) { 646#if defined(OS_ANDROID) 647 if (SynchronousCompositorFactory* factory = 648 SynchronousCompositorFactory::GetInstance()) 649 compositor_message_loop_proxy_ = 650 factory->GetCompositorMessageLoop(); 651#endif 652 if (!compositor_message_loop_proxy_.get()) { 653 compositor_thread_.reset(new base::Thread("Compositor")); 654 compositor_thread_->Start(); 655#if defined(OS_ANDROID) 656 compositor_thread_->SetPriority(base::kThreadPriority_Display); 657#endif 658 compositor_message_loop_proxy_ = 659 compositor_thread_->message_loop_proxy(); 660 compositor_message_loop_proxy_->PostTask( 661 FROM_HERE, 662 base::Bind(base::IgnoreResult(&ThreadRestrictions::SetIOAllowed), 663 false)); 664 } 665 666 InputHandlerManagerClient* input_handler_manager_client = NULL; 667#if defined(OS_ANDROID) 668 if (SynchronousCompositorFactory* factory = 669 SynchronousCompositorFactory::GetInstance()) { 670 input_handler_manager_client = factory->GetInputHandlerManagerClient(); 671 } 672#endif 673 if (!input_handler_manager_client) { 674 input_event_filter_ = 675 new InputEventFilter(this, compositor_message_loop_proxy_); 676 AddFilter(input_event_filter_.get()); 677 input_handler_manager_client = input_event_filter_.get(); 678 } 679 input_handler_manager_.reset( 680 new InputHandlerManager(compositor_message_loop_proxy_, 681 input_handler_manager_client)); 682 } 683 684 scoped_refptr<base::MessageLoopProxy> output_surface_loop; 685 if (enable) 686 output_surface_loop = compositor_message_loop_proxy_; 687 else 688 output_surface_loop = base::MessageLoopProxy::current(); 689 690 compositor_output_surface_filter_ = 691 CompositorOutputSurface::CreateFilter(output_surface_loop.get()); 692 AddFilter(compositor_output_surface_filter_.get()); 693 694 WebScriptController::enableV8SingleThreadMode(); 695 696 RenderThreadImpl::RegisterSchemes(); 697 698 EnableWebCoreLogChannels( 699 command_line.GetSwitchValueASCII(switches::kWebCoreLogChannels)); 700 701 web_database_observer_impl_.reset( 702 new WebDatabaseObserverImpl(sync_message_filter())); 703 WebKit::WebDatabase::setObserver(web_database_observer_impl_.get()); 704 705 SetRuntimeFeaturesDefaultsAndUpdateFromArgs(command_line); 706 707 if (!media::IsMediaLibraryInitialized()) { 708 WebRuntimeFeatures::enableMediaPlayer(false); 709 WebRuntimeFeatures::enableWebAudio(false); 710 } 711 712 FOR_EACH_OBSERVER(RenderProcessObserver, observers_, WebKitInitialized()); 713 714 devtools_agent_message_filter_ = new DevToolsAgentFilter(); 715 AddFilter(devtools_agent_message_filter_.get()); 716 717 if (GetContentClient()->renderer()->RunIdleHandlerWhenWidgetsHidden()) 718 ScheduleIdleHandler(kLongIdleHandlerDelayMs); 719 720 webkit::SetSharedMemoryAllocationFunction(AllocateSharedMemoryFunction); 721} 722 723void RenderThreadImpl::RegisterSchemes() { 724 // swappedout: pages should not be accessible, and should also 725 // be treated as empty documents that can commit synchronously. 726 WebString swappedout_scheme(ASCIIToUTF16(kSwappedOutScheme)); 727 WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(swappedout_scheme); 728 WebSecurityPolicy::registerURLSchemeAsEmptyDocument(swappedout_scheme); 729} 730 731void RenderThreadImpl::RecordUserMetrics(const std::string& action) { 732 Send(new ViewHostMsg_UserMetricsRecordAction(action)); 733} 734 735scoped_ptr<base::SharedMemory> 736 RenderThreadImpl::HostAllocateSharedMemoryBuffer(size_t size) { 737 if (size > static_cast<size_t>(std::numeric_limits<int>::max())) 738 return scoped_ptr<base::SharedMemory>(); 739 740 base::SharedMemoryHandle handle; 741 bool success; 742 IPC::Message* message = 743 new ChildProcessHostMsg_SyncAllocateSharedMemory(size, &handle); 744 745 // Allow calling this from the compositor thread. 746 if (base::MessageLoop::current() == message_loop()) 747 success = ChildThread::Send(message); 748 else 749 success = sync_message_filter()->Send(message); 750 751 if (!success) 752 return scoped_ptr<base::SharedMemory>(); 753 754 if (!base::SharedMemory::IsHandleValid(handle)) 755 return scoped_ptr<base::SharedMemory>(); 756 757 return scoped_ptr<base::SharedMemory>(new base::SharedMemory(handle, false)); 758} 759 760void RenderThreadImpl::RegisterExtension(v8::Extension* extension) { 761 WebScriptController::registerExtension(extension); 762} 763 764void RenderThreadImpl::ScheduleIdleHandler(int64 initial_delay_ms) { 765 idle_notification_delay_in_ms_ = initial_delay_ms; 766 idle_timer_.Stop(); 767 idle_timer_.Start(FROM_HERE, 768 base::TimeDelta::FromMilliseconds(initial_delay_ms), 769 this, &RenderThreadImpl::IdleHandler); 770} 771 772void RenderThreadImpl::IdleHandler() { 773 bool run_in_foreground_tab = (widget_count_ > hidden_widget_count_) && 774 GetContentClient()->renderer()-> 775 RunIdleHandlerWhenWidgetsHidden(); 776 if (run_in_foreground_tab) { 777 IdleHandlerInForegroundTab(); 778 return; 779 } 780 781 base::allocator::ReleaseFreeMemory(); 782 783 v8::V8::IdleNotification(); 784 785 // Schedule next invocation. 786 // Dampen the delay using the algorithm (if delay is in seconds): 787 // delay = delay + 1 / (delay + 2) 788 // Using floor(delay) has a dampening effect such as: 789 // 1s, 1, 1, 2, 2, 2, 2, 3, 3, ... 790 // If the delay is in milliseconds, the above formula is equivalent to: 791 // delay_ms / 1000 = delay_ms / 1000 + 1 / (delay_ms / 1000 + 2) 792 // which is equivalent to 793 // delay_ms = delay_ms + 1000*1000 / (delay_ms + 2000). 794 // Note that idle_notification_delay_in_ms_ would be reset to 795 // kInitialIdleHandlerDelayMs in RenderThreadImpl::WidgetHidden. 796 ScheduleIdleHandler(idle_notification_delay_in_ms_ + 797 1000000 / (idle_notification_delay_in_ms_ + 2000)); 798 799 FOR_EACH_OBSERVER(RenderProcessObserver, observers_, IdleNotification()); 800} 801 802void RenderThreadImpl::IdleHandlerInForegroundTab() { 803 // Increase the delay in the same way as in IdleHandler, 804 // but make it periodic by reseting it once it is too big. 805 int64 new_delay_ms = idle_notification_delay_in_ms_ + 806 1000000 / (idle_notification_delay_in_ms_ + 2000); 807 if (new_delay_ms >= kLongIdleHandlerDelayMs) 808 new_delay_ms = kShortIdleHandlerDelayMs; 809 810 if (idle_notifications_to_skip_ > 0) { 811 idle_notifications_to_skip_--; 812 } else { 813 int cpu_usage = 0; 814 Send(new ViewHostMsg_GetCPUUsage(&cpu_usage)); 815 // Idle notification hint roughly specifies the expected duration of the 816 // idle pause. We set it proportional to the idle timer delay. 817 int idle_hint = static_cast<int>(new_delay_ms / 10); 818 if (cpu_usage < kIdleCPUUsageThresholdInPercents) { 819 base::allocator::ReleaseFreeMemory(); 820 if (v8::V8::IdleNotification(idle_hint)) { 821 // V8 finished collecting garbage. 822 new_delay_ms = kLongIdleHandlerDelayMs; 823 } 824 } 825 } 826 ScheduleIdleHandler(new_delay_ms); 827} 828 829int64 RenderThreadImpl::GetIdleNotificationDelayInMs() const { 830 return idle_notification_delay_in_ms_; 831} 832 833void RenderThreadImpl::SetIdleNotificationDelayInMs( 834 int64 idle_notification_delay_in_ms) { 835 idle_notification_delay_in_ms_ = idle_notification_delay_in_ms; 836} 837 838void RenderThreadImpl::ToggleWebKitSharedTimer(bool suspend) { 839 if (suspend_webkit_shared_timer_) { 840 EnsureWebKitInitialized(); 841 if (suspend) { 842 webkit_platform_support_->SuspendSharedTimer(); 843 } else { 844 webkit_platform_support_->ResumeSharedTimer(); 845 } 846 } 847} 848 849void RenderThreadImpl::UpdateHistograms(int sequence_number) { 850 child_histogram_message_filter()->SendHistograms(sequence_number); 851} 852 853int RenderThreadImpl::PostTaskToAllWebWorkers(const base::Closure& closure) { 854 return webkit_glue::WorkerTaskRunner::Instance()->PostTaskToAllThreads( 855 closure); 856} 857 858bool RenderThreadImpl::ResolveProxy(const GURL& url, std::string* proxy_list) { 859 bool result = false; 860 Send(new ViewHostMsg_ResolveProxy(url, &result, proxy_list)); 861 return result; 862} 863 864void RenderThreadImpl::PostponeIdleNotification() { 865 idle_notifications_to_skip_ = 2; 866} 867 868scoped_refptr<RendererGpuVideoAcceleratorFactories> 869RenderThreadImpl::GetGpuFactories() { 870 DCHECK(IsMainThread()); 871 872 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 873 scoped_refptr<RendererGpuVideoAcceleratorFactories> gpu_factories; 874 if (!cmd_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) { 875 if (!gpu_va_context_provider_ || 876 gpu_va_context_provider_->DestroyedOnMainThread()) { 877 gpu_va_context_provider_ = ContextProviderCommandBuffer::Create( 878 make_scoped_ptr( 879 WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( 880 this, 881 WebKit::WebGraphicsContext3D::Attributes(), 882 GURL("chrome://gpu/RenderThreadImpl::GetGpuVDAContext3D"))), 883 "GPU-VideoAccelerator-Offscreen"); 884 } 885 } 886 GpuChannelHost* gpu_channel_host = GetGpuChannel(); 887 if (gpu_channel_host) { 888 gpu_factories = new RendererGpuVideoAcceleratorFactories( 889 gpu_channel_host, gpu_va_context_provider_); 890 } 891 return gpu_factories; 892} 893 894scoped_ptr<WebGraphicsContext3DCommandBufferImpl> 895RenderThreadImpl::CreateOffscreenContext3d() { 896 WebKit::WebGraphicsContext3D::Attributes attributes; 897 attributes.shareResources = true; 898 attributes.depth = false; 899 attributes.stencil = false; 900 attributes.antialias = false; 901 attributes.noAutomaticFlushes = true; 902 903 return make_scoped_ptr( 904 WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( 905 this, 906 attributes, 907 GURL("chrome://gpu/RenderThreadImpl::CreateOffscreenContext3d"))); 908} 909 910scoped_refptr<cc::ContextProvider> 911RenderThreadImpl::OffscreenCompositorContextProvider() { 912 DCHECK(IsMainThread()); 913 914#if defined(OS_ANDROID) 915 if (SynchronousCompositorFactory* factory = 916 SynchronousCompositorFactory::GetInstance()) { 917 if (compositor_message_loop_proxy_) 918 return factory->GetOffscreenContextProviderForCompositorThread(); 919 return factory->GetOffscreenContextProviderForMainThread(); 920 } 921#endif 922 923 if (!offscreen_compositor_contexts_.get() || 924 offscreen_compositor_contexts_->DestroyedOnMainThread()) { 925 offscreen_compositor_contexts_ = ContextProviderCommandBuffer::Create( 926 CreateOffscreenContext3d(), 927 "Compositor-Offscreen"); 928 } 929 return offscreen_compositor_contexts_; 930} 931 932scoped_refptr<cc::ContextProvider> 933RenderThreadImpl::SharedMainThreadContextProvider() { 934 DCHECK(IsMainThread()); 935#if defined(OS_ANDROID) 936 if (SynchronousCompositorFactory* factory = 937 SynchronousCompositorFactory::GetInstance()) 938 return factory->GetOffscreenContextProviderForMainThread(); 939#endif 940 941 if (!shared_main_thread_contexts_ || 942 shared_main_thread_contexts_->DestroyedOnMainThread()) { 943 if (compositor_message_loop_proxy_) { 944 // In threaded compositing mode, we have to create a new ContextProvider 945 // to bind to the main thread since the compositor's is bound to the 946 // compositor thread. 947 shared_main_thread_contexts_ = 948 ContextProviderCommandBuffer::Create(CreateOffscreenContext3d(), 949 "Offscreen-MainThread"); 950 } else { 951 // In single threaded mode, we can use the same context provider. 952 shared_main_thread_contexts_ = 953 static_cast<ContextProviderCommandBuffer*>( 954 OffscreenCompositorContextProvider().get()); 955 } 956 } 957 if (shared_main_thread_contexts_ && 958 !shared_main_thread_contexts_->BindToCurrentThread()) 959 shared_main_thread_contexts_ = NULL; 960 return shared_main_thread_contexts_; 961} 962 963AudioRendererMixerManager* RenderThreadImpl::GetAudioRendererMixerManager() { 964 if (!audio_renderer_mixer_manager_) { 965 audio_renderer_mixer_manager_.reset(new AudioRendererMixerManager( 966 GetAudioHardwareConfig())); 967 } 968 969 return audio_renderer_mixer_manager_.get(); 970} 971 972media::AudioHardwareConfig* RenderThreadImpl::GetAudioHardwareConfig() { 973 if (!audio_hardware_config_) { 974 media::AudioParameters input_params; 975 media::AudioParameters output_params; 976 Send(new ViewHostMsg_GetAudioHardwareConfig( 977 &input_params, &output_params)); 978 979 audio_hardware_config_.reset(new media::AudioHardwareConfig( 980 input_params, output_params)); 981 audio_message_filter_->SetAudioHardwareConfig(audio_hardware_config_.get()); 982 } 983 984 return audio_hardware_config_.get(); 985} 986 987#if defined(OS_WIN) 988void RenderThreadImpl::PreCacheFontCharacters(const LOGFONT& log_font, 989 const string16& str) { 990 Send(new ViewHostMsg_PreCacheFontCharacters(log_font, str)); 991} 992 993void RenderThreadImpl::PreCacheFont(const LOGFONT& log_font) { 994 Send(new ChildProcessHostMsg_PreCacheFont(log_font)); 995} 996 997void RenderThreadImpl::ReleaseCachedFonts() { 998 Send(new ChildProcessHostMsg_ReleaseCachedFonts()); 999} 1000 1001#endif // OS_WIN 1002 1003bool RenderThreadImpl::IsMainThread() { 1004 return !!current(); 1005} 1006 1007base::MessageLoop* RenderThreadImpl::GetMainLoop() { 1008 return message_loop(); 1009} 1010 1011scoped_refptr<base::MessageLoopProxy> RenderThreadImpl::GetIOLoopProxy() { 1012 return io_message_loop_proxy_; 1013} 1014 1015base::WaitableEvent* RenderThreadImpl::GetShutDownEvent() { 1016 return shutdown_event_; 1017} 1018 1019scoped_ptr<base::SharedMemory> RenderThreadImpl::AllocateSharedMemory( 1020 size_t size) { 1021 return scoped_ptr<base::SharedMemory>( 1022 HostAllocateSharedMemoryBuffer(size)); 1023} 1024 1025int32 RenderThreadImpl::CreateViewCommandBuffer( 1026 int32 surface_id, const GPUCreateCommandBufferConfig& init_params) { 1027 TRACE_EVENT1("gpu", 1028 "RenderThreadImpl::CreateViewCommandBuffer", 1029 "surface_id", 1030 surface_id); 1031 1032 int32 route_id = MSG_ROUTING_NONE; 1033 IPC::Message* message = new GpuHostMsg_CreateViewCommandBuffer( 1034 surface_id, 1035 init_params, 1036 &route_id); 1037 1038 // Allow calling this from the compositor thread. 1039 thread_safe_sender()->Send(message); 1040 1041 return route_id; 1042} 1043 1044void RenderThreadImpl::CreateImage( 1045 gfx::PluginWindowHandle window, 1046 int32 image_id, 1047 const CreateImageCallback& callback) { 1048 NOTREACHED(); 1049} 1050 1051void RenderThreadImpl::DeleteImage(int32 image_id, int32 sync_point) { 1052 NOTREACHED(); 1053} 1054 1055void RenderThreadImpl::DoNotSuspendWebKitSharedTimer() { 1056 suspend_webkit_shared_timer_ = false; 1057} 1058 1059void RenderThreadImpl::DoNotNotifyWebKitOfModalLoop() { 1060 notify_webkit_of_modal_loop_ = false; 1061} 1062 1063void RenderThreadImpl::OnSetZoomLevelForCurrentURL(const std::string& scheme, 1064 const std::string& host, 1065 double zoom_level) { 1066 RenderViewZoomer zoomer(scheme, host, zoom_level); 1067 RenderView::ForEach(&zoomer); 1068} 1069 1070bool RenderThreadImpl::OnControlMessageReceived(const IPC::Message& msg) { 1071 ObserverListBase<RenderProcessObserver>::Iterator it(observers_); 1072 RenderProcessObserver* observer; 1073 while ((observer = it.GetNext()) != NULL) { 1074 if (observer->OnControlMessageReceived(msg)) 1075 return true; 1076 } 1077 1078 // Some messages are handled by delegates. 1079 if (appcache_dispatcher_->OnMessageReceived(msg) || 1080 dom_storage_dispatcher_->OnMessageReceived(msg)) { 1081 return true; 1082 } 1083 1084 bool handled = true; 1085 IPC_BEGIN_MESSAGE_MAP(RenderThreadImpl, msg) 1086 IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevelForCurrentURL, 1087 OnSetZoomLevelForCurrentURL) 1088 // TODO(port): removed from render_messages_internal.h; 1089 // is there a new non-windows message I should add here? 1090 IPC_MESSAGE_HANDLER(ViewMsg_New, OnCreateNewView) 1091 IPC_MESSAGE_HANDLER(ViewMsg_PurgePluginListCache, OnPurgePluginListCache) 1092 IPC_MESSAGE_HANDLER(ViewMsg_NetworkStateChanged, OnNetworkStateChanged) 1093 IPC_MESSAGE_HANDLER(ViewMsg_TempCrashWithData, OnTempCrashWithData) 1094 IPC_MESSAGE_HANDLER(ViewMsg_SetRendererProcessID, OnSetRendererProcessID) 1095 IPC_MESSAGE_HANDLER(ViewMsg_SetWebKitSharedTimersSuspended, 1096 OnSetWebKitSharedTimersSuspended) 1097 IPC_MESSAGE_UNHANDLED(handled = false) 1098 IPC_END_MESSAGE_MAP() 1099 return handled; 1100} 1101 1102void RenderThreadImpl::OnCreateNewView(const ViewMsg_New_Params& params) { 1103 EnsureWebKitInitialized(); 1104 // When bringing in render_view, also bring in webkit's glue and jsbindings. 1105 RenderViewImpl::Create( 1106 params.opener_route_id, 1107 params.renderer_preferences, 1108 params.web_preferences, 1109 params.view_id, 1110 params.main_frame_routing_id, 1111 params.surface_id, 1112 params.session_storage_namespace_id, 1113 params.frame_name, 1114 false, 1115 params.swapped_out, 1116 params.hidden, 1117 params.next_page_id, 1118 params.screen_info, 1119 params.accessibility_mode, 1120 params.allow_partial_swap); 1121} 1122 1123GpuChannelHost* RenderThreadImpl::EstablishGpuChannelSync( 1124 CauseForGpuLaunch cause_for_gpu_launch) { 1125 TRACE_EVENT0("gpu", "RenderThreadImpl::EstablishGpuChannelSync"); 1126 1127 if (gpu_channel_.get()) { 1128 // Do nothing if we already have a GPU channel or are already 1129 // establishing one. 1130 if (!gpu_channel_->IsLost()) 1131 return gpu_channel_.get(); 1132 1133 // Recreate the channel if it has been lost. 1134 gpu_channel_ = NULL; 1135 } 1136 1137 // Ask the browser for the channel name. 1138 int client_id = 0; 1139 IPC::ChannelHandle channel_handle; 1140 gpu::GPUInfo gpu_info; 1141 if (!Send(new GpuHostMsg_EstablishGpuChannel(cause_for_gpu_launch, 1142 &client_id, 1143 &channel_handle, 1144 &gpu_info)) || 1145#if defined(OS_POSIX) 1146 channel_handle.socket.fd == -1 || 1147#endif 1148 channel_handle.name.empty()) { 1149 // Otherwise cancel the connection. 1150 return NULL; 1151 } 1152 1153 GetContentClient()->SetGpuInfo(gpu_info); 1154 1155 // Cache some variables that are needed on the compositor thread for our 1156 // implementation of GpuChannelHostFactory. 1157 io_message_loop_proxy_ = ChildProcess::current()->io_message_loop_proxy(); 1158 shutdown_event_ = ChildProcess::current()->GetShutDownEvent(); 1159 1160 gpu_channel_ = GpuChannelHost::Create( 1161 this, 0, client_id, gpu_info, channel_handle); 1162 return gpu_channel_.get(); 1163} 1164 1165WebKit::WebMediaStreamCenter* RenderThreadImpl::CreateMediaStreamCenter( 1166 WebKit::WebMediaStreamCenterClient* client) { 1167#if defined(OS_ANDROID) 1168 if (CommandLine::ForCurrentProcess()->HasSwitch( 1169 switches::kDisableWebRTC)) 1170 return NULL; 1171#endif 1172 1173#if defined(ENABLE_WEBRTC) 1174 if (!media_stream_center_) { 1175 media_stream_center_ = GetContentClient()->renderer() 1176 ->OverrideCreateWebMediaStreamCenter(client); 1177 if (!media_stream_center_) { 1178 scoped_ptr<MediaStreamCenter> media_stream_center( 1179 new MediaStreamCenter(client, GetMediaStreamDependencyFactory())); 1180 AddObserver(media_stream_center.get()); 1181 media_stream_center_ = media_stream_center.release(); 1182 } 1183 } 1184#endif 1185 return media_stream_center_; 1186} 1187 1188MediaStreamDependencyFactory* 1189RenderThreadImpl::GetMediaStreamDependencyFactory() { 1190#if defined(ENABLE_WEBRTC) 1191 if (!media_stream_factory_) { 1192 media_stream_factory_.reset(new MediaStreamDependencyFactory( 1193 vc_manager_.get(), p2p_socket_dispatcher_.get())); 1194 } 1195#endif 1196 return media_stream_factory_.get(); 1197} 1198 1199GpuChannelHost* RenderThreadImpl::GetGpuChannel() { 1200 if (!gpu_channel_.get()) 1201 return NULL; 1202 1203 if (gpu_channel_->IsLost()) 1204 return NULL; 1205 1206 return gpu_channel_.get(); 1207} 1208 1209void RenderThreadImpl::OnPurgePluginListCache(bool reload_pages) { 1210 EnsureWebKitInitialized(); 1211 // The call below will cause a GetPlugins call with refresh=true, but at this 1212 // point we already know that the browser has refreshed its list, so disable 1213 // refresh temporarily to prevent each renderer process causing the list to be 1214 // regenerated. 1215 webkit_platform_support_->set_plugin_refresh_allowed(false); 1216 WebKit::resetPluginCache(reload_pages); 1217 webkit_platform_support_->set_plugin_refresh_allowed(true); 1218 1219 FOR_EACH_OBSERVER(RenderProcessObserver, observers_, PluginListChanged()); 1220} 1221 1222void RenderThreadImpl::OnNetworkStateChanged(bool online) { 1223 EnsureWebKitInitialized(); 1224 WebNetworkStateNotifier::setOnLine(online); 1225} 1226 1227void RenderThreadImpl::OnTempCrashWithData(const GURL& data) { 1228 GetContentClient()->SetActiveURL(data); 1229 CHECK(false); 1230} 1231 1232void RenderThreadImpl::OnSetRendererProcessID(base::ProcessId process_id) { 1233 renderer_process_id_ = process_id; 1234} 1235 1236void RenderThreadImpl::OnSetWebKitSharedTimersSuspended(bool suspend) { 1237 ToggleWebKitSharedTimer(suspend); 1238} 1239 1240void RenderThreadImpl::OnMemoryPressure( 1241 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { 1242 base::allocator::ReleaseFreeMemory(); 1243 1244 if (memory_pressure_level == 1245 base::MemoryPressureListener::MEMORY_PRESSURE_CRITICAL) { 1246 // Trigger full v8 garbage collection on critical memory notification. 1247 v8::V8::LowMemoryNotification(); 1248 // Clear the image cache. 1249 WebKit::WebImageCache::clear(); 1250 // Purge Skia font cache, by setting it to 0 and then again to the previous 1251 // limit. 1252 size_t font_cache_limit = SkGraphics::SetFontCacheLimit(0); 1253 SkGraphics::SetFontCacheLimit(font_cache_limit); 1254 } else { 1255 // Otherwise trigger a couple of v8 GCs using IdleNotification. 1256 if (!v8::V8::IdleNotification()) 1257 v8::V8::IdleNotification(); 1258 } 1259} 1260 1261scoped_refptr<base::MessageLoopProxy> 1262RenderThreadImpl::GetFileThreadMessageLoopProxy() { 1263 DCHECK(message_loop() == base::MessageLoop::current()); 1264 if (!file_thread_) { 1265 file_thread_.reset(new base::Thread("Renderer::FILE")); 1266 file_thread_->Start(); 1267 } 1268 return file_thread_->message_loop_proxy(); 1269} 1270 1271scoped_refptr<base::MessageLoopProxy> 1272RenderThreadImpl::GetMediaThreadMessageLoopProxy() { 1273 DCHECK(message_loop() == base::MessageLoop::current()); 1274 if (!media_thread_) { 1275 media_thread_.reset(new base::Thread("Media")); 1276 media_thread_->Start(); 1277 1278#if defined(OS_ANDROID) 1279 renderer_demuxer_ = new RendererDemuxerAndroid(); 1280 AddFilter(renderer_demuxer_.get()); 1281#endif 1282 } 1283 return media_thread_->message_loop_proxy(); 1284} 1285 1286void RenderThreadImpl::SetFlingCurveParameters( 1287 const std::vector<float>& new_touchpad, 1288 const std::vector<float>& new_touchscreen) { 1289 webkit_platform_support_->SetFlingCurveParameters(new_touchpad, 1290 new_touchscreen); 1291 1292} 1293 1294void RenderThreadImpl::SampleGamepads(WebKit::WebGamepads* data) { 1295 if (!gamepad_shared_memory_reader_) 1296 gamepad_shared_memory_reader_.reset(new GamepadSharedMemoryReader); 1297 gamepad_shared_memory_reader_->SampleGamepads(*data); 1298} 1299 1300base::ProcessId RenderThreadImpl::renderer_process_id() const { 1301 return renderer_process_id_; 1302} 1303 1304} // namespace content 1305