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:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
428
gaia/shared/resources/apn/query.js
Executable file
428
gaia/shared/resources/apn/query.js
Executable file
|
|
@ -0,0 +1,428 @@
|
|||
'use strict';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function onload() {
|
||||
var DEBUG = false;
|
||||
|
||||
var OPERATOR_VARIANT_FILE = '../apn.json';
|
||||
var GNOME_DB_FILE = 'service_providers.xml';
|
||||
var ANDROID_DB_FILE = 'apns_conf.xml';
|
||||
var LOCAL_ANDROID_DB_FILE = 'apns_conf_local.xml';
|
||||
var OPERATOR_VARIANT_DB_FILE = 'operator_variant.xml';
|
||||
|
||||
var gGnomeDB = null;
|
||||
var gAndroidDB = null;
|
||||
var gOperatorVariantDB = null;
|
||||
|
||||
|
||||
/**
|
||||
* XML helpers: load & query XML databases
|
||||
*/
|
||||
|
||||
function loadXML(url) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', url, false);
|
||||
xhr.send();
|
||||
return xhr.responseXML;
|
||||
}
|
||||
|
||||
function queryXML(xmlDocument, query) {
|
||||
var xpe = new XPathEvaluator();
|
||||
var nsResolver = xpe.createNSResolver(xmlDocument);
|
||||
return xpe.evaluate(query, xmlDocument, nsResolver, 0, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Merge the Android and Gnome APN and the Operator Variant databases
|
||||
*/
|
||||
|
||||
function queryAndroidDB(mcc, mnc) {
|
||||
var query = '//apn';
|
||||
if (mcc) {
|
||||
query += '[@mcc=' + mcc + ']'; // Mobile Country Code
|
||||
}
|
||||
if (mnc) {
|
||||
query += '[@mnc=' + mnc + ']'; // Mobile Network Code
|
||||
}
|
||||
|
||||
var result = queryXML(gAndroidDB, query);
|
||||
var res = result.iterateNext();
|
||||
var found = [];
|
||||
|
||||
while (res) { // turn each resulting XML element into a JS object
|
||||
var apn = {};
|
||||
for (var i = 0; i < res.attributes.length; i++) {
|
||||
var name = res.attributes[i].name;
|
||||
var value = res.attributes[i].value;
|
||||
if (name == 'type') { // array of comma-separated values
|
||||
apn.type = value.split(',');
|
||||
} else { // all other attributes are plain strings
|
||||
apn[name] = value;
|
||||
}
|
||||
}
|
||||
found.push(apn);
|
||||
res = result.iterateNext();
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
function queryGnomeDB(mcc, mnc, setting) {
|
||||
var query = '//gsm[network-id' + '[@mcc=' + mcc + '][@mnc=' + mnc + ']' +
|
||||
']/' + setting;
|
||||
var result = queryXML(gGnomeDB, query);
|
||||
var node = result.iterateNext();
|
||||
return node ? node.textContent : '';
|
||||
}
|
||||
|
||||
function queryOperatorVariantDB(mcc, mnc) {
|
||||
var query = '//operator' + '[@mcc=' + mcc + '][@mnc=' + mnc + ']';
|
||||
var result = queryXML(gOperatorVariantDB, query);
|
||||
var res = result.iterateNext();
|
||||
var found = [];
|
||||
|
||||
while (res) { // turn each resulting XML element into a JS object
|
||||
var operatorSettings = {};
|
||||
for (var i = 0; i < res.attributes.length; i++) {
|
||||
var name = res.attributes[i].name;
|
||||
var value = res.attributes[i].value;
|
||||
operatorSettings[name] = value;
|
||||
}
|
||||
found.push(operatorSettings);
|
||||
res = result.iterateNext();
|
||||
}
|
||||
|
||||
return found.length ? found[0] : null;
|
||||
}
|
||||
|
||||
function padLeft(num, length) {
|
||||
var r = String(num);
|
||||
while (r.length < length) {
|
||||
r = '0' + r;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
function mergeDBs() {
|
||||
var apn = {};
|
||||
|
||||
for (var mcc = 1; mcc < 999; mcc++) {
|
||||
var country = {};
|
||||
|
||||
var _mcc = padLeft(mcc, 3);
|
||||
|
||||
var result = queryAndroidDB(_mcc);
|
||||
|
||||
if (result && result.length) {
|
||||
result.sort();
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
/* jshint loopfunc: true */
|
||||
var mnc = result[i].mnc;
|
||||
|
||||
var operatorVariantSettings = {};
|
||||
var voicemail = queryGnomeDB(_mcc, mnc, 'voicemail');
|
||||
if (voicemail) {
|
||||
operatorVariantSettings.voicemail = voicemail;
|
||||
if (DEBUG) {
|
||||
console.log(operatorVariantSettings.voicemail + ': ' + voicemail);
|
||||
}
|
||||
}
|
||||
var otherSettings = queryOperatorVariantDB(_mcc, mnc);
|
||||
if (otherSettings) {
|
||||
if (DEBUG) {
|
||||
console.log('Other operator settings: ' +
|
||||
JSON.stringify(otherSettings));
|
||||
}
|
||||
if (!operatorVariantSettings.voicemail) {
|
||||
voicemail = otherSettings.voicemail;
|
||||
if (voicemail) {
|
||||
operatorVariantSettings.voicemail = voicemail;
|
||||
}
|
||||
}
|
||||
|
||||
var enableStrict7BitEncodingForSms =
|
||||
otherSettings.enableStrict7BitEncodingForSms;
|
||||
if (enableStrict7BitEncodingForSms) {
|
||||
operatorVariantSettings.enableStrict7BitEncodingForSms =
|
||||
enableStrict7BitEncodingForSms == 'true';
|
||||
}
|
||||
var cellBroadcastSearchList =
|
||||
otherSettings.cellBroadcastSearchList;
|
||||
if (cellBroadcastSearchList) {
|
||||
var searchListObj = {};
|
||||
var lists = cellBroadcastSearchList.split('|');
|
||||
lists.forEach(function(list) {
|
||||
var parts = list.split(':');
|
||||
searchListObj[parts[0]] = parts[1];
|
||||
});
|
||||
operatorVariantSettings.cellBroadcastSearchList = searchListObj;
|
||||
}
|
||||
|
||||
var operatorSizeLimitation =
|
||||
otherSettings.operatorSizeLimitation;
|
||||
if (operatorSizeLimitation) {
|
||||
operatorVariantSettings.operatorSizeLimitation =
|
||||
+operatorSizeLimitation;
|
||||
}
|
||||
var skipProxy = otherSettings.skipProxy;
|
||||
if (skipProxy == 'true') {
|
||||
var skipProxyFor = otherSettings.skipProxyFor;
|
||||
if (skipProxyFor) {
|
||||
if (skipProxyFor.indexOf(result[i].carrier) != -1) {
|
||||
if (DEBUG) {
|
||||
console.log('Skip proxy setting for: ' + result[i].carrier);
|
||||
}
|
||||
result[i].proxy = result[i].port = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete(result[i].mcc);
|
||||
delete(result[i].mnc);
|
||||
if (country[mnc]) {
|
||||
if (DEBUG) { // warn about the duplicate (mcc, mnc) tuple
|
||||
if (country[mnc].length == 1) {
|
||||
console.log('duplicate mcc/mnc: ' + _mcc + '/' + mnc);
|
||||
console.log(' - ' + country[mnc][0].carrier);
|
||||
}
|
||||
console.log(' - ' + result[i].carrier);
|
||||
}
|
||||
country[mnc].push(result[i]);
|
||||
} else {
|
||||
country[mnc] = [result[i]];
|
||||
if (voicemail || otherSettings) {
|
||||
operatorVariantSettings.type = [];
|
||||
operatorVariantSettings.type.push('operatorvariant');
|
||||
country[mnc].push(operatorVariantSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
apn[_mcc] = country;
|
||||
}
|
||||
}
|
||||
|
||||
return apn;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* User Interface
|
||||
*/
|
||||
|
||||
var gAPN;
|
||||
var apnPrefNames = {
|
||||
'default': {
|
||||
'ril.data.carrier': 'carrier',
|
||||
'ril.data.apn': 'apn',
|
||||
'ril.data.user': 'user',
|
||||
'ril.data.passwd': 'password',
|
||||
'ril.data.httpProxyHost': 'proxy',
|
||||
'ril.data.httpProxyPort': 'port',
|
||||
'ril.data.authtype': 'authtype',
|
||||
'ril.data.mtu': 'mtu'
|
||||
},
|
||||
'supl': {
|
||||
'ril.supl.carrier': 'carrier',
|
||||
'ril.supl.apn': 'apn',
|
||||
'ril.supl.user': 'user',
|
||||
'ril.supl.passwd': 'password',
|
||||
'ril.supl.httpProxyHost': 'proxy',
|
||||
'ril.supl.httpProxyPort': 'port',
|
||||
'ril.supl.authtype': 'authtype',
|
||||
'ril.supl.mtu': 'mtu'
|
||||
},
|
||||
'mms': {
|
||||
'ril.mms.carrier': 'carrier',
|
||||
'ril.mms.apn': 'apn',
|
||||
'ril.mms.user': 'user',
|
||||
'ril.mms.passwd': 'password',
|
||||
'ril.mms.httpProxyHost': 'proxy',
|
||||
'ril.mms.httpProxyPort': 'port',
|
||||
'ril.mms.mmsc': 'mmsc',
|
||||
'ril.mms.mmsproxy': 'mmsproxy',
|
||||
'ril.mms.mmsport': 'mmsport',
|
||||
'ril.mms.authtype': 'authtype',
|
||||
'ril.mms.mtu': 'mtu'
|
||||
},
|
||||
'dun': {
|
||||
'ril.dun.carrier': 'carrier',
|
||||
'ril.dun.apn': 'apn',
|
||||
'ril.dun.user': 'user',
|
||||
'ril.dun.passwd': 'password',
|
||||
'ril.dun.httpProxyHost': 'proxy',
|
||||
'ril.dun.httpProxyPort': 'port',
|
||||
'ril.dun.authtype': 'authtype',
|
||||
'ril.dun.mtu': 'mtu'
|
||||
},
|
||||
'ims': {
|
||||
'ril.ims.carrier': 'carrier',
|
||||
'ril.ims.apn': 'apn',
|
||||
'ril.ims.user': 'user',
|
||||
'ril.ims.passwd': 'password',
|
||||
'ril.ims.httpProxyHost': 'proxy',
|
||||
'ril.ims.httpProxyPort': 'port',
|
||||
'ril.ims.authtype': 'authtype',
|
||||
'ril.ims.mtu': 'mtu'
|
||||
},
|
||||
'fota': {
|
||||
'ril.fota.carrier': 'carrier',
|
||||
'ril.fota.apn': 'apn',
|
||||
'ril.fota.user': 'user',
|
||||
'ril.fota.passwd': 'password',
|
||||
'ril.fota.httpProxyHost': 'proxy',
|
||||
'ril.fota.httpProxyPort': 'port',
|
||||
'ril.fota.authtype': 'authtype',
|
||||
'ril.fota.mtu': 'mtu'
|
||||
},
|
||||
'operatorvariant': {
|
||||
'ril.iccInfo.mbdn': 'voicemail',
|
||||
'ril.sms.strict7BitEncoding.enabled': 'enableStrict7BitEncodingForSms',
|
||||
'ril.cellbroadcast.searchlist': 'cellBroadcastSearchList',
|
||||
'dom.mms.operatorSizeLimitation': 'operatorSizeLimitation'
|
||||
}
|
||||
};
|
||||
|
||||
var booleanPrefNames = [
|
||||
'ril.sms.strict7BitEncoding.enabled'
|
||||
];
|
||||
|
||||
function loadDB(output, callback) {
|
||||
output.textContent = '\n loading database...';
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', OPERATOR_VARIANT_FILE, true);
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState == 4) {
|
||||
if (xhr.status == 200 || xhr.status === 0) {
|
||||
// the JSON database is already available -- we don't use
|
||||
// xhr.responseType = 'json' to be compatible with Chrome... sigh.
|
||||
gAPN = JSON.parse(xhr.responseText);
|
||||
} else {
|
||||
// the JSON database is not available, merge the three XML databases
|
||||
output.textContent = '\n merging databases, this takes a while...';
|
||||
gAndroidDB = loadXML(ANDROID_DB_FILE);
|
||||
// First merge the local DB
|
||||
var localAndroidDB = loadXML(LOCAL_ANDROID_DB_FILE);
|
||||
var localApns =
|
||||
localAndroidDB.documentElement.querySelectorAll('apn');
|
||||
var androidApns;
|
||||
var androidApn;
|
||||
for (var localApn of localApns) {
|
||||
if (localApn.getAttribute('overwrite') &&
|
||||
localApn.getAttribute('carrier_name')) {
|
||||
var pattern = '[carrier="' +
|
||||
localApn.getAttribute('carrier_name') + '"]';
|
||||
androidApns =
|
||||
gAndroidDB.documentElement.querySelectorAll(pattern);
|
||||
var matchFound = false;
|
||||
for (androidApn of androidApns) {
|
||||
if (androidApn &&
|
||||
androidApn.getAttribute('carrier') ===
|
||||
localApn.getAttribute('carrier_name')) {
|
||||
|
||||
if (DEBUG) {
|
||||
console.log('- replace "' +
|
||||
androidApn.getAttribute('apn') +
|
||||
'" to "' + localApn.getAttribute('apn') +
|
||||
'"');
|
||||
}
|
||||
localApn.removeAttribute('overwrite');
|
||||
localApn.removeAttribute('carrier_name');
|
||||
var parent = androidApn.parentNode;
|
||||
parent.insertBefore(localApn, androidApn);
|
||||
parent.removeChild(androidApn);
|
||||
matchFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!matchFound) {
|
||||
alert('Warning!\nCould not find APN \'' +
|
||||
localApn.getAttribute('carrier_name') +
|
||||
'\'. Which is expected to be overwrited.');
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// use local apn to patch origin carrier name in the Android DB
|
||||
// if the name is not the correct one (see bug 863126).
|
||||
// Note: This patch will not function once we get
|
||||
// the correct names updated in the upstream database.
|
||||
if (localApn.getAttribute('name')) {
|
||||
var localPattern = 'apn' +
|
||||
'[mcc="' + localApn.getAttribute('mcc') + '"]' +
|
||||
'[mnc="' + localApn.getAttribute('mnc') + '"]';
|
||||
androidApns =
|
||||
gAndroidDB.documentElement.querySelectorAll(localPattern);
|
||||
for (androidApn of androidApns) {
|
||||
if (androidApn &&
|
||||
androidApn.getAttribute('carrier') ===
|
||||
localApn.getAttribute('carrier')) {
|
||||
if (DEBUG) {
|
||||
console.log('- replace "' +
|
||||
androidApn.getAttribute('carrier') +
|
||||
'" to "' + localApn.getAttribute('name') +
|
||||
'"');
|
||||
}
|
||||
androidApn.setAttribute('carrier',
|
||||
localApn.getAttribute('name'));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
gAndroidDB.documentElement.appendChild(localApn);
|
||||
}
|
||||
}
|
||||
// Then the Gnome DB
|
||||
gGnomeDB = loadXML(GNOME_DB_FILE);
|
||||
gOperatorVariantDB = loadXML(OPERATOR_VARIANT_DB_FILE);
|
||||
gAPN = mergeDBs();
|
||||
}
|
||||
output.textContent = DEBUG ?
|
||||
JSON.stringify(gAPN, true, 2) :
|
||||
JSON.stringify(gAPN, true, 0)
|
||||
.replace(/("[0-9]+"):{/g, '\n$1: {')
|
||||
.replace(/("[0-9]+"):\[/g, '\n $1: [')
|
||||
.replace(/},\n/g, '\n},\n')
|
||||
.replace(/\[{/g, '[\n {')
|
||||
.replace(/},{/g, '},\n {')
|
||||
.replace(/}(],?)/g, '}\n $1')
|
||||
.replace(/]}}$/, ']\n}\n}');
|
||||
callback();
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function update() {
|
||||
var selection = document.getElementById('selection');
|
||||
var mcc = document.querySelector('input[name=mcc]').value;
|
||||
var mnc = document.querySelector('input[name=mnc]').value;
|
||||
var res = gAPN[mcc] ? (gAPN[mcc][mnc] || []) : [];
|
||||
selection.textContent = JSON.stringify(res, true, 2);
|
||||
|
||||
var preferences = document.getElementById('preferences');
|
||||
var prefs = {};
|
||||
for (var type in apnPrefNames) {
|
||||
var apn = {};
|
||||
for (var i = 0; i < res.length; i++) {
|
||||
if (res[i].type.indexOf(type) != -1) {
|
||||
apn = res[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
var prefNames = apnPrefNames[type];
|
||||
for (var key in prefNames) {
|
||||
var name = apnPrefNames[type][key];
|
||||
if (booleanPrefNames.indexOf(key) != -1) {
|
||||
prefs[key] = apn[name] || false;
|
||||
} else {
|
||||
prefs[key] = apn[name] || '';
|
||||
}
|
||||
}
|
||||
}
|
||||
preferences.textContent = JSON.stringify(prefs, true, 2);
|
||||
}
|
||||
|
||||
document.querySelector('form').oninput = update;
|
||||
loadDB(document.querySelector('textarea'), update);
|
||||
});
|
||||
Loading…
Reference in a new issue