From 0a06037af622d7e115942d9ab09d2222c09fece0 Mon Sep 17 00:00:00 2001 From: "Ilya Ig. Petrov" Date: Mon, 8 Feb 2016 14:55:41 +0500 Subject: [PATCH] Icon title shows proxy. Added storage migration code. --- .../extnesion/block-informer - Copy.js | 93 ++++++++++ .../extnesion/block-informer.js | 37 +++- .../extnesion/icons/ribbon-partly32.png | Bin 0 -> 1527 bytes .../extnesion/manifest.json | 2 +- .../sync-pac-script-with-pac-provider.js | 175 ++++++++++++------ 5 files changed, 238 insertions(+), 69 deletions(-) create mode 100755 extensions/chromium/minimalistic-pac-setter/extnesion/block-informer - Copy.js create mode 100755 extensions/chromium/minimalistic-pac-setter/extnesion/icons/ribbon-partly32.png diff --git a/extensions/chromium/minimalistic-pac-setter/extnesion/block-informer - Copy.js b/extensions/chromium/minimalistic-pac-setter/extnesion/block-informer - Copy.js new file mode 100755 index 0000000..ae7dd00 --- /dev/null +++ b/extensions/chromium/minimalistic-pac-setter/extnesion/block-informer - Copy.js @@ -0,0 +1,93 @@ +'use strict'; + +// Shows user PageAction icon if any part of the current site is being blocked and proxied. + +function getHostname(url) { + var a = document.createElement('a'); + a.href = url; + return a.hostname; +} + +function blockInform(details) { + if (details.tabId !== -1 && window.antiCensorRu.pacProvider && window.antiCensorRu.pacProvider.proxyIps && window.antiCensorRu.pacProvider.proxyIps[ details.ip ]) { + + console.log(details.url, details.type, details); + var ifMainFrame = details.type === 'main_frame'; + var doesSetIconEraseTitlePromise = new Promise( + (resolve, reject) => { + if (false && ifMainFrame) + chrome.pageAction.setIcon({ + path: '/icons/ribbon32.png', + tabId: details.tabId + }, + () => { + chrome.pageAction.show(details.tabId); + resolve(); + } + ); + else resolve(); + } + ); + doesSetIconEraseTitlePromise + .then( + res => chrome.pageAction.getTitle( + { tabId: details.tabId }, + title => { + + var ifTitleSetAlready = /\n/.test(title); // Initially title equals extension name. + var proxyHost = window.antiCensorRu.pacProvider.proxyIps[ details.ip ]; + var hostname = getHostname(details.url).trim(); + var ifShouldUpdateTitle = !ifTitleSetAlready; + var indent = ' '; + + if (!ifTitleSetAlready) { + console.log('Main frame?', ifMainFrame); + console.log(ifTitleSetAlready, title); + console.log('Setting for', details.url, details.type); + if (false && !ifMainFrame) + chrome.pageAction.setIcon({ + path: '/icons/ribbon-partly32.png', + tabId: details.tabId + }); + title = 'Разблокированы:\n'+ indent + hostname +'\nПрокси:\n'+ indent + proxyHost; + } else { + title = title.replace(/Прокси:([\s\S]+)/, '{0}\n$&'); + var proxies = RegExp.$1; + if (proxies.indexOf(proxyHost) == -1) { + title = title.replace(/Прокси:[\s\S]+/, '$&\n'+ indent + proxyHost); + ifShouldUpdateTitle = true; + } + + var ifHostListedAlready = title.split(/\r?\n/g).some( + line => line.trim() === hostname + ); + if (!ifHostListedAlready) { + title = title.replace('{0}', indent + hostname); + ifShouldUpdateTitle = true; + } else if (ifShouldUpdateTitle) + title = title.replace('\n{0}', ''); + } + + if (ifShouldUpdateTitle) { + chrome.pageAction.setTitle({ + title: title, + tabId: details.tabId + }); + + } + } + ) + ); + + } +} + +chrome.webRequest.onCompleted.addListener( + blockInform, + { urls: [''] } +); + +chrome.webRequest.onErrorOccurred.addListener( + blockInform, + { urls: [''] } +); diff --git a/extensions/chromium/minimalistic-pac-setter/extnesion/block-informer.js b/extensions/chromium/minimalistic-pac-setter/extnesion/block-informer.js index c01dfba..c233f5b 100755 --- a/extensions/chromium/minimalistic-pac-setter/extnesion/block-informer.js +++ b/extensions/chromium/minimalistic-pac-setter/extnesion/block-informer.js @@ -18,20 +18,37 @@ function blockInform(details) { chrome.pageAction.getTitle( { tabId: details.tabId }, - result => { + title => { + + var ifTitleSetAlready = !/\n/.test(title); + var proxyHost = window.antiCensorRu.pacProvider.proxyIps[ details.ip ]; + var hostname = getHostname(details.url); + var ifShouldUpdateTitle = false; + var indent = ' '; - if (!/\n/.test(result)) - result = 'Разблокированы:'; + // Initially title equals extension name. + if (ifTitleSetAlready) { + title = 'Разблокированы:\n'+ indent + hostname +'\nПрокси:\n'+ indent + proxyHost; + ifShouldUpdateTitle = true; + } else { + title = title.replace(/Прокси:([\s\S]+)/, '{0}\n$&'); + var proxies = RegExp.$1; + if (proxies.indexOf(proxyHost) == -1) { + title = title.replace(/Прокси:[\s\S]+/, '$&\n'+ indent + proxyHost); + ifShouldUpdateTitle = true; + } - var hostname = getHostname(details.url).trim(); + var ifHostListedAlready = title.indexOf(hostname) != -1; + if (!ifHostListedAlready) { + title = title.replace('{0}', indent + hostname); + ifShouldUpdateTitle = true; + } else if (ifShouldUpdateTitle) + title = title.replace('{0}\n', ''); + } - var ifListed = result.split(/\r?\n/g).some( - line => line.trim() === hostname - ); - - if (!ifListed) + if (ifShouldUpdateTitle) chrome.pageAction.setTitle({ - title: result +'\n'+ hostname, + title: title, tabId: details.tabId }); } diff --git a/extensions/chromium/minimalistic-pac-setter/extnesion/icons/ribbon-partly32.png b/extensions/chromium/minimalistic-pac-setter/extnesion/icons/ribbon-partly32.png new file mode 100755 index 0000000000000000000000000000000000000000..df694f79e9f7f8621c6c400404f0c5f9f51cece9 GIT binary patch literal 1527 zcmV8W9O-s)3k* zDOQPqxJsb-0yF|rX($}XLV3pzzY(~@Pg1mwKp!9phzIHb4^RnQ0nX{FTpa6o!W|H|2lfC%Vt}92Rr#S<#uZ~A z9xo}{2|xn+#b|GtrMq2Hv?uP`0BhD89K>pj27GA!#{$dlWd+s%308ePurdbn8@eiQ zmlVx5Vz8uWId^P;q-Y7i^A6ECU6lhsVG{-{w*FZTS@zwmzzD$aX!n*BZ749WF?L;* zmr9B@-6c+v6m4vy22?>$1J)UE%7Ea-^%*;kZXL&}1Mk!OYQw2gbyYqAY`2bGv7^-H z?OSln1oMh2f4pmVcBBbKK8Ce0Mug7{0C7egs}AOpa-$Sro}_3!+?Yg|Z#dmMud8O-$z67HwR4albaXmh?!f7hxXwoNf#FU; zE#xFXprloo!;1#b3a3jPCvXYSPom*?Qwof>Jy3U+h_))ItAC@v{l_y z+^S2hv#(ouz}Z|cDOyG)bTJSV00YP!6mj-{>#Cd|&49$PQR}@MU6n6{JaL$njwM01CQi@Q2hhT0n~$2ZBz)YmT#@9ylHr`GP)wm~!XxOR05&IK!U(l7Z7A z?!B(cYa25l%sJXZFT1{bPqx?Dcdk|EFy*<&HsLi5k9D5&Pqpi@-|p*v{X9z!E$8fp z5q<-L22>hw)_{%G&P&aJWhR(*F`%FVk}DwDfC6XVnzZqzq-dt3Xy&66wwcv}$27sL z5k&LV;qT6}Lim=+nTyN{Pn_x0b#YYJ!2|$8kYYeE8rUvDPn?l9aYusz`Mok5`abV9 z(w1k0ASLLDt7~dJ11hWFez6&xGhm7dRnhjzgsM$_N9UEcOa>setb`ZO>;s@i@UT4n z6&rdm&?0$ZLS41!jw_YW$%MU*5ZufMSt5WJcGf_e2_Kno#)L`}LM9ZOu%QO}XC2?J zSQ!!Xi#Fml4FK{Vc!m;(Z`_P;J|$9INq|5txUc1>?j#q?1Q_u`-jO`F9ZrDMSHz)*UVB|Y3qZdxX_|w7&f6cJXY9o z1>m5gZeJlyrDOvoMY{%M0`$9bdKEARASC)&F<{DVIu+jVJMGh{U*|d2+wX$^*H}ih z05}S?v1M-+Z9uTD@N527n=dzSf192=R&*`DG(%Ff!;+$PYz^)(c~*=-+(uHgVql?D zo_6_9GE07{kBHuQS_k!c?t28_Q0MfpcFvJJIt2A09fEow&^+lA7kt0qB7Y9}GSYit z+gEQeth5M#wQ1vdZ)nywq8j>&4)O!Q?nvZ= z0>3wqmwWxJO`8bNNm8_2U6q#r4VPAF%VcH^dxwzdi%K36eXQ(1c}FuiCs^bk0CRw! z>w_actJDA~U+m8AAYc3yfRzI#v$#G__(oUdk&X%E125a{)UpzkmZeYi{?#ru9+)GZ)8*A49M+;@M5$=Q@1i`+I(zTHlYrfk^3i6eFfk dpV~EP!2jvjP2Lzz{(%4h002ovPDHLkV1i;$wj=-m literal 0 HcmV?d00001 diff --git a/extensions/chromium/minimalistic-pac-setter/extnesion/manifest.json b/extensions/chromium/minimalistic-pac-setter/extnesion/manifest.json index 3396b00..470badd 100755 --- a/extensions/chromium/minimalistic-pac-setter/extnesion/manifest.json +++ b/extensions/chromium/minimalistic-pac-setter/extnesion/manifest.json @@ -3,7 +3,7 @@ "name": "Ненавязчивый РосКомНадзор", "description": "Аргументы против цензуры: https://git.io/vEkI9", - "version": "0.0.0.9", + "version": "0.0.0.10", "icons": { "128": "/icons/ribbon128.png" }, diff --git a/extensions/chromium/minimalistic-pac-setter/extnesion/sync-pac-script-with-pac-provider.js b/extensions/chromium/minimalistic-pac-setter/extnesion/sync-pac-script-with-pac-provider.js index ce1f1e1..485f38c 100755 --- a/extensions/chromium/minimalistic-pac-setter/extnesion/sync-pac-script-with-pac-provider.js +++ b/extensions/chromium/minimalistic-pac-setter/extnesion/sync-pac-script-with-pac-provider.js @@ -19,22 +19,31 @@ window.antiCensorRu = { // PUBLIC + + version: chrome.runtime.getManifest().version, pacProviders: { Антизапрет: { pacUrl: 'http://antizapret.prostovpn.org/proxy.pac', proxyHosts: ['proxy.antizapret.prostovpn.org'], - proxyIps: {'195.154.110.37': true} + proxyIps: { + '195.154.110.37': 'proxy.antizapret.prostovpn.org' + } }, Антиценз: { pacUrl: 'https://config.anticenz.org/proxy.pac', proxyHosts: ['gw2.anticenz.org'], - proxyIps: {'185.120.5.7': true} + proxyIps: { + '5.196.220.114': 'gw2.anticenz.org' + } }, Оба_и_на_свитчах: { pacUrl: 'https://drive.google.com/uc?export=download&id=0B-ZCVSvuNWf0akpCOURNS2VCTmc', proxyHosts: ['gw2.anticenz.org', 'proxy.antizapret.prostovpn.org'], - proxyIps: {'195.154.110.37': true, '185.120.5.7': true} + proxyIps: { + '5.196.220.114': 'gw2.anticenz.org', + '195.154.110.37': 'proxy.antizapret.prostovpn.org' + } } }, @@ -50,11 +59,14 @@ window.antiCensorRu = { get pacProvider() { return this.pacProviders[this.currentPacProviderKey] }, /* - Offer PAC choice if this is the first time extension was installed. + Is it the first time extension installed? Do something, e.g. initiate PAC sync. */ - ifFirstInstall: true, + ifFirstInstall: false, + lastPacUpdateStamp: 0, // PROTECTED + + _periodicUpdateAlarmReason: 'Периодичное обновление PAC-скрипта Антизапрет', pushToStorage(cb) { @@ -65,28 +77,64 @@ window.antiCensorRu = { onlySettable[key] = this[key] return chrome.storage.local.clear( - () => chrome.storage.local.set( - onlySettable, - () => cb && cb(chrome.runtime.lastError, onlySettable) - ) - ); - + () => chrome.storage.local.set( + onlySettable, + () => cb && cb(chrome.runtime.lastError, onlySettable) + ) + ); + }, pullFromStorage(cb) { chrome.storage.local.get(null, storage => { - console.log('In storage:', storage); + console.log('In storage:', storage); for(var key of Object.keys(storage)) this[key] = storage[key]; console.log('Synced with storage, any callback?', !!cb); - console.log('ifFirstInstall?', this.ifFirstInstall); if (cb) cb(chrome.runtime.lastError, storage); }); }, + + migrateStorage(cb) { + chrome.storage.local.get(null, oldStorage => { + + var getPubCounter = version => parseInt( version.match(/\d+$/)[0] ); + var version = oldStorage.version || '0.0.0.0'; + var oldPubCounter = getPubCounter( version ); + + if (oldPubCounter > 9) { + console.log('No migration required, storage pub', oldPubCounter, 'is up to date.'); + return cb && cb(chrome.runtime.lastError, oldStorage); + } - lastPacUpdateStamp: 0, + console.log('Starting storage migration from publication', oldPubCounter, 'to', getPubCounter( this.version )); + + this._currentPacProviderKey = oldStorage._currentPacProviderKey; + this.lastPacUpdateStamp = oldStorage.lastPacUpdateStamp; + // There is no need to persist other properties in the storage. + + return this.pushToStorage(cb); + + /* + + History of Changes to Storage + ----------------------------- + + Version 0.0.0.10 + + * Added this.version + * PacProvider.proxyIps changed from {ip -> Boolean} to {ip -> hostname} + + Version 0.0.0.8-9 + + * Changed storage.ifNotInstalled to storage.ifFirstInstall + * Added storage.lastPacUpdateStamp + + **/ + }); + }, syncWithPacProvider(cb) { var cb = cb || (() => {}); @@ -119,52 +167,66 @@ window.antiCensorRu = { ); }, - _periodicUpdateAlarmReason: 'Периодичное обновление PAC-скрипта Антизапрет', - installPac(key, cb) { - if(typeof(key) === 'function') { - cb = key; - key = undefined; - } + if(typeof(key) === 'function') { + cb = key; + key = undefined; + } - if(key) - this.currentPacProviderKey = key; + if(key) + this.currentPacProviderKey = key; var cb = asyncLogGroup('Installing PAC...', cb); - chrome.alarms.clear(this._periodicUpdateAlarmReason, - () => chrome.alarms.create(this._periodicUpdateAlarmReason, { - periodInMinutes: 4*60 - }) + chrome.alarms.clear( + this._periodicUpdateAlarmReason, + () => chrome.alarms.create( + this._periodicUpdateAlarmReason, + { periodInMinutes: 4*60 } + ) ); this.syncWithPacProvider(cb); }, clearPac(cb) { - var cb = asyncLogGroup('Cearing PAC...', cb); - chrome.alarms.clearAll( () => chrome.proxy.settings.clear( - {}, - () => { - this.currentPacProviderKey = undefined; - return this.pushToStorage(cb); - }) - ); + var cb = asyncLogGroup('Cearing alarms and PAC...', cb); + chrome.alarms.clearAll( + () => chrome.proxy.settings.clear( + {}, + () => { + this.currentPacProviderKey = undefined; + return this.pushToStorage(cb); + } + ) + ); } }; // ON EACH LAUNCH OF EXTENSION +// Not only on Chrome's startUp, but aslo on Enable/Disable window.storageSyncedPromise = new Promise( - (resolve, reject) => window.antiCensorRu.pullFromStorage( - (err, res) => err ? reject(err) : resolve(res) - ) + (resolve, reject) => { + /* We have to migrate on each launch, because: + 1. There is no way to check that chrome.runtime.onInstalled wasn't fired except timeout. + 2. There is no way to schedule onInstalled before pullFromStorage without timeouts. + 3. So inside onInstalled storage may only be already pulled. + */ + window.antiCensorRu.migrateStorage( + (err, migratedStorage) => + err ? reject(err) : window.antiCensorRu.pullFromStorage( + (err, res) => err ? reject(err) : resolve(res) + ) + ); + } ); window.storageSyncedPromise.then( storage => { + chrome.alarms.onAlarm.addListener( alarm => { if (alarm.name === window.antiCensorRu._periodicUpdateAlarmReason) { @@ -181,27 +243,24 @@ window.storageSyncedPromise.then( 'Next update is scheduled on', new Date(alarm.scheduledTime).toLocaleString('ru-RU') ) ); + } ); -chrome.runtime.onInstalled.addListener( details => { - console.log('Extension just installed, reason:', details.reason); +chrome.runtime.onInstalled.addListener( installDetails => { + console.log('Extension just installed, reason:', installDetails.reason); window.storageSyncedPromise.then( storage => { - // Change property name from version 0.0.0.7 - window.antiCensorRu.ifFirstInstall = window.antiCensorRu.ifNotInstalled; - delete window.antiCensorRu.ifNotInstalled; - - switch(details.reason) { + switch(installDetails.reason) { case 'update': - console.log('Ah, it\'s just an update or reload. Do nothing.'); - //window.antiCensorRu.installPac(); + console.log('Update or reload. Do nothing.'); break; case 'install': window.antiCensorRu.ifFirstInstall = true; chrome.runtime.openOptionsPage(); } + } ) }); @@ -213,7 +272,7 @@ function asyncLogGroup() { var cb = args.pop(); console.group.apply(console, args); return function() { - console.log('Finished'); + console.log('Finished'); console.groupEnd(); var _cb = cb || (() => {}); return _cb.apply(this, arguments); @@ -258,7 +317,7 @@ function updatePacProxyIps(provider, cb) { (err, res) => { if (!err) { provider.proxyIps = provider.proxyIps || {}; - provider.proxyIps[ JSON.parse(res).answer[0].rdata ] = true; + provider.proxyIps[ JSON.parse(res).answer[0].rdata ] = proxyHost; } else failure.errors[proxyHost] = err; @@ -286,16 +345,16 @@ function setPacScriptFromProvider(provider, cb) { } console.log('Clearing chrome proxy settings...'); return chrome.proxy.settings.clear({}, () => { - var config = { - mode: 'pac_script', - pacScript: { - mandatory: false, - data: res - } - }; - console.log('Setting chrome proxy settings...'); - chrome.proxy.settings.set( {value: config}, cb ); - }); + var config = { + mode: 'pac_script', + pacScript: { + mandatory: false, + data: res + } + }; + console.log('Setting chrome proxy settings...'); + chrome.proxy.settings.set( {value: config}, cb ); + }); } );