mirror of
https://github.com/anticensority/runet-censorship-bypass.git
synced 2024-11-24 02:13:43 +03:00
Add eslint w/ Google styles, restyle
This commit is contained in:
parent
9ef8939127
commit
77a88e5778
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
|||
node_modules
|
||||
npm-debug.log
|
||||
.swp
|
||||
|
|
27
extensions/chromium/minimalistic-pac-setter/.eslintrc.js
Normal file
27
extensions/chromium/minimalistic-pac-setter/.eslintrc.js
Normal file
|
@ -0,0 +1,27 @@
|
|||
module.exports = {
|
||||
"extends": ["eslint:recommended", "google"],
|
||||
"plugins": [
|
||||
//"hapi"
|
||||
],
|
||||
"env": {
|
||||
"browser": true,
|
||||
"webextensions": true,
|
||||
"es6": true
|
||||
},
|
||||
"globals": {
|
||||
"chrome": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"sourceType": "script",
|
||||
"ecmaFeatures": {
|
||||
"impliedStrict": false
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"strict": ["error", "global"],
|
||||
"no-console": "off",
|
||||
"padded-blocks": "off",
|
||||
"require-jsdoc": "off"
|
||||
//"hapi/hapi-scope-start": ["warn"]
|
||||
}
|
||||
};
|
File diff suppressed because it is too large
Load Diff
|
@ -1,152 +1,169 @@
|
|||
'use strict';
|
||||
|
||||
// Shows user browserAction icon if any part of the current site is being blocked and proxied.
|
||||
|
||||
/*
|
||||
In what moment the title of the previous icon is cleared?
|
||||
By my observations it usually takes place near tabs.onUpdate of tab status to "loading".
|
||||
So if you set a title earlier it may be cleared by browser.
|
||||
It pertains not only to page refesh but to newly opened pages too.
|
||||
Also on loosing title see:
|
||||
https://github.com/ilyaigpetrov/repository-for-chrome-bugs/blob/master/browserAction-title-lost-after-setting/background.js
|
||||
Crazy parallel Chrome.
|
||||
**/
|
||||
|
||||
window.chrome.browserAction.setBadgeBackgroundColor({
|
||||
color: '#db4b2f'
|
||||
});
|
||||
|
||||
window.tabWithError2ip = {}; // For errors only: Error? -> Check this IP!
|
||||
|
||||
{
|
||||
|
||||
const _tabCallbacks = {};
|
||||
|
||||
function afterTabUpdated(tabId, cb) {
|
||||
if (_tabCallbacks[tabId])
|
||||
_tabCallbacks[tabId].push(cb);
|
||||
else _tabCallbacks[tabId] = [cb];
|
||||
}
|
||||
|
||||
function onTabUpdate(tabId) {
|
||||
if (_tabCallbacks[tabId]) {
|
||||
_tabCallbacks[tabId].map( f => f() );
|
||||
delete _tabCallbacks[tabId];
|
||||
}
|
||||
}
|
||||
|
||||
chrome.tabs.onUpdated.addListener( onTabUpdate );
|
||||
|
||||
function isInsideTabWithIp(requestDetails) {
|
||||
return requestDetails.tabId !== -1 && requestDetails.ip
|
||||
}
|
||||
|
||||
chrome.webRequest.onErrorOccurred.addListener(
|
||||
(requestDetails) =>
|
||||
isInsideTabWithIp(requestDetails) &&
|
||||
(
|
||||
isProxiedAndInformed(requestDetails) || requestDetails.type === 'main_frame' && ( window.tabWithError2ip[requestDetails.tabId] = requestDetails.ip )
|
||||
),
|
||||
{ urls: ['<all_urls>'] }
|
||||
);
|
||||
|
||||
chrome.tabs.onRemoved.addListener( (tabId) => { onTabUpdate(tabId); delete window.tabWithError2ip[tabId] } );
|
||||
|
||||
function updateTitle(requestDetails, cb) {
|
||||
|
||||
chrome.browserAction.getTitle(
|
||||
{ tabId: requestDetails.tabId },
|
||||
(title) => {
|
||||
|
||||
const ifTitleSetAlready = /\n/.test(title);
|
||||
const proxyHost = window.antiCensorRu.getPacProvider().proxyIps[ requestDetails.ip ];
|
||||
|
||||
const hostname = new URL( requestDetails.url ).hostname;
|
||||
|
||||
let ifShouldUpdateTitle = false;
|
||||
const indent = ' ';
|
||||
const proxyTitle = 'Прокси:';
|
||||
|
||||
if (!ifTitleSetAlready) {
|
||||
title = 'Разблокированы:\n'+ indent + hostname +'\n'+ proxyTitle +'\n'+ indent + proxyHost;
|
||||
ifShouldUpdateTitle = true;
|
||||
|
||||
chrome.browserAction.setBadgeText({
|
||||
tabId: requestDetails.tabId,
|
||||
text: requestDetails.type === 'main_frame' ? '1' : '%1'
|
||||
});
|
||||
|
||||
}
|
||||
else {
|
||||
const hostsProxiesPair = title.split(proxyTitle);
|
||||
|
||||
if (hostsProxiesPair[1].indexOf(proxyHost) === -1) {
|
||||
title = title.replace(hostsProxiesPair[1], hostsProxiesPair[1] +'\n'+ indent + proxyHost);
|
||||
ifShouldUpdateTitle = true;
|
||||
}
|
||||
|
||||
if (hostsProxiesPair[0].indexOf(hostname) === -1) {
|
||||
title = title.replace(proxyTitle, indent + hostname +'\n'+ proxyTitle);
|
||||
ifShouldUpdateTitle = true;
|
||||
|
||||
const _cb = cb;
|
||||
cb = () => chrome.browserAction.getBadgeText(
|
||||
{tabId: requestDetails.tabId},
|
||||
(result) => {
|
||||
|
||||
chrome.browserAction.setBadgeText(
|
||||
{
|
||||
tabId: requestDetails.tabId,
|
||||
text: ( isNaN( result.charAt(0) ) && result.charAt(0) || '' ) + (hostsProxiesPair[0].split('\n').length - 1)
|
||||
}
|
||||
);
|
||||
return _cb();
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (ifShouldUpdateTitle) {
|
||||
chrome.browserAction.setTitle({
|
||||
title: title,
|
||||
tabId: requestDetails.tabId
|
||||
});
|
||||
}
|
||||
|
||||
return cb();
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
let previousUpdateTitleFinished = Promise.resolve();
|
||||
|
||||
function isProxiedAndInformed(requestDetails) {
|
||||
|
||||
if ( !(requestDetails.ip && antiCensorRu.isProxied( requestDetails.ip )) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const ifMainFrame = requestDetails.type === 'main_frame';
|
||||
|
||||
previousUpdateTitleFinished = previousUpdateTitleFinished.then(
|
||||
() => new Promise(
|
||||
(resolve) => {
|
||||
const cb = () => updateTitle( requestDetails, resolve );
|
||||
return ifMainFrame ? afterTabUpdated(requestDetails.tabId, cb) : cb();
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
chrome.webRequest.onResponseStarted.addListener(
|
||||
(requestDetails) => isInsideTabWithIp(requestDetails) && isProxiedAndInformed(requestDetails),
|
||||
{ urls: ['<all_urls>'] }
|
||||
);
|
||||
|
||||
}
|
||||
'use strict';
|
||||
|
||||
// Shows user browserAction icon if any part of the current site is being
|
||||
// blocked and proxied.
|
||||
|
||||
/*
|
||||
In what moment the title of the previous icon is cleared?
|
||||
By my observations it usually takes place near tabs.onUpdate of tab status
|
||||
to "loading".
|
||||
So if you set a title earlier it may be cleared by browser.
|
||||
It pertains not only to page refesh but to newly opened pages too.
|
||||
Also on loosing title see:
|
||||
https://github.com/ilyaigpetrov/repository-for-chrome-bugs/blob/master/browserAction-title-lost-after-setting/background.js
|
||||
Crazy parallel Chrome.
|
||||
**/
|
||||
|
||||
window.chrome.browserAction.setBadgeBackgroundColor({
|
||||
color: '#db4b2f',
|
||||
});
|
||||
|
||||
window.tabWithError2ip = {}; // For errors only: Error? -> Check this IP!
|
||||
|
||||
{
|
||||
|
||||
const _tabCallbacks = {};
|
||||
|
||||
function afterTabUpdated(tabId, cb) {
|
||||
if (_tabCallbacks[tabId])
|
||||
_tabCallbacks[tabId].push(cb);
|
||||
else _tabCallbacks[tabId] = [cb];
|
||||
}
|
||||
|
||||
function onTabUpdate(tabId) {
|
||||
if (_tabCallbacks[tabId]) {
|
||||
_tabCallbacks[tabId].map( (f) => f() );
|
||||
delete _tabCallbacks[tabId];
|
||||
}
|
||||
}
|
||||
|
||||
chrome.tabs.onUpdated.addListener( onTabUpdate );
|
||||
|
||||
function isInsideTabWithIp(requestDetails) {
|
||||
return requestDetails.tabId !== -1 && requestDetails.ip;
|
||||
}
|
||||
|
||||
chrome.webRequest.onErrorOccurred.addListener(
|
||||
(requestDetails) =>
|
||||
isInsideTabWithIp(requestDetails) &&
|
||||
(
|
||||
isProxiedAndInformed(requestDetails)
|
||||
|| requestDetails.type === 'main_frame'
|
||||
&& (window.tabWithError2ip[requestDetails.tabId] = requestDetails.ip)
|
||||
),
|
||||
{urls: ['<all_urls>']}
|
||||
);
|
||||
|
||||
chrome.tabs.onRemoved.addListener( (tabId) => {
|
||||
onTabUpdate(tabId);
|
||||
delete window.tabWithError2ip[tabId];
|
||||
});
|
||||
|
||||
function updateTitle(requestDetails, cb) {
|
||||
|
||||
chrome.browserAction.getTitle(
|
||||
{tabId: requestDetails.tabId},
|
||||
(title) => {
|
||||
|
||||
const ifTitleSetAlready = /\n/.test(title);
|
||||
const proxyHost = window.antiCensorRu.getPacProvider()
|
||||
.proxyIps[requestDetails.ip];
|
||||
|
||||
const hostname = new URL( requestDetails.url ).hostname;
|
||||
|
||||
let ifShouldUpdateTitle = false;
|
||||
const indent = ' ';
|
||||
const proxyTitle = 'Прокси:';
|
||||
|
||||
if (!ifTitleSetAlready) {
|
||||
title = 'Разблокированы:\n' + indent + hostname + '\n'
|
||||
+ proxyTitle + '\n' + indent + proxyHost;
|
||||
ifShouldUpdateTitle = true;
|
||||
|
||||
chrome.browserAction.setBadgeText({
|
||||
tabId: requestDetails.tabId,
|
||||
text: requestDetails.type === 'main_frame' ? '1' : '%1',
|
||||
});
|
||||
|
||||
} else {
|
||||
const hostsProxiesPair = title.split(proxyTitle);
|
||||
|
||||
if (hostsProxiesPair[1].indexOf(proxyHost) === -1) {
|
||||
title = title.replace(
|
||||
hostsProxiesPair[1],
|
||||
hostsProxiesPair[1] + '\n' + indent + proxyHost
|
||||
);
|
||||
ifShouldUpdateTitle = true;
|
||||
}
|
||||
|
||||
if (hostsProxiesPair[0].indexOf(hostname) === -1) {
|
||||
title = title.replace(
|
||||
proxyTitle,
|
||||
indent + hostname + '\n' + proxyTitle
|
||||
);
|
||||
ifShouldUpdateTitle = true;
|
||||
|
||||
const _cb = cb;
|
||||
cb = () => chrome.browserAction.getBadgeText(
|
||||
{tabId: requestDetails.tabId},
|
||||
(result) => {
|
||||
|
||||
chrome.browserAction.setBadgeText(
|
||||
{
|
||||
tabId: requestDetails.tabId,
|
||||
text: (isNaN( result.charAt(0)) && result.charAt(0) || '')
|
||||
+ (hostsProxiesPair[0].split('\n').length - 1),
|
||||
}
|
||||
);
|
||||
return _cb();
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (ifShouldUpdateTitle) {
|
||||
chrome.browserAction.setTitle({
|
||||
title: title,
|
||||
tabId: requestDetails.tabId,
|
||||
});
|
||||
}
|
||||
|
||||
return cb();
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
let previousUpdateTitleFinished = Promise.resolve();
|
||||
|
||||
function isProxiedAndInformed(requestDetails) {
|
||||
|
||||
if ( !(requestDetails.ip
|
||||
&& window.antiCensorRu.isProxied( requestDetails.ip )) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const ifMainFrame = requestDetails.type === 'main_frame';
|
||||
|
||||
previousUpdateTitleFinished = previousUpdateTitleFinished.then(
|
||||
() => new Promise(
|
||||
(resolve) => {
|
||||
const cb = () => updateTitle( requestDetails, resolve );
|
||||
return ifMainFrame
|
||||
? afterTabUpdated(requestDetails.tabId, cb) : cb();
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
chrome.webRequest.onResponseStarted.addListener(
|
||||
(requestDetails) => isInsideTabWithIp(requestDetails)
|
||||
&& isProxiedAndInformed(requestDetails),
|
||||
{urls: ['<all_urls>']}
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,23 +1,43 @@
|
|||
'use strict';
|
||||
|
||||
{
|
||||
|
||||
const createMenuLinkEntry = (title, tab2url) => chrome.contextMenus.create({
|
||||
title: title,
|
||||
contexts: ['browser_action'],
|
||||
onclick: (menuInfo, tab) => Promise.resolve( tab2url( tab ) ).then( (url) => chrome.tabs.create({url: url}) )
|
||||
});
|
||||
|
||||
createMenuLinkEntry( 'Сайт доступен из-за границы? Is up?', (tab) => 'http://isup.me/'+ new URL(tab.url).hostname );
|
||||
|
||||
createMenuLinkEntry( 'Сайт в реестре блокировок?', (tab) => 'https://antizapret.info/index.php?search=' + tab.url );
|
||||
|
||||
createMenuLinkEntry( 'Из архива archive.org', (tab) => 'https://web.archive.org/web/*/' + tab.url );
|
||||
|
||||
createMenuLinkEntry( 'Открыть веб прокси (не наш)', (tab) => 'https://kproxy.com' );
|
||||
|
||||
createMenuLinkEntry( 'Другие варианты разблокировки', (tab) => 'https://rebrand.ly/unblock#' + tab.url );
|
||||
|
||||
createMenuLinkEntry( 'У меня проблемы с расширением!', (tab) => 'https://rebrand.ly/ac-support');
|
||||
|
||||
};
|
||||
'use strict';
|
||||
|
||||
{
|
||||
|
||||
const createMenuLinkEntry = (title, tab2url) => chrome.contextMenus.create({
|
||||
title: title,
|
||||
contexts: ['browser_action'],
|
||||
onclick:
|
||||
(menuInfo, tab) => Promise.resolve( tab2url( tab ) )
|
||||
.then( (url) => chrome.tabs.create({url: url}) ),
|
||||
});
|
||||
|
||||
createMenuLinkEntry(
|
||||
'Сайт доступен из-за границы? Is up?',
|
||||
(tab) => 'http://isup.me/' + new URL(tab.url).hostname
|
||||
);
|
||||
|
||||
createMenuLinkEntry(
|
||||
'Сайт в реестре блокировок?',
|
||||
(tab) => 'https://antizapret.info/index.php?search=' + tab.url
|
||||
);
|
||||
|
||||
createMenuLinkEntry(
|
||||
'Из архива archive.org',
|
||||
(tab) => 'https://web.archive.org/web/*/' + tab.url
|
||||
);
|
||||
|
||||
createMenuLinkEntry(
|
||||
'Открыть веб прокси (не наш)',
|
||||
(tab) => 'https://kproxy.com'
|
||||
);
|
||||
|
||||
createMenuLinkEntry(
|
||||
'Другие варианты разблокировки',
|
||||
(tab) => 'https://rebrand.ly/unblock#' + tab.url
|
||||
);
|
||||
|
||||
createMenuLinkEntry(
|
||||
'У меня проблемы с расширением!',
|
||||
(tab) => 'https://rebrand.ly/ac-support'
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,174 +1,189 @@
|
|||
'use strict';
|
||||
|
||||
chrome.runtime.getBackgroundPage( (backgroundPage) => {
|
||||
|
||||
const getStatus = () => document.querySelector('#status');
|
||||
|
||||
const setStatusTo = (msg) => {
|
||||
|
||||
const status = getStatus();
|
||||
if (msg) {
|
||||
status.classList.remove('off');
|
||||
status.innerHTML = msg;
|
||||
}
|
||||
else {
|
||||
status.classList.add('off');
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const antiCensorRu = backgroundPage.antiCensorRu;
|
||||
|
||||
// SET DATE
|
||||
|
||||
const setDate = () => {
|
||||
|
||||
let dateForUser = 'никогда';
|
||||
if( antiCensorRu.lastPacUpdateStamp ) {
|
||||
let diff = Date.now() - antiCensorRu.lastPacUpdateStamp;
|
||||
let units = ' мс';
|
||||
const gauges = [
|
||||
[1000, ' с'],
|
||||
[60, ' мин'],
|
||||
[60, ' ч'],
|
||||
[24, ' дн'],
|
||||
[7, ' недель'],
|
||||
[4, ' месяцев'],
|
||||
[12, ' г']
|
||||
];
|
||||
for(const g of gauges) {
|
||||
const diffy = Math.floor(diff / g[0]);
|
||||
if (!diffy)
|
||||
break;
|
||||
diff = diffy;
|
||||
units = g[1];
|
||||
}
|
||||
dateForUser = diff + units + ' назад';
|
||||
}
|
||||
|
||||
const dateElement = document.querySelector('.update-date');
|
||||
dateElement.innerText = dateForUser;
|
||||
dateElement.title = new Date(antiCensorRu.lastPacUpdateStamp).toLocaleString('ru-RU');
|
||||
|
||||
};
|
||||
|
||||
setDate();
|
||||
chrome.storage.onChanged.addListener( (changes) => changes.lastPacUpdateStamp.newValue && setDate() );
|
||||
|
||||
// CLOSE BUTTON
|
||||
|
||||
document.querySelector('.close-button').onclick = () => window.close();
|
||||
|
||||
// RADIOS
|
||||
|
||||
const currentProviderRadio = () => {
|
||||
|
||||
const id = antiCensorRu.currentPacProviderKey || 'none';
|
||||
return document.querySelector('#'+id);
|
||||
|
||||
}
|
||||
const checkChosenProvider = () => currentProviderRadio().checked = true;
|
||||
|
||||
const showError = (err) => {
|
||||
|
||||
let clarification = err.clarification;
|
||||
const ifNotCritical = clarification && clarification.ifNotCritical;
|
||||
let message = err.message || '';
|
||||
|
||||
while( clarification ) {
|
||||
message = (clarification && (clarification.message + ' ')) + message;
|
||||
clarification = clarification.prev;
|
||||
}
|
||||
message = message.trim();
|
||||
setStatusTo(
|
||||
`<span style="color:red">${ifNotCritical ? 'Некритичная ошибка.' : 'Ошибка!'}</span>
|
||||
<br/>
|
||||
<span style="font-size: 0.9em; color: darkred">${message}</span>
|
||||
<a href class="link-button">[Ещё подробнее]</a>`
|
||||
);
|
||||
getStatus().querySelector('.link-button').onclick = function() {
|
||||
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = `
|
||||
Более подробную информацию можно узнать из логов фоновой страницы:<br/>
|
||||
<a href="chrome://extensions?id=${chrome.runtime.id}" data-in-bg="true">chrome://extensions</a> › Это расширение › Отладка страниц: фоновая страница › Console (DevTools)
|
||||
<br>
|
||||
Ещё: ${JSON.stringify({err: err, stack: err.stack})}
|
||||
`;
|
||||
getStatus().replaceChild(div, this);
|
||||
return false;
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
const enableDisableInputs = function () {
|
||||
|
||||
const inputs = document.querySelectorAll('input');
|
||||
for ( let i = 0; i < inputs.length; i++ ) {
|
||||
inputs[i].disabled = !inputs[i].disabled;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const conduct = (beforeStatus, operation, afterStatus, onSuccess) => {
|
||||
|
||||
setStatusTo(beforeStatus);
|
||||
enableDisableInputs();
|
||||
operation((err) => {
|
||||
if (err) {
|
||||
showError(err);
|
||||
}
|
||||
else {
|
||||
setStatusTo(afterStatus);
|
||||
onSuccess && onSuccess();
|
||||
}
|
||||
enableDisableInputs();
|
||||
})
|
||||
|
||||
};
|
||||
|
||||
const ul = document.querySelector('#list-of-providers');
|
||||
const _firstChild = ul.firstChild;
|
||||
for( const providerKey of Object.keys(antiCensorRu.pacProviders).sort() ) {
|
||||
const li = document.createElement('li');
|
||||
li.innerHTML = `<input type="radio" name="pacProvider" id="${providerKey}"> <label for="${providerKey}">${providerKey}</label> <a href class="link-button checked-radio-panel">[обновить]</a>`;
|
||||
li.querySelector('.link-button').onclick = () => { conduct( 'Обновляем...', (cb) => antiCensorRu.syncWithPacProvider(cb), 'Обновлено.' ); return false; };
|
||||
ul.insertBefore( li, _firstChild );
|
||||
}
|
||||
checkChosenProvider();
|
||||
|
||||
const radios = [].slice.apply( document.querySelectorAll('[name=pacProvider]') );
|
||||
for(const radio of radios) {
|
||||
radio.onclick = function(event) {
|
||||
|
||||
if (event.target.id === (antiCensorRu.currentPacProviderKey || 'none')) {
|
||||
return false;
|
||||
}
|
||||
const pacKey = event.target.id;
|
||||
if (pacKey === 'none') {
|
||||
conduct(
|
||||
'Отключение...',
|
||||
(cb) => antiCensorRu.clearPac(cb),
|
||||
'Отключено.',
|
||||
checkChosenProvider
|
||||
);
|
||||
}
|
||||
else {
|
||||
conduct(
|
||||
'Установка...',
|
||||
(cb) => antiCensorRu.installPac(pacKey, cb),
|
||||
'PAC-скрипт установлен.',
|
||||
checkChosenProvider
|
||||
);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
setStatusTo('');
|
||||
if (antiCensorRu.ifFirstInstall) {
|
||||
currentProviderRadio().click();
|
||||
}
|
||||
|
||||
});
|
||||
'use strict';
|
||||
|
||||
chrome.runtime.getBackgroundPage( (backgroundPage) => {
|
||||
|
||||
const getStatus = () => document.querySelector('#status');
|
||||
|
||||
const setStatusTo = (msg) => {
|
||||
|
||||
const status = getStatus();
|
||||
if (msg) {
|
||||
status.classList.remove('off');
|
||||
status.innerHTML = msg;
|
||||
} else {
|
||||
status.classList.add('off');
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const antiCensorRu = backgroundPage.antiCensorRu;
|
||||
|
||||
// SET DATE
|
||||
|
||||
const setDate = () => {
|
||||
|
||||
let dateForUser = 'никогда';
|
||||
if( antiCensorRu.lastPacUpdateStamp ) {
|
||||
let diff = Date.now() - antiCensorRu.lastPacUpdateStamp;
|
||||
let units = ' мс';
|
||||
const gauges = [
|
||||
[1000, ' с'],
|
||||
[60, ' мин'],
|
||||
[60, ' ч'],
|
||||
[24, ' дн'],
|
||||
[7, ' недель'],
|
||||
[4, ' месяцев'],
|
||||
[12, ' г'],
|
||||
];
|
||||
for(const g of gauges) {
|
||||
const diffy = Math.floor(diff / g[0]);
|
||||
if (!diffy)
|
||||
break;
|
||||
diff = diffy;
|
||||
units = g[1];
|
||||
}
|
||||
dateForUser = diff + units + ' назад';
|
||||
}
|
||||
|
||||
const dateElement = document.querySelector('.update-date');
|
||||
dateElement.innerText = dateForUser;
|
||||
dateElement.title = new Date(antiCensorRu.lastPacUpdateStamp)
|
||||
.toLocaleString('ru-RU');
|
||||
|
||||
};
|
||||
|
||||
setDate();
|
||||
chrome.storage.onChanged.addListener(
|
||||
(changes) => changes.lastPacUpdateStamp.newValue && setDate()
|
||||
);
|
||||
|
||||
// CLOSE BUTTON
|
||||
|
||||
document.querySelector('.close-button').onclick = () => window.close();
|
||||
|
||||
// RADIOS
|
||||
|
||||
const currentProviderRadio = () => {
|
||||
|
||||
const id = antiCensorRu.currentPacProviderKey || 'none';
|
||||
return document.querySelector('#'+id);
|
||||
|
||||
};
|
||||
const checkChosenProvider = () => currentProviderRadio().checked = true;
|
||||
|
||||
const showError = (err) => {
|
||||
|
||||
let clarification = err.clarification;
|
||||
const ifNotCritical = clarification && clarification.ifNotCritical;
|
||||
let message = err.message || '';
|
||||
|
||||
while( clarification ) {
|
||||
message = (clarification && (clarification.message + ' ')) + message;
|
||||
clarification = clarification.prev;
|
||||
}
|
||||
message = message.trim();
|
||||
setStatusTo(
|
||||
`<span style="color:red">
|
||||
${ifNotCritical ? 'Некритичная ошибка.' : 'Ошибка!'}
|
||||
</span>
|
||||
<br/>
|
||||
<span style="font-size: 0.9em; color: darkred">${message}</span>
|
||||
<a href class="link-button">[Ещё подробнее]</a>`
|
||||
);
|
||||
getStatus().querySelector('.link-button').onclick = function() {
|
||||
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = `
|
||||
Более подробную информацию можно узнать из логов фоновой страницы:<br/>
|
||||
<a href="chrome://extensions?id=${chrome.runtime.id}" data-in-bg="true">
|
||||
chrome://extensions</a> ›
|
||||
Это расширение › Отладка страниц: фоновая страница › Console (DevTools)
|
||||
<br>
|
||||
Ещё: ${JSON.stringify({err: err, stack: err.stack})}
|
||||
`;
|
||||
getStatus().replaceChild(div, this);
|
||||
return false;
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
const enableDisableInputs = function() {
|
||||
|
||||
const inputs = document.querySelectorAll('input');
|
||||
for ( let i = 0; i < inputs.length; i++ ) {
|
||||
inputs[i].disabled = !inputs[i].disabled;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const conduct = (beforeStatus, operation, afterStatus, onSuccess) => {
|
||||
|
||||
setStatusTo(beforeStatus);
|
||||
enableDisableInputs();
|
||||
operation((err) => {
|
||||
if (err) {
|
||||
showError(err);
|
||||
} else {
|
||||
setStatusTo(afterStatus);
|
||||
onSuccess && onSuccess();
|
||||
}
|
||||
enableDisableInputs();
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
const ul = document.querySelector('#list-of-providers');
|
||||
const _firstChild = ul.firstChild;
|
||||
for( const providerKey of Object.keys(antiCensorRu.pacProviders).sort() ) {
|
||||
const li = document.createElement('li');
|
||||
li.innerHTML = `<input type="radio" name="pacProvider" id="${providerKey}">
|
||||
<label for="${providerKey}">${providerKey}</label>
|
||||
<a href class="link-button checked-radio-panel">[обновить]</a>`;
|
||||
li.querySelector('.link-button').onclick =
|
||||
() => {
|
||||
conduct(
|
||||
'Обновляем...', (cb) => antiCensorRu.syncWithPacProvider(cb),
|
||||
'Обновлено.'
|
||||
);
|
||||
return false;
|
||||
};
|
||||
ul.insertBefore( li, _firstChild );
|
||||
}
|
||||
checkChosenProvider();
|
||||
|
||||
const radios = [].slice.apply(
|
||||
document.querySelectorAll('[name=pacProvider]')
|
||||
);
|
||||
for(const radio of radios) {
|
||||
radio.onclick = function(event) {
|
||||
|
||||
if (event.target.id === (antiCensorRu.currentPacProviderKey || 'none')) {
|
||||
return false;
|
||||
}
|
||||
const pacKey = event.target.id;
|
||||
if (pacKey === 'none') {
|
||||
conduct(
|
||||
'Отключение...',
|
||||
(cb) => antiCensorRu.clearPac(cb),
|
||||
'Отключено.',
|
||||
checkChosenProvider
|
||||
);
|
||||
} else {
|
||||
conduct(
|
||||
'Установка...',
|
||||
(cb) => antiCensorRu.installPac(pacKey, cb),
|
||||
'PAC-скрипт установлен.',
|
||||
checkChosenProvider
|
||||
);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
setStatusTo('');
|
||||
if (antiCensorRu.ifFirstInstall) {
|
||||
currentProviderRadio().click();
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -13,9 +13,9 @@ const updateLinks = () => {
|
|||
for (let i = 0; i < links.length; i++) {
|
||||
const ln = links[i];
|
||||
const location = ln.href;
|
||||
ln.onclick = function () {
|
||||
ln.onclick = function() {
|
||||
|
||||
chrome.tabs.create({ active: !this.dataset.inBg, url: location });
|
||||
chrome.tabs.create({active: !this.dataset.inBg, url: location});
|
||||
return false;
|
||||
|
||||
};
|
||||
|
@ -24,6 +24,11 @@ const updateLinks = () => {
|
|||
};
|
||||
|
||||
new MutationObserver( updateLinks )
|
||||
.observe(target, { attributes: false, subtree: true, childList: true, characterData: false });
|
||||
.observe(target, {
|
||||
attributes: false,
|
||||
subtree: true,
|
||||
childList: true,
|
||||
characterData: false,
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', updateLinks);
|
||||
|
|
|
@ -4,13 +4,15 @@ const setStatusTo = (msg) => document.getElementById('status').innerHTML = msg;
|
|||
|
||||
const red = (text) => '<span style="color: red">' + text + '</span>';
|
||||
|
||||
const editor = ace.edit('editor');
|
||||
const editor = window.ace.edit('editor');
|
||||
editor.getSession().setOptions({
|
||||
mode: "ace/mode/javascript",
|
||||
useSoftTabs: true
|
||||
mode: 'ace/mode/javascript',
|
||||
useSoftTabs: true,
|
||||
});
|
||||
|
||||
chrome.proxy.settings.onChange.addListener( (details) => setStatusTo(red( details.levelOfControl + '!') ) );
|
||||
chrome.proxy.settings.onChange.addListener(
|
||||
(details) => setStatusTo(red( details.levelOfControl + '!') )
|
||||
);
|
||||
|
||||
document.querySelector('#read-button').onclick = () => {
|
||||
|
||||
|
@ -36,8 +38,8 @@ document.querySelector('#save-button').onclick = () => {
|
|||
mode: 'pac_script',
|
||||
pacScript: {
|
||||
mandatory: false,
|
||||
data: editor.getValue()
|
||||
}
|
||||
data: editor.getValue(),
|
||||
},
|
||||
};
|
||||
chrome.proxy.settings.set( {value: config}, () => alert('Saved!') );
|
||||
|
||||
|
|
21
extensions/chromium/minimalistic-pac-setter/package.json
Normal file
21
extensions/chromium/minimalistic-pac-setter/package.json
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name": "russian-censorship-bypass",
|
||||
"version": "0.0.15",
|
||||
"description": "Development tools for chromium extension",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"lint": "./node_modules/.bin/eslint ./extension/**/*.js --ignore-pattern vendor"
|
||||
},
|
||||
"author": "Ilya Ig. Petrov",
|
||||
"license": "GPLv3",
|
||||
"devDependencies": {
|
||||
"eslint": "^3.11.1",
|
||||
"eslint-config-airbnb": "^13.0.0",
|
||||
"eslint-config-google": "^0.7.1",
|
||||
"eslint-plugin-hapi": "^4.0.0",
|
||||
"eslint-plugin-import": "^2.2.0",
|
||||
"eslint-plugin-jsx-a11y": "^2.2.3",
|
||||
"eslint-plugin-react": "^6.7.1"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user