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

Side by Side Diff: chrome/browser/extensions/extension_settings_storage_cache.cc

Issue 7189029: Implement an initial extension settings API. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Make clang happy Created 9 years, 4 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) 2011 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/extension_settings_storage_cache.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/message_loop.h"
11 #include "base/task.h"
12 #include "base/json/json_writer.h"
13
14 namespace {
15
16 void RemoveAll(DictionaryValue* from, const ListValue* keys_to_remove) {
17 std::string key;
18 for (ListValue::const_iterator it = keys_to_remove->begin();
19 it != keys_to_remove->end(); ++it) {
20 if ((*it)->GetAsString(&key)) {
21 from->Remove(key, NULL);
22 }
23 }
24 }
25
26 // Callback which delegates to a given callback but caches any result if
27 // successful. Takes an optional parameter of existing settings to merge with
28 // before returning to the callback (may be NULL) and an optional parameter of
29 // keys to remove from the cache post-success (may be NULL).
30 class CacheModifyingCallback : public ExtensionSettingsStorage::Callback {
31 public:
32 // Takes ownership of callback, existing, and keys_to_remove.
33 CacheModifyingCallback(
34 ExtensionSettingsStorage::Callback* delegate,
35 base::WeakPtr<DictionaryValue> cache,
36 DictionaryValue* existing,
37 ListValue* keys_to_remove)
38 : delegate_(delegate),
39 cache_(cache),
40 existing_(existing),
41 keys_to_remove_(keys_to_remove) {
42 }
43
44 static CacheModifyingCallback* Create(
45 ExtensionSettingsStorage::Callback* delegate,
46 base::WeakPtr<DictionaryValue> cache_ptr_) {
47 return new CacheModifyingCallback(
48 delegate,
49 cache_ptr_,
50 NULL,
51 NULL);
52 }
53
54 static CacheModifyingCallback* Create(
55 ExtensionSettingsStorage::Callback* delegate,
56 base::WeakPtr<DictionaryValue> cache_ptr_,
57 DictionaryValue* existing) {
58 return new CacheModifyingCallback(
59 delegate,
60 cache_ptr_,
61 existing,
62 NULL);
63 }
64
65 static CacheModifyingCallback* Create(
66 ExtensionSettingsStorage::Callback* delegate,
67 base::WeakPtr<DictionaryValue> cache_ptr_,
68 ListValue* remove) {
69 return new CacheModifyingCallback(
70 delegate,
71 cache_ptr_,
72 NULL,
73 remove);
74 }
75
76 virtual void OnSuccess(DictionaryValue* settings) OVERRIDE {
77 // Note checking that the weak reference to the cache is still valid.
78 // It might be NULL if the owning ExtensionSettingsStorageCache has been
79 // deleted.
80 // Also, settings may be NULL for Remove/Clear.
81 if (settings != NULL && cache_.get() != NULL) {
82 cache_->MergeDictionary(settings);
83 }
84 if (settings != NULL && existing_ != NULL) {
85 settings->MergeDictionary(existing_.get());
86 }
87 if (cache_.get() != NULL && keys_to_remove_ != NULL) {
88 RemoveAll(cache_, keys_to_remove_.get());
89 }
90 delegate_->OnSuccess(settings);
91 }
92
93 virtual void OnFailure(const std::string& message) OVERRIDE {
94 delegate_->OnFailure(message);
95 }
96
97 private:
98 scoped_ptr<ExtensionSettingsStorage::Callback> delegate_;
99 base::WeakPtr<DictionaryValue> cache_;
100 scoped_ptr<DictionaryValue> existing_;
101 scoped_ptr<ListValue> keys_to_remove_;
102 };
103
104 } // namespace
105
106 ExtensionSettingsStorageCache::ExtensionSettingsStorageCache(
107 ExtensionSettingsStorage* delegate)
108 : delegate_(delegate), cache_ptr_factory_(&cache_) {
109 }
110
111 ExtensionSettingsStorageCache::~ExtensionSettingsStorageCache() {
112 }
113
114 void ExtensionSettingsStorageCache::DeleteSoon() {
115 delegate_->DeleteSoon();
116 delete this;
117 }
118
119 void ExtensionSettingsStorageCache::Get(const std::string& key,
120 ExtensionSettingsStorageCache::Callback* callback) {
121 Value *value;
122 if (GetFromCache(key, &value)) {
123 DictionaryValue* settings = new DictionaryValue();
124 settings->Set(key, value);
125 MessageLoop::current()->PostTask(
126 FROM_HERE,
127 base::Bind(
128 &ExtensionSettingsStorageCache::Callback::OnSuccess,
129 base::Unretained(callback),
130 settings));
131 } else {
132 delegate_->Get(
133 key,
134 CacheModifyingCallback::Create(
135 callback,
136 cache_ptr_factory_.GetWeakPtr()));
137 }
138 }
139
140 void ExtensionSettingsStorageCache::Get(const ListValue& keys,
141 ExtensionSettingsStorageCache::Callback* callback) {
142 std::string key;
143 DictionaryValue* settings = new DictionaryValue();
144 ListValue missing_keys;
145
146 for (ListValue::const_iterator it = keys.begin(); it != keys.end(); ++it) {
147 if ((*it)->GetAsString(&key)) {
148 Value *value;
149 if (GetFromCache(key, &value)) {
150 settings->Set(key, value);
151 } else {
152 missing_keys.Append(Value::CreateStringValue(key));
153 }
154 }
155 }
156
157 if (missing_keys.empty()) {
158 MessageLoop::current()->PostTask(
159 FROM_HERE,
160 base::Bind(
161 &ExtensionSettingsStorageCache::Callback::OnSuccess,
162 base::Unretained(callback),
163 settings));
164 } else {
165 delegate_->Get(
166 missing_keys,
167 CacheModifyingCallback::Create(
168 callback,
169 cache_ptr_factory_.GetWeakPtr(),
170 settings));
171 }
172 }
173
174 void ExtensionSettingsStorageCache::Get(
175 ExtensionSettingsStorageCache::Callback* callback) {
176 // Copy the cache when passing in, as a semi-hack so that caching a no-op
177 // storage object works (which always returns empty from Get()).
178 delegate_->Get(
179 CacheModifyingCallback::Create(
180 callback,
181 cache_ptr_factory_.GetWeakPtr(),
182 cache_.DeepCopy()));
183 }
184
185 void ExtensionSettingsStorageCache::Set(
186 const std::string& key,
187 const Value& value,
188 ExtensionSettingsStorageCache::Callback* callback) {
189 // Invalidate the cached entry first, in case the set fails.
190 cache_.Remove(key, NULL);
191 delegate_->Set(
192 key,
193 value,
194 CacheModifyingCallback::Create(
195 callback,
196 cache_ptr_factory_.GetWeakPtr()));
197 }
198
199 void ExtensionSettingsStorageCache::Set(
200 const DictionaryValue& values,
201 ExtensionSettingsStorageCache::Callback* callback) {
202 // Invalidate the cached entries first, in case the set fails.
203 for (DictionaryValue::key_iterator it = values.begin_keys();
204 it != values.end_keys(); ++it) {
205 cache_.RemoveWithoutPathExpansion(*it, NULL);
206 }
207 delegate_->Set(
208 values,
209 CacheModifyingCallback::Create(
210 callback,
211 cache_ptr_factory_.GetWeakPtr()));
212 }
213
214 void ExtensionSettingsStorageCache::Remove(
215 const std::string& key,
216 ExtensionSettingsStorageCache::Callback *callback) {
217 // Invalidate the cached entry first, in case the remove fails.
218 // We will also need to do if after the callback, to avoid race conditions
219 // whether other API calls fill the cache on the UI thread.
220 // This would be a good time to use structured cloning...
221 cache_.Remove(key, NULL);
222 ListValue* key_list = new ListValue();
223 key_list->Append(Value::CreateStringValue(key));
224 delegate_->Remove(
225 key,
226 CacheModifyingCallback::Create(
227 callback,
228 cache_ptr_factory_.GetWeakPtr(),
229 key_list));
230 }
231
232 void ExtensionSettingsStorageCache::Remove(
233 const ListValue& keys,
234 ExtensionSettingsStorageCache::Callback *callback) {
235 std::string key;
236 // Invalidate each cached entry first, in case the remove fails.
237 // We will also need to do if after the callback, to avoid race conditions
238 // whether other API calls fill the cache on the UI thread.
239 RemoveAll(&cache_, &keys);
240 delegate_->Remove(
241 keys,
242 CacheModifyingCallback::Create(
243 callback,
244 cache_ptr_factory_.GetWeakPtr(),
245 keys.DeepCopy()));
246 }
247
248 void ExtensionSettingsStorageCache::Clear(
249 ExtensionSettingsStorageCache::Callback* callback) {
250 cache_.Clear();
251 delegate_->Clear(
252 CacheModifyingCallback::Create(
253 callback,
254 cache_ptr_factory_.GetWeakPtr()));
255 }
256
257 bool ExtensionSettingsStorageCache::GetFromCache(
258 const std::string& key, Value** value) {
259 Value* cached_value;
260 if (!cache_.Get(key, &cached_value)) {
261 return false;
262 }
263 *value = cached_value->DeepCopy();
264 return true;
265 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698