mirror of
https://github.com/zero-peak/ZeroOmega.git
synced 2025-01-22 15:08:12 -05:00
Implement proxy script for WebExtensions. #102.
This commit is contained in:
parent
d65c29f34d
commit
f421810959
@ -296,6 +296,7 @@ refreshActivePageIfEnabled = ->
|
|||||||
chrome.tabs.reload(tabs[0].id, {bypassCache: true})
|
chrome.tabs.reload(tabs[0].id, {bypassCache: true})
|
||||||
|
|
||||||
chrome.runtime.onMessage.addListener (request, sender, respond) ->
|
chrome.runtime.onMessage.addListener (request, sender, respond) ->
|
||||||
|
return unless request and request.method
|
||||||
options.ready.then ->
|
options.ready.then ->
|
||||||
target = options
|
target = options
|
||||||
method = target[request.method]
|
method = target[request.method]
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
path = require('path')
|
||||||
module.exports =
|
module.exports =
|
||||||
index:
|
index:
|
||||||
files:
|
files:
|
||||||
@ -26,3 +27,17 @@ module.exports =
|
|||||||
browserifyOptions:
|
browserifyOptions:
|
||||||
extensions: '.coffee'
|
extensions: '.coffee'
|
||||||
standalone: 'OmegaTargetChromium'
|
standalone: 'OmegaTargetChromium'
|
||||||
|
omega_webext_proxy_script:
|
||||||
|
files:
|
||||||
|
'build/js/omega_webext_proxy_script.min.js':
|
||||||
|
'omega_webext_proxy_script.js'
|
||||||
|
options:
|
||||||
|
alias:
|
||||||
|
'omega-pac': 'omega-pac/omega_pac.min.js'
|
||||||
|
plugin:
|
||||||
|
if process.env.BUILD == 'release'
|
||||||
|
[['minifyify', {map: false}]]
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
browserifyOptions:
|
||||||
|
noParse: [require.resolve('omega-pac/omega_pac.min.js')]
|
||||||
|
@ -23,6 +23,9 @@ module.exports =
|
|||||||
src:
|
src:
|
||||||
files: ['src/**/*.coffee']
|
files: ['src/**/*.coffee']
|
||||||
tasks: ['coffeelint:src', 'browserify', 'copy:target_self']
|
tasks: ['coffeelint:src', 'browserify', 'copy:target_self']
|
||||||
|
browserify_omega_webext_proxy_script:
|
||||||
|
files: ['omega_webext_proxy_script.js']
|
||||||
|
tasks: ['browserify:omega_webext_proxy_script']
|
||||||
coffee:
|
coffee:
|
||||||
files: ['src/**/*.coffee', '*.coffee']
|
files: ['src/**/*.coffee', '*.coffee']
|
||||||
tasks: ['coffeelint:src', 'coffee', 'copy:target_self']
|
tasks: ['coffeelint:src', 'coffee', 'copy:target_self']
|
||||||
|
113
omega-target-chromium-extension/omega_webext_proxy_script.js
Normal file
113
omega-target-chromium-extension/omega_webext_proxy_script.js
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
FindProxyForURL = (function () {
|
||||||
|
var OmegaPac = require('omega-pac');
|
||||||
|
var options = {};
|
||||||
|
var state = {};
|
||||||
|
var activeProfile = null;
|
||||||
|
var fallbackResult = 'DIRECT';
|
||||||
|
var pacCache = {};
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
|
return FindProxyForURL;
|
||||||
|
|
||||||
|
function FindProxyForURL(url, host, details) {
|
||||||
|
if (!activeProfile) {
|
||||||
|
warn('Warning: Proxy script not initialized on handling: ' + url);
|
||||||
|
return fallbackResult;
|
||||||
|
}
|
||||||
|
// Moz: Neither path or query is included url regardless of scheme for now.
|
||||||
|
// This is even more strict than Chromium restricting HTTPS URLs.
|
||||||
|
// Therefore, it leads to different behavior than the icon and badge.
|
||||||
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=1337001
|
||||||
|
var request = OmegaPac.Conditions.requestFromUrl(url);
|
||||||
|
var profile = activeProfile;
|
||||||
|
var matchResult, next;
|
||||||
|
while (profile) {
|
||||||
|
matchResult = OmegaPac.Profiles.match(profile, request)
|
||||||
|
if (!matchResult) {
|
||||||
|
if (profile.profileType === 'DirectProfile') {
|
||||||
|
return 'DIRECT';
|
||||||
|
} else if (profile.pacScript) {
|
||||||
|
return runPacProfile(profile.pacScript);
|
||||||
|
} else {
|
||||||
|
warn('Warning: Unsupported profile: ' + profile.profileType);
|
||||||
|
return fallbackResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(matchResult)) {
|
||||||
|
next = matchResult[0];
|
||||||
|
// TODO: Maybe also return user/pass if Mozilla supports it or it ends
|
||||||
|
// up standardized in WebExtensions in the future.
|
||||||
|
// MOZ: Mozilla has a bug tracked for user/pass in PAC return value.
|
||||||
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=1319641
|
||||||
|
if (next.charCodeAt(0) !== 43) {
|
||||||
|
// MOZ: HTTPS proxies are supported under the prefix PROXY.
|
||||||
|
// https://dxr.mozilla.org/mozilla-central/source/toolkit/components/extensions/ProxyScriptContext.jsm#180
|
||||||
|
return next.replace(/HTTPS /g, 'PROXY ');
|
||||||
|
}
|
||||||
|
} else if (matchResult.profileName) {
|
||||||
|
next = OmegaPac.Profiles.nameAsKey(matchResult.profileName)
|
||||||
|
} else {
|
||||||
|
return fallbackResult;
|
||||||
|
}
|
||||||
|
profile = OmegaPac.Profiles.byKey(next, options)
|
||||||
|
}
|
||||||
|
warn('Warning: Cannot find profile: ' + next);
|
||||||
|
return fallbackResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
function runPacProfile(profile) {
|
||||||
|
var cached = pacCache[profile.name];
|
||||||
|
if (!cached || cached.revision !== profile.revision) {
|
||||||
|
// https://github.com/FelisCatus/SwitchyOmega/issues/390
|
||||||
|
var body = ';\n' + profile.pacScript + '\n\n/* End of PAC */;'
|
||||||
|
body += 'return FindProxyForURL';
|
||||||
|
var func = new Function(body).call(this);
|
||||||
|
|
||||||
|
if (typeof func !== 'function') {
|
||||||
|
warn('Warning: Cannot compile pacScript: ' + profile.name);
|
||||||
|
func = function() { return fallbackResult; };
|
||||||
|
}
|
||||||
|
cached = {func: func, revision: profile.revision}
|
||||||
|
pacCache[cacheKey] = cached;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Moz: Most scripts probably won't run without global PAC functions.
|
||||||
|
// Example: dnsDomainIs, shExpMatch, isInNet.
|
||||||
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=1353510
|
||||||
|
return cached.func.call(this);
|
||||||
|
} catch (ex) {
|
||||||
|
warn('Warning: Error occured in pacScript: ' + profile.name, ex);
|
||||||
|
return fallbackResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function warn(message, error) {
|
||||||
|
// We don't have console here and alert is not implemented.
|
||||||
|
// Throwing and messaging seems to be the only ways to communicate.
|
||||||
|
// MOZ: alert(): https://bugzilla.mozilla.org/show_bug.cgi?id=1353510
|
||||||
|
browser.runtime.sendMessage({
|
||||||
|
event: 'proxyScriptLog',
|
||||||
|
message: message,
|
||||||
|
error: error,
|
||||||
|
level: 'warn',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
browser.runtime.sendMessage({event: 'proxyScriptLoaded'});
|
||||||
|
browser.runtime.onMessage.addListener(function(message) {
|
||||||
|
if (message.event === 'proxyScriptStateChanged') {
|
||||||
|
state = message.state;
|
||||||
|
options = message.options;
|
||||||
|
if (!state.currentProfileName) {
|
||||||
|
activeProfile = state.tempProfile;
|
||||||
|
} else {
|
||||||
|
activeProfile = OmegaPac.Profiles.byName(state.currentProfileName,
|
||||||
|
options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})();
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"name": "__MSG_manifest_app_name__",
|
"name": "__MSG_manifest_app_name__",
|
||||||
"version": "2.4.5",
|
"version": "2.4.7",
|
||||||
"description": "__MSG_manifest_app_description__",
|
"description": "__MSG_manifest_app_description__",
|
||||||
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkhwZJT76btQ04EEMOFtZPLESD1TmSVjbLjs0OyesD9Ht8YllFPfJ3qmtbSQGVuvmxH1GK/jUO2QcEWb8bHuOjoRlq20fi5j5Aq90O8FKET+y5D8PxCyi3WmnquiEwaE5cNmaCsw/G2JlO+bZOtdQ/QKOvMxBAegABYimEGfSvCMVUEvpymys0gBhLoch72zPAiJUBkf0z8BtjYTueMRcRXkrSeRPLygUDQnZ1TkQWMYYBp/zqpD5ggxytAklEMQzR9Hn0lqu5s7iuUAgihbysPn/8Wh00Zj5FySpK//KcpG3JS7UWxC28oSt8z5ZR3YimnX+HX3P36V0mC1pgM4o7wIDAQAB",
|
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkhwZJT76btQ04EEMOFtZPLESD1TmSVjbLjs0OyesD9Ht8YllFPfJ3qmtbSQGVuvmxH1GK/jUO2QcEWb8bHuOjoRlq20fi5j5Aq90O8FKET+y5D8PxCyi3WmnquiEwaE5cNmaCsw/G2JlO+bZOtdQ/QKOvMxBAegABYimEGfSvCMVUEvpymys0gBhLoch72zPAiJUBkf0z8BtjYTueMRcRXkrSeRPLygUDQnZ1TkQWMYYBp/zqpD5ggxytAklEMQzR9Hn0lqu5s7iuUAgihbysPn/8Wh00Zj5FySpK//KcpG3JS7UWxC28oSt8z5ZR3YimnX+HX3P36V0mC1pgM4o7wIDAQAB",
|
||||||
"icons": {
|
"icons": {
|
||||||
@ -43,11 +43,19 @@
|
|||||||
"ftp://*/*",
|
"ftp://*/*",
|
||||||
"<all_urls>"
|
"<all_urls>"
|
||||||
],
|
],
|
||||||
|
"content_security_policy":
|
||||||
|
"script-src 'self' 'unsafe-eval'; object-src 'self';",
|
||||||
"commands": {
|
"commands": {
|
||||||
"_execute_browser_action": {
|
"_execute_browser_action": {
|
||||||
"suggested_key": {
|
"suggested_key": {
|
||||||
"default": "Alt+Shift+O"
|
"default": "Alt+Shift+O"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"applications": {
|
||||||
|
"gecko": {
|
||||||
|
"id": "switchyomega@example.com",
|
||||||
|
"strict_min_version": "55.0a1"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,12 +24,13 @@
|
|||||||
"heap": "^0.2.6",
|
"heap": "^0.2.6",
|
||||||
"omega-target": "../omega-target",
|
"omega-target": "../omega-target",
|
||||||
"omega-web": "../omega-web",
|
"omega-web": "../omega-web",
|
||||||
|
"omega-pac": "../omega-pac",
|
||||||
"xhr": "^1.16.0"
|
"xhr": "^1.16.0"
|
||||||
},
|
},
|
||||||
"browser": {
|
"browser": {
|
||||||
"omega-target": "./omega_target_shim.js"
|
"omega-target": "./omega_target_shim.js"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "npm link omega-target && npm link omega-web"
|
"dev": "npm link omega-target && npm link omega-web && npm link omega-pac"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,6 +128,14 @@ class ChromeOptions extends OmegaTarget.Options
|
|||||||
proxySettings.onChange.addListener @_proxyChangeListener
|
proxySettings.onChange.addListener @_proxyChangeListener
|
||||||
@_proxyChangeWatchers.push(callback)
|
@_proxyChangeWatchers.push(callback)
|
||||||
applyProfileProxy: (profile, meta) ->
|
applyProfileProxy: (profile, meta) ->
|
||||||
|
if chrome?.proxy?.settings?
|
||||||
|
return @applyProfileProxySettings(profile, meta)
|
||||||
|
else if browser?.proxy?.registerProxyScript?
|
||||||
|
return @applyProfileProxyScript(profile, meta)
|
||||||
|
else
|
||||||
|
ex = new Error('Your browser does not support proxy settings!')
|
||||||
|
return Promise.reject ex
|
||||||
|
applyProfileProxySettings: (profile, meta) ->
|
||||||
meta ?= profile
|
meta ?= profile
|
||||||
if profile.profileType == 'SystemProfile'
|
if profile.profileType == 'SystemProfile'
|
||||||
# Clear proxy settings, returning proxy control to Chromium.
|
# Clear proxy settings, returning proxy control to Chromium.
|
||||||
@ -171,6 +179,71 @@ class ChromeOptions extends OmegaTarget.Options
|
|||||||
proxySettings.get {}, @_proxyChangeListener
|
proxySettings.get {}, @_proxyChangeListener
|
||||||
return
|
return
|
||||||
|
|
||||||
|
_proxyScriptUrl: 'js/omega_webext_proxy_script.min.js'
|
||||||
|
_proxyScriptDisabled: false
|
||||||
|
applyProfileProxyScript: (profile, state) ->
|
||||||
|
state = state ? {}
|
||||||
|
state.currentProfileName = profile.name
|
||||||
|
if profile.name == ''
|
||||||
|
state.tempProfile = @_tempProfile
|
||||||
|
if profile.profileType == 'SystemProfile'
|
||||||
|
# MOZ: SystemProfile cannot be done now due to lack of "PASS" support.
|
||||||
|
# https://bugzilla.mozilla.org/show_bug.cgi?id=1319634
|
||||||
|
# In the mean time, let's just set an invalid script to unregister it.
|
||||||
|
browser.proxy.registerProxyScript('js/omega_invalid_proxy_script.min.js')
|
||||||
|
@_proxyScriptDisabled = true
|
||||||
|
else
|
||||||
|
@_proxyScriptState = state
|
||||||
|
@_initWebextProxyScript().then => @_proxyScriptStateChanged()
|
||||||
|
# Proxy authentication is not covered in WebExtensions standard now.
|
||||||
|
# MOZ: Mozilla has a bug tracked to implemented it in PAC return value.
|
||||||
|
# https://bugzilla.mozilla.org/show_bug.cgi?id=1319641
|
||||||
|
return Promise.resolve()
|
||||||
|
|
||||||
|
_proxyScriptInitialized: false
|
||||||
|
_proxyScriptState: {}
|
||||||
|
_initWebextProxyScript: ->
|
||||||
|
if not @_proxyScriptInitialized
|
||||||
|
browser.proxy.onProxyError.addListener (err) =>
|
||||||
|
if err and err.message.indexOf('Invalid Proxy Rule: DIRECT') >= 0
|
||||||
|
# MOZ: DIRECT cannot be correctly parsed due to a bug. Even though it
|
||||||
|
# throws, it actually falls back to direct connection so it works.
|
||||||
|
# https://bugzilla.mozilla.org/show_bug.cgi?id=1355198
|
||||||
|
return
|
||||||
|
@log.error(err)
|
||||||
|
browser.runtime.onMessage.addListener (message) =>
|
||||||
|
return unless message.event == 'proxyScriptLog'
|
||||||
|
if message.level == 'error'
|
||||||
|
@log.error(message)
|
||||||
|
else if message.level == 'warn'
|
||||||
|
@log.warn(message)
|
||||||
|
else
|
||||||
|
@log.log(message)
|
||||||
|
|
||||||
|
if not @_proxyScriptInitialized or @_proxyScriptDisabled
|
||||||
|
promise = new Promise (resolve) ->
|
||||||
|
onMessage = (message) ->
|
||||||
|
return unless message.event == 'proxyScriptLoaded'
|
||||||
|
resolve()
|
||||||
|
browser.runtime.onMessage.removeListener onMessage
|
||||||
|
return
|
||||||
|
browser.runtime.onMessage.addListener onMessage
|
||||||
|
browser.proxy.registerProxyScript(@_proxyScriptUrl)
|
||||||
|
@_proxyScriptDisabled = false
|
||||||
|
else
|
||||||
|
promise = Promise.resolve()
|
||||||
|
@_proxyScriptInitialized = true
|
||||||
|
return promise
|
||||||
|
|
||||||
|
_proxyScriptStateChanged: ->
|
||||||
|
browser.runtime.sendMessage({
|
||||||
|
event: 'proxyScriptStateChanged'
|
||||||
|
state: @_proxyScriptState
|
||||||
|
options: @_options
|
||||||
|
}, {
|
||||||
|
toProxyScript: true
|
||||||
|
})
|
||||||
|
|
||||||
_quickSwitchInit: false
|
_quickSwitchInit: false
|
||||||
_quickSwitchContextMenuCreated: false
|
_quickSwitchContextMenuCreated: false
|
||||||
_quickSwitchCanEnable: false
|
_quickSwitchCanEnable: false
|
||||||
|
Loading…
Reference in New Issue
Block a user