OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 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 /** | |
6 * @fileoverview | |
7 * 'settings-quick-unlock-setup-pin' is the settings page for choosing a PIN. | |
8 * | |
9 * Example: | |
10 * | |
11 * <settings-quick-unlock-setup-pin | |
12 * set-modes="[[quickUnlockSetModes]]" | |
13 * current-route="{{currentRoute}}"> | |
14 * </settings-quick-unlock-setup-pin> | |
15 */ | |
16 | |
17 (function() { | |
18 'use strict'; | |
19 | |
20 /** | |
21 * Metainformation about a problem message to pass to showProblem. |class| is | |
22 * the css class to show the problem message with. |messageId| is the i18n | |
23 * string id to use. | |
24 * @const | |
25 */ | |
26 var ProblemInfo = { | |
27 TOO_SHORT: { | |
28 messageId: 'quickUnlockConfigurePinChoosePinTooShort', | |
29 class: 'error' | |
30 }, | |
31 WEAK: { | |
32 messageId: 'quickUnlockConfigurePinChoosePinWeakPinWarning', | |
33 class: 'warning' | |
34 }, | |
35 MISMATCHED: { | |
36 messageId: 'quickUnlockConfigurePinMismatchedPins', | |
37 class: 'error' | |
38 } | |
39 }; | |
40 | |
41 /** | |
42 * A list of the top-10 most commmonly used PINs. This list is taken from | |
43 * www.datagenetics.com/blog/september32012/. | |
44 * @const | |
45 */ | |
46 var WEAK_PINS = [ | |
47 '1234', '1111', '0000', '1212', '7777', '1004', '2000', '4444', '2222', | |
48 '6969' | |
49 ]; | |
50 | |
51 Polymer({ | |
52 is: 'settings-quick-unlock-setup-pin', | |
53 | |
54 behaviors: [ | |
55 QuickUnlockPasswordDetectBehavior, | |
56 I18nBehavior | |
57 ], | |
58 | |
59 properties: { | |
60 /** | |
61 * The current PIN keyboard value. | |
62 * @private | |
63 */ | |
64 pinKeyboardValue_: String, | |
65 | |
66 /** | |
67 * Stores the initial PIN value so it can be confirmed. | |
68 * @private | |
69 */ | |
70 initialPin_: String, | |
71 | |
72 /** | |
73 * The actual problem message to display. | |
74 * @private | |
75 */ | |
76 problemMessage_: String, | |
77 | |
78 /** | |
79 * The type of problem class to show (warning or error). | |
80 */ | |
81 problemClass_: String, | |
82 | |
83 /** | |
84 * Should the step-specific submit button be displayed? | |
85 * @private | |
86 */ | |
87 enableSubmit_: Boolean, | |
88 | |
89 /** | |
90 * The current step/subpage we are on. | |
91 * @private | |
92 */ | |
93 isConfirmStep_: { | |
94 type: Boolean, | |
95 value: false | |
96 }, | |
97 }, | |
98 | |
99 observers: [ | |
100 'onRouteChanged_(currentRoute)', | |
101 'onSetModesChanged_(setModes)' | |
102 ], | |
103 | |
104 /** @override */ | |
105 attached: function() { | |
106 this.resetState_(); | |
107 this.askForPasswordIfUnset(); | |
108 }, | |
109 | |
110 /** | |
111 * @param {!SettingsRoute} currentRoute | |
112 * @private | |
113 */ | |
114 onRouteChanged_: function(currentRoute) { | |
115 if (this.isScreenActive(QuickUnlockScreen.SETUP_PIN)) { | |
116 this.askForPasswordIfUnset(); | |
117 } else { | |
118 // If the user hits the back button, they can leave the element | |
119 // half-completed; therefore, reset state if the element is not active. | |
120 this.resetState_(); | |
121 } | |
122 }, | |
123 | |
124 /** @private */ | |
125 onSetModesChanged_: function() { | |
126 if (this.isScreenActive(QuickUnlockScreen.SETUP_PIN)) | |
127 this.askForPasswordIfUnset(); | |
128 }, | |
129 | |
130 /** | |
131 * Resets the element to the initial state. | |
132 * @private | |
133 */ | |
134 resetState_: function() { | |
135 this.initialPin_ = ''; | |
136 this.pinKeyboardValue_ = ''; | |
137 this.enableSubmit_ = false; | |
138 this.isConfirmStep_ = false; | |
139 this.onPinChange_(); | |
140 }, | |
141 | |
142 /** | |
143 * Returns true if the given PIN is likely easy to guess. | |
144 * @private | |
145 * @param {string} pin | |
146 * @return {boolean} | |
147 */ | |
148 isPinWeak_: function(pin) { | |
149 // Warn if it's a top-10 pin. | |
150 if (WEAK_PINS.includes(pin)) | |
151 return true; | |
152 | |
153 // Warn if the PIN is consecutive digits. | |
154 var delta = 0; | |
155 for (var i = 1; i < pin.length; ++i) { | |
156 var prev = Number(pin[i - 1]); | |
157 var num = Number(pin[i]); | |
158 if (Number.isNaN(prev) || Number.isNaN(num)) | |
159 return false; | |
160 delta = Math.max(delta, Math.abs(num - prev)); | |
161 } | |
162 | |
163 return delta <= 1; | |
164 }, | |
165 | |
166 /** | |
167 * Returns true if the given PIN matches PIN requirements, such as minimum | |
168 * length. | |
169 * @private | |
170 * @param {string|undefined} pin | |
171 * @return {boolean} | |
172 */ | |
173 isPinLongEnough_: function(pin) { | |
174 return !!(pin && pin.length >= 4); | |
tommycli
2016/07/13 22:15:10
this seems odd.
Does !!pin && pin.length >=4 work
jdufault
2016/07/13 22:18:39
Done.
| |
175 }, | |
176 | |
177 /** | |
178 * Returns true if the PIN is ready to be changed to a new value. | |
179 * @private | |
180 * @return {boolean} | |
181 */ | |
182 canSubmit_: function() { | |
183 return this.isPinLongEnough_(this.pinKeyboardValue_) && | |
184 this.initialPin_ == this.pinKeyboardValue_; | |
185 }, | |
186 | |
187 /** | |
188 * Notify the user about a problem. | |
189 * @private | |
190 * @param {!{messageId: string, class: string}} problemInfo | |
191 */ | |
192 showProblem_: function(problemInfo) { | |
193 this.problemMessage_ = this.i18n(problemInfo.messageId); | |
194 this.problemClass_ = problemInfo.class; | |
195 this.updateStyles(); | |
196 }, | |
197 | |
198 /** @private */ | |
199 hideProblem_: function() { | |
200 this.problemMessage_ = ''; | |
201 this.problemClass_ = ''; | |
202 }, | |
203 | |
204 /** @private */ | |
205 onPinChange_: function() { | |
206 if (!this.isConfirmStep_) { | |
207 var isPinLongEnough = this.isPinLongEnough_(this.pinKeyboardValue_); | |
208 var isWeak = isPinLongEnough && this.isPinWeak_(this.pinKeyboardValue_); | |
209 | |
210 if (!isPinLongEnough && this.pinKeyboardValue_) | |
211 this.showProblem_(ProblemInfo.TOO_SHORT); | |
212 else if (isWeak) | |
213 this.showProblem_(ProblemInfo.WEAK); | |
214 else | |
215 this.hideProblem_(); | |
216 | |
217 this.enableSubmit_ = isPinLongEnough; | |
218 | |
219 } else { | |
220 var canSubmit = this.canSubmit_(); | |
221 | |
222 if (!canSubmit && this.pinKeyboardValue_) | |
223 this.showProblem_(ProblemInfo.MISMATCHED); | |
224 else | |
225 this.hideProblem_(); | |
226 | |
227 this.enableSubmit_ = canSubmit; | |
228 } | |
229 }, | |
230 | |
231 /** @private */ | |
232 onPinSubmit_: function() { | |
233 if (!this.isConfirmStep_) { | |
234 if (this.isPinLongEnough_(this.pinKeyboardValue_)) { | |
235 this.initialPin_ = this.pinKeyboardValue_; | |
236 this.pinKeyboardValue_ = ''; | |
237 this.isConfirmStep_ = true; | |
238 this.onPinChange_(); | |
239 } | |
240 } else { | |
241 // onPinSubmit_ gets called if the user hits enter on the PIN keyboard. | |
242 // The PIN is not guaranteed to be valid in that case. | |
243 if (!this.canSubmit_()) | |
244 return; | |
245 | |
246 function onSetModesCompleted(didSet) { | |
247 if (!didSet) { | |
248 console.error('Failed to update pin'); | |
249 return; | |
250 } | |
251 | |
252 this.resetState_(); | |
253 this.currentRoute = { | |
254 page: 'basic', | |
255 section: 'people', | |
256 subpage: [QuickUnlockScreen.CHOOSE_METHOD] | |
257 }; | |
258 } | |
259 | |
260 this.setModes.call( | |
261 null, | |
262 [chrome.quickUnlockPrivate.QuickUnlockMode.PIN], | |
263 [this.pinKeyboardValue_], | |
264 onSetModesCompleted.bind(this)); | |
265 } | |
266 }, | |
267 | |
268 /** | |
269 * @private | |
270 * @param {string} problemMessage | |
271 * @return {boolean} | |
272 */ | |
273 hasProblem_: function(problemMessage) { | |
274 return !!problemMessage; | |
275 }, | |
276 | |
277 /** | |
278 * @private | |
279 * @param {boolean} isConfirmStep | |
280 * @return {string} | |
281 */ | |
282 getTitleMessage_: function(isConfirmStep) { | |
283 if (!isConfirmStep) | |
284 return this.i18n('quickUnlockConfigurePinChoosePinTitle'); | |
285 return this.i18n('quickUnlockConfigurePinConfirmPinTitle'); | |
286 }, | |
287 | |
288 /** | |
289 * @private | |
290 * @param {boolean} isConfirmStep | |
291 * @return {string} | |
292 */ | |
293 getContinueMessage_: function(isConfirmStep) { | |
294 if (!isConfirmStep) | |
295 return this.i18n('quickUnlockConfigurePinContinueButton'); | |
296 return this.i18n('save'); | |
297 }, | |
298 }); | |
299 | |
300 })(); | |
OLD | NEW |