mirror of
https://github.com/anticensority/runet-censorship-bypass.git
synced 2024-11-24 02:13:43 +03:00
Lint as airbnb, refactor chrome.storage for localStorage
This commit is contained in:
parent
a606d25227
commit
79f51186c7
|
@ -1,5 +1,5 @@
|
|||
module.exports = {
|
||||
extends: ['eslint:recommended', 'google'],
|
||||
extends: ['eslint:recommended', 'airbnb'],
|
||||
env: {
|
||||
browser: true,
|
||||
webextensions: true,
|
||||
|
@ -20,14 +20,23 @@ module.exports = {
|
|||
'no-console': 'off',
|
||||
'padded-blocks': 'off',
|
||||
'require-jsdoc': 'off',
|
||||
|
||||
// Taken from airbnb:
|
||||
'no-multi-assign': 'off',
|
||||
'arrow-parens': ['error', 'always'],
|
||||
'no-plusplus': 'off',
|
||||
'comma-dangle': ['error', {
|
||||
arrays: 'always-multiline',
|
||||
objects: 'always-multiline',
|
||||
imports: 'always-multiline',
|
||||
exports: 'always-multiline',
|
||||
functions: 'ignore',
|
||||
}],
|
||||
/* Taken from airbnb:
|
||||
'max-len': ['error', 100, 2, {
|
||||
ignoreUrls: true,
|
||||
ignoreComments: false,
|
||||
ignoreRegExpLiterals: true,
|
||||
ignoreStrings: true,
|
||||
ignoreTemplateLiterals: true,
|
||||
}],
|
||||
}],*/
|
||||
},
|
||||
};
|
||||
|
|
|
@ -8,8 +8,11 @@
|
|||
"author": "Ilya Ig. Petrov",
|
||||
"license": "GPLv3",
|
||||
"devDependencies": {
|
||||
"eslint": "^3.15.0",
|
||||
"eslint-config-google": "^0.7.1"
|
||||
"eslint": "^3.16.1",
|
||||
"eslint-config-airbnb": "^14.1.0",
|
||||
"eslint-plugin-import": "^2.2.0",
|
||||
"eslint-plugin-jsx-a11y": "^4.0.0",
|
||||
"eslint-plugin-react": "^6.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"del": "^2.2.2",
|
||||
|
|
18
extensions/chromium/runet-censorship-bypass/problems.txt
Normal file
18
extensions/chromium/runet-censorship-bypass/problems.txt
Normal file
|
@ -0,0 +1,18 @@
|
|||
|
||||
/mnt/d/__Storage__/Workspace/repos/LATEST/extensions/chromium/runet-censorship-bypass/src/extension-full/20-ip-to-host-api.js
|
||||
19:9 error Unexpected dangling '_' in '_match' no-underscore-dangle
|
||||
23:35 error Expected property shorthand object-shorthand
|
||||
27:9 error Unexpected dangling '_' in '_test' no-underscore-dangle
|
||||
53:9 error Unexpected dangling '_' in '_state' no-underscore-dangle
|
||||
58:9 error Unexpected dangling '_' in '_createHostObj' no-underscore-dangle
|
||||
64:9 error Unexpected dangling '_' in '_getHostObj' no-underscore-dangle
|
||||
73:11 error Unexpected dangling '_' in '_antizapret' no-underscore-dangle
|
||||
174:9 error Unexpected dangling '_' in '_canonize' no-underscore-dangle
|
||||
232:11 error Unexpected dangling '_' in '_purgeOldIpsForSync' no-underscore-dangle
|
||||
252:24 error Unexpected dangling '_' in '_addAsync' no-underscore-dangle
|
||||
300:7 error Unexpected dangling '_' in '_updateAllAsync' no-underscore-dangle
|
||||
308:7 error Unexpected dangling '_' in '_updateAllAsync' no-underscore-dangle
|
||||
330:7 error Unexpected dangling '_' in '_replaceAllAsync' no-underscore-dangle
|
||||
|
||||
✖ 13 problems (13 errors, 0 warnings)
|
||||
|
|
@ -8,11 +8,11 @@
|
|||
// I believe logging objects precludes them from being GCed.
|
||||
// I also don't remove logs for sake of client-side troubleshooting
|
||||
// (though no one sent me logs so far).
|
||||
['log', 'warn', 'error'].forEach( (meth) => {
|
||||
const _meth = window.console[meth].bind(console);
|
||||
window.console[meth] = function(...args) {
|
||||
['log', 'warn', 'error'].forEach((meth) => {
|
||||
const originalMeth = window.console[meth].bind(console);
|
||||
window.console[meth] = function wrappedForDebug(...args) {
|
||||
|
||||
_meth(...args.map((a) => '' + a));
|
||||
originalMeth(...args.map((a) => `${a}`/* toString, but safer */));
|
||||
|
||||
};
|
||||
});
|
||||
|
@ -33,7 +33,7 @@
|
|||
|
||||
throwIfError(err) {
|
||||
|
||||
if(err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@
|
|||
// method invokation.
|
||||
const err = chrome.runtime.lastError || chrome.extension.lastError;
|
||||
if (!err) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
console.warn('API returned error:', err);
|
||||
return new Error(err.message); // Add stack.
|
||||
|
@ -62,7 +62,7 @@
|
|||
chromified(cb = self.mandatory()) {
|
||||
|
||||
// Take error first callback and convert it to chrome API callback.
|
||||
return function(...args) {
|
||||
return function cbForChromeApi(...args) {
|
||||
|
||||
const err = self.checkChromeError();
|
||||
self.timeouted(cb)(err, ...args);
|
||||
|
@ -71,35 +71,42 @@
|
|||
|
||||
},
|
||||
|
||||
getProp(obj, path = self.mandatory()) {
|
||||
getProp(targetObj, path = self.mandatory()) {
|
||||
|
||||
const props = path.split('.');
|
||||
if (!props.length) {
|
||||
throw new TypeError('Property must be supplied.');
|
||||
}
|
||||
const lastProp = props.pop();
|
||||
for( const prop of props ) {
|
||||
if (!(prop in obj)) {
|
||||
return undefined;
|
||||
|
||||
const ifSupportsInOp = (obj) =>
|
||||
['object', 'function'].includes(typeof obj);
|
||||
|
||||
return props.reduce((currentObj, prop) => {
|
||||
|
||||
if (
|
||||
ifSupportsInOp(currentObj)
|
||||
&& prop in currentObj
|
||||
) {
|
||||
return currentObj[prop];
|
||||
}
|
||||
obj = obj[prop];
|
||||
}
|
||||
return obj[lastProp];
|
||||
return undefined;
|
||||
|
||||
}, targetObj);
|
||||
|
||||
},
|
||||
|
||||
assert(value) {
|
||||
|
||||
if(!value) {
|
||||
if (!value) {
|
||||
console.assert(value);
|
||||
throw new Error('Assert failed for:' + value);
|
||||
throw new Error(`Assert failed for:${value}`);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
addRequestResponder(requestType, responder) {
|
||||
|
||||
if( privates.requestToResponder[requestType] ) {
|
||||
if (privates.requestToResponder[requestType]) {
|
||||
throw new TypeError(`Request ${requestType} already has responder!`);
|
||||
}
|
||||
privates.requestToResponder[requestType] = responder;
|
||||
|
@ -109,9 +116,9 @@
|
|||
fireRequest(requestType, ...args) {
|
||||
|
||||
const cb = args.slice(-1)[0];
|
||||
self.assert(typeof(cb) === 'function');
|
||||
self.assert(typeof cb === 'function');
|
||||
const responder = privates.requestToResponder[requestType];
|
||||
if(responder) {
|
||||
if (responder) {
|
||||
responder(...args);
|
||||
} else {
|
||||
cb();
|
||||
|
@ -123,18 +130,18 @@
|
|||
|
||||
return function state(key, value) {
|
||||
|
||||
key = prefix + key;
|
||||
const prefixedKey = prefix + key;
|
||||
if (value === null) {
|
||||
return localStorage.removeItem(key);
|
||||
return localStorage.removeItem(prefixedKey);
|
||||
}
|
||||
if (value === undefined) {
|
||||
const item = localStorage.getItem(key);
|
||||
const item = localStorage.getItem(prefixedKey);
|
||||
return item && JSON.parse(item);
|
||||
}
|
||||
if (value instanceof Date) {
|
||||
throw new TypeError('Converting Date format to JSON is not supported.');
|
||||
}
|
||||
localStorage.setItem(key, JSON.stringify(value));
|
||||
return localStorage.setItem(prefixedKey, JSON.stringify(value));
|
||||
|
||||
};
|
||||
|
||||
|
@ -168,15 +175,15 @@
|
|||
|
||||
searchSettingsForUrl(niddle) {
|
||||
|
||||
return 'chrome://settings/search#' + (chrome.i18n.getMessage(niddle) || niddle);
|
||||
return `chrome://settings/search#${(chrome.i18n.getMessage(niddle) || niddle)}`;
|
||||
|
||||
},
|
||||
|
||||
whichExtensionHtml() {
|
||||
|
||||
return chrome.i18n.getMessage('noControl') +
|
||||
` <a href="${ this.searchSettingsForUrl('proxy') }">
|
||||
${ chrome.i18n.getMessage('which') }
|
||||
return `${chrome.i18n.getMessage('noControl')}
|
||||
<a href="${this.searchSettingsForUrl('proxy')}">
|
||||
${chrome.i18n.getMessage('which')}
|
||||
</a>`;
|
||||
|
||||
},
|
||||
|
|
|
@ -8,38 +8,36 @@
|
|||
const errorJsonReplacer = function errorJsonReplacer(key, value) {
|
||||
|
||||
// fooWindow.ErrorEvent !== barWindow.ErrorEvent
|
||||
if (!( value && value.constructor
|
||||
if (!(value && value.constructor
|
||||
&& ['Error', 'Event'].some(
|
||||
(suff) => value.constructor.name.endsWith(suff)
|
||||
)
|
||||
(suff) => value.constructor.name.endsWith(suff))
|
||||
)) {
|
||||
return value;
|
||||
}
|
||||
const alt = {};
|
||||
|
||||
Object.getOwnPropertyNames(value).forEach(function(key) {
|
||||
const alt = Object.getOwnPropertyNames(value).reduce(
|
||||
(acc, ownProp) =>
|
||||
Object.assign(acc, { [ownProp]: value[ownProp] }),
|
||||
{}
|
||||
);
|
||||
|
||||
alt[key] = value[key];
|
||||
|
||||
}, value);
|
||||
|
||||
for(const prop in value) {
|
||||
for (const prop in value) { // eslint-disable-line no-restricted-syntax
|
||||
if (/^[A-Z]/.test(prop)) {
|
||||
// MOUSEMOVE, CLICK, KEYUP, NONE, etc.
|
||||
continue;
|
||||
continue; // eslint-disable-line no-continue
|
||||
}
|
||||
alt[prop] = value[prop];
|
||||
}
|
||||
|
||||
if (value.constructor.name === 'ErrorEvent') {
|
||||
for(const circularProp of
|
||||
[ // First line are circular props.
|
||||
'target', 'srcElement', 'path', 'currentTarget',
|
||||
'bubbles', 'cancelBubble', 'cancelable', 'composed',
|
||||
'defaultPrevented', 'eventPhase', 'isTrusted', 'returnValue',
|
||||
'timeStamp']) {
|
||||
[
|
||||
'target', 'srcElement', 'path', 'currentTarget',
|
||||
'bubbles', 'cancelBubble', 'cancelable', 'composed',
|
||||
'defaultPrevented', 'eventPhase', 'isTrusted', 'returnValue',
|
||||
'timeStamp',
|
||||
].forEach((circularProp) => {
|
||||
delete alt[circularProp];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (value.name) {
|
||||
|
@ -53,8 +51,8 @@
|
|||
const openAndFocus = function openAndFocus(url) {
|
||||
|
||||
chrome.tabs.create(
|
||||
{url: url},
|
||||
(tab) => chrome.windows.update(tab.windowId, {focused: true})
|
||||
{ url },
|
||||
(tab) => chrome.windows.update(tab.windowId, { focused: true })
|
||||
);
|
||||
|
||||
};
|
||||
|
@ -69,13 +67,11 @@
|
|||
|
||||
viewError(type = window.utils.mandatory(), err) {
|
||||
|
||||
const errors = err ? {[type]: err} : this.idToError;
|
||||
const errors = err ? { [type]: err } : this.idToError;
|
||||
const json = JSON.stringify(errors, errorJsonReplacer, 0);
|
||||
|
||||
openAndFocus(
|
||||
'http://rebrand.ly/ac-error/?json=' + encodeURIComponent(json) +
|
||||
(type ? '&type=' + encodeURIComponent(type) : '') +
|
||||
'&version=' + chrome.runtime.getManifest().version
|
||||
`http://rebrand.ly/ac-error/?json=${encodeURIComponent(json)}${type ? `&type=${encodeURIComponent(type)}` : ''}&version=${chrome.runtime.getManifest().version}`
|
||||
);
|
||||
|
||||
},
|
||||
|
@ -93,19 +89,18 @@
|
|||
switch(onOffStr, eventName) {
|
||||
|
||||
if (!['on', 'off'].includes(onOffStr)) {
|
||||
throw new TypeError('First argument bust be "on" or "off".');
|
||||
}
|
||||
for(
|
||||
const name of (eventName ? [eventName] : this.getEventsMap().keys() )
|
||||
) {
|
||||
this.state( ifPrefix + name, onOffStr === 'on' ? 'on' : null );
|
||||
throw new TypeError('First argument must be "on" or "off".');
|
||||
}
|
||||
(eventName ? [eventName] : this.getEventsMap().keys()).forEach(
|
||||
(name) =>
|
||||
this.state(ifPrefix + name, onOffStr === 'on' ? 'on' : null)
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
isOn(eventName) {
|
||||
|
||||
return this.state( ifPrefix + eventName );
|
||||
return this.state(ifPrefix + eventName);
|
||||
|
||||
},
|
||||
|
||||
|
@ -123,7 +118,7 @@
|
|||
}
|
||||
|
||||
if (this.ifControlled) {
|
||||
chrome.browserAction.setIcon( {path: './icons/default-128.png'} );
|
||||
chrome.browserAction.setIcon({ path: './icons/default-128.png' });
|
||||
} else {
|
||||
chrome.browserAction.setIcon({
|
||||
path: './icons/default-grayscale-128.png',
|
||||
|
@ -163,12 +158,12 @@
|
|||
id, title, errOrMessage,
|
||||
{
|
||||
icon = 'default-128.png',
|
||||
context = extName + ' ' + extVersion,
|
||||
context = `${extName} ${extVersion}`,
|
||||
ifSticky = true,
|
||||
} = {}
|
||||
) {
|
||||
|
||||
if ( !this.isOn(id) ) {
|
||||
if (!this.isOn(id)) {
|
||||
return;
|
||||
}
|
||||
this.idToError[id] = errOrMessage;
|
||||
|
@ -176,12 +171,12 @@
|
|||
chrome.notifications.create(
|
||||
id,
|
||||
{
|
||||
title: title,
|
||||
message: message,
|
||||
title,
|
||||
message,
|
||||
contextMessage: context,
|
||||
requireInteraction: ifSticky,
|
||||
type: 'basic',
|
||||
iconUrl: './icons/' + icon,
|
||||
iconUrl: `./icons/${icon}`,
|
||||
appIconMaskUrl: './icons/default-mask-128.png',
|
||||
isClickable: true,
|
||||
}
|
||||
|
@ -193,15 +188,16 @@
|
|||
|
||||
win.addEventListener('error', (errEvent) => {
|
||||
|
||||
console.warn(name + ':GLOBAL ERROR', errEvent);
|
||||
console.warn(`${name}:GLOBAL ERROR`, errEvent);
|
||||
this.mayNotify('ext-error', 'Ошибка расширения', errEvent,
|
||||
{icon: 'ext-error-128.png'});
|
||||
{ icon: 'ext-error-128.png' }
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
win.addEventListener('unhandledrejection', (event) => {
|
||||
|
||||
console.warn(name + ': Unhandled rejection. Throwing error.');
|
||||
console.warn(`${name}: Unhandled rejection. Throwing error.`);
|
||||
event.preventDefault();
|
||||
console.log('ev', event);
|
||||
throw event.reason;
|
||||
|
@ -225,24 +221,23 @@
|
|||
|
||||
chrome.proxy.settings.get(
|
||||
{},
|
||||
timeouted( handlers.isControllable.bind(handlers) )
|
||||
timeouted(handlers.isControllable.bind(handlers))
|
||||
);
|
||||
|
||||
chrome.notifications.onClicked.addListener( timeouted( (notId) => {
|
||||
chrome.notifications.onClicked.addListener(timeouted((notId) => {
|
||||
|
||||
chrome.notifications.clear(notId);
|
||||
if(notId === 'no-control') {
|
||||
if (notId === 'no-control') {
|
||||
return openAndFocus(
|
||||
window.utils.messages.searchSettingsForUrl('proxy')
|
||||
);
|
||||
window.utils.messages.searchSettingsForUrl('proxy'));
|
||||
}
|
||||
handlers.viewError(notId);
|
||||
return handlers.viewError(notId);
|
||||
|
||||
}));
|
||||
|
||||
handlers.installListenersOn(window, 'BG');
|
||||
|
||||
chrome.proxy.onProxyError.addListener( timeouted( (details) => {
|
||||
chrome.proxy.onProxyError.addListener(timeouted((details) => {
|
||||
|
||||
if (!handlers.ifControlled) {
|
||||
return;
|
||||
|
@ -256,26 +251,26 @@
|
|||
console.warn('PAC ERROR', details);
|
||||
// TOOD: add "view pac script at this line" button.
|
||||
handlers.mayNotify('pac-error', 'Ошибка PAC!',
|
||||
details.error + '\n' + details.details,
|
||||
{icon: 'pac-error-128.png'}
|
||||
`${details.error}\n${details.details}`,
|
||||
{ icon: 'pac-error-128.png' }
|
||||
);
|
||||
|
||||
}));
|
||||
|
||||
chrome.proxy.settings.onChange.addListener( timeouted( (details) => {
|
||||
chrome.proxy.settings.onChange.addListener(timeouted((details) => {
|
||||
|
||||
console.log('Proxy settings changed.', details);
|
||||
const noCon = 'no-control';
|
||||
const ifWasControllable = handlers.ifControllable;
|
||||
if ( !handlers.isControllable(details) && ifWasControllable ) {
|
||||
if (!handlers.isControllable(details) && ifWasControllable) {
|
||||
handlers.mayNotify(
|
||||
noCon,
|
||||
chrome.i18n.getMessage('noControl'),
|
||||
chrome.i18n.getMessage('which'),
|
||||
{icon: 'no-control-128.png', ifSticky: false}
|
||||
{ icon: 'no-control-128.png', ifSticky: false }
|
||||
);
|
||||
} else {
|
||||
chrome.notifications.clear( noCon );
|
||||
chrome.notifications.clear(noCon);
|
||||
}
|
||||
|
||||
}));
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
/*
|
||||
* Error Library
|
||||
* PURPOSE 1:
|
||||
|
@ -32,7 +33,7 @@
|
|||
|
||||
},
|
||||
|
||||
clarify: function(err, message = mandatory(), {data} = {}) {
|
||||
clarify(err, message = mandatory(), { data } = {}) {
|
||||
|
||||
if (!err) {
|
||||
return err;
|
||||
|
@ -46,9 +47,9 @@
|
|||
|
||||
},
|
||||
|
||||
clarifyThen: function(message, cb = mandatory()) {
|
||||
clarifyThen(message, cb = mandatory()) {
|
||||
|
||||
return (err, ...args) => cb( self.clarify(err, message), ...args );
|
||||
return (err, ...args) => cb(self.clarify(err, message), ...args);
|
||||
|
||||
},
|
||||
|
||||
|
|
|
@ -39,35 +39,31 @@
|
|||
get(url, cb = mandatory()) {
|
||||
|
||||
const start = Date.now();
|
||||
fetch(url, {cache: 'no-store'}).then(
|
||||
fetch(url, { cache: 'no-store' }).then(
|
||||
(res) => {
|
||||
|
||||
const textCb =
|
||||
(err) => {
|
||||
|
||||
console.log('Reading response as text...');
|
||||
res.text().then(
|
||||
(text) => {
|
||||
console.log('Calling CB...');
|
||||
cb(err, text);
|
||||
},
|
||||
(text) => cb(err, text),
|
||||
cb
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
const status = res.status;
|
||||
if ( !( status >= 200 && status < 300 || status === 304 ) ) {
|
||||
if (!((status >= 200 && status < 300) || status === 304)) {
|
||||
return textCb(
|
||||
errorsLib.clarify(
|
||||
res,
|
||||
'Получен ответ с неудачным HTTP-кодом ' + status + '.'
|
||||
`Получен ответ с неудачным HTTP-кодом ${status}.`
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
console.log('GETed with success:', url, Date.now() - start);
|
||||
textCb();
|
||||
return textCb();
|
||||
|
||||
},
|
||||
errorsLib.clarifyThen(checkCon, cb)
|
||||
|
|
|
@ -65,36 +65,10 @@
|
|||
|
||||
const getDefaults = function getDefaults() {
|
||||
|
||||
return Object.keys(configs).reduce((acc, key) => {
|
||||
|
||||
acc[key] = configs[key].dflt;
|
||||
return acc;
|
||||
|
||||
}, {});
|
||||
|
||||
};
|
||||
|
||||
const getCurrentConfigs = function getCurrentConfigs() {
|
||||
|
||||
const mods = kitchenState(modsKey);
|
||||
return new PacModifiers(mods || {});
|
||||
|
||||
};
|
||||
|
||||
const getOrderedConfigsForUser = function getOrderedConfigs() {
|
||||
|
||||
const pacMods = getCurrentConfigs();
|
||||
return Object.keys(configs).reduce((arr, key) => {
|
||||
|
||||
const conf = configs[key];
|
||||
if(typeof(conf.index) === 'number') {
|
||||
arr[conf.index] = conf;
|
||||
conf.value = pacMods[key];
|
||||
conf.key = key;
|
||||
}
|
||||
return arr;
|
||||
|
||||
}, []);
|
||||
return Object.keys(configs).reduce((acc, key) =>
|
||||
Object.assign(acc, { [key]: configs[key].dflt }),
|
||||
{}
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
|
@ -110,17 +84,17 @@
|
|||
);
|
||||
|
||||
Object.assign(this, defaults, mods);
|
||||
this.ifNoMods = ifAllDefaults ? true : false;
|
||||
this.ifNoMods = ifAllDefaults;
|
||||
|
||||
let customProxyArray = [];
|
||||
if (this.customProxyStringRaw) {
|
||||
customProxyArray = this.customProxyStringRaw
|
||||
.replace(/#.*$/mg, '') // Strip comments.
|
||||
.split( /(?:[^\S\r\n]*(?:;|\r?\n)+[^\S\r\n]*)+/g )
|
||||
.map( (p) => p.trim() )
|
||||
.filter( (p) => p && /\s+/g.test(p) );
|
||||
.split(/(?:[^\S\r\n]*(?:;|\r?\n)+[^\S\r\n]*)+/g)
|
||||
.map((p) => p.trim())
|
||||
.filter((p) => p && /\s+/g.test(p));
|
||||
if (this.ifUseSecureProxiesOnly) {
|
||||
customProxyArray = customProxyArray.filter( (p) => !p.startsWith('HTTP ') );
|
||||
customProxyArray = customProxyArray.filter((p) => !p.startsWith('HTTP '));
|
||||
}
|
||||
}
|
||||
if (this.ifUseLocalTor) {
|
||||
|
@ -142,13 +116,13 @@
|
|||
if (this.ifMindExceptions && this.exceptions) {
|
||||
this.included = [];
|
||||
this.excluded = [];
|
||||
for(const host of Object.keys(this.exceptions)) {
|
||||
Object.keys(this.exceptions).forEach((host) => {
|
||||
if (this.exceptions[host]) {
|
||||
this.included.push(host);
|
||||
} else {
|
||||
this.excluded.push(host);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (this.included && !this.filteredCustomsString) {
|
||||
throw new TypeError(
|
||||
'Проксировать свои сайты можно только через свои прокси. Нет ни одного своего прокси, удовлетворяющего вашим требованиям!'
|
||||
|
@ -160,6 +134,73 @@
|
|||
|
||||
}
|
||||
|
||||
const getCurrentConfigs = function getCurrentConfigs() {
|
||||
|
||||
const mods = kitchenState(modsKey);
|
||||
return new PacModifiers(mods || {});
|
||||
|
||||
};
|
||||
|
||||
const getOrderedConfigsForUser = function getOrderedConfigs() {
|
||||
|
||||
const pacMods = getCurrentConfigs();
|
||||
return Object.keys(configs).reduce((arr, key) => {
|
||||
|
||||
const conf = configs[key];
|
||||
if (typeof conf.index === 'number') {
|
||||
Object.assign(arr, { [conf.index]: conf });
|
||||
conf.value = pacMods[key];
|
||||
conf.key = key;
|
||||
}
|
||||
return arr;
|
||||
|
||||
}, []);
|
||||
|
||||
};
|
||||
|
||||
const privates = {};
|
||||
|
||||
privates.tryNowAsync = function tryNowAsync(maybeDetails, maybeCb = throwIfError) {
|
||||
|
||||
let cb;
|
||||
let detailsOrUndefined;
|
||||
if (typeof maybeDetails === 'function') {
|
||||
detailsOrUndefined = undefined;
|
||||
cb = maybeDetails;
|
||||
} else {
|
||||
detailsOrUndefined = maybeDetails;
|
||||
cb = maybeCb;
|
||||
}
|
||||
|
||||
new Promise((resolve) => (
|
||||
detailsOrUndefined
|
||||
? resolve(detailsOrUndefined)
|
||||
: chrome.proxy.settings.get({}, timeouted(resolve))
|
||||
)).then((details) => {
|
||||
|
||||
if (
|
||||
details.levelOfControl === 'controlled_by_this_extension'
|
||||
) {
|
||||
const pac = window.utils.getProp(details, 'value.pacScript');
|
||||
if (pac && pac.data) {
|
||||
// Delete old kitchen modifications.
|
||||
pac.data = pac.data.replace(
|
||||
new RegExp(`${kitchenStartsMark}[\\s\\S]*$`, 'g'),
|
||||
''
|
||||
);
|
||||
return chrome.proxy.settings.set(details, chromified(cb));
|
||||
}
|
||||
}
|
||||
|
||||
kitchenState(ifIncontinence, true);
|
||||
return cb(null, null, new TypeError(
|
||||
'Не найдено активного PAC-скрипта! Изменения будут применены при возвращении контроля настроек прокси или установке нового PAC-скрипта.'
|
||||
));
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
window.apis.pacKitchen = {
|
||||
|
||||
getPacMods: getCurrentConfigs,
|
||||
|
@ -167,13 +208,13 @@
|
|||
|
||||
cook(pacData, pacMods = mandatory()) {
|
||||
|
||||
return pacMods.ifNoMods ? pacData : pacData + `${ kitchenStartsMark }
|
||||
return pacMods.ifNoMods ? pacData : `${pacData}${kitchenStartsMark}
|
||||
;+function(global) {
|
||||
"use strict";
|
||||
|
||||
const originalFindProxyForURL = FindProxyForURL;
|
||||
global.FindProxyForURL = function(url, host) {
|
||||
${function() {
|
||||
${((function generateNewFindProxyForURL() {
|
||||
|
||||
let res = pacMods.ifProhibitDns ? `
|
||||
global.dnsResolve = function(host) { return null; };
|
||||
|
@ -203,42 +244,42 @@
|
|||
`;
|
||||
}
|
||||
|
||||
if(
|
||||
if (
|
||||
!pacMods.ifUseSecureProxiesOnly &&
|
||||
!pacMods.filteredCustomsString &&
|
||||
pacMods.ifUsePacScriptProxies
|
||||
) {
|
||||
return res + `
|
||||
return `${res}
|
||||
return originalFindProxyForURL(url, host);
|
||||
`;
|
||||
}
|
||||
|
||||
return res + `
|
||||
return `${res}
|
||||
const originalProxyString = originalFindProxyForURL(url, host);
|
||||
let originalProxyArray = originalProxyString.split(/(?:\\s*;\\s*)+/g).filter( (p) => p );
|
||||
if (originalProxyArray.every( (p) => /^DIRECT$/i.test(p) )) {
|
||||
// Directs only or null, no proxies.
|
||||
return originalProxyString;
|
||||
}
|
||||
return ` +
|
||||
function() {
|
||||
return ${
|
||||
((function getProxies() {
|
||||
|
||||
if (!pacMods.ifUsePacScriptProxies) {
|
||||
return '"' + pacMods.filteredCustomsString + '"';
|
||||
return `"${pacMods.filteredCustomsString}"`;
|
||||
}
|
||||
let filteredOriginalsExp = 'originalProxyString';
|
||||
if (pacMods.ifUseSecureProxiesOnly) {
|
||||
filteredOriginalsExp =
|
||||
'originalProxyArray.filter( (p) => !p.toUpperCase().startsWith("HTTP ") ).join("; ")';
|
||||
}
|
||||
if ( !pacMods.filteredCustomsString ) {
|
||||
if (!pacMods.filteredCustomsString) {
|
||||
return filteredOriginalsExp;
|
||||
}
|
||||
return '"' + pacMods.filteredCustomsString + '; " + ' + filteredOriginalsExp;
|
||||
return `"${pacMods.filteredCustomsString}; " + ${filteredOriginalsExp}`;
|
||||
|
||||
}() + ' + "; DIRECT";'; // Without DIRECT you will get 'PROXY CONN FAILED' pac-error.
|
||||
})())} + "; DIRECT";`; // Without DIRECT you will get 'PROXY CONN FAILED' pac-error.
|
||||
|
||||
}()}
|
||||
})())}
|
||||
|
||||
};
|
||||
|
||||
|
@ -246,68 +287,33 @@
|
|||
|
||||
},
|
||||
|
||||
_tryNowAsync(details, cb = throwIfError) {
|
||||
|
||||
if (typeof(details) === 'function') {
|
||||
cb = details;
|
||||
details = undefined;
|
||||
}
|
||||
|
||||
new Promise((resolve) =>
|
||||
|
||||
details
|
||||
? resolve(details)
|
||||
: chrome.proxy.settings.get({}, timeouted(resolve) )
|
||||
|
||||
).then( (details) => {
|
||||
|
||||
if (
|
||||
details.levelOfControl === 'controlled_by_this_extension'
|
||||
) {
|
||||
const pac = window.utils.getProp(details, 'value.pacScript');
|
||||
if (pac && pac.data) {
|
||||
// Delete old kitchen modifications.
|
||||
pac.data = pac.data.replace(
|
||||
new RegExp(kitchenStartsMark + '[\\s\\S]*$', 'g'),
|
||||
''
|
||||
);
|
||||
return chrome.proxy.settings.set(details, chromified(cb));
|
||||
}
|
||||
}
|
||||
|
||||
kitchenState(ifIncontinence, true);
|
||||
cb(null, null, new TypeError(
|
||||
'Не найдено активного PAC-скрипта! Изменения будут применены при возвращении контроля настроек прокси или установке нового PAC-скрипта.'
|
||||
));
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
checkIncontinence(details) {
|
||||
|
||||
if ( kitchenState(ifIncontinence) ) {
|
||||
this._tryNowAsync(details, () => {/* Swallow. */});
|
||||
if (kitchenState(ifIncontinence)) {
|
||||
privates.tryNowAsync(details, () => { /* Swallow. */ });
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
|
||||
keepCookedNowAsync(pacMods = mandatory(), cb = throwIfError) {
|
||||
keepCookedNowAsync(maybePacMods = mandatory(), maybeCb = throwIfError) {
|
||||
|
||||
if (typeof(pacMods) === 'function') {
|
||||
cb = pacMods;
|
||||
let pacMods;
|
||||
let cb;
|
||||
if (typeof maybePacMods === 'function') {
|
||||
cb = maybePacMods;
|
||||
pacMods = getCurrentConfigs();
|
||||
} else {
|
||||
try {
|
||||
pacMods = new PacModifiers(pacMods);
|
||||
} catch(e) {
|
||||
pacMods = new PacModifiers(maybePacMods);
|
||||
} catch (e) {
|
||||
return cb(e);
|
||||
}
|
||||
kitchenState(modsKey, pacMods);
|
||||
cb = maybeCb;
|
||||
}
|
||||
console.log('Keep cooked now...', pacMods);
|
||||
this._tryNowAsync(
|
||||
return privates.tryNowAsync(
|
||||
(err, res, ...warns) => {
|
||||
|
||||
console.log('Try now err:', err);
|
||||
|
@ -320,8 +326,12 @@
|
|||
return cb(null, res, ...warns);
|
||||
}
|
||||
|
||||
const hosts = par.map( (ps) => ps.split(/\s+/)[1] );
|
||||
window.utils.fireRequest('ip-to-host-replace-all', hosts, (err, res, ...moreWarns) => cb( err, res, ...warns.concat(moreWarns) ));
|
||||
const hosts = par.map((ps) => ps.split(/\s+/)[1]);
|
||||
return window.utils.fireRequest(
|
||||
'ip-to-host-replace-all',
|
||||
hosts,
|
||||
(ipErr, ipRes, ...ipWarns) => cb(ipErr, ipRes, ...warns.concat(ipWarns))
|
||||
);
|
||||
|
||||
}
|
||||
);
|
||||
|
@ -340,20 +350,20 @@
|
|||
|
||||
const pacKitchen = window.apis.pacKitchen;
|
||||
|
||||
const originalSet = chrome.proxy.settings.set.bind( chrome.proxy.settings );
|
||||
const originalSet = chrome.proxy.settings.set.bind(chrome.proxy.settings);
|
||||
|
||||
chrome.proxy.settings.set = function(details, cb) {
|
||||
chrome.proxy.settings.set = function modifiedSet(details, cb = () => {}) {
|
||||
|
||||
const pac = window.utils.getProp(details, 'value.pacScript');
|
||||
if (!(pac && pac.data)) {
|
||||
return originalSet(details, cb);
|
||||
}
|
||||
const pacMods = getCurrentConfigs();
|
||||
pac.data = pacKitchen.cook( pac.data, pacMods );
|
||||
originalSet({value: details.value}, (/* No args. */) => {
|
||||
pac.data = pacKitchen.cook(pac.data, pacMods);
|
||||
return originalSet({ value: details.value }, (/* No args. */) => {
|
||||
|
||||
kitchenState(ifIncontinence, null);
|
||||
cb && cb();
|
||||
cb();
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -35,11 +35,11 @@
|
|||
const asyncLogGroup = function asyncLogGroup(...args) {
|
||||
|
||||
const cb = args.pop();
|
||||
if(!(cb && typeof(cb) === 'function')) {
|
||||
throw new TypeError('cb must be a function, but got: ' + cb);
|
||||
if (!cb || typeof cb !== 'function') {
|
||||
throw new TypeError(`cb must be a function, but got: ${cb}`);
|
||||
}
|
||||
console.group(...args);
|
||||
return function(...cbArgs) {
|
||||
return function finishLogGroup(...cbArgs) {
|
||||
|
||||
console.groupEnd();
|
||||
console.log('Group finished.');
|
||||
|
@ -61,23 +61,23 @@
|
|||
},
|
||||
};
|
||||
console.log('Setting chrome proxy settings...');
|
||||
chrome.proxy.settings.set( {value: config}, chromified((err) => {
|
||||
chrome.proxy.settings.set({ value: config }, chromified((err) => {
|
||||
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
handlers.updateControlState( () => {
|
||||
return handlers.updateControlState(() => {
|
||||
|
||||
if ( !handlers.ifControlled ) {
|
||||
if (!handlers.ifControlled) {
|
||||
|
||||
console.warn('Failed, other extension is in control.');
|
||||
return cb(
|
||||
new Error( window.utils.messages.whichExtensionHtml() )
|
||||
new Error(window.utils.messages.whichExtensionHtml())
|
||||
);
|
||||
|
||||
}
|
||||
console.log('Successfuly set PAC in proxy settings..');
|
||||
cb();
|
||||
return cb();
|
||||
|
||||
});
|
||||
|
||||
|
@ -86,25 +86,25 @@
|
|||
};
|
||||
|
||||
const updatePacProxyIps = function updatePacProxyIps(
|
||||
cb = throwIfError
|
||||
originalCb = throwIfError
|
||||
) {
|
||||
|
||||
cb = asyncLogGroup(
|
||||
const cb = asyncLogGroup(
|
||||
'Getting IPs for PAC hosts...',
|
||||
cb
|
||||
originalCb
|
||||
);
|
||||
window.utils.fireRequest('ip-to-host-update-all', cb);
|
||||
|
||||
};
|
||||
|
||||
const setPacScriptFromProviderAsync = function setPacScriptFromProviderAsync(
|
||||
provider, lastModified = mandatory(), cb = throwIfError
|
||||
provider, lastModified = mandatory(), originalCb = throwIfError
|
||||
) {
|
||||
|
||||
const pacUrl = provider.pacUrls[0];
|
||||
cb = asyncLogGroup(
|
||||
const cb = asyncLogGroup(
|
||||
'Getting PAC script from provider...', pacUrl,
|
||||
cb
|
||||
originalCb
|
||||
);
|
||||
|
||||
httpLib.ifModifiedSince(pacUrl, lastModified, (err, newLastModified) => {
|
||||
|
@ -112,10 +112,9 @@
|
|||
if (!newLastModified) {
|
||||
return cb(
|
||||
null,
|
||||
{lastModified},
|
||||
{ lastModified },
|
||||
new Warning(
|
||||
'Ваш PAC-скрипт не нуждается в обновлении. Его дата: ' +
|
||||
lastModified
|
||||
`Ваш PAC-скрипт не нуждается в обновлении. Его дата: ${lastModified}.`
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -126,7 +125,7 @@
|
|||
() => new Promise(
|
||||
(resolve, reject) => httpLib.get(
|
||||
url,
|
||||
(newErr, pacData) => newErr ? reject(newErr) : resolve(pacData)
|
||||
(newErr, pacData) => (newErr ? reject(newErr) : resolve(pacData))
|
||||
)
|
||||
)
|
||||
),
|
||||
|
@ -139,29 +138,75 @@
|
|||
|
||||
setPacAsync(
|
||||
pacData,
|
||||
(err, res) => cb(
|
||||
err,
|
||||
Object.assign(res || {}, {lastModified: newLastModified})
|
||||
(pacErr, pacRes) => cb(
|
||||
pacErr,
|
||||
Object.assign(pacRes || {}, { lastModified: newLastModified })
|
||||
)
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
clarifyThen(
|
||||
'Не удалось скачать PAC-скрипт с адресов: [ '
|
||||
+ provider.pacUrls.join(' , ') + ' ].',
|
||||
`Не удалось скачать PAC-скрипт с адресов: [ ${provider.pacUrls.join(' , ')} ].`,
|
||||
cb
|
||||
)
|
||||
|
||||
);
|
||||
return undefined;
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
window.apis.antiCensorRu = {
|
||||
const currentVersion = chrome.runtime.getManifest().version;
|
||||
|
||||
version: chrome.runtime.getManifest().version,
|
||||
const privates = {
|
||||
|
||||
pacUpdatePeriodInMinutes: 12 * 60,
|
||||
periodicUpdateAlarmReason: 'Периодичное обновление PAC-скрипта',
|
||||
state: window.utils.createStorage('anti-censor-ru-'),
|
||||
|
||||
get version() {
|
||||
return this.state('version');
|
||||
},
|
||||
set version(newValue) {
|
||||
return this.state('version', newValue);
|
||||
},
|
||||
|
||||
get ifFirstInstall() {
|
||||
return this.version === null;
|
||||
},
|
||||
set ifFirstInstall(newValue) {
|
||||
if (newValue) {
|
||||
throw new TypeError('ifFirstInstall can\'t be set to true!');
|
||||
}
|
||||
this.version = currentVersion;
|
||||
},
|
||||
|
||||
get currentPacProviderKey() {
|
||||
return this.state('current-pac');
|
||||
},
|
||||
set currentPacProviderKey(newValue) {
|
||||
return this.state('current-pac', newValue);
|
||||
},
|
||||
|
||||
get lastPacUpdateStamp() {
|
||||
return this.state('last-pac-update-stamp') || 0;
|
||||
},
|
||||
set lastPacUpdateStamp(newValue) {
|
||||
return this.state('last-pac-update-stamp', newValue);
|
||||
},
|
||||
|
||||
get currentPacProviderLastModified() {
|
||||
return this.state('current-pac-last-mod') || 0;
|
||||
},
|
||||
set currentPacProviderLastModified(newValue) {
|
||||
return this.state('current-pac-last-mod', newValue);
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
window.apis.antiCensorRu = {
|
||||
|
||||
pacProviders: {
|
||||
Антизапрет: {
|
||||
|
@ -199,20 +244,24 @@
|
|||
},
|
||||
},
|
||||
|
||||
_currentPacProviderKey: 'Антизапрет',
|
||||
|
||||
/* Is it the first time extension installed?
|
||||
Do something, e.g. initiate PAC sync.
|
||||
*/
|
||||
ifFirstInstall: false,
|
||||
lastPacUpdateStamp: 0,
|
||||
get ifFirstInstall() {
|
||||
|
||||
_currentPacProviderLastModified: 0, // Not initialized.
|
||||
return privates.ifFirstInstall;
|
||||
|
||||
},
|
||||
get lastPacUpdateStamp() {
|
||||
|
||||
return privates.lastPacUpdateStamp;
|
||||
|
||||
},
|
||||
|
||||
getLastModifiedForKey(key = mandatory()) {
|
||||
|
||||
if (this._currentPacProviderKey === key) {
|
||||
return new Date(this._currentPacProviderLastModified).toUTCString();
|
||||
if (privates.currentPacProviderKey === key) {
|
||||
return new Date(privates.currentPacProviderLastModified).toUTCString();
|
||||
}
|
||||
return new Date(0).toUTCString();
|
||||
|
||||
|
@ -220,21 +269,21 @@
|
|||
|
||||
setLastModified(newValue = mandatory()) {
|
||||
|
||||
this._currentPacProviderLastModified = newValue;
|
||||
privates.currentPacProviderLastModified = newValue;
|
||||
|
||||
},
|
||||
|
||||
mustBeKey(key = mandatory()) {
|
||||
|
||||
if ( !(key === null || this.pacProviders[key]) ) {
|
||||
throw new TypeError('No provider for key:' + key);
|
||||
if (key !== null && !this.pacProviders[key]) {
|
||||
throw new TypeError(`No provider for key:${key}`);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
getCurrentPacProviderKey() {
|
||||
|
||||
return this._currentPacProviderKey;
|
||||
return privates.currentPacProviderKey;
|
||||
|
||||
},
|
||||
|
||||
|
@ -244,15 +293,17 @@
|
|||
) {
|
||||
|
||||
this.mustBeKey(newKey);
|
||||
this._currentPacProviderKey = newKey;
|
||||
this._currentPacProviderLastModified = lastModified;
|
||||
privates.currentPacProviderKey = newKey;
|
||||
privates.currentPacProviderLastModified = lastModified;
|
||||
|
||||
},
|
||||
|
||||
getPacProvider(key) {
|
||||
getPacProvider(maybeKey) {
|
||||
|
||||
if(key) {
|
||||
this.mustBeKey(key);
|
||||
let key;
|
||||
if (maybeKey) {
|
||||
this.mustBeKey(maybeKey);
|
||||
key = maybeKey;
|
||||
} else {
|
||||
key = this.getCurrentPacProviderKey();
|
||||
}
|
||||
|
@ -260,40 +311,18 @@
|
|||
|
||||
},
|
||||
|
||||
_periodicUpdateAlarmReason: 'Периодичное обновление PAC-скрипта',
|
||||
syncWithPacProviderAsync(maybeKey = this.currentPacProvierKey, maybeCb = throwIfError) {
|
||||
|
||||
pushToStorageAsync(cb = throwIfError) {
|
||||
|
||||
console.log('Pushing to storage...');
|
||||
|
||||
// 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'
|
||||
) {
|
||||
onlySettable[key] = this[key];
|
||||
}
|
||||
}
|
||||
|
||||
chrome.storage.local.clear(
|
||||
() => chrome.storage.local.set(
|
||||
onlySettable,
|
||||
chromified(cb)
|
||||
)
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
syncWithPacProviderAsync(
|
||||
key = this.currentPacProvierKey, cb = throwIfError) {
|
||||
|
||||
if( typeof(key) === 'function' ) {
|
||||
cb = key;
|
||||
let key;
|
||||
let originalCb;
|
||||
if (typeof maybeKey === 'function') {
|
||||
key = this.getCurrentPacProviderKey();
|
||||
originalCb = maybeKey;
|
||||
} else {
|
||||
key = maybeKey;
|
||||
originalCb = maybeCb;
|
||||
}
|
||||
cb = asyncLogGroup('Syncing with PAC provider ' + key + '...', cb);
|
||||
const cb = asyncLogGroup(`Syncing with PAC provider ${key}...`, originalCb);
|
||||
|
||||
if (key === null) {
|
||||
// No pac provider set.
|
||||
|
@ -303,15 +332,15 @@
|
|||
const pacProvider = this.getPacProvider(key);
|
||||
|
||||
const pacSetPromise = new Promise(
|
||||
(resolve, reject) => setPacScriptFromProviderAsync(
|
||||
(resolve) => setPacScriptFromProviderAsync(
|
||||
pacProvider,
|
||||
this.getLastModifiedForKey(key),
|
||||
(err, res, ...warns) => {
|
||||
|
||||
if (!err) {
|
||||
this.setCurrentPacProviderKey(key, res.lastModified);
|
||||
this.lastPacUpdateStamp = Date.now();
|
||||
this.ifFirstInstall = false;
|
||||
privates.lastPacUpdateStamp = Date.now();
|
||||
privates.ifFirstInstall = false;
|
||||
this.setAlarms();
|
||||
}
|
||||
|
||||
|
@ -322,7 +351,7 @@
|
|||
);
|
||||
|
||||
const ipsErrorPromise = new Promise(
|
||||
(resolve, reject) => updatePacProxyIps(
|
||||
(resolve) => updatePacProxyIps(
|
||||
resolve
|
||||
)
|
||||
);
|
||||
|
@ -337,27 +366,25 @@
|
|||
if (ipsErr) {
|
||||
warns.push(ipsErr);
|
||||
}
|
||||
this.pushToStorageAsync(
|
||||
(pushErr) => cb(pacErr || pushErr, null, ...warns)
|
||||
);
|
||||
return cb(pacErr, null, ...warns);
|
||||
|
||||
},
|
||||
cb
|
||||
);
|
||||
return undefined;
|
||||
|
||||
},
|
||||
|
||||
_pacUpdatePeriodInMinutes: 12*60,
|
||||
get pacUpdatePeriodInMinutes() {
|
||||
|
||||
return this._pacUpdatePeriodInMinutes;
|
||||
return privates.pacUpdatePeriodInMinutes;
|
||||
|
||||
},
|
||||
|
||||
setAlarms() {
|
||||
|
||||
let nextUpdateMoment = this.lastPacUpdateStamp
|
||||
+ this._pacUpdatePeriodInMinutes*60*1000;
|
||||
+ (privates.pacUpdatePeriodInMinutes * 60 * 1000);
|
||||
const now = Date.now();
|
||||
if (nextUpdateMoment < now) {
|
||||
nextUpdateMoment = now;
|
||||
|
@ -369,10 +396,10 @@
|
|||
);
|
||||
|
||||
chrome.alarms.create(
|
||||
this._periodicUpdateAlarmReason,
|
||||
privates.periodicUpdateAlarmReason,
|
||||
{
|
||||
when: nextUpdateMoment,
|
||||
periodInMinutes: this._pacUpdatePeriodInMinutes,
|
||||
periodInMinutes: privates.pacUpdatePeriodInMinutes,
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -390,14 +417,14 @@
|
|||
if (this.currentProviderKey !== key) {
|
||||
return this.syncWithPacProviderAsync(key, cb);
|
||||
}
|
||||
console.log(key + ' already installed.');
|
||||
cb();
|
||||
console.log(`${key} already installed.`);
|
||||
return cb();
|
||||
|
||||
},
|
||||
|
||||
clearPacAsync(cb = throwIfError) {
|
||||
clearPacAsync(originalCb = throwIfError) {
|
||||
|
||||
cb = asyncLogGroup('Cearing alarms and PAC...', cb);
|
||||
const cb = asyncLogGroup('Cearing alarms and PAC...', originalCb);
|
||||
chrome.alarms.clearAll(
|
||||
() => chrome.proxy.settings.clear(
|
||||
{},
|
||||
|
@ -407,9 +434,7 @@
|
|||
return cb(err);
|
||||
}
|
||||
this.setCurrentPacProviderKey(null);
|
||||
this.pushToStorageAsync(
|
||||
() => handlers.updateControlState(cb)
|
||||
);
|
||||
return handlers.updateControlState(cb);
|
||||
|
||||
})
|
||||
)
|
||||
|
@ -420,12 +445,7 @@
|
|||
};
|
||||
|
||||
// ON EACH LAUNCH, STARTUP, RELOAD, UPDATE, ENABLE
|
||||
chrome.storage.local.get(null, chromified( (err, oldStorage) => {
|
||||
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
((async function init() {
|
||||
/*
|
||||
Event handlers that ALWAYS work (even if installation is not done
|
||||
or failed).
|
||||
|
@ -435,14 +455,14 @@
|
|||
const antiCensorRu = window.apis.antiCensorRu;
|
||||
|
||||
chrome.alarms.onAlarm.addListener(
|
||||
timeouted( (alarm) => {
|
||||
timeouted((alarm) => {
|
||||
|
||||
if (alarm.name === antiCensorRu._periodicUpdateAlarmReason) {
|
||||
if (alarm.name === privates.periodicUpdateAlarmReason) {
|
||||
console.log(
|
||||
'Periodic PAC update triggered:',
|
||||
new Date().toLocaleString('ru-RU')
|
||||
);
|
||||
antiCensorRu.syncWithPacProviderAsync(() => {/* swallow */});
|
||||
antiCensorRu.syncWithPacProviderAsync(() => { /* swallow */ });
|
||||
}
|
||||
|
||||
})
|
||||
|
@ -456,24 +476,14 @@
|
|||
|
||||
});
|
||||
|
||||
console.log('Storage on init:', oldStorage);
|
||||
antiCensorRu.ifFirstInstall = Object.keys(oldStorage).length === 0;
|
||||
|
||||
if (antiCensorRu.ifFirstInstall) {
|
||||
// INSTALL
|
||||
console.log('Installing...');
|
||||
privates.currentPacProviderKey = 'Антизапрет';
|
||||
return chrome.runtime.openOptionsPage();
|
||||
}
|
||||
|
||||
// LAUNCH, RELOAD, UPDATE
|
||||
// Use old or migrate to default.
|
||||
antiCensorRu._currentPacProviderKey =
|
||||
oldStorage._currentPacProviderKey || null;
|
||||
antiCensorRu.lastPacUpdateStamp =
|
||||
oldStorage.lastPacUpdateStamp || antiCensorRu.lastPacUpdateStamp;
|
||||
antiCensorRu._currentPacProviderLastModified =
|
||||
oldStorage._currentPacProviderLastModified
|
||||
|| antiCensorRu._currentPacProviderLastModified;
|
||||
console.log(
|
||||
'Last PAC update was on',
|
||||
new Date(antiCensorRu.lastPacUpdateStamp).toLocaleString('ru-RU')
|
||||
|
@ -487,44 +497,48 @@
|
|||
2. We have to check storage for migration before using it.
|
||||
Better on each launch then on each pull.
|
||||
*/
|
||||
const ifUpdating = antiCensorRu.version !== oldStorage.version;
|
||||
const ifUpdating = currentVersion !== privates.version;
|
||||
|
||||
if (!ifUpdating) {
|
||||
|
||||
// LAUNCH, RELOAD, ENABLE
|
||||
antiCensorRu.pacProviders = oldStorage.pacProviders;
|
||||
console.log('Extension launched, reloaded or enabled.');
|
||||
|
||||
} else {
|
||||
|
||||
// UPDATE & MIGRATION
|
||||
const key = antiCensorRu._currentPacProviderKey;
|
||||
if (key !== null) {
|
||||
const ifVeryOld = !Object.keys(antiCensorRu.pacProviders).includes(key);
|
||||
const ifWasForced = localStorage.getItem('provider-backup');
|
||||
if ( ifVeryOld || !ifWasForced ) {
|
||||
if (!ifWasForced) {
|
||||
localStorage.setItem('provider-backup', antiCensorRu._currentPacProviderKey);
|
||||
// Use old or migrate to defaults.
|
||||
const oldStorage = await new Promise((resolve) =>
|
||||
chrome.storage.local.get(null, resolve)
|
||||
);
|
||||
if (Object.keys(oldStorage).length) {
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
let oldKey = oldStorage._currentPacProviderKey;
|
||||
if (oldKey) {
|
||||
const ifVeryOld = !Object.keys(antiCensorRu.pacProviders).includes(oldKey);
|
||||
const ifWasForced = localStorage.getItem('provider-backup');
|
||||
if (ifVeryOld || !ifWasForced) {
|
||||
if (!ifWasForced) {
|
||||
localStorage.setItem('provider-backup', oldKey);
|
||||
}
|
||||
oldKey = 'Антизапрет';
|
||||
}
|
||||
antiCensorRu._currentPacProviderKey = 'Антизапрет';
|
||||
}
|
||||
privates.currentPacProviderKey = oldKey || null;
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
privates.currentPacProviderLastModified = oldStorage._currentPacProviderLastModified || 0;
|
||||
privates.lastPacUpdateStamp = oldStorage.lastPacUpdateStamp || 0;
|
||||
await new Promise((resolve) => chrome.storage.local.clear(resolve));
|
||||
}
|
||||
privates.version = currentVersion;
|
||||
console.log('Extension updated.');
|
||||
|
||||
}
|
||||
|
||||
if (antiCensorRu.getPacProvider()) {
|
||||
|
||||
const ifAlarmTriggered = antiCensorRu.setAlarms();
|
||||
|
||||
if (ifAlarmTriggered) {
|
||||
return; // Already pushed.
|
||||
}
|
||||
|
||||
}
|
||||
if( ifUpdating ) {
|
||||
antiCensorRu.pushToStorageAsync();
|
||||
antiCensorRu.setAlarms();
|
||||
}
|
||||
return undefined;
|
||||
|
||||
/*
|
||||
History of Changes to Storage (Migration Guide)
|
||||
|
@ -540,7 +554,6 @@
|
|||
* Change storage.ifNotInstalled to storage.ifFirstInstall.
|
||||
* Add storage.lastPacUpdateStamp.
|
||||
**/
|
||||
|
||||
}));
|
||||
})());
|
||||
|
||||
}
|
||||
|
|
|
@ -12,13 +12,13 @@
|
|||
|
||||
chrome.runtime.onInstalled.addListener(
|
||||
() => chrome.contextMenus.create({
|
||||
id: id,
|
||||
title: title,
|
||||
id,
|
||||
title,
|
||||
contexts: ['browser_action'],
|
||||
}, timeouted(() => {
|
||||
|
||||
const err = chrome.runtime.lastError;
|
||||
if(err) {
|
||||
if (err) {
|
||||
console.warn('Context menu error:', err);
|
||||
throw err;
|
||||
}
|
||||
|
@ -28,9 +28,9 @@
|
|||
|
||||
chrome.contextMenus.onClicked.addListener((info, tab) => {
|
||||
|
||||
if(info.menuItemId === id) {
|
||||
Promise.resolve( tab2url( tab ) )
|
||||
.then( (url) => chrome.tabs.create({url: url}) );
|
||||
if (info.menuItemId === id) {
|
||||
Promise.resolve(tab2url(tab))
|
||||
.then((url) => chrome.tabs.create({ url }));
|
||||
}
|
||||
|
||||
});
|
||||
|
@ -45,32 +45,32 @@
|
|||
<input name='InstantCheckUrl' value='${new URL(tab.url).hostname}'
|
||||
type='hidden'>
|
||||
</form>
|
||||
<script>document.querySelector('.tracker-form').submit()<\/script>`
|
||||
<script>document.querySelector('.tracker-form').submit()</script>`
|
||||
);
|
||||
|
||||
createMenuLinkEntry(
|
||||
'Сайт в реестре блокировок?',
|
||||
(tab) => 'https://antizapret.info/index.php?search=' + new URL(tab.url).hostname
|
||||
(tab) => `https://antizapret.info/index.php?search=${new URL(tab.url).hostname}`
|
||||
);
|
||||
|
||||
createMenuLinkEntry(
|
||||
'Из архива archive.org',
|
||||
(tab) => 'https://web.archive.org/web/*/' + tab.url
|
||||
(tab) => `https://web.archive.org/web/*/${tab.url}`
|
||||
);
|
||||
|
||||
createMenuLinkEntry(
|
||||
'Через Google Translate',
|
||||
(tab) => 'https://translate.google.com/translate?hl=&sl=en&tl=ru&anno=2&sandbox=1&u=' + tab.url
|
||||
(tab) => `https://translate.google.com/translate?hl=&sl=en&tl=ru&anno=2&sandbox=1&u=${tab.url}`
|
||||
);
|
||||
|
||||
createMenuLinkEntry(
|
||||
'Другие варианты разблокировки',
|
||||
(tab) => 'https://rebrand.ly/ac-unblock#' + tab.url
|
||||
(tab) => `https://rebrand.ly/ac-unblock#${tab.url}`
|
||||
);
|
||||
|
||||
createMenuLinkEntry(
|
||||
'У меня проблемы с расширением!',
|
||||
(tab) => 'https://rebrand.ly/ac-support'
|
||||
() => 'https://rebrand.ly/ac-support'
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
@ -9,100 +9,42 @@
|
|||
// IP REGEX starts.
|
||||
|
||||
const portOpt = '(:\\d+)?'; // The only capturing group, sic!
|
||||
const ipv4portOpt = '(?:[0-9]{1,3}\\.){3}[0-9]{1,3}' + portOpt;
|
||||
const ipv4portOpt = `(?:[0-9]{1,3}\\.){3}[0-9]{1,3}${portOpt}`;
|
||||
const ipv6nake = '(?:[0-9a-f]{0,4}:){2,7}[0-9a-f]{0,4}';
|
||||
const ipv6portOpt = '(?:' + ipv6nake + '|' + '\\[' + ipv6nake + '\\]' + portOpt + ')';
|
||||
const ipv6portOpt = `(?:${ipv6nake}|\\[${ipv6nake}\\]${portOpt})`;
|
||||
|
||||
const ipv4Re = new RegExp('^' + ipv4portOpt + '$');
|
||||
const ipv6Re = new RegExp('^' + ipv6portOpt + '$');
|
||||
const ipv4Re = new RegExp(`^${ipv4portOpt}$`);
|
||||
const ipv6Re = new RegExp(`^${ipv6portOpt}$`);
|
||||
|
||||
const _match = function _match(ipRe, str) {
|
||||
const reMatchIp = function reMatchIp(ipRe, str) {
|
||||
|
||||
const m = (str.match(ipRe) || []).filter( (c) => c );
|
||||
const m = (str.match(ipRe) || []).filter((c) => c);
|
||||
const port = m.length > 1 ? m.pop() : false;
|
||||
return {ifMatched: m.length, port: port};
|
||||
return { ifMatched: m.length, port };
|
||||
|
||||
};
|
||||
|
||||
const _test = {
|
||||
const matchIpv4v6 = function matchIpv4v6(str) {
|
||||
|
||||
ipv4: _match.bind(null, ipv4Re),
|
||||
ipv6: _match.bind(null, ipv6Re),
|
||||
ipv4v6: function(str) {
|
||||
|
||||
let mr = this.ipv4(str);
|
||||
if (mr.ifMatched) {
|
||||
mr.ifv4 = true;
|
||||
mr.canonical = str.replace(mr.port, '');
|
||||
return mr;
|
||||
}
|
||||
mr = this.ipv6(str);
|
||||
if (mr.ifMatched) {
|
||||
mr.ifv6 = true;
|
||||
mr.canonical = str.replace(mr.port, '').replace(/[\[\]]/g, '');
|
||||
return mr;
|
||||
}
|
||||
let mr = reMatchIp(ipv4Re, str);
|
||||
if (mr.ifMatched) {
|
||||
mr.ifv4 = true;
|
||||
mr.canonical = str.replace(mr.port, '');
|
||||
return mr;
|
||||
|
||||
},
|
||||
}
|
||||
mr = reMatchIp(ipv6Re, str);
|
||||
if (mr.ifMatched) {
|
||||
mr.ifv6 = true;
|
||||
mr.canonical = str.replace(mr.port, '').replace(/[[\]]/g, '');
|
||||
return mr;
|
||||
}
|
||||
return mr;
|
||||
|
||||
};
|
||||
|
||||
// IP REGEX ends.
|
||||
|
||||
const _state = window.utils.createStorage('ip-to-host');
|
||||
const ip2host = '';
|
||||
|
||||
const privates = {};
|
||||
|
||||
const _createHostObj = function _addHostObj(hostStr) {
|
||||
|
||||
return (privates._strToHostObj[hostStr] = {host: hostStr});
|
||||
|
||||
};
|
||||
|
||||
const _getHostObj = function _getHostObj(hostStr) {
|
||||
|
||||
return privates._strToHostObj[hostStr] || _createHostObj(hostStr);
|
||||
|
||||
};
|
||||
|
||||
const reinit = function reinit() {
|
||||
|
||||
// Defaults.
|
||||
const _antizapret = {
|
||||
/* Don't use directly, please.
|
||||
Encoded to counter abuse. */
|
||||
host: '\x70\x72\x6f\x78\x79\x2e\x61\x6e\x74\x69\x7a\x61\x70\x72\x65\x74\x2e\x70\x72\x6f\x73\x74\x6f\x76\x70\x6e\x2e\x6f\x72\x67',
|
||||
};
|
||||
privates._strToHostObj = {
|
||||
[_antizapret.host]: _antizapret,
|
||||
};
|
||||
|
||||
privates._ipToHostObj = {};
|
||||
for( const ip of [
|
||||
// IPs of Antizapret.
|
||||
'195.123.209.38',
|
||||
'137.74.171.91',
|
||||
'51.15.39.201',
|
||||
'2001:bc8:4700:2300::1:d07',
|
||||
'2a02:27ac::10',
|
||||
] ) {
|
||||
privates._ipToHostObj[ip] = _antizapret;
|
||||
}
|
||||
|
||||
// Persisted.
|
||||
const ipToHost = _state(ip2host);
|
||||
if (ipToHost) {
|
||||
for( const ip of Object.keys(ipToHost) ) {
|
||||
const host = ipToHost[ip];
|
||||
privates._ipToHostObj[ip] = _getHostObj(host);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
reinit();
|
||||
// GET IPS starts.
|
||||
|
||||
const getIpsFor = function getIpsFor(host, cb = mandatory()) {
|
||||
|
||||
|
@ -113,29 +55,32 @@
|
|||
const promises = types.map(
|
||||
(type) => new Promise((resolve) =>
|
||||
httpLib.get(
|
||||
'https://dns.google.com/resolve?type=' + type + '&name=' + host,
|
||||
(err, res) => {
|
||||
`https://dns.google.com/resolve?type=${type}&name=${host}`,
|
||||
(httpErr, httpRes) => {
|
||||
|
||||
if (res) {
|
||||
let res = httpRes;
|
||||
let err = httpErr;
|
||||
if (httpRes) {
|
||||
let jsonRes = {};
|
||||
try {
|
||||
res = JSON.parse(res);
|
||||
console.log('JSON parsed.');
|
||||
if (err || res.Status) {
|
||||
jsonRes = JSON.parse(httpRes);
|
||||
res = jsonRes;
|
||||
if (httpErr || jsonRes.Status) {
|
||||
const msg = ['Answer', 'Comment', 'Status']
|
||||
.filter( (prop) => res[prop] )
|
||||
.map( (prop) => prop + ': ' + JSON.stringify( res[prop] ) )
|
||||
.filter((prop) => jsonRes[prop])
|
||||
.map((prop) => `${prop}: ${JSON.stringify(jsonRes[prop])}`)
|
||||
.join(', \n');
|
||||
err = clarify(err || {}, 'Сервер (json): ' + msg, {data: res});
|
||||
err = clarify(httpErr || {}, `Сервер (json): ${msg}`, { data: jsonRes });
|
||||
} else {
|
||||
res = res.Answer || [];
|
||||
res = res.filter(
|
||||
res = (jsonRes.Answer || []).filter(
|
||||
(record) => types.includes(record.type)
|
||||
).map( (ans) => ans.data );
|
||||
).map((ans) => ans.data);
|
||||
}
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
err = clarify(
|
||||
e,
|
||||
'Сервер (текст): ' + res, err ? {data: err} : undefined
|
||||
`Сервер (текст): ${res}`,
|
||||
httpErr ? { data: httpErr } : undefined
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -148,7 +93,7 @@
|
|||
Promise.all(promises).then(
|
||||
([[v4err, v4res], [v6err, v6res]]) => {
|
||||
|
||||
if(v4err) {
|
||||
if (v4err) {
|
||||
return cb(v4err, v4res);
|
||||
}
|
||||
const ips = v4res;
|
||||
|
@ -158,77 +103,101 @@
|
|||
} else {
|
||||
warns = [v6err];
|
||||
}
|
||||
cb(null, ips, ...warns);
|
||||
return cb(null, ips, ...warns);
|
||||
|
||||
}
|
||||
);
|
||||
return undefined;
|
||||
|
||||
};
|
||||
|
||||
const _canonize = function canonize(addrArr) {
|
||||
// GET IPS ends.
|
||||
|
||||
const ipSet = new Set();
|
||||
const hostSet = new Set();
|
||||
const ipToHostKey = '';
|
||||
const privates = {
|
||||
|
||||
for( const addr of addrArr ) {
|
||||
state: window.utils.createStorage('ip-to-host'),
|
||||
|
||||
const ipm = _test.ipv4v6(addr);
|
||||
if (ipm.ifMatched) {
|
||||
ipSet.add( ipm.canonical );
|
||||
} else {
|
||||
hostSet.add( addr.replace(/:\d+$/, '') );
|
||||
}
|
||||
createHostObj(hostStr) {
|
||||
|
||||
}
|
||||
|
||||
console.log('Canonized hosts/ips:', hostSet.size + '/' + ipSet.size);
|
||||
return [ipSet, hostSet];
|
||||
|
||||
};
|
||||
|
||||
const self = window.apis.ipToHost = {
|
||||
|
||||
persistData() {
|
||||
|
||||
console.log('Persisting ipToHost...', privates);
|
||||
const ipToHost = {};
|
||||
for( const ip of Object.keys(privates._ipToHostObj) ) {
|
||||
ipToHost[ip] = privates._ipToHostObj[ip].host;
|
||||
}
|
||||
_state(ip2host, ipToHost);
|
||||
return (this.strToHostObj[hostStr] = { host: hostStr });
|
||||
|
||||
},
|
||||
|
||||
getHostObj(hostStr) {
|
||||
|
||||
return this.strToHostObj[hostStr] || this.createHostObj(hostStr);
|
||||
|
||||
},
|
||||
|
||||
reinit() {
|
||||
|
||||
// Defaults.
|
||||
const antizapret = {
|
||||
/* Don't use directly, please.
|
||||
Encoded to counter abuse. */
|
||||
host: '\x70\x72\x6f\x78\x79\x2e\x61\x6e\x74\x69\x7a\x61\x70\x72\x65\x74\x2e\x70\x72\x6f\x73\x74\x6f\x76\x70\x6e\x2e\x6f\x72\x67',
|
||||
};
|
||||
this.strToHostObj = {
|
||||
[antizapret.host]: antizapret,
|
||||
};
|
||||
|
||||
this.ipToHostObj = {};
|
||||
[ // IPs of Antizapret.
|
||||
'195.123.209.38',
|
||||
'137.74.171.91',
|
||||
'51.15.39.201',
|
||||
'2001:bc8:4700:2300::1:d07',
|
||||
'2a02:27ac::10',
|
||||
].forEach((ip) => {
|
||||
this.ipToHostObj[ip] = antizapret;
|
||||
});
|
||||
|
||||
// Persisted.
|
||||
const ipToHost = this.state(ipToHostKey);
|
||||
if (ipToHost) {
|
||||
Object.keys(ipToHost).forEach((ip) => {
|
||||
|
||||
const host = ipToHost[ip];
|
||||
this.ipToHostObj[ip] = this.getHostObj(host);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
// POST INIT
|
||||
|
||||
resetToDefaults() {
|
||||
|
||||
_state(ip2host, null);
|
||||
reinit();
|
||||
this.state(ipToHostKey, null);
|
||||
this.reinit();
|
||||
|
||||
},
|
||||
|
||||
_purgeOldIpsForSync(hostStr) {
|
||||
purgeOldIpsForSync(hostStr) {
|
||||
|
||||
console.log('Purging old IPs for', hostStr);
|
||||
for(const ip of Object.keys(privates._ipToHostObj)) {
|
||||
if (hostStr === privates._ipToHostObj[ip].host) {
|
||||
delete privates._ipToHostObj[ip];
|
||||
Object.keys(privates.ipToHostObj).forEach((ip) => {
|
||||
if (hostStr === this.ipToHostObj[ip].host) {
|
||||
delete this.ipToHostObj[ip];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
_addAsync(hostStr, cb = mandatory()) {
|
||||
addAsync(hostStr, cb = mandatory()) {
|
||||
|
||||
getIpsFor(hostStr, (err, ips, ...warns) => {
|
||||
|
||||
console.log('Got IPs + err?:', ips, err);
|
||||
if (!err) {
|
||||
this._purgeOldIpsForSync(hostStr);
|
||||
this.purgeOldIpsForSync(hostStr);
|
||||
// Object may be shared, string can't.
|
||||
const hostObj = _getHostObj(hostStr);
|
||||
for(const ip of ips) {
|
||||
privates._ipToHostObj[ip] = hostObj;
|
||||
}
|
||||
const hostObj = privates.getHostObj(hostStr);
|
||||
ips.forEach((ip) => {
|
||||
privates.ipToHostObj[ip] = hostObj;
|
||||
});
|
||||
}
|
||||
return cb(err, null, ...warns);
|
||||
|
||||
|
@ -236,22 +205,22 @@
|
|||
|
||||
},
|
||||
|
||||
_updateAllAsync(cb = mandatory()) {
|
||||
updateAllAsync(cb = mandatory()) {
|
||||
|
||||
const hostArr = Object.keys(privates._strToHostObj);
|
||||
const hostArr = Object.keys(this.strToHostObj);
|
||||
console.log('Update all:', hostArr);
|
||||
|
||||
const promises = hostArr.map(
|
||||
(hostStr) => new Promise(
|
||||
(resolve) => this._addAsync(
|
||||
(resolve) => this.addAsync(
|
||||
hostStr,
|
||||
(...args) => resolve(args)
|
||||
)
|
||||
)
|
||||
);
|
||||
Promise.all( promises ).then( (cbsRes) => {
|
||||
Promise.all(promises).then((cbsRes) => {
|
||||
|
||||
const errors = cbsRes.map( ([err]) => err ).filter( (err) => err );
|
||||
const errors = cbsRes.map(([err]) => err).filter((err) => err);
|
||||
let newError;
|
||||
const ifAllErrors = cbsRes.length === errors.length;
|
||||
if (errors.length) {
|
||||
|
@ -270,25 +239,71 @@
|
|||
return cb(newError);
|
||||
}
|
||||
}
|
||||
cb(null, null, newError);
|
||||
return cb(null, null, newError);
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
_replaceAllAsync(hostArr = mandatory(), cb) {
|
||||
replaceAllAsync(maybeHostArr = mandatory(), maybeCb) {
|
||||
|
||||
if (typeof(hostArr) === 'function') {
|
||||
cb = hostArr;
|
||||
hostArr = Object.keys(privates._strToHostObj);
|
||||
let hostArr;
|
||||
let cb;
|
||||
if (typeof maybeHostArr === 'function') {
|
||||
hostArr = Object.keys(this.strToHostObj);
|
||||
cb = maybeHostArr;
|
||||
} else {
|
||||
hostArr = maybeHostArr;
|
||||
cb = maybeCb;
|
||||
}
|
||||
|
||||
this.resetToDefaults();
|
||||
for(const hostStr of hostArr) {
|
||||
_createHostObj(hostStr);
|
||||
hostArr.forEach((hostStr) => this.createHostObj(hostStr));
|
||||
|
||||
this.updateAllAsync(cb);
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
privates.reinit();
|
||||
|
||||
const canonize = function canonize(addrArr) {
|
||||
|
||||
const ipSet = new Set();
|
||||
const hostSet = new Set();
|
||||
|
||||
addrArr.forEach((addr) => {
|
||||
|
||||
const ipm = matchIpv4v6(addr);
|
||||
if (ipm.ifMatched) {
|
||||
ipSet.add(ipm.canonical);
|
||||
} else {
|
||||
hostSet.add(addr.replace(/:\d+$/, ''));
|
||||
}
|
||||
|
||||
this._updateAllAsync(cb);
|
||||
});
|
||||
|
||||
console.log(`Canonized hosts/ips: ${hostSet.size}/${ipSet.size}`);
|
||||
return [ipSet, hostSet];
|
||||
|
||||
};
|
||||
|
||||
const theApi = window.apis.ipToHost = {
|
||||
|
||||
persistData() {
|
||||
|
||||
console.log('Persisting ipToHost...', privates);
|
||||
const ipToHost = {};
|
||||
Object.keys(privates.ipToHostObj).forEach((ip) => {
|
||||
ipToHost[ip] = privates.ipToHostObj[ip].host;
|
||||
});
|
||||
privates.state(ipToHostKey, ipToHost);
|
||||
|
||||
},
|
||||
|
||||
resetToDefaults() {
|
||||
|
||||
privates.resetToDefaults();
|
||||
|
||||
},
|
||||
|
||||
|
@ -296,7 +311,7 @@
|
|||
|
||||
updateAllAsync(cb = mandatory()) {
|
||||
|
||||
this._updateAllAsync((err, ...args) => {
|
||||
privates.updateAllAsync((err, ...args) => {
|
||||
|
||||
if (!err) {
|
||||
this.persistData();
|
||||
|
@ -310,14 +325,15 @@
|
|||
replaceAllAsync(addrArr, cb = mandatory()) {
|
||||
|
||||
console.log('Replacing...');
|
||||
const [ipSet, hostSet] = _canonize(addrArr);
|
||||
for( const ip of ipSet ) {
|
||||
const host = _getHostObj(ip);
|
||||
privates._ipToHostObj[ip] = host;
|
||||
}
|
||||
const [ipSet, hostSet] = canonize(addrArr);
|
||||
ipSet.forEach((ip) => {
|
||||
|
||||
privates.ipToHostObj[ip] = privates.getHostObj(ip);
|
||||
|
||||
});
|
||||
|
||||
const hostArr = Array.from(hostSet);
|
||||
this._replaceAllAsync(hostArr, (allErr, ...args) => {
|
||||
privates.replaceAllAsync(hostArr, (allErr, ...args) => {
|
||||
|
||||
if (!allErr) {
|
||||
this.persistData();
|
||||
|
@ -330,7 +346,7 @@
|
|||
|
||||
get(ip) {
|
||||
|
||||
const tmp = privates._ipToHostObj[ip];
|
||||
const tmp = privates.ipToHostObj[ip];
|
||||
return tmp && tmp.host;
|
||||
|
||||
},
|
||||
|
@ -338,14 +354,14 @@
|
|||
};
|
||||
|
||||
window.utils.addRequestResponder(
|
||||
'ip-to-host-update-all', (...args) => self.updateAllAsync(...args)
|
||||
'ip-to-host-update-all', (...args) => theApi.updateAllAsync(...args)
|
||||
);
|
||||
window.utils.addRequestResponder(
|
||||
'ip-to-host-replace-all', (...args) => self.replaceAllAsync(...args)
|
||||
'ip-to-host-replace-all', (...args) => theApi.replaceAllAsync(...args)
|
||||
);
|
||||
window.utils.addRequestResponder(
|
||||
'ip-to-host-reset-to-defaults', (cb) => {
|
||||
self.resetToDefaults();
|
||||
theApi.resetToDefaults();
|
||||
cb();
|
||||
}
|
||||
);
|
||||
|
|
|
@ -20,47 +20,52 @@
|
|||
color: '#db4b2f',
|
||||
});
|
||||
|
||||
const _tabCallbacks = {};
|
||||
const privates = {};
|
||||
|
||||
privates.tabCallbacks = {};
|
||||
|
||||
const afterTabUpdated = function afterTabUpdated(tabId, cb) {
|
||||
|
||||
if (_tabCallbacks[tabId]) {
|
||||
_tabCallbacks[tabId].push(cb);
|
||||
if (privates.tabCallbacks[tabId]) {
|
||||
privates.tabCallbacks[tabId].push(cb);
|
||||
} else {
|
||||
_tabCallbacks[tabId] = [cb];
|
||||
privates.tabCallbacks[tabId] = [cb];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const onTabUpdate = function onTabUpdate(tabId) {
|
||||
|
||||
if (_tabCallbacks[tabId]) {
|
||||
_tabCallbacks[tabId].map( (f) => f() );
|
||||
delete _tabCallbacks[tabId];
|
||||
if (privates.tabCallbacks[tabId]) {
|
||||
privates.tabCallbacks[tabId].map((f) => f());
|
||||
delete privates.tabCallbacks[tabId];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
chrome.tabs.onUpdated.addListener( onTabUpdate );
|
||||
chrome.tabs.onUpdated.addListener(onTabUpdate);
|
||||
|
||||
const updateTitle = function updateTitle(requestDetails, proxyHost, cb) {
|
||||
|
||||
chrome.browserAction.getTitle(
|
||||
{tabId: requestDetails.tabId},
|
||||
{ tabId: requestDetails.tabId },
|
||||
(title) => {
|
||||
|
||||
const ifTitleSetAlready = /\n/.test(title);
|
||||
|
||||
const hostname = new URL( requestDetails.url ).hostname;
|
||||
const hostname = new URL(requestDetails.url).hostname;
|
||||
|
||||
let ifShouldUpdateTitle = false;
|
||||
const indent = ' ';
|
||||
const proxyTitle = 'Прокси:';
|
||||
|
||||
let theLatestCb = cb;
|
||||
let newTitle = title;
|
||||
|
||||
if (!ifTitleSetAlready) {
|
||||
|
||||
title = 'Разблокированы:\n' + indent + hostname + '\n'
|
||||
+ proxyTitle + '\n' + indent + proxyHost;
|
||||
newTitle = `Разблокированы:\n${indent}${hostname}\n${proxyTitle}\n`
|
||||
+ `${indent}${proxyHost}`;
|
||||
ifShouldUpdateTitle = true;
|
||||
|
||||
chrome.browserAction.setBadgeText({
|
||||
|
@ -70,37 +75,36 @@
|
|||
|
||||
} else {
|
||||
|
||||
const hostsProxiesPair = title.split(proxyTitle);
|
||||
const hostsProxiesPair = newTitle.split(proxyTitle);
|
||||
|
||||
if (hostsProxiesPair[1].indexOf(proxyHost) === -1) {
|
||||
title = title.replace(
|
||||
newTitle = newTitle.replace(
|
||||
hostsProxiesPair[1],
|
||||
hostsProxiesPair[1] + '\n' + indent + proxyHost
|
||||
`${hostsProxiesPair[1]}\n${indent}${proxyHost}`
|
||||
);
|
||||
ifShouldUpdateTitle = true;
|
||||
}
|
||||
|
||||
if (hostsProxiesPair[0].indexOf(hostname) === -1) {
|
||||
|
||||
title = title.replace(
|
||||
newTitle = newTitle.replace(
|
||||
proxyTitle,
|
||||
indent + hostname + '\n' + proxyTitle
|
||||
`${indent}${hostname}\n${proxyTitle}`
|
||||
);
|
||||
ifShouldUpdateTitle = true;
|
||||
|
||||
const _cb = cb;
|
||||
cb = () => chrome.browserAction.getBadgeText(
|
||||
{tabId: requestDetails.tabId},
|
||||
theLatestCb = () => chrome.browserAction.getBadgeText(
|
||||
{ tabId: requestDetails.tabId },
|
||||
(result) => {
|
||||
|
||||
const charPrefix = isNaN(result.charAt(0)) ? result.charAt(0) : '';
|
||||
chrome.browserAction.setBadgeText(
|
||||
{
|
||||
tabId: requestDetails.tabId,
|
||||
text: (isNaN( result.charAt(0)) && result.charAt(0) || '')
|
||||
+ (hostsProxiesPair[0].split('\n').length - 1),
|
||||
text: charPrefix + (hostsProxiesPair[0].split('\n').length - 1),
|
||||
}
|
||||
);
|
||||
return _cb();
|
||||
return cb();
|
||||
|
||||
}
|
||||
);
|
||||
|
@ -111,12 +115,12 @@
|
|||
|
||||
if (ifShouldUpdateTitle) {
|
||||
chrome.browserAction.setTitle({
|
||||
title: title,
|
||||
title: newTitle,
|
||||
tabId: requestDetails.tabId,
|
||||
});
|
||||
}
|
||||
|
||||
return cb();
|
||||
return theLatestCb();
|
||||
|
||||
}
|
||||
);
|
||||
|
@ -127,7 +131,7 @@
|
|||
|
||||
const tryProxyAndInform = function tryProxyAndInform(requestDetails) {
|
||||
|
||||
const host = window.apis.ipToHost.get( requestDetails.ip );
|
||||
const host = window.apis.ipToHost.get(requestDetails.ip);
|
||||
if (!host) {
|
||||
return;
|
||||
}
|
||||
|
@ -137,7 +141,7 @@
|
|||
previousUpdateTitleFinished = previousUpdateTitleFinished.then(
|
||||
() => new Promise(
|
||||
(resolve) => {
|
||||
const cb = () => updateTitle( requestDetails, host, resolve );
|
||||
const cb = () => updateTitle(requestDetails, host, resolve);
|
||||
return ifMainFrame
|
||||
? afterTabUpdated(requestDetails.tabId, cb) : cb();
|
||||
}
|
||||
|
@ -155,11 +159,11 @@
|
|||
|
||||
};
|
||||
|
||||
for(const eventName of ['onResponseStarted', 'onErrorOccurred']) {
|
||||
['onResponseStarted', 'onErrorOccurred'].forEach((eventName) =>
|
||||
chrome.webRequest[eventName].addListener(
|
||||
onRequest,
|
||||
{urls: ['<all_urls>']}
|
||||
);
|
||||
}
|
||||
{ urls: ['<all_urls>'] }
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
{
|
||||
window.apis.version.ifMini = true;
|
||||
chrome.browserAction.setBadgeText({ text: 'M' });
|
||||
|
||||
window.apis.version.ifMini = true;
|
||||
chrome.browserAction.setBadgeText({text: 'M'});
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const commonContext = {
|
||||
version: '0.21',
|
||||
version: '0.22',
|
||||
};
|
||||
|
||||
exports.contexts = {};
|
||||
|
|
Loading…
Reference in New Issue
Block a user