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