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