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,544 @@
require([
'shared/stk_helper'
], function(STKHelper) {
'use strict';
(function() {
var iccManager = window.navigator.mozIccManager;
function getIcc(iccId) {
window.DUMP('ICC Getting ICC for ' + iccId);
return iccManager.getIccById(iccId);
}
/**
* Move settings to foreground
*/
function reopenSettings() {
navigator.mozApps.getSelf().onsuccess = function getSelfCB(evt) {
var app = evt.target.result;
app.launch('settings');
};
}
// Consts
// 3GPP spec: TS 11.14
// 13.4 Type of Command and Next Action Indicator
const STK_NEXT_ACTION_INDICATOR = {
16: 'stkItemsNaiSetUpCall',
17: 'stkItemsNaiSendSs',
18: 'stkItemsNaiSendUssd',
19: 'stkItemsNaiSendSms',
32: 'stkItemsNaiPlayTone',
33: 'stkItemsNaiDisplayText',
34: 'stkItemsNaiGetInkey',
35: 'stkItemsNaiGetInput',
36: 'stkItemsNaiSelectItem',
37: 'stkItemsNaiSetUpMenu',
40: 'stkItemsNaiSetIdleModeText',
48: 'stkItemsNaiPerformCardApdu', // class "a"
49: 'stkItemsNaiPowerOnCard', // class "a"
50: 'stkItemsNaiPowerOffCard', // class "a"
51: 'stkItemsNaiGetReaderStatus', // class "a"
64: 'stkItemsNaiOpenChannel', // class "e"
65: 'stkItemsNaiCloseChannel', // class "e"
66: 'stkItemsNaiReceiveData', // class "e"
67: 'stkItemsNaiSendData', // class "e"
68: 'stkItemsNaiGetChannelStatus', // class "e"
96: 'Reserved', // for TIA/EIA-136
129: 'stkItemsNaiEndOfTheProactiveSession'
};
/**
* Init
*/
var iccStkList = document.getElementById('icc-stk-list');
var iccStkMainHeader = document.getElementById('icc-stk-main-header');
var iccStkHeader = document.getElementById('icc-stk-header');
var iccStkSubheader = document.getElementById('icc-stk-subheader');
var stkOpenAppName = null;
var stkLastSelectedText = null;
var goBackTimer = {
timer: null,
timeout: 0
};
var selectTimer = {
timer: null,
timeout: 0
};
var _visibilityChangeHandler = null;
var _backHandler = null;
init();
/**
* This is a helper for localizing DOM Elements using L10nID.
* Second argument may take one of the following forms:
* a string -> l10nId
* an object -> {id: l10nId, args: l10nArgs}
* an object -> {raw: string}
*
* Read more at MDN: http://mzl.la/1A76Fby
*/
function localizeElement(element, l10n) {
if (typeof(l10n) === 'string') {
element.setAttribute('data-l10n-id', l10n);
} else if (l10n.raw) {
element.removeAttribute('data-l10n-id');
element.textContent = l10n.raw;
} else {
document.l10n.setAttributes(element, l10n.id, l10n.attrs);
}
}
function sendVisibilityChangeEvent() {
navigator.mozApps.getSelf().onsuccess = function(evt) {
var app = evt.target.result;
app.connect('settingsstk').then(function onConnAccepted(ports) {
window.DUMP('STK_Settings IAC: ' + ports);
ports.forEach(function(port) {
window.DUMP('STK_Settings IAC: ' + port);
port.postMessage('StkMenuHidden');
});
}, function onConnRejected(reason) {
window.DUMP('STK_Settings IAC is rejected');
window.DUMP(reason);
});
};
}
function getNextActionString(nextActionList, index) {
window.DUMP('STK NAL: ' + nextActionList);
var nextActionString;
if (nextActionList &&
nextActionList[index] !== null &&
nextActionList[index] !== 96 &&
STK_NEXT_ACTION_INDICATOR[nextActionList[index]]) {
nextActionString = STK_NEXT_ACTION_INDICATOR[nextActionList[index]];
} else {
nextActionString = null;
}
return nextActionString;
}
function visibilityChangeHandler() {
if (document.hidden && Settings && Settings.currentPanel == '#icc') {
window.DUMP('STK_Settings visibilityChangeHandler');
sendVisibilityChangeEvent();
}
}
/**
* Init STK UI
*/
function init() {
window.addEventListener('stkasynccommand',
function do_handleAsyncSTKCmd(event) {
handleSTKMessage(event.detail.message);
});
window.addEventListener('stkmenuselection',
function do_handleAsyncSTKCmd(event) {
updateMenu(event.detail.menu);
});
document.addEventListener('visibilitychange',
visibilityChangeHandler, false);
iccStkMainHeader.addEventListener('action', function onBack() {
if (typeof _backHandler === 'function') {
_backHandler();
}
});
}
function addCloseNotificationsEvents(message) {
function onVisibilityChange() {
if (document.hidden && Settings && Settings.currentPanel == '#icc') {
document.removeEventListener('visibilitychange',
_visibilityChangeHandler, false);
stkResTerminate(message);
}
}
document.removeEventListener('visibilitychange',
_visibilityChangeHandler, false);
_visibilityChangeHandler = onVisibilityChange;
document.addEventListener('visibilitychange',
_visibilityChangeHandler, false);
window.onbeforeunload = function() {
responseSTKCommand(message, {
resultCode: iccManager.STK_RESULT_NO_RESPONSE_FROM_USER
}, true);
};
}
function returnToSettingsMainMenu() {
if (Settings) {
Settings.currentPanel = '#root';
}
}
function stkResTerminate(message) {
returnToSettingsMainMenu();
responseSTKCommand(message, {
resultCode: iccManager.STK_RESULT_UICC_SESSION_TERM_BY_USER
}, true);
}
function stkResGoBack(message) {
responseSTKCommand(message, {
resultCode: iccManager.STK_RESULT_BACKWARD_MOVE_BY_USER
});
// We'll return to settings if no STK response received in a grace period
var reqTimerGoBack =
window.navigator.mozSettings.createLock().get('icc.goBackTimeout');
reqTimerGoBack.onsuccess = function icc_getTimerGoBackSuccess() {
goBackTimer.timeout = reqTimerGoBack.result['icc.goBackTimeout'];
goBackTimer.timer = setTimeout(function() {
returnToSettingsMainMenu();
}, goBackTimer.timeout);
};
}
function stkResNoResponse(message) {
var reqTimerSelect =
window.navigator.mozSettings.createLock().get('icc.selectTimeout');
reqTimerSelect.onsuccess = function icc_getTimerSelectSuccess() {
selectTimer.timeout = reqTimerSelect.result['icc.selectTimeout'];
selectTimer.timer = setTimeout(function() {
responseSTKCommand(message, {
resultCode: iccManager.STK_RESULT_NO_RESPONSE_FROM_USER
}, true);
returnToSettingsMainMenu();
}, selectTimer.timeout);
};
}
function stkCancelGoBack() {
if (goBackTimer.timer) {
window.clearTimeout(goBackTimer.timer);
goBackTimer.timer = null;
}
if (selectTimer.timer) {
window.clearTimeout(selectTimer.timer);
selectTimer.timer = null;
}
}
/**
* Response ICC Command
*/
function responseSTKCommand(message, response) {
window.DUMP('sendStkResponse to message: ', message);
window.DUMP('sendStkResponse -- # response = ', response);
getIcc(message.iccId).sendStkResponse(message.command, response);
}
/**
* Handle ICC Messages
*/
function handleSTKMessage(message) {
window.DUMP('STK Proactive Message:', message);
stkCancelGoBack();
reopenSettings();
switch (message.command.typeOfCommand) {
case iccManager.STK_CMD_SELECT_ITEM:
addCloseNotificationsEvents(message);
updateSelection(message);
Settings.currentPanel = '#icc';
_backHandler = stkResGoBack.bind(null, message);
break;
default:
window.DUMP('STK Message not managed... response OK');
responseSTKCommand(message, {
resultCode: iccManager.STK_RESULT_OK
});
}
}
/**
* Navigate through all available STK applications
*/
function updateMenu(menu) {
window.DUMP('Showing STK main menu: ', menu);
stkOpenAppName = null;
stkCancelGoBack();
clearList();
if (!menu || !menu.entries || !menu.entries.items ||
(menu.entries.items.length == 1 && menu.entries.items[0] === null)) {
return;
}
window.DUMP('STK Main App Menu title: ' + menu.entries.title);
window.DUMP('STK Main App Menu default item: ' +
menu.entries.defaultItem);
showTitle({raw: menu.entries.title});
menu.entries.items.forEach(function(menuItem, index) {
window.DUMP('STK Main App Menu item: ' + menuItem.text + ' # ' +
menuItem.identifier);
var nextActionString = getNextActionString(menu.entries.nextActionList,
index);
// Get the first icon if exists
var icon = STKHelper.getFirstIconRawData(menuItem);
if (icon) {
iccStkList.dataset.customIcon = true;
}
window.DUMP('STK NEXTACTION: ' + nextActionString);
iccStkList.appendChild(buildMenuEntry({
id: 'stk-menuitem-' + menuItem.identifier,
icon: icon,
text: {raw: menuItem.text},
nai: nextActionString,
onclick: onMainMenuItemClick,
attributes: [
['stk-menu-item-identifier', menuItem.identifier],
['stk-menu-item-iccId', menu.iccId]
]
}));
});
// Optional Help menu
if (menu.entries.isHelpAvailable) {
iccStkList.appendChild(buildMenuEntry({
id: 'stk-helpmenuitem',
text: 'operatorServices-helpmenu',
onclick: function __onHelpClick__(event) {
showHelpMenu(menu, event);
},
attributes: []
}));
}
getIcc(menu.iccId).onstksessionend = function handleSTKSessionEnd(event) {
updateMenu(menu);
Settings.currentPanel = '#icc';
};
_backHandler = function backToRootPanel() {
Settings.currentPanel = '#root';
};
}
function onMainMenuItemClick(event) {
var iccId = event.target.getAttribute('stk-menu-item-iccId');
var identifier = event.target.getAttribute('stk-menu-item-identifier');
window.DUMP('sendStkMenuSelection: ', identifier);
getIcc(iccId).sendStkMenuSelection(identifier, false);
stkLastSelectedText = event.target.textContent;
stkOpenAppName = stkLastSelectedText;
}
function showHelpMenu(menu, event) {
window.DUMP('Showing STK help menu');
stkOpenAppName = null;
clearList();
showTitle('operatorServices-helpmenu');
menu.entries.items.forEach(function(menuItem) {
window.DUMP('STK Main App Help item: ' + menuItem.text + ' # ' +
menuItem.identifier);
var icon = STKHelper.getFirstIconRawData(menuItem);
if (icon) {
iccStkList.dataset.customIcon = true;
}
iccStkList.appendChild(buildMenuEntry({
id: 'stk-helpitem-' + menuItem.identifier,
text: {raw: menuItem.text},
icon: icon,
onclick: onMainMenuHelpItemClick,
attributes: [
['stk-help-item-identifier', menuItem.identifier],
['stk-menu-item-iccId', menu.iccId]
]
}));
});
_backHandler = updateMenu.bind(null, menu);
}
function onMainMenuHelpItemClick(event) {
var iccId = event.target.getAttribute('stk-menu-item-iccId');
var identifier = event.target.getAttribute('stk-help-item-identifier');
window.DUMP('sendStkHelpMenuSelection: ', identifier);
getIcc(iccId).sendStkMenuSelection(identifier, true);
stkLastSelectedText = event.target.textContent;
stkOpenAppName = stkLastSelectedText;
}
/**
* Navigate through the STK application options
*/
function updateSelection(message) {
var menu = message.command.options;
window.DUMP('Showing STK menu');
clearList();
window.DUMP('STK App Menu title: ' + menu.title);
window.DUMP('STK App Menu default item: ' + menu.defaultItem);
showTitle({raw: menu.title});
menu.items.forEach(function(menuItem, index) {
window.DUMP('STK App Menu item: ' + menuItem.text + ' # ' +
menuItem.identifier);
var nextActionString = getNextActionString(menu.nextActionList, index);
window.DUMP('STK NEXTACTION: ' + nextActionString);
var icon = STKHelper.getFirstIconRawData(menuItem);
if (icon) {
iccStkList.dataset.customIcon = true;
}
iccStkList.appendChild(buildMenuEntry({
id: 'stk-menuitem-' + menuItem.identifier,
text: {raw: menuItem.text},
icon: icon,
nai: nextActionString,
onclick: function onSelectOptionClick(event) {
document.removeEventListener('visibilitychange',
_visibilityChangeHandler, false);
onSelectOption(message, event);
},
attributes: [['stk-select-option-identifier', menuItem.identifier]]
}));
});
// Optional Help menu
if (menu.isHelpAvailable) {
iccStkList.appendChild(buildMenuEntry({
id: 'stk-helpmenuitem',
text: 'operatorServices-helpmenu',
onclick: function __onHelpClick__(event) {
showHelpSelection(message, event);
},
attributes: []
}));
}
stkResNoResponse(message);
}
function onSelectOption(message, event) {
var identifier =
event.target.getAttribute('stk-select-option-identifier');
responseSTKCommand(message, {
resultCode: iccManager.STK_RESULT_OK,
itemIdentifier: identifier
});
stkLastSelectedText = event.target.textContent;
}
function showHelpSelection(message, event) {
var menu = message.command.options;
window.DUMP('Showing STK help menu');
stkOpenAppName = null;
clearList();
showTitle('operatorServices-helpmenu');
menu.items.forEach(function(menuItem) {
window.DUMP('STK Main App Help item: ' + menuItem.text + ' # ' +
menuItem.identifier);
var icon = STKHelper.getFirstIconRawData(menuItem);
if (icon) {
iccStkList.dataset.customIcon = true;
}
iccStkList.appendChild(buildMenuEntry({
id: 'stk-helpitem-' + menuItem.identifier,
text: {raw: menuItem.text},
icon: icon,
onclick: function onSelectOptionClick(event) {
onSelectionHelpItemClick(message, event);
},
attributes: [
['stk-help-item-identifier', menuItem.identifier],
['stk-menu-item-iccId', menu.iccId]
]
}));
});
_backHandler = updateSelection.bind(null, message);
}
function onSelectionHelpItemClick(message, event) {
var identifier = event.target.getAttribute('stk-help-item-identifier');
window.DUMP('sendStkHelpMenuSelection: ', identifier);
responseSTKCommand(message, {
resultCode: iccManager.STK_RESULT_HELP_INFO_REQUIRED,
itemIdentifier: identifier
});
stkLastSelectedText = event.target.textContent;
}
/**
* Auxiliar methods
*/
function showTitle(titleL10n) {
// If the application is automatically opened (no come from main menu)
if (!stkOpenAppName) {
stkOpenAppName = titleL10n;
}
localizeElement(iccStkHeader, stkOpenAppName);
// Show section
if (stkOpenAppName != titleL10n) {
localizeElement(iccStkSubheader, titleL10n);
iccStkSubheader.parentNode.classList.remove('hiddenheader');
iccStkSubheader.classList.remove('hidden');
} else {
localizeElement(iccStkSubheader, {raw: ''});
iccStkSubheader.parentNode.classList.add('hiddenheader');
iccStkSubheader.classList.add('hidden');
}
}
function clearList() {
while (iccStkList.hasChildNodes()) {
iccStkList.removeChild(iccStkList.lastChild);
}
}
function buildMenuEntry(entry) {
var li = document.createElement('li');
if (entry.nai) {
var small = document.createElement('small');
localizeElement(small, entry.nai);
li.appendChild(small);
}
if (entry.icon) {
var iconContainer = document.createElement('span');
iconContainer.appendChild(STKHelper.getIconCanvas(entry.icon));
li.appendChild(iconContainer);
}
var a = document.createElement('a');
a.id = entry.id;
entry.attributes.forEach(function attrIterator(attr) {
a.setAttribute(attr[0], attr[1]);
});
localizeElement(a, entry.text);
a.onclick = entry.onclick;
a.href = '#icc';
li.appendChild(a);
return li;
}
})();
window.dispatchEvent(new CustomEvent('iccPageLoaded', {
detail: {}
}));
});