From fa756d806a8fb60b19d5a46fae4a21524d91dacf Mon Sep 17 00:00:00 2001 From: "proxy.zeroomega" Date: Sat, 15 Feb 2025 08:32:40 +0800 Subject: [PATCH] 1. Improve the performance of a large number of Rule Lists 2. Fix the pop-up window issue in Edge for Android #93 --- omega-pac/src/pac_generator.coffee | 12 +++++++ omega-pac/src/profiles.coffee | 10 +++++- .../overlay/x-background.js | 10 ++++++ .../src/module/external_api.coffee | 2 +- .../src/module/options.coffee | 3 +- .../src/module/proxy/proxy_impl.coffee | 29 +++++++++++++++- .../module/proxy/proxy_impl_settings.coffee | 34 +++++++++++++++++++ omega-target/src/options.coffee | 30 +++++++++++++++- 8 files changed, 124 insertions(+), 6 deletions(-) diff --git a/omega-pac/src/pac_generator.coffee b/omega-pac/src/pac_generator.coffee index 55a1dcd..ef0e9dd 100644 --- a/omega-pac/src/pac_generator.coffee +++ b/omega-pac/src/pac_generator.coffee @@ -73,6 +73,18 @@ module.exports = ] new U2.AST_Do( body: new U2.AST_BlockStatement body: [ + new U2.AST_If( + condition: new U2.AST_UnaryPrefix( + operator: "!", + expression: new U2.AST_Sub( + expression: new U2.AST_SymbolRef name: 'profiles' + property: new U2.AST_SymbolRef name: 'result' + ) + ) + body: new U2.AST_Return( + value: new U2.AST_SymbolRef name: "result" + ) + ) new U2.AST_SimpleStatement body: new U2.AST_Assign( left: new U2.AST_SymbolRef name: 'result' operator: '=' diff --git a/omega-pac/src/profiles.coffee b/omega-pac/src/profiles.coffee index 5fd86d7..a545536 100644 --- a/omega-pac/src/profiles.coffee +++ b/omega-pac/src/profiles.coffee @@ -472,7 +472,13 @@ module.exports = exports = match: (profile, request) -> result = exports.match(profile, request, 'SwitchProfile') compile: (profile) -> - exports.compile(profile, 'SwitchProfile') + if profile.isTempPacProfile + exports.compile(profile, 'SwitchProfile') + else + if profile.pacScript + exports.compile(profile, 'PacProfile') + else + exports.compile(profile, 'SwitchProfile') updateUrl: (profile) -> profile.sourceUrl updateContentTypeHints: -> [ '!text/html' @@ -497,6 +503,8 @@ module.exports = exports = if formatHandler.preprocess? data = formatHandler.preprocess(data) return false if profile.ruleList == data + # regenerator pacScript + profile.pacScript = '' profile.ruleList = data return true 'SwitchyRuleListProfile': 'RuleListProfile' diff --git a/omega-target-chromium-extension/overlay/x-background.js b/omega-target-chromium-extension/overlay/x-background.js index 3003e6c..2e245ff 100644 --- a/omega-target-chromium-extension/overlay/x-background.js +++ b/omega-target-chromium-extension/overlay/x-background.js @@ -24,6 +24,16 @@ import "./js/background.js" // zeroBackground const isFirefox = !!globalThis.localStorage const zcb = globalThis.zeroDetectModeCB +globalThis.POPUPHTMLURL = './popup-iframe.html' +//if android, (eg. edge canary for android), use default popup/index.html +//https://github.com/zero-peak/ZeroOmega/issues/93 +if (globalThis.navigator && /Android/i.test(globalThis.navigator.userAgent)){ + globalThis.POPUPHTMLURL = './popup/index.html' +} + +// keepAlive +setInterval(chrome.runtime.getPlatformInfo, 25 * 1000) //https://developer.chrome.com/docs/extensions/develop/migrate/to-service-workers + function detectPrivateMode(cb) { var db, tempMode,on, off; if (zcb) { diff --git a/omega-target-chromium-extension/src/module/external_api.coffee b/omega-target-chromium-extension/src/module/external_api.coffee index fa006fd..658844b 100644 --- a/omega-target-chromium-extension/src/module/external_api.coffee +++ b/omega-target-chromium-extension/src/module/external_api.coffee @@ -23,7 +23,7 @@ module.exports = class ExternalApi @options.setProxyNotControllable(null) #chrome.action.setPopup?({popup: 'popup/index.html'}) - chrome.action.setPopup?({popup: 'popup-iframe.html'}) + chrome.action.setPopup?({popup: globalThis.POPUPHTMLURL}) @options.reloadQuickSwitch() @disabled = false @options.clearBadge() diff --git a/omega-target-chromium-extension/src/module/options.coffee b/omega-target-chromium-extension/src/module/options.coffee index e938757..4736b1f 100644 --- a/omega-target-chromium-extension/src/module/options.coffee +++ b/omega-target-chromium-extension/src/module/options.coffee @@ -164,8 +164,7 @@ class ChromeOptions extends OmegaTarget.Options if quickSwitch chrome.action.setPopup({popup: ''}) else - #chrome.action.setPopup({popup: 'popup/index.html'}) - chrome.action.setPopup({popup: 'popup-iframe.html'}) + chrome.action.setPopup({popup: globalThis.POPUPHTMLURL}) chrome.contextMenus?.update('enableQuickSwitch', {checked: !!quickSwitch}) Promise.resolve() diff --git a/omega-target-chromium-extension/src/module/proxy/proxy_impl.coffee b/omega-target-chromium-extension/src/module/proxy/proxy_impl.coffee index a5ffda3..f03b148 100644 --- a/omega-target-chromium-extension/src/module/proxy/proxy_impl.coffee +++ b/omega-target-chromium-extension/src/module/proxy/proxy_impl.coffee @@ -2,6 +2,10 @@ OmegaTarget = require('omega-target') Promise = OmegaTarget.Promise ProxyAuth = require('./proxy_auth') + +# TODO temp profile will always create new cache. +profilePacCache = new Map() + class ProxyImpl constructor: (log) -> @log = log @@ -31,6 +35,25 @@ class ProxyImpl ) getProfilePacScript: (profile, meta, options) -> meta ?= profile + referenced_profiles = [] + ref_set = OmegaPac.Profiles.allReferenceSet(profile, + options, profileNotFound: @_profileNotFound.bind(this)) + for own _, name of ref_set + _profile = OmegaPac.Profiles.byName(name, options) + if _profile + referenced_profiles.push(_profile) + cachedProfiles = profilePacCache.keys().toArray() + allProfiles = Object.values(options) + cachedProfiles.forEach((cachedProfile) -> + if allProfiles.indexOf(cachedProfile) < 0 + profilePacCache.delete(cachedProfile) + ) + profilePac = profilePacCache.get(profile) + profilePacKey = referenced_profiles.map( + (_profile) -> _profile.name + '_' + (_profile.revision or 1) + ).join(',') + if profilePac?[profilePacKey] + return profilePac[profilePacKey] ast = OmegaPac.PacGenerator.script(options, profile, profileNotFound: @_profileNotFound.bind(this)) ast = OmegaPac.PacGenerator.compress(ast) @@ -39,6 +62,10 @@ class ProxyImpl profileName = profileName.replace(/\*/g, '\\u002a') profileName = profileName.replace(/\\/g, '\\u002f') prefix = "/*OmegaProfile*#{profileName}*#{meta.revision}*/" - return prefix + script + pacScript = prefix + script + profilePac = {} + profilePac[profilePacKey] = pacScript + profilePacCache.set(profile, profilePac) + return pacScript module.exports = ProxyImpl diff --git a/omega-target-chromium-extension/src/module/proxy/proxy_impl_settings.coffee b/omega-target-chromium-extension/src/module/proxy/proxy_impl_settings.coffee index 47b5a8b..b8cee1f 100644 --- a/omega-target-chromium-extension/src/module/proxy/proxy_impl_settings.coffee +++ b/omega-target-chromium-extension/src/module/proxy/proxy_impl_settings.coffee @@ -4,6 +4,29 @@ Promise = OmegaTarget.Promise chromeApiPromisify = require('../chrome_api').chromeApiPromisify ProxyImpl = require('./proxy_impl') +notExistentWebsite = "preflight-auth.non-existent-website.zzzzzzzzeroomega.zero" + +getFirstAuthProfile = (profile, options) -> + for rule in profile.rules + profileName = rule.profileName + _profile = OmegaPac.Profiles.byName(profileName, options) + return _profile if _profile.auth + +addAuthPreflightRule = (profile, options) -> + return unless profile.profileType is 'SwitchProfile' + return unless profile.rules or profile.rules.length is 0 + authProfile = getFirstAuthProfile(profile, options) + return unless authProfile + profile.rules.unshift({ + "condition": { + "conditionType": "HostWildcardCondition" + "pattern": notExistentWebsite + } + "isPreflightRule": true + "profileName": authProfile.name + }) + return authProfile + class SettingsProxyImpl extends ProxyImpl @isSupported: -> chrome?.proxy?.settings? features: ['fullUrlHttp', 'pacScript', 'watchProxyChange'] @@ -14,6 +37,7 @@ class SettingsProxyImpl extends ProxyImpl return chromeApiPromisify(chrome.proxy.settings, 'clear')({}).then => chrome.proxy.settings.get {}, @_proxyChangeListener return + authProfile = null config = {} if profile.profileType == 'DirectProfile' config['mode'] = 'direct' @@ -31,14 +55,24 @@ class SettingsProxyImpl extends ProxyImpl config = @_fixedProfileConfig(profile) else config['mode'] = 'pac_script' + authProfile = addAuthPreflightRule(profile, options) config['pacScript'] = mandatory: true data: @getProfilePacScript(profile, meta, options) return @setProxyAuth(profile, options).then(-> return chromeApiPromisify(chrome.proxy.settings, 'set')({value: config}) ).then(=> + if authProfile + fetch("https://" + notExistentWebsite).catch(-> authProfile) chrome.proxy.settings.get {}, @_proxyChangeListener return + ).finally(-> + if authProfile + profile.rules.forEach((rule, index) -> + if rule.isPreflightRule + profile.rules.splice(index, 1) + ) + profile.rules ) _fixedProfileConfig: (profile) -> config = {} diff --git a/omega-target/src/options.coffee b/omega-target/src/options.coffee index a016586..fb3c5f3 100644 --- a/omega-target/src/options.coffee +++ b/omega-target/src/options.coffee @@ -5,6 +5,31 @@ Storage = require './storage' OmegaPac = require 'omega-pac' jsondiffpatch = require 'jsondiffpatch' + + +PROFILETEMPPACKEY = '__tempZeroRuleListPac' + +generateProfileTempPac = (profile) -> + tempProfile = OmegaPac.Profiles.create(PROFILETEMPPACKEY, profile.profileType) + tempProfile.defaultProfileName = profile.defaultProfileName + tempProfile.format = profile.format + tempProfile.matchProfileName = profile.matchProfileName + tempProfile.ruleList = profile.ruleList + tempProfile.isTempPacProfile = true + options = {} + nameKey = OmegaPac.Profiles.nameAsKey(tempProfile.name) + options[nameKey] = tempProfile + profileNotFound = -> 'ignore' + + ast = OmegaPac.PacGenerator.script(options, tempProfile.name, + profileNotFound: profileNotFound) + pac = ast.print_to_string(beautify: true, comments: true) + pac = OmegaPac.PacGenerator.ascii(pac) + return pac + + + + class Options ###* # The entire set of options including profiles and other settings. @@ -109,7 +134,7 @@ class Options @_storage.get(null) else @sync.init({gistId, gistToken}).catch((e) -> - console.error('sync init fail::', e) + console.log('sync init fail::', e) ) @_syncWatchStop = @sync.watchAndPull(@_storage) @sync.copyTo(@_storage).catch(Storage.StorageUnavailableError, => @@ -384,6 +409,8 @@ class Options value.revision) continue if result >= 0 profilesChanged = true + if value.profileType is 'RuleListProfile' + value.pacScript = generateProfileTempPac(value) if key is '-builtinProfiles' currentProfileAffected = 'changed' @_options[key] = value @@ -722,6 +749,7 @@ class Options profile.lastUpdate = new Date().toISOString() if OmegaPac.Profiles.update(profile, data) OmegaPac.Profiles.dropCache(profile) + OmegaPac.Profiles.updateRevision(profile) changes = {} changes[key] = profile @_setOptions(changes).return(profile)