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

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: Comments, GCC compile fix 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/memory/scoped_ptr.h"
8 #include "chrome/browser/extensions/extension_settings_sync_util.h"
9 #include "chrome/browser/sync/api/sync_data.h"
10 #include "chrome/browser/sync/protocol/extension_setting_specifics.pb.h"
11 #include "content/browser/browser_thread.h"
12
13 namespace {
14
15 // Inserts all the keys from a dictionary into a set of strings.
16 void InsertAll(const DictionaryValue& src, std::set<std::string>* dst) {
17 for (DictionaryValue::key_iterator it = src.begin_keys();
18 it != src.end_keys(); ++it) {
19 dst->insert(*it);
20 }
21 }
22
23 } // namespace
24
25 SyncableExtensionSettingsStorage::SyncableExtensionSettingsStorage(
26 std::string extension_id, ExtensionSettingsStorage* delegate)
27 : extension_id_(extension_id), delegate_(delegate), sync_processor_(NULL) {
28 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
29 }
30
31 SyncableExtensionSettingsStorage::~SyncableExtensionSettingsStorage() {
32 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
33 }
34
35 ExtensionSettingsStorage::Result SyncableExtensionSettingsStorage::Get(
36 const std::string& key) {
37 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
38 return delegate_->Get(key);
39 }
40
41 ExtensionSettingsStorage::Result SyncableExtensionSettingsStorage::Get(
42 const std::vector<std::string>& keys) {
43 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
44 return delegate_->Get(keys);
45 }
46
47 ExtensionSettingsStorage::Result SyncableExtensionSettingsStorage::Get() {
48 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
49 return delegate_->Get();
50 }
51
52 ExtensionSettingsStorage::Result SyncableExtensionSettingsStorage::Set(
53 const std::string& key, const Value& value) {
54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
55 Result result = delegate_->Set(key, value);
56 if (result.HasError()) {
57 return result;
58 }
59 if (sync_processor_) {
60 SendAddsOrUpdatesToSync(*result.GetSettings());
61 }
62 return result;
63 }
64
65 ExtensionSettingsStorage::Result SyncableExtensionSettingsStorage::Set(
66 const DictionaryValue& values) {
67 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
68 Result result = delegate_->Set(values);
69 if (result.HasError()) {
70 return result;
71 }
72 if (sync_processor_) {
73 SendAddsOrUpdatesToSync(*result.GetSettings());
74 }
75 return result;
76 }
77
78 ExtensionSettingsStorage::Result SyncableExtensionSettingsStorage::Remove(
79 const std::string& key) {
80 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
81 Result result = delegate_->Remove(key);
82 if (result.HasError()) {
83 return result;
84 }
85 if (sync_processor_) {
86 std::vector<std::string> keys;
87 keys.push_back(key);
88 SendDeletesToSync(keys);
89 }
90 return result;
91 }
92
93 ExtensionSettingsStorage::Result SyncableExtensionSettingsStorage::Remove(
94 const std::vector<std::string>& keys) {
95 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
96 Result result = delegate_->Remove(keys);
97 if (result.HasError()) {
98 return result;
99 }
100 if (sync_processor_) {
101 SendDeletesToSync(keys);
102 }
103 return result;
104 }
105
106 ExtensionSettingsStorage::Result SyncableExtensionSettingsStorage::Clear() {
107 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
108 Result result = delegate_->Clear();
109 if (result.HasError()) {
110 return result;
111 }
112 if (sync_processor_) {
113 SendDeletesToSync(
114 std::vector<std::string>(synced_keys_.begin(), synced_keys_.end()));
115 }
116 return result;
117 }
118
119 // Sync-related methods.
120
121 SyncError SyncableExtensionSettingsStorage::StartSyncing(
122 const DictionaryValue& sync_state, SyncChangeProcessor* sync_processor) {
123 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
124 DCHECK(!sync_processor_);
125 DCHECK(synced_keys_.empty());
126 sync_processor_ = sync_processor;
127 InsertAll(sync_state, &synced_keys_);
128
129 Result maybe_settings = delegate_->Get();
130 if (maybe_settings.HasError()) {
131 return SyncError(
132 FROM_HERE,
133 std::string("Failed to get settings: ") + maybe_settings.GetError(),
134 syncable::EXTENSION_SETTINGS);
135 }
136
137 DictionaryValue* settings = maybe_settings.GetSettings();
138 if (sync_state.empty()) {
139 SendLocalSettingsToSync(*settings);
140 } else {
141 OverwriteLocalSettingsWithSync(sync_state, *settings);
142 }
143 return SyncError();
144 }
145
146 void SyncableExtensionSettingsStorage::SendLocalSettingsToSync(
147 const DictionaryValue& settings) {
148 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
149 SyncChangeList changes;
150 for (DictionaryValue::key_iterator it = settings.begin_keys();
151 it != settings.end_keys(); ++it) {
152 Value* value;
153 settings.GetWithoutPathExpansion(*it, &value);
154 changes.push_back(
155 extension_settings_sync_util::CreateAdd(extension_id_, *it, *value));
156 }
157
158 if (changes.empty()) {
159 return;
160 }
161
162 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, changes);
163 if (error.IsSet()) {
164 LOG(WARNING) << "Failed to send changes to sync: " << error.message();
akalin 2011/09/20 14:53:11 have this return an error and propagate to StartSy
not at google - send to devlin 2011/09/21 00:20:14 Done.
165 return;
166 }
167
168 InsertAll(settings, &synced_keys_);
169 }
170
171 void SyncableExtensionSettingsStorage::OverwriteLocalSettingsWithSync(
172 const DictionaryValue& sync_state, const DictionaryValue& settings) {
173 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
174 // Treat this as a list of changes to sync and use ProcessSyncChanges.
175 // This gives notifications etc for free.
176 scoped_ptr<DictionaryValue> new_sync_state(sync_state.DeepCopy());
177
178 ExtensionSettingSyncDataList changes;
179 for (DictionaryValue::key_iterator it = settings.begin_keys();
180 it != settings.end_keys(); ++it) {
181 Value* sync_value = NULL;
182 if (new_sync_state->RemoveWithoutPathExpansion(*it, &sync_value)) {
183 Value* local_value = NULL;
184 settings.GetWithoutPathExpansion(*it, &local_value);
185 if (!local_value->Equals(sync_value)) {
186 // Sync value is different, update local setting with new value.
187 changes.push_back(
188 ExtensionSettingSyncData(
189 SyncChange::ACTION_UPDATE, extension_id_, *it, sync_value));
190 }
191 } else {
192 // Not synced, delete local setting.
193 changes.push_back(
194 ExtensionSettingSyncData(
195 SyncChange::ACTION_DELETE,
196 extension_id_,
197 *it,
198 new DictionaryValue()));
199 }
200 }
201
202 // Add all new settings to local settings.
203 while (!new_sync_state->empty()) {
204 std::string key = *new_sync_state->begin_keys();
205 Value* value;
206 new_sync_state->RemoveWithoutPathExpansion(key, &value);
207 changes.push_back(
208 ExtensionSettingSyncData(
209 SyncChange::ACTION_ADD, extension_id_, key, value));
210 }
211
212 if (!changes.empty()) {
213 ProcessSyncChanges(changes);
akalin 2011/09/20 14:53:11 propagate return value from here to StartSyncing
not at google - send to devlin 2011/09/21 00:20:14 Done.
214 }
215 }
216
217 void SyncableExtensionSettingsStorage::StopSyncing() {
218 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
219 DCHECK(sync_processor_);
220 sync_processor_ = NULL;
221 synced_keys_.clear();
222 }
223
224 std::vector<SyncError> SyncableExtensionSettingsStorage::ProcessSyncChanges(
225 const ExtensionSettingSyncDataList& sync_changes) {
226 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
227 DCHECK(sync_processor_);
228 DCHECK(!sync_changes.empty()) << "No sync changes for " << extension_id_;
229
230 std::vector<SyncError> errors;
231
232 for (ExtensionSettingSyncDataList::const_iterator it = sync_changes.begin();
233 it != sync_changes.end(); ++it) {
234 DCHECK_EQ(extension_id_, it->extension_id());
235 switch (it->change_type()) {
236 case SyncChange::ACTION_ADD:
237 case SyncChange::ACTION_UPDATE: {
238 synced_keys_.insert(it->key());
239 Result result = delegate_->Set(it->key(), it->value());
240 if (result.HasError()) {
241 errors.push_back(SyncError(
242 FROM_HERE,
243 std::string("Error pushing sync change to local settings: ") +
244 result.GetError(),
245 syncable::EXTENSION_SETTINGS));
246 }
247 break;
248 }
249
250 case SyncChange::ACTION_DELETE: {
251 synced_keys_.erase(it->key());
252 Result result = delegate_->Remove(it->key());
253 if (result.HasError()) {
254 errors.push_back(SyncError(
255 FROM_HERE,
256 std::string("Error removing sync change from local settings: ") +
257 result.GetError(),
258 syncable::EXTENSION_SETTINGS));
259 }
260 break;
261 }
262
263 default:
264 NOTREACHED();
265 }
266 }
267
268 return errors;
269 }
270
271 void SyncableExtensionSettingsStorage::SendAddsOrUpdatesToSync(
272 const DictionaryValue& settings) {
273 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
274 DCHECK(sync_processor_);
275
276 SyncChangeList changes;
277 for (DictionaryValue::key_iterator it = settings.begin_keys();
278 it != settings.end_keys(); ++it) {
279 Value* value = NULL;
280 settings.GetWithoutPathExpansion(*it, &value);
281 DCHECK(value);
282 if (synced_keys_.count(*it)) {
283 // Key is synced, send ACTION_UPDATE to sync.
284 changes.push_back(
285 extension_settings_sync_util::CreateUpdate(
286 extension_id_, *it, *value));
287 } else {
288 // Key is not synced, send ACTION_ADD to sync.
289 changes.push_back(
290 extension_settings_sync_util::CreateAdd(extension_id_, *it, *value));
291 }
292 }
293
294 if (changes.empty()) {
295 return;
296 }
297
298 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, changes);
299 if (error.IsSet()) {
300 LOG(WARNING) << "Failed to send changes to sync: " << error.message();
301 return;
302 }
303
304 InsertAll(settings, &synced_keys_);
305 }
306
307 void SyncableExtensionSettingsStorage::SendDeletesToSync(
308 const std::vector<std::string>& keys) {
309 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
310 DCHECK(sync_processor_);
311
312 SyncChangeList changes;
313 for (std::vector<std::string>::const_iterator it = keys.begin();
314 it != keys.end(); ++it) {
315 // Only remove from sync if it's actually synced.
316 if (synced_keys_.count(*it)) {
317 changes.push_back(
318 extension_settings_sync_util::CreateDelete(extension_id_, *it));
319 }
320 }
321
322 if (changes.empty()) {
323 return;
324 }
325
326 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, changes);
327 if (error.IsSet()) {
328 LOG(WARNING) << "Failed to send changes to sync: " << error.message();
329 return;
330 }
331
332 for (std::vector<std::string>::const_iterator it = keys.begin();
333 it != keys.end(); ++it) {
334 synced_keys_.erase(*it);
335 }
336 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698