This source file includes following definitions.
- FindOrCreateDictionary
- mu_id_
- Get
- CreateSyncDataForValue
- SetValueInternal
- GetValue
- SetValue
- Subscribe
- RegisterProfilePrefs
- CreateSyncDataForSetting
- Shutdown
- MergeDataAndStartSyncing
- StopSyncing
- GetAllSyncData
- ProcessSyncChanges
#include "chrome/browser/managed_mode/managed_user_shared_settings_service.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/prefs/pref_service.h"
#include "base/prefs/scoped_user_pref_update.h"
#include "base/values.h"
#include "chrome/common/pref_names.h"
#include "components/user_prefs/pref_registry_syncable.h"
#include "sync/api/sync_change.h"
#include "sync/api/sync_data.h"
#include "sync/api/sync_error.h"
#include "sync/api/sync_error_factory.h"
#include "sync/api/sync_merge_result.h"
#include "sync/protocol/sync.pb.h"
using base::DictionaryValue;
using base::Value;
using syncer::MANAGED_USER_SHARED_SETTINGS;
using syncer::ModelType;
using syncer::SyncChange;
using syncer::SyncChangeList;
using syncer::SyncChangeProcessor;
using syncer::SyncData;
using syncer::SyncDataList;
using syncer::SyncError;
using syncer::SyncErrorFactory;
using syncer::SyncMergeResult;
namespace {
const char kAcknowledged[] = "acknowledged";
const char kValue[] = "value";
DictionaryValue* FindOrCreateDictionary(DictionaryValue* parent,
const std::string& key) {
DictionaryValue* dict = NULL;
if (!parent->GetDictionaryWithoutPathExpansion(key, &dict)) {
dict = new DictionaryValue;
parent->SetWithoutPathExpansion(key, dict);
}
return dict;
}
class ScopedManagedUserSharedSettingsUpdate {
public:
ScopedManagedUserSharedSettingsUpdate(PrefService* prefs,
const std::string& mu_id)
: update_(prefs, prefs::kManagedUserSharedSettings), mu_id_(mu_id) {
DCHECK(!mu_id.empty());
std::string id = prefs->GetString(prefs::kManagedUserId);
DCHECK(id.empty() || id == mu_id);
}
DictionaryValue* Get() {
return FindOrCreateDictionary(update_.Get(), mu_id_);
}
private:
DictionaryPrefUpdate update_;
std::string mu_id_;
};
SyncData CreateSyncDataForValue(
const std::string& mu_id,
const std::string& key,
const Value& dict_value) {
const DictionaryValue* dict = NULL;
if (!dict_value.GetAsDictionary(&dict))
return SyncData();
const Value* value = NULL;
if (!dict->Get(kValue, &value))
return SyncData();
bool acknowledged = false;
dict->GetBoolean(kAcknowledged, &acknowledged);
return ManagedUserSharedSettingsService::CreateSyncDataForSetting(
mu_id, key, *value, acknowledged);
}
}
ManagedUserSharedSettingsService::ManagedUserSharedSettingsService(
PrefService* prefs)
: prefs_(prefs) {}
ManagedUserSharedSettingsService::~ManagedUserSharedSettingsService() {}
void ManagedUserSharedSettingsService::SetValueInternal(
const std::string& mu_id,
const std::string& key,
const Value& value,
bool acknowledged) {
ScopedManagedUserSharedSettingsUpdate update(prefs_, mu_id);
DictionaryValue* update_dict = update.Get();
DictionaryValue* dict = NULL;
bool has_key = update_dict->GetDictionaryWithoutPathExpansion(key, &dict);
if (!has_key) {
dict = new DictionaryValue;
update_dict->SetWithoutPathExpansion(key, dict);
}
dict->SetWithoutPathExpansion(kValue, value.DeepCopy());
dict->SetBooleanWithoutPathExpansion(kAcknowledged, acknowledged);
if (!sync_processor_)
return;
SyncData data = CreateSyncDataForSetting(mu_id, key, value, acknowledged);
SyncChange::SyncChangeType change_type =
has_key ? SyncChange::ACTION_UPDATE : SyncChange::ACTION_ADD;
SyncChangeList changes;
changes.push_back(SyncChange(FROM_HERE, change_type, data));
SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, changes);
DCHECK(!error.IsSet()) << error.ToString();
}
const Value* ManagedUserSharedSettingsService::GetValue(
const std::string& mu_id,
const std::string& key) {
const DictionaryValue* data =
prefs_->GetDictionary(prefs::kManagedUserSharedSettings);
const DictionaryValue* dict = NULL;
if (!data->GetDictionaryWithoutPathExpansion(mu_id, &dict))
return NULL;
const DictionaryValue* settings = NULL;
if (!dict->GetDictionaryWithoutPathExpansion(key, &settings))
return NULL;
const Value* value = NULL;
if (!settings->GetWithoutPathExpansion(kValue, &value))
return NULL;
return value;
}
void ManagedUserSharedSettingsService::SetValue(
const std::string& mu_id,
const std::string& key,
const Value& value) {
SetValueInternal(mu_id, key, value, true);
}
scoped_ptr<ManagedUserSharedSettingsService::ChangeCallbackList::Subscription>
ManagedUserSharedSettingsService::Subscribe(
const ManagedUserSharedSettingsService::ChangeCallback& cb) {
return callbacks_.Add(cb);
}
void ManagedUserSharedSettingsService::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterDictionaryPref(
prefs::kManagedUserSharedSettings,
user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
}
SyncData ManagedUserSharedSettingsService::CreateSyncDataForSetting(
const std::string& mu_id,
const std::string& key,
const Value& value,
bool acknowledged) {
std::string json_value;
base::JSONWriter::Write(&value, &json_value);
::sync_pb::EntitySpecifics specifics;
specifics.mutable_managed_user_shared_setting()->set_mu_id(mu_id);
specifics.mutable_managed_user_shared_setting()->set_key(key);
specifics.mutable_managed_user_shared_setting()->set_value(json_value);
specifics.mutable_managed_user_shared_setting()->set_acknowledged(
acknowledged);
std::string title = mu_id + ":" + key;
return SyncData::CreateLocalData(title, title, specifics);
}
void ManagedUserSharedSettingsService::Shutdown() {}
syncer::SyncMergeResult
ManagedUserSharedSettingsService::MergeDataAndStartSyncing(
syncer::ModelType type,
const syncer::SyncDataList& initial_sync_data,
scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
scoped_ptr<syncer::SyncErrorFactory> error_handler) {
DCHECK_EQ(MANAGED_USER_SHARED_SETTINGS, type);
sync_processor_ = sync_processor.Pass();
error_handler_ = error_handler.Pass();
std::map<std::string, std::set<std::string> > seen_keys;
for (SyncDataList::const_iterator it = initial_sync_data.begin();
it != initial_sync_data.end();
++it) {
DCHECK_EQ(MANAGED_USER_SHARED_SETTINGS, it->GetDataType());
const ::sync_pb::ManagedUserSharedSettingSpecifics&
managed_user_shared_setting =
it->GetSpecifics().managed_user_shared_setting();
scoped_ptr<Value> value(
base::JSONReader::Read(managed_user_shared_setting.value()));
const std::string& mu_id = managed_user_shared_setting.mu_id();
ScopedManagedUserSharedSettingsUpdate update(prefs_, mu_id);
const std::string& key = managed_user_shared_setting.key();
DictionaryValue* dict = FindOrCreateDictionary(update.Get(), key);
dict->SetWithoutPathExpansion(kValue, value.release());
DCHECK(managed_user_shared_setting.acknowledged());
dict->SetBooleanWithoutPathExpansion(
kAcknowledged, managed_user_shared_setting.acknowledged());
callbacks_.Notify(mu_id, key);
seen_keys[mu_id].insert(key);
}
SyncChangeList change_list;
const DictionaryValue* all_settings =
prefs_->GetDictionary(prefs::kManagedUserSharedSettings);
for (DictionaryValue::Iterator it(*all_settings); !it.IsAtEnd();
it.Advance()) {
const DictionaryValue* dict = NULL;
bool success = it.value().GetAsDictionary(&dict);
DCHECK(success);
const std::set<std::string>& seen = seen_keys[it.key()];
for (DictionaryValue::Iterator jt(*dict); !jt.IsAtEnd(); jt.Advance()) {
if (seen.count(jt.key()) > 0)
continue;
SyncData data = CreateSyncDataForValue(it.key(), jt.key(), jt.value());
DCHECK(data.IsValid());
change_list.push_back(
SyncChange(FROM_HERE, SyncChange::ACTION_ADD, data));
}
}
SyncMergeResult result(MANAGED_USER_SHARED_SETTINGS);
if (change_list.size() > 0) {
result.set_error(
sync_processor_->ProcessSyncChanges(FROM_HERE, change_list));
}
return result;
}
void ManagedUserSharedSettingsService::StopSyncing(syncer::ModelType type) {
DCHECK_EQ(MANAGED_USER_SHARED_SETTINGS, type);
sync_processor_.reset();
error_handler_.reset();
}
syncer::SyncDataList ManagedUserSharedSettingsService::GetAllSyncData(
syncer::ModelType type) const {
DCHECK_EQ(MANAGED_USER_SHARED_SETTINGS, type);
SyncDataList data;
const DictionaryValue* all_settings =
prefs_->GetDictionary(prefs::kManagedUserSharedSettings);
for (DictionaryValue::Iterator it(*all_settings); !it.IsAtEnd();
it.Advance()) {
const DictionaryValue* dict = NULL;
bool success = it.value().GetAsDictionary(&dict);
DCHECK(success);
for (DictionaryValue::Iterator jt(*dict); !jt.IsAtEnd(); jt.Advance()) {
data.push_back(CreateSyncDataForValue(it.key(), jt.key(), jt.value()));
}
}
return data;
}
syncer::SyncError ManagedUserSharedSettingsService::ProcessSyncChanges(
const tracked_objects::Location& from_here,
const syncer::SyncChangeList& change_list) {
for (SyncChangeList::const_iterator it = change_list.begin();
it != change_list.end();
++it) {
SyncData data = it->sync_data();
DCHECK_EQ(MANAGED_USER_SHARED_SETTINGS, data.GetDataType());
const ::sync_pb::ManagedUserSharedSettingSpecifics&
managed_user_shared_setting =
data.GetSpecifics().managed_user_shared_setting();
const std::string& key = managed_user_shared_setting.key();
const std::string& mu_id = managed_user_shared_setting.mu_id();
ScopedManagedUserSharedSettingsUpdate update(prefs_, mu_id);
DictionaryValue* update_dict = update.Get();
DictionaryValue* dict = NULL;
bool has_key = update_dict->GetDictionaryWithoutPathExpansion(key, &dict);
switch (it->change_type()) {
case SyncChange::ACTION_ADD:
case SyncChange::ACTION_UPDATE: {
DCHECK(managed_user_shared_setting.acknowledged());
if (has_key) {
DCHECK_EQ(SyncChange::ACTION_UPDATE, it->change_type());
} else {
DCHECK_EQ(SyncChange::ACTION_ADD, it->change_type());
dict = new DictionaryValue;
update_dict->SetWithoutPathExpansion(key, dict);
}
scoped_ptr<Value> value(
base::JSONReader::Read(managed_user_shared_setting.value()));
dict->SetWithoutPathExpansion(kValue, value.release());
dict->SetBooleanWithoutPathExpansion(
kAcknowledged, managed_user_shared_setting.acknowledged());
break;
}
case SyncChange::ACTION_DELETE: {
if (has_key)
update_dict->RemoveWithoutPathExpansion(key, NULL);
else
NOTREACHED() << "Trying to delete nonexistent key " << key;
break;
}
case SyncChange::ACTION_INVALID: {
NOTREACHED();
break;
}
}
callbacks_.Notify(mu_id, key);
}
SyncError error;
return error;
}