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