From 7fb69c7cda6f7975930bedc58cecab5e6b03504c Mon Sep 17 00:00:00 2001 From: FelisCatus Date: Sat, 6 Dec 2014 20:34:49 +0800 Subject: [PATCH] Add externalApi (cross-extension messaging) support. --- omega-i18n/en/messages.json | 12 ++++ omega-i18n/zh_CN/messages.json | 12 ++++ omega-i18n/zh_HK/messages.json | 12 ++++ omega-i18n/zh_TW/messages.json | 12 ++++ .../background.coffee | 9 ++- omega-target-chromium-extension/index.coffee | 1 + .../omega_target_web.coffee | 2 + .../src/external_api.coffee | 62 +++++++++++++++++++ .../src/options.coffee | 5 +- .../src/switchysharp.coffee | 4 +- omega-target/src/options.coffee | 23 ++++--- omega-web/src/coffee/popup.coffee | 7 +++ omega-web/src/less/popup.less | 12 +++- omega-web/src/popup.jade | 5 +- 14 files changed, 160 insertions(+), 18 deletions(-) create mode 100644 omega-target-chromium-extension/src/external_api.coffee diff --git a/omega-i18n/en/messages.json b/omega-i18n/en/messages.json index 59872e2..7a4fd21 100644 --- a/omega-i18n/en/messages.json +++ b/omega-i18n/en/messages.json @@ -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" }, diff --git a/omega-i18n/zh_CN/messages.json b/omega-i18n/zh_CN/messages.json index 450de16..d7657b8 100644 --- a/omega-i18n/zh_CN/messages.json +++ b/omega-i18n/zh_CN/messages.json @@ -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": "添加条件到情景模式" }, diff --git a/omega-i18n/zh_HK/messages.json b/omega-i18n/zh_HK/messages.json index bb41176..db4e739 100644 --- a/omega-i18n/zh_HK/messages.json +++ b/omega-i18n/zh_HK/messages.json @@ -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": "添加條件到情景模式" }, diff --git a/omega-i18n/zh_TW/messages.json b/omega-i18n/zh_TW/messages.json index b53a8ab..97d5071 100644 --- a/omega-i18n/zh_TW/messages.json +++ b/omega-i18n/zh_TW/messages.json @@ -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": "添加條件到情景模式" }, diff --git a/omega-target-chromium-extension/background.coffee b/omega-target-chromium-extension/background.coffee index 89c338b..df6cb2f 100644 --- a/omega-target-chromium-extension/background.coffee +++ b/omega-target-chromium-extension/background.coffee @@ -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'] diff --git a/omega-target-chromium-extension/index.coffee b/omega-target-chromium-extension/index.coffee index d7d884d..89f1e86 100644 --- a/omega-target-chromium-extension/index.coffee +++ b/omega-target-chromium-extension/index.coffee @@ -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') diff --git a/omega-target-chromium-extension/omega_target_web.coffee b/omega-target-chromium-extension/omega_target_web.coffee index d686524..a1a4e08 100644 --- a/omega-target-chromium-extension/omega_target_web.coffee +++ b/omega-target-chromium-extension/omega_target_web.coffee @@ -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 diff --git a/omega-target-chromium-extension/src/external_api.coffee b/omega-target-chromium-extension/src/external_api.coffee new file mode 100644 index 0000000..4cf7c74 --- /dev/null +++ b/omega-target-chromium-extension/src/external_api.coffee @@ -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 + ) diff --git a/omega-target-chromium-extension/src/options.coffee b/omega-target-chromium-extension/src/options.coffee index ae08202..1a85f5e 100644 --- a/omega-target-chromium-extension/src/options.coffee +++ b/omega-target-chromium-extension/src/options.coffee @@ -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 diff --git a/omega-target-chromium-extension/src/switchysharp.coffee b/omega-target-chromium-extension/src/switchysharp.coffee index 76a99fe..b5c5c9e 100644 --- a/omega-target-chromium-extension/src/switchysharp.coffee +++ b/omega-target-chromium-extension/src/switchysharp.coffee @@ -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 diff --git a/omega-target/src/options.coffee b/omega-target/src/options.coffee index f5fea4d..3b83fbe 100644 --- a/omega-target/src/options.coffee +++ b/omega-target/src/options.coffee @@ -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.} changes A map from keys to values. diff --git a/omega-web/src/coffee/popup.coffee b/omega-web/src/coffee/popup.coffee index 47ed0c2..281c52e 100644 --- a/omega-web/src/coffee/popup.coffee +++ b/omega-web/src/coffee/popup.coffee @@ -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 diff --git a/omega-web/src/less/popup.less b/omega-web/src/less/popup.less index b8fd84a..abe9c6f 100644 --- a/omega-web/src/less/popup.less +++ b/omega-web/src/less/popup.less @@ -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; + } } diff --git a/omega-web/src/popup.jade b/omega-web/src/popup.jade index 69f8800..5a91988 100644 --- a/omega-web/src/popup.jade +++ b/omega-web/src/popup.jade @@ -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')