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,8 @@
(function(exports){'use strict';var NUMBER_OF_DECIMALS=2;var BYTE_SCALE=['B','KB','MB','GB','TB'];function _getFormattedSize(bytes){if(bytes===undefined||isNaN(bytes)){return Promise.resolve(null);}
var index=0;while(bytes>=1024&&index<BYTE_SCALE.length){bytes/=1024;++index;}
return document.l10n.formatValue('byteUnit-'+BYTE_SCALE[index]).then(unit=>{return document.l10n.formatValue('fileSize',{size:bytes.toFixed(NUMBER_OF_DECIMALS),unit:unit});});}
function _calcPercentage(currently,total){if(total===0){return 0;}
return parseInt((100*currently)/total);}
var DownloadFormatter={getFormattedSize:function(bytes){return _getFormattedSize(bytes);},getPercentage:function(download){return _calcPercentage(download.currentBytes,download.totalBytes);},getFileName:function(download){return download.path.split('/').pop();},getTotalSize:function(download){var bytes=download.totalBytes;return _getFormattedSize(bytes);},getDownloadedSize:function(download){var bytes=download.currentBytes;return _getFormattedSize(bytes);},getDate:function(download){var date;try{date=download.startTime;}catch(ex){date=new Date();console.error(ex);}
var formatter=mozIntl._gaia.RelativeDate(navigator.languages);return formatter.format(date);},getUUID:function(download){return download.id||this.getFileName(download);}};exports.DownloadFormatter=DownloadFormatter;}(this));

View file

@ -0,0 +1,28 @@
var DownloadHelper=(function(){var CODE={FILE_NOT_FOUND:'FILE_NOT_FOUND',DEVICE_STORAGE:'DEVICE_STORAGE',MIME_TYPE_NOT_SUPPORTED:'MIME_TYPE_NOT_SUPPORTED',INVALID_STATE:'INVALID_STATE',NO_SDCARD:'NO_SDCARD',NO_PROVIDER:'NO_PROVIDER',UNMOUNTED_SDCARD:'UNMOUNTED_SDCARD'};var Request=function(){this.done=function(result){if(typeof this.onsuccess==='function'){this.result=result;window.setTimeout(function(){this.onsuccess({target:this});}.bind(this),0);}};this.failed=function(error){if(typeof this.onerror==='function'){this.error=error;window.setTimeout(function(){this.onerror({target:this});}.bind(this),0);}};};var STORAGE_NAME_BY_DEFAULT='sdcard';var STORAGE_NAME_KEY='device.storage.writable.name';var storageName=STORAGE_NAME_BY_DEFAULT;LazyLoader.load('shared/js/settings_listener.js',function settingsLoaded(){SettingsListener.observe(STORAGE_NAME_KEY,STORAGE_NAME_BY_DEFAULT,function setStorageName(evt){var settingValue=evt.settingValue;if(settingValue){storageName=settingValue;}});});function sendError(req,message,code){req.failed({message:message,code:code});console.error(message);}
function getBlob(download){var req=new Request();var storage=getVolume(download.storageName);var storeAvailableReq=storage.available();storeAvailableReq.onsuccess=function available_onsuccess(e){var path=download.storagePath;switch(storeAvailableReq.result){case'unavailable':sendError(req,' Could not open the file: '+path+' from '+
download.storageName,CODE.NO_SDCARD);break;case'shared':sendError(req,' Could not open the file: '+path+' from '+
download.storageName,CODE.UNMOUNTED_SDCARD);break;default:try{var storeGetReq=storage.get(path);storeGetReq.onsuccess=function store_onsuccess(){req.done(storeGetReq.result);};storeGetReq.onerror=function store_onerror(){sendError(req,storeGetReq.error.name+' Could not open the file: '+path+' from '+
download.storageName,CODE.FILE_NOT_FOUND);};}catch(ex){sendError(req,'Error getting the file '+path+' from '+
download.storageName,CODE.DEVICE_STORAGE);}}};storeAvailableReq.onerror=function available_onerror(){sendError(req,'Error getting storage state ',CODE.DEVICE_STORAGE);};return req;}
var Action=function Action(params){this.req=params.request;this.name=params.actionType.activityName;};Action.prototype={run:function a_run(){var activity=new MozActivity({name:this.name,data:this.data});activity.onsuccess=this._onsuccess.bind(this);activity.onerror=this._onerror.bind(this);},_onsuccess:function a_onsuccess(){this.req.done();},_onerror:function a_onerror(evt){this.req.failed({message:evt.target.error.name});}};var OpenAction=function OpenAction(params){Action.call(this,params);this.data={url:params.download.path,filename:DownloadFormatter.getFileName(params.download),type:params.type,blob:params.blob};};OpenAction.prototype={__proto__:Action.prototype};var ShareAction=function ShareAction(params){Action.call(this,params);this.data={type:params.type.split('/')[0]+'/*',blobs:[params.blob],filenames:[DownloadFormatter.getFileName(params.download)]};};ShareAction.prototype={__proto__:Action.prototype,_onerror:function sa_onerror(evt){if(evt.target.error.name!=='NO_PROVIDER'){return;}
sendError(this.req,'No provider to share file',CODE.NO_PROVIDER);}};var InfoAction=function InfoAction(params){Action.call(this,params);this.data={name:DownloadFormatter.getFileName(params.download),type:params.type,blob:params.blob,size:params.download.totalBytes,path:params.download.path};};InfoAction.prototype={__proto__:Action.prototype,run:function ia_run(){this.req.done(this.data);}};var ActionsFactory={TYPE:{OPEN:{activityName:'open',actionClass:OpenAction},SHARE:{activityName:'share',actionClass:ShareAction},INFO:{actionClass:InfoAction},WALLPAPER:{activityName:'setwallpaper',actionClass:ShareAction},RINGTONE:{activityName:'setringtone',actionClass:ShareAction}},create:function af_create(params){return new params.actionType.actionClass(params);}};function getType(download){var fileName=DownloadFormatter.getFileName(download);var type=MimeMapper.guessTypeFromFileProperties(fileName,download.contentType);return type;}
function runAction(actionType,download){var req=new Request();window.setTimeout(function launching(){var state=download.state;if(state==='succeeded'||state==='finalized'){LazyLoader.load(['shared/js/mime_mapper.js','shared/js/download/download_formatter.js'],function loaded(){var type=getType(download);if(type.length===0){type=download.contentType;if(actionType!==ActionsFactory.TYPE.OPEN&&actionType!==ActionsFactory.TYPE.INFO){sendError(req,'Mime type not supported: '+type,CODE.MIME_TYPE_NOT_SUPPORTED);return;}}
var blobReq=getBlob(download);blobReq.onsuccess=function(){ActionsFactory.create({actionType:actionType,download:download,type:type,blob:blobReq.result,request:req}).run();};blobReq.onerror=function(){req.failed(blobReq.error);};});return;}
sendError(req,'Becareful, the download is not finished!',CODE.INVALID_STATE);},0);return req;}
function remove(download){var req=new Request();var incompleteDownload=download.state!=='succeeded';setTimeout(function(){if(incompleteDownload){if(!navigator.mozDownloadManager){sendError(req,'DownloadManager not present',CODE.INVALID_STATE);}else{download.pause().then(function(){navigator.mozDownloadManager.remove(download).then(function success(){req.done(download);},function error(){sendError(req,'DownloadManager doesnt know about this download',CODE.INVALID_STATE);});},function(){sendError(req,'Failed to pause download before removal',CODE.INVALID_STATE);});}}else{req.done(download);}},0);return incompleteDownload?req:doRemoveFromPhone(req,download);}
function doRemoveFromPhone(deleteRequest,download){var req=new Request();deleteRequest.onsuccess=function(){var storage=getVolume(download.storageName);var storeAvailableReq=storage.available();storeAvailableReq.onsuccess=function available_onsuccess(e){var path=download.path;switch(storeAvailableReq.result){case'unavailable':sendError(req,' Could not delete the file: '+path+' from '+
storageName,CODE.NO_SDCARD);break;case'shared':sendError(req,' Could not delete the file: '+path+' from '+
storageName,CODE.UNMOUNTED_SDCARD);break;default:var storeDeleteReq=storage.delete(download.storagePath);storeDeleteReq.onsuccess=function store_onsuccess(){if(download.state==='succeeded'){LazyLoader.load(['/shared/js/download/download_store.js'],function(){DownloadStore.remove(download);});}
req.done(storeDeleteReq.result);};storeDeleteReq.onerror=function store_onerror(){sendError(req,storeDeleteReq.error.name+' Could not remove the file: '+download.path+' from '+
storageName,CODE.FILE_NOT_FOUND);};}};storeAvailableReq.onerror=function available_onerror(){sendError(req,'Error getting storage state ',CODE.DEVICE_STORAGE);};};deleteRequest.onerror=function(error){sendError(req,error.message,error.code);};return req;}
function handlerError(error,download,cb){LazyLoader.load('shared/js/download/download_ui.js',(function loaded(){var req;var show=DownloadUI.show;if(error.message&&(error.message.endsWith('canceled')||error.message.endsWith('cancelled'))){cb&&cb(null);return;}
switch(error.code){case CODE.NO_SDCARD:case CODE.UNMOUNTED_SDCARD:case CODE.FILE_NOT_FOUND:case CODE.NO_PROVIDER:req=show(DownloadUI.TYPE[error.code],download,true);req.onconfirm=cb;break;case CODE.MIME_TYPE_NOT_SUPPORTED:req=show(DownloadUI.TYPE.UNSUPPORTED_FILE_TYPE,download,true);req.onconfirm=function tuftOnConfirm(){showRemoveFileUI(download,cb);};break;default:req=show(DownloadUI.TYPE.FILE_OPEN_ERROR,download,true);req.onconfirm=function tfoeOnConfirm(){showRemoveFileUI(download,cb);};break;}
req.oncancel=cb;}));}
function showRemoveFileUI(download,cb){var req=DownloadUI.show(DownloadUI.TYPE.DELETE,download,true);req.oncancel=cb;req.onconfirm=function doRemove(){if(typeof cb==='function'){cb(download);}else{remove(download);}};}
function getFreeSpace(cb){var storage=navigator.getDeviceStorage(storageName);if(!storage){console.error('Cannot get free space size in sdcard');cb(null);return;}
var req=storage.freeSpace();req.onsuccess=function(e){cb(e.target.result);};req.onerror=function(){cb(null);};}
function getVolume(volumeName){var volumes=navigator.getDeviceStorages('sdcard');if(!volumeName||volumeName===''){return volumes[0];}
for(var i=0;i<volumes.length;++i){if(volumes[i].storageName===volumeName){return volumes[i];}}
return volumes[0];}
return{open:function(download){return runAction(ActionsFactory.TYPE.OPEN,download);},share:function(download){return runAction(ActionsFactory.TYPE.SHARE,download);},wallpaper:function(download){return runAction(ActionsFactory.TYPE.WALLPAPER,download);},ringtone:function(download){return runAction(ActionsFactory.TYPE.RINGTONE,download);},info:function(download){return runAction(ActionsFactory.TYPE.INFO,download);},remove:remove,get CODE(){return CODE;},handlerError:handlerError,getFreeSpace:getFreeSpace};}());

View file

@ -0,0 +1,31 @@
var DownloadStore=(function(){var datastore;const DATASTORE_NAME='download_store';var downloadListDB;var downloadList=[];var lastRevisionId;const LIST_DB='download_list';const LIST_STORE='download_list';const LIST_KEY=0;const REVISION_KEY=1;var Request=function(){this.done=function(result){if(typeof this.onsuccess==='function'){this.result=result;window.setTimeout(function(){this.onsuccess({target:this});}.bind(this),0);}};this.failed=function(error){if(typeof this.onerror==='function'){this.error=error;window.setTimeout(function(){this.onerror({target:this});}.bind(this),0);}};};function promisify(request){return new Promise(function(resolve,reject){request.onsuccess=(event)=>{resolve(event.target.result);};request.onerror=(event)=>{reject(event.target.errorCode);};});}
var readyState;function init(success,fail){if(readyState==='initialized'){success();return;}
if(readyState==='initializing'){document.addEventListener('ds-initialized',function oninitalized(){document.removeEventListener('ds-initialized',oninitalized);success();});return;}
readyState='initializing';if(!navigator.getDataStores){var messageError='Data store: DataStore API is not working';console.error(messageError);fail({message:messageError});return;}
navigator.getDataStores(DATASTORE_NAME).then(function(ds){var messageError='Download Store: Cannot get access to the DataStore';if(ds.length<1){console.error(messageError);throw({message:messageError});}
datastore=ds[0];}).then(function(){return openDownloadListIndexedDB();}).then(function(db){downloadListDB=db;var listStore=downloadListDB.transaction(LIST_STORE,'readonly').objectStore(LIST_STORE);return Promise.all([promisify(listStore.get(LIST_KEY)).then((value)=>{downloadList=value;}),promisify(listStore.get(REVISION_KEY)).then((value)=>{lastRevisionId=value;})]);}).then(function(){readyState='initialized';const LEGACY_INDEX_ID=1;if(downloadList&&downloadList.includes(LEGACY_INDEX_ID)){return promisify(get(LEGACY_INDEX_ID)).then((download)=>{if('byTimestamp'in download){downloadList.splice(downloadList.indexOf(LEGACY_INDEX_ID),1);}});}}).then(function(){notifyOpenSuccess(success);}).catch(function(e){console.error('Error while opening the Download Store: ',e.message);fail(e);});}
function openDownloadListIndexedDB(){return new Promise(function(resolve,reject){var request=indexedDB.open(LIST_DB);request.onsuccess=function(event){var db=event.target.result;resolve(db);};request.onerror=function(event){reject(event.target.errorCode);};request.onupgradeneeded=function(event){var db=event.target.result;promisify(db.createObjectStore(LIST_STORE)).then(()=>{var listStore=db.transaction(LIST_STORE,'readwrite').objectStore(LIST_STORE);return Promise.all([promisify(listStore.add([],LIST_KEY)),promisify(listStore.add(0,REVISION_KEY))]);}).catch(reject);};request.onblocked=function(event){reject(event.target.errorCode);};});}
function notifyOpenSuccess(cb){window.setTimeout(cb,0);document.dispatchEvent(new CustomEvent('ds-initialized'));}
var fieldsToPropagate=['url','path','totalBytes','contentType','startTime','state','storageName','storagePath'];function cookDownload(download){var ret=Object.create(null);fieldsToPropagate.forEach(function(field){ret[field]=download[field];});ret.finalizeTime=new Date();return ret;}
function defaultError(req){return defaultErrorCb.bind(null,req);}
function defaultErrorCb(request,error){request.failed(error);}
function defaultSuccess(req){return defaultSuccessCb.bind(null,req);}
function defaultSuccessCb(request,result){request.done(result);}
function updateDownloadList(){var cursor=datastore.sync(lastRevisionId);function cursorResolve(task){switch(task.operation){case'done':lastRevisionId=task.revisionId;var listStore=downloadListDB.transaction(LIST_STORE,'readwrite').objectStore(LIST_STORE);return Promise.all([promisify(listStore.put(downloadList,LIST_KEY)),promisify(listStore.put(lastRevisionId,REVISION_KEY))]);case'clear':downloadList=[];break;case'add':downloadList.push(task.id);break;case'update':break;case'remove':var i=downloadList.indexOf(task.id);if(i>=0){downloadList.splice(i,1);}
break;}
return cursor.next().then(cursorResolve);}
return cursor.next().then(cursorResolve);}
function doAdd(download,req){var downloadCooked=cookDownload(download);datastore.add(downloadCooked).then(function(id){downloadCooked.id=id;datastore.put(downloadCooked,id).then(function(){req.done(downloadCooked);},defaultError(req));},defaultError(req));}
function add(download){var req=new Request();window.setTimeout(function(){init(doAdd.bind(null,download,req),req.failed.bind(req));});return req;}
function doGet(id,req){datastore.get(id).then(function(download){req.done(download);},defaultError(req));}
function get(id){var req=new Request();window.setTimeout(function(){init(doGet.bind(null,id,req),req.failed.bind(req));});return req;}
function doGetAll(req){updateDownloadList().then(function(){datastore.get.apply(datastore,downloadList).then(defaultSuccess(req),defaultError(req));},defaultError(req));}
function getAll(){var req=new Request();window.setTimeout(function(){init(doGetAll.bind(null,req),req.failed.bind(req));});return req;}
function doRemove(id,req){datastore.remove(id).then(function(success){if(success){defaultSuccess(req);}else{req.failed({message:'The download with id: '+id+'does not exist'});}},defaultError(req));}
function remove(download){var req=new Request();window.setTimeout(function(){init(doRemove.bind(null,download.id,req),req.failed.bind(req));});return req;}
function doAddListener(listener){datastore.addEventListener('change',listener);}
function addListener(listener){var req=new Request();window.setTimeout(function(){init(doAddListener.bind(null,listener),req.failed.bind(req));});return req;}
function doRemoveListener(listener){datastore.removeEventListener('change',listener);}
function removeListener(listener){var req=new Request();window.setTimeout(function(){init(doRemoveListener.bind(null,listener),req.failed.bind(req));});return req;}
return{get:get,getAll:getAll,add:add,remove:remove,addListener:addListener,removeListener:removeListener};}());

View file

@ -0,0 +1,24 @@
var DownloadUI=(function(){var DownloadType=function(name,classes,isPlainMessage){this.name=name;this.classes=classes;this.isPlainMessage=isPlainMessage;this.numberOfButtons=classes.indexOf('full')!==-1?1:2;};var ERRORS={NO_MEMORY:2152857616,NO_SDCARD:2152857618,UNMOUNTED_SDCARD:2152857621};var TYPES={STOP:new DownloadType('stop',['danger'],true),STOPPED:new DownloadType('stopped',['recommend'],true),FAILED:new DownloadType('failed',['recommend']),DELETE:new DownloadType('delete',['danger']),DELETE_ALL:new DownloadType('delete_all',['danger']),UNSUPPORTED_FILE_TYPE:new DownloadType('unsupported_file_type',['danger']),FILE_NOT_FOUND:new DownloadType('file_not_found',['recommend','full'],true),FILE_OPEN_ERROR:new DownloadType('file_open_error',['danger']),NO_SDCARD:new DownloadType('no_sdcard_found_2',['recommend','full'],true),UNMOUNTED_SDCARD:new DownloadType('unmounted_sdcard_2',['recommend','full'],true),NO_PROVIDER:new DownloadType('no_provider',['recommend','full'],true),NO_MEMORY:new DownloadType('no_memory',['recommend','full'],true)};var DownloadAction=function(id,type){this.id=id;this.name=id.toLowerCase();this.title=this.name+'_downloaded_file';this.type=type;};var ACTIONS={OPEN:new DownloadAction('OPEN','confirm'),SHARE:new DownloadAction('SHARE','confirm'),WALLPAPER:new DownloadAction('WALLPAPER','confirm'),RINGTONE:new DownloadAction('RINGTONE','confirm')};var confirm=null;var actionMenu=null;var Request=function(){this.cancel=function(){removeContainers();if(typeof this.oncancel==='function'){this.oncancel();}};this.confirm=function(result){removeContainers();if(typeof this.onconfirm==='function'){this.result=result;this.onconfirm({target:this});}};};function removeContainers(){removeConfirm();removeActionMenu();}
function addConfirm(){if(confirm!==null){confirm.parentNode.removeChild(confirm);}
confirm=document.createElement('form');confirm.id='downloadConfirmUI';confirm.setAttribute('role','dialog');confirm.setAttribute('data-type','confirm');confirm.setAttribute('data-z-index-level','100');var screen=document.getElementById('screen');var container=screen||document.body;container.appendChild(confirm);}
function removeConfirm(){if(confirm===null){return;}
confirm.innerHTML='';confirm.style.display='none';}
window.addEventListener('home',removeContainers);window.addEventListener('holdhome',removeContainers);function l10n(element,l10nid,l10nargs){if(l10nargs){element.setAttribute('data-l10n-args',JSON.stringify(l10nargs));}
element.setAttribute('data-l10n-id',l10nid);return element;}
function createConfirm(type,req,downloads){addConfirm();var dialog=document.createElement('section');var header=document.createElement('h1');l10n(header,type.name+'_download_title');dialog.appendChild(header);var message=document.createElement('p');if(type.isPlainMessage){l10n(message,type.name+'_download_message');}else{var args=Object.create(null);if(type===TYPES.DELETE_ALL){args.number=downloads.length;}else{args.name=DownloadFormatter.getFileName(downloads[0]);}
l10n(message,type.name+'_download_message',args);}
dialog.appendChild(message);var menu=document.createElement('menu');menu.dataset.items=type.numberOfButtons;if(type.numberOfButtons===2){var lButton=document.createElement('button');lButton.type='button';lButton.setAttribute('data-l10n-id',type.name+'_download_left_button');lButton.onclick=function l_cancel(){lButton.onclick=null;req.cancel();};menu.appendChild(lButton);}
var rButton=document.createElement('button');rButton.type='button';type.classes.forEach(function(clazz){rButton.classList.add(clazz);});rButton.setAttribute('data-l10n-id',type.name+'_download_right_button');rButton.onclick=function r_confirm(){rButton.onclick=null;req.confirm();};menu.appendChild(rButton);dialog.appendChild(menu);confirm.appendChild(dialog);confirm.style.display='block';}
function addActionMenu(){if(actionMenu!==null){document.body.removeChild(actionMenu);}
actionMenu=document.createElement('gaia-menu');actionMenu.id='downloadActionMenuUI';actionMenu.className='actions';}
function removeActionMenu(){if(actionMenu===null){return;}
actionMenu.hide();document.body.removeChild(actionMenu);actionMenu=null;}
function createActionMenu(req,download){var actions=[ACTIONS.OPEN,ACTIONS.SHARE];var fileName=DownloadFormatter.getFileName(download);var type=MimeMapper.guessTypeFromFileProperties(fileName,download.contentType);if(type.length>0){if(type.startsWith('image/')){actions.push(ACTIONS.WALLPAPER);}else if(type.startsWith('audio/')){actions.push(ACTIONS.RINGTONE);}}
doCreateActionMenu(req,fileName,actions);}
function doCreateActionMenu(req,fileName,actions){addActionMenu();var header=document.createElement('header');header.textContent=fileName;actionMenu.appendChild(header);actions.forEach(function addActionButton(action){var button=document.createElement('button');button.id=action.id;l10n(button,action.title);button.dataset.type=action.type;actionMenu.appendChild(button);button.addEventListener('click',function buttonCliked(evt){button.removeEventListener('click',buttonCliked);req[evt.target.dataset.type](ACTIONS[evt.target.id]);});});document.body.appendChild(actionMenu);actionMenu.removeAttribute('hidden');}
var styleSheets=['shared/style/buttons.css','shared/style/headers.css','shared/style/confirm.css'];function show(type,downloads,ignoreStyles){var req=new Request();downloads=Array.isArray(downloads)?downloads:[downloads];window.setTimeout(function(){var libs=['shared/js/download/download_formatter.js'];if(!ignoreStyles){libs.push.apply(libs,styleSheets);}
if(type===null){type=TYPES.STOPPED;var download=downloads[0];if(download.state==='finalized'||download.state==='stopped'&&download.error!==null){type=TYPES.FAILED;}}
LazyLoader.load(libs,createConfirm.call(this,type,req,downloads));},0);return req;}
function showActions(download){var req=new Request();window.setTimeout(function(){LazyLoader.load(['shared/js/mime_mapper.js','shared/js/download/download_formatter.js','shared/js/component_utils.js','shared/elements/gaia_menu/script.js'],createActionMenu.call(this,req,download));},0);return req;}
return{show:show,showActions:showActions,hide:removeContainers,get ERRORS(){return ERRORS;},get TYPE(){return TYPES;}};}());