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.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View file

@ -0,0 +1,53 @@
define(function() {
'use strict';
var DialogPanel = require('modules/dialog_panel');
var SimPinDialog = require('panels/simpin_dialog/simpin_dialog');
return function ctor_simpin_dialog() {
var elements = {};
return DialogPanel({
onInit: function(panel) {
this._method = '';
this._simpinDialog = null;
elements.panel = panel;
elements.dialogTitle = panel.querySelector('gaia-header h1');
elements.dialogDone = panel.querySelector('button[type="submit"]');
elements.triesLeftMsg = panel.querySelector('.sim-triesLeft');
elements.errorMsg = panel.querySelector('.sim-errorMsg');
elements.errorMsgHeader = panel.querySelector('.sim-messageHeader');
elements.errorMsgBody = panel.querySelector('.sim-messageBody');
elements.pinArea = panel.querySelector('.sim-pinArea');
elements.pinInput = elements.pinArea.querySelector('input');
elements.pukArea = panel.querySelector('.sim-pukArea');
elements.pukInput = elements.pukArea.querySelector('input');
elements.newPinArea = panel.querySelector('.sim-newPinArea');
elements.newPinInput = elements.newPinArea.querySelector('input');
elements.confirmPinArea = panel.querySelector('.sim-confirmPinArea');
elements.confirmPinInput =
elements.confirmPinArea.querySelector('input');
},
onBeforeShow: function(panel, options) {
options.cardIndex = options.cardIndex || 0;
options.pinOptions = options.pinOptions || {};
this._method = options.method;
this._simpinDialog = SimPinDialog(elements);
this._simpinDialog.init(options);
},
onShow: function() {
if (this._method === 'unlock_puk' || this._method === 'unlock_puk2') {
elements.pukInput.focus();
} else {
elements.pinInput.focus();
}
},
onSubmit: function() {
return this._simpinDialog.verify();
},
onHide: function() {
this._simpinDialog.clear();
}
});
};
});

View file

@ -0,0 +1,697 @@
/**
* SimPinDialog is a constructor function that can help us process
* any simpin related works like enable/disable lock, change pins ... etc.
*
* @module @SimPinDialog
*/
define(function(require) {
'use strict';
var SimSecurity = require('modules/sim_security');
var DialogService = require('modules/dialog_service');
var l10n = document.l10n;
var _debug = false;
var debug = function() {};
if (_debug) {
debug = function spd_debug(msg) {
console.log('--> [SimPinDialog]: ' + msg);
};
}
function SimPinDialog(elements) {
this._localize = l10n.setAttributes;
this._elements = elements;
this._method = '';
this._mode = '';
this._cardIndex = 0;
this._pinOptions = {};
this._allowedRetryCounts = {
pin: 3,
pin2: 3,
puk: 10,
puk2: 10
};
}
SimPinDialog.prototype = {
/**
* init function
*
* @memberOf SimPinDialog
* @access public
* @param {Object} options
* @param {String} options.method - lock, unlock ... etc
* @param {Number} options.cardIndex - which simcard
* @param {Object} options.pinOptions - extra arguments for icc operations
*/
init: function(options) {
this._method = options.method;
this._cardIndex = options.cardIndex;
this._pinOptions = options.pinOptions;
this._bindInputClickEvent();
this._initUI();
},
/**
* We will call this function when users click on submit button to make sure
* DialogService can do the right thing.
*
* @memberOf SimPinDialog
* @access public
* @return {Promise}
*/
verify: function() {
switch (this._method) {
// unlock SIM
case 'unlock_pin':
return this._unlockPin();
case 'unlock_puk':
return this._unlockPuk('puk');
case 'unlock_puk2':
return this._unlockPuk('puk2');
// PIN lock
case 'enable_lock':
return this._enableLock(true);
case 'disable_lock':
return this._enableLock(false);
case 'change_pin':
return this._changePin('pin');
// get PIN2 code (FDN contact list)
case 'get_pin2':
return this._updateFdnContact();
// PIN2 lock (FDN)
case 'enable_fdn':
return this._enableFdn(true);
case 'disable_fdn':
return this._enableFdn(false);
case 'change_pin2':
return this._changePin('pin2');
default:
return Promise.reject();
}
},
/**
* We will clear all pre-set values when the dialog is hidden.
*
* @memberOf SimPinDialog
* @access public
*/
clear: function() {
this._elements.errorMsgHeader.textContent = '';
this._elements.errorMsgBody.textContent = '';
this._elements.triesLeftMsg.textContent = '';
this._elements.pinInput.value = '';
this._elements.pukInput.value = '';
this._elements.newPinInput.value = '';
this._elements.confirmPinInput.value = '';
this._elements.errorMsg.hidden = true;
this._elements.triesLeftMsg.hidden = true;
},
/**
* Unlock pin
*
* @memberOf SimPinDialog
* @access private
* @return {Promise}
*/
_unlockPin: function() {
var pin = this._elements.pinInput.value;
if (pin === '') {
return Promise.reject();
}
return this._unlockCardLock({
lockType: 'pin',
pin: pin
});
},
/**
* Unlock puk1 or puk2
*
* @memberOf SimPinDialog
* @param {String} lockType
* @access private
* @return {Promise}
*/
_unlockPuk: function(lockType) {
lockType = lockType || 'puk';
var puk = this._elements.pukInput.value;
var newPin = this._elements.newPinInput.value;
var confirmPin = this._elements.confirmPinInput.value;
if (puk === '' || newPin === '' || confirmPin === '') {
return Promise.reject();
}
if (newPin !== confirmPin) {
this._showMessage('newPinErrorMsg');
this._elements.newPinInput.value = '';
this._elements.confirmPinInput.value = '';
this._elements.pukInput.value = '';
this._elements.pukInput.focus();
return Promise.reject();
}
return this._unlockCardLock({
lockType: lockType,
puk: puk,
newPin: newPin
});
},
/**
* This is an internal function to pass all arguments to icc and waiting
* for returned results.
*
* @memberOf SimPinDialog
* @param {Object} options
* @param {String} options.pin
* @param {String} options.puk
* @param {String} options.newPin
* @access private
* @return {Promise}
*/
_unlockCardLock: function(options) {
return SimSecurity.unlockCardLock(this._cardIndex, options).then(() => {
// do nothing
}, (error) => {
var needToCloseDialog = this._handleCardLockError({
lockType: options.lockType,
error: error
});
if (!needToCloseDialog) {
return Promise.reject();
}
});
},
/**
* Lock pin
*
* @memberOf SimPinDialog
* @param {Boolean} enabled
* @access private
* @return {Promise}
*/
_enableLock: function(enabled) {
var pin = this._elements.pinInput.value;
if (pin === '') {
return Promise.reject();
}
return this._setCardLock({
lockType: 'pin',
pin: pin,
enabled: enabled
});
},
/**
* Enable FDN on Simcards and related Call functions under its own panel.
*
* @memberOf SimPinDialog
* @param {Boolean} enabled
* @access private
* @return {Promise}
*/
_enableFdn: function(enabled) {
var pin = this._elements.pinInput.value;
if (pin === '') {
return Promise.reject();
}
return this._setCardLock({
lockType: 'fdn',
pin2: pin,
enabled: enabled
});
},
/**
* Change the pre-defined codes in the simcard.
*
* @memberOf SimPinDialog
* @param {String} lockType
* @access private
* @return {Promise}
*/
_changePin: function(lockType) {
// lockType = `pin' or `pin2'
lockType = lockType || 'pin';
var pin = this._elements.pinInput.value;
var newPin = this._elements.newPinInput.value;
var confirmPin = this._elements.confirmPinInput.value;
if (pin === '' || newPin === '' || confirmPin === '') {
return Promise.reject();
}
if (newPin !== confirmPin) {
this._showMessage('newPinErrorMsg');
this._elements.newPinInput.value = '';
this._elements.confirmPinInput.value = '';
this._elements.pinInput.value = '';
this._elements.pinInput.focus();
return Promise.reject();
}
return this._setCardLock({
lockType: lockType,
pin: pin,
newPin: newPin
});
},
/**
* This is an internal function to pass all arguments to icc and waiting
* for returned results.
*
* @memberOf SimPinDialog
* @param {Object} options
* @param {String} options.lockType
* @param {String} options.pin
* @param {String} options.newPin
* @param {String} options.pin2
* @param {Boolean} options.enabled
* @access private
* @return {Promise}
*/
_setCardLock: function(options) {
return SimSecurity.setCardLock(this._cardIndex, options).then(() => {
// do nothing
}, (error) => {
var needToCloseDialog = this._handleCardLockError({
lockType: options.lockType,
error: error
});
if (!needToCloseDialog) {
return Promise.reject();
}
});
},
/**
* this function is used when we are going to update fdn contacts under
* call panel.
*
* @memberOf SimPinDialog
* @access private
* @return {Promise}
*/
_updateFdnContact: function() {
// Updates a FDN contact. For some reason, `icc.updateContact` requires
// the pin input value instead of delegating to `icc.setCardLock`.
// That means that, in case of failure, the error is different that the
// one that `icc.setCardLock` gives. This means that we have to handle
// it separatedly instead of being able to use the existing
// `handleCardLockError` above.
//
// Among other things, it doesn't include the retryCount, so we can't
// tell the user how many remaining tries she has. What a mess.
// This should be solved when bug 1070941 is fixed.
var fdnContact = this._pinOptions.fdnContact;
return SimSecurity.updateContact(this._cardIndex, 'fdn', fdnContact,
this._elements.pinInput.value).then(() => {
return fdnContact;
}, (error) => {
switch (error.name) {
case 'IncorrectPassword':
case 'SimPin2':
// TODO: count retries (not supported by the platform) ->
// Bug 1070941
this._initUI('get_pin2');
this._showMessage('fdnErrorMsg');
this._elements.pinInput.value = '';
this._elements.pinInput.focus();
return Promise.reject();
case 'SimPuk2':
this._initUI('unlock_puk2');
this._elements.pukInput.focus();
return Promise.reject();
case 'NoFreeRecordFound':
DialogService.alert('fdnNoFDNFreeRecord');
return fdnContact;
default:
console.error('Could not edit FDN contact on SIM card - ', error);
return fdnContact;
}
});
},
/**
* We will try to handle all returned errors here when requests are
* returned from icc.
*
* @memberOf SimPinDialog
* @param {Object} options
* @param {String} options.lockType
* @param {Object} options.error
* @param {Number} options.error.retryCount
* @param {String} options.error.name
* @access private
* @return {Boolean} - true means close dialog, others mean not
*/
_handleCardLockError: function(options) {
var error = options.error;
var lockType = options.lockType;
var retryCount = error.retryCount;
var errorName = error.name;
debug('_handleCardLockError: ' + errorName);
// expected: 'pin', 'fdn', 'puk'
if (!lockType) {
// we don't know what's going on here, we have close the dialog.
console.error('`handleCardLockError` called without a lockType. ' +
'This should never even happen.', error);
return true;
}
switch (errorName) {
case 'SimPuk2':
case 'IncorrectPassword':
return this._handleRetryPassword(lockType, retryCount);
default:
DialogService.alert('genericLockError');
console.error('Error of type ' + errorName +
' happened coming from an IccCardLockError event', error);
return true;
}
},
/**
* We will handle all retry cases here to make sure we can change to
* the right UI for users to continue.
*
* @memberOf SimPinDialog
* @param {String} lockType
* @param {Number} retryCount
* @access private
* @return {Boolean} - true means close dialog, others mean not
*/
_handleRetryPassword: function(lockType, retryCount) {
// after three strikes, ask for PUK/PUK2
if (retryCount <= 0) {
debug('_handleRetryPassword lockType:' + lockType);
if (lockType === 'pin') {
// we leave this for system app, so let's close the dialog
return true;
} else if (lockType === 'fdn' || lockType === 'pin2') {
this._initUI('unlock_puk2');
this._elements.pukInput.focus();
return false;
} else {
// out of PUK/PUK2: we're doomed
DialogService.alert('genericLockError');
return true;
}
} else {
// We still have retryCount, let users input values again
var msgId = (retryCount > 1) ? 'AttemptMsg3' : 'LastChanceMsg';
this._showMessage(lockType + 'ErrorMsg', lockType + msgId, {
n: retryCount
});
this._showRetryCount(retryCount);
if (lockType === 'pin' || lockType === 'fdn') {
this._elements.pinInput.value = '';
this._elements.pinInput.focus();
} else if (lockType === 'puk') {
this._elements.pukInput.value = '';
this._elements.pukInput.focus();
} else if (lockType === 'puk2') {
this._elements.pinInput.value = '';
this._elements.pukInput.value = '';
this._elements.pukInput.focus();
}
return false;
}
},
/**
* we will use `mode` to decide what kind of UI should be shown/hidden.
*
* @memberOf SimPinDialog
* @param {String} mode
* @access private
*/
_setMode: function(mode) {
this._mode = mode;
this._elements.pinArea.hidden = (mode === 'puk');
this._elements.pukArea.hidden = (mode !== 'puk');
this._elements.newPinArea.hidden =
this._elements.confirmPinArea.hidden = (mode === 'pin');
},
/**
* We can show any message on the screen.
*
* @memberOf SimPinDialog
* @param {String} headerL10nId
* @param {String} bodyL10nId
* @param {Object} args
* @access private
*/
_showMessage: function(headerL10nId, bodyL10nId, args) {
if (!headerL10nId) {
this._elements.errorMsg.hidden = true;
return;
}
this._elements.errorMsgHeader.setAttribute('data-l10n-id', headerL10nId);
if (bodyL10nId) {
this._localize(this._elements.errorMsgBody, bodyL10nId, args);
}
this._elements.errorMsg.hidden = false;
},
/**
* To hint users about how many times they can retry before the simcard
* got locked.
*
* @memberOf SimPinDialog
* @param {Number} retryCount
* @access private
*/
_showRetryCount: function(retryCount) {
if (!retryCount) {
this._elements.triesLeftMsg.hidden = true;
} else {
this._localize(this._elements.triesLeftMsg, 'inputCodeRetriesLeft', {
n: retryCount
});
this._elements.triesLeftMsg.hidden = false;
}
},
/**
* bind onclick event on all inputs
*
* @memberOf SimPinDialog
* @access private
*/
_bindInputClickEvent: function() {
var elements = this._elements;
var inputs = [
'pinInput',
'pukInput',
'newPinInput',
'confirmPinInput'
];
inputs.forEach((inputName) => {
var input = elements[inputName];
input.oninput = () => {
this._updateDoneButtonState();
};
});
},
/**
* We have to control `done` button in each condition to make sure
* its state is right based on user's input
*
* @memberOf SimPinDialog
* @access private
*/
_updateDoneButtonState: function() {
var elements = this._elements;
switch (this._mode) {
case 'change_pin':
if (elements.pinInput.value.length < 4 ||
elements.newPinInput.value.length < 4 ||
elements.confirmPinInput.value.length < 4 ||
elements.newPinInput.value.length !==
elements.confirmPinInput.value.length) {
elements.dialogDone.disabled = true;
} else {
elements.dialogDone.disabled = false;
}
break;
case 'pin':
elements.dialogDone.disabled = (elements.pinInput.value.length < 4);
break;
case 'puk':
elements.dialogDone.disabled = (elements.pukInput.value.length < 4);
break;
default:
console.error('we should not jump to this condition');
break;
}
},
/**
* We will change the UI based on current lockType.
*
* @memberOf SimPinDialog
* @access private
*/
_initUI: function(method) {
if (method) {
this._method = method;
}
this._showMessage();
this._showRetryCount(); // Clear the retry count at first
this._elements.dialogDone.disabled = true;
var lockType = 'pin'; // used to query the number of retries left
debug('initUI method: ' + this._method);
switch (this._method) {
// get PIN code
case 'get_pin2':
lockType = 'pin2';
this._setMode('pin');
this._localize(this._elements.pinArea.querySelector('div'),
'simPin2');
this._localize(this._elements.dialogTitle, lockType + 'Title');
break;
// unlock SIM
case 'unlock_pin':
this._setMode('pin');
this._localize(this._elements.pinArea.querySelector('div'),
'simPin');
this._localize(this._elements.dialogTitle, 'pinTitle');
break;
case 'unlock_puk':
lockType = 'puk';
this._setMode('puk');
this._showMessage('simCardLockedMsg', 'enterPukMsg');
this._localize(this._elements.pukArea.querySelector('div'),
'pukCode');
this._localize(this._elements.dialogTitle, 'pukTitle');
this._localize(this._elements.newPinArea.querySelector('div'),
'newSimPinMsg');
this._localize(this._elements.confirmPinArea.querySelector('div'),
'confirmNewSimPinMsg');
break;
case 'unlock_puk2':
lockType = 'puk2';
this._setMode('puk');
this._showMessage('simCardLockedMsg', 'enterPuk2Msg');
this._localize(this._elements.pukArea.querySelector('div'),
'puk2Code');
this._localize(this._elements.dialogTitle, 'puk2Title');
this._localize(this._elements.newPinArea.querySelector('div'),
'newSimPin2Msg');
this._localize(this._elements.confirmPinArea.querySelector('div'),
'confirmNewSimPin2Msg');
break;
// PIN lock
case 'enable_lock':
this._setMode('pin');
this._localize(this._elements.pinArea.querySelector('div'),
'simPin');
this._localize(this._elements.dialogTitle, 'pinTitle');
break;
case 'disable_lock':
this._setMode('pin');
this._localize(this._elements.pinArea.querySelector('div'),
'simPin');
this._localize(this._elements.dialogTitle, 'pinTitle');
break;
case 'change_pin':
this._setMode('change_pin');
this._localize(this._elements.pinArea.querySelector('div'),
'simPin');
this._localize(this._elements.newPinArea.querySelector('div'),
'newSimPinMsg');
this._localize(this._elements.confirmPinArea.querySelector('div'),
'confirmNewSimPinMsg');
this._localize(this._elements.dialogTitle, 'newpinTitle');
break;
// FDN lock (PIN2)
case 'enable_fdn':
lockType = 'pin2';
this._setMode('pin');
this._localize(this._elements.pinArea.querySelector('div'),
'simPin2');
this._localize(this._elements.dialogTitle, 'fdnEnable');
break;
case 'disable_fdn':
lockType = 'pin2';
this._setMode('pin');
this._localize(this._elements.pinArea.querySelector('div'),
'simPin2');
this._localize(this._elements.dialogTitle, 'fdnDisable');
break;
case 'change_pin2':
lockType = 'pin2';
this._setMode('change_pin');
this._localize(this._elements.pinArea.querySelector('div'),
'simPin2');
this._localize(this._elements.newPinArea.querySelector('div'),
'newSimPin2Msg');
this._localize(this._elements.confirmPinArea.querySelector('div'),
'confirmNewSimPin2Msg');
this._localize(this._elements.dialogTitle, 'fdnReset');
break;
// unsupported
default:
console.error('unsupported "' + this._method + '" method');
break;
}
// display the number of remaining retries if necessary
// XXX this only works with the emulator
// (and some commercial RIL stacks...)
// https://bugzilla.mozilla.org/show_bug.cgi?id=905173
SimSecurity.getCardLockRetryCount(this._cardIndex, lockType)
.then((result) => {
var retryCount = result.retryCount;
if (retryCount === this._allowedRetryCounts[lockType]) {
// hide the retry count if users had not input incorrect codes
retryCount = null;
}
this._showRetryCount(retryCount);
});
}
};
return function ctor_simPinDialog(elements) {
return new SimPinDialog(elements);
};
});