Home | History | Annotate | Download | only in login
      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/chromeos/login/supervised_user_manager_impl.h"
      6 
      7 #include "base/file_util.h"
      8 #include "base/files/file_path.h"
      9 #include "base/prefs/pref_registry_simple.h"
     10 #include "base/prefs/pref_service.h"
     11 #include "base/prefs/scoped_user_pref_update.h"
     12 #include "base/strings/string_util.h"
     13 #include "base/strings/stringprintf.h"
     14 #include "base/strings/utf_string_conversions.h"
     15 #include "base/threading/sequenced_worker_pool.h"
     16 #include "base/values.h"
     17 #include "chrome/browser/browser_process.h"
     18 #include "chrome/browser/chromeos/login/managed/locally_managed_user_constants.h"
     19 #include "chrome/browser/chromeos/login/user_manager_impl.h"
     20 #include "chrome/browser/chromeos/profiles/profile_helper.h"
     21 #include "chrome/browser/managed_mode/managed_user_service.h"
     22 #include "chrome/browser/managed_mode/managed_user_service_factory.h"
     23 #include "chromeos/settings/cros_settings_names.h"
     24 #include "content/public/browser/browser_thread.h"
     25 #include "google_apis/gaia/gaia_auth_util.h"
     26 
     27 using content::BrowserThread;
     28 
     29 namespace {
     30 
     31 // A map from locally managed user local user id to sync user id.
     32 const char kManagedUserSyncId[] =
     33     "ManagedUserSyncId";
     34 
     35 // A map from locally managed user id to manager user id.
     36 const char kManagedUserManagers[] =
     37     "ManagedUserManagers";
     38 
     39 // A map from locally managed user id to manager display name.
     40 const char kManagedUserManagerNames[] =
     41     "ManagedUserManagerNames";
     42 
     43 // A map from locally managed user id to manager display e-mail.
     44 const char kManagedUserManagerDisplayEmails[] =
     45     "ManagedUserManagerDisplayEmails";
     46 
     47 // A vector pref of the locally managed accounts defined on this device, that
     48 // had not logged in yet.
     49 const char kLocallyManagedUsersFirstRun[] = "LocallyManagedUsersFirstRun";
     50 
     51 // A pref of the next id for locally managed users generation.
     52 const char kLocallyManagedUsersNextId[] =
     53     "LocallyManagedUsersNextId";
     54 
     55 // A pref of the next id for locally managed users generation.
     56 const char kLocallyManagedUserCreationTransactionDisplayName[] =
     57     "LocallyManagedUserCreationTransactionDisplayName";
     58 
     59 // A pref of the next id for locally managed users generation.
     60 const char kLocallyManagedUserCreationTransactionUserId[] =
     61     "LocallyManagedUserCreationTransactionUserId";
     62 
     63 std::string LoadSyncToken(base::FilePath profile_dir) {
     64   std::string token;
     65   base::FilePath token_file =
     66       profile_dir.Append(chromeos::kManagedUserTokenFilename);
     67   VLOG(1) << "Loading" << token_file.value();
     68   if (!base::ReadFileToString(token_file, &token))
     69     return std::string();
     70   return token;
     71 }
     72 
     73 } // namespace
     74 
     75 namespace chromeos {
     76 
     77 // static
     78 void SupervisedUserManager::RegisterPrefs(PrefRegistrySimple* registry) {
     79   registry->RegisterListPref(kLocallyManagedUsersFirstRun);
     80   registry->RegisterIntegerPref(kLocallyManagedUsersNextId, 0);
     81   registry->RegisterStringPref(
     82       kLocallyManagedUserCreationTransactionDisplayName, "");
     83   registry->RegisterStringPref(
     84       kLocallyManagedUserCreationTransactionUserId, "");
     85   registry->RegisterDictionaryPref(kManagedUserSyncId);
     86   registry->RegisterDictionaryPref(kManagedUserManagers);
     87   registry->RegisterDictionaryPref(kManagedUserManagerNames);
     88   registry->RegisterDictionaryPref(kManagedUserManagerDisplayEmails);
     89 }
     90 
     91 SupervisedUserManagerImpl::SupervisedUserManagerImpl(UserManagerImpl* owner)
     92     : owner_(owner),
     93       cros_settings_(CrosSettings::Get()) {
     94   // SupervisedUserManager instance should be used only on UI thread.
     95   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     96 }
     97 
     98 SupervisedUserManagerImpl::~SupervisedUserManagerImpl() {
     99 }
    100 
    101 std::string SupervisedUserManagerImpl::GenerateUserId() {
    102   int counter = g_browser_process->local_state()->
    103       GetInteger(kLocallyManagedUsersNextId);
    104   std::string id;
    105   bool user_exists;
    106   do {
    107     id = base::StringPrintf("%d@%s", counter,
    108         UserManager::kLocallyManagedUserDomain);
    109     counter++;
    110     user_exists = (NULL != owner_->FindUser(id));
    111     DCHECK(!user_exists);
    112     if (user_exists) {
    113       LOG(ERROR) << "Supervised user with id " << id << " already exists.";
    114     }
    115   } while (user_exists);
    116 
    117   g_browser_process->local_state()->
    118       SetInteger(kLocallyManagedUsersNextId, counter);
    119 
    120   g_browser_process->local_state()->CommitPendingWrite();
    121   return id;
    122 }
    123 
    124 const User* SupervisedUserManagerImpl::CreateUserRecord(
    125       const std::string& manager_id,
    126       const std::string& local_user_id,
    127       const std::string& sync_user_id,
    128       const base::string16& display_name) {
    129   const User* user = FindByDisplayName(display_name);
    130   DCHECK(!user);
    131   if (user)
    132     return user;
    133   const User* manager = owner_->FindUser(manager_id);
    134   CHECK(manager);
    135 
    136   PrefService* local_state = g_browser_process->local_state();
    137 
    138   User* new_user = User::CreateLocallyManagedUser(local_user_id);
    139 
    140   owner_->AddUserRecord(new_user);
    141 
    142   ListPrefUpdate prefs_new_users_update(local_state,
    143                                         kLocallyManagedUsersFirstRun);
    144   DictionaryPrefUpdate sync_id_update(local_state, kManagedUserSyncId);
    145   DictionaryPrefUpdate manager_update(local_state, kManagedUserManagers);
    146   DictionaryPrefUpdate manager_name_update(local_state,
    147                                            kManagedUserManagerNames);
    148   DictionaryPrefUpdate manager_email_update(local_state,
    149                                             kManagedUserManagerDisplayEmails);
    150 
    151   prefs_new_users_update->Insert(0, new base::StringValue(local_user_id));
    152 
    153   sync_id_update->SetWithoutPathExpansion(local_user_id,
    154       new base::StringValue(sync_user_id));
    155   manager_update->SetWithoutPathExpansion(local_user_id,
    156       new base::StringValue(manager->email()));
    157   manager_name_update->SetWithoutPathExpansion(local_user_id,
    158       new base::StringValue(manager->GetDisplayName()));
    159   manager_email_update->SetWithoutPathExpansion(local_user_id,
    160       new base::StringValue(manager->display_email()));
    161 
    162   owner_->SaveUserDisplayName(local_user_id, display_name);
    163 
    164   g_browser_process->local_state()->CommitPendingWrite();
    165   return new_user;
    166 }
    167 
    168 std::string SupervisedUserManagerImpl::GetUserSyncId(const std::string& user_id)
    169     const {
    170   PrefService* local_state = g_browser_process->local_state();
    171   const DictionaryValue* sync_ids =
    172       local_state->GetDictionary(kManagedUserSyncId);
    173   std::string result;
    174   sync_ids->GetStringWithoutPathExpansion(user_id, &result);
    175   return result;
    176 }
    177 
    178 base::string16 SupervisedUserManagerImpl::GetManagerDisplayName(
    179     const std::string& user_id) const {
    180   PrefService* local_state = g_browser_process->local_state();
    181   const DictionaryValue* manager_names =
    182       local_state->GetDictionary(kManagedUserManagerNames);
    183   base::string16 result;
    184   if (manager_names->GetStringWithoutPathExpansion(user_id, &result) &&
    185       !result.empty())
    186     return result;
    187   return UTF8ToUTF16(GetManagerDisplayEmail(user_id));
    188 }
    189 
    190 std::string SupervisedUserManagerImpl::GetManagerUserId(
    191       const std::string& user_id) const {
    192   PrefService* local_state = g_browser_process->local_state();
    193   const DictionaryValue* manager_ids =
    194       local_state->GetDictionary(kManagedUserManagers);
    195   std::string result;
    196   manager_ids->GetStringWithoutPathExpansion(user_id, &result);
    197   return result;
    198 }
    199 
    200 std::string SupervisedUserManagerImpl::GetManagerDisplayEmail(
    201       const std::string& user_id) const {
    202   PrefService* local_state = g_browser_process->local_state();
    203   const DictionaryValue* manager_mails =
    204       local_state->GetDictionary(kManagedUserManagerDisplayEmails);
    205   std::string result;
    206   if (manager_mails->GetStringWithoutPathExpansion(user_id, &result) &&
    207       !result.empty()) {
    208     return result;
    209   }
    210   return GetManagerUserId(user_id);
    211 }
    212 
    213 const User* SupervisedUserManagerImpl::FindByDisplayName(
    214     const base::string16& display_name) const {
    215   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    216   const UserList& users = owner_->GetUsers();
    217   for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
    218     if (((*it)->GetType() == User::USER_TYPE_LOCALLY_MANAGED) &&
    219         ((*it)->display_name() == display_name)) {
    220       return *it;
    221     }
    222   }
    223   return NULL;
    224 }
    225 
    226 const User* SupervisedUserManagerImpl::FindBySyncId(
    227     const std::string& sync_id) const {
    228   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    229   const UserList& users = owner_->GetUsers();
    230   for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
    231     if (((*it)->GetType() == User::USER_TYPE_LOCALLY_MANAGED) &&
    232         (GetUserSyncId((*it)->email()) == sync_id)) {
    233       return *it;
    234     }
    235   }
    236   return NULL;
    237 }
    238 
    239 void SupervisedUserManagerImpl::StartCreationTransaction(
    240       const base::string16& display_name) {
    241   g_browser_process->local_state()->
    242       SetString(kLocallyManagedUserCreationTransactionDisplayName,
    243            UTF16ToASCII(display_name));
    244   g_browser_process->local_state()->CommitPendingWrite();
    245 }
    246 
    247 void SupervisedUserManagerImpl::SetCreationTransactionUserId(
    248       const std::string& email) {
    249   g_browser_process->local_state()->
    250       SetString(kLocallyManagedUserCreationTransactionUserId,
    251                 email);
    252   g_browser_process->local_state()->CommitPendingWrite();
    253 }
    254 
    255 void SupervisedUserManagerImpl::CommitCreationTransaction() {
    256   g_browser_process->local_state()->
    257       ClearPref(kLocallyManagedUserCreationTransactionDisplayName);
    258   g_browser_process->local_state()->
    259       ClearPref(kLocallyManagedUserCreationTransactionUserId);
    260   g_browser_process->local_state()->CommitPendingWrite();
    261 }
    262 
    263 bool SupervisedUserManagerImpl::HasFailedUserCreationTransaction() {
    264   return !(g_browser_process->local_state()->
    265                GetString(kLocallyManagedUserCreationTransactionDisplayName).
    266                    empty());
    267 }
    268 
    269 void SupervisedUserManagerImpl::RollbackUserCreationTransaction() {
    270   PrefService* prefs = g_browser_process->local_state();
    271 
    272   std::string display_name = prefs->
    273       GetString(kLocallyManagedUserCreationTransactionDisplayName);
    274   std::string user_id = prefs->
    275       GetString(kLocallyManagedUserCreationTransactionUserId);
    276 
    277   LOG(WARNING) << "Cleaning up transaction for "
    278                << display_name << "/" << user_id;
    279 
    280   if (user_id.empty()) {
    281     // Not much to do - just remove transaction.
    282     prefs->ClearPref(kLocallyManagedUserCreationTransactionDisplayName);
    283     prefs->CommitPendingWrite();
    284     return;
    285   }
    286 
    287   if (gaia::ExtractDomainName(user_id) !=
    288           UserManager::kLocallyManagedUserDomain) {
    289     LOG(WARNING) << "Clean up transaction for  non-locally managed user found :"
    290                  << user_id << ", will not remove data";
    291     prefs->ClearPref(kLocallyManagedUserCreationTransactionDisplayName);
    292     prefs->ClearPref(kLocallyManagedUserCreationTransactionUserId);
    293     prefs->CommitPendingWrite();
    294     return;
    295   }
    296   owner_->RemoveNonOwnerUserInternal(user_id, NULL);
    297 
    298   prefs->ClearPref(kLocallyManagedUserCreationTransactionDisplayName);
    299   prefs->ClearPref(kLocallyManagedUserCreationTransactionUserId);
    300   prefs->CommitPendingWrite();
    301 }
    302 
    303 void SupervisedUserManagerImpl::RemoveNonCryptohomeData(
    304     const std::string& user_id) {
    305   PrefService* prefs = g_browser_process->local_state();
    306   ListPrefUpdate prefs_new_users_update(prefs, kLocallyManagedUsersFirstRun);
    307   prefs_new_users_update->Remove(base::StringValue(user_id), NULL);
    308 
    309   DictionaryPrefUpdate synd_id_update(prefs, kManagedUserSyncId);
    310   synd_id_update->RemoveWithoutPathExpansion(user_id, NULL);
    311 
    312   DictionaryPrefUpdate managers_update(prefs, kManagedUserManagers);
    313   managers_update->RemoveWithoutPathExpansion(user_id, NULL);
    314 
    315   DictionaryPrefUpdate manager_names_update(prefs,
    316                                             kManagedUserManagerNames);
    317   manager_names_update->RemoveWithoutPathExpansion(user_id, NULL);
    318 
    319   DictionaryPrefUpdate manager_emails_update(prefs,
    320                                              kManagedUserManagerDisplayEmails);
    321   manager_emails_update->RemoveWithoutPathExpansion(user_id, NULL);
    322 }
    323 
    324 bool SupervisedUserManagerImpl::CheckForFirstRun(const std::string& user_id) {
    325   ListPrefUpdate prefs_new_users_update(g_browser_process->local_state(),
    326                                         kLocallyManagedUsersFirstRun);
    327   return prefs_new_users_update->Remove(base::StringValue(user_id), NULL);
    328 }
    329 
    330 void SupervisedUserManagerImpl::UpdateManagerName(const std::string& manager_id,
    331     const base::string16& new_display_name) {
    332   PrefService* local_state = g_browser_process->local_state();
    333 
    334   const DictionaryValue* manager_ids =
    335       local_state->GetDictionary(kManagedUserManagers);
    336 
    337   DictionaryPrefUpdate manager_name_update(local_state,
    338                                            kManagedUserManagerNames);
    339   for (DictionaryValue::Iterator it(*manager_ids); !it.IsAtEnd();
    340       it.Advance()) {
    341     std::string user_id;
    342     bool has_manager_id = it.value().GetAsString(&user_id);
    343     DCHECK(has_manager_id);
    344     if (user_id == manager_id) {
    345       manager_name_update->SetWithoutPathExpansion(
    346           it.key(),
    347           new base::StringValue(new_display_name));
    348     }
    349   }
    350 }
    351 
    352 void SupervisedUserManagerImpl::LoadSupervisedUserToken(
    353     Profile* profile,
    354     const LoadTokenCallback& callback) {
    355   // TODO(antrim): use profile->GetPath() once we sure it is safe.
    356   base::FilePath profile_dir = ProfileHelper::GetProfilePathByUserIdHash(
    357       UserManager::Get()->GetUserByProfile(profile)->username_hash());
    358   PostTaskAndReplyWithResult(
    359       content::BrowserThread::GetBlockingPool(),
    360       FROM_HERE,
    361       base::Bind(&LoadSyncToken, profile_dir),
    362       callback);
    363 }
    364 
    365 void SupervisedUserManagerImpl::ConfigureSyncWithToken(
    366     Profile* profile,
    367     const std::string& token) {
    368   if (!token.empty())
    369     ManagedUserServiceFactory::GetForProfile(profile)->InitSync(token);
    370 }
    371 
    372 }  // namespace chromeos
    373