Commit 99c49b51 authored by yoz@chromium.org's avatar yoz@chromium.org

Add an arbitrary delay before unloading lazy background pages.

BUG=119619
TEST=Make sure that lazy page process stays open until 10 seconds after the last of a series of events it's listening for.

Review URL: https://chromiumcodereview.appspot.com/10272019

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@134853 0039d316-1c4b-4281-b951-d872f2087c98
parent f2a4ec55
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/lazy_instance.h" #include "base/lazy_instance.h"
#include "base/message_loop.h"
#include "base/string_number_conversions.h"
#include "base/time.h"
#include "chrome/browser/extensions/extension_event_router.h" #include "chrome/browser/extensions/extension_event_router.h"
#include "chrome/browser/extensions/extension_process_manager.h" #include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_host.h" #include "chrome/browser/extensions/extension_host.h"
...@@ -125,7 +128,8 @@ ExtensionProcessManager* ExtensionProcessManager::Create(Profile* profile) { ...@@ -125,7 +128,8 @@ ExtensionProcessManager* ExtensionProcessManager::Create(Profile* profile) {
} }
ExtensionProcessManager::ExtensionProcessManager(Profile* profile) ExtensionProcessManager::ExtensionProcessManager(Profile* profile)
: site_instance_(SiteInstance::Create(profile)) { : site_instance_(SiteInstance::Create(profile)),
weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
Profile* original_profile = profile->GetOriginalProfile(); Profile* original_profile = profile->GetOriginalProfile();
registrar_.Add(this, chrome::NOTIFICATION_EXTENSIONS_READY, registrar_.Add(this, chrome::NOTIFICATION_EXTENSIONS_READY,
content::Source<Profile>(original_profile)); content::Source<Profile>(original_profile));
...@@ -145,6 +149,20 @@ ExtensionProcessManager::ExtensionProcessManager(Profile* profile) ...@@ -145,6 +149,20 @@ ExtensionProcessManager::ExtensionProcessManager(Profile* profile)
content::Source<content::BrowserContext>(profile)); content::Source<content::BrowserContext>(profile));
registrar_.Add(this, content::NOTIFICATION_DEVTOOLS_WINDOW_CLOSING, registrar_.Add(this, content::NOTIFICATION_DEVTOOLS_WINDOW_CLOSING,
content::Source<content::BrowserContext>(profile)); content::Source<content::BrowserContext>(profile));
event_page_idle_time_ = base::TimeDelta::FromSeconds(10);
unsigned idle_time_sec = 0;
if (base::StringToUint(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kEventPageIdleTime), &idle_time_sec)) {
event_page_idle_time_ = base::TimeDelta::FromSeconds(idle_time_sec);
}
event_page_unloading_time_ = base::TimeDelta::FromSeconds(5);
unsigned unloading_time_sec = 0;
if (base::StringToUint(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kEventPageUnloadingTime), &unloading_time_sec)) {
event_page_unloading_time_ = base::TimeDelta::FromSeconds(
unloading_time_sec);
}
} }
ExtensionProcessManager::~ExtensionProcessManager() { ExtensionProcessManager::~ExtensionProcessManager() {
...@@ -414,22 +432,31 @@ int ExtensionProcessManager::DecrementLazyKeepaliveCount( ...@@ -414,22 +432,31 @@ int ExtensionProcessManager::DecrementLazyKeepaliveCount(
int& count = background_page_data_[extension->id()].lazy_keepalive_count; int& count = background_page_data_[extension->id()].lazy_keepalive_count;
DCHECK_GT(count, 0); DCHECK_GT(count, 0);
if (--count == 0) if (--count == 0) {
OnLazyBackgroundPageIdle(extension->id()); MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&ExtensionProcessManager::OnLazyBackgroundPageIdle,
weak_ptr_factory_.GetWeakPtr(), extension->id(),
++background_page_data_[extension->id()].close_sequence_id),
event_page_idle_time_);
}
return count; return count;
} }
void ExtensionProcessManager::OnLazyBackgroundPageIdle( void ExtensionProcessManager::OnLazyBackgroundPageIdle(
const std::string& extension_id) { const std::string& extension_id, int sequence_id) {
ExtensionHost* host = GetBackgroundHostForExtension(extension_id); ExtensionHost* host = GetBackgroundHostForExtension(extension_id);
if (host && !background_page_data_[extension_id].is_closing) { if (host && !background_page_data_[extension_id].is_closing &&
sequence_id == background_page_data_[extension_id].close_sequence_id) {
// Tell the renderer we are about to close. This is a simple ping that the // Tell the renderer we are about to close. This is a simple ping that the
// renderer will respond to. The purpose is to control sequencing: if the // renderer will respond to. The purpose is to control sequencing: if the
// extension remains idle until the renderer responds with an ACK, then we // extension remains idle until the renderer responds with an ACK, then we
// know that the extension process is ready to shut down. // know that the extension process is ready to shut down. If our
// close_sequence_id has already changed, then we would ignore the
// ShouldUnloadAck, so we don't send the ping.
host->render_view_host()->Send(new ExtensionMsg_ShouldUnload( host->render_view_host()->Send(new ExtensionMsg_ShouldUnload(
extension_id, ++background_page_data_[extension_id].close_sequence_id)); extension_id, sequence_id));
} }
} }
...@@ -449,10 +476,21 @@ void ExtensionProcessManager::OnShouldUnloadAck( ...@@ -449,10 +476,21 @@ void ExtensionProcessManager::OnShouldUnloadAck(
if (host && if (host &&
sequence_id == background_page_data_[extension_id].close_sequence_id) { sequence_id == background_page_data_[extension_id].close_sequence_id) {
background_page_data_[extension_id].is_closing = true; background_page_data_[extension_id].is_closing = true;
host->render_view_host()->Send(new ExtensionMsg_Unload(extension_id)); MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&ExtensionProcessManager::CloseLazyBackgroundPageNow,
weak_ptr_factory_.GetWeakPtr(), extension_id),
event_page_unloading_time_);
} }
} }
void ExtensionProcessManager::CloseLazyBackgroundPageNow(
const std::string& extension_id) {
ExtensionHost* host = GetBackgroundHostForExtension(extension_id);
if (host)
host->render_view_host()->Send(new ExtensionMsg_Unload(extension_id));
}
void ExtensionProcessManager::OnUnloadAck(const std::string& extension_id) { void ExtensionProcessManager::OnUnloadAck(const std::string& extension_id) {
ExtensionHost* host = GetBackgroundHostForExtension(extension_id); ExtensionHost* host = GetBackgroundHostForExtension(extension_id);
if (host) if (host)
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/time.h"
#include "content/public/common/view_type.h" #include "content/public/common/view_type.h"
#include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_registrar.h"
...@@ -182,8 +184,10 @@ class ExtensionProcessManager : public content::NotificationObserver { ...@@ -182,8 +184,10 @@ class ExtensionProcessManager : public content::NotificationObserver {
// These are called when the extension transitions between idle and active. // These are called when the extension transitions between idle and active.
// They control the process of closing the background page when idle. // They control the process of closing the background page when idle.
void OnLazyBackgroundPageIdle(const std::string& extension_id); void OnLazyBackgroundPageIdle(const std::string& extension_id,
int sequence_id);
void OnLazyBackgroundPageActive(const std::string& extension_id); void OnLazyBackgroundPageActive(const std::string& extension_id);
void CloseLazyBackgroundPageNow(const std::string& extension_id);
// Updates a potentially-registered RenderViewHost once it has been // Updates a potentially-registered RenderViewHost once it has been
// associated with a WebContents. This allows us to gather information that // associated with a WebContents. This allows us to gather information that
...@@ -192,6 +196,16 @@ class ExtensionProcessManager : public content::NotificationObserver { ...@@ -192,6 +196,16 @@ class ExtensionProcessManager : public content::NotificationObserver {
BackgroundPageDataMap background_page_data_; BackgroundPageDataMap background_page_data_;
// The time to delay between an extension becoming idle and
// sending a ShouldUnload message; read from command-line switch.
base::TimeDelta event_page_idle_time_;
// The time to delay between sending a ShouldUnload message and
// sending a Unload message; read from command-line switch.
base::TimeDelta event_page_unloading_time_;
base::WeakPtrFactory<ExtensionProcessManager> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ExtensionProcessManager); DISALLOW_COPY_AND_ASSIGN(ExtensionProcessManager);
}; };
......
...@@ -103,6 +103,9 @@ public: ...@@ -103,6 +103,9 @@ public:
void SetUpCommandLine(CommandLine* command_line) { void SetUpCommandLine(CommandLine* command_line) {
ExtensionApiTest::SetUpCommandLine(command_line); ExtensionApiTest::SetUpCommandLine(command_line);
command_line->AppendSwitch(switches::kEnableExperimentalExtensionApis); command_line->AppendSwitch(switches::kEnableExperimentalExtensionApis);
// Set shorter delays to prevent test timeouts.
command_line->AppendSwitchASCII(switches::kEventPageIdleTime, "1");
command_line->AppendSwitchASCII(switches::kEventPageUnloadingTime, "1");
} }
// Loads the extension, which temporarily starts the lazy background page // Loads the extension, which temporarily starts the lazy background page
......
...@@ -645,6 +645,14 @@ const char kExperimentalSpellcheckerFeatures[] = ...@@ -645,6 +645,14 @@ const char kExperimentalSpellcheckerFeatures[] =
// numbers. // numbers.
const char kExplicitlyAllowedPorts[] = "explicitly-allowed-ports"; const char kExplicitlyAllowedPorts[] = "explicitly-allowed-ports";
// The time in seconds 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.
const char kEventPageUnloadingTime[] = "event-page-unloading-time";
// Marks a renderer as extension process. // Marks a renderer as extension process.
const char kExtensionProcess[] = "extension-process"; const char kExtensionProcess[] = "extension-process";
......
...@@ -18,7 +18,8 @@ namespace switches { ...@@ -18,7 +18,8 @@ namespace switches {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Can't find the switch you are looking for? Try looking in // Can't find the switch you are looking for? Try looking in
// ui/gfx/gl/gl_switches.cc or base/base_switches.cc or // ui/gfx/gl/gl_switches.cc or base/base_switches.cc or
// content/common/content_switches.cc or media/base/media_switches.cc instead. // content/public/common/content_switches.cc or media/base/media_switches.cc
// instead.
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// All switches in alphabetical order. The switches should be documented // All switches in alphabetical order. The switches should be documented
...@@ -178,6 +179,8 @@ extern const char kEnableWatchdog[]; ...@@ -178,6 +179,8 @@ extern const char kEnableWatchdog[];
extern const char kEnableWebsiteSettings[]; extern const char kEnableWebsiteSettings[];
extern const char kEnableWebSocketOverSpdy[]; extern const char kEnableWebSocketOverSpdy[];
extern const char kEnableWebStoreLink[]; extern const char kEnableWebStoreLink[];
extern const char kEventPageIdleTime[];
extern const char kEventPageUnloadingTime[];
extern const char kExperimentalSpellcheckerFeatures[]; extern const char kExperimentalSpellcheckerFeatures[];
extern const char kExplicitlyAllowedPorts[]; extern const char kExplicitlyAllowedPorts[];
extern const char kExtensionProcess[]; extern const char kExtensionProcess[];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment