Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / supervised_user / legacy / supervised_user_shared_settings_service.cc
blobddd6f295ba6a3eb4f81e6df6414d3d55ea9ce92a
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/supervised_user/legacy/supervised_user_shared_settings_service.h"
7 #include <map>
8 #include <set>
10 #include "base/json/json_reader.h"
11 #include "base/json/json_writer.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/prefs/scoped_user_pref_update.h"
14 #include "base/values.h"
15 #include "chrome/common/pref_names.h"
16 #include "components/pref_registry/pref_registry_syncable.h"
17 #include "sync/api/sync_change.h"
18 #include "sync/api/sync_data.h"
19 #include "sync/api/sync_error.h"
20 #include "sync/api/sync_error_factory.h"
21 #include "sync/api/sync_merge_result.h"
22 #include "sync/protocol/sync.pb.h"
24 using base::DictionaryValue;
25 using base::Value;
26 using syncer::ModelType;
27 using syncer::SUPERVISED_USER_SHARED_SETTINGS;
28 using syncer::SyncChange;
29 using syncer::SyncChangeList;
30 using syncer::SyncChangeProcessor;
31 using syncer::SyncData;
32 using syncer::SyncDataList;
33 using syncer::SyncError;
34 using syncer::SyncErrorFactory;
35 using syncer::SyncMergeResult;
37 namespace {
39 const char kAcknowledged[] = "acknowledged";
40 const char kValue[] = "value";
42 DictionaryValue* FindOrCreateDictionary(DictionaryValue* parent,
43 const std::string& key) {
44 DictionaryValue* dict = NULL;
45 if (!parent->GetDictionaryWithoutPathExpansion(key, &dict)) {
46 dict = new DictionaryValue;
47 parent->SetWithoutPathExpansion(key, dict);
49 return dict;
52 class ScopedSupervisedUserSharedSettingsUpdate {
53 public:
54 ScopedSupervisedUserSharedSettingsUpdate(PrefService* prefs,
55 const std::string& su_id)
56 : update_(prefs, prefs::kSupervisedUserSharedSettings), su_id_(su_id) {
57 DCHECK(!su_id.empty());
59 // A supervised user can only modify their own settings.
60 std::string id = prefs->GetString(prefs::kSupervisedUserId);
61 DCHECK(id.empty() || id == su_id);
64 DictionaryValue* Get() {
65 return FindOrCreateDictionary(update_.Get(), su_id_);
68 private:
69 DictionaryPrefUpdate update_;
70 std::string su_id_;
73 SyncData CreateSyncDataForValue(
74 const std::string& su_id,
75 const std::string& key,
76 const Value& dict_value) {
77 const DictionaryValue* dict = NULL;
78 if (!dict_value.GetAsDictionary(&dict))
79 return SyncData();
81 const Value* value = NULL;
82 if (!dict->Get(kValue, &value))
83 return SyncData();
85 bool acknowledged = false;
86 dict->GetBoolean(kAcknowledged, &acknowledged);
88 return SupervisedUserSharedSettingsService::CreateSyncDataForSetting(
89 su_id, key, *value, acknowledged);
92 } // namespace
95 SupervisedUserSharedSettingsService::SupervisedUserSharedSettingsService(
96 PrefService* prefs)
97 : prefs_(prefs) {}
99 SupervisedUserSharedSettingsService::~SupervisedUserSharedSettingsService() {}
101 void SupervisedUserSharedSettingsService::SetValueInternal(
102 const std::string& su_id,
103 const std::string& key,
104 const Value& value,
105 bool acknowledged) {
106 ScopedSupervisedUserSharedSettingsUpdate update(prefs_, su_id);
107 DictionaryValue* update_dict = update.Get();
109 DictionaryValue* dict = NULL;
110 bool has_key = update_dict->GetDictionaryWithoutPathExpansion(key, &dict);
111 if (!has_key) {
112 dict = new DictionaryValue;
113 update_dict->SetWithoutPathExpansion(key, dict);
115 dict->SetWithoutPathExpansion(kValue, value.DeepCopy());
116 dict->SetBooleanWithoutPathExpansion(kAcknowledged, acknowledged);
118 if (!sync_processor_)
119 return;
121 SyncData data = CreateSyncDataForSetting(su_id, key, value, acknowledged);
122 SyncChange::SyncChangeType change_type =
123 has_key ? SyncChange::ACTION_UPDATE : SyncChange::ACTION_ADD;
124 SyncChangeList changes;
125 changes.push_back(SyncChange(FROM_HERE, change_type, data));
126 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, changes);
127 DCHECK(!error.IsSet()) << error.ToString();
130 const Value* SupervisedUserSharedSettingsService::GetValue(
131 const std::string& su_id,
132 const std::string& key) {
133 const DictionaryValue* data =
134 prefs_->GetDictionary(prefs::kSupervisedUserSharedSettings);
135 const DictionaryValue* dict = NULL;
136 if (!data->GetDictionaryWithoutPathExpansion(su_id, &dict))
137 return NULL;
139 const DictionaryValue* settings = NULL;
140 if (!dict->GetDictionaryWithoutPathExpansion(key, &settings))
141 return NULL;
143 const Value* value = NULL;
144 if (!settings->GetWithoutPathExpansion(kValue, &value))
145 return NULL;
147 return value;
150 void SupervisedUserSharedSettingsService::SetValue(
151 const std::string& su_id,
152 const std::string& key,
153 const Value& value) {
154 SetValueInternal(su_id, key, value, true);
157 scoped_ptr<
158 SupervisedUserSharedSettingsService::ChangeCallbackList::Subscription>
159 SupervisedUserSharedSettingsService::Subscribe(
160 const SupervisedUserSharedSettingsService::ChangeCallback& cb) {
161 return callbacks_.Add(cb);
164 // static
165 void SupervisedUserSharedSettingsService::RegisterProfilePrefs(
166 user_prefs::PrefRegistrySyncable* registry) {
167 registry->RegisterDictionaryPref(
168 prefs::kSupervisedUserSharedSettings,
169 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
172 // static
173 SyncData SupervisedUserSharedSettingsService::CreateSyncDataForSetting(
174 const std::string& su_id,
175 const std::string& key,
176 const Value& value,
177 bool acknowledged) {
178 std::string json_value;
179 base::JSONWriter::Write(&value, &json_value);
180 ::sync_pb::EntitySpecifics specifics;
181 specifics.mutable_managed_user_shared_setting()->set_mu_id(su_id);
182 specifics.mutable_managed_user_shared_setting()->set_key(key);
183 specifics.mutable_managed_user_shared_setting()->set_value(json_value);
184 specifics.mutable_managed_user_shared_setting()->set_acknowledged(
185 acknowledged);
186 std::string title = su_id + ":" + key;
187 return SyncData::CreateLocalData(title, title, specifics);
190 void SupervisedUserSharedSettingsService::Shutdown() {}
192 syncer::SyncMergeResult
193 SupervisedUserSharedSettingsService::MergeDataAndStartSyncing(
194 syncer::ModelType type,
195 const syncer::SyncDataList& initial_sync_data,
196 scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
197 scoped_ptr<syncer::SyncErrorFactory> error_handler) {
198 DCHECK_EQ(SUPERVISED_USER_SHARED_SETTINGS, type);
199 sync_processor_ = sync_processor.Pass();
200 error_handler_ = error_handler.Pass();
202 // We keep a map from MU ID to the set of keys that we have seen in the
203 // initial sync data.
204 std::map<std::string, std::set<std::string> > seen_keys;
206 // Iterate over all initial sync data, and update it locally. This means that
207 // the value from the server always wins over a local value.
208 for (const SyncData& sync_data : initial_sync_data) {
209 DCHECK_EQ(SUPERVISED_USER_SHARED_SETTINGS, sync_data.GetDataType());
210 const ::sync_pb::ManagedUserSharedSettingSpecifics&
211 supervised_user_shared_setting =
212 sync_data.GetSpecifics().managed_user_shared_setting();
213 scoped_ptr<Value> value(
214 base::JSONReader::Read(supervised_user_shared_setting.value()));
215 const std::string& su_id = supervised_user_shared_setting.mu_id();
216 ScopedSupervisedUserSharedSettingsUpdate update(prefs_, su_id);
217 const std::string& key = supervised_user_shared_setting.key();
218 DictionaryValue* dict = FindOrCreateDictionary(update.Get(), key);
219 dict->SetWithoutPathExpansion(kValue, value.release());
221 // Every setting we get from the server should have the acknowledged flag
222 // set.
223 DCHECK(supervised_user_shared_setting.acknowledged());
224 dict->SetBooleanWithoutPathExpansion(
225 kAcknowledged, supervised_user_shared_setting.acknowledged());
226 callbacks_.Notify(su_id, key);
228 seen_keys[su_id].insert(key);
231 // Iterate over all settings that we have locally, which includes settings
232 // that were just synced down. We filter those out using |seen_keys|.
233 SyncChangeList change_list;
234 const DictionaryValue* all_settings =
235 prefs_->GetDictionary(prefs::kSupervisedUserSharedSettings);
236 for (DictionaryValue::Iterator it(*all_settings); !it.IsAtEnd();
237 it.Advance()) {
238 const DictionaryValue* dict = NULL;
239 bool success = it.value().GetAsDictionary(&dict);
240 DCHECK(success);
242 const std::set<std::string>& seen = seen_keys[it.key()];
243 for (DictionaryValue::Iterator jt(*dict); !jt.IsAtEnd(); jt.Advance()) {
244 // We only need to upload settings that we haven't seen in the initial
245 // sync data (which means they were added locally).
246 if (seen.count(jt.key()) > 0)
247 continue;
249 SyncData data = CreateSyncDataForValue(it.key(), jt.key(), jt.value());
250 DCHECK(data.IsValid());
251 change_list.push_back(
252 SyncChange(FROM_HERE, SyncChange::ACTION_ADD, data));
256 SyncMergeResult result(SUPERVISED_USER_SHARED_SETTINGS);
257 // Process all the accumulated changes.
258 if (change_list.size() > 0) {
259 result.set_error(
260 sync_processor_->ProcessSyncChanges(FROM_HERE, change_list));
263 // TODO(bauerb): Statistics?
264 return result;
267 void SupervisedUserSharedSettingsService::StopSyncing(syncer::ModelType type) {
268 DCHECK_EQ(SUPERVISED_USER_SHARED_SETTINGS, type);
269 sync_processor_.reset();
270 error_handler_.reset();
273 syncer::SyncDataList SupervisedUserSharedSettingsService::GetAllSyncData(
274 syncer::ModelType type) const {
275 DCHECK_EQ(SUPERVISED_USER_SHARED_SETTINGS, type);
276 SyncDataList data;
277 const DictionaryValue* all_settings =
278 prefs_->GetDictionary(prefs::kSupervisedUserSharedSettings);
279 for (DictionaryValue::Iterator it(*all_settings); !it.IsAtEnd();
280 it.Advance()) {
281 const DictionaryValue* dict = NULL;
282 bool success = it.value().GetAsDictionary(&dict);
283 DCHECK(success);
284 for (DictionaryValue::Iterator jt(*dict); !jt.IsAtEnd(); jt.Advance()) {
285 data.push_back(CreateSyncDataForValue(it.key(), jt.key(), jt.value()));
288 return data;
291 syncer::SyncError SupervisedUserSharedSettingsService::ProcessSyncChanges(
292 const tracked_objects::Location& from_here,
293 const syncer::SyncChangeList& change_list) {
294 for (const SyncChange& sync_change : change_list) {
295 SyncData data = sync_change.sync_data();
296 DCHECK_EQ(SUPERVISED_USER_SHARED_SETTINGS, data.GetDataType());
297 const ::sync_pb::ManagedUserSharedSettingSpecifics&
298 supervised_user_shared_setting =
299 data.GetSpecifics().managed_user_shared_setting();
300 const std::string& key = supervised_user_shared_setting.key();
301 const std::string& su_id = supervised_user_shared_setting.mu_id();
302 ScopedSupervisedUserSharedSettingsUpdate update(prefs_, su_id);
303 DictionaryValue* update_dict = update.Get();
304 DictionaryValue* dict = NULL;
305 bool has_key = update_dict->GetDictionaryWithoutPathExpansion(key, &dict);
306 switch (sync_change.change_type()) {
307 case SyncChange::ACTION_ADD:
308 case SyncChange::ACTION_UPDATE: {
309 // Every setting we get from the server should have the acknowledged
310 // flag set.
311 DCHECK(supervised_user_shared_setting.acknowledged());
313 if (has_key) {
314 // If the supervised user already exists, it should be an update
315 // action.
316 DCHECK_EQ(SyncChange::ACTION_UPDATE, sync_change.change_type());
317 } else {
318 // Otherwise, it should be an add action.
319 DCHECK_EQ(SyncChange::ACTION_ADD, sync_change.change_type());
320 dict = new DictionaryValue;
321 update_dict->SetWithoutPathExpansion(key, dict);
323 scoped_ptr<Value> value(
324 base::JSONReader::Read(supervised_user_shared_setting.value()));
325 dict->SetWithoutPathExpansion(kValue, value.release());
326 dict->SetBooleanWithoutPathExpansion(
327 kAcknowledged, supervised_user_shared_setting.acknowledged());
328 break;
330 case SyncChange::ACTION_DELETE: {
331 if (has_key)
332 update_dict->RemoveWithoutPathExpansion(key, NULL);
333 else
334 NOTREACHED() << "Trying to delete nonexistent key " << key;
335 break;
337 case SyncChange::ACTION_INVALID: {
338 NOTREACHED();
339 break;
342 callbacks_.Notify(su_id, key);
345 SyncError error;
346 return error;