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