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,619 @@
/* global ConfigManager, CostControl, debug, Common, asyncStorage, Formatting,
NotificationHelper, _, MozActivity, NetworkUsageAlarm, LazyLoader,
SimManager, IACManager, DEBUGGING
*/
/*jshint -W020 */
/* The previous directive,ignore the "Read only" errors, that are produced when
redirect global objects (Common and Costcontrol) to parent versions to avoid
conflicts.
*/
(function() {
'use strict';
function inStandAloneMode() {
return window.parent.location.pathname === '/message_handler.html';
}
// Redirect global objects to parent versions to avoid conflicts
if (!inStandAloneMode()) {
ConfigManager = window.parent.ConfigManager;
CostControl = window.parent.CostControl;
SimManager = window.parent.SimManager;
}
// XXX: This case implies that message handler triggered by system
// (inStandAlone check) has replaced CC application (history's length check).
//
// This only occurs when the system (window manager) has detected there is
// already an iframe for CC application, it is in background and it is
// not the message handler. So, as the CC index.html uses the this file
// inside an iframe (no standalone mode), all the messages should be attended
// so we can conclude **there is nothing to do**.
if (inStandAloneMode() && window.history.length > 1) {
debug('Nothing to do in message handler, returning to app...');
window.history.back();
}
function inApplicationMode() {
return window.parent.location.pathname === '/index.html';
}
// Close if in standalone mode
var closing;
function closeIfProceeds() {
debug('Checking for closing...');
if (inStandAloneMode()) {
closing = Common.closeApplication();
}
}
// XXX: Remove from here when this is solved
// https://bugzilla.mozilla.org/show_bug.cgi?id=800431
function addAlarmTimeout(type, delay) {
var date = new Date();
date.setTime(date.getTime() + delay);
var request = navigator.mozAlarms.add(date, 'ignoreTimezone', {type: type});
return request;
}
window.addAlarmTimeout = addAlarmTimeout;
// XXX: Remove from here when this is solved
// https://bugzilla.mozilla.org/show_bug.cgi?id=800431
function setNextReset(when, callback) {
// XXX: This is not part of configuration by SIM so we bypass ConfigManager
asyncStorage.getItem('nextResetAlarm', function(id) {
// There is already an alarm, remove it
debug('Current nextResetAlarm', id + '.', id ? 'Removing.' : '');
if (id) {
navigator.mozAlarms.remove(id);
}
// If no when, disable alarms passing null
if (!when) {
debug('Automatic reset disabled');
updateResetAttributes(null, null, callback);
return;
}
// If the alarm is in the past, fake it was launched
if (when.getTime() < Date.now()) {
debug('Faking a past reset alarm');
_onAlarm({ data: { type: 'nextReset' } });
if (callback) {
setTimeout(callback);
}
return;
}
// If when is provided, request an alarm an set the new values
var alarms = navigator.mozAlarms;
var request = alarms.add(when, 'ignoreTimezone', {type: 'nextReset' });
request.onsuccess = function _onSuccess() {
debug('Setting nextResetAlarm', request.result, 'to', when);
updateResetAttributes(request.result, when, callback);
};
});
}
window.setNextReset = setNextReset;
function getTopUpTimeout(callback) {
SimManager.requestDataSimIcc(function(dataSimIcc) {
ConfigManager.requestSettings(dataSimIcc.iccId,
function _onSettings(settings) {
var request = navigator.mozAlarms.getAll();
request.onsuccess = function(e) {
var alarms = e.target.result;
var length = alarms.length;
if (!length) {
callback(null);
return;
}
var refId = settings.waitingForTopUp;
var index = 0, alarm, found = false;
while (index < length && !found) {
alarm = alarms[index];
found = (alarm.id === refId);
index++;
}
if (found) {
debug('TopUp timeout found:', alarm.date);
callback(alarm.date);
} else {
callback(null);
}
};
});
});
}
window.getTopUpTimeout = getTopUpTimeout;
function addNetworkUsageAlarm(dataInterface, dataLimit, onsuccess, onerror) {
onsuccess = onsuccess || function() {};
onerror = onerror || function() {};
NetworkUsageAlarm.updateAlarm(dataInterface, dataLimit, onsuccess, onerror);
}
window.addNetworkUsageAlarm = addNetworkUsageAlarm;
// Update the nextResetAlarm and nextReset values and request for
// synchronization.
function updateResetAttributes(alarmId, date, callback) {
asyncStorage.setItem('nextResetAlarm', alarmId, function _updateOption() {
ConfigManager.setOption({ nextReset: date }, function _sync() {
localStorage.sync = 'nextReset#' + Math.random();
if (callback) {
callback();
}
});
});
}
function sendIncorrectTopUpNotification(callback) {
var title = 'topup-incorrectcode-title2';
var message = 'topup-incorrectcode-message3';
sendNotification('topUpError', title, message);
if (callback) {
callback();
}
}
function sendBalanceThresholdNotification(remaining, settings, callback) {
debug('Low limit already notified:', settings.lowLimitNotified);
debug('Zero balance already notified:', settings.lowLimitNotified);
// Zero reached notification
var type;
if (remaining.balance === 0 && !settings.zeroBalanceNotified) {
type = 'zeroBalance';
// There is a limit an we are below that limit and we did not notified yet
} else if (settings.lowLimit &&
remaining.balance < settings.lowLimitThreshold &&
!settings.lowLimitNotified) {
type = 'lowBalance';
// No need for notification
} else if (callback) {
setTimeout(callback);
return;
}
debug('Notification type:', type);
// Get l10n for remaining balance
var remainingBalance = _('currency', {
currency: remaining.currency,
value: remaining.balance
});
// Compose notification and send it
var title = 'low-balance-notification-title';
var message = {
id: 'low-balance-notification-text',
args: { remaining: remainingBalance }
};
if (type === 'zeroBalance') {
title = 'usage';
message = 'zero-balance-message';
}
sendNotification(type, title, message);
// Finally mark the notification as sent
var update = {};
var notified = (type === 'lowBalance') ? 'lowLimitNotified' :
'zeroBalanceNotified';
update[notified] = true;
ConfigManager.setOption(update, callback);
}
window.sendBalanceThresholdNotification = sendBalanceThresholdNotification;
// When receiving an alarm, differenciate by type and act
function _onAlarm(alarm) {
clearTimeout(closing);
SimManager.requestDataSimIcc(function(dataSimIcc) {
function _launchNextReset() {
ConfigManager.requestSettings(dataSimIcc.iccId,
function _onSettings(settings) {
Common.resetAll(function updateNextResetAndClose() {
Common.updateNextReset(settings.trackingPeriod, settings.resetTime,
closeIfProceeds);
});
});
}
switch (alarm.data.type) {
case 'balanceTimeout':
ConfigManager.requestSettings(dataSimIcc.iccId,
function _onSettings(settings) {
settings.errors.BALANCE_TIMEOUT = true;
ConfigManager.setOption(
{ 'errors': settings.errors, 'waitingForBalance': null },
function _onBalanceTimeout() {
debug('Timeout for balance');
debug('Trying to synchronize!');
localStorage.sync = 'errors#' + Math.random();
closeIfProceeds();
}
);
});
break;
case 'topupTimeout':
ConfigManager.requestSettings(dataSimIcc.iccId,
function _onSettings(settings) {
settings.errors.TOPUP_TIMEOUT = true;
ConfigManager.setOption(
{ 'errors': settings.errors, 'waitingForTopUp': null },
function _onBalanceTimeout() {
debug('Timeout for topup');
debug('Trying to synchronize!');
localStorage.sync = 'errors#' + Math.random();
closeIfProceeds();
}
);
});
break;
case 'nextReset':
if (!Common.allNetworkInterfaceLoaded) {
Common.loadNetworkInterfaces(_launchNextReset);
} else {
_launchNextReset();
}
break;
}
});
}
function getNofificationAction(type, app) {
var activityName, action;
var noop = function() {};
switch (type) {
case 'lowBalance':
case 'zeroBalance':
activityName = 'costcontrol/balance';
action = function() {
if (window.parent.BalanceTab) {
window.parent.CostControlApp.showBalanceTab();
}
};
break;
case 'topUpError' :
activityName = 'costcontrol/balance';
action = function() {
if (window.parent.BalanceTab) {
window.parent.BalanceTab.topUpWithCode(true);
}
};
break;
default:
activityName = 'costcontrol/data_usage';
action = function() {
if (window.parent.CostControlApp) {
window.parent.CostControlApp.showDataUsageTab();
}
};
break;
}
if (!inStandAloneMode()) {
return function() {
if (inApplicationMode()) {
app.launch();
action && action();
} else {
type = new MozActivity({name: activityName});
}
};
}
return noop;
}
function sendNotification(notificationType, title, message) {
navigator.mozApps.getSelf().onsuccess = function _onAppReady(evt) {
var app = evt.target.result;
var iconURL = NotificationHelper.getIconURI(app);
var navigate = getNofificationAction(notificationType, app);
NotificationHelper.send(title, {
'bodyL10n': message,
'icon': iconURL,
'data': notificationType
}).then(function(notification) {
notification.addEventListener('click', function() {
notification.close();
navigate();
});
});
};
}
function _onNetworkAlarm(alarm) {
clearTimeout(closing);
navigator.mozApps.getSelf().onsuccess = function _onAppReady(evt) {
SimManager.requestDataSimIcc(function(dataSimIcc) {
ConfigManager.requestSettings(dataSimIcc.iccId,
function _onSettings(settings) {
var limit = Common.getDataLimit(settings);
var limitText = Formatting.formatData(Formatting.smartRound(limit));
var title = {
id: 'data-limit-notification-title2',
args: { limit: limitText }
};
var message = 'data-limit-notification-text2';
sendNotification('dataUsage', title, message);
ConfigManager.setOption({ 'dataUsageNotified': true },
closeIfProceeds);
return;
});
});
};
}
function disableSilentModeFor(type, configuration) {
LazyLoader.load('js/iac_manager.js', function() {
IACManager.init(configuration);
IACManager.broadcastEndOfSMSQuery(type).then(function(msg) {
debug('After broadcasting for ' + type + ' (disabling)');
});
});
}
// Register in standalone or for application
var costcontrol;
function _getCCInstance() {
CostControl.getInstance(function _onCostControl(ccontrol) {
costcontrol = ccontrol;
if (inStandAloneMode() || inApplicationMode()) {
debug('Installing handlers');
// When receiving an SMS, recognize and parse
navigator.mozSetMessageHandler('sms-received', function _onSMS(sms) {
clearTimeout(closing);
ConfigManager.requestAll(function _onInfo(configuration, settings) {
var isBalanceResponse =
configuration.balance &&
Array.isArray(configuration.balance.senders) &&
configuration.balance.senders.indexOf(sms.sender) > -1;
var isTopupResponse =
configuration.topup &&
Array.isArray(configuration.topup.senders) &&
configuration.topup.senders.indexOf(sms.sender) > -1;
// Non expected SMS
if (!isBalanceResponse && !isTopupResponse) {
closeIfProceeds();
return;
}
// Parse the message
debug('Parsing received SMS');
var isBalance, isConfirmation, isError;
isBalance = isConfirmation = isError = false;
debug('Trying to recognize balance SMS');
var description = new RegExp(configuration.balance.regexp);
var balanceData = sms.body.match(description);
if (!balanceData) {
debug('Trying to recognize zero balance SMS');
// Some carriers use another response messages format
// for zero balance
var zeroDescription = configuration.balance.zero_regexp ?
new RegExp(configuration.balance.zero_regexp) : null;
if (zeroDescription && zeroDescription.test(sms.body)) {
balanceData = ['0.00', '0', '0'];
}
}
isBalance = !!balanceData;
if (!isBalance || balanceData.length < 2) {
console.warn('Impossible to parse balance message.');
debug('Trying to recognize TopUp confirmation SMS');
description = new RegExp(configuration.topup.confirmation_regexp);
isConfirmation = !!sms.body.match(description);
if (!isConfirmation) {
console.warn('Impossible to parse TopUp confirmation message.');
debug('Trying to recognize TopUp error SMS');
description =
new RegExp(configuration.topup.incorrect_code_regexp);
isError = !!sms.body.match(description);
if (!isError) {
console.warn('Impossible to parse TopUp confirmation msg.');
}
}
}
if (!isBalance && !isConfirmation && !isError) {
closeIfProceeds();
return;
}
if (!DEBUGGING &&
(isBalance && (settings.waitingForBalance !== null)) ||
(isConfirmation && (settings.waitingForTopUp !== null))) {
var mobileMessageManager = window.navigator.mozMobileMessage;
mobileMessageManager.delete(sms.id);
}
if (isBalance) {
// Compose new balance
var integer = balanceData[1].replace(/[^0-9]/g, '');
var decimal = balanceData[2] || '0';
var newBalance = {
balance: parseFloat(integer + '.' + decimal),
currency: configuration.credit.currency,
timestamp: new Date()
};
if (settings.waitingForBalance !== null) {
// Remove the timeout
navigator.mozAlarms.remove(settings.waitingForBalance);
debug('Balance timeout:', settings.waitingForBalance,
'removed');
disableSilentModeFor('balance', configuration);
}
// Store new balance and sync
ConfigManager.setOption(
{ 'lastBalance': newBalance, 'waitingForBalance': null },
function _onSet() {
debug('Balance up to date and stored');
debug('Trying to synchronize!');
localStorage.sync = 'lastBalance#' + Math.random();
sendBalanceThresholdNotification(newBalance, settings,
closeIfProceeds);
}
);
} else if (isConfirmation) {
if (settings.waitingForTopUp !== null) {
// Store SUCCESS for TopIp and sync
navigator.mozAlarms.remove(settings.waitingForTopUp);
debug('TopUp timeout:', settings.waitingForTopUp, 'removed');
disableSilentModeFor('topup', configuration);
}
ConfigManager.setOption(
{
'waitingForTopUp': null,
'lowLimitNotified': false,
'zeroBalanceNotified': false
},
function _onSet() {
debug('TopUp confirmed!');
debug('Trying to synchronize!');
localStorage.sync = 'waitingForTopUp#' + Math.random();
closeIfProceeds();
}
);
} else if (isError) {
// Store ERROR for TopUp and sync
settings.errors.INCORRECT_TOPUP_CODE = true;
navigator.mozAlarms.remove(settings.waitingForTopUp);
debug('TopUp timeout: ', settings.waitingForTopUp, 'removed');
ConfigManager.setOption(
{
'errors': settings.errors,
'waitingForTopUp': null,
'lowLimitNotified': false,
'zeroBalanceNotified': false
},
function _onSet() {
debug('Balance up to date and stored');
debug('Trying to synchronize!');
localStorage.sync = 'errors#' + Math.random();
sendIncorrectTopUpNotification(closeIfProceeds);
}
);
}
});
});
navigator.mozSetMessageHandler('networkstats-alarm', _onNetworkAlarm);
navigator.mozSetMessageHandler('alarm', _onAlarm);
// Count a new SMS
navigator.mozSetMessageHandler('sms-sent', function _onSent(sms) {
clearTimeout(closing);
debug('SMS sent!');
var configuration = ConfigManager.configuration;
var mode = ConfigManager.getApplicationMode();
if (mode === 'PREPAID' &&
!costcontrol.isBalanceRequestSMS(sms, configuration)) {
costcontrol.request({ type: 'balance' });
}
if (mode === 'PREPAID' &&
costcontrol.isBalanceRequestSMS(sms, configuration)) {
closeIfProceeds();
} else {
var mobileMessageManager = window.navigator.mozMobileMessage;
var infoRequest =
mobileMessageManager.getSegmentInfoForText(sms.body);
infoRequest.onsuccess = function onInfo(evt) {
var realCount, smsInfo = evt.target.result;
if (!smsInfo || !smsInfo.segments) {
console.error(
'Invalid getSegmentInfoForText() result. Counting 1 segment');
realCount = 1;
} else {
realCount = smsInfo.segments;
}
updateSMSCount(realCount);
};
infoRequest.onerror = function onError() {
console.error('Can not retrieve segment info for body ' +
sms.body);
updateSMSCount(1);
};
}
function updateSMSCount(count) {
SimManager.requestDataSimIcc(function(dataSimIcc) {
ConfigManager.requestSettings(dataSimIcc.iccId,
function _onSettings(settings) {
settings.lastTelephonyActivity.timestamp = new Date();
settings.lastTelephonyActivity.smscount += count;
ConfigManager.setOption({
lastTelephonyActivity: settings.lastTelephonyActivity
}, function _sync() {
localStorage.sync = 'lastTelephonyActivity#' + Math.random();
closeIfProceeds();
});
});
});
}
});
// When a call ends
navigator.mozSetMessageHandler('telephony-call-ended',
function _onCall(tcall) {
clearTimeout(closing);
if (tcall.direction !== 'outgoing') {
closeIfProceeds();
return;
}
debug('Outgoing call finished!');
SimManager.requestDataSimIcc(function(dataSimIcc) {
ConfigManager.requestSettings(dataSimIcc.iccId,
function _onSettings(settings) {
var mode = ConfigManager.getApplicationMode();
if (mode === 'PREPAID') {
costcontrol.request({ type: 'balance' });
}
settings.lastTelephonyActivity.timestamp = new Date();
settings.lastTelephonyActivity.calltime += tcall.duration;
ConfigManager.setOption({
lastTelephonyActivity: settings.lastTelephonyActivity
}, function _sync() {
localStorage.sync = 'lastTelephonyActivity#' + Math.random();
closeIfProceeds();
});
});
});
}
);
}
// Notify message handler is ready
var readyEvent = new CustomEvent('messagehandlerready');
window.parent.dispatchEvent(readyEvent);
});
}
_getCCInstance();
}());