Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Unified Diff: chrome/browser/apps/ephemeral_app_service.cc

Issue 344543006: Disable ephemeral apps after they stop running (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Prevent demotion of installed app due to race condition Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/apps/ephemeral_app_service.cc
diff --git a/chrome/browser/apps/ephemeral_app_service.cc b/chrome/browser/apps/ephemeral_app_service.cc
index 067de9cc7067b990e3fd5b764774ab13a0f68a0e..9793539048a4d5794a1f405086ec37c59bc292f0 100644
--- a/chrome/browser/apps/ephemeral_app_service.cc
+++ b/chrome/browser/apps/ephemeral_app_service.cc
@@ -4,7 +4,9 @@
#include "chrome/browser/apps/ephemeral_app_service.h"
+#include "apps/app_lifetime_monitor_factory.h"
#include "base/command_line.h"
+#include "base/message_loop/message_loop.h"
#include "chrome/browser/apps/ephemeral_app_service_factory.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_service.h"
@@ -23,6 +25,7 @@
using extensions::Extension;
using extensions::ExtensionPrefs;
+using extensions::ExtensionRegistry;
using extensions::ExtensionSet;
using extensions::ExtensionSystem;
@@ -41,6 +44,13 @@ const int kGarbageCollectAppsInstallDelay = 15;
// kMaxEphemeralAppsCount.
const int kGarbageCollectAppsTriggerCount = 35;
+// The number of seconds after an app has stopped running before it will be
+// unloaded and disabled.
+const int kDefaultUnloadAppDelay = 1;
+
+// The number of seconds after startup before unloading inactive ephemeral apps.
+const int kUnloadAppsOnStartupDelay = 5;
+
} // namespace
const int EphemeralAppService::kAppInactiveThreshold = 10;
@@ -55,17 +65,16 @@ EphemeralAppService* EphemeralAppService::Get(Profile* profile) {
EphemeralAppService::EphemeralAppService(Profile* profile)
: profile_(profile),
extension_registry_observer_(this),
- ephemeral_app_count_(-1) {
+ ephemeral_app_count_(-1),
+ unload_idle_app_delay_(kDefaultUnloadAppDelay),
+ weak_ptr_factory_(this) {
if (!CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableEphemeralApps))
return;
- extension_registry_observer_.Add(
- extensions::ExtensionRegistry::Get(profile_));
+ extension_registry_observer_.Add(ExtensionRegistry::Get(profile_));
registrar_.Add(this, chrome::NOTIFICATION_EXTENSIONS_READY,
content::Source<Profile>(profile_));
- registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
- content::Source<Profile>(profile_));
}
EphemeralAppService::~EphemeralAppService() {
@@ -80,11 +89,6 @@ void EphemeralAppService::Observe(
Init();
break;
}
- case chrome::NOTIFICATION_PROFILE_DESTROYED: {
- // Ideally we need to know when the extension system is shutting down.
- garbage_collect_apps_timer_.Stop();
- break;
- }
default:
NOTREACHED();
}
@@ -100,8 +104,10 @@ void EphemeralAppService::OnExtensionWillBeInstalled(
// An ephemeral app was just promoted to a regular installed app.
--ephemeral_app_count_;
DCHECK_GE(ephemeral_app_count_, 0);
+ HandleEphemeralAppPromoted(extension);
} else if (!is_update &&
extensions::util::IsEphemeralApp(extension->id(), profile_)) {
+ // A new ephemeral app was launched.
++ephemeral_app_count_;
if (ephemeral_app_count_ >= kGarbageCollectAppsTriggerCount) {
TriggerGarbageCollect(
@@ -119,16 +125,51 @@ void EphemeralAppService::OnExtensionUninstalled(
}
}
+void EphemeralAppService::OnAppStop(Profile* profile,
+ const std::string& app_id) {
+ if (!extensions::util::IsEphemeralApp(app_id, profile_))
+ return;
+
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&EphemeralAppService::UnloadEphemeralApp,
+ weak_ptr_factory_.GetWeakPtr(),
+ app_id),
+ base::TimeDelta::FromSeconds(unload_idle_app_delay_));
+}
+
+void EphemeralAppService::OnChromeTerminating() {
+ garbage_collect_apps_timer_.Stop();
+
+ extension_registry_observer_.RemoveAll();
+
+ apps::AppLifetimeMonitor* lifetime_monitor =
+ apps::AppLifetimeMonitorFactory::GetForProfile(profile_);
+ DCHECK(lifetime_monitor);
+ lifetime_monitor->RemoveObserver(this);
+}
+
void EphemeralAppService::Init() {
InitEphemeralAppCount();
+
+ apps::AppLifetimeMonitor* lifetime_monitor =
+ apps::AppLifetimeMonitorFactory::GetForProfile(profile_);
+ DCHECK(lifetime_monitor);
+ lifetime_monitor->AddObserver(this);
+
TriggerGarbageCollect(
base::TimeDelta::FromSeconds(kGarbageCollectAppsStartupDelay));
+
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&EphemeralAppService::UnloadEphemeralAppsOnStartup,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::TimeDelta::FromSeconds(kUnloadAppsOnStartupDelay));
}
void EphemeralAppService::InitEphemeralAppCount() {
scoped_ptr<ExtensionSet> extensions =
- extensions::ExtensionRegistry::Get(profile_)
- ->GenerateInstalledExtensionsSet();
+ ExtensionRegistry::Get(profile_)->GenerateInstalledExtensionsSet();
ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_);
DCHECK(prefs);
@@ -141,6 +182,62 @@ void EphemeralAppService::InitEphemeralAppCount() {
}
}
+void EphemeralAppService::UnloadEphemeralApp(const std::string& app_id) {
+ if (!extensions::util::IsEphemeralApp(app_id, profile_) ||
+ !extensions::util::IsExtensionIdle(app_id, profile_)) {
+ return;
+ }
+
+ // After an ephemeral app has stopped running, unload it from extension
+ // system to prevent all background activity.
+ ExtensionService* service =
+ ExtensionSystem::Get(profile_)->extension_service();
+ DCHECK(service);
+ service->DisableExtension(app_id, Extension::DISABLE_INACTIVE_EPHEMERAL_APP);
+}
+
+void EphemeralAppService::UnloadEphemeralAppsOnStartup() {
+ ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_);
+ DCHECK(prefs);
+ ExtensionService* service =
+ ExtensionSystem::Get(profile_)->extension_service();
+ DCHECK(service);
+
+ // Ensure that all inactive ephemeral apps are unloaded from extension system
+ // to prevent all background activity. This is done on startup to catch any
+ // apps that escaped unloading on shutdown.
+ scoped_ptr<ExtensionSet> extensions =
+ ExtensionRegistry::Get(profile_)->GenerateInstalledExtensionsSet();
+ for (ExtensionSet::const_iterator it = extensions->begin();
+ it != extensions->end();
+ ++it) {
+ const Extension* extension = *it;
+ if (prefs->IsEphemeralApp(extension->id()) &&
+ !prefs->IsExtensionDisabled(extension->id()) &&
+ !prefs->IsExtensionRunning(extension->id()) &&
+ extensions::util::IsExtensionIdle(extension->id(), profile_)) {
+ service->DisableExtension(extension->id(),
+ Extension::DISABLE_INACTIVE_EPHEMERAL_APP);
+ }
+ }
+}
+
+void EphemeralAppService::HandleEphemeralAppPromoted(const Extension* app) {
+ // When ephemeral apps are promoted to regular install apps, remove the
+ // DISABLE_INACTIVE_EPHEMERAL_APP reason and enable the app if there are no
+ // other reasons.
+ ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_);
+ DCHECK(prefs);
+
+ int disable_reasons = prefs->GetDisableReasons(app->id());
+ if (disable_reasons & Extension::DISABLE_INACTIVE_EPHEMERAL_APP) {
+ prefs->RemoveDisableReason(app->id(),
+ Extension::DISABLE_INACTIVE_EPHEMERAL_APP);
+ if (disable_reasons == Extension::DISABLE_INACTIVE_EPHEMERAL_APP)
+ prefs->SetExtensionState(app->id(), Extension::ENABLED);
+ }
+}
+
void EphemeralAppService::TriggerGarbageCollect(const base::TimeDelta& delay) {
if (!garbage_collect_apps_timer_.IsRunning()) {
garbage_collect_apps_timer_.Start(
@@ -153,8 +250,7 @@ void EphemeralAppService::TriggerGarbageCollect(const base::TimeDelta& delay) {
void EphemeralAppService::GarbageCollectApps() {
scoped_ptr<ExtensionSet> extensions =
- extensions::ExtensionRegistry::Get(profile_)
- ->GenerateInstalledExtensionsSet();
+ ExtensionRegistry::Get(profile_)->GenerateInstalledExtensionsSet();
ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_);
DCHECK(prefs);

Powered by Google App Engine
This is Rietveld 408576698