| 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 |