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

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: Addressed review comments and refactoring Created 6 years, 4 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 46df9cf7875f2559cb2db24a613ec1b4fc1dbec2..f23cc9085e64534363c3ff47f1a0685cd95cff41 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"
@@ -44,6 +46,13 @@ const int kGarbageCollectAppsInstallDelay = 15;
// kMaxEphemeralAppsCount.
const int kGarbageCollectAppsTriggerCount = 35;
+// The number of seconds after an app has stopped running before it will be
+// disabled.
+const int kDefaultDisableAppDelay = 1;
+
+// The number of seconds after startup before disabling inactive ephemeral apps.
+const int kDisableAppsOnStartupDelay = 5;
+
} // namespace
const int EphemeralAppService::kAppInactiveThreshold = 10;
@@ -58,17 +67,13 @@ EphemeralAppService* EphemeralAppService::Get(Profile* profile) {
EphemeralAppService::EphemeralAppService(Profile* profile)
: profile_(profile),
extension_registry_observer_(this),
- ephemeral_app_count_(-1) {
- if (!CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableEphemeralApps))
- return;
-
- extension_registry_observer_.Add(ExtensionRegistry::Get(profile_));
+ app_lifetime_monitor_observer_(this),
+ ephemeral_app_count_(-1),
+ disable_idle_app_delay_(kDefaultDisableAppDelay),
+ weak_ptr_factory_(this) {
registrar_.Add(this,
extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED,
content::Source<Profile>(profile_));
- registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
- content::Source<Profile>(profile_));
}
EphemeralAppService::~EphemeralAppService() {
@@ -119,11 +124,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();
}
@@ -139,8 +139,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(
@@ -159,10 +161,46 @@ 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::DisableEphemeralApp,
+ weak_ptr_factory_.GetWeakPtr(),
+ app_id),
+ base::TimeDelta::FromSeconds(disable_idle_app_delay_));
+}
+
+void EphemeralAppService::OnChromeTerminating() {
+ garbage_collect_apps_timer_.Stop();
+
+ extension_registry_observer_.RemoveAll();
+ app_lifetime_monitor_observer_.RemoveAll();
+}
+
void EphemeralAppService::Init() {
InitEphemeralAppCount();
+
+ // Start observing.
+ extension_registry_observer_.Add(ExtensionRegistry::Get(profile_));
+ app_lifetime_monitor_observer_.Add(
+ apps::AppLifetimeMonitorFactory::GetForProfile(profile_));
+
+ // Execute startup clean up tasks (except during tests).
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType))
+ return;
+
TriggerGarbageCollect(
base::TimeDelta::FromSeconds(kGarbageCollectAppsStartupDelay));
+
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&EphemeralAppService::DisableEphemeralAppsOnStartup,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::TimeDelta::FromSeconds(kDisableAppsOnStartupDelay));
}
void EphemeralAppService::InitEphemeralAppCount() {
@@ -180,6 +218,76 @@ void EphemeralAppService::InitEphemeralAppCount() {
}
}
+void EphemeralAppService::DisableEphemeralApp(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 and disable it 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::DisableEphemeralAppsOnStartup() {
+ ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_);
+ DCHECK(prefs);
+ ExtensionService* service =
+ ExtensionSystem::Get(profile_)->extension_service();
+ DCHECK(service);
+
+ // Ensure that all inactive ephemeral apps are disabled to prevent all
+ // background activity. This is done on startup to catch any apps that escaped
+ // being disabled 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()))
+ continue;
+
+ // Only V2 apps are installed ephemerally. Remove other ephemeral app types
+ // that were cached before this policy was introduced.
+ if (!extension->is_platform_app()) {
+ service->UninstallExtension(
+ extension->id(),
+ extensions::UNINSTALL_REASON_ORPHANED_EPHEMERAL_EXTENSION,
+ base::Bind(&base::DoNothing),
+ NULL);
+ continue;
+ }
+
+ if (!prefs->HasDisableReason(extension->id(),
+ Extension::DISABLE_INACTIVE_EPHEMERAL_APP) &&
+ !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(
« no previous file with comments | « chrome/browser/apps/ephemeral_app_service.h ('k') | chrome/browser/apps/ephemeral_app_service_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698