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 /** @private */ | |
111 onRouteChanged_: function(currentRoute) { | |
112 if (this.isScreenActive(QuickUnlockScreen.SETUP_PIN)) { | |
113 this.askForPasswordIfUnset(); | |
114 } else { | |
115 // If the user hits the back button, they can leave the element | |
116 // half-completed; therefore, reset state if the element is not active. | |
117 this.resetState_(); | |
118 } | |
119 }, | |
120 | |
121 /** @private */ | |
122 onSetModesChanged_: function() { | |
123 if (this.isScreenActive(QuickUnlockScreen.SETUP_PIN)) | |
124 this.askForPasswordIfUnset(); | |
125 }, | |
126 | |
127 /** | |
128 * Resets the element to the initial state. | |
129 * @private | |
130 */ | |
131 resetState_: function() { | |
132 this.initialPin_ = ''; | |
133 this.pinKeyboardValue_ = ''; | |
134 this.enableSubmit_ = false; | |
135 this.isConfirmStep_ = false; | |
136 this.onPinChange_(); | |
137 }, | |
138 | |
139 /** | |
140 * Returns true if the given PIN is likely easy to guess. | |
141 * @private | |
tommycli
2016/07/13 21:56:26
@param and @return annotations plz
And same comme
jdufault
2016/07/13 22:10:39
Done.
| |
142 */ | |
143 isPinWeak_: function(pin) { | |
144 // Warn if it's a top-10 pin. | |
145 if (WEAK_PINS.includes(pin)) | |
146 return true; | |
147 | |
148 // Warn if the PIN is consecutive digits. | |
149 var delta = 0; | |
150 for (var i = 1; i < pin.length; ++i) { | |
151 var prev = Number(pin[i - 1]); | |
152 var num = Number(pin[i]); | |
153 if (Number.isNaN(prev) || Number.isNaN(num)) | |
154 return false; | |
155 delta = Math.max(delta, Math.abs(num - prev)); | |
156 } | |
157 | |
158 return delta <= 1; | |
159 }, | |
160 | |
161 /** | |
162 * Returns true if the given PIN matches PIN requirements, such as minimum | |
163 * length. | |
164 * @private | |
165 */ | |
166 isPinLongEnough_: function(pin) { | |
167 return pin && pin.length >= 4; | |
168 }, | |
169 | |
170 /** | |
171 * Returns true if the PIN is ready to be changed to a new value. | |
172 * @private | |
173 */ | |
174 canSubmit_: function() { | |
175 return this.isPinLongEnough_(this.pinKeyboardValue_) && | |
176 this.initialPin_ == this.pinKeyboardValue_; | |
177 }, | |
178 | |
179 /** | |
180 * Notify the user about a problem. | |
181 * @private | |
182 */ | |
183 showProblem_: function(problemInfo) { | |
184 this.problemMessage_ = this.i18n(problemInfo.messageId); | |
185 this.problemClass_ = problemInfo.class; | |
186 this.updateStyles(); | |
187 }, | |
188 | |
189 /** @private */ | |
190 hideProblem_: function() { | |
191 this.problemMessage_ = ''; | |
192 this.problemClass_ = ''; | |
193 }, | |
194 | |
195 /** @private */ | |
196 onPinChange_: function() { | |
197 if (!this.isConfirmStep_) { | |
198 var isPinLongEnough = this.isPinLongEnough_(this.pinKeyboardValue_); | |
199 var isWeak = isPinLongEnough && this.isPinWeak_(this.pinKeyboardValue_); | |
200 | |
201 if (!isPinLongEnough && this.pinKeyboardValue_) | |
202 this.showProblem_(ProblemInfo.TOO_SHORT); | |
203 else if (isWeak) | |
204 this.showProblem_(ProblemInfo.WEAK); | |
205 else | |
206 this.hideProblem_(); | |
207 | |
208 this.enableSubmit_ = isPinLongEnough; | |
209 | |
210 } else { | |
211 var canSubmit = this.canSubmit_(); | |
212 | |
213 if (!canSubmit && this.pinKeyboardValue_) | |
214 this.showProblem_(ProblemInfo.MISMATCHED); | |
215 else | |
216 this.hideProblem_(); | |
217 | |
218 this.enableSubmit_ = canSubmit; | |
219 } | |
220 }, | |
221 | |
222 /** @private */ | |
223 onPinSubmit_: function() { | |
224 if (!this.isConfirmStep_) { | |
225 if (this.isPinLongEnough_(this.pinKeyboardValue_)) { | |
226 this.initialPin_ = this.pinKeyboardValue_; | |
227 this.pinKeyboardValue_ = ''; | |
228 this.isConfirmStep_ = true; | |
229 this.onPinChange_(); | |
230 } | |
231 } else { | |
232 // onPinSubmit_ gets called if the user hits enter on the PIN keyboard. | |
233 // The PIN is not guaranteed to be valid in that case. | |
234 if (!this.canSubmit_()) | |
235 return; | |
236 | |
237 function onSetModesCompleted(didSet) { | |
238 if (!didSet) { | |
239 console.error('Failed to update pin'); | |
240 return; | |
241 } | |
242 | |
243 this.resetState_(); | |
244 this.currentRoute = { | |
245 page: 'basic', | |
246 section: 'people', | |
247 subpage: [QuickUnlockScreen.CHOOSE_METHOD] | |
248 }; | |
249 } | |
250 | |
251 this.setModes.call( | |
252 null, | |
253 [chrome.quickUnlockPrivate.QuickUnlockMode.PIN], | |
254 [this.pinKeyboardValue_], | |
255 onSetModesCompleted.bind(this)); | |
256 } | |
257 }, | |
258 | |
259 /** @private */ | |
260 hasProblem_: function(problemMessage_) { | |
261 return !!problemMessage_; | |
262 }, | |
263 | |
264 /** @private */ | |
265 getTitleMessage_: function(isConfirmStep) { | |
266 if (!isConfirmStep) | |
267 return this.i18n('quickUnlockConfigurePinChoosePinTitle'); | |
268 return this.i18n('quickUnlockConfigurePinConfirmPinTitle'); | |
269 }, | |
270 | |
271 /** @private */ | |
272 getContinueMessage_: function(isConfirmStep) { | |
273 if (!isConfirmStep) | |
274 return this.i18n('quickUnlockConfigurePinContinueButton'); | |
275 return this.i18n('save'); | |
276 }, | |
277 }); | |
278 | |
279 })(); | |
OLD | NEW |