From 3c13d279fd0de683b5b2dcb4a16fa898a31e1a6c Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Mon, 2 Dec 2024 10:59:16 -0500 Subject: [PATCH] draft --- platform/mv3/chromium/manifest.json | 11 +- .../mv3/extension/_locales/en/messages.json | 6 +- platform/mv3/extension/js/ruleset-manager.js | 137 +++++++++++++----- platform/mv3/extension/js/strict-block.js | 6 +- platform/mv3/firefox/manifest.json | 11 +- platform/mv3/make-rulesets.js | 2 +- 6 files changed, 127 insertions(+), 46 deletions(-) diff --git a/platform/mv3/chromium/manifest.json b/platform/mv3/chromium/manifest.json index 6f775f676..ff981f7c3 100644 --- a/platform/mv3/chromium/manifest.json +++ b/platform/mv3/chromium/manifest.json @@ -42,5 +42,14 @@ "managed_schema": "managed_storage.json" }, "version": "1.0", - "web_accessible_resources": [] + "web_accessible_resources": [ + { + "resources": [ + "/strict-block.html" + ], + "matches": [ + "" + ] + } + ] } diff --git a/platform/mv3/extension/_locales/en/messages.json b/platform/mv3/extension/_locales/en/messages.json index 0d69a4929..9ad38953a 100644 --- a/platform/mv3/extension/_locales/en/messages.json +++ b/platform/mv3/extension/_locales/en/messages.json @@ -243,7 +243,11 @@ "message": "uBO Lite has prevented the following page from loading:", "description": "Sentence used in the strict-blocked page" }, - "strictblockBack": { + "strictblockNoParamsPrompt": { + "message": "without parameters", + "description": "Label to be used for the parameter-less URL" + }, + "strictblockBack": { "message": "Go back", "description": "A button to go back to the previous webpage" }, diff --git a/platform/mv3/extension/js/ruleset-manager.js b/platform/mv3/extension/js/ruleset-manager.js index 28062e5b7..fba403e42 100644 --- a/platform/mv3/extension/js/ruleset-manager.js +++ b/platform/mv3/extension/js/ruleset-manager.js @@ -39,7 +39,8 @@ import { ubolLog } from './debug.js'; const TRUSTED_DIRECTIVE_BASE_RULE_ID = 8000000; -let dynamicRulesetId = 1; +let dynamicRuleId = 1; +let sessionRuleId = 1; /******************************************************************************/ @@ -82,6 +83,17 @@ function getDynamicRules(...args) { return getDynamicRules.promise; } +function getSessionRules(...args) { + if ( getSessionRules.promise !== undefined ) { + return getSessionRules.promise; + } + getSessionRules.promise = dnr.getSessionRules(...args).then(rules => { + getSessionRules.promise = undefined; + return rules; + }); + return getSessionRules.promise; +} + /******************************************************************************/ async function pruneInvalidRegexRules(realm, rulesIn) { @@ -143,7 +155,7 @@ async function updateRegexRules(toAdd) { for ( const rules of regexRulesets ) { if ( Array.isArray(rules) === false ) { continue; } for ( const rule of rules ) { - rule.id = dynamicRulesetId++; + rule.id = dynamicRuleId++; allRules.push(rule); } } @@ -181,7 +193,7 @@ async function updateRemoveparamRules(toAdd) { for ( const rules of removeparamRulesets ) { if ( Array.isArray(rules) === false ) { continue; } for ( const rule of rules ) { - rule.id = dynamicRulesetId++; + rule.id = dynamicRuleId++; allRules.push(rule); } } @@ -220,7 +232,7 @@ async function updateRedirectRules(toAdd) { for ( const rules of redirectRulesets ) { if ( Array.isArray(rules) === false ) { continue; } for ( const rule of rules ) { - rule.id = dynamicRulesetId++; + rule.id = dynamicRuleId++; allRules.push(rule); } } @@ -259,7 +271,7 @@ async function updateModifyHeadersRules(toAdd) { for ( const rules of rulesets ) { if ( Array.isArray(rules) === false ) { continue; } for ( const rule of rules ) { - rule.id = dynamicRulesetId++; + rule.id = dynamicRuleId++; allRules.push(rule); } } @@ -275,7 +287,7 @@ async function updateModifyHeadersRules(toAdd) { /******************************************************************************/ -async function updateStrictBlockRules(toAdd) { +async function updateStrictBlockRules(dynamicRules, sessionRules) { const [ hasOmnipotence, rulesetDetails, @@ -296,8 +308,6 @@ async function updateStrictBlockRules(toAdd) { } const strictBlockRulesets = await Promise.all(toFetch); - const allExcluded = permanentlyExcluded.concat(temporarilyExcluded); - // Strict-block rules can only be enforced with omnipotence let toStrictBlock = new Set(); if ( hasOmnipotence ) { @@ -305,66 +315,115 @@ async function updateStrictBlockRules(toAdd) { if ( Array.isArray(hostnames) === false ) { continue; } toStrictBlock = toStrictBlock.union(new Set(hostnames)); } - } else if ( allExcluded.length !== 0 ) { - localRemove('excludedStrictBlockHostnames'); - sessionRemove('excludedStrictBlockHostnames'); - allExcluded.length = 0; + } else { + if ( permanentlyExcluded.length !== 0 ) { + localRemove('excludedStrictBlockHostnames'); + permanentlyExcluded.length = 0; + } + if ( temporarilyExcluded.length !== 0 ) { + sessionRemove('excludedStrictBlockHostnames'); + temporarilyExcluded.length = 0; + } } - for ( const hn of allExcluded ) { + for ( const hn of permanentlyExcluded ) { toStrictBlock.delete(hn); } if ( toStrictBlock.size === 0 ) { return; } - - const ubolOrigin = runtime.getURL('').replace(/\/$/, ''); - const rule = { - id: dynamicRulesetId++, + const dynamicRule = { + id: dynamicRuleId++, action: { type: 'redirect', redirect: { - regexSubstitution: `${ubolOrigin}/strict-block.html#\\0`, + regexSubstitution: `${runtime.getURL('/strict-block.html')}#\\0`, }, }, condition: { - regexFilter: '^https:?//.+', + regexFilter: '^https?://.+', requestDomains: Array.from(toStrictBlock), resourceTypes: [ 'main_frame' ], }, priority: 29, }; - if ( allExcluded.length !== 0 ) { - rule.condition.excludedRequestDomains = allExcluded; + if ( permanentlyExcluded.length !== 0 ) { + dynamicRule.condition.excludedRequestDomains = permanentlyExcluded; } - toAdd.push(rule); + dynamicRules.push(dynamicRule); + ubolLog(`Add 1 DNR dynamic rule with ${toStrictBlock.size} strict-blocked domains`); - ubolLog(`Add 1 DNR strict-block rules with ${toStrictBlock.size} domains`); + if ( temporarilyExcluded.length === 0 ) { return; } + sessionRules.push({ + id: sessionRuleId++, + action: { + type: 'allow', + }, + condition: { + requestDomains: temporarilyExcluded, + resourceTypes: [ 'main_frame' ], + }, + priority: 29, + }); + ubolLog(`Add 1 DNR session rule with ${temporarilyExcluded.length} unstrict-blocked domains`); } /******************************************************************************/ async function updateDynamicRules() { - dynamicRulesetId = 1; - const addRules = []; - const [ removeRuleIds ] = await Promise.all([ + dynamicRuleId = 1; + sessionRuleId = 1; + const dynamicRules = []; + const sessionRules = []; + const [ + dynamicRuleIds, + sessionRuleIds, + ] = await Promise.all([ getDynamicRules().then(rules => rules.map(rule => rule.id) .filter(id => id < TRUSTED_DIRECTIVE_BASE_RULE_ID) ), - updateRegexRules(addRules), - updateRemoveparamRules(addRules), - updateRedirectRules(addRules), - updateModifyHeadersRules(addRules), - updateStrictBlockRules(addRules), + getSessionRules().then(rules => rules.map(rule => rule.id)), + updateRegexRules(dynamicRules), + updateRemoveparamRules(dynamicRules), + updateRedirectRules(dynamicRules), + updateModifyHeadersRules(dynamicRules), + updateStrictBlockRules(dynamicRules, sessionRules), ]); - if ( addRules.length === 0 && removeRuleIds.length === 0 ) { return; } - if ( removeRuleIds.length !== 0 ) { - ubolLog(`Remove ${removeRuleIds.length} dynamic DNR rules`); + if ( dynamicRules.length === 0 && dynamicRuleIds.length === 0 ) { return; } + const promises = []; + if ( dynamicRules.length !== 0 || dynamicRuleIds.length !== 0 ) { + promises.push( + dnr.updateDynamicRules({ + addRules: dynamicRules, + removeRuleIds: dynamicRuleIds, + }).then(( ) => { + if ( dynamicRuleIds.length !== 0 ) { + ubolLog(`Remove ${dynamicRuleIds.length} dynamic DNR rules`); + } + if ( dynamicRules.length !== 0 ) { + ubolLog(`Add ${dynamicRules.length} dynamic DNR rules`); + } + }).catch(reason => { + console.error(`updateDynamicRules() / ${reason}`); + }) + ); } - if ( addRules.length !== 0 ) { - ubolLog(`Add ${addRules.length} dynamic DNR rules`); + if ( sessionRules.length !== 0 || sessionRuleIds.length !== 0 ) { + promises.push( + dnr.updateSessionRules({ + addRules: sessionRules, + removeRuleIds: sessionRuleIds, + }).then(( ) => { + if ( sessionRuleIds.length !== 0 ) { + ubolLog(`Remove ${sessionRuleIds.length} session DNR rules`); + } + if ( sessionRules.length !== 0 ) { + ubolLog(`Add ${sessionRules.length} session DNR rules`); + } + }).catch(reason => { + console.error(`updateSessionRules() / ${reason}`); + }) + ); } - return dnr.updateDynamicRules({ addRules, removeRuleIds }).catch(reason => { - console.error(`updateDynamicRules() / ${reason}`); - }); + return Promise.all(promises); } /******************************************************************************/ diff --git a/platform/mv3/extension/js/strict-block.js b/platform/mv3/extension/js/strict-block.js index 8311be51f..651b4b50e 100644 --- a/platform/mv3/extension/js/strict-block.js +++ b/platform/mv3/extension/js/strict-block.js @@ -116,7 +116,7 @@ qs$('#theURL > p > span:first-of-type').append(urlToFragment(toURL.href)); if ( search === '' ) { return false; } url.search = ''; - const li = liFromParam(i18n$('docblockedNoParamsPrompt'), url.href); + const li = liFromParam(i18n$('strictblockNoParamsPrompt'), url.href); parentNode.appendChild(li); const params = new self.URLSearchParams(search); @@ -169,8 +169,8 @@ if ( window.history.length > 1 ) { dom.on('#disableWarning', 'change', ev => { const checked = ev.target.checked; - dom.cl.toggle('[data-i18n="docblockedBack"]', 'disabled', checked); - dom.cl.toggle('[data-i18n="docblockedClose"]', 'disabled', checked); + dom.cl.toggle('[data-i18n="strictblockBack"]', 'disabled', checked); + dom.cl.toggle('[data-i18n="strictblockClose"]', 'disabled', checked); }); dom.on('#proceed', 'click', ( ) => { diff --git a/platform/mv3/firefox/manifest.json b/platform/mv3/firefox/manifest.json index 926fa7abc..9b6deb4b4 100644 --- a/platform/mv3/firefox/manifest.json +++ b/platform/mv3/firefox/manifest.json @@ -51,5 +51,14 @@ ], "short_name": "uBO Lite", "version": "1.0", - "web_accessible_resources": [] + "web_accessible_resources": [ + { + "resources": [ + "/strict-block.html" + ], + "matches": [ + "" + ] + } + ] } diff --git a/platform/mv3/make-rulesets.js b/platform/mv3/make-rulesets.js index dab7b1698..cb519e134 100644 --- a/platform/mv3/make-rulesets.js +++ b/platform/mv3/make-rulesets.js @@ -1368,7 +1368,7 @@ async function main() { if ( platform === 'chromium' ) { web_accessible_resources.use_dynamic_url = true; } - manifest.web_accessible_resources = [ web_accessible_resources ]; + manifest.web_accessible_resources.push(web_accessible_resources); // Patch manifest version property manifest.version = version;