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