2014-09-20 11:49:04 -04:00
|
|
|
OmegaTargetCurrent = Object.create(OmegaTargetChromium)
|
|
|
|
Promise = OmegaTargetCurrent.Promise
|
|
|
|
Promise.longStackTraces()
|
|
|
|
|
|
|
|
OmegaTargetCurrent.Log = Object.create(OmegaTargetCurrent.Log)
|
|
|
|
Log = OmegaTargetCurrent.Log
|
|
|
|
Log.log = (args...) ->
|
|
|
|
console.log(args...)
|
|
|
|
localStorage['log'] += args.map(Log.str.bind(Log)).join(' ') + '\n'
|
|
|
|
Log.error = (args...) ->
|
|
|
|
console.error(args...)
|
|
|
|
content = args.map(Log.str.bind(Log)).join(' ')
|
2014-12-19 08:27:17 -05:00
|
|
|
localStorage['logLastError'] = content
|
2014-09-20 11:49:04 -04:00
|
|
|
localStorage['log'] += 'ERROR: ' + content + '\n'
|
|
|
|
|
|
|
|
unhandledPromises = []
|
|
|
|
unhandledPromisesId = []
|
|
|
|
unhandledPromisesNextId = 1
|
|
|
|
Promise.onPossiblyUnhandledRejection (reason, promise) ->
|
|
|
|
Log.error("[#{unhandledPromisesNextId}] Unhandled rejection:\n", reason)
|
|
|
|
unhandledPromises.push(promise)
|
|
|
|
unhandledPromisesId.push(unhandledPromisesNextId)
|
|
|
|
unhandledPromisesNextId++
|
|
|
|
Promise.onUnhandledRejectionHandled (promise) ->
|
|
|
|
index = unhandledPromises.indexOf(promise)
|
|
|
|
Log.log("[#{unhandledPromisesId[index]}] Rejection handled!", promise)
|
|
|
|
unhandledPromises.splice(index, 1)
|
|
|
|
unhandledPromisesId.splice(index, 1)
|
|
|
|
|
|
|
|
iconCache = {}
|
2017-02-26 02:42:52 -05:00
|
|
|
drawContext = null
|
2017-02-26 20:46:25 -05:00
|
|
|
drawError = null
|
2014-09-20 11:49:04 -04:00
|
|
|
drawIcon = (resultColor, profileColor) ->
|
|
|
|
cacheKey = "omega+#{resultColor ? ''}+#{profileColor}"
|
|
|
|
icon = iconCache[cacheKey]
|
|
|
|
return icon if icon
|
2017-02-26 20:40:25 -05:00
|
|
|
try
|
|
|
|
if not drawContext?
|
|
|
|
drawContext = document.getElementById('canvas-icon').getContext('2d')
|
2017-02-26 02:42:52 -05:00
|
|
|
|
2017-02-26 20:40:25 -05:00
|
|
|
icon = {}
|
2017-03-01 00:22:53 -05:00
|
|
|
for size in [16, 19, 24, 32, 38]
|
2017-02-26 20:40:25 -05:00
|
|
|
drawContext.scale(size, size)
|
|
|
|
drawContext.clearRect(0, 0, 1, 1)
|
|
|
|
if resultColor?
|
|
|
|
drawOmega drawContext, resultColor, profileColor
|
|
|
|
else
|
|
|
|
drawOmega drawContext, profileColor
|
|
|
|
drawContext.setTransform(1, 0, 0, 1, 0, 0)
|
|
|
|
icon[size] = drawContext.getImageData(0, 0, size, size)
|
2017-02-26 20:46:25 -05:00
|
|
|
catch e
|
|
|
|
if not drawError?
|
|
|
|
drawError = e
|
|
|
|
Log.error(e)
|
2017-02-26 20:40:25 -05:00
|
|
|
icon = null
|
2017-02-26 02:42:52 -05:00
|
|
|
|
2014-09-20 11:49:04 -04:00
|
|
|
return iconCache[cacheKey] = icon
|
|
|
|
|
2014-10-03 05:15:41 -04:00
|
|
|
charCodeUnderscore = '_'.charCodeAt(0)
|
|
|
|
isHidden = (name) -> (name.charCodeAt(0) == charCodeUnderscore and
|
|
|
|
name.charCodeAt(1) == charCodeUnderscore)
|
|
|
|
|
|
|
|
dispName = (name) -> chrome.i18n.getMessage('profile_' + name) || name
|
|
|
|
|
2014-09-20 11:49:04 -04:00
|
|
|
actionForUrl = (url) ->
|
|
|
|
options.ready.then(->
|
|
|
|
request = OmegaPac.Conditions.requestFromUrl(url)
|
|
|
|
options.matchProfile(request)
|
|
|
|
).then ({profile, results}) ->
|
|
|
|
current = options.currentProfile()
|
2014-10-25 11:41:39 -04:00
|
|
|
currentName = dispName(current.name)
|
|
|
|
if current.profileType == 'VirtualProfile'
|
|
|
|
realCurrentName = current.defaultProfileName
|
|
|
|
currentName += " [#{dispName(realCurrentName)}]"
|
|
|
|
current = options.profile(realCurrentName)
|
2014-09-20 11:49:04 -04:00
|
|
|
details = ''
|
|
|
|
direct = false
|
2014-10-03 05:15:41 -04:00
|
|
|
attached = false
|
2016-03-17 09:10:28 -04:00
|
|
|
condition2Str = (condition) ->
|
|
|
|
condition.pattern || OmegaPac.Conditions.str(condition)
|
2014-09-20 11:49:04 -04:00
|
|
|
for result in results
|
|
|
|
if Array.isArray(result)
|
|
|
|
if not result[1]?
|
2014-10-03 05:15:41 -04:00
|
|
|
attached = false
|
|
|
|
name = result[0]
|
|
|
|
if name[0] == '+'
|
|
|
|
name = name.substr(1)
|
|
|
|
if isHidden(name)
|
|
|
|
attached = true
|
2014-10-25 11:41:39 -04:00
|
|
|
else if name != realCurrentName
|
2014-10-03 05:15:41 -04:00
|
|
|
details += chrome.i18n.getMessage 'browserAction_defaultRuleDetails'
|
|
|
|
details += " => #{dispName(name)}\n"
|
2014-09-20 11:49:04 -04:00
|
|
|
else if result[1].length == 0
|
2014-10-03 05:15:41 -04:00
|
|
|
if result[0] == 'DIRECT'
|
|
|
|
details += chrome.i18n.getMessage('browserAction_directResult')
|
|
|
|
details += '\n'
|
2014-12-27 06:20:36 -05:00
|
|
|
direct = true
|
2014-10-03 05:15:41 -04:00
|
|
|
else
|
|
|
|
details += "#{result[0]}\n"
|
2014-09-20 11:49:04 -04:00
|
|
|
else if typeof result[1] == 'string'
|
|
|
|
details += "#{result[1]} => #{result[0]}\n"
|
|
|
|
else
|
2016-03-17 09:10:28 -04:00
|
|
|
condition = condition2Str(result[1].condition ? result[1])
|
2014-10-03 05:15:41 -04:00
|
|
|
details += "#{condition} => "
|
2014-09-20 11:49:04 -04:00
|
|
|
if result[0] == 'DIRECT'
|
2014-10-03 05:15:41 -04:00
|
|
|
details += chrome.i18n.getMessage('browserAction_directResult')
|
|
|
|
details += '\n'
|
2014-09-20 11:49:04 -04:00
|
|
|
direct = true
|
2014-10-03 05:15:41 -04:00
|
|
|
else
|
|
|
|
details += "#{result[0]}\n"
|
2014-09-20 11:49:04 -04:00
|
|
|
else if result.profileName
|
|
|
|
if result.isTempRule
|
|
|
|
details += chrome.i18n.getMessage('browserAction_tempRulePrefix')
|
2014-10-03 05:15:41 -04:00
|
|
|
else if attached
|
|
|
|
details += chrome.i18n.getMessage('browserAction_attachedPrefix')
|
|
|
|
attached = false
|
2016-03-17 09:10:28 -04:00
|
|
|
condition = result.source ? condition2Str(result.condition)
|
2014-10-03 05:15:41 -04:00
|
|
|
details += "#{condition} => #{dispName(result.profileName)}\n"
|
2014-09-20 11:49:04 -04:00
|
|
|
|
2014-11-12 10:34:27 -05:00
|
|
|
if not details
|
|
|
|
details = options.printProfile(current)
|
|
|
|
|
2014-12-19 10:37:47 -05:00
|
|
|
resultColor = profile.color
|
|
|
|
profileColor = current.color
|
|
|
|
|
|
|
|
icon = null
|
2014-12-27 06:20:36 -05:00
|
|
|
if direct
|
|
|
|
resultColor = options.profile('direct').color
|
|
|
|
profileColor = profile.color
|
|
|
|
else if profile.name == current.name and options.isCurrentProfileStatic()
|
|
|
|
resultColor = profileColor = profile.color
|
|
|
|
icon = drawIcon(profile.color)
|
2014-12-19 10:37:47 -05:00
|
|
|
else
|
|
|
|
resultColor = profile.color
|
|
|
|
profileColor = current.color
|
|
|
|
|
|
|
|
icon ?= drawIcon(resultColor, profileColor)
|
2014-09-20 11:49:04 -04:00
|
|
|
return {
|
|
|
|
title: chrome.i18n.getMessage('browserAction_titleWithResult', [
|
2014-10-25 11:41:39 -04:00
|
|
|
currentName
|
2014-10-03 05:15:41 -04:00
|
|
|
dispName(profile.name)
|
2014-09-20 11:49:04 -04:00
|
|
|
details
|
|
|
|
])
|
|
|
|
icon: icon
|
2014-12-19 10:37:47 -05:00
|
|
|
resultColor: resultColor
|
|
|
|
profileColor: profileColor
|
2014-09-20 11:49:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-24 23:01:47 -04:00
|
|
|
storage = new OmegaTargetCurrent.Storage('local')
|
2014-09-20 11:49:04 -04:00
|
|
|
state = new OmegaTargetCurrent.BrowserStorage(localStorage, 'omega.local.')
|
2015-01-18 12:09:17 -05:00
|
|
|
|
2017-03-24 23:01:47 -04:00
|
|
|
if chrome?.storage?.sync or browser?.storage?.sync
|
|
|
|
syncStorage = new OmegaTargetCurrent.Storage('sync')
|
2015-04-19 07:21:29 -04:00
|
|
|
sync = new OmegaTargetCurrent.OptionsSync(syncStorage)
|
|
|
|
if localStorage['omega.local.syncOptions'] != '"sync"'
|
|
|
|
sync.enabled = false
|
|
|
|
sync.transformValue = OmegaTargetCurrent.Options.transformValueForSync
|
2015-01-18 12:09:17 -05:00
|
|
|
|
|
|
|
options = new OmegaTargetCurrent.Options(null, storage, state, Log, sync)
|
2014-12-06 07:34:49 -05:00
|
|
|
options.externalApi = new OmegaTargetCurrent.ExternalApi(options)
|
|
|
|
options.externalApi.listen()
|
|
|
|
|
|
|
|
if chrome.runtime.id != OmegaTargetCurrent.SwitchySharp.extId
|
|
|
|
options.switchySharp = new OmegaTargetCurrent.SwitchySharp()
|
|
|
|
options.switchySharp.monitor()
|
2014-09-20 11:49:04 -04:00
|
|
|
|
|
|
|
tabs = new OmegaTargetCurrent.ChromeTabs(actionForUrl)
|
|
|
|
tabs.watch()
|
|
|
|
|
2014-12-22 06:34:24 -05:00
|
|
|
options._inspect = new OmegaTargetCurrent.Inspect (url, tab) ->
|
2014-12-19 10:37:47 -05:00
|
|
|
if url == tab.url
|
|
|
|
options.clearBadge()
|
|
|
|
tabs.processTab(tab)
|
|
|
|
state.remove('inspectUrl')
|
|
|
|
return
|
|
|
|
|
|
|
|
state.set({inspectUrl: url})
|
|
|
|
|
|
|
|
actionForUrl(url).then (action) ->
|
|
|
|
parsedUrl = OmegaTargetCurrent.Url.parse(url)
|
|
|
|
if parsedUrl.hostname == OmegaTargetCurrent.Url.parse(tab.url).hostname
|
|
|
|
urlDisp = parsedUrl.path
|
|
|
|
else
|
|
|
|
urlDisp = parsedUrl.hostname
|
|
|
|
|
|
|
|
title = chrome.i18n.getMessage('browserAction_titleInspect', urlDisp) + '\n'
|
|
|
|
title += action.title
|
|
|
|
chrome.browserAction.setTitle(title: title, tabId: tab.id)
|
|
|
|
tabs.setTabBadge(tab, {
|
|
|
|
text: '#'
|
|
|
|
color: action.resultColor
|
|
|
|
})
|
|
|
|
|
2014-09-20 11:49:04 -04:00
|
|
|
options.setProxyNotControllable(null)
|
|
|
|
timeout = null
|
|
|
|
|
|
|
|
options.watchProxyChange (details) ->
|
2014-12-06 07:34:49 -05:00
|
|
|
return if options.externalApi.disabled
|
2014-12-16 05:27:18 -05:00
|
|
|
return unless details
|
2014-11-07 02:38:34 -05:00
|
|
|
notControllableBefore = options.proxyNotControllable()
|
|
|
|
internal = false
|
2015-01-01 07:17:46 -05:00
|
|
|
noRevert = false
|
2014-09-20 11:49:04 -04:00
|
|
|
switch details['levelOfControl']
|
|
|
|
when "controlled_by_other_extensions", "not_controllable"
|
|
|
|
reason =
|
|
|
|
if details['levelOfControl'] == 'not_controllable'
|
|
|
|
'policy'
|
|
|
|
else
|
|
|
|
'app'
|
|
|
|
options.setProxyNotControllable(reason)
|
2015-01-01 07:17:46 -05:00
|
|
|
noRevert = true
|
2014-09-20 11:49:04 -04:00
|
|
|
else
|
|
|
|
options.setProxyNotControllable(null)
|
|
|
|
|
2014-11-07 02:38:34 -05:00
|
|
|
if details['levelOfControl'] == 'controlled_by_this_extension'
|
|
|
|
internal = true
|
|
|
|
return if not notControllableBefore
|
2014-09-20 11:49:04 -04:00
|
|
|
Log.log('external proxy: ', details)
|
|
|
|
|
|
|
|
# Chromium will send chrome.proxy.settings.onChange on extension unload,
|
|
|
|
# just after the current extension has lost control of the proxy settings.
|
|
|
|
# This is just annoying, and may change the currentProfileName state
|
|
|
|
# suprisingly.
|
|
|
|
# To workaround this issue, wait for some time before setting the proxy.
|
|
|
|
# However this will cause some delay before the settings are processed.
|
|
|
|
clearTimeout(timeout) if timeout?
|
2014-11-07 02:38:34 -05:00
|
|
|
parsed = null
|
2014-09-20 11:49:04 -04:00
|
|
|
timeout = setTimeout (->
|
2015-01-01 07:17:46 -05:00
|
|
|
options.setExternalProfile(parsed, {noRevert: noRevert, internal: internal})
|
2014-09-20 11:49:04 -04:00
|
|
|
), 500
|
2014-11-07 02:38:34 -05:00
|
|
|
|
|
|
|
parsed = options.parseExternalProfile(details)
|
2014-09-20 11:49:04 -04:00
|
|
|
return
|
|
|
|
|
|
|
|
external = false
|
|
|
|
options.currentProfileChanged = (reason) ->
|
|
|
|
iconCache = {}
|
|
|
|
|
|
|
|
if reason == 'external'
|
|
|
|
external = true
|
|
|
|
else if reason != 'clearBadge'
|
|
|
|
external = false
|
|
|
|
|
2014-10-25 11:41:39 -04:00
|
|
|
current = options.currentProfile()
|
|
|
|
currentName = ''
|
|
|
|
if current
|
|
|
|
currentName = dispName(current.name)
|
|
|
|
if current.profileType == 'VirtualProfile'
|
|
|
|
realCurrentName = current.defaultProfileName
|
|
|
|
currentName += " [#{dispName(realCurrentName)}]"
|
|
|
|
current = options.profile(realCurrentName)
|
2014-11-07 02:38:34 -05:00
|
|
|
|
|
|
|
details = options.printProfile(current)
|
|
|
|
if currentName
|
|
|
|
title = chrome.i18n.getMessage('browserAction_titleWithResult', [
|
|
|
|
currentName, '', details])
|
|
|
|
else
|
|
|
|
title = details
|
|
|
|
|
|
|
|
if external and current.profileType != 'SystemProfile'
|
2014-09-20 11:49:04 -04:00
|
|
|
message = chrome.i18n.getMessage('browserAction_titleExternalProxy')
|
|
|
|
title = message + '\n' + title
|
|
|
|
options.setBadge()
|
|
|
|
|
2014-12-27 06:20:36 -05:00
|
|
|
if not current.name or not OmegaPac.Profiles.isInclusive(current)
|
|
|
|
icon = drawIcon(current.color)
|
|
|
|
else
|
|
|
|
icon = drawIcon(options.profile('direct').color, current.color)
|
|
|
|
|
2014-09-20 11:49:04 -04:00
|
|
|
tabs.resetAll(
|
2014-12-27 06:20:36 -05:00
|
|
|
icon: icon
|
2014-09-20 11:49:04 -04:00
|
|
|
title: title
|
|
|
|
)
|
|
|
|
|
|
|
|
encodeError = (obj) ->
|
|
|
|
if obj instanceof Error
|
|
|
|
{
|
|
|
|
_error: 'error'
|
|
|
|
name: obj.name
|
|
|
|
message: obj.message
|
|
|
|
stack: obj.stack
|
|
|
|
original: obj
|
|
|
|
}
|
|
|
|
else
|
|
|
|
obj
|
|
|
|
|
2017-03-14 00:25:46 -04:00
|
|
|
refreshActivePageIfEnabled = ->
|
2017-03-17 21:18:38 -04:00
|
|
|
return if localStorage['omega.local.refreshOnProfileChange'] == 'false'
|
2017-03-14 00:25:46 -04:00
|
|
|
chrome.tabs.query {active: true, lastFocusedWindow: true}, (tabs) ->
|
2017-03-25 00:24:39 -04:00
|
|
|
url = tabs[0].url
|
|
|
|
return if not url
|
|
|
|
return if url.substr(0, 6) == 'chrome'
|
|
|
|
return if url.substr(0, 6) == 'about:'
|
|
|
|
return if url.substr(0, 4) == 'moz-'
|
|
|
|
chrome.tabs.reload(tabs[0].id, {bypassCache: true})
|
2017-03-14 00:25:46 -04:00
|
|
|
|
2014-09-20 11:49:04 -04:00
|
|
|
chrome.runtime.onMessage.addListener (request, sender, respond) ->
|
2017-04-13 22:41:08 -04:00
|
|
|
return unless request and request.method
|
2014-09-20 11:49:04 -04:00
|
|
|
options.ready.then ->
|
|
|
|
target = options
|
|
|
|
method = target[request.method]
|
|
|
|
if typeof method != 'function'
|
|
|
|
Log.error("No such method #{request.method}!")
|
|
|
|
respond(
|
|
|
|
error:
|
|
|
|
reason: 'noSuchMethod'
|
|
|
|
)
|
|
|
|
return
|
|
|
|
|
|
|
|
promise = Promise.resolve().then -> method.apply(target, request.args)
|
2017-03-14 00:25:46 -04:00
|
|
|
if request.refreshActivePage
|
|
|
|
promise.then refreshActivePageIfEnabled
|
2015-02-09 03:35:14 -05:00
|
|
|
return if request.noReply
|
2014-09-20 11:49:04 -04:00
|
|
|
|
|
|
|
promise.then (result) ->
|
|
|
|
if request.method == 'updateProfile'
|
|
|
|
for own key, value of result
|
|
|
|
result[key] = encodeError(value)
|
|
|
|
respond(result: result)
|
|
|
|
|
|
|
|
promise.catch (error) ->
|
|
|
|
Log.error(request.method + ' ==>', error)
|
|
|
|
respond(error: encodeError(error))
|
|
|
|
|
|
|
|
# Wait for my response!
|
2015-02-09 03:35:14 -05:00
|
|
|
return true unless request.noReply
|