Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(506)

Side by Side Diff: chrome/browser/extensions/settings/settings_storage_quota_enforcer.cc

Issue 9284013: Extension Storage API: expose storage quota information to extensions, via: (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: with use-after-free fixed Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/settings/settings_storage_quota_enforcer.h" 5 #include "chrome/browser/extensions/settings/settings_storage_quota_enforcer.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/json/json_writer.h" 8 #include "base/json/json_writer.h"
9 #include "base/memory/scoped_ptr.h" 9 #include "base/memory/scoped_ptr.h"
10 #include "base/message_loop.h" 10 #include "base/message_loop.h"
11 #include "base/metrics/histogram.h" 11 #include "base/metrics/histogram.h"
12 #include "chrome/common/extensions/api/extension_api.h"
12 13
13 namespace extensions { 14 namespace extensions {
14 15
15 namespace { 16 namespace {
16 17
17 const char* kExceededQuotaErrorMessage = "Quota exceeded"; 18 const char* kExceededQuotaErrorMessage = "Quota exceeded";
18 19
19 // Resources there are a quota for. 20 // Resources there are a quota for.
20 enum Resource { 21 enum Resource {
21 TOTAL_BYTES, 22 QUOTA_BYTES,
22 BYTES_PER_SETTING, 23 QUOTA_BYTES_PER_ITEM,
23 KEY_COUNT 24 MAX_ITEMS
24 }; 25 };
25 26
26 // Allocates a setting in a record of total and per-setting usage. 27 // Allocates a setting in a record of total and per-setting usage.
27 void Allocate( 28 void Allocate(
28 const std::string& key, 29 const std::string& key,
29 const Value& value, 30 const Value& value,
30 size_t* used_total, 31 size_t* used_total,
31 std::map<std::string, size_t>* used_per_setting) { 32 std::map<std::string, size_t>* used_per_setting) {
32 // Calculate the setting size based on its JSON serialization size. 33 // Calculate the setting size based on its JSON serialization size.
33 // TODO(kalman): Does this work with different encodings? 34 // TODO(kalman): Does this work with different encodings?
(...skipping 13 matching lines...) Expand all
47 size_t* used_total, 48 size_t* used_total,
48 std::map<std::string, size_t>* used_per_setting, 49 std::map<std::string, size_t>* used_per_setting,
49 const std::string& key) { 50 const std::string& key) {
50 *used_total -= (*used_per_setting)[key]; 51 *used_total -= (*used_per_setting)[key];
51 used_per_setting->erase(key); 52 used_per_setting->erase(key);
52 } 53 }
53 54
54 // Returns an error result and logs the quota exceeded to UMA. 55 // Returns an error result and logs the quota exceeded to UMA.
55 SettingsStorage::WriteResult QuotaExceededFor(Resource resource) { 56 SettingsStorage::WriteResult QuotaExceededFor(Resource resource) {
56 switch (resource) { 57 switch (resource) {
57 case TOTAL_BYTES: 58 case QUOTA_BYTES:
58 UMA_HISTOGRAM_COUNTS_100( 59 UMA_HISTOGRAM_COUNTS_100(
59 "Extensions.SettingsQuotaExceeded.TotalBytes", 1); 60 "Extensions.SettingsQuotaExceeded.TotalBytes", 1);
60 break; 61 break;
61 case BYTES_PER_SETTING: 62 case QUOTA_BYTES_PER_ITEM:
62 UMA_HISTOGRAM_COUNTS_100( 63 UMA_HISTOGRAM_COUNTS_100(
63 "Extensions.SettingsQuotaExceeded.BytesPerSetting", 1); 64 "Extensions.SettingsQuotaExceeded.BytesPerSetting", 1);
64 break; 65 break;
65 case KEY_COUNT: 66 case MAX_ITEMS:
66 UMA_HISTOGRAM_COUNTS_100( 67 UMA_HISTOGRAM_COUNTS_100(
67 "Extensions.SettingsQuotaExceeded.KeyCount", 1); 68 "Extensions.SettingsQuotaExceeded.KeyCount", 1);
68 break; 69 break;
69 default: 70 default:
70 NOTREACHED(); 71 NOTREACHED();
71 } 72 }
72 return SettingsStorage::WriteResult(kExceededQuotaErrorMessage); 73 return SettingsStorage::WriteResult(kExceededQuotaErrorMessage);
73 } 74 }
74 75
75 } // namespace 76 } // namespace
(...skipping 10 matching lines...) Expand all
86 87
87 for (DictionaryValue::Iterator it(maybe_settings.settings()); it.HasNext(); 88 for (DictionaryValue::Iterator it(maybe_settings.settings()); it.HasNext();
88 it.Advance()) { 89 it.Advance()) {
89 Allocate( 90 Allocate(
90 it.key(), it.value(), &used_total_, &used_per_setting_); 91 it.key(), it.value(), &used_total_, &used_per_setting_);
91 } 92 }
92 } 93 }
93 94
94 SettingsStorageQuotaEnforcer::~SettingsStorageQuotaEnforcer() {} 95 SettingsStorageQuotaEnforcer::~SettingsStorageQuotaEnforcer() {}
95 96
97 size_t SettingsStorageQuotaEnforcer::GetBytesInUse(const std::string& key) {
98 std::map<std::string, size_t>::iterator maybe_used =
99 used_per_setting_.find(key);
100 return maybe_used == used_per_setting_.end() ? 0u : maybe_used->second;
101 }
102
103 size_t SettingsStorageQuotaEnforcer::GetBytesInUse(
104 const std::vector<std::string>& keys) {
105 size_t used = 0;
106 for (std::vector<std::string>::const_iterator it = keys.begin();
107 it != keys.end(); ++it) {
108 used += GetBytesInUse(*it);
109 }
110 return used;
111 }
112
113 size_t SettingsStorageQuotaEnforcer::GetBytesInUse() {
114 // All SettingsStorage implementations rely on GetBytesInUse being
115 // implemented here.
116 return used_total_;
117 }
118
96 SettingsStorage::ReadResult SettingsStorageQuotaEnforcer::Get( 119 SettingsStorage::ReadResult SettingsStorageQuotaEnforcer::Get(
97 const std::string& key) { 120 const std::string& key) {
98 return delegate_->Get(key); 121 return delegate_->Get(key);
99 } 122 }
100 123
101 SettingsStorage::ReadResult SettingsStorageQuotaEnforcer::Get( 124 SettingsStorage::ReadResult SettingsStorageQuotaEnforcer::Get(
102 const std::vector<std::string>& keys) { 125 const std::vector<std::string>& keys) {
103 return delegate_->Get(keys); 126 return delegate_->Get(keys);
104 } 127 }
105 128
106 SettingsStorage::ReadResult SettingsStorageQuotaEnforcer::Get() { 129 SettingsStorage::ReadResult SettingsStorageQuotaEnforcer::Get() {
107 return delegate_->Get(); 130 return delegate_->Get();
108 } 131 }
109 132
110 SettingsStorage::WriteResult SettingsStorageQuotaEnforcer::Set( 133 SettingsStorage::WriteResult SettingsStorageQuotaEnforcer::Set(
111 WriteOptions options, const std::string& key, const Value& value) { 134 WriteOptions options, const std::string& key, const Value& value) {
112 size_t new_used_total = used_total_; 135 size_t new_used_total = used_total_;
113 std::map<std::string, size_t> new_used_per_setting = used_per_setting_; 136 std::map<std::string, size_t> new_used_per_setting = used_per_setting_;
114 Allocate(key, value, &new_used_total, &new_used_per_setting); 137 Allocate(key, value, &new_used_total, &new_used_per_setting);
115 138
116 if (options != IGNORE_QUOTA) { 139 if (options != IGNORE_QUOTA) {
117 if (new_used_total > limits_.quota_bytes) { 140 if (new_used_total > limits_.quota_bytes) {
118 return QuotaExceededFor(TOTAL_BYTES); 141 return QuotaExceededFor(QUOTA_BYTES);
119 } 142 }
120 if (new_used_per_setting[key] > limits_.quota_bytes_per_setting) { 143 if (new_used_per_setting[key] > limits_.quota_bytes_per_item) {
121 return QuotaExceededFor(BYTES_PER_SETTING); 144 return QuotaExceededFor(QUOTA_BYTES_PER_ITEM);
122 } 145 }
123 if (new_used_per_setting.size() > limits_.max_keys) { 146 if (new_used_per_setting.size() > limits_.max_items) {
124 return QuotaExceededFor(KEY_COUNT); 147 return QuotaExceededFor(MAX_ITEMS);
125 } 148 }
126 } 149 }
127 150
128 WriteResult result = delegate_->Set(options, key, value); 151 WriteResult result = delegate_->Set(options, key, value);
129 if (result.HasError()) { 152 if (result.HasError()) {
130 return result; 153 return result;
131 } 154 }
132 155
133 used_total_ = new_used_total; 156 used_total_ = new_used_total;
134 used_per_setting_.swap(new_used_per_setting); 157 used_per_setting_.swap(new_used_per_setting);
135 return result; 158 return result;
136 } 159 }
137 160
138 SettingsStorage::WriteResult SettingsStorageQuotaEnforcer::Set( 161 SettingsStorage::WriteResult SettingsStorageQuotaEnforcer::Set(
139 WriteOptions options, const DictionaryValue& values) { 162 WriteOptions options, const DictionaryValue& values) {
140 size_t new_used_total = used_total_; 163 size_t new_used_total = used_total_;
141 std::map<std::string, size_t> new_used_per_setting = used_per_setting_; 164 std::map<std::string, size_t> new_used_per_setting = used_per_setting_;
142 for (DictionaryValue::Iterator it(values); it.HasNext(); it.Advance()) { 165 for (DictionaryValue::Iterator it(values); it.HasNext(); it.Advance()) {
143 Allocate(it.key(), it.value(), &new_used_total, &new_used_per_setting); 166 Allocate(it.key(), it.value(), &new_used_total, &new_used_per_setting);
144 167
145 if (options != IGNORE_QUOTA && 168 if (options != IGNORE_QUOTA &&
146 new_used_per_setting[it.key()] > limits_.quota_bytes_per_setting) { 169 new_used_per_setting[it.key()] > limits_.quota_bytes_per_item) {
147 return QuotaExceededFor(BYTES_PER_SETTING); 170 return QuotaExceededFor(QUOTA_BYTES_PER_ITEM);
148 } 171 }
149 } 172 }
150 173
151 if (options != IGNORE_QUOTA) { 174 if (options != IGNORE_QUOTA) {
152 if (new_used_total > limits_.quota_bytes) { 175 if (new_used_total > limits_.quota_bytes) {
153 return QuotaExceededFor(TOTAL_BYTES); 176 return QuotaExceededFor(QUOTA_BYTES);
154 } 177 }
155 if (new_used_per_setting.size() > limits_.max_keys) { 178 if (new_used_per_setting.size() > limits_.max_items) {
156 return QuotaExceededFor(KEY_COUNT); 179 return QuotaExceededFor(MAX_ITEMS);
157 } 180 }
158 } 181 }
159 182
160 WriteResult result = delegate_->Set(options, values); 183 WriteResult result = delegate_->Set(options, values);
161 if (result.HasError()) { 184 if (result.HasError()) {
162 return result; 185 return result;
163 } 186 }
164 187
165 used_total_ = new_used_total; 188 used_total_ = new_used_total;
166 used_per_setting_ = new_used_per_setting; 189 used_per_setting_ = new_used_per_setting;
(...skipping 30 matching lines...) Expand all
197 return result; 220 return result;
198 } 221 }
199 222
200 while (!used_per_setting_.empty()) { 223 while (!used_per_setting_.empty()) {
201 Free(&used_total_, &used_per_setting_, used_per_setting_.begin()->first); 224 Free(&used_total_, &used_per_setting_, used_per_setting_.begin()->first);
202 } 225 }
203 return result; 226 return result;
204 } 227 }
205 228
206 } // namespace extensions 229 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698