Advertisement
Guest User

Untitled

a guest
Jun 16th, 2016
409
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. 1.
  2. var DEV=0,CFG={URL:{ROOT:DEV?"http://brwsr.local":"https://distill.io",API:DEV?"http://api.brwsr.local/v1":"https://api.distill.io/v1",BROADCAST:DEV?"http://broadcast.brwsr.local":"https://broadcast.distill.io",STATIC:DEV?"http://brwsrcdn.local":"https://brwsrcdn.com",WELCOME:"https://distill.freshdesk.com/support/solutions/articles/188306-getting-started-with"},VERSION:"1.5.0"};CFG.URL.BASE=chrome.runtime.getURL("");CFG.URL.CHANGELOG=CFG.URL.BASE+"changelog.html";CFG.URL.WELCOME=CFG.URL.ROOT+"/help/gettingstarted/chrome";CFG.URL.BLANK=CFG.URL.BASE+"blank.html";CFG.CLIENT={TYPE:11,NAME:"chrome",INFO:"Google Chrome"};var ID=function(x){return function(){return x++}}(1);var DBG=0;function S4(){return((1+Math.random())*65536|0).toString(16).substring(1)}function guid(){return S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4()}function makeURLChecker(baseUrl){var parts=baseUrl.split("/");parts[0]="^(http|https):";var re=new RegExp(parts.join("\\/"),"i");return function check(href){return re.test(href)}}var isUs=makeURLChecker(CFG.URL.ROOT);var Supports={tabForXFrame:true};const C={TYPE_ERR:0,TYPE_TEXT:1,TYPE_HTML:2,TYPE_JSON:3,TYPE_XML:4,TYPE_FEED:5,TYPE_FORM:6,TYPE_PDF_HTML:7,TYPE_RULE:1,TYPE_RULE_GROUP:2,OP_AND:1,OP_OR:2,CONTENT_TYPE_TEXT:1,CONTENT_TYPE_CHANGED_TEXT:2,RULE_NOT_EMPTY:1,RULE_HAS_TEXT:2,RULE_HAS_TEXT_NOT:3,RULE_HAS_NUMBER_LT:4,RULE_HAS_NUMBER_GT:5,RULE_HAS_NUMBER_DECR_MIN:6,RULE_HAS_NUMBER_INCR_MIN:7,RULE_MATCH_REGEX:8,RULE_HAS_NUMBER_DECR_PERCENT_MIN:9,RULE_HAS_NUMBER_INCR_PERCENT_MIN:10,STATE_DEFAULT:0,STATE_NEW:10,STATE_INIT:20,STATE_UNAUTHORIZED:30,STATE_AUTHORIZED:35,STATE_READY:40,STATE_RESTRICTED:50,STATE_DISCARD:90,STATE_DEL:100,STATE_DONE:100,STATE_ATTR_VERIFY:10,STATE_ATTR_VERIFY_INIT:20,STATE_ATTR_VERIFY_WAIT:30,STATE_ATTR_VERIFY_DONE:40,ACTION_EMAIL:1,ACTION_SMS:2,ACTION_PUSH:3,ACTION_MACRO:4,ACTION_WEBHOOK:5,ACTION_LOCAL_AUDIO:101,ACTION_LOCAL_POPUP:102,RUN_STATE_INIT:1,RUN_STATE_WAIT:2,RUN_STATE_WIP:3,LOCAL_STATE_SYNCED:0,LOCAL_STATE_POST:1,LOCAL_STATE_POST_ERR:10,LOCAL_STATE_PUT:2,LOCAL_STATE_PUT_ERR:20,LOCAL_STATE_DEL:3,LOCAL_STATE_DEL_ERR:30,CLIENT_FF:10,CLIENT_CR:11,CLIENT_OP:12,CLIENT_SF:13,CLIENT_CRAPP:14,CLIENT_MAC:20,TIME_INFINITE:2592e3};_.templateSettings={interpolate:/\{\{(.+?)\}\}/g};function errFmt(str){return function(data){return str.replace(/\{\{(\w*)\}\}/g,function(x,key){return data[key]||""})}}function Err(code,msg,defaults){var tpl=errFmt(msg),maker=function(data){_.defaults(data,defaults);var err={code:code,msg:tpl(data),data:data};return err};maker.si=function(err){return code===err.code};return maker}_.extend(Err,{ABORT:Err("ABORT","Activity aborted!"),NOT_FOUND:Err("NOT_FOUND","{{type}} not found with {{param}} {{id}}.",{param:"id"}),PARAM_INVALID:Err("PARAM_INVALID","Invalid {{param}}, got: {{value}}"),PARAM_NOT_FOUND:Err("PARAM_NOT_FOUND","{{param}} not found."),PORT_WEB_REQUEST_NA:Err("PORT_WEB_REQUEST_NA","Request cannot be served."),TIMEOUT:Err("TIMEOUT","{{type}} timedout after {{time}} seconds."),TYPE_UNNOWN:Err("TYPE_UNNOWN","{{type}} of unknown type: {{value}}"),UNHANDLED:function(e){return{code:"UNHANDLED",msg:e.toString(),data:e.stack}},AUTH_NA:Err("AUTH_NA","Account authentication details are not available."),SELECTION_EMPTY:Err("SELECTION_EMPTY","Selection did not match any content")});var gEvents=_.extend({},Backbone.Events);function createEventSource(callback){HTTP.request({url:CFG.URL.BROADCAST+"/temp_token",method:"POST",headers:apiHeaders()},function(err,res,xhr){if(err){callback(err,res)}else{var source=new EventSource(CFG.URL.BROADCAST+"/events/"+res.token);callback(null,source)}})}var REGEX_CHARS_SPECIAL="*.?^$[]{}()/+,:|!".split("").map(function(chr){return[new RegExp("\\"+chr,"g"),"\\"+chr]});function wildcardMatch(pattern,str){var expr=pattern.split("*").map(function(block){REGEX_CHARS_SPECIAL.forEach(function(replacer){block=block.replace(replacer[0],replacer[1])});return block}).join(".*");var regex=new RegExp("^"+expr+"$");return regex.test(str)}function getHostname(url){return url.split("/")[2]}var NotifyAudio=function(){function defaultSrc(){return"/skin/media/bell_strike.ogg"}return{play:function(action){var src=action&&action.config&&action.config.tone||defaultSrc(),player=new Audio;if(src.indexOf("tone:")==0){KVStore.findOne(src,function(err,doc){play(doc.value)})}else{play(src)}function play(src){player.src=src;player.play()}}}}();var NotifyPopup=typeof webkitNotifications=="undefined"?function(){chrome.notifications.onButtonClicked.addListener(function(notificationId,btnIndex){var id=notificationId.split(":")[0];service.markReadById(id);chrome.notifications.clear(notificationId)});chrome.notifications.onClicked.addListener(function(notificationId){var id=notificationId.split(":")[0];service.openAndMarkRead(id);chrome.notifications.clear(notificationId)});chrome.notifications.onShowSettings.addListener(function(){});return{hide:function(){},show:function(action,context){PopupMessageStore.create({rel:SieveStore.name,key:context.sieve.id,uri:context.sieve.uri,title:context.sieve.name},function(err,msg){var title=context.sieve.name,body=context.sieve_data.text;body=body.length>70?body.substring(0,70)+"...":body;chrome.notifications.create(context.sieve.id+":"+msg.id,{type:"basic",title:msg.title,message:context.sieve_data.text,iconUrl:"ui/img/distill_128.png",buttons:[{title:"Mark as Read"}]},function(notificationId){})})}}}():function(){var popup;return{hide:function(){popup&&popup.cancel();popup=null},show:function(action,context){popup&&popup.cancel();PopupMessageStore.create({rel:SieveStore.name,key:context.sieve.id,uri:context.sieve.uri,title:context.sieve.name},function(err,msg){var title=context.sieve.name,body=context.sieve_data.text;body=body.length>70?body.substring(0,70)+"...":body;popup=webkitNotifications.createNotification("/ui/img/distill_48.png",title,body);popup.onclose=function(){if(popup){popup.onclose=popup.onclick=null;popup=null}};popup.onclick=function(){service.openAndMarkRead(context.sieve.id,function(){popup.cancel()})};popup.show()})}}}();var DATE_0=new Date(0);var DAYS=[0,1,2,3,4,5,6];var DAY_NAMES=["SUN","MON","TUE","WED","THU","FRI","SAT"];TypeDescriptors={DURATION:{desc:"Duration expressed in milliseconds",validate:function(value,cb){if(_.isNumber(value)&&!_.isNaN(value))cb(null);else cb({code:"ADEX00X",data:"Value is not a number:"+value})},type:"Number"},JavaScript:{desc:"JavaScript code",validate:function(value,cb){return cb({code:"ADEX0000000X",desc:"Not implemented"})},type:"String"},REGEX:{desc:"Regular Expression definition",descriptors:[{desc:"Regular expression",must:true,name:"expression",type:"String"},{"default":"im",desc:"Regular expression flags",must:false,name:"flags",type:"String"}],validate:function(value,cb){return cb({code:"ADEX0000000X",desc:"Not implemented"})},type:"Object"},URL:{desc:"Specifies a valid URL",validate:function(value,cb){return cb({code:"ADEX0000000X",desc:"Not implemented"})},type:"String"},WEBPAGE_LOCATOR:{desc:"A locator is used to pick elements from a webpage",descriptors:[{desc:"Index of window wrt to root window for evaluating locator",must:false,name:"windowIndex",type:"Number"},{desc:"Type of locator",must:true,name:"type",type:"String"},{desc:"Locator expression",must:true,name:"expr",type:"String"}],validate:function(value,cb){return cb({code:"ADEX0000000X",desc:"Not implemented"})},type:"Object"},WEEKLY_SCHEDULE:{desc:"Represents time in a week wrt. from Sunday",descriptors:[{desc:"Day in a week",many:true,must:true,name:"days",type:"DAY",vals:DAYS},{desc:"Time since beginning of the day",must:true,name:"time",type:"TIME"}],validate:function(value,cb){cb(null)},type:"Object"}};ActionDescriptors={};ActionDescriptors[C.ACTION_EMAIL]={descriptors:[{desc:"Template for subject",name:"subject",type:"STRING_TEMPLATE"},{desc:"Template for email body",name:"body",type:"HTML_TEMPLATE"}],act:function alert_email(action,context,cb){ActionEmail.send(action,context,cb)}},ActionDescriptors[C.ACTION_LOCAL_POPUP]={descriptors:[],act:function(action,context,cb){if(Prefs.get("actions.popup",true)){NotifyPopup.show(action,context)}cb()}};ActionDescriptors[C.ACTION_PUSH]={descriptors:[],act:function(action,context,cb){ActionPush.send(action,context,cb)}};ActionDescriptors[C.ACTION_SMS]={descriptors:[{}],act:function(action,context,cb){ActionSMS.send(action,context,cb)}};ActionDescriptors[C.ACTION_WEBHOOK]={descriptors:[],act:function(action,context,cb){ActionWebhook.send(action,context,cb)}};ActionDescriptors[C.ACTION_LOCAL_AUDIO]={descriptors:[{desc:"Name or URL of the file to play audio",must:true,name:"src",type:"SRC"},{desc:"Playback duration",must:false,name:"duration",type:"DURATION"}],act:function(action,context,cb){if(Prefs.get("actions.audio",true)){NotifyAudio.play(action,context)}cb()}};ScheduleDescriptors={undefined:{getSchedule:function(cfg,logs){return-1}},LIVE:{getSchedule:function(){return 0}},INTERVAL:{descriptors:[{desc:"The interval at which task should be scheduled.",name:"interval",type:"DURATION"}],getSchedule:function(cfg,logs){var checkedOn,lastCheckedOn,interval=cfg.interval,now=Date.now()/1e3|0;if(_.isUndefined(interval)){return-1}if(interval>=C.TIME_INFINITE){return-1}checkedOn=_.map(logs,function(log){return new Date(log.ts)});lastCheckedOn=(_.max(checkedOn)||DATE_0).valueOf()/1e3|0;if(logs.length>0&&logs[0].err){var errs=_.pluck(logs,"err"),indexNull=_.indexOf(errs,null);if(indexNull>=0){return lastCheckedOn+Math.min(120,interval)}}return Math.max(now,lastCheckedOn+interval)+1}},WEEKLY:{descriptors:[{desc:"A set of times at which the task will be executed.",many:true,must:true,name:"triggers",type:"WEEKLY_SCHEDULE"}],getSchedule:function(cfg,logs){var checkedOn,dateNextWeek,datePrevWeek,lastCheckedOn,nextCheckDate,now,now0,prevCheckDate,scheduleDates;now=new Date;now0=new Date(now);now0.setHours(0);now0.setMinutes(0);now0.setSeconds(0);checkedOn=_.map(logs,function(log){return new Date(log.ts)});scheduleDates=_.reduce(cfg.triggers,function(all,trigger){var time0;time0=new Date(now0);time0.setSeconds(trigger.time/1e3);_.each(trigger.days,function(day){var time;time=new Date(time0);time.setDate(time.getDate()+day-time.getDay());return all.push(time)});return all},[]);scheduleDates.sort();dateNextWeek=_.first(scheduleDates);dateNextWeek.setDate(dateNextWeek.getDate()+7);scheduleDates.push(dateNextWeek);datePrevWeek=_.last(scheduleDates);datePrevWeek.setDate(datePrevWeek.getDate()-7);scheduleDates.unshift(datePrevWeek);lastCheckedOn=_.first(checkedOn)||DATE_0;nextCheckDate=_.detect(scheduleDates,function(date){return date>=now});scheduleDates.reverse();prevCheckDate=_.detect(scheduleDates,function(date){return date<nextCheckDate});scheduleDates.reverse();if(lastCheckedOn<prevCheckDate){return(now.valueOf()/1e3|0)+1}else{return(nextCheckDate.valueOf()/1e3|0)+1}}}};ResultProcessors={WEBPAGE:{DOM:{descriptors:[{"default":true,desc:"Filter content text",name:"filtertext"}],changes:function(dold,dnew,cb){var seq1=_.filter(dold.data.split(/\s/),filterEmpty),seq2=_.filter(dnew.data.split(/\s/),filterEmpty),matcher=new difflib.SequenceMatcher(seq1,seq2),opcodes=matcher.get_opcodes(),changes=opcodes.length==0?null:getChanges();cb(null,changes);function filterEmpty(x){return!!x}function getChanges(){var ins=[],del=[],summ=[];_.each(opcodes,function(op){var _n=seq2.slice(op[3],op[4]).join(" "),_o=seq1.slice(op[1],op[2]).join(" ");if(op[0]=="replace"){del.push(_o);ins.push(_n);summ.push("<ins>",_.escape(_n),"</ins>")}else if(op[0]=="insert"){ins.push(_n);summ.push("<ins>",_.escape(_n),"</ins>")}else if(op[0]=="delete"){del.push(_o)}else{summ.push(_o)}});return{del:del,ins:ins,summ:summ.join(" ")}}}}}};function matchRule(context){var rule=context.rule,config=rule&&JSON.parse(rule.config);return!config||matchRuleConfig(config,context.inserts,context.dels,context.items[0].text,(context.items[1]||{}).text||"")}function matchRuleConfig(config,inserts,dels,text,oldText){if(config.type==C.TYPE_RULE){return matchRule_RULE(config,inserts,dels,text,oldText)}else if(config.type==C.TYPE_RULE_GROUP){return matchRule_RULE_GROUP(config,inserts,dels,text,oldText)}else{DBG&&console.error("unknown type of rule config: ",config);return false}}function containsText(string,text){return string.toLowerCase().indexOf((text||"").toLowerCase())>=0}function matchRule_RULE(config,inserts,dels,text,oldText){var content=text,oldContent=oldText,matched=false,numbers,oldNumbers,rule=config.rule,params=rule.params;if(config.contentType==C.CONTENT_TYPE_CHANGED_TEXT){content=inserts;oldContent=dels}switch(rule.type){case C.RULE_NOT_EMPTY:matched=!_.isEmpty(content);break;case C.RULE_HAS_TEXT:matched=containsText(content,params.input);break;case C.RULE_HAS_TEXT_NOT:matched=!containsText(content,params.input);break;case C.RULE_HAS_NUMBER_LT:numbers=findNumbers(content);matched=_.any(numbers,function(num){return num<params.input});break;case C.RULE_HAS_NUMBER_GT:numbers=findNumbers(content);matched=_.any(numbers,function(num){return num>params.input});break;case C.RULE_HAS_NUMBER_DECR_MIN:numbers=findNumbers(content);oldNumbers=findNumbers(oldContent);for(var i=Math.min(numbers.length,oldNumbers.length)-1;i>=0;i-=1){if(oldNumbers[i]-numbers[i]>params.input){matched=true;break}}break;case C.RULE_HAS_NUMBER_INCR_MIN:numbers=findNumbers(content);oldNumbers=findNumbers(oldContent);for(var i=Math.min(numbers.length,oldNumbers.length)-1;i>=0;i-=1){if(numbers[i]-oldNumbers[i]>params.input){matched=true;break}}break;case C.RULE_HAS_NUMBER_DECR_PERCENT_MIN:numbers=findNumbers(content);oldNumbers=findNumbers(oldContent);for(var i=Math.min(numbers.length,oldNumbers.length)-1;i>=0;i-=1){var percentChange=(oldNumbers[i]-numbers[i])*100/oldNumbers[i];if(percentChange>params.input){matched=true;break}}break;case C.RULE_HAS_NUMBER_INCR_PERCENT_MIN:numbers=findNumbers(content);oldNumbers=findNumbers(oldContent);for(var i=Math.min(numbers.length,oldNumbers.length)-1;i>=0;i-=1){var percentChange=(numbers[i]-oldNumbers[i])*100/oldNumbers[i];if(percentChange>params.input){matched=true;break}}break;case C.RULE_MATCH_REGEX:matched=content.match(new RegExp(params.input.expr,params.input.flags));break;default:return false}return matched}function matchRule_RULE_GROUP(config,inserts,dels,text,oldText){return!config.rules||config.rules.length===0||_[config.op==C.OP_AND?"all":"any"](config.rules,function(ruleConfig){return matchRuleConfig(ruleConfig,inserts,dels,text,oldText)})}function findNumbers(text){var matches=text.match(/-*[0-9,.\s]+/g)||[];var numbers=[];for(var i=0,len=matches.length;i<len;i+=1){var a_num=matches[i];if(a_num.length>0){a_num=parseFloat(a_num.replace(/([\s,]*)/g,""));if(!isNaN(a_num)){numbers.push(a_num)}}}return numbers}const MSG_INIT=1,MSG_EVENT=2,MSG_REQUEST=3,MSG_RESPONSE=4,MSG_LOG=5;function SimplePort(port){var self=this,callbacks={},id=ID(),requestHandler;_.extend(self,Backbone.Events);self.id=id;self.port=port;self.destroy=destroy;self.postMessage=postMessage;self.sendEvent=sendEvent;self.sendRequest=sendRequest;self.setRequestHandler=setRequestHandler;port.onMessage.addListener(onMessage);port.onDisconnect.addListener(onUnload);function destroy(){if(!self)return;_.each(callbacks,function(cb,id){try{DBG&&console.warn("EXTN:SimplePort: Request did not complete.",id,cb.msg);cb.fn("Callback request did not complete.")}catch(e){DBG&&console.error("EXTN:SimplePort: error in callback: -- ",self.id,e,e.stack);DBG&&console.error(e)}delete callbacks[id]});sendEvent("destroy");self.trigger("disconnect",self);self.off();self.stopListening();callbacks=null;self=null;port&&port.disconnect()}function onMessage(msg){if(msg.type==MSG_REQUEST){var id=msg._id,input=msg.data,path=msg.path;if(requestHandler){requestHandler(path,input,function(err,data){if(!port)return;port.postMessage({_id:id,type:MSG_RESPONSE,data:data,err:err})})}else{port.postMessage({_id:id,type:MSG_RESPONSE,err:Err.UNHANDLED(new Error("Request handler not set"))})}}else if(msg.type==MSG_RESPONSE){var id=msg._id,cb=callbacks[id];delete callbacks[id];cb.fn(msg.err,msg.data)}else if(msg.type==MSG_EVENT){var event=msg.data,newType="port:"+event.type;self.trigger(newType,_.extend({},event,{type:newType}))}else{DBG&&console.error("EXTN:SimplePort:Unhandled message: <- ",id,msg)}}function onUnload(){port=null;destroy()}function postMessage(msg){port.postMessage(msg)}function sendEvent(name,event){port&&port.postMessage({data:{event:event,type:name},type:MSG_EVENT})}function sendRequest(path,data,cb){if(typeof data=="function"){cb=data;data=null}var msg={_id:ID(),data:data,path:path,type:MSG_REQUEST};callbacks[msg._id]={fn:cb,msg:msg};port.postMessage(msg)}function setRequestHandler(handler){requestHandler=handler}}function LoaderPort(port,attrs){var self=this,callbacks={};_.extend(self,Backbone.Events);self.attrs=attrs;self.id=ID();self.port=port;self.name=port.name;self.ready=false;self.uri=attrs.uri;self.destroy=destroy;self.isRoot=isRoot;self.sendEvent=sendEvent;self.sendRequest=sendRequest;port.onMessage.addListener(onMessage);port.onDisconnect.addListener(onUnload);port.postMessage({type:"content:load",scripts:["lib/underscore.js","content/content.js","content/port-ready.js"]});function destroy(){if(!self)return;_.each(callbacks,function(cb,id){try{DBG&&console.warn("PORT: Request did not complete.",attrs.uri,id,cb.msg);cb.fn("Callback request did not complete.")}catch(e){DBG&&console.error("PORT: error in callback: -- ",self.id,e,e.stack)}delete callbacks[id]});self.trigger("disconnect",self);self.off();self.stopListening();callbacks=null;self=null;port&&port.disconnect()}function isRoot(){return attrs.root||attrs.parent&&attrs.parent.id==="BG"}function onContentMessage(msg){msg.uri=self.attrs.uri;if(msg.type==MSG_RESPONSE){var id=msg._id,cb=callbacks[id];delete callbacks[id];cb.fn(msg.err,msg.data)}else if(msg.type==MSG_EVENT){var event=msg.data,newType="window:"+event.type;self.trigger(newType,_.extend({},event,{type:newType}))}else{DBG&&console.error("PORT: Unhandled message: <- ",id,msg)}}function onMessage(msg){switch(msg.type){case"port:ready":self.ready=true;self.title=msg.data.title;self.trigger("ready",self);break;case"content":onContentMessage(msg.data);break;default:DBG&&console.error("EXTN:LoaderPort:Unhandled message:",msg);break}}function onUnload(){port=null;destroy()}function postMessage(msg){port.postMessage({type:"content",data:msg})}function sendEvent(name,event){postMessage({data:{event:event,type:name},type:MSG_EVENT})}function sendRequest(path,data,cb){if(typeof data=="function"){cb=data;data=null}var msg={_id:ID(),data:data,path:path,type:MSG_REQUEST};callbacks[msg._id]={fn:cb,msg:msg};postMessage(msg)}}function StaticLocaderPort(loader,options){var self=this,id=ID(),ID_BRIDGE="sentinel-bridge",iframe=loader.iframe,doc=iframe.contentDocument,uri=loader.url,win=iframe.contentWindow,callbacks={},loading={};this.data={href:loader.url};this.id=id;this.uri=uri;this.destroy=destroy;this.sendEvent=sendEvent;this.sendRequest=sendRequest;this.isRoot=function(){return true};_.extend(this,Backbone.Events);win.addEventListener("unload",onUnload,true);onReady();win.loadScript=_loadScript;function _loadScript(path){return loading[path]||(loading[path]=new Promise(function(resolve,reject){var xhr=new XMLHttpRequest;xhr.open("GET",path);xhr.onerror=function(e){reject(Error("XHR onerror: "+e))};xhr.onload=function(e){try{(function(){win.eval(xhr.responseText)}).call(win);resolve()}catch(e){DBG&&console.error("Error loading script: ",path,e);reject(e)}};xhr.send()}))}function onReady(){win.addEventListener("DistillEventWeb",onMessage,true);win.addEventListener("DistillEventWebReady",ready,true);var promise=Promise.resolve();["lib/underscore.js","content/content.js","content/port-ready.js"].map(function(src){return chrome.runtime.getURL("")+src}).forEach(function(path){promise=promise.then(function(){return _loadScript(path)})})}function destroy(){if(!self)return;_.each(callbacks,function(cb,id){try{DBG&&console.warn("PORT: Request did not complete.",uri,id,cb.msg);cb.fn("Callback request did not complete.")}catch(e){DBG&&console.error("PORT: error in callback: -- ",self.id,e)}delete callbacks[id]});win.removeEventListener("DistillEventWeb",onMessage,true);win.removeEventListener("unload",destroy,true);self.trigger("disconnect",self);self.off();self.stopListening();doc=null;win=null;callbacks=null;self=null}function onMessage(e){var bridge=doc.getElementById(ID_BRIDGE);if(!bridge){DBG&&console.error("Message from content with null bridge from: ",uri);return}var msg=JSON.parse(bridge.textContent);bridge.textContent="";msg.uri=win.location.href;if(msg.type==MSG_RESPONSE){var id=msg._id;var cb=callbacks[id];delete callbacks[id];cb.fn(msg.err,msg.data)}else if(msg.type==MSG_EVENT){var event=msg.data;var newType="window:"+event.type;self.trigger(newType,_.extend({},event,{type:newType}))}else{DBG&&console.error("PORT: Unhandled message: <- ",id,msg)}}function onUnload(){destroy()}function postMessage(msg){var bridge=doc.getElementById(ID_BRIDGE);if(!bridge){DBG&&console.error("EXTN:PORT:postMessage: bridge is null. ",msg,uri);return}bridge.textContent=JSON.stringify(msg);var event=doc.createEvent("Event");event.initEvent("DistillEventExt",true,true);win.dispatchEvent(event)}function ready(){_.each(_.toArray(doc.getElementsByClassName("alertdocontent")),function(el){el.parentNode.removeChild(el)});self.ready=true;self.trigger("ready",self)}function sendEvent(name,event){try{postMessage({data:{event:event,type:name},type:MSG_EVENT})}catch(e){DBG&&console.error(e)}}function sendRequest(path,data,cb){if(typeof data=="function"){cb=data;data=null}var msg={_id:ID(),data:data,path:path,type:MSG_REQUEST};callbacks[msg._id]={fn:cb,msg:msg};postMessage(msg)}}chrome.tabs.query||(chrome.tabs.query=function(qi,callback){chrome.windows.getAll({populate:true},function(windows){callback(windows.reduce(function(redux,window){return redux.concat(window.tabs.filter(function(tab){return filterTab(window,tab)}))},[]))});function filterTab(window,tab){return(qi.selected===undefined||qi.selected===tab.selected)&&(qi.pinned===undefined||qi.pinned===tab.pinned)&&(qi.highlighted===undefined||qi.highlighted===tab.highlighted)&&(qi.status===undefined||qi.status===tab.status)&&(qi.title===undefined||wildcardMatch(qi.title,tab.title))&&(qi.url===undefined||wildcardMatch(qi.url,tab.url))&&(qi.windowId===undefined||qi.windowId===window.id)&&(qi.windowType===undefined||qi.windowType===window.type)}});var DEFAULT_LIMIT=20;function SimpleStore(name){this.name=name;var store=this.storage.getItem(this.name);this.data=store&&JSON.parse(store)||{}}_.extend(SimpleStore.prototype,Backbone.Events,{defaults:{},storage:localStorage,__init__:function(callback){callback()},del:function(key){var value=this.data[key];delete this.data[key];this.save();return value},getDefault:function(key){return this.defaults[key]},get:function(key,defaultValue){var value=this.data[key];return value!==void 0?value:arguments.length>1?defaultValue:this.getDefault(key)},save:function(){this.storage.setItem(this.name,JSON.stringify(this.data))},set:function(key,value){var oldValue=this.data[key];if(oldValue!==value){this.data[key]=value;this.save();this.trigger("change:"+key,value,oldValue,key);gEvents.trigger("change:pref:"+key,value,oldValue,key)}}});Prefs=new SimpleStore("prefs");if(!Prefs.get("since"))Prefs.set("since",{time:new Date,version:CFG.VERSION});function execQuery(sql,values,options,callback){if(_.isFunction(options)){callback=options;options=null}if(_.isFunction(values)){callback=values;options=null;values=null}options||(options={});var rows=[],isSelect=sql.slice(0,6)=="SELECT";SQLStore.db.transaction(function(tx){tx.executeSql(sql,values,function(tx,result){if(options.count){callback(null,result.rows.item(0))}else if(isSelect){var rows=result.rows,len=rows.length,newRows=new Array(len);for(var i=0;i<len;i+=1){newRows[i]=_.clone(rows.item(i))}callback(null,newRows)}else{callback(null,_.pick(result,"length"))}},function(tx,err){callback({code:"SQL:"+err.code,message:err.message})})})}function openConnection(name,callback){SQLStore.db=openDatabase(name,1,"Distill data store",1e3*1024*1024);callback()}function tableCreate(store,callback){var sql=Statements.createTable(store);execQuery(sql,function(err){if(err){callback(err)}else{MaintLog.create({name:store.name,version:store.versions[store.versions.length-1].version},callback)}})}function tableUpgradeFromVersion(store,currentVersion,callback){var versions=store.versions,indexCurrent=_.indexOf(versions,_.findWhere(versions,{version:currentVersion})),currentVersions=_.first(versions,indexCurrent+1),newVersions=_.rest(versions,indexCurrent+1);if(indexCurrent<0||newVersions.length==0){throw new Error("Incorrect version to upgrade from: "+currentVersion)}async.series([function(callback){execQuery("ALTER TABLE "+store.name+" RENAME to _tmp_",callback)},function(callback){tableCreate(store,callback)},function(callback){var unchangedFields=_.flatten(_.pluck(currentVersions,"fields")),unchangedFieldNames=_.pluck(unchangedFields,"name"),newOrRenamedFields=_.flatten(_.pluck(newVersions,"fields")),newOrRenamedFieldNames=_.pluck(newOrRenamedFields,"name"),renamedFields=_.filter(newOrRenamedFields,function(field){return field.oldName}),renamedOldNames=_.pluck(renamedFields,"oldName"),renamedNewNames=_.pluck(renamedFields,"name"),oldSelectFields=unchangedFieldNames.concat(renamedOldNames).join(","),newInsertFields=unchangedFieldNames.concat(renamedNewNames).join(",");execQuery("INSERT INTO "+store.name+" ("+newInsertFields+")SELECT "+oldSelectFields+" FROM _tmp_",callback)},function(callback){execQuery("DROP TABLE _tmp_",callback)}],callback)}function initStores(callback){openConnection("distill.sqlite",function(err){if(err){return callback(err)}async.eachSeries([MaintLog,ClientStore,UserStore,SieveStore,TagStore,SieveDataStore,ActionStore,RuleStore,AttrStore,ErrorStore,WorkStore,PopupMessageStore,KVStore],function(store,callback){store.tableInit(function(err){err&&console.error("err:",err);callback(err)})},function(err){if(err){return callback(err)}Prefs.__init__(callback)})})}Prefs.defaults={active:true,nworkers:3,"account.sync":false,"actions.audio":true,"actions.popup":true,"actions.popup.autohide":20,"x-frame-load-in":"tab"};function intToTS(doc){var newDoc=_.extend({},doc);_.each(doc,function(value,key){if(key==="ts"||key.indexOf("ts_")===0){if(_.isNumber(value)){newDoc[key]=new Date(value).toISOString()}}});return newDoc}function tsToInt(doc){var newDoc=_.extend({},doc);_.each(doc,function(value,key){var name=key.split(".")[0];if(name==="ts"||name.indexOf("ts_")===0){if(_.isString(value)){newDoc[key]=new Date(value).valueOf()}}});return newDoc}function SQLStore(options){var self=this;_.extend(this,{primaryKey:"id",tableName:options.name},options,{fields:_.flatten(_.pluck(options.versions,"fields"))});this.fieldNames=_.pluck(this.fields,"name");this.isSynced=hasField("_state");this.create=create;this.destroy=destroy;this.destroyWithSubQuery=destroyWithSubQuery;this.tableInit=tableInit;this.find=find;this.findOne=findOne;this.hasField=hasField;this.update=update;SQLStore[this.name]=this;function create(doc,callback){doc=tsToInt(doc);_.defaults(doc,{id:guid(),_state:C.LOCAL_STATE_POST},_.result(self,"defaults"));var id=doc.id,outValues=[],sql=Statements.insert(self,doc,outValues);callback||(callback=function(){});execQuery(sql,outValues,function(err,doc){if(err){callback(err)}else{findOne(id,function(err,doc){callback(err,intToTS(doc));!err&&doc&&gEvents.trigger("store:"+self.name+":create",doc)})}})}function destroy(query,callback){query||(query={});if(_.isString(query))query={id:query};query=tsToInt(query);callback||(callback=function(){});async.series({list:function(callback){find(query,{only:["id"]},callback)},destroys:function(callback){var outValues=[],sql=Statements.destroy(self,query,outValues);execQuery(sql,outValues,callback)}},function(err,result){callback(err,result.destroys);if(!err&&result.list.count>0){result.list.data.forEach(function(row){gEvents.trigger("store:"+self.name+":destroy",row)})}})}function destroyWithSubQuery(query,options,callback){options||(options={});query=tsToInt(query);var ids;_.extend(options,{only:["id"]});async.waterfall([function(callback){var outValues=[],subQuery=Statements.select(self,query,options,outValues);execQuery(subQuery,outValues,options,callback)},function(rows,callback){ids=_.pluck(rows,"id");var outValues=[],destroyQuery=Statements.destroy(self,{"id.in":ids},outValues);execQuery(destroyQuery,outValues,callback)}],function(err,result){callback(err,result);if(!err){_.each(ids,function(id){gEvents.trigger("store:"+self.name+":destroy",{id:id})})}})}function find(query,options,callback){if(_.isFunction(options)){callback=options;options={}}query||(query={});query=tsToInt(query);options||(options={});callback||(callback=function(){});_.defaults(options,{limit:DEFAULT_LIMIT,offset:0,order:["-ts"]});async.parallel({data:function(callback){var outValues=[],sql=Statements.select(self,query,options,outValues);execQuery(sql,outValues,options,callback)},total_count:function(callback){var outValues=[],countOptions={count:1},sql=Statements.select(self,query,countOptions,outValues);execQuery(sql,outValues,countOptions,callback)}},function(err,result){if(err){DBG&&console.error("ERR:STORE:",err);callback(err)}else{result.data=_.map(result.data,intToTS);result.count=result.data.length;result.offset=options.offset;result.total_count=result.total_count.count;callback(null,result)}})}function findOne(query,options,callback){if(_.isFunction(options)){callback=options;options={}}query||(query={});if(_.isString(query))query={id:query};query=tsToInt(query);options||(options={});callback||(callback=function(){});if(_.isFunction(options)){callback=options;options={}}_.extend(options,{limit:1});var outValues=[],sql=Statements.select(self,query,options,outValues);execQuery(sql,outValues,options,function(err,result){callback(err,result&&result.length>0?intToTS(result[0]):null)})}function hasField(name){return self.fieldNames.indexOf(name)>=0}function tableInit(callback){var outValues=[],sql=Statements.select({tableName:"sqlite_master",fields:[{name:"name"}]},{name:self.name},{only:["name"]},outValues);execQuery(sql,outValues,function(err,result){if(err){DBG&&console.error("failed to fetch data from sqlite_master",err);callback(err)}else{if(result.length==1){tableCheckForUpgrade(callback)}else{tableCreate(self,callback)}}})}function tableCheckForUpgrade(callback){var currentVersion=self.versions[0].version,latestVersion=self.versions[self.versions.length-1].version;MaintLog.findOne({name:self.name},{limit:1,order:["-ts"]},function(err,doc){err&&console.error("err:",err);if(doc){currentVersion=doc.version}if(latestVersion>currentVersion){tableUpgradeFromVersion(self,currentVersion,callback)}else{callback()}})}function update(query,doc,callback){callback||(callback=function(){});query||(query={});if(_.isString(query))query={id:query};query=tsToInt(query);doc=tsToInt(doc);if(doc.ts_mod===-1){delete doc.ts_mod}else if(_.isUndefined(doc.ts_mod)){doc.ts_mod=Date.now()}async.series({list:function(callback){find(query,{only:["id"]},callback)},updateSynced:function(callback){var tDoc=_.omit(doc),tQuery=_.omit(query);if(self.isSynced){if(_.isUndefined(tQuery._state)){tQuery.$or={_state:null,"_state.in":[C.LOCAL_STATE_SYNCED]}}if(tDoc._state===-1){delete tDoc._state}else if(_.isUndefined(tDoc._state)){tDoc._state=C.LOCAL_STATE_PUT}}var outValues=[],sql=Statements.update(self,tQuery,tDoc,outValues);execQuery(sql,outValues,callback)},updateUnsynced:function(callback){if(!self.isSynced){callback();return}var tDoc=_.omit(doc),tQuery=_.omit(query);if(_.isUndefined(tQuery._state)){tQuery["_state.ne"]=C.LOCAL_STATE_SYNCED}if(tDoc._state===-1){delete tDoc._state}if(_.isEmpty(tDoc)){callback();return}var outValues=[],sql=Statements.update(self,tQuery,tDoc,outValues);execQuery(sql,outValues,callback)}},function(err,result){
  3.  
  4. 2.
  5. callback(err,result.list.count);if(!err&&result.list.count>0){result.list.data.forEach(function(row){gEvents.trigger("store:"+self.name+":update",_.extend(row,doc))})}})}}var MaintLog=new SQLStore({name:"maint_logs",versions:[{version:1,fields:[{name:"id",type:"string",primaryKey:1},{name:"name",type:"string"},{name:"version",type:"integer"},{name:"ts",type:"integer","default":"(strftime('%s', 'now')*1000.0)"}]}]});var ClientStore=new SQLStore({name:"clients",urls:{root:"/clients",id:"/clients/{{id}}"},versions:[{version:1,fields:[{name:"user_id",type:"string"},{name:"type",type:"integer"},{name:"name",type:"string"},{name:"state",type:"integer","default":C.STATE_DEFAULT},{name:"ts_mod",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"ts",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"_state",type:"integer","default":C.LOCAL_STATE_SYNCED}]},{version:2,fields:[{name:"info",type:"string"}]},{version:3,fields:[]},{version:4,fields:[{name:"id",type:"string",oldName:"id"}]}],unique:["id","user_id"],extension:", UNIQUE (id, user_id) ON CONFLICT REPLACE"});var UserStore=new SQLStore({name:"users",urls:{root:"/users",id:"/users"},versions:[{version:1,fields:[{name:"id",type:"string",primaryKey:1},{name:"name",type:"string"},{name:"full_name",type:"string"},{name:"bio",type:"string"},{name:"email",type:"string"},{name:"website",type:"string"},{name:"state",type:"integer","default":C.STATE_DEFAULT},{name:"ts_mod",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"ts",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"_state",type:"integer","default":C.LOCAL_STATE_SYNCED}]},{version:2,fields:[{name:"locale",type:"string"}]}]});var SieveStore=new SQLStore({name:"sieves",urls:{root:"/sieves",id:"/sieves/{{id}}"},versions:[{version:1,fields:[{name:"id",type:"string",primaryKey:1},{name:"user_id",type:"string"},{name:"name",type:"string"},{name:"uri",type:"string"},{name:"rule_id",type:"string"},{name:"content_type",type:"integer"},{name:"config",type:"string"},{name:"schedule",type:"string"},{name:"state",type:"integer","default":C.STATE_READY},{name:"text",type:"string"},{name:"tags",type:"string"},{name:"ts_data",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"ts_view",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"ts_mod",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"ts",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"_state",type:"integer","default":C.LOCAL_STATE_SYNCED}]},{version:2,fields:[{name:"client_id",type:"string"}]},{version:3,fields:[{name:"err",type:"string"}]}],defaults:function(){return{client_id:Prefs.get("client.id"),user_id:auth.getId()}}});var TagStore=new SQLStore({name:"tags",urls:{root:"/tags",id:"/tags/{{id}}"},versions:[{version:1,fields:[{name:"id",type:"string",primaryKey:1},{name:"name",type:"string"},{name:"ts_mod",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"ts",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"_state",type:"integer","default":C.LOCAL_STATE_SYNCED}]},{version:2,fields:[{name:"user_id",type:"string"},{name:"state",type:"integer","default":C.STATE_DEFAULT}]}],defaults:function(){return{user_id:auth.getId(),state:0}}});var SieveDataStore=new SQLStore({name:"sieve_data",urls:{root:"/sieves/-/data",id:"/sieves/{{sieve_id}}/data/{{id}}"},versions:[{version:1,fields:[{name:"id",type:"string",primaryKey:1},{name:"sieve_id",type:"string"},{name:"data_type",type:"integer"},{name:"data",type:"string"},{name:"text",type:"string"},{name:"ts_mod",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"ts",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"_state",type:"integer","default":C.LOCAL_STATE_SYNCED}]},{version:2,fields:[{name:"state",type:"integer","default":C.STATE_DEFAULT}]}]});var ActionStore=new SQLStore({name:"actions",urls:{root:"/sieves/-/actions",id:"/sieves/{{sieve_id}}/actions/{{id}}"},versions:[{version:1,fields:[{name:"id",type:"string",primaryKey:1},{name:"sieve_id",type:"string"},{name:"type",type:"integer"},{name:"config",type:"string"},{name:"state",type:"integer","default":C.STATE_DEFAULT},{name:"ts_mod",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"ts",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"_state",type:"integer","default":C.LOCAL_STATE_SYNCED}]},{version:2,fields:[{name:"user_id",type:"string"}]}],defaults:function(){return{state:0,user_id:auth.getId()}}});var RuleStore=new SQLStore({name:"rules",urls:{root:"/rules",id:"/rules/{{id}}"},versions:[{version:1,fields:[{name:"id",type:"string",primaryKey:1},{name:"user_id",type:"string"},{name:"name",type:"string"},{name:"config",type:"string"},{name:"ts_mod",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"ts",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"_state",type:"integer","default":C.LOCAL_STATE_SYNCED}]},{version:2,fields:[{name:"state",type:"integer","default":C.STATE_DEFAULT}]}],defaults:function(){return{user_id:auth.getId()}}});var AttrStore=new SQLStore({name:"attrs",urls:{root:"/users/attrs",id:"/users/attrs/{{id}}"},versions:[{version:1,fields:[{name:"id",type:"string",primaryKey:1},{name:"user_id",type:"string"},{name:"name",type:"string"},{name:"value",type:"string"},{name:"state",type:"integer"},{name:"ts_mod",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"ts",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"_state",type:"integer","default":C.LOCAL_STATE_SYNCED}]}],defaults:function(){return{user_id:auth.getId()}}});var ErrorStore=new SQLStore({name:"errors",versions:[{version:1,fields:[{name:"id",type:"string",primaryKey:1},{name:"context",type:"string"},{name:"msg",type:"string"},{name:"data",type:"string"},{name:"err",type:"string"},{name:"ts_mod",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"ts",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"_state",type:"integer","default":C.LOCAL_STATE_SYNCED}]}]});var WorkStore=new SQLStore({name:"works",versions:[{version:1,fields:[{name:"id",type:"string",primaryKey:1},{name:"rel",type:"string"},{name:"key",type:"string"},{name:"err",type:"string"},{name:"data",type:"string"},{name:"duration",type:"integer"},{name:"ts_mod",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"ts",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"_state",type:"integer","default":C.LOCAL_STATE_SYNCED}]}]});var PopupMessageStore=new SQLStore({name:"popup_messages",versions:[{version:1,fields:[{name:"id",type:"string",primaryKey:1},{name:"rel",type:"string"},{name:"key",type:"string"},{name:"uri",type:"string"},{name:"title",type:"string"},{name:"ts_mod",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"ts",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"_state",type:"integer","default":C.LOCAL_STATE_SYNCED}]},{version:2,fields:[{name:"msg",type:"string"}]}]});var KVStore=new SQLStore({name:"kv",versions:[{version:1,fields:[{name:"id",type:"string",primaryKey:1},{name:"value",type:"string"},{name:"ts_mod",type:"integer","default":"(strftime('%s', 'now')*1000.0)"},{name:"ts",type:"integer","default":"(strftime('%s', 'now')*1000.0)"}]}]});var REMOTE_LOCAL_NAME_MAP={clients:"clients",sieves:"sieves",sieve_actions:"actions",sieve_data:"sieve_data",sieve_rules:"rules",user_attrs:"attrs",tags:"tags",users:"users"};const TIMEOUT_FIND_LOADER=5e3,TIMEOUT_LOAD=3e4;function WebpageLoader(options){var self=this;this.options=options||{};this.ports=[];this.id=WebpageLoader.ID++;WebpageLoader.INSTANCES.push(this);this.createView(function(){self.options.info.url&&self.load(self.options.info.url)})}_.extend(WebpageLoader.prototype,Backbone.Events,{rootPort:null,timeout:6e4,uri:null,addPort:function(port){port.bind("ready",this.onPortReady,this);port.bind("disconnect",this.onPortDisconnect,this);if(port.isRoot()){this.rootPort=port;this.ports.unshift(port);this.uri=port.uri;this.trigger("reset")}else{this.ports.push(port)}},addPortEvents:function(aPort){var self=this;aPort.bind("all",forwardEvent);function forwardEvent(eventName,event){var newType="port:"+eventName;self.trigger(newType,_.extend({},event,{portId:aPort.id,type:newType}),aPort)}},createView:function(callback){throw new Error("Not implemented")},destroy:function(){if(this.destroyed)return;_.each(this.ports.splice(0),function(port){port.destroy()});this.destroyed=true;WebpageLoader.INSTANCES.splice(WebpageLoader.INSTANCES.indexOf(this),1);this.off();this.stopListening();this.rootPort=null;this.destroy2&&this.destroy2()},findPorts:function(portSelector){var filter=function(){return false};if(portSelector.id&&portSelector.uri){return[portSelector]}else if(portSelector=="<root>"){return[this.rootPort]}else if(portSelector=="<all>"){filter=function(port){return true}}else if(_.isNumber(portSelector)){filter=function(port,index){return index===portSelector}}else if(portSelector.href){if(typeof portSelector.href=="object"){var regex=new RegExp(portSelector.href.pattern,portSelector.href.flags||"i");filter=function(port){return regex.test(port.data.href)}}else{filter=function(port){return port.data.href==portSelector.href}}}else if(portSelector.indices!=undefined){filter=function(port,index){return portSelector.indices.indexOf(index)>=0}}return _.filter(this.ports,filter)},getPort:function(portId){for(var i=0;i<this.ports.length;i+=1){if(this.ports[i].id==portId){return this.ports[i]}}},getPortIndex:function(portId){for(var i=0;i<this.ports.length;i+=1){if(this.ports[i].id==portId){return i}}return-1},load:function(url,cb,timeoutPeriod){var self=this,timeoutPeriod=timeoutPeriod||TIMEOUT_LOAD,timeoutId=setTimeout(timeout,timeoutPeriod);this.bind("port:connect",onPortConnect);this.setURL(url);cb&&cb();function done(){self.unbind("port:connect",onPortConnect);clearTimeout(timeoutId)}function onPortConnect(aPort,aLoader){if(aPort==this.rootPort){done()}}function timeout(){DBG&&console.error("ERR:LOADER:timeout",self,self.uri);done();self.trigger("load_error",self,url)}},onPortDisconnect:function(aPort){if(aPort==this.rootPort){this.rootPort=null}var index=this.ports.indexOf(aPort);this.ports.splice(index,1)},onPortReady:function(aPort){var self=this;this.addPortEvents(aPort);this.trigger("port:connect",aPort,this);if(aPort!=this.rootPort||aPort.uri!="about:blank"){function sendEvents(){if(aPort==self.rootPort){self.trigger("load:root",aPort,self)}self.trigger("load",aPort,self)}var pageMods=this.options.pageMods;if(pageMods){aPort.sendRequest("require",pageMods,function(err){if(err){DBG&&console.error("Failed to load pageMods for:",aPort)}else{sendEvents()}})}else{sendEvents()}}},port_request:function(portSelector,input,cb){var matchingPorts=this.findPorts(portSelector);if(matchingPorts.length==0){cb(Err.NOT_FOUND({type:"port",param:"selector",id:JSON.stringify(portSelector),data:portSelector,loader:this.id}))}else{matchingPorts[0].sendRequest(input.path,input.data,cb)}},setURL:function(url){throw new Error("setURL not implelemented by WebpageLoader subclass:",this.constructor)}});WebpageLoader.ID=1;WebpageLoader.INSTANCES=[];WebpageLoader.get=function WL_get(id){return _.detect(WebpageLoader.INSTANCES,function(loader){return loader.id==id})};function FramePool(){this.frames=[];this.count=0}FramePool.prototype._create=function(){this.count+=1;return document.createElement("iframe")};FramePool.prototype.borrow=function(){var frame=this.frames.pop()||this._create();frame.src="about:blank";document.body.appendChild(frame);return frame};FramePool.prototype.credit=function(frame){if(!frame){throw new Error("Returning frame, but is undefined.")}frame.src="about:blank";document.body.removeChild(frame);this.frames.push(frame)};var framePool=new FramePool;function FrameLoader(options){_.defaults(options,{removeFrames:false});WebpageLoader.call(this,options)}_.extend(FrameLoader.prototype,WebpageLoader.prototype,{createView:function(callback){var height=this.height=this.id%2e3+600,width=this.width=Math.random()*1e3|0+800,iframe=this.iframe=framePool.borrow();iframe.width=this.width+this.getFlags();iframe.height=this.height;callback()},destroy2:function(){framePool.credit(this.iframe);this.iframe=null},getFlags:function(){var flags=0;if(this.options.removeFrames){flags|=1<<0}return flags},setURL:function(url){this.iframe.src=url}});function StaticLoader(options){WebpageLoader.call(this,options)}_.extend(StaticLoader.prototype,WebpageLoader.prototype,{width:800,createView:function(callback){var height=this.height=this.id%200+600,iframe=this.iframe=framePool.borrow();iframe.width=this.width;iframe.height=this.height;callback()},destroy2:function(){framePool.credit(this.iframe);this.iframe=null},onFrameLoad:function(){this.iframe.onload=null;var port=new StaticLocaderPort(this);this.addPort(port)},setURL:function(url){this.url=url;var self=this;HTTP.get({url:url},function(err,res,xhr){if(!err){var html=Feed.sanitize(res);self.iframe.contentWindow.URL_CDN=chrome.extension.getURL("/content");self.iframe.contentDocument.documentElement.innerHTML=html}else{self.iframe.contentDocument.body.innerHTML='<b style="color:#F00">Failed to load page<b>'}self.onFrameLoad()})}});function TabLoader(options){WebpageLoader.call(this,options)}_.extend(TabLoader.prototype,WebpageLoader.prototype,{tabId:null,url:"about:blank",createView:function(callback){var self=this,info=this.options.info;this.options.info=_.defaults(info,{pinned:true,active:false});if(info.tabId){chrome.tabs.get(info.tabId,function(tab){if(!tab){DBG&&console.error("EXTN: loader.js: tab to attach to not found");return self.destroy()}self.tabId=tab.id;chrome.tabs.executeScript(tab.id,{allFrames:true,file:"port-loader.js",runAt:"document_start"})});callback()}else{var info=_.pick(info,"active","index","pinned");info.url=info.url||CFG.URL.BLANK;chrome.tabs.getSelected(function(activeTab){if(info.after=="activeTab"){info.index=activeTab.index+1}chrome.tabs.create(info,function(tab){self.tabId=tab.id;callback()})})}},destroy2:function(){if(!this.options.info.tabId&&this.tabId){try{var id=this.tabId;chrome.tabs.remove(id,function(){setTimeout(function(){chrome.tabs.get(id,function(tab){if(tab){chrome.tabs.update(id,{pinned:false},function(){chrome.tabs.remove(id)})}})},200)})}catch(e){}removePinnedTab(this._tabURL)}},setURL:function(url){this._tabURL=url;chrome.tabs.update(this.tabId,{url:url});if(this.options.info.pinned){addPinnedTab(url)}}});function WindowLoader(options){TabLoader.call(this,options)}_.extend(WindowLoader.prototype,TabLoader.prototype,{createView:function(callback){var self=this,info=_.pick(self.options.info,"url","tabId","left","top","width","height","focused","type","state");info=_.defaults(info,{url:CFG.URL.BLANK,state:"minimized"});chrome.windows.create(info,function(window){var tabs=window.tabs;self.tabId=tabs[0].id})},destroy2:function(){if(!this.options.tabId&&this.tabId){try{var id=this.tabId;chrome.tabs.remove(id,function(){setTimeout(function(){chrome.tabs.update(id,{pinned:false},function(){chrome.tabs.remove(id)})},200)})}catch(e){}removePinnedTab(this._tabURL)}}});function addPinnedTab(url){var urls=Prefs.get("tabs.pinned.urls",[]);if(urls.indexOf(url)<0){urls.push(url)}Prefs.set("tabs.pinned.urls",urls)}function removePinnedTab(url){var urls=Prefs.get("tabs.pinned.urls",[]),index=urls.indexOf(url);if(index>=0){urls.splice(index,1)}Prefs.set("tabs.pinned.urls",urls)}function removePinnedTabs(url){var urls=Prefs.get("tabs.pinned.urls",[]);_.each(urls,function(url){chrome.tabs.query({pinned:true,url:url},function(tabs){if(tabs.length>0){chrome.tabs.remove(_.pluck(tabs,"id"))}})});Prefs.set("tabs.pinned.urls",[])}function loaderFindFrameLoader(attrs){return _.find(WebpageLoader.INSTANCES,function(loader){return attrs.parent.id==="BG"&&loader.height==attrs.size.height&&loader.width==attrs.size.width||_.any(loader.ports,function(port){return port.attrs.id===attrs.parent.id})})}function createLoader(options,callback){if(options.dynamic===false){callback(null,new StaticLoader(options))}else if(options.type=="tab"){callback(null,new TabLoader(options))}else if(options.type=="window"){callback(null,new WindowLoader(options))}else{callback(null,new FrameLoader(options))}}function loaderAttachPort(port,callback){var name=port.name,attrs=JSON.parse(name.substring("loader:".length)),tab=port.sender.tab,loader=tab&&_.findWhere(WebpageLoader.INSTANCES,{tabId:tab.id})||!tab&&loaderFindFrameLoader(attrs);loader&&loader.addPort(new LoaderPort(port,attrs));return!!loader}chrome.tabs.onReplaced.addListener(function(added,removed){_.each(WebpageLoader.INSTANCES,function(loader){if(loader.tabId===removed){loader.tabId=added}})});chrome.tabs.onRemoved.addListener(function(tabId,removeInfo){var loaders=_.where(WebpageLoader.INSTANCES,{tabId:tabId});loaders.forEach(function(loader){loader.destroy()})});function VisualSelector(options,resultCallback){var self=this,id=ID(),loader=options.loader,model=options.model,port,state=_.extend({selectorOn:false,expanded:true},Prefs.get("visualselector.uistate"),options.state);_.extend(self,Backbone.Events);self.id=id;self.loader=loader;self.destroy=destroy;self.setPort=setPort;VisualSelector.INSTANCES.push(self);if(loader.rootPort)load();self.listenTo(loader,"reset",load);function destroy(){if(!self)return;VisualSelector.INSTANCES.splice(VisualSelector.INSTANCES.indexOf(self),1);self.off();self.stopListening();self=null}function initPort(){port.on("disconnect",function(){self&&(self.port=port=null)});port.on("port:close",onClose);port.on("port:save",onSave);port.on("port:uistate",onUIState);port.listenTo(loader,"load",onLoaderPortLoad);port.listenTo(loader,"reset",onLoaderReset);port.listenTo(loader,"port:window:select:close",function(event,aPort){port.postMessage({type:"loader:port:window:select:close",data:_.extend({index:loader.getPortIndex(event.portId),title:aPort.title,uri:aPort.uri},event)})});port.listenTo(loader,"port:window:select:display",function(event,aPort){port.postMessage({type:"loader:port:window:select:display",data:_.extend({index:loader.getPortIndex(event.portId),title:aPort.title,uri:aPort.uri},event)})});port.listenTo(loader,"port:window:select:new",function(event,aPort){port.postMessage({type:"loader:port:window:select:new",data:_.extend({index:loader.getPortIndex(event.portId),title:aPort.title,uri:aPort.uri},event)})});port.setRequestHandler(requestHandler);port.postMessage({type:"load",data:{model:model,state:state}});if(loader.rootPort){onLoaderReset()}_.each(loader.ports,function(loaderPort){onLoaderPortLoad(loaderPort)});function onLoaderReset(){if(!port)return;port.postMessage({type:"loader:reset",data:_.pick(loader.rootPort,"title","uri")})}function onLoaderPortLoad(loaderPort){if(!port)return;if(loaderPort.ready){port.postMessage({type:"loader:load",data:{index:loader.getPortIndex(loaderPort.id)}})}}}function load(){chrome.tabs.executeScript(loader.tabId,{code:"window.DISTILL_LOCALE="+JSON.stringify(Prefs.get("locale")),runAt:"document_start"});chrome.tabs.executeScript(loader.tabId,{file:"port-selector.js",runAt:"document_start"})}function onClose(event){chrome.tabs.executeScript(loader.tabId,{code:"remove()"});resultCallback()}function onSave(event){chrome.tabs.executeScript(loader.tabId,{code:"remove()"});resultCallback(null,event.data)}function onUIState(event){state=event.data;Prefs.set("visualselector.uistate",event.data)}function requestHandler(path,input,sendResponse){switch(path){case"loader/port_request":loader.port_request(input.portSelector,input.data,sendResponse);break;default:break}}function setPort(_port){if(port)port.destroy();self.port=port=_port;initPort();self.trigger("port:connect",port)}}VisualSelector.INSTANCES=[];function selectorAttachPort(port){var tabId=port.sender.tab.id,vs=_.find(VisualSelector.INSTANCES,function(vs){return vs.loader.tabId==tabId});vs&&vs.setPort(new SimplePort(port));return!!vs}const TYPE_FORM_ENCODED="application/x-www-form-urlencoded",TYPE_JSON="application/json",RE_XML=/((\/xml)|(\+xml))$/;function encodeParams(params){return _.map(params,function(value,name){return name+"="+encodeURIComponent(value)}).join("&")}var HTTP={request:function(options,callback){var xhr,params=options.params,json=options.json||{},contentType=params?TYPE_FORM_ENCODED:TYPE_JSON,str=contentType==TYPE_JSON?JSON.stringify(json):encodeParams(params),method=options.method||"GET",url=options.url;if(method=="GET"&&!_.isEmpty(json)){url+=(url.indexOf("?")<0?"?":"&")+qs.stringify(json)}xhr=new XMLHttpRequest;xhr.onreadystatechange=onreadystatechange;xhr.open(method,url,true);setHeaders();if(method=="GET"){xhr.send(null)}else{xhr.send(str)}function onreadystatechange(){if(xhr.readyState==4){var text=xhr.responseText,contentType=xhr.getResponseHeader("content-type")||"text",isJSON=contentType.indexOf(TYPE_JSON)==0,isXML=RE_XML.test(contentType),response=isJSON?JSON.parse(text):isXML?xhr.responseXML:text,status=xhr.status;callback(status!=200?{status:status}:null,response,xhr)}}function setHeaders(){xhr.withCredentials=true;if(method!="GET"){xhr.setRequestHeader("Content-type",contentType)}_.each(options.headers,function(value,key){xhr.setRequestHeader(key,value)})}return xhr},del:function(options,callback){_.extend(options,{method:"DELETE"});return HTTP.request(options,callback)},head:function(options,callback){_.extend(options,{method:"HEAD"});return HTTP.request(options,callback)},get:function(options,callback){_.extend(options,{method:"GET"});return HTTP.request(options,callback)},post:function(options,callback){_.extend(options,{method:"POST"});return HTTP.request(options,callback)},put:function(options,callback){_.extend(options,{method:"PUT"});return HTTP.request(options,callback)}};function apiHeaders(){return{Authorization:Prefs.get("service.auth_token"),"X-Requested-With":"XMLHttpRequest","X-ClientType":CFG.CLIENT.TYPE,"X-ClientID":Prefs.get("client.id")}}function api(url,method,json,callback,_retriedOn401){if(typeof method=="function"){callback=method;json=null;method="GET"}else if(typeof json=="function"){callback=json;json=null}if(url.indexOf("http:")!=0&&url.indexOf("https:")!=0){url=CFG.URL.API+url}return HTTP.request({url:url,method:method,json:json,headers:apiHeaders()},function(err,res,xhr){if(err&&err.status==401&&!_retriedOn401){auth.save(auth.get(),function(err,res){if(err){callback(err)}else{api(url,method,json,callback,true)}})}else{err&&console.error("api error: ",err,url,method,json);callback(err,res)}})}var auth=_.extend({check:function(params,callback){HTTP.post({url:CFG.URL.API+"/users/auth_check",params:params},callback)},clear:function(callback){var token=Prefs.del("service.auth_token");Prefs.del("service.name");if(token){HTTP.post({url:CFG.URL.API+"/users/auth_token_expire",params:{token:token}},callback)}else{callback()}auth.trigger("clear")},get:function(callback){var name=Prefs.get("service.name"),password=Prefs.get("service.password"),cred=password?{name:name,password:password}:null;callback&&callback(null,cred);return cred},getName:function(){return Prefs.get("service.name")},save:function(params,callback){auth.check(params,function(err,res){if(err){Prefs.set("service.password",null);Prefs.set("service.auth_token",null);auth.trigger("err:save");callback(err)}else{Prefs.set("service.name",params.name);Prefs.set("service.password",params.password);HTTP.post({url:CFG.URL.API+"/users/auth_token",params:params},function(err,res){if(err){callback(err)}else{Prefs.set("service.auth_token",res.token);callback();auth.init()}})}})}},Backbone.Events);auth.getId=function(){return Prefs.get("service.user_id")};auth.init=function(callback){var creds=auth.get(),name=creds&&creds.name,oldUserId=auth.getId(),user;callback||(callback=function(err){err&&console.error("auth.init",err)});if(!creds)return callback();async.waterfall([function(callback){UserStore.findOne({$or:{name:name,email:name}},callback)},function(_user,callback){user=_user;if(creds&&!user){api("/users","GET",null,callback)}else{callback(null,null)}},function(result,callback){if(result&&result.data.length>0){user=result.data[0];UserStore.create(_.extend({_state:C.LOCAL_STATE_SYNCED},user),callback)}else{callback()}if(user&&oldUserId!=user.id){Prefs.set("service.user_id",user.id)}auth.trigger("init")}],callback)};var SyncId={webAppId:"ffffffff-ffff-ffff-ffff-ffffffffffff",init:function(callback){var user_id=auth.getId();SyncId.findId(function(err,client_id){if(client_id){Prefs.set("client.id",client_id);var query={id:client_id};user_id&&(query.user_id=user_id);ClientStore.findOne(query,function(err,doc){if(!doc){SyncId.create(callback)}else{callback(null,doc)}})}else{SyncId.create(callback)}})},findId:function(callback){var client_id=Prefs.get("client.id");if(client_id){callback(null,client_id)}else{KVStore.findOne({id:"client_id"},function(err,doc){callback(err,doc&&doc.value)})}},create:function(callback){var client_id=Prefs.get("client.id"),user_id=auth.getId(),clientDoc;async.waterfall([function(callback){var doc={type:CFG.CLIENT.TYPE,name:CFG.CLIENT.NAME,info:CFG.CLIENT.INFO,state:C.STATE_UNAUTHORIZED};client_id&&(doc.id=client_id);user_id&&(doc.user_id=user_id);ClientStore.create(doc,callback)},function(_clientDoc,callback){clientDoc=_clientDoc;client_id=clientDoc.id;Prefs.set("client.id",client_id);KVStore.destroy({id:"client_id"},callback)},function(res,callback){KVStore.create({id:"client_id",value:client_id},callback)}],function(err){callback(err,clientDoc)})}};function pruneDeletedSieve(callback){execQuery("DELETE FROM sieves WHERE state = ? AND (_state = ? OR user_id IS NULL)",[C.STATE_DEL,C.LOCAL_STATE_POST],{},function(err,list){if(err){callback(err)}else{pruneOrphanedData(callback)}})}function pruneOrphanedData(callback){async.series([function(callback){async.each([ActionStore,SieveDataStore],function(store,callback){var n=store.name,sql="SELECT "+n+".id FROM "+n+" LEFT JOIN sieves ON "+n+".sieve_id=sieves.id WHERE sieves.id IS NULL";execQuery(sql,[],{},function(err,list){if(err){callback(err)}else{var ids=_.pluck(list,"id");async.whilst(function(){return ids.length>0},function(callback){store.destroy({"id.in":ids.splice(0,500)},callback)},callback)}})},callback)},function(callback){var sql="SELECT rules.id FROM rules LEFT JOIN sieves on rules.id = sieves.rule_id where sieves.rule_id IS NULL";execQuery(sql,[],{},function(err,list){if(err){callback(err)}else{RuleStore.destroy({"id.in":_.pluck(list,"id")},callback)}})}],callback)}function initData(callback){var clientId=Prefs.get("client.id");async.series([pruneDeletedSieve,function(callback){PopupMessageStore.destroy({},callback)},function(callback){async.each([ClientStore,SieveStore,TagStore,SieveDataStore,ActionStore,RuleStore,AttrStore],function(store,callback){store.update({_state:null},{_state:C.LOCAL_STATE_POST,ts_mod:-1},callback)},callback)},function(callback){async.each([ClientStore,SieveStore,TagStore,SieveDataStore,ActionStore,RuleStore,AttrStore],function(store,callback){store.update({state:null},{state:C.STATE_DEFAULT,ts_mod:-1,_state:-1},callback)},callback)},function(callback){SieveStore.update({rule_id:""},{rule_id:null,ts_mod:-1,_state:-1},callback)},function(callback){SieveStore.update({client_id:null},{client_id:clientId,ts_mod:-1,_state:-1},callback)},function(callback){var user_id=auth.getId();if(!user_id){callback();return}async.parallel([function(callback){ClientStore.update({user_id:null,"id.ne":SyncId.webAppId},{user_id:user_id,ts_mod:-1,_state:-1},callback)},function(callback){async.each([SieveStore,TagStore,ActionStore,RuleStore,AttrStore],function(store,callback){store.update({user_id:null},{user_id:user_id,ts_mod:-1,_state:-1},callback)},callback)}],callback)}],callback)}var SyncMan=_.extend({},Backbone.Events,{accountEnabled:false,syncTimer:{},canSync:function(){return auth.get()!=null&&Prefs.get("account.sync")},clearTimers:function(){_.each(this.syncTimer,function(timeoutId){clearTimeout(timeoutId)});this.syncTimer={}},del:function(store,callback){var urlTpl=_.template(store.urls.id);store.find({_state:C.LOCAL_STATE_DEL},function(err,resp){if(err){callback(err);return}async.eachSeries(resp.data,function(doc,callback){var url=urlTpl(doc);api(url,"DELETE",function(err){if(err){console.error("error deleting model from server:",err);store.update(doc.id,{_state:C.LOCAL_STATE_DEL_ERR},callback)}else{store.destroy(doc.id,callback)}})},callback)})},get:function(store,options,callback){if(typeof options=="function"){callback=options;options={}}function getSyncSuffix(){var query=options.query||{},keys=Object.keys(query).sort();if(keys.length===0){return""}var parts=keys.map(function(key){return key+"_"+query[key]});return"_"+parts.join("_")}var tsDoc,resp,user_id=auth.getId(),tsSyncId=user_id+"_ts_sync_"+store.name+getSyncSuffix();async.waterfall([function(callback){KVStore.findOne(tsSyncId,{only:["id","value"]},callback)},function(_tsDoc,callback){tsDoc=_tsDoc;var url=store.urls.root,query=_.extend({client_id:"-",state:"-",_opt:{order:["ts_mod","id"],limit:10}},options.query);if(tsDoc){var parts=tsDoc.value.split(","),sTsMod=new Date(parts[0]),sId=parts[1];if(sId){query.$or={"ts_mod.gt":tsDoc?new Date(sTsMod.valueOf()+1).toISOString():void 0,$and1:{"ts_mod.gte":tsDoc?sTsMod.toISOString():void 0,"id.gt":sId}}}else{query["ts_mod.gt"]=new Date(sTsMod.valueOf()+1).toISOString()}}else{query["state.nin"]=[C.STATE_DEL]}api(url,"GET",query,callback)},function(_resp,callback){resp=_resp;async.eachSeries(resp.data,function(remoteDoc,callback){var query=_.pick(remoteDoc,"id","user_id");store.findOne(query,{only:["id","_state"]},function(err,localDoc){remoteDoc._state=C.LOCAL_STATE_SYNCED;if(_.isUndefined(remoteDoc.state)){remoteDoc.state=C.STATE_DEFAULT}if(localDoc){if(remoteDoc.state==C.STATE_DEL){store.destroy(query,callback)}else{if(localDoc._state===C.LOCAL_STATE_PUT){callback()}else{store.update(query,remoteDoc,callback)}}}else{store.create(remoteDoc,callback)}})},callback)},function(callback){if(resp.count===0){callback()}else{var doc=_.pick(resp.data[resp.count-1],"id","ts_mod"),ref=doc.ts_mod+","+doc.id;if(tsDoc){KVStore.update(tsDoc.id,{value:ref},callback)}else{KVStore.create({id:tsSyncId,value:ref},callback)}}}],function(err){if(err){callback(err)}else if(resp.total_count>resp.count){SyncMan.get(store,options,callback)}else{callback()}})},post:function(store,callback){var url=store.urls.root,user_id=auth.getId();store.find({user_id:user_id,_state:C.LOCAL_STATE_POST,$or:{state:null,"state.nin":[C.STATE_DEL]}},{limit:10,order:["ts_mod"]},function(err,resp){async.eachSeries(resp.data,function(doc,callback){api(url,"POST",doc,function(err,savedDoc){if(err&&err.status>200&&err.status<502){var urlTpl=_.template(store.urls.id),urlId=urlTpl(doc);api(urlId,"GET",function(errGet,doc){if(errGet){if(errGet.status>200&&errGet.status<502){store.update(doc.id,{_state:C.LOCAL_STATE_POST_ERR},function(errUpdate){callback()})}else{callback(err)}}else{store.update(doc.id,{_state:C.LOCAL_STATE_PUT},function(errUpdate){callback()})}})}else if(err){callback(err)}else{var query=_.pick(doc,"id","user_id","ts_mod");store.update(query,_.extend(savedDoc,{_state:C.LOCAL_STATE_SYNCED}),function(err,count){if(err){callback(err)}else if(count==0){store.update(_.omit(query,"ts_mod"),{_state:C.LOCAL_STATE_PUT},callback)}else{callback()}})}})},function(err){if(err){callback(err)}else if(resp.total_count>resp.count){SyncMan.post(store,callback)}else{callback()}})})},put:function(store,callback){var urlTpl=_.template(store.urls.id);user_id=auth.getId();store.find({user_id:user_id,_state:C.LOCAL_STATE_PUT},{limit:10},function(err,resp){async.eachSeries(resp.data,function(doc,callback){var url=urlTpl(doc),query=_.pick(doc,"id","user_id");api(url,"PUT",doc,function(err,doc){if(err){if(err.status==404){store.update(query,{_state:C.LOCAL_STATE_POST},function(errUpdate){callback()})}else if(err.status>200&&err.status<502){store.update(query,{_state:C.LOCAL_STATE_PUT_ERR
  6.  
  7. 3.
  8. },function(errUpdate){callback()})}else{callback(err)}}else{query=_.pick(doc,"id","user_id");store.update(query,_.extend(doc,{_state:C.LOCAL_STATE_SYNCED}),callback)}})},function(err){if(err){callback(err)}else if(resp.total_count>resp.count){SyncMan.put(store,callback)}else{callback()}})})},sync:function(clearTimers,callback){clearTimers&&this.clearTimers();pruneDeletedSieve(function(err){if(err){return callback(err)}async.eachSeries([ClientStore,UserStore,AttrStore,RuleStore,SieveStore,SieveDataStore,ActionStore,TagStore],function(store,callback){SyncMan.syncStore(store,callback)},callback)})},syncStore:function(store,options,callback){var self=this,name=store.name;if(typeof options=="function"){callback=options;options={}}callback||(callback=function(err){err&&console.error(err)});_.defaults(options,{delay:100,retry:0});if(!this.canSync()){callback({msg:"e_sync_disabled"});return}if(!this.accountEnabled){callback({msg:"e_sync_server_na"});return}if(!this.syncTimer[name]){var timeoutId=setTimeout(function(){var syncTimeoutId=setTimeout(function(){if(self.syncTimer[name]===timeoutId){DBG&&console.error("Removing store's lock after timeout:",name);self.syncTimer[name]=0}},120*1e3);self._syncStore(store,function(err,res){clearTimeout(syncTimeoutId);self.syncTimer[name]=0;if(err){DBG&&console.error("Sync failed",err)}callback(err)})},options.delay);this.syncTimer[name]=timeoutId}else{self.once(name+":sync",function(err,res){if(err){callback(err)}else{if(options.retry==0){options.retry+=1;self.syncStore(store,options,callback)}else{callback()}}})}},_syncStore:function(store,callback){SyncMan.trigger(store.name+":sync:init");async.series({del:function(callback){SyncMan.del(store,callback)},get:function(callback){SyncMan.get(store,callback)},put:function(callback){SyncMan.put(store,callback)},post:function(callback){SyncMan.post(store,callback)}},function(err,res){callback(err,res);SyncMan.trigger(store.name+":sync",err,res)})}});var ActionEmail={send:function(action,context,callback){auth.get(function(err,cred){if(err||!cred){callback(err||Err.AUTH_NA());return}api("/agents/actions/email","POST",{action:action,sieve:_.pick(context.sieve,"id","name","uri","ts"),sieve_data:_.pick(context.sieve_data,"id","text","data","ts")},callback)})}};var ActionPush={send:function(action,context,callback){auth.get(function(err,cred){if(err||!cred){callback(err||Err.AUTH_NA());return}api("/agents/actions/push","POST",{action:action,sieve:_.pick(context.sieve,"id","name","uri","ts"),sieve_data:_.pick(context.sieve_data,"id","text","ts")},callback)})}};var ActionSMS={send:function(action,context,callback){auth.get(function(err,cred){if(err||!cred){callback(err||Err.AUTH_NA());return}api("/agents/actions/sms","POST",{action:action,sieve:_.pick(context.sieve,"id","name","uri","ts"),sieve_data:_.pick(context.sieve_data,"id","text","ts")},callback)})}};var ActionWebhook={send:function(action,context,callback){auth.get(function(err,cred){if(err||!cred){callback(err||Err.AUTH_NA());return}api("/agents/actions/webhook","POST",{action:action,sieve:_.pick(context.sieve,"id","name","uri","ts"),sieve_data:_.pick(context.sieve_data,"id","text","data","ts")},callback)})}};var Feed={domParser:new DOMParser,parse:function(xml,name,group){var root,result;if(xml.getElementsByTagName("rdf:RDF").length||xml.getElementsByTagName("RDF").length){return Feed.parseRss1(xml,name,group)}if((root=xml.getElementsByTagName("rss"))&&root.length){if(root[0].getAttribute("version")==="2.0"){return Feed.parseRss2(root[0],name,group)}if(root[0].getAttribute("version")==="0.91"){return Feed.parseRss091(root[0],name,group)}throw new Error(" unknown rss version...")}if(xml.getElementsByTagName("feed").length){return Feed.parseAtom(xml,name,group)}throw new Error("unsupported feed");return false},getNodeValue:function(root,name,attr){try{var node=root.getElementsByTagName(name)[0];if(attr){return node.getAttribute(attr)}return Feed.sanitize(node.childNodes[0].nodeValue)}catch(er){return""}},sanitize:function(text){if(!/<\w.*>/.test(text))return text;var doc=Feed.domParser.parseFromString(text,"text/html"),kachra=doc&&doc.querySelectorAll("script,noscript,frame,iframe,object");if(!doc||!doc.body)return text;_.toArray(kachra).forEach(function(el){var parent=el.parentNode;parent&&parent.removeChild(el)});Feed.sanitizeAttributes(doc.documentElement);return doc.documentElement.outerHTML},sanitizeAttributes:function(el){var attrs=_.toArray(el.attributes);_.each(attrs,function(attr){if(attr.nodeName.indexOf("on")==0){el.removeAttribute(attr)}else if(attr.value.toLowerCase().split(":")[0]=="javascript"){el.removeAttribute(attr)}});_.each(el.childNodes,Feed.sanitizeAttributes)},parseRss1:function(xmlRoot,name,group){var result=[],channel=xmlRoot.getElementsByTagName("channel")[0],items=xmlRoot.getElementsByTagName("item"),item,i;for(i=0;i<items.length;i+=1){item=items[i];try{result[result.length]=FeedItem(Feed.getNodeValue(item,"title"),Feed.getNodeValue(item,"description"),Feed.getNodeValue(item,"link"),Feed.getNodeValue(item,"dc:date")||Feed.getNodeValue(item,"pubDate")||Feed.getNodeValue(item,"date")||"",item)}catch(er){throw new Error("Unable to parse item "+i+": "+er.message)}}return{title:Feed.getNodeValue(channel,"title"),link:Feed.getNodeValue(channel,"link"),summary:Feed.getNodeValue(channel,"description"),published:Feed.getNodeValue(channel,"pubDate")||Feed.getNodeValue(channel,"dc:date")||Feed.getNodeValue(channel,"date")||"",entries:result}},parseRss2:function(xmlRoot,name,group){var i,result=[],item,channel=xmlRoot.getElementsByTagName("channel")[0],items=xmlRoot.getElementsByTagName("item");for(i=0;i<items.length;i+=1){item=items[i];try{result[result.length]=FeedItem(Feed.getNodeValue(item,"title"),Feed.getNodeValue(item,"description"),Feed.getNodeValue(item,"link"),Feed.getNodeValue(item,"pubDate")||Feed.getNodeValue(item,"dc:date")||Feed.getNodeValue(item,"date")||"",item)}catch(er){throw new Error("Feed.parseRss2 fail for "+i+" "+j+" ("+er.message+")")}}return{title:Feed.getNodeValue(channel,"title"),link:Feed.getNodeValue(channel,"link"),summary:Feed.getNodeValue(channel,"description"),published:Feed.getNodeValue(channel,"pubDate")||Feed.getNodeValue(channel,"dc:date")||Feed.getNodeValue(channel,"date")||"",entries:result}},parseRss091:function(xmlRoot,name,group){var i,result=[],item,channel=xmlRoot.getElementsByTagName("channel")[0],items=xmlRoot.getElementsByTagName("item");for(i=0;i<items.length;i+=1){item=items[i];try{result[result.length]=FeedItem(Feed.getNodeValue(item,"title"),Feed.getNodeValue(item,"description"),Feed.getNodeValue(item,"link"),Feed.getNodeValue(item,"pubDate")||Feed.getNodeValue(item,"dc:date")||Feed.getNodeValue(item,"date")||"",item)}catch(er){throw new Error("Feed.parseRss2 fail for "+i+" ("+er.message+")")}}return{title:Feed.getNodeValue(channel,"title"),link:Feed.getNodeValue(channel,"link"),summary:Feed.getNodeValue(channel,"description"),published:Feed.getNodeValue(channel,"pubDate")||Feed.getNodeValue(channel,"dc:date")||Feed.getNodeValue(channel,"date")||"",entries:result}},parseAtom:function(xmlRoot,name,group){var result=[],i,item,aUri,rootEl=xmlRoot.getElementsByTagName("feed")[0],baseUri=rootEl.getAttribute("xml:base"),items=xmlRoot.getElementsByTagName("entry");for(i=0;i<items.length;i+=1){item=items[i];try{aUri=Feed.getNodeValue(item,"link","href");if(baseUri&&aUri&&aUri.indexOf(":")<0){aUri=baseUri+aUri}result[result.length]=FeedItem(Feed.getNodeValue(item,"title"),Feed.getNodeValue(item,"summary"),aUri,Feed.getNodeValue(item,"published")||Feed.getNodeValue(item,"published")||"",item)}catch(er){throw new Error("Unable to parse item "+i+": "+er.message)}}return{title:Feed.getNodeValue(rootEl,"title"),link:Feed.getNodeValue(rootEl,"link","href"),summary:Feed.getNodeValue(rootEl,"description"),published:Feed.getNodeValue(rootEl,"published")||Feed.getNodeValue(rootEl,"updated")||"",entries:result}},fetch:function(url,callback){var xhr=HTTP.get({url:url,headers:{"X-Moz":"livebookmarks"}},function(err,response){if(err){console.error("error getting feed from: "+url);callback(err)}else{if(response.nodeType===Node.DOCUMENT_NODE){Feed.fromXML(response,callback)}else{Feed.fromString(response,callback)}}})},fromString:function(text,url,callback){if(typeof url=="function"){callback=url;url=""}var parser=new DOMParser,doc=parser.parseFromString(text,"application/xml");Feed.fromXML(doc,callback)},fromXML:function(doc,callback){if(doc){callback(null,Feed.parse(doc))}else{callback(ERR.PARAM_INVALID({param:"feed",value:"EMPTY"}))}},getText:function(feed){var buff=[feed.title];feed.entries.forEach(function(entry,index){buff.push(entry.title,entry.summary)});return buff.join(" \n")}};function FeedItem(title,summary,url,date,dom){return{title:title,link:url,summary:summary,published:date}}function Runner(sieve){var self=this,startedOn=Date.now(),type=sieve.content_type,config=sieve.config,context=new APIContext({pageMods:["locator"]});this.run=run;function getMetrics(){var endedOn=Date.now();return{on:startedOn,duration:endedOn-startedOn}}function run(resultCallback){switch(type){case C.TYPE_HTML:context.run_html(sieve,config,runnerCallback);break;case C.TYPE_FEED:run_feed(runnerCallback);break;default:resultCallback(Err.PARAM_INVALID({param:"config_type",value:type}));break}self.abort=abort;function abort(){runnerCallback(Err.ABORT({type:SieveStore.name,id:sieve.id}))}function runnerCallback(err,data){try{context._close()}catch(e){DBG&&console.error("RUNNER: error closing context:",e)}context=null;self=this;try{resultCallback&&resultCallback(err,data,getMetrics())}catch(e){DBG&&console.error("RUNNER: ERROR calling callback:",e);ErrorStore.create({context:"runner",msg:"Failed to call result callback after running job",data:JSON.stringify(sieve),err:JSON.stringify(Err.UNHANDLED(e))})}resultCallback=null}}function run_feed(callback){Feed.fetch(config.uri,function(err,feed){callback(err,err?null:{data_type:C.TYPE_FEED,data:JSON.stringify(feed),text:Feed.getText(feed)})})}}function LiveRunner(sieve){var startedOn=Date.now(),type=sieve.content_type,config=sieve.config,context=new APIContext({pageMods:["live"]});this.run=run;function getMetrics(){var endedOn=Date.now();return{on:startedOn,duration:endedOn-startedOn}}function run(resultCallback){switch(type){case C.TYPE_HTML:context.run_live_html(sieve,config,runnerCallback);break;default:resultCallback(Err.PARAM_INVALID({param:"config_type",value:type}));break}this.abort=abort;function abort(){try{context._close()}catch(e){DBG&&console.error("RUNNER: error closing context:",e)}context=null;self=null;runnerCallback(Err.ABORT({type:SieveStore.name,id:sieve.id}))}function runnerCallback(err,data){try{resultCallback(err,data,getMetrics())}catch(e){DBG&&console.error("RUNNER: ERROR calling callback:",e);ErrorStore.create({context:"runner",msg:"Failed to call result callback after running job",data:JSON.stringify(sieve),err:JSON.stringify(Err.UNHANDLED(e))})}}}}function APIContext(options){this.options=_.defaults(options||{},{openin:"bg"});this.pageMods=options.pageMods;this.pages=[]}_.extend(APIContext.prototype,Backbone.Events,{_addLoader:function(loader){var self=this;this.pages.push(loader);this.listenTo(loader,"load",this._onLoad);this.listenTo(loader,"load_error",this._onLoadError);this.listenTo(loader,"port:window:live:result",function(event){self.trigger("result",{page_id:loader.id,result:event.result})})},run_html:function(sieve,config,runCallback){var LOAD_TIMEOUT=60,self=this,result={data_type:C.TYPE_HTML,data:"",text:""},timeout=config.timeout,timeoutId;if(_.isNumber(timeout)){LOAD_TIMEOUT=timeout}if(LOAD_TIMEOUT>0){timeoutId=setTimeout(function(){DBG&&console.error("RUNNER:timeout");runCallback(Err.TIMEOUT({type:"Loading page",time:LOAD_TIMEOUT}));runCallback=function(err,data){DBG&&console.error("runCallback called after TIMEOUT",err,data)}},LOAD_TIMEOUT*1e3)}if(!config.selections){return runCallback(new Error("Invalid selections"))}function processResultAndCallback(err){clearTimeout(timeoutId);if(!err){var text=result.text.trim(),re=config.regexp;if(_.isString(re)){re={expr:re,flags:"gim"}}if(re&&re.expr){var matches=text.match(new RegExp(re.expr,re.flags||""));if(matches&&matches.length>0){text=matches.join(" ")}else{text=""}}result.text=text}delete self;runCallback(err,result)}async.mapSeries(config.selections,function(pageSelection,callback){pageSelection.uri||(pageSelection.uri=sieve.uri);self._page_filter(config,pageSelection,result,callback)},processResultAndCallback)},run_live_html:function(sieve,config,runCallback){var LOAD_TIMEOUT=60,self=this,result={data_type:C.TYPE_HTML,data:"",text:""},timeout=config.timeout,timeoutId;if(_.isNumber(timeout)){LOAD_TIMEOUT=timeout}if(LOAD_TIMEOUT>0){timeoutId=setTimeout(function(){DBG&&console.error("RUNNER:timeout");runCallback(Err.TIMEOUT({type:"Loading page",time:LOAD_TIMEOUT}));runCallback=function(err,data){DBG&&console.error("runCallback called after TIMEOUT",err,data)}},LOAD_TIMEOUT*1e3)}if(!config.selections){return runCallback(new Error("Invalid selections"))}function processResultAndCallback(err,_result){result.data=_result.html;result.text=_result.text;clearTimeout(timeoutId);if(!err){var text=result.text.trim(),re=config.regexp;if(_.isString(re)){re={expr:re,flags:"gim"}}if(re&&re.expr){var matches=text.match(new RegExp(re.expr,re.flags||""));if(matches&&matches.length>0){text=matches.join(" ")}else{text=""}}result.text=text}runCallback(err,result)}var pageSelection=config.selections[0];pageSelection.uri||(pageSelection.uri=sieve.uri);self._page_load(pageSelection,function(err,page){if(err){DBG&&console.error("LIVERUNNER: _page_load error",err);processResultAndCallback(err);return}clearTimeout(timeoutId);pageSelection.frames.forEach(function(frame){var selections=self._update_frame_selections(config,frame);self.page_frame_request({page_id:page.page_id,frame:frame.index,input:{path:"live_init",data:{includes:selections.includes,excludes:selections.excludes}}},function(err){if(err){DBG&&console.error("Failed to live_init",err);processResultAndCallback(err)}else{}})})});self.on("result",function(event){processResultAndCallback(null,event.result)})},_update_frame_selections:function(config,frame){var includes=frame.includes,excludes=frame.excludes||[];if(config.includeScript){includes.push({type:"xpath",expr:"//script[not(@src)]"})}else{excludes.push({type:"css",expr:"script"},{type:"xpath",expr:"//@*[starts-with(name(), 'on')]"})}if(config.includeStyle){includes.push({type:"css",expr:"style"},{type:"css",expr:"link[rel='stylesheet']"})}else{excludes.push({type:"css",expr:"style"},{type:"css",expr:"link[rel='stylesheet']"},{type:"xpath",expr:"//@*[name() ='style']"})}excludes.push({type:"css",expr:"frame"},{type:"css",expr:"iframe"});includes.push({type:"css",expr:"base"});return{excludes:excludes,includes:includes}},_frame_filter:function(config,page,frame,result,frameDone,retryCount){var MAX_RETRY_COUNT_ON_EMPTY_TEXT=4,MAX_RETRY_COUNT_ON_EMPTY_TEXT_FOR_HTML=1,RETRY_DELAY_ON_EMPTY_TEXT=5,self=this,selections=self._update_frame_selections(config,frame);async.waterfall([function(callback){self.page_frame_request({page_id:page.page_id,frame:frame.index,input:{path:"filterHTML",data:{includes:selections.includes,excludes:selections.excludes}}},callback)},function(ignore,callback){self.page_frame_request({page_id:page.page_id,frame:frame.index,input:{path:"getHTML"}},callback)},function(html,callback){result.data+=html;self.page_frame_request({page_id:page.page_id,frame:frame.index,input:{path:"getText"}},callback)}],function(err,text){if(err){frameDone(err)}else if(text){result.text+=text;frameDone(null)}else if(retryCount>MAX_RETRY_COUNT_ON_EMPTY_TEXT||config.dataAttr==="data"&&retryCount>MAX_RETRY_COUNT_ON_EMPTY_TEXT_FOR_HTML){frameDone(null)}else{setTimeout(function(){retryCount+=1;self._frame_filter(config,page,frame,result,frameDone,retryCount)},RETRY_DELAY_ON_EMPTY_TEXT*1e3)}})},_page_filter:function(config,pageSelection,result,callback){var self=this;async.waterfall([function(callback){self._page_load(pageSelection,callback)},function _select(page,callback){var frames=_.sortBy(pageSelection.frames,function(frame){return-frame.index});async.mapSeries(frames,function(frame,callback){self._frame_filter(config,page,frame,result,callback,0)},callback)}],callback)},_page_load:function(pageSelection,callback){var self=this;async.waterfall([function(callback){self.page_new(_.pick(pageSelection,"uri","dynamic"),callback)},function(page,callback){var frameIndices=_.pluck(pageSelection.frames,"index");self.page_load({page_id:page.page_id,uri:pageSelection.uri},function(){});self.on("load",onLoad);self.on("load_error",onLoadError);function onLoad(e){frameIndices=_.without(frameIndices,e.frame.index);if(frameIndices.length==0){self.off("load",onLoad);self.off("load_error",onLoadError);callback(null,page)}}function onLoadError(e){DBG&&console.error("event:load_error:%j",e);self.removeListener("load",onLoad);self.removeListener("load_error",onLoadError);callback(e)}}],callback)},_close:function(){this.off();this.stopListening();this.pages.forEach(function(loader){loader.destroy()});this.pages=null},_onLoad:function(aPort,aLoader){var self=this,event={page_id:aLoader.id,frame:{index:aLoader.ports.indexOf(aPort),uri:aPort.uri}};aLoader.port_request(aPort,{path:"require",data:this.pageMods},function(err){self.trigger("load",event)})},_onLoadError:function(aLoader,url){var hostname=getHostname(url),xframPrefName="x-frame-options."+hostname,hasXFrame=Prefs.get(xframPrefName);hasXFrame===false&&Prefs.del(xframPrefName)},_removeLoader:function(loader){_.remove(self.pages,loader)},page_close:function(input,cb){var self=this;with_loader(input.page_id,function(err,loader){if(err)return cb(err);loader.destroy();cb();self._removeLoader(loader)})},page_eval:function(input,cb){with_loader(input.page_id,function(err,loader){if(err)return cb(err);loader.eval(input.script,function(err,data){if(err)return cb(err);cb(null,{page_id:input.page_id,data:data})})})},page_load:function(input,cb){if(_.isEmpty(input.uri)){return Err.PARAM_INVALID({param:"uri",value:"empty"})}with_loader(input.page_id,function(err,loader){if(err)return cb(err);loader.load(input.uri,function(err,data){if(err)return cb(err);cb(null)})})},page_new:function(input,cb){var self=this;if(self.options.openin=="tab"){input.type="tab"}if(input.dynamic!==false&&Supports.tabForXFrame&&input.uri&&input.type===void 0){var hostname=getHostname(input.uri),sitePref="x-frame-options."+hostname,hasXFrame=Prefs.get(sitePref);if(hasXFrame!==void 0){hasXFrame&&setOpenInTab();create()}else{HTTP.get({url:input.uri},function(err,res,xhr){if(err){cb(err)}else{checkResponseAndCreate(res,xhr)}})}function checkResponseAndCreate(res,xhr){hasXFrame=xhr.getResponseHeader("x-frame-options")||/x-frame-options/i.test(res);Prefs.set(sitePref,hasXFrame);hasXFrame&&setOpenInTab();create()}function setOpenInTab(){var userPref=Prefs.get("x-frame-load-in");if(userPref=="tab"){_.defaults(input,{type:"tab",info:_.defaults(input.info||{},{active:false,index:0,pinned:true})})}else if(userPref=="window"){_.defaults(input,{type:"window",info:_.defaults(input.info||{},{active:false})})}else if(userPref=="bg"){input.dynamic=false}}}else{create()}function create(){input.info||(input.info={});createLoader(input,function(err,loader){if(err){callback(err)}else{self._addLoader(loader);_.delay(cb,2e3,null,{page_id:loader.id})}})}},page_frame_request:function(input,cb){with_loader(input.page_id,function(err,loader){if(err)return cb(err);loader.port_request(input.frame,input.input,cb)})},http_request:HTTP.request});function with_loader(page_id,callback){var loader=WebpageLoader.get(page_id);callback(!loader&&Err.NOT_FOUND({type:"loader",param:"id",id:page_id}),loader)}var DATE_START=new Date;DBG&&console.log("init main",DATE_START);function showUpdateNotes(version,newVersion){chrome.tabs.create({url:CFG.URL.CHANGELOG+"?from="+version+"&to="+newVersion,active:true})}function upgradeCheck(){var version=Prefs.get("version"),newVersion=CFG.VERSION;if(!version){Prefs.set("version",newVersion);setTimeout(function(){chrome.tabs.create({url:CFG.URL.WELCOME+"?utm_source=install",active:true})},2e3)}else if(version!=newVersion){var oldDate=version.split(".").pop();Prefs.set("version",newVersion);setTimeout(function(){showUpdateNotes(version,newVersion)},2e3)}}var Scheduler=function(){var timeouts={},runners={},liveRunners={},checkInetervalId,q=[],nActive=0,initialized=false;function checkQueue(){var nMaxWorkers=Prefs.get("nworkers"),nWaiting=q.length;if(nWaiting>0&&nActive<nMaxWorkers){SieveStore.findOne(q.shift(),{only:["id","name","uri","config","content_type","schedule","err","rule_id"]},function(err,sieve){if(!sieve){return}sieve.config=JSON.parse(sieve.config);run(sieve,function(err){err&&console.error("Error running:",sieve,err);nActive-=1;if(!(err&&Err.ABORT.si(err))){schedule(sieve)}else{}});nActive+=1;if(nActive<nMaxWorkers&&nWaiting>1){setTimeout(checkQueue,200)}})}}function deSchedule(sieve){var id=_.isString(sieve)?sieve:sieve.id,timeoutId=timeouts[id],liveRunner=liveRunners[id];if(timeoutId){delete timeouts[id];clearTimeout(timeoutId)}if(liveRunner){liveRunner.abort()}}function getSchedule(sieve,callback){var schedule=sieve.schedule;WorkStore.find({rel:SieveStore.name,key:sieve.id},{limit:10,only:["id","err","ts"],order:["-ts"]},function(err,result){if(err){callback(err)}else{var scheduler=ScheduleDescriptors[schedule.type];if(!scheduler){callback(Err.TYPE_UNNOWN({type:"scheduler",value:schedule.type}))}else{callback(null,scheduler.getSchedule(schedule.params,result.data))}}})}function onUpdate(sieve){var state=sieve.state;if(state!=void 0&&state!=C.STATE_READY){deSchedule(sieve)}else if(state==C.STATE_READY){schedule(sieve.id)}else if("schedule"in sieve){schedule(sieve)}}function processResult(sieve,result,doneCallback){var dataAttr=sieve.config.dataAttr||"text",ignoreWhitespace=sieve.config.ignoreWhitespace!==false;SieveDataStore.findOne({sieve_id:sieve.id},{only:["id","ts","text","data"],order:["-ts"]},function(err,lastData){if(err){doneCallback(err)}else{var RE_WHITESPACE=/\s|\b/g,RE_SPLIT=/\s+|\b/g,equal=lastData&&(ignoreWhitespace?_.isEqual(lastData[dataAttr].replace(RE_WHITESPACE,""),result[dataAttr].replace(RE_WHITESPACE,"")):_.isEqual(lastData[dataAttr].split(RE_SPLIT),result[dataAttr].split(RE_SPLIT)));if(equal){if(sieve.err){SieveStore.update(sieve.id,{err:null},doneCallback)}else{doneCallback()}}else{saveData(lastData)}}});function saveData(lastData){async.parallel({sieve_data:function(callback){SieveDataStore.create(_.extend({sieve_id:sieve.id},result),callback)},sieve:function(callback){var doc={err:null,text:result.text.slice(0,200),ts_data:Date.now()};if(!lastData){doc.ts_view=doc.ts_data+1}SieveStore.update(sieve.id,doc,callback)}},function(err,results){doneCallback(err);if(lastData){function find_diff(text_old,text_new){var dmp=new diff_match_patch,a=dmp.diff_wordsToChars_(text_old,text_new),diffs=dmp.diff_main(a.chars1,a.chars2,false);dmp.diff_charsToLines_(diffs,a.wordArray);return diffs}function getSummary(diffs){console.log("diffs:",diffs);var firstIns=-1,firstInsEnd=-1,len=0,summary=_.reduce(diffs,function(buff,aDiff){var op=aDiff[0],text=aDiff[1];if(op==DIFF_EQUAL){buff.push(text);len+=text.length}else if(op==DIFF_INSERT){text="*"+text.trim()+"*";buff.push(text);if(firstIns<0){firstIns=len;firstInsEnd=firstIns+text.length}len+=text.length}return buff},[]).join("");if(firstIns>40){if(firstInsEnd>80){summary="..."+summary.slice(firstIns-10)}}return summary.slice(0,200)}var curData=results.sieve_data,diffs=find_diff(lastData.text,curData.text),dels=_.reduce(diffs,function(buff,aDiff){if(aDiff[0]==DIFF_DELETE){buff.push(aDiff[1])}return buff},[]).join(" "),inserts=_.reduce(diffs,function(buff,aDiff){if(aDiff[0]==DIFF_INSERT){buff.push(aDiff[1])}return buff},[]).join(" "),context={sieve:sieve,sieve_data:results.sieve_data,items:[curData,lastData],diffs:diffs,dels:dels,inserts:inserts};ActionManager.computeActions(context);SieveDataStore.destroyWithSubQuery({sieve_id:sieve.id},{limit:10,offset:10,order:["-ts"]},function(err){if(err){DBG&&console.error("Scheduler:SieveDataStore:destroyWithSubQuery",err)}})}})}}function qNow(id){deSchedule(id);q.push(id);gEvents.trigger("worker:sieve:state",{id:id,state:C.RUN_STATE_WAIT})}function resetAll(){_.each(_.values(timeouts),deSchedule);_.each(_.values(runners),stop);scheduleAll()}function run(sieve,callback){var runner=new Runner(sieve);stop(sieve);runners[sieve.id]=runner;runner.run(function(errRun,result,metrics){delete runners[sieve.id];sieveResultHandler(sieve,errRun,result,metrics,callback)});gEvents.trigger("worker:sieve:state",{id:sieve.id,state:C.RUN_STATE_WIP})}function runLive(sieve){var oldRunner=liveRunners[sieve.id];if(oldRunner){console.error("LiveRunner already running");return}var liveRunner=new LiveRunner(sieve);liveRunners[sieve.id]=liveRunner;liveRunner.run(function(errRun,result,metrics){if(errRun){DBG&&console.error("Error running live monitor",errRun,sieve);if(Err.ABORT.si(errRun)){delete liveRunners[sieve.id]}else if(Err.TIMEOUT.si(errRun)){liveRunner.abort()}}sieveResultHandler(sieve,errRun,result,metrics,function(err){if(!err){return}})})}function sieveResultHandler(sieve,errRun,result,metrics,callback){if(errRun&&Err.ABORT.si(errRun)){callback(errRun);return}var work={rel:SieveStore.name,key:sieve.id,duration:metrics.duration};if(!errRun&&result.text.length==0){if(sieve.config&&sieve.config.ignoreEmptyText!==false){errRun=Err.SELECTION_EMPTY()}}errRun&&(work.err=JSON.stringify(errRun));WorkStore.create(work,function(errSaveWork){if(errSaveWork){DBG&&console.error("Scheduler: failed to save work result to DB")}if(errRun){SieveStore.update(sieve.id,{err:work.err},function(){callback(errRun)})}else{processResult(sieve,result,callback)}WorkStore.destroyWithSubQuery({rel:SieveStore.name,key:sieve.id},{limit:10,offset:10,order:["-ts"]},function(err){if(err){DBG&&console.error("Scheduler:WorkStore:create:destroy:err",err)}})});gEvents.trigger("worker:sieve:state",{id:sieve.id,state:C.RUN_STATE_INIT})}function schedule(sieve,callback){callback||(callback=function(err){if(err)throw err});var client_id=Prefs.get("client.id"),user_id=auth.getId(),id=_.isString(sieve)?sieve:sieve.id;SieveStore.findOne(id,function(err,sieve){if(!sieve||sieve.client_id!=client_id||user_id&&sieve.user_id!=user_id||sieve.state!=C.STATE_READY){deSchedule(sieve);return}sieve.config=JSON.parse(sieve.config);sieve.schedule=JSON.parse(sieve.schedule);if(sieve.schedule.type=="LIVE"){return runLive(sieve)}else{deSchedule(sieve)}getSchedule(sieve,function(err,scheduleOn){if(err){DBG&&console.error("Error getting schedule:",sieve,err);callback(err)}else if(scheduleOn<0){callback()}else{var intervalInMs=Math.min(scheduleOn*1e3-Date.now(),2147483647);timeouts[sieve.id]=setTimeout(function(){qNow(sieve.id)},intervalInMs);callback()}})})}function scheduleAll(offset){offset||(offset=0);SieveStore.find({state:C.STATE_READY,client_id:Prefs.get("client.id"),$or:[["user_id",auth.getId()],["user_id",null]]},{limit:1e3,offset:offset,only:["id","schedule","ts"],order:["-ts"]},function(err,result){if(err){DBG&&console.error("Failed to schedule.")}else{async.eachSeries(result.data,schedule,function(err){if(err){DBG&&console.error("Error scheduling:",err)}else{if(result.total_count>result.count+result.offset){scheduleAll(result.offset+result.count)}}})}})}function stop(sieve){var oldRunner=runners[sieve.id];delete runners[sieve.id];if(oldRunner){oldRunner.abort()}}return{isBusy:function(){return _.size(runners)>0},checkNow:function(ids){_.each(ids,qNow)},init:function(){_.delay(scheduleAll,6e3);checkInetervalId=setInterval(function(){checkQueue()},1e3);gEvents.on("store:"+SieveStore.name+":create",schedule);gEvents.on("store:"+SieveStore.name+":update",onUpdate);gEvents.on("store:"+SieveStore.name+":destroy",deSchedule);initialized=true},uninit:function(){initialized=false;clearInterval(checkInetervalId);gEvents.off("store:"+SieveStore.name+":create",schedule);gEvents.off("store:"+SieveStore.name+":update",onUpdate);gEvents.off("store:"+SieveStore.name+":destroy",deSchedule);_.each(_.values(runners),function(runner){runner.abort()});_.each(timeouts,clearTimeout);timeouts={};q.splice(0)}}}();var ActionManager=function(){function computeActions(context){async.waterfall([function(callback){async.parallel({rule:function(callback){if(context.sieve.rule_id){RuleStore.findOne(context.sieve.rule_id,callback)}else{callback(null)}},actions:function(callback){ActionStore.find({sieve_id:context.sieve.id,state:0},callback)}},callback)},function(result,callback){context.actions=result.actions.data;context.rule=result.rule;if(matchRule(context)){takeActions(context)}else{SieveStore.update(context.sieve.id,{ts_view:Date.now()})}callback()}])}function takeActions(context){async.each(context.actions,function(action,callback){var desc=ActionDescriptors[action.type];if(!desc){DBG&&console.error("Invalid action type",action);callback(Err.NOT_FOUND({type:"action:desc",id:action.type}))}else{action.config&&(action.config=JSON.parse(action.config));desc.act(action,context,callback)}})}return{computeActions:computeActions,init:function(){},uninit:function(){}}}();function Service(options){var self=this;this.options=_.extend({},this.OPTIONS,options);this.active=true;this.state=new Backbone.Model({unread:0});this.state.on("change:unread",function(event){gEvents.trigger("change:unread",this.state.get("unread"))},this);_.extend(this,Backbone.Events);this.init(function(err){if(err){DBG&&console.error("Failed to init distill service:",err)}self.trigger("init init:data");Prefs.on("change:service.user_id",function(){self.initData()});Prefs.on("change:account.sync",function(enabled){if(enabled){self.initSync()}})});upgradeCheck()}_.extend(Service.prototype,{appUrl:CFG.URL.BASE+"inbox.html",Scheduler:Scheduler,SyncMan:SyncMan,checkNow:Scheduler.checkNow,init:function(callback){gEvents.on("store:"+SieveDataStore.name+":create",this.onSieveDataCreate,this);this.initData(callback)},initData:function(callback){var self=this;async.series([initStores,function(callback){auth.init(function(err){err&&console.error("Failed to init auth",err);callback()})},SyncId.init,initData,function(callback){self.ready=true;self.trigger("init");callback()},function(callback){self.initSync(callback)},function(callback){if(auth.getId()&&!SyncMan.canSync()){async.parallel([function(callback){SyncMan.get(UserStore,callback)},function(callback){SyncMan.get(AttrStore,callback)}],callback)}else{callback()}}],callback)},initSync:function(callback){callback||(callback=function(){});var self=this;if(SyncMan.canSync()){createEventSource(function(err,res){if(err){var retryInterval=3e5;DBG&&console.error("SSE failed to initialize:",err,res);if(err.status==401){auth.save(auth.get(),function(err,res){callback(err)})}else{if(err.status==403){retryInterval=36e5}else if(err.status==0||err.status>500){retryInterval=5e3}setTimeout(_.bind(self.initSync,self),retryInterval);callback()}}else{SyncMan.accountEnabled=true;self.setEventSource(res,callback)}})}else{this.setEventSource(null);callback()}},markRead:function(){SieveStore.update({state:C.STATE_READY,"ts_view.lt":{name:"ts_data",type:"field"}},{ts_view:Date.now()});this.syncStore(SieveStore)},markReadById:function(id){SieveStore.update(id,{ts_view:Date.now()});this.syncStore(SieveStore)},pause:function(){Scheduler.uninit();ActionManager.uninit();gEvents.off("store:create:"+SieveStore.name,this.onSieveCreate,this);gEvents.off("store:destroy:"+SieveStore.name,this.onSieveDestroy,this);gEvents.off("store:update:"+SieveStore.name,this.onSieveUpdate,this)},onSieveCreate:function(doc){this.updateState(doc.id)},onSieveDataCreate:function(doc){var self=this;if(doc._state!==C.LOCAL_STATE_SYNCED){this.syncStore(SieveDataStore,function(err){if(!err){self.syncStore(SieveStore,{delay:100})}})}},onSieveDestroy:function(doc){
  9.  
  10. 4.
  11. this.updateState(doc.id)},onSieveUpdate:function(doc){this.updateState(doc.id)},open:function(id,options,callback){var self=this;if(typeof options=="function"){callback=options;options={}}SieveStore.findOne(id,{only:["uri"]},function(err,sieve){if(err){callback(Err.NOT_FOUND({type:"sieve",id:id}))}else{var url=sieve.uri;self.showURL(url,options,callback)}})},openAndMarkRead:function(id,options,callback){var self=this;SieveStore.update(id,{ts_view:Date.now()},function(){self.open(id,options,callback)});this.syncStore(SieveStore)},openGettingStarted:function(){chrome.tabs.create({url:CFG.URL.WELCOME,active:true})},resume:function(){Scheduler.init();ActionManager.init();gEvents.on("store:"+SieveStore.name+":create",this.onSieveCreate,this);gEvents.on("store:"+SieveStore.name+":destroy",this.onSieveDestroy,this);gEvents.on("store:"+SieveStore.name+":update",this.onSieveUpdate,this);this.updateState()},setActive:function(active){this.active=active;this[active?"resume":"pause"]();gEvents.trigger("service:active",active)},setEventSource:function(source,callback){DBG&&console.log("setEventSource");var self=this;callback||(callback=function(){});if(this.eventSource){this.eventSource.close()}this.eventSource=source;if(source){source.addEventListener("message",function(e){var data=JSON.parse(e.data),store=SQLStore[REMOTE_LOCAL_NAME_MAP[data.name]];DBG&&console.log("events:store found?",data.name,!!store);store&&store.findOne(data.id,{only:["ts_mod"]},function(err,doc){if(err){DBG&&console.error("Error fetching doc:",err)}else if(!doc){self.syncStore(store)}else{var ts1=new Date(data.ts_mod),ts2=new Date(doc.ts_mod),delta=Math.abs(ts1.valueOf()-ts2.valueOf());DBG&&console.log("ts:",data.ts_mod,ts1,doc.ts_mod,ts2,delta);if(delta>5e3){self.syncStore(store)}}})});source.addEventListener("error",function(e){DBG&&console.error("EventSource error",e);switch(e.target.readyState){case EventSource.CLOSED:self.initSync();break}});SyncMan.sync(false,callback)}else{callback()}},showInInbox:function(id,callback){chrome.tabs.create({active:true,url:this.appUrl+"+#inbox/"+id},function(){callback&&callback()})},showWatchlist:function(callback){this.showURL(this.appUrl)},showURL:function(url,options,callback){if(typeof options=="function"){callback=options;options={}}options||(options={});callback||(callback=function(err){err&&console.error("showURL:",err)});chrome.tabs.query({url:url},function(tabs){if(tabs&&tabs.length>0){chrome.tabs.update(tabs[0].id,{active:true,url:url},function(tab){callback(null,tab)})}else{chrome.tabs.query({active:true},function(tabs){var tab=tabs.length>0&&tabs[0];if(tab&&options.openInBlank!==false&&/^(about:blank)|(about:newtab)|(chrome:\/\/newtab)/.test(tab.url)){chrome.tabs.update(tab.id,{active:true,url:url},function(tab){callback(null,tab)})}else{chrome.tabs.create({active:true,url:url},function(tab){callback(null,tab)})}})}})},syncStore:function(store,options,callback){if(typeof options=="function"){callback=options;options=null}if(SyncMan.canSync()){SyncMan.syncStore(store,options||{delay:5e3},function(){})}},updateState:function(sieveId){var self=this;SieveStore.find({state:C.STATE_READY,"ts_view.lt":{name:"ts_data",type:"field"}},{only:["id"],limit:1},function(err,result){self.state.set("unread",result.total_count)});if(sieveId){SieveStore.findOne(sieveId,{only:["_state"]},function(err,doc){if(doc&&doc._state!==C.LOCAL_STATE_SYNCED){self.syncStore(SieveStore,{delay:1e3})}})}}});(function(){var since=Date.now(),count=0,startDurationAvg=0,startTimeoutAvg=0,lastDurationAvg=0,lastTimeoutAvg=0,SAMPLE_SIZE=50,warmup=true;gEvents.on("store:works:create",function(work){count+=1;if(warmup){if(count<SAMPLE_SIZE){return}else{warmup=false;count=0}}var lastCount=count>SAMPLE_SIZE?SAMPLE_SIZE:count,isTimedout=work.err&&work.err.indexOf("TIMEOUT")>0;if(count<=SAMPLE_SIZE){startDurationAvg=startDurationAvg+(work.duration-startDurationAvg)/count;if(isTimedout){startTimeoutAvg=startTimeoutAvg+1/count}}lastDurationAvg=lastDurationAvg+(work.duration-lastDurationAvg)/lastCount;if(isTimedout){lastTimeoutAvg=lastTimeoutAvg+(1-lastTimeoutAvg)/lastCount}if(lastDurationAvg>3*startDurationAvg||startTimeoutAvg>.01&&lastTimeoutAvg>3*startTimeoutAvg||count>SAMPLE_SIZE&&lastTimeoutAvg>.3||count>20*SAMPLE_SIZE){setTimeout(reload,1e3)}});chrome.tabs.query({url:["about:blank","chrome://blank/"]},function(tabs){tabs.forEach(restore)})})();function reload(){service.Scheduler.uninit();chrome.tabs.query({url:CFG.URL.BASE+"*"},function(tabs){async.each(tabs,function(tab,callback){chrome.tabs.update(tab.id,{url:"about:blank#"+encodeURIComponent(tab.url)},function(){callback()})},function(){setTimeout(function(){chrome.runtime.reload()},1e3)})})}function restore(tab){var idxHash=tab.url.indexOf("#"),url=idxHash>0?tab.url.slice(idxHash+1):null;if(url){url=decodeURIComponent(url);chrome.tabs.update(tab.id,{url:url})}}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement