summaryrefslogtreecommitdiffstats
path: root/chrome/renderer
diff options
context:
space:
mode:
authormpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-07 22:12:36 +0000
committermpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-07 22:12:36 +0000
commit71d6d858d9221d44bd156028ae1478599d95e53a (patch)
treee26ce5e66444de65e6ee1e68b6a44c898c5391b9 /chrome/renderer
parentc1c97f3280ba6914bf19ed9cdfdfbf5dc3e29f77 (diff)
downloadchromium_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.cc76
-rw-r--r--chrome/renderer/render_thread.h17
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);
};