Revert 285173 "Removed InProcessBrowserTest::CleanUpOnMainThread()"
[chromium-blink-merge.git] / chrome / browser / extensions / extension_storage_monitor_browsertest.cc
blobc71fa4ffbbc7f03d534c55854c09017d70f79937
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.
5 #include <set>
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/extensions/extension_test_message_listener.h"
13 #include "chrome/browser/ui/extensions/application_launch.h"
14 #include "content/public/test/test_utils.h"
15 #include "extensions/browser/extension_prefs.h"
16 #include "extensions/browser/extension_registry.h"
17 #include "extensions/browser/extension_system.h"
18 #include "extensions/browser/test_extension_registry_observer.h"
19 #include "ui/message_center/message_center.h"
20 #include "ui/message_center/message_center_observer.h"
22 namespace extensions {
24 namespace {
26 const int kInitialUsageThreshold = 500;
28 const char kWriteDataApp[] = "storage_monitor/write_data";
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);
39 virtual ~NotificationObserver() {
40 message_center_->RemoveObserver(this);
43 bool HasReceivedNotification() const {
44 return received_notifications_.find(target_notification_id_) !=
45 received_notifications_.end();
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;
54 waiting_ = true;
55 content::RunMessageLoop();
56 waiting_ = false;
57 return HasReceivedNotification();
60 private:
61 // MessageCenterObserver implementation:
62 virtual void OnNotificationAdded(
63 const std::string& notification_id) OVERRIDE {
64 received_notifications_.insert(notification_id);
66 if (waiting_ && HasReceivedNotification())
67 base::MessageLoopForUI::current()->Quit();
70 message_center::MessageCenter* message_center_;
71 std::set<std::string> received_notifications_;
72 std::string target_notification_id_;
73 bool waiting_;
76 } // namespace
78 class ExtensionStorageMonitorTest : public ExtensionBrowserTest {
79 public:
80 ExtensionStorageMonitorTest() : storage_monitor_(NULL) {}
82 protected:
83 // ExtensionBrowserTest overrides:
84 virtual void SetUpOnMainThread() OVERRIDE {
85 ExtensionBrowserTest::SetUpOnMainThread();
87 InitStorageMonitor();
90 ExtensionStorageMonitor* monitor() {
91 CHECK(storage_monitor_);
92 return storage_monitor_;
95 int64 GetInitialExtensionThreshold() {
96 CHECK(storage_monitor_);
97 return storage_monitor_->initial_extension_threshold_;
100 int64 GetInitialEphemeralThreshold() {
101 CHECK(storage_monitor_);
102 return storage_monitor_->initial_ephemeral_threshold_;
105 void DisableForInstalledExtensions() {
106 CHECK(storage_monitor_);
107 storage_monitor_->enable_for_all_extensions_ = false;
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;
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;
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;
130 std::string GetNotificationId(const std::string& extension_id) {
131 return monitor()->GetNotificationId(extension_id);
134 bool IsStorageNotificationEnabled(const std::string& extension_id) {
135 return monitor()->IsStorageNotificationEnabled(extension_id);
138 int64 GetNextStorageThreshold(const std::string& extension_id) {
139 return monitor()->GetNextStorageThreshold(extension_id);
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);
149 void WriteBytesNotExpectingNotification(const Extension* extension,
150 int num_bytes) {
151 WriteBytes(extension, num_bytes, false);
154 void SimulateUninstallDialogAccept() {
155 // Ensure the uninstall dialog was shown and fake an accept.
156 ASSERT_TRUE(monitor()->uninstall_dialog_.get());
157 monitor()->ExtensionUninstallAccepted();
160 private:
161 void InitStorageMonitor() {
162 storage_monitor_ = ExtensionStorageMonitor::Get(profile());
163 ASSERT_TRUE(storage_monitor_);
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;
171 // To ensure storage events are dispatched from QuotaManager immediately.
172 storage_monitor_->observer_rate_ = 0;
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()));
185 OpenApplication(AppLaunchParams(
186 profile(), extension, LAUNCH_CONTAINER_NONE, NEW_WINDOW));
187 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
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());
193 if (expected_notification) {
194 EXPECT_TRUE(notification_observer.WaitForNotification());
195 } else {
196 base::RunLoop().RunUntilIdle();
197 EXPECT_FALSE(notification_observer.HasReceivedNotification());
201 ExtensionStorageMonitor* storage_monitor_;
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);
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());
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);
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);
234 // Exceed the first threshold.
235 WriteBytesExpectingNotification(extension, GetInitialExtensionThreshold());
237 // Stay within the next threshold.
238 WriteBytesNotExpectingNotification(extension, 1);
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());
248 EXPECT_TRUE(IsStorageNotificationEnabled(extension->id()));
250 // Fake clicking the notification button to disable notifications.
251 message_center::MessageCenter::Get()->ClickOnNotificationButton(
252 GetNotificationId(extension->id()),
253 ExtensionStorageMonitor::BUTTON_DISABLE_NOTIFICATION);
255 EXPECT_FALSE(IsStorageNotificationEnabled(extension->id()));
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);
263 WriteBytesNotExpectingNotification(extension, next_data_size);
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());
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);
279 // Promote the ephemeral app.
280 ExtensionService* service =
281 ExtensionSystem::Get(profile())->extension_service();
282 service->PromoteEphemeralApp(extension, false);
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()));
289 // Since the threshold was increased, a notification should not be
290 // triggered.
291 WriteBytesNotExpectingNotification(extension, next_data_size);
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());
303 // Promote the ephemeral app.
304 ExtensionService* service =
305 ExtensionSystem::Get(profile())->extension_service();
306 service->PromoteEphemeralApp(extension, false);
308 // The next threshold should not have changed.
309 EXPECT_EQ(saved_next_threshold, GetNextStorageThreshold(extension->id()));
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();
319 const Extension* extension = InitWriteDataApp();
320 ASSERT_TRUE(extension);
321 WriteBytesNotExpectingNotification(extension, GetInitialExtensionThreshold());
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());
331 // Fake clicking the notification button to uninstall.
332 message_center::MessageCenter::Get()->ClickOnNotificationButton(
333 GetNotificationId(extension->id()),
334 ExtensionStorageMonitor::BUTTON_UNINSTALL);
336 // Also fake accepting the uninstall.
337 TestExtensionRegistryObserver observer(ExtensionRegistry::Get(profile()),
338 extension->id());
339 SimulateUninstallDialogAccept();
340 observer.WaitForExtensionUninstalled();
343 } // namespace extensions