diff options
author | scheib@chromium.org <scheib@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-03 01:25:32 +0000 |
---|---|---|
committer | scheib@chromium.org <scheib@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-03 01:25:32 +0000 |
commit | 38877015653d92a3937c8516b77c6b88181fc3d9 (patch) | |
tree | 805dad84377e8a7c8c3e92ba1573c8ebf1aae175 /extensions | |
parent | a316ad7a2e6baefb32be587e2cd701930a092dad (diff) | |
download | chromium_src-38877015653d92a3937c8516b77c6b88181fc3d9.zip chromium_src-38877015653d92a3937c8516b77c6b88181fc3d9.tar.gz chromium_src-38877015653d92a3937c8516b77c6b88181fc3d9.tar.bz2 |
Add KeepaliveImpulse to extension process manager.
Impulses are an efficient way to handle certain types
of activity from extensions. E.g. the work in progress
to keep NaCl plugins in background pages alive. An
Increment / Decrement approach would require extensive
and fragile instrumentation of all APIs. Impulses
can be sent upon any api activity and act as an
implicit increment with a timed out decrement.
See design doc:
https://docs.google.com/a/chromium.org/document/d/1mI0lS1rfAf-BAGLmWAEcWy37Xq9dOvgfMx8OqeUMXts/edit#
BUG=298339
Review URL: https://codereview.chromium.org/60613004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@238261 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'extensions')
-rw-r--r-- | extensions/browser/process_manager.cc | 94 | ||||
-rw-r--r-- | extensions/browser/process_manager.h | 16 | ||||
-rw-r--r-- | extensions/common/switches.cc | 6 |
3 files changed, 92 insertions, 24 deletions
diff --git a/extensions/browser/process_manager.cc b/extensions/browser/process_manager.cc index a1ee794..7cd0ecf 100644 --- a/extensions/browser/process_manager.cc +++ b/extensions/browser/process_manager.cc @@ -133,6 +133,10 @@ struct ProcessManager::BackgroundPageData { // The count of things keeping the lazy background page alive. int lazy_keepalive_count; + // Tracks if an impulse event has occured since the last polling check. + bool keepalive_impulse; + bool previous_keepalive_impulse; + // This is used with the ShouldSuspend message, to ensure that the extension // remained idle between sending the message and receiving the ack. int close_sequence_id; @@ -147,7 +151,11 @@ struct ProcessManager::BackgroundPageData { linked_ptr<base::ElapsedTimer> since_suspended; BackgroundPageData() - : lazy_keepalive_count(0), close_sequence_id(0), is_closing(false) {} + : lazy_keepalive_count(0), + keepalive_impulse(false), + previous_keepalive_impulse(false), + close_sequence_id(0), + is_closing(false) {} }; // @@ -197,22 +205,25 @@ ProcessManager::ProcessManager(BrowserContext* context, } event_page_idle_time_ = base::TimeDelta::FromSeconds(10); - unsigned idle_time_sec = 0; + unsigned idle_time_msec = 0; if (base::StringToUint(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - extensions::switches::kEventPageIdleTime), &idle_time_sec)) { - event_page_idle_time_ = base::TimeDelta::FromSeconds(idle_time_sec); + extensions::switches::kEventPageIdleTime), &idle_time_msec)) { + CHECK(idle_time_msec > 0); // OnKeepaliveImpulseCheck requires non zero. + event_page_idle_time_ = base::TimeDelta::FromMilliseconds(idle_time_msec); } event_page_suspending_time_ = base::TimeDelta::FromSeconds(5); - unsigned suspending_time_sec = 0; + unsigned suspending_time_msec = 0; if (base::StringToUint(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( extensions::switches::kEventPageSuspendingTime), - &suspending_time_sec)) { + &suspending_time_msec)) { event_page_suspending_time_ = - base::TimeDelta::FromSeconds(suspending_time_sec); + base::TimeDelta::FromMilliseconds(suspending_time_msec); } content::DevToolsManager::GetInstance()->AddAgentStateCallback( devtools_callback_); + + OnKeepaliveImpulseCheck(); } ProcessManager::~ProcessManager() { @@ -346,38 +357,38 @@ int ProcessManager::GetLazyKeepaliveCount(const Extension* extension) { return background_page_data_[extension->id()].lazy_keepalive_count; } -int ProcessManager::IncrementLazyKeepaliveCount(const Extension* extension) { +void ProcessManager::IncrementLazyKeepaliveCount(const Extension* extension) { if (!BackgroundInfo::HasLazyBackgroundPage(extension)) - return 0; + return; int& count = background_page_data_[extension->id()].lazy_keepalive_count; if (++count == 1) OnLazyBackgroundPageActive(extension->id()); - - return count; } -int ProcessManager::DecrementLazyKeepaliveCount(const Extension* extension) { +void ProcessManager::DecrementLazyKeepaliveCount(const Extension* extension) { if (!BackgroundInfo::HasLazyBackgroundPage(extension)) - return 0; + return; + DecrementLazyKeepaliveCount(extension->id()); +} - int& count = background_page_data_[extension->id()].lazy_keepalive_count; +void ProcessManager::DecrementLazyKeepaliveCount( + const std::string& extension_id) { + int& count = background_page_data_[extension_id].lazy_keepalive_count; DCHECK_GT(count, 0); // If we reach a zero keepalive count when the lazy background page is about // to be closed, incrementing close_sequence_id will cancel the close // sequence and cause the background page to linger. So check is_closing // before initiating another close sequence. - if (--count == 0 && !background_page_data_[extension->id()].is_closing) { + if (--count == 0 && !background_page_data_[extension_id].is_closing) { base::MessageLoop::current()->PostDelayedTask( FROM_HERE, base::Bind(&ProcessManager::OnLazyBackgroundPageIdle, - weak_ptr_factory_.GetWeakPtr(), extension->id(), - ++background_page_data_[extension->id()].close_sequence_id), + weak_ptr_factory_.GetWeakPtr(), extension_id, + ++background_page_data_[extension_id].close_sequence_id), event_page_idle_time_); } - - return count; } void ProcessManager::IncrementLazyKeepaliveCountForView( @@ -394,6 +405,51 @@ void ProcessManager::IncrementLazyKeepaliveCountForView( } } +// This implementation layers on top of the keepalive count. An impulse sets +// a per extension flag. On a regular interval that flag is checked. Changes +// from the flag not being set to set cause an IncrementLazyKeepaliveCount. +void ProcessManager::KeepaliveImpulse(const Extension* extension) { + if (!BackgroundInfo::HasLazyBackgroundPage(extension)) + return; + + BackgroundPageData& bd = background_page_data_[extension->id()]; + + if (!bd.keepalive_impulse) { + bd.keepalive_impulse = true; + if (!bd.previous_keepalive_impulse) { + IncrementLazyKeepaliveCount(extension); + } + } +} + +// DecrementLazyKeepaliveCount is called when no calls to KeepaliveImpulse +// have been made for at least event_page_idle_time_. In the best case an +// impulse was made just before being cleared, and the decrement will occur +// event_page_idle_time_ later, causing a 2 * event_page_idle_time_ total time +// for extension to be shut down based on impulses. Worst case is an impulse +// just after a clear, adding one check cycle and resulting in 3x total time. +void ProcessManager::OnKeepaliveImpulseCheck() { + for (BackgroundPageDataMap::iterator i = background_page_data_.begin(); + i != background_page_data_.end(); + ++i) { + if (i->second.previous_keepalive_impulse && !i->second.keepalive_impulse) + DecrementLazyKeepaliveCount(i->first); + + i->second.previous_keepalive_impulse = i->second.keepalive_impulse; + i->second.keepalive_impulse = false; + } + + // OnKeepaliveImpulseCheck() is always called in constructor, but in unit + // tests there will be no message loop. In that event don't schedule tasks. + if (base::MessageLoop::current()) { + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::Bind(&ProcessManager::OnKeepaliveImpulseCheck, + weak_ptr_factory_.GetWeakPtr()), + event_page_idle_time_); + } +} + void ProcessManager::OnLazyBackgroundPageIdle(const std::string& extension_id, int sequence_id) { ExtensionHost* host = GetBackgroundHostForExtension(extension_id); diff --git a/extensions/browser/process_manager.h b/extensions/browser/process_manager.h index 669ebe7..379c364 100644 --- a/extensions/browser/process_manager.h +++ b/extensions/browser/process_manager.h @@ -86,12 +86,17 @@ class ProcessManager : public content::NotificationObserver { // When this reaches 0, we will begin the process of shutting down the page. // "Things" include pending events, resource loads, and API calls. int GetLazyKeepaliveCount(const Extension* extension); - int IncrementLazyKeepaliveCount(const Extension* extension); - int DecrementLazyKeepaliveCount(const Extension* extension); + void IncrementLazyKeepaliveCount(const Extension* extension); + void DecrementLazyKeepaliveCount(const Extension* extension); void IncrementLazyKeepaliveCountForView( content::RenderViewHost* render_view_host); + // Keeps a background page alive. Unlike IncrementLazyKeepaliveCount, these + // impulses will only keep the page alive for a limited amount of time unless + // called regularly. + void KeepaliveImpulse(const Extension* extension); + // Handles a response to the ShouldSuspend message, used for lazy background // pages. void OnShouldSuspendAck(const std::string& extension_id, int sequence_id); @@ -164,6 +169,13 @@ class ProcessManager : public content::NotificationObserver { // Close the given |host| iff it's a background page. void CloseBackgroundHost(ExtensionHost* host); + // Internal implementation of DecrementLazyKeepaliveCount with an + // |extension_id| known to have a lazy background page. + void DecrementLazyKeepaliveCount(const std::string& extension_id); + + // Checks if keepalive impulses have occured, and adjusts keep alive count. + void OnKeepaliveImpulseCheck(); + // These are called when the extension transitions between idle and active. // They control the process of closing the background page when idle. void OnLazyBackgroundPageIdle(const std::string& extension_id, diff --git a/extensions/common/switches.cc b/extensions/common/switches.cc index 82222c4..5d50344 100644 --- a/extensions/common/switches.cc +++ b/extensions/common/switches.cc @@ -34,12 +34,12 @@ const char kEnableExperimentalExtensionApis[] = // them in the chrome:extensions page. const char kErrorConsole[] = "error-console"; -// The time in seconds that an extension event page can be idle before it +// The time in milliseconds that an extension event page can be idle before it // is shut down. const char kEventPageIdleTime[] = "event-page-idle-time"; -// The time in seconds that an extension event page has between being notified -// of its impending unload and that unload happening. +// The time in milliseconds that an extension event page has between being +// notified of its impending unload and that unload happening. const char kEventPageSuspendingTime[] = "event-page-unloading-time"; // Enables extensions running scripts on chrome:// URLs. |