1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <vector>
6
7#include "chrome/browser/apps/ephemeral_app_browsertest.h"
8#include "chrome/browser/apps/ephemeral_app_service.h"
9#include "chrome/browser/profiles/profile.h"
10#include "content/public/test/test_utils.h"
11#include "extensions/browser/extension_prefs.h"
12#include "extensions/browser/extension_registry.h"
13#include "extensions/browser/notification_types.h"
14#include "extensions/common/manifest.h"
15
16using extensions::Extension;
17using extensions::ExtensionPrefs;
18using extensions::ExtensionRegistry;
19
20namespace {
21
22const int kNumTestApps = 2;
23const char* kTestApps[] = {
24  "app_window/generic",
25  "minimal"
26};
27
28}  // namespace
29
30class EphemeralAppServiceBrowserTest : public EphemeralAppTestBase {
31 protected:
32  void LoadApps() {
33    for (int i = 0; i < kNumTestApps; ++i) {
34      const Extension* extension = InstallEphemeralApp(kTestApps[i]);
35      ASSERT_TRUE(extension);
36      app_ids_.push_back(extension->id());
37    }
38
39    ASSERT_EQ(kNumTestApps, (int) app_ids_.size());
40  }
41
42  void GarbageCollectEphemeralApps() {
43    EphemeralAppService* ephemeral_service = EphemeralAppService::Get(
44        browser()->profile());
45    ASSERT_TRUE(ephemeral_service);
46    ephemeral_service->GarbageCollectApps();
47  }
48
49  void InitEphemeralAppCount(EphemeralAppService* ephemeral_service) {
50    ephemeral_service->InitEphemeralAppCount();
51  }
52
53  void DisableEphemeralAppsOnStartup() {
54    EphemeralAppService* ephemeral_service =
55        EphemeralAppService::Get(browser()->profile());
56    ASSERT_TRUE(ephemeral_service);
57    ephemeral_service->DisableEphemeralAppsOnStartup();
58  }
59
60  std::vector<std::string> app_ids_;
61};
62
63// Verifies that inactive ephemeral apps are uninstalled and active apps are
64// not removed. Extensive testing of the ephemeral app cache's replacement
65// policies is done in the unit tests for EphemeralAppService. This is more
66// like an integration test.
67IN_PROC_BROWSER_TEST_F(EphemeralAppServiceBrowserTest,
68                       GarbageCollectInactiveApps) {
69  EphemeralAppService* ephemeral_service =
70      EphemeralAppService::Get(browser()->profile());
71  ASSERT_TRUE(ephemeral_service);
72  InitEphemeralAppCount(ephemeral_service);
73
74  LoadApps();
75
76  const base::Time time_now = base::Time::Now();
77  ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile());
78  ASSERT_TRUE(prefs);
79
80  // Set launch time for an inactive app.
81  std::string inactive_app_id = app_ids_[0];
82  base::Time inactive_launch = time_now -
83      base::TimeDelta::FromDays(EphemeralAppService::kAppInactiveThreshold + 1);
84  prefs->SetLastLaunchTime(inactive_app_id, inactive_launch);
85
86  // Set launch time for an active app.
87  std::string active_app_id = app_ids_[1];
88  base::Time active_launch = time_now -
89      base::TimeDelta::FromDays(EphemeralAppService::kAppKeepThreshold);
90  prefs->SetLastLaunchTime(active_app_id, active_launch);
91
92  // Perform garbage collection.
93  content::WindowedNotificationObserver uninstall_signal(
94      extensions::NOTIFICATION_EXTENSION_UNINSTALLED_DEPRECATED,
95      content::Source<Profile>(browser()->profile()));
96  GarbageCollectEphemeralApps();
97  uninstall_signal.Wait();
98
99  ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
100  ASSERT_TRUE(registry);
101  EXPECT_FALSE(registry->GetExtensionById(inactive_app_id,
102                                          ExtensionRegistry::EVERYTHING));
103  EXPECT_TRUE(
104      registry->GetExtensionById(active_app_id, ExtensionRegistry::EVERYTHING));
105
106  EXPECT_EQ(1, ephemeral_service->ephemeral_app_count());
107}
108
109// Verify that the count of ephemeral apps is maintained correctly.
110IN_PROC_BROWSER_TEST_F(EphemeralAppServiceBrowserTest, EphemeralAppCount) {
111  EphemeralAppService* ephemeral_service =
112      EphemeralAppService::Get(browser()->profile());
113  ASSERT_TRUE(ephemeral_service);
114  InitEphemeralAppCount(ephemeral_service);
115
116  // The count should not increase for regular installed apps.
117  EXPECT_TRUE(InstallPlatformApp("minimal"));
118  EXPECT_EQ(0, ephemeral_service->ephemeral_app_count());
119
120  // The count should increase when an ephemeral app is added.
121  const Extension* app = InstallEphemeralApp(kMessagingReceiverApp);
122  ASSERT_TRUE(app);
123  EXPECT_EQ(1, ephemeral_service->ephemeral_app_count());
124
125  // The count should remain constant if the ephemeral app is updated.
126  const std::string app_id = app->id();
127  app = UpdateEphemeralApp(
128      app_id, GetTestPath(kMessagingReceiverAppV2),
129      GetTestPath(kMessagingReceiverApp).ReplaceExtension(
130          FILE_PATH_LITERAL(".pem")));
131  ASSERT_TRUE(app);
132  EXPECT_EQ(1, ephemeral_service->ephemeral_app_count());
133
134  // The count should decrease when an ephemeral app is promoted to a regular
135  // installed app.
136  PromoteEphemeralApp(app);
137  EXPECT_EQ(0, ephemeral_service->ephemeral_app_count());
138}
139
140// Verify that the cache of ephemeral apps is correctly cleared. Running apps
141// should not be removed.
142IN_PROC_BROWSER_TEST_F(EphemeralAppServiceBrowserTest, ClearCachedApps) {
143  const Extension* running_app =
144      InstallAndLaunchEphemeralApp(kMessagingReceiverApp);
145  const Extension* inactive_app =
146      InstallAndLaunchEphemeralApp(kDispatchEventTestApp);
147  std::string inactive_app_id = inactive_app->id();
148  std::string running_app_id = running_app->id();
149  CloseAppWaitForUnload(inactive_app_id);
150
151  EphemeralAppService* ephemeral_service =
152      EphemeralAppService::Get(browser()->profile());
153  ASSERT_TRUE(ephemeral_service);
154  EXPECT_EQ(2, ephemeral_service->ephemeral_app_count());
155
156  ephemeral_service->ClearCachedApps();
157
158  ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
159  ASSERT_TRUE(registry);
160  EXPECT_FALSE(registry->GetExtensionById(inactive_app_id,
161                                          ExtensionRegistry::EVERYTHING));
162  EXPECT_TRUE(registry->GetExtensionById(running_app_id,
163                                         ExtensionRegistry::EVERYTHING));
164
165  EXPECT_EQ(1, ephemeral_service->ephemeral_app_count());
166}
167
168// Verify that the service will unload and disable ephemeral apps on startup.
169IN_PROC_BROWSER_TEST_F(EphemeralAppServiceBrowserTest,
170                       DisableEphemeralAppsOnStartup) {
171  const Extension* installed_app = InstallPlatformApp(kNotificationsTestApp);
172  const Extension* running_app =
173      InstallAndLaunchEphemeralApp(kMessagingReceiverApp);
174  const Extension* inactive_app = InstallEphemeralApp(kDispatchEventTestApp);
175  const Extension* disabled_app = InstallEphemeralApp(kFileSystemTestApp);
176  ASSERT_TRUE(installed_app);
177  ASSERT_TRUE(running_app);
178  ASSERT_TRUE(inactive_app);
179  ASSERT_TRUE(disabled_app);
180  DisableEphemeralApp(disabled_app, Extension::DISABLE_PERMISSIONS_INCREASE);
181
182  ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
183  ASSERT_TRUE(registry);
184  EXPECT_TRUE(registry->enabled_extensions().Contains(installed_app->id()));
185  EXPECT_TRUE(registry->enabled_extensions().Contains(running_app->id()));
186  EXPECT_TRUE(registry->enabled_extensions().Contains(inactive_app->id()));
187  EXPECT_TRUE(registry->disabled_extensions().Contains(disabled_app->id()));
188
189  DisableEphemeralAppsOnStartup();
190
191  // Verify that the inactive app is disabled.
192  EXPECT_TRUE(registry->enabled_extensions().Contains(installed_app->id()));
193  EXPECT_TRUE(registry->enabled_extensions().Contains(running_app->id()));
194  EXPECT_TRUE(registry->disabled_extensions().Contains(inactive_app->id()));
195  EXPECT_TRUE(registry->disabled_extensions().Contains(disabled_app->id()));
196
197  ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
198  ASSERT_TRUE(prefs);
199  EXPECT_FALSE(prefs->HasDisableReason(
200      installed_app->id(), Extension::DISABLE_INACTIVE_EPHEMERAL_APP));
201  EXPECT_FALSE(prefs->HasDisableReason(
202      running_app->id(), Extension::DISABLE_INACTIVE_EPHEMERAL_APP));
203  EXPECT_TRUE(prefs->HasDisableReason(
204      inactive_app->id(), Extension::DISABLE_INACTIVE_EPHEMERAL_APP));
205  EXPECT_TRUE(prefs->HasDisableReason(
206      disabled_app->id(), Extension::DISABLE_INACTIVE_EPHEMERAL_APP));
207  EXPECT_TRUE(prefs->HasDisableReason(
208      disabled_app->id(), Extension::DISABLE_PERMISSIONS_INCREASE));
209}
210