mirror of
https://github.com/anticensority/runet-censorship-bypass.git
synced 2024-11-27 20:03:45 +03:00
Add eslint w/ Google styles, restyle
This commit is contained in:
parent
9ef8939127
commit
77a88e5778
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
|||
node_modules
|
||||
npm-debug.log
|
||||
.swp
|
||||
|
|
27
extensions/chromium/minimalistic-pac-setter/.eslintrc.js
Normal file
27
extensions/chromium/minimalistic-pac-setter/.eslintrc.js
Normal file
|
@ -0,0 +1,27 @@
|
|||
module.exports = {
|
||||
"extends": ["eslint:recommended", "google"],
|
||||
"plugins": [
|
||||
//"hapi"
|
||||
],
|
||||
"env": {
|
||||
"browser": true,
|
||||
"webextensions": true,
|
||||
"es6": true
|
||||
},
|
||||
"globals": {
|
||||
"chrome": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"sourceType": "script",
|
||||
"ecmaFeatures": {
|
||||
"impliedStrict": false
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"strict": ["error", "global"],
|
||||
"no-console": "off",
|
||||
"padded-blocks": "off",
|
||||
"require-jsdoc": "off"
|
||||
//"hapi/hapi-scope-start": ["warn"]
|
||||
}
|
||||
};
|
|
@ -3,7 +3,8 @@
|
|||
/*
|
||||
Task 1. Gets IPs for proxies of antizapret/anticenz via dns over https.
|
||||
These IPs are used in block-informer to inform user when proxy is ON.
|
||||
Task 2. Downloads PAC proxy script from antizapret/anticenz/my Google Drive and sets it in Chromium settings.
|
||||
Task 2. Downloads PAC proxy script from antizapret/anticenz/
|
||||
my Google Drive and sets it in Chromium settings.
|
||||
Task 3. Schedules tasks 1 & 2 for every 4 hours.
|
||||
*/
|
||||
|
||||
|
@ -25,26 +26,26 @@
|
|||
proxyHosts: ['proxy.antizapret.prostovpn.org'],
|
||||
proxyIps: {
|
||||
'195.123.209.38': 'proxy.antizapret.prostovpn.org',
|
||||
'2a02:27ac::10': 'proxy.antizapret.prostovpn.org'
|
||||
}
|
||||
'2a02:27ac::10': 'proxy.antizapret.prostovpn.org',
|
||||
},
|
||||
},
|
||||
Антиценз: {
|
||||
pacUrl: 'https://config.anticenz.org/proxy.pac',
|
||||
proxyHosts: ['gw2.anticenz.org'],
|
||||
proxyIps: {
|
||||
'5.196.220.114': 'gw2.anticenz.org'
|
||||
}
|
||||
'5.196.220.114': 'gw2.anticenz.org',
|
||||
},
|
||||
},
|
||||
Оба_и_на_свитчах: {
|
||||
//pacUrl: 'https://drive.google.com/uc?export=download&id=0B-ZCVSvuNWf0akpCOURNS2VCTmc', // 0.14
|
||||
// pacUrl: 'https://drive.google.com/uc?export=download&id=0B-ZCVSvuNWf0akpCOURNS2VCTmc', // 0.14
|
||||
pacUrl: 'https://drive.google.com/uc?export=download&id=0B-ZCVSvuNWf0bzNUR2F4RF8wOU0', // 0.15
|
||||
proxyHosts: ['proxy.antizapret.prostovpn.org', 'gw2.anticenz.org'],
|
||||
proxyIps: {
|
||||
'195.123.209.38': 'proxy.antizapret.prostovpn.org',
|
||||
'2a02:27ac::10': 'proxy.antizapret.prostovpn.org',
|
||||
'5.196.220.114': 'gw2.anticenz.org'
|
||||
}
|
||||
}
|
||||
'2a02:27ac::10': 'proxy.antizapret.prostovpn.org',
|
||||
'5.196.220.114': 'gw2.anticenz.org',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
_currentPacProviderKey: 'Оба_и_на_свитчах',
|
||||
|
@ -52,20 +53,26 @@
|
|||
isProxied(ip) {
|
||||
|
||||
// Executed on each request with ip. Make it as fast as possible.
|
||||
return this._currentPacProviderKey && this.pacProviders[this._currentPacProviderKey].proxyIps.hasOwnProperty(ip);
|
||||
// The benefit of removing lookups is little, e.g. this._currentProxyIps && this._currentProxyIps.hasOwnProperty(ip);
|
||||
// Property lookups are cheap (I tested).
|
||||
return this._currentPacProviderKey
|
||||
&& this.pacProviders[this._currentPacProviderKey]
|
||||
.proxyIps.hasOwnProperty(ip);
|
||||
|
||||
},
|
||||
|
||||
mustBeKey(key) {
|
||||
|
||||
if ( !(key === null || this.pacProviders[key]) ) {
|
||||
throw new IllegalArgumentException('No provider for key:' + key);
|
||||
throw new TypeError('No provider for key:' + key);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
get currentPacProviderKey() { return this._currentPacProviderKey },
|
||||
get currentPacProviderKey() {
|
||||
|
||||
return this._currentPacProviderKey;
|
||||
|
||||
},
|
||||
set currentPacProviderKey(newKey) {
|
||||
|
||||
this.mustBeKey(newKey);
|
||||
|
@ -77,16 +84,15 @@
|
|||
|
||||
if(key) {
|
||||
this.mustBeKey(key);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
key = this.currentPacProviderKey;
|
||||
}
|
||||
return this.pacProviders[key];
|
||||
|
||||
},
|
||||
|
||||
/*
|
||||
Is it the first time extension installed? Do something, e.g. initiate PAC sync.
|
||||
/* Is it the first time extension installed?
|
||||
Do something, e.g. initiate PAC sync.
|
||||
*/
|
||||
ifFirstInstall: false,
|
||||
lastPacUpdateStamp: 0,
|
||||
|
@ -100,7 +106,10 @@
|
|||
// Copy only settable properties (except functions).
|
||||
const onlySettable = {};
|
||||
for(const key of Object.keys(this)) {
|
||||
if (Object.getOwnPropertyDescriptor(this, key).writable && typeof(this[key]) !== 'function') {
|
||||
if (
|
||||
Object.getOwnPropertyDescriptor(this, key).writable
|
||||
&& typeof(this[key]) !== 'function'
|
||||
) {
|
||||
onlySettable[key] = this[key];
|
||||
}
|
||||
}
|
||||
|
@ -142,7 +151,11 @@
|
|||
|
||||
if (key === null) {
|
||||
// No pac provider set.
|
||||
return cb({clarification:{message:'Сперва выберите PAC-провайдера.'}});
|
||||
return cb({
|
||||
clarification: {
|
||||
message: 'Сперва выберите PAC-провайдера.',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const pacProvider = this.getPacProvider(key);
|
||||
|
@ -199,23 +212,28 @@
|
|||
|
||||
setAlarms() {
|
||||
|
||||
let nextUpdateMoment = this.lastPacUpdateStamp + this._pacUpdatePeriodInMinutes*60*1000;
|
||||
let nextUpdateMoment = this.lastPacUpdateStamp
|
||||
+ this._pacUpdatePeriodInMinutes*60*1000;
|
||||
const now = Date.now();
|
||||
if (nextUpdateMoment < now) {
|
||||
nextUpdateMoment = now;
|
||||
}
|
||||
|
||||
console.log( 'Next PAC update is scheduled on', new Date(nextUpdateMoment).toLocaleString('ru-RU') );
|
||||
console.log(
|
||||
'Next PAC update is scheduled on',
|
||||
new Date(nextUpdateMoment).toLocaleString('ru-RU')
|
||||
);
|
||||
|
||||
chrome.alarms.create(
|
||||
this._periodicUpdateAlarmReason,
|
||||
{
|
||||
when: nextUpdateMoment,
|
||||
periodInMinutes: this._pacUpdatePeriodInMinutes
|
||||
periodInMinutes: this._pacUpdatePeriodInMinutes,
|
||||
}
|
||||
);
|
||||
|
||||
return nextUpdateMoment === now; // ifAlarmTriggered. May be changed in the future.
|
||||
// ifAlarmTriggered. May be changed in the future.
|
||||
return nextUpdateMoment === now;
|
||||
|
||||
},
|
||||
|
||||
|
@ -251,7 +269,7 @@
|
|||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
|
@ -260,15 +278,20 @@
|
|||
|
||||
checkChromeError();
|
||||
/*
|
||||
Event handlers that ALWAYS work (even if installation is not done or failed).
|
||||
Event handlers that ALWAYS work (even if installation is not done
|
||||
or failed).
|
||||
E.g. install window may fail to open or be closed by user accidentally.
|
||||
In such case extension _should_ try to work on default parameters.
|
||||
*/
|
||||
const antiCensorRu = window.antiCensorRu;
|
||||
chrome.alarms.onAlarm.addListener(
|
||||
(alarm) => {
|
||||
|
||||
if (alarm.name === antiCensorRu._periodicUpdateAlarmReason) {
|
||||
console.log('Periodic PAC update triggered:', new Date().toLocaleString('ru-RU'));
|
||||
console.log(
|
||||
'Periodic PAC update triggered:',
|
||||
new Date().toLocaleString('ru-RU')
|
||||
);
|
||||
antiCensorRu.syncWithPacProvider(/* Swallows errors. */);
|
||||
}
|
||||
|
||||
|
@ -276,7 +299,7 @@
|
|||
);
|
||||
console.log('Alarm listener installed. We won\'t miss any PAC update.');
|
||||
|
||||
window.addEventListener('online', () => {
|
||||
window.addEventListener('online', () => {
|
||||
|
||||
console.log('We are online, checking periodic updates...');
|
||||
antiCensorRu.setAlarms();
|
||||
|
@ -288,11 +311,16 @@
|
|||
|
||||
if (!antiCensorRu.ifFirstInstall) {
|
||||
// LAUNCH, RELOAD, UPDATE
|
||||
antiCensorRu._currentPacProviderKey = oldStorage._currentPacProviderKey || null; // Old or migrate.
|
||||
antiCensorRu.lastPacUpdateStamp = oldStorage.lastPacUpdateStamp || antiCensorRu.lastPacUpdateStamp; // Old or migrate to default.
|
||||
console.log( 'Last PAC update was on', new Date(antiCensorRu.lastPacUpdateStamp).toLocaleString('ru-RU') );
|
||||
}
|
||||
else {
|
||||
// Use old or migrate to default.
|
||||
antiCensorRu._currentPacProviderKey =
|
||||
oldStorage._currentPacProviderKey || null;
|
||||
antiCensorRu.lastPacUpdateStamp =
|
||||
oldStorage.lastPacUpdateStamp || antiCensorRu.lastPacUpdateStamp;
|
||||
console.log(
|
||||
'Last PAC update was on',
|
||||
new Date(antiCensorRu.lastPacUpdateStamp).toLocaleString('ru-RU')
|
||||
);
|
||||
} else {
|
||||
// INSTALL
|
||||
console.log('Installing...');
|
||||
return chrome.runtime.openOptionsPage();
|
||||
|
@ -308,7 +336,8 @@
|
|||
}
|
||||
|
||||
/*
|
||||
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.
|
||||
2. We have to check storage for migration before using it.
|
||||
Better on each launch then on each pull.
|
||||
|
@ -343,26 +372,27 @@
|
|||
function asyncLogGroup(...args) {
|
||||
|
||||
const cb = args.pop() || (() => {});
|
||||
console.group.apply(console, args);
|
||||
console.group(...args);
|
||||
return function(...cbArgs) {
|
||||
|
||||
console.groupEnd();
|
||||
console.log('Group finished.');
|
||||
cb.apply(this, cbArgs);
|
||||
cb(...cbArgs);
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function checkChromeError(betterStack) {
|
||||
|
||||
// Chrome API calls your cb in a context different from the point of API method invokation.
|
||||
// Chrome API calls your cb in a context different from the point of API
|
||||
// method invokation.
|
||||
const err = chrome.runtime.lastError || chrome.extension.lastError || null;
|
||||
if (err) {
|
||||
const args = ['API returned error:', err];
|
||||
if (betterStack) {
|
||||
args.push('\n' + betterStack);
|
||||
}
|
||||
console.warn.apply(console, args);
|
||||
console.warn(...args);
|
||||
}
|
||||
return err;
|
||||
|
||||
|
@ -371,14 +401,14 @@
|
|||
function chromified(cb, ...replaceArgs) {
|
||||
|
||||
const stack = (new Error()).stack;
|
||||
// Take error first callback and covert it to chrome api callback.
|
||||
// Take error first callback and convert it to chrome api callback.
|
||||
return function(...args) {
|
||||
|
||||
if (replaceArgs.length) {
|
||||
args = replaceArgs;
|
||||
}
|
||||
const err = checkChromeError(stack);
|
||||
cb && cb.call(this, err, ...args);
|
||||
cb && cb.call(null, err, ...args);
|
||||
|
||||
};
|
||||
|
||||
|
@ -390,8 +420,8 @@
|
|||
mode: 'pac_script',
|
||||
pacScript: {
|
||||
mandatory: false,
|
||||
data: pacData
|
||||
}
|
||||
data: pacData,
|
||||
},
|
||||
};
|
||||
console.log('Setting chrome proxy settings...');
|
||||
chrome.proxy.settings.set( {value: config}, () => {
|
||||
|
@ -405,7 +435,7 @@
|
|||
const ifThis = details.levelOfControl.startsWith('controlled_by_this');
|
||||
if (!ifThis) {
|
||||
console.warn('Failed, other extension is in control.');
|
||||
return cb({clarification: {message:'Настройки прокси контролирует другое расширение. <a href="chrome://settings/search#proxy">Какое?</a>'}});
|
||||
return cb({clarification: {message: 'Настройки прокси контролирует другое расширение. <a href="chrome://settings/search#proxy">Какое?</a>'}});
|
||||
}
|
||||
console.log('Successfuly set PAC in proxy settings..');
|
||||
cb();
|
||||
|
@ -426,7 +456,9 @@
|
|||
.then( (text) => cb(err, text), cb );
|
||||
const status = res.status;
|
||||
if ( !( status >= 200 && status < 300 || status === 304 ) ) {
|
||||
res.clarification = {message: 'Получен ответ с неудачным HTTP-кодом ' + status + '.'};
|
||||
res.clarification = {
|
||||
message: 'Получен ответ с неудачным HTTP-кодом ' + status + '.',
|
||||
};
|
||||
return textCb(res);
|
||||
}
|
||||
console.log('GETed with success:', url, Date.now() - start);
|
||||
|
@ -435,7 +467,9 @@
|
|||
},
|
||||
(err) => {
|
||||
|
||||
err.clarification = {message: 'Что-то не так с сетью, проверьте соединение.'};
|
||||
err.clarification = {
|
||||
message: 'Что-то не так с сетью, проверьте соединение.',
|
||||
};
|
||||
cb && cb(err);
|
||||
|
||||
}
|
||||
|
@ -446,17 +480,17 @@
|
|||
|
||||
// args: { host:..., type: 'AAAA', filter: ['AAAA'] }
|
||||
if (!(args.host && args.type && cb)) {
|
||||
throw new Error('Wrong args:' + host + ',' + type);
|
||||
throw new Error('Wrong args:' + args.host + ',' + args.type);
|
||||
}
|
||||
|
||||
const type2str = {
|
||||
// https://en.wikipedia.org/wiki/List_of_DNS_record_types
|
||||
// A, AAAA may be localized (github, e.g.), but you may use ANY
|
||||
1: 'A', // IPv4
|
||||
1: 'A', // IPv4
|
||||
28: 'AAAA', // IPv6
|
||||
2: 'NS',
|
||||
5: 'CNAME', // Synonyms, returned by server together with A/AAAA.
|
||||
255: 'ANY' // Deprecated on some servers, not recommended
|
||||
2: 'NS',
|
||||
5: 'CNAME', // Synonyms, returned by server together with A/AAAA.
|
||||
255: 'ANY', // Deprecated on some servers, not recommended
|
||||
};
|
||||
|
||||
httpGet(
|
||||
|
@ -468,25 +502,25 @@
|
|||
console.log('Json parsed.');
|
||||
if (err || res.Status) {
|
||||
const msg = ['Answer', 'Comment', 'Status']
|
||||
.filter( (prop) => res[ prop ] )
|
||||
.map( (prop) => prop + ': ' + JSON.stringify( res[ prop ] ) )
|
||||
.filter( (prop) => res[prop] )
|
||||
.map( (prop) => prop + ': ' + JSON.stringify( res[prop] ) )
|
||||
.join(', \n');
|
||||
err.clarification.message += ' Сервер (json): ' + msg;
|
||||
err.data = err.data || res;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
res = res.Answer || [];
|
||||
for (const record of res) {
|
||||
record.type = type2str[ record.type ];
|
||||
record.type = type2str[record.type];
|
||||
}
|
||||
if ( args.filter ) {
|
||||
res = res.filter( (record) => args.filter.indexOf( record.type ) > -1 );
|
||||
res = res.filter(
|
||||
(record) => args.filter.indexOf( record.type ) > -1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(e) {
|
||||
err = e || err || {clarification:{message:''}};
|
||||
err.clarification = err.clarification || { message: '' };
|
||||
} catch(e) {
|
||||
err = e || err || {clarification: {message: ''}};
|
||||
err.clarification = err.clarification || {message: ''};
|
||||
err.clarification.message += ' Сервер (текст): '+ res;
|
||||
err.clarification.message.trim();
|
||||
err.data = err.data || res;
|
||||
|
@ -495,7 +529,7 @@
|
|||
cb( err, res );
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
function getDnsRecords(args, cb) {
|
||||
|
||||
|
@ -506,18 +540,22 @@
|
|||
host: 'proxy.navalny.cia.gov',
|
||||
// Optional
|
||||
types: {
|
||||
string: ['A', 'AAAA'], // <- Default. Makes one request per each type.
|
||||
filter: ['A', 'AAAA'], // <- Default. E.g., you want to get rid of CNAME type from response.
|
||||
string: ['A', 'AAAA'],
|
||||
// ^ Default. Makes one request per each type.
|
||||
filter: ['A', 'AAAA'],
|
||||
// ^ Default. E.g., you want to get rid of CNAME type from
|
||||
// response.
|
||||
}
|
||||
}
|
||||
Exmple of answer from google:
|
||||
"Answer":
|
||||
[
|
||||
{
|
||||
"name": "apple.com.", // Always matches name in the Question section
|
||||
"type": 1, // A - Standard DNS RR type
|
||||
"TTL": 3599, // Record's time-to-live in seconds
|
||||
"data": "17.178.96.59" // Data for A - IP address as text
|
||||
"name": "apple.com.", // Always matches name in the Question
|
||||
// section.
|
||||
"type": 1, // A - Standard DNS RR type.
|
||||
"TTL": 3599, // Record's time-to-live in seconds.
|
||||
"data": "17.178.96.59" // Data for A - IP address as text.
|
||||
},
|
||||
...
|
||||
Exmple of output:
|
||||
|
@ -529,25 +567,37 @@
|
|||
}
|
||||
args.types = Object.assign({
|
||||
string: ['A', 'AAAA'],
|
||||
filter: ['A', 'AAAA']
|
||||
filter: ['A', 'AAAA'],
|
||||
}, args.types);
|
||||
|
||||
const promises = args.types.string.map(
|
||||
(type) => new Promise( (resolve, reject) =>
|
||||
getOneDnsRecord({ host: args.host, type: type, filter: args.types.filter }, (err, res) => err ? reject(err) : resolve(res) )
|
||||
getOneDnsRecord(
|
||||
{host: args.host, type: type, filter: args.types.filter},
|
||||
(err, res) => err ? reject(err) : resolve(res) )
|
||||
)
|
||||
);
|
||||
Promise.all(promises).then( (answers) => cb( null, [].concat.apply([], answers) ), cb );
|
||||
Promise.all(promises).then(
|
||||
(answers) => cb( null, [].concat(...answers) ),
|
||||
cb
|
||||
);
|
||||
}
|
||||
|
||||
const getIpDnsRecords = (host, cb) => getDnsRecords({ host: host }, cb);
|
||||
const getIpDnsRecords = (host, cb) => getDnsRecords({host: host}, cb);
|
||||
|
||||
function updatePacProxyIps(provider, cb) {
|
||||
|
||||
cb = asyncLogGroup('Getting IP for '+ provider.proxyHosts.join(', ') +'...', cb);
|
||||
cb = asyncLogGroup(
|
||||
'Getting IP for '+ provider.proxyHosts.join(', ') + '...',
|
||||
cb
|
||||
);
|
||||
let failure = {
|
||||
clarification: {message:'Не удалось получить один или несколько IP адресов для прокси-серверов. Иконка для уведомления об обходе блокировок может не отображаться.'},
|
||||
errors: {}
|
||||
clarification: {
|
||||
message: 'Не удалось получить один или несколько IP адресов для' +
|
||||
' прокси-серверов. Иконка для уведомления об обходе блокировок ' +
|
||||
'может не отображаться.',
|
||||
},
|
||||
errors: {},
|
||||
};
|
||||
let i = 0;
|
||||
provider.proxyHosts.map(
|
||||
|
@ -557,9 +607,10 @@
|
|||
|
||||
if (!err) {
|
||||
provider.proxyIps = provider.proxyIps || {};
|
||||
records.forEach( (ans) => provider.proxyIps[ ans.data ] = proxyHost );
|
||||
}
|
||||
else {
|
||||
records.forEach(
|
||||
(ans) => provider.proxyIps[ans.data] = proxyHost
|
||||
);
|
||||
} else {
|
||||
failure.errors[proxyHost] = err;
|
||||
}
|
||||
|
||||
|
@ -574,7 +625,10 @@
|
|||
|
||||
function setPacScriptFromProvider(provider, cb) {
|
||||
|
||||
cb = asyncLogGroup('Getting pac script from provider...', provider.pacUrl, cb);
|
||||
cb = asyncLogGroup(
|
||||
'Getting pac script from provider...', provider.pacUrl,
|
||||
cb
|
||||
);
|
||||
|
||||
httpGet(
|
||||
provider.pacUrl,
|
||||
|
@ -582,8 +636,9 @@
|
|||
|
||||
if (err) {
|
||||
err.clarification = {
|
||||
message: 'Не удалось скачать PAC-скрипт с адреса: ' + provider.pacUrl + '.',
|
||||
prev: err.clarification
|
||||
message: 'Не удалось скачать PAC-скрипт с адреса: '
|
||||
+ provider.pacUrl + '.',
|
||||
prev: err.clarification,
|
||||
};
|
||||
return cb(err);
|
||||
}
|
||||
|
@ -612,6 +667,6 @@ window.addEventListener('unhandledrejection', (event) => {
|
|||
chrome.proxy.settings.onChange.addListener((details) => {
|
||||
|
||||
console.log('Proxy settings changed.', details);
|
||||
const ifOther = details.levelOfControl.startsWith('controlled_by_other');
|
||||
// const ifOther = details.levelOfControl.startsWith('controlled_by_other');
|
||||
|
||||
});
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
'use strict';
|
||||
|
||||
// Shows user browserAction icon if any part of the current site is being blocked and proxied.
|
||||
// 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".
|
||||
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:
|
||||
|
@ -13,7 +15,7 @@
|
|||
**/
|
||||
|
||||
window.chrome.browserAction.setBadgeBackgroundColor({
|
||||
color: '#db4b2f'
|
||||
color: '#db4b2f',
|
||||
});
|
||||
|
||||
window.tabWithError2ip = {}; // For errors only: Error? -> Check this IP!
|
||||
|
@ -30,7 +32,7 @@ window.tabWithError2ip = {}; // For errors only: Error? -> Check this IP!
|
|||
|
||||
function onTabUpdate(tabId) {
|
||||
if (_tabCallbacks[tabId]) {
|
||||
_tabCallbacks[tabId].map( f => f() );
|
||||
_tabCallbacks[tabId].map( (f) => f() );
|
||||
delete _tabCallbacks[tabId];
|
||||
}
|
||||
}
|
||||
|
@ -38,28 +40,34 @@ window.tabWithError2ip = {}; // For errors only: Error? -> Check this IP!
|
|||
chrome.tabs.onUpdated.addListener( onTabUpdate );
|
||||
|
||||
function isInsideTabWithIp(requestDetails) {
|
||||
return requestDetails.tabId !== -1 && requestDetails.ip
|
||||
return requestDetails.tabId !== -1 && requestDetails.ip;
|
||||
}
|
||||
|
||||
chrome.webRequest.onErrorOccurred.addListener(
|
||||
(requestDetails) =>
|
||||
isInsideTabWithIp(requestDetails) &&
|
||||
(
|
||||
isProxiedAndInformed(requestDetails) || requestDetails.type === 'main_frame' && ( window.tabWithError2ip[requestDetails.tabId] = requestDetails.ip )
|
||||
isProxiedAndInformed(requestDetails)
|
||||
|| requestDetails.type === 'main_frame'
|
||||
&& (window.tabWithError2ip[requestDetails.tabId] = requestDetails.ip)
|
||||
),
|
||||
{ urls: ['<all_urls>'] }
|
||||
{urls: ['<all_urls>']}
|
||||
);
|
||||
|
||||
chrome.tabs.onRemoved.addListener( (tabId) => { onTabUpdate(tabId); delete window.tabWithError2ip[tabId] } );
|
||||
chrome.tabs.onRemoved.addListener( (tabId) => {
|
||||
onTabUpdate(tabId);
|
||||
delete window.tabWithError2ip[tabId];
|
||||
});
|
||||
|
||||
function updateTitle(requestDetails, cb) {
|
||||
|
||||
chrome.browserAction.getTitle(
|
||||
{ tabId: requestDetails.tabId },
|
||||
{tabId: requestDetails.tabId},
|
||||
(title) => {
|
||||
|
||||
const ifTitleSetAlready = /\n/.test(title);
|
||||
const proxyHost = window.antiCensorRu.getPacProvider().proxyIps[ requestDetails.ip ];
|
||||
const proxyHost = window.antiCensorRu.getPacProvider()
|
||||
.proxyIps[requestDetails.ip];
|
||||
|
||||
const hostname = new URL( requestDetails.url ).hostname;
|
||||
|
||||
|
@ -68,25 +76,31 @@ window.tabWithError2ip = {}; // For errors only: Error? -> Check this IP!
|
|||
const proxyTitle = 'Прокси:';
|
||||
|
||||
if (!ifTitleSetAlready) {
|
||||
title = 'Разблокированы:\n'+ indent + hostname +'\n'+ proxyTitle +'\n'+ indent + proxyHost;
|
||||
title = 'Разблокированы:\n' + indent + hostname + '\n'
|
||||
+ proxyTitle + '\n' + indent + proxyHost;
|
||||
ifShouldUpdateTitle = true;
|
||||
|
||||
chrome.browserAction.setBadgeText({
|
||||
tabId: requestDetails.tabId,
|
||||
text: requestDetails.type === 'main_frame' ? '1' : '%1'
|
||||
text: requestDetails.type === 'main_frame' ? '1' : '%1',
|
||||
});
|
||||
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
const hostsProxiesPair = title.split(proxyTitle);
|
||||
|
||||
if (hostsProxiesPair[1].indexOf(proxyHost) === -1) {
|
||||
title = title.replace(hostsProxiesPair[1], hostsProxiesPair[1] +'\n'+ indent + proxyHost);
|
||||
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);
|
||||
title = title.replace(
|
||||
proxyTitle,
|
||||
indent + hostname + '\n' + proxyTitle
|
||||
);
|
||||
ifShouldUpdateTitle = true;
|
||||
|
||||
const _cb = cb;
|
||||
|
@ -97,7 +111,8 @@ window.tabWithError2ip = {}; // For errors only: Error? -> Check this IP!
|
|||
chrome.browserAction.setBadgeText(
|
||||
{
|
||||
tabId: requestDetails.tabId,
|
||||
text: ( isNaN( result.charAt(0) ) && result.charAt(0) || '' ) + (hostsProxiesPair[0].split('\n').length - 1)
|
||||
text: (isNaN( result.charAt(0)) && result.charAt(0) || '')
|
||||
+ (hostsProxiesPair[0].split('\n').length - 1),
|
||||
}
|
||||
);
|
||||
return _cb();
|
||||
|
@ -111,7 +126,7 @@ window.tabWithError2ip = {}; // For errors only: Error? -> Check this IP!
|
|||
if (ifShouldUpdateTitle) {
|
||||
chrome.browserAction.setTitle({
|
||||
title: title,
|
||||
tabId: requestDetails.tabId
|
||||
tabId: requestDetails.tabId,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -121,12 +136,12 @@ window.tabWithError2ip = {}; // For errors only: Error? -> Check this IP!
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
let previousUpdateTitleFinished = Promise.resolve();
|
||||
|
||||
function isProxiedAndInformed(requestDetails) {
|
||||
|
||||
if ( !(requestDetails.ip && antiCensorRu.isProxied( requestDetails.ip )) ) {
|
||||
if ( !(requestDetails.ip
|
||||
&& window.antiCensorRu.isProxied( requestDetails.ip )) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -136,7 +151,8 @@ window.tabWithError2ip = {}; // For errors only: Error? -> Check this IP!
|
|||
() => new Promise(
|
||||
(resolve) => {
|
||||
const cb = () => updateTitle( requestDetails, resolve );
|
||||
return ifMainFrame ? afterTabUpdated(requestDetails.tabId, cb) : cb();
|
||||
return ifMainFrame
|
||||
? afterTabUpdated(requestDetails.tabId, cb) : cb();
|
||||
}
|
||||
)
|
||||
);
|
||||
|
@ -145,8 +161,9 @@ window.tabWithError2ip = {}; // For errors only: Error? -> Check this IP!
|
|||
}
|
||||
|
||||
chrome.webRequest.onResponseStarted.addListener(
|
||||
(requestDetails) => isInsideTabWithIp(requestDetails) && isProxiedAndInformed(requestDetails),
|
||||
{ urls: ['<all_urls>'] }
|
||||
(requestDetails) => isInsideTabWithIp(requestDetails)
|
||||
&& isProxiedAndInformed(requestDetails),
|
||||
{urls: ['<all_urls>']}
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
@ -5,19 +5,39 @@
|
|||
const createMenuLinkEntry = (title, tab2url) => chrome.contextMenus.create({
|
||||
title: title,
|
||||
contexts: ['browser_action'],
|
||||
onclick: (menuInfo, tab) => Promise.resolve( tab2url( tab ) ).then( (url) => chrome.tabs.create({url: url}) )
|
||||
onclick:
|
||||
(menuInfo, tab) => Promise.resolve( tab2url( tab ) )
|
||||
.then( (url) => chrome.tabs.create({url: url}) ),
|
||||
});
|
||||
|
||||
createMenuLinkEntry( 'Сайт доступен из-за границы? Is up?', (tab) => 'http://isup.me/'+ new URL(tab.url).hostname );
|
||||
createMenuLinkEntry(
|
||||
'Сайт доступен из-за границы? Is up?',
|
||||
(tab) => 'http://isup.me/' + new URL(tab.url).hostname
|
||||
);
|
||||
|
||||
createMenuLinkEntry( 'Сайт в реестре блокировок?', (tab) => 'https://antizapret.info/index.php?search=' + tab.url );
|
||||
createMenuLinkEntry(
|
||||
'Сайт в реестре блокировок?',
|
||||
(tab) => 'https://antizapret.info/index.php?search=' + tab.url
|
||||
);
|
||||
|
||||
createMenuLinkEntry( 'Из архива archive.org', (tab) => 'https://web.archive.org/web/*/' + tab.url );
|
||||
createMenuLinkEntry(
|
||||
'Из архива archive.org',
|
||||
(tab) => 'https://web.archive.org/web/*/' + tab.url
|
||||
);
|
||||
|
||||
createMenuLinkEntry( 'Открыть веб прокси (не наш)', (tab) => 'https://kproxy.com' );
|
||||
createMenuLinkEntry(
|
||||
'Открыть веб прокси (не наш)',
|
||||
(tab) => 'https://kproxy.com'
|
||||
);
|
||||
|
||||
createMenuLinkEntry( 'Другие варианты разблокировки', (tab) => 'https://rebrand.ly/unblock#' + tab.url );
|
||||
createMenuLinkEntry(
|
||||
'Другие варианты разблокировки',
|
||||
(tab) => 'https://rebrand.ly/unblock#' + tab.url
|
||||
);
|
||||
|
||||
createMenuLinkEntry( 'У меня проблемы с расширением!', (tab) => 'https://rebrand.ly/ac-support');
|
||||
createMenuLinkEntry(
|
||||
'У меня проблемы с расширением!',
|
||||
(tab) => 'https://rebrand.ly/ac-support'
|
||||
);
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -10,8 +10,7 @@ chrome.runtime.getBackgroundPage( (backgroundPage) => {
|
|||
if (msg) {
|
||||
status.classList.remove('off');
|
||||
status.innerHTML = msg;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
status.classList.add('off');
|
||||
}
|
||||
|
||||
|
@ -34,7 +33,7 @@ chrome.runtime.getBackgroundPage( (backgroundPage) => {
|
|||
[24, ' дн'],
|
||||
[7, ' недель'],
|
||||
[4, ' месяцев'],
|
||||
[12, ' г']
|
||||
[12, ' г'],
|
||||
];
|
||||
for(const g of gauges) {
|
||||
const diffy = Math.floor(diff / g[0]);
|
||||
|
@ -48,12 +47,15 @@ chrome.runtime.getBackgroundPage( (backgroundPage) => {
|
|||
|
||||
const dateElement = document.querySelector('.update-date');
|
||||
dateElement.innerText = dateForUser;
|
||||
dateElement.title = new Date(antiCensorRu.lastPacUpdateStamp).toLocaleString('ru-RU');
|
||||
dateElement.title = new Date(antiCensorRu.lastPacUpdateStamp)
|
||||
.toLocaleString('ru-RU');
|
||||
|
||||
};
|
||||
|
||||
setDate();
|
||||
chrome.storage.onChanged.addListener( (changes) => changes.lastPacUpdateStamp.newValue && setDate() );
|
||||
chrome.storage.onChanged.addListener(
|
||||
(changes) => changes.lastPacUpdateStamp.newValue && setDate()
|
||||
);
|
||||
|
||||
// CLOSE BUTTON
|
||||
|
||||
|
@ -66,7 +68,7 @@ chrome.runtime.getBackgroundPage( (backgroundPage) => {
|
|||
const id = antiCensorRu.currentPacProviderKey || 'none';
|
||||
return document.querySelector('#'+id);
|
||||
|
||||
}
|
||||
};
|
||||
const checkChosenProvider = () => currentProviderRadio().checked = true;
|
||||
|
||||
const showError = (err) => {
|
||||
|
@ -81,7 +83,9 @@ chrome.runtime.getBackgroundPage( (backgroundPage) => {
|
|||
}
|
||||
message = message.trim();
|
||||
setStatusTo(
|
||||
`<span style="color:red">${ifNotCritical ? 'Некритичная ошибка.' : 'Ошибка!'}</span>
|
||||
`<span style="color:red">
|
||||
${ifNotCritical ? 'Некритичная ошибка.' : 'Ошибка!'}
|
||||
</span>
|
||||
<br/>
|
||||
<span style="font-size: 0.9em; color: darkred">${message}</span>
|
||||
<a href class="link-button">[Ещё подробнее]</a>`
|
||||
|
@ -91,7 +95,9 @@ chrome.runtime.getBackgroundPage( (backgroundPage) => {
|
|||
const div = document.createElement('div');
|
||||
div.innerHTML = `
|
||||
Более подробную информацию можно узнать из логов фоновой страницы:<br/>
|
||||
<a href="chrome://extensions?id=${chrome.runtime.id}" data-in-bg="true">chrome://extensions</a> › Это расширение › Отладка страниц: фоновая страница › Console (DevTools)
|
||||
<a href="chrome://extensions?id=${chrome.runtime.id}" data-in-bg="true">
|
||||
chrome://extensions</a> ›
|
||||
Это расширение › Отладка страниц: фоновая страница › Console (DevTools)
|
||||
<br>
|
||||
Ещё: ${JSON.stringify({err: err, stack: err.stack})}
|
||||
`;
|
||||
|
@ -102,7 +108,7 @@ chrome.runtime.getBackgroundPage( (backgroundPage) => {
|
|||
|
||||
};
|
||||
|
||||
const enableDisableInputs = function () {
|
||||
const enableDisableInputs = function() {
|
||||
|
||||
const inputs = document.querySelectorAll('input');
|
||||
for ( let i = 0; i < inputs.length; i++ ) {
|
||||
|
@ -118,13 +124,12 @@ chrome.runtime.getBackgroundPage( (backgroundPage) => {
|
|||
operation((err) => {
|
||||
if (err) {
|
||||
showError(err);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
setStatusTo(afterStatus);
|
||||
onSuccess && onSuccess();
|
||||
}
|
||||
enableDisableInputs();
|
||||
})
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
|
@ -132,13 +137,24 @@ chrome.runtime.getBackgroundPage( (backgroundPage) => {
|
|||
const _firstChild = ul.firstChild;
|
||||
for( const providerKey of Object.keys(antiCensorRu.pacProviders).sort() ) {
|
||||
const li = document.createElement('li');
|
||||
li.innerHTML = `<input type="radio" name="pacProvider" id="${providerKey}"> <label for="${providerKey}">${providerKey}</label> <a href class="link-button checked-radio-panel">[обновить]</a>`;
|
||||
li.querySelector('.link-button').onclick = () => { conduct( 'Обновляем...', (cb) => antiCensorRu.syncWithPacProvider(cb), 'Обновлено.' ); return false; };
|
||||
li.innerHTML = `<input type="radio" name="pacProvider" id="${providerKey}">
|
||||
<label for="${providerKey}">${providerKey}</label>
|
||||
<a href class="link-button checked-radio-panel">[обновить]</a>`;
|
||||
li.querySelector('.link-button').onclick =
|
||||
() => {
|
||||
conduct(
|
||||
'Обновляем...', (cb) => antiCensorRu.syncWithPacProvider(cb),
|
||||
'Обновлено.'
|
||||
);
|
||||
return false;
|
||||
};
|
||||
ul.insertBefore( li, _firstChild );
|
||||
}
|
||||
checkChosenProvider();
|
||||
|
||||
const radios = [].slice.apply( document.querySelectorAll('[name=pacProvider]') );
|
||||
const radios = [].slice.apply(
|
||||
document.querySelectorAll('[name=pacProvider]')
|
||||
);
|
||||
for(const radio of radios) {
|
||||
radio.onclick = function(event) {
|
||||
|
||||
|
@ -153,8 +169,7 @@ chrome.runtime.getBackgroundPage( (backgroundPage) => {
|
|||
'Отключено.',
|
||||
checkChosenProvider
|
||||
);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
conduct(
|
||||
'Установка...',
|
||||
(cb) => antiCensorRu.installPac(pacKey, cb),
|
||||
|
|
|
@ -13,9 +13,9 @@ const updateLinks = () => {
|
|||
for (let i = 0; i < links.length; i++) {
|
||||
const ln = links[i];
|
||||
const location = ln.href;
|
||||
ln.onclick = function () {
|
||||
ln.onclick = function() {
|
||||
|
||||
chrome.tabs.create({ active: !this.dataset.inBg, url: location });
|
||||
chrome.tabs.create({active: !this.dataset.inBg, url: location});
|
||||
return false;
|
||||
|
||||
};
|
||||
|
@ -24,6 +24,11 @@ const updateLinks = () => {
|
|||
};
|
||||
|
||||
new MutationObserver( updateLinks )
|
||||
.observe(target, { attributes: false, subtree: true, childList: true, characterData: false });
|
||||
.observe(target, {
|
||||
attributes: false,
|
||||
subtree: true,
|
||||
childList: true,
|
||||
characterData: false,
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', updateLinks);
|
||||
|
|
|
@ -4,13 +4,15 @@ const setStatusTo = (msg) => document.getElementById('status').innerHTML = msg;
|
|||
|
||||
const red = (text) => '<span style="color: red">' + text + '</span>';
|
||||
|
||||
const editor = ace.edit('editor');
|
||||
const editor = window.ace.edit('editor');
|
||||
editor.getSession().setOptions({
|
||||
mode: "ace/mode/javascript",
|
||||
useSoftTabs: true
|
||||
mode: 'ace/mode/javascript',
|
||||
useSoftTabs: true,
|
||||
});
|
||||
|
||||
chrome.proxy.settings.onChange.addListener( (details) => setStatusTo(red( details.levelOfControl + '!') ) );
|
||||
chrome.proxy.settings.onChange.addListener(
|
||||
(details) => setStatusTo(red( details.levelOfControl + '!') )
|
||||
);
|
||||
|
||||
document.querySelector('#read-button').onclick = () => {
|
||||
|
||||
|
@ -36,8 +38,8 @@ document.querySelector('#save-button').onclick = () => {
|
|||
mode: 'pac_script',
|
||||
pacScript: {
|
||||
mandatory: false,
|
||||
data: editor.getValue()
|
||||
}
|
||||
data: editor.getValue(),
|
||||
},
|
||||
};
|
||||
chrome.proxy.settings.set( {value: config}, () => alert('Saved!') );
|
||||
|
||||
|
|
21
extensions/chromium/minimalistic-pac-setter/package.json
Normal file
21
extensions/chromium/minimalistic-pac-setter/package.json
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name": "russian-censorship-bypass",
|
||||
"version": "0.0.15",
|
||||
"description": "Development tools for chromium extension",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"lint": "./node_modules/.bin/eslint ./extension/**/*.js --ignore-pattern vendor"
|
||||
},
|
||||
"author": "Ilya Ig. Petrov",
|
||||
"license": "GPLv3",
|
||||
"devDependencies": {
|
||||
"eslint": "^3.11.1",
|
||||
"eslint-config-airbnb": "^13.0.0",
|
||||
"eslint-config-google": "^0.7.1",
|
||||
"eslint-plugin-hapi": "^4.0.0",
|
||||
"eslint-plugin-import": "^2.2.0",
|
||||
"eslint-plugin-jsx-a11y": "^2.2.3",
|
||||
"eslint-plugin-react": "^6.7.1"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user