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