Fix undefined uiRaw in popup, add gulp building mini-version, rm micro-version
|
@ -1 +0,0 @@
|
||||||
Blue Ribbon Icon: http://www.iconsdb.com/icon-sets/cardboard-blue-icons/ribbon-12-icon.html
|
|
|
@ -1,313 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
console.log('Started.');
|
|
||||||
|
|
||||||
window.state = {
|
|
||||||
lastError: null,
|
|
||||||
ifNotControllable: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
window.whichExtensionHtml = `
|
|
||||||
|
|
||||||
${chrome.i18n.getMessage('noControl')}
|
|
||||||
<a href="chrome://settings/search#${chrome.i18n.getMessage('proxy')}">
|
|
||||||
${chrome.i18n.getMessage('which')}
|
|
||||||
</a>`;
|
|
||||||
|
|
||||||
const resetBadge = function resetBadge() {
|
|
||||||
|
|
||||||
okBadge('M');
|
|
||||||
chrome.browserAction.setTitle({title: ''});
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
window.timeouted = (cb) => (...args) => window.setTimeout(() => cb(...args), 0);
|
|
||||||
|
|
||||||
const errorJsonReplacer = function errorJsonReplacer(key, value) {
|
|
||||||
|
|
||||||
// fooWindow.ErrorEvent !== barWindow.ErrorEvent
|
|
||||||
if (!( value && value.constructor
|
|
||||||
&& ['Error', 'Event'].some(
|
|
||||||
(suff) => value.constructor.name.endsWith(suff)
|
|
||||||
)
|
|
||||||
)) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
const alt = {};
|
|
||||||
|
|
||||||
Object.getOwnPropertyNames(value).forEach(function(key) {
|
|
||||||
|
|
||||||
alt[key] = value[key];
|
|
||||||
|
|
||||||
}, value);
|
|
||||||
|
|
||||||
for(const prop in value) {
|
|
||||||
if (/^[A-Z]/.test(prop)) {
|
|
||||||
// MOUSEMOVE, CLICK, KEYUP, NONE, etc.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
alt[prop] = value[prop];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value.constructor.name === 'ErrorEvent') {
|
|
||||||
for(const circularProp of
|
|
||||||
[ // First line are circular props.
|
|
||||||
'target', 'srcElement', 'path', 'currentTarget',
|
|
||||||
'bubbles', 'cancelBubble', 'cancelable', 'composed',
|
|
||||||
'defaultPrevented', 'eventPhase', 'isTrusted', 'returnValue',
|
|
||||||
'timeStamp']) {
|
|
||||||
delete alt[circularProp];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value.name) {
|
|
||||||
alt.name = value.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return alt;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const extName = chrome.runtime.getManifest().name;
|
|
||||||
|
|
||||||
chrome.notifications.onClicked.addListener( timeouted( (notId) => {
|
|
||||||
|
|
||||||
chrome.notifications.clear(notId);
|
|
||||||
const err = window.state.lastError;
|
|
||||||
err.extName = extName;
|
|
||||||
const type = 'ext-error';
|
|
||||||
const json = JSON.stringify(err, errorJsonReplacer, 0);
|
|
||||||
const url = 'http://rebrand.ly/ac-error/?json=' + encodeURIComponent(json)
|
|
||||||
+ (type ? '&type=' + encodeURIComponent(type) : '')
|
|
||||||
+ '&version=' + chrome.runtime.getManifest().version;
|
|
||||||
chrome.tabs.create(
|
|
||||||
{url: url}
|
|
||||||
);
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
const mayNotify = function mayNotify(
|
|
||||||
id, title, errOrMessage,
|
|
||||||
{
|
|
||||||
icon = 'default-128.png',
|
|
||||||
ifSticky = true,
|
|
||||||
} = {}
|
|
||||||
) {
|
|
||||||
|
|
||||||
const message = errOrMessage.message || errOrMessage.toString();
|
|
||||||
chrome.notifications.create(
|
|
||||||
id,
|
|
||||||
{
|
|
||||||
title: title,
|
|
||||||
message: message,
|
|
||||||
contextMessage:
|
|
||||||
extName + ' ' + chrome.runtime.getManifest().version.replace(/\d+\.\d+\./g, ''),
|
|
||||||
requireInteraction: ifSticky,
|
|
||||||
type: 'basic',
|
|
||||||
iconUrl: './icons/' + icon,
|
|
||||||
isClickable: true,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
window.installListenersOn = function installListenersOn(win, name, cb) {
|
|
||||||
|
|
||||||
win.addEventListener('error', (errEvent) => {
|
|
||||||
|
|
||||||
window.state.lastError = errEvent;
|
|
||||||
console.warn(name + ':GLOBAL ERROR', errEvent);
|
|
||||||
mayNotify('ext-error', 'Ошибка расширения!', errEvent, {icon: 'ext-error-128.png'});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
win.addEventListener('unhandledrejection', (event) => {
|
|
||||||
|
|
||||||
console.warn(name + ': Unhandled rejection. Throwing error.');
|
|
||||||
event.preventDefault();
|
|
||||||
console.log('ev', event);
|
|
||||||
throw event.reason;
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
if (cb) {
|
|
||||||
// In most cases getBackgroundPage( (bg) => installListenersOn
|
|
||||||
// Without setTimeout errors are swallowed, bug #357568
|
|
||||||
timeouted(cb)();
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
window.installListenersOn(window, 'BG');
|
|
||||||
|
|
||||||
const redBadge = function redBadge(msg) {
|
|
||||||
|
|
||||||
chrome.browserAction.setBadgeBackgroundColor({
|
|
||||||
color: '#db4b2f',
|
|
||||||
});
|
|
||||||
chrome.browserAction.setBadgeText({
|
|
||||||
text: msg,
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const defaultColorPromise = new Promise( function (resolve) {
|
|
||||||
|
|
||||||
chrome.browserAction.getBadgeBackgroundColor({}, resolve);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
const okBadge = function okBadge(msg) {
|
|
||||||
|
|
||||||
defaultColorPromise.then( function (defaultColor) {
|
|
||||||
chrome.browserAction.setBadgeBackgroundColor({
|
|
||||||
color: defaultColor,
|
|
||||||
});
|
|
||||||
chrome.browserAction.setBadgeText({
|
|
||||||
text: msg,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const mandatory = (err) => {
|
|
||||||
|
|
||||||
throw new TypeError('This arg is required!');
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const throwIfError = (err) => {
|
|
||||||
|
|
||||||
if (err) {
|
|
||||||
throw new Error('Got error in cb!');
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const areSettingsNotControllableFor = function areSettingsNotControllable(details = mandatory()) {
|
|
||||||
|
|
||||||
state.ifNotControllable = ['controlled_by_other', 'not_controllable']
|
|
||||||
.some( (pref) => details.levelOfControl.startsWith(pref) );
|
|
||||||
|
|
||||||
if (state.ifNotControllable) {
|
|
||||||
console.warn('Failed, other extension is in control.');
|
|
||||||
state.ifNotControlled = true;
|
|
||||||
redBadge('xCTRL');
|
|
||||||
chrome.browserAction.setTitle({title: 'Другое расширение контролирует прокси'});
|
|
||||||
} else {
|
|
||||||
console.log('Settings are under our control.');
|
|
||||||
state.ifNotControlled = !details.levelOfControl.startsWith('controlled_by_this');
|
|
||||||
resetBadge();
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
chrome.proxy.settings.onChange.addListener( (details) => {
|
|
||||||
|
|
||||||
console.log('CHANGED prx');
|
|
||||||
areSettingsNotControllableFor(details);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
const updateControlState = function updateControlState(cb = mandatory()) {
|
|
||||||
|
|
||||||
chrome.proxy.settings.get({}, timeouted( (details) => {
|
|
||||||
|
|
||||||
areSettingsNotControllableFor(details);
|
|
||||||
cb();
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const mayUpdatePac = function mayUpdatePac(cb = mandatory()) {
|
|
||||||
|
|
||||||
if (Date.now() < (localStorage.lastPacUpdateStamp || 0) + 12*60*60*1000 ) {
|
|
||||||
console.log('Too early for an update.' );
|
|
||||||
return cb();
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch('https://rebrand.ly/ac-light-pac').then(
|
|
||||||
(res) => {
|
|
||||||
|
|
||||||
const status = res.status;
|
|
||||||
if ( !( status >= 200 && status < 300 || status === 304 ) ) {
|
|
||||||
return cb(new Error('Не удалось скачать скрипт, ошибка ' + status));
|
|
||||||
}
|
|
||||||
return res.text();
|
|
||||||
|
|
||||||
},
|
|
||||||
cb
|
|
||||||
).then( (pacData) => {
|
|
||||||
|
|
||||||
console.log('Updating PAC...');
|
|
||||||
chrome.proxy.settings.set(
|
|
||||||
{
|
|
||||||
value: {
|
|
||||||
mode: 'pac_script',
|
|
||||||
pacScript: {
|
|
||||||
// Use only with extension!
|
|
||||||
data: pacData
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
timeouted(() => {
|
|
||||||
|
|
||||||
const err = chrome.runtime.lastError || chrome.extension.lastError;
|
|
||||||
if(err) {
|
|
||||||
console.log('Updated with error:', err);
|
|
||||||
state.lastError = err;
|
|
||||||
redBadge('ERR');
|
|
||||||
chrome.browserAction.setTitle({title: 'Произошла ошибка'});
|
|
||||||
setTimeout(resetBadge, 10000);
|
|
||||||
return cb(err);
|
|
||||||
}
|
|
||||||
console.log('Updated, no errors.');
|
|
||||||
localStorage.lastPacUpdateStamp = Date.now();
|
|
||||||
updateControlState( () => {
|
|
||||||
|
|
||||||
if(state.ifNotControlled) {
|
|
||||||
cb(new Error(window.whichExtensionHtml));
|
|
||||||
} else {
|
|
||||||
cb();
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
},
|
|
||||||
cb
|
|
||||||
);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
window.switchPac = function switchPac(onOff, cb = mandatory()) {
|
|
||||||
|
|
||||||
if(onOff !== 'off') {
|
|
||||||
localStorage.onOff = 'on';
|
|
||||||
chrome.browserAction.setIcon( {path: './icons/default-128.png'} );
|
|
||||||
return mayUpdatePac(cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
chrome.proxy.settings.clear({}, timeouted(() => {
|
|
||||||
|
|
||||||
localStorage.lastPacUpdateStamp = 0;
|
|
||||||
localStorage.onOff = 'off';
|
|
||||||
chrome.browserAction.setIcon({
|
|
||||||
path: './icons/default-grayscale-128.png',
|
|
||||||
});
|
|
||||||
cb();
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
resetBadge();
|
|
||||||
switchPac( localStorage.onOff, (err) => {
|
|
||||||
|
|
||||||
updateControlState(() => throwIfError(err));
|
|
||||||
|
|
||||||
});
|
|
|
@ -1,17 +0,0 @@
|
||||||
{
|
|
||||||
"extName": {
|
|
||||||
"message": "Облегчённый обход блокировок Рунета"
|
|
||||||
},
|
|
||||||
"extDesc": {
|
|
||||||
"message": "Обход интернет-цензуры в России: https://rebrand.ly/ac-wiki"
|
|
||||||
},
|
|
||||||
"proxy": {
|
|
||||||
"message": "прокси"
|
|
||||||
},
|
|
||||||
"noControl": {
|
|
||||||
"message": "Другое расширение контролирует настройки прокси!"
|
|
||||||
},
|
|
||||||
"which": {
|
|
||||||
"message": "Какое?"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,111 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html style="display: none; will-change: display">
|
|
||||||
<head>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
.hor-padded {
|
|
||||||
padding-left: 1.4em;
|
|
||||||
padding-right: 1.4em;
|
|
||||||
}
|
|
||||||
header, .control-row {
|
|
||||||
white-space: nowrap;
|
|
||||||
word-break: keep-all;
|
|
||||||
}
|
|
||||||
input[type="radio"], label {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.control-row {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
margin: 2em 1em 1em;
|
|
||||||
}
|
|
||||||
header {
|
|
||||||
padding-bottom: 0.4em;
|
|
||||||
}
|
|
||||||
hr {
|
|
||||||
border-width: 1px 0 0 0;
|
|
||||||
margin: 0 0 0.6em 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
.greeting {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
:root:not(.if-error) .greeting {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
:root:not(.if-not-controlled) .if-not-controlled,
|
|
||||||
:root:not(.if-error) .if-error
|
|
||||||
{
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.ver-padded {
|
|
||||||
padding-top: 1em;
|
|
||||||
padding-bottom: 1em;
|
|
||||||
}
|
|
||||||
.centered {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.warn {
|
|
||||||
background-color: red;
|
|
||||||
color: white;
|
|
||||||
font-weight: bold;
|
|
||||||
|
|
||||||
border-bottom: 1px solid #bfbfbf;
|
|
||||||
}
|
|
||||||
.warn a {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
header, main {
|
|
||||||
border-bottom: 1px solid #bfbfbf;
|
|
||||||
}
|
|
||||||
ul, ol {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
list-style-type: none;
|
|
||||||
}
|
|
||||||
li, li > * {
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
#pac-switch {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-around;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
#pac-switch li {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 1em;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<section class="if-not-controlled warn hor-padded ver-padded centered" id="which-extension"></section>
|
|
||||||
<header class="hor-padded">
|
|
||||||
<h2>Обход блокировок Рунета МИКРО</h2>
|
|
||||||
</header>
|
|
||||||
<main class="hor-padded ver-padded">
|
|
||||||
<section>
|
|
||||||
<ol id="pac-switch">
|
|
||||||
<li><input type="radio" value="on" id="pac-on" name="pac-switch"/> <label for="pac-on">ON</label></li>
|
|
||||||
<li><input type="radio" value="off" id="pac-off" name="pac-switch"/> <label for="pac-off">OFF</label></li>
|
|
||||||
</ol>
|
|
||||||
</section>
|
|
||||||
</main>
|
|
||||||
<footer>
|
|
||||||
<section id="status" class="greeting hor-padded" style="padding-top: 0.5em; padding-bottom: 0">
|
|
||||||
Данная версия предназначена для слабых компьютеров, она не сообщает о разблокировках и не имеет настроек.
|
|
||||||
</section>
|
|
||||||
<section class="if-error centered">
|
|
||||||
<div>Ошибка!</div>
|
|
||||||
<span id="last-error"></span>
|
|
||||||
</section>
|
|
||||||
<div class="control-row">
|
|
||||||
<input type="button" value="Готово" class="close-button"> <a href="../debug/index.html" style="text-decoration: none; margin-left: 1em;">Полная версия расширения</a>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
<script src="./index.js"></script>
|
|
||||||
<script src="./keep-links-clickable.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,61 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
chrome.runtime.getBackgroundPage( (backgroundPage) => {
|
|
||||||
|
|
||||||
const state = backgroundPage.state;
|
|
||||||
|
|
||||||
if( state.ifNotControllable ) {
|
|
||||||
document.getElementById('which-extension').innerHTML = backgroundPage.whichExtensionHtml;
|
|
||||||
document.documentElement.classList.add('if-not-controlled');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( state.lastError) {
|
|
||||||
|
|
||||||
const err = ['message', 'stack', 'name'].reduce((acc, prop) => {
|
|
||||||
|
|
||||||
acc[prop] = state.lastError[prop];
|
|
||||||
return acc;
|
|
||||||
|
|
||||||
}, {});
|
|
||||||
document.getElementById('last-error').innerHTML = JSON.stringify(err);
|
|
||||||
document.documentElement.classList.add('if-error');
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const setStatusTo = (msg) => {
|
|
||||||
document.getElementById('status').innerHTML = msg;
|
|
||||||
};
|
|
||||||
|
|
||||||
if(localStorage.onOff === 'on') {
|
|
||||||
document.getElementById('pac-on').checked = true;
|
|
||||||
} else {
|
|
||||||
document.getElementById('pac-off').checked = true;
|
|
||||||
}
|
|
||||||
document.getElementById('pac-switch').onclick = function(event) {
|
|
||||||
|
|
||||||
if(event.target.tagName !== 'INPUT') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
setStatusTo('Ждите...');
|
|
||||||
const cb = () => {
|
|
||||||
|
|
||||||
event.target.checked = true;
|
|
||||||
setStatusTo('Готово!');
|
|
||||||
|
|
||||||
};
|
|
||||||
if (event.target.id === 'pac-on') {
|
|
||||||
backgroundPage.switchPac('on', cb);
|
|
||||||
} else {
|
|
||||||
backgroundPage.switchPac('off', cb);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// CLOSE BUTTON
|
|
||||||
|
|
||||||
document.querySelector('.close-button').onclick = () => window.close();
|
|
||||||
|
|
||||||
document.documentElement.style.display = '';
|
|
||||||
|
|
||||||
});
|
|
4
extensions/chromium/runet-censorship-bypass/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
node_modules
|
||||||
|
npm-debug.log
|
||||||
|
.swp
|
||||||
|
build/
|
0
extensions/chromium/runet-censorship-bypass/README.md
Executable file → Normal file
|
@ -1,49 +0,0 @@
|
||||||
'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(
|
|
||||||
'Сайт доступен из-за границы?',
|
|
||||||
(tab) => `data:text/html;charset=utf8,<title>Запрашиваю...</title>
|
|
||||||
<form class='tracker-form' method='POST'
|
|
||||||
action='https://www.host-tracker.com/ru/InstantCheck/Create'>
|
|
||||||
<input name='InstantCheckUrl' value='${new URL(tab.url).hostname}'
|
|
||||||
type='hidden'>
|
|
||||||
</form>
|
|
||||||
<script>document.querySelector('.tracker-form').submit()<\/script>`
|
|
||||||
);
|
|
||||||
|
|
||||||
createMenuLinkEntry(
|
|
||||||
'Сайт в реестре блокировок?',
|
|
||||||
(tab) => 'https://antizapret.info/index.php?search=' + new URL(tab.url).hostname
|
|
||||||
);
|
|
||||||
|
|
||||||
createMenuLinkEntry(
|
|
||||||
'Из архива archive.org',
|
|
||||||
(tab) => 'https://web.archive.org/web/*/' + tab.url
|
|
||||||
);
|
|
||||||
|
|
||||||
createMenuLinkEntry(
|
|
||||||
'Через Google Translate',
|
|
||||||
(tab) => 'https://translate.google.com/translate?hl=&sl=en&tl=ru&anno=2&sandbox=1&u=' + tab.url
|
|
||||||
);
|
|
||||||
|
|
||||||
createMenuLinkEntry(
|
|
||||||
'Другие варианты разблокировки',
|
|
||||||
(tab) => 'https://rebrand.ly/ac-unblock#' + tab.url
|
|
||||||
);
|
|
||||||
|
|
||||||
createMenuLinkEntry(
|
|
||||||
'Руководство / Помощь / Ссылки',
|
|
||||||
(tab) => 'https://rebrand.ly/ac-wiki'
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
{
|
|
||||||
"extName": {
|
|
||||||
"message": "Runet Censorship Bypass"
|
|
||||||
},
|
|
||||||
"extDesc": {
|
|
||||||
"message": "Circumvent Russian Internet Censorship: https://rebrand.ly/ac-wiki"
|
|
||||||
},
|
|
||||||
"proxy": {
|
|
||||||
"message": "proxy"
|
|
||||||
},
|
|
||||||
"noControl": {
|
|
||||||
"message": "Other extension controls proxy!"
|
|
||||||
},
|
|
||||||
"which": {
|
|
||||||
"message": "Which?"
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 9.3 KiB |
|
@ -1,37 +0,0 @@
|
||||||
'use strict';
|
|
||||||
/*
|
|
||||||
In popup links are not clickable at all, fix it.
|
|
||||||
On other pages "chrome://" links are not clickable, fix it.
|
|
||||||
Use only if really required because of performance penalty.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
|
|
||||||
const target = document.documentElement;
|
|
||||||
|
|
||||||
const updateLinks = () => {
|
|
||||||
|
|
||||||
const links = document.querySelectorAll('a:not([href=""])');
|
|
||||||
for (let i = 0; i < links.length; i++) {
|
|
||||||
const ln = links[i];
|
|
||||||
const location = ln.href;
|
|
||||||
ln.onclick = function() {
|
|
||||||
|
|
||||||
chrome.tabs.create({active: !this.dataset.inBg, url: location});
|
|
||||||
return false;
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
new MutationObserver( updateLinks )
|
|
||||||
.observe(target, {
|
|
||||||
attributes: true,
|
|
||||||
subtree: true,
|
|
||||||
childList: true,
|
|
||||||
characterData: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', updateLinks);
|
|
||||||
|
|
||||||
}
|
|
86
extensions/chromium/runet-censorship-bypass/gulpfile.js
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const gulp = require('gulp');
|
||||||
|
const del = require('del');
|
||||||
|
const through = require('through2');
|
||||||
|
const PluginError = require('gulp-util').PluginError;
|
||||||
|
|
||||||
|
const PluginName = 'Template literals';
|
||||||
|
|
||||||
|
const templatePlugin = (context) => through.obj(function(file, encoding, cb) {
|
||||||
|
|
||||||
|
const tjson = '.tmpl.json';
|
||||||
|
if (file.path.endsWith(tjson)) {
|
||||||
|
|
||||||
|
file.path = file.path.replace(new RegExp(`${tjson}$`), '.json');
|
||||||
|
|
||||||
|
if (file.isStream()) {
|
||||||
|
return cb(new PluginError(PluginName, 'Streams not supported!'));
|
||||||
|
} else if (file.isBuffer()) {
|
||||||
|
|
||||||
|
const stringsContext = new Proxy(context, {
|
||||||
|
get: function(target, prop) {
|
||||||
|
return target[prop] || '';
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
file.contents = new Buffer(
|
||||||
|
(new Function('ctx', 'return `' + String(file.contents) + '`;'))(stringsContext)
|
||||||
|
);
|
||||||
|
} catch(e) {
|
||||||
|
return cb(new PluginError(PluginName, e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
cb(null, file);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('default', ['build']);
|
||||||
|
|
||||||
|
gulp.task('clean', function() {
|
||||||
|
|
||||||
|
return del.sync('./build');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
const commonContext = {
|
||||||
|
version: '0.19',
|
||||||
|
};
|
||||||
|
|
||||||
|
const contextMini = Object.assign({
|
||||||
|
nameSuffixEn: ' MINI',
|
||||||
|
nameSuffixRu: ' МИНИ',
|
||||||
|
}, commonContext);
|
||||||
|
|
||||||
|
gulp.task('_cp-common', ['clean'], function() {
|
||||||
|
|
||||||
|
gulp.src(['./src/extension-common/**/*'])
|
||||||
|
.pipe(templatePlugin(contextMini))
|
||||||
|
.pipe(gulp.dest('./build/extension-mini'))
|
||||||
|
|
||||||
|
gulp.src(['./src/extension-common/**/*'])
|
||||||
|
.pipe(templatePlugin(commonContext))
|
||||||
|
.pipe(gulp.dest('./build/extension-full'));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('_cp-mini', ['_cp-common'], function() {
|
||||||
|
|
||||||
|
gulp.src(['./src/extension-mini/**/*'])
|
||||||
|
.pipe(templatePlugin(contextMini))
|
||||||
|
.pipe(gulp.dest('./build/extension-mini'));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('_cp-full', ['_cp-common'], function() {
|
||||||
|
|
||||||
|
gulp.src(['./src/extension-full/**/*'])
|
||||||
|
.pipe(templatePlugin(commonContext))
|
||||||
|
.pipe(gulp.dest('./build/extension-full'));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('build', ['_cp-mini', '_cp-full']);
|
0
extensions/chromium/runet-censorship-bypass/kasparov.ru-title.jpg
Executable file → Normal file
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 77 KiB |
0
extensions/chromium/runet-censorship-bypass/krrb-kiwiirc-irccloud-slideshare.jpg
Executable file → Normal file
Before Width: | Height: | Size: 306 KiB After Width: | Height: | Size: 306 KiB |
|
@ -1,10 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "russian-censorship-bypass",
|
"name": "runet-censorship-bypass",
|
||||||
"version": "0.0.15",
|
"version": "0.0.19",
|
||||||
"description": "Development tools for chromium extension",
|
"description": "Development tools for chromium extension",
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
|
||||||
"lint": "./node_modules/.bin/eslint ./runet-censorship-bypass/extension/**/*.js --ignore-pattern vendor"
|
"lint": "./node_modules/.bin/eslint ./runet-censorship-bypass/extension/**/*.js --ignore-pattern vendor"
|
||||||
},
|
},
|
||||||
"author": "Ilya Ig. Petrov",
|
"author": "Ilya Ig. Petrov",
|
||||||
|
@ -12,5 +10,10 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^3.15.0",
|
"eslint": "^3.15.0",
|
||||||
"eslint-config-google": "^0.7.1"
|
"eslint-config-google": "^0.7.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"del": "^2.2.2",
|
||||||
|
"gulp": "^3.9.1",
|
||||||
|
"through2": "^2.0.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
0
extensions/chromium/runet-censorship-bypass/slideshare-menu.jpg
Executable file → Normal file
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 85 KiB |
|
@ -84,6 +84,18 @@
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
addEventHandler(type, handler) {
|
||||||
|
|
||||||
|
document.addEventListener(type, (event) => handler(...event.detail));
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
fireEvent(type, ...args) {
|
||||||
|
|
||||||
|
document.dispatchEvent( new CustomEvent(type, { detail: args }) );
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
createStorage(prefix) {
|
createStorage(prefix) {
|
||||||
|
|
||||||
return function state(key, value) {
|
return function state(key, value) {
|
|
@ -113,7 +113,6 @@
|
||||||
|
|
||||||
isControllable(details) {
|
isControllable(details) {
|
||||||
|
|
||||||
console.log('IS',details);
|
|
||||||
this.ifControllable = window.utils.areSettingsControllableFor(details);
|
this.ifControllable = window.utils.areSettingsControllableFor(details);
|
||||||
|
|
||||||
if (this.ifControllable) {
|
if (this.ifControllable) {
|
|
@ -321,10 +321,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const hosts = par.map( (ps) => ps.split(/\s+/)[1] );
|
const hosts = par.map( (ps) => ps.split(/\s+/)[1] );
|
||||||
window.apis.ipToHost.replaceAllAsync(
|
window.utils.fireEvent('ip-to-host-replace-all', hosts, throwIfError);
|
||||||
|
cb(null, null, ...warns);
|
||||||
|
/*window.apis.ipToHost.replaceAllAsync(
|
||||||
hosts,
|
hosts,
|
||||||
(...args) => cb(...args, ...warns)
|
(...args) => cb(...args, ...warns)
|
||||||
);
|
);*/
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
|
@ -93,7 +93,9 @@
|
||||||
'Getting IPs for PAC hosts...',
|
'Getting IPs for PAC hosts...',
|
||||||
cb
|
cb
|
||||||
);
|
);
|
||||||
window.apis.ipToHost.updateAllAsync(cb);
|
window.utils.fireEvent('ip-to-host-update-all', throwIfError);
|
||||||
|
cb();
|
||||||
|
//window.apis.ipToHost.updateAllAsync(cb);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -197,7 +199,7 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
_currentPacProviderKey: 'Антицензорити',
|
_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.
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
|
const timeouted = window.utils.timeouted;
|
||||||
|
|
||||||
let seqId = 0;
|
let seqId = 0;
|
||||||
|
|
||||||
const createMenuLinkEntry = (title, tab2url) => {
|
const createMenuLinkEntry = (title, tab2url) => {
|
||||||
|
@ -17,7 +19,7 @@
|
||||||
|
|
||||||
const err = chrome.runtime.lastError;
|
const err = chrome.runtime.lastError;
|
||||||
if(err) {
|
if(err) {
|
||||||
console.warn('CTX MENU ERR', err);
|
console.warn('Context menu error:', err);
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Files of this directory must be copied into final build without modifications.
|
|
@ -1,9 +1,9 @@
|
||||||
{
|
{
|
||||||
"extName": {
|
"extName": {
|
||||||
"message": "Runet Censorship Bypass MICRO"
|
"message": "Runet Censorship Bypass${ctx.nameSuffixEn}"
|
||||||
},
|
},
|
||||||
"extDesc": {
|
"extDesc": {
|
||||||
"message": "Circumvent Russian Internet Censorship: https://rebrand.ly/ac-wiki"
|
"message": "Circumvent Russian Internet Censorship: https://rebrand.ly/ac-wiki"
|
||||||
},
|
},
|
||||||
"proxy": {
|
"proxy": {
|
||||||
"message": "proxy"
|
"message": "proxy"
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"extName": {
|
"extName": {
|
||||||
"message": "Обход блокировок Рунета"
|
"message": "Обход блокировок Рунета${ctx.nameSuffixRu}"
|
||||||
},
|
},
|
||||||
"extDesc": {
|
"extDesc": {
|
||||||
"message": "Обход интернет-цензуры в России: https://rebrand.ly/ac-wiki"
|
"message": "Обход интернет-цензуры в России: https://rebrand.ly/ac-wiki"
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.8 KiB |
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 9.6 KiB |
|
@ -226,7 +226,7 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// IF INSIDE OPTIONS
|
// IF INSIDE OPTIONS TAB
|
||||||
|
|
||||||
const currentTab = await new Promise(
|
const currentTab = await new Promise(
|
||||||
(resolve) => chrome.tabs.query(
|
(resolve) => chrome.tabs.query(
|
||||||
|
@ -503,6 +503,7 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
|
||||||
const _firstChild = modPanel.firstChild;
|
const _firstChild = modPanel.firstChild;
|
||||||
const keyToLi = {};
|
const keyToLi = {};
|
||||||
const customProxyStringKey = 'customProxyStringRaw';
|
const customProxyStringKey = 'customProxyStringRaw';
|
||||||
|
const uiRaw = 'ui-proxy-string-raw';
|
||||||
|
|
||||||
for(const conf of pacKitchen.getOrderedConfigs()) {
|
for(const conf of pacKitchen.getOrderedConfigs()) {
|
||||||
|
|
||||||
|
@ -518,7 +519,6 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
|
||||||
if (key !== customProxyStringKey) {
|
if (key !== customProxyStringKey) {
|
||||||
li.innerHTML += infoSign(conf.desc);
|
li.innerHTML += infoSign(conf.desc);
|
||||||
} else {
|
} else {
|
||||||
const uiRaw = 'ui-proxy-string-raw';
|
|
||||||
li.innerHTML += `<a href="${conf.url}" class="info-sign info-url">🛈</a><br/>
|
li.innerHTML += `<a href="${conf.url}" class="info-sign info-url">🛈</a><br/>
|
||||||
<textarea
|
<textarea
|
||||||
spellcheck="false"
|
spellcheck="false"
|
|
@ -186,7 +186,7 @@
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
window.apis.ipToHost = {
|
const self = window.apis.ipToHost = {
|
||||||
|
|
||||||
persist() {
|
persist() {
|
||||||
|
|
||||||
|
@ -276,20 +276,6 @@
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
updateAllAsync(cb = mandatory()) {
|
|
||||||
|
|
||||||
this._updateAllAsync((err, ...args) => {
|
|
||||||
|
|
||||||
if (!err) {
|
|
||||||
this.persist();
|
|
||||||
}
|
|
||||||
cb(err, ...args);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
_replaceAllAsync(hostArr = mandatory(), cb) {
|
_replaceAllAsync(hostArr = mandatory(), cb) {
|
||||||
|
|
||||||
if (typeof(hostArr) === 'function') {
|
if (typeof(hostArr) === 'function') {
|
||||||
|
@ -306,6 +292,21 @@
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// PUBLIC
|
||||||
|
|
||||||
|
updateAllAsync(cb = mandatory()) {
|
||||||
|
|
||||||
|
this._updateAllAsync((err, ...args) => {
|
||||||
|
|
||||||
|
if (!err) {
|
||||||
|
this.persist();
|
||||||
|
}
|
||||||
|
cb(err, ...args);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
replaceAllAsync(addrArr, cb = mandatory()) {
|
replaceAllAsync(addrArr, cb = mandatory()) {
|
||||||
|
|
||||||
console.log('Replacing...');
|
console.log('Replacing...');
|
||||||
|
@ -336,4 +337,7 @@
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
window.utils.addEventHandler('ip-to-host-update-all', (...args) => self.updateAllAsync(...args) );
|
||||||
|
window.utils.addEventHandler('ip-to-host-replace-all', (...args) => self.replaceAllAsync(...args) );
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
{
|
{
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
|
|
||||||
"name": "__MSG_extName__ 0.19",
|
"name": "__MSG_extName__",
|
||||||
"default_locale": "ru",
|
"default_locale": "ru",
|
||||||
"description": "__MSG_extDesc__",
|
"description": "__MSG_extDesc__",
|
||||||
"version": "0.0.0.19",
|
"version": "0.0.${ctx.version}",
|
||||||
"icons": {
|
"icons": {
|
||||||
"128": "/icons/default-128.png"
|
"128": "/icons/default-128.png"
|
||||||
},
|
},
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"browser_action": {
|
"browser_action": {
|
||||||
"default_title": "Этот сайт благословлён 0.19",
|
"default_title": "Этот сайт благословлён ${ctx.version}",
|
||||||
"default_popup": "/pages/choose-pac-provider/index.html"
|
"default_popup": "/pages/choose-pac-provider/index.html"
|
||||||
},
|
},
|
||||||
"options_ui": {
|
"options_ui": {
|
|
@ -0,0 +1,7 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
chrome.browserAction.setBadgeText({text: 'M'});
|
||||||
|
|
||||||
|
}
|
|
@ -1,18 +1,20 @@
|
||||||
{
|
{
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
|
|
||||||
"name": "__MSG_extName__ 0.17",
|
"name": "__MSG_extName__",
|
||||||
"default_locale": "ru",
|
"default_locale": "ru",
|
||||||
"description": "__MSG_extDesc__",
|
"description": "__MSG_extDesc__",
|
||||||
"version": "0.0.0.17",
|
"version": "0.0.${ctx.version}",
|
||||||
"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",
|
||||||
|
"alarms",
|
||||||
|
"storage",
|
||||||
"<all_urls>",
|
"<all_urls>",
|
||||||
"tabs",
|
"tabs",
|
||||||
"contextMenus",
|
"contextMenus",
|
||||||
|
@ -22,16 +24,22 @@
|
||||||
"background": {
|
"background": {
|
||||||
"persistent": false,
|
"persistent": false,
|
||||||
"scripts": [
|
"scripts": [
|
||||||
"00-set-pac.js",
|
"00-init-apis.js",
|
||||||
"40-context-menus.js"
|
"11-error-handlers-api.js",
|
||||||
|
"12-errors-lib.js",
|
||||||
|
"13-http-lib.js",
|
||||||
|
"15-pac-kitchen-api.js",
|
||||||
|
"17-sync-pac-script-with-pac-provider-api.js",
|
||||||
|
"40-context-menus.js",
|
||||||
|
"50-for-mini-only.js"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"browser_action": {
|
"browser_action": {
|
||||||
"default_title": "Этот сайт благословлён 0.17",
|
"default_title": "Этот сайт благословлён ${ctx.version}-mini",
|
||||||
"default_popup": "pages/show-state/index.html"
|
"default_popup": "/pages/choose-pac-provider/index.html"
|
||||||
},
|
},
|
||||||
"options_ui": {
|
"options_ui": {
|
||||||
"page": "pages/show-state/index.html",
|
"page": "/pages/choose-pac-provider/index.html",
|
||||||
"chrome_style": true
|
"chrome_style": true
|
||||||
}
|
}
|
||||||
}
|
}
|