VulpesOS/assets/webapps/fl.gaiamobile.org/gaia_build_defer_download.js
OverSu b38dea0597 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.
2026-09-30 23:13:03 +02:00

127 lines
No EOL
26 KiB
JavaScript

;'use strict';(function(exports){if(exports.ForwardLock){return;}
const mimeSubtype='vnd.mozilla.oma.drm.fl';const SECRET_SETTINGS_ID='oma.drm.forward_lock.secret.key';var secret=null;function xor(buffer,key){var words=new Uint32Array(buffer,0,buffer.byteLength>>2);for(var i=0,n=words.length;i<n;i++){words[i]^=key;}}
function lockBuffer(secret,content,type,metadata){var header='LOCKED 1 '+escape(type)+'\n';if(metadata){for(var p in metadata){header+=escape(p)+':'+escape(metadata[p])+'\n';}}
header+='\0';var buffer=new Uint8Array(new Uint8Array(content)).buffer;xor(buffer,secret);return new Blob([header,buffer],{type:type.split('/')[0]+'/'+mimeSubtype});}
function lockBlob(secret,blob,metadata,callback){var reader=new FileReader();reader.readAsArrayBuffer(blob);reader.onload=function(){callback(lockBuffer(secret,reader.result,blob.type,metadata));};}
function unlockBlob(secret,blob,callback,errorCallback){if(!secret){return error('no secret supplied');}
var reader=new FileReader();reader.readAsArrayBuffer(blob);reader.onload=function(){var buffer=reader.result;var bytes=new Uint8Array(buffer);var header='';var contentStart;for(var i=0;i<bytes.length;i++){if(bytes[i]===0){contentStart=i+1;break;}
header+=String.fromCharCode(bytes[i]);}
if(!header.startsWith('LOCKED')){return error('Bad magic number');}
if(header.substring(6,9)!==' 1 '){return error('Unsupported version number');}
if(!contentStart){return error('No content');}
var eol=header.indexOf('\n');if(eol===-1){return error('malformed header');}
var type=unescape(header.substring(9,eol).trim());var metadata={};var lines=header.substring(eol+1).split('\n');for(var j=0;j<lines.length;j++){var line=lines[j];if(!line){continue;}
var[key,value]=line.split(':');if(!key||!value){return error('malformed metadata');}
metadata[unescape(key)]=unescape(value);}
var content=buffer.slice(contentStart);xor(content,secret);var blob=new Blob([content],{type:type});try{callback(blob,metadata);}
catch(e){console.error('Exception in content callback',e);}};function error(msg){msg='LCKA.decrypt(): '+msg;if(errorCallback){try{errorCallback(msg);}
catch(e){console.error('Exception in error callback',e);}}
else{console.error(msg);}}}
function getKey(callback){try{if(secret!==null){report(secret);return;}
var lock=navigator.mozSettings.createLock();var getreq=lock.get(SECRET_SETTINGS_ID);getreq.onsuccess=function(){secret=getreq.result[SECRET_SETTINGS_ID]||null;report(secret);};getreq.onerror=function(){console.error('Error getting ForwardLock setting',getreq.error);report(null);};}
catch(e){console.error('Exception in ForwardLock.getKey():',e);report(null);}
function report(secret){if(callback){try{callback(secret);}
catch(e){console.error('Exception in ForwardLock.getKey() callback',e);}}}}
function getOrCreateKey(callback){getKey(function(key){if(key!==null){report(key);return;}
secret=((Math.random()*0xFFFFFFFF)|0)+1;var setting={};setting[SECRET_SETTINGS_ID]=secret;var setreq=navigator.mozSettings.createLock().set(setting);setreq.onsuccess=function(){report(secret);};setreq.onerror=function(){console.error('Failed to set key in ForwardLock.getOrCreateKey()',setreq.error.name);secret=null;};});function report(secret){if(callback){try{callback(secret);}
catch(e){console.error('Exception in ForwardLock.getOrCreateKey() callback');}}}}
exports.ForwardLock={lockBuffer:lockBuffer,lockBlob:lockBlob,unlockBlob:unlockBlob,mimeSubtype:mimeSubtype,getKey:getKey,getOrCreateKey:getOrCreateKey};}(window));;'use strict';function getUnusedFilename(storage,name,callback){var getreq=storage.get(name);getreq.onerror=function(){callback(name);};getreq.onsuccess=function(){var version=0;var p=name.lastIndexOf('/');var dir=name.substring(0,p+1);var file=name.substring(p+1);p=file.lastIndexOf('.');if(p===-1){p=file.length;}
var ext=file.substring(p);var base=file.substring(0,p);var parts=base.match(/^(.*)_(\d{1,2})$/);if(parts){base=parts[1];version=parseInt(parts[2]);}
var newname=dir+base+'_'+(version+1)+ext;getUnusedFilename(storage,newname,callback);};};'use strict';function getStorageIfAvailable(kind,size,success,error){var storage=navigator.getDeviceStorage(kind);storage.available().onsuccess=function(e){if(e.target.result!=='available'){if(error){error(e.target.result);}}
else{storage.freeSpace().onsuccess=function(e){if(e.target.result<size){if(error){error(e.target.result);}}
else{success(storage);}};}};};'use strict';var MediaUtils={formatDate:function(timestamp){if(!timestamp||timestamp===undefined||isNaN(timestamp)){return;}
return new Date(timestamp).toLocaleString(navigator.languages,{'month':'numeric','year':'numeric','day':'numeric'});},getLocalizedSizeTokens:function(size){if(!size||size===undefined||isNaN(size)){return Promise.resolve('');}
var units=['B','KB','MB','GB','TB','PB','EB','ZB','YB'];var i=0;while(size>=1024&&i<(units.length-1)){size/=1024;++i;}
var sizeDecimal=i<2?Math.round(size):Math.round(size*10)/10;return document.l10n.formatValue('byteUnit-'+units[i]).then((unit)=>{return{size:sizeDecimal,unit};});},getLocalizedSize:function(size){return this.getLocalizedSizeTokens(size).then((args)=>{return document.l10n.formatValue('fileSize',args);});},formatDuration:function(duration){function padLeft(num,length){var r=String(num);while(r.length<length){r='0'+r;}
return r;}
duration=Math.round(duration);var minutes=Math.floor(duration/60);var seconds=duration%60;if(minutes<60){return padLeft(minutes,2)+':'+padLeft(seconds,2);}
var hours=Math.floor(minutes/60);minutes=Math.floor(minutes%60);return hours+':'+padLeft(minutes,2)+':'+padLeft(seconds,2);},populateMediaInfo:function(data){for(var id in data){if(data.hasOwnProperty(id)){var element=document.getElementById(id);if(element){if(typeof data[id]==='string'){element.setAttribute('data-l10n-id',data[id]);}else if(data[id].hasOwnProperty('raw')){element.removeAttribute('data-l10n-id');element.textContent=data[id].raw;}else{document.l10n.setAttributes(element,data[id].id,data[id].args);}}}}},binarySearch:function(array,element,comparator,from,to){if(comparator===undefined){comparator=function(a,b){return a-b;};}
if(from===undefined){return MediaUtils.binarySearch(array,element,comparator,0,array.length);}
if(from===to){return from;}
var mid=Math.floor((from+to)/2);var result=comparator(element,array[mid]);if(result<0){return MediaUtils.binarySearch(array,element,comparator,from,mid);}
else{return MediaUtils.binarySearch(array,element,comparator,mid+1,to);}}};;'use strict';const DEBUG=true;const OMADownloadStatus=Object.freeze({SUCCESS:'900 Success',INSUFFICIENT_MEMORY:'901 Insufficient memory',USER_CANCELLED:'902 User Cancelled',LOSS_OF_SERVICE:'903 Loss of Service',ATTRIBUTE_MISMATCH:'905 Attribute mismatch',INVALID_DESCRIPTOR:'906 Invalid descriptor',INVALID_DDVERSION:'951 Invalid DDVersion',DEVICE_ABORTED:'952 Device Aborted',NON_ACCEPTABLE_CONTENT:'953 Non-Acceptable Content',LOADER_ERROR:'954 Loader Error'});const DOWNLOAD_ERROR='download_error';const INSTALL_ERROR='install_error';const ERR_DESCRIPTOR_DOWNLOAD_FAILED='err_descriptor_download_failed';const ERR_BAD_DESCRIPTOR='err_bad_descriptor';const ERR_TOO_BIG='err_too_big';const ERR_UNSUPPORTED_TYPE='err_unsupported_type';const ERR_BAD_TYPE='err_bad_type';const ERR_CONTENT_DOWNLOAD_FAILED='err_content_download_failed';const ERR_BAD_DRM_MESSAGE='err_bad_drm_message';const ERR_BAD_IMAGE='err_bad_image';const ERR_BAD_AUDIO='err_bad_audio';const ERR_NO_SPACE='err_no_space';const ERR_NO_SDCARD='err_no_sdcard';const ERR_SDCARD_IN_USE='err_sdcard_in_use';const ERR_DB_STORE_FAILURE='err_db_store_failure';const ERR_DS_SAVE_FAILURE='err_ds_save_failure';const SUCCESS_SONG='success_song';const SUCCESS_RINGTONE='success_ringtone';const SUCCESS_WALLPAPER='success_wallpaper';const systemXHR=Object.freeze({mozSystem:true});const SupportedImageTypes=Object.freeze({'image/jpeg':true,'image/png':true,'image/gif':true,'image/bmp':true});const SupportedAudioTypes=Object.freeze({'audio/mpeg':true,'audio/mp4':true,'audio/opus':true,'audio/ogg':true});const MimeTypeAliases=Object.freeze({'audio/mp3':'audio/mpeg'});const RINGTONE_KEY='dialer.ringtone';const RINGTONE_NAME_KEY='dialer.ringtone.name';const RINGTONE_ID_KEY='dialer.ringtone.id';const WALLPAPER_KEY='wallpaper.image';const SONG='song';const RINGTONE='ringtone';const WALLPAPER='wallpaper';const MAX_DOWNLOAD_SIZE=16*1024*1024;;'use strict';function debug(...args){if(!DEBUG){return;}
if(!debug.startTime){debug.startTime=Date.now();}
args.unshift('[Locked Content]',Date.now()-debug.startTime);console.log.apply(console,args);}
function $(id){return document.getElementById(id);}
function _(id,args){return navigator.mozL10n.get(id,args);}
function showDialog(options){function close(e){document.body.removeChild(dialog);e.preventDefault();e.stopPropagation();}
var cancelButton;var okButton;var dialog=document.createElement('form');dialog.setAttribute('role','dialog');dialog.dataset.type='confirm';var section=document.createElement('section');dialog.appendChild(section);if(options.title){var title=document.createElement('h1');title.textContent=options.title;section.appendChild(title);}
var msg=document.createElement('p');msg.textContent=options.message;section.appendChild(msg);if(options.details){var details=document.createElement('p');var small=document.createElement('small');small.textContent=options.details;details.appendChild(small);section.appendChild(details);}
var menu=document.createElement('menu');dialog.appendChild(menu);if(options.cancelCallback){cancelButton=document.createElement('button');menu.appendChild(cancelButton);cancelButton.textContent=options.cancelText||_('cancel');cancelButton.onclick=function(e){close(e);options.cancelCallback();};}
if(options.okCallback){okButton=document.createElement('button');menu.appendChild(okButton);okButton.textContent=options.okText||_('ok');if(options.danger){okButton.classList.add('danger');}
else if(!options.cancelCallback){okButton.classList.add('recommend');}
okButton.onclick=function(e){close(e);options.okCallback();};}
if(okButton&&!cancelButton){okButton.classList.add('full');}
if(cancelButton&&!okButton){cancelButton.classList.add('full');}
document.body.appendChild(dialog);};'use strict';var objectStore=(function(){const DBNAME='LOCKEDCONTENT';const DBVERSION=1;const STORENAMES=['ringtones','wallpapers'];var db;function getStore(access,storeName,callback){if(STORENAMES.indexOf(storeName)===-1){throw Error('unknown object store name:',storeName);}
if(db){callback(db.transaction(storeName,access).objectStore(storeName));}
else{initDB(function(){getStore(access,storeName,callback);});}}
function initDB(callback){var open=indexedDB.open(DBNAME,DBVERSION);open.onsuccess=function(){db=open.result;callback();};open.onupgradeneeded=function(){STORENAMES.forEach(function(storeName){open.result.createObjectStore(storeName,{autoIncrement:true,keyPath:'id'});});};open.onerror=function(){console.error('can not open database:',open.error.name);};}
return{readonly:function readonly(storeName,callback){getStore('readonly',storeName,callback);},readwrite:function readwrite(storeName,callback){getStore('readwrite',storeName,callback);}};}());;'use strict';function BinaryStringView(data){if(typeof data==='string'){this.bytes=new Uint8Array(data.length);for(var i=0;i<data.length;i++){this.bytes[i]=(data.charCodeAt(i)&0xFF);}}else if(data instanceof Uint8Array){this.bytes=data;}else if(data instanceof ArrayBuffer){this.bytes=new Uint8Array(data);}else{throw TypeError();}
this.length=this.bytes.length;this.buffer=this.bytes.buffer;this.byteOffset=this.bytes.byteOffset;this.byteLength=this.bytes.byteLength;}
BinaryStringView.prototype.toString=function toString(){var s='';for(var i=0;i<this.length;i++){s+=String.fromCharCode(this.bytes[i]);}
return s;};BinaryStringView.prototype.toArrayBuffer=function toArrayBuffer(){return this.buffer.slice(this.byteOffset,this.byteOffset+this.byteLength);};BinaryStringView.prototype.charAt=function(i){return String.fromCharCode(this.bytes[i]);};BinaryStringView.prototype.slice=function slice(from,to){if(to===undefined){return new BinaryStringView(this.bytes.subarray(from));}else{return new BinaryStringView(this.bytes.subarray(from,to));}};BinaryStringView.prototype.trim=function(){var start=0,end=this.length-1;var WS=/\s/;while(start<=end&&WS.test(this.charAt(start))){start++;}
while(end>=start&&WS.test(this.charAt(end))){end--;}
return this.slice(start,end+1);};BinaryStringView.prototype.indexOf=function indexOf(target,start){if(typeof target==='string'){target=new BinaryStringView(target);}
start=Math.min(start||0,this.length);if(target.length===0){return start;}
var end=this.length-target.length;var i=start;while(i<=end){var j=0;while(this.bytes[i+j]===target.bytes[j]){if(++j===target.length){return i;}}
i++;}
return-1;};BinaryStringView.prototype.lastIndexOf=function indexOf(target,start){if(typeof target==='string'){target=new BinaryStringView(target);}
if(target.length===0){return Math.min(start||this.length,this.length);}
start=start||this.length-1;var i=start;while(i>=0){var j=0;while(this.bytes[i+j]===target.bytes[j]){if(++j===target.length){return i;}}
i--;}
return-1;};;'use strict';window.addEventListener('load',function(){navigator.mozL10n.once(function(){navigator.mozSetMessageHandler('activity',view);});});function view(activity){debug('view() invoked for activity',activity.source.name,'with data',JSON.stringify(activity.source.data));var descriptor={};var mimeType;var isImage=false;var isAudio=false;var installType;var hasDescriptor;var activityType=normalizeMimeType(activity.source.data.type);if(activityType==='application/vnd.oma.drm.message'){hasDescriptor=false;var url=(activity.source.data.url||'');descriptor.name=getFileNameFromURL(url);descriptor.size=0;descriptor.types=['application/vnd.oma.drm.message'];descriptor.objectURI=url;displayDownloadProgress();}else{hasDescriptor=true;downloadDescriptor(activity.source.data.url);}
function normalizeMimeType(type){type=type.split(';')[0];type=type.toLowerCase();if(type in MimeTypeAliases){type=MimeTypeAliases[type];}
return type;}
function askSongOrRingtone(aCallback){showDialog({message:_('ringtone-or-song-question'),okText:_('ringtone-response'),cancelText:_('song-response'),okCallback:aCallback.bind(undefined,RINGTONE),cancelCallback:aCallback.bind(undefined,SONG)});}
function getFileNameFromURL(aUri){var name='';if(aUri){name=aUri.split('/').pop();if(name.endsWith('.dm')){name=name.slice(0,-3);}
if(name.length>18){name=name.substring(0,15)+'\u2026';}}
return name;}
function getFileNameFromHeader(aHeader){var regexp=/filename="([^"]*)"/i;var match=regexp.exec(aHeader);var name=match&&match[1];if(name){name=getFileNameFromURL(name);}
return name;}
function reportError(type,errorID,downloadStatus,details){console.error(type,errorID,downloadStatus,details);if(downloadStatus){sendStatus(downloadStatus);}
details='['+(details?errorID+': '+details:errorID)+']';showDialog({title:_(type)||type,message:_(errorID),details:details,okCallback:function(){activity.postError(errorID);}});}
function reportSuccess(successID){sendStatus(OMADownloadStatus.success);showDialog({message:_(successID)||successID,okCallback:function(){activity.postResult({success:true});}});}
function sendStatus(status,callback){if(descriptor.installNotifyURI){var xhr=new XMLHttpRequest(systemXHR);xhr.open('POST',descriptor.installNotifyURI);xhr.timeout=1000;xhr.send(status);if(callback){xhr.onloadend=function(){callback();};}}else if(callback){callback();}}
function downloadDescriptor(descriptorURL){debug('Step 1: downloading descriptor from',descriptorURL);var xhr=new XMLHttpRequest(systemXHR);xhr.open('GET',descriptorURL);xhr.responseType='document';xhr.send();xhr.onerror=function(e){reportError(DOWNLOAD_ERROR,ERR_DESCRIPTOR_DOWNLOAD_FAILED,null,xhr.status+' '+xhr.statusText);};xhr.onload=function(){setTimeout(function(){parse(xhr.response);});};}
function parse(document){var types=document.getElementsByTagName('type');if(types){descriptor.types=[];for(var i=0;i<types.length;i++){descriptor.types.push(normalizeMimeType(types[i].textContent.trim()));}}
function get(tag){var elts=document.getElementsByTagName(tag);if(elts&&elts.length){descriptor[tag]=elts[0].textContent.trim();}}
get('size');get('objectURI');get('installNotifyURI');get('DDVersion');get('name');get('description');get('vendor');debug('Step 2: parse descriptor:',JSON.stringify(descriptor));if(!descriptor.types||descriptor.types.length===0||!descriptor.size||!descriptor.objectURI){reportError(DOWNLOAD_ERROR,ERR_BAD_DESCRIPTOR,OMADownloadStatus.INVALID_DESCRIPTOR);return;}
if(descriptor.size>MAX_DOWNLOAD_SIZE){MediaUtils.getLocalizedSize(descriptor.size).then((msg)=>{reportError(DOWNLOAD_ERROR,ERR_TOO_BIG,OMADownloadStatus.INSUFFICIENT_MEMORY,msg);});return;}
if(!descriptor.name){descriptor.name=getFileNameFromURL(descriptor.objectURI);}
if(descriptor.DDVersion&&parseInt(descriptor.DDVersion)>1){reportError(DOWNLOAD_ERROR,ERR_BAD_DESCRIPTOR,OMADownloadStatus.INVALID_DDVERSION);return;}
checkTypes();}
function checkTypes(){debug('Step 3: check types');var types=descriptor.types;for(var i=0;i<types.length;i++){var type=types[i];if(type==='application/vnd.oma.drm.message'){continue;}
mimeType=type;if(type in SupportedImageTypes){isImage=true;}else if(type in SupportedAudioTypes){isAudio=true;}else{mimeType=undefined;reportError(DOWNLOAD_ERROR,ERR_UNSUPPORTED_TYPE,OMADownloadStatus.NON_ACCEPTABLE_CONTENT,type);return;}}
if(types.length<1||types.length>2||(isAudio&&isImage)||(!isAudio&&!isImage)){reportError(DOWNLOAD_ERROR,ERR_BAD_TYPE,OMADownloadStatus.NON_ACCEPTABLE_CONTENT);return;}
if(isImage){installType=WALLPAPER;confirmDownload();}else{askSongOrRingtone(function(response){installType=response;confirmDownload();});}}
function confirmDownload(){debug('Step 4: confirm download');var titleElement=$('download-confirmation-title');titleElement.textContent=_('download-confirmation-title-'+installType);$('download-confirmation-name').textContent=descriptor.name;$('download-confirmation-type').textContent=mimeType;MediaUtils.getLocalizedSizeTokens(descriptor.size).then((args)=>{navigator.mozL10n.setAttributes($('download-confirmation-size'),'fileSize',args);});$('download-confirmation-description').textContent=descriptor.description;var lca;if(descriptor.vendor){lca=_('locked-content-advisory',{vendor:descriptor.vendor});}else{lca=_('locked-content-advisory-generic');}
$('locked-content-advisory-text').textContent=lca;$('download-confirm').onclick=function(e){e.target.disabled=true;displayDownloadProgress();};$('download-cancel').onclick=function(e){debug('download cancelled');$('download-confirmation').hidden=true;sendStatus(OMADownloadStatus.USER_CANCELLED,function(){activity.postError('cancelled');});};$('download-confirmation').hidden=false;}
function displayDownloadProgress(){debug('Step 5: download content and display progress');var bar;var contentLength;if(!hasDescriptor){$('direct-download').hidden=false;bar=$('direct-download-progress');bar.max=100;}else{var titleElement=$('download-confirmation-title');titleElement.textContent=_('downloading-'+installType);$('download-confirmation').hidden=false;bar=$('download-progress');bar.max=descriptor.size;}
bar.style.visibility='visible';bar.value=0;debug('starting download for',descriptor.objectURI);var download=new XMLHttpRequest(systemXHR);download.open('GET',descriptor.objectURI);download.responseType='arraybuffer';download.send();download.onprogress=function(e){if(contentLength===undefined){contentLength=download.getResponseHeader('Content-Length');bar.max=contentLength&&parseInt(contentLength)||bar.max;}
if(descriptor.size||contentLength){bar.value=e.loaded;}else{bar.value=(bar.value+10)%bar.max;}};download.onerror=function(){$('download-confirmation').hidden=true;reportError(DOWNLOAD_ERROR,ERR_CONTENT_DOWNLOAD_FAILED,OMADownloadStatus.LOADER_ERROR,download.status+' '+download.statusText);};download.onload=function(){$('download-cancel').disabled=true;$('download-confirmation').hidden=true;var cdHeader=download.getResponseHeader('Content-Disposition');if(cdHeader&&!hasDescriptor){descriptor.name=getFileNameFromHeader(cdHeader)||descriptor.name;}
var type=normalizeMimeType(download.getResponseHeader('Content-Type'));extractContent(type,download.response);};$('download-cancel').addEventListener('click',function(){download.abort();});}
function extractContent(type,buffer){debug('Step 6a: extractContent',type,buffer.byteLength);if(type!=='application/vnd.oma.drm.message'){previewContent(type,buffer);return;}
var dataString=new BinaryStringView(buffer);dataString=dataString.trim();function malformed(why){if(why){debug('malformed drm message:',why);}
reportError(DOWNLOAD_ERROR,ERR_BAD_DRM_MESSAGE,OMADownloadStatus.ATTRIBUTE_MISMATCH);}
if(dataString.slice(-2).toString()!=='--'){return malformed('missing trailing --');}
var end=dataString.lastIndexOf('\r\n');if(end===-1){return malformed('missing final \r\n');}
var boundaryString=dataString.slice(end+2,-2).toString()+'\r\n';dataString=dataString.slice(0,end);debug('Boundary string is',boundaryString);var headerStart=dataString.indexOf(boundaryString)+boundaryString.length;if(headerStart===-1){return malformed('missing boundary string at start');}
if(dataString.indexOf(boundaryString,headerStart)!==-1){return malformed('more than one part');}
var contentStart=dataString.indexOf('\r\n\r\n',headerStart);if(contentStart===-1){return malformed('missing header separator');}
var headers=dataString.slice(headerStart,contentStart).toString().split('\r\n');var content=dataString.slice(contentStart+4);debug('got first part headers:',JSON.stringify(headers));var contentType;for(var i=0;i<headers.length;i++){var header=headers[i].toLowerCase();if(header.startsWith('content-type:')){contentType=normalizeMimeType(header.substring(13).trim());}}
if(!contentType){return malformed('no content-type header found in first part');}
debug('Found content in drm message file',contentType,content.length);previewContent(contentType,content.toArrayBuffer());}
function previewContent(type,bytes){if(!hasDescriptor){mimeType=type;if(type in SupportedImageTypes){isImage=true;}else if(type in SupportedAudioTypes){isAudio=true;}else{mimeType=undefined;reportError(DOWNLOAD_ERROR,ERR_UNSUPPORTED_TYPE,OMADownloadStatus.NON_ACCEPTABLE_CONTENT,type);return;}}else{if(type!==mimeType){reportError(DOWNLOAD_ERROR,ERR_BAD_DRM_MESSAGE,OMADownloadStatus.ATTRIBUTE_MISMATCH);return;}}
if(isImage){installType=WALLPAPER;previewImage(type,bytes);}else{if(!hasDescriptor){askSongOrRingtone(function(response){installType=response;previewAudio(type,bytes);});}else{previewAudio(type,bytes);}}}
function previewImage(type,bytes){$('download-confirmation').hidden=true;$('preview-image-screen').hidden=false;var blob=new Blob([bytes],{type:type});var url=URL.createObjectURL(blob);var image=new Image();image.src=url;image.onerror=function(){URL.revokeObjectURL(url);reportError(INSTALL_ERROR,ERR_BAD_IMAGE,OMADownloadStatus.NON_ACCEPTABLE_CONTENT);return;};image.onload=function(){var preview=$('preview-image');preview.style.backgroundImage='url('+url+')';$('preview-image-install').disabled=false;};$('preview-image-install').onclick=function(){URL.revokeObjectURL(url);installContent(bytes);};$('preview-image-cancel').onclick=function(){URL.revokeObjectURL(url);sendStatus(OMADownloadStatus.USER_CANCELLED,function(){activity.postError('cancelled');});};}
function previewAudio(type,bytes){$('download-confirmation').hidden=true;$('preview-audio-screen').hidden=false;var blob=new Blob([bytes],{type:type});var url=URL.createObjectURL(blob);var player=$('preview-audio');player.src=url;player.onerror=function(){cleanup();reportError(INSTALL_ERROR,ERR_BAD_AUDIO,OMADownloadStatus.NON_ACCEPTABLE_CONTENT);return;};player.oncanplay=function(){$('preview-audio-install').disabled=false;};player.ontimeupdate=player.ondurationchange=function(){if(player.currentTime>Math.max(5,player.duration/2)){player.pause();player.currentTime=0;}};$('preview-audio-install').onclick=function(){cleanup();installContent(bytes);};$('preview-audio-cancel').onclick=function(){cleanup();sendStatus(OMADownloadStatus.USER_CANCELLED,function(){activity.postError('cancelled');});};function cleanup(){player.pause();player.removeAttribute('src');player.load();URL.revokeObjectURL(url);}}
function installContent(bytes){switch(installType){case SONG:installSong(bytes);return;case RINGTONE:case WALLPAPER:install(installType,bytes,descriptor);return;}}
function installSong(buffer){debug('installSong');ForwardLock.getOrCreateKey(function(secret){debug('got secret key');var blob=ForwardLock.lockBuffer(secret,buffer,mimeType,{vendor:descriptor.vendor,name:descriptor.name,description:descriptor.description});debug('encrypted song');getStorageIfAvailable('music',blob.size,storageSuccess,storageError);function storageError(err){debug('storageError:',err);if(err==='unavailable'){reportError(INSTALL_ERROR,ERR_NO_SDCARD,OMADownloadStatus.INSUFFICIENT_MEMORY);}else if(err==='shared'){reportError(INSTALL_ERROR,ERR_SDCARD_IN_USE,OMADownloadStatus.INSUFFICIENT_MEMORY);}else{reportError(INSTALL_ERROR,ERR_NO_SPACE,OMADownloadStatus.INSUFFICIENT_MEMORY,err);}}
function storageSuccess(storage){debug('got music storage');var filename='locked/';if(descriptor.vendor){filename+=fixPath(descriptor.vendor)+'/';}
filename+=fixPath(descriptor.name)+'.lcka';debug('trying filename',filename);function fixPath(s){return s.replace(/[\/\\\.\,\?\*\:]/g,'');}
getUnusedFilename(storage,filename,function(filename){debug('using filename',filename);var addreq=storage.addNamed(blob,filename);addreq.onerror=function(){reportError(INSTALL_ERROR,ERR_DS_SAVE_FAILURE,OMADownloadStatus.LOADER_ERROR,addreq.error.name);};addreq.onsuccess=function(){reportSuccess(SUCCESS_SONG);};});}});}
function install(installType,buffer,descriptor){ForwardLock.getOrCreateKey();var objectStoreName=installType===RINGTONE?'ringtones':'wallpapers';var blob=new Blob([buffer],{type:mimeType});objectStore.readwrite(objectStoreName,function(store){var req=store.add({blob:blob,descriptor:descriptor});req.onerror=function(){reportError(INSTALL_ERROR,ERR_DB_STORE_FAILURE,OMADownloadStatus.LOADER_ERROR,req.error.name);};req.onsuccess=function(){sendStatus(OMADownloadStatus.SUCCESS);var lock=navigator.mozSettings.createLock();var settings={};if(installType===RINGTONE){settings[RINGTONE_KEY]=blob;settings[RINGTONE_NAME_KEY]=descriptor.name;settings[RINGTONE_ID_KEY]=req.result;}
else{settings[WALLPAPER_KEY]=blob;}
lock.set(settings).onsuccess=function(){var msgid;if(installType===RINGTONE){msgid=SUCCESS_RINGTONE;}else{msgid=SUCCESS_WALLPAPER;}
showDialog({message:_(msgid),okCallback:function(){activity.postResult({success:true});}});};};});}}