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..6f4721002d73ba4a43c763001d794056b2ae0062 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,42 @@ 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 { |
+ // Queue the item up to be uploaded when we start syncing |
+ // (in MergeDataAndStartSyncing()). |
+ content::RecordAction(UserMetricsAction("ManagedUsers_UploadItem_Queued")); |
+ dict = GetQueuedItems(); |
+ } |
+ dict->SetWithoutPathExpansion(key_suffix, value.release()); |
+} |
+ |
void ManagedUserSettingsService::SetLocalSettingForTesting( |
const std::string& key, |
scoped_ptr<Value> value) { |
@@ -80,9 +144,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( |
+ 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 +321,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_) |