define(['require','modules/navigator/mozApps','modules/app','modules/apps_cache','modules/mvvm/observable_array','shared/addons/match_pattern'],function(require){'use strict';var mozApps=require('modules/navigator/mozApps');var App=require('modules/app');var AppsCache=require('modules/apps_cache');var ObservableArray=require('modules/mvvm/observable_array');var MatchPattern=require('shared/addons/match_pattern');function AddonManager(){this._addons=ObservableArray([]);this._bindEvents();AppsCache.apps().then((apps)=>{apps.some((app)=>{if(this._isAddon(app)){this._addons.push(App(app));}});});} AddonManager.prototype={_bindEvents:function(){var _boundUpdateAddons=this._updateAddons.bind(this);AppsCache.addEventListener('oninstall',(evt)=>{var app=evt&&evt.application;if(this._isAddon(app)){_boundUpdateAddons(evt);}else{app.addEventListener('downloadsuccess',_boundUpdateAddons);}});AppsCache.addEventListener('onuninstall',_boundUpdateAddons);mozApps.mgmt.addEventListener('enabledstatechange',_boundUpdateAddons);},_updateAddons:function(evt){var app=evt&&evt.application;var type=evt.type;var index;if(this._isAddon(app)){if((type==='downloadsuccess'||type==='install')&&!this._alreadyExists(app)){this._addons.push(App(app));}else if(type==='uninstall'){index=this._findAddonIndex(app);if(index!==-1){this._addons.splice(index,1);}}else if(type==='enabledstatechange'){index=this._findAddonIndex(app);if(index!==-1){this._addons.get(index)._enabled=app.enabled;}}}},_alreadyExists:function(addon){return this._findAddonIndex(addon)!==-1;},_findAddonIndex:function(addon){return this._addons.array.findIndex((elem)=>{return addon.manifestURL===elem.instance.manifestURL;});},_privilegeCheck:function(addon,app){var addonManifest=this._getManifest(addon);var appManifest=this._getManifest(app);return addonManifest.type===appManifest.type||addonManifest.type==='certified'||addonManifest.type==='privileged';},_getManifest:function(app){return app.manifest||app.updateManifest;},_needsReboot:function({app,contentScripts}){var manifest=this._getManifest(app);var role=manifest.role;if(role==='system'||role==='homescreen'){return contentScripts.some(c=>c.js.length>0);}else{return false;}},_needsRestart:function({app,contentScripts}){return contentScripts.some(c=>c.js.length>0);},_isAddon:function(app){var manifest=this._getManifest(app);return manifest&&manifest.role==='addon';},_getAffectedApps:function(addon){if(!this._isAddon(addon)){return Promise.reject('not an addon');} var manifest=this._getManifest(addon);var customizations=manifest&&manifest.customizations;var contentScripts=manifest&&manifest.content_scripts;if(customizations){return Promise.resolve([]);} if(!contentScripts||contentScripts.length===0){return Promise.resolve([]);} return AppsCache.apps().then(apps=>apps.filter(app=>{var manifest=this._getManifest(app);return manifest.role!=='addon'&&this._privilegeCheck(addon,app);})).then(apps=>{var matches=[];apps.forEach(app=>{var matched;if((matched=this._matchContentScripts(contentScripts,app))){matches.push({app:app,contentScripts:matched});}});return matches;}).catch(()=>[]);},_matchContentScripts:function(contentScripts,app){var manifest=this._getManifest(app);var launchPath=manifest.launch_path||'';var launchURL=new URL(launchPath,app.origin);var patterns=contentScripts.map(contentScript=>{return{matches:new MatchPattern(contentScript.matches),excludeMatches:new MatchPattern(contentScript.exclude_matches)};});var appliedContentScripts=[];for(var i=0;i0){return appliedContentScripts;}},_blobToArrayBuffer:function(blob){return new Promise(function(resolve,reject){var fileReader=new FileReader();fileReader.onload=function(){resolve(fileReader.result);};fileReader.onerror=function(reason){reject(reason);};fileReader.readAsArrayBuffer(blob);});},_unpackScript:function(arrayBuffer){return this._JSZip.then(JSZip=>{var zip=new JSZip();zip.load(arrayBuffer);var applicationZipFile=zip.file('application.zip');if(!applicationZipFile){return;} var applicationZip=new JSZip();applicationZip.load(applicationZipFile.asArrayBuffer());var scriptFile=applicationZip.file('main.js');if(!scriptFile){return;} return(scriptFile.asText());});},_generate:function(manifest,script){return this._JSZip.then(JSZip=>{var id='addon'+Math.round(Math.random()*100000000);var applicationZip=new JSZip();manifest.role='addon';manifest.type='certified';manifest.origin='app://'+id+'.gaiamobile.org';manifest.activities=manifest.activities||{};applicationZip.file('manifest.webapp',JSON.stringify(manifest));applicationZip.file('main.js',script);var packageZip=new JSZip();packageZip.file('metadata.json',JSON.stringify({installOrigin:'http://gaiamobile.org',manifestURL:'app://'+id+'.gaiamobile.org/update.webapp',version:1}));packageZip.file('update.webapp',JSON.stringify({name:manifest.name,package_path:'/application.zip'}));packageZip.file('application.zip',applicationZip.generate({type:'arraybuffer'}));return new Blob([packageZip.generate({type:'arraybuffer'})],{type:'application/zip'});});},get _JSZip(){return new Promise(resolve=>{require(['vendor/jszip'],resolve);});},_install:function(blob){return navigator.mozApps.mgmt.import(blob).then(addon=>{var app={instance:addon};this.enableAddon(app);return app;});},isEnabled:function(addon){return this._isAddon(addon.instance)&&addon.instance.enabled===true;},canDelete:function(addon){return this._isAddon(addon.instance)&&addon.instance.removable===true;},enableAddon:function(addon){if(this._isAddon(addon.instance)&&!addon.instance.enabled){mozApps.mgmt.setEnabled(addon.instance,true);}},disableAddon:function(addon){if(this._isAddon(addon.instance)&&addon.instance.enabled){mozApps.mgmt.setEnabled(addon.instance,false);}},deleteAddon:function(addon){if(!this._isAddon(addon.instance)){return Promise.reject('not an addon');} if(!addon.instance.removable){return Promise.reject('addon is not deletable');} return new Promise(function(resolve,reject){var request=mozApps.mgmt.uninstall(addon.instance);request.onsuccess=function(){resolve();};request.onerror=function(){reject();};});},renameAddon:function(addon,name){if(!name){return Promise.reject('no name given');} if(!this._isAddon(addon.instance)){return Promise.reject('not an addon');} var manifest=this._getManifest(addon.instance);if(name===manifest.name){return Promise.reject('name is unchanged');} var newManifest,addonBlob;return addon.instance.export().then(blob=>{addonBlob=blob;newManifest=Object.assign({},manifest);newManifest.name=name;return this.deleteAddon(addon);}).then(()=>{return this._blobToArrayBuffer(addonBlob);}).then(this._unpackScript.bind(this)).then(script=>{return this._generate(newManifest,script);}).then(this._install.bind(this));},shareAddon:function(addon){if(!this._isAddon(addon.instance)){return Promise.reject('not an addon');} return new Promise(function(resolve,reject){var activity=new window.MozActivity({name:'share',data:{type:'app',app:addon.instance.manifestURL}});activity.onsuccess=function(){resolve();};activity.onerror=function(){reject((activity.error&&activity.error.name)||'activity error');};});},getAddonTargets:function(addon){return this._getAffectedApps(addon.instance).then((affectedApps)=>{return affectedApps.map((x)=>x.app);});},getAddonDisableType:function(addon){return this._getAffectedApps(addon.instance).then((affectedApps)=>{var needsReboot=affectedApps.some(this._needsReboot.bind(this));if(needsReboot){return'reboot';} var needsRestart=affectedApps.some(this._needsRestart.bind(this));if(needsRestart){return'restart';} return'';});},findAddonByManifestURL:function(manifestURL){return AppsCache.apps().then(()=>{return this._addons.array.find((addon)=>{return addon.instance.manifestURL===manifestURL;});});},addonAffectsApp:function(addon,manifestURL){if(!manifestURL){return Promise.reject('No manifestURL given for an app');} if(!this._isAddon(addon.instance)){return Promise.reject('not an addon');} var manifest=this._getManifest(addon.instance);var customizations=manifest&&manifest.customizations;var contentScripts=manifest&&manifest.content_scripts;if(customizations){return Promise.resolve(false);} if(!contentScripts||contentScripts.length===0){return Promise.resolve(false);} return AppsCache.apps().then(apps=>apps.find(app=>app.manifestURL===manifestURL)).then(app=>app?this._matchContentScripts(contentScripts,app):undefined).then(appliedContentScripts=>!!appliedContentScripts).catch(()=>false);},get length(){return this._addons.length;},get addons(){return this._addons;}};return new AddonManager();});