OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/extension_storage_monitor.h" | 5 #include "chrome/browser/extensions/extension_storage_monitor.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
(...skipping 28 matching lines...) Expand all Loading... |
39 using content::BrowserThread; | 39 using content::BrowserThread; |
40 | 40 |
41 namespace extensions { | 41 namespace extensions { |
42 | 42 |
43 namespace { | 43 namespace { |
44 | 44 |
45 // The rate at which we would like to observe storage events. | 45 // The rate at which we would like to observe storage events. |
46 const int kStorageEventRateSec = 30; | 46 const int kStorageEventRateSec = 30; |
47 | 47 |
48 // The storage type to monitor. | 48 // The storage type to monitor. |
49 const quota::StorageType kMonitorStorageType = quota::kStorageTypePersistent; | 49 const storage::StorageType kMonitorStorageType = |
| 50 storage::kStorageTypePersistent; |
50 | 51 |
51 // Set the thresholds for the first notification. Ephemeral apps have a lower | 52 // Set the thresholds for the first notification. Ephemeral apps have a lower |
52 // threshold than installed extensions and apps. Once a threshold is exceeded, | 53 // threshold than installed extensions and apps. Once a threshold is exceeded, |
53 // it will be doubled to throttle notifications. | 54 // it will be doubled to throttle notifications. |
54 const int64 kMBytes = 1024 * 1024; | 55 const int64 kMBytes = 1024 * 1024; |
55 const int64 kEphemeralAppInitialThreshold = 250 * kMBytes; | 56 const int64 kEphemeralAppInitialThreshold = 250 * kMBytes; |
56 const int64 kExtensionInitialThreshold = 1000 * kMBytes; | 57 const int64 kExtensionInitialThreshold = 1000 * kMBytes; |
57 | 58 |
58 // Notifications have an ID so that we can update them. | 59 // Notifications have an ID so that we can update them. |
59 const char kNotificationIdFormat[] = "ExtensionStorageMonitor-$1-$2"; | 60 const char kNotificationIdFormat[] = "ExtensionStorageMonitor-$1-$2"; |
(...skipping 21 matching lines...) Expand all Loading... |
81 return ExtensionRegistry::Get(context)->GetExtensionById( | 82 return ExtensionRegistry::Get(context)->GetExtensionById( |
82 extension_id, ExtensionRegistry::EVERYTHING); | 83 extension_id, ExtensionRegistry::EVERYTHING); |
83 } | 84 } |
84 | 85 |
85 } // namespace | 86 } // namespace |
86 | 87 |
87 // StorageEventObserver monitors the storage usage of extensions and lives on | 88 // StorageEventObserver monitors the storage usage of extensions and lives on |
88 // the IO thread. When a threshold is exceeded, a message will be posted to the | 89 // the IO thread. When a threshold is exceeded, a message will be posted to the |
89 // UI thread, which displays the notification. | 90 // UI thread, which displays the notification. |
90 class StorageEventObserver | 91 class StorageEventObserver |
91 : public base::RefCountedThreadSafe< | 92 : public base::RefCountedThreadSafe<StorageEventObserver, |
92 StorageEventObserver, | 93 BrowserThread::DeleteOnIOThread>, |
93 BrowserThread::DeleteOnIOThread>, | 94 public storage::StorageObserver { |
94 public quota::StorageObserver { | |
95 public: | 95 public: |
96 explicit StorageEventObserver( | 96 explicit StorageEventObserver( |
97 base::WeakPtr<ExtensionStorageMonitor> storage_monitor) | 97 base::WeakPtr<ExtensionStorageMonitor> storage_monitor) |
98 : storage_monitor_(storage_monitor) { | 98 : storage_monitor_(storage_monitor) { |
99 } | 99 } |
100 | 100 |
101 // Register as an observer for the extension's storage events. | 101 // Register as an observer for the extension's storage events. |
102 void StartObservingForExtension( | 102 void StartObservingForExtension( |
103 scoped_refptr<quota::QuotaManager> quota_manager, | 103 scoped_refptr<storage::QuotaManager> quota_manager, |
104 const std::string& extension_id, | 104 const std::string& extension_id, |
105 const GURL& site_url, | 105 const GURL& site_url, |
106 int64 next_threshold, | 106 int64 next_threshold, |
107 int rate) { | 107 int rate) { |
108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
109 DCHECK(quota_manager.get()); | 109 DCHECK(quota_manager.get()); |
110 | 110 |
111 GURL origin = site_url.GetOrigin(); | 111 GURL origin = site_url.GetOrigin(); |
112 StorageState& state = origin_state_map_[origin]; | 112 StorageState& state = origin_state_map_[origin]; |
113 state.quota_manager = quota_manager; | 113 state.quota_manager = quota_manager; |
114 state.extension_id = extension_id; | 114 state.extension_id = extension_id; |
115 state.next_threshold = next_threshold; | 115 state.next_threshold = next_threshold; |
116 | 116 |
117 quota::StorageObserver::MonitorParams params( | 117 storage::StorageObserver::MonitorParams params( |
118 kMonitorStorageType, | 118 kMonitorStorageType, origin, base::TimeDelta::FromSeconds(rate), false); |
119 origin, | |
120 base::TimeDelta::FromSeconds(rate), | |
121 false); | |
122 quota_manager->AddStorageObserver(this, params); | 119 quota_manager->AddStorageObserver(this, params); |
123 } | 120 } |
124 | 121 |
125 // Updates the threshold for an extension already being monitored. | 122 // Updates the threshold for an extension already being monitored. |
126 void UpdateThresholdForExtension(const std::string& extension_id, | 123 void UpdateThresholdForExtension(const std::string& extension_id, |
127 int64 next_threshold) { | 124 int64 next_threshold) { |
128 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 125 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
129 | 126 |
130 for (OriginStorageStateMap::iterator it = origin_state_map_.begin(); | 127 for (OriginStorageStateMap::iterator it = origin_state_map_.begin(); |
131 it != origin_state_map_.end(); | 128 it != origin_state_map_.end(); |
132 ++it) { | 129 ++it) { |
133 if (it->second.extension_id == extension_id) { | 130 if (it->second.extension_id == extension_id) { |
134 it->second.next_threshold = next_threshold; | 131 it->second.next_threshold = next_threshold; |
135 break; | 132 break; |
136 } | 133 } |
137 } | 134 } |
138 } | 135 } |
139 | 136 |
140 // Deregister as an observer for the extension's storage events. | 137 // Deregister as an observer for the extension's storage events. |
141 void StopObservingForExtension(const std::string& extension_id) { | 138 void StopObservingForExtension(const std::string& extension_id) { |
142 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
143 | 140 |
144 for (OriginStorageStateMap::iterator it = origin_state_map_.begin(); | 141 for (OriginStorageStateMap::iterator it = origin_state_map_.begin(); |
145 it != origin_state_map_.end(); ) { | 142 it != origin_state_map_.end(); ) { |
146 if (it->second.extension_id == extension_id) { | 143 if (it->second.extension_id == extension_id) { |
147 quota::StorageObserver::Filter filter(kMonitorStorageType, it->first); | 144 storage::StorageObserver::Filter filter(kMonitorStorageType, it->first); |
148 it->second.quota_manager->RemoveStorageObserverForFilter(this, filter); | 145 it->second.quota_manager->RemoveStorageObserverForFilter(this, filter); |
149 origin_state_map_.erase(it++); | 146 origin_state_map_.erase(it++); |
150 } else { | 147 } else { |
151 ++it; | 148 ++it; |
152 } | 149 } |
153 } | 150 } |
154 } | 151 } |
155 | 152 |
156 // Stop observing all storage events. Called during shutdown. | 153 // Stop observing all storage events. Called during shutdown. |
157 void StopObserving() { | 154 void StopObserving() { |
158 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 155 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
159 | 156 |
160 for (OriginStorageStateMap::iterator it = origin_state_map_.begin(); | 157 for (OriginStorageStateMap::iterator it = origin_state_map_.begin(); |
161 it != origin_state_map_.end(); ++it) { | 158 it != origin_state_map_.end(); ++it) { |
162 it->second.quota_manager->RemoveStorageObserver(this); | 159 it->second.quota_manager->RemoveStorageObserver(this); |
163 } | 160 } |
164 origin_state_map_.clear(); | 161 origin_state_map_.clear(); |
165 } | 162 } |
166 | 163 |
167 private: | 164 private: |
168 friend class base::DeleteHelper<StorageEventObserver>; | 165 friend class base::DeleteHelper<StorageEventObserver>; |
169 friend struct content::BrowserThread::DeleteOnThread< | 166 friend struct content::BrowserThread::DeleteOnThread< |
170 content::BrowserThread::IO>; | 167 content::BrowserThread::IO>; |
171 | 168 |
172 struct StorageState { | 169 struct StorageState { |
173 scoped_refptr<quota::QuotaManager> quota_manager; | 170 scoped_refptr<storage::QuotaManager> quota_manager; |
174 std::string extension_id; | 171 std::string extension_id; |
175 int64 next_threshold; | 172 int64 next_threshold; |
176 | 173 |
177 StorageState() : next_threshold(0) {} | 174 StorageState() : next_threshold(0) {} |
178 }; | 175 }; |
179 typedef std::map<GURL, StorageState> OriginStorageStateMap; | 176 typedef std::map<GURL, StorageState> OriginStorageStateMap; |
180 | 177 |
181 virtual ~StorageEventObserver() { | 178 virtual ~StorageEventObserver() { |
182 DCHECK(origin_state_map_.empty()); | 179 DCHECK(origin_state_map_.empty()); |
183 StopObserving(); | 180 StopObserving(); |
184 } | 181 } |
185 | 182 |
186 // quota::StorageObserver implementation. | 183 // storage::StorageObserver implementation. |
187 virtual void OnStorageEvent(const Event& event) OVERRIDE { | 184 virtual void OnStorageEvent(const Event& event) OVERRIDE { |
188 OriginStorageStateMap::iterator state = | 185 OriginStorageStateMap::iterator state = |
189 origin_state_map_.find(event.filter.origin); | 186 origin_state_map_.find(event.filter.origin); |
190 if (state == origin_state_map_.end()) | 187 if (state == origin_state_map_.end()) |
191 return; | 188 return; |
192 | 189 |
193 if (event.usage >= state->second.next_threshold) { | 190 if (event.usage >= state->second.next_threshold) { |
194 while (event.usage >= state->second.next_threshold) | 191 while (event.usage >= state->second.next_threshold) |
195 state->second.next_threshold *= 2; | 192 state->second.next_threshold *= 2; |
196 | 193 |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
464 if (!storage_observer_.get()) { | 461 if (!storage_observer_.get()) { |
465 storage_observer_ = | 462 storage_observer_ = |
466 new StorageEventObserver(weak_ptr_factory_.GetWeakPtr()); | 463 new StorageEventObserver(weak_ptr_factory_.GetWeakPtr()); |
467 } | 464 } |
468 | 465 |
469 GURL site_url = | 466 GURL site_url = |
470 extensions::util::GetSiteForExtensionId(extension->id(), context_); | 467 extensions::util::GetSiteForExtensionId(extension->id(), context_); |
471 content::StoragePartition* storage_partition = | 468 content::StoragePartition* storage_partition = |
472 content::BrowserContext::GetStoragePartitionForSite(context_, site_url); | 469 content::BrowserContext::GetStoragePartitionForSite(context_, site_url); |
473 DCHECK(storage_partition); | 470 DCHECK(storage_partition); |
474 scoped_refptr<quota::QuotaManager> quota_manager( | 471 scoped_refptr<storage::QuotaManager> quota_manager( |
475 storage_partition->GetQuotaManager()); | 472 storage_partition->GetQuotaManager()); |
476 | 473 |
477 GURL storage_origin(site_url.GetOrigin()); | 474 GURL storage_origin(site_url.GetOrigin()); |
478 if (extension->is_hosted_app()) | 475 if (extension->is_hosted_app()) |
479 storage_origin = AppLaunchInfo::GetLaunchWebURL(extension).GetOrigin(); | 476 storage_origin = AppLaunchInfo::GetLaunchWebURL(extension).GetOrigin(); |
480 | 477 |
481 BrowserThread::PostTask( | 478 BrowserThread::PostTask( |
482 BrowserThread::IO, | 479 BrowserThread::IO, |
483 FROM_HERE, | 480 FROM_HERE, |
484 base::Bind(&StorageEventObserver::StartObservingForExtension, | 481 base::Bind(&StorageEventObserver::StartObservingForExtension, |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
612 void ExtensionStorageMonitor::SetStorageNotificationEnabled( | 609 void ExtensionStorageMonitor::SetStorageNotificationEnabled( |
613 const std::string& extension_id, | 610 const std::string& extension_id, |
614 bool enable_notifications) { | 611 bool enable_notifications) { |
615 extension_prefs_->UpdateExtensionPref( | 612 extension_prefs_->UpdateExtensionPref( |
616 extension_id, | 613 extension_id, |
617 kPrefDisableStorageNotifications, | 614 kPrefDisableStorageNotifications, |
618 enable_notifications ? NULL : new base::FundamentalValue(true)); | 615 enable_notifications ? NULL : new base::FundamentalValue(true)); |
619 } | 616 } |
620 | 617 |
621 } // namespace extensions | 618 } // namespace extensions |
OLD | NEW |