2015-12-20 23:28:41 +03:00
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Task 1. Gets IP for host proxy.antizapret.prostovpn.org with dns-lg.com.
|
|
|
|
|
This IP is used in block-informer to inform user when proxy is ON.
|
|
|
|
|
Task 2. Downloads PAC proxy script from Antizapret and sets it in Chromium settings.
|
|
|
|
|
Task 3. Schedules tasks 1 & 2 for every 2 hours.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
In background scripts use window.antiCensorRu public variables.
|
|
|
|
|
Thay are synced with chrome.storage so they persist restarts.
|
|
|
|
|
In pages window.antiCensorRu are not accessible,
|
|
|
|
|
use chrome.runtime.getBackgroundPage(..),
|
|
|
|
|
avoid old extension.getBackgroundPage.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
window.antiCensorRu = {
|
|
|
|
|
|
|
|
|
|
// PUBLIC
|
|
|
|
|
|
|
|
|
|
pacProviders: {
|
|
|
|
|
Антизапрет: {
|
|
|
|
|
pacUrl: 'http://antizapret.prostovpn.org/proxy.pac',
|
2016-01-17 22:27:54 +03:00
|
|
|
|
proxyHosts: ['proxy.antizapret.prostovpn.org'],
|
|
|
|
|
proxyIps: {'195.154.110.37': true}
|
2015-12-20 23:28:41 +03:00
|
|
|
|
},
|
|
|
|
|
Антиценз: {
|
|
|
|
|
pacUrl: 'https://config.anticenz.org/proxy.pac',
|
2016-01-18 00:09:55 +03:00
|
|
|
|
proxyHosts: ['gw2.anticenz.org'],
|
|
|
|
|
proxyIps: {'185.120.5.7': true}
|
2016-01-17 22:27:54 +03:00
|
|
|
|
},
|
|
|
|
|
Оба_и_на_свитчах: {
|
|
|
|
|
pacUrl: 'https://drive.google.com/uc?export=download&id=0B-ZCVSvuNWf0akpCOURNS2VCTmc',
|
2016-01-18 00:09:55 +03:00
|
|
|
|
proxyHosts: ['gw2.anticenz.org', 'proxy.antizapret.prostovpn.org'],
|
|
|
|
|
proxyIps: {'195.154.110.37': true, '185.120.5.7': true}
|
2015-12-20 23:28:41 +03:00
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2016-01-17 22:27:54 +03:00
|
|
|
|
_currentPacProviderKey: 'Оба_и_на_свитчах',
|
2015-12-20 23:28:41 +03:00
|
|
|
|
|
|
|
|
|
get currentPacProviderKey() { return this._currentPacProviderKey },
|
|
|
|
|
set currentPacProviderKey(newKey) {
|
|
|
|
|
if (newKey && !this.pacProviders[newKey])
|
|
|
|
|
throw new IllegalArgumentException('No provider for key:'+newKey);
|
|
|
|
|
this._currentPacProviderKey = newKey;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
get pacProvider() { return this.pacProviders[this.currentPacProviderKey] },
|
|
|
|
|
|
2016-01-26 19:47:09 +03:00
|
|
|
|
/*
|
|
|
|
|
Offer PAC choice if this is the first time extension was installed.
|
|
|
|
|
*/
|
|
|
|
|
ifFirstInstall: true,
|
2015-12-20 23:28:41 +03:00
|
|
|
|
|
|
|
|
|
// PROTECTED
|
|
|
|
|
|
|
|
|
|
pushToStorage(cb) {
|
|
|
|
|
// Copy only settable properties.
|
|
|
|
|
var onlySettable = {};
|
|
|
|
|
for(var key of Object.keys(this))
|
|
|
|
|
if (Object.getOwnPropertyDescriptor(this, key).writable && typeof(this[key]) !== 'function')
|
|
|
|
|
onlySettable[key] = this[key]
|
|
|
|
|
|
2016-01-26 19:47:09 +03:00
|
|
|
|
return chrome.storage.local.set(onlySettable, () => cb && cb(chrome.runtime.lastError, onlySettable) );
|
2015-12-20 23:28:41 +03:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
pullFromStorage(cb) {
|
|
|
|
|
chrome.storage.local.get(null, storage => {
|
|
|
|
|
for(var key of Object.keys(storage))
|
|
|
|
|
this[key] = storage[key];
|
|
|
|
|
|
2016-01-26 19:05:23 +03:00
|
|
|
|
console.log('Synced with storage, any callback?', !!cb);
|
2015-12-20 23:28:41 +03:00
|
|
|
|
if (cb)
|
2016-01-26 18:50:25 +03:00
|
|
|
|
cb(chrome.runtime.lastError, storage);
|
2015-12-20 23:28:41 +03:00
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
2016-01-26 13:38:40 +03:00
|
|
|
|
lastPacUpdateStamp: 0,
|
|
|
|
|
|
2015-12-20 23:28:41 +03:00
|
|
|
|
syncWithPacProvider(cb) {
|
|
|
|
|
setPacScriptFromProvider(
|
|
|
|
|
this.pacProvider,
|
2016-01-26 13:38:40 +03:00
|
|
|
|
err => {
|
|
|
|
|
if (!err)
|
|
|
|
|
this.lastPacUpdateStamp = Date.now();
|
2016-01-17 22:27:54 +03:00
|
|
|
|
updatePacProxyIps(
|
2015-12-20 23:28:41 +03:00
|
|
|
|
this.pacProvider,
|
|
|
|
|
() => {
|
2016-01-26 19:47:09 +03:00
|
|
|
|
this.ifFirstInstall = false;
|
2015-12-20 23:28:41 +03:00
|
|
|
|
this.pushToStorage(cb)
|
|
|
|
|
}
|
|
|
|
|
)}
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
|
2016-01-18 00:09:55 +03:00
|
|
|
|
_periodicUpdateAlarmReason: 'Периодичное обновление PAC-скрипта Антизапрет',
|
|
|
|
|
|
2015-12-20 23:28:41 +03:00
|
|
|
|
installPac(key, cb) {
|
2016-01-17 22:27:54 +03:00
|
|
|
|
|
2015-12-20 23:28:41 +03:00
|
|
|
|
if(typeof(key) === 'function') {
|
|
|
|
|
cb = key;
|
|
|
|
|
key = undefined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(key)
|
|
|
|
|
this.currentPacProviderKey = key;
|
|
|
|
|
|
|
|
|
|
var cb = asyncLogGroup('Installing PAC...', cb);
|
|
|
|
|
|
2016-01-18 00:09:55 +03:00
|
|
|
|
chrome.alarms.clear(this._periodicUpdateAlarmReason,
|
|
|
|
|
() => chrome.alarms.create(this._periodicUpdateAlarmReason, {
|
|
|
|
|
periodInMinutes: 4*60
|
|
|
|
|
})
|
2015-12-20 23:28:41 +03:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
2016-01-26 18:50:25 +03:00
|
|
|
|
// ON EACH LAUNCH OF EXTENSION
|
|
|
|
|
|
|
|
|
|
window.storageSyncedPromise = new Promise(
|
|
|
|
|
(resolve, reject) => 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) {
|
|
|
|
|
console.log('Periodic update triggered:', new Date());
|
|
|
|
|
window.antiCensorRu.syncWithPacProvider();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
);
|
2016-01-26 19:05:23 +03:00
|
|
|
|
console.log('Alarm listener installed. We won\'t miss any PAC update.');
|
|
|
|
|
|
|
|
|
|
chrome.alarms.get(
|
|
|
|
|
window.antiCensorRu._periodicUpdateAlarmReason,
|
|
|
|
|
alarm => alarm && console.log(
|
|
|
|
|
'Next update is scheduled on', new Date(alarm.scheduledTime).toLocaleString('ru-RU')
|
|
|
|
|
)
|
|
|
|
|
);
|
2016-01-26 18:50:25 +03:00
|
|
|
|
}
|
|
|
|
|
);
|
2015-12-20 23:28:41 +03:00
|
|
|
|
|
|
|
|
|
chrome.runtime.onInstalled.addListener( details => {
|
2016-01-26 19:05:23 +03:00
|
|
|
|
console.log('Extension just installed, reason:', details.reason);
|
2016-01-26 18:50:25 +03:00
|
|
|
|
window.storageSyncedPromise.then(
|
|
|
|
|
storage => {
|
|
|
|
|
switch(details.reason) {
|
|
|
|
|
case 'update':
|
2016-01-26 19:05:23 +03:00
|
|
|
|
console.log('Ah, it\'s just an update or reload. Do nothing.');
|
|
|
|
|
//window.antiCensorRu.installPac();
|
2016-01-26 18:50:25 +03:00
|
|
|
|
break;
|
|
|
|
|
case 'install':
|
2016-01-26 19:47:09 +03:00
|
|
|
|
window.antiCensorRu.ifFirstInstall = true;
|
2016-01-26 18:50:25 +03:00
|
|
|
|
chrome.runtime.openOptionsPage();
|
2016-01-18 00:09:55 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-01-26 18:50:25 +03:00
|
|
|
|
)
|
2015-12-20 23:28:41 +03:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// PRIVATE
|
|
|
|
|
|
|
|
|
|
function asyncLogGroup() {
|
|
|
|
|
var args = [].slice.apply(arguments);
|
|
|
|
|
var cb = args.pop();
|
|
|
|
|
console.group.apply(console, args);
|
|
|
|
|
return function() {
|
|
|
|
|
console.log('Finished');
|
|
|
|
|
console.groupEnd();
|
|
|
|
|
var _cb = cb || (() => {});
|
|
|
|
|
return _cb.apply(this, arguments);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function httpGet(url, cb) {
|
|
|
|
|
var cb = cb || (() => {});
|
|
|
|
|
var req = new XMLHttpRequest();
|
|
|
|
|
var ifAsync = true;
|
|
|
|
|
req.open('GET', url, ifAsync);
|
|
|
|
|
req.onload = event => {
|
2016-01-17 22:27:54 +03:00
|
|
|
|
if (req.status !== 200)
|
2015-12-20 23:28:41 +03:00
|
|
|
|
return cb(event);
|
|
|
|
|
console.log('GETed with success.');
|
|
|
|
|
return cb(null, req.responseText)
|
|
|
|
|
};
|
|
|
|
|
req.onerror = cb;
|
|
|
|
|
req.send();
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-17 22:27:54 +03:00
|
|
|
|
function updatePacProxyIps(provider, cb) {
|
|
|
|
|
if (!provider.proxyHosts) {
|
|
|
|
|
console.log(provider+' has no proxies defined.');
|
|
|
|
|
return cb(null, null);
|
|
|
|
|
}
|
|
|
|
|
var cb = asyncLogGroup('Getting IP for '+ provider.proxyHosts.join(', ') +'...', cb);
|
|
|
|
|
var i = 0;
|
|
|
|
|
for (var proxyHost of provider.proxyHosts) {
|
|
|
|
|
httpGet(
|
|
|
|
|
'http://www.dns-lg.com/google1/'+ proxyHost +'/A',
|
|
|
|
|
(err, res) => {
|
|
|
|
|
if (!err) {
|
|
|
|
|
provider.proxyIps = provider.proxyIps || {};
|
|
|
|
|
provider.proxyIps[ JSON.parse(res).answer[0].rdata ] = true;
|
|
|
|
|
}
|
2016-01-18 00:09:55 +03:00
|
|
|
|
if ( ++i == provider.proxyHosts.length )
|
2016-01-17 22:27:54 +03:00
|
|
|
|
return cb(err, 'Complete.');
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
}
|
2015-12-20 23:28:41 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setPacScriptFromProvider(provider, cb) {
|
|
|
|
|
var cb = asyncLogGroup('Getting pac script from provider...', provider.pacUrl, cb);
|
2016-01-17 22:27:54 +03:00
|
|
|
|
|
2015-12-20 23:28:41 +03:00
|
|
|
|
httpGet(
|
|
|
|
|
provider.pacUrl,
|
|
|
|
|
(err, res) => {
|
|
|
|
|
if (err)
|
|
|
|
|
return cb(err);
|
|
|
|
|
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 );
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
}
|