15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <vector>
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/apps/ephemeral_app_browsertest.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/apps/ephemeral_app_service.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/test/test_utils.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_prefs.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/common/manifest.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using extensions::Extension;
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using extensions::ExtensionPrefs;
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using extensions::ExtensionSystem;
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int kNumTestApps = 2;
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char* kTestApps[] = {
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  "app_window/generic",
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  "minimal"
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class EphemeralAppServiceBrowserTest : public EphemeralAppTestBase {
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) protected:
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void LoadApps() {
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (int i = 0; i < kNumTestApps; ++i) {
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      const Extension* extension = InstallEphemeralApp(kTestApps[i]);
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ASSERT_TRUE(extension);
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      app_ids_.push_back(extension->id());
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ASSERT_EQ(kNumTestApps, (int) app_ids_.size());
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void GarbageCollectEphemeralApps() {
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EphemeralAppService* ephemeral_service = EphemeralAppService::Get(
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        browser()->profile());
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ASSERT_TRUE(ephemeral_service);
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ephemeral_service->GarbageCollectApps();
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void InitEphemeralAppCount(EphemeralAppService* ephemeral_service) {
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ephemeral_service->InitEphemeralAppCount();
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<std::string> app_ids_;
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Verifies that inactive ephemeral apps are uninstalled and active apps are
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// not removed. Extensive testing of the ephemeral app cache's replacement
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// policies is done in the unit tests for EphemeralAppService. This is more
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// like an integration test.
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(EphemeralAppServiceBrowserTest,
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       GarbageCollectInactiveApps) {
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EphemeralAppService* ephemeral_service =
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      EphemeralAppService::Get(browser()->profile());
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_TRUE(ephemeral_service);
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  InitEphemeralAppCount(ephemeral_service);
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LoadApps();
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::Time time_now = base::Time::Now();
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile());
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(prefs);
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Set launch time for an inactive app.
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string inactive_app_id = app_ids_[0];
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::Time inactive_launch = time_now -
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::TimeDelta::FromDays(EphemeralAppService::kAppInactiveThreshold + 1);
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  prefs->SetLastLaunchTime(inactive_app_id, inactive_launch);
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Set launch time for an active app.
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string active_app_id = app_ids_[1];
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::Time active_launch = time_now -
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::TimeDelta::FromDays(EphemeralAppService::kAppKeepThreshold);
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  prefs->SetLastLaunchTime(active_app_id, active_launch);
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Perform garbage collection.
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  content::WindowedNotificationObserver uninstall_signal(
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      chrome::NOTIFICATION_EXTENSION_UNINSTALLED_DEPRECATED,
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      content::Source<Profile>(browser()->profile()));
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GarbageCollectEphemeralApps();
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  uninstall_signal.Wait();
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExtensionService* service = ExtensionSystem::Get(browser()->profile())
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ->extension_service();
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_TRUE(service);
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(service->GetInstalledExtension(inactive_app_id));
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(service->GetInstalledExtension(active_app_id));
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(1, ephemeral_service->ephemeral_app_count());
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Verify that the count of ephemeral apps is maintained correctly.
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(EphemeralAppServiceBrowserTest,
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       EphemeralAppCount) {
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EphemeralAppService* ephemeral_service =
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      EphemeralAppService::Get(browser()->profile());
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_TRUE(ephemeral_service);
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  InitEphemeralAppCount(ephemeral_service);
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // The count should not increase for regular installed apps.
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(InstallPlatformApp("minimal"));
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(0, ephemeral_service->ephemeral_app_count());
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // The count should increase when an ephemeral app is added.
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const Extension* app = InstallEphemeralApp(kMessagingReceiverApp);
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_TRUE(app);
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(1, ephemeral_service->ephemeral_app_count());
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // The count should remain constant if the ephemeral app is updated.
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const std::string app_id = app->id();
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  app = UpdateEphemeralApp(
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      app_id, GetTestPath(kMessagingReceiverAppV2),
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      GetTestPath(kMessagingReceiverApp).ReplaceExtension(
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          FILE_PATH_LITERAL(".pem")));
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_TRUE(app);
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(1, ephemeral_service->ephemeral_app_count());
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // The count should decrease when an ephemeral app is promoted to a regular
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // installed app.
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PromoteEphemeralApp(app);
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(0, ephemeral_service->ephemeral_app_count());
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
132