Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / chromeos / login / managed / locally_managed_user_creation_controller.cc
blobc88738bb9cd3913c2e2485ad6766f351929b59f8
1 // Copyright (c) 2012 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.
5 #include "chrome/browser/chromeos/login/managed/locally_managed_user_creation_controller.h"
7 #include "base/bind.h"
8 #include "base/file_util.h"
9 #include "base/files/file_path.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_util.h"
12 #include "base/sys_info.h"
13 #include "base/task_runner_util.h"
14 #include "base/threading/sequenced_worker_pool.h"
15 #include "base/values.h"
16 #include "chrome/browser/chromeos/login/managed/locally_managed_user_constants.h"
17 #include "chrome/browser/chromeos/login/managed/supervised_user_authentication.h"
18 #include "chrome/browser/chromeos/login/mount_manager.h"
19 #include "chrome/browser/chromeos/login/supervised_user_manager.h"
20 #include "chrome/browser/chromeos/login/user.h"
21 #include "chrome/browser/chromeos/login/user_manager.h"
22 #include "chrome/browser/lifetime/application_lifetime.h"
23 #include "chrome/browser/sync/profile_sync_service.h"
24 #include "chrome/browser/sync/profile_sync_service_factory.h"
25 #include "chromeos/dbus/dbus_thread_manager.h"
26 #include "chromeos/dbus/session_manager_client.h"
27 #include "content/public/browser/browser_thread.h"
28 #include "content/public/browser/user_metrics.h"
29 #include "crypto/random.h"
30 #include "google_apis/gaia/google_service_auth_error.h"
32 namespace chromeos {
34 namespace {
36 const int kMasterKeySize = 32;
37 const int kUserCreationTimeoutSeconds = 30; // 30 seconds.
39 bool StoreManagedUserFiles(const std::string& token,
40 const base::FilePath& base_path) {
41 if (!base::SysInfo::IsRunningOnChromeOS()) {
42 // If running on desktop, cryptohome stub does not create home directory.
43 base::CreateDirectory(base_path);
45 base::FilePath token_file = base_path.Append(kManagedUserTokenFilename);
46 int bytes = file_util::WriteFile(token_file, token.c_str(), token.length());
47 return bytes >= 0;
50 } // namespace
52 // static
53 const int LocallyManagedUserCreationController::kDummyAvatarIndex = -111;
55 LocallyManagedUserCreationController::StatusConsumer::~StatusConsumer() {}
57 LocallyManagedUserCreationController::UserCreationContext::UserCreationContext()
58 : avatar_index(kDummyAvatarIndex),
59 token_acquired(false),
60 token_succesfully_written(false),
61 creation_type(NEW_USER),
62 manager_profile(NULL) {}
64 LocallyManagedUserCreationController::UserCreationContext::
65 ~UserCreationContext() {}
67 // static
68 LocallyManagedUserCreationController*
69 LocallyManagedUserCreationController::current_controller_ = NULL;
71 LocallyManagedUserCreationController::LocallyManagedUserCreationController(
72 LocallyManagedUserCreationController::StatusConsumer* consumer,
73 const std::string& manager_id)
74 : consumer_(consumer),
75 weak_factory_(this) {
76 DCHECK(!current_controller_) << "More than one controller exist.";
77 current_controller_ = this;
78 creation_context_.reset(
79 new LocallyManagedUserCreationController::UserCreationContext());
80 creation_context_->manager_id = manager_id;
83 LocallyManagedUserCreationController::~LocallyManagedUserCreationController() {
84 current_controller_ = NULL;
87 void LocallyManagedUserCreationController::SetUpCreation(
88 const base::string16& display_name,
89 const std::string& password,
90 int avatar_index) {
91 DCHECK(creation_context_);
92 creation_context_->display_name = display_name;
93 creation_context_->password = password;
94 creation_context_->avatar_index = avatar_index;
97 void LocallyManagedUserCreationController::StartImport(
98 const base::string16& display_name,
99 const std::string& password,
100 int avatar_index,
101 const std::string& sync_id,
102 const std::string& master_key) {
103 DCHECK(creation_context_);
104 creation_context_->creation_type = USER_IMPORT;
105 creation_context_->display_name = display_name;
106 creation_context_->password = password;
107 creation_context_->avatar_index = avatar_index;
108 creation_context_->sync_user_id = sync_id;
109 creation_context_->master_key = master_key;
110 StartCreation();
113 void LocallyManagedUserCreationController::SetManagerProfile(
114 Profile* manager_profile) {
115 creation_context_->manager_profile = manager_profile;
118 void LocallyManagedUserCreationController::StartCreation() {
119 DCHECK(creation_context_);
120 VLOG(1) << "Starting supervised user creation";
122 ProfileSyncService* sync_service =
123 ProfileSyncServiceFactory::GetInstance()->GetForProfile(
124 creation_context_->manager_profile);
125 ProfileSyncService::SyncStatusSummary status =
126 sync_service->QuerySyncStatusSummary();
128 if (status == ProfileSyncService::DATATYPES_NOT_INITIALIZED)
129 consumer_->OnLongCreationWarning();
131 timeout_timer_.Start(
132 FROM_HERE, base::TimeDelta::FromSeconds(kUserCreationTimeoutSeconds),
133 this,
134 &LocallyManagedUserCreationController::CreationTimedOut);
135 SupervisedUserManager* manager =
136 UserManager::Get()->GetSupervisedUserManager();
137 manager->StartCreationTransaction(creation_context_->display_name);
139 creation_context_->local_user_id = manager->GenerateUserId();
141 if (creation_context_->creation_type == NEW_USER) {
142 creation_context_->sync_user_id =
143 ManagedUserRegistrationUtility::GenerateNewManagedUserId();
146 manager->CreateUserRecord(
147 creation_context_->manager_id,
148 creation_context_->local_user_id,
149 creation_context_->sync_user_id,
150 creation_context_->display_name);
152 manager->SetCreationTransactionUserId(creation_context_->local_user_id);
153 SupervisedUserAuthentication* authentication = manager->GetAuthentication();
154 if (authentication->FillDataForNewUser(creation_context_->local_user_id,
155 creation_context_->password,
156 &creation_context_->password_data)) {
157 authentication->StorePasswordData(creation_context_->local_user_id,
158 creation_context_->password_data);
160 VLOG(1) << "Creating cryptohome";
161 authenticator_ = new ManagedUserAuthenticator(this);
162 authenticator_->AuthenticateToCreate(creation_context_->local_user_id,
163 authentication->TransformPassword(
164 creation_context_->local_user_id,
165 creation_context_->password));
168 void LocallyManagedUserCreationController::OnAuthenticationFailure(
169 ManagedUserAuthenticator::AuthState error) {
170 timeout_timer_.Stop();
171 ErrorCode code = NO_ERROR;
172 switch (error) {
173 case ManagedUserAuthenticator::NO_MOUNT:
174 code = CRYPTOHOME_NO_MOUNT;
175 break;
176 case ManagedUserAuthenticator::FAILED_MOUNT:
177 code = CRYPTOHOME_FAILED_MOUNT;
178 break;
179 case ManagedUserAuthenticator::FAILED_TPM:
180 code = CRYPTOHOME_FAILED_TPM;
181 break;
182 default:
183 NOTREACHED();
185 if (consumer_)
186 consumer_->OnCreationError(code);
189 void LocallyManagedUserCreationController::OnMountSuccess(
190 const std::string& mount_hash) {
191 creation_context_->mount_hash = mount_hash;
193 if (creation_context_->creation_type == NEW_USER) {
194 // Generate master password.
195 char master_key_bytes[kMasterKeySize];
196 crypto::RandBytes(&master_key_bytes, sizeof(master_key_bytes));
197 creation_context_->master_key = StringToLowerASCII(base::HexEncode(
198 reinterpret_cast<const void*>(master_key_bytes),
199 sizeof(master_key_bytes)));
202 VLOG(1) << "Adding master key";
203 SupervisedUserAuthentication* authentication = UserManager::Get()->
204 GetSupervisedUserManager()->GetAuthentication();
206 authenticator_->AddMasterKey(creation_context_->local_user_id,
207 authentication->TransformPassword(
208 creation_context_->local_user_id,
209 creation_context_->password),
210 creation_context_->master_key);
213 void LocallyManagedUserCreationController::OnAddKeySuccess() {
214 creation_context_->registration_utility =
215 ManagedUserRegistrationUtility::Create(
216 creation_context_->manager_profile);
218 VLOG(1) << "Creating user on server";
219 // TODO(antrim) : add password data to sync once API is ready.
220 // http://crbug.com/316168
221 ManagedUserRegistrationInfo info(creation_context_->display_name,
222 creation_context_->avatar_index);
223 info.master_key = creation_context_->master_key;
224 timeout_timer_.Stop();
225 creation_context_->registration_utility->Register(
226 creation_context_->sync_user_id,
227 info,
228 base::Bind(&LocallyManagedUserCreationController::RegistrationCallback,
229 weak_factory_.GetWeakPtr()));
232 void LocallyManagedUserCreationController::RegistrationCallback(
233 const GoogleServiceAuthError& error,
234 const std::string& token) {
235 if (error.state() == GoogleServiceAuthError::NONE) {
236 timeout_timer_.Start(
237 FROM_HERE, base::TimeDelta::FromSeconds(kUserCreationTimeoutSeconds),
238 this,
239 &LocallyManagedUserCreationController::CreationTimedOut);
240 TokenFetched(token);
241 } else {
242 LOG(ERROR) << "Managed user creation failed. Error code " << error.state();
243 if (consumer_)
244 consumer_->OnCreationError(CLOUD_SERVER_ERROR);
248 void LocallyManagedUserCreationController::CreationTimedOut() {
249 LOG(ERROR) << "Supervised user creation timed out.";
250 if (consumer_)
251 consumer_->OnCreationTimeout();
254 void LocallyManagedUserCreationController::FinishCreation() {
255 chrome::AttemptUserExit();
258 void LocallyManagedUserCreationController::CancelCreation() {
259 creation_context_->registration_utility.reset();
260 chrome::AttemptUserExit();
263 std::string LocallyManagedUserCreationController::GetManagedUserId() {
264 DCHECK(creation_context_);
265 return creation_context_->local_user_id;
268 void LocallyManagedUserCreationController::TokenFetched(
269 const std::string& token) {
270 creation_context_->token_acquired = true;
271 creation_context_->token = token;
273 PostTaskAndReplyWithResult(
274 content::BrowserThread::GetBlockingPool(),
275 FROM_HERE,
276 base::Bind(&StoreManagedUserFiles,
277 creation_context_->token,
278 MountManager::GetHomeDir(creation_context_->mount_hash)),
279 base::Bind(
280 &LocallyManagedUserCreationController::OnManagedUserFilesStored,
281 weak_factory_.GetWeakPtr()));
284 void LocallyManagedUserCreationController::OnManagedUserFilesStored(
285 bool success) {
286 timeout_timer_.Stop();
288 content::RecordAction(
289 base::UserMetricsAction("ManagedMode_LocallyManagedUserCreated"));
291 if (!success) {
292 if (consumer_)
293 consumer_->OnCreationError(TOKEN_WRITE_FAILED);
294 return;
296 // Assume that new token is valid. It will be automatically invalidated if
297 // sync service fails to use it.
298 UserManager::Get()->SaveUserOAuthStatus(creation_context_->local_user_id,
299 User::OAUTH2_TOKEN_STATUS_VALID);
300 UserManager::Get()->GetSupervisedUserManager()->
301 CommitCreationTransaction();
302 if (consumer_)
303 consumer_->OnCreationSuccess();
306 } // namespace chromeos