This commit is contained in:
Raymond Hill 2024-12-03 12:29:56 -05:00
parent b894c26ffc
commit 5c765449c4
No known key found for this signature in database
GPG key ID: 25E1490B761470C2
7 changed files with 109 additions and 61 deletions

View file

@ -231,6 +231,14 @@
"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"

View file

@ -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"],

View file

@ -31,6 +31,7 @@
<p><label id="autoReload" data-i18n="autoReloadLabel"><span class="input checkbox"><input type="checkbox"><svg viewBox="0 0 24 24"><path d="M1.73,12.91 8.1,19.28 22.79,4.59"/></svg></span>_</label>
</p>
<p><label id="showBlockedCount" data-i18n="showBlockedCountLabel"><span class="input checkbox"><input type="checkbox"><svg viewBox="0 0 24 24"><path d="M1.73,12.91 8.1,19.28 22.79,4.59"/></svg></span>_</label>
<p><label id="strictBlockMode" data-i18n="enableStrictBlockLabel"><span class="input checkbox"><input type="checkbox"><svg viewBox="0 0 24 24"><path d="M1.73,12.91 8.1,19.28 22.79,4.59"/></svg></span>_</label><legend data-i18n="enableStrictBlockLegend"></legend>
<p id="developerMode" hidden><label><span class="input checkbox"><input type="checkbox"><svg viewBox="0 0 24 24"><path d="M1.73,12.91 8.1,19.28 22.79,4.59"/></svg></span>Developer mode</label>
</div>

View file

@ -50,6 +50,7 @@ import {
excludeFromStrictBlock,
getEnabledRulesetsDetails,
getRulesetDetails,
setStrictBlockMode,
updateDynamicRules,
} from './ruleset-manager.js';
@ -214,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,
@ -245,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);

View file

@ -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;

View file

@ -31,16 +31,22 @@ import {
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 STRICTBLOCK_BASE_RULE_ID = 7000000;
const TRUSTED_DIRECTIVE_BASE_RULE_ID = 8000000;
let dynamicRuleId = 1;
let sessionRuleId = 1;
/******************************************************************************/
@ -264,6 +270,8 @@ async function updateModifyHeadersRules(toAdd) {
/******************************************************************************/
async function updateStrictBlockRules(dynamicRules, sessionRules) {
if ( rulesetConfig.strictBlockMode === false ) { return; }
const [
hasOmnipotence,
rulesetDetails,
@ -315,7 +323,7 @@ async function updateStrictBlockRules(dynamicRules, sessionRules) {
}
if ( strictblockPath === '' ) { return; }
const dynamicRule = {
id: dynamicRuleId++,
id: STRICTBLOCK_BASE_RULE_ID,
action: {
type: 'redirect',
redirect: {
@ -337,7 +345,7 @@ async function updateStrictBlockRules(dynamicRules, sessionRules) {
if ( temporarilyExcluded.length === 0 ) { return; }
sessionRules.push({
id: sessionRuleId++,
id: STRICTBLOCK_BASE_RULE_ID,
action: {
type: 'allow',
},
@ -350,10 +358,64 @@ async function updateStrictBlockRules(dynamicRules, sessionRules) {
ubolLog(`Add 1 DNR session rule with ${temporarilyExcluded.length} excluded strictblock domains`);
}
async function commitStrictBlockRules() {
const [
beforePermanentRules,
beforeTemporaryRules,
] = await Promise.all([
dnr.getDynamicRules({ ruleIds: [ STRICTBLOCK_BASE_RULE_ID ] }),
dnr.getSessionRules({ ruleIds: [ STRICTBLOCK_BASE_RULE_ID ] }),
]);
if ( beforePermanentRules?.length ) {
ubolLog(`Remove 1 DNR dynamic strictblock rule`);
}
if ( beforeTemporaryRules?.length ) {
ubolLog(`Remove 1 DNR session strictblock rule`);
}
const afterPermanentRules = [];
const afterTemporaryRules = [];
await updateStrictBlockRules(afterPermanentRules, afterTemporaryRules)
return Promise.all([
dnr.updateDynamicRules({
addRules: afterPermanentRules,
removeRuleIds: beforePermanentRules.map(rule => rule.id),
}),
dnr.updateSessionRules({
addRules: afterTemporaryRules,
removeRuleIds: beforeTemporaryRules.map(rule => rule.id),
}),
]);
}
async function excludeFromStrictBlock(hostname, permanent) {
if ( typeof hostname !== 'string' || hostname === '' ) { return; }
const readFn = permanent ? localRead : sessionRead;
const hostnames = new Set(await readFn('excludedStrictBlockHostnames'));
hostnames.add(hostname);
const writeFn = permanent ? localWrite : sessionWrite;
await writeFn('excludedStrictBlockHostnames', Array.from(hostnames));
return commitStrictBlockRules();
}
async function setStrictBlockMode(state) {
const newState = Boolean(state);
if ( newState === rulesetConfig.strictBlockMode ) { return; }
rulesetConfig.strictBlockMode = newState;
const promises = [ saveRulesetConfig() ];
if ( newState === false ) {
promises.push(
localRemove('excludedStrictBlockHostnames'),
sessionRemove('excludedStrictBlockHostnames')
);
}
await Promise.all(promises);
return commitStrictBlockRules();
}
/******************************************************************************/
async function updateDynamicRules() {
dynamicRuleId = sessionRuleId = 1;
dynamicRuleId = 1;
const dynamicRules = [];
const sessionRules = [];
const [
@ -474,7 +536,6 @@ async function filteringModesToDNR(modes) {
rule0.condition.excludedRequestDomains = Array.from(afterExcludedRequestDomainSet);
}
addRules.push(rule0);
unexcludeFromStrictBlock(afterRequestDomainSet);
// https://github.com/uBlockOrigin/uBOL-home/issues/114
const rule1 = {
id: TRUSTED_DIRECTIVE_BASE_RULE_ID+1,
@ -499,60 +560,6 @@ async function filteringModesToDNR(modes) {
/******************************************************************************/
async function excludeFromStrictBlock(hostname, permanent) {
if ( typeof hostname !== 'string' || hostname === '' ) { return; }
const readFn = permanent ? localRead : sessionRead;
const hostnames = new Set(await readFn('excludedStrictBlockHostnames'));
hostnames.add(hostname);
const writeFn = permanent ? localWrite : sessionWrite;
await writeFn('excludedStrictBlockHostnames', Array.from(hostnames));
return updateDynamicRules();
}
async function unexcludeFromStrictBlock(hostnames) {
const [
permanentlyExcluded,
temporarilyExcluded,
] = await Promise.all([
localRead('excludedStrictBlockHostnames').then(r => r = new Set(r)),
sessionRead('excludedStrictBlockHostnames').then(r => r = new Set(r)),
]);
const permanentCountBefore = permanentlyExcluded.size;
const temporaryCountBefore = temporarilyExcluded.size;
for ( const hn of hostnames ) {
permanentlyExcluded.delete(hn);
temporarilyExcluded.delete(hn);
}
const promises = [];
if ( permanentlyExcluded.size !== permanentCountBefore ) {
if ( permanentlyExcluded.size === 0 ) {
promises.push(
localRemove('excludedStrictBlockHostnames')
);
} else {
promises.push(
localWrite('excludedStrictBlockHostnames', Array.from(permanentlyExcluded))
);
}
}
if ( temporarilyExcluded.size !== temporaryCountBefore ) {
if ( temporarilyExcluded.size === 0 ) {
promises.push(
sessionRemove('excludedStrictBlockHostnames')
);
} else {
promises.push(
sessionWrite('excludedStrictBlockHostnames', Array.from(temporarilyExcluded))
);
}
}
if ( promises.length === 0 ) { return; }
await Promise.all(promises);
return updateDynamicRules();
}
/******************************************************************************/
async function defaultRulesetsFromLanguage() {
const out = await dnr.getEnabledRulesets();
@ -672,5 +679,6 @@ export {
filteringModesToDNR,
getRulesetDetails,
getEnabledRulesetsDetails,
setStrictBlockMode,
updateDynamicRules,
};

View file

@ -67,6 +67,8 @@ function renderWidgets() {
}
}
qs$('#strictBlockMode input[type="checkbox"]').checked = cachedRulesetData.strictBlockMode;
{
dom.prop('#developerMode input[type="checkbox"]', 'checked',
Boolean(cachedRulesetData.developerMode)
@ -146,6 +148,13 @@ dom.on('#showBlockedCount input[type="checkbox"]', 'change', ev => {
});
});
dom.on('#strictBlockMode input[type="checkbox"]', 'change', ev => {
sendMessage({
what: 'setStrictBlockMode',
state: ev.target.checked,
});
});
dom.on('#developerMode input[type="checkbox"]', 'change', ev => {
sendMessage({
what: 'setDeveloperMode',
@ -240,6 +249,13 @@ listen.onmessage = ev => {
}
}
if ( message.strictBlockMode !== undefined ) {
if ( message.strictBlockMode !== local.strictBlockMode ) {
local.strictBlockMode = message.strictBlockMode;
render = true;
}
}
if ( message.adminRulesets !== undefined ) {
if ( hashFromIterable(message.adminRulesets) !== hashFromIterable(local.adminRulesets) ) {
local.adminRulesets = message.adminRulesets;