ips not forget, proxy may have several ips

This commit is contained in:
Ilya Ig. Petrov 2016-02-13 20:53:27 +05:00
parent 54b5eba5a8
commit 508069c802
7 changed files with 183 additions and 182 deletions

View File

@ -0,0 +1,121 @@
'use strict';
// Shows user browserAction icon if any part of the current site is being blocked and proxied.
/*
In what moment the title of the previous icon is cleared?
By my observations it usually takes place near tabs.onUpdate of tab status to "loading".
So if you set a title earlier it may be cleared by browser.
It pertains not only to page refesh but to newly opened pages too.
Also on loosing title see:
https://github.com/ilyaigpetrov/repository-for-chrome-bugs/blob/master/browserAction-title-lost-after-setting/background.js
Crazy parallel Chrome.
**/
window.onTabUpdated = {};
chrome.tabs.onRemoved.addListener( tabId => delete window.onTabUpdated[tabId] );
function afterTabUpdated(tabId, cb) {
if (window.onTabUpdated[tabId])
window.onTabUpdated[tabId].push(cb);
else window.onTabUpdated[tabId] = [cb];
}
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
if (window.onTabUpdated[tabId]) {
window.onTabUpdated[tabId].map( f => f() );
delete window.onTabUpdated[tabId];
}
});
var previousUpdateTitleFinished = Promise.resolve();
function blockInform(requestDetails) {
if (requestDetails.tabId === -1 || !window.antiCensorRu.pacProvider || !window.antiCensorRu.pacProvider.proxyIps || !window.antiCensorRu.pacProvider.proxyIps[ requestDetails.ip ])
return;
previousUpdateTitleFinished = previousUpdateTitleFinished.then(
() => new Promise(
resolve => {
var cb = () => updateTitle( requestDetails, resolve );
return requestDetails.type === 'main_frame' ? afterTabUpdated(requestDetails.tabId, cb) : cb();
}
)
);
function updateTitle(requestDetails, cb) {
chrome.browserAction.getTitle(
{ tabId: requestDetails.tabId },
title => {
var ifTitleSetAlready = /\n/.test(title);
var proxyHost = window.antiCensorRu.pacProvider.proxyIps[ requestDetails.ip ];
var a = document.createElement('a');
a.href = requestDetails.url;
var hostname = a.hostname;
var ifShouldUpdateTitle = false;
var indent = ' ';
var proxyTitle = 'Прокси:';
if (!ifTitleSetAlready) {
title = 'Разблокированы:\n'+ indent + hostname +'\n'+ proxyTitle +'\n'+ indent + proxyHost;
ifShouldUpdateTitle = true;
chrome.browserAction.setBadgeText({
tabId: requestDetails.tabId,
text: requestDetails.type === 'main_frame' ? '1' : '%1'
});
} else {
var hostsProxiesPair = title.split(proxyTitle);
if (hostsProxiesPair[1].indexOf(proxyHost) === -1) {
title = title.replace(hostsProxiesPair[1], hostsProxiesPair[1] +'\n'+ indent + proxyHost);
ifShouldUpdateTitle = true;
}
if (hostsProxiesPair[0].indexOf(hostname) === -1) {
title = title.replace(proxyTitle, indent + hostname +'\n'+ proxyTitle);
ifShouldUpdateTitle = true;
var _cb = cb;
cb = () => chrome.browserAction.getBadgeText(
{tabId: requestDetails.tabId},
result => {
chrome.browserAction.setBadgeText(
{
tabId: requestDetails.tabId,
text: ( isNaN( result.charAt(0) ) && result.charAt(0) || '' ) + (hostsProxiesPair[0].split('\n').length - 1)
}
);
return _cb();
}
);
}
}
if (ifShouldUpdateTitle)
chrome.browserAction.setTitle({
title: title,
tabId: requestDetails.tabId
});
return cb();
}
);
}
}
chrome.webRequest.onResponseStarted.addListener(
blockInform,
{ urls: ['<all_urls>'] }
);
chrome.webRequest.onErrorOccurred.addListener(
blockInform,
{ urls: ['<all_urls>'] }
);

View File

@ -3,7 +3,7 @@
"name": "Обход блокировок Рунета", "name": "Обход блокировок Рунета",
"description": "Аргументы против цензуры: https://git.io/vEkI9", "description": "Аргументы против цензуры: https://git.io/vEkI9",
"version": "0.0.0.11", "version": "0.0.0.12",
"icons": { "icons": {
"128": "/icons/ribbon128.png" "128": "/icons/ribbon128.png"
}, },

View File

@ -25,7 +25,8 @@ window.antiCensorRu = {
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: { proxyIps: {
'195.154.110.37': 'proxy.antizapret.prostovpn.org' '195.154.110.37': 'proxy.antizapret.prostovpn.org',
'195.123.209.38': 'proxy.antizapret.prostovpn.org'
} }
}, },
Антиценз: { Антиценз: {
@ -37,10 +38,11 @@ window.antiCensorRu = {
}, },
Обаа_свитчах: { Обаа_свитчах: {
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: ['proxy.antizapret.prostovpn.org', 'gw2.anticenz.org'],
proxyIps: { proxyIps: {
'5.196.220.114': 'gw2.anticenz.org', '195.154.110.37': 'proxy.antizapret.prostovpn.org',
'195.154.110.37': 'proxy.antizapret.prostovpn.org' '195.123.209.38': 'proxy.antizapret.prostovpn.org',
'5.196.220.114': 'gw2.anticenz.org'
} }
} }
}, },
@ -95,7 +97,7 @@ window.antiCensorRu = {
}, },
syncWithPacProvider(cb) { syncWithPacProvider(cb) {
var cb = cb || (() => {}); var cb = asyncLogGroup('Syncing with PAC provider...', cb);
if (!this.pacProvider) if (!this.pacProvider)
return cb({clarification: 'Сперва выберите PAC-провайдера.'}); return cb({clarification: 'Сперва выберите PAC-провайдера.'});
@ -105,8 +107,11 @@ window.antiCensorRu = {
(err, res) => { (err, res) => {
if (err) if (err)
return reject(err); return reject(err);
this.lastPacUpdateStamp = Date.now(); this.lastPacUpdateStamp = Date.now();
this.ifFirstInstall = false; this.ifFirstInstall = false;
this.setAlarms();
return resolve(res); return resolve(res);
} }
) )
@ -127,15 +132,29 @@ window.antiCensorRu = {
); );
}, },
_pacUpdatePeriodInMinutes: 4*60,
setAlarms() { setAlarms() {
var nextUpdateMoment = this.lastPacUpdateStamp + this._pacUpdatePeriodInMinutes*60*1000;
var now = Date.now();
if (nextUpdateMoment < now)
nextUpdateMoment = now;
console.log( 'Next PAC update is scheduled on', new Date(nextUpdateMoment).toLocaleString('ru-RU') );
chrome.alarms.create( chrome.alarms.create(
this._periodicUpdateAlarmReason, this._periodicUpdateAlarmReason,
{ periodInMinutes: 4*60 } {
when: nextUpdateMoment,
periodInMinutes: this._pacUpdatePeriodInMinutes
}
); );
return nextUpdateMoment === now; // ifAlarmTriggered. Return value may be changed.
}, },
installPac(key, cb) { installPac(key, cb) {
if(typeof(key) === 'function') { if(typeof(key) === 'function') {
cb = key; cb = key;
key = undefined; key = undefined;
@ -144,12 +163,7 @@ window.antiCensorRu = {
if(key) if(key)
this.currentPacProviderKey = key; this.currentPacProviderKey = key;
var cb = asyncLogGroup('Installing PAC...', cb);
this.setAlarms();
return this.syncWithPacProvider(cb); return this.syncWithPacProvider(cb);
}, },
clearPac(cb) { clearPac(cb) {
@ -171,42 +185,33 @@ window.antiCensorRu = {
chrome.storage.local.get(null, oldStorage => { chrome.storage.local.get(null, oldStorage => {
console.log('Init on storage:', oldStorage); console.log('Init on storage:', oldStorage);
antiCensorRu.ifFirstInstall = Object.keys(oldStorage).length === 0; antiCensorRu.ifFirstInstall = Object.keys(oldStorage).length === 0;
// Finish each init with this callback setting alarm listeners. if (!antiCensorRu.ifFirstInstall) {
function cb(err) { // LAUNCH, RELOAD, UPDATE
chrome.alarms.onAlarm.addListener( antiCensorRu._currentPacProviderKey = oldStorage._currentPacProviderKey;
alarm => { antiCensorRu.lastPacUpdateStamp = oldStorage.lastPacUpdateStamp || antiCensorRu.lastPacUpdateStamp;
if (alarm.name === antiCensorRu._periodicUpdateAlarmReason) {
console.log('Periodic update triggered:', new Date());
antiCensorRu.syncWithPacProvider();
}
}
);
console.log('Alarm listener installed. We won\'t miss any PAC update.');
chrome.alarms.get(
antiCensorRu._periodicUpdateAlarmReason,
alarm => {
if (alarm)
console.log(
'Next update is scheduled on', new Date(alarm.scheduledTime).toLocaleString('ru-RU')
);
else if (!antiCensorRu.ifFirstInstall && antiCensorRu.pacProvider) {
antiCensorRu.setAlarms();
console.error('KNOWN BUG: Alarms were lost. See issues on GitHub. Don\'t worry, next update was rescheduled.');
}
}
);
} }
// INSTALL chrome.alarms.onAlarm.addListener(
alarm => {
if (alarm.name === antiCensorRu._periodicUpdateAlarmReason) {
console.log('Periodic PAC update triggered:', new Date().toLocaleString('ru-RU'));
antiCensorRu.syncWithPacProvider();
}
}
);
console.log('Alarm listener installed. We won\'t miss any PAC update.');
if (antiCensorRu.ifFirstInstall) { if (antiCensorRu.ifFirstInstall) {
// INSTALL
console.log('Installing...'); console.log('Installing...');
return chrome.runtime.openOptionsPage(cb); return chrome.runtime.openOptionsPage();
} }
if (!antiCensorRu.pacProvider)
return console.log('No PAC provider set. Do nothing.');
/* /*
1. There is no way to check that chrome.runtime.onInstalled wasn't fired except timeout. 1. There is no way to check that chrome.runtime.onInstalled wasn't fired except timeout.
Otherwise we could put storage migration code only there. Otherwise we could put storage migration code only there.
@ -214,26 +219,20 @@ chrome.storage.local.get(null, oldStorage => {
Better on each launch then on each pull. Better on each launch then on each pull.
*/ */
// LAUNCH, RELOAD, UPDATE var ifAlarmTriggered = antiCensorRu.setAlarms();
antiCensorRu._currentPacProviderKey = oldStorage._currentPacProviderKey;
antiCensorRu.lastPacUpdateStamp = oldStorage.lastPacUpdateStamp || antiCensorRu.lastPacUpdateStamp;
if (antiCensorRu.version === oldStorage.version) { if (antiCensorRu.version === oldStorage.version) {
// LAUNCH, RELOAD // LAUNCH, RELOAD
console.log('Launch or reload. Do nothing.'); antiCensorRu.pacProviders = oldStorage.pacProviders;
return cb(); return console.log('Extension launched, reloaded or enabled.');
} }
// UPDATE & MIGRATION // UPDATE & MIGRATION
console.log('Updating...'); console.log('Extension updated.');
return antiCensorRu.pacProvider && if (!ifAlarmTriggered)
updatePacProxyIps( updatePacProxyIps(
antiCensorRu.pacProvider, antiCensorRu.pacProvider,
ipsError => { ipsError => ipsError ? console.log('Error updating IPs:', ipsError) : antiCensorRu.pushToStorage()
if (ipsError) ipsError.ifNotCritical = true;
antiCensorRu.pushToStorage( pushError => cb( pushError || ipsError ) );
}
); );
/* /*
@ -261,8 +260,8 @@ 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.groupEnd(); console.groupEnd();
console.log('Group finished.');
var _cb = cb || (() => {}); var _cb = cb || (() => {});
return _cb.apply(this, arguments); return _cb.apply(this, arguments);
} }
@ -296,13 +295,15 @@ function updatePacProxyIps(provider, cb) {
errors: {} errors: {}
}; };
var i = 0; var i = 0;
for (var proxyHost of provider.proxyHosts) { provider.proxyHosts.map(
httpGet( proxyHost => httpGet(
'http://www.dns-lg.com/google1/'+ proxyHost +'/A', 'http://www.dns-lg.com/google1/'+ proxyHost +'/A',
(err, res) => { (err, res) => {
if (!err) { if (!err) {
provider.proxyIps = provider.proxyIps || {}; provider.proxyIps = provider.proxyIps || {};
provider.proxyIps[ JSON.parse(res).answer[0].rdata ] = proxyHost; JSON.parse(res).answer.map(
ans => provider.proxyIps[ ans.rdata ] = proxyHost
)
} else } else
failure.errors[proxyHost] = err; failure.errors[proxyHost] = err;
@ -311,8 +312,8 @@ function updatePacProxyIps(provider, cb) {
return cb(failure, provider.proxyIps); return cb(failure, provider.proxyIps);
} }
} }
); )
} );
} }
function setPacScriptFromProvider(provider, cb) { function setPacScriptFromProvider(provider, cb) {

View File

@ -1,121 +0,0 @@
'use strict';
// Shows user browserAction icon if any part of the current site is being blocked and proxied.
/*
In what moment the title of the previous icon is cleared?
By my observations it usually takes place near tabs.onUpdate of tab status to "loading".
So if you set a title earlier it may be cleared by browser.
It pertains not only to page refesh but to newly opened pages too.
Also on loosing title see:
https://github.com/ilyaigpetrov/repository-for-chrome-bugs/blob/master/browserAction-title-lost-after-setting/background.js
Crazy parallel Chrome.
**/
window.onTabUpdated = {};
chrome.tabs.onRemoved.addListener( tabId => delete window.onTabUpdated[tabId] );
function afterTabUpdated(tabId, cb) {
if (window.onTabUpdated[tabId])
window.onTabUpdated[tabId].push(cb);
else window.onTabUpdated[tabId] = [cb];
}
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
if (window.onTabUpdated[tabId]) {
window.onTabUpdated[tabId].map( f => f() );
delete window.onTabUpdated[tabId];
}
});
var previousUpdateTitleFinished = Promise.resolve();
function blockInform(requestDetails) {
if (requestDetails.tabId !== -1 && window.antiCensorRu.pacProvider && window.antiCensorRu.pacProvider.proxyIps && window.antiCensorRu.pacProvider.proxyIps[ requestDetails.ip ]) {
previousUpdateTitleFinished = previousUpdateTitleFinished.then(
() => new Promise(
resolve => {
var cb = () => updateTitle( requestDetails, resolve );
return requestDetails.type === 'main_frame' ? afterTabUpdated(requestDetails.tabId, cb) : cb();
}
)
);
function updateTitle(requestDetails, cb) {
chrome.browserAction.getTitle(
{ tabId: requestDetails.tabId },
title => {
var ifTitleSetAlready = /\n/.test(title);
var proxyHost = window.antiCensorRu.pacProvider.proxyIps[ requestDetails.ip ];
var a = document.createElement('a');
a.href = requestDetails.url;
var hostname = a.hostname;
var ifShouldUpdateTitle = false;
var indent = ' ';
var proxyTitle = 'Прокси:';
if (!ifTitleSetAlready) {
title = 'Разблокированы:\n'+ indent + hostname +'\n'+ proxyTitle +'\n'+ indent + proxyHost;
ifShouldUpdateTitle = true;
chrome.browserAction.setBadgeText({
tabId: requestDetails.tabId,
text: requestDetails.type === 'main_frame' ? '1' : '%1'
});
} else {
var hostsProxiesPair = title.split(proxyTitle);
if (hostsProxiesPair[1].indexOf(proxyHost) === -1) {
title = title.replace(hostsProxiesPair[1], hostsProxiesPair[1] +'\n'+ indent + proxyHost);
ifShouldUpdateTitle = true;
}
if (hostsProxiesPair[0].indexOf(hostname) === -1) {
title = title.replace(proxyTitle, indent + hostname +'\n'+ proxyTitle);
ifShouldUpdateTitle = true;
var _cb = cb;
cb = () => chrome.browserAction.getBadgeText(
{tabId: requestDetails.tabId},
result => {
chrome.browserAction.setBadgeText(
{
tabId: requestDetails.tabId,
text: ( isNaN( result.charAt(0) ) && result.charAt(0) || '' ) + (hostsProxiesPair[0].split('\n').length - 1)
}
);
return _cb();
}
);
}
}
if (ifShouldUpdateTitle)
chrome.browserAction.setTitle({
title: title,
tabId: requestDetails.tabId
});
return cb();
}
);
}
}
}
chrome.webRequest.onResponseStarted.addListener(
blockInform,
{ urls: ['<all_urls>'] }
);
chrome.webRequest.onErrorOccurred.addListener(
blockInform,
{ urls: ['<all_urls>'] }
);