Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / managed_mode / managed_user_sync_service.cc
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/user_prefs/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/default_user_images.h"
25 #endif
26
27 using base::DictionaryValue;
28 using user_prefs::PrefRegistrySyncable;
29 using syncer::MANAGED_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::kManagedUsers,
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::kManagedUsers);
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::kManagedUsers);
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, MANAGED_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::kManagedUsers);
313 }
314
315 bool ManagedUserSyncService::UpdateManagedUserAvatarIfNeeded(
316     const std::string& id,
317     int avatar_index) {
318   DictionaryPrefUpdate update(prefs_, prefs::kManagedUsers);
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(MANAGED_USERS, type);
402   sync_processor_ = sync_processor.Pass();
403   error_handler_ = error_handler.Pass();
404
405   SyncChangeList change_list;
406   SyncMergeResult result(MANAGED_USERS);
407
408   DictionaryPrefUpdate update(prefs_, prefs::kManagedUsers);
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(MANAGED_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(MANAGED_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::kManagedUsers);
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::kManagedUsers);
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(MANAGED_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::kManagedUsers);
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::kManagedUsers);
565   for (std::vector<ManagedUsersCallback>::iterator it = callbacks_.begin();
566        it != callbacks_.end(); ++it) {
567     it->Run(managed_users);
568   }
569   callbacks_.clear();
570 }