diff --git a/platform/mv3/chromium/manifest.json b/platform/mv3/chromium/manifest.json index 49f1381b2c679..72760301c5a32 100644 --- a/platform/mv3/chromium/manifest.json +++ b/platform/mv3/chromium/manifest.json @@ -25,7 +25,7 @@ "128": "img/icon_128.png" }, "manifest_version": 3, - "minimum_chrome_version": "119.0", + "minimum_chrome_version": "122.0", "name": "__MSG_extName__", "options_page": "dashboard.html", "optional_host_permissions": [ @@ -41,6 +41,5 @@ "storage": { "managed_schema": "managed_storage.json" }, - "version": "1.0", - "web_accessible_resources": [] + "version": "1.0" } diff --git a/platform/mv3/extension/_locales/en/messages.json b/platform/mv3/extension/_locales/en/messages.json index 60cc95401447c..17a5b24cd7935 100644 --- a/platform/mv3/extension/_locales/en/messages.json +++ b/platform/mv3/extension/_locales/en/messages.json @@ -231,8 +231,44 @@ "message": "Show the number of blocked requests on the toolbar icon", "description": "Label for a checkbox in the options page" }, + "enableStrictBlockLabel": { + "message": "Enable strict blocking", + "description": "Label for a checkbox in the options page" + }, + "enableStrictBlockLegend": { + "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", + "description": "Label for a checkbox in the options page" + }, "findListsPlaceholder": { "message": "Find lists", "description": "Placeholder for the input field used to find lists" + }, + "strictblockTitle": { + "message": "Page blocked", + "description": "Webpage title for the strict-blocked page" + }, + "strictblockSentence1": { + "message": "uBO Lite has prevented the following page from loading:", + "description": "Sentence used in the strict-blocked page" + }, + "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" + }, + "strictblockClose": { + "message": "Close this window", + "description": "A button to close the current tab" + }, + "strictblockDontWarn": { + "message": "Don't warn me again about this site", + "description": "Label for checkbox in document-blocked page" + }, + "strictblockProceed": { + "message": "Proceed", + "description": "A button to navigate to the blocked page" } } diff --git a/platform/mv3/extension/css/settings.css b/platform/mv3/extension/css/settings.css index feefcadd8c3ee..a8b07d2a1894c 100644 --- a/platform/mv3/extension/css/settings.css +++ b/platform/mv3/extension/css/settings.css @@ -12,8 +12,11 @@ body.firstRun .firstRun { h3 { margin: 1em 0; } -p { - white-space: pre-line; + +label + legend { + color: color-mix(in srgb, currentColor 69%, transparent); + font-size: small; + margin-inline-start: var(--default-gap-large); } body[data-forbid~="dashboard"] #dashboard-nav [data-pane="settings"], diff --git a/platform/mv3/extension/css/strictblock.css b/platform/mv3/extension/css/strictblock.css new file mode 100644 index 0000000000000..f7534078cca7b --- /dev/null +++ b/platform/mv3/extension/css/strictblock.css @@ -0,0 +1,147 @@ +/** + uBlock Origin - a browser extension to block requests. + Copyright (C) 2018-present Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock +*/ + +body { + display: flex; + padding: var(--default-gap-xxlarge) var(--default-gap-small); + justify-content: center; + } +:root.mobile body { + padding: var(--default-gap-small); + } + +#rootContainer { + width: min(100%, 640px); + } +#rootContainer > * { + margin: 0 0 var(--default-gap-xxlarge) 0; + } +:root.mobile #rootContainer > * { + margin-bottom: var(--default-gap-xlarge); + } + +p { + margin: 0.5em 0; + } +a { + text-decoration: none; + } +.code { + font-size: 13px; + word-break: break-all; + } +#warningSign { + color: var(--accent-surface-1); + fill: var(--accent-surface-1); + font-size: 96px; + line-height: 1; + width: 100%; + } +:root.mobile #warningSign { + font-size: 64px; + } +#theURL { + color: var(--ink-2); + padding: 0; + } +#theURL > * { + margin: 0; + } +#theURL > p { + position: relative; + z-index: 10; + } +#theURL > p > span:first-of-type { + display: block; + max-height: 6lh; + overflow-y: auto; + } +:root.mobile #theURL > p > span:first-of-type { + max-height: 3lh; + } +#theURL #toggleParse { + background-color: transparent; + top: 100%; + box-sizing: border-box; + color: var(--ink-3); + fill: var(--ink-3); + cursor: pointer; + font-size: 1.2rem; + padding: var(--default-gap-xxsmall); + position: absolute; + transform: translate(0, -50%); + } +#theURL:not(.collapsed) #toggleParse > span:first-of-type { + display: none; + } +#theURL.collapsed #toggleParse > span:last-of-type { + display: none; + } +body[dir="ltr"] #toggleParse { + right: 0; + } +body[dir="rtl"] #toggleParse { + left: 0; + } +#theURL > p:hover #toggleParse { + transform: translate(0, -50%) scale(1.15); + } +#parsed { + background-color: var(--surface-1); + border: 4px solid var(--surface-2); + font-size: small; + overflow-x: auto; + padding: var(--default-gap-xxsmall); + text-align: initial; + text-overflow: ellipsis; + } +#theURL.collapsed > #parsed { + display: none; + } +#parsed ul, #parsed li { + list-style-type: none; + } +#parsed li { + white-space: nowrap; + } +#parsed span { + display: inline-block; + } +#parsed span:first-of-type { + font-weight: bold; + } + +#actionContainer { + display: flex; + justify-content: space-between; + } +:root.mobile #actionContainer { + justify-content: center; + display: flex; + flex-direction: column; + } +#actionContainer > button { + margin-bottom: 2rem + } + +/* Small-screen devices */ +:root.mobile button { + width: 100%; + } diff --git a/platform/mv3/extension/dashboard.html b/platform/mv3/extension/dashboard.html index bcd1726bd05a3..5ac63f3d06d0f 100644 --- a/platform/mv3/extension/dashboard.html +++ b/platform/mv3/extension/dashboard.html @@ -31,6 +31,7 @@
+
diff --git a/platform/mv3/extension/js/background.js b/platform/mv3/extension/js/background.js
index 2e3a41124f5c0..a58dd70639a48 100644
--- a/platform/mv3/extension/js/background.js
+++ b/platform/mv3/extension/js/background.js
@@ -47,8 +47,10 @@ import {
import {
enableRulesets,
+ excludeFromStrictBlock,
getEnabledRulesetsDetails,
getRulesetDetails,
+ setStrictBlockMode,
updateDynamicRules,
} from './ruleset-manager.js';
@@ -213,6 +215,7 @@ function onMessage(request, sender, callback) {
autoReload: rulesetConfig.autoReload,
showBlockedCount: rulesetConfig.showBlockedCount,
canShowBlockedCount,
+ strictBlockMode: rulesetConfig.strictBlockMode,
firstRun: process.firstRun,
isSideloaded,
developerMode: rulesetConfig.developerMode,
@@ -244,6 +247,13 @@ function onMessage(request, sender, callback) {
});
return true;
+ case 'setStrictBlockMode':
+ setStrictBlockMode(request.state).then(( ) => {
+ callback();
+ broadcastMessage({ strictBlockMode: rulesetConfig.strictBlockMode });
+ });
+ return true;
+
case 'setDeveloperMode':
rulesetConfig.developerMode = request.state;
toggleDeveloperMode(rulesetConfig.developerMode);
@@ -335,6 +345,13 @@ function onMessage(request, sender, callback) {
});
return true;
+ case 'excludeFromStrictBlock': {
+ excludeFromStrictBlock(request.hostname, request.permanent).then(( ) => {
+ callback();
+ });
+ return true;
+ }
+
case 'getMatchedRules':
getMatchedRules(request.tabId).then(entries => {
callback(entries);
@@ -360,19 +377,19 @@ function onMessage(request, sender, callback) {
async function start() {
await loadRulesetConfig();
- if ( process.wakeupRun === false ) {
+ const rulesetsUpdated = process.wakeupRun === false &&
await enableRulesets(rulesetConfig.enabledRulesets);
- }
// We need to update the regex rules only when ruleset version changes.
if ( process.wakeupRun === false ) {
const currentVersion = getCurrentVersion();
if ( currentVersion !== rulesetConfig.version ) {
ubolLog(`Version change: ${rulesetConfig.version} => ${currentVersion}`);
- updateDynamicRules().then(( ) => {
- rulesetConfig.version = currentVersion;
- saveRulesetConfig();
- });
+ rulesetConfig.version = currentVersion;
+ saveRulesetConfig();
+ if ( rulesetsUpdated === false ) {
+ updateDynamicRules();
+ }
}
}
diff --git a/platform/mv3/extension/js/config.js b/platform/mv3/extension/js/config.js
index 71524e56048bb..e3859e63fa42f 100644
--- a/platform/mv3/extension/js/config.js
+++ b/platform/mv3/extension/js/config.js
@@ -33,6 +33,7 @@ export const rulesetConfig = {
enabledRulesets: [ 'default' ],
autoReload: true,
showBlockedCount: true,
+ strictBlockMode: true,
developerMode: false,
};
@@ -50,6 +51,7 @@ export async function loadRulesetConfig() {
rulesetConfig.enabledRulesets = sessionData.enabledRulesets;
rulesetConfig.autoReload = sessionData.autoReload ?? true;
rulesetConfig.showBlockedCount = sessionData.showBlockedCount ?? true;
+ rulesetConfig.strictBlockMode = sessionData.strictBlockMode ?? true;
rulesetConfig.developerMode = sessionData.developerMode ?? false;
process.wakeupRun = true;
return;
@@ -60,6 +62,7 @@ export async function loadRulesetConfig() {
rulesetConfig.enabledRulesets = localData.enabledRulesets;
rulesetConfig.autoReload = localData.autoReload ?? true;
rulesetConfig.showBlockedCount = localData.showBlockedCount ?? true;
+ rulesetConfig.strictBlockMode = localData.strictBlockMode ?? true;
rulesetConfig.developerMode = localData.developerMode ?? false;
sessionWrite('rulesetConfig', rulesetConfig);
return;
diff --git a/platform/mv3/extension/js/ext.js b/platform/mv3/extension/js/ext.js
index 94d5118a211b5..0a5a98f4f59a2 100644
--- a/platform/mv3/extension/js/ext.js
+++ b/platform/mv3/extension/js/ext.js
@@ -98,6 +98,12 @@ export async function sessionWrite(key, value) {
return browser.storage.session.set({ [key]: value });
}
+export async function sessionRemove(key) {
+ if ( browser.storage instanceof Object === false ) { return; }
+ if ( browser.storage.session instanceof Object === false ) { return; }
+ return browser.storage.session.remove(key);
+}
+
/******************************************************************************/
export async function adminRead(key) {
diff --git a/platform/mv3/extension/js/mode-manager.js b/platform/mv3/extension/js/mode-manager.js
index 335c8da166d73..3630925caad9a 100644
--- a/platform/mv3/extension/js/mode-manager.js
+++ b/platform/mv3/extension/js/mode-manager.js
@@ -19,11 +19,6 @@
Home: https://github.com/gorhill/uBlock
*/
-import {
- TRUSTED_DIRECTIVE_BASE_RULE_ID,
- getDynamicRules,
-} from './ruleset-manager.js';
-
import {
broadcastMessage,
hostnamesFromMatches,
@@ -33,12 +28,12 @@ import {
import {
browser,
- dnr,
localRead, localWrite,
sessionRead, sessionWrite,
} from './ext.js';
import { adminReadEx } from './admin.js';
+import { filteringModesToDNR } from './ruleset-manager.js';
/******************************************************************************/
@@ -74,19 +69,6 @@ const pruneHostnameFromSet = (hostname, hnSet) => {
/******************************************************************************/
-const eqSets = (setBefore, setAfter) => {
- if ( setBefore.size !== setAfter.size ) { return false; }
- for ( const hn of setAfter ) {
- if ( setBefore.has(hn) === false ) { return false; }
- }
- for ( const hn of setBefore ) {
- if ( setAfter.has(hn) === false ) { return false; }
- }
- return true;
-};
-
-/******************************************************************************/
-
const serializeModeDetails = details => {
return {
none: Array.from(details.none),
@@ -284,93 +266,6 @@ async function writeFilteringModeDetails(afterDetails) {
/******************************************************************************/
-async function filteringModesToDNR(modes) {
- const dynamicRuleMap = await getDynamicRules();
- const trustedRule = dynamicRuleMap.get(TRUSTED_DIRECTIVE_BASE_RULE_ID+0);
- const beforeRequestDomainSet = new Set(trustedRule?.condition.requestDomains);
- const beforeExcludedRrequestDomainSet = new Set(trustedRule?.condition.excludedRequestDomains);
- if ( trustedRule !== undefined && beforeRequestDomainSet.size === 0 ) {
- beforeRequestDomainSet.add('all-urls');
- } else {
- beforeExcludedRrequestDomainSet.add('all-urls');
- }
-
- const noneHostnames = new Set([ ...modes.none ]);
- const notNoneHostnames = new Set([ ...modes.basic, ...modes.optimal, ...modes.complete ]);
- let afterRequestDomainSet = new Set();
- let afterExcludedRequestDomainSet = new Set();
- if ( noneHostnames.has('all-urls') ) {
- afterRequestDomainSet = new Set([ 'all-urls' ]);
- afterExcludedRequestDomainSet = notNoneHostnames;
- } else {
- afterRequestDomainSet = noneHostnames;
- afterExcludedRequestDomainSet = new Set([ 'all-urls' ]);
- }
-
- if ( eqSets(beforeRequestDomainSet, afterRequestDomainSet) ) {
- if ( eqSets(beforeExcludedRrequestDomainSet, afterExcludedRequestDomainSet) ) {
- return;
- }
- }
-
- const removeRuleIds = [
- TRUSTED_DIRECTIVE_BASE_RULE_ID+0,
- TRUSTED_DIRECTIVE_BASE_RULE_ID+1,
- ];
- dynamicRuleMap.delete(TRUSTED_DIRECTIVE_BASE_RULE_ID+0);
- dynamicRuleMap.delete(TRUSTED_DIRECTIVE_BASE_RULE_ID+1);
-
- const allowEverywhere = afterRequestDomainSet.delete('all-urls');
- afterExcludedRequestDomainSet.delete('all-urls');
-
- const addRules = [];
- if (
- allowEverywhere ||
- afterRequestDomainSet.size !== 0 ||
- afterExcludedRequestDomainSet.size !== 0
- ) {
- const rule0 = {
- id: TRUSTED_DIRECTIVE_BASE_RULE_ID+0,
- action: { type: 'allowAllRequests' },
- condition: {
- resourceTypes: [ 'main_frame' ],
- },
- priority: 100,
- };
- if ( afterRequestDomainSet.size !== 0 ) {
- rule0.condition.requestDomains = Array.from(afterRequestDomainSet);
- } else if ( afterExcludedRequestDomainSet.size !== 0 ) {
- rule0.condition.excludedRequestDomains = Array.from(afterExcludedRequestDomainSet);
- }
- addRules.push(rule0);
- dynamicRuleMap.set(TRUSTED_DIRECTIVE_BASE_RULE_ID+0, rule0);
- // https://github.com/uBlockOrigin/uBOL-home/issues/114
- const rule1 = {
- id: TRUSTED_DIRECTIVE_BASE_RULE_ID+1,
- action: { type: 'allow' },
- condition: {
- resourceTypes: [ 'script' ],
- },
- priority: 100,
- };
- if ( rule0.condition.requestDomains ) {
- rule1.condition.initiatorDomains = rule0.condition.requestDomains.slice();
- } else if ( rule0.condition.excludedRequestDomains ) {
- rule1.condition.excludedInitiatorDomains = rule0.condition.excludedRequestDomains.slice();
- }
- addRules.push(rule1);
- dynamicRuleMap.set(TRUSTED_DIRECTIVE_BASE_RULE_ID+1, rule1);
- }
-
- const updateOptions = { removeRuleIds };
- if ( addRules.length ) {
- updateOptions.addRules = addRules;
- }
- await dnr.updateDynamicRules(updateOptions);
-}
-
-/******************************************************************************/
-
export async function getFilteringModeDetails() {
const actualDetails = await readFilteringModeDetails();
return {
diff --git a/platform/mv3/extension/js/popup.js b/platform/mv3/extension/js/popup.js
index b12a3fbcc9cef..98b4d54ce1434 100644
--- a/platform/mv3/extension/js/popup.js
+++ b/platform/mv3/extension/js/popup.js
@@ -34,7 +34,7 @@ import punycode from './punycode.js';
const popupPanelData = {};
const currentTab = {};
-let tabHostname = '';
+const tabURL = new URL(runtime.getURL('/'));
/******************************************************************************/
@@ -68,8 +68,8 @@ function setFilteringMode(level, commit = false) {
}
async function commitFilteringMode() {
- if ( tabHostname === '' ) { return; }
- const targetHostname = normalizedHostname(tabHostname);
+ if ( tabURL.hostname === '' ) { return; }
+ const targetHostname = normalizedHostname(tabURL.hostname);
const modeSlider = qs$('.filteringModeSlider');
const afterLevel = parseInt(modeSlider.dataset.level, 10);
const beforeLevel = parseInt(modeSlider.dataset.levelBefore, 10);
@@ -100,7 +100,9 @@ async function commitFilteringMode() {
}
if ( actualLevel !== beforeLevel && popupPanelData.autoReload ) {
self.setTimeout(( ) => {
- browser.tabs.reload(currentTab.id);
+ browser.tabs.update(currentTab.id, {
+ url: tabURL.href,
+ });
}, 437);
}
}
@@ -317,8 +319,12 @@ async function init() {
let url;
try {
+ const strictBlockURL = runtime.getURL('/strictblock.');
url = new URL(currentTab.url);
- tabHostname = url.hostname || '';
+ if ( url.href.startsWith(strictBlockURL) ) {
+ url = new URL(url.hash.slice(1));
+ }
+ tabURL.href = url.href || '';
} catch(ex) {
}
@@ -326,7 +332,7 @@ async function init() {
const response = await sendMessage({
what: 'popupPanelData',
origin: url.origin,
- hostname: normalizedHostname(tabHostname),
+ hostname: normalizedHostname(tabURL.hostname),
});
if ( response instanceof Object ) {
Object.assign(popupPanelData, response);
@@ -337,7 +343,7 @@ async function init() {
setFilteringMode(popupPanelData.level);
- dom.text('#hostname', punycode.toUnicode(tabHostname));
+ dom.text('#hostname', punycode.toUnicode(tabURL.hostname));
dom.cl.toggle('#showMatchedRules', 'enabled',
popupPanelData.isSideloaded === true &&
diff --git a/platform/mv3/extension/js/ruleset-manager.js b/platform/mv3/extension/js/ruleset-manager.js
index f7d811e7d87bd..c9490e6836592 100644
--- a/platform/mv3/extension/js/ruleset-manager.js
+++ b/platform/mv3/extension/js/ruleset-manager.js
@@ -23,25 +23,44 @@ import {
browser,
dnr,
i18n,
+ runtime,
} from './ext.js';
+import {
+ localRead, localRemove, localWrite,
+ sessionRead, sessionRemove, sessionWrite,
+} from './ext.js';
+
+import {
+ rulesetConfig,
+ saveRulesetConfig,
+} from './config.js';
+
+
import { fetchJSON } from './fetch.js';
import { getAdminRulesets } from './admin.js';
import { ubolLog } from './debug.js';
/******************************************************************************/
-const RULE_REALM_SIZE = 1000000;
-const REGEXES_REALM_START = 1000000;
-const REGEXES_REALM_END = REGEXES_REALM_START + RULE_REALM_SIZE;
-const REMOVEPARAMS_REALM_START = REGEXES_REALM_END;
-const REMOVEPARAMS_REALM_END = REMOVEPARAMS_REALM_START + RULE_REALM_SIZE;
-const REDIRECT_REALM_START = REMOVEPARAMS_REALM_END;
-const REDIRECT_REALM_END = REDIRECT_REALM_START + RULE_REALM_SIZE;
-const MODIFYHEADERS_REALM_START = REDIRECT_REALM_END;
-const MODIFYHEADERS_REALM_END = MODIFYHEADERS_REALM_START + RULE_REALM_SIZE;
+const STRICTBLOCK_BASE_RULE_ID = 7000000;
const TRUSTED_DIRECTIVE_BASE_RULE_ID = 8000000;
+let dynamicRuleId = 1;
+
+/******************************************************************************/
+
+const eqSets = (setBefore, setAfter) => {
+ if ( setBefore.size !== setAfter.size ) { return false; }
+ for ( const hn of setAfter ) {
+ if ( setBefore.has(hn) === false ) { return false; }
+ }
+ for ( const hn of setBefore ) {
+ if ( setAfter.has(hn) === false ) { return false; }
+ }
+ return true;
+};
+
/******************************************************************************/
function getRulesetDetails() {
@@ -59,79 +78,50 @@ function getRulesetDetails() {
/******************************************************************************/
-function getDynamicRules() {
- if ( getDynamicRules.dynamicRuleMapPromise !== undefined ) {
- return getDynamicRules.dynamicRuleMapPromise;
- }
- getDynamicRules.dynamicRuleMapPromise = dnr.getDynamicRules().then(rules => {
- const rulesMap = new Map(rules.map(rule => [ rule.id, rule ]));
- ubolLog(`Dynamic rule count: ${rulesMap.size}`);
- ubolLog(`Available dynamic rule count: ${dnr.MAX_NUMBER_OF_DYNAMIC_AND_SESSION_RULES - rulesMap.size}`);
- return rulesMap;
- });
- return getDynamicRules.dynamicRuleMapPromise;
-}
-
-/******************************************************************************/
-
async function pruneInvalidRegexRules(realm, rulesIn) {
- // Avoid testing already tested regexes
- const dynamicRules = await dnr.getDynamicRules();
- const validRegexSet = new Set(
- dynamicRules.filter(rule =>
- rule.condition?.regexFilter && true || false
- ).map(rule =>
- rule.condition.regexFilter
- )
- );
+ const rejectedRegexRules = [];
+
+ const validateRegex = regex => {
+ return dnr.isRegexSupported({ regex, isCaseSensitive: false }).then(result => {
+ const isSupported = result?.isSupported || false;
+ pruneInvalidRegexRules.validated.set(regex, isSupported);
+ if ( isSupported ) { return true; }
+ rejectedRegexRules.push(`\t${regex} ${result?.reason}`);
+ return false;
+ });
+ };
// Validate regex-based rules
const toCheck = [];
- const rejectedRegexRules = [];
for ( const rule of rulesIn ) {
if ( rule.condition?.regexFilter === undefined ) {
toCheck.push(true);
continue;
}
- const {
- regexFilter: regex,
- isUrlFilterCaseSensitive: isCaseSensitive
- } = rule.condition;
- if ( validRegexSet.has(regex) ) {
- toCheck.push(true);
- continue;
- }
- if ( pruneInvalidRegexRules.invalidRegexes.has(regex) ) {
- toCheck.push(false);
+ const { regexFilter } = rule.condition;
+ if ( pruneInvalidRegexRules.validated.has(regexFilter) ) {
+ toCheck.push(pruneInvalidRegexRules.validated.get(regexFilter));
continue;
}
- toCheck.push(
- dnr.isRegexSupported({ regex, isCaseSensitive }).then(result => {
- if ( result.isSupported ) { return true; }
- pruneInvalidRegexRules.invalidRegexes.add(regex);
- rejectedRegexRules.push(`\t${regex} ${result.reason}`);
- return false;
- })
- );
+ toCheck.push(validateRegex(regexFilter));
}
// Collate results
const isValid = await Promise.all(toCheck);
if ( rejectedRegexRules.length !== 0 ) {
- ubolLog(
- `${realm} realm: rejected regexes:\n`,
+ ubolLog(`${realm} realm: rejected regexes:\n`,
rejectedRegexRules.join('\n')
);
}
return rulesIn.filter((v, i) => isValid[i]);
}
-pruneInvalidRegexRules.invalidRegexes = new Set();
+pruneInvalidRegexRules.validated = new Map();
/******************************************************************************/
-async function updateRegexRules() {
+async function updateRegexRules(toAdd) {
const rulesetDetails = await getEnabledRulesetsDetails();
// Fetch regexes for all enabled rulesets
@@ -144,69 +134,31 @@ async function updateRegexRules() {
// Collate all regexes rules
const allRules = [];
- let regexRuleId = REGEXES_REALM_START;
for ( const rules of regexRulesets ) {
if ( Array.isArray(rules) === false ) { continue; }
for ( const rule of rules ) {
- rule.id = regexRuleId++;
+ rule.id = dynamicRuleId++;
allRules.push(rule);
}
}
+ if ( allRules.length === 0 ) { return; }
- const validatedRules = await pruneInvalidRegexRules('regexes', allRules);
-
- // Add validated regex rules to dynamic ruleset without affecting rules
- // outside regex rules realm.
- const dynamicRuleMap = await getDynamicRules();
- const newRuleMap = new Map(validatedRules.map(rule => [ rule.id, rule ]));
- const addRules = [];
- const removeRuleIds = [];
-
- for ( const oldRule of dynamicRuleMap.values() ) {
- if ( oldRule.id < REGEXES_REALM_START ) { continue; }
- if ( oldRule.id >= REGEXES_REALM_END ) { continue; }
- const newRule = newRuleMap.get(oldRule.id);
- if ( newRule === undefined ) {
- removeRuleIds.push(oldRule.id);
- dynamicRuleMap.delete(oldRule.id);
- } else if ( JSON.stringify(oldRule) !== JSON.stringify(newRule) ) {
- removeRuleIds.push(oldRule.id);
- addRules.push(newRule);
- dynamicRuleMap.set(oldRule.id, newRule);
- }
- }
-
- for ( const newRule of newRuleMap.values() ) {
- if ( dynamicRuleMap.has(newRule.id) ) { continue; }
- addRules.push(newRule);
- dynamicRuleMap.set(newRule.id, newRule);
- }
+ const validRules = await pruneInvalidRegexRules('regexes', allRules);
+ if ( validRules.length === 0 ) { return; }
- if ( addRules.length === 0 && removeRuleIds.length === 0 ) { return; }
-
- if ( removeRuleIds.length !== 0 ) {
- ubolLog(`Remove ${removeRuleIds.length} DNR regex rules`);
- }
- if ( addRules.length !== 0 ) {
- ubolLog(`Add ${addRules.length} DNR regex rules`);
- }
-
- return dnr.updateDynamicRules({ addRules, removeRuleIds }).catch(reason => {
- console.error(`updateRegexRules() / ${reason}`);
- });
+ ubolLog(`Add ${validRules.length} DNR regex rules`);
+ toAdd.push(...validRules);
}
/******************************************************************************/
-async function updateRemoveparamRules() {
+async function updateRemoveparamRules(toAdd) {
const [
hasOmnipotence,
rulesetDetails,
- dynamicRuleMap,
] = await Promise.all([
browser.permissions.contains({ origins: [ '