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