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

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

Issue 11747025: Run the JSON Schema Compiler's bundle compilation on JSON files. Previously it (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix ms release build Created 7 years, 11 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/extensions/settings/settings_storage_quota_enforcer.h"
6
7 #include "base/bind.h"
8 #include "base/json/json_writer.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/message_loop.h"
11 #include "base/metrics/histogram.h"
12 #include "chrome/common/extensions/api/extension_api.h"
13 #include "extensions/common/error_utils.h"
14
15 namespace extensions {
16
17 namespace {
18
19 const char* kQuotaExceededError = "* quota exceeded.";
20
21 // Resources there are a quota for.
22 enum Resource {
23 QUOTA_BYTES,
24 QUOTA_BYTES_PER_ITEM,
25 MAX_ITEMS
26 };
27
28 // Allocates a setting in a record of total and per-setting usage.
29 void Allocate(
30 const std::string& key,
31 const Value& value,
32 size_t* used_total,
33 std::map<std::string, size_t>* used_per_setting) {
34 // Calculate the setting size based on its JSON serialization size.
35 // TODO(kalman): Does this work with different encodings?
36 // TODO(kalman): This is duplicating work that the leveldb delegate
37 // implementation is about to do, and it would be nice to avoid this.
38 std::string value_as_json;
39 base::JSONWriter::Write(&value, &value_as_json);
40 size_t new_size = key.size() + value_as_json.size();
41 size_t existing_size = (*used_per_setting)[key];
42
43 *used_total += (new_size - existing_size);
44 (*used_per_setting)[key] = new_size;
45 }
46
47 // Frees the allocation of a setting in a record of total and per-setting usage.
48 void Free(
49 size_t* used_total,
50 std::map<std::string, size_t>* used_per_setting,
51 const std::string& key) {
52 *used_total -= (*used_per_setting)[key];
53 used_per_setting->erase(key);
54 }
55
56 // Returns an error result and logs the quota exceeded to UMA.
57 ValueStore::WriteResult QuotaExceededFor(Resource resource) {
58 std::string name;
59 switch (resource) {
60 case QUOTA_BYTES:
61 name = "QUOTA_BYTES";
62 UMA_HISTOGRAM_COUNTS_100(
63 "Extensions.SettingsQuotaExceeded.TotalBytes", 1);
64 break;
65 case QUOTA_BYTES_PER_ITEM:
66 name = "QUOTA_BYTES_PER_ITEM";
67 UMA_HISTOGRAM_COUNTS_100(
68 "Extensions.SettingsQuotaExceeded.BytesPerSetting", 1);
69 break;
70 case MAX_ITEMS:
71 name = "MAX_ITEMS";
72 UMA_HISTOGRAM_COUNTS_100(
73 "Extensions.SettingsQuotaExceeded.KeyCount", 1);
74 break;
75 default:
76 NOTREACHED();
77 }
78 return ValueStore::MakeWriteResult(
79 ErrorUtils::FormatErrorMessage(kQuotaExceededError, name));
80 }
81
82 } // namespace
83
84 SettingsStorageQuotaEnforcer::SettingsStorageQuotaEnforcer(
85 const Limits& limits, ValueStore* delegate)
86 : limits_(limits), delegate_(delegate), used_total_(0) {
87 ReadResult maybe_settings = delegate_->Get();
88 if (maybe_settings->HasError()) {
89 LOG(WARNING) << "Failed to get initial settings for quota: " <<
90 maybe_settings->error();
91 return;
92 }
93
94 for (DictionaryValue::Iterator it(*maybe_settings->settings().get());
95 it.HasNext(); it.Advance()) {
96 Allocate(
97 it.key(), it.value(), &used_total_, &used_per_setting_);
98 }
99 }
100
101 SettingsStorageQuotaEnforcer::~SettingsStorageQuotaEnforcer() {}
102
103 size_t SettingsStorageQuotaEnforcer::GetBytesInUse(const std::string& key) {
104 std::map<std::string, size_t>::iterator maybe_used =
105 used_per_setting_.find(key);
106 return maybe_used == used_per_setting_.end() ? 0u : maybe_used->second;
107 }
108
109 size_t SettingsStorageQuotaEnforcer::GetBytesInUse(
110 const std::vector<std::string>& keys) {
111 size_t used = 0;
112 for (std::vector<std::string>::const_iterator it = keys.begin();
113 it != keys.end(); ++it) {
114 used += GetBytesInUse(*it);
115 }
116 return used;
117 }
118
119 size_t SettingsStorageQuotaEnforcer::GetBytesInUse() {
120 // All ValueStore implementations rely on GetBytesInUse being
121 // implemented here.
122 return used_total_;
123 }
124
125 ValueStore::ReadResult SettingsStorageQuotaEnforcer::Get(
126 const std::string& key) {
127 return delegate_->Get(key);
128 }
129
130 ValueStore::ReadResult SettingsStorageQuotaEnforcer::Get(
131 const std::vector<std::string>& keys) {
132 return delegate_->Get(keys);
133 }
134
135 ValueStore::ReadResult SettingsStorageQuotaEnforcer::Get() {
136 return delegate_->Get();
137 }
138
139 ValueStore::WriteResult SettingsStorageQuotaEnforcer::Set(
140 WriteOptions options, const std::string& key, const Value& value) {
141 size_t new_used_total = used_total_;
142 std::map<std::string, size_t> new_used_per_setting = used_per_setting_;
143 Allocate(key, value, &new_used_total, &new_used_per_setting);
144
145 if (!(options & IGNORE_QUOTA)) {
146 if (new_used_total > limits_.quota_bytes) {
147 return QuotaExceededFor(QUOTA_BYTES);
148 }
149 if (new_used_per_setting[key] > limits_.quota_bytes_per_item) {
150 return QuotaExceededFor(QUOTA_BYTES_PER_ITEM);
151 }
152 if (new_used_per_setting.size() > limits_.max_items) {
153 return QuotaExceededFor(MAX_ITEMS);
154 }
155 }
156
157 WriteResult result = delegate_->Set(options, key, value);
158 if (result->HasError()) {
159 return result.Pass();
160 }
161
162 used_total_ = new_used_total;
163 used_per_setting_.swap(new_used_per_setting);
164 return result.Pass();
165 }
166
167 ValueStore::WriteResult SettingsStorageQuotaEnforcer::Set(
168 WriteOptions options, const DictionaryValue& values) {
169 size_t new_used_total = used_total_;
170 std::map<std::string, size_t> new_used_per_setting = used_per_setting_;
171 for (DictionaryValue::Iterator it(values); it.HasNext(); it.Advance()) {
172 Allocate(it.key(), it.value(), &new_used_total, &new_used_per_setting);
173
174 if (!(options & IGNORE_QUOTA) &&
175 new_used_per_setting[it.key()] > limits_.quota_bytes_per_item) {
176 return QuotaExceededFor(QUOTA_BYTES_PER_ITEM);
177 }
178 }
179
180 if (!(options & IGNORE_QUOTA)) {
181 if (new_used_total > limits_.quota_bytes) {
182 return QuotaExceededFor(QUOTA_BYTES);
183 }
184 if (new_used_per_setting.size() > limits_.max_items) {
185 return QuotaExceededFor(MAX_ITEMS);
186 }
187 }
188
189 WriteResult result = delegate_->Set(options, values);
190 if (result->HasError()) {
191 return result.Pass();
192 }
193
194 used_total_ = new_used_total;
195 used_per_setting_ = new_used_per_setting;
196 return result.Pass();
197 }
198
199 ValueStore::WriteResult SettingsStorageQuotaEnforcer::Remove(
200 const std::string& key) {
201 WriteResult result = delegate_->Remove(key);
202 if (result->HasError()) {
203 return result.Pass();
204 }
205 Free(&used_total_, &used_per_setting_, key);
206 return result.Pass();
207 }
208
209 ValueStore::WriteResult SettingsStorageQuotaEnforcer::Remove(
210 const std::vector<std::string>& keys) {
211 WriteResult result = delegate_->Remove(keys);
212 if (result->HasError()) {
213 return result.Pass();
214 }
215
216 for (std::vector<std::string>::const_iterator it = keys.begin();
217 it != keys.end(); ++it) {
218 Free(&used_total_, &used_per_setting_, *it);
219 }
220 return result.Pass();
221 }
222
223 ValueStore::WriteResult SettingsStorageQuotaEnforcer::Clear() {
224 WriteResult result = delegate_->Clear();
225 if (result->HasError()) {
226 return result.Pass();
227 }
228
229 while (!used_per_setting_.empty()) {
230 Free(&used_total_, &used_per_setting_, used_per_setting_.begin()->first);
231 }
232 return result.Pass();
233 }
234
235 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698