Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2081)

Unified Diff: chrome/browser/managed_mode/managed_user_shared_settings_service.cc

Issue 123293003: Add ManagedUserSharedSettingsService. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix Created 6 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/managed_mode/managed_user_shared_settings_service.cc
diff --git a/chrome/browser/managed_mode/managed_user_shared_settings_service.cc b/chrome/browser/managed_mode/managed_user_shared_settings_service.cc
new file mode 100644
index 0000000000000000000000000000000000000000..13dbeb596ae441870cfe705f3e2473f3aecc74a2
--- /dev/null
+++ b/chrome/browser/managed_mode/managed_user_shared_settings_service.cc
@@ -0,0 +1,328 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#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) {
+ // A supervised user can only modify their own settings.
+ std::string id = prefs->GetString(prefs::kManagedUserId);
+ DCHECK(id.empty() || id == mu_id);
Pam (message me for reviews) 2014/01/08 10:30:40 Suggest also checking that the mu_id is not empty.
Bernhard Bauer 2014/01/08 11:42:04 Done.
+ }
+
+ 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);
+}
+
+} // namespace
+
+
+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))
Pam (message me for reviews) 2014/01/08 10:30:40 It would be worth documenting these three nested d
Bernhard Bauer 2014/01/08 11:42:04 Done.
+ 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::CallbackList::Subscription>
+ManagedUserSharedSettingsService::Subscribe(
+ const ManagedUserSharedSettingsService::Callback& cb) {
+ return callbacks_.Add(cb);
+}
+
+// static
+void ManagedUserSharedSettingsService::RegisterProfilePrefs(
+ user_prefs::PrefRegistrySyncable* registry) {
+ registry->RegisterDictionaryPref(
+ prefs::kManagedUserSharedSettings,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+}
+
+// static
+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;
Pam (message me for reviews) 2014/01/08 10:30:40 How 'bout some inline comments?
Bernhard Bauer 2014/01/08 11:42:04 Done.
+ 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);
+ // Process all the accumulated changes.
+ if (change_list.size() > 0) {
+ result.set_error(
+ sync_processor_->ProcessSyncChanges(FROM_HERE, change_list));
+ }
+
+ // TODO(bauerb): Statistics?
+ 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: {
+ if (has_key) {
+ // For an update action, the managed user should already exist.
Pam (message me for reviews) 2014/01/08 10:30:40 This comment is backwards from the logic; i.e., it
Bernhard Bauer 2014/01/08 11:42:04 It's a sanity check to make sure that the copy of
+ DCHECK_EQ(SyncChange::ACTION_UPDATE, it->change_type());
+ } else {
+ // For an add action, it should not.
+ 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;
+}

Powered by Google App Engine
This is Rietveld 408576698