background.js 19 KB

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