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#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_STORAGE_MONITOR_H_
6#define CHROME_BROWSER_EXTENSIONS_EXTENSION_STORAGE_MONITOR_H_
7
8#include <set>
9
10#include "base/memory/ref_counted.h"
11#include "base/memory/weak_ptr.h"
12#include "base/scoped_observer.h"
13#include "chrome/browser/extensions/extension_uninstall_dialog.h"
14#include "components/keyed_service/core/keyed_service.h"
15#include "content/public/browser/notification_observer.h"
16#include "content/public/browser/notification_registrar.h"
17#include "extensions/browser/extension_registry_observer.h"
18
19namespace content {
20class BrowserContext;
21}
22
23namespace gfx {
24class Image;
25}
26
27namespace extensions {
28
29class Extension;
30class ExtensionPrefs;
31class ExtensionRegistry;
32class StorageEventObserver;
33
34// ExtensionStorageMonitor monitors the storage usage of extensions and apps
35// that are granted unlimited storage and displays notifications when high
36// usage is detected.
37class ExtensionStorageMonitor : public KeyedService,
38                                public content::NotificationObserver,
39                                public ExtensionRegistryObserver,
40                                public ExtensionUninstallDialog::Delegate {
41 public:
42  static ExtensionStorageMonitor* Get(content::BrowserContext* context);
43
44  // Indices of buttons in the notification. Exposed for testing.
45  enum ButtonIndex {
46    BUTTON_DISABLE_NOTIFICATION = 0,
47    BUTTON_UNINSTALL
48  };
49
50  explicit ExtensionStorageMonitor(content::BrowserContext* context);
51  virtual ~ExtensionStorageMonitor();
52
53 private:
54  // content::NotificationObserver overrides:
55  virtual void Observe(int type,
56                       const content::NotificationSource& source,
57                       const content::NotificationDetails& details) OVERRIDE;
58
59  // ExtensionRegistryObserver overrides:
60  virtual void OnExtensionLoaded(content::BrowserContext* browser_context,
61                                 const Extension* extension) OVERRIDE;
62  virtual void OnExtensionUnloaded(
63      content::BrowserContext* browser_context,
64      const Extension* extension,
65      UnloadedExtensionInfo::Reason reason) OVERRIDE;
66  virtual void OnExtensionWillBeInstalled(
67      content::BrowserContext* browser_context,
68      const Extension* extension,
69      bool is_update,
70      bool from_ephemeral,
71      const std::string& old_name) OVERRIDE;
72  virtual void OnExtensionUninstalled(
73      content::BrowserContext* browser_context,
74      const Extension* extension,
75      extensions::UninstallReason reason) OVERRIDE;
76
77  // Overridden from ExtensionUninstallDialog::Delegate:
78  virtual void ExtensionUninstallAccepted() OVERRIDE;
79  virtual void ExtensionUninstallCanceled() OVERRIDE;
80
81  std::string GetNotificationId(const std::string& extension_id);
82
83  void OnStorageThresholdExceeded(const std::string& extension_id,
84                                  int64 next_threshold,
85                                  int64 current_usage);
86  void OnImageLoaded(const std::string& extension_id,
87                     int64 current_usage,
88                     const gfx::Image& image);
89  void OnNotificationButtonClick(const std::string& extension_id,
90                                 int button_index);
91
92  void DisableStorageMonitoring(const std::string& extension_id);
93  void StartMonitoringStorage(const Extension* extension);
94  void StopMonitoringStorage(const std::string& extension_id);
95  void StopMonitoringAll();
96
97  void RemoveNotificationForExtension(const std::string& extension_id);
98  void RemoveAllNotifications();
99
100  // Displays the prompt for uninstalling the extension.
101  void ShowUninstallPrompt(const std::string& extension_id);
102
103  // Returns/sets the next threshold for displaying a notification if an
104  // extension or app consumes excessive disk space.
105  int64 GetNextStorageThreshold(const std::string& extension_id) const;
106  void SetNextStorageThreshold(const std::string& extension_id,
107                               int64 next_threshold);
108
109  // Returns the raw next storage threshold value stored in prefs. Returns 0 if
110  // the initial threshold has not yet been reached.
111  int64 GetNextStorageThresholdFromPrefs(const std::string& extension_id) const;
112
113  // Returns/sets whether notifications should be shown if an extension or app
114  // consumes too much disk space.
115  bool IsStorageNotificationEnabled(const std::string& extension_id) const;
116  void SetStorageNotificationEnabled(const std::string& extension_id,
117                                     bool enable_notifications);
118
119  // Initially, monitoring will only be applied to ephemeral apps. This flag
120  // is set by tests to enable for all extensions and apps.
121  bool enable_for_all_extensions_;
122
123  // The first notification is shown after the initial threshold is exceeded.
124  // Ephemeral apps have a lower threshold than fully installed extensions.
125  // A lower threshold is set by tests.
126  int64 initial_extension_threshold_;
127  int64 initial_ephemeral_threshold_;
128
129  // The rate (in seconds) at which we would like to receive storage updates
130  // from QuotaManager. Overridden in tests.
131  int observer_rate_;
132
133  // IDs of extensions that notifications were shown for.
134  std::set<std::string> notified_extension_ids_;
135
136  content::BrowserContext* context_;
137  extensions::ExtensionPrefs* extension_prefs_;
138
139  content::NotificationRegistrar registrar_;
140  ScopedObserver<extensions::ExtensionRegistry,
141                 extensions::ExtensionRegistryObserver>
142      extension_registry_observer_;
143
144  // StorageEventObserver monitors storage for extensions on the IO thread.
145  scoped_refptr<StorageEventObserver> storage_observer_;
146
147  // Modal dialog used to confirm removal of an extension.
148  scoped_ptr<ExtensionUninstallDialog> uninstall_dialog_;
149
150  // The ID of the extension that is the subject of the uninstall confirmation
151  // dialog.
152  std::string uninstall_extension_id_;
153
154  base::WeakPtrFactory<ExtensionStorageMonitor> weak_ptr_factory_;
155
156  friend class StorageEventObserver;
157  friend class ExtensionStorageMonitorTest;
158
159  DISALLOW_COPY_AND_ASSIGN(ExtensionStorageMonitor);
160};
161
162}  // namespace extensions
163
164#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_STORAGE_MONITOR_H_
165