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