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