Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
127 lines
No EOL
26 KiB
JavaScript
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});}});};};});}} |