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

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

Issue 8177022: Add onChanged events to the extension settings API, both from sync and between (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: changes return string Created 9 years, 2 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
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/syncable_extension_settings_storage.h" 5 #include "chrome/browser/extensions/syncable_extension_settings_storage.h"
6 6
7 #include "base/memory/scoped_ptr.h" 7 #include "base/memory/scoped_ptr.h"
8 #include "chrome/browser/extensions/extension_settings_sync_util.h" 8 #include "chrome/browser/extensions/extension_settings_sync_util.h"
9 #include "chrome/browser/sync/api/sync_data.h" 9 #include "chrome/browser/sync/api/sync_data.h"
10 #include "chrome/browser/sync/protocol/extension_setting_specifics.pb.h" 10 #include "chrome/browser/sync/protocol/extension_setting_specifics.pb.h"
11 #include "content/browser/browser_thread.h" 11 #include "content/browser/browser_thread.h"
12 12
13 SyncableExtensionSettingsStorage::SyncableExtensionSettingsStorage( 13 SyncableExtensionSettingsStorage::SyncableExtensionSettingsStorage(
14 std::string extension_id, ExtensionSettingsStorage* delegate) 14 const scoped_refptr<ObserverListThreadSafe<ExtensionSettingsObserver> >&
15 : extension_id_(extension_id), delegate_(delegate), sync_processor_(NULL) { 15 observers,
16 const std::string& extension_id,
17 ExtensionSettingsStorage* delegate)
18 : observers_(observers),
19 extension_id_(extension_id),
20 delegate_(delegate),
21 sync_processor_(NULL) {
16 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 22 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
17 } 23 }
18 24
19 SyncableExtensionSettingsStorage::~SyncableExtensionSettingsStorage() { 25 SyncableExtensionSettingsStorage::~SyncableExtensionSettingsStorage() {
20 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 26 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
21 } 27 }
22 28
23 ExtensionSettingsStorage::Result SyncableExtensionSettingsStorage::Get( 29 ExtensionSettingsStorage::Result SyncableExtensionSettingsStorage::Get(
24 const std::string& key) { 30 const std::string& key) {
25 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 31 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 sync_processor_ = sync_processor; 117 sync_processor_ = sync_processor;
112 118
113 Result maybe_settings = delegate_->Get(); 119 Result maybe_settings = delegate_->Get();
114 if (maybe_settings.HasError()) { 120 if (maybe_settings.HasError()) {
115 return SyncError( 121 return SyncError(
116 FROM_HERE, 122 FROM_HERE,
117 std::string("Failed to get settings: ") + maybe_settings.GetError(), 123 std::string("Failed to get settings: ") + maybe_settings.GetError(),
118 syncable::EXTENSION_SETTINGS); 124 syncable::EXTENSION_SETTINGS);
119 } 125 }
120 126
121 DictionaryValue* settings = maybe_settings.GetSettings(); 127 const DictionaryValue* settings = maybe_settings.GetSettings();
122 if (sync_state.empty()) { 128 if (sync_state.empty()) {
123 return SendLocalSettingsToSync(*settings); 129 return SendLocalSettingsToSync(*settings);
124 } 130 }
125 return OverwriteLocalSettingsWithSync(sync_state, *settings); 131 return OverwriteLocalSettingsWithSync(sync_state, *settings);
126 } 132 }
127 133
128 SyncError SyncableExtensionSettingsStorage::SendLocalSettingsToSync( 134 SyncError SyncableExtensionSettingsStorage::SendLocalSettingsToSync(
129 const DictionaryValue& settings) { 135 const DictionaryValue& settings) {
130 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 136 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
131 SyncChangeList changes; 137 SyncChangeList changes;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 synced_keys_.clear(); 223 synced_keys_.clear();
218 } 224 }
219 225
220 std::vector<SyncError> SyncableExtensionSettingsStorage::ProcessSyncChanges( 226 std::vector<SyncError> SyncableExtensionSettingsStorage::ProcessSyncChanges(
221 const ExtensionSettingSyncDataList& sync_changes) { 227 const ExtensionSettingSyncDataList& sync_changes) {
222 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
223 DCHECK(sync_processor_); 229 DCHECK(sync_processor_);
224 DCHECK(!sync_changes.empty()) << "No sync changes for " << extension_id_; 230 DCHECK(!sync_changes.empty()) << "No sync changes for " << extension_id_;
225 231
226 std::vector<SyncError> errors; 232 std::vector<SyncError> errors;
233 ExtensionSettingChanges::Builder changes;
227 234
228 for (ExtensionSettingSyncDataList::const_iterator it = sync_changes.begin(); 235 for (ExtensionSettingSyncDataList::const_iterator it = sync_changes.begin();
229 it != sync_changes.end(); ++it) { 236 it != sync_changes.end(); ++it) {
230 DCHECK_EQ(extension_id_, it->extension_id()); 237 DCHECK_EQ(extension_id_, it->extension_id());
238
239 const std::string& key = it->key();
240 const Value& value = it->value();
241
242 scoped_ptr<Value> current_value;
243 {
244 Result maybe_settings = Get(it->key());
245 if (maybe_settings.HasError()) {
246 errors.push_back(SyncError(
247 FROM_HERE,
248 std::string("Error getting current sync state for ") +
249 extension_id_ + "/" + key + ": " + maybe_settings.GetError(),
250 syncable::EXTENSION_SETTINGS));
251 continue;
252 }
253 const DictionaryValue* settings = maybe_settings.GetSettings();
254 if (settings) {
255 Value* value = NULL;
256 if (settings->GetWithoutPathExpansion(key, &value)) {
257 current_value.reset(value->DeepCopy());
258 }
259 }
260 }
261
262 SyncError error;
263
231 switch (it->change_type()) { 264 switch (it->change_type()) {
232 case SyncChange::ACTION_ADD: 265 case SyncChange::ACTION_ADD:
233 case SyncChange::ACTION_UPDATE: { 266 if (!current_value.get()) {
234 synced_keys_.insert(it->key()); 267 error = OnSyncAdd(key, value, &changes);
235 Result result = delegate_->Set(it->key(), it->value()); 268 } else {
236 if (result.HasError()) { 269 // Already a value; hopefully a local change has beaten sync in a
237 errors.push_back(SyncError( 270 // race and it's not a bug, so pretend it's an update.
238 FROM_HERE, 271 LOG(WARNING) << "Got add from sync for existing setting " <<
239 std::string("Error pushing sync change to local settings: ") + 272 extension_id_ << "/" << key;
240 result.GetError(), 273 error = OnSyncUpdate(key, *current_value, value, &changes);
241 syncable::EXTENSION_SETTINGS));
242 } 274 }
243 break; 275 break;
244 }
245 276
246 case SyncChange::ACTION_DELETE: { 277 case SyncChange::ACTION_UPDATE:
247 synced_keys_.erase(it->key()); 278 if (current_value.get()) {
248 Result result = delegate_->Remove(it->key()); 279 error = OnSyncUpdate(key, *current_value, value, &changes);
249 if (result.HasError()) { 280 } else {
250 errors.push_back(SyncError( 281 // Similarly, pretend it's an add.
251 FROM_HERE, 282 LOG(WARNING) << "Got update from sync for nonexistent setting" <<
252 std::string("Error removing sync change from local settings: ") + 283 extension_id_ << "/" << key;
253 result.GetError(), 284 error = OnSyncAdd(key, value, &changes);
254 syncable::EXTENSION_SETTINGS));
255 } 285 }
256 break; 286 break;
257 } 287
288 case SyncChange::ACTION_DELETE:
289 if (current_value.get()) {
290 error = OnSyncDelete(key, *current_value, &changes);
akalin 2011/10/17 17:37:38 make OnSyncDelete take a Value* and pass current_v
not at google - send to devlin 2011/10/17 23:05:44 Done.
291 } else {
292 // Similarly, ignore it.
293 LOG(WARNING) << "Got delete from sync for nonexistent setting " <<
294 extension_id_ << "/" << key;
295 }
296 break;
258 297
259 default: 298 default:
260 NOTREACHED(); 299 NOTREACHED();
261 } 300 }
301
302 if (error.IsSet()) {
303 errors.push_back(error);
304 }
262 } 305 }
263 306
307 observers_->Notify(
308 &ExtensionSettingsObserver::OnSettingsChanged,
309 static_cast<Profile*>(NULL),
310 extension_id_,
311 changes.Build());
312
264 return errors; 313 return errors;
265 } 314 }
266 315
267 void SyncableExtensionSettingsStorage::SendAddsOrUpdatesToSync( 316 void SyncableExtensionSettingsStorage::SendAddsOrUpdatesToSync(
268 const std::set<std::string>& changed_keys, 317 const std::set<std::string>& changed_keys,
269 const DictionaryValue& settings) { 318 const DictionaryValue& settings) {
270 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 319 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
271 DCHECK(sync_processor_); 320 DCHECK(sync_processor_);
272 DCHECK(!changed_keys.empty()); 321 DCHECK(!changed_keys.empty());
273 322
(...skipping 26 matching lines...) Expand all
300 349
301 void SyncableExtensionSettingsStorage::SendDeletesToSync( 350 void SyncableExtensionSettingsStorage::SendDeletesToSync(
302 const std::set<std::string>& keys) { 351 const std::set<std::string>& keys) {
303 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 352 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
304 DCHECK(sync_processor_); 353 DCHECK(sync_processor_);
305 DCHECK(!keys.empty()); 354 DCHECK(!keys.empty());
306 355
307 SyncChangeList changes; 356 SyncChangeList changes;
308 for (std::set<std::string>::const_iterator it = keys.begin(); 357 for (std::set<std::string>::const_iterator it = keys.begin();
309 it != keys.end(); ++it) { 358 it != keys.end(); ++it) {
310 DCHECK(synced_keys_.count(*it)); 359 if (!synced_keys_.count(*it)) {
360 LOG(WARNING) << "Deleted " << *it << " but no entry in synced_keys";
361 continue;
362 }
311 changes.push_back( 363 changes.push_back(
312 extension_settings_sync_util::CreateDelete(extension_id_, *it)); 364 extension_settings_sync_util::CreateDelete(extension_id_, *it));
313 } 365 }
314 366
367 if (changes.empty()) {
368 return;
369 }
370
315 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, changes); 371 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, changes);
316 if (error.IsSet()) { 372 if (error.IsSet()) {
317 LOG(WARNING) << "Failed to send changes to sync: " << error.message(); 373 LOG(WARNING) << "Failed to send changes to sync: " << error.message();
318 return; 374 return;
319 } 375 }
320 376
321 for (std::set<std::string>::const_iterator it = keys.begin(); 377 for (std::set<std::string>::const_iterator it = keys.begin();
322 it != keys.end(); ++it) { 378 it != keys.end(); ++it) {
323 synced_keys_.erase(*it); 379 synced_keys_.erase(*it);
324 } 380 }
325 } 381 }
382
383 SyncError SyncableExtensionSettingsStorage::OnSyncAdd(
384 const std::string& key,
385 const Value& new_value,
386 ExtensionSettingChanges::Builder* changes) {
387 synced_keys_.insert(key);
388 Result result = delegate_->Set(key, new_value);
389 if (result.HasError()) {
390 return SyncError(
391 FROM_HERE,
392 std::string("Error pushing sync add to local settings: ") +
393 result.GetError(),
394 syncable::EXTENSION_SETTINGS);
395 }
396 changes->AppendChange(key, NULL, new_value.DeepCopy());
397 return SyncError();
398 }
399
400 SyncError SyncableExtensionSettingsStorage::OnSyncUpdate(
401 const std::string& key,
402 const Value& old_value,
403 const Value& new_value,
404 ExtensionSettingChanges::Builder* changes) {
405 Result result = delegate_->Set(key, new_value);
406 if (result.HasError()) {
407 return SyncError(
408 FROM_HERE,
409 std::string("Error pushing sync update to local settings: ") +
410 result.GetError(),
411 syncable::EXTENSION_SETTINGS);
412 }
413 changes->AppendChange(key, old_value.DeepCopy(), new_value.DeepCopy());
414 return SyncError();
415 }
416
417 SyncError SyncableExtensionSettingsStorage::OnSyncDelete(
418 const std::string& key,
419 const Value& old_value,
420 ExtensionSettingChanges::Builder* changes) {
421 synced_keys_.erase(key);
422 Result result = delegate_->Remove(key);
423 if (result.HasError()) {
424 return SyncError(
425 FROM_HERE,
426 std::string("Error pushing sync remove to local settings: ") +
427 result.GetError(),
428 syncable::EXTENSION_SETTINGS);
429 }
430 changes->AppendChange(key, old_value.DeepCopy(), NULL);
431 return SyncError();
432 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698