1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
28bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
38bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// found in the LICENSE file.
48bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chromeos/login/users/supervised_user_manager_impl.h"
68bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/files/file_path.h"
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
98bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/prefs/pref_registry_simple.h"
108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/prefs/pref_service.h"
111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/prefs/scoped_user_pref_update.h"
128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/strings/string_util.h"
138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/strings/stringprintf.h"
148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/strings/utf_string_conversions.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/threading/sequenced_worker_pool.h"
168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/values.h"
178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/browser_process.h"
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/chromeos/login/supervised/supervised_user_authentication.h"
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/chromeos/login/supervised/supervised_user_constants.h"
206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/browser/chromeos/login/users/chrome_user_manager_impl.h"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/chromeos/profiles/profile_helper.h"
22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/supervised_user/supervised_user_service.h"
23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chromeos/login/user_names.h"
258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chromeos/settings/cros_settings_names.h"
26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/user_manager/user_type.h"
278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "google_apis/gaia/gaia_auth_util.h"
298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)using content::BrowserThread;
318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)namespace {
338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Names for pref keys in Local State.
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// A map from supervised user local user id to sync user id.
365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kSupervisedUserSyncId[] = "ManagedUserSyncId";
378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// A map from supervised user id to manager user id.
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kSupervisedUserManagers[] = "ManagedUserManagers";
408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// A map from supervised user id to manager display name.
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kSupervisedUserManagerNames[] = "ManagedUserManagerNames";
438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// A map from supervised user id to manager display e-mail.
45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char kSupervisedUserManagerDisplayEmails[] =
468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    "ManagedUserManagerDisplayEmails";
478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// A vector pref of the supervised accounts defined on this device, that had
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// not logged in yet.
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kSupervisedUsersFirstRun[] = "LocallyManagedUsersFirstRun";
518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// A pref of the next id for supervised users generation.
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kSupervisedUsersNextId[] = "LocallyManagedUsersNextId";
548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// A pref of the next id for supervised users generation.
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kSupervisedUserCreationTransactionDisplayName[] =
578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    "LocallyManagedUserCreationTransactionDisplayName";
588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// A pref of the next id for supervised users generation.
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kSupervisedUserCreationTransactionUserId[] =
618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    "LocallyManagedUserCreationTransactionUserId";
628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A map from user id to password schema id.
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kSupervisedUserPasswordSchema[] =
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "SupervisedUserPasswordSchema";
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A map from user id to password salt.
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kSupervisedUserPasswordSalt[] =
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "SupervisedUserPasswordSalt";
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A map from user id to password revision.
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kSupervisedUserPasswordRevision[] =
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "SupervisedUserPasswordRevision";
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// A map from user id to flag indicating if password should be updated upon
76c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// signin.
77c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst char kSupervisedUserNeedPasswordUpdate[] =
78c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "SupervisedUserNeedPasswordUpdate";
79c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
80c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// A map from user id to flag indicating if cryptohome does not have signature
81c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// key.
82c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst char kSupervisedUserIncompleteKey[] = "SupervisedUserHasIncompleteKey";
83c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string LoadSyncToken(base::FilePath profile_dir) {
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string token;
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::FilePath token_file =
87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      profile_dir.Append(chromeos::kSupervisedUserTokenFilename);
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  VLOG(1) << "Loading" << token_file.value();
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!base::ReadFileToString(token_file, &token))
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return std::string();
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return token;
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} // namespace
958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)namespace chromeos {
978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kSchemaVersion[] = "SchemaVersion";
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kPasswordRevision[] = "PasswordRevision";
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kSalt[] = "PasswordSalt";
10123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)const char kPasswordSignature[] = "PasswordSignature";
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kEncryptedPassword[] = "EncryptedPassword";
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kRequirePasswordUpdate[] = "RequirePasswordUpdate";
104effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst char kHasIncompleteKey[] = "HasIncompleteKey";
10523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)const char kPasswordEncryptionKey[] = "password.hmac.encryption";
10623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)const char kPasswordSignatureKey[] = "password.hmac.signature";
10723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kPasswordUpdateFile[] = "password.update";
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int kMinPasswordRevision = 1;
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// static
1128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SupervisedUserManager::RegisterPrefs(PrefRegistrySimple* registry) {
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  registry->RegisterListPref(kSupervisedUsersFirstRun);
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  registry->RegisterIntegerPref(kSupervisedUsersNextId, 0);
1158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  registry->RegisterStringPref(
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      kSupervisedUserCreationTransactionDisplayName, "");
1178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  registry->RegisterStringPref(
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      kSupervisedUserCreationTransactionUserId, "");
119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  registry->RegisterDictionaryPref(kSupervisedUserSyncId);
120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  registry->RegisterDictionaryPref(kSupervisedUserManagers);
121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  registry->RegisterDictionaryPref(kSupervisedUserManagerNames);
122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  registry->RegisterDictionaryPref(kSupervisedUserManagerDisplayEmails);
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  registry->RegisterDictionaryPref(kSupervisedUserPasswordSchema);
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  registry->RegisterDictionaryPref(kSupervisedUserPasswordSalt);
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  registry->RegisterDictionaryPref(kSupervisedUserPasswordRevision);
127c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
128c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  registry->RegisterDictionaryPref(kSupervisedUserNeedPasswordUpdate);
129c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  registry->RegisterDictionaryPref(kSupervisedUserIncompleteKey);
1308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)SupervisedUserManagerImpl::SupervisedUserManagerImpl(
1336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ChromeUserManagerImpl* owner)
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : owner_(owner), cros_settings_(CrosSettings::Get()) {
1358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // SupervisedUserManager instance should be used only on UI thread.
1368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  authentication_.reset(new SupervisedUserAuthentication(this));
1388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)SupervisedUserManagerImpl::~SupervisedUserManagerImpl() {
1418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)std::string SupervisedUserManagerImpl::GenerateUserId() {
1448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  int counter = g_browser_process->local_state()->
1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      GetInteger(kSupervisedUsersNextId);
1468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  std::string id;
1478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  bool user_exists;
1488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  do {
149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    id = base::StringPrintf(
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        "%d@%s", counter, chromeos::login::kSupervisedUserDomain);
1518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    counter++;
1528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    user_exists = (NULL != owner_->FindUser(id));
1538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    DCHECK(!user_exists);
1548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (user_exists) {
1558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      LOG(ERROR) << "Supervised user with id " << id << " already exists.";
1568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
1578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  } while (user_exists);
1588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  g_browser_process->local_state()->
1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      SetInteger(kSupervisedUsersNextId, counter);
1618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  g_browser_process->local_state()->CommitPendingWrite();
1638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return id;
1648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool SupervisedUserManagerImpl::HasSupervisedUsers(
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const std::string& manager_id) const {
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const user_manager::UserList& users = owner_->GetUsers();
1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (user_manager::UserList::const_iterator it = users.begin();
1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       it != users.end();
1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       ++it) {
1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if ((*it)->GetType() == user_manager::USER_TYPE_SUPERVISED) {
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (manager_id == GetManagerUserId((*it)->email()))
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return true;
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return false;
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const user_manager::User* SupervisedUserManagerImpl::CreateUserRecord(
1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const std::string& manager_id,
1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const std::string& local_user_id,
1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const std::string& sync_user_id,
1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const base::string16& display_name) {
1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const user_manager::User* user = FindByDisplayName(display_name);
1868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(!user);
1878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (user)
1888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return user;
1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const user_manager::User* manager = owner_->FindUser(manager_id);
1908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  CHECK(manager);
1918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  PrefService* local_state = g_browser_process->local_state();
1938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  user_manager::User* new_user =
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      user_manager::User::CreateSupervisedUser(local_user_id);
1968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  owner_->AddUserRecord(new_user);
1988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ListPrefUpdate prefs_new_users_update(local_state,
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        kSupervisedUsersFirstRun);
201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DictionaryPrefUpdate sync_id_update(local_state, kSupervisedUserSyncId);
202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DictionaryPrefUpdate manager_update(local_state, kSupervisedUserManagers);
2038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DictionaryPrefUpdate manager_name_update(local_state,
204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                           kSupervisedUserManagerNames);
205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DictionaryPrefUpdate manager_email_update(
206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      local_state,
207f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      kSupervisedUserManagerDisplayEmails);
2088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  prefs_new_users_update->Insert(0, new base::StringValue(local_user_id));
2108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  sync_id_update->SetWithoutPathExpansion(local_user_id,
2128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      new base::StringValue(sync_user_id));
2138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  manager_update->SetWithoutPathExpansion(local_user_id,
2148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      new base::StringValue(manager->email()));
2158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  manager_name_update->SetWithoutPathExpansion(local_user_id,
2168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      new base::StringValue(manager->GetDisplayName()));
2178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  manager_email_update->SetWithoutPathExpansion(local_user_id,
2188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      new base::StringValue(manager->display_email()));
2198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  owner_->SaveUserDisplayName(local_user_id, display_name);
2218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  g_browser_process->local_state()->CommitPendingWrite();
2238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return new_user;
2248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
2258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)std::string SupervisedUserManagerImpl::GetUserSyncId(const std::string& user_id)
2278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const {
2288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  std::string result;
229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  GetUserStringValue(user_id, kSupervisedUserSyncId, &result);
2308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return result;
2318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
2328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 SupervisedUserManagerImpl::GetManagerDisplayName(
2348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const std::string& user_id) const {
2358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  PrefService* local_state = g_browser_process->local_state();
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::DictionaryValue* manager_names =
237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      local_state->GetDictionary(kSupervisedUserManagerNames);
238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 result;
2398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (manager_names->GetStringWithoutPathExpansion(user_id, &result) &&
2408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      !result.empty())
2418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return result;
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return base::UTF8ToUTF16(GetManagerDisplayEmail(user_id));
2438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
2448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)std::string SupervisedUserManagerImpl::GetManagerUserId(
2468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      const std::string& user_id) const {
2478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  std::string result;
248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  GetUserStringValue(user_id, kSupervisedUserManagers, &result);
2498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return result;
2508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
2518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)std::string SupervisedUserManagerImpl::GetManagerDisplayEmail(
2538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      const std::string& user_id) const {
2548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  std::string result;
255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (GetUserStringValue(user_id,
256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                         kSupervisedUserManagerDisplayEmails,
257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                         &result) &&
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !result.empty())
2598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return result;
2608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return GetManagerUserId(user_id);
2618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
2628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SupervisedUserManagerImpl::GetPasswordInformation(
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& user_id,
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue* result) {
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int value;
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (GetUserIntegerValue(user_id, kSupervisedUserPasswordSchema, &value))
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    result->SetIntegerWithoutPathExpansion(kSchemaVersion, value);
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (GetUserIntegerValue(user_id, kSupervisedUserPasswordRevision, &value))
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    result->SetIntegerWithoutPathExpansion(kPasswordRevision, value);
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
272c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  bool flag;
273c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (GetUserBooleanValue(user_id, kSupervisedUserNeedPasswordUpdate, &flag))
274c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    result->SetBooleanWithoutPathExpansion(kRequirePasswordUpdate, flag);
275c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (GetUserBooleanValue(user_id, kSupervisedUserIncompleteKey, &flag))
276c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    result->SetBooleanWithoutPathExpansion(kHasIncompleteKey, flag);
277c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string salt;
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (GetUserStringValue(user_id, kSupervisedUserPasswordSalt, &salt))
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    result->SetStringWithoutPathExpansion(kSalt, salt);
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SupervisedUserManagerImpl::SetPasswordInformation(
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const std::string& user_id,
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const base::DictionaryValue* password_info) {
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int value;
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (password_info->GetIntegerWithoutPathExpansion(kSchemaVersion, &value))
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SetUserIntegerValue(user_id, kSupervisedUserPasswordSchema, value);
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (password_info->GetIntegerWithoutPathExpansion(kPasswordRevision, &value))
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SetUserIntegerValue(user_id, kSupervisedUserPasswordRevision, value);
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
292c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  bool flag;
293c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (password_info->GetBooleanWithoutPathExpansion(kRequirePasswordUpdate,
294c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                                    &flag)) {
295c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    SetUserBooleanValue(user_id, kSupervisedUserNeedPasswordUpdate, flag);
296c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
297c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (password_info->GetBooleanWithoutPathExpansion(kHasIncompleteKey, &flag))
298c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    SetUserBooleanValue(user_id, kSupervisedUserIncompleteKey, flag);
299c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string salt;
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (password_info->GetStringWithoutPathExpansion(kSalt, &salt))
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SetUserStringValue(user_id, kSupervisedUserPasswordSalt, salt);
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  g_browser_process->local_state()->CommitPendingWrite();
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool SupervisedUserManagerImpl::GetUserStringValue(
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& user_id,
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const char* key,
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string* out_value) const {
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PrefService* local_state = g_browser_process->local_state();
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::DictionaryValue* dictionary = local_state->GetDictionary(key);
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return dictionary->GetStringWithoutPathExpansion(user_id, out_value);
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool SupervisedUserManagerImpl::GetUserIntegerValue(
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& user_id,
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const char* key,
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int* out_value) const {
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PrefService* local_state = g_browser_process->local_state();
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::DictionaryValue* dictionary = local_state->GetDictionary(key);
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return dictionary->GetIntegerWithoutPathExpansion(user_id, out_value);
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
324c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool SupervisedUserManagerImpl::GetUserBooleanValue(const std::string& user_id,
325c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                                    const char* key,
326c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                                    bool* out_value) const {
327c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  PrefService* local_state = g_browser_process->local_state();
328c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const base::DictionaryValue* dictionary = local_state->GetDictionary(key);
329c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return dictionary->GetBooleanWithoutPathExpansion(user_id, out_value);
330c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
331c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SupervisedUserManagerImpl::SetUserStringValue(
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& user_id,
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const char* key,
3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& value) {
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PrefService* local_state = g_browser_process->local_state();
3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DictionaryPrefUpdate update(local_state, key);
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  update->SetStringWithoutPathExpansion(user_id, value);
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SupervisedUserManagerImpl::SetUserIntegerValue(
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& user_id,
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const char* key,
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const int value) {
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PrefService* local_state = g_browser_process->local_state();
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DictionaryPrefUpdate update(local_state, key);
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  update->SetIntegerWithoutPathExpansion(user_id, value);
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
350c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid SupervisedUserManagerImpl::SetUserBooleanValue(const std::string& user_id,
351c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                                    const char* key,
352c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                                    const bool value) {
353c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  PrefService* local_state = g_browser_process->local_state();
354c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DictionaryPrefUpdate update(local_state, key);
355c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  update->SetBooleanWithoutPathExpansion(user_id, value);
356c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
357c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const user_manager::User* SupervisedUserManagerImpl::FindByDisplayName(
359a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& display_name) const {
3608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const user_manager::UserList& users = owner_->GetUsers();
3625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (user_manager::UserList::const_iterator it = users.begin();
3635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       it != users.end();
3645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       ++it) {
3655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (((*it)->GetType() == user_manager::USER_TYPE_SUPERVISED) &&
3668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        ((*it)->display_name() == display_name)) {
3678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return *it;
3688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
3698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
3708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return NULL;
3718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
3728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const user_manager::User* SupervisedUserManagerImpl::FindBySyncId(
3748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const std::string& sync_id) const {
3758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const user_manager::UserList& users = owner_->GetUsers();
3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (user_manager::UserList::const_iterator it = users.begin();
3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       it != users.end();
3795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       ++it) {
3805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (((*it)->GetType() == user_manager::USER_TYPE_SUPERVISED) &&
3818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        (GetUserSyncId((*it)->email()) == sync_id)) {
3828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return *it;
3838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
3848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
3858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return NULL;
3868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
3878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SupervisedUserManagerImpl::StartCreationTransaction(
389a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const base::string16& display_name) {
3908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  g_browser_process->local_state()->
3915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      SetString(kSupervisedUserCreationTransactionDisplayName,
392a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                base::UTF16ToASCII(display_name));
3938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  g_browser_process->local_state()->CommitPendingWrite();
3948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
3958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SupervisedUserManagerImpl::SetCreationTransactionUserId(
3978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      const std::string& email) {
3988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  g_browser_process->local_state()->
3995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      SetString(kSupervisedUserCreationTransactionUserId,
4008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                email);
4018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  g_browser_process->local_state()->CommitPendingWrite();
4028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
4038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SupervisedUserManagerImpl::CommitCreationTransaction() {
4058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  g_browser_process->local_state()->
4065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ClearPref(kSupervisedUserCreationTransactionDisplayName);
4078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  g_browser_process->local_state()->
4085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ClearPref(kSupervisedUserCreationTransactionUserId);
4098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  g_browser_process->local_state()->CommitPendingWrite();
4108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
4118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool SupervisedUserManagerImpl::HasFailedUserCreationTransaction() {
4138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return !(g_browser_process->local_state()->
4145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               GetString(kSupervisedUserCreationTransactionDisplayName).
4158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                   empty());
4168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
4178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SupervisedUserManagerImpl::RollbackUserCreationTransaction() {
4198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  PrefService* prefs = g_browser_process->local_state();
4208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  std::string display_name = prefs->
4225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      GetString(kSupervisedUserCreationTransactionDisplayName);
4238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  std::string user_id = prefs->
4245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      GetString(kSupervisedUserCreationTransactionUserId);
4258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  LOG(WARNING) << "Cleaning up transaction for "
4278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)               << display_name << "/" << user_id;
4288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (user_id.empty()) {
4308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Not much to do - just remove transaction.
4315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    prefs->ClearPref(kSupervisedUserCreationTransactionDisplayName);
432f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    prefs->CommitPendingWrite();
4338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
4348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
4358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (gaia::ExtractDomainName(user_id) !=
4375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      chromeos::login::kSupervisedUserDomain) {
4385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(WARNING) << "Clean up transaction for  non-supervised user found :"
4398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                 << user_id << ", will not remove data";
4405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    prefs->ClearPref(kSupervisedUserCreationTransactionDisplayName);
4415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    prefs->ClearPref(kSupervisedUserCreationTransactionUserId);
442f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    prefs->CommitPendingWrite();
4438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
4448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
445f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  owner_->RemoveNonOwnerUserInternal(user_id, NULL);
4468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  prefs->ClearPref(kSupervisedUserCreationTransactionDisplayName);
4485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  prefs->ClearPref(kSupervisedUserCreationTransactionUserId);
4498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  prefs->CommitPendingWrite();
4508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
4518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SupervisedUserManagerImpl::RemoveNonCryptohomeData(
4538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const std::string& user_id) {
4548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  PrefService* prefs = g_browser_process->local_state();
4555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ListPrefUpdate prefs_new_users_update(prefs, kSupervisedUsersFirstRun);
4568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  prefs_new_users_update->Remove(base::StringValue(user_id), NULL);
4578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
458f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CleanPref(user_id, kSupervisedUserSyncId);
459f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CleanPref(user_id, kSupervisedUserManagers);
460f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CleanPref(user_id, kSupervisedUserManagerNames);
461f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CleanPref(user_id, kSupervisedUserManagerDisplayEmails);
4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CleanPref(user_id, kSupervisedUserPasswordSalt);
4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CleanPref(user_id, kSupervisedUserPasswordSchema);
4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CleanPref(user_id, kSupervisedUserPasswordRevision);
465c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  CleanPref(user_id, kSupervisedUserNeedPasswordUpdate);
466c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  CleanPref(user_id, kSupervisedUserIncompleteKey);
4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SupervisedUserManagerImpl::CleanPref(const std::string& user_id,
4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                          const char* key) {
4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PrefService* prefs = g_browser_process->local_state();
4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DictionaryPrefUpdate dict_update(prefs, key);
4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dict_update->RemoveWithoutPathExpansion(user_id, NULL);
4748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
4758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool SupervisedUserManagerImpl::CheckForFirstRun(const std::string& user_id) {
4778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ListPrefUpdate prefs_new_users_update(g_browser_process->local_state(),
4785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        kSupervisedUsersFirstRun);
4798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return prefs_new_users_update->Remove(base::StringValue(user_id), NULL);
4808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
4818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SupervisedUserManagerImpl::UpdateManagerName(const std::string& manager_id,
483a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& new_display_name) {
4848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  PrefService* local_state = g_browser_process->local_state();
4858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::DictionaryValue* manager_ids =
487f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      local_state->GetDictionary(kSupervisedUserManagers);
4888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DictionaryPrefUpdate manager_name_update(local_state,
490f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                           kSupervisedUserManagerNames);
4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (base::DictionaryValue::Iterator it(*manager_ids); !it.IsAtEnd();
4928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      it.Advance()) {
4938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    std::string user_id;
4948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    bool has_manager_id = it.value().GetAsString(&user_id);
4958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    DCHECK(has_manager_id);
4968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (user_id == manager_id) {
4978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      manager_name_update->SetWithoutPathExpansion(
4988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          it.key(),
4998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          new base::StringValue(new_display_name));
5008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
5018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
5028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
5038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SupervisedUserAuthentication* SupervisedUserManagerImpl::GetAuthentication() {
5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return authentication_.get();
5065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SupervisedUserManagerImpl::LoadSupervisedUserToken(
5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Profile* profile,
5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const LoadTokenCallback& callback) {
5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(antrim): use profile->GetPath() once we sure it is safe.
5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::FilePath profile_dir = ProfileHelper::GetProfilePathByUserIdHash(
513116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      ProfileHelper::Get()->GetUserByProfile(profile)->username_hash());
5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PostTaskAndReplyWithResult(
5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      content::BrowserThread::GetBlockingPool(),
5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      FROM_HERE,
5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&LoadSyncToken, profile_dir),
5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      callback);
5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SupervisedUserManagerImpl::ConfigureSyncWithToken(
5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Profile* profile,
5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& token) {
5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!token.empty())
525f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    SupervisedUserServiceFactory::GetForProfile(profile)->InitSync(token);
5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}  // namespace chromeos
529