1 // Copyright (c) 2012 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 cr.define('mobile', function() { 6 7 function SimUnlock() { 8 } 9 10 cr.addSingletonGetter(SimUnlock); 11 12 // State of the dialog. 13 SimUnlock.SIM_UNLOCK_LOADING = -1; 14 SimUnlock.SIM_ABSENT_NOT_LOCKED = 0, 15 SimUnlock.SIM_NOT_LOCKED_ASK_PIN = 1; 16 SimUnlock.SIM_NOT_LOCKED_CHANGE_PIN = 2; 17 SimUnlock.SIM_LOCKED_PIN = 3; 18 SimUnlock.SIM_LOCKED_NO_PIN_TRIES_LEFT = 4; 19 SimUnlock.SIM_LOCKED_PUK = 5; 20 SimUnlock.SIM_LOCKED_NO_PUK_TRIES_LEFT = 6; 21 SimUnlock.SIM_DISABLED = 7; 22 23 // Mode of the dialog. 24 SimUnlock.SIM_DIALOG_UNLOCK = 0; 25 SimUnlock.SIM_DIALOG_CHANGE_PIN = 1; 26 SimUnlock.SIM_DIALOG_SET_LOCK_ON = 2; 27 SimUnlock.SIM_DIALOG_SET_LOCK_OFF = 3; 28 29 // Error codes. 30 SimUnlock.ERROR_PIN = 'incorrectPin'; 31 SimUnlock.ERROR_PUK = 'incorrectPuk'; 32 SimUnlock.ERROR_OK = 'ok'; 33 34 // Misc constants. 35 SimUnlock.PIN_MIN_LENGTH = 4; 36 SimUnlock.PUK_LENGTH = 8; 37 38 SimUnlock.localStrings_ = new LocalStrings(); 39 40 SimUnlock.prototype = { 41 initialized_: false, 42 mode_: SimUnlock.SIM_DIALOG_UNLOCK, 43 pukValue_: '', 44 state_: SimUnlock.SIM_UNLOCK_LOADING, 45 46 changeState_: function(simInfo) { 47 var newState = simInfo.state; 48 var error = simInfo.error; 49 var tries = simInfo.tries; 50 var pinMessage; 51 this.hideAll_(); 52 switch (newState) { 53 case SimUnlock.SIM_UNLOCK_LOADING: 54 break; 55 case SimUnlock.SIM_ABSENT_NOT_LOCKED: 56 SimUnlock.close(); 57 break; 58 case SimUnlock.SIM_LOCKED_PIN: 59 if (error == SimUnlock.ERROR_OK) { 60 pinMessage = SimUnlock.localStrings_.getStringF( 61 'enterPinTriesMessage', tries); 62 $('pin-error-msg').classList.remove('error'); 63 } else if (error == SimUnlock.ERROR_PIN) { 64 pinMessage = SimUnlock.localStrings_.getStringF( 65 'incorrectPinTriesMessage', tries); 66 $('pin-error-msg').classList.add('error'); 67 } 68 $('pin-error-msg').textContent = pinMessage; 69 $('pin-input').value = ''; 70 SimUnlock.enablePinDialog(true); 71 $('locked-pin-overlay').hidden = false; 72 $('pin-input').focus(); 73 break; 74 case SimUnlock.SIM_NOT_LOCKED_ASK_PIN: 75 if (error == SimUnlock.ERROR_OK) { 76 pinMessage = SimUnlock.localStrings_.getString('enterPinMessage'); 77 $('pin-error-msg').classList.remove('error'); 78 } else if (error == SimUnlock.ERROR_PIN) { 79 pinMessage = SimUnlock.localStrings_.getStringF( 80 'incorrectPinTriesMessage', tries); 81 $('pin-error-msg').classList.add('error'); 82 } 83 $('pin-error-msg').textContent = pinMessage; 84 $('pin-input').value = ''; 85 SimUnlock.enablePinDialog(true); 86 $('locked-pin-overlay').hidden = false; 87 $('pin-input').focus(); 88 break; 89 case SimUnlock.SIM_NOT_LOCKED_CHANGE_PIN: 90 SimUnlock.prepareChoosePinDialog(true); 91 if (error == SimUnlock.ERROR_OK) { 92 pinMessage = SimUnlock.localStrings_.getString('changePinMessage'); 93 $('choose-pin-msg').classList.remove('error'); 94 } else if (error == SimUnlock.ERROR_PIN) { 95 pinMessage = SimUnlock.localStrings_.getStringF( 96 'incorrectPinTriesMessage', tries); 97 $('choose-pin-msg').classList.add('error'); 98 } 99 $('choose-pin-msg').textContent = pinMessage; 100 $('old-pin-input').value = ''; 101 $('new-pin-input').value = ''; 102 $('retype-new-pin-input').value = ''; 103 $('choose-pin-overlay').hidden = false; 104 SimUnlock.enableChoosePinDialog(true); 105 $('old-pin-input').focus(); 106 break; 107 case SimUnlock.SIM_LOCKED_NO_PIN_TRIES_LEFT: 108 $('locked-pin-no-tries-overlay').hidden = false; 109 break; 110 case SimUnlock.SIM_LOCKED_PUK: 111 $('puk-input').value = ''; 112 if (tries && tries >= 0) { 113 var pukMessage = SimUnlock.localStrings_.getStringF( 114 'enterPukWarning', tries); 115 $('puk-warning-msg').textContent = pukMessage; 116 } 117 $('enter-puk-confirm').disabled = true; 118 $('locked-puk-overlay').hidden = false; 119 $('puk-input').focus(); 120 break; 121 case SimUnlock.SIM_LOCKED_NO_PUK_TRIES_LEFT: 122 $('locked-puk-no-tries-overlay').hidden = false; 123 break; 124 case SimUnlock.SIM_DISABLED: 125 $('sim-disabled-overlay').hidden = false; 126 break; 127 } 128 this.state_ = newState; 129 }, 130 131 /** 132 * Returns current state of the dialog. 133 * @type {number} value of the state. 134 */ 135 get state() { 136 return this.state_; 137 }, 138 139 hideAll_: function() { 140 $('locked-pin-overlay').hidden = true; 141 $('locked-pin-no-tries-overlay').hidden = true; 142 $('locked-puk-overlay').hidden = true; 143 $('choose-pin-overlay').hidden = true; 144 $('locked-puk-no-tries-overlay').hidden = true; 145 $('sim-disabled-overlay').hidden = true; 146 }, 147 148 newPinEntered_: function(newPin, newPin2) { 149 var changePinMode = this.state_ == SimUnlock.SIM_NOT_LOCKED_CHANGE_PIN; 150 if (newPin.length < SimUnlock.PIN_MIN_LENGTH || 151 newPin2.length < SimUnlock.PIN_MIN_LENGTH || 152 (changePinMode && 153 $('old-pin-input').value.length < SimUnlock.PIN_MIN_LENGTH)) { 154 return; 155 } 156 if (newPin != newPin2) { 157 $('choose-pin-error').hidden = false; 158 $('old-pin-input').value = ''; 159 $('new-pin-input').value = ''; 160 $('retype-new-pin-input').value = ''; 161 if (changePinMode) 162 $('old-pin-input').focus(); 163 else 164 $('new-pin-input').focus(); 165 } else { 166 $('choose-pin-error').hidden = true; 167 SimUnlock.enableChoosePinDialog(false); 168 if (changePinMode) { 169 var oldPin = $('old-pin-input').value; 170 chrome.send('changePinCode', [oldPin, newPin]); 171 } else { 172 chrome.send('enterPukCode', [this.pukValue_, newPin]); 173 this.pukValue_ = ''; 174 } 175 } 176 }, 177 178 pukEntered_: function(pukValue) { 179 if (pukValue.length < SimUnlock.PUK_LENGTH) 180 return; 181 this.pukValue_ = pukValue; 182 this.hideAll_(); 183 SimUnlock.prepareChoosePinDialog(false); 184 SimUnlock.enableChoosePinDialog(true); 185 $('new-pin-input').value = ''; 186 $('retype-new-pin-input').value = ''; 187 $('choose-pin-overlay').hidden = false; 188 $('new-pin-input').focus(); 189 }, 190 191 updateSimStatus_: function(simInfo) { 192 this.changeState_(simInfo); 193 }, 194 }; 195 196 SimUnlock.cancel = function() { 197 chrome.send('cancel'); 198 SimUnlock.close(); 199 }; 200 201 SimUnlock.close = function() { 202 window.close(); 203 }; 204 205 SimUnlock.initialize = function() { 206 this.initialized_ = true; 207 208 var modePattern = /(^\?|&)mode=([^&#]*)/; 209 var results = modePattern.exec(window.location.search); 210 if (results == null) { 211 this.mode_ = SimUnlock.SIM_DIALOG_UNLOCK; 212 } else { 213 var mode = results[2]; 214 if (mode == 'change-pin') 215 this.mode_ = SimUnlock.SIM_DIALOG_CHANGE_PIN; 216 else if (mode == 'set-lock-on') 217 this.mode_ = SimUnlock.SIM_DIALOG_SET_LOCK_ON; 218 else if (mode == 'set-lock-off') 219 this.mode_ = SimUnlock.SIM_DIALOG_SET_LOCK_OFF; 220 } 221 222 // PIN input screen. 223 $('pin-input').addEventListener('keydown', function(event) { 224 if (event.keyIdentifier == 'Enter') { 225 SimUnlock.submitPin(); 226 return; 227 } 228 }); 229 $('pin-input').addEventListener('keyup', function(event) { 230 $('enter-pin-confirm').disabled = 231 $('enter-pin-dismiss').disabled || 232 this.value.length < SimUnlock.PIN_MIN_LENGTH; 233 }); 234 $('pin-input').addEventListener('textInput', 235 SimUnlock.processInput.bind(this)); 236 $('enter-pin-confirm').addEventListener('click', function(event) { 237 SimUnlock.submitPin(); 238 }); 239 $('enter-pin-dismiss').addEventListener('click', function(event) { 240 SimUnlock.cancel(); 241 }); 242 243 // No PIN retries left screen. 244 $('pin-no-tries-proceed').addEventListener('click', function(event) { 245 chrome.send('proceedToPukInput'); 246 }); 247 $('pin-no-tries-dismiss').addEventListener('click', function(event) { 248 SimUnlock.cancel(); 249 }); 250 251 // PUK input screen. 252 $('puk-input').addEventListener('keydown', function(event) { 253 if (event.keyIdentifier == 'Enter') { 254 SimUnlock.pukEntered($('puk-input').value); 255 return; 256 } 257 }); 258 $('puk-input').addEventListener('keyup', function(event) { 259 $('enter-puk-confirm').disabled = 260 $('enter-puk-dismiss').disabled || 261 this.value.length < SimUnlock.PUK_LENGTH; 262 }); 263 $('puk-input').addEventListener('textInput', 264 SimUnlock.processInput.bind(this)); 265 $('enter-puk-confirm').addEventListener('click', function(event) { 266 SimUnlock.pukEntered($('puk-input').value); 267 }); 268 $('enter-puk-dismiss').addEventListener('click', function(event) { 269 SimUnlock.cancel(); 270 }); 271 272 // Change PIN / new PIN screen. 273 $('old-pin-input').addEventListener('keydown', function(event) { 274 if (event.keyIdentifier == 'Enter') { 275 if (this.value.length >= SimUnlock.PIN_MIN_LENGTH) 276 $('new-pin-input').focus(); 277 return; 278 } 279 }); 280 $('old-pin-input').addEventListener('keyup', function(event) { 281 $('choose-pin-confirm').disabled = 282 $('choose-pin-dismiss').disabled || 283 this.value.length < SimUnlock.PIN_MIN_LENGTH || 284 $('new-pin-input').value.length < SimUnlock.PIN_MIN_LENGTH || 285 $('retype-new-pin-input').value.length < SimUnlock.PIN_MIN_LENGTH; 286 }); 287 $('old-pin-input').addEventListener('textInput', 288 SimUnlock.processInput.bind(this)); 289 $('new-pin-input').addEventListener('keydown', function(event) { 290 if (event.keyIdentifier == 'Enter') { 291 if (this.value.length >= SimUnlock.PIN_MIN_LENGTH) 292 $('retype-new-pin-input').focus(); 293 return; 294 } 295 }); 296 $('new-pin-input').addEventListener('keyup', function(event) { 297 var changePinMode = 298 SimUnlock.getInstance().state == SimUnlock.SIM_NOT_LOCKED_CHANGE_PIN; 299 var oldPinLengthOk = 300 $('old-pin-input').value.length >= SimUnlock.PIN_MIN_LENGTH; 301 var oldPinOk = !changePinMode || oldPinLengthOk; 302 $('choose-pin-confirm').disabled = 303 $('choose-pin-dismiss').disabled || 304 this.value.length < SimUnlock.PIN_MIN_LENGTH || 305 $('retype-new-pin-input').value.length < SimUnlock.PIN_MIN_LENGTH || 306 !oldPinOk; 307 }); 308 $('new-pin-input').addEventListener('textInput', 309 SimUnlock.processInput.bind(this)); 310 $('retype-new-pin-input').addEventListener('keyup', function(event) { 311 var changePinMode = 312 SimUnlock.getInstance().state == SimUnlock.SIM_NOT_LOCKED_CHANGE_PIN; 313 var oldPinLengthOk = 314 $('old-pin-input').value.length >= SimUnlock.PIN_MIN_LENGTH; 315 var oldPinOk = !changePinMode || oldPinLengthOk; 316 $('choose-pin-confirm').disabled = 317 $('choose-pin-dismiss').disabled || 318 this.value.length < SimUnlock.PIN_MIN_LENGTH || 319 $('new-pin-input').value.length < SimUnlock.PIN_MIN_LENGTH || 320 !oldPinOk; 321 }); 322 $('retype-new-pin-input').addEventListener('keydown', function(event) { 323 if (event.keyIdentifier == 'Enter') { 324 SimUnlock.newPinEntered($('new-pin-input').value, 325 $('retype-new-pin-input').value); 326 return; 327 } 328 }); 329 $('retype-new-pin-input').addEventListener('textInput', 330 SimUnlock.processInput.bind(this)); 331 $('choose-pin-confirm').addEventListener('click', function(event) { 332 SimUnlock.newPinEntered($('new-pin-input').value, 333 $('retype-new-pin-input').value); 334 }); 335 $('choose-pin-dismiss').addEventListener('click', function(event) { 336 SimUnlock.cancel(); 337 }); 338 339 // SIM blocked screens. 340 $('puk-no-tries-confirm').addEventListener('click', function(event) { 341 SimUnlock.close(); 342 }); 343 $('sim-disabled-confirm').addEventListener('click', function(event) { 344 SimUnlock.close(); 345 }); 346 chrome.send('simStatusInitialize', [this.mode_]); 347 }; 348 349 SimUnlock.enablePinDialog = function(enabled) { 350 $('pin-input').disabled = !enabled; 351 // Ok button is initially disabled. 352 $('enter-pin-confirm').disabled = true; 353 $('enter-pin-dismiss').disabled = !enabled; 354 }; 355 356 SimUnlock.enableChoosePinDialog = function(enabled) { 357 $('old-pin-input').disabled = !enabled; 358 $('new-pin-input').disabled = !enabled; 359 $('retype-new-pin-input').disabled = !enabled; 360 // Ok button is initially disabled. 361 $('choose-pin-confirm').disabled = true; 362 $('choose-pin-dismiss').disabled = !enabled; 363 }; 364 365 SimUnlock.submitPin = function() { 366 var pin = $('pin-input').value; 367 if (pin.length < SimUnlock.PIN_MIN_LENGTH) 368 return; 369 SimUnlock.enablePinDialog(false); 370 chrome.send('enterPinCode', [pin]); 371 }; 372 373 SimUnlock.prepareChoosePinDialog = function(changePin) { 374 // Our dialog has different height than choose-pin step of the 375 // unlock process which we're reusing. 376 if (changePin) { 377 $('choose-pin-content-area').classList.remove('choose-pin-content-area'); 378 $('choose-pin-content-area').classList.add('change-pin-content-area'); 379 var title = SimUnlock.localStrings_.getString('changePinTitle'); 380 $('choose-pin-title').textContent = title; 381 } else { 382 $('choose-pin-content-area').classList.remove('change-pin-content-area'); 383 $('choose-pin-content-area').classList.add('choose-pin-content-area'); 384 var pinMessage = SimUnlock.localStrings_.getString('choosePinMessage'); 385 $('choose-pin-msg').classList.remove('error'); 386 $('choose-pin-msg').textContent = pinMessage; 387 var title = SimUnlock.localStrings_.getString('choosePinTitle'); 388 $('choose-pin-title').textContent = title; 389 } 390 $('old-pin-label').hidden = !changePin; 391 $('old-pin-input-area').hidden = !changePin; 392 }; 393 394 SimUnlock.newPinEntered = function(newPin, newPin2) { 395 SimUnlock.getInstance().newPinEntered_(newPin, newPin2); 396 }; 397 398 SimUnlock.pukEntered = function(pukValue) { 399 SimUnlock.getInstance().pukEntered_(pukValue); 400 }; 401 402 /** 403 * Processes PIN/PUK fields input, restricting it to 0..9. 404 */ 405 SimUnlock.processInput = function(event) { 406 if (/[^0-9]+/gi.test(event.data)) 407 event.preventDefault(); 408 }; 409 410 SimUnlock.simStateChanged = function(simInfo) { 411 SimUnlock.getInstance().updateSimStatus_(simInfo); 412 }; 413 414 // Export 415 return { 416 SimUnlock: SimUnlock 417 }; 418 419 }); 420 421 disableTextSelectAndDrag(); 422