| OLD | NEW |
| (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 } | |
| OLD | NEW |