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