Add externalApi (cross-extension messaging) support.

This commit is contained in:
FelisCatus 2014-12-06 20:34:49 +08:00
parent c34e9423f6
commit 7fb69c7cda
14 changed files with 160 additions and 18 deletions

View File

@ -700,9 +700,21 @@
"popup_proxyNotControllable_unknown": {
"message": "The proxy settings cannot be controlled. Please check your system and browser settings."
},
"popup_proxyNotControllable_disabled": {
"message": "The proxy settings are disabled by explicit request from other app(s) or extension(s)."
},
"popup_proxyNotControllable_upgrade": {
"message": "Proxy settings are now controlled by a newer version of SwitchyOmega."
},
"popup_proxyNotControllableDetails": {
"message": "You cannot switch profiles with SwitchyOmega unless you fix the problem above."
},
"popup_proxyNotControllableDetails_upgrade": {
"message": "You can't enable two (or more) versions of SwitchyOmega at the same time. Please disable one of them."
},
"popup_proxyNotControllableManage": {
"message": "Manage extensions"
},
"popup_addConditionTo": {
"message": "Add condition to"
},

View File

@ -700,9 +700,21 @@
"popup_proxyNotControllable_unknown": {
"message": "无法设置代理设置。请检查系统和浏览器设置。"
},
"popup_proxyNotControllable_disabled": {
"message": "在其他应用或扩展的要求下SwitchyOmega 已经禁用代理设置。"
},
"popup_proxyNotControllable_upgrade": {
"message": "代理设置现在由新版本的 SwitchyOmega 控制。"
},
"popup_proxyNotControllableDetails": {
"message": "如果不解决以上问题则无法使用SwitchyOmega切换代理。"
},
"popup_proxyNotControllableDetails_upgrade": {
"message": "两个不同版本的 SwitchyOmega (如稳定版和测试版)不能共存。请禁用其中之一。"
},
"popup_proxyNotControllableManage": {
"message": "管理扩展"
},
"popup_addConditionTo": {
"message": "添加条件到情景模式"
},

View File

@ -700,9 +700,21 @@
"popup_proxyNotControllable_unknown": {
"message": "無法設置代理設置。請檢查系統和瀏覽器設置。"
},
"popup_proxyNotControllable_disabled": {
"message": "在其他程式或擴展的要求下SwitchyOmega 已經禁用代理設置。"
},
"popup_proxyNotControllable_upgrade": {
"message": "代理設置現在由新版本的 SwitchyOmega 控制。"
},
"popup_proxyNotControllableDetails": {
"message": "如果不解決以上問題則無法使用SwitchyOmega切換代理。"
},
"popup_proxyNotControllableDetails_upgrade": {
"message": "兩個不同版本的 SwitchyOmega (如穩定版和測試版)不能共存。請禁用其中之一。"
},
"popup_proxyNotControllableManage": {
"message": "管理擴展"
},
"popup_addConditionTo": {
"message": "添加條件到情景模式"
},

View File

@ -700,9 +700,21 @@
"popup_proxyNotControllable_unknown": {
"message": "無法設定代理設定。請檢查系統和瀏覽器設定。"
},
"popup_proxyNotControllable_disabled": {
"message": "在其他程式或擴展的要求下SwitchyOmega 已經禁用代理設置。"
},
"popup_proxyNotControllable_upgrade": {
"message": "代理設置現在由新版本的 SwitchyOmega 控制。"
},
"popup_proxyNotControllableDetails": {
"message": "如果不解決以上問題則無法使用SwitchyOmega切換代理。"
},
"popup_proxyNotControllableDetails_upgrade": {
"message": "兩個不同版本的 SwitchyOmega (如穩定版和測試版)不能共存。請禁用其中之一。"
},
"popup_proxyNotControllableManage": {
"message": "管理擴展"
},
"popup_addConditionTo": {
"message": "添加條件到情景模式"
},

View File

@ -122,8 +122,12 @@ actionForUrl = (url) ->
storage = new OmegaTargetCurrent.Storage(chrome.storage.local, 'local')
state = new OmegaTargetCurrent.BrowserStorage(localStorage, 'omega.local.')
options = new OmegaTargetCurrent.Options(null, storage, state, Log)
options.switchySharp = new OmegaTargetCurrent.SwitchySharp()
options.switchySharp.monitor()
options.externalApi = new OmegaTargetCurrent.ExternalApi(options)
options.externalApi.listen()
if chrome.runtime.id != OmegaTargetCurrent.SwitchySharp.extId
options.switchySharp = new OmegaTargetCurrent.SwitchySharp()
options.switchySharp.monitor()
tabs = new OmegaTargetCurrent.ChromeTabs(actionForUrl)
tabs.watch()
@ -132,6 +136,7 @@ options.setProxyNotControllable(null)
timeout = null
options.watchProxyChange (details) ->
return if options.externalApi.disabled
notControllableBefore = options.proxyNotControllable()
internal = false
switch details['levelOfControl']

View File

@ -3,6 +3,7 @@ module.exports =
Options: require('./src/options')
ChromeTabs: require('./src/tabs')
SwitchySharp: require('./src/switchysharp')
ExternalApi: require('./src/external_api.coffee')
Url: require('url')
for name, value of require('omega-target')

View File

@ -121,5 +121,7 @@ angular.module('omegaTarget', []).factory 'omegaTarget', ($q) ->
chrome.tabs.reload(tabs[0].id)
d.resolve()
return d.promise
openManage: ->
chrome.tabs.create url: 'chrome://extensions/?id=' + chrome.runtime.id
return omegaTarget

View File

@ -0,0 +1,62 @@
OmegaTarget = require('omega-target')
OmegaPac = OmegaTarget.OmegaPac
Promise = OmegaTarget.Promise
module.exports = class ExternalApi
constructor: (options) ->
@options = options
knownExts:
'padekgcemlokbadohgkifijomclgjgif': 32
disabled: false
listen: ->
chrome.runtime.onConnectExternal.addListener (port) =>
port.onMessage.addListener (msg) => @onMessage(msg, port)
port.onDisconnect.addListener @reenable.bind(this)
_previousProfileName: null
reenable: ->
return unless @disabled
@options.setProxyNotControllable(null)
chrome.browserAction.setPopup({popup: 'popup.html'})
@options.reloadQuickSwitch()
@disabled = false
@options.clearBadge()
@options.applyProfile(@_previousProfileName)
checkPerm: (port, level) ->
perm = @knownExts[port.sender.id] || 0
if perm < level
port.postMessage({action: 'error', error: 'permission'})
false
else
true
onMessage: (msg, port) ->
@options.log.log("#{port.sender.id} -> #{msg.action}", msg)
switch msg.action
when 'disable'
return unless @checkPerm(port, 16)
return if @disabled
@disabled = true
@_previousProfileName = @options.currentProfile()?.name || 'system'
@options.applyProfile('system').then =>
reason = 'disabled'
if @knownExts[port.sender.id] >= 32
reason = 'upgrade'
@options.setProxyNotControllable reason, {text: 'X', color: '#5ab432'}
chrome.browserAction.setPopup({popup: 'popup.html'})
port.postMessage({action: 'state', state: 'disabled'})
when 'enable'
@reenable()
port.postMessage({action: 'state', state: 'enabled'})
when 'getOptions'
return unless @checkPerm(port, 8)
port.postMessage({action: 'options', options: @options.getAll()})
else
port.postMessage(
action: 'error'
error: 'noSuchAction'
action_name: msg.action
)

View File

@ -39,11 +39,11 @@ class ChromeOptions extends OmegaTarget.Options
_proxyNotControllable: null
proxyNotControllable: -> @_proxyNotControllable
setProxyNotControllable: (reason) ->
setProxyNotControllable: (reason, badge) ->
@_proxyNotControllable = reason
if reason
@_state.set({'proxyNotControllable': reason})
@setBadge()
@setBadge(badge)
else
@_state.remove(['proxyNotControllable'])
@clearBadge()
@ -66,6 +66,7 @@ class ChromeOptions extends OmegaTarget.Options
else
@_badgeTitle = null
clearBadge: ->
return if @externalApi.disabled
if @_badgeTitle
@currentProfileChanged('clearBadge')
if @_proxyNotControllable

View File

@ -3,7 +3,7 @@ OmegaPac = OmegaTarget.OmegaPac
Promise = OmegaTarget.Promise
module.exports = class SwitchySharp
extId: 'dpplabbmogkhghncfbfdeeokoefdjegm'
@extId: 'dpplabbmogkhghncfbfdeeokoefdjegm'
port: null
monitor: (action) ->
@ -45,7 +45,7 @@ module.exports = class SwitchySharp
_connect: ->
if not @port
@port = chrome.runtime.connect(@extId)
@port = chrome.runtime.connect(SwitchySharp.extId)
@port.onDisconnect.addListener(@_onDisconnect.bind(this))
@port.onMessage.addListener(@_onMessage.bind(this))
try

View File

@ -259,14 +259,7 @@ class Options
@_state.set({'refreshOnProfileChange': refresh})
if changes['-enableQuickSwitch']? or changes['-quickSwitchProfiles']?
if @_options['-enableQuickSwitch']
profiles = @_options['-quickSwitchProfiles']
if profiles.length >= 2
@setQuickSwitch(profiles)
else
@setQuickSwitch(null)
else
@setQuickSwitch(null)
@reloadQuickSwitch()
if changes['-downloadInterval']?
@schedule 'updateProfile', @_options['-downloadInterval'], =>
@updateProfile()
@ -274,6 +267,20 @@ class Options
handler()
@_storage.watch null, handler
###*
# Reload the quick switch according to settings.
# @returns {Promise} A promise which is fulfilled when the quick switch is set
###
reloadQuickSwitch: ->
if @_options['-enableQuickSwitch']
profiles = @_options['-quickSwitchProfiles']
if profiles.length >= 2
@setQuickSwitch(profiles)
else
@setQuickSwitch(null)
else
@setQuickSwitch(null)
###*
# @callback watchCallback
# @param {Object.<string, {}>} changes A map from keys to values.

View File

@ -11,6 +11,13 @@ module.filter 'dispName', (omegaTarget) ->
module.controller 'PopupCtrl', ($scope, $window, $q, omegaTarget,
profileIcons, profileOrder, dispNameFilter, getVirtualTarget) ->
$scope.closePopup = ->
$window.close()
$scope.openManage = ->
omegaTarget.openManage()
$window.close()
refreshOnProfileChange = false
refresh = ->
if refreshOnProfileChange

View File

@ -103,8 +103,10 @@ legend,
padding: 10px;
}
.condition-controls .btn-primary {
float: right;
.condition-controls, .proxy-not-controllable-controls {
.btn-primary {
float: right;
}
}
.external-profile {
@ -128,5 +130,9 @@ legend,
.proxy-not-controllable {
min-width: 400px;
padding: 10px 5px;
padding: 10px 10px;
.proxy-not-controllable-controls {
margin-bottom: 0;
}
}

View File

@ -120,7 +120,10 @@ html(lang='en' ng-app='omegaPopup' ng-controller='PopupCtrl' ng-csp)
button.btn.btn-primary(type='submit' ng-disabled='conditionForm.$invalid') {{'popup_addCondition' | tr}}
div.proxy-not-controllable(ng-show='proxyNotControllable')
p.text-danger {{'popup_proxyNotControllable_' + proxyNotControllable | tr}}
p.help-block {{'popup_proxyNotControllableDetails' | tr}}
p.help-block {{('popup_proxyNotControllableDetails_' + proxyNotControllable | tr) || ('popup_proxyNotControllableDetails' | tr)}}
p.proxy-not-controllable-controls
button.btn.btn-default(ng-click='closePopup()') {{'dialog_cancel' | tr}}
button.btn.btn-primary(ng-click='openManage()') {{'popup_proxyNotControllableManage' | tr}}
script(src='js/log_error.js')
script(src='lib/FileSaver/FileSaver.js')