From 203b2235aaee886bd74de48ba6b0e36bb63bc096 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Thu, 24 Apr 2025 19:32:40 -0400 Subject: [PATCH] [mv3] Reflect no-filtering mode on the toolbar icon Related issue: https://github.com/uBlockOrigin/uBOL-home/issues/198 --- platform/mv3/chromium/manifest.json | 4 +- platform/mv3/extension/img/icon_128_off.png | Bin 0 -> 3004 bytes platform/mv3/extension/img/icon_16_off.png | Bin 0 -> 446 bytes platform/mv3/extension/img/icon_32_off.png | Bin 0 -> 802 bytes platform/mv3/extension/img/icon_64_off.png | Bin 0 -> 1483 bytes platform/mv3/extension/js/action.js | 120 ++++++++++++++++++++ platform/mv3/extension/js/background.js | 56 +++------ platform/mv3/extension/js/ext.js | 1 - platform/mv3/extension/js/mode-manager.js | 33 +++--- platform/mv3/extension/js/utils.js | 36 +++++- platform/mv3/firefox/manifest.json | 4 +- platform/mv3/safari/manifest.json | 4 +- 12 files changed, 202 insertions(+), 56 deletions(-) create mode 100644 platform/mv3/extension/img/icon_128_off.png create mode 100644 platform/mv3/extension/img/icon_16_off.png create mode 100644 platform/mv3/extension/img/icon_32_off.png create mode 100644 platform/mv3/extension/img/icon_64_off.png create mode 100644 platform/mv3/extension/js/action.js diff --git a/platform/mv3/chromium/manifest.json b/platform/mv3/chromium/manifest.json index f42001a9d..c633619b6 100644 --- a/platform/mv3/chromium/manifest.json +++ b/platform/mv3/chromium/manifest.json @@ -40,7 +40,9 @@ "activeTab", "declarativeNetRequest", "scripting", - "storage" + "storage", + "tabs", + "webNavigation" ], "short_name": "uBO Lite", "storage": { diff --git a/platform/mv3/extension/img/icon_128_off.png b/platform/mv3/extension/img/icon_128_off.png new file mode 100644 index 0000000000000000000000000000000000000000..f878785974fcf94da46916f4582048b703cb4e7a GIT binary patch literal 3004 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 literal 0 HcmV?d00001 diff --git a/platform/mv3/extension/img/icon_64_off.png b/platform/mv3/extension/img/icon_64_off.png new file mode 100644 index 0000000000000000000000000000000000000000..d9a22955a509c6a9e15c587139ed6e452d06b187 GIT binary patch literal 1483 zcmV;+1vL7JP)$7*-}9W) z_y6njKJR(IV3ABIwOJ|kn^Nk$QtFMxsz=Hq2zLWb-QC^gXV0Ep0Z>p-@VQdzWni<2 z3?{NZl0e~BV5hF@uQoR~=jpnB*L6+P*tBWWpr&c9z)lgFGz|cy)N8=@g9i_;85tST z!ue)pWlh)D*Y^V70DDA4B_#l*lm&PNc+2bcmJSRIq{ni9et!Oq%F4=op)*Xu2gRd@&xla-Z~=Ya2lFGOT~NdZtw3Gle_Z45|U8ub~_~{C8I?}MSlZ-0apM&FboU3=#+gn3=(sifNjL-EJo}HT71R)oQ)YfdBLSF5OG`6t6G%@_*CPV3*=)Lrn?S?}2w1IF z)8>Gbl$0spdN=@nZcZqg)uy;PS$Z4F%ohcvR7^`!TefUjR7FiqO|iI7&K&JpLOGc@ z0)qFv9*1z6Ffo9MXaEFE3?L8<0KbU=_@e>vkEUs690&o7+|xCN@cqN-bTT|V9FHu# zXy$Y}0WL%n0bO}{d8SK*`T6-1KxZ@nPM4OJ4x0@?NlD2ta3&%E5g7)?Oqc*i4Q&x4 z0N}C-0bB`HI2(ZDE|<$R%5!pZ0Dg)EK+F2|>#v#xKt)BxRiGv02r*Qlh+I%gT?9-K z2AP?e7e%B$mIweiG;=paGTO?OE2n`&vt17dV7JHP8Ax^jH8nK@!0wmgvt`JHq*d1t22-0iTwYm5nBw`111dQQ(t1_XN%* z0uYgXg@uLfZnryWW{Prha;8?VUj3bj?2F`UiSn6SJswYYMn=Yx7oU-lL2Yeq7w~2@ z{!sxC5gqU}HZ~r2I2=oM_1JE=tH#F0F5m^D&XKjn@&igK8*sR-t?ikyu`$b15}%co zrRwYJPXNywxr+q{U_eL%zU}PntnTaUTd@?x7Zw%<%F4=q1R6yorn!tcZwFCIy?5=} zwQcR~?e0bH>MmzzXMZUoyXJELy!OK=rJe@%?BBnCO&}1EM7Q^i8#kT--Vu?X=lYz5 zI51%Y_V)Mp*B(1|?7>8cU$<`EXi-s-7kE8VKOc7hcYvq`K5A)cS>yNn;}Q)HheI_q zG@JoG5Ro4i;+YFtQ6m~Y^ZWfTwzjseQfgs(Oc9~Fy83c%Zmt*DI^TaiZUF88@dU89 zqod=g!NI|K9h%C^%ezrkRrM?Iwuqcw=(@%=aT(_Y-)(DaD;gUclNiIDhK7dUfv<_< z`N6nnZlhUztn2zq&CSh^MLKU}u~?|7sqwj7uA{(q5sB+kT_TUpJ_79S?d`4T>gvi0 z ({ + originAndPathMatches: `^https?://(.+\\.)?${a}/` + })), + }); + + if ( wakeup === undefined ) { return; } + + // If waking up, update icon for existing tabs + const tabs = await browser.tabs.query({ + url: Array.from(toToggle).map(a => `*://*.${a}/*`) + }).catch(( ) => ([])); + + for ( const tab of tabs ) { + toggleToolbarIcon(tab.id); + } +} diff --git a/platform/mv3/extension/js/background.js b/platform/mv3/extension/js/background.js index 6af564822..4668b467f 100644 --- a/platform/mv3/extension/js/background.js +++ b/platform/mv3/extension/js/background.js @@ -21,6 +21,7 @@ import { MODE_BASIC, + MODE_NONE, MODE_OPTIMAL, getDefaultFilteringMode, getFilteringMode, @@ -38,6 +39,7 @@ import { import { broadcastMessage, + gotoURL, hasBroadHostPermissions, hostnamesFromMatches, } from './utils.js'; @@ -46,7 +48,6 @@ import { browser, localRead, localRemove, localWrite, runtime, - windows, } from './ext.js'; import { @@ -76,6 +77,7 @@ import { import { dnr } from './ext-compat.js'; import { registerInjectables } from './scripting-manager.js'; +import { syncToolbarIcon } from './action.js'; /******************************************************************************/ @@ -133,36 +135,6 @@ async function onPermissionsAdded(permissions) { /******************************************************************************/ -async function gotoURL(url, type) { - const pageURL = new URL(url, runtime.getURL('/')); - const tabs = await browser.tabs.query({ - url: pageURL.href, - windowType: type !== 'popup' ? 'normal' : 'popup' - }); - - if ( Array.isArray(tabs) && tabs.length !== 0 ) { - const { windowId, id } = tabs[0]; - return Promise.all([ - browser.windows.update(windowId, { focused: true }), - browser.tabs.update(id, { active: true }), - ]); - } - - if ( type === 'popup' ) { - return windows.create({ - type: 'popup', - url: pageURL.href, - }); - } - - return browser.tabs.create({ - active: true, - url: pageURL.href, - }); -} - -/******************************************************************************/ - function onMessage(request, sender, callback) { // Does not require trusted origin. @@ -340,12 +312,18 @@ function onMessage(request, sender, callback) { break; case 'setFilteringMode': { - getFilteringMode(request.hostname).then(actualLevel => { - if ( request.level === actualLevel ) { return actualLevel; } + let trustedSitesChanged = false; + getFilteringMode(request.hostname).then(beforeLevel => { + if ( request.level === beforeLevel ) { return beforeLevel; } + trustedSitesChanged = beforeLevel === MODE_NONE; return setFilteringMode(request.hostname, request.level); - }).then(actualLevel => { + }).then(afterLevel => { registerInjectables(); - callback(actualLevel); + trustedSitesChanged ||= afterLevel === MODE_NONE; + if ( trustedSitesChanged ) { + syncToolbarIcon(); + } + callback(afterLevel); }); return true; } @@ -378,6 +356,7 @@ function onMessage(request, sender, callback) { case 'setTrustedSites': setTrustedSites(request.hostnames).then(( ) => { registerInjectables(); + syncToolbarIcon(true); return Promise.all([ getDefaultFilteringMode(), getTrustedSites(), @@ -404,7 +383,7 @@ function onMessage(request, sender, callback) { return true; case 'showMatchedRules': - windows.create({ + browser.windows.create({ type: 'popup', url: `/matched-rules.html?tab=${request.tabId}`, }); @@ -436,7 +415,7 @@ function onCommand(command, tab) { /******************************************************************************/ -async function launch() { +async function startSession() { const currentVersion = getCurrentVersion(); const isNewVersion = currentVersion !== rulesetConfig.version; @@ -499,9 +478,10 @@ async function start() { await loadRulesetConfig(); if ( process.wakeupRun === false ) { - await launch(); + await startSession(); } + syncToolbarIcon(process.wakeupRun); toggleDeveloperMode(rulesetConfig.developerMode); } diff --git a/platform/mv3/extension/js/ext.js b/platform/mv3/extension/js/ext.js index ea1ab61ce..a2e6f18f5 100644 --- a/platform/mv3/extension/js/ext.js +++ b/platform/mv3/extension/js/ext.js @@ -26,7 +26,6 @@ import { webext } from './ext-compat.js'; export const browser = webext; export const i18n = browser.i18n; export const runtime = browser.runtime; -export const windows = browser.windows; /******************************************************************************/ diff --git a/platform/mv3/extension/js/mode-manager.js b/platform/mv3/extension/js/mode-manager.js index 41abc057d..6affead57 100644 --- a/platform/mv3/extension/js/mode-manager.js +++ b/platform/mv3/extension/js/mode-manager.js @@ -334,13 +334,18 @@ export async function getTrustedSites() { } export async function setTrustedSites(hostnames) { - const filteringModes = await getFilteringModeDetails(); + const [ + filteringModes, + hasOmnipotence, + ] = await Promise.all([ + getFilteringModeDetails(), + hasBroadHostPermissions(), + ]); const { none } = filteringModes; const hnSet = new Set(hostnames); let modified = false; - // Set default mode to Basic when removing No-filtering as default mode if ( none.has('all-urls') && hnSet.has('all-urls') === false ) { - applyFilteringMode(filteringModes, 'all-urls', MODE_BASIC); + applyFilteringMode(filteringModes, 'all-urls', hasOmnipotence ? MODE_OPTIMAL : MODE_BASIC); modified = true; } for ( const hn of none ) { @@ -389,16 +394,18 @@ export async function syncWithBrowserPermissions() { const afterMode = await getDefaultFilteringMode(); if ( afterMode > MODE_BASIC ) { return afterMode !== beforeMode; } const filteringModes = await getFilteringModeDetails(); - const { optimal, complete } = filteringModes; - for ( const hn of optimal ) { - if ( allowedHostnames.has(hn) ) { continue; } - optimal.delete(hn); - modified = true; - } - for ( const hn of complete ) { - if ( allowedHostnames.has(hn) ) { continue; } - complete.delete(hn); - modified = true; + if ( allowedHostnames.has('all-urls') === false ) { + const { optimal, complete } = filteringModes; + for ( const hn of optimal ) { + if ( allowedHostnames.has(hn) ) { continue; } + optimal.delete(hn); + modified = true; + } + for ( const hn of complete ) { + if ( allowedHostnames.has(hn) ) { continue; } + complete.delete(hn); + modified = true; + } } await writeFilteringModeDetails(filteringModes); return modified; diff --git a/platform/mv3/extension/js/utils.js b/platform/mv3/extension/js/utils.js index 00451f15f..94ed121b2 100644 --- a/platform/mv3/extension/js/utils.js +++ b/platform/mv3/extension/js/utils.js @@ -19,7 +19,10 @@ Home: https://github.com/gorhill/uBlock */ -import { browser } from './ext.js'; +import { + browser, + runtime, +} from './ext.js'; /******************************************************************************/ @@ -149,6 +152,36 @@ async function hasBroadHostPermissions() { /******************************************************************************/ +async function gotoURL(url, type) { + const pageURL = new URL(url, runtime.getURL('/')); + const tabs = await browser.tabs.query({ + url: pageURL.href, + windowType: type !== 'popup' ? 'normal' : 'popup' + }); + + if ( Array.isArray(tabs) && tabs.length !== 0 ) { + const { windowId, id } = tabs[0]; + return Promise.all([ + browser.windows.update(windowId, { focused: true }), + browser.tabs.update(id, { active: true }), + ]); + } + + if ( type === 'popup' ) { + return browser.windows.create({ + type: 'popup', + url: pageURL.href, + }); + } + + return browser.tabs.create({ + active: true, + url: pageURL.href, + }); +} + +/******************************************************************************/ + export { broadcastMessage, parsedURLromOrigin, @@ -161,4 +194,5 @@ export { matchesFromHostnames, hostnamesFromMatches, hasBroadHostPermissions, + gotoURL, }; diff --git a/platform/mv3/firefox/manifest.json b/platform/mv3/firefox/manifest.json index c2dd5a3aa..73d2fa1dd 100644 --- a/platform/mv3/firefox/manifest.json +++ b/platform/mv3/firefox/manifest.json @@ -52,7 +52,9 @@ "activeTab", "declarativeNetRequest", "scripting", - "storage" + "storage", + "tabs", + "webNavigation" ], "short_name": "uBO Lite", "version": "1.0", diff --git a/platform/mv3/safari/manifest.json b/platform/mv3/safari/manifest.json index ba7cc7715..a24dfb885 100644 --- a/platform/mv3/safari/manifest.json +++ b/platform/mv3/safari/manifest.json @@ -39,7 +39,9 @@ "declarativeNetRequest", "declarativeNetRequestWithHostAccess", "scripting", - "storage" + "storage", + "tabs", + "webNavigation" ], "short_name": "uBO Lite", "version": "1.0",