Adding instrumentation to locate the source of jankiness
[chromium-blink-merge.git] / chrome / browser / signin / easy_unlock_auth_attempt.cc
blob9a1842cac79a71d59616f7372155d60bc27b2542
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/signin/easy_unlock_auth_attempt.h"
7 #include "base/logging.h"
8 #include "chrome/browser/extensions/api/screenlock_private/screenlock_private_api.h"
9 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/browser/signin/screenlock_bridge.h"
11 #include "crypto/encryptor.h"
12 #include "crypto/symmetric_key.h"
15 #if defined(OS_CHROMEOS)
16 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
17 #endif
19 namespace {
21 // Fake secret used to force invalid login.
22 const char kStubSecret[] = "\xFF\x00";
24 // Decrypts the secret that should be used to login from |wrapped_secret| using
25 // raw AES key |raw_key|.
26 // In a case of error, an empty string is returned.
27 std::string UnwrapSecret(const std::string& wrapped_secret,
28 const std::string& raw_key) {
29 if (raw_key.empty())
30 return std::string();
32 // Import the key structure.
33 scoped_ptr<crypto::SymmetricKey> key(
34 crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, raw_key));
36 if (!key)
37 return std::string();
39 std::string iv(raw_key.size(), ' ');
40 crypto::Encryptor encryptor;
41 if (!encryptor.Init(key.get(), crypto::Encryptor::CBC, iv))
42 return std::string();
44 std::string secret;
45 if (!encryptor.Decrypt(wrapped_secret, &secret))
46 return std::string();
48 return secret;
51 } // namespace
53 EasyUnlockAuthAttempt::EasyUnlockAuthAttempt(Profile* profile,
54 const std::string& user_id,
55 Type type)
56 : profile_(profile),
57 state_(STATE_IDLE),
58 user_id_(user_id),
59 type_(type) {
62 EasyUnlockAuthAttempt::~EasyUnlockAuthAttempt() {
63 if (state_ == STATE_RUNNING)
64 Cancel(user_id_);
67 bool EasyUnlockAuthAttempt::Start(const std::string& user_id) {
68 DCHECK(state_ == STATE_IDLE);
70 if (!ScreenlockBridge::Get()->IsLocked())
71 return false;
73 if (user_id != user_id_) {
74 Cancel(user_id);
75 return false;
78 ScreenlockBridge::LockHandler::AuthType auth_type =
79 ScreenlockBridge::Get()->lock_handler()->GetAuthType(user_id);
81 if (auth_type != ScreenlockBridge::LockHandler::USER_CLICK) {
82 Cancel(user_id);
83 return false;
86 state_ = STATE_RUNNING;
88 // TODO(tbarzic): Replace this with an easyUnlockPrivate event that will
89 // report more context to the app (e.g. user id, whether the attempt is for
90 // signin or unlock).
91 extensions::ScreenlockPrivateEventRouter* router =
92 extensions::ScreenlockPrivateEventRouter::GetFactoryInstance()->Get(
93 profile_);
94 return router->OnAuthAttempted(auth_type, "");
97 void EasyUnlockAuthAttempt::FinalizeUnlock(const std::string& user_id,
98 bool success) {
99 if (state_ != STATE_RUNNING || user_id != user_id_)
100 return;
102 if (type_ != TYPE_UNLOCK) {
103 Cancel(user_id_);
104 return;
107 if (!ScreenlockBridge::Get()->IsLocked())
108 return;
110 if (success) {
111 ScreenlockBridge::Get()->lock_handler()->Unlock(user_id_);
112 } else {
113 ScreenlockBridge::Get()->lock_handler()->EnableInput();
116 state_ = STATE_DONE;
119 void EasyUnlockAuthAttempt::FinalizeSignin(const std::string& user_id,
120 const std::string& wrapped_secret,
121 const std::string& raw_session_key) {
122 if (state_ != STATE_RUNNING || user_id != user_id_)
123 return;
125 if (type_ != TYPE_SIGNIN) {
126 Cancel(user_id_);
127 return;
130 if (!ScreenlockBridge::Get()->IsLocked())
131 return;
134 std::string unwrapped_secret = UnwrapSecret(wrapped_secret, raw_session_key);
136 // If secret is not set, set it to an arbitrary value, otherwise there will
137 // be no authenitcation attempt and the ui will get stuck.
138 // TODO(tbarzic): Find a better way to handle this case.
139 if (unwrapped_secret.empty())
140 unwrapped_secret = kStubSecret;
142 std::string key_label;
143 #if defined(OS_CHROMEOS)
144 key_label = chromeos::EasyUnlockKeyManager::GetKeyLabel(0u);
145 #endif // defined(OS_CHROMEOS)
147 ScreenlockBridge::Get()->lock_handler()->AttemptEasySignin(
148 user_id,
149 unwrapped_secret,
150 key_label);
151 state_ = STATE_DONE;
154 void EasyUnlockAuthAttempt::Cancel(const std::string& user_id) {
155 if (type_ == TYPE_UNLOCK)
156 FinalizeUnlock(user_id, false);
157 else
158 FinalizeSignin(user_id, "", "");
159 state_ = STATE_DONE;