background.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. var db,port=null,pos=0;
  2. function initDb(callback) {
  3. var request=indexedDB.open('Violentmonkey',1);
  4. request.onsuccess=function(e){db=request.result;if(callback) callback();};
  5. request.onerror=function(e){console.log('IndexedDB error: '+e.target.error.message);};
  6. request.onupgradeneeded=function(e){
  7. var r=e.currentTarget.result,o;
  8. // scripts: id uri custom meta enabled update code position
  9. o=r.createObjectStore('scripts',{keyPath:'id',autoIncrement:true});
  10. o.createIndex('uri','uri',{unique:true});
  11. o.createIndex('update','update',{unique:false});
  12. o.createIndex('position','position',{unique:false}); // should be unique at last
  13. // require: uri code
  14. o=r.createObjectStore('require',{keyPath:'uri'});
  15. // cache: uri data
  16. o=r.createObjectStore('cache',{keyPath:'uri'});
  17. // values: uri values
  18. o=r.createObjectStore('values',{keyPath:'uri'});
  19. };
  20. }
  21. function getNameURI(i) {
  22. var ns=i.meta.namespace||'',n=i.meta.name||'',k=escape(ns)+':'+escape(n)+':';
  23. if(!ns&&!n) k+=i.id;
  24. return k;
  25. }
  26. function getMeta(j){return {id:j.id,custom:j.custom,meta:j.meta,enabled:j.enabled,update:j.update};}
  27. function parseMeta(d){
  28. var o=-1,meta={include:[],exclude:[],match:[],require:[],resource:[],grant:[]};
  29. d.replace(/(?:^|\n)\/\/\s*([@=]\S+)(.*)/g,function(m,k,v){
  30. if(o<0&&k=='==UserScript==') o=1;
  31. else if(k=='==/UserScript==') o=0;
  32. if(o==1&&k[0]=='@') k=k.slice(1); else return;
  33. v=v.replace(/^\s+|\s+$/g,'');
  34. if(meta[k]&&meta[k].push) meta[k].push(v); // multiple values allowed
  35. else if(!(k in meta)) meta[k]=v; // only first value will be stored
  36. });
  37. meta.resources={};
  38. meta.resource.forEach(function(i){
  39. o=i.match(/^(\w\S*)\s+(.*)/);
  40. if(o) meta.resources[o[1]]=o[2];
  41. });
  42. delete meta.resource;
  43. if(!meta.homepageURL&&meta.homepage) meta.homepageURL=meta.homepage; // @homepageURL instead of @homepage
  44. return meta;
  45. }
  46. function newScript() {
  47. var r={
  48. custom: {},
  49. enabled: 1,
  50. update: 1,
  51. code: '// ==UserScript==\n// @name New Script\n// ==/UserScript==\n'
  52. };
  53. r.meta=parseMeta(r.code);
  54. return r;
  55. }
  56. function removeScript(i,src,callback) {
  57. var o=db.transaction('scripts','readwrite').objectStore('scripts');
  58. o.delete(i);
  59. if(callback) callback();
  60. }
  61. function saveScript(i,src,callback) {
  62. var o=db.transaction('scripts','readwrite').objectStore('scripts');
  63. i.enabled=i.enabled?1:0;
  64. i.update=i.update?1:0;
  65. if(!i.position) i.position=++pos;
  66. if(callback) callback();
  67. return o.put(i);
  68. }
  69. function vacuum(o,src,callback) {
  70. var ids=[],cc={},rq={},vl={},w=0,p=0;
  71. function init(){
  72. var o=db.transaction('scripts').objectStore('scripts');
  73. o.index('position').openCursor().onsuccess=function(e){
  74. var r=e.target.result,v,i;
  75. if(r) {
  76. v=r.value;ids.push(v.id);
  77. v.meta.require.forEach(function(i){rq[i]=1;});
  78. for(i in v.meta.resources) cc[v.meta.resources[i]]=1;
  79. if(v.meta.icon) cc[v.meta.icon]=1;vl[v.uri]=1;
  80. r.continue();
  81. } else vacuumPosition();
  82. };
  83. }
  84. function vacuumPosition(){
  85. var i=ids.shift();
  86. if(i) {
  87. var o=db.transaction('scripts','readwrite').objectStore('scripts');
  88. o.get(i).onsuccess=function(e){
  89. var r=e.target.result;r.position=++p;
  90. o.put(r).onsuccess=vacuumPosition;
  91. };
  92. } else {
  93. pos=p;
  94. vacuumDB('require',rq);
  95. vacuumDB('cache',cc);
  96. vacuumDB('values',vl);
  97. }
  98. }
  99. function vacuumDB(dbName,dic){
  100. w++;
  101. var o=db.transaction(dbName,'readwrite').objectStore(dbName);
  102. o.openCursor().onsuccess=function(e){
  103. var r=e.target.result,v;
  104. if(r) {
  105. v=r.value;
  106. if(!dic[v.uri]) o.delete(v.uri);
  107. else dic[v.uri]++; // stored
  108. r.continue();
  109. } else finish();
  110. };
  111. }
  112. function finish(){
  113. if(!--w) {
  114. var i;
  115. for(i in rq) if(rq[i]==1) fetchRequire(i);
  116. for(i in cc) if(cc[i]==1) fetchCache(i);
  117. chrome.tabs.sendMessage(src.tab.id,{cmd:'Vacuumed'});
  118. }
  119. }
  120. init();
  121. if(callback) callback();
  122. }
  123. function move(data,src,callback){
  124. var o=db.transaction('scripts','readwrite').objectStore('scripts');
  125. o.get(data.id).onsuccess=function(e){
  126. var r=e.target.result,k,s,x=r.position;
  127. if(data.offset<0) {
  128. k=IDBKeyRange.upperBound(x,true);
  129. s='prev';
  130. data.offset=-data.offset;
  131. } else {
  132. k=IDBKeyRange.lowerBound(x,true);
  133. s='next';
  134. }
  135. o.index('position').openCursor(k,s).onsuccess=function(e){
  136. var p=e.target.result,v;
  137. if(p) {
  138. data.offset--;
  139. v=p.value;v.position=x;o.put(v);x=p.key;
  140. if(data.offset) p.continue();
  141. else {r.position=x;o.put(r);}
  142. }
  143. };
  144. };
  145. if(callback) callback();
  146. }
  147. function str2RE(s){return s.replace(/(\.|\?|\/)/g,'\\$1').replace(/\*/g,'.*?');}
  148. function autoReg(s, w) {
  149. if(!w&&s[0]=='/'&&s.slice(-1)=='/') return RegExp(s.slice(1,-1));
  150. return RegExp('^'+str2RE(s)+'$');
  151. }
  152. var match_reg=/(.*?):\/\/([^\/]*)\/(.*)/;
  153. function matchTest(s,u) {
  154. var m=s.match(match_reg);
  155. if(!m) return false;
  156. if(m[1]=='*') {
  157. if(u[1]!='http'&&u[1]!='https') return false;
  158. } else if(m[1]!=u[1]) return false;
  159. if(m[2]!='*') {
  160. if(m[2].slice(0,2)=='*.') {
  161. if(u[2]!=m[2].slice(2)&&u[2].slice(1-m[2].length)!=m[2].slice(1)) return false;
  162. } else if(m[2]!=u[2]) return false;
  163. }
  164. if(!autoReg(m[3],1).test(u[3])) return false;
  165. return true;
  166. }
  167. function testURL(url,e) {
  168. var f=true,i,inc=[],exc=[],mat=[],u=url.match(match_reg);
  169. if(e.custom._match!=false&&e.meta.match) mat=mat.concat(e.meta.match);
  170. if(e.custom.match) mat=mat.concat(e.custom.match);
  171. if(e.custom._include!=false&&e.meta.include) inc=inc.concat(e.meta.include);
  172. if(e.custom.include) inc=inc.concat(e.custom.include);
  173. if(e.custom._exclude!=false&&e.meta.exclude) exc=exc.concat(e.meta.exclude);
  174. if(e.custom.exclude) exc=exc.concat(e.custom.exclude);
  175. if(mat.length) {
  176. for(i=0;i<mat.length;i++) if(f=matchTest(mat[i],u)) break;
  177. } else for(i=0;i<inc.length;i++) if(f=autoReg(inc[i]).test(url)) break;
  178. if(f) for(i=0;i<exc.length;i++) if(!(f=!autoReg(exc[i]).test(url))) break;
  179. return f;
  180. }
  181. function getScript(id,src,callback) { // for user edit
  182. var o=db.transaction('scripts').objectStore('scripts');
  183. o.get(id).onsuccess=function(e){
  184. var r=e.target.result,v;
  185. if(r) {
  186. v=getMeta(r);
  187. v.code=r.code;
  188. if(callback) callback(v);
  189. }
  190. };
  191. }
  192. function getMetas(ids,src,callback) { // for popup menu
  193. var o=db.transaction('scripts').objectStore('scripts'),data=[],id;
  194. function getOne(){
  195. var id=ids.shift();
  196. if(id) o.get(id).onsuccess=function(e){
  197. var r=e.target.result;
  198. if(r) data.push(getMeta(r));
  199. getOne();
  200. }; else callback(data);
  201. }
  202. getOne();
  203. }
  204. function getCacheB64(ids,src,callback) {
  205. var o=db.transaction('cache').objectStore('cache'),data={};
  206. function loop(){
  207. var i=ids.pop();
  208. if(i) o.get(i).onsuccess=function(e){
  209. var r=e.target.result,b,u;
  210. if(r) {
  211. if(typeof r.data=='string') data[i]=r.data;
  212. else
  213. // XXX: old data, update it
  214. setTimeout(function(){fetchCache(i)},1);
  215. }
  216. loop();
  217. }; else callback(data);
  218. }
  219. loop();
  220. }
  221. function getInjected(url,src,callback) { // for injected
  222. function getScripts(){
  223. var o=db.transaction('scripts').objectStore('scripts'),n=0,require={};
  224. o.index('position').openCursor().onsuccess=function(e){
  225. var i,r=e.target.result,v;
  226. if(r) {
  227. v=r.value;
  228. if(testURL(url,v)) {
  229. data.scripts.push(v);if(v.enabled) n++;
  230. values.push(v.uri);
  231. v.meta.require.forEach(function(i){require[i]=1;});
  232. for(i in v.meta.resources) cache[v.meta.resources[i]]=1;
  233. }
  234. r.continue();
  235. } else {
  236. if(n) {
  237. chrome.browserAction.setBadgeBackgroundColor({color:'#808',tabId:src.tab.id});
  238. chrome.browserAction.setBadgeText({text:n.toString(),tabId:src.tab.id});
  239. }
  240. getRequire(Object.getOwnPropertyNames(require));
  241. }
  242. };
  243. }
  244. function getRequire(require){
  245. function loop(){
  246. var i=require.pop();
  247. if(i) o.get(i).onsuccess=function(e){
  248. var r=e.target.result;
  249. if(r) data.require[i]=r.code;
  250. loop();
  251. }; else getCache();
  252. }
  253. var o=db.transaction('require').objectStore('require');
  254. loop();
  255. }
  256. function getCache(){
  257. getCacheB64(Object.getOwnPropertyNames(cache),src,function(o){
  258. data.cache=o;
  259. getValues();
  260. });
  261. }
  262. function getValues(){
  263. function loop(){
  264. var i=values.pop();
  265. if(i) o.get(i).onsuccess=function(e){
  266. var r=e.target.result;
  267. if(r) data.values[i]=r.values;
  268. loop();
  269. }; else finish();
  270. }
  271. var o=db.transaction('values').objectStore('values');
  272. loop();
  273. }
  274. function finish(){callback(data);}
  275. var data={scripts:[],values:{},require:{}},cache={},values=[];
  276. if(data.isApplied=settings.isApplied) getScripts(); else finish();
  277. }
  278. function fetchURL(url, cb, type, headers) {
  279. var req=new XMLHttpRequest(),i;
  280. req.open('GET', url, true);
  281. if(type) req.responseType = type;
  282. if(headers) for(i in headers)
  283. req.setRequestHeader(i,headers[i]);
  284. if(cb) req.onloadend = cb;
  285. req.send();
  286. }
  287. var u_cache={},u_require={};
  288. function saveCache(url,data,callback) {
  289. var o=db.transaction('cache','readwrite').objectStore('cache');
  290. o.put({uri:url,data:data}).onsuccess=callback;
  291. }
  292. function fetchCache(url) {
  293. if(u_cache[url]) return;
  294. u_cache[url]=1;
  295. fetchURL(url, function() {
  296. if (this.status!=200) return;
  297. //saveCache(url,this.response,function(){delete u_cache[url];});
  298. var r=new FileReader();
  299. r.onload=function(e){
  300. saveCache(url,window.btoa(r.result),function(){delete u_cache[url];});
  301. };
  302. r.readAsBinaryString(this.response);
  303. }, 'blob');
  304. }
  305. function saveRequire(url,data,callback) {
  306. var o=db.transaction('require','readwrite').objectStore('require');
  307. o.put({uri:url,code:data}).onsuccess=callback;
  308. }
  309. function fetchRequire(url) {
  310. if(u_require[url]) return;
  311. u_require[url]=1;
  312. fetchURL(url, function(){
  313. if(this.status==200) saveRequire(url,this.responseText,function(){delete u_require[url];});
  314. });
  315. }
  316. function updateItem(r){
  317. if(port) try{
  318. port.postMessage(r);
  319. }catch(e){
  320. port=null;
  321. console.log(e);
  322. }
  323. }
  324. function queryScript(id,meta,callback){
  325. var o=db.transaction('scripts').objectStore('scripts');
  326. function finish(r){
  327. if(!r) r=newScript();
  328. if(callback) callback(r);
  329. }
  330. function queryMeta() {
  331. var uri=getNameURI({id:'',meta:meta});
  332. if(uri!='::') o.index('uri').get(uri).onsuccess=function(e){
  333. finish(e.target.result);
  334. }; else finish();
  335. }
  336. function queryId() {
  337. if(id) o.get(id).onsuccess=function(e){
  338. var r=e.target.result;
  339. if(r) finish(r); else queryMeta();
  340. }; else queryMeta();
  341. }
  342. queryId();
  343. }
  344. function parseScript(o,src,callback) {
  345. var i,r={status:0,message:'message' in o?o.message:_('msgUpdated')};
  346. function finish(){
  347. if(src) chrome.tabs.sendMessage(src.tab.id,{cmd:'ShowMessage',data:r});
  348. updateItem(r);
  349. }
  350. if(o.status&&o.status!=200||o.code=='') { // net error
  351. r.status=-1;r.message=_('msgErrorFetchingScript');finish();
  352. } else { // store script
  353. var meta=parseMeta(o.code);
  354. queryScript(o.id,meta,function(c){
  355. if(!c.id){r.status=1;r.message=_('msgInstalled');}
  356. if(o.more) for(i in o.more) if(i in c) c[i]=o.more[i]; // for import and user edit
  357. c.meta=meta;c.code=o.code;c.uri=getNameURI(c);
  358. if(o.from&&!c.meta.homepageURL&&!c.custom.homepageURL&&!/^(file|data):/.test(o.from)) c.custom.homepageURL=o.from;
  359. if(o.url&&!/^(file|data):/.test(o.url)) c.custom.lastInstallURL=o.url;
  360. saveScript(c,src).onsuccess=function(e){
  361. r.id=c.id=e.target.result;r.obj=getMeta(c);finish();
  362. };
  363. });
  364. meta.require.forEach(function(u){ // @require
  365. var c=o.require&&o.require[u];
  366. if(c) saveRequire(u,c); else fetchRequire(u);
  367. });
  368. for(d in meta.resources) { // @resource
  369. var u=meta.resources[d],c=o.resources&&o.resources[u];
  370. if(c) saveCache(u,c); else fetchCache(u);
  371. }
  372. if(meta.icon) fetchCache(meta.icon); // @icon
  373. }
  374. if(callback) callback();
  375. }
  376. function canUpdate(o,n){
  377. o=(o||'').split('.');
  378. n=(n||'').split('.');
  379. var r=/(\d*)([a-z]*)(\d*)([a-z]*)/i;
  380. while(o.length&&n.length){
  381. var vo=o.shift().match(r),vn=n.shift().match(r);
  382. vo.shift();vn.shift();
  383. vo[0]=parseInt(vo[0]||0,10);
  384. vo[2]=parseInt(vo[2]||0,10);
  385. vn[0]=parseInt(vn[0]||0,10);
  386. vn[2]=parseInt(vn[2]||0,10);
  387. while(vo.length&&vn.length){
  388. var eo=vo.shift(),en=vn.shift();
  389. if(eo!=en) return eo<en;
  390. }
  391. }
  392. return n.length;
  393. }
  394. function setValue(data,src,callback){
  395. var o=db.transaction('values','readwrite').objectStore('values');
  396. o.put({uri:data.uri,values:data.values});
  397. if(callback) callback(); // it seems that CALLBACK does not work with READWRITE transaction
  398. }
  399. function getOption(k,src,callback){
  400. var v=localStorage.getItem(k)||'',r=true;
  401. try{
  402. v=JSON.parse(v);
  403. settings[k]=v;
  404. }catch(e){
  405. v=null;
  406. r=false;
  407. }
  408. if(callback) callback(v);
  409. return r;
  410. }
  411. function setOption(o,src,callback){
  412. if(!o.check||(o.key in settings)) {
  413. localStorage.setItem(o.key,JSON.stringify(o.value));
  414. settings[o.key]=o.value;
  415. }
  416. if(callback) callback(o.value);
  417. }
  418. function initSettings(){
  419. function init(k,v){
  420. if(!getOption(k)) setOption({key:k,value:v});
  421. }
  422. init('isApplied',true);
  423. init('autoUpdate',true);
  424. init('lastUpdate',0);
  425. init('withData',true);
  426. init('closeAfterInstall',false);
  427. init('search',_('defaultSearch'));
  428. init('dataVer',0);
  429. }
  430. function updateMeta(d,src,callback) {
  431. var o=db.transaction('scripts','readwrite').objectStore('scripts');
  432. o.get(d.id).onsuccess=function(e){
  433. var r=e.target.result,i;
  434. if(!r) return;
  435. for(i in d) if(i in r) r[i]=d[i];
  436. o.put(r).onsuccess=function(e){ // store script without another transaction
  437. updateItem({id:d.id,obj:getMeta(r),status:0});
  438. };
  439. };
  440. if(callback) callback();
  441. }
  442. var _update={};
  443. function checkUpdateO(o) {
  444. if(_update[o.id]) return;_update[o.id]=1;
  445. function finish(){delete _update[o.id];}
  446. var r={id:o.id,updating:1,status:2};
  447. function update() {
  448. if(du) {
  449. r.message=_('msgUpdating');
  450. fetchURL(du,function(){
  451. parseScript({
  452. id: o.id,
  453. status: this.status,
  454. code: this.responseText
  455. });
  456. });
  457. } else r.message='<span class=new>'+_('msgNewVersion')+'</span>';
  458. updateItem(r);finish();
  459. }
  460. var du=o.custom.downloadURL||o.meta.downloadURL||o.custom.lastInstallURL,
  461. u=o.custom.updateURL||o.meta.updateURL||du;
  462. if(u) {
  463. r.message=_('msgCheckingForUpdate');updateItem(r);
  464. fetchURL(u,function() {
  465. r.message=_('msgErrorFetchingUpdateInfo');
  466. if(this.status==200) try {
  467. var m=parseMeta(this.responseText);
  468. if(canUpdate(o.meta.version,m.version)) return update();
  469. r.message=_('msgNoUpdate');
  470. } catch(e){}
  471. delete r.updating;
  472. updateItem(r);finish();
  473. },null,{Accept:'text/x-userscript-meta'});
  474. } else finish();
  475. }
  476. function checkUpdate(id,src,callback) {
  477. var o=db.transaction('scripts').objectStore('scripts');
  478. o.get(id).onsuccess=function(e){
  479. var r=e.target.result;
  480. if(r) checkUpdateO(r);
  481. if(callback) callback();
  482. };
  483. }
  484. function checkUpdateAll(e,src,callback) {
  485. setOption({key:'lastUpdate',value:Date.now()});
  486. var o=db.transaction('scripts').objectStore('scripts');
  487. o.index('update').openCursor(1).onsuccess=function(e){
  488. var r=e.target.result;
  489. if(!r) {
  490. if(callback) callback();
  491. return;
  492. }
  493. checkUpdateO(r.value);
  494. r.continue();
  495. };
  496. }
  497. var checking=false;
  498. function autoCheck() {
  499. function check() {
  500. if(settings.autoUpdate) {
  501. if(Date.now()-settings.lastUpdate>=864e5) checkUpdateAll();
  502. setTimeout(check,36e5);
  503. } else checking=false;
  504. }
  505. if(!checking) {checking=true;check();}
  506. }
  507. function autoUpdate(o,src,callback){
  508. o=!!o;
  509. setOption({key:'autoUpdate',value:o},src,autoCheck);
  510. if(callback) callback(o);
  511. }
  512. function getData(d,src,callback) {
  513. function getScripts(){
  514. var o=db.transaction('scripts').objectStore('scripts');
  515. o.index('position').openCursor().onsuccess=function(e){
  516. var r=e.target.result,v;
  517. if(r) {
  518. v=r.value;
  519. if(v.meta.icon) cache[v.meta.icon]=1;
  520. data.scripts.push(getMeta(v));
  521. r.continue();
  522. } else getCache();
  523. };
  524. function getCache(){
  525. getCacheB64(Object.getOwnPropertyNames(cache),src,function(o){
  526. for(var i in o) o[i]='data:image/png;base64,'+o[i];
  527. data.cache=o;
  528. callback(data);
  529. });
  530. }
  531. }
  532. var data={settings:settings,scripts:[]},cache={};
  533. getScripts();
  534. }
  535. function exportZip(z,src,callback){
  536. function getScripts(){
  537. function loop(){
  538. var i=z.data.shift();
  539. if(i) o.get(i).onsuccess=function(e){
  540. var r=e.target.result;
  541. if(r) {
  542. d.scripts.push(r);
  543. if(z.values) values.push(r.uri);
  544. }
  545. loop();
  546. }; else getValues();
  547. }
  548. var o=db.transaction('scripts').objectStore('scripts');
  549. loop();
  550. }
  551. function getValues(){
  552. function loop(){
  553. var i=values.shift();
  554. if(i) o.get(i).onsuccess=function(e){
  555. var r=e.target.result;
  556. if(r) d.values[i]=r.values;
  557. loop();
  558. }; else finish();
  559. }
  560. if(z.values) {
  561. var o=db.transaction('values').objectStore('values');
  562. d.values={};loop();
  563. } else finish();
  564. }
  565. function finish(){callback(d);}
  566. var d={scripts:[],settings:settings},values=[];
  567. getScripts();
  568. }
  569. chrome.runtime.onConnect.addListener(function(p){
  570. port=p;
  571. p.onDisconnect.addListener(function(){port=null;});
  572. });
  573. var settings={};
  574. initSettings();
  575. initDb(function(){
  576. var dataVer=1;
  577. getOption('dataVer',null,function(ver){
  578. pos=null;
  579. var o=db.transaction('scripts','readwrite').objectStore('scripts');
  580. o.index('position').openCursor(null,'prev').onsuccess=function(e){
  581. var r=e.target.result;
  582. if(pos===null) pos=r?r.key:0;
  583. if(ver<dataVer) {
  584. if(r) {
  585. r.value.meta=parseMeta(r.value.code);
  586. o.put(r.value).onsuccess=function(){r.continue();};
  587. } else {
  588. console.log('Data upgraded.');
  589. setOption({key:'dataVer',value:dataVer});
  590. }
  591. }
  592. };
  593. });
  594. chrome.runtime.onMessage.addListener(function(req,src,callback) {
  595. var maps={
  596. NewScript:function(o,src,callback){callback(newScript());},
  597. RemoveScript: removeScript,
  598. GetData: getData,
  599. GetInjected: getInjected,
  600. CheckUpdate: checkUpdate,
  601. CheckUpdateAll: checkUpdateAll,
  602. SaveScript: saveScript,
  603. UpdateMeta: updateMeta,
  604. SetValue: setValue,
  605. GetOption: getOption,
  606. SetOption: setOption,
  607. ExportZip: exportZip,
  608. ParseScript: parseScript,
  609. GetScript: getScript, // for user edit
  610. GetMetas: getMetas, // for popup menu
  611. AutoUpdate: autoUpdate,
  612. Vacuum: vacuum,
  613. Move: move,
  614. ParseMeta: function(o,src,callback){callback(parseMeta(o));},
  615. },f=maps[req.cmd];
  616. if(f) f(req.data,src,callback);
  617. return true;
  618. });
  619. chrome.browserAction.setIcon({path:'images/icon19'+(settings.isApplied?'':'w')+'.png'});
  620. setTimeout(autoCheck,2e4);
  621. });
  622. chrome.webRequest.onBeforeRequest.addListener(function(o){
  623. if(/\.user\.js([\?#]|$)/.test(o.url)) {
  624. var x=new XMLHttpRequest();
  625. x.open('GET',o.url,false);
  626. x.send();
  627. if((!x.status||x.status==200)&&x.responseText[0]=='/') {
  628. if(o.tabId<0) chrome.tabs.create({url:chrome.extension.getURL('/confirm.html')+'?url='+encodeURIComponent(o.url)});
  629. else chrome.tabs.get(o.tabId,function(t){
  630. chrome.tabs.create({url:chrome.extension.getURL('/confirm.html')+'?url='+encodeURIComponent(o.url)+'&from='+encodeURIComponent(t.url)});
  631. });
  632. return {redirectUrl:'javascript:history.back()'};
  633. }
  634. }
  635. },{
  636. urls:['*://*/*','file://*/*'],types:['main_frame']
  637. },['blocking']);