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