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