From 85114c104589d7b38aebcdfc115fe0265558e7b1 Mon Sep 17 00:00:00 2001 From: suziwen Date: Sat, 23 Mar 2024 12:58:16 +0800 Subject: [PATCH] Compatible with Firefox mv3 --- README.md | 2 + omega-target-chromium-extension/bfirefox.sh | 11 +++ .../overlay/localstorage-polyfill.js | 36 ++++---- .../overlay/manifest-firefox.json | 54 ++++++++++++ .../overlay/manifest.json | 2 +- .../src/coffee/background.coffee | 1 + .../src/coffee/background_preload.coffee | 35 +++----- .../src/module/options.coffee | 85 ++++++++++--------- omega-target/src/browser_storage.coffee | 8 +- omega-web/bower.json | 4 +- omega-web/src/coffee/popup.coffee | 2 +- omega-web/src/popup/grant_permissions.html | 11 +++ omega-web/src/popup/js/grant_permissions.js | 9 ++ omega-web/src/popup/js/loader.js | 48 +++++++---- 14 files changed, 207 insertions(+), 101 deletions(-) create mode 100755 omega-target-chromium-extension/bfirefox.sh create mode 100644 omega-target-chromium-extension/overlay/manifest-firefox.json create mode 100644 omega-web/src/popup/grant_permissions.html create mode 100644 omega-web/src/popup/js/grant_permissions.js diff --git a/README.md b/README.md index 951a859..44b923f 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ ZeroOmega, forked from SwitchyOmega compatible with manifest v3 [Microsoft Edge Addons](https://microsoftedge.microsoft.com/addons/detail/zeroomegaproxy-switchy-/dmaldhchmoafliphkijbfhaomcgglmgd) +[ZeroOmega--Proxy Switchy](https://addons.mozilla.org/en-US/firefox/addon/zeroomega/) + Manage and switch between multiple proxies quickly & easily. [![Translation status](https://hosted.weblate.org/widgets/switchyomega/-/svg-badge.svg)](https://hosted.weblate.org/engage/switchyomega/?utm_source=widget) diff --git a/omega-target-chromium-extension/bfirefox.sh b/omega-target-chromium-extension/bfirefox.sh new file mode 100755 index 0000000..5e64ea9 --- /dev/null +++ b/omega-target-chromium-extension/bfirefox.sh @@ -0,0 +1,11 @@ +#!/bin/bash +. ~/.nvm/nvm.sh +nvm use 11.9.0 +rm -f ./release.zip +#minify-all-js ./build -j +cd build +rm -f manifest-chrome.json +mv manifest.json manifest-chrome.json +mv manifest-firefox.json manifest.json +zip -r ../release.zip ./* +mv manifest-chrome.json manifest.json diff --git a/omega-target-chromium-extension/overlay/localstorage-polyfill.js b/omega-target-chromium-extension/overlay/localstorage-polyfill.js index ed5f81e..754de83 100644 --- a/omega-target-chromium-extension/overlay/localstorage-polyfill.js +++ b/omega-target-chromium-extension/overlay/localstorage-polyfill.js @@ -42,21 +42,23 @@ class LocalStorage { } const instance = new LocalStorage() -globalThis.localStorage = new Proxy(instance, { - set: function (obj, prop, value) { - if (LocalStorage.prototype.hasOwnProperty(prop)) { - instance[prop] = value - } else { - instance.setItem(prop, value) +if (!globalThis.localStorage) { + globalThis.localStorage = new Proxy(instance, { + set: function (obj, prop, value) { + if (LocalStorage.prototype.hasOwnProperty(prop)) { + instance[prop] = value + } else { + instance.setItem(prop, value) + } + return true + }, + get: function (target, name) { + if (LocalStorage.prototype.hasOwnProperty(name)) { + return instance[name] + } + if (valuesMap.has(name)) { + return instance.getItem(name) + } } - return true - }, - get: function (target, name) { - if (LocalStorage.prototype.hasOwnProperty(name)) { - return instance[name] - } - if (valuesMap.has(name)) { - return instance.getItem(name) - } - } -}) + }) +} diff --git a/omega-target-chromium-extension/overlay/manifest-firefox.json b/omega-target-chromium-extension/overlay/manifest-firefox.json new file mode 100644 index 0000000..e62d9aa --- /dev/null +++ b/omega-target-chromium-extension/overlay/manifest-firefox.json @@ -0,0 +1,54 @@ +{ + "manifest_version": 3, + "name": "ZeroOmega--Proxy Switchy manifest v3 version", + "version": "3.1.0", + "description": "__MSG_manifest_app_description__", + "icons": { + "16": "img/icons/omega-action-16.png", + "24": "img/icons/omega-action-24.png", + "32": "img/icons/omega-action-32.png", + "48": "img/icons/omega-48.png", + "64": "img/icons/omega-64.png", + "128": "img/icons/omega-128.png" + }, + "default_locale": "en", + "action": { + "default_icon": { + "16": "img/icons/omega-action-16.png", + "19": "img/icons/omega-action-19.png", + "24": "img/icons/omega-action-24.png", + "32": "img/icons/omega-action-32.png" + }, + "default_title": "__MSG_manifest_icon_default_title__", + "default_popup": "popup/index.html" + }, + "background": { + "scripts": ["x-background.js"], + "type": "module" + }, + "minimum_chrome_version": "111", + "options_ui": { + "page": "options.html", + "browser_style": false, + "open_in_tab": true + }, + "commands": { + "_execute_action": { "suggested_key": { "default": "Alt+Shift+O" } } + }, + "permissions": [ + "proxy", + "tabs", + "alarms", + "storage", + "webRequest", + "webRequestBlocking", + "contextMenus" + ], + "host_permissions": [""], + "browser_specific_settings": { + "gecko": { + "id": "suziwen1@gmail.com", + "strict_min_version": "111.0" + } + } +} diff --git a/omega-target-chromium-extension/overlay/manifest.json b/omega-target-chromium-extension/overlay/manifest.json index 925a0bd..8731788 100644 --- a/omega-target-chromium-extension/overlay/manifest.json +++ b/omega-target-chromium-extension/overlay/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "ZeroOmega--Proxy Switchy manifest v3 version", - "version": "3.0.0", + "version": "3.1.0", "description": "__MSG_manifest_app_description__", "icons": { "16": "img/icons/omega-action-16.png", diff --git a/omega-target-chromium-extension/src/coffee/background.coffee b/omega-target-chromium-extension/src/coffee/background.coffee index ff0cbcd..049efef 100644 --- a/omega-target-chromium-extension/src/coffee/background.coffee +++ b/omega-target-chromium-extension/src/coffee/background.coffee @@ -184,6 +184,7 @@ proxyImpl = OmegaTargetCurrent.proxy.getProxyImpl(Log) state.set({proxyImplFeatures: proxyImpl.features}) options = new OmegaTargetCurrent.Options(null, storage, state, Log, sync, proxyImpl) + options.externalApi = new OmegaTargetCurrent.ExternalApi(options) options.externalApi.listen() diff --git a/omega-target-chromium-extension/src/coffee/background_preload.coffee b/omega-target-chromium-extension/src/coffee/background_preload.coffee index 034a846..9440787 100644 --- a/omega-target-chromium-extension/src/coffee/background_preload.coffee +++ b/omega-target-chromium-extension/src/coffee/background_preload.coffee @@ -1,25 +1,18 @@ -globalThis.window = globalThis -globalThis.global = globalThis +if not globalThis.window + globalThis.window = globalThis + globalThis.global = globalThis window.UglifyJS_NoUnsafeEval = true -window.OmegaContextMenuQuickSwitchHandler = -> null - chrome.runtime.onInstalled.addListener( -> - if chrome.contextMenus? - # We don't need this API. However its presence indicates that Chrome >= 35 - # which provides info.checked we need in contextMenu callback. - # https://developer.chrome.com/extensions/contextMenus - if chrome.i18n.getUILanguage? - chrome.contextMenus.create({ - id: 'enableQuickSwitch' - title: chrome.i18n.getMessage('contextMenu_enableQuickSwitch') - type: 'checkbox' - checked: false - contexts: ["action"] - }) - chrome.contextMenus.onClicked.addListener((info, tab) -> - switch info.menuItemId - when 'enableQuickSwitch' - globalThis.OmegaContextMenuQuickSwitchHandler(info) - ) + # We don't need this API. However its presence indicates that Chrome >= 35 + # which provides info.checked we need in contextMenu callback. + # https://developer.chrome.com/extensions/contextMenus + if chrome.i18n.getUILanguage? + chrome.contextMenus.create({ + id: 'enableQuickSwitch' + title: chrome.i18n.getMessage('contextMenu_enableQuickSwitch') + type: 'checkbox' + checked: false + contexts: ["action"] + }) ) diff --git a/omega-target-chromium-extension/src/module/options.coffee b/omega-target-chromium-extension/src/module/options.coffee index e15bf02..917dce2 100644 --- a/omega-target-chromium-extension/src/module/options.coffee +++ b/omega-target-chromium-extension/src/module/options.coffee @@ -12,6 +12,50 @@ class ChromeOptions extends OmegaTarget.Options fetchUrl: fetchUrl + constructor: (args...) -> + super(args...) + chrome.contextMenus.onClicked.addListener((info, tab) => + @ready.then( => + switch info.menuItemId + when 'enableQuickSwitch' + changes = {} + changes['-enableQuickSwitch'] = info.checked + setOptions = @_setOptions(changes) + if info.checked and not @_quickSwitchCanEnable + setOptions.then -> + chrome.tabs.create( + url: chrome.runtime.getURL('options.html#/ui') + ) + ) + ) + + chrome.action.onClicked.addListener (tab) => + if browser?.proxy?.onRequest? + browser.permissions.request({origins: [""]}) + @ready.then( => + @clearBadge() + if not @_options['-enableQuickSwitch'] + # If we reach here, then the browser does not support popup. + # Let's open the popup page in a tab. + chrome.tabs.create(url: 'popup/index.html') + return + profiles = @_options['-quickSwitchProfiles'] + index = profiles.indexOf(@_currentProfileName) + index = (index + 1) % profiles.length + @applyProfile(profiles[index]).then => + if @_options['-refreshOnProfileChange'] + url = tab.pendingUrl or tab.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-' + if tab.pendingUrl + chrome.tabs.update(tab.id, {url: url}) + else + chrome.tabs.reload(tab.id) + ) + + updateProfile: (args...) -> super(args...).then (results) -> error = false @@ -68,48 +112,11 @@ class ChromeOptions extends OmegaTarget.Options chrome.action.setBadgeText?(text: '') return - _quickSwitchInit: false - _quickSwitchHandlerReady: false _quickSwitchCanEnable: false setQuickSwitch: (quickSwitch, canEnable) -> @_quickSwitchCanEnable = canEnable - if not @_quickSwitchHandlerReady - @_quickSwitchHandlerReady = true - window.OmegaContextMenuQuickSwitchHandler = (info) => - changes = {} - changes['-enableQuickSwitch'] = info.checked - setOptions = @_setOptions(changes) - if info.checked and not @_quickSwitchCanEnable - setOptions.then -> - chrome.tabs.create( - url: chrome.runtime.getURL('options.html#/ui') - ) - - if quickSwitch or not chrome.action.setPopup? - chrome.action.setPopup?({popup: ''}) - if not @_quickSwitchInit - @_quickSwitchInit = true - chrome.action.onClicked.addListener (tab) => - @clearBadge() - if not @_options['-enableQuickSwitch'] - # If we reach here, then the browser does not support popup. - # Let's open the popup page in a tab. - chrome.tabs.create(url: 'popup/index.html') - return - profiles = @_options['-quickSwitchProfiles'] - index = profiles.indexOf(@_currentProfileName) - index = (index + 1) % profiles.length - @applyProfile(profiles[index]).then => - if @_options['-refreshOnProfileChange'] - url = tab.pendingUrl or tab.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-' - if tab.pendingUrl - chrome.tabs.update(tab.id, {url: url}) - else - chrome.tabs.reload(tab.id) + if quickSwitch + chrome.action.setPopup({popup: ''}) else chrome.action.setPopup({popup: 'popup/index.html'}) diff --git a/omega-target/src/browser_storage.coffee b/omega-target/src/browser_storage.coffee index 7e5aff6..c48071a 100644 --- a/omega-target/src/browser_storage.coffee +++ b/omega-target/src/browser_storage.coffee @@ -10,7 +10,7 @@ class BrowserStorage extends Storage get: (keys) -> promiseResult = idbKeyval.get('localStorage').then((initValuesMap) => if !_globalLocalStorageCache - @proto.initValuesMap(initValuesMap) + @proto.initValuesMap?(initValuesMap) _globalLocalStorageCache = true map = {} if typeof keys == 'string' @@ -33,13 +33,14 @@ class BrowserStorage extends Storage set: (items) -> promiseResult = idbKeyval.get('localStorage').then((initValuesMap) => if !_globalLocalStorageCache - @proto.initValuesMap(initValuesMap) + @proto.initValuesMap?(initValuesMap) _globalLocalStorageCache = true for own key, value of items value = JSON.stringify(value) @proto.setItem.call(@storage, @prefix + key, value) return items ).then((items) => + return items unless @proto.getValuesMap initValuesMap = @proto.getValuesMap() idbKeyval.set('localStorage', initValuesMap).then( -> return items @@ -50,7 +51,7 @@ class BrowserStorage extends Storage remove: (keys) -> promiseResult = idbKeyval.get('localStorage').then((initValuesMap) => if !_globalLocalStorageCache - @proto.initValuesMap(initValuesMap) + @proto.initValuesMap?(initValuesMap) _globalLocalStorageCache = true if not keys? if not @prefix @@ -70,6 +71,7 @@ class BrowserStorage extends Storage @proto.removeItem.call(@storage, @prefix + key) ).then( => + return unless @proto.getValuesMap initValuesMap = @proto.getValuesMap() idbKeyval.set('localStorage', initValuesMap).then( -> return diff --git a/omega-web/bower.json b/omega-web/bower.json index 5aa206d..446d26d 100644 --- a/omega-web/bower.json +++ b/omega-web/bower.json @@ -21,7 +21,7 @@ "tests" ], "dependencies": { - "angular": "~1.7.2", + "angular": "~1.8.2", "angular-animate": "~1.7.2", "angular-loader": "~1.7.2", "angular-i18n": "~1.7.2", @@ -127,6 +127,6 @@ } }, "resolutions": { - "angular": "~1.7.2" + "angular": "~1.8.2" } } diff --git a/omega-web/src/coffee/popup.coffee b/omega-web/src/coffee/popup.coffee index d4a0dd8..cb92e04 100644 --- a/omega-web/src/coffee/popup.coffee +++ b/omega-web/src/coffee/popup.coffee @@ -178,7 +178,7 @@ module.controller 'PopupCtrl', ($scope, $window, $q, omegaTarget, $scope.saveExternal = -> $scope.nameExternal.open = false - name = $scope.externalProfile.name + name = $scope.externalProfile?.name if name omegaTarget.addProfile($scope.externalProfile).then -> omegaTarget.applyProfile(name).then -> diff --git a/omega-web/src/popup/grant_permissions.html b/omega-web/src/popup/grant_permissions.html new file mode 100644 index 0000000..cdc544d --- /dev/null +++ b/omega-web/src/popup/grant_permissions.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/omega-web/src/popup/js/grant_permissions.js b/omega-web/src/popup/js/grant_permissions.js new file mode 100644 index 0000000..3f35174 --- /dev/null +++ b/omega-web/src/popup/js/grant_permissions.js @@ -0,0 +1,9 @@ + +const btn = document.querySelector('#grant-permissions-btn') +btn.onclick = async ()=>{ + const permissionValue = {origins: [""]} + const hasPermission = await browser.permissions.request(permissionValue); + if (hasPermission) { + location.href = 'index.html' + } +} diff --git a/omega-web/src/popup/js/loader.js b/omega-web/src/popup/js/loader.js index 21a5559..8eeef2c 100644 --- a/omega-web/src/popup/js/loader.js +++ b/omega-web/src/popup/js/loader.js @@ -2,21 +2,35 @@ window.OmegaPopup = {}; $script(['js/index.js', 'js/profiles.js', 'js/keyboard.js'], 'om-main'); $script(['js/i18n.js']); $script('../js/omega_target_popup.js', 'om-target', function() { - OmegaTargetPopup.getActivePageInfo(function(err, info) { - window.OmegaPopup.pageInfo = info; - $script.done('om-page-info'); - }); - OmegaTargetPopup.getState([ - 'availableProfiles', - 'currentProfileName', - 'validResultProfiles', - 'isSystemProfile', - 'currentProfileCanAddRule', - 'proxyNotControllable', - 'externalProfile', - 'showExternalProfile', - ], function(err, state) { - window.OmegaPopup.state = state; - $script.done('om-state'); - }); + function init(){ + OmegaTargetPopup.getActivePageInfo(function(err, info) { + window.OmegaPopup.pageInfo = info; + $script.done('om-page-info'); + }); + OmegaTargetPopup.getState([ + 'availableProfiles', + 'currentProfileName', + 'validResultProfiles', + 'isSystemProfile', + 'currentProfileCanAddRule', + 'proxyNotControllable', + 'externalProfile', + 'showExternalProfile', + ], function(err, state) { + window.OmegaPopup.state = state; + $script.done('om-state'); + }); + } + const permissionValue = {origins: [""]} + if (globalThis.browser && browser.proxy && browser.proxy.onRequest){ + chrome.permissions.contains(permissionValue).then((hasPermission)=>{ + if (!hasPermission) { + location.href = 'grant_permissions.html' + } else { + init(); + } + }) + } else { + init(); + } });