Refactor err handlers, unixify newlines, restructure files

This commit is contained in:
Ilya Ig. Petrov 2016-12-01 07:01:20 -08:00
parent 257495168c
commit 6750872ea5
11 changed files with 357 additions and 206 deletions

View File

@ -1,26 +1,30 @@
# О расширении # Dev
Обход интернет-цензуры в России пока что не является преступлением. Linting JS: `npm run lint`
Расширение позволяет обходить блокировки РосКомНадзора, давая вам доступ # О расширении
к библиотекам, энциклопедиям, сайтам оппозиционеров, а также к неповинным
сайтам, случайно заблокированным в силу разных причин. Обход интернет-цензуры в России пока что не является преступлением.
Проксирует только заблокированные сайты, оставляя нетронутыми все остальные. Расширение позволяет обходить блокировки РосКомНадзора, давая вам доступ
к библиотекам, энциклопедиям, сайтам оппозиционеров, а также к неповинным
Устанавливает PAC-скрипт, работающий через сервера anticenz.org и antizapret.prostovpn.org. сайтам, случайно заблокированным в силу разных причин.
Обновляет PAC-скрипт каждые 4 часа, что составляет примерно 7MB трафика в сутки. Проксирует только заблокированные сайты, оставляя нетронутыми все остальные.
Также расширение постоянно потребляет ~15MB памяти для информирования о блокировках через иконку.
Устанавливает PAC-скрипт, работающий через сервера anticenz.org и antizapret.prostovpn.org.
Синяя лента кампания фонда EFF в защиту свобод слова, прессы и союзов.
Обновляет PAC-скрипт каждые 4 часа, что составляет примерно 7MB трафика в сутки.
Если расширение не работает: https://git.io/vgDDj Также расширение постоянно потребляет ~15MB памяти для информирования о блокировках через иконку.
Антицензура на Реддите: https://www.reddit.com/r/anticensorship_russia Синяя лента кампания фонда EFF в защиту свобод слова, прессы и союзов.
Группа в G+: https://goo.gl/Lh0Cjh
История изменений: https://github.com/ilyaigpetrov/anti-censorship-russia/releases Если расширение не работает: https://git.io/vgDDj
# Дополнительно Антицензура на Реддите: https://www.reddit.com/r/anticensorship_russia
Группа в G+: https://goo.gl/Lh0Cjh
Иконка синей ленты: http://www.iconsdb.com/icon-sets/cardboard-blue-icons/ribbon-12-icon.html История изменений: https://github.com/ilyaigpetrov/anti-censorship-russia/releases
# Дополнительно
Иконка синей ленты: http://www.iconsdb.com/icon-sets/cardboard-blue-icons/ribbon-12-icon.html

View File

@ -1,56 +0,0 @@
'use strict';
{
const extName = chrome.runtime.getManifest().name;
const notify = (
id,
title,
message,
icon = 'default-128.png',
context = extName
) => chrome.notifications.create(
id,
{
title: title,
message: message,
contextMessage: context,
requireInteraction: true,
type: 'basic',
iconUrl: './icons/' + icon,
}
);
window.addEventListener('error', (err) => {
console.warn('Global error');
notify('Unhandled error', 'Unhandled error', JSON.stringify(err),
'ext-error-128.png');
});
window.addEventListener('unhandledrejection', (event) => {
console.warn('Unhandled rejection. Throwing error.');
event.preventDefault();
throw event.reason;
});
chrome.proxy.onProxyError.addListener((details) => {
console.warn('PAC ERROR:', details);
notify('pac-error', ' PAC !', JSON.stringify(details),
'pac-error-128.png' );
});
chrome.proxy.settings.onChange.addListener((details) => {
console.log('Proxy settings changed.', details);
// const ifOther = details.levelOfControl.startsWith('controlled_by_other');
notify('Proxy change', 'Proxy changed', JSON.stringify(details),
'no-control-128.png');
});
}

View File

@ -0,0 +1,14 @@
'use strict';
window.utils = {
areSettingsNotControlledFor(details) {
return ['controlled_by_other', 'not_controllable']
.some( (prefix) => details.levelOfControl.startsWith(prefix) );
},
};
window.apis = {};

View File

@ -0,0 +1,148 @@
'use strict';
{ // Private namespace
const handlersState = function(key, value) {
console.log(key, value, '!');
key = 'handlers-' + key;
if (value === null) {
return localStorage.removeItem(key);
}
if (value === undefined) {
const item = localStorage.getItem(key);
return item && JSON.parse(item);
}
if (value instanceof Date) {
throw new TypeError('Converting Date format to JSON is not supported.');
}
localStorage.setItem(key, JSON.stringify(value));
};
const ifPrefix = 'if-on-';
window.apis.errorHandlers = {
getEventsMap() {
return new Map([
['pac-error', 'ошибки PAC скриптов'],
['ext-error', 'ошибки расширения'],
['no-control', 'утеря контроля над настройками'],
]);
},
switch(onOffStr, eventName) {
if (!['on', 'off'].includes(onOffStr)) {
throw new TypeError('First argument bust be "on" or "off".');
}
for(
const name of (eventName ? [eventName] : this.getEventsMap().keys() )
) {
handlersState( ifPrefix + name, onOffStr === 'on' ? 'on' : null );
}
},
isOn(eventName) {
return handlersState( ifPrefix + eventName);
},
ifNotControlled: null,
isNotControlled(details) {
this.ifNotControlled = window.utils.areSettingsNotControlledFor( details );
if (this.ifNotControlled) {
chrome.browserAction.disable();
} else {
chrome.browserAction.enable();
}
return this.ifNotControlled;
},
};
}
// INIT
chrome.proxy.settings.get(
{},
(details) => window.apis.errorHandlers.isNotControlled(details)
);
{
const extName = chrome.runtime.getManifest().name;
const mayNotify = function(
id, title, message,
icon = 'default-128.png',
context = extName
) {
if ( !window.apis.errorHandlers.isOn(id) ) {
return;
}
chrome.notifications.create(
id,
{
title: title,
message: message,
contextMessage: context,
requireInteraction: true,
type: 'basic',
iconUrl: './icons/' + icon,
isClickable: true,
}
);
};
window.addEventListener('error', (err) => {
console.warn('GLOBAL ERROR', err);
mayNotify('ext-error', 'Unhandled error', JSON.stringify(err),
'ext-error-128.png');
});
window.addEventListener('unhandledrejection', (event) => {
console.warn('Unhandled rejection. Throwing error.');
event.preventDefault();
throw event.reason;
});
chrome.proxy.onProxyError.addListener((details) => {
if (window.apis.errorHandlers.ifNoControl) {
return;
}
console.warn('PAC ERROR', details);
mayNotify('pac-error', ' PAC !', JSON.stringify(details),
'pac-error-128.png' );
});
chrome.proxy.settings.onChange.addListener((details) => {
console.log('Proxy settings changed.', details);
const noCon = 'no-control';
if ( window.apis.errorHandlers.isNotControlled(details) ) {
mayNotify(noCon, 'Proxy changed', JSON.stringify(details),
'no-control-128.png');
} else {
chrome.notifications.clear( noCon );
}
});
}

View File

@ -9,39 +9,17 @@
*/ */
/* /*
In background scripts use window.antiCensorRu public variables. In background scripts use window.apis.antiCensorRu public variables.
In pages window.antiCensorRu is not accessible, In pages window.apis.antiCensorRu is not accessible,
use chrome.runtime.getBackgroundPage(..), use chrome.runtime.getBackgroundPage(..),
extension.getBackgroundPage is deprecated extension.getBackgroundPage is deprecated
*/ */
{ // Private namespace starts. { // Private namespace starts.
window.antiCensorRu = { window.apis.antiCensorRu = {
version: chrome.runtime.getManifest().version, version: chrome.runtime.getManifest().version,
fixErrorsContext() {
/* `setTimeout` changes context of execution from other window
(e.g. popup) to background window, so we may catch errors
in bg error handlers.
More: https://bugs.chromium.org/p/chromium/issues/detail?id=357568
*/
for(const prop of Object.keys(this)) {
if ( typeof(this[prop]) === 'function' ) {
const method = this[prop];
this[prop] = function(...args) {
setTimeout(method.bind(this, ...args), 0);
};
}
}
},
throw() {
throw new Error('Artificial error');
},
pacProviders: { pacProviders: {
Антизапрет: { Антизапрет: {
pacUrl: 'https://antizapret.prostovpn.org/proxy.pac', pacUrl: 'https://antizapret.prostovpn.org/proxy.pac',
@ -293,6 +271,7 @@
} }
) )
); );
}, },
}; };
@ -307,8 +286,7 @@
E.g. install window may fail to open or be closed by user accidentally. E.g. install window may fail to open or be closed by user accidentally.
In such case extension _should_ try to work on default parameters. In such case extension _should_ try to work on default parameters.
*/ */
const antiCensorRu = window.antiCensorRu; const antiCensorRu = window.apis.antiCensorRu;
antiCensorRu.fixErrorsContext();
chrome.alarms.onAlarm.addListener( chrome.alarms.onAlarm.addListener(
(alarm) => { (alarm) => {
@ -393,6 +371,7 @@
* Changed storage.ifNotInstalled to storage.ifFirstInstall * Changed storage.ifNotInstalled to storage.ifFirstInstall
* Added storage.lastPacUpdateStamp * Added storage.lastPacUpdateStamp
**/ **/
}); });
function asyncLogGroup(...args) { function asyncLogGroup(...args) {
@ -406,6 +385,7 @@
cb(...cbArgs); cb(...cbArgs);
}; };
} }
function checkChromeError(betterStack) { function checkChromeError(betterStack) {
@ -458,8 +438,7 @@
} }
chrome.proxy.settings.get({}, (details) => { chrome.proxy.settings.get({}, (details) => {
const ifThis = details.levelOfControl.startsWith('controlled_by_this'); if ( window.utils.areSettingsNotControlledFor( details ) ) {
if (!ifThis) {
console.warn('Failed, other extension is in control.'); console.warn('Failed, other extension is in control.');
return cb({clarification: {message: 'Настройки прокси контролирует другое расширение. <a href="chrome://settings/search#proxy">Какое?</a>'}}); return cb({clarification: {message: 'Настройки прокси контролирует другое расширение. <a href="chrome://settings/search#proxy">Какое?</a>'}});
} }
@ -500,6 +479,7 @@
} }
); );
} }
function getIpsFor(host, cb) { function getIpsFor(host, cb) {
@ -600,6 +580,7 @@
} }
) )
); );
} }
function setPacScriptFromProvider(provider, cb) { function setPacScriptFromProvider(provider, cb) {
@ -625,6 +606,7 @@
} }
); );
} }
} }

View File

@ -0,0 +1,23 @@
'use strict';
/* `setTimeout` changes context of execution from other window
(e.g. popup) to background window, so we may catch errors
in bg error handlers.
More: https://bugs.chromium.org/p/chromium/issues/detail?id=357568
*/
// Fix error context of methods of all APIs.
for(const api of Object.keys(window.apis)) {
for(const prop of Object.keys(api)) {
if ( typeof(api[prop]) !== 'function' ) {
continue;
}
const method = api[prop];
api[prop] = function(...args) {
setTimeout(method.bind(this, ...args), 0);
};
}
}

View File

@ -14,6 +14,8 @@
Crazy parallel Chrome. Crazy parallel Chrome.
**/ **/
const antiCensorRu = window.apis.antiCensorRu;
window.chrome.browserAction.setBadgeBackgroundColor({ window.chrome.browserAction.setBadgeBackgroundColor({
color: '#db4b2f', color: '#db4b2f',
}); });
@ -66,7 +68,7 @@ window.tabWithError2ip = {}; // For errors only: Error? -> Check this IP!
(title) => { (title) => {
const ifTitleSetAlready = /\n/.test(title); const ifTitleSetAlready = /\n/.test(title);
const proxyHost = window.antiCensorRu.getPacProvider() const proxyHost = antiCensorRu.getPacProvider()
.proxyIps[requestDetails.ip]; .proxyIps[requestDetails.ip];
const hostname = new URL( requestDetails.url ).hostname; const hostname = new URL( requestDetails.url ).hostname;
@ -141,7 +143,7 @@ window.tabWithError2ip = {}; // For errors only: Error? -> Check this IP!
function isProxiedAndInformed(requestDetails) { function isProxiedAndInformed(requestDetails) {
if ( !(requestDetails.ip if ( !(requestDetails.ip
&& window.antiCensorRu.isProxied( requestDetails.ip )) ) { && antiCensorRu.isProxied( requestDetails.ip )) ) {
return false; return false;
} }

View File

@ -1,34 +1,34 @@
{ {
"manifest_version": 2, "manifest_version": 2,
"name": "Обход блокировок Рунета 0.15", "name": "Обход блокировок Рунета 0.15",
"description": "Аргументы против цензуры: https://git.io/vEkI9", "description": "Аргументы против цензуры: https://git.io/vEkI9",
"version": "0.0.0.15", "version": "0.0.0.15",
"icons": { "icons": {
"128": "/icons/default-128.png" "128": "/icons/default-128.png"
}, },
"author": "ilyaigpetrov@gmail.com", "author": "ilyaigpetrov@gmail.com",
"homepage_url": "https://github.com/anticensorship-russia/chromium-extension", "homepage_url": "https://github.com/anticensorship-russia/chromium-extension",
"permissions": [ "permissions": [
"proxy", "proxy",
"webRequest", "webRequest",
"alarms", "alarms",
"storage", "storage",
"<all_urls>", "<all_urls>",
"tabs", "tabs",
"contextMenus", "contextMenus",
"notifications" "notifications"
], ],
"background": { "background": {
"scripts": ["0-error-handlers.js", "1-sync-pac-script-with-pac-provider.js", "2-block-informer.js", "3-context-menus.js"] "scripts": ["00-init-apis.js", "11-api-error-handlers.js", "12-api-sync-pac-script-with-pac-provider.js", "20-api-fixes.js", "30-block-informer.js", "40-context-menus.js"]
}, },
"browser_action": { "browser_action": {
"default_title": "Этот сайт благословлён", "default_title": "Этот сайт благословлён",
"default_popup": "/pages/choose-pac-provider/index.html" "default_popup": "/pages/choose-pac-provider/index.html"
}, },
"options_ui": { "options_ui": {
"page": "/pages/choose-pac-provider/index.html", "page": "/pages/choose-pac-provider/index.html",
"chrome_style": true "chrome_style": true
} }
} }

View File

@ -1,58 +1,73 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Выбор провайдера PAC</title> <title>Выбор провайдера PAC</title>
<style> <style>
ul { label {
list-style-type: none; user-select: none;
padding: 0; }
margin: 0; ul {
margin-bottom: 1em; list-style-type: none;
} padding: 0;
li, footer { margin: 0;
display: block; margin-bottom: 1em;
white-space: nowrap; }
word-break: keep-all; li, footer {
} display: block;
li > * { white-space: nowrap;
vertical-align: middle; word-break: keep-all;
} }
input[type="radio"], label { li > * {
cursor: pointer; vertical-align: middle;
} }
.off { input[type="radio"], label {
display: none; cursor: pointer;
} }
.link-button, .link-button:visited { .off {
color: #0000EE; display: none;
text-decoration: none; }
} .link-button, .link-button:visited {
.link-button:hover { color: #0000EE;
text-decoration: underline; text-decoration: none;
} }
.checked-radio-panel { .link-button:hover {
visibility: hidden; text-decoration: underline;
} }
input:checked ~ .checked-radio-panel { .checked-radio-panel {
visibility: visible; visibility: hidden;
} }
footer { input:checked ~ .checked-radio-panel {
margin: 2em 1em 1em; visibility: visible;
} }
</style> footer {
</head> margin: 2em 1em 1em;
<body> }
<ul id="list-of-providers"> hr {
<li><input type="radio" name="pacProvider" id="none" checked> <label for="none">Отключить</label></li> border-width: 1px 0 0 0;
</ul> }
<div style="white-space: nowrap"> #configs-panel > header {
Обновлялись: <span class="update-date">...</span> margin: 0.6em 0 0.4em;
</div> }
<div id="status">Загрузка...</div> </style>
<footer> </head>
<input type="button" value="Готово" class="close-button">&nbsp;<a href="../debug/index.html" style="text-decoration: none; margin-left: 1em;">Отладка</a> <body>
</footer> <ul id="list-of-providers">
<script src="./index.js"></script> <li><input type="radio" name="pacProvider" id="none" checked> <label for="none">Отключить</label></li>
<script src="./keep-links-clickable.js"></script> </ul>
</body> <div style="white-space: nowrap">
</html> Обновлялись: <span class="update-date">...</span>
</div>
<div id="status">Загрузка...</div>
<hr/>
<div id="configs-panel">
<header>Я ❤️ уведомления:</header>
<ul id="list-of-handlers">
</ul>
</div>
<footer>
<input type="button" value="Готово" class="close-button">&nbsp;<a href="../debug/index.html" style="text-decoration: none; margin-left: 1em;">Отладка</a>
</footer>
<script src="./index.js"></script>
<script src="./keep-links-clickable.js"></script>
</body>
</html>

View File

@ -16,7 +16,7 @@ chrome.runtime.getBackgroundPage( (backgroundPage) => {
}; };
const antiCensorRu = backgroundPage.antiCensorRu; const antiCensorRu = backgroundPage.apis.antiCensorRu;
// SET DATE // SET DATE
@ -182,6 +182,25 @@ chrome://extensions</a>
}; };
} }
const conpanel = document.getElementById('list-of-handlers');
backgroundPage.apis.errorHandlers.getEventsMap().forEach( (value, name) => {
const li = document.createElement('li');
li.innerHTML = `
<input type="checkbox" id="if-on-${name}"/>
<label for="if-on-${name}">${value}</label>`;
const box = li.querySelector('input');
box.checked = backgroundPage.apis.errorHandlers.isOn(name);
box.onclick = function() {
const id = this.id.replace('if-on-', '');
backgroundPage.apis.errorHandlers.switch(this.checked ? 'on' : 'off', id);
};
conpanel.appendChild(li);
});
setStatusTo(''); setStatusTo('');
if (antiCensorRu.ifFirstInstall) { if (antiCensorRu.ifFirstInstall) {
const id = antiCensorRu.currentPacProviderKey || 'none'; const id = antiCensorRu.currentPacProviderKey || 'none';