| Index: extensions/browser/process_manager.cc
|
| diff --git a/extensions/browser/process_manager.cc b/extensions/browser/process_manager.cc
|
| index a1ee794ace65ef55a82aa923bf09acabab0e1e1a..7cd0ecfb3c3243e077b2edc8210f8aa2b28b3371 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);
|
|
|