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

Side by Side Diff: chrome/browser/extensions/api/storage/syncable_settings_storage.cc

Issue 11826048: Revert 176015 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 7 years, 11 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) 2012 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/api/storage/syncable_settings_storage.h"
6
7 #include "chrome/browser/extensions/api/storage/settings_namespace.h"
8 #include "chrome/browser/extensions/api/storage/settings_sync_processor.h"
9 #include "chrome/browser/extensions/api/storage/settings_sync_util.h"
10 #include "content/public/browser/browser_thread.h"
11 #include "sync/api/sync_data.h"
12 #include "sync/protocol/extension_setting_specifics.pb.h"
13
14 namespace extensions {
15
16 using content::BrowserThread;
17
18 SyncableSettingsStorage::SyncableSettingsStorage(
19 const scoped_refptr<ObserverListThreadSafe<SettingsObserver> >&
20 observers,
21 const std::string& extension_id,
22 ValueStore* delegate)
23 : observers_(observers),
24 extension_id_(extension_id),
25 delegate_(delegate) {
26 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
27 }
28
29 SyncableSettingsStorage::~SyncableSettingsStorage() {
30 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
31 }
32
33 size_t SyncableSettingsStorage::GetBytesInUse(const std::string& key) {
34 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
35 return delegate_->GetBytesInUse(key);
36 }
37
38 size_t SyncableSettingsStorage::GetBytesInUse(
39 const std::vector<std::string>& keys) {
40 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
41 return delegate_->GetBytesInUse(keys);
42 }
43
44 size_t SyncableSettingsStorage::GetBytesInUse() {
45 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
46 return delegate_->GetBytesInUse();
47 }
48
49 ValueStore::ReadResult SyncableSettingsStorage::Get(
50 const std::string& key) {
51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
52 return delegate_->Get(key);
53 }
54
55 ValueStore::ReadResult SyncableSettingsStorage::Get(
56 const std::vector<std::string>& keys) {
57 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
58 return delegate_->Get(keys);
59 }
60
61 ValueStore::ReadResult SyncableSettingsStorage::Get() {
62 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
63 return delegate_->Get();
64 }
65
66 ValueStore::WriteResult SyncableSettingsStorage::Set(
67 WriteOptions options, const std::string& key, const Value& value) {
68 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
69 WriteResult result = delegate_->Set(options, key, value);
70 if (result->HasError()) {
71 return result.Pass();
72 }
73 SyncResultIfEnabled(result);
74 return result.Pass();
75 }
76
77 ValueStore::WriteResult SyncableSettingsStorage::Set(
78 WriteOptions options, const DictionaryValue& values) {
79 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
80 WriteResult result = delegate_->Set(options, values);
81 if (result->HasError()) {
82 return result.Pass();
83 }
84 SyncResultIfEnabled(result);
85 return result.Pass();
86 }
87
88 ValueStore::WriteResult SyncableSettingsStorage::Remove(
89 const std::string& key) {
90 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
91 WriteResult result = delegate_->Remove(key);
92 if (result->HasError()) {
93 return result.Pass();
94 }
95 SyncResultIfEnabled(result);
96 return result.Pass();
97 }
98
99 ValueStore::WriteResult SyncableSettingsStorage::Remove(
100 const std::vector<std::string>& keys) {
101 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
102 WriteResult result = delegate_->Remove(keys);
103 if (result->HasError()) {
104 return result.Pass();
105 }
106 SyncResultIfEnabled(result);
107 return result.Pass();
108 }
109
110 ValueStore::WriteResult SyncableSettingsStorage::Clear() {
111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
112 WriteResult result = delegate_->Clear();
113 if (result->HasError()) {
114 return result.Pass();
115 }
116 SyncResultIfEnabled(result);
117 return result.Pass();
118 }
119
120 void SyncableSettingsStorage::SyncResultIfEnabled(
121 const ValueStore::WriteResult& result) {
122 if (sync_processor_.get() && !result->changes().empty()) {
123 syncer::SyncError error = sync_processor_->SendChanges(result->changes());
124 if (error.IsSet())
125 StopSyncing();
126 }
127 }
128
129 // Sync-related methods.
130
131 syncer::SyncError SyncableSettingsStorage::StartSyncing(
132 const DictionaryValue& sync_state,
133 scoped_ptr<SettingsSyncProcessor> sync_processor) {
134 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
135 DCHECK(!sync_processor_.get());
136
137 sync_processor_ = sync_processor.Pass();
138 sync_processor_->Init(sync_state);
139
140 ReadResult maybe_settings = delegate_->Get();
141 if (maybe_settings->HasError()) {
142 return syncer::SyncError(
143 FROM_HERE,
144 std::string("Failed to get settings: ") + maybe_settings->error(),
145 sync_processor_->type());
146 }
147
148 const DictionaryValue& settings = *maybe_settings->settings().get();
149 if (sync_state.empty())
150 return SendLocalSettingsToSync(settings);
151 else
152 return OverwriteLocalSettingsWithSync(sync_state, settings);
153 }
154
155 syncer::SyncError SyncableSettingsStorage::SendLocalSettingsToSync(
156 const DictionaryValue& settings) {
157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
158
159 ValueStoreChangeList changes;
160 for (DictionaryValue::Iterator i(settings); i.HasNext(); i.Advance()) {
161 changes.push_back(ValueStoreChange(i.key(), NULL, i.value().DeepCopy()));
162 }
163
164 if (changes.empty())
165 return syncer::SyncError();
166
167 syncer::SyncError error = sync_processor_->SendChanges(changes);
168 if (error.IsSet())
169 StopSyncing();
170
171 return error;
172 }
173
174 syncer::SyncError SyncableSettingsStorage::OverwriteLocalSettingsWithSync(
175 const DictionaryValue& sync_state, const DictionaryValue& settings) {
176 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
177 // Treat this as a list of changes to sync and use ProcessSyncChanges.
178 // This gives notifications etc for free.
179 scoped_ptr<DictionaryValue> new_sync_state(sync_state.DeepCopy());
180
181 SettingSyncDataList changes;
182 for (DictionaryValue::Iterator it(settings); it.HasNext(); it.Advance()) {
183 Value* orphaned_sync_value = NULL;
184 if (new_sync_state->RemoveWithoutPathExpansion(
185 it.key(), &orphaned_sync_value)) {
186 scoped_ptr<Value> sync_value(orphaned_sync_value);
187 if (sync_value->Equals(&it.value())) {
188 // Sync and local values are the same, no changes to send.
189 } else {
190 // Sync value is different, update local setting with new value.
191 changes.push_back(
192 SettingSyncData(
193 syncer::SyncChange::ACTION_UPDATE,
194 extension_id_,
195 it.key(),
196 sync_value.Pass()));
197 }
198 } else {
199 // Not synced, delete local setting.
200 changes.push_back(
201 SettingSyncData(
202 syncer::SyncChange::ACTION_DELETE,
203 extension_id_,
204 it.key(),
205 scoped_ptr<Value>(new DictionaryValue())));
206 }
207 }
208
209 // Add all new settings to local settings.
210 while (!new_sync_state->empty()) {
211 std::string key = *new_sync_state->begin_keys();
212 Value* value = NULL;
213 CHECK(new_sync_state->RemoveWithoutPathExpansion(key, &value));
214 changes.push_back(
215 SettingSyncData(
216 syncer::SyncChange::ACTION_ADD,
217 extension_id_,
218 key,
219 scoped_ptr<Value>(value)));
220 }
221
222 if (changes.empty())
223 return syncer::SyncError();
224
225 return ProcessSyncChanges(changes);
226 }
227
228 void SyncableSettingsStorage::StopSyncing() {
229 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
230 sync_processor_.reset();
231 }
232
233 syncer::SyncError SyncableSettingsStorage::ProcessSyncChanges(
234 const SettingSyncDataList& sync_changes) {
235 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
236 DCHECK(!sync_changes.empty()) << "No sync changes for " << extension_id_;
237
238 if (!sync_processor_.get()) {
239 return syncer::SyncError(
240 FROM_HERE,
241 std::string("Sync is inactive for ") + extension_id_,
242 syncer::UNSPECIFIED);
243 }
244
245 std::vector<syncer::SyncError> errors;
246 ValueStoreChangeList changes;
247
248 for (SettingSyncDataList::const_iterator it = sync_changes.begin();
249 it != sync_changes.end(); ++it) {
250 DCHECK_EQ(extension_id_, it->extension_id());
251
252 const std::string& key = it->key();
253 const Value& value = it->value();
254
255 scoped_ptr<Value> current_value;
256 {
257 ReadResult maybe_settings = Get(it->key());
258 if (maybe_settings->HasError()) {
259 errors.push_back(syncer::SyncError(
260 FROM_HERE,
261 std::string("Error getting current sync state for ") +
262 extension_id_ + "/" + key + ": " + maybe_settings->error(),
263 sync_processor_->type()));
264 continue;
265 }
266 Value* value = NULL;
267 if (maybe_settings->settings()->GetWithoutPathExpansion(key, &value)) {
268 current_value.reset(value->DeepCopy());
269 }
270 }
271
272 syncer::SyncError error;
273
274 switch (it->change_type()) {
275 case syncer::SyncChange::ACTION_ADD:
276 if (!current_value.get()) {
277 error = OnSyncAdd(key, value.DeepCopy(), &changes);
278 } else {
279 // Already a value; hopefully a local change has beaten sync in a
280 // race and it's not a bug, so pretend it's an update.
281 LOG(WARNING) << "Got add from sync for existing setting " <<
282 extension_id_ << "/" << key;
283 error = OnSyncUpdate(
284 key, current_value.release(), value.DeepCopy(), &changes);
285 }
286 break;
287
288 case syncer::SyncChange::ACTION_UPDATE:
289 if (current_value.get()) {
290 error = OnSyncUpdate(
291 key, current_value.release(), value.DeepCopy(), &changes);
292 } else {
293 // Similarly, pretend it's an add.
294 LOG(WARNING) << "Got update from sync for nonexistent setting" <<
295 extension_id_ << "/" << key;
296 error = OnSyncAdd(key, value.DeepCopy(), &changes);
297 }
298 break;
299
300 case syncer::SyncChange::ACTION_DELETE:
301 if (current_value.get()) {
302 error = OnSyncDelete(key, current_value.release(), &changes);
303 } else {
304 // Similarly, ignore it.
305 LOG(WARNING) << "Got delete from sync for nonexistent setting " <<
306 extension_id_ << "/" << key;
307 }
308 break;
309
310 default:
311 NOTREACHED();
312 }
313
314 if (error.IsSet()) {
315 errors.push_back(error);
316 }
317 }
318
319 sync_processor_->NotifyChanges(changes);
320
321 observers_->Notify(
322 &SettingsObserver::OnSettingsChanged,
323 extension_id_,
324 settings_namespace::SYNC,
325 ValueStoreChange::ToJson(changes));
326
327 // TODO(kalman): Something sensible with multiple errors.
328 return errors.empty() ? syncer::SyncError() : errors[0];
329 }
330
331 syncer::SyncError SyncableSettingsStorage::OnSyncAdd(
332 const std::string& key,
333 Value* new_value,
334 ValueStoreChangeList* changes) {
335 DCHECK(new_value);
336 WriteResult result = delegate_->Set(IGNORE_QUOTA, key, *new_value);
337 if (result->HasError()) {
338 return syncer::SyncError(
339 FROM_HERE,
340 std::string("Error pushing sync add to local settings: ") +
341 result->error(),
342 sync_processor_->type());
343 }
344 changes->push_back(ValueStoreChange(key, NULL, new_value));
345 return syncer::SyncError();
346 }
347
348 syncer::SyncError SyncableSettingsStorage::OnSyncUpdate(
349 const std::string& key,
350 Value* old_value,
351 Value* new_value,
352 ValueStoreChangeList* changes) {
353 DCHECK(old_value);
354 DCHECK(new_value);
355 WriteResult result = delegate_->Set(IGNORE_QUOTA, key, *new_value);
356 if (result->HasError()) {
357 return syncer::SyncError(
358 FROM_HERE,
359 std::string("Error pushing sync update to local settings: ") +
360 result->error(),
361 sync_processor_->type());
362 }
363 changes->push_back(ValueStoreChange(key, old_value, new_value));
364 return syncer::SyncError();
365 }
366
367 syncer::SyncError SyncableSettingsStorage::OnSyncDelete(
368 const std::string& key,
369 Value* old_value,
370 ValueStoreChangeList* changes) {
371 DCHECK(old_value);
372 WriteResult result = delegate_->Remove(key);
373 if (result->HasError()) {
374 return syncer::SyncError(
375 FROM_HERE,
376 std::string("Error pushing sync remove to local settings: ") +
377 result->error(),
378 sync_processor_->type());
379 }
380 changes->push_back(ValueStoreChange(key, old_value, NULL));
381 return syncer::SyncError();
382 }
383
384 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698