1c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// found in the LICENSE file.
4c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
5c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include <set>
6c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
7c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/run_loop.h"
8c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/strings/string_number_conversions.h"
9c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/extensions/extension_browsertest.h"
1046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
11c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/extensions/extension_storage_monitor.h"
12c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/ui/extensions/application_launch.h"
13c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "content/public/test/test_utils.h"
14c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/browser/extension_prefs.h"
15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/browser/extension_registry.h"
1646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/browser/extension_system.h"
17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/browser/test_extension_registry_observer.h"
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/test/extension_test_message_listener.h"
19c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/message_center/message_center.h"
20c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/message_center/message_center_observer.h"
21c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
22c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnamespace extensions {
23c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
24c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnamespace {
25c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
26c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst int kInitialUsageThreshold = 500;
27c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
28c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst char kWriteDataApp[] = "storage_monitor/write_data";
29c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
30c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass NotificationObserver : public message_center::MessageCenterObserver {
31c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch public:
32c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  explicit NotificationObserver(const std::string& target_notification)
33c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      : message_center_(message_center::MessageCenter::Get()),
34c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        target_notification_id_(target_notification),
35c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        waiting_(false) {
36c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    message_center_->AddObserver(this);
37c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
38c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
39c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual ~NotificationObserver() {
40c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    message_center_->RemoveObserver(this);
41c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
42c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
43c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  bool HasReceivedNotification() const {
44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return received_notifications_.find(target_notification_id_) !=
45c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      received_notifications_.end();
46c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
47c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
48c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Runs the message loop and returns true if a notification is received.
49c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Immediately returns true if a notification has already been received.
50c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  bool WaitForNotification() {
51c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (HasReceivedNotification())
52c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return true;
53c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
54c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    waiting_ = true;
55c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    content::RunMessageLoop();
56c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    waiting_ = false;
57c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return HasReceivedNotification();
58c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
59c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
60c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch private:
61c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // MessageCenterObserver implementation:
62c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual void OnNotificationAdded(
63c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      const std::string& notification_id) OVERRIDE {
64c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    received_notifications_.insert(notification_id);
65c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
66c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (waiting_ && HasReceivedNotification())
67c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      base::MessageLoopForUI::current()->Quit();
68c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
69c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
70c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  message_center::MessageCenter* message_center_;
71c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  std::set<std::string> received_notifications_;
72c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  std::string target_notification_id_;
73c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  bool waiting_;
74c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch};
75c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
76c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}  // namespace
77c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
78c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass ExtensionStorageMonitorTest : public ExtensionBrowserTest {
7946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) public:
8046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ExtensionStorageMonitorTest() : storage_monitor_(NULL) {}
8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
82c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch protected:
8346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // ExtensionBrowserTest overrides:
8446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual void SetUpOnMainThread() OVERRIDE {
8546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    ExtensionBrowserTest::SetUpOnMainThread();
86c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
8746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    InitStorageMonitor();
8846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
89c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
9046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ExtensionStorageMonitor* monitor() {
9146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    CHECK(storage_monitor_);
9246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return storage_monitor_;
93c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
94c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
9546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  int64 GetInitialExtensionThreshold() {
9646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    CHECK(storage_monitor_);
9746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return storage_monitor_->initial_extension_threshold_;
9846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
9946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
10046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  int64 GetInitialEphemeralThreshold() {
10146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    CHECK(storage_monitor_);
10246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return storage_monitor_->initial_ephemeral_threshold_;
10346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
10446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
10546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  void DisableForInstalledExtensions() {
10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    CHECK(storage_monitor_);
10746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    storage_monitor_->enable_for_all_extensions_ = false;
10846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
109c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
11046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const Extension* InitWriteDataApp() {
111c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    base::FilePath path = test_data_dir_.AppendASCII(kWriteDataApp);
112c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const Extension* extension = InstallExtension(path, 1);
113c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    EXPECT_TRUE(extension);
114c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return extension;
115c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
116c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
11746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const Extension* InitWriteDataEphemeralApp() {
11846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // The threshold for installed extensions should be higher than ephemeral
11946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // apps.
12046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    storage_monitor_->initial_extension_threshold_ =
12146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        storage_monitor_->initial_ephemeral_threshold_ * 4;
12246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
12346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    base::FilePath path = test_data_dir_.AppendASCII(kWriteDataApp);
12446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const Extension* extension = InstallEphemeralAppWithSourceAndFlags(
12546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        path, 1, Manifest::INTERNAL, Extension::NO_FLAGS);
12646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    EXPECT_TRUE(extension);
12746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return extension;
12846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
12946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
130c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  std::string GetNotificationId(const std::string& extension_id) {
13146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return monitor()->GetNotificationId(extension_id);
13246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
13346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
13446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  bool IsStorageNotificationEnabled(const std::string& extension_id) {
13546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return monitor()->IsStorageNotificationEnabled(extension_id);
13646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
13746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
13846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  int64 GetNextStorageThreshold(const std::string& extension_id) {
13946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return monitor()->GetNextStorageThreshold(extension_id);
140c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
142c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void WriteBytesExpectingNotification(const Extension* extension,
143c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                       int num_bytes) {
14446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    int64 previous_threshold = GetNextStorageThreshold(extension->id());
145c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    WriteBytes(extension, num_bytes, true);
14646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    EXPECT_GT(GetNextStorageThreshold(extension->id()), previous_threshold);
147c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
148c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
149c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void WriteBytesNotExpectingNotification(const Extension* extension,
150c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                         int num_bytes) {
151c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    WriteBytes(extension, num_bytes, false);
152c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
153c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  void SimulateUninstallDialogAccept() {
15546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Ensure the uninstall dialog was shown and fake an accept.
15646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    ASSERT_TRUE(monitor()->uninstall_dialog_.get());
15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    monitor()->ExtensionUninstallAccepted();
15846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
15946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
16046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) private:
16146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  void InitStorageMonitor() {
16246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    storage_monitor_ = ExtensionStorageMonitor::Get(profile());
16346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    ASSERT_TRUE(storage_monitor_);
16446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
16546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Override thresholds so that we don't have to write a huge amount of data
16646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // to trigger notifications in these tests.
16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    storage_monitor_->enable_for_all_extensions_ = true;
16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    storage_monitor_->initial_extension_threshold_ = kInitialUsageThreshold;
16946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    storage_monitor_->initial_ephemeral_threshold_ = kInitialUsageThreshold;
17046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
17146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // To ensure storage events are dispatched from QuotaManager immediately.
17246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    storage_monitor_->observer_rate_ = 0;
17346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
17446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
175c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Write a number of bytes to persistent storage.
176c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void WriteBytes(const Extension* extension,
177c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                  int num_bytes,
178c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                  bool expected_notification) {
179c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ExtensionTestMessageListener launched_listener("launched", true);
180c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ExtensionTestMessageListener write_complete_listener(
181c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        "write_complete", false);
182c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    NotificationObserver notification_observer(
183c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        GetNotificationId(extension->id()));
184c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
185c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    OpenApplication(AppLaunchParams(
186c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        profile(), extension, LAUNCH_CONTAINER_NONE, NEW_WINDOW));
187c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
188c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
189c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // Instruct the app to write |num_bytes| of data.
190c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    launched_listener.Reply(base::IntToString(num_bytes));
191c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ASSERT_TRUE(write_complete_listener.WaitUntilSatisfied());
192c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
193c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (expected_notification) {
194c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      EXPECT_TRUE(notification_observer.WaitForNotification());
195c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    } else {
196c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      base::RunLoop().RunUntilIdle();
197c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      EXPECT_FALSE(notification_observer.HasReceivedNotification());
198c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
199c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
20046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
20146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ExtensionStorageMonitor* storage_monitor_;
202c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch};
203c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
204c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Control - No notifications should be shown if usage remains under the
205c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// threshold.
206c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochIN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, UnderThreshold) {
207c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const Extension* extension = InitWriteDataApp();
208c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ASSERT_TRUE(extension);
209c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  WriteBytesNotExpectingNotification(extension, 1);
210c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
211c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
212c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Ensure a notification is shown when usage reaches the first threshold.
213c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochIN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, ExceedInitialThreshold) {
214c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const Extension* extension = InitWriteDataApp();
215c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ASSERT_TRUE(extension);
21646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  WriteBytesExpectingNotification(extension, GetInitialExtensionThreshold());
217c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
218c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
219c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Ensure a notification is shown when usage immediately exceeds double the
220c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// first threshold.
221c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochIN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, DoubleInitialThreshold) {
222c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const Extension* extension = InitWriteDataApp();
223c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ASSERT_TRUE(extension);
22446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  WriteBytesExpectingNotification(extension,
22546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                  GetInitialExtensionThreshold() * 2);
226c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
227c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
228c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Ensure that notifications are not fired if the next threshold has not been
229c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// reached.
230c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochIN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, ThrottleNotifications) {
231c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const Extension* extension = InitWriteDataApp();
232c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ASSERT_TRUE(extension);
233c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
234c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Exceed the first threshold.
23546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  WriteBytesExpectingNotification(extension, GetInitialExtensionThreshold());
236c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
237c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Stay within the next threshold.
238c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  WriteBytesNotExpectingNotification(extension, 1);
239c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
240c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
241c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Verify that notifications are disabled when the user clicks the action button
242c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// in the notification.
243c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochIN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, UserDisabledNotifications) {
244c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const Extension* extension = InitWriteDataApp();
245c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ASSERT_TRUE(extension);
24646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  WriteBytesExpectingNotification(extension, GetInitialExtensionThreshold());
247c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
24846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  EXPECT_TRUE(IsStorageNotificationEnabled(extension->id()));
249c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
25046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Fake clicking the notification button to disable notifications.
251c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  message_center::MessageCenter::Get()->ClickOnNotificationButton(
252c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      GetNotificationId(extension->id()),
253c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      ExtensionStorageMonitor::BUTTON_DISABLE_NOTIFICATION);
254c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
25546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  EXPECT_FALSE(IsStorageNotificationEnabled(extension->id()));
256c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
257c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Expect to receive no further notifications when usage continues to
258c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // increase.
25946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  int64 next_threshold = GetNextStorageThreshold(extension->id());
26046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  int64 next_data_size = next_threshold - GetInitialExtensionThreshold();
26146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ASSERT_GT(next_data_size, 0);
262c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
263c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  WriteBytesNotExpectingNotification(extension, next_data_size);
264c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
265c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
26646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Verify that thresholds for ephemeral apps are reset when they are
26746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// promoted to regular installed apps.
26846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, EphemeralAppLowUsage) {
26946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const Extension* extension = InitWriteDataEphemeralApp();
27046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ASSERT_TRUE(extension);
27146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  WriteBytesExpectingNotification(extension, GetInitialEphemeralThreshold());
27246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
27346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Store the number of bytes until the next threshold is reached.
27446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  int64 next_threshold = GetNextStorageThreshold(extension->id());
27546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  int64 next_data_size = next_threshold - GetInitialEphemeralThreshold();
27646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ASSERT_GT(next_data_size, 0);
27746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  EXPECT_GE(GetInitialExtensionThreshold(), next_threshold);
27846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
27946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Promote the ephemeral app.
28046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ExtensionService* service =
28146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      ExtensionSystem::Get(profile())->extension_service();
28246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  service->PromoteEphemeralApp(extension, false);
28346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
28446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // The next threshold should now be equal to the initial threshold for
28546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // extensions (which is higher than the initial threshold for ephemeral apps).
28646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  EXPECT_EQ(GetInitialExtensionThreshold(),
28746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            GetNextStorageThreshold(extension->id()));
28846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
28946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Since the threshold was increased, a notification should not be
29046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // triggered.
29146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  WriteBytesNotExpectingNotification(extension, next_data_size);
29246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
29346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
29446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Verify that thresholds for ephemeral apps are not reset when they are
29546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// promoted to regular installed apps if their usage is higher than the initial
29646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// threshold for installed extensions.
29746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, EphemeralAppWithHighUsage) {
29846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const Extension* extension = InitWriteDataEphemeralApp();
29946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ASSERT_TRUE(extension);
30046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  WriteBytesExpectingNotification(extension, GetInitialExtensionThreshold());
30146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  int64 saved_next_threshold = GetNextStorageThreshold(extension->id());
30246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
30346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Promote the ephemeral app.
30446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ExtensionService* service =
30546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      ExtensionSystem::Get(profile())->extension_service();
30646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  service->PromoteEphemeralApp(extension, false);
30746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
30846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // The next threshold should not have changed.
30946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  EXPECT_EQ(saved_next_threshold, GetNextStorageThreshold(extension->id()));
31046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
31146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
31246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Ensure that monitoring is disabled for installed extensions if
31346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// |enable_for_all_extensions_| is false. This test can be removed if monitoring
31446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// is eventually enabled for all extensions.
31546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest,
31646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                       DisableForInstalledExtensions) {
31746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DisableForInstalledExtensions();
31846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
31946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const Extension* extension = InitWriteDataApp();
32046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ASSERT_TRUE(extension);
32146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  WriteBytesNotExpectingNotification(extension, GetInitialExtensionThreshold());
32246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
32346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
32446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Verify that notifications are disabled when the user clicks the action button
32546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// in the notification.
32646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, UninstallExtension) {
32746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const Extension* extension = InitWriteDataApp();
32846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ASSERT_TRUE(extension);
32946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  WriteBytesExpectingNotification(extension, GetInitialExtensionThreshold());
33046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
33146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Fake clicking the notification button to uninstall.
33246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  message_center::MessageCenter::Get()->ClickOnNotificationButton(
33346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      GetNotificationId(extension->id()),
33446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      ExtensionStorageMonitor::BUTTON_UNINSTALL);
33546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
33646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Also fake accepting the uninstall.
337116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  TestExtensionRegistryObserver observer(ExtensionRegistry::Get(profile()),
338116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         extension->id());
33946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  SimulateUninstallDialogAccept();
340116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  observer.WaitForExtensionUninstalled();
34146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
34246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
343c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}  // namespace extensions
344