VulpesOS/host/Downloads.sys.mjs
OverSu 1311bed5e9 Release Preview 20 shared desktop, Android and Sargo updates
Restore Gaia settings and media workflows, extend native network adapters, and align the APK payload. Generate French/English changelogs and website entries from the simplified JSON source.

Validation: shared JS and Tundra unit tests; desktop workflows and persistence; signed APK payload parity; Sargo RAM and installed startup with boot readback. Android runtime qualification is recorded separately.
2026-10-13 00:19:45 +02:00

30 lines
1.7 KiB
JavaScript

// SPDX-License-Identifier: MPL-2.0
// Download identities belong to Gecko; paths supplied by content are never used.
export class GaiaDownloads {
constructor() {this.ids=new WeakMap();this.items=new Map();}
async request(app, params={}) {
if(!['settings','system'].includes(app.id))throw Error('PERMISSION_DENIED');
if(!['list','pause','resume','remove','blob'].includes(params.operation))throw Error('INVALID_VALUE');
const {Downloads}=ChromeUtils.importESModule('resource://gre/modules/Downloads.sys.mjs');
const list=await Downloads.getList(Downloads.PUBLIC);
const entries=await list.getAll();
this.items.clear();
const rows=entries.map(item=>{
if(!this.ids.has(item))this.ids.set(item,Services.uuid.generateUUID().toString());
const id=this.ids.get(item);this.items.set(id,item);
return {id,url:item.source.url,path:item.target.path,startTime:+item.startTime,
contentType:item.contentType||'application/octet-stream',currentBytes:item.currentBytes,totalBytes:item.totalBytes,
state:item.succeeded?'succeeded':item.stopped?'stopped':'downloading'};
});
if(params.operation==='list')return rows;
const item=this.items.get(params.id);if(!item)throw Error('DOWNLOAD_NOT_FOUND');
if(params.operation==='blob') {
if(!item.succeeded)throw Error('DOWNLOAD_NOT_COMPLETE');
return File.createFromFileName(item.target.path);
}
if(params.operation==='pause')await item.cancel();
if(params.operation==='resume')await item.start();
if(params.operation==='remove') {await item.cancel();await item.finalize(true);if(item.succeeded)await IOUtils.remove(item.target.path,{ignoreAbsent:true});await list.remove(item);}
return true;
}
}