diff --git a/.gitignore b/.gitignore index a088b6f..c489503 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules bower_components +package-lock.json diff --git a/README.md b/README.md index e38096d..3fc74c9 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ To build the project: grunt # After building, a folder will be generated: cd .. # Return to project root. - ls omega-chromium-extension/build/ + ls omega-target-chromium-extension/build/ # The folder above can be loaded as an unpacked extension in Chromium now. To enable `grunt watch`, run `grunt watch` once in the `omega-build` directory. diff --git a/omega-pac/uglifyjs.js b/omega-pac/uglifyjs.js index d0e268d..942de68 100644 --- a/omega-pac/uglifyjs.js +++ b/omega-pac/uglifyjs.js @@ -1,5 +1,5 @@ (function(exports, global) { - global["UglifyJS"] = exports; + globalThis["UglifyJS"] = exports; "use strict"; function array_to_hash(a) { var ret = Object.create(null); @@ -6720,4 +6720,4 @@ exports["SourceMap"] = SourceMap; })({}, function() { return this; -}()); \ No newline at end of file +}()); diff --git a/omega-target-chromium-extension/.gitignore b/omega-target-chromium-extension/.gitignore index 8ff7020..7154fdb 100644 --- a/omega-target-chromium-extension/.gitignore +++ b/omega-target-chromium-extension/.gitignore @@ -3,5 +3,6 @@ /tmp /build +/build* /release.zip /web-ext-artifacts diff --git a/omega-target-chromium-extension/b.sh b/omega-target-chromium-extension/b.sh new file mode 100755 index 0000000..f1e484b --- /dev/null +++ b/omega-target-chromium-extension/b.sh @@ -0,0 +1,5 @@ +#!/bin/bash +. ~/.nvm/nvm.sh +nvm use 11.9.0 +minify-all-js ./build -j +cd build && zip -r ../release.zip ./* diff --git a/omega-target-chromium-extension/overlay/idb-keyval.js b/omega-target-chromium-extension/overlay/idb-keyval.js new file mode 100644 index 0000000..8176c3f --- /dev/null +++ b/omega-target-chromium-extension/overlay/idb-keyval.js @@ -0,0 +1 @@ +function _slicedToArray(t,n){return _arrayWithHoles(t)||_iterableToArrayLimit(t,n)||_unsupportedIterableToArray(t,n)||_nonIterableRest()}function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _unsupportedIterableToArray(t,n){if(t){if("string"==typeof t)return _arrayLikeToArray(t,n);var r=Object.prototype.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?_arrayLikeToArray(t,n):void 0}}function _arrayLikeToArray(t,n){(null==n||n>t.length)&&(n=t.length);for(var r=0,e=new Array(n);r0&&void 0!==arguments[0]?arguments[0]:o();return t("readwrite",(function(t){return t.clear(),n(t.transaction)}))},t.createStore=r,t.del=function(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:o();return r("readwrite",(function(r){return r.delete(t),n(r.transaction)}))},t.delMany=function(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:o();return r("readwrite",(function(r){return t.forEach((function(t){return r.delete(t)})),n(r.transaction)}))},t.entries=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:o();return t("readonly",(function(r){if(r.getAll&&r.getAllKeys)return Promise.all([n(r.getAllKeys()),n(r.getAll())]).then((function(t){var n=_slicedToArray(t,2),r=n[0],e=n[1];return r.map((function(t,n){return[t,e[n]]}))}));var e=[];return t("readonly",(function(t){return u(t,(function(t){return e.push([t.key,t.value])})).then((function(){return e}))}))}))},t.get=function(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:o();return r("readonly",(function(r){return n(r.get(t))}))},t.getMany=function(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:o();return r("readonly",(function(r){return Promise.all(t.map((function(t){return n(r.get(t))})))}))},t.keys=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:o();return t("readonly",(function(t){if(t.getAllKeys)return n(t.getAllKeys());var r=[];return u(t,(function(t){return r.push(t.key)})).then((function(){return r}))}))},t.promisifyRequest=n,t.set=function(t,r){var e=arguments.length>2&&void 0!==arguments[2]?arguments[2]:o();return e("readwrite",(function(e){return e.put(r,t),n(e.transaction)}))},t.setMany=function(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:o();return r("readwrite",(function(r){return t.forEach((function(t){return r.put(t[1],t[0])})),n(r.transaction)}))},t.update=function(t,r){var e=arguments.length>2&&void 0!==arguments[2]?arguments[2]:o();return e("readwrite",(function(e){return new Promise((function(o,u){e.get(t).onsuccess=function(){try{e.put(r(this.result),t),o(n(e.transaction))}catch(t){u(t)}}}))}))},t.values=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:o();return t("readonly",(function(t){if(t.getAll)return n(t.getAll());var r=[];return u(t,(function(t){return r.push(t.value)})).then((function(){return r}))}))},Object.defineProperty(t,"__esModule",{value:!0})})); diff --git a/omega-target-chromium-extension/overlay/localstorage-polyfill.js b/omega-target-chromium-extension/overlay/localstorage-polyfill.js new file mode 100644 index 0000000..ed5f81e --- /dev/null +++ b/omega-target-chromium-extension/overlay/localstorage-polyfill.js @@ -0,0 +1,62 @@ +'use strict' +let valuesMap = new Map() + +class LocalStorage { + getItem (key) { + const stringKey = String(key) + if (valuesMap.has(key)) { + return String(valuesMap.get(stringKey)) + } + return null + } + + setItem (key, val) { + valuesMap.set(String(key), String(val)) + } + + removeItem (key) { + valuesMap.delete(key) + } + + clear () { + valuesMap.clear() + } + + key (i) { + if (arguments.length === 0) { + throw new TypeError("Failed to execute 'key' on 'Storage': 1 argument required, but only 0 present.") // this is a TypeError implemented on Chrome, Firefox throws Not enough arguments to Storage.key. + } + var arr = Array.from(valuesMap.keys()) + return arr[i] + } + + get length () { + return valuesMap.size + } + initValuesMap (_valuesMap){ + valuesMap = new Map(Object.entries(_valuesMap || {})) + } + getValuesMap (){ + return Object.fromEntries(valuesMap); + } +} +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) + } + 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.json b/omega-target-chromium-extension/overlay/manifest.json index 26b465d..925a0bd 100644 --- a/omega-target-chromium-extension/overlay/manifest.json +++ b/omega-target-chromium-extension/overlay/manifest.json @@ -1,9 +1,8 @@ { - "manifest_version": 2, - "name": "__MSG_manifest_app_name__", - "version": "2.5.21", + "manifest_version": 3, + "name": "ZeroOmega--Proxy Switchy manifest v3 version", + "version": "3.0.0", "description": "__MSG_manifest_app_description__", - "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkhwZJT76btQ04EEMOFtZPLESD1TmSVjbLjs0OyesD9Ht8YllFPfJ3qmtbSQGVuvmxH1GK/jUO2QcEWb8bHuOjoRlq20fi5j5Aq90O8FKET+y5D8PxCyi3WmnquiEwaE5cNmaCsw/G2JlO+bZOtdQ/QKOvMxBAegABYimEGfSvCMVUEvpymys0gBhLoch72zPAiJUBkf0z8BtjYTueMRcRXkrSeRPLygUDQnZ1TkQWMYYBp/zqpD5ggxytAklEMQzR9Hn0lqu5s7iuUAgihbysPn/8Wh00Zj5FySpK//KcpG3JS7UWxC28oSt8z5ZR3YimnX+HX3P36V0mC1pgM4o7wIDAQAB", "icons": { "16": "img/icons/omega-action-16.png", "24": "img/icons/omega-action-24.png", @@ -13,8 +12,7 @@ "128": "img/icons/omega-128.png" }, "default_locale": "en", - "browser_action": { - "browser_style": false, + "action": { "default_icon": { "16": "img/icons/omega-action-16.png", "19": "img/icons/omega-action-19.png", @@ -25,40 +23,27 @@ "default_popup": "popup/index.html" }, "background": { - "page": "background.html" + "service_worker": "x-background.js", + "type": "module" }, - "minimum_chrome_version": "22.0.0", + "minimum_chrome_version": "111", "options_page": "options.html", "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", - "downloads", - "webRequestBlocking", - "contextMenus", - - "http://*/*", - "https://*/*", - "" + "webRequestAuthProvider", + "contextMenus" ], - "commands": { - "_execute_browser_action": { - "suggested_key": { - "default": "Alt+Shift+O" - } - } - }, - "applications": { - "gecko": { - "id": "switchyomega@feliscatus.addons.mozilla.org", - "strict_min_version": "55.0a1" - } - } + "host_permissions": [""] } diff --git a/omega-target-chromium-extension/overlay/x-background.js b/omega-target-chromium-extension/overlay/x-background.js new file mode 100644 index 0000000..0251867 --- /dev/null +++ b/omega-target-chromium-extension/overlay/x-background.js @@ -0,0 +1,11 @@ +import "./js/background_preload.js" +import "./idb-keyval.js" +import "./localstorage-polyfill.js" +import "./js/log_error.js" +//import "./lib/FileSaver/FileSaver.min.js" +import "./js/omega_debug.js" +import "./js/omega_pac.min.js" +import "./js/omega_target.min.js" +import "./js/omega_target_chromium_extension.min.js" +import "./img/icons/draw_omega.js" +import "./js/background.js" diff --git a/omega-target-chromium-extension/src/coffee/background.coffee b/omega-target-chromium-extension/src/coffee/background.coffee index ac4514a..fa1fb18 100644 --- a/omega-target-chromium-extension/src/coffee/background.coffee +++ b/omega-target-chromium-extension/src/coffee/background.coffee @@ -45,7 +45,8 @@ drawIcon = (resultColor, profileColor) -> return icon if icon try if not drawContext? - drawContext = document.getElementById('canvas-icon').getContext('2d') + canvas = new OffscreenCanvas(300, 300) + drawContext = canvas.getContext('2d', { willReadFrequently: true }) icon = {} for size in [16, 19, 24, 32, 38] @@ -186,7 +187,7 @@ options = new OmegaTargetCurrent.Options(null, storage, state, Log, sync, options.externalApi = new OmegaTargetCurrent.ExternalApi(options) options.externalApi.listen() -if chrome.runtime.id != OmegaTargetCurrent.SwitchySharp.extId +if chrome.runtime.id != OmegaTargetCurrent.SwitchySharp.extId and false options.switchySharp = new OmegaTargetCurrent.SwitchySharp() options.switchySharp.monitor() @@ -212,7 +213,7 @@ options._inspect = new OmegaTargetCurrent.Inspect (url, tab) -> title = chrome.i18n.getMessage('browserAction_titleInspect', urlDisp) + '\n' title += action.title - chrome.browserAction.setTitle(title: title, tabId: tab.id) + chrome.action.setTitle(title: title, tabId: tab.id) tabs.setTabBadge(tab, { text: '#' color: action.resultColor @@ -320,12 +321,15 @@ encodeError = (obj) -> refreshActivePageIfEnabled = -> return if localStorage['omega.local.refreshOnProfileChange'] == 'false' chrome.tabs.query {active: true, lastFocusedWindow: true}, (tabs) -> - url = tabs[0].url + url = tabs[0].url or 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}) + if tabs[0].pendingUrl + chrome.tabs.update(tabs[0].id, {url: url}) + else + chrome.tabs.reload(tabs[0].id, {bypassCache: true}) chrome.runtime.onMessage.addListener (request, sender, respond) -> return unless request and request.method @@ -333,6 +337,9 @@ chrome.runtime.onMessage.addListener (request, sender, respond) -> if request.method == 'getState' target = state method = state.get + else if request.method == 'setState' + target = state + method = state.set else target = options method = target[request.method] diff --git a/omega-target-chromium-extension/src/coffee/background_preload.coffee b/omega-target-chromium-extension/src/coffee/background_preload.coffee index ced9727..034a846 100644 --- a/omega-target-chromium-extension/src/coffee/background_preload.coffee +++ b/omega-target-chromium-extension/src/coffee/background_preload.coffee @@ -1,32 +1,25 @@ +globalThis.window = globalThis +globalThis.global = globalThis window.UglifyJS_NoUnsafeEval = true -localStorage['log'] = '' -localStorage['logLastError'] = '' window.OmegaContextMenuQuickSwitchHandler = -> null -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? - # We must create the menu item here before others to make it first in menu. - chrome.contextMenus.create({ - id: 'enableQuickSwitch' - title: chrome.i18n.getMessage('contextMenu_enableQuickSwitch') - type: 'checkbox' - checked: false - contexts: ["browser_action"] - onclick: (info) -> window.OmegaContextMenuQuickSwitchHandler(info) - }) - - chrome.contextMenus.create({ - title: chrome.i18n.getMessage('popup_reportIssues') - contexts: ["browser_action"] - onclick: OmegaDebug.reportIssue - }) - - chrome.contextMenus.create({ - title: chrome.i18n.getMessage('popup_errorLog') - contexts: ["browser_action"] - onclick: OmegaDebug.downloadLog - }) +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) + ) +) diff --git a/omega-target-chromium-extension/src/coffee/omega_debug.coffee b/omega-target-chromium-extension/src/coffee/omega_debug.coffee index 92ba61b..28a0b2b 100644 --- a/omega-target-chromium-extension/src/coffee/omega_debug.coffee +++ b/omega-target-chromium-extension/src/coffee/omega_debug.coffee @@ -6,12 +6,7 @@ window.OmegaDebug = downloadLog: -> blob = new Blob [localStorage['log']], {type: "text/plain;charset=utf-8"} filename = "OmegaLog_#{Date.now()}.txt" - - if browser?.downloads?.download? - url = URL.createObjectURL(blob) - browser.downloads.download({url: url, filename: filename}) - else - saveAs(blob, filename) + saveAs(blob, filename) resetOptions: -> localStorage.clear() # Prevent options loading from sync storage after reload. diff --git a/omega-target-chromium-extension/src/coffee/omega_target_web.coffee b/omega-target-chromium-extension/src/coffee/omega_target_web.coffee index 4e2cee1..1530c5f 100644 --- a/omega-target-chromium-extension/src/coffee/omega_target_web.coffee +++ b/omega-target-chromium-extension/src/coffee/omega_target_web.coffee @@ -50,19 +50,27 @@ angular.module('omegaTarget', []).factory 'omegaTarget', ($q) -> omegaTarget = options: null state: (name, value) -> + d = $q.defer() if arguments.length == 1 - getValue = (key) -> try JSON.parse(localStorage[prefix + key]) if Array.isArray(name) - return $q.when(name.map(getValue)) + callBackground('getState', name).then((values) -> + d.resolve(name.map((key) -> values[key])) + ) else - value = getValue(name) + callBackground('getState', [name]).then( (values) -> + d.resolve(values[name]) + ) else - localStorage[prefix + name] = JSON.stringify(value) - return $q.when(value) + newItem = {} + newItem[name] = value + callBackground('setState', newItem).then( -> + d.resolve(value) + ) + return d.promise lastUrl: (url) -> name = 'web.last_url' if url - omegaTarget.state(name, url) + localStorage[prefix + name] = url url else try JSON.parse(localStorage[prefix + name]) @@ -91,7 +99,7 @@ angular.module('omegaTarget', []).factory 'omegaTarget', ($q) -> getMessage: chrome.i18n.getMessage.bind(chrome.i18n) openOptions: (hash) -> d = $q['defer']() - options_url = chrome.extension.getURL('options.html') + options_url = chrome.runtime.getURL('options.html') chrome.tabs.query url: options_url, (tabs) -> url = if hash urlParser.href = tabs[0]?.url || options_url @@ -124,10 +132,10 @@ angular.module('omegaTarget', []).factory 'omegaTarget', ($q) -> clearBadge = true d = $q['defer']() chrome.tabs.query {active: true, lastFocusedWindow: true}, (tabs) -> - if not tabs[0]?.url + if tabs.length == 0 or not (tabs[0].pendingUrl || tabs[0].url) d.resolve(null) return - args = {tabId: tabs[0].id, url: tabs[0].url} + args = {tabId: tabs[0].id, url: tabs[0].pendingUrl || tabs[0].url} if tabs[0].id and requestInfoCallback connectBackground('tabRequestInfo', args, requestInfoCallback) @@ -136,8 +144,12 @@ angular.module('omegaTarget', []).factory 'omegaTarget', ($q) -> refreshActivePage: -> d = $q['defer']() chrome.tabs.query {active: true, lastFocusedWindow: true}, (tabs) -> - if tabs[0].url and not isChromeUrl(tabs[0].url) - chrome.tabs.reload(tabs[0].id, {bypassCache: true}) + url = tabs[0].pendingUrl || tabs[0].url + if url and not isChromeUrl(url) + if tabs[0].pendingUrl + chrome.tabs.update(tabs[0].id, {url}) + else + chrome.tabs.reload(tabs[0].id, {bypassCache: true}) d.resolve() return d.promise openManage: -> diff --git a/omega-target-chromium-extension/src/js/omega_target_popup.js b/omega-target-chromium-extension/src/js/omega_target_popup.js index ae0b893..c3d6283 100644 --- a/omega-target-chromium-extension/src/js/omega_target_popup.js +++ b/omega-target-chromium-extension/src/js/omega_target_popup.js @@ -24,25 +24,15 @@ var requestInfoCallback = null; OmegaTargetPopup = { getState: function (keys, cb) { - if (typeof localStorage === 'undefined' || !localStorage.length) { - callBackground('getState', [keys], cb); - return; - } - var results = {}; - keys.forEach(function(key) { - try { - results[key] = JSON.parse(localStorage['omega.local.' + key]); - } catch (_) { - return null; - } - }); - if (cb) cb(null, results); + callBackground('getState', [keys], cb); + return; }, applyProfile: function (name, cb) { callBackgroundNoReply('applyProfile', [name], cb); }, openOptions: function (hash, cb) { - var options_url = chrome.extension.getURL('options.html'); + var options_url = chrome.runtime.getURL('options.html'); + console.log('open options.....') chrome.tabs.query({ url: options_url @@ -66,8 +56,8 @@ OmegaTargetPopup = { }, getActivePageInfo: function(cb) { chrome.tabs.query({active: true, lastFocusedWindow: true}, function (tabs) { - if (tabs.length === 0 || !tabs[0].url) return cb(); - var args = {tabId: tabs[0].id, url: tabs[0].url}; + if (tabs.length === 0 || !(tabs[0].pendingUrl || tabs[0].url)) return cb(); + var args = {tabId: tabs[0].id, url: tabs[0].pendingUrl || tabs[0].url}; callBackground('getPageInfo', [args], cb) }); }, diff --git a/omega-target-chromium-extension/src/module/external_api.coffee b/omega-target-chromium-extension/src/module/external_api.coffee index 8f58534..6e172c1 100644 --- a/omega-target-chromium-extension/src/module/external_api.coffee +++ b/omega-target-chromium-extension/src/module/external_api.coffee @@ -22,7 +22,7 @@ module.exports = class ExternalApi return unless @disabled @options.setProxyNotControllable(null) - chrome.browserAction.setPopup?({popup: 'popup/index.html'}) + chrome.action.setPopup?({popup: 'popup/index.html'}) @options.reloadQuickSwitch() @disabled = false @options.clearBadge() @@ -49,7 +49,7 @@ module.exports = class ExternalApi if @knownExts[port.sender.id] >= 32 reason = 'upgrade' @options.setProxyNotControllable reason, {text: 'X', color: '#5ab432'} - chrome.browserAction.setPopup?({popup: 'popup/index.html'}) + chrome.action.setPopup?({popup: 'popup/index.html'}) port.postMessage({action: 'state', state: 'disabled'}) when 'enable' @reenable() diff --git a/omega-target-chromium-extension/src/module/fetch_url.coffee b/omega-target-chromium-extension/src/module/fetch_url.coffee index 83da436..212d681 100644 --- a/omega-target-chromium-extension/src/module/fetch_url.coffee +++ b/omega-target-chromium-extension/src/module/fetch_url.coffee @@ -1,10 +1,14 @@ Promise = OmegaTarget.Promise -xhr = Promise.promisify(require('xhr')) +#xhr = Promise.promisify(require('xhr')) Url = require('url') ContentTypeRejectedError = OmegaTarget.ContentTypeRejectedError xhrWrapper = (args...) -> - xhr(args...).catch (err) -> + fetch(args...).then((response) -> + response.text().then((body) -> + return [response, body] + ) + ).catch (err) -> throw err unless err.isOperational if not err.statusCode throw new OmegaTarget.NetworkError(err) diff --git a/omega-target-chromium-extension/src/module/inspect.coffee b/omega-target-chromium-extension/src/module/inspect.coffee index 7fa2375..91da11b 100644 --- a/omega-target-chromium-extension/src/module/inspect.coffee +++ b/omega-target-chromium-extension/src/module/inspect.coffee @@ -15,6 +15,7 @@ module.exports = class Inspect return unless chrome.i18n.getUILanguage? return if @_enabled + return webResource = [ "http://*/*" diff --git a/omega-target-chromium-extension/src/module/options.coffee b/omega-target-chromium-extension/src/module/options.coffee index 09ac9f2..e15bf02 100644 --- a/omega-target-chromium-extension/src/module/options.coffee +++ b/omega-target-chromium-extension/src/module/options.coffee @@ -51,11 +51,11 @@ class ChromeOptions extends OmegaTarget.Options else text: '?' color: '#49afcd' - chrome.browserAction.setBadgeText(text: options.text) - chrome.browserAction.setBadgeBackgroundColor(color: options.color) + chrome.action.setBadgeText(text: options.text) + chrome.action.setBadgeBackgroundColor(color: options.color) if options.title @_badgeTitle = options.title - chrome.browserAction.setTitle(title: options.title) + chrome.action.setTitle(title: options.title) else @_badgeTitle = null clearBadge: -> @@ -65,7 +65,7 @@ class ChromeOptions extends OmegaTarget.Options if @_proxyNotControllable @setBadge() else - chrome.browserAction.setBadgeText?(text: '') + chrome.action.setBadgeText?(text: '') return _quickSwitchInit: false @@ -82,14 +82,14 @@ class ChromeOptions extends OmegaTarget.Options if info.checked and not @_quickSwitchCanEnable setOptions.then -> chrome.tabs.create( - url: chrome.extension.getURL('options.html#/ui') + url: chrome.runtime.getURL('options.html#/ui') ) - if quickSwitch or not chrome.browserAction.setPopup? - chrome.browserAction.setPopup?({popup: ''}) + if quickSwitch or not chrome.action.setPopup? + chrome.action.setPopup?({popup: ''}) if not @_quickSwitchInit @_quickSwitchInit = true - chrome.browserAction.onClicked.addListener (tab) => + chrome.action.onClicked.addListener (tab) => @clearBadge() if not @_options['-enableQuickSwitch'] # If we reach here, then the browser does not support popup. @@ -101,14 +101,17 @@ class ChromeOptions extends OmegaTarget.Options index = (index + 1) % profiles.length @applyProfile(profiles[index]).then => if @_options['-refreshOnProfileChange'] - url = tab.url + 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-' - chrome.tabs.reload(tab.id) + if tab.pendingUrl + chrome.tabs.update(tab.id, {url: url}) + else + chrome.tabs.reload(tab.id) else - chrome.browserAction.setPopup({popup: 'popup/index.html'}) + chrome.action.setPopup({popup: 'popup/index.html'}) chrome.contextMenus?.update('enableQuickSwitch', {checked: !!quickSwitch}) Promise.resolve() @@ -135,14 +138,22 @@ class ChromeOptions extends OmegaTarget.Options if info.errorCount > 0 info.badgeSet = true badge = {text: info.errorCount.toString(), color: '#f0ad4e'} - chrome.browserAction.setBadgeText(text: badge.text, tabId: tabId) - chrome.browserAction.setBadgeBackgroundColor( + chrome.action.setBadgeText(text: badge.text, tabId: tabId) + .catch((e) -> + console.log('error:',e) + ) + chrome.action.setBadgeBackgroundColor( color: badge.color tabId: tabId + ).catch((e) -> + console.log('error:',e) ) else if info.badgeSet info.badgeSet = false - chrome.browserAction.setBadgeText(text: '', tabId: tabId) + chrome.action.setBadgeText(text: '', tabId: tabId) + .catch((e) -> + console.log('error:',e) + ) @_tabRequestInfoPorts[tabId]?.postMessage({ errorCount: info.errorCount summary: info.summary @@ -210,10 +221,7 @@ class ChromeOptions extends OmegaTarget.Options upgrade: (options, changes) -> super(options).catch (err) => return Promise.reject err if options?['schemaVersion'] - getOldOptions = if @switchySharp - @switchySharp.getOptions().timeout(1000) - else - Promise.reject() + getOldOptions = Promise.reject() getOldOptions = getOldOptions.catch -> if options?['config'] @@ -239,16 +247,17 @@ class ChromeOptions extends OmegaTarget.Options return this && super(upgraded, upgraded) onFirstRun: (reason) -> - chrome.tabs.create url: chrome.extension.getURL('options.html') + console.log('first run ....') + chrome.tabs.create url: chrome.runtime.getURL('options.html') getPageInfo: ({tabId, url}) -> errorCount = @_requestMonitor?.tabInfo[tabId]?.errorCount result = if errorCount then {errorCount: errorCount} else null getBadge = new Promise (resolve, reject) -> - if not chrome.browserAction.getBadgeText? + if not chrome.action.getBadgeText? resolve('') return - chrome.browserAction.getBadgeText {tabId: tabId}, (result) -> + chrome.action.getBadgeText {tabId: tabId}, (result) -> resolve(result) getInspectUrl = @_state.get({inspectUrl: ''}) diff --git a/omega-target-chromium-extension/src/module/tabs.coffee b/omega-target-chromium-extension/src/module/tabs.coffee index 108b4f4..508e73e 100644 --- a/omega-target-chromium-extension/src/module/tabs.coffee +++ b/omega-target-chromium-extension/src/module/tabs.coffee @@ -25,10 +25,10 @@ class ChromeTabs tabs.forEach (tab) => @_dirtyTabs[tab.id] = tab.id @onUpdated tab.id, {}, tab if tab.active - if chrome.browserAction.setPopup? - chrome.browserAction.setTitle({title: action.title}) + if chrome.action.setPopup? + chrome.action.setTitle({title: action.title}) else - chrome.browserAction.setTitle({title: action.shortTitle}) + chrome.action.setTitle({title: action.shortTitle}) @setIcon(action.icon) onUpdated: (tabId, changeInfo, tab) -> @@ -42,32 +42,35 @@ class ChromeTabs processTab: (tab, changeInfo) -> if @_badgeTab for own id of @_badgeTab - try chrome.browserAction.setBadgeText?(text: '', tabId: id) + try chrome.action.setBadgeText?(text: '', tabId: id) @_badgeTab = null if not tab.url? or tab.url.indexOf("chrome") == 0 if @_defaultAction - chrome.browserAction.setTitle({ + chrome.action.setTitle({ title: @_defaultAction.title tabId: tab.id }) @clearIcon tab.id return - @actionForUrl(tab.url).then (action) => + @actionForUrl(tab.url).then((action) => if not action @clearIcon tab.id return @setIcon(action.icon, tab.id) - if chrome.browserAction.setPopup? - chrome.browserAction.setTitle({title: action.title, tabId: tab.id}) + if chrome.action.setPopup? + chrome.action.setTitle({title: action.title, tabId: tab.id}) else - chrome.browserAction.setTitle({title: action.shortTitle, tabId: tab.id}) + chrome.action.setTitle({title: action.shortTitle, tabId: tab.id}) + ).catch((e) -> + console.log('error:', e) + ) setTabBadge: (tab, badge) -> @_badgeTab ?= {} @_badgeTab[tab.id] = true - chrome.browserAction.setBadgeText?(text: badge.text, tabId: tab.id) - chrome.browserAction.setBadgeBackgroundColor?( + chrome.action.setBadgeText?(text: badge.text, tabId: tab.id) + chrome.action.setBadgeBackgroundColor?( color: badge.color tabId: tab.id ) @@ -87,11 +90,11 @@ class ChromeTabs _chromeSetIcon: (params) -> try - chrome.browserAction.setIcon?(params, @ignoreError) + chrome.action.setIcon?(params, @ignoreError) catch _ # Some legacy Chrome versions will panic if there are other icon sizes. params.imageData = {19: params.imageData[19], 38: params.imageData[38]} - chrome.browserAction.setIcon?(params, @ignoreError) + chrome.action.setIcon?(params, @ignoreError) clearIcon: (tabId) -> return unless @_defaultAction?.icon? diff --git a/omega-target-chromium-extension/src/module/web_request_monitor.coffee b/omega-target-chromium-extension/src/module/web_request_monitor.coffee index d360405..a5b807c 100644 --- a/omega-target-chromium-extension/src/module/web_request_monitor.coffee +++ b/omega-target-chromium-extension/src/module/web_request_monitor.coffee @@ -128,8 +128,8 @@ module.exports = class WebRequestMonitor chrome.tabs.onCreated.addListener (tab) => return unless tab.id @tabInfo[tab.id] = @_newTabInfo() - chrome.tabs.onRemoved.addListener (tab) => - delete @tabInfo[tab.id] + chrome.tabs.onRemoved.addListener (tabId) => + delete @tabInfo[tabId] chrome.tabs.onReplaced?.addListener (added, removed) => @tabInfo[added] ?= @_newTabInfo() delete @tabInfo[removed] diff --git a/omega-target/src/browser_storage.coffee b/omega-target/src/browser_storage.coffee index 05d0575..7e5aff6 100644 --- a/omega-target/src/browser_storage.coffee +++ b/omega-target/src/browser_storage.coffee @@ -1,51 +1,80 @@ Storage = require('./storage') Promise = require('bluebird') +_globalLocalStorageCache = null + class BrowserStorage extends Storage constructor: (@storage, @prefix = '') -> @proto = Object.getPrototypeOf(@storage) get: (keys) -> - map = {} - if typeof keys == 'string' - map[keys] = undefined - else if Array.isArray(keys) - for key in keys - map[key] = undefined - else if typeof keys == 'object' - map = keys - for own key of map - try - value = JSON.parse(@proto.getItem.call(@storage, @prefix + key)) - map[key] = value if value? - if typeof map[key] == 'undefined' - delete map[key] - Promise.resolve map + promiseResult = idbKeyval.get('localStorage').then((initValuesMap) => + if !_globalLocalStorageCache + @proto.initValuesMap(initValuesMap) + _globalLocalStorageCache = true + map = {} + if typeof keys == 'string' + map[keys] = undefined + else if Array.isArray(keys) + for key in keys + map[key] = undefined + else if typeof keys == 'object' + map = keys + for own key of map + try + value = JSON.parse(@proto.getItem.call(@storage, @prefix + key)) + map[key] = value if value? + if typeof map[key] == 'undefined' + delete map[key] + return map + ) + Promise.resolve promiseResult set: (items) -> - for own key, value of items - value = JSON.stringify(value) - @proto.setItem.call(@storage, @prefix + key, value) - Promise.resolve items + promiseResult = idbKeyval.get('localStorage').then((initValuesMap) => + if !_globalLocalStorageCache + @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) => + initValuesMap = @proto.getValuesMap() + idbKeyval.set('localStorage', initValuesMap).then( -> + return items + ) + ) + Promise.resolve promiseResult remove: (keys) -> - if not keys? - if not @prefix - @proto.clear.call(@storage) - else - index = 0 - while true - key = @proto.key.call(index) - break if key == null - if @key.substr(0, @prefix.length) == @prefix - @proto.removeItem.call(@storage, @prefix + keys) - else - index++ - if typeof keys == 'string' - @proto.removeItem.call(@storage, @prefix + keys) - for key in keys - @proto.removeItem.call(@storage, @prefix + key) + promiseResult = idbKeyval.get('localStorage').then((initValuesMap) => + if !_globalLocalStorageCache + @proto.initValuesMap(initValuesMap) + _globalLocalStorageCache = true + if not keys? + if not @prefix + @proto.clear.call(@storage) + else + index = 0 + while true + key = @proto.key.call(index) + break if key == null + if @key.substr(0, @prefix.length) == @prefix + @proto.removeItem.call(@storage, @prefix + keys) + else + index++ + if typeof keys == 'string' + @proto.removeItem.call(@storage, @prefix + keys) + for key in keys + @proto.removeItem.call(@storage, @prefix + key) - Promise.resolve() + ).then( => + initValuesMap = @proto.getValuesMap() + idbKeyval.set('localStorage', initValuesMap).then( -> + return + ) + ) + Promise.resolve promiseResult module.exports = BrowserStorage diff --git a/omega-web/bower.json b/omega-web/bower.json index bd3aa4a..5aa206d 100644 --- a/omega-web/bower.json +++ b/omega-web/bower.json @@ -34,7 +34,7 @@ "ngprogress": "~1.0.4", "angular-ui-sortable": "~0.13.3", "jsondiffpatch": "~0.1.7", - "angular-spectrum-colorpicker": "~1.3.5", + "angular-spectrum-colorpicker": "git://github.com/suziwen/angular-spectrum-colorpicker.git#main", "blob": "*", "FileSaver": "=1.3.3", "angular-ui-utils": "bower-validate", diff --git a/omega-web/img/icons/draw_omega.js b/omega-web/img/icons/draw_omega.js index c41cf2a..ccae6e7 100644 --- a/omega-web/img/icons/draw_omega.js +++ b/omega-web/img/icons/draw_omega.js @@ -1,4 +1,4 @@ -var drawOmega = function (ctx, outerCircleColor, innerCircleColor) { +globalThis.drawOmega = function (ctx, outerCircleColor, innerCircleColor) { ctx.globalCompositeOperation = "source-over"; ctx.fillStyle = outerCircleColor; ctx.beginPath(); diff --git a/omega-web/img/icons/omega-128.png b/omega-web/img/icons/omega-128.png index fbf5306..14d0d7c 100644 Binary files a/omega-web/img/icons/omega-128.png and b/omega-web/img/icons/omega-128.png differ diff --git a/omega-web/img/icons/omega-128.svg b/omega-web/img/icons/omega-128.svg index dba99e6..a2993f5 100644 --- a/omega-web/img/icons/omega-128.svg +++ b/omega-web/img/icons/omega-128.svg @@ -1,12 +1 @@ - - - - + \ No newline at end of file diff --git a/omega-web/img/icons/omega-48.png b/omega-web/img/icons/omega-48.png index f4a689d..0e815a6 100644 Binary files a/omega-web/img/icons/omega-48.png and b/omega-web/img/icons/omega-48.png differ diff --git a/omega-web/img/icons/omega-64.png b/omega-web/img/icons/omega-64.png index 018d95e..8feea74 100644 Binary files a/omega-web/img/icons/omega-64.png and b/omega-web/img/icons/omega-64.png differ diff --git a/omega-web/img/icons/omega-action-16.png b/omega-web/img/icons/omega-action-16.png index 78c14af..46f3348 100644 Binary files a/omega-web/img/icons/omega-action-16.png and b/omega-web/img/icons/omega-action-16.png differ diff --git a/omega-web/img/icons/omega-action-19.png b/omega-web/img/icons/omega-action-19.png index edf0876..3498aa0 100644 Binary files a/omega-web/img/icons/omega-action-19.png and b/omega-web/img/icons/omega-action-19.png differ diff --git a/omega-web/img/icons/omega-action-24.png b/omega-web/img/icons/omega-action-24.png index 0b4cc03..adfe356 100644 Binary files a/omega-web/img/icons/omega-action-24.png and b/omega-web/img/icons/omega-action-24.png differ diff --git a/omega-web/img/icons/omega-action-32.png b/omega-web/img/icons/omega-action-32.png index d01d954..07e4118 100644 Binary files a/omega-web/img/icons/omega-action-32.png and b/omega-web/img/icons/omega-action-32.png differ diff --git a/omega-web/img/icons/omega-action.svg b/omega-web/img/icons/omega-action.svg index 8e1dcd3..ec1f754 100644 --- a/omega-web/img/icons/omega-action.svg +++ b/omega-web/img/icons/omega-action.svg @@ -1,12 +1 @@ - - - - + \ No newline at end of file diff --git a/omega-web/src/omega/app.coffee b/omega-web/src/omega/app.coffee index cef99a4..a4a6a8b 100644 --- a/omega-web/src/omega/app.coffee +++ b/omega-web/src/omega/app.coffee @@ -30,7 +30,7 @@ angular.module('omega').constant 'isProfileNameReserved', (name) -> name.charCodeAt(1) == charCodeUnderscore) angular.module('omega').config ($stateProvider, $urlRouterProvider, - $httpProvider, $animateProvider, $compileProvider) -> +$httpProvider, $animateProvider, $compileProvider) -> $compileProvider.aHrefSanitizationWhitelist( /^\s*(https?|ftp|mailto|chrome-extension|moz-extension):/) $compileProvider.imgSrcSanitizationWhitelist( @@ -77,7 +77,7 @@ angular.module('omega').factory '$exceptionHandler', ($log) -> $log.error(exception, cause) angular.module('omega').factory 'omegaDebug', ($window, $rootScope, - $injector) -> +$injector) -> omegaDebug = $window.OmegaDebug ? {} omegaDebug.downloadLog ?= -> @@ -96,14 +96,6 @@ angular.module('omega').factory 'omegaDebug', ($window, $rootScope, omegaDebug angular.module('omega').factory 'downloadFile', -> - if browser?.downloads?.download? - return (blob, filename) -> - url = URL.createObjectURL(blob) - if filename - browser.downloads.download({url: url, filename: filename}) - else - browser.downloads.download({url: url}) - else - return (blob, filename) -> - noAutoBom = true - saveAs(blob, filename, noAutoBom) + return (blob, filename) -> + noAutoBom = true + saveAs(blob, filename, noAutoBom) diff --git a/omega-web/src/options.jade b/omega-web/src/options.jade index d403610..a523325 100644 --- a/omega-web/src/options.jade +++ b/omega-web/src/options.jade @@ -13,7 +13,7 @@ html(lang='en' ng-controller='MasterCtrl' ng-csp) .container-fluid header.col-lg-2.col-sm-3.side-nav h1 - a(ui-sref='about' title='{{"about_title" | tr}}') {{'appNameShort' | tr}} + a(ui-sref='about' title='{{"about_title" | tr}}') Zero Omega sup.om-experimental.text-danger(ng-show='isExperimental') | {{'options_experimental_badge' | tr}} nav.nav.nav-pills.nav-stacked diff --git a/omega-web/src/popup/js/profiles.js b/omega-web/src/popup/js/profiles.js index 0507352..f47c60e 100644 --- a/omega-web/src/popup/js/profiles.js +++ b/omega-web/src/popup/js/profiles.js @@ -1,7 +1,4 @@ (function() { - $script.ready('om-state', updateMenuByState); - $script.ready('om-page-info', updateMenuByPageInfo); - $script.ready(['om-state', 'om-page-info'], updateMenuByStateAndPageInfo); var profileTemplate = document.getElementById('js-profile-tpl') .cloneNode(true); @@ -25,6 +22,10 @@ 'RuleListProfile': 3000, }; + $script.ready('om-state', updateMenuByState); + $script.ready('om-page-info', updateMenuByPageInfo); + $script.ready(['om-state', 'om-page-info'], updateMenuByStateAndPageInfo); + return; function updateMenuByState() {