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
LoadSyncToken(base::FilePath profile_dir)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
RegisterPrefs(PrefRegistrySimple * registry)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
SupervisedUserManagerImpl(UserManagerImpl * owner)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
~SupervisedUserManagerImpl()98 SupervisedUserManagerImpl::~SupervisedUserManagerImpl() {
99 }
100
GenerateUserId()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
CreateUserRecord(const std::string & manager_id,const std::string & local_user_id,const std::string & sync_user_id,const base::string16 & display_name)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
GetUserSyncId(const std::string & user_id) const168 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
GetManagerDisplayName(const std::string & user_id) const178 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
GetManagerUserId(const std::string & user_id) const190 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
GetManagerDisplayEmail(const std::string & user_id) const200 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
FindByDisplayName(const base::string16 & display_name) const213 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
FindBySyncId(const std::string & sync_id) const226 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
StartCreationTransaction(const base::string16 & display_name)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
SetCreationTransactionUserId(const std::string & email)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
CommitCreationTransaction()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
HasFailedUserCreationTransaction()263 bool SupervisedUserManagerImpl::HasFailedUserCreationTransaction() {
264 return !(g_browser_process->local_state()->
265 GetString(kLocallyManagedUserCreationTransactionDisplayName).
266 empty());
267 }
268
RollbackUserCreationTransaction()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
RemoveNonCryptohomeData(const std::string & user_id)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
CheckForFirstRun(const std::string & user_id)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
UpdateManagerName(const std::string & manager_id,const base::string16 & new_display_name)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
LoadSupervisedUserToken(Profile * profile,const LoadTokenCallback & callback)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
ConfigureSyncWithToken(Profile * profile,const std::string & token)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