Chromium Code Reviews| Index: chrome/browser/managed_mode/managed_user_settings_service.cc |
| diff --git a/chrome/browser/managed_mode/managed_user_settings_service.cc b/chrome/browser/managed_mode/managed_user_settings_service.cc |
| index 7f86b078bfe205398975658b7ae395bb04a215e2..8c8baa3766927720463f4e7be197674b2998d6eb 100644 |
| --- a/chrome/browser/managed_mode/managed_user_settings_service.cc |
| +++ b/chrome/browser/managed_mode/managed_user_settings_service.cc |
| @@ -15,11 +15,25 @@ |
| #include "chrome/common/chrome_constants.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/user_metrics.h" |
| +#include "sync/api/sync_change.h" |
| +#include "sync/api/sync_error_factory.h" |
| +#include "sync/protocol/sync.pb.h" |
| using base::DictionaryValue; |
| +using base::JSONReader; |
| using base::Value; |
| using content::BrowserThread; |
| using content::UserMetricsAction; |
| +using syncer::MANAGED_USER_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; |
| const char kAtomicSettings[] = "atomic_settings"; |
| const char kManagedUserInternalItemPrefix[] = "X-"; |
| @@ -41,6 +55,20 @@ ManagedUserSettingsService::ManagedUserSettingsService() |
| ManagedUserSettingsService::~ManagedUserSettingsService() {} |
| void ManagedUserSettingsService::Init( |
| + base::FilePath profile_path, |
| + base::SequencedTaskRunner* sequenced_task_runner, |
| + bool load_synchronously) { |
| + base::FilePath path = |
| + profile_path.Append(chrome::kManagedUserSettingsFilename); |
| + PersistentPrefStore* store = new JsonPrefStore(path, sequenced_task_runner); |
| + Init(store); |
| + if (load_synchronously) |
| + store_->ReadPrefs(); |
| + else |
| + store_->ReadPrefsAsync(NULL); |
| +} |
| + |
| +void ManagedUserSettingsService::Init( |
| scoped_refptr<PersistentPrefStore> store) { |
| DCHECK(!store_); |
| store_ = store; |
| @@ -69,6 +97,40 @@ void ManagedUserSettingsService::Clear() { |
| store_->RemoveValue(kAtomicSettings); |
| store_->RemoveValue(kSplitSettings); |
| } |
| + |
| +// static |
| +std::string ManagedUserSettingsService::MakeSplitSettingKey( |
| + const std::string& prefix, |
| + const std::string& key) { |
| + return prefix + kSplitSettingKeySeparator + key; |
| +} |
| + |
| +void ManagedUserSettingsService::UploadItem(const std::string& key, |
| + scoped_ptr<Value> value) { |
| + DCHECK(!SettingShouldApplyToPrefs(key)); |
| + |
| + std::string key_suffix = key; |
| + DictionaryValue* dict = NULL; |
| + if (sync_processor_) { |
| + content::RecordAction(UserMetricsAction("ManagedUsers_UploadItem_Syncing")); |
| + dict = GetDictionaryAndSplitKey(&key_suffix); |
| + DCHECK(GetQueuedItems()->empty()); |
| + SyncChangeList change_list; |
| + SyncData data = CreateSyncDataForSetting(key, *value); |
| + SyncChange::SyncChangeType change_type = |
| + dict->HasKey(key_suffix) ? SyncChange::ACTION_UPDATE |
| + : SyncChange::ACTION_ADD; |
| + change_list.push_back(SyncChange(FROM_HERE, change_type, data)); |
| + SyncError error = |
| + sync_processor_->ProcessSyncChanges(FROM_HERE, change_list); |
| + DCHECK(!error.IsSet()) << error.ToString(); |
| + } else { |
| + content::RecordAction(UserMetricsAction("ManagedUsers_UploadItem_Queued")); |
|
Pam (message me for reviews)
2013/09/09 15:13:49
A quick comment here explaining when (whence) queu
Bernhard Bauer
2013/09/09 15:31:31
Done.
|
| + dict = GetQueuedItems(); |
| + } |
| + dict->SetWithoutPathExpansion(key_suffix, value.release()); |
| +} |
| + |
| void ManagedUserSettingsService::SetLocalSettingForTesting( |
| const std::string& key, |
| scoped_ptr<Value> value) { |
| @@ -80,9 +142,148 @@ void ManagedUserSettingsService::SetLocalSettingForTesting( |
| InformSubscribers(); |
| } |
| +// static |
| +SyncData ManagedUserSettingsService::CreateSyncDataForSetting( |
| + const std::string& name, |
| + const Value& value) { |
| + std::string json_value; |
| + base::JSONWriter::Write(&value, &json_value); |
| + ::sync_pb::EntitySpecifics specifics; |
| + specifics.mutable_managed_user_setting()->set_name(name); |
| + specifics.mutable_managed_user_setting()->set_value(json_value); |
| + return SyncData::CreateLocalData(name, name, specifics); |
| +} |
| + |
| void ManagedUserSettingsService::Shutdown() { |
| store_->RemoveObserver(this); |
| } |
| + |
| +SyncMergeResult ManagedUserSettingsService::MergeDataAndStartSyncing( |
|
Pam (message me for reviews)
2013/09/09 15:13:49
I'm assuming the bulk of this is copied from the p
Bernhard Bauer
2013/09/09 15:31:31
That is correct.
|
| + ModelType type, |
| + const SyncDataList& initial_sync_data, |
| + scoped_ptr<SyncChangeProcessor> sync_processor, |
| + scoped_ptr<SyncErrorFactory> error_handler) { |
| + DCHECK_EQ(MANAGED_USER_SETTINGS, type); |
| + sync_processor_ = sync_processor.Pass(); |
| + error_handler_ = error_handler.Pass(); |
| + |
| + // Clear all atomic and split settings, then recreate them from Sync data. |
| + Clear(); |
| + for (SyncDataList::const_iterator it = initial_sync_data.begin(); |
| + it != initial_sync_data.end(); ++it) { |
| + DCHECK_EQ(MANAGED_USER_SETTINGS, it->GetDataType()); |
| + const ::sync_pb::ManagedUserSettingSpecifics& managed_user_setting = |
| + it->GetSpecifics().managed_user_setting(); |
| + scoped_ptr<Value> value(JSONReader::Read(managed_user_setting.value())); |
| + std::string name_suffix = managed_user_setting.name(); |
| + DictionaryValue* dict = GetDictionaryAndSplitKey(&name_suffix); |
| + dict->SetWithoutPathExpansion(name_suffix, value.release()); |
| + } |
| + store_->ReportValueChanged(kAtomicSettings); |
| + store_->ReportValueChanged(kSplitSettings); |
| + InformSubscribers(); |
| + |
| + // Upload all the queued up items (either with an ADD or an UPDATE action, |
| + // depending on whether they already exist) and move them to split settings. |
| + SyncChangeList change_list; |
| + DictionaryValue* queued_items = GetQueuedItems(); |
| + for (DictionaryValue::Iterator it(*queued_items); !it.IsAtEnd(); |
| + it.Advance()) { |
| + std::string key_suffix = it.key(); |
| + DictionaryValue* dict = GetDictionaryAndSplitKey(&key_suffix); |
| + SyncData data = CreateSyncDataForSetting(it.key(), it.value()); |
| + SyncChange::SyncChangeType change_type = |
| + dict->HasKey(key_suffix) ? SyncChange::ACTION_UPDATE |
| + : SyncChange::ACTION_ADD; |
| + change_list.push_back(SyncChange(FROM_HERE, change_type, data)); |
| + dict->SetWithoutPathExpansion(key_suffix, it.value().DeepCopy()); |
| + } |
| + queued_items->Clear(); |
| + |
| + SyncMergeResult result(MANAGED_USER_SETTINGS); |
| + // Process all the accumulated changes from the queued items. |
| + if (change_list.size() > 0) { |
| + store_->ReportValueChanged(kQueuedItems); |
| + result.set_error( |
| + sync_processor_->ProcessSyncChanges(FROM_HERE, change_list)); |
| + } |
| + |
| + // TODO(bauerb): Statistics? |
| + return result; |
| +} |
| + |
| +void ManagedUserSettingsService::StopSyncing(ModelType type) { |
| + DCHECK_EQ(syncer::MANAGED_USER_SETTINGS, type); |
| + sync_processor_.reset(); |
| + error_handler_.reset(); |
| +} |
| + |
| +SyncDataList ManagedUserSettingsService::GetAllSyncData( |
| + ModelType type) const { |
| + DCHECK_EQ(syncer::MANAGED_USER_SETTINGS, type); |
| + SyncDataList data; |
| + for (DictionaryValue::Iterator it(*GetAtomicSettings()); !it.IsAtEnd(); |
| + it.Advance()) { |
| + data.push_back(CreateSyncDataForSetting(it.key(), it.value())); |
| + } |
| + for (DictionaryValue::Iterator it(*GetSplitSettings()); !it.IsAtEnd(); |
| + it.Advance()) { |
| + const DictionaryValue* dict = NULL; |
| + it.value().GetAsDictionary(&dict); |
| + for (DictionaryValue::Iterator jt(*dict); !jt.IsAtEnd(); jt.Advance()) { |
| + data.push_back(CreateSyncDataForSetting( |
| + MakeSplitSettingKey(it.key(), jt.key()), jt.value())); |
| + } |
| + } |
| + DCHECK_EQ(0u, GetQueuedItems()->size()); |
| + return data; |
| +} |
| + |
| +SyncError ManagedUserSettingsService::ProcessSyncChanges( |
| + const tracked_objects::Location& from_here, |
| + const 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_SETTINGS, data.GetDataType()); |
| + const ::sync_pb::ManagedUserSettingSpecifics& managed_user_setting = |
| + data.GetSpecifics().managed_user_setting(); |
| + std::string key = managed_user_setting.name(); |
| + DictionaryValue* dict = GetDictionaryAndSplitKey(&key); |
| + switch (it->change_type()) { |
| + case SyncChange::ACTION_ADD: |
| + case SyncChange::ACTION_UPDATE: { |
| + scoped_ptr<Value> value(JSONReader::Read(managed_user_setting.value())); |
| + if (dict->HasKey(key)) { |
| + DLOG_IF(WARNING, it->change_type() == SyncChange::ACTION_ADD) |
| + << "Value for key " << key << " already exists"; |
| + } else { |
| + DLOG_IF(WARNING, it->change_type() == SyncChange::ACTION_UPDATE) |
| + << "Value for key " << key << " doesn't exist yet"; |
| + } |
| + dict->SetWithoutPathExpansion(key, value.release()); |
| + break; |
| + } |
| + case SyncChange::ACTION_DELETE: { |
| + DLOG_IF(WARNING, !dict->HasKey(key)) << "Trying to delete nonexistent " |
| + << "key " << key; |
| + dict->RemoveWithoutPathExpansion(key, NULL); |
| + break; |
| + } |
| + case SyncChange::ACTION_INVALID: { |
| + NOTREACHED(); |
| + break; |
| + } |
| + } |
| + } |
| + store_->ReportValueChanged(kAtomicSettings); |
| + store_->ReportValueChanged(kSplitSettings); |
| + InformSubscribers(); |
| + |
| + SyncError error; |
| + return error; |
| +} |
| + |
| void ManagedUserSettingsService::OnPrefValueChanged(const std::string& key) {} |
| void ManagedUserSettingsService::OnInitializationCompleted(bool success) { |
| @@ -118,6 +319,24 @@ DictionaryValue* ManagedUserSettingsService::GetQueuedItems() const { |
| return GetOrCreateDictionary(kQueuedItems); |
| } |
| +DictionaryValue* ManagedUserSettingsService::GetDictionaryAndSplitKey( |
| + std::string* key) const { |
| + size_t pos = key->find_first_of(kSplitSettingKeySeparator); |
| + if (pos == std::string::npos) |
| + return GetAtomicSettings(); |
| + |
| + DictionaryValue* split_settings = GetSplitSettings(); |
| + std::string prefix = key->substr(0, pos); |
| + DictionaryValue* dict = NULL; |
| + if (!split_settings->GetDictionary(prefix, &dict)) { |
| + dict = new DictionaryValue; |
| + DCHECK(!split_settings->HasKey(prefix)); |
| + split_settings->Set(prefix, dict); |
| + } |
| + key->erase(0, pos + 1); |
| + return dict; |
| +} |
| + |
| scoped_ptr<DictionaryValue> ManagedUserSettingsService::GetSettings() { |
| DCHECK(IsReady()); |
| if (!active_) |