1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// found in the LICENSE file. 4a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/supervised_user/supervised_user_sync_service.h" 6a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 7a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/bind.h" 858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/callback.h" 91e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/prefs/scoped_user_pref_update.h" 1058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/strings/stringprintf.h" 12a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/values.h" 13c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/profiles/profile_avatar_icon_util.h" 14a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/common/pref_names.h" 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/pref_registry/pref_registry_syncable.h" 16a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "sync/api/sync_change.h" 17a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "sync/api/sync_data.h" 18a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "sync/api/sync_error.h" 19a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "sync/api/sync_error_factory.h" 20a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "sync/api/sync_merge_result.h" 21a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "sync/protocol/sync.pb.h" 22a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_CHROMEOS) 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/user_manager/user_image/default_user_images.h" 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 27a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using base::DictionaryValue; 28a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using user_prefs::PrefRegistrySyncable; 29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)using syncer::SUPERVISED_USERS; 30a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using syncer::ModelType; 31a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using syncer::SyncChange; 32a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using syncer::SyncChangeList; 33a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using syncer::SyncChangeProcessor; 34a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using syncer::SyncData; 35a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using syncer::SyncDataList; 36a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using syncer::SyncError; 37a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using syncer::SyncErrorFactory; 38a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using syncer::SyncMergeResult; 39a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using sync_pb::ManagedUserSpecifics; 40a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 41a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)namespace { 42a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#if defined(OS_CHROMEOS) 448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)const char kChromeOSAvatarPrefix[] = "chromeos-avatar-index:"; 458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#else 4658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const char kChromeAvatarPrefix[] = "chrome-avatar-index:"; 478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#endif 48a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 49a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)SyncData CreateLocalSyncData(const std::string& id, 50a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const std::string& name, 51a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) bool acknowledged, 5258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::string& master_key, 5358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::string& chrome_avatar, 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& chromeos_avatar, 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& password_signature_key, 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& password_encryption_key) { 57a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ::sync_pb::EntitySpecifics specifics; 58a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) specifics.mutable_managed_user()->set_id(id); 59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) specifics.mutable_managed_user()->set_name(name); 6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!chrome_avatar.empty()) 6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) specifics.mutable_managed_user()->set_chrome_avatar(chrome_avatar); 6258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!chromeos_avatar.empty()) 6358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) specifics.mutable_managed_user()->set_chromeos_avatar(chromeos_avatar); 64a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!master_key.empty()) 65a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) specifics.mutable_managed_user()->set_master_key(master_key); 66a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (acknowledged) 67a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) specifics.mutable_managed_user()->set_acknowledged(true); 68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!password_signature_key.empty()) { 69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) specifics.mutable_managed_user()-> 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) set_password_signature_key(password_signature_key); 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!password_encryption_key.empty()) { 73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) specifics.mutable_managed_user()-> 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) set_password_encryption_key(password_encryption_key); 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 76a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return SyncData::CreateLocalData(id, name, specifics); 77a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 78a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 7923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)SyncData CreateSyncDataFromDictionaryEntry(const std::string& id, 8023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const base::Value& value) { 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::DictionaryValue* dict = NULL; 8223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) bool success = value.GetAsDictionary(&dict); 8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(success); 8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bool acknowledged = false; 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dict->GetBoolean(SupervisedUserSyncService::kAcknowledged, &acknowledged); 8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::string name; 87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dict->GetString(SupervisedUserSyncService::kName, &name); 8858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(!name.empty()); 8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::string master_key; 90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dict->GetString(SupervisedUserSyncService::kMasterKey, &master_key); 9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::string chrome_avatar; 92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dict->GetString(SupervisedUserSyncService::kChromeAvatar, &chrome_avatar); 9358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::string chromeos_avatar; 94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dict->GetString(SupervisedUserSyncService::kChromeOsAvatar, &chromeos_avatar); 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string signature; 96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dict->GetString(SupervisedUserSyncService::kPasswordSignatureKey, &signature); 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string encryption; 98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dict->GetString(SupervisedUserSyncService::kPasswordEncryptionKey, 99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &encryption); 10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 10123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return CreateLocalSyncData(id, 10223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) name, 10323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) acknowledged, 10423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) master_key, 10523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) chrome_avatar, 10623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) chromeos_avatar, 10723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) signature, 10823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) encryption); 10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} // namespace 112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char SupervisedUserSyncService::kAcknowledged[] = "acknowledged"; 114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char SupervisedUserSyncService::kChromeAvatar[] = "chromeAvatar"; 115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char SupervisedUserSyncService::kChromeOsAvatar[] = "chromeOsAvatar"; 116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char SupervisedUserSyncService::kMasterKey[] = "masterKey"; 117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char SupervisedUserSyncService::kName[] = "name"; 118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char SupervisedUserSyncService::kPasswordSignatureKey[] = 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "passwordSignatureKey"; 120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char SupervisedUserSyncService::kPasswordEncryptionKey[] = 121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "passwordEncryptionKey"; 122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const int SupervisedUserSyncService::kNoAvatar = -100; 12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SupervisedUserSyncService::SupervisedUserSyncService(PrefService* prefs) 125a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) : prefs_(prefs) { 126a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) pref_change_registrar_.Init(prefs_); 127a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) pref_change_registrar_.Add( 128a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) prefs::kGoogleServicesLastUsername, 129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::Bind(&SupervisedUserSyncService::OnLastSignedInUsernameChange, 130a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Unretained(this))); 131a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 132a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SupervisedUserSyncService::~SupervisedUserSyncService() { 134a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 135a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 136a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// static 137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserSyncService::RegisterProfilePrefs( 138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PrefRegistrySyncable* registry) { 139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) registry->RegisterDictionaryPref(prefs::kSupervisedUsers, 140a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PrefRegistrySyncable::UNSYNCABLE_PREF); 141a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 142a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 14358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// static 144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool SupervisedUserSyncService::GetAvatarIndex(const std::string& avatar_str, 145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int* avatar_index) { 14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(avatar_index); 14758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (avatar_str.empty()) { 148d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) *avatar_index = kNoAvatar; 14958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return true; 15058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 1518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#if defined(OS_CHROMEOS) 1528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const char* prefix = kChromeOSAvatarPrefix; 1538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#else 1548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const char* prefix = kChromeAvatarPrefix; 1558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#endif 1568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) size_t prefix_len = strlen(prefix); 15758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (avatar_str.size() <= prefix_len || 1588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) avatar_str.substr(0, prefix_len) != prefix) { 15958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return false; 16058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 16158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!base::StringToInt(avatar_str.substr(prefix_len), avatar_index)) 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const int kChromeOSDummyAvatarIndex = -111; 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_CHROMEOS) 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return (*avatar_index == kChromeOSDummyAvatarIndex || 1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) (*avatar_index >= user_manager::kFirstDefaultImageIndex && 1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) *avatar_index < user_manager::kDefaultImagesCount)); 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#else 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Check if the Chrome avatar index is set to a dummy value. Some early 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // supervised user profiles on ChromeOS stored a dummy avatar index as a 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Chrome Avatar before there was logic to sync the ChromeOS avatar 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // separately. Handle this as if the Chrome Avatar was not chosen yet (which 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // is correct for these profiles). 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (*avatar_index == kChromeOSDummyAvatarIndex) 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *avatar_index = kNoAvatar; 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return (*avatar_index == kNoAvatar || 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (*avatar_index >= 0 && 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static_cast<size_t>(*avatar_index) < 182c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch profiles::GetDefaultAvatarIconCount())); 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 18558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 18658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// static 187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)std::string SupervisedUserSyncService::BuildAvatarString(int avatar_index) { 1888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#if defined(OS_CHROMEOS) 1898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const char* prefix = kChromeOSAvatarPrefix; 1908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#else 1918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const char* prefix = kChromeAvatarPrefix; 1928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#endif 1938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return base::StringPrintf("%s%d", prefix, avatar_index); 19458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 19558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserSyncService::AddObserver( 197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SupervisedUserSyncServiceObserver* observer) { 198a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) observers_.AddObserver(observer); 199a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 200a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserSyncService::RemoveObserver( 202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SupervisedUserSyncServiceObserver* observer) { 203a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) observers_.RemoveObserver(observer); 204a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 205a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)scoped_ptr<base::DictionaryValue> SupervisedUserSyncService::CreateDictionary( 20723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const std::string& name, 20823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const std::string& master_key, 20923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const std::string& signature_key, 21023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const std::string& encryption_key, 21123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) int avatar_index) { 21223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue()); 21323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) result->SetString(kName, name); 21423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) result->SetString(kMasterKey, master_key); 21523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) result->SetString(kPasswordSignatureKey, signature_key); 21623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) result->SetString(kPasswordEncryptionKey, encryption_key); 21723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // TODO(akuegel): Get rid of the avatar stuff here when Chrome OS switches 21823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // to the avatar index that is stored as a shared setting. 21923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) std::string chrome_avatar; 22023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) std::string chromeos_avatar; 22123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#if defined(OS_CHROMEOS) 22223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) chromeos_avatar = BuildAvatarString(avatar_index); 22323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#else 22423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) chrome_avatar = BuildAvatarString(avatar_index); 22523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#endif 22623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) result->SetString(kChromeAvatar, chrome_avatar); 22723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) result->SetString(kChromeOsAvatar, chromeos_avatar); 22823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return result.Pass(); 22923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 23023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserSyncService::AddSupervisedUser( 232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& id, 233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& name, 234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& master_key, 235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& signature_key, 236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& encryption_key, 237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int avatar_index) { 238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) UpdateSupervisedUserImpl(id, 239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) name, 240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) master_key, 241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) signature_key, 242f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) encryption_key, 243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) avatar_index, 244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) true /* add */); 24523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 24623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserSyncService::UpdateSupervisedUser( 24823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const std::string& id, 24923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const std::string& name, 25023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const std::string& master_key, 25123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const std::string& signature_key, 25223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const std::string& encryption_key, 25323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) int avatar_index) { 254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) UpdateSupervisedUserImpl(id, 255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) name, 256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) master_key, 257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) signature_key, 258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) encryption_key, 259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) avatar_index, 260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) false /* update */); 26123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 26223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserSyncService::UpdateSupervisedUserImpl( 26423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const std::string& id, 26523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const std::string& name, 26623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const std::string& master_key, 26723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const std::string& signature_key, 26823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const std::string& encryption_key, 26923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) int avatar_index, 27023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) bool add_user) { 271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DictionaryPrefUpdate update(prefs_, prefs::kSupervisedUsers); 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* dict = update.Get(); 27323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) scoped_ptr<base::DictionaryValue> value = CreateDictionary( 27423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) name, master_key, signature_key, encryption_key, avatar_index); 27523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 27623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) DCHECK_EQ(add_user, !dict->HasKey(id)); 27723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) base::DictionaryValue* entry = value.get(); 27823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) dict->SetWithoutPathExpansion(id, value.release()); 279a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 280a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!sync_processor_) 281a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 282a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 283a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // If we're already syncing, create a new change and upload it. 284a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SyncChangeList change_list; 28523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) change_list.push_back( 28623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) SyncChange(FROM_HERE, 28723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) add_user ? SyncChange::ACTION_ADD : SyncChange::ACTION_UPDATE, 28823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) CreateSyncDataFromDictionaryEntry(id, *entry))); 289a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SyncError error = 290a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) sync_processor_->ProcessSyncChanges(FROM_HERE, change_list); 291a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK(!error.IsSet()) << error.ToString(); 292a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 293a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserSyncService::DeleteSupervisedUser(const std::string& id) { 295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DictionaryPrefUpdate update(prefs_, prefs::kSupervisedUsers); 296d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) bool success = update->RemoveWithoutPathExpansion(id, NULL); 297d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(success); 298d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 299a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!sync_processor_) 300a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 301a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 302a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SyncChangeList change_list; 303a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) change_list.push_back(SyncChange( 304a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) FROM_HERE, 305a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SyncChange::ACTION_DELETE, 306f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SyncData::CreateLocalDelete(id, SUPERVISED_USERS))); 307a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SyncError sync_error = 308a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) sync_processor_->ProcessSyncChanges(FROM_HERE, change_list); 309a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK(!sync_error.IsSet()); 310a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 311a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const base::DictionaryValue* SupervisedUserSyncService::GetSupervisedUsers() { 31358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(sync_processor_); 314f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return prefs_->GetDictionary(prefs::kSupervisedUsers); 31558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 31658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool SupervisedUserSyncService::UpdateSupervisedUserAvatarIfNeeded( 318d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::string& id, 319d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int avatar_index) { 320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DictionaryPrefUpdate update(prefs_, prefs::kSupervisedUsers); 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* dict = update.Get(); 322d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(dict->HasKey(id)); 3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* value = NULL; 324d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) bool success = dict->GetDictionaryWithoutPathExpansion(id, &value); 325d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(success); 326d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 327d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) bool acknowledged = false; 328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->GetBoolean(SupervisedUserSyncService::kAcknowledged, &acknowledged); 329d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string name; 330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->GetString(SupervisedUserSyncService::kName, &name); 331d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string master_key; 332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->GetString(SupervisedUserSyncService::kMasterKey, &master_key); 333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string signature; 334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->GetString(SupervisedUserSyncService::kPasswordSignatureKey, 335f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &signature); 336a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string encryption; 337f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->GetString(SupervisedUserSyncService::kPasswordEncryptionKey, 338f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &encryption); 339d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string chromeos_avatar; 340f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->GetString(SupervisedUserSyncService::kChromeOsAvatar, 341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &chromeos_avatar); 342d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string chrome_avatar; 343f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->GetString(SupervisedUserSyncService::kChromeAvatar, &chrome_avatar); 344a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // The following check is just for safety. We want to avoid that the existing 345a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // avatar selection is overwritten. Currently we don't allow the user to 346a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // choose a different avatar in the recreation dialog, anyway, if there is 347a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // already an avatar selected. 348a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(OS_CHROMEOS) 349a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!chromeos_avatar.empty() && avatar_index != kNoAvatar) 350a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 351a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#else 352d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!chrome_avatar.empty() && avatar_index != kNoAvatar) 353d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return false; 354a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif 355d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 356d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) chrome_avatar = avatar_index == kNoAvatar ? 357d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string() : BuildAvatarString(avatar_index); 358a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(OS_CHROMEOS) 359a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) value->SetString(kChromeOsAvatar, chrome_avatar); 360a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#else 361d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) value->SetString(kChromeAvatar, chrome_avatar); 362a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif 363d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 364d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!sync_processor_) 365d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return true; 366d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 367d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SyncChangeList change_list; 368d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) change_list.push_back(SyncChange( 369d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FROM_HERE, 370d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SyncChange::ACTION_UPDATE, 371d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) CreateLocalSyncData(id, name, acknowledged, master_key, 372a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) chrome_avatar, chromeos_avatar, 373a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) signature, encryption))); 374d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SyncError error = 375d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) sync_processor_->ProcessSyncChanges(FROM_HERE, change_list); 376d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!error.IsSet()) << error.ToString(); 377d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return true; 378d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 379d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 380f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserSyncService::ClearSupervisedUserAvatar( 381f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& id) { 382f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool cleared = UpdateSupervisedUserAvatarIfNeeded(id, kNoAvatar); 383d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(cleared); 384d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 385d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 386f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserSyncService::GetSupervisedUsersAsync( 387f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const SupervisedUsersCallback& callback) { 38858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // If we are already syncing, just run the callback. 38958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (sync_processor_) { 390f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) callback.Run(GetSupervisedUsers()); 39158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 39258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 39358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 39458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Otherwise queue it up until we start syncing. 39558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) callbacks_.push_back(callback); 39658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 39758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 398f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserSyncService::Shutdown() { 399f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NotifySupervisedUsersSyncingStopped(); 400a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 401a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 402f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SyncMergeResult SupervisedUserSyncService::MergeDataAndStartSyncing( 403a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ModelType type, 404a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const SyncDataList& initial_sync_data, 405a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) scoped_ptr<SyncChangeProcessor> sync_processor, 406a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) scoped_ptr<SyncErrorFactory> error_handler) { 407f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK_EQ(SUPERVISED_USERS, type); 408a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) sync_processor_ = sync_processor.Pass(); 409a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) error_handler_ = error_handler.Pass(); 410a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 411a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SyncChangeList change_list; 412f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SyncMergeResult result(SUPERVISED_USERS); 413a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 414f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DictionaryPrefUpdate update(prefs_, prefs::kSupervisedUsers); 4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* dict = update.Get(); 416a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) result.set_num_items_before_association(dict->size()); 417a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) std::set<std::string> seen_ids; 418a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) int num_items_added = 0; 419a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) int num_items_modified = 0; 420a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) for (SyncDataList::const_iterator it = initial_sync_data.begin(); 421a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) it != initial_sync_data.end(); ++it) { 422f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK_EQ(SUPERVISED_USERS, it->GetDataType()); 423f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ManagedUserSpecifics& supervised_user = 424a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) it->GetSpecifics().managed_user(); 4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* value = new base::DictionaryValue(); 426f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->SetString(kName, supervised_user.name()); 427f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->SetBoolean(kAcknowledged, supervised_user.acknowledged()); 428f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->SetString(kMasterKey, supervised_user.master_key()); 429f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->SetString(kChromeAvatar, supervised_user.chrome_avatar()); 430f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->SetString(kChromeOsAvatar, supervised_user.chromeos_avatar()); 431a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) value->SetString(kPasswordSignatureKey, 432f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) supervised_user.password_signature_key()); 433a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) value->SetString(kPasswordEncryptionKey, 434f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) supervised_user.password_encryption_key()); 435f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (dict->HasKey(supervised_user.id())) 436a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) num_items_modified++; 437a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) else 438a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) num_items_added++; 439f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dict->SetWithoutPathExpansion(supervised_user.id(), value); 440f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) seen_ids.insert(supervised_user.id()); 441a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 442a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) { 444a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (seen_ids.find(it.key()) != seen_ids.end()) 445a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) continue; 446a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 44723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) change_list.push_back( 44823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) SyncChange(FROM_HERE, 44923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) SyncChange::ACTION_ADD, 45023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) CreateSyncDataFromDictionaryEntry(it.key(), it.value()))); 451a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 452a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) result.set_error(sync_processor_->ProcessSyncChanges(FROM_HERE, change_list)); 453a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 454a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) result.set_num_items_modified(num_items_modified); 455a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) result.set_num_items_added(num_items_added); 456a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) result.set_num_items_after_association(dict->size()); 457a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 45858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DispatchCallbacks(); 45958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 460a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return result; 461a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 462a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 463f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserSyncService::StopSyncing(ModelType type) { 464f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK_EQ(SUPERVISED_USERS, type); 465a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // The observers may want to change the Sync data, so notify them before 466a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // resetting the |sync_processor_|. 467f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NotifySupervisedUsersSyncingStopped(); 468a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) sync_processor_.reset(); 469a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) error_handler_.reset(); 470a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 471a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 472f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SyncDataList SupervisedUserSyncService::GetAllSyncData( 473a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ModelType type) const { 474a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SyncDataList data; 475f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DictionaryPrefUpdate update(prefs_, prefs::kSupervisedUsers); 4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* dict = update.Get(); 4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) 47823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) data.push_back(CreateSyncDataFromDictionaryEntry(it.key(), it.value())); 47958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 480a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return data; 481a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 482a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 483f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SyncError SupervisedUserSyncService::ProcessSyncChanges( 484a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const tracked_objects::Location& from_here, 485a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const SyncChangeList& change_list) { 486a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SyncError error; 487f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DictionaryPrefUpdate update(prefs_, prefs::kSupervisedUsers); 4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* dict = update.Get(); 489a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) for (SyncChangeList::const_iterator it = change_list.begin(); 490a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) it != change_list.end(); ++it) { 491a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SyncData data = it->sync_data(); 492f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK_EQ(SUPERVISED_USERS, data.GetDataType()); 493f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ManagedUserSpecifics& supervised_user = 494a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) data.GetSpecifics().managed_user(); 495a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) switch (it->change_type()) { 496a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) case SyncChange::ACTION_ADD: 497a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) case SyncChange::ACTION_UPDATE: { 498a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Every item we get from the server should be acknowledged. 499f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK(supervised_user.acknowledged()); 5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::DictionaryValue* old_value = NULL; 501f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dict->GetDictionaryWithoutPathExpansion(supervised_user.id(), 502f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &old_value); 503a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 504f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // For an update action, the supervised user should already exist, for 505f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // an add action, it should not. 506a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK_EQ( 507a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) old_value ? SyncChange::ACTION_UPDATE : SyncChange::ACTION_ADD, 508a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) it->change_type()); 509a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 510f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // If the supervised user switched from unacknowledged to acknowledged, 511a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // we might need to continue with a registration. 512a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (old_value && !old_value->HasKey(kAcknowledged)) 513f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NotifySupervisedUserAcknowledged(supervised_user.id()); 514a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* value = new base::DictionaryValue; 516f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->SetString(kName, supervised_user.name()); 517f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->SetBoolean(kAcknowledged, supervised_user.acknowledged()); 518f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->SetString(kMasterKey, supervised_user.master_key()); 519f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->SetString(kChromeAvatar, supervised_user.chrome_avatar()); 520f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) value->SetString(kChromeOsAvatar, supervised_user.chromeos_avatar()); 521a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) value->SetString(kPasswordSignatureKey, 522f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) supervised_user.password_signature_key()); 523a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) value->SetString(kPasswordEncryptionKey, 524f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) supervised_user.password_encryption_key()); 525f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dict->SetWithoutPathExpansion(supervised_user.id(), value); 5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 527f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NotifySupervisedUsersChanged(); 528a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) break; 529a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 530a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) case SyncChange::ACTION_DELETE: { 531f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK(dict->HasKey(supervised_user.id())) << supervised_user.id(); 532f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dict->RemoveWithoutPathExpansion(supervised_user.id(), NULL); 533a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) break; 534a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 535a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) case SyncChange::ACTION_INVALID: { 536a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) NOTREACHED(); 537a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) break; 538a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 539a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 540a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 541a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return error; 542a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 543a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 544f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserSyncService::OnLastSignedInUsernameChange() { 545a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK(!sync_processor_); 546a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 547f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // If the last signed in user changes, we clear all data, to avoid supervised 548a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // users from one custodian appearing in another one's profile. 549f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) prefs_->ClearPref(prefs::kSupervisedUsers); 550a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 551a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 552f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserSyncService::NotifySupervisedUserAcknowledged( 553f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& supervised_user_id) { 554f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FOR_EACH_OBSERVER(SupervisedUserSyncServiceObserver, observers_, 555f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) OnSupervisedUserAcknowledged(supervised_user_id)); 556a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 557a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 558f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserSyncService::NotifySupervisedUsersSyncingStopped() { 559f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FOR_EACH_OBSERVER(SupervisedUserSyncServiceObserver, observers_, 560f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) OnSupervisedUsersSyncingStopped()); 561a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 56258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 563f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserSyncService::NotifySupervisedUsersChanged() { 564f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FOR_EACH_OBSERVER(SupervisedUserSyncServiceObserver, 5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) observers_, 566f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) OnSupervisedUsersChanged()); 5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 569f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserSyncService::DispatchCallbacks() { 570f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::DictionaryValue* supervised_users = 571f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) prefs_->GetDictionary(prefs::kSupervisedUsers); 572f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (std::vector<SupervisedUsersCallback>::iterator it = callbacks_.begin(); 57358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) it != callbacks_.end(); ++it) { 574f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) it->Run(supervised_users); 57558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 57658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) callbacks_.clear(); 57758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 578