From 6bfa7245f3760b44fd3586fdac71f758f1a1cdb3 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Sat, 12 Jul 2025 11:16:29 -0400 Subject: [PATCH] [mv3] Normalize rulesets read from package This ensures rulesets are properly rendered in DNR ruleset viewer in Safari. --- platform/mv3/extension/js/debug.js | 12 ++++++---- platform/mv3/extension/js/ext-compat.js | 11 +++++++-- platform/mv3/extension/js/ro-dnr-editor.js | 7 +++++- platform/mv3/safari/ext-compat.js | 28 +++++++++++++++++----- 4 files changed, 45 insertions(+), 13 deletions(-) diff --git a/platform/mv3/extension/js/debug.js b/platform/mv3/extension/js/debug.js index b11e84725..e57781327 100644 --- a/platform/mv3/extension/js/debug.js +++ b/platform/mv3/extension/js/debug.js @@ -19,7 +19,7 @@ Home: https://github.com/gorhill/uBlock */ -import { INITIATOR_DOMAINS, dnr } from './ext-compat.js'; +import { dnr, normalizeDNRRules } from './ext-compat.js'; import { browser } from './ext.js'; /******************************************************************************/ @@ -62,7 +62,11 @@ const getRuleset = async rulesetId => { } else { const response = await fetch(`/rulesets/main/${rulesetId}.json`).catch(( ) => undefined); if ( response === undefined ) { return; } - rules = await response.json().catch(( ) => undefined); + rules = await response.json().catch(( ) => + undefined + ).then(rules => + normalizeDNRRules(rules) + ); } if ( Array.isArray(rules) === false ) { return; } const ruleset = new Map(); @@ -72,8 +76,8 @@ const getRuleset = async rulesetId => { if ( condition.requestDomains ) { condition.requestDomains = pruneLongLists(condition.requestDomains); } - if ( condition[INITIATOR_DOMAINS] ) { - condition[INITIATOR_DOMAINS] = pruneLongLists(condition[INITIATOR_DOMAINS]); + if ( condition.initiatorDomains ) { + condition.initiatorDomains = pruneLongLists(condition.initiatorDomains); } } const ruleId = rule.id; diff --git a/platform/mv3/extension/js/ext-compat.js b/platform/mv3/extension/js/ext-compat.js index 0d431c472..e5f66f042 100644 --- a/platform/mv3/extension/js/ext-compat.js +++ b/platform/mv3/extension/js/ext-compat.js @@ -21,8 +21,6 @@ export const webext = self.browser || self.chrome; export const dnr = webext.declarativeNetRequest || {}; -export const INITIATOR_DOMAINS = 'initiatorDomains'; -export const EXCLUDED_INITIATOR_DOMAINS = 'excludedInitiatorDomains'; /******************************************************************************/ @@ -36,6 +34,15 @@ const isSameRules = (a, b) => { /******************************************************************************/ +export function normalizeDNRRules(rules, ruleIds) { + if ( Array.isArray(rules) === false ) { return rules; } + return Array.isArray(ruleIds) + ? rules.filter(rule => ruleIds.includes(rule.id)) + : rules; +} + +/******************************************************************************/ + dnr.setAllowAllRules = async function(id, allowed, notAllowed, reverse, priority) { const [ beforeDynamicRules, diff --git a/platform/mv3/extension/js/ro-dnr-editor.js b/platform/mv3/extension/js/ro-dnr-editor.js index c2e960bc7..795301eb4 100644 --- a/platform/mv3/extension/js/ro-dnr-editor.js +++ b/platform/mv3/extension/js/ro-dnr-editor.js @@ -21,6 +21,7 @@ import { DNREditor } from './dnr-editor.js'; import { i18n$ } from './i18n.js'; +import { normalizeDNRRules } from './ext-compat.js'; import { sendMessage } from './ext.js'; import { textFromRules } from './dnr-parser.js'; @@ -59,7 +60,11 @@ export class ReadOnlyDNREditor extends DNREditor { for ( const [ realm, dir ] of Object.entries(realms) ) { if ( Boolean(rulesetDetails.rules?.[realm]) === false ) { continue; } promises.push( - fetch(`./rulesets/${dir}/${this.id}.json`).then(response => response.json()) + fetch(`./rulesets/${dir}/${this.id}.json`).then(response => + response.json() + ).then(rules => + normalizeDNRRules(rules) + ) ); } const parts = await Promise.all(promises); diff --git a/platform/mv3/safari/ext-compat.js b/platform/mv3/safari/ext-compat.js index a88c20c7c..b0bb945ea 100644 --- a/platform/mv3/safari/ext-compat.js +++ b/platform/mv3/safari/ext-compat.js @@ -21,8 +21,6 @@ export const webext = self.browser; -export const INITIATOR_DOMAINS = 'domains'; -export const EXCLUDED_INITIATOR_DOMAINS = 'excludedDomains'; /******************************************************************************/ @@ -86,6 +84,26 @@ const isSameRules = (a, b) => { /******************************************************************************/ +export function normalizeDNRRules(rules, ruleIds) { + if ( Array.isArray(rules) === false ) { return rules; } + const selectedRules = Array.isArray(ruleIds) + ? rules.filter(rule => ruleIds.includes(rule.id)) + : rules; + selectedRules.forEach(rule => { + if ( Array.isArray(rule.domains) ) { + rules.initiatorDomains = rule.domains; + delete rule.domains; + } + if ( Array.isArray(rule.excludedDomains) ) { + rules.excludedInitiatorDomains = rule.excludedDomains; + delete rule.excludedDomains; + } + }); + return selectedRules; +} + +/******************************************************************************/ + export const dnr = { DYNAMIC_RULESET_ID: '_dynamic', MAX_NUMBER_OF_ENABLED_STATIC_RULESETS: nativeDNR.MAX_NUMBER_OF_ENABLED_STATIC_RULESETS, @@ -97,8 +115,7 @@ export const dnr = { return new Promise(resolve => { nativeDNR.getDynamicRules(rules => { if ( Array.isArray(rules) === false ) { return resolve([]); } - if ( Array.isArray(ruleIds) === false ) { return resolve(rules); } - return resolve(rules.filter(rule => ruleIds.includes(rule.id))); + return resolve(normalizeDNRRules(rules, ruleIds)); }); }); }, @@ -112,8 +129,7 @@ export const dnr = { return new Promise(resolve => { nativeDNR.getSessionRules(rules => { if ( Array.isArray(rules) === false ) { return resolve([]); } - if ( Array.isArray(ruleIds) === false ) { return resolve(rules); } - return resolve(rules.filter(rule => ruleIds.includes(rule.id))); + return resolve(normalizeDNRRules(rules, ruleIds)); }); }); },