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

Side by Side Diff: chrome/browser/managed_mode/managed_user_sync_service.cc

Issue 335833003: Rename "managed (mode|user)" to "supervised user" (part 2) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: review comments (+ a few other cleanups) Created 6 years, 6 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_sync_service.h"
6
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/prefs/scoped_user_pref_update.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/values.h"
13 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
14 #include "chrome/common/pref_names.h"
15 #include "components/pref_registry/pref_registry_syncable.h"
16 #include "sync/api/sync_change.h"
17 #include "sync/api/sync_data.h"
18 #include "sync/api/sync_error.h"
19 #include "sync/api/sync_error_factory.h"
20 #include "sync/api/sync_merge_result.h"
21 #include "sync/protocol/sync.pb.h"
22
23 #if defined(OS_CHROMEOS)
24 #include "chrome/browser/chromeos/login/users/avatar/default_user_images.h"
25 #endif
26
27 using base::DictionaryValue;
28 using user_prefs::PrefRegistrySyncable;
29 using syncer::SUPERVISED_USERS;
30 using syncer::ModelType;
31 using syncer::SyncChange;
32 using syncer::SyncChangeList;
33 using syncer::SyncChangeProcessor;
34 using syncer::SyncData;
35 using syncer::SyncDataList;
36 using syncer::SyncError;
37 using syncer::SyncErrorFactory;
38 using syncer::SyncMergeResult;
39 using sync_pb::ManagedUserSpecifics;
40
41 namespace {
42
43 #if defined(OS_CHROMEOS)
44 const char kChromeOSAvatarPrefix[] = "chromeos-avatar-index:";
45 #else
46 const char kChromeAvatarPrefix[] = "chrome-avatar-index:";
47 #endif
48
49 SyncData CreateLocalSyncData(const std::string& id,
50 const std::string& name,
51 bool acknowledged,
52 const std::string& master_key,
53 const std::string& chrome_avatar,
54 const std::string& chromeos_avatar,
55 const std::string& password_signature_key,
56 const std::string& password_encryption_key) {
57 ::sync_pb::EntitySpecifics specifics;
58 specifics.mutable_managed_user()->set_id(id);
59 specifics.mutable_managed_user()->set_name(name);
60 if (!chrome_avatar.empty())
61 specifics.mutable_managed_user()->set_chrome_avatar(chrome_avatar);
62 if (!chromeos_avatar.empty())
63 specifics.mutable_managed_user()->set_chromeos_avatar(chromeos_avatar);
64 if (!master_key.empty())
65 specifics.mutable_managed_user()->set_master_key(master_key);
66 if (acknowledged)
67 specifics.mutable_managed_user()->set_acknowledged(true);
68 if (!password_signature_key.empty()) {
69 specifics.mutable_managed_user()->
70 set_password_signature_key(password_signature_key);
71 }
72 if (!password_encryption_key.empty()) {
73 specifics.mutable_managed_user()->
74 set_password_encryption_key(password_encryption_key);
75 }
76 return SyncData::CreateLocalData(id, name, specifics);
77 }
78
79 SyncData CreateSyncDataFromDictionaryEntry(const std::string& id,
80 const base::Value& value) {
81 const base::DictionaryValue* dict = NULL;
82 bool success = value.GetAsDictionary(&dict);
83 DCHECK(success);
84 bool acknowledged = false;
85 dict->GetBoolean(ManagedUserSyncService::kAcknowledged, &acknowledged);
86 std::string name;
87 dict->GetString(ManagedUserSyncService::kName, &name);
88 DCHECK(!name.empty());
89 std::string master_key;
90 dict->GetString(ManagedUserSyncService::kMasterKey, &master_key);
91 std::string chrome_avatar;
92 dict->GetString(ManagedUserSyncService::kChromeAvatar, &chrome_avatar);
93 std::string chromeos_avatar;
94 dict->GetString(ManagedUserSyncService::kChromeOsAvatar, &chromeos_avatar);
95 std::string signature;
96 dict->GetString(ManagedUserSyncService::kPasswordSignatureKey, &signature);
97 std::string encryption;
98 dict->GetString(ManagedUserSyncService::kPasswordEncryptionKey, &encryption);
99
100 return CreateLocalSyncData(id,
101 name,
102 acknowledged,
103 master_key,
104 chrome_avatar,
105 chromeos_avatar,
106 signature,
107 encryption);
108 }
109
110 } // namespace
111
112 const char ManagedUserSyncService::kAcknowledged[] = "acknowledged";
113 const char ManagedUserSyncService::kChromeAvatar[] = "chromeAvatar";
114 const char ManagedUserSyncService::kChromeOsAvatar[] = "chromeOsAvatar";
115 const char ManagedUserSyncService::kMasterKey[] = "masterKey";
116 const char ManagedUserSyncService::kName[] = "name";
117 const char ManagedUserSyncService::kPasswordSignatureKey[] =
118 "passwordSignatureKey";
119 const char ManagedUserSyncService::kPasswordEncryptionKey[] =
120 "passwordEncryptionKey";
121 const int ManagedUserSyncService::kNoAvatar = -100;
122
123 ManagedUserSyncService::ManagedUserSyncService(PrefService* prefs)
124 : prefs_(prefs) {
125 pref_change_registrar_.Init(prefs_);
126 pref_change_registrar_.Add(
127 prefs::kGoogleServicesLastUsername,
128 base::Bind(&ManagedUserSyncService::OnLastSignedInUsernameChange,
129 base::Unretained(this)));
130 }
131
132 ManagedUserSyncService::~ManagedUserSyncService() {
133 }
134
135 // static
136 void ManagedUserSyncService::RegisterProfilePrefs(
137 PrefRegistrySyncable* registry) {
138 registry->RegisterDictionaryPref(prefs::kSupervisedUsers,
139 PrefRegistrySyncable::UNSYNCABLE_PREF);
140 }
141
142 // static
143 bool ManagedUserSyncService::GetAvatarIndex(const std::string& avatar_str,
144 int* avatar_index) {
145 DCHECK(avatar_index);
146 if (avatar_str.empty()) {
147 *avatar_index = kNoAvatar;
148 return true;
149 }
150 #if defined(OS_CHROMEOS)
151 const char* prefix = kChromeOSAvatarPrefix;
152 #else
153 const char* prefix = kChromeAvatarPrefix;
154 #endif
155 size_t prefix_len = strlen(prefix);
156 if (avatar_str.size() <= prefix_len ||
157 avatar_str.substr(0, prefix_len) != prefix) {
158 return false;
159 }
160
161 if (!base::StringToInt(avatar_str.substr(prefix_len), avatar_index))
162 return false;
163
164 const int kChromeOSDummyAvatarIndex = -111;
165
166 #if defined(OS_CHROMEOS)
167 return (*avatar_index == kChromeOSDummyAvatarIndex ||
168 (*avatar_index >= chromeos::kFirstDefaultImageIndex &&
169 *avatar_index < chromeos::kDefaultImagesCount));
170 #else
171 // Check if the Chrome avatar index is set to a dummy value. Some early
172 // supervised user profiles on ChromeOS stored a dummy avatar index as a
173 // Chrome Avatar before there was logic to sync the ChromeOS avatar
174 // separately. Handle this as if the Chrome Avatar was not chosen yet (which
175 // is correct for these profiles).
176 if (*avatar_index == kChromeOSDummyAvatarIndex)
177 *avatar_index = kNoAvatar;
178 return (*avatar_index == kNoAvatar ||
179 (*avatar_index >= 0 &&
180 static_cast<size_t>(*avatar_index) <
181 profiles::GetDefaultAvatarIconCount()));
182 #endif
183 }
184
185 // static
186 std::string ManagedUserSyncService::BuildAvatarString(int avatar_index) {
187 #if defined(OS_CHROMEOS)
188 const char* prefix = kChromeOSAvatarPrefix;
189 #else
190 const char* prefix = kChromeAvatarPrefix;
191 #endif
192 return base::StringPrintf("%s%d", prefix, avatar_index);
193 }
194
195 void ManagedUserSyncService::AddObserver(
196 ManagedUserSyncServiceObserver* observer) {
197 observers_.AddObserver(observer);
198 }
199
200 void ManagedUserSyncService::RemoveObserver(
201 ManagedUserSyncServiceObserver* observer) {
202 observers_.RemoveObserver(observer);
203 }
204
205 scoped_ptr<base::DictionaryValue> ManagedUserSyncService::CreateDictionary(
206 const std::string& name,
207 const std::string& master_key,
208 const std::string& signature_key,
209 const std::string& encryption_key,
210 int avatar_index) {
211 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue());
212 result->SetString(kName, name);
213 result->SetString(kMasterKey, master_key);
214 result->SetString(kPasswordSignatureKey, signature_key);
215 result->SetString(kPasswordEncryptionKey, encryption_key);
216 // TODO(akuegel): Get rid of the avatar stuff here when Chrome OS switches
217 // to the avatar index that is stored as a shared setting.
218 std::string chrome_avatar;
219 std::string chromeos_avatar;
220 #if defined(OS_CHROMEOS)
221 chromeos_avatar = BuildAvatarString(avatar_index);
222 #else
223 chrome_avatar = BuildAvatarString(avatar_index);
224 #endif
225 result->SetString(kChromeAvatar, chrome_avatar);
226 result->SetString(kChromeOsAvatar, chromeos_avatar);
227 return result.Pass();
228 }
229
230 void ManagedUserSyncService::AddManagedUser(const std::string& id,
231 const std::string& name,
232 const std::string& master_key,
233 const std::string& signature_key,
234 const std::string& encryption_key,
235 int avatar_index) {
236 UpdateManagedUserImpl(id,
237 name,
238 master_key,
239 signature_key,
240 encryption_key,
241 avatar_index,
242 true /* add */);
243 }
244
245 void ManagedUserSyncService::UpdateManagedUser(
246 const std::string& id,
247 const std::string& name,
248 const std::string& master_key,
249 const std::string& signature_key,
250 const std::string& encryption_key,
251 int avatar_index) {
252 UpdateManagedUserImpl(id,
253 name,
254 master_key,
255 signature_key,
256 encryption_key,
257 avatar_index,
258 false /* update */);
259 }
260
261 void ManagedUserSyncService::UpdateManagedUserImpl(
262 const std::string& id,
263 const std::string& name,
264 const std::string& master_key,
265 const std::string& signature_key,
266 const std::string& encryption_key,
267 int avatar_index,
268 bool add_user) {
269 DictionaryPrefUpdate update(prefs_, prefs::kSupervisedUsers);
270 base::DictionaryValue* dict = update.Get();
271 scoped_ptr<base::DictionaryValue> value = CreateDictionary(
272 name, master_key, signature_key, encryption_key, avatar_index);
273
274 DCHECK_EQ(add_user, !dict->HasKey(id));
275 base::DictionaryValue* entry = value.get();
276 dict->SetWithoutPathExpansion(id, value.release());
277
278 if (!sync_processor_)
279 return;
280
281 // If we're already syncing, create a new change and upload it.
282 SyncChangeList change_list;
283 change_list.push_back(
284 SyncChange(FROM_HERE,
285 add_user ? SyncChange::ACTION_ADD : SyncChange::ACTION_UPDATE,
286 CreateSyncDataFromDictionaryEntry(id, *entry)));
287 SyncError error =
288 sync_processor_->ProcessSyncChanges(FROM_HERE, change_list);
289 DCHECK(!error.IsSet()) << error.ToString();
290 }
291
292 void ManagedUserSyncService::DeleteManagedUser(const std::string& id) {
293 DictionaryPrefUpdate update(prefs_, prefs::kSupervisedUsers);
294 bool success = update->RemoveWithoutPathExpansion(id, NULL);
295 DCHECK(success);
296
297 if (!sync_processor_)
298 return;
299
300 SyncChangeList change_list;
301 change_list.push_back(SyncChange(
302 FROM_HERE,
303 SyncChange::ACTION_DELETE,
304 SyncData::CreateLocalDelete(id, SUPERVISED_USERS)));
305 SyncError sync_error =
306 sync_processor_->ProcessSyncChanges(FROM_HERE, change_list);
307 DCHECK(!sync_error.IsSet());
308 }
309
310 const base::DictionaryValue* ManagedUserSyncService::GetManagedUsers() {
311 DCHECK(sync_processor_);
312 return prefs_->GetDictionary(prefs::kSupervisedUsers);
313 }
314
315 bool ManagedUserSyncService::UpdateManagedUserAvatarIfNeeded(
316 const std::string& id,
317 int avatar_index) {
318 DictionaryPrefUpdate update(prefs_, prefs::kSupervisedUsers);
319 base::DictionaryValue* dict = update.Get();
320 DCHECK(dict->HasKey(id));
321 base::DictionaryValue* value = NULL;
322 bool success = dict->GetDictionaryWithoutPathExpansion(id, &value);
323 DCHECK(success);
324
325 bool acknowledged = false;
326 value->GetBoolean(ManagedUserSyncService::kAcknowledged, &acknowledged);
327 std::string name;
328 value->GetString(ManagedUserSyncService::kName, &name);
329 std::string master_key;
330 value->GetString(ManagedUserSyncService::kMasterKey, &master_key);
331 std::string signature;
332 value->GetString(ManagedUserSyncService::kPasswordSignatureKey, &signature);
333 std::string encryption;
334 value->GetString(ManagedUserSyncService::kPasswordEncryptionKey, &encryption);
335 std::string chromeos_avatar;
336 value->GetString(ManagedUserSyncService::kChromeOsAvatar, &chromeos_avatar);
337 std::string chrome_avatar;
338 value->GetString(ManagedUserSyncService::kChromeAvatar, &chrome_avatar);
339 // The following check is just for safety. We want to avoid that the existing
340 // avatar selection is overwritten. Currently we don't allow the user to
341 // choose a different avatar in the recreation dialog, anyway, if there is
342 // already an avatar selected.
343 #if defined(OS_CHROMEOS)
344 if (!chromeos_avatar.empty() && avatar_index != kNoAvatar)
345 return false;
346 #else
347 if (!chrome_avatar.empty() && avatar_index != kNoAvatar)
348 return false;
349 #endif
350
351 chrome_avatar = avatar_index == kNoAvatar ?
352 std::string() : BuildAvatarString(avatar_index);
353 #if defined(OS_CHROMEOS)
354 value->SetString(kChromeOsAvatar, chrome_avatar);
355 #else
356 value->SetString(kChromeAvatar, chrome_avatar);
357 #endif
358
359 if (!sync_processor_)
360 return true;
361
362 SyncChangeList change_list;
363 change_list.push_back(SyncChange(
364 FROM_HERE,
365 SyncChange::ACTION_UPDATE,
366 CreateLocalSyncData(id, name, acknowledged, master_key,
367 chrome_avatar, chromeos_avatar,
368 signature, encryption)));
369 SyncError error =
370 sync_processor_->ProcessSyncChanges(FROM_HERE, change_list);
371 DCHECK(!error.IsSet()) << error.ToString();
372 return true;
373 }
374
375 void ManagedUserSyncService::ClearManagedUserAvatar(const std::string& id) {
376 bool cleared = UpdateManagedUserAvatarIfNeeded(id, kNoAvatar);
377 DCHECK(cleared);
378 }
379
380 void ManagedUserSyncService::GetManagedUsersAsync(
381 const ManagedUsersCallback& callback) {
382 // If we are already syncing, just run the callback.
383 if (sync_processor_) {
384 callback.Run(GetManagedUsers());
385 return;
386 }
387
388 // Otherwise queue it up until we start syncing.
389 callbacks_.push_back(callback);
390 }
391
392 void ManagedUserSyncService::Shutdown() {
393 NotifyManagedUsersSyncingStopped();
394 }
395
396 SyncMergeResult ManagedUserSyncService::MergeDataAndStartSyncing(
397 ModelType type,
398 const SyncDataList& initial_sync_data,
399 scoped_ptr<SyncChangeProcessor> sync_processor,
400 scoped_ptr<SyncErrorFactory> error_handler) {
401 DCHECK_EQ(SUPERVISED_USERS, type);
402 sync_processor_ = sync_processor.Pass();
403 error_handler_ = error_handler.Pass();
404
405 SyncChangeList change_list;
406 SyncMergeResult result(SUPERVISED_USERS);
407
408 DictionaryPrefUpdate update(prefs_, prefs::kSupervisedUsers);
409 base::DictionaryValue* dict = update.Get();
410 result.set_num_items_before_association(dict->size());
411 std::set<std::string> seen_ids;
412 int num_items_added = 0;
413 int num_items_modified = 0;
414 for (SyncDataList::const_iterator it = initial_sync_data.begin();
415 it != initial_sync_data.end(); ++it) {
416 DCHECK_EQ(SUPERVISED_USERS, it->GetDataType());
417 const ManagedUserSpecifics& managed_user =
418 it->GetSpecifics().managed_user();
419 base::DictionaryValue* value = new base::DictionaryValue();
420 value->SetString(kName, managed_user.name());
421 value->SetBoolean(kAcknowledged, managed_user.acknowledged());
422 value->SetString(kMasterKey, managed_user.master_key());
423 value->SetString(kChromeAvatar, managed_user.chrome_avatar());
424 value->SetString(kChromeOsAvatar, managed_user.chromeos_avatar());
425 value->SetString(kPasswordSignatureKey,
426 managed_user.password_signature_key());
427 value->SetString(kPasswordEncryptionKey,
428 managed_user.password_encryption_key());
429 if (dict->HasKey(managed_user.id()))
430 num_items_modified++;
431 else
432 num_items_added++;
433 dict->SetWithoutPathExpansion(managed_user.id(), value);
434 seen_ids.insert(managed_user.id());
435 }
436
437 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
438 if (seen_ids.find(it.key()) != seen_ids.end())
439 continue;
440
441 change_list.push_back(
442 SyncChange(FROM_HERE,
443 SyncChange::ACTION_ADD,
444 CreateSyncDataFromDictionaryEntry(it.key(), it.value())));
445 }
446 result.set_error(sync_processor_->ProcessSyncChanges(FROM_HERE, change_list));
447
448 result.set_num_items_modified(num_items_modified);
449 result.set_num_items_added(num_items_added);
450 result.set_num_items_after_association(dict->size());
451
452 DispatchCallbacks();
453
454 return result;
455 }
456
457 void ManagedUserSyncService::StopSyncing(ModelType type) {
458 DCHECK_EQ(SUPERVISED_USERS, type);
459 // The observers may want to change the Sync data, so notify them before
460 // resetting the |sync_processor_|.
461 NotifyManagedUsersSyncingStopped();
462 sync_processor_.reset();
463 error_handler_.reset();
464 }
465
466 SyncDataList ManagedUserSyncService::GetAllSyncData(
467 ModelType type) const {
468 SyncDataList data;
469 DictionaryPrefUpdate update(prefs_, prefs::kSupervisedUsers);
470 base::DictionaryValue* dict = update.Get();
471 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance())
472 data.push_back(CreateSyncDataFromDictionaryEntry(it.key(), it.value()));
473
474 return data;
475 }
476
477 SyncError ManagedUserSyncService::ProcessSyncChanges(
478 const tracked_objects::Location& from_here,
479 const SyncChangeList& change_list) {
480 SyncError error;
481 DictionaryPrefUpdate update(prefs_, prefs::kSupervisedUsers);
482 base::DictionaryValue* dict = update.Get();
483 for (SyncChangeList::const_iterator it = change_list.begin();
484 it != change_list.end(); ++it) {
485 SyncData data = it->sync_data();
486 DCHECK_EQ(SUPERVISED_USERS, data.GetDataType());
487 const ManagedUserSpecifics& managed_user =
488 data.GetSpecifics().managed_user();
489 switch (it->change_type()) {
490 case SyncChange::ACTION_ADD:
491 case SyncChange::ACTION_UPDATE: {
492 // Every item we get from the server should be acknowledged.
493 DCHECK(managed_user.acknowledged());
494 const base::DictionaryValue* old_value = NULL;
495 dict->GetDictionaryWithoutPathExpansion(managed_user.id(), &old_value);
496
497 // For an update action, the managed user should already exist, for an
498 // add action, it should not.
499 DCHECK_EQ(
500 old_value ? SyncChange::ACTION_UPDATE : SyncChange::ACTION_ADD,
501 it->change_type());
502
503 // If the managed user switched from unacknowledged to acknowledged,
504 // we might need to continue with a registration.
505 if (old_value && !old_value->HasKey(kAcknowledged))
506 NotifyManagedUserAcknowledged(managed_user.id());
507
508 base::DictionaryValue* value = new base::DictionaryValue;
509 value->SetString(kName, managed_user.name());
510 value->SetBoolean(kAcknowledged, managed_user.acknowledged());
511 value->SetString(kMasterKey, managed_user.master_key());
512 value->SetString(kChromeAvatar, managed_user.chrome_avatar());
513 value->SetString(kChromeOsAvatar, managed_user.chromeos_avatar());
514 value->SetString(kPasswordSignatureKey,
515 managed_user.password_signature_key());
516 value->SetString(kPasswordEncryptionKey,
517 managed_user.password_encryption_key());
518 dict->SetWithoutPathExpansion(managed_user.id(), value);
519
520 NotifyManagedUsersChanged();
521 break;
522 }
523 case SyncChange::ACTION_DELETE: {
524 DCHECK(dict->HasKey(managed_user.id())) << managed_user.id();
525 dict->RemoveWithoutPathExpansion(managed_user.id(), NULL);
526 break;
527 }
528 case SyncChange::ACTION_INVALID: {
529 NOTREACHED();
530 break;
531 }
532 }
533 }
534 return error;
535 }
536
537 void ManagedUserSyncService::OnLastSignedInUsernameChange() {
538 DCHECK(!sync_processor_);
539
540 // If the last signed in user changes, we clear all data, to avoid managed
541 // users from one custodian appearing in another one's profile.
542 prefs_->ClearPref(prefs::kSupervisedUsers);
543 }
544
545 void ManagedUserSyncService::NotifyManagedUserAcknowledged(
546 const std::string& managed_user_id) {
547 FOR_EACH_OBSERVER(ManagedUserSyncServiceObserver, observers_,
548 OnManagedUserAcknowledged(managed_user_id));
549 }
550
551 void ManagedUserSyncService::NotifyManagedUsersSyncingStopped() {
552 FOR_EACH_OBSERVER(ManagedUserSyncServiceObserver, observers_,
553 OnManagedUsersSyncingStopped());
554 }
555
556 void ManagedUserSyncService::NotifyManagedUsersChanged() {
557 FOR_EACH_OBSERVER(ManagedUserSyncServiceObserver,
558 observers_,
559 OnManagedUsersChanged());
560 }
561
562 void ManagedUserSyncService::DispatchCallbacks() {
563 const base::DictionaryValue* managed_users =
564 prefs_->GetDictionary(prefs::kSupervisedUsers);
565 for (std::vector<ManagedUsersCallback>::iterator it = callbacks_.begin();
566 it != callbacks_.end(); ++it) {
567 it->Run(managed_users);
568 }
569 callbacks_.clear();
570 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698