This source file includes following definitions.
- flare_
- GetBytesInUse
- GetBytesInUse
- GetBytesInUse
- Get
- Get
- Get
- Remove
- Remove
- Clear
- Restore
- RestoreKey
- SyncResultIfEnabled
- StartSyncing
- SendLocalSettingsToSync
- OverwriteLocalSettingsWithSync
- StopSyncing
- ProcessSyncChanges
- OnSyncAdd
- OnSyncUpdate
- OnSyncDelete
#include "chrome/browser/extensions/api/storage/syncable_settings_storage.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/extensions/api/storage/settings_sync_processor.h"
#include "chrome/browser/extensions/api/storage/settings_sync_util.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/browser/api/storage/settings_namespace.h"
#include "sync/api/sync_data.h"
#include "sync/protocol/extension_setting_specifics.pb.h"
namespace extensions {
using content::BrowserThread;
SyncableSettingsStorage::SyncableSettingsStorage(
const scoped_refptr<ObserverListThreadSafe<SettingsObserver> >&
observers,
const std::string& extension_id,
ValueStore* delegate,
syncer::ModelType sync_type,
const syncer::SyncableService::StartSyncFlare& flare)
: observers_(observers),
extension_id_(extension_id),
delegate_(delegate),
sync_type_(sync_type),
flare_(flare) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
}
SyncableSettingsStorage::~SyncableSettingsStorage() {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
}
size_t SyncableSettingsStorage::GetBytesInUse(const std::string& key) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
return delegate_->GetBytesInUse(key);
}
size_t SyncableSettingsStorage::GetBytesInUse(
const std::vector<std::string>& keys) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
return delegate_->GetBytesInUse(keys);
}
size_t SyncableSettingsStorage::GetBytesInUse() {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
return delegate_->GetBytesInUse();
}
ValueStore::ReadResult SyncableSettingsStorage::Get(
const std::string& key) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
return delegate_->Get(key);
}
ValueStore::ReadResult SyncableSettingsStorage::Get(
const std::vector<std::string>& keys) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
return delegate_->Get(keys);
}
ValueStore::ReadResult SyncableSettingsStorage::Get() {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
return delegate_->Get();
}
ValueStore::WriteResult SyncableSettingsStorage::Set(
WriteOptions options, const std::string& key, const base::Value& value) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
WriteResult result = delegate_->Set(options, key, value);
if (result->HasError()) {
return result.Pass();
}
SyncResultIfEnabled(result);
return result.Pass();
}
ValueStore::WriteResult SyncableSettingsStorage::Set(
WriteOptions options, const base::DictionaryValue& values) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
WriteResult result = delegate_->Set(options, values);
if (result->HasError()) {
return result.Pass();
}
SyncResultIfEnabled(result);
return result.Pass();
}
ValueStore::WriteResult SyncableSettingsStorage::Remove(
const std::string& key) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
WriteResult result = delegate_->Remove(key);
if (result->HasError()) {
return result.Pass();
}
SyncResultIfEnabled(result);
return result.Pass();
}
ValueStore::WriteResult SyncableSettingsStorage::Remove(
const std::vector<std::string>& keys) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
WriteResult result = delegate_->Remove(keys);
if (result->HasError()) {
return result.Pass();
}
SyncResultIfEnabled(result);
return result.Pass();
}
ValueStore::WriteResult SyncableSettingsStorage::Clear() {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
WriteResult result = delegate_->Clear();
if (result->HasError()) {
return result.Pass();
}
SyncResultIfEnabled(result);
return result.Pass();
}
bool SyncableSettingsStorage::Restore() {
StopSyncing();
return delegate_->Restore();
}
bool SyncableSettingsStorage::RestoreKey(const std::string& key) {
StopSyncing();
return delegate_->RestoreKey(key);
}
void SyncableSettingsStorage::SyncResultIfEnabled(
const ValueStore::WriteResult& result) {
if (result->changes().empty())
return;
if (sync_processor_.get()) {
syncer::SyncError error = sync_processor_->SendChanges(result->changes());
if (error.IsSet())
StopSyncing();
} else {
flare_.Run(sync_type_);
}
}
syncer::SyncError SyncableSettingsStorage::StartSyncing(
const base::DictionaryValue& sync_state,
scoped_ptr<SettingsSyncProcessor> sync_processor) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
DCHECK(!sync_processor_.get());
sync_processor_ = sync_processor.Pass();
sync_processor_->Init(sync_state);
ReadResult maybe_settings = delegate_->Get();
if (maybe_settings->HasError()) {
return syncer::SyncError(
FROM_HERE,
syncer::SyncError::DATATYPE_ERROR,
base::StringPrintf("Failed to get settings: %s",
maybe_settings->error().message.c_str()),
sync_processor_->type());
}
const base::DictionaryValue& settings = maybe_settings->settings();
return sync_state.empty() ?
SendLocalSettingsToSync(settings) :
OverwriteLocalSettingsWithSync(sync_state, settings);
}
syncer::SyncError SyncableSettingsStorage::SendLocalSettingsToSync(
const base::DictionaryValue& settings) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
ValueStoreChangeList changes;
for (base::DictionaryValue::Iterator i(settings); !i.IsAtEnd(); i.Advance()) {
changes.push_back(ValueStoreChange(i.key(), NULL, i.value().DeepCopy()));
}
if (changes.empty())
return syncer::SyncError();
syncer::SyncError error = sync_processor_->SendChanges(changes);
if (error.IsSet())
StopSyncing();
return error;
}
syncer::SyncError SyncableSettingsStorage::OverwriteLocalSettingsWithSync(
const base::DictionaryValue& sync_state,
const base::DictionaryValue& settings) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
scoped_ptr<base::DictionaryValue> new_sync_state(sync_state.DeepCopy());
SettingSyncDataList changes;
for (base::DictionaryValue::Iterator it(settings);
!it.IsAtEnd(); it.Advance()) {
scoped_ptr<base::Value> sync_value;
if (new_sync_state->RemoveWithoutPathExpansion(it.key(), &sync_value)) {
if (sync_value->Equals(&it.value())) {
} else {
changes.push_back(
SettingSyncData(
syncer::SyncChange::ACTION_UPDATE,
extension_id_,
it.key(),
sync_value.Pass()));
}
} else {
changes.push_back(
SettingSyncData(
syncer::SyncChange::ACTION_DELETE,
extension_id_,
it.key(),
scoped_ptr<base::Value>(new base::DictionaryValue())));
}
}
while (!new_sync_state->empty()) {
base::DictionaryValue::Iterator first_entry(*new_sync_state);
std::string key = first_entry.key();
scoped_ptr<base::Value> value;
CHECK(new_sync_state->RemoveWithoutPathExpansion(key, &value));
changes.push_back(
SettingSyncData(
syncer::SyncChange::ACTION_ADD,
extension_id_,
key,
value.Pass()));
}
if (changes.empty())
return syncer::SyncError();
return ProcessSyncChanges(changes);
}
void SyncableSettingsStorage::StopSyncing() {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
sync_processor_.reset();
}
syncer::SyncError SyncableSettingsStorage::ProcessSyncChanges(
const SettingSyncDataList& sync_changes) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
DCHECK(!sync_changes.empty()) << "No sync changes for " << extension_id_;
if (!sync_processor_.get()) {
return syncer::SyncError(
FROM_HERE,
syncer::SyncError::DATATYPE_ERROR,
std::string("Sync is inactive for ") + extension_id_,
syncer::UNSPECIFIED);
}
std::vector<syncer::SyncError> errors;
ValueStoreChangeList changes;
for (SettingSyncDataList::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 base::Value& value = it->value();
scoped_ptr<base::Value> current_value;
{
ReadResult maybe_settings = Get(it->key());
if (maybe_settings->HasError()) {
errors.push_back(syncer::SyncError(
FROM_HERE,
syncer::SyncError::DATATYPE_ERROR,
base::StringPrintf("Error getting current sync state for %s/%s: %s",
extension_id_.c_str(), key.c_str(),
maybe_settings->error().message.c_str()),
sync_processor_->type()));
continue;
}
maybe_settings->settings().RemoveWithoutPathExpansion(key,
¤t_value);
}
syncer::SyncError error;
switch (it->change_type()) {
case syncer::SyncChange::ACTION_ADD:
if (!current_value.get()) {
error = OnSyncAdd(key, value.DeepCopy(), &changes);
} else {
LOG(WARNING) << "Got add from sync for existing setting " <<
extension_id_ << "/" << key;
error = OnSyncUpdate(
key, current_value.release(), value.DeepCopy(), &changes);
}
break;
case syncer::SyncChange::ACTION_UPDATE:
if (current_value.get()) {
error = OnSyncUpdate(
key, current_value.release(), value.DeepCopy(), &changes);
} else {
LOG(WARNING) << "Got update from sync for nonexistent setting" <<
extension_id_ << "/" << key;
error = OnSyncAdd(key, value.DeepCopy(), &changes);
}
break;
case syncer::SyncChange::ACTION_DELETE:
if (current_value.get()) {
error = OnSyncDelete(key, current_value.release(), &changes);
} else {
LOG(WARNING) << "Got delete from sync for nonexistent setting " <<
extension_id_ << "/" << key;
}
break;
default:
NOTREACHED();
}
if (error.IsSet()) {
errors.push_back(error);
}
}
sync_processor_->NotifyChanges(changes);
observers_->Notify(
&SettingsObserver::OnSettingsChanged,
extension_id_,
settings_namespace::SYNC,
ValueStoreChange::ToJson(changes));
return errors.empty() ? syncer::SyncError() : errors[0];
}
syncer::SyncError SyncableSettingsStorage::OnSyncAdd(
const std::string& key,
base::Value* new_value,
ValueStoreChangeList* changes) {
DCHECK(new_value);
WriteResult result = delegate_->Set(IGNORE_QUOTA, key, *new_value);
if (result->HasError()) {
return syncer::SyncError(
FROM_HERE,
syncer::SyncError::DATATYPE_ERROR,
base::StringPrintf("Error pushing sync add to local settings: %s",
result->error().message.c_str()),
sync_processor_->type());
}
changes->push_back(ValueStoreChange(key, NULL, new_value));
return syncer::SyncError();
}
syncer::SyncError SyncableSettingsStorage::OnSyncUpdate(
const std::string& key,
base::Value* old_value,
base::Value* new_value,
ValueStoreChangeList* changes) {
DCHECK(old_value);
DCHECK(new_value);
WriteResult result = delegate_->Set(IGNORE_QUOTA, key, *new_value);
if (result->HasError()) {
return syncer::SyncError(
FROM_HERE,
syncer::SyncError::DATATYPE_ERROR,
base::StringPrintf("Error pushing sync update to local settings: %s",
result->error().message.c_str()),
sync_processor_->type());
}
changes->push_back(ValueStoreChange(key, old_value, new_value));
return syncer::SyncError();
}
syncer::SyncError SyncableSettingsStorage::OnSyncDelete(
const std::string& key,
base::Value* old_value,
ValueStoreChangeList* changes) {
DCHECK(old_value);
WriteResult result = delegate_->Remove(key);
if (result->HasError()) {
return syncer::SyncError(
FROM_HERE,
syncer::SyncError::DATATYPE_ERROR,
base::StringPrintf("Error pushing sync remove to local settings: %s",
result->error().message.c_str()),
sync_processor_->type());
}
changes->push_back(ValueStoreChange(key, old_value, NULL));
return syncer::SyncError();
}
}