-
Notifications
You must be signed in to change notification settings - Fork 6.6k
/
lock_state_behavior.js
264 lines (236 loc) · 8.73 KB
/
lock_state_behavior.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js';
import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/ash/common/web_ui_listener_behavior.js';
import {AuthFactorConfig, AuthFactorConfigInterface, PinFactorEditor, PinFactorEditorInterface, RecoveryFactorEditor, RecoveryFactorEditorInterface} from 'chrome://resources/mojo/chromeos/ash/services/auth_factor_config/public/mojom/auth_factor_config.mojom-webui.js';
/**
* @fileoverview
* Contains utilities that help identify the current way that the lock screen
* will be displayed.
*/
/** @enum {string} */
export const LockScreenUnlockType = {
VALUE_PENDING: 'value_pending',
PASSWORD: 'password',
PIN_PASSWORD: 'pin+password',
};
/**
* Determining if the device supports PIN sign-in takes time, as it may require
* a cryptohome call. This means incorrect strings may be shown for a brief
* period, and updating them causes UI flicker.
*
* Cache the value since the behavior is instantiated multiple times. Caching
* is safe because PIN login support depends only on hardware capabilities. The
* value does not change after discovered.
*
* @type {boolean|undefined}
*/
let cachedHasPinLogin = undefined;
/** @polymerBehavior */
export const LockStateBehaviorImpl = {
properties: {
/**
* The currently selected unlock type.
* @type {!LockScreenUnlockType}
*/
selectedUnlockType:
{type: String, notify: true, value: LockScreenUnlockType.VALUE_PENDING},
/**
* True/false if there is a PIN set; undefined if the computation is still
* pending. This is a separate value from selectedUnlockType because the UI
* can change the selectedUnlockType before setting up a PIN.
* @type {boolean|undefined}
*/
hasPin: {type: Boolean, notify: true},
/**
* True if the PIN backend supports signin. undefined iff the value is still
* resolving.
* @type {boolean|undefined}
*/
hasPinLogin: {type: Boolean, notify: true},
/**
* Interface for chrome.quickUnlockPrivate calls. May be overridden by
* tests.
* @type {QuickUnlockPrivate}
*/
quickUnlockPrivate: {type: Object, value: chrome.quickUnlockPrivate},
/**
* Interface for calls to the ash AuthFactorConfig service. May be
* overridden by tests.
* @type {AuthFactorConfigInterface}
*/
authFactorConfig: {type: Object, value: AuthFactorConfig.getRemote()},
/**
* Interface for calls to the ash RecoveryFactorEditor service. May be
* overridden by tests.
* @type {RecoveryFactorEditorInterface}
*/
recoveryFactorEditor:
{type: Object, value: RecoveryFactorEditor.getRemote()},
/**
* Interface for calls to the ash PinFactorEditor service. May be
* overridden by tests.
* @type {PinFactorEditorInterface}
*/
pinFactorEditor: {type: Object, value: PinFactorEditor.getRemote()},
},
/** @override */
attached() {
this.boundOnActiveModesChanged_ =
this.updateUnlockType.bind(this, /*activeModesChanged=*/ true);
this.quickUnlockPrivate.onActiveModesChanged.addListener(
this.boundOnActiveModesChanged_);
// See comment on |cachedHasPinLogin| declaration.
if (cachedHasPinLogin === undefined) {
this.addWebUIListener(
'pin-login-available-changed',
this.handlePinLoginAvailableChanged_.bind(this));
chrome.send('RequestPinLoginState');
} else {
this.hasPinLogin = cachedHasPinLogin;
}
this.updateUnlockType(/*activeModesChanged=*/ false);
},
/** @override */
detached() {
this.quickUnlockPrivate.onActiveModesChanged.removeListener(
this.boundOnActiveModesChanged_);
},
/**
* Updates the selected unlock type radio group. This function will get called
* after preferences are initialized, after the quick unlock mode has been
* changed, and after the lockscreen preference has changed.
*
* @param {boolean} activeModesChanged If the function is called because
* active modes have changed.
*/
updateUnlockType(activeModesChanged) {
this.quickUnlockPrivate.getActiveModes(modes => {
if (modes.includes(chrome.quickUnlockPrivate.QuickUnlockMode.PIN)) {
this.hasPin = true;
this.selectedUnlockType = LockScreenUnlockType.PIN_PASSWORD;
} else {
// A race condition can occur:
// (1) User selects PIN_PASSSWORD, and successfully sets a pin, adding
// QuickUnlockMode.PIN to active modes.
// (2) User selects PASSWORD, QuickUnlockMode.PIN capability is cleared
// from the active modes, notifying LockStateBehavior to call
// updateUnlockType to fetch the active modes asynchronously.
// (3) User selects PIN_PASSWORD, but the process from step 2 has
// not yet completed.
// In this case, do not forcibly select the PASSWORD radio button even
// though the unlock type is still PASSWORD (|hasPin| is false). If the
// user wishes to set a pin, they will have to click the set pin button.
// See https://crbug.com/1054327 for details.
if (activeModesChanged && !this.hasPin &&
this.selectedUnlockType === LockScreenUnlockType.PIN_PASSWORD) {
return;
}
this.hasPin = false;
this.selectedUnlockType = LockScreenUnlockType.PASSWORD;
}
});
},
/**
* Sets the lock screen enabled state.
* @param {string} authToken The token returned by
* QuickUnlockPrivate.getAuthToken
* @param {boolean} enabled
* @param {function(boolean): void} onComplete
* @see quickUnlockPrivate.setLockScreenEnabled
*/
setLockScreenEnabled(authToken, enabled, onComplete) {
this.quickUnlockPrivate.setLockScreenEnabled(authToken, enabled, () => {
let success = true;
if (chrome.runtime.lastError) {
console.warn(
'setLockScreenEnabled failed: ' + chrome.runtime.lastError.message);
success = false;
}
if (onComplete) {
onComplete(success);
}
});
},
/**
* Handler for when the pin login available state has been updated.
* @private
*/
handlePinLoginAvailableChanged_(isAvailable) {
this.hasPinLogin = isAvailable;
cachedHasPinLogin = this.hasPinLogin;
},
};
/**
* @interface
* @extends {I18nBehaviorInterface}
* @extends {WebUIListenerBehaviorInterface}
*/
export class LockStateBehaviorInterface {
constructor() {
/**
* The currently selected unlock type.
* @type {!LockScreenUnlockType}
*/
this.selectedUnlockType;
/**
* True/false if there is a PIN set; undefined if the computation is still
* pending. This is a separate value from selectedUnlockType because the UI
* can change the selectedUnlockType before setting up a PIN.
* @type {boolean|undefined}
*/
this.hasPin;
/**
* True if the PIN backend supports signin. undefined iff the value is still
* resolving.
* @type {boolean|undefined}
*/
this.hasPinLogin;
/**
* Interface for chrome.quickUnlockPrivate calls. May be overridden by
* tests.
* @type {QuickUnlockPrivate}
*/
this.quickUnlockPrivate;
/**
* Interface for calls to the ash AuthFactorConfig service. May be
* overridden by tests.
* @type {AuthFactorConfigInterface}
*/
this.authFactorConfig;
/**
* Interface for calls to the ash RecoveryFactorEditor service. May be
* overridden by tests.
* @type {RecoveryFactorEditorInterface}
*/
this.recoveryFactorEditor;
/**
* Interface for calls to the ash PinFactorEditor service. May be
* overridden by tests.
* @type {PinFactorEditorInterface}
*/
this.pinFactorEditor;
}
/**
* Updates the selected unlock type radio group. This function will get called
* after preferences are initialized, after the quick unlock mode has been
* changed, and after the lockscreen preference has changed.
*
* @param {boolean} activeModesChanged If the function is called because
* active modes have changed.
*/
updateUnlockType(activeModesChanged) {}
/**
* Sets the lock screen enabled state.
* @param {string} authToken The token returned by
* QuickUnlockPrivate.getAuthToken
* @param {boolean} enabled
* @param {function(boolean): void} onComplete
* @see quickUnlockPrivate.setLockScreenEnabled
*/
setLockScreenEnabled(authToken, enabled, onComplete) {}
}
/** @polymerBehavior */
export const LockStateBehavior =
[I18nBehavior, WebUIListenerBehavior, LockStateBehaviorImpl];