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