Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / extension_storage_monitor_browsertest.cc
1 // Copyright 2014 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 <set>
6
7 #include "base/run_loop.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "chrome/browser/extensions/extension_browsertest.h"
10 #include "chrome/browser/extensions/extension_service.h"
11 #include "chrome/browser/extensions/extension_storage_monitor.h"
12 #include "chrome/browser/ui/extensions/application_launch.h"
13 #include "content/public/test/test_utils.h"
14 #include "extensions/browser/extension_prefs.h"
15 #include "extensions/browser/extension_registry.h"
16 #include "extensions/browser/extension_system.h"
17 #include "extensions/browser/test_extension_registry_observer.h"
18 #include "extensions/test/extension_test_message_listener.h"
19 #include "ui/message_center/message_center.h"
20 #include "ui/message_center/message_center_observer.h"
21
22 namespace extensions {
23
24 namespace {
25
26 const int kInitialUsageThreshold = 500;
27
28 const char kWriteDataApp[] = "storage_monitor/write_data";
29
30 class NotificationObserver : public message_center::MessageCenterObserver {
31  public:
32   explicit NotificationObserver(const std::string& target_notification)
33       : message_center_(message_center::MessageCenter::Get()),
34         target_notification_id_(target_notification),
35         waiting_(false) {
36     message_center_->AddObserver(this);
37   }
38
39   virtual ~NotificationObserver() {
40     message_center_->RemoveObserver(this);
41   }
42
43   bool HasReceivedNotification() const {
44     return received_notifications_.find(target_notification_id_) !=
45       received_notifications_.end();
46   }
47
48   // Runs the message loop and returns true if a notification is received.
49   // Immediately returns true if a notification has already been received.
50   bool WaitForNotification() {
51     if (HasReceivedNotification())
52       return true;
53
54     waiting_ = true;
55     content::RunMessageLoop();
56     waiting_ = false;
57     return HasReceivedNotification();
58   }
59
60  private:
61   // MessageCenterObserver implementation:
62   virtual void OnNotificationAdded(
63       const std::string& notification_id) OVERRIDE {
64     received_notifications_.insert(notification_id);
65
66     if (waiting_ && HasReceivedNotification())
67       base::MessageLoopForUI::current()->Quit();
68   }
69
70   message_center::MessageCenter* message_center_;
71   std::set<std::string> received_notifications_;
72   std::string target_notification_id_;
73   bool waiting_;
74 };
75
76 }  // namespace
77
78 class ExtensionStorageMonitorTest : public ExtensionBrowserTest {
79  public:
80   ExtensionStorageMonitorTest() : storage_monitor_(NULL) {}
81
82  protected:
83   // ExtensionBrowserTest overrides:
84   virtual void SetUpOnMainThread() OVERRIDE {
85     ExtensionBrowserTest::SetUpOnMainThread();
86
87     InitStorageMonitor();
88   }
89
90   ExtensionStorageMonitor* monitor() {
91     CHECK(storage_monitor_);
92     return storage_monitor_;
93   }
94
95   int64 GetInitialExtensionThreshold() {
96     CHECK(storage_monitor_);
97     return storage_monitor_->initial_extension_threshold_;
98   }
99
100   int64 GetInitialEphemeralThreshold() {
101     CHECK(storage_monitor_);
102     return storage_monitor_->initial_ephemeral_threshold_;
103   }
104
105   void DisableForInstalledExtensions() {
106     CHECK(storage_monitor_);
107     storage_monitor_->enable_for_all_extensions_ = false;
108   }
109
110   const Extension* InitWriteDataApp() {
111     base::FilePath path = test_data_dir_.AppendASCII(kWriteDataApp);
112     const Extension* extension = InstallExtension(path, 1);
113     EXPECT_TRUE(extension);
114     return extension;
115   }
116
117   const Extension* InitWriteDataEphemeralApp() {
118     // The threshold for installed extensions should be higher than ephemeral
119     // apps.
120     storage_monitor_->initial_extension_threshold_ =
121         storage_monitor_->initial_ephemeral_threshold_ * 4;
122
123     base::FilePath path = test_data_dir_.AppendASCII(kWriteDataApp);
124     const Extension* extension = InstallEphemeralAppWithSourceAndFlags(
125         path, 1, Manifest::INTERNAL, Extension::NO_FLAGS);
126     EXPECT_TRUE(extension);
127     return extension;
128   }
129
130   std::string GetNotificationId(const std::string& extension_id) {
131     return monitor()->GetNotificationId(extension_id);
132   }
133
134   bool IsStorageNotificationEnabled(const std::string& extension_id) {
135     return monitor()->IsStorageNotificationEnabled(extension_id);
136   }
137
138   int64 GetNextStorageThreshold(const std::string& extension_id) {
139     return monitor()->GetNextStorageThreshold(extension_id);
140   }
141
142   void WriteBytesExpectingNotification(const Extension* extension,
143                                        int num_bytes) {
144     int64 previous_threshold = GetNextStorageThreshold(extension->id());
145     WriteBytes(extension, num_bytes, true);
146     EXPECT_GT(GetNextStorageThreshold(extension->id()), previous_threshold);
147   }
148
149   void WriteBytesNotExpectingNotification(const Extension* extension,
150                                          int num_bytes) {
151     WriteBytes(extension, num_bytes, false);
152   }
153
154   void SimulateUninstallDialogAccept() {
155     // Ensure the uninstall dialog was shown and fake an accept.
156     ASSERT_TRUE(monitor()->uninstall_dialog_.get());
157     monitor()->ExtensionUninstallAccepted();
158   }
159
160  private:
161   void InitStorageMonitor() {
162     storage_monitor_ = ExtensionStorageMonitor::Get(profile());
163     ASSERT_TRUE(storage_monitor_);
164
165     // Override thresholds so that we don't have to write a huge amount of data
166     // to trigger notifications in these tests.
167     storage_monitor_->enable_for_all_extensions_ = true;
168     storage_monitor_->initial_extension_threshold_ = kInitialUsageThreshold;
169     storage_monitor_->initial_ephemeral_threshold_ = kInitialUsageThreshold;
170
171     // To ensure storage events are dispatched from QuotaManager immediately.
172     storage_monitor_->observer_rate_ = 0;
173   }
174
175   // Write a number of bytes to persistent storage.
176   void WriteBytes(const Extension* extension,
177                   int num_bytes,
178                   bool expected_notification) {
179     ExtensionTestMessageListener launched_listener("launched", true);
180     ExtensionTestMessageListener write_complete_listener(
181         "write_complete", false);
182     NotificationObserver notification_observer(
183         GetNotificationId(extension->id()));
184
185     OpenApplication(AppLaunchParams(
186         profile(), extension, LAUNCH_CONTAINER_NONE, NEW_WINDOW));
187     ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
188
189     // Instruct the app to write |num_bytes| of data.
190     launched_listener.Reply(base::IntToString(num_bytes));
191     ASSERT_TRUE(write_complete_listener.WaitUntilSatisfied());
192
193     if (expected_notification) {
194       EXPECT_TRUE(notification_observer.WaitForNotification());
195     } else {
196       base::RunLoop().RunUntilIdle();
197       EXPECT_FALSE(notification_observer.HasReceivedNotification());
198     }
199   }
200
201   ExtensionStorageMonitor* storage_monitor_;
202 };
203
204 // Control - No notifications should be shown if usage remains under the
205 // threshold.
206 IN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, UnderThreshold) {
207   const Extension* extension = InitWriteDataApp();
208   ASSERT_TRUE(extension);
209   WriteBytesNotExpectingNotification(extension, 1);
210 }
211
212 // Ensure a notification is shown when usage reaches the first threshold.
213 IN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, ExceedInitialThreshold) {
214   const Extension* extension = InitWriteDataApp();
215   ASSERT_TRUE(extension);
216   WriteBytesExpectingNotification(extension, GetInitialExtensionThreshold());
217 }
218
219 // Ensure a notification is shown when usage immediately exceeds double the
220 // first threshold.
221 IN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, DoubleInitialThreshold) {
222   const Extension* extension = InitWriteDataApp();
223   ASSERT_TRUE(extension);
224   WriteBytesExpectingNotification(extension,
225                                   GetInitialExtensionThreshold() * 2);
226 }
227
228 // Ensure that notifications are not fired if the next threshold has not been
229 // reached.
230 IN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, ThrottleNotifications) {
231   const Extension* extension = InitWriteDataApp();
232   ASSERT_TRUE(extension);
233
234   // Exceed the first threshold.
235   WriteBytesExpectingNotification(extension, GetInitialExtensionThreshold());
236
237   // Stay within the next threshold.
238   WriteBytesNotExpectingNotification(extension, 1);
239 }
240
241 // Verify that notifications are disabled when the user clicks the action button
242 // in the notification.
243 IN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, UserDisabledNotifications) {
244   const Extension* extension = InitWriteDataApp();
245   ASSERT_TRUE(extension);
246   WriteBytesExpectingNotification(extension, GetInitialExtensionThreshold());
247
248   EXPECT_TRUE(IsStorageNotificationEnabled(extension->id()));
249
250   // Fake clicking the notification button to disable notifications.
251   message_center::MessageCenter::Get()->ClickOnNotificationButton(
252       GetNotificationId(extension->id()),
253       ExtensionStorageMonitor::BUTTON_DISABLE_NOTIFICATION);
254
255   EXPECT_FALSE(IsStorageNotificationEnabled(extension->id()));
256
257   // Expect to receive no further notifications when usage continues to
258   // increase.
259   int64 next_threshold = GetNextStorageThreshold(extension->id());
260   int64 next_data_size = next_threshold - GetInitialExtensionThreshold();
261   ASSERT_GT(next_data_size, 0);
262
263   WriteBytesNotExpectingNotification(extension, next_data_size);
264 }
265
266 // Verify that thresholds for ephemeral apps are reset when they are
267 // promoted to regular installed apps.
268 IN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, EphemeralAppLowUsage) {
269   const Extension* extension = InitWriteDataEphemeralApp();
270   ASSERT_TRUE(extension);
271   WriteBytesExpectingNotification(extension, GetInitialEphemeralThreshold());
272
273   // Store the number of bytes until the next threshold is reached.
274   int64 next_threshold = GetNextStorageThreshold(extension->id());
275   int64 next_data_size = next_threshold - GetInitialEphemeralThreshold();
276   ASSERT_GT(next_data_size, 0);
277   EXPECT_GE(GetInitialExtensionThreshold(), next_threshold);
278
279   // Promote the ephemeral app.
280   ExtensionService* service =
281       ExtensionSystem::Get(profile())->extension_service();
282   service->PromoteEphemeralApp(extension, false);
283
284   // The next threshold should now be equal to the initial threshold for
285   // extensions (which is higher than the initial threshold for ephemeral apps).
286   EXPECT_EQ(GetInitialExtensionThreshold(),
287             GetNextStorageThreshold(extension->id()));
288
289   // Since the threshold was increased, a notification should not be
290   // triggered.
291   WriteBytesNotExpectingNotification(extension, next_data_size);
292 }
293
294 // Verify that thresholds for ephemeral apps are not reset when they are
295 // promoted to regular installed apps if their usage is higher than the initial
296 // threshold for installed extensions.
297 IN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, EphemeralAppWithHighUsage) {
298   const Extension* extension = InitWriteDataEphemeralApp();
299   ASSERT_TRUE(extension);
300   WriteBytesExpectingNotification(extension, GetInitialExtensionThreshold());
301   int64 saved_next_threshold = GetNextStorageThreshold(extension->id());
302
303   // Promote the ephemeral app.
304   ExtensionService* service =
305       ExtensionSystem::Get(profile())->extension_service();
306   service->PromoteEphemeralApp(extension, false);
307
308   // The next threshold should not have changed.
309   EXPECT_EQ(saved_next_threshold, GetNextStorageThreshold(extension->id()));
310 }
311
312 // Ensure that monitoring is disabled for installed extensions if
313 // |enable_for_all_extensions_| is false. This test can be removed if monitoring
314 // is eventually enabled for all extensions.
315 IN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest,
316                        DisableForInstalledExtensions) {
317   DisableForInstalledExtensions();
318
319   const Extension* extension = InitWriteDataApp();
320   ASSERT_TRUE(extension);
321   WriteBytesNotExpectingNotification(extension, GetInitialExtensionThreshold());
322 }
323
324 // Verify that notifications are disabled when the user clicks the action button
325 // in the notification.
326 IN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, UninstallExtension) {
327   const Extension* extension = InitWriteDataApp();
328   ASSERT_TRUE(extension);
329   WriteBytesExpectingNotification(extension, GetInitialExtensionThreshold());
330
331   // Fake clicking the notification button to uninstall.
332   message_center::MessageCenter::Get()->ClickOnNotificationButton(
333       GetNotificationId(extension->id()),
334       ExtensionStorageMonitor::BUTTON_UNINSTALL);
335
336   // Also fake accepting the uninstall.
337   TestExtensionRegistryObserver observer(ExtensionRegistry::Get(profile()),
338                                          extension->id());
339   SimulateUninstallDialogAccept();
340   observer.WaitForExtensionUninstalled();
341 }
342
343 }  // namespace extensions