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,106 @@
'use strict';
(function(exports) {
var LayoutDictionaryDownloader = function(imEngineId, dictFilename) {
this.imEngineId = imEngineId;
this.dictFilename = dictFilename;
this._xhr = null;
};
// Remote URLs to download the data. We require the remote server to have
// CORS turned on since we are not asking for SystemXHR permission.
LayoutDictionaryDownloader.prototype.REMOTE_URL =
'https://fxos.cdn.mozilla.net/dictionaries/%imEngineId/%ver/%dictFilename';
// If the data schema changes in an incompatible way, we must bump the
// version-to-download here.
LayoutDictionaryDownloader.prototype.ENGINE_DATA_VERSIONS = Object.freeze({
'latin': 1
});
LayoutDictionaryDownloader.prototype.onprogress = null;
LayoutDictionaryDownloader.prototype.load = function() {
if (this._xhr) {
throw new Error('LayoutDictionaryDownloader: Already downloading...');
}
var p = new Promise(function(resolve, reject) {
var url = this.REMOTE_URL
.replace('%imEngineId', this.imEngineId)
.replace('%ver', this.ENGINE_DATA_VERSIONS[this.imEngineId])
.replace('%dictFilename', this.dictFilename);
var xhr = this._xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'arraybuffer';
xhr.onprogress = function(evt) {
if (typeof this.onprogress === 'function') {
this.onprogress(evt.loaded, evt.total);
}
}.bind(this);
xhr.onloadend = function() {
this._xhr = null;
var data = xhr.response;
// We will only resolve the promise when the data is verified.
// For any other situration, we simply return the HTTP status code as
// a rejected placeholder value.
// (it doesn't really matter if you got 200/404/500
// or anything if it's not what you are looking for right :-/?)
if (data && this._verifyData(data)) {
if (typeof this.onprogress === 'function') {
this.onprogress(data.byteLength, data.byteLength);
}
resolve(data);
} else {
reject(xhr.statusText);
}
}.bind(this);
xhr.send();
}.bind(this));
return p;
};
LayoutDictionaryDownloader.prototype.abort = function() {
if (!this._xhr) {
throw new Error('LayoutDictionaryDownloader: ' +
'Not downloading but abort is called.');
}
this._xhr.abort();
this._xhr = null;
};
LayoutDictionaryDownloader.prototype._verifyData = function(buffer) {
switch (this.imEngineId) {
case 'latin':
// There is only first 8 bytes to check -- we can't be sure if the data
// is truncated. However that shouldn't happen since our CDN sends out
// Content-Length header.
//
// TODO: Harden the verification here in some way.
//
if (!(buffer instanceof ArrayBuffer) || buffer.byteLength < 8) {
return false;
}
var view = new Uint8Array(buffer, 0, 8);
return (String.fromCharCode.apply(String, view) === 'FxOSDICT');
default:
throw new Error('LayoutDictionaryDownloader: ' +
'No verify method available for this imEngine.');
}
};
exports.LayoutDictionaryDownloader = LayoutDictionaryDownloader;
}(window));