Icon title shows proxy. Added storage migration code.

This commit is contained in:
Ilya Ig. Petrov 2016-02-08 14:55:41 +05:00
parent 03cec0b7bd
commit 0a06037af6
5 changed files with 238 additions and 69 deletions

View File

@ -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: ['<all_urls>'] }
);
chrome.webRequest.onErrorOccurred.addListener(
blockInform,
{ urls: ['<all_urls>'] }
);

View File

@ -18,20 +18,37 @@ function blockInform(details) {
chrome.pageAction.getTitle( chrome.pageAction.getTitle(
{ tabId: details.tabId }, { 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)) // Initially title equals extension name.
result = 'Разблокированы:'; 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( if (ifShouldUpdateTitle)
line => line.trim() === hostname
);
if (!ifListed)
chrome.pageAction.setTitle({ chrome.pageAction.setTitle({
title: result +'\n'+ hostname, title: title,
tabId: details.tabId tabId: details.tabId
}); });
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -3,7 +3,7 @@
"name": "Ненавязчивый РосКомНадзор", "name": "Ненавязчивый РосКомНадзор",
"description": "Аргументы против цензуры: https://git.io/vEkI9", "description": "Аргументы против цензуры: https://git.io/vEkI9",
"version": "0.0.0.9", "version": "0.0.0.10",
"icons": { "icons": {
"128": "/icons/ribbon128.png" "128": "/icons/ribbon128.png"
}, },

View File

@ -19,22 +19,31 @@
window.antiCensorRu = { window.antiCensorRu = {
// PUBLIC // PUBLIC
version: chrome.runtime.getManifest().version,
pacProviders: { pacProviders: {
Антизапрет: { Антизапрет: {
pacUrl: 'http://antizapret.prostovpn.org/proxy.pac', pacUrl: 'http://antizapret.prostovpn.org/proxy.pac',
proxyHosts: ['proxy.antizapret.prostovpn.org'], 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', pacUrl: 'https://config.anticenz.org/proxy.pac',
proxyHosts: ['gw2.anticenz.org'], 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', pacUrl: 'https://drive.google.com/uc?export=download&id=0B-ZCVSvuNWf0akpCOURNS2VCTmc',
proxyHosts: ['gw2.anticenz.org', 'proxy.antizapret.prostovpn.org'], 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] }, 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 // PROTECTED
_periodicUpdateAlarmReason: 'Периодичное обновление PAC-скрипта Антизапрет',
pushToStorage(cb) { pushToStorage(cb) {
@ -65,28 +77,64 @@ window.antiCensorRu = {
onlySettable[key] = this[key] onlySettable[key] = this[key]
return chrome.storage.local.clear( return chrome.storage.local.clear(
() => chrome.storage.local.set( () => chrome.storage.local.set(
onlySettable, onlySettable,
() => cb && cb(chrome.runtime.lastError, onlySettable) () => cb && cb(chrome.runtime.lastError, onlySettable)
) )
); );
}, },
pullFromStorage(cb) { pullFromStorage(cb) {
chrome.storage.local.get(null, storage => { chrome.storage.local.get(null, storage => {
console.log('In storage:', storage); console.log('In storage:', storage);
for(var key of Object.keys(storage)) for(var key of Object.keys(storage))
this[key] = storage[key]; this[key] = storage[key];
console.log('Synced with storage, any callback?', !!cb); console.log('Synced with storage, any callback?', !!cb);
console.log('ifFirstInstall?', this.ifFirstInstall);
if (cb) if (cb)
cb(chrome.runtime.lastError, storage); 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) { syncWithPacProvider(cb) {
var cb = cb || (() => {}); var cb = cb || (() => {});
@ -119,52 +167,66 @@ window.antiCensorRu = {
); );
}, },
_periodicUpdateAlarmReason: 'Периодичное обновление PAC-скрипта Антизапрет',
installPac(key, cb) { installPac(key, cb) {
if(typeof(key) === 'function') { if(typeof(key) === 'function') {
cb = key; cb = key;
key = undefined; key = undefined;
} }
if(key) if(key)
this.currentPacProviderKey = key; this.currentPacProviderKey = key;
var cb = asyncLogGroup('Installing PAC...', cb); var cb = asyncLogGroup('Installing PAC...', cb);
chrome.alarms.clear(this._periodicUpdateAlarmReason, chrome.alarms.clear(
() => chrome.alarms.create(this._periodicUpdateAlarmReason, { this._periodicUpdateAlarmReason,
periodInMinutes: 4*60 () => chrome.alarms.create(
}) this._periodicUpdateAlarmReason,
{ periodInMinutes: 4*60 }
)
); );
this.syncWithPacProvider(cb); this.syncWithPacProvider(cb);
}, },
clearPac(cb) { clearPac(cb) {
var cb = asyncLogGroup('Cearing PAC...', cb); var cb = asyncLogGroup('Cearing alarms and PAC...', cb);
chrome.alarms.clearAll( () => chrome.proxy.settings.clear( chrome.alarms.clearAll(
{}, () => chrome.proxy.settings.clear(
() => { {},
this.currentPacProviderKey = undefined; () => {
return this.pushToStorage(cb); this.currentPacProviderKey = undefined;
}) return this.pushToStorage(cb);
); }
)
);
} }
}; };
// ON EACH LAUNCH OF EXTENSION // ON EACH LAUNCH OF EXTENSION
// Not only on Chrome's startUp, but aslo on Enable/Disable
window.storageSyncedPromise = new Promise( window.storageSyncedPromise = new Promise(
(resolve, reject) => window.antiCensorRu.pullFromStorage( (resolve, reject) => {
(err, res) => err ? reject(err) : resolve(res) /* 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( window.storageSyncedPromise.then(
storage => { storage => {
chrome.alarms.onAlarm.addListener( chrome.alarms.onAlarm.addListener(
alarm => { alarm => {
if (alarm.name === window.antiCensorRu._periodicUpdateAlarmReason) { 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') 'Next update is scheduled on', new Date(alarm.scheduledTime).toLocaleString('ru-RU')
) )
); );
} }
); );
chrome.runtime.onInstalled.addListener( details => { chrome.runtime.onInstalled.addListener( installDetails => {
console.log('Extension just installed, reason:', details.reason); console.log('Extension just installed, reason:', installDetails.reason);
window.storageSyncedPromise.then( window.storageSyncedPromise.then(
storage => { storage => {
// Change property name from version 0.0.0.7 switch(installDetails.reason) {
window.antiCensorRu.ifFirstInstall = window.antiCensorRu.ifNotInstalled;
delete window.antiCensorRu.ifNotInstalled;
switch(details.reason) {
case 'update': case 'update':
console.log('Ah, it\'s just an update or reload. Do nothing.'); console.log('Update or reload. Do nothing.');
//window.antiCensorRu.installPac();
break; break;
case 'install': case 'install':
window.antiCensorRu.ifFirstInstall = true; window.antiCensorRu.ifFirstInstall = true;
chrome.runtime.openOptionsPage(); chrome.runtime.openOptionsPage();
} }
} }
) )
}); });
@ -213,7 +272,7 @@ function asyncLogGroup() {
var cb = args.pop(); var cb = args.pop();
console.group.apply(console, args); console.group.apply(console, args);
return function() { return function() {
console.log('Finished'); console.log('Finished');
console.groupEnd(); console.groupEnd();
var _cb = cb || (() => {}); var _cb = cb || (() => {});
return _cb.apply(this, arguments); return _cb.apply(this, arguments);
@ -258,7 +317,7 @@ function updatePacProxyIps(provider, cb) {
(err, res) => { (err, res) => {
if (!err) { if (!err) {
provider.proxyIps = provider.proxyIps || {}; provider.proxyIps = provider.proxyIps || {};
provider.proxyIps[ JSON.parse(res).answer[0].rdata ] = true; provider.proxyIps[ JSON.parse(res).answer[0].rdata ] = proxyHost;
} else } else
failure.errors[proxyHost] = err; failure.errors[proxyHost] = err;
@ -286,16 +345,16 @@ function setPacScriptFromProvider(provider, cb) {
} }
console.log('Clearing chrome proxy settings...'); console.log('Clearing chrome proxy settings...');
return chrome.proxy.settings.clear({}, () => { return chrome.proxy.settings.clear({}, () => {
var config = { var config = {
mode: 'pac_script', mode: 'pac_script',
pacScript: { pacScript: {
mandatory: false, mandatory: false,
data: res data: res
} }
}; };
console.log('Setting chrome proxy settings...'); console.log('Setting chrome proxy settings...');
chrome.proxy.settings.set( {value: config}, cb ); chrome.proxy.settings.set( {value: config}, cb );
}); });
} }
); );