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

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

Powered by Google App Engine
This is Rietveld 408576698