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