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