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

Side by Side 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, 11 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2013 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.
4
5 #include "chrome/browser/managed_mode/managed_user_shared_settings_service.h"
6
7 #include "base/json/json_reader.h"
8 #include "base/json/json_writer.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/prefs/scoped_user_pref_update.h"
11 #include "base/values.h"
12 #include "chrome/common/pref_names.h"
13 #include "components/user_prefs/pref_registry_syncable.h"
14 #include "sync/api/sync_change.h"
15 #include "sync/api/sync_data.h"
16 #include "sync/api/sync_error.h"
17 #include "sync/api/sync_error_factory.h"
18 #include "sync/api/sync_merge_result.h"
19 #include "sync/protocol/sync.pb.h"
20
21 using base::DictionaryValue;
22 using base::Value;
23 using syncer::MANAGED_USER_SHARED_SETTINGS;
24 using syncer::ModelType;
25 using syncer::SyncChange;
26 using syncer::SyncChangeList;
27 using syncer::SyncChangeProcessor;
28 using syncer::SyncData;
29 using syncer::SyncDataList;
30 using syncer::SyncError;
31 using syncer::SyncErrorFactory;
32 using syncer::SyncMergeResult;
33
34 namespace {
35
36 const char kAcknowledged[] = "acknowledged";
37 const char kValue[] = "value";
38
39 DictionaryValue* FindOrCreateDictionary(DictionaryValue* parent,
40 const std::string& key) {
41 DictionaryValue* dict = NULL;
42 if (!parent->GetDictionaryWithoutPathExpansion(key, &dict)) {
43 dict = new DictionaryValue;
44 parent->SetWithoutPathExpansion(key, dict);
45 }
46 return dict;
47 }
48
49 class ScopedManagedUserSharedSettingsUpdate {
50 public:
51 ScopedManagedUserSharedSettingsUpdate(PrefService* prefs,
52 const std::string& mu_id)
53 : update_(prefs, prefs::kManagedUserSharedSettings), mu_id_(mu_id) {
54 // A supervised user can only modify their own settings.
55 std::string id = prefs->GetString(prefs::kManagedUserId);
56 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.
57 }
58
59 DictionaryValue* Get() {
60 return FindOrCreateDictionary(update_.Get(), mu_id_);
61 }
62
63 private:
64 DictionaryPrefUpdate update_;
65 std::string mu_id_;
66 };
67
68 SyncData CreateSyncDataForValue(
69 const std::string& mu_id,
70 const std::string& key,
71 const Value& dict_value) {
72 const DictionaryValue* dict = NULL;
73 if (!dict_value.GetAsDictionary(&dict))
74 return SyncData();
75
76 const Value* value = NULL;
77 if (!dict->Get(kValue, &value))
78 return SyncData();
79
80 bool acknowledged = false;
81 dict->GetBoolean(kAcknowledged, &acknowledged);
82
83 return ManagedUserSharedSettingsService::CreateSyncDataForSetting(
84 mu_id, key, *value, acknowledged);
85 }
86
87 } // namespace
88
89
90 ManagedUserSharedSettingsService::ManagedUserSharedSettingsService(
91 PrefService* prefs)
92 : prefs_(prefs) {}
93
94 ManagedUserSharedSettingsService::~ManagedUserSharedSettingsService() {}
95
96 void ManagedUserSharedSettingsService::SetValueInternal(
97 const std::string& mu_id,
98 const std::string& key,
99 const Value& value,
100 bool acknowledged) {
101 ScopedManagedUserSharedSettingsUpdate update(prefs_, mu_id);
102 DictionaryValue* update_dict = update.Get();
103
104 DictionaryValue* dict = NULL;
105 bool has_key = update_dict->GetDictionaryWithoutPathExpansion(key, &dict);
106 if (!has_key) {
107 dict = new DictionaryValue;
108 update_dict->SetWithoutPathExpansion(key, dict);
109 }
110 dict->SetWithoutPathExpansion(kValue, value.DeepCopy());
111 dict->SetBooleanWithoutPathExpansion(kAcknowledged, acknowledged);
112
113 if (!sync_processor_)
114 return;
115
116 SyncData data = CreateSyncDataForSetting(mu_id, key, value, acknowledged);
117 SyncChange::SyncChangeType change_type =
118 has_key ? SyncChange::ACTION_UPDATE : SyncChange::ACTION_ADD;
119 SyncChangeList changes;
120 changes.push_back(SyncChange(FROM_HERE, change_type, data));
121 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, changes);
122 DCHECK(!error.IsSet()) << error.ToString();
123 }
124
125 const Value* ManagedUserSharedSettingsService::GetValue(
126 const std::string& mu_id,
127 const std::string& key) {
128 const DictionaryValue* data =
129 prefs_->GetDictionary(prefs::kManagedUserSharedSettings);
130 const DictionaryValue* dict = NULL;
131 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.
132 return NULL;
133
134 const DictionaryValue* settings = NULL;
135 if (!dict->GetDictionaryWithoutPathExpansion(key, &settings))
136 return NULL;
137
138 const Value* value = NULL;
139 if (!settings->GetWithoutPathExpansion(kValue, &value))
140 return NULL;
141
142 return value;
143 }
144
145 void ManagedUserSharedSettingsService::SetValue(
146 const std::string& mu_id,
147 const std::string& key,
148 const Value& value) {
149 SetValueInternal(mu_id, key, value, true);
150 }
151
152 scoped_ptr<ManagedUserSharedSettingsService::CallbackList::Subscription>
153 ManagedUserSharedSettingsService::Subscribe(
154 const ManagedUserSharedSettingsService::Callback& cb) {
155 return callbacks_.Add(cb);
156 }
157
158 // static
159 void ManagedUserSharedSettingsService::RegisterProfilePrefs(
160 user_prefs::PrefRegistrySyncable* registry) {
161 registry->RegisterDictionaryPref(
162 prefs::kManagedUserSharedSettings,
163 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
164 }
165
166 // static
167 SyncData ManagedUserSharedSettingsService::CreateSyncDataForSetting(
168 const std::string& mu_id,
169 const std::string& key,
170 const Value& value,
171 bool acknowledged) {
172 std::string json_value;
173 base::JSONWriter::Write(&value, &json_value);
174 ::sync_pb::EntitySpecifics specifics;
175 specifics.mutable_managed_user_shared_setting()->set_mu_id(mu_id);
176 specifics.mutable_managed_user_shared_setting()->set_key(key);
177 specifics.mutable_managed_user_shared_setting()->set_value(json_value);
178 specifics.mutable_managed_user_shared_setting()->set_acknowledged(
179 acknowledged);
180 std::string title = mu_id + ":" + key;
181 return SyncData::CreateLocalData(title, title, specifics);
182 }
183
184 void ManagedUserSharedSettingsService::Shutdown() {}
185
186 syncer::SyncMergeResult
187 ManagedUserSharedSettingsService::MergeDataAndStartSyncing(
188 syncer::ModelType type,
189 const syncer::SyncDataList& initial_sync_data,
190 scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
191 scoped_ptr<syncer::SyncErrorFactory> error_handler) {
192 DCHECK_EQ(MANAGED_USER_SHARED_SETTINGS, type);
193 sync_processor_ = sync_processor.Pass();
194 error_handler_ = error_handler.Pass();
195
196 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.
197 for (SyncDataList::const_iterator it = initial_sync_data.begin();
198 it != initial_sync_data.end();
199 ++it) {
200 DCHECK_EQ(MANAGED_USER_SHARED_SETTINGS, it->GetDataType());
201 const ::sync_pb::ManagedUserSharedSettingSpecifics&
202 managed_user_shared_setting =
203 it->GetSpecifics().managed_user_shared_setting();
204 scoped_ptr<Value> value(
205 base::JSONReader::Read(managed_user_shared_setting.value()));
206 const std::string& mu_id = managed_user_shared_setting.mu_id();
207 ScopedManagedUserSharedSettingsUpdate update(prefs_, mu_id);
208 const std::string& key = managed_user_shared_setting.key();
209 DictionaryValue* dict = FindOrCreateDictionary(update.Get(), key);
210 dict->SetWithoutPathExpansion(kValue, value.release());
211 DCHECK(managed_user_shared_setting.acknowledged());
212 dict->SetBooleanWithoutPathExpansion(
213 kAcknowledged, managed_user_shared_setting.acknowledged());
214 callbacks_.Notify(mu_id, key);
215
216 seen_keys[mu_id].insert(key);
217 }
218
219 SyncChangeList change_list;
220 const DictionaryValue* all_settings =
221 prefs_->GetDictionary(prefs::kManagedUserSharedSettings);
222 for (DictionaryValue::Iterator it(*all_settings); !it.IsAtEnd();
223 it.Advance()) {
224 const DictionaryValue* dict = NULL;
225 bool success = it.value().GetAsDictionary(&dict);
226 DCHECK(success);
227
228 const std::set<std::string>& seen = seen_keys[it.key()];
229 for (DictionaryValue::Iterator jt(*dict); !jt.IsAtEnd(); jt.Advance()) {
230 if (seen.count(jt.key()) > 0)
231 continue;
232
233 SyncData data = CreateSyncDataForValue(it.key(), jt.key(), jt.value());
234 DCHECK(data.IsValid());
235 change_list.push_back(
236 SyncChange(FROM_HERE, SyncChange::ACTION_ADD, data));
237 }
238 }
239
240 SyncMergeResult result(MANAGED_USER_SHARED_SETTINGS);
241 // Process all the accumulated changes.
242 if (change_list.size() > 0) {
243 result.set_error(
244 sync_processor_->ProcessSyncChanges(FROM_HERE, change_list));
245 }
246
247 // TODO(bauerb): Statistics?
248 return result;
249 }
250
251 void ManagedUserSharedSettingsService::StopSyncing(syncer::ModelType type) {
252 DCHECK_EQ(MANAGED_USER_SHARED_SETTINGS, type);
253 sync_processor_.reset();
254 error_handler_.reset();
255 }
256
257 syncer::SyncDataList ManagedUserSharedSettingsService::GetAllSyncData(
258 syncer::ModelType type) const {
259 DCHECK_EQ(MANAGED_USER_SHARED_SETTINGS, type);
260 SyncDataList data;
261 const DictionaryValue* all_settings =
262 prefs_->GetDictionary(prefs::kManagedUserSharedSettings);
263 for (DictionaryValue::Iterator it(*all_settings); !it.IsAtEnd();
264 it.Advance()) {
265 const DictionaryValue* dict = NULL;
266 bool success = it.value().GetAsDictionary(&dict);
267 DCHECK(success);
268 for (DictionaryValue::Iterator jt(*dict); !jt.IsAtEnd(); jt.Advance()) {
269 data.push_back(CreateSyncDataForValue(it.key(), jt.key(), jt.value()));
270 }
271 }
272 return data;
273 }
274
275 syncer::SyncError ManagedUserSharedSettingsService::ProcessSyncChanges(
276 const tracked_objects::Location& from_here,
277 const syncer::SyncChangeList& change_list) {
278 for (SyncChangeList::const_iterator it = change_list.begin();
279 it != change_list.end();
280 ++it) {
281 SyncData data = it->sync_data();
282 DCHECK_EQ(MANAGED_USER_SHARED_SETTINGS, data.GetDataType());
283 const ::sync_pb::ManagedUserSharedSettingSpecifics&
284 managed_user_shared_setting =
285 data.GetSpecifics().managed_user_shared_setting();
286 const std::string& key = managed_user_shared_setting.key();
287 const std::string& mu_id = managed_user_shared_setting.mu_id();
288 ScopedManagedUserSharedSettingsUpdate update(prefs_, mu_id);
289 DictionaryValue* update_dict = update.Get();
290 DictionaryValue* dict = NULL;
291 bool has_key = update_dict->GetDictionaryWithoutPathExpansion(key, &dict);
292 switch (it->change_type()) {
293 case SyncChange::ACTION_ADD:
294 case SyncChange::ACTION_UPDATE: {
295 if (has_key) {
296 // 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
297 DCHECK_EQ(SyncChange::ACTION_UPDATE, it->change_type());
298 } else {
299 // For an add action, it should not.
300 DCHECK_EQ(SyncChange::ACTION_ADD, it->change_type());
301 dict = new DictionaryValue;
302 update_dict->SetWithoutPathExpansion(key, dict);
303 }
304 scoped_ptr<Value> value(
305 base::JSONReader::Read(managed_user_shared_setting.value()));
306 dict->SetWithoutPathExpansion(kValue, value.release());
307 dict->SetBooleanWithoutPathExpansion(
308 kAcknowledged, managed_user_shared_setting.acknowledged());
309 break;
310 }
311 case SyncChange::ACTION_DELETE: {
312 if (has_key)
313 update_dict->RemoveWithoutPathExpansion(key, NULL);
314 else
315 NOTREACHED() << "Trying to delete nonexistent key " << key;
316 break;
317 }
318 case SyncChange::ACTION_INVALID: {
319 NOTREACHED();
320 break;
321 }
322 }
323 callbacks_.Notify(mu_id, key);
324 }
325
326 SyncError error;
327 return error;
328 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698