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