From 314bf57b943099eebdc6451692d0cd76d0c6ebc7 Mon Sep 17 00:00:00 2001 From: "Ilya Ig. Petrov" Date: Wed, 22 Nov 2017 12:13:45 +0500 Subject: [PATCH 01/18] First working version --- .../src/extension-common/00-init-apis.js | 35 ++++++++ .../extension-common/11-error-handlers-api.js | 38 ++++---- .../extension-common/35-pac-kitchen-api.js | 12 ++- .../src/extension-common/default.pac.js | 17 ++++ .../src/extension-common/manifest.tmpl.json | 4 +- .../src/extension-common/pages/debug/index.js | 89 ++++++++++--------- .../pages/options/package-lock.json | 22 +++++ .../options/src/components/PacChooser.js | 14 +-- 8 files changed, 161 insertions(+), 70 deletions(-) create mode 100644 extensions/chromium/runet-censorship-bypass/src/extension-common/default.pac.js diff --git a/extensions/chromium/runet-censorship-bypass/src/extension-common/00-init-apis.js b/extensions/chromium/runet-censorship-bypass/src/extension-common/00-init-apis.js index 1b1566c..eeb2f6c 100644 --- a/extensions/chromium/runet-censorship-bypass/src/extension-common/00-init-apis.js +++ b/extensions/chromium/runet-censorship-bypass/src/extension-common/00-init-apis.js @@ -241,6 +241,9 @@ const compareVersions = (a, b) => versionToInt(a) - versionToInt(b); window.apis = { + platform: { + ifFirefox: navigator.userAgent.toLowerCase().includes('firefox'), + }, version: { ifMini: false, build: chrome.runtime.getManifest().version.replace(/\d+\.\d+\./g, ''), @@ -249,4 +252,36 @@ }, }; + // Shims for FireFox + + if (!chrome.proxy.settings) { + + let currentSettings = {}; + + chrome.proxy.settings = { + get: (_, cb) => { + + currentSettings.levelOfControl = 'controlled_by_this_extension'; // May be lie, but this field is required. + cb(currentSettings); + + }, + onChange: { + addListener: () => {}, + }, + set: (details, cb) => { + + browser.proxy.unregister(); + browser.proxy.register('./default.pac.js'); + + + browser.proxy.onProxyError.addListener((...err) => { console.log('ERROR IN PAC:', ...err) }); + + browser.runtime.sendMessage(details, {toProxyScript: true}); + currentSettings = details; + cb(); + + }, + }; + } + } diff --git a/extensions/chromium/runet-censorship-bypass/src/extension-common/11-error-handlers-api.js b/extensions/chromium/runet-censorship-bypass/src/extension-common/11-error-handlers-api.js index 96d3263..67ac40e 100644 --- a/extensions/chromium/runet-censorship-bypass/src/extension-common/11-error-handlers-api.js +++ b/extensions/chromium/runet-censorship-bypass/src/extension-common/11-error-handlers-api.js @@ -8,6 +8,9 @@ const errorJsonReplacer = function errorJsonReplacer(key, value) { // fooWindow.ErrorEvent !== barWindow.ErrorEvent + if (value === window) { + return; // STUPID, because other window object may be passed. + } if (!( value && value.constructor && ['Error', 'Event'].some( (suff) => value.constructor.name.endsWith(suff) @@ -114,20 +117,22 @@ isControllable(details) { - this.ifControllable = window.utils.areSettingsControllableFor(details); + if (details) { + this.ifControllable = window.utils.areSettingsControllableFor(details); - if (this.ifControllable) { - this.ifControlled = window.utils.areSettingsControlledFor(details); - } else { - this.ifControlled = false; - } + if (this.ifControllable) { + this.ifControlled = window.utils.areSettingsControlledFor(details); + } else { + this.ifControlled = false; + } - if (this.ifControlled) { - chrome.browserAction.setIcon( {path: './icons/default-128.png'} ); - } else { - chrome.browserAction.setIcon({ - path: './icons/default-grayscale-128.png', - }); + if (this.ifControlled) { + chrome.browserAction.setIcon( {path: './icons/default-128.png'} ); + } else { + chrome.browserAction.setIcon({ + path: './icons/default-grayscale-128.png', + }); + } } return this.ifControllable; @@ -136,7 +141,9 @@ isControlled(details) { - this.isControllable(details); + if (details) { + this.isControllable(details); + } return this.ifControlled; }, @@ -175,16 +182,15 @@ const message = errOrMessage.message || errOrMessage.toString(); chrome.notifications.create( id, - { + Object.assign({ title: title, message: message, contextMessage: context, - requireInteraction: ifSticky, type: 'basic', iconUrl: './icons/' + icon, appIconMaskUrl: './icons/default-mask-128.png', isClickable: true, - } + }, window.apis.platform.ifFirefox ? {} : { requireInteraction: ifSticky }), ); }, diff --git a/extensions/chromium/runet-censorship-bypass/src/extension-common/35-pac-kitchen-api.js b/extensions/chromium/runet-censorship-bypass/src/extension-common/35-pac-kitchen-api.js index 64e2c03..ecfede7 100644 --- a/extensions/chromium/runet-censorship-bypass/src/extension-common/35-pac-kitchen-api.js +++ b/extensions/chromium/runet-censorship-bypass/src/extension-common/35-pac-kitchen-api.js @@ -317,11 +317,11 @@ return pacMods.ifNoMods ? pacData : pacData + `${ kitchenStartsMark } /******/ -/******/;+function(global) { +/******/;(function(global) { /******/ "use strict"; /******/ /******/ const originalFindProxyForURL = FindProxyForURL; -/******/ global.FindProxyForURL = function(url, host) { +/******/ const tmp = function(url, host) { /******/ ${ function() { @@ -453,7 +453,13 @@ ${ pacMods.filteredCustomsString }; -}(this);`; + if (global) { +/******/ global.FindProxyForURL = tmp; + } else { +/******/ FindProxyForURL = tmp; + } + +})(this);`; }, diff --git a/extensions/chromium/runet-censorship-bypass/src/extension-common/default.pac.js b/extensions/chromium/runet-censorship-bypass/src/extension-common/default.pac.js new file mode 100644 index 0000000..6b4603b --- /dev/null +++ b/extensions/chromium/runet-censorship-bypass/src/extension-common/default.pac.js @@ -0,0 +1,17 @@ +var coolFind = () => {}; +this.FindProxyForURL = function (...args) { + return coolFind(...args); +}; + +const dnsResolve = this.dnsResolve || (() => null); // Welcome to hell! Someone forgot dns. + +browser.runtime.onMessage.addListener((details) => { + const pacData = + details && details.value && details.value.pacScript && details.value.pacScript.data; + if (!pacData) { + throw new Error('Never install empty PAC scripts!'); + } + coolFind = (function() { eval(pacData); return FindProxyForURL; })(); + +}); + diff --git a/extensions/chromium/runet-censorship-bypass/src/extension-common/manifest.tmpl.json b/extensions/chromium/runet-censorship-bypass/src/extension-common/manifest.tmpl.json index ad52cb9..b9d38df 100644 --- a/extensions/chromium/runet-censorship-bypass/src/extension-common/manifest.tmpl.json +++ b/extensions/chromium/runet-censorship-bypass/src/extension-common/manifest.tmpl.json @@ -45,5 +45,7 @@ "options_ui": { "page": "/pages/options/index.html", "chrome_style": false - } + }, + + "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'" } diff --git a/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/debug/index.js b/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/debug/index.js index ef0e255..6157146 100644 --- a/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/debug/index.js +++ b/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/debug/index.js @@ -1,60 +1,63 @@ 'use strict'; -const setStatusTo = (msg) => document.getElementById('status').innerHTML = msg; +chrome.runtime.getBackgroundPage((bgWin) => { -const red = (text) => '' + text + ''; + const setStatusTo = (msg) => document.getElementById('status').innerHTML = msg; -const editor = window.ace.edit('editor'); -editor.getSession().setOptions({ - mode: 'ace/mode/javascript', - useSoftTabs: true, -}); - -chrome.proxy.settings.onChange.addListener( - (details) => setStatusTo(red( details.levelOfControl + '!') ) -); - -function _read() { - - chrome.proxy.settings.get({}, (details) => { - - let control = details.levelOfControl; - if (control.startsWith('controlled_by_other')) { - control = red(control); - } - setStatusTo(control); - console.log(details); - const pac = details.value.pacScript; - const data = pac && pac.data || 'PAC скрипт не установлен.'; - editor.setValue( data ); + const red = (text) => '' + text + ''; + const editor = window.ace.edit('editor'); + editor.getSession().setOptions({ + mode: 'ace/mode/javascript', + useSoftTabs: true, }); -} + bgWin.chrome.proxy.settings.onChange.addListener( + (details) => setStatusTo(red( details.levelOfControl + '!') ) + ); -document.querySelector('#read-button').onclick = _read; + function _read() { -document.querySelector('#save-button').onclick = () => { + bgWin.chrome.proxy.settings.get({}, (details) => { + + let control = details.levelOfControl; + if (control.startsWith('controlled_by_other')) { + control = red(control); + } + setStatusTo(control); + console.log(details); + const pac = details.value.pacScript; + const data = pac && pac.data || 'PAC скрипт не установлен.'; + editor.setValue( data ); + + }); + + } + + document.querySelector('#read-button').onclick = _read; + + document.querySelector('#save-button').onclick = () => { + + const config = { + mode: 'pac_script', + pacScript: { + mandatory: false, + data: editor.getValue(), + }, + }; + bgWin.chrome.proxy.settings.set( {value: config}, () => alert('Saved!') ); - const config = { - mode: 'pac_script', - pacScript: { - mandatory: false, - data: editor.getValue(), - }, }; - chrome.proxy.settings.set( {value: config}, () => alert('Saved!') ); -}; + document.querySelector('#clear-button').onclick = () => { -document.querySelector('#clear-button').onclick = () => { + bgWin.chrome.proxy.settings.clear({}, () => { - chrome.proxy.settings.clear({}, () => { + alert('Cleared! Reading...'); + _read(); - alert('Cleared! Reading...'); - _read(); + }); - }); - -}; + }; +}) diff --git a/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/options/package-lock.json b/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/options/package-lock.json index 849d0e2..c29d856 100644 --- a/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/options/package-lock.json +++ b/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/options/package-lock.json @@ -1205,10 +1205,21 @@ "integrity": "sha512-H1b0LNa197L/y2eBcVSQxpldkgzK15HU3xG1hCn0xJ4rxRSo6n78/fabBqyuUYMA1CtVa1Z7WnAVa9FKvlFecQ==", "dev": true, "requires": { + "inferno": "3.8.0", "inferno-shared": "3.8.0", "inferno-vnode-flags": "3.8.0" }, "dependencies": { + "inferno": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/inferno/-/inferno-3.8.0.tgz", + "integrity": "sha512-6s/hAYOrKNB0a8FDNHTJlz13d9uup7fVpvfd+2XPzxE69h8WgtMl+CSTIxHkW8RuEcc+hFAqi0ScsXVkMor5pw==", + "dev": true, + "requires": { + "inferno-shared": "3.8.0", + "inferno-vnode-flags": "3.8.0" + } + }, "inferno-vnode-flags": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/inferno-vnode-flags/-/inferno-vnode-flags-3.8.0.tgz", @@ -1223,11 +1234,22 @@ "integrity": "sha512-OOCSFxgnQUYvT8bhkE7OearfQi4NXevHVE49rExHhbf6m7U/AW5uQ/Ji8+BmX//sQY4YjQIvZnD/t1O+UEEBgA==", "dev": true, "requires": { + "inferno": "3.8.0", "inferno-component": "3.8.0", "inferno-shared": "3.8.0", "inferno-vnode-flags": "3.8.0" }, "dependencies": { + "inferno": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/inferno/-/inferno-3.8.0.tgz", + "integrity": "sha512-6s/hAYOrKNB0a8FDNHTJlz13d9uup7fVpvfd+2XPzxE69h8WgtMl+CSTIxHkW8RuEcc+hFAqi0ScsXVkMor5pw==", + "dev": true, + "requires": { + "inferno-shared": "3.8.0", + "inferno-vnode-flags": "3.8.0" + } + }, "inferno-vnode-flags": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/inferno-vnode-flags/-/inferno-vnode-flags-3.8.0.tgz", diff --git a/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/options/src/components/PacChooser.js b/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/options/src/components/PacChooser.js index 894c146..47de8ec 100644 --- a/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/options/src/components/PacChooser.js +++ b/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/options/src/components/PacChooser.js @@ -63,7 +63,7 @@ export default function getPacChooser(theState) { this.updatePac = function updatePac(onSuccess) { props.funs.conduct( 'Обновляем...', - (cb) => props.apis.antiCensorRu.syncWithPacProviderAsync(cb), + (cb) => theState.apis.antiCensorRu.syncWithPacProviderAsync(cb), 'Обновлено.', onSuccess ); @@ -75,7 +75,7 @@ export default function getPacChooser(theState) { getCurrentProviderId() { - return this.props.apis.antiCensorRu.getCurrentPacProviderKey() || 'none'; + return theState.apis.antiCensorRu.getCurrentPacProviderKey() || 'none'; } @@ -94,7 +94,7 @@ export default function getPacChooser(theState) { const pacKey = event.target.id; if ( pacKey === ( - this.props.apis.antiCensorRu.getCurrentPacProviderKey() || 'none' + theState.apis.antiCensorRu.getCurrentPacProviderKey() || 'none' ) ) { return false; @@ -102,7 +102,7 @@ export default function getPacChooser(theState) { if (pacKey === 'none') { this.props.funs.conduct( 'Отключение...', - (cb) => this.props.apis.antiCensorRu.clearPacAsync(cb), + (cb) => theState.apis.antiCensorRu.clearPacAsync(cb), 'Отключено.', () => this.setState({ chosenPacName: 'none' }), checkChosenProvider @@ -110,7 +110,7 @@ export default function getPacChooser(theState) { } else { this.props.funs.conduct( 'Установка...', - (cb) => this.props.apis.antiCensorRu.installPacAsync(pacKey, cb), + (cb) => theState.apis.antiCensorRu.installPacAsync(pacKey, cb), 'PAC-скрипт установлен.', checkChosenProvider ); @@ -127,7 +127,7 @@ export default function getPacChooser(theState) { {props.flags.ifInsideOptionsPage && (
PAC-скрипт:
)}