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