ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / chrome / browser / chromeos / login / supervised / supervised_user_login_flow.cc
blobcbbbc6e0d37e0a3a078c2cdcd79981ee20e12e5a
1 // Copyright 2014 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/supervised/supervised_user_login_flow.h"
7 #include "base/base64.h"
8 #include "base/command_line.h"
9 #include "base/logging.h"
10 #include "base/metrics/histogram.h"
11 #include "base/prefs/pref_registry_simple.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/values.h"
14 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
15 #include "chrome/browser/chromeos/login/supervised/supervised_user_authentication.h"
16 #include "chrome/browser/chromeos/login/supervised/supervised_user_constants.h"
17 #include "chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.h"
18 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
19 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
20 #include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
21 #include "chrome/browser/chromeos/login/wizard_controller.h"
22 #include "chrome/common/chrome_switches.h"
23 #include "chromeos/login/auth/key.h"
24 #include "components/user_manager/user_manager.h"
25 #include "content/public/browser/browser_thread.h"
27 using content::BrowserThread;
29 namespace chromeos {
31 SupervisedUserLoginFlow::SupervisedUserLoginFlow(
32 const std::string& user_id)
33 : ExtendedUserFlow(user_id),
34 data_loaded_(false),
35 weak_factory_(this) {
38 SupervisedUserLoginFlow::~SupervisedUserLoginFlow() {}
40 void SupervisedUserLoginFlow::AppendAdditionalCommandLineSwitches() {
41 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
42 if (user_manager->IsCurrentUserNew()) {
43 // Supervised users should launch into empty desktop on first run.
44 base::CommandLine::ForCurrentProcess()->AppendSwitch(
45 ::switches::kSilentLaunch);
49 bool SupervisedUserLoginFlow::CanLockScreen() {
50 return true;
53 bool SupervisedUserLoginFlow::ShouldLaunchBrowser() {
54 return data_loaded_;
57 bool SupervisedUserLoginFlow::ShouldSkipPostLoginScreens() {
58 return true;
61 bool SupervisedUserLoginFlow::SupportsEarlyRestartToApplyFlags() {
62 return false;
65 bool SupervisedUserLoginFlow::HandleLoginFailure(const AuthFailure& failure) {
66 return false;
69 bool SupervisedUserLoginFlow::HandlePasswordChangeDetected() {
70 return false;
73 void SupervisedUserLoginFlow::OnSyncSetupDataLoaded(
74 const std::string& token) {
75 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
76 ConfigureSync(token);
79 void SupervisedUserLoginFlow::ConfigureSync(const std::string& token) {
80 data_loaded_ = true;
82 // TODO(antrim): add error handling (no token loaded).
83 // See also: http://crbug.com/312751
84 ChromeUserManager::Get()->GetSupervisedUserManager()->ConfigureSyncWithToken(
85 profile_, token);
86 SupervisedUserAuthentication* auth =
87 ChromeUserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
89 if (auth->HasScheduledPasswordUpdate(user_id())) {
90 auth->LoadPasswordUpdateData(
91 user_id(),
92 base::Bind(&SupervisedUserLoginFlow::OnPasswordChangeDataLoaded,
93 weak_factory_.GetWeakPtr()),
94 base::Bind(&SupervisedUserLoginFlow::OnPasswordChangeDataLoadFailed,
95 weak_factory_.GetWeakPtr()));
96 return;
98 Finish();
101 void SupervisedUserLoginFlow::HandleLoginSuccess(
102 const UserContext& login_context) {
103 context_ = login_context;
106 void SupervisedUserLoginFlow::OnPasswordChangeDataLoaded(
107 const base::DictionaryValue* password_data) {
108 // Edge case, when manager has signed in and already updated the password.
109 SupervisedUserAuthentication* auth =
110 ChromeUserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
111 if (!auth->NeedPasswordChange(user_id(), password_data)) {
112 VLOG(1) << "Password already changed for " << user_id();
113 auth->ClearScheduledPasswordUpdate(user_id());
114 Finish();
115 return;
118 // Two cases now - we can currently have either old-style password, or new
119 // password.
120 std::string base64_signature;
121 std::string signature;
122 std::string password;
123 int revision = 0;
124 int schema = 0;
125 bool success = password_data->GetStringWithoutPathExpansion(
126 kPasswordSignature, &base64_signature);
127 success &= password_data->GetIntegerWithoutPathExpansion(kPasswordRevision,
128 &revision);
129 success &=
130 password_data->GetIntegerWithoutPathExpansion(kSchemaVersion, &schema);
131 success &= password_data->GetStringWithoutPathExpansion(kEncryptedPassword,
132 &password);
133 if (!success) {
134 LOG(ERROR) << "Incomplete data for password change";
136 UMA_HISTOGRAM_ENUMERATION(
137 "ManagedUsers.ChromeOS.PasswordChange",
138 SupervisedUserAuthentication::PASSWORD_CHANGE_FAILED_INCOMPLETE_DATA,
139 SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
140 Finish();
141 return;
143 base::Base64Decode(base64_signature, &signature);
144 scoped_ptr<base::DictionaryValue> data_copy(password_data->DeepCopy());
145 cryptohome::KeyDefinition key(password,
146 kCryptohomeSupervisedUserKeyLabel,
147 kCryptohomeSupervisedUserKeyPrivileges);
149 authenticator_ = ExtendedAuthenticator::Create(this);
150 SupervisedUserAuthentication::Schema current_schema =
151 auth->GetPasswordSchema(user_id());
153 key.revision = revision;
155 if (SupervisedUserAuthentication::SCHEMA_PLAIN == current_schema) {
156 // We need to add new key, and block old one. As we don't actually have
157 // signature key, use Migrate privilege instead of AuthorizedUpdate.
158 key.privileges = kCryptohomeSupervisedUserIncompleteKeyPrivileges;
160 VLOG(1) << "Adding new schema key";
161 DCHECK(context_.GetKey()->GetLabel().empty());
162 authenticator_->AddKey(context_,
163 key,
164 false /* no key exists */,
165 base::Bind(&SupervisedUserLoginFlow::OnNewKeyAdded,
166 weak_factory_.GetWeakPtr(),
167 Passed(&data_copy)));
168 } else if (SupervisedUserAuthentication::SCHEMA_SALT_HASHED ==
169 current_schema) {
170 VLOG(1) << "Updating the key";
172 if (auth->HasIncompleteKey(user_id())) {
173 // We need to use Migrate instead of Authorized Update privilege.
174 key.privileges = kCryptohomeSupervisedUserIncompleteKeyPrivileges;
176 // Just update the key.
177 DCHECK_EQ(context_.GetKey()->GetLabel(), kCryptohomeSupervisedUserKeyLabel);
178 authenticator_->UpdateKeyAuthorized(
179 context_,
180 key,
181 signature,
182 base::Bind(&SupervisedUserLoginFlow::OnPasswordUpdated,
183 weak_factory_.GetWeakPtr(),
184 Passed(&data_copy)));
185 } else {
186 NOTREACHED() << "Unsupported password schema";
190 void SupervisedUserLoginFlow::OnNewKeyAdded(
191 scoped_ptr<base::DictionaryValue> password_data) {
192 VLOG(1) << "New key added";
193 SupervisedUserAuthentication* auth =
194 ChromeUserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
195 auth->StorePasswordData(user_id(), *password_data.get());
196 auth->MarkKeyIncomplete(user_id(), true /* incomplete */);
197 authenticator_->RemoveKey(
198 context_,
199 kLegacyCryptohomeSupervisedUserKeyLabel,
200 base::Bind(&SupervisedUserLoginFlow::OnOldKeyRemoved,
201 weak_factory_.GetWeakPtr()));
204 void SupervisedUserLoginFlow::OnOldKeyRemoved() {
205 UMA_HISTOGRAM_ENUMERATION(
206 "ManagedUsers.ChromeOS.PasswordChange",
207 SupervisedUserAuthentication::PASSWORD_CHANGED_IN_USER_SESSION,
208 SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
209 Finish();
212 void SupervisedUserLoginFlow::OnPasswordChangeDataLoadFailed() {
213 LOG(ERROR) << "Could not load data for password change";
215 UMA_HISTOGRAM_ENUMERATION(
216 "ManagedUsers.ChromeOS.PasswordChange",
217 SupervisedUserAuthentication::PASSWORD_CHANGE_FAILED_LOADING_DATA,
218 SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
219 Finish();
222 void SupervisedUserLoginFlow::OnAuthenticationFailure(
223 ExtendedAuthenticator::AuthState state) {
224 LOG(ERROR) << "Authentication error during password change";
226 UMA_HISTOGRAM_ENUMERATION(
227 "ManagedUsers.ChromeOS.PasswordChange",
228 SupervisedUserAuthentication::
229 PASSWORD_CHANGE_FAILED_AUTHENTICATION_FAILURE,
230 SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
231 Finish();
234 void SupervisedUserLoginFlow::OnPasswordUpdated(
235 scoped_ptr<base::DictionaryValue> password_data) {
236 VLOG(1) << "Updated password for supervised user";
238 SupervisedUserAuthentication* auth =
239 ChromeUserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
241 // Incomplete state is not there in password_data, carry it from old state.
242 bool was_incomplete = auth->HasIncompleteKey(user_id());
243 auth->StorePasswordData(user_id(), *password_data.get());
244 if (was_incomplete)
245 auth->MarkKeyIncomplete(user_id(), true /* incomplete */);
247 UMA_HISTOGRAM_ENUMERATION(
248 "ManagedUsers.ChromeOS.PasswordChange",
249 SupervisedUserAuthentication::PASSWORD_CHANGED_IN_USER_SESSION,
250 SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
251 Finish();
254 void SupervisedUserLoginFlow::Finish() {
255 UserSessionManager::GetInstance()->DoBrowserLaunch(profile_, host());
256 profile_ = NULL;
257 UnregisterFlowSoon();
260 void SupervisedUserLoginFlow::LaunchExtraSteps(
261 Profile* profile) {
262 profile_ = profile;
263 ChromeUserManager::Get()->GetSupervisedUserManager()->LoadSupervisedUserToken(
264 profile,
265 base::Bind(&SupervisedUserLoginFlow::OnSyncSetupDataLoaded,
266 weak_factory_.GetWeakPtr()));
269 } // namespace chromeos