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