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 |