diff options
author | kalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-22 03:32:07 +0000 |
---|---|---|
committer | kalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-22 03:32:07 +0000 |
commit | be80eae925e1bb08b0584e55cd47accceba09390 (patch) | |
tree | 2209732664ad91da73883747415c1bddb60ab25c /chrome/browser/extensions/syncable_extension_settings_storage.cc | |
parent | 15245b8b5298a41363183deba5f5e156c6d0ac74 (diff) | |
download | chromium_src-be80eae925e1bb08b0584e55cd47accceba09390.zip chromium_src-be80eae925e1bb08b0584e55cd47accceba09390.tar.gz chromium_src-be80eae925e1bb08b0584e55cd47accceba09390.tar.bz2 |
Re-commit 106660 with the crashing test disabled. Reverted in 106671.
Add onChanged events to the extension settings API, both from sync and between
split mode background pages.
BUG=97545
TEST=ExtensionSettingsStorageUnittest, ExtensionSettingsSyncUnittest, ExtensionSettingsApitest
Review URL: http://codereview.chromium.org/8177022
TBR=rsleevi@chromium.org
Review URL: http://codereview.chromium.org/8361027
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@106848 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/extensions/syncable_extension_settings_storage.cc')
-rw-r--r-- | chrome/browser/extensions/syncable_extension_settings_storage.cc | 161 |
1 files changed, 137 insertions, 24 deletions
diff --git a/chrome/browser/extensions/syncable_extension_settings_storage.cc b/chrome/browser/extensions/syncable_extension_settings_storage.cc index f9820f4..8ec5d17 100644 --- a/chrome/browser/extensions/syncable_extension_settings_storage.cc +++ b/chrome/browser/extensions/syncable_extension_settings_storage.cc @@ -11,8 +11,14 @@ #include "content/browser/browser_thread.h" SyncableExtensionSettingsStorage::SyncableExtensionSettingsStorage( - std::string extension_id, ExtensionSettingsStorage* delegate) - : extension_id_(extension_id), delegate_(delegate), sync_processor_(NULL) { + const scoped_refptr<ObserverListThreadSafe<ExtensionSettingsObserver> >& + observers, + const std::string& extension_id, + ExtensionSettingsStorage* delegate) + : observers_(observers), + extension_id_(extension_id), + delegate_(delegate), + sync_processor_(NULL) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); } @@ -118,7 +124,7 @@ SyncError SyncableExtensionSettingsStorage::StartSyncing( syncable::EXTENSION_SETTINGS); } - DictionaryValue* settings = maybe_settings.GetSettings(); + const DictionaryValue* settings = maybe_settings.GetSettings(); if (sync_state.empty()) { return SendLocalSettingsToSync(*settings); } @@ -224,43 +230,88 @@ std::vector<SyncError> SyncableExtensionSettingsStorage::ProcessSyncChanges( DCHECK(!sync_changes.empty()) << "No sync changes for " << extension_id_; std::vector<SyncError> errors; + ExtensionSettingChanges::Builder changes; for (ExtensionSettingSyncDataList::const_iterator it = sync_changes.begin(); it != sync_changes.end(); ++it) { DCHECK_EQ(extension_id_, it->extension_id()); + + const std::string& key = it->key(); + const Value& value = it->value(); + + scoped_ptr<Value> current_value; + { + Result maybe_settings = Get(it->key()); + if (maybe_settings.HasError()) { + errors.push_back(SyncError( + FROM_HERE, + std::string("Error getting current sync state for ") + + extension_id_ + "/" + key + ": " + maybe_settings.GetError(), + syncable::EXTENSION_SETTINGS)); + continue; + } + const DictionaryValue* settings = maybe_settings.GetSettings(); + if (settings) { + Value* value = NULL; + if (settings->GetWithoutPathExpansion(key, &value)) { + current_value.reset(value->DeepCopy()); + } + } + } + + SyncError error; + switch (it->change_type()) { case SyncChange::ACTION_ADD: - case SyncChange::ACTION_UPDATE: { - synced_keys_.insert(it->key()); - Result result = delegate_->Set(it->key(), it->value()); - if (result.HasError()) { - errors.push_back(SyncError( - FROM_HERE, - std::string("Error pushing sync change to local settings: ") + - result.GetError(), - syncable::EXTENSION_SETTINGS)); + if (!current_value.get()) { + error = OnSyncAdd(key, value.DeepCopy(), &changes); + } else { + // Already a value; hopefully a local change has beaten sync in a + // race and it's not a bug, so pretend it's an update. + LOG(WARNING) << "Got add from sync for existing setting " << + extension_id_ << "/" << key; + error = OnSyncUpdate( + key, current_value.release(), value.DeepCopy(), &changes); } break; - } - case SyncChange::ACTION_DELETE: { - synced_keys_.erase(it->key()); - Result result = delegate_->Remove(it->key()); - if (result.HasError()) { - errors.push_back(SyncError( - FROM_HERE, - std::string("Error removing sync change from local settings: ") + - result.GetError(), - syncable::EXTENSION_SETTINGS)); + case SyncChange::ACTION_UPDATE: + if (current_value.get()) { + error = OnSyncUpdate( + key, current_value.release(), value.DeepCopy(), &changes); + } else { + // Similarly, pretend it's an add. + LOG(WARNING) << "Got update from sync for nonexistent setting" << + extension_id_ << "/" << key; + error = OnSyncAdd(key, value.DeepCopy(), &changes); + } + break; + + case SyncChange::ACTION_DELETE: + if (current_value.get()) { + error = OnSyncDelete(key, current_value.release(), &changes); + } else { + // Similarly, ignore it. + LOG(WARNING) << "Got delete from sync for nonexistent setting " << + extension_id_ << "/" << key; } break; - } default: NOTREACHED(); } + + if (error.IsSet()) { + errors.push_back(error); + } } + observers_->Notify( + &ExtensionSettingsObserver::OnSettingsChanged, + static_cast<Profile*>(NULL), + extension_id_, + changes.Build()); + return errors; } @@ -307,11 +358,18 @@ void SyncableExtensionSettingsStorage::SendDeletesToSync( SyncChangeList changes; for (std::set<std::string>::const_iterator it = keys.begin(); it != keys.end(); ++it) { - DCHECK(synced_keys_.count(*it)); + if (!synced_keys_.count(*it)) { + LOG(WARNING) << "Deleted " << *it << " but no entry in synced_keys"; + continue; + } changes.push_back( extension_settings_sync_util::CreateDelete(extension_id_, *it)); } + if (changes.empty()) { + return; + } + SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, changes); if (error.IsSet()) { LOG(WARNING) << "Failed to send changes to sync: " << error.message(); @@ -323,3 +381,58 @@ void SyncableExtensionSettingsStorage::SendDeletesToSync( synced_keys_.erase(*it); } } + +SyncError SyncableExtensionSettingsStorage::OnSyncAdd( + const std::string& key, + Value* new_value, + ExtensionSettingChanges::Builder* changes) { + DCHECK(new_value); + synced_keys_.insert(key); + Result result = delegate_->Set(key, *new_value); + if (result.HasError()) { + return SyncError( + FROM_HERE, + std::string("Error pushing sync add to local settings: ") + + result.GetError(), + syncable::EXTENSION_SETTINGS); + } + changes->AppendChange(key, NULL, new_value); + return SyncError(); +} + +SyncError SyncableExtensionSettingsStorage::OnSyncUpdate( + const std::string& key, + Value* old_value, + Value* new_value, + ExtensionSettingChanges::Builder* changes) { + DCHECK(old_value); + DCHECK(new_value); + Result result = delegate_->Set(key, *new_value); + if (result.HasError()) { + return SyncError( + FROM_HERE, + std::string("Error pushing sync update to local settings: ") + + result.GetError(), + syncable::EXTENSION_SETTINGS); + } + changes->AppendChange(key, old_value, new_value); + return SyncError(); +} + +SyncError SyncableExtensionSettingsStorage::OnSyncDelete( + const std::string& key, + Value* old_value, + ExtensionSettingChanges::Builder* changes) { + DCHECK(old_value); + synced_keys_.erase(key); + Result result = delegate_->Remove(key); + if (result.HasError()) { + return SyncError( + FROM_HERE, + std::string("Error pushing sync remove to local settings: ") + + result.GetError(), + syncable::EXTENSION_SETTINGS); + } + changes->AppendChange(key, old_value, NULL); + return SyncError(); +} |