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