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

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

Issue 7747043: WORK IN PROGRESS. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Small change 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 AddOrUpdateSyncCallback : public ExtensionSettingsStorage::Callback {
47 public:
48 AddOrUpdateSyncCallback(
49 Callback* delegate,
50 const std::string& extension_id,
51 base::WeakPtr<SyncableExtensionSettingsStorage::SyncDeps> sync_deps)
52 : delegate_(delegate),
53 extension_id_(extension_id),
54 sync_deps_(sync_deps) {}
55
56 void OnSuccess(DictionaryValue* settings) OVERRIDE {
57 if (!sync_deps_) {
58 delegate_->OnSuccess(settings);
59 return;
60 }
61
62 SyncChangeList sync_changes;
63 for (DictionaryValue::key_iterator it = settings->begin_keys();
64 it != settings->end_keys(); ++it) {
65 Value* value;
66 settings->GetWithoutPathExpansion(*it, &value);
67 if (sync_deps_->keys()->count(*it)) {
68 // TODO Key is synced, send ACTION_UPDATE to sync.
69 LOG(INFO) << "Pushing sync update to sync for " << *it;
70 sync_changes.push_back(ExtensionSettingsSyncHelper::CreateUpdate(
71 extension_id_, *it, *value));
72 } else {
73 // TODO Key is not synced, send ACTION_ADD to sync.
74 LOG(INFO) << "Pushing sync add to sync for " << *it;
75 sync_changes.push_back(ExtensionSettingsSyncHelper::CreateAdd(
76 extension_id_, *it, *value));
77 }
78 }
79
80 SyncError error =
81 sync_deps_->processor()->ProcessSyncChanges(FROM_HERE, sync_changes);
82 if (error.IsSet()) {
83 LOG(WARNING) << "Failed to send changes to sync: " << error.message();
84 } else {
85 // Sync was successful, record those keys as synced.
86 sync_deps_->keys()->insert(settings->begin_keys(), settings->end_keys());
87 }
88
89 delegate_->OnSuccess(settings);
90 }
91
92 void OnFailure(const std::string& error) {
93 LOG(WARNING) << "Settings operation failed, not sending to sync: " << error;
94 delegate_->OnFailure(error);
95 }
96
97 private:
98 scoped_ptr<Callback> delegate_;
99 std::string extension_id_;
100 base::WeakPtr<SyncableExtensionSettingsStorage::SyncDeps> sync_deps_;
101 };
102
103 } // namespace
104
105 void SyncableExtensionSettingsStorage::Set(
106 const std::string& key,
107 const Value& value,
108 ExtensionSettingsStorage::Callback* callback) {
109 if (sync_deps_ != NULL) {
110 callback = new AddOrUpdateSyncCallback(
111 callback, extension_id_, sync_deps_->AsWeakPtr());
112 }
113 delegate_->Set(key, value, callback);
114 }
115
116 void SyncableExtensionSettingsStorage::Set(
117 const DictionaryValue& values,
118 ExtensionSettingsStorage::Callback* callback) {
119 if (sync_deps_ != NULL) {
120 callback = new AddOrUpdateSyncCallback(
121 callback, extension_id_, sync_deps_->AsWeakPtr());
122 }
123 delegate_->Set(values, callback);
124 }
125
126 namespace {
127
128 class RemoveFromSyncCallback : public ExtensionSettingsStorage::Callback {
129 public:
130 RemoveFromSyncCallback(
131 Callback* delegate,
132 const std::string& extension_id,
133 // Ownership of keys_to_remove is taken.
134 std::set<std::string>* keys_to_remove,
135 base::WeakPtr<SyncableExtensionSettingsStorage::SyncDeps> sync_deps)
136 : delegate_(delegate),
137 extension_id_(extension_id),
138 keys_to_remove_(keys_to_remove),
139 sync_deps_(sync_deps) {
140 DCHECK(!keys_to_remove->empty());
141 }
142
143 void OnSuccess(DictionaryValue* settings) OVERRIDE {
144 if (!sync_deps_) {
145 delegate_->OnSuccess(settings);
146 return;
147 }
148
149 SyncChangeList sync_changes;
150 for (std::set<std::string>::iterator it = keys_to_remove_->begin();
151 it != keys_to_remove_->end(); ++it) {
152 LOG(INFO) <<
153 "Pushing sync remove to sync for " << extension_id_ << "/" << *it;
154 SyncChange sync_delete =
155 ExtensionSettingsSyncHelper::CreateDelete(extension_id_, *it);
156 sync_changes.push_back(sync_delete);
157 }
158
159 SyncError error =
160 sync_deps_->processor()->ProcessSyncChanges(FROM_HERE, sync_changes);
161 if (error.IsSet()) {
162 LOG(WARNING) << "Failed to send changes to sync: " << error.message();
163 } else {
164 // Sync was successful, record those keys as deleted from sync.
165 sync_deps_->keys()->erase(
166 keys_to_remove_->begin(), keys_to_remove_->end());
167 }
168
169 delegate_->OnSuccess(settings);
170 }
171
172 void OnFailure(const std::string& error) {
173 LOG(WARNING) << "Settings operation failed, not sending to sync: " << error;
174 delegate_->OnFailure(error);
175 }
176
177 private:
178 scoped_ptr<Callback> delegate_;
179 std::string extension_id_;
180 scoped_ptr<std::set<std::string> > keys_to_remove_;
181 base::WeakPtr<SyncableExtensionSettingsStorage::SyncDeps> sync_deps_;
182 };
183
184 } // namespace
185
186 void SyncableExtensionSettingsStorage::Remove(
187 const std::string& key, ExtensionSettingsStorage::Callback* callback) {
188 if (sync_deps_ != NULL) {
189 std::set<std::string>* keys_to_remove = new std::set<std::string>();
190 keys_to_remove->insert(key);
191 callback = new RemoveFromSyncCallback(
192 callback,
193 extension_id_,
194 keys_to_remove,
195 sync_deps_->AsWeakPtr());
196 }
197 delegate_->Remove(key, callback);
198 }
199
200 void SyncableExtensionSettingsStorage::Remove(
201 const ListValue& keys, ExtensionSettingsStorage::Callback* callback) {
202 if (sync_deps_ != NULL) {
203 std::set<std::string>* keys_to_remove = new std::set<std::string>();
204 for (ListValue::const_iterator it = keys.begin(); it != keys.end(); ++it) {
205 std::string key_to_remove;
206 if ((*it)->GetAsString(&key_to_remove)) {
207 keys_to_remove->insert(key_to_remove);
208 }
209 }
210 callback = new RemoveFromSyncCallback(
211 callback,
212 extension_id_,
213 keys_to_remove,
214 sync_deps_->AsWeakPtr());
215 }
216 delegate_->Remove(keys, callback);
217 }
218
219 void SyncableExtensionSettingsStorage::Clear(
220 ExtensionSettingsStorage::Callback* callback) {
221 if (sync_deps_ != NULL) {
222 callback = new RemoveFromSyncCallback(
223 callback,
224 extension_id_,
225 // Remove all the synced keys.
226 new std::set<std::string>(*sync_deps_->keys()),
227 sync_deps_->AsWeakPtr());
228 }
229 delegate_->Clear(callback);
230 }
231
232 void SyncableExtensionSettingsStorage::DeleteSoon() {
233 delegate_->DeleteSoon();
234 delete this;
235 }
236
237 // Sync-related methods.
238
239 namespace {
240
241 class SendAllLocalSettingsToSync : public ExtensionSettingsStorage::Callback {
242 public:
243 SendAllLocalSettingsToSync(
244 const std::string& extension_id,
245 base::WeakPtr<SyncableExtensionSettingsStorage::SyncDeps> sync_deps)
246 : extension_id_(extension_id), sync_deps_(sync_deps) {}
247
248 virtual void OnSuccess(DictionaryValue* settings) OVERRIDE {
249 scoped_ptr<DictionaryValue> settings_ownership(settings);
250 if (!sync_deps_) {
251 return;
252 }
253
254 SyncChangeList add_to_sync;
255 for (DictionaryValue::key_iterator it = settings->begin_keys();
256 it != settings->end_keys(); ++it) {
257 Value* value;
258 settings->GetWithoutPathExpansion(*it, &value);
259 add_to_sync.push_back(ExtensionSettingsSyncHelper::CreateAdd(
260 extension_id_, *it, *value));
261 }
262
263 SyncError error =
264 sync_deps_->processor()->ProcessSyncChanges(FROM_HERE, add_to_sync);
265 if (error.IsSet()) {
266 LOG(WARNING) << "Failed to send changes to sync: " << error.message();
267 } else {
268 // Sync was successful, record those keys as synced.
269 sync_deps_->keys()->insert(settings->begin_keys(), settings->end_keys());
270 }
271 }
272
273 virtual void OnFailure(const std::string& error) OVERRIDE {
274 LOG(WARNING) << "Settings operation failed, not sending to sync: " << error;
275 }
276
277 private:
278 std::string extension_id_;
279 base::WeakPtr<SyncableExtensionSettingsStorage::SyncDeps> sync_deps_;
280 };
281
282 class OverwriteLocalSettingsCallback
283 : public ExtensionSettingsStorage::Callback {
284 public:
285 OverwriteLocalSettingsCallback(
286 // Ownership NOT taken.
287 SyncableExtensionSettingsStorage* storage,
288 // Ownership taken.
289 DictionaryValue* sync_state)
290 : storage_(storage), sync_state_(sync_state) {}
291
292 virtual void OnSuccess(DictionaryValue* local_state) {
293 scoped_ptr<DictionaryValue> local_state_ownership(local_state);
294 // Pretend they're sync changes to process.
295 ExtensionSettingsSyncDataList sync_changes;
296 for (DictionaryValue::key_iterator it = local_state->begin_keys();
297 it != local_state->end_keys(); ++it) {
298 Value* sync_value;
299 if (sync_state_->RemoveWithoutPathExpansion(*it, &sync_value)) {
300 Value* local_value;
301 local_state->GetWithoutPathExpansion(*it, &local_value);
302 if (!local_value->Equals(sync_value)) {
303 // Sync value is different, update locally with new value.
304 sync_changes.push_back(ExtensionSettingsSyncData(
305 SyncChange::ACTION_UPDATE, "", *it, sync_value));
306 }
307 } else {
308 // No sync value, delete locally.
309 sync_changes.push_back(ExtensionSettingsSyncData(
310 SyncChange::ACTION_DELETE, "", *it, new DictionaryValue()));
311 }
312 }
313
314 for (DictionaryValue::key_iterator it = sync_state_->begin_keys();
315 it != sync_state_->end_keys(); ++it) {
316 Value* sync_value;
317 // Missing local value for synced setting, add locally.
318 // If it's safe to RemoveWithoutPathExpansion the DeepCopy would be
319 // unnecessary.
320 sync_state_->GetWithoutPathExpansion(*it, &sync_value);
321 sync_changes.push_back(ExtensionSettingsSyncData(
322 SyncChange::ACTION_ADD, "", *it, sync_value->DeepCopy()));
323 }
324
325 if (!sync_changes.empty()) {
326 storage_->ProcessSyncChanges(sync_changes);
327 }
328 }
329
330 virtual void OnFailure(const std::string& error) {
331 LOG(WARNING) <<
332 "Settings operation failed, local state not in sync: " << error;
333 }
334
335 private:
336 // XXX(kalman): weak pointer or refcount or ughhhhh.
337 SyncableExtensionSettingsStorage* storage_;
338 scoped_ptr<DictionaryValue> sync_state_;
339 };
340
341 } // namespace
342
343 void SyncableExtensionSettingsStorage::StartSyncing(
344 const DictionaryValue& sync_state, SyncChangeProcessor* sync_processor) {
345 DCHECK(sync_deps_ == NULL);
346 sync_deps_ = new SyncDeps(sync_processor);
347 sync_deps_->keys()->insert(sync_state.begin_keys(), sync_state.end_keys());
348
349 // Push local state to sync if there is no sync data yet, otherwise overwrite
350 // local state with sync state (via a callback).
351 if (sync_state.empty()) {
352 Get(new SendAllLocalSettingsToSync(extension_id_, sync_deps_->AsWeakPtr()));
353 } else {
354 Get(new OverwriteLocalSettingsCallback(this, sync_state.DeepCopy()));
355 }
356 }
357
358 void SyncableExtensionSettingsStorage::StopSyncing() {
359 DCHECK(sync_deps_ != NULL);
360 delete sync_deps_;
361 sync_deps_ = NULL;
362 }
363
364 void SyncableExtensionSettingsStorage::ProcessSyncChanges(
365 const ExtensionSettingsSyncDataList& sync_changes) {
366 DCHECK(sync_deps_ != NULL);
367 DCHECK(!sync_changes.empty()) << "No sync changes for " << extension_id_;
368 for (ExtensionSettingsSyncDataList::const_iterator it = sync_changes.begin();
369 it != sync_changes.end(); ++it) {
370 switch (it->change_type()) {
371 case SyncChange::ACTION_ADD:
372 case SyncChange::ACTION_UPDATE:
373 sync_deps_->keys()->insert(it->key());
374 delegate_->Set(
375 it->key(),
376 *it->value(),
377 new ExtensionSettingsStorage::NoopCallback());
378 break;
379 case SyncChange::ACTION_DELETE:
380 sync_deps_->keys()->erase(it->key());
381 delegate_->Remove(
382 it->key(),
383 new ExtensionSettingsStorage::NoopCallback());
384 break;
385 default:
386 NOTREACHED();
387 }
388 }
389 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698