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