diff --git a/extensions/chromium/runet-censorship-bypass-light/extension/00-init-apis.js b/extensions/chromium/runet-censorship-bypass-light/extension/00-init-apis.js
deleted file mode 100644
index deeea8e..0000000
--- a/extensions/chromium/runet-censorship-bypass-light/extension/00-init-apis.js
+++ /dev/null
@@ -1,33 +0,0 @@
-'use strict';
-
-window.utils = {
-
- areSettingsNotControlledFor(details) {
-
- return ['controlled_by_other', 'not_controllable']
- .some( (prefix) => details.levelOfControl.startsWith(prefix) );
-
- },
-
- messages: {
-
- searchSettingsForUrl(niddle) {
-
- return 'chrome://settings/search#' + (chrome.i18n.getMessage(niddle) || niddle);
-
- },
-
- whichExtensionHtml() {
-
- return chrome.i18n.getMessage('noControl') +
- `
- ${ chrome.i18n.getMessage('which') }
- `;
-
- },
-
- },
-
-};
-
-window.apis = {};
diff --git a/extensions/chromium/runet-censorship-bypass-light/extension/00-set-pac.js b/extensions/chromium/runet-censorship-bypass-light/extension/00-set-pac.js
new file mode 100644
index 0000000..7329e6e
--- /dev/null
+++ b/extensions/chromium/runet-censorship-bypass-light/extension/00-set-pac.js
@@ -0,0 +1,313 @@
+'use strict';
+
+console.log('Started.');
+
+window.state = {
+ lastError: null,
+ ifNotControllable: false,
+};
+
+window.whichExtensionHtml = `
+
+ ${chrome.i18n.getMessage('noControl')}
+
+ ${chrome.i18n.getMessage('which')}
+ `;
+
+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));
+
+});
diff --git a/extensions/chromium/runet-censorship-bypass-light/extension/12-set-pac-url.js b/extensions/chromium/runet-censorship-bypass-light/extension/12-set-pac-url.js
deleted file mode 100644
index 42bb04b..0000000
--- a/extensions/chromium/runet-censorship-bypass-light/extension/12-set-pac-url.js
+++ /dev/null
@@ -1,91 +0,0 @@
-'use strict';
-
-window.state = {
- lastError: null,
- ifNotControlled: false
-};
-
-function redBadge(msg) {
-
- window.chrome.browserAction.setBadgeBackgroundColor({
- color: '#db4b2f',
- });
- chrome.browserAction.setBadgeText({
- text: msg,
- });
-
-}
-
-let defaultColorPromise = new Promise( function (resolve) {
-
- chrome.browserAction.getBadgeBackgroundColor({}, resolve);
-
-});
-
-function okBadge(msg) {
-
- defaultColorPromise.then( function (defaultColor) {
- window.chrome.browserAction.setBadgeBackgroundColor({
- color: defaultColor,
- });
- chrome.browserAction.setBadgeText({
- text: msg,
- });
- });
-
-}
-
-function checkControlFor(details) {
-
- state.ifNotControlled = utils.areSettingsNotControlledFor(details);
- if (state.ifNotControlled) {
- console.warn('Failed, other extension is in control.');
- redBadge('xCTRL');
- } else {
- console.log('Successfuly set PAC in proxy settings..');
- okBadge('ok');
- }
-
-}
-
-chrome.proxy.settings.onChange.addListener( checkControlFor );
-
-chrome.proxy.onProxyError.addListener((details) => {
-
- console.error(details);
- //if (window.state.ifNotControlled) {
- // return;
- //}
-});
-
-chrome.proxy.settings.set(
- {
- value: {
- mode: 'pac_script',
- pacScript: {
- /*
- Don't use in system configs! Because Win does poor caching.
- Url is encoded to counter abuse.
- Source: CloudFlare
- */
- //url: 'https://anticensorship-russia.tk/generated-pac-scripts/on-switches-0.17.pac',
- //url: 'https://antizapret.prostovpn.org/proxy.pac',
- url: 'http://localhost:8080/on-switches-0.17.pac',
- mandatory: true
- //url: '\x68\x74\x74\x70\x73\x3a\x2f\x2f\x61\x6e\x74\x69\x63\x65\x6e\x73\x6f\x72\x73\x68\x69\x70\x2d\x72\x75\x73\x73\x69\x61\x2e\x74\x6b\x2f\x67\x65\x6e\x65\x72\x61\x74\x65\x64\x2d\x70\x61\x63\x2d\x73\x63\x72\x69\x70\x74\x73\x2f\x6f\x6e\x2d\x73\x77\x69\x74\x63\x68\x65\x73\x2d\x30\x2e\x31\x37\x2e\x70\x61\x63',
- },
- },
- },
- function() {
-
- const err = chrome.runtime.lastError || chrome.extension.lastError;
- if(err) {
- alert(333)
- redBadge('ERR');
- } else {
- alert(11);
- chrome.proxy.settings.get({}, checkControlFor);
- }
-
- }
-);
diff --git a/extensions/chromium/runet-censorship-bypass-light/extension/40-context-menus.js b/extensions/chromium/runet-censorship-bypass-light/extension/40-context-menus.js
index 2db6a12..038bf43 100644
--- a/extensions/chromium/runet-censorship-bypass-light/extension/40-context-menus.js
+++ b/extensions/chromium/runet-censorship-bypass-light/extension/40-context-menus.js
@@ -2,13 +2,38 @@
{
- 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}) ),
- });
+ let seqId = 0;
+
+ const createMenuLinkEntry = (title, tab2url) => {
+
+ const id = (++seqId).toString();
+
+ chrome.runtime.onInstalled.addListener(
+ () => chrome.contextMenus.create({
+ id: id,
+ title: title,
+ contexts: ['browser_action']
+ }, timeouted(() => {
+
+ const err = chrome.runtime.lastError;
+ if(err) {
+ console.warn('CTX MENU ERR', err);
+ throw err;
+ }
+
+ }))
+ );
+
+ chrome.contextMenus.onClicked.addListener((info, tab) => {
+
+ if(info.menuItemId === id) {
+ Promise.resolve( tab2url( tab ) )
+ .then( (url) => chrome.tabs.create({url: url}) );
+ }
+
+ });
+
+ };
createMenuLinkEntry(
'Сайт доступен из-за границы? Is up?',
diff --git a/extensions/chromium/runet-censorship-bypass-light/extension/_locales/en/messages.json b/extensions/chromium/runet-censorship-bypass-light/extension/_locales/en/messages.json
index ea37145..e221d4e 100644
--- a/extensions/chromium/runet-censorship-bypass-light/extension/_locales/en/messages.json
+++ b/extensions/chromium/runet-censorship-bypass-light/extension/_locales/en/messages.json
@@ -1,6 +1,6 @@
{
"extName": {
- "message": "Light Runet Censorship Bypass"
+ "message": "Runet Censorship Bypass MICRO"
},
"extDesc": {
"message": "Circumvent Russian Internet Censorship: https://rebrand.ly/ac-wiki"
diff --git a/extensions/chromium/runet-censorship-bypass-light/extension/icons/ext-error-128.png b/extensions/chromium/runet-censorship-bypass-light/extension/icons/ext-error-128.png
new file mode 100644
index 0000000..4317d1f
Binary files /dev/null and b/extensions/chromium/runet-censorship-bypass-light/extension/icons/ext-error-128.png differ
diff --git a/extensions/chromium/runet-censorship-bypass-light/extension/manifest.json b/extensions/chromium/runet-censorship-bypass-light/extension/manifest.json
index cdf7578..8c90cd7 100644
--- a/extensions/chromium/runet-censorship-bypass-light/extension/manifest.json
+++ b/extensions/chromium/runet-censorship-bypass-light/extension/manifest.json
@@ -13,8 +13,6 @@
"permissions": [
"proxy",
- "alarms",
- "storage",
"",
"tabs",
"contextMenus",
@@ -22,10 +20,10 @@
],
"background": {
- "persistent": true,
+ "persistent": false,
"scripts": [
- "00-init-apis.js",
- "12-set-pac-url.js"
+ "00-set-pac.js",
+ "40-context-menus.js"
]
},
"browser_action": {
diff --git a/extensions/chromium/runet-censorship-bypass-light/extension/pages/show-state/index.html b/extensions/chromium/runet-censorship-bypass-light/extension/pages/show-state/index.html
index 45fb4c2..42d1342 100644
--- a/extensions/chromium/runet-censorship-bypass-light/extension/pages/show-state/index.html
+++ b/extensions/chromium/runet-censorship-bypass-light/extension/pages/show-state/index.html
@@ -1,43 +1,111 @@
-
+
- Выбор провайдера PAC
-
- Обход блокировок Рунета облегчённый
+
+
+ Обход блокировок Рунета МИКРО
-
-
-
-
-
-
-
-
-
+
+
+
+
diff --git a/extensions/chromium/runet-censorship-bypass-light/extension/pages/show-state/index.js b/extensions/chromium/runet-censorship-bypass-light/extension/pages/show-state/index.js
index 0d55e8e..5389fba 100644
--- a/extensions/chromium/runet-censorship-bypass-light/extension/pages/show-state/index.js
+++ b/extensions/chromium/runet-censorship-bypass-light/extension/pages/show-state/index.js
@@ -4,30 +4,58 @@ chrome.runtime.getBackgroundPage( (backgroundPage) => {
const state = backgroundPage.state;
- if( state.ifNotControlled ) {
- document.getElementById('which-extension').innerHTML
- = backgroundPage.utils.messages.whichExtensionHtml();
- document.querySelectorAll('.if-not-controlled').forEach( (node) => {
-
- node.style.display = 'block';
-
- });
+ if( state.ifNotControllable ) {
+ document.getElementById('which-extension').innerHTML = backgroundPage.whichExtensionHtml;
+ document.documentElement.classList.add('if-not-controlled');
}
- if (state.lastError) {
+ if ( state.lastError) {
- document.querySelectorAll('.if-error').forEach( (node) => {
+ const err = ['message', 'stack', 'name'].reduce((acc, prop) => {
- node.style.display = 'block';
+ acc[prop] = state.lastError[prop];
+ return acc;
+
+ }, {});
+ document.getElementById('last-error').innerHTML = JSON.stringify(err);
+ document.documentElement.classList.add('if-error');
- });
- document.getElementById('last-error').innerHTML = state.lastError;
}
- document.documentElement.style.display = '';
+ 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 = '';
+
});
diff --git a/extensions/chromium/runet-censorship-bypass-light/extension/pages/show-state/keep-links-clickable.js b/extensions/chromium/runet-censorship-bypass-light/extension/pages/show-state/keep-links-clickable.js
new file mode 100644
index 0000000..8d139cf
--- /dev/null
+++ b/extensions/chromium/runet-censorship-bypass-light/extension/pages/show-state/keep-links-clickable.js
@@ -0,0 +1,37 @@
+'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);
+
+}