diff options
author | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-07 22:12:36 +0000 |
---|---|---|
committer | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-07 22:12:36 +0000 |
commit | 71d6d858d9221d44bd156028ae1478599d95e53a (patch) | |
tree | e26ce5e66444de65e6ee1e68b6a44c898c5391b9 /chrome/renderer | |
parent | c1c97f3280ba6914bf19ed9cdfdfbf5dc3e29f77 (diff) | |
download | chromium_src-71d6d858d9221d44bd156028ae1478599d95e53a.zip chromium_src-71d6d858d9221d44bd156028ae1478599d95e53a.tar.gz chromium_src-71d6d858d9221d44bd156028ae1478599d95e53a.tar.bz2 |
Hook up V8 idle notifications for extension prcoesses.
We reset the idle timer after any activity, which includes an extension event
or message, or a new extension view being created. The timer runs after 10
seconds of idleness.
BUG=29329
Review URL: http://codereview.chromium.org/460062
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@34002 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer')
-rw-r--r-- | chrome/renderer/render_thread.cc | 76 | ||||
-rw-r--r-- | chrome/renderer/render_thread.h | 17 |
2 files changed, 67 insertions, 26 deletions
diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc index 2a62005..9dd5cdc 100644 --- a/chrome/renderer/render_thread.cc +++ b/chrome/renderer/render_thread.cc @@ -93,6 +93,8 @@ using WebKit::WebView; namespace { static const unsigned int kCacheStatsDelayMS = 2000 /* milliseconds */; static const double kInitialIdleHandlerDelayS = 1.0 /* seconds */; +static const double kInitialExtensionIdleHandlerDelayS = 5.0 /* seconds */; +static const int64 kMaxExtensionIdleHandlerDelayS = 5*60 /* seconds */; static base::LazyInstance<base::ThreadLocalPointer<RenderThread> > lazy_tls( base::LINKER_INITIALIZED); @@ -161,11 +163,15 @@ void RenderThread::Init() { CoInitialize(0); #endif + std::string type_str = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kProcessType); + is_extension_process_ = type_str == switches::kExtensionProcess; plugin_refresh_allowed_ = true; cache_stats_task_pending_ = false; widget_count_ = 0; hidden_widget_count_ = 0; - idle_notification_delay_in_s_ = kInitialIdleHandlerDelayS; + idle_notification_delay_in_s_ = is_extension_process_ ? + kInitialExtensionIdleHandlerDelayS : kInitialIdleHandlerDelayS; task_factory_.reset(new ScopedRunnableMethodFactory<RenderThread>(this)); visited_link_slave_.reset(new VisitedLinkSlave()); @@ -220,25 +226,16 @@ void RenderThread::RemoveFilter(IPC::ChannelProxy::MessageFilter* 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); - } + if (!is_extension_process() && + widget_count_ && hidden_widget_count_ == widget_count_) + ScheduleIdleHandler(kInitialIdleHandlerDelayS); } 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. + if (!is_extension_process()) + idle_timer_.Stop(); } void RenderThread::Resolve(const char* name, size_t length) { @@ -291,6 +288,11 @@ void RenderThread::OnExtensionSetAPIPermissions( const std::string& extension_id, const std::vector<std::string>& permissions) { ExtensionProcessBindings::SetAPIPermissions(extension_id, permissions); + + // This is called when starting a new extension page, so start the idle + // handler ticking. + DCHECK(is_extension_process()); + ScheduleIdleHandler(kInitialExtensionIdleHandlerDelayS); } void RenderThread::OnExtensionSetHostPermissions( @@ -500,6 +502,14 @@ void RenderThread::EnsureWebKitInitialized() { if (webkit_client_.get()) return; + // For extensions, we want to ensure we call the IdleHandler every so often, + // even if the extension keeps up activity. + if (is_extension_process()) { + forced_idle_timer_.Start( + base::TimeDelta::FromSeconds(kMaxExtensionIdleHandlerDelayS), + this, &RenderThread::IdleHandler); + } + v8::V8::SetCounterFunction(StatsTable::FindLocation); v8::V8::SetCreateHistogramFunction(CreateHistogram); v8::V8::SetAddHistogramSampleFunction(AddHistogramSample); @@ -601,11 +611,6 @@ 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 defined(OS_WIN) && defined(USE_TCMALLOC) MallocExtension::instance()->ReleaseFreeMemory(); #endif @@ -620,18 +625,37 @@ void RenderThread::IdleHandler() { // 1s, 1, 1, 2, 2, 2, 2, 3, 3, ... // Note that idle_notification_delay_in_s_ would be reset to // kInitialIdleHandlerDelayS in RenderThread::WidgetHidden. - idle_notification_delay_in_s_ += - 1.0 / (idle_notification_delay_in_s_ + 2.0); + ScheduleIdleHandler(idle_notification_delay_in_s_ + + 1.0 / (idle_notification_delay_in_s_ + 2.0)); + if (is_extension_process()) { + // Dampen the forced delay as well if the extension stays idle for long + // periods of time. + int64 forced_delay_s = + std::max(static_cast<int64>(idle_notification_delay_in_s_), + kMaxExtensionIdleHandlerDelayS); + forced_idle_timer_.Stop(); + forced_idle_timer_.Start( + base::TimeDelta::FromSeconds(forced_delay_s), + this, &RenderThread::IdleHandler); + } +} - // 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::ScheduleIdleHandler(double initial_delay_s) { + idle_notification_delay_in_s_ = initial_delay_s; + idle_timer_.Stop(); + idle_timer_.Start( + base::TimeDelta::FromSeconds(static_cast<int64>(initial_delay_s)), + this, &RenderThread::IdleHandler); } void RenderThread::OnExtensionMessageInvoke(const std::string& function_name, const ListValue& args) { RendererExtensionBindings::Invoke(function_name, args, NULL); + + // Reset the idle handler each time there's any activity like event or message + // dispatch, for which Invoke is the chokepoint. + if (is_extension_process()) + ScheduleIdleHandler(kInitialExtensionIdleHandlerDelayS); } void RenderThread::OnPurgeMemory() { diff --git a/chrome/renderer/render_thread.h b/chrome/renderer/render_thread.h index f5e0d80..8a376aa 100644 --- a/chrome/renderer/render_thread.h +++ b/chrome/renderer/render_thread.h @@ -12,6 +12,8 @@ #include "base/shared_memory.h" #include "base/string16.h" #include "base/task.h" +#include "base/time.h" +#include "base/timer.h" #include "build/build_config.h" #include "chrome/common/child_thread.h" #include "chrome/common/css_colors.h" @@ -125,6 +127,8 @@ class RenderThread : public RenderThreadBase, bool plugin_refresh_allowed() const { return plugin_refresh_allowed_; } + bool is_extension_process() const { return is_extension_process_; } + // Do DNS prefetch resolution of a hostname. void Resolve(const char* name, size_t length); @@ -206,6 +210,9 @@ class RenderThread : public RenderThreadBase, // A task we invoke periodically to assist with idle cleanup. void IdleHandler(); + // Schedule a call to IdleHandler with the given initial delay. + void ScheduleIdleHandler(double initial_delay_s); + // These objects live solely on the render thread. scoped_ptr<ScopedRunnableMethodFactory<RenderThread> > task_factory_; scoped_ptr<VisitedLinkSlave> visited_link_slave_; @@ -242,6 +249,16 @@ class RenderThread : public RenderThreadBase, // The current value of the idle notification timer delay. double idle_notification_delay_in_s_; + // True if this renderer is running extensions. + bool is_extension_process_; + + // Timer that periodically calls IdleHandler. + base::RepeatingTimer<RenderThread> idle_timer_; + + // Same as above, but on a longer timer and will run even if the process is + // not idle, to ensure that IdleHandle gets called eventually. + base::RepeatingTimer<RenderThread> forced_idle_timer_; + DISALLOW_COPY_AND_ASSIGN(RenderThread); }; |