| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @fileoverview | 6 * @fileoverview |
| 7 * 'settings-setup-pin-dialog' is the settings page for choosing a PIN. | 7 * 'settings-setup-pin-dialog' is the settings page for choosing a PIN. |
| 8 * | 8 * |
| 9 * Example: | 9 * Example: |
| 10 * | 10 * |
| 11 * <settings-setup-pin-dialog set-modes="[[quickUnlockSetModes]]"> | 11 * <settings-setup-pin-dialog set-modes="[[quickUnlockSetModes]]"> |
| 12 * </settings-setup-pin-dialog> | 12 * </settings-setup-pin-dialog> |
| 13 */ | 13 */ |
| 14 | 14 |
| 15 (function() { | 15 (function() { |
| 16 'use strict'; | 16 'use strict'; |
| 17 | 17 |
| 18 /** | 18 /** |
| 19 * Keep in sync with the string keys provided by settings. | 19 * Keep in sync with the string keys provided by settings. |
| 20 * @enum {string} | 20 * @enum {string} |
| 21 */ | 21 */ |
| 22 var MessageType = { | 22 var MessageType = { |
| 23 TOO_SHORT: 'configurePinTooShort', | 23 TOO_SHORT: 'configurePinTooShort', |
| 24 TOO_LONG: 'configurePinTooLong', | 24 TOO_LONG: 'configurePinTooLong', |
| 25 TOO_WEAK: 'configurePinWeakPin', | 25 TOO_WEAK: 'configurePinWeakPin', |
| 26 MISMATCH: 'configurePinMismatched' | 26 MISMATCH: 'configurePinMismatched' |
| 27 }; | 27 }; |
| 28 | 28 |
| 29 /** @enum {string} */ | 29 /** @enum {string} */ |
| 30 var ProblemType = { | 30 var ProblemType = {WARNING: 'warning', ERROR: 'error'}; |
| 31 WARNING: 'warning', | 31 |
| 32 ERROR: 'error' | 32 Polymer({ |
| 33 }; | 33 is: 'settings-setup-pin-dialog', |
| 34 | 34 |
| 35 Polymer({ | 35 behaviors: [I18nBehavior], |
| 36 is: 'settings-setup-pin-dialog', | 36 |
| 37 | 37 properties: { |
| 38 behaviors: [I18nBehavior], | 38 /** |
| 39 | 39 * The current PIN keyboard value. |
| 40 properties: { | 40 * @private |
| 41 /** | 41 */ |
| 42 * The current PIN keyboard value. | 42 pinKeyboardValue_: String, |
| 43 |
| 44 /** |
| 45 * Stores the initial PIN value so it can be confirmed. |
| 46 * @private |
| 47 */ |
| 48 initialPin_: String, |
| 49 |
| 50 /** |
| 51 * The actual problem message to display. |
| 52 * @private |
| 53 */ |
| 54 problemMessage_: String, |
| 55 |
| 56 /** |
| 57 * The type of problem class to show (warning or error). |
| 58 */ |
| 59 problemClass_: String, |
| 60 |
| 61 /** |
| 62 * Should the step-specific submit button be displayed? |
| 63 * @private |
| 64 */ |
| 65 enableSubmit_: Boolean, |
| 66 |
| 67 /** |
| 68 * writeUma_ is a function that handles writing uma stats. It may be |
| 69 * overridden for tests. |
| 70 * |
| 71 * @type {Function} |
| 72 * @private |
| 73 */ |
| 74 writeUma_: { |
| 75 type: Object, |
| 76 value: function() { |
| 77 return settings.recordLockScreenProgress; |
| 78 } |
| 79 }, |
| 80 |
| 81 /** |
| 82 * The current step/subpage we are on. |
| 83 * @private |
| 84 */ |
| 85 isConfirmStep_: {type: Boolean, value: false}, |
| 86 |
| 87 /** |
| 88 * Interface for chrome.quickUnlockPrivate calls. May be overriden by |
| 89 * tests. |
| 90 * @private |
| 91 */ |
| 92 quickUnlockPrivate_: {type: Object, value: chrome.quickUnlockPrivate}, |
| 93 }, |
| 94 |
| 95 /** @override */ |
| 96 attached: function() { |
| 97 this.resetState_(); |
| 98 }, |
| 99 |
| 100 open: function() { |
| 101 this.$.dialog.showModal(); |
| 102 this.$.pinKeyboard.focus(); |
| 103 }, |
| 104 |
| 105 close: function() { |
| 106 if (this.$.dialog.open) |
| 107 this.$.dialog.close(); |
| 108 |
| 109 this.resetState_(); |
| 110 }, |
| 111 |
| 112 /** |
| 113 * Resets the element to the initial state. |
| 43 * @private | 114 * @private |
| 44 */ | 115 */ |
| 45 pinKeyboardValue_: String, | 116 resetState_: function() { |
| 46 | 117 this.initialPin_ = ''; |
| 47 /** | 118 this.pinKeyboardValue_ = ''; |
| 48 * Stores the initial PIN value so it can be confirmed. | 119 this.enableSubmit_ = false; |
| 49 * @private | 120 this.isConfirmStep_ = false; |
| 50 */ | 121 this.hideProblem_(); |
| 51 initialPin_: String, | 122 this.onPinChange_(); |
| 52 | 123 }, |
| 53 /** | 124 |
| 54 * The actual problem message to display. | 125 /** @private */ |
| 55 * @private | 126 onCancelTap_: function() { |
| 56 */ | 127 this.resetState_(); |
| 57 problemMessage_: String, | |
| 58 | |
| 59 /** | |
| 60 * The type of problem class to show (warning or error). | |
| 61 */ | |
| 62 problemClass_: String, | |
| 63 | |
| 64 /** | |
| 65 * Should the step-specific submit button be displayed? | |
| 66 * @private | |
| 67 */ | |
| 68 enableSubmit_: Boolean, | |
| 69 | |
| 70 /** | |
| 71 * writeUma_ is a function that handles writing uma stats. It may be | |
| 72 * overridden for tests. | |
| 73 * | |
| 74 * @type {Function} | |
| 75 * @private | |
| 76 */ | |
| 77 writeUma_: { | |
| 78 type: Object, | |
| 79 value: function() { return settings.recordLockScreenProgress; } | |
| 80 }, | |
| 81 | |
| 82 /** | |
| 83 * The current step/subpage we are on. | |
| 84 * @private | |
| 85 */ | |
| 86 isConfirmStep_: { | |
| 87 type: Boolean, | |
| 88 value: false | |
| 89 }, | |
| 90 | |
| 91 /** | |
| 92 * Interface for chrome.quickUnlockPrivate calls. May be overriden by tests. | |
| 93 * @private | |
| 94 */ | |
| 95 quickUnlockPrivate_: { | |
| 96 type: Object, | |
| 97 value: chrome.quickUnlockPrivate | |
| 98 }, | |
| 99 }, | |
| 100 | |
| 101 /** @override */ | |
| 102 attached: function() { | |
| 103 this.resetState_(); | |
| 104 }, | |
| 105 | |
| 106 open: function() { | |
| 107 this.$.dialog.showModal(); | |
| 108 this.$.pinKeyboard.focus(); | |
| 109 }, | |
| 110 | |
| 111 close: function() { | |
| 112 if (this.$.dialog.open) | |
| 113 this.$.dialog.close(); | 128 this.$.dialog.close(); |
| 114 | 129 }, |
| 115 this.resetState_(); | 130 |
| 116 }, | 131 /** |
| 117 | |
| 118 /** | |
| 119 * Resets the element to the initial state. | |
| 120 * @private | |
| 121 */ | |
| 122 resetState_: function() { | |
| 123 this.initialPin_ = ''; | |
| 124 this.pinKeyboardValue_ = ''; | |
| 125 this.enableSubmit_ = false; | |
| 126 this.isConfirmStep_ = false; | |
| 127 this.hideProblem_(); | |
| 128 this.onPinChange_(); | |
| 129 }, | |
| 130 | |
| 131 /** @private */ | |
| 132 onCancelTap_: function() { | |
| 133 this.resetState_(); | |
| 134 this.$.dialog.close(); | |
| 135 }, | |
| 136 | |
| 137 /** | |
| 138 * Returns true if the PIN is ready to be changed to a new value. | 132 * Returns true if the PIN is ready to be changed to a new value. |
| 139 * @private | 133 * @private |
| 140 * @return {boolean} | 134 * @return {boolean} |
| 141 */ | 135 */ |
| 142 canSubmit_: function() { | 136 canSubmit_: function() { |
| 143 return this.initialPin_ == this.pinKeyboardValue_; | 137 return this.initialPin_ == this.pinKeyboardValue_; |
| 144 }, | 138 }, |
| 145 | 139 |
| 146 /** | 140 /** |
| 147 * Handles writting the appropriate message to |problemMessage_|. | 141 * Handles writting the appropriate message to |problemMessage_|. |
| 148 * @private | 142 * @private |
| 149 * @param {string} messageId | 143 * @param {string} messageId |
| 150 * @param {chrome.quickUnlockPrivate.CredentialRequirements} requirements | 144 * @param {chrome.quickUnlockPrivate.CredentialRequirements} requirements |
| 151 * The requirements received from getCredentialRequirements. | 145 * The requirements received from getCredentialRequirements. |
| 152 */ | 146 */ |
| 153 processPinRequirements_: function(messageId, requirements) { | 147 processPinRequirements_: function(messageId, requirements) { |
| 154 var additionalInformation = ''; | 148 var additionalInformation = ''; |
| 155 switch (messageId) { | 149 switch (messageId) { |
| 156 case MessageType.TOO_SHORT: | 150 case MessageType.TOO_SHORT: |
| 157 additionalInformation = requirements.minLength.toString(); | 151 additionalInformation = requirements.minLength.toString(); |
| 158 break; | |
| 159 case MessageType.TOO_LONG: | |
| 160 additionalInformation = requirements.maxLength.toString(); | |
| 161 break; | |
| 162 case MessageType.TOO_WEAK: | |
| 163 case MessageType.MISMATCH: | |
| 164 break; | |
| 165 default: | |
| 166 assertNotReached(); | |
| 167 break; | |
| 168 } | |
| 169 this.problemMessage_ = this.i18n(messageId, additionalInformation); | |
| 170 }, | |
| 171 | |
| 172 /** | |
| 173 * Notify the user about a problem. | |
| 174 * @private | |
| 175 * @param {string} messageId | |
| 176 * @param {string} problemClass | |
| 177 */ | |
| 178 showProblem_: function(messageId, problemClass) { | |
| 179 this.quickUnlockPrivate_.getCredentialRequirements( | |
| 180 chrome.quickUnlockPrivate.QuickUnlockMode.PIN, | |
| 181 this.processPinRequirements_.bind(this, messageId)); | |
| 182 this.problemClass_ = problemClass; | |
| 183 this.updateStyles(); | |
| 184 this.enableSubmit_ = problemClass != ProblemType.ERROR && | |
| 185 messageId != MessageType.MISMATCH; | |
| 186 }, | |
| 187 | |
| 188 /** @private */ | |
| 189 hideProblem_: function() { | |
| 190 this.problemMessage_ = ''; | |
| 191 this.problemClass_ = ''; | |
| 192 }, | |
| 193 | |
| 194 /** | |
| 195 * Processes the message received from the quick unlock api and hides/shows | |
| 196 * the problem based on the message. | |
| 197 * @private | |
| 198 * @param {chrome.quickUnlockPrivate.CredentialCheck} message The message | |
| 199 * received from checkCredential. | |
| 200 */ | |
| 201 processPinProblems_: function(message) { | |
| 202 if (!message.errors.length && !message.warnings.length) { | |
| 203 this.hideProblem_(); | |
| 204 this.enableSubmit_ = true; | |
| 205 return; | |
| 206 } | |
| 207 | |
| 208 if (message.warnings.length) { | |
| 209 assert(message.warnings[0] == | |
| 210 chrome.quickUnlockPrivate.CredentialProblem.TOO_WEAK); | |
| 211 this.showProblem_(MessageType.TOO_WEAK, ProblemType.WARNING); | |
| 212 } | |
| 213 | |
| 214 if (message.errors.length) { | |
| 215 switch (message.errors[0]) { | |
| 216 case chrome.quickUnlockPrivate.CredentialProblem.TOO_SHORT: | |
| 217 this.showProblem_(MessageType.TOO_SHORT, ProblemType.ERROR); | |
| 218 break; | 152 break; |
| 219 case chrome.quickUnlockPrivate.CredentialProblem.TOO_LONG: | 153 case MessageType.TOO_LONG: |
| 220 this.showProblem_(MessageType.TOO_LONG, ProblemType.ERROR); | 154 additionalInformation = requirements.maxLength.toString(); |
| 221 break; | 155 break; |
| 222 case chrome.quickUnlockPrivate.CredentialProblem.TOO_WEAK: | 156 case MessageType.TOO_WEAK: |
| 223 this.showProblem_(MessageType.TOO_WEAK, ProblemType.ERROR); | 157 case MessageType.MISMATCH: |
| 224 break; | 158 break; |
| 225 default: | 159 default: |
| 226 assertNotReached(); | 160 assertNotReached(); |
| 227 break; | 161 break; |
| 228 } | 162 } |
| 229 } | 163 this.problemMessage_ = this.i18n(messageId, additionalInformation); |
| 230 | 164 }, |
| 231 }, | 165 |
| 232 | 166 /** |
| 233 /** @private */ | 167 * Notify the user about a problem. |
| 234 onPinChange_: function() { | 168 * @private |
| 235 if (!this.isConfirmStep_) { | 169 * @param {string} messageId |
| 236 if (this.pinKeyboardValue_) { | 170 * @param {string} problemClass |
| 237 this.quickUnlockPrivate_.checkCredential( | 171 */ |
| 238 chrome.quickUnlockPrivate.QuickUnlockMode.PIN, | 172 showProblem_: function(messageId, problemClass) { |
| 239 this.pinKeyboardValue_, | 173 this.quickUnlockPrivate_.getCredentialRequirements( |
| 240 this.processPinProblems_.bind(this)); | 174 chrome.quickUnlockPrivate.QuickUnlockMode.PIN, |
| 241 } | 175 this.processPinRequirements_.bind(this, messageId)); |
| 242 return; | 176 this.problemClass_ = problemClass; |
| 243 } | 177 this.updateStyles(); |
| 244 | 178 this.enableSubmit_ = problemClass != ProblemType.ERROR && |
| 245 if (this.canSubmit_()) { | 179 messageId != MessageType.MISMATCH; |
| 246 this.hideProblem_(); | 180 }, |
| 247 this.enableSubmit_ = true; | 181 |
| 248 return; | 182 /** @private */ |
| 249 } | 183 hideProblem_: function() { |
| 250 | 184 this.problemMessage_ = ''; |
| 251 this.showProblem_(MessageType.MISMATCH, ProblemType.WARNING); | 185 this.problemClass_ = ''; |
| 252 }, | 186 }, |
| 253 | 187 |
| 254 /** @private */ | 188 /** |
| 255 onPinSubmit_: function() { | 189 * Processes the message received from the quick unlock api and hides/shows |
| 256 if (!this.isConfirmStep_) { | 190 * the problem based on the message. |
| 257 this.initialPin_ = this.pinKeyboardValue_; | 191 * @private |
| 258 this.pinKeyboardValue_ = ''; | 192 * @param {chrome.quickUnlockPrivate.CredentialCheck} message The message |
| 259 this.isConfirmStep_ = true; | 193 * received from checkCredential. |
| 260 this.onPinChange_(); | 194 */ |
| 261 this.$.pinKeyboard.focus(); | 195 processPinProblems_: function(message) { |
| 262 this.writeUma_(LockScreenProgress.ENTER_PIN); | 196 if (!message.errors.length && !message.warnings.length) { |
| 263 return; | 197 this.hideProblem_(); |
| 264 } | 198 this.enableSubmit_ = true; |
| 265 // onPinSubmit_ gets called if the user hits enter on the PIN keyboard. | 199 return; |
| 266 // The PIN is not guaranteed to be valid in that case. | 200 } |
| 267 if (!this.canSubmit_()) { | 201 |
| 268 this.showProblem_(MessageType.MISMATCH, ProblemType.ERROR); | 202 if (message.warnings.length) { |
| 269 return; | 203 assert( |
| 270 } | 204 message.warnings[0] == |
| 271 | 205 chrome.quickUnlockPrivate.CredentialProblem.TOO_WEAK); |
| 272 function onSetModesCompleted(didSet) { | 206 this.showProblem_(MessageType.TOO_WEAK, ProblemType.WARNING); |
| 273 if (!didSet) { | 207 } |
| 274 console.error('Failed to update pin'); | 208 |
| 275 return; | 209 if (message.errors.length) { |
| 276 } | 210 switch (message.errors[0]) { |
| 277 | 211 case chrome.quickUnlockPrivate.CredentialProblem.TOO_SHORT: |
| 278 this.resetState_(); | 212 this.showProblem_(MessageType.TOO_SHORT, ProblemType.ERROR); |
| 279 this.fire('done'); | 213 break; |
| 280 } | 214 case chrome.quickUnlockPrivate.CredentialProblem.TOO_LONG: |
| 281 | 215 this.showProblem_(MessageType.TOO_LONG, ProblemType.ERROR); |
| 282 this.setModes.call( | 216 break; |
| 283 null, | 217 case chrome.quickUnlockPrivate.CredentialProblem.TOO_WEAK: |
| 284 [chrome.quickUnlockPrivate.QuickUnlockMode.PIN], | 218 this.showProblem_(MessageType.TOO_WEAK, ProblemType.ERROR); |
| 285 [this.pinKeyboardValue_], | 219 break; |
| 286 onSetModesCompleted.bind(this)); | 220 default: |
| 287 this.writeUma_(LockScreenProgress.CONFIRM_PIN); | 221 assertNotReached(); |
| 288 }, | 222 break; |
| 289 | 223 } |
| 290 /** | 224 } |
| 225 |
| 226 }, |
| 227 |
| 228 /** @private */ |
| 229 onPinChange_: function() { |
| 230 if (!this.isConfirmStep_) { |
| 231 if (this.pinKeyboardValue_) { |
| 232 this.quickUnlockPrivate_.checkCredential( |
| 233 chrome.quickUnlockPrivate.QuickUnlockMode.PIN, |
| 234 this.pinKeyboardValue_, this.processPinProblems_.bind(this)); |
| 235 } |
| 236 return; |
| 237 } |
| 238 |
| 239 if (this.canSubmit_()) { |
| 240 this.hideProblem_(); |
| 241 this.enableSubmit_ = true; |
| 242 return; |
| 243 } |
| 244 |
| 245 this.showProblem_(MessageType.MISMATCH, ProblemType.WARNING); |
| 246 }, |
| 247 |
| 248 /** @private */ |
| 249 onPinSubmit_: function() { |
| 250 if (!this.isConfirmStep_) { |
| 251 this.initialPin_ = this.pinKeyboardValue_; |
| 252 this.pinKeyboardValue_ = ''; |
| 253 this.isConfirmStep_ = true; |
| 254 this.onPinChange_(); |
| 255 this.$.pinKeyboard.focus(); |
| 256 this.writeUma_(LockScreenProgress.ENTER_PIN); |
| 257 return; |
| 258 } |
| 259 // onPinSubmit_ gets called if the user hits enter on the PIN keyboard. |
| 260 // The PIN is not guaranteed to be valid in that case. |
| 261 if (!this.canSubmit_()) { |
| 262 this.showProblem_(MessageType.MISMATCH, ProblemType.ERROR); |
| 263 return; |
| 264 } |
| 265 |
| 266 function onSetModesCompleted(didSet) { |
| 267 if (!didSet) { |
| 268 console.error('Failed to update pin'); |
| 269 return; |
| 270 } |
| 271 |
| 272 this.resetState_(); |
| 273 this.fire('done'); |
| 274 } |
| 275 |
| 276 this.setModes.call( |
| 277 null, [chrome.quickUnlockPrivate.QuickUnlockMode.PIN], |
| 278 [this.pinKeyboardValue_], onSetModesCompleted.bind(this)); |
| 279 this.writeUma_(LockScreenProgress.CONFIRM_PIN); |
| 280 }, |
| 281 |
| 282 /** |
| 291 * @private | 283 * @private |
| 292 * @param {string} problemMessage | 284 * @param {string} problemMessage |
| 293 * @return {boolean} | 285 * @return {boolean} |
| 294 */ | 286 */ |
| 295 hasProblem_: function(problemMessage) { | 287 hasProblem_: function(problemMessage) { |
| 296 return !!problemMessage; | 288 return !!problemMessage; |
| 297 }, | 289 }, |
| 298 | 290 |
| 299 /** | 291 /** |
| 300 * @private | 292 * @private |
| 301 * @param {boolean} isConfirmStep | 293 * @param {boolean} isConfirmStep |
| 302 * @return {string} | 294 * @return {string} |
| 303 */ | 295 */ |
| 304 getTitleMessage_: function(isConfirmStep) { | 296 getTitleMessage_: function(isConfirmStep) { |
| 305 return this.i18n(isConfirmStep ? 'configurePinConfirmPinTitle' : | 297 return this.i18n( |
| 306 'configurePinChoosePinTitle'); | 298 isConfirmStep ? 'configurePinConfirmPinTitle' : |
| 307 }, | 299 'configurePinChoosePinTitle'); |
| 308 | 300 }, |
| 309 /** | 301 |
| 302 /** |
| 310 * @private | 303 * @private |
| 311 * @param {boolean} isConfirmStep | 304 * @param {boolean} isConfirmStep |
| 312 * @return {string} | 305 * @return {string} |
| 313 */ | 306 */ |
| 314 getContinueMessage_: function(isConfirmStep) { | 307 getContinueMessage_: function(isConfirmStep) { |
| 315 return this.i18n(isConfirmStep ? 'confirm' : 'configurePinContinueButton'); | 308 return this.i18n( |
| 316 }, | 309 isConfirmStep ? 'confirm' : 'configurePinContinueButton'); |
| 317 }); | 310 }, |
| 311 }); |
| 318 | 312 |
| 319 })(); | 313 })(); |
| OLD | NEW |