diff options
Diffstat (limited to 'chrome/renderer/render_thread.cc')
-rw-r--r-- | chrome/renderer/render_thread.cc | 68 |
1 files changed, 64 insertions, 4 deletions
diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc index c6e5b17..f517c9c 100644 --- a/chrome/renderer/render_thread.cc +++ b/chrome/renderer/render_thread.cc @@ -9,6 +9,7 @@ #include "base/command_line.h" #include "base/lazy_instance.h" +#include "base/logging.h" #include "base/shared_memory.h" #include "base/stats_table.h" #include "base/thread_local.h" @@ -58,6 +59,8 @@ using WebKit::WebString; namespace { static const unsigned int kCacheStatsDelayMS = 2000 /* milliseconds */; +static const double kInitialIdleHandlerDelayS = 1.0 /* seconds */; + static base::LazyInstance<base::ThreadLocalPointer<RenderThread> > lazy_tls( base::LINKER_INITIALIZED); @@ -105,8 +108,11 @@ void RenderThread::Init() { #endif plugin_refresh_allowed_ = true; - cache_stats_factory_.reset( - new ScopedRunnableMethodFactory<RenderThread>(this)); + cache_stats_task_pending_ = false; + widget_count_ = 0; + hidden_widget_count_ = 0; + idle_notification_delay_in_s_ = kInitialIdleHandlerDelayS; + task_factory_.reset(new ScopedRunnableMethodFactory<RenderThread>(this)); visited_link_slave_.reset(new VisitedLinkSlave()); user_script_slave_.reset(new UserScriptSlave()); @@ -156,6 +162,30 @@ void RenderThread::RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) { channel()->RemoveFilter(filter); } +void RenderThread::WidgetHidden() { + DCHECK(hidden_widget_count_ < widget_count_); + hidden_widget_count_++ ; + if (widget_count_ && hidden_widget_count_ == widget_count_) { + // Reset the delay. + idle_notification_delay_in_s_ = kInitialIdleHandlerDelayS; + + // Schedule the IdleHandler to wakeup in a bit. + MessageLoop::current()->PostDelayedTask(FROM_HERE, + task_factory_->NewRunnableMethod(&RenderThread::IdleHandler), + static_cast<int64>(floor(idle_notification_delay_in_s_)) * 1000); + } +} + +void RenderThread::WidgetRestored() { + DCHECK(hidden_widget_count_ > 0); + hidden_widget_count_--; + + // Note: we may have a timer pending to call the IdleHandler (see the + // WidgetHidden() code). But we don't bother to cancel it as it is + // benign and won't do anything if the tab is un-hidden when it is + // called. +} + void RenderThread::Resolve(const char* name, size_t length) { return dns_master_->Resolve(name, length); } @@ -316,15 +346,17 @@ void RenderThread::InformHostOfCacheStats() { WebCache::UsageStats stats; WebCache::getUsageStats(&stats); Send(new ViewHostMsg_UpdatedCacheStats(stats)); + cache_stats_task_pending_ = false; } void RenderThread::InformHostOfCacheStatsLater() { // Rate limit informing the host of our cache stats. - if (!cache_stats_factory_->empty()) + if (cache_stats_task_pending_) return; + cache_stats_task_pending_ = true; MessageLoop::current()->PostDelayedTask(FROM_HERE, - cache_stats_factory_->NewRunnableMethod( + task_factory_->NewRunnableMethod( &RenderThread::InformHostOfCacheStats), kCacheStatsDelayMS); } @@ -424,6 +456,34 @@ void RenderThread::EnsureWebKitInitialized() { } } +void RenderThread::IdleHandler() { + // It is possible that the timer was set while the widgets were idle, + // but that they are no longer idle. If so, just return. + if (!widget_count_ || hidden_widget_count_ < widget_count_) + return; + + if (v8::V8::IsDead()) + return; + + LOG(INFO) << "RenderThread calling v8 IdleNotification for " << this; + + // When V8::IdleNotification returns true, it means that it has cleaned up + // as much as it can. There is no point in continuing to call it. + if (!v8::V8::IdleNotification(false)) { + // Dampen the delay using the algorithm: + // delay = delay + 1 / (delay + 2) + // Using floor(delay) has a dampening effect such as: + // 1s, 1, 1, 2, 2, 2, 2, 3, 3, ... + idle_notification_delay_in_s_ += + 1.0 / (idle_notification_delay_in_s_ + 2.0); + + // Schedule the next timer. + MessageLoop::current()->PostDelayedTask(FROM_HERE, + task_factory_->NewRunnableMethod(&RenderThread::IdleHandler), + static_cast<int64>(floor(idle_notification_delay_in_s_)) * 1000); + } +} + void RenderThread::OnExtensionMessageInvoke(const std::string& function_name, const ListValue& args) { RendererExtensionBindings::Invoke(function_name, args, NULL); |