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