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