VulpesOS/gaia/apps/system/js/sim_lock_system_dialog.js
OverSu b38dea0597 Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
2026-09-30 23:13:03 +02:00

509 lines
16 KiB
JavaScript
Executable file

/* global SystemDialog, SIMSlotManager, applications, Service, LazyLoader */
'use strict';
(function(exports) {
/**
* @class SimLockSystemDialog
* @param {options} object for attributes `onShow`, `onHide` callback.
* @extends SystemDialog
*/
var SimLockSystemDialog = function(controller) {
this.instanceID = 'simlock-dialog';
this.controller = controller;
this.options = {};
/**
* render the dialog
*/
LazyLoader.load('shared/elements/gaia-component/gaia-component.js')
.then(() => {
LazyLoader.load([
'shared/elements/gaia-dialog/gaia-dialog.js',
'shared/elements/gaia-text-input/gaia-text-input.js'
])
.then(() => {
this.render();
});
});
this._dispatchEvent('created');
};
var ORIENTATION = 'portrait-primary';
SimLockSystemDialog.prototype = Object.create(SystemDialog.prototype,
{
visible: {
configurable: false,
get: function() {
return this._visible;
}
},
});
SimLockSystemDialog.prototype.lockType = 'pin';
SimLockSystemDialog.prototype.lockTypeMap = {
'pinRequired': 'pin',
'pukRequired': 'puk',
'networkLocked': 'nck',
'corporateLocked': 'cck',
'serviceProviderLocked': 'spck',
'network1Locked': 'nck1',
'network2Locked': 'nck2',
'hrpdNetworkLocked': 'hnck',
'ruimCorporateLocked': 'rcck',
'ruimServiceProviderLocked': 'rspck'
};
SimLockSystemDialog.prototype.customID = 'simlock-dialog';
SimLockSystemDialog.prototype.DEBUG = false;
SimLockSystemDialog.prototype.name = 'SimLockSystemDialog';
SimLockSystemDialog.prototype.EVENT_PREFIX = 'simlock';
SimLockSystemDialog.prototype.view = function spd_view() {
return `<gaia-dialog id="${this.instanceID}">
<div class="dialog-content" data-z-index-level="system-dialog">
<gaia-header>
<h1></h1>
</gaia-header>
<div class="container">
<div id="errorMsg" class="error" hidden>
<div id="messageHeader">The PIN was incorrect.</div>
<span id="messageBody">3 tries left.</span>
</div>
<!-- tries left -->
<div id="triesLeft" data-l10n-id="inputCodeRetriesLeft" hidden>
</div>
<!-- sim pin input field -->
<div id="pinArea" hidden>
<div data-l10n-id="simPin"></div>
<div class="input-wrapper">
<gaia-text-input type="password" x-inputmode="digit"
maxlength="8" name="simpin"/>
</div>
</div>
<!-- sim puk input field -->
<div id="pukArea" hidden>
<div data-l10n-id="pukCode"></div>
<div class="input-wrapper">
<gaia-text-input type="password" x-inputmode="digit"
maxlength="8" name="simpuk"/>
</div>
</div>
<!-- sim nck/cck/spck input field -->
<div id="xckArea" hidden>
<div name="xckDesc" data-l10n-id="nckCode"></div>
<div class="input-wrapper">
<gaia-text-input type="password" x-inputmode="digit"
maxlength="8" name="xckpin" />
</div>
</div>
<!-- new sim pin input field -->
<div id="newPinArea" hidden>
<div data-l10n-id="newSimPinMsg"></div>
<div class="input-wrapper">
<gaia-text-input type="password" x-inputmode="digit"
maxlength="8" name="newSimpin"/>
</div>
</div>
<!-- confirm new sim pin input field -->
<div id="confirmPinArea" hidden>
<div data-l10n-id="confirmNewSimPinMsg"></div>
<div class="input-wrapper">
<gaia-text-input type="password" x-inputmode="digit"
maxlength="8" name="confirmNewSimpin"/>
</div>
</div>
</div>
</div>
<fieldset>
<button data-l10n-id="skip" class="cancel">Skip</button>
<button data-l10n-id="ok" disabled class="submit primary">
OK
</button>
</fieldset>
</gaia-dialog>`;
};
SimLockSystemDialog.prototype.onHide = function() {
this._visible = false;
this.controller && this.controller.onHide();
};
SimLockSystemDialog.prototype.updateHeight = function() {
var height = Service.query('LayoutManager.height');
this.containerElement.style.height = height + 'px';
// We need to manually set the gaia-dialog height,
// as it is fixed positioned
this.element.style.height = height + 'px';
this.debug('updateHeight: new height = ' + height);
document.activeElement.scrollIntoView(false);
};
SimLockSystemDialog.prototype._registerEvents = function() {
this.dialogDone.addEventListener('click', this.verify.bind(this));
this.dialogSkip.addEventListener('click', this.skip.bind(this));
[this.dialogDone, this.dialogSkip].forEach((button) => {
button.addEventListener('mousedown', this._handle_mousedown.bind(this));
});
this.header.addEventListener('action', this.back.bind(this));
this.element.addEventListener('closed', this.hide.bind(this));
this.pinInput = this.getNumberPasswordInputField('simpin');
this.pukInput = this.getNumberPasswordInputField('simpuk');
this.xckInput = this.getNumberPasswordInputField('xckpin');
this.newPinInput = this.getNumberPasswordInputField('newSimpin');
this.confirmPinInput =
this.getNumberPasswordInputField('confirmNewSimpin');
};
SimLockSystemDialog.prototype._fetchElements = function spl_initElements() {
this.element = document.getElementById('simlock-dialog');
this.header = this.element.querySelector('gaia-header');
this.dialogTitle = this.header.querySelector('h1');
this.pinArea = document.getElementById('pinArea');
this.pukArea = document.getElementById('pukArea');
this.xckArea = document.getElementById('xckArea');
this.desc = this.element.querySelector('#xckArea div[name="xckDesc"]');
this.newPinArea = document.getElementById('newPinArea');
this.confirmPinArea = document.getElementById('confirmPinArea');
this.triesLeftMsg = document.getElementById('triesLeft');
this.errorMsg = document.getElementById('errorMsg');
this.errorMsgHeader = document.getElementById('messageHeader');
this.errorMsgBody = document.getElementById('messageBody');
this.containerDiv = this.element.querySelector('.container');
this.dialogDone = this.element.querySelector('button.submit');
this.dialogSkip = this.element.querySelector('button.cancel');
};
SimLockSystemDialog.prototype.getNumberPasswordInputField = function(name) {
var selector = 'gaia-text-input[name="' + name + '"]';
var inputField = document.querySelector(selector);
var self = this;
inputField.addEventListener('input', function(evt) {
if (evt.target !== inputField) {
return;
}
checkDialogDone();
});
inputField.addEventListener('focus', function() {
checkDialogDone();
});
function checkDialogDone() {
if (inputField.value.length >= 4) {
self.dialogDone.removeAttribute('disabled');
} else {
self.dialogDone.setAttribute('disabled', 'disabled');
}
}
return inputField;
};
SimLockSystemDialog.prototype.handleCardState = function() {
var _ = navigator.mozL10n.setAttributes;
if (!this._currentSlot) {
return;
}
var card = this._currentSlot.simCard;
var cardState = card.cardState;
var lockType = this.lockTypeMap[cardState];
var request = this._currentSlot.getCardLockRetryCount(lockType);
request.onsuccess = (function() {
var retryCount = request.result.retryCount;
if (retryCount) {
var l10nArgs = { n: retryCount };
_(this.triesLeftMsg, 'inputCodeRetriesLeft', l10nArgs);
this.triesLeftMsg.hidden = false;
}
}).bind(this);
request.onerror = function() {
console.log('Could not fetch CardLockRetryCount', request.error.name);
};
switch (lockType) {
case 'pin':
this.lockType = lockType;
this.errorMsg.hidden = true;
this.inputFieldControl(true, false, false, false);
break;
case 'puk':
this.lockType = lockType;
_(this.errorMsgHeader, 'simCardLockedMsg');
_(this.errorMsgBody, 'enterPukMsg');
this.errorMsg.hidden = false;
this.inputFieldControl(false, true, false, true);
break;
case 'nck':
case 'cck':
case 'spck':
case 'nck1':
case 'nck2':
case 'hnck':
case 'rcck':
case 'rspck':
this.lockType = lockType;
this.errorMsg.hidden = true;
this.inputFieldControl(false, false, true, false);
_(this.desc, lockType + 'Code');
break;
default:
this.skip();
break;
}
if (this.lockType !== 'pin' || !SIMSlotManager.isMultiSIM()) {
_(this.dialogTitle, this.lockType + 'Title');
} else {
_(this.dialogTitle, 'multiSIMpinTitle',
{ n: this._currentSlot.index + 1 });
}
};
SimLockSystemDialog.prototype.handleError = function(lockType, retryCount) {
var retry = (retryCount) ? retryCount : -1;
this.showErrorMsg(retry, lockType);
if (retry === -1) {
this.skip();
return;
}
if (lockType === 'pin') {
this.pinInput.focus();
} else if (lockType === 'puk') {
this.pukInput.focus();
} else {
this.xckInput.focus();
}
};
SimLockSystemDialog.prototype.showErrorMsg = function(retry, type) {
var _ = navigator.mozL10n.setAttributes;
var l10nArgs = { n: retry };
_(this.triesLeftMsg, 'inputCodeRetriesLeft', l10nArgs);
_(this.errorMsgHeader, type + 'ErrorMsg');
if (retry !== 1) {
_(this.errorMsgBody, type + 'AttemptMsg2', l10nArgs);
} else {
_(this.errorMsgBody, type + 'LastChanceMsg');
}
this.errorMsg.hidden = false;
};
SimLockSystemDialog.prototype.unlockPin = function() {
var pin = this.pinInput.value;
if (pin === '') {
return;
}
var options = { lockType: 'pin', pin: pin };
this.unlockCardLock(options);
};
SimLockSystemDialog.prototype.unlockPuk = function() {
var _ = navigator.mozL10n.setAttributes;
var puk = this.pukInput.value;
var newPin = this.newPinInput.value;
var confirmPin = this.confirmPinInput.value;
if (puk === '' || newPin === '' || confirmPin === '') {
return;
}
if (newPin !== confirmPin) {
_(this.errorMsgHeader, 'newPinErrorMsg');
_(this.errorMsgBody, '');
this.errorMsg.hidden = false;
return;
}
var options = {lockType: 'puk', puk: puk, newPin: newPin };
this.unlockCardLock(options);
this.clear();
};
SimLockSystemDialog.prototype.unlockXck = function() {
var xck = this.xckInput.value;
if (xck === '') {
return;
}
var options = {lockType: this.lockType, pin: xck };
this.unlockCardLock(options);
this.clear();
};
SimLockSystemDialog.prototype.unlockCardLock = function(options) {
var req = this._currentSlot.unlockCardLock(options);
this.disableInput();
req.onsuccess = this.requestClose.bind(this, 'success');
req.onerror = (function spl_unlockCardLockError(result) {
this.clear();
this.handleError(options.lockType, req.error.retryCount);
}).bind(this);
};
SimLockSystemDialog.prototype.focus = function() {
switch (this.lockType) {
case 'pin':
this.pinInput.focus();
break;
case 'puk':
this.pukInput.focus();
break;
default:
this.xckInput.focus();
break;
}
};
SimLockSystemDialog.prototype.inputFieldControl =
function(isPin, isPuk, isXck, isNewPin) {
this.pinArea.hidden = !isPin;
this.pukArea.hidden = !isPuk;
this.xckArea.hidden = !isXck;
this.newPinArea.hidden = !isNewPin;
this.confirmPinArea.hidden = !isNewPin;
this.requestFocus();
};
SimLockSystemDialog.prototype._handle_mousedown = function(evt) {
evt.preventDefault();
};
SimLockSystemDialog.prototype.verify = function() {
if (this.lockType === 'pin') {
this.unlockPin();
} else if (this.lockType === 'puk') {
this.unlockPuk();
} else {
this.unlockXck();
}
return false;
};
SimLockSystemDialog.prototype.onHide = function() {
this.clear();
if (this.onclose) {
this.onclose();
}
};
SimLockSystemDialog.prototype.disableInput = function() {
this.pinInput.disabled = true;
this.pukInput.disabled = true;
this.xckInput.disabled = true;
this.newPinInput.disabled = true;
this.confirmPinInput.disabled = true;
};
SimLockSystemDialog.prototype.enableInput = function() {
this.pinInput.disabled = false;
this.pukInput.disabled = false;
this.xckInput.disabled = false;
this.newPinInput.disabled = false;
this.confirmPinInput.disabled = false;
};
SimLockSystemDialog.prototype.clear = function() {
this.enableInput();
this.errorMsg.hidden = true;
this.pinInput.clear();
this.pukInput.clear();
this.xckInput.clear();
this.newPinInput.clear();
this.confirmPinInput.clear();
this.dialogDone.setAttribute('disabled', 'disabled');
};
SimLockSystemDialog.prototype.onclose = null;
SimLockSystemDialog.prototype._visible = false;
/**
* Show the SIM pin dialog
* @param {Object} slot SIMSlot instance.
* @param {Boolean} [skipped] If the last slot is skipped or not.
*/
SimLockSystemDialog.prototype.show = function(slot, skipped) {
this.clear();
if (slot) {
this._currentSlot = slot;
}
SystemDialog.prototype.show.apply(this);
this.element.open();
var appWindow = Service.query('getTopMostWindow');
appWindow.lockOrientation(ORIENTATION);
this._visible = true;
this.lockType = 'pin';
this.handleCardState();
if (skipped) {
this.header.setAttribute('action', 'back');
// Force header-text to be repositioned
// now the action-button is present
this.dialogTitle.textContent = this.dialogTitle.textContent;
} else {
this.header.removeAttribute('action');
}
};
SimLockSystemDialog.prototype.requestClose = function() {
this._dispatchEvent('requestclose');
};
SimLockSystemDialog.prototype.hide = function() {
this._visible = false;
SystemDialog.prototype.hide.apply(this);
var appWindow = Service.query('getTopMostWindow');
appWindow.lockOrientation();
};
SimLockSystemDialog.prototype.close = function() {
this._dispatchEvent('close');
this.element && this.element.close();
this._visible = false;
};
SimLockSystemDialog.prototype.skip = function(evt) {
this._dispatchEvent('skip');
};
SimLockSystemDialog.prototype.back = function() {
this._dispatchEvent('back');
};
SimLockSystemDialog.prototype.requestFocus = function() {
this._dispatchEvent('requestfocus');
};
SimLockSystemDialog.prototype._dispatchEvent = function _dispatchEvent(name) {
var self = this;
if (applications.ready) {
this.publish(name);
} else {
window.addEventListener('applicationready', function onReady() {
window.removeEventListener('applicationready', onReady);
self.publish(name);
});
}
};
exports.SimLockSystemDialog = SimLockSystemDialog;
}(window));