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