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

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

Powered by Google App Engine
This is Rietveld 408576698