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

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

Issue 7775008: Enable sync for the settings from the Extension Settings API. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Reordering Created 9 years, 3 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/syncable_extension_settings_storage.h"
6
7 #include "base/bind.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop.h"
10 #include "base/task.h"
11 #include "chrome/browser/extensions/extension_settings_sync_helper.h"
12 #include "chrome/browser/sync/api/sync_data.h"
13 #include "chrome/browser/sync/protocol/extension_setting_specifics.pb.h"
14
15 SyncableExtensionSettingsStorage::SyncDeps::SyncDeps(
16 SyncChangeProcessor* processor) : processor_(processor) {
17 DCHECK(processor != NULL);
18 }
19
20 SyncableExtensionSettingsStorage::SyncDeps::~SyncDeps() {
21 }
22
23 SyncableExtensionSettingsStorage::SyncableExtensionSettingsStorage(
24 std::string extension_id, ExtensionSettingsStorage* delegate)
25 : extension_id_(extension_id), delegate_(delegate), sync_deps_(NULL) {}
26
27 SyncableExtensionSettingsStorage::~SyncableExtensionSettingsStorage() {}
28
29 void SyncableExtensionSettingsStorage::Get(
30 const std::string& key, ExtensionSettingsStorage::Callback* callback) {
31 delegate_->Get(key, callback);
32 }
33
34 void SyncableExtensionSettingsStorage::Get(
35 const ListValue& keys, ExtensionSettingsStorage::Callback* callback) {
36 delegate_->Get(keys, callback);
37 }
38
39 void SyncableExtensionSettingsStorage::Get(
40 ExtensionSettingsStorage::Callback* callback) {
41 delegate_->Get(callback);
42 }
43
44 namespace {
45
46 class SendAddsOrUpdatesToSyncCallback
47 : public ExtensionSettingsStorage::Callback {
48 public:
49 SendAddsOrUpdatesToSyncCallback(
50 Callback* delegate,
51 const std::string& extension_id,
52 base::WeakPtr<SyncableExtensionSettingsStorage::SyncDeps> sync_deps)
53 : delegate_(delegate),
54 extension_id_(extension_id),
55 sync_deps_(sync_deps) {}
56
57 void OnSuccess(DictionaryValue* settings) OVERRIDE {
58 if (!sync_deps_) {
59 delegate_->OnSuccess(settings);
60 return;
61 }
62
63 SyncChangeList sync_changes;
64 for (DictionaryValue::key_iterator it = settings->begin_keys();
65 it != settings->end_keys(); ++it) {
66 Value* value;
67 settings->GetWithoutPathExpansion(*it, &value);
68 if (sync_deps_->keys()->count(*it)) {
69 // Key is synced, send ACTION_UPDATE to sync.
70 sync_changes.push_back(ExtensionSettingsSyncHelper::CreateUpdate(
71 extension_id_, *it, *value));
72 } else {
73 // Key is not synced, send ACTION_ADD to sync.
74 sync_changes.push_back(ExtensionSettingsSyncHelper::CreateAdd(
75 extension_id_, *it, *value));
76 }
77 }
78
79 if (sync_changes.empty()) {
80 delegate_->OnSuccess(settings);
81 return;
82 }
83
84 SyncError error =
85 sync_deps_->processor()->ProcessSyncChanges(FROM_HERE, sync_changes);
86 if (error.IsSet()) {
87 LOG(WARNING) << "Failed to send changes to sync: " << error.message();
88 } else {
89 // Sync was successful, record those keys as synced.
90 sync_deps_->keys()->insert(settings->begin_keys(), settings->end_keys());
91 }
92
93 delegate_->OnSuccess(settings);
94 }
95
96 void OnFailure(const std::string& error) {
97 LOG(WARNING) << "Settings operation failed, not sending to sync: " << error;
98 delegate_->OnFailure(error);
99 }
100
101 private:
102 scoped_ptr<Callback> delegate_;
103 std::string extension_id_;
104 base::WeakPtr<SyncableExtensionSettingsStorage::SyncDeps> sync_deps_;
105 };
106
107 } // namespace
108
109 void SyncableExtensionSettingsStorage::Set(
110 const std::string& key,
111 const Value& value,
112 ExtensionSettingsStorage::Callback* callback) {
113 if (sync_deps_ != NULL) {
114 callback = new SendAddsOrUpdatesToSyncCallback(
115 callback, extension_id_, sync_deps_->AsWeakPtr());
116 }
117 delegate_->Set(key, value, callback);
118 }
119
120 void SyncableExtensionSettingsStorage::Set(
121 const DictionaryValue& values,
122 ExtensionSettingsStorage::Callback* callback) {
123 if (sync_deps_ != NULL) {
124 callback = new SendAddsOrUpdatesToSyncCallback(
125 callback, extension_id_, sync_deps_->AsWeakPtr());
126 }
127 delegate_->Set(values, callback);
128 }
129
130 namespace {
131
132 class SendDeletesToSyncCallback : public ExtensionSettingsStorage::Callback {
133 public:
134 SendDeletesToSyncCallback(
135 // Ownership is taken.
136 Callback* delegate,
137 const std::string& extension_id,
138 // Ownership is taken.
139 std::set<std::string>* keys_to_remove,
140 base::WeakPtr<SyncableExtensionSettingsStorage::SyncDeps> sync_deps)
141 : delegate_(delegate),
142 extension_id_(extension_id),
143 keys_to_remove_(keys_to_remove),
144 sync_deps_(sync_deps) {
145 DCHECK(!keys_to_remove->empty());
146 }
147
148 void OnSuccess(DictionaryValue* settings) OVERRIDE {
149 DCHECK(settings == NULL);
150 if (!sync_deps_) {
151 delegate_->OnSuccess(settings);
152 return;
153 }
154
155 SyncChangeList sync_changes;
156 for (std::set<std::string>::iterator it = keys_to_remove_->begin();
157 it != keys_to_remove_->end(); ++it) {
158 // Only remove from sync if it's actually synced.
159 if (sync_deps_->keys()->count(*it)) {
160 sync_changes.push_back(
161 ExtensionSettingsSyncHelper::CreateDelete(extension_id_, *it));
162 }
163 }
164
165 if (sync_changes.empty()) {
166 delegate_->OnSuccess(settings);
167 return;
168 }
169
170 SyncError error =
171 sync_deps_->processor()->ProcessSyncChanges(FROM_HERE, sync_changes);
172 if (error.IsSet()) {
173 LOG(WARNING) << "Failed to send changes to sync: " << error.message();
174 } else {
175 // Sync was successful, record those keys as deleted from sync.
176 for (std::set<std::string>::iterator it = keys_to_remove_->begin();
177 it != keys_to_remove_->end(); ++it) {
178 sync_deps_->keys()->erase(*it);
179 }
180 }
181
182 delegate_->OnSuccess(settings);
183 }
184
185 void OnFailure(const std::string& error) {
186 LOG(WARNING) << "Settings operation failed, not sending to sync: " << error;
187 delegate_->OnFailure(error);
188 }
189
190 private:
191 scoped_ptr<Callback> delegate_;
192 std::string extension_id_;
193 scoped_ptr<std::set<std::string> > keys_to_remove_;
194 base::WeakPtr<SyncableExtensionSettingsStorage::SyncDeps> sync_deps_;
195 };
196
197 } // namespace
198
199 void SyncableExtensionSettingsStorage::Remove(
200 const std::string& key, ExtensionSettingsStorage::Callback* callback) {
201 if (sync_deps_ != NULL) {
202 std::set<std::string>* keys_to_remove = new std::set<std::string>();
203 keys_to_remove->insert(key);
204 callback = new SendDeletesToSyncCallback(
205 callback,
206 extension_id_,
207 keys_to_remove,
208 sync_deps_->AsWeakPtr());
209 }
210 delegate_->Remove(key, callback);
211 }
212
213 void SyncableExtensionSettingsStorage::Remove(
214 const ListValue& keys, ExtensionSettingsStorage::Callback* callback) {
215 if (sync_deps_ != NULL) {
216 std::set<std::string>* keys_to_remove = new std::set<std::string>();
217 std::string key_to_remove;
218 for (ListValue::const_iterator it = keys.begin(); it != keys.end(); ++it) {
219 if ((*it)->GetAsString(&key_to_remove)) {
220 keys_to_remove->insert(key_to_remove);
221 }
222 }
223 callback = new SendDeletesToSyncCallback(
224 callback,
225 extension_id_,
226 keys_to_remove,
227 sync_deps_->AsWeakPtr());
228 }
229 delegate_->Remove(keys, callback);
230 }
231
232 void SyncableExtensionSettingsStorage::Clear(
233 ExtensionSettingsStorage::Callback* callback) {
234 if (sync_deps_ != NULL) {
235 callback = new SendDeletesToSyncCallback(
236 callback,
237 extension_id_,
238 // Remove all the synced keys.
239 new std::set<std::string>(*sync_deps_->keys()),
240 sync_deps_->AsWeakPtr());
241 }
242 delegate_->Clear(callback);
243 }
244
245 void SyncableExtensionSettingsStorage::DeleteSoon() {
246 delegate_->DeleteSoon();
247 delete this;
248 }
249
250 // Sync-related methods.
251
252 namespace {
253
254 class SendAllLocalSettingsToSyncCallback
255 : public ExtensionSettingsStorage::Callback {
256 public:
257 SendAllLocalSettingsToSyncCallback(
258 const std::string& extension_id,
259 base::WeakPtr<SyncableExtensionSettingsStorage::SyncDeps> sync_deps)
260 : extension_id_(extension_id), sync_deps_(sync_deps) {}
261
262 virtual void OnSuccess(DictionaryValue* settings) OVERRIDE {
263 scoped_ptr<DictionaryValue> settings_ownership(settings);
264 if (!sync_deps_) {
265 return;
266 }
267
268 SyncChangeList sync_changes;
269 for (DictionaryValue::key_iterator it = settings->begin_keys();
270 it != settings->end_keys(); ++it) {
271 Value* value;
272 settings->GetWithoutPathExpansion(*it, &value);
273 sync_changes.push_back(ExtensionSettingsSyncHelper::CreateAdd(
274 extension_id_, *it, *value));
275 }
276
277 if (sync_changes.empty()) {
278 return;
279 }
280
281 SyncError error =
282 sync_deps_->processor()->ProcessSyncChanges(FROM_HERE, sync_changes);
283 if (error.IsSet()) {
284 LOG(WARNING) << "Failed to send changes to sync: " << error.message();
285 } else {
286 // Sync was successful, record those keys as synced.
287 sync_deps_->keys()->insert(settings->begin_keys(), settings->end_keys());
288 }
289 }
290
291 virtual void OnFailure(const std::string& error) OVERRIDE {
292 LOG(WARNING) << "Settings operation failed, not sending to sync: " << error;
293 }
294
295 private:
296 std::string extension_id_;
297 base::WeakPtr<SyncableExtensionSettingsStorage::SyncDeps> sync_deps_;
298 };
299
300 class OverwriteLocalSettingsFromSyncCallback
301 : public ExtensionSettingsStorage::Callback {
302 public:
303 OverwriteLocalSettingsFromSyncCallback(
304 base::WeakPtr<SyncableExtensionSettingsStorage> storage,
305 // Ownership taken.
306 DictionaryValue* sync_state)
307 : storage_(storage), sync_state_(sync_state) {}
308
309 virtual void OnSuccess(DictionaryValue* local_state) {
310 scoped_ptr<DictionaryValue> local_state_ownership(local_state);
311 if (!storage_) {
312 return;
313 }
314
315 // Pretend they're sync changes to process, because they are.
316 ExtensionSettingSyncDataList sync_changes;
317 for (DictionaryValue::key_iterator it = local_state->begin_keys();
318 it != local_state->end_keys(); ++it) {
319 Value* sync_value;
320 if (sync_state_->RemoveWithoutPathExpansion(*it, &sync_value)) {
321 Value* local_value;
322 local_state->GetWithoutPathExpansion(*it, &local_value);
323 if (!local_value->Equals(sync_value)) {
324 // Sync value is different, update locally with new value.
325 sync_changes.push_back(ExtensionSettingSyncData(
326 SyncChange::ACTION_UPDATE, "", *it, sync_value));
327 }
328 } else {
329 // No sync value, delete locally.
330 sync_changes.push_back(ExtensionSettingSyncData(
331 SyncChange::ACTION_DELETE, "", *it, new DictionaryValue()));
332 }
333 }
334
335 for (DictionaryValue::key_iterator it = sync_state_->begin_keys();
336 it != sync_state_->end_keys(); ++it) {
337 Value* sync_value;
338 // Missing local value for synced setting, add locally.
339 // If it's safe to RemoveWithoutPathExpansion the DeepCopy would be
340 // unnecessary.
341 sync_state_->GetWithoutPathExpansion(*it, &sync_value);
342 sync_changes.push_back(ExtensionSettingSyncData(
343 SyncChange::ACTION_ADD, "", *it, sync_value->DeepCopy()));
344 }
345
346 if (!sync_changes.empty()) {
347 storage_->ProcessSyncChanges(sync_changes);
348 }
349 }
350
351 virtual void OnFailure(const std::string& error) {
352 LOG(WARNING) <<
353 "Settings operation failed, local state not in sync: " << error;
354 }
355
356 private:
357 base::WeakPtr<SyncableExtensionSettingsStorage> storage_;
358 scoped_ptr<DictionaryValue> sync_state_;
359 };
360
361 } // namespace
362
363 void SyncableExtensionSettingsStorage::StartSyncing(
364 const DictionaryValue& sync_state, SyncChangeProcessor* sync_processor) {
365 DCHECK(sync_deps_ == NULL);
366 sync_deps_ = new SyncDeps(sync_processor);
367 sync_deps_->keys()->insert(sync_state.begin_keys(), sync_state.end_keys());
368
369 // Send local state to sync if there is no sync data yet, otherwise overwrite
370 // local state with sync state (via a callback).
371 if (sync_state.empty()) {
372 Get(new SendAllLocalSettingsToSyncCallback(
373 extension_id_, sync_deps_->AsWeakPtr()));
374 } else {
375 Get(new OverwriteLocalSettingsFromSyncCallback(
376 this->AsWeakPtr(), sync_state.DeepCopy()));
377 }
378 }
379
380 void SyncableExtensionSettingsStorage::StopSyncing() {
381 DCHECK(sync_deps_ != NULL);
382 delete sync_deps_;
383 sync_deps_ = NULL;
384 }
385
386 namespace {
387
388 // Callback from storage methods which does nothing.
389 // TODO(kalman): Replace with actual implementations when notifications of sync
390 // changes need to be sent to extensions.
391 class NoopCallback : public ExtensionSettingsStorage::Callback {
392 public:
393 virtual ~NoopCallback() {}
394 virtual void OnSuccess(DictionaryValue* s) OVERRIDE { delete s; }
395 virtual void OnFailure(const std::string& message) OVERRIDE {}
396 };
397
398 } // namespace
399
400 void SyncableExtensionSettingsStorage::ProcessSyncChanges(
401 const ExtensionSettingSyncDataList& sync_changes) {
402 DCHECK(sync_deps_ != NULL);
403 DCHECK(!sync_changes.empty()) << "No sync changes for " << extension_id_;
404 for (ExtensionSettingSyncDataList::const_iterator it = sync_changes.begin();
405 it != sync_changes.end(); ++it) {
406 switch (it->change_type()) {
407 case SyncChange::ACTION_ADD:
408 case SyncChange::ACTION_UPDATE:
409 sync_deps_->keys()->insert(it->key());
410 delegate_->Set(
411 it->key(),
412 *it->value(),
413 new NoopCallback());
414 break;
415 case SyncChange::ACTION_DELETE:
416 sync_deps_->keys()->erase(it->key());
417 delegate_->Remove(
418 it->key(),
419 new NoopCallback());
420 break;
421 default:
422 NOTREACHED();
423 }
424 }
425 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698