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