[mv3] Do not collect matched rules by default when side-loaded

Collecting matched rules when the extension is side-loaded is now
opt-in, by enabling "Developer mode" in the dashboard.

The reason is to allow the extension to behave same as the official
released version when side-loaded.

Specifically, as side-loaded extension, uBOL's service worker would
wake up due to matched-rule listener even though it would not wake
up the worker with same configuration in stable release.
This commit is contained in:
Raymond Hill 2024-11-21 12:54:28 -05:00
parent b2d7bb72c7
commit 4979aa51f5
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
6 changed files with 110 additions and 81 deletions

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><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>
<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="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 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> </div>
<div class="firstRun"> <div class="firstRun">

View File

@ -50,6 +50,7 @@ import {
import { import {
getMatchedRules, getMatchedRules,
isSideloaded, isSideloaded,
toggleDeveloperMode,
ubolLog, ubolLog,
} from './debug.js'; } from './debug.js';
@ -207,6 +208,8 @@ function onMessage(request, sender, callback) {
showBlockedCount: rulesetConfig.showBlockedCount, showBlockedCount: rulesetConfig.showBlockedCount,
canShowBlockedCount, canShowBlockedCount,
firstRun: process.firstRun, firstRun: process.firstRun,
isSideloaded,
developerMode: rulesetConfig.developerMode,
}); });
process.firstRun = false; process.firstRun = false;
}); });
@ -234,6 +237,14 @@ function onMessage(request, sender, callback) {
}); });
return true; return true;
case 'setDeveloperMode':
rulesetConfig.developerMode = request.state;
toggleDeveloperMode(rulesetConfig.developerMode);
saveRulesetConfig().then(( ) => {
callback();
});
return true;
case 'popupPanelData': { case 'popupPanelData': {
Promise.all([ Promise.all([
getFilteringMode(request.hostname), getFilteringMode(request.hostname),
@ -248,6 +259,7 @@ function onMessage(request, sender, callback) {
hasGreatPowers: results[2], hasGreatPowers: results[2],
rulesetDetails: results[3], rulesetDetails: results[3],
isSideloaded, isSideloaded,
developerMode: rulesetConfig.developerMode,
}); });
}); });
return true; return true;
@ -402,6 +414,8 @@ async function start() {
process.firstRun = false; process.firstRun = false;
} }
} }
toggleDeveloperMode(rulesetConfig.developerMode);
} }
// https://github.com/uBlockOrigin/uBOL-home/issues/199 // https://github.com/uBlockOrigin/uBOL-home/issues/199

View File

@ -33,6 +33,7 @@ export const rulesetConfig = {
enabledRulesets: [ 'default' ], enabledRulesets: [ 'default' ],
autoReload: true, autoReload: true,
showBlockedCount: true, showBlockedCount: true,
developerMode: false,
}; };
export const process = { export const process = {
@ -47,12 +48,9 @@ export async function loadRulesetConfig() {
if ( sessionData ) { if ( sessionData ) {
rulesetConfig.version = sessionData.version; rulesetConfig.version = sessionData.version;
rulesetConfig.enabledRulesets = sessionData.enabledRulesets; rulesetConfig.enabledRulesets = sessionData.enabledRulesets;
rulesetConfig.autoReload = typeof sessionData.autoReload === 'boolean' rulesetConfig.autoReload = sessionData.autoReload ?? true;
? sessionData.autoReload rulesetConfig.showBlockedCount = sessionData.showBlockedCount ?? true;
: true; rulesetConfig.developerMode = sessionData.developerMode ?? false;
rulesetConfig.showBlockedCount = typeof sessionData.showBlockedCount === 'boolean'
? sessionData.showBlockedCount
: true;
process.wakeupRun = true; process.wakeupRun = true;
return; return;
} }
@ -60,12 +58,9 @@ export async function loadRulesetConfig() {
if ( localData ) { if ( localData ) {
rulesetConfig.version = localData.version; rulesetConfig.version = localData.version;
rulesetConfig.enabledRulesets = localData.enabledRulesets; rulesetConfig.enabledRulesets = localData.enabledRulesets;
rulesetConfig.autoReload = typeof localData.autoReload === 'boolean' rulesetConfig.autoReload = localData.autoReload ?? true;
? localData.autoReload rulesetConfig.showBlockedCount = localData.showBlockedCount ?? true;
: true; rulesetConfig.developerMode = localData.developerMode ?? false;
rulesetConfig.showBlockedCount = typeof localData.showBlockedCount === 'boolean'
? localData.showBlockedCount
: true;
sessionWrite('rulesetConfig', rulesetConfig); sessionWrite('rulesetConfig', rulesetConfig);
return; return;
} }

View File

@ -19,21 +19,11 @@
Home: https://github.com/gorhill/uBlock Home: https://github.com/gorhill/uBlock
*/ */
import { browser, dnr } from './ext.js'; import { dnr } from './ext.js';
/******************************************************************************/ /******************************************************************************/
export const isSideloaded = (( ) => { export const isSideloaded = dnr.onRuleMatchedDebug instanceof Object;
if ( dnr.onRuleMatchedDebug instanceof Object === false ) { return false; }
const { id } = browser.runtime;
// https://addons.mozilla.org/en-US/firefox/addon/ublock-origin-lite/
if ( id === 'uBOLite@raymondhill.net' ) { return false; }
// https://chromewebstore.google.com/detail/ddkjiahejlhfcafbddmgiahcphecmpfh
if ( id === 'ddkjiahejlhfcafbddmgiahcphecmpfh' ) { return false; }
// https://microsoftedge.microsoft.com/addons/detail/cimighlppcgcoapaliogpjjdehbnofhn
if ( id === 'cimighlppcgcoapaliogpjjdehbnofhn' ) { return false; }
return true;
})();
/******************************************************************************/ /******************************************************************************/
@ -45,66 +35,62 @@ export const ubolLog = (...args) => {
/******************************************************************************/ /******************************************************************************/
const rulesets = new Map();
const bufferSize = isSideloaded ? 256 : 1;
const matchedRules = new Array(bufferSize);
matchedRules.fill(null);
let writePtr = 0;
const pruneLongLists = list => {
if ( list.length <= 21 ) { return list; }
return [ ...list.slice(0, 10), '...', ...list.slice(-10) ];
};
const getRuleset = async rulesetId => {
if ( rulesets.has(rulesetId) ) {
return rulesets.get(rulesetId);
}
let rules;
if ( rulesetId === dnr.DYNAMIC_RULESET_ID ) {
rules = await dnr.getDynamicRules().catch(( ) => undefined);
} else {
const response = await fetch(`/rulesets/main/${rulesetId}.json`).catch(( ) => undefined);
if ( response === undefined ) { return; }
rules = await response.json().catch(( ) => undefined);
}
if ( Array.isArray(rules) === false ) { return; }
const ruleset = new Map();
for ( const rule of rules ) {
const condition = rule.condition;
if ( condition ) {
if ( condition.requestDomains ) {
condition.requestDomains = pruneLongLists(condition.requestDomains);
}
if ( condition.initiatorDomains ) {
condition.initiatorDomains = pruneLongLists(condition.initiatorDomains);
}
}
const ruleId = rule.id;
rule.id = `${rulesetId}/${ruleId}`;
ruleset.set(ruleId, rule);
}
rulesets.set(rulesetId, ruleset);
return ruleset;
};
const getRuleDetails = async ruleInfo => {
const { rulesetId, ruleId } = ruleInfo.rule;
const ruleset = await getRuleset(rulesetId);
if ( ruleset === undefined ) { return; }
return { request: ruleInfo.request, rule: ruleset.get(ruleId) };
};
/******************************************************************************/
export const getMatchedRules = (( ) => { export const getMatchedRules = (( ) => {
const noopFn = ( ) => Promise.resolve([]); const noopFn = ( ) => Promise.resolve([]);
if ( isSideloaded !== true ) { return noopFn; } if ( isSideloaded !== true ) { return noopFn; }
if ( dnr.onRuleMatchedDebug instanceof Object === false ) { return noopFn; }
const rulesets = new Map();
const bufferSize = 256;
const matchedRules = new Array(bufferSize);
matchedRules.fill(null);
let writePtr = 0;
const pruneLongLists = list => {
if ( list.length <= 21 ) { return list; }
return [ ...list.slice(0, 10), '...', ...list.slice(-10) ];
};
const getRuleset = async rulesetId => {
if ( rulesets.has(rulesetId) ) {
return rulesets.get(rulesetId);
}
let rules;
if ( rulesetId === dnr.DYNAMIC_RULESET_ID ) {
rules = await dnr.getDynamicRules().catch(( ) => undefined);
} else {
const response = await fetch(`/rulesets/main/${rulesetId}.json`).catch(( ) => undefined);
if ( response === undefined ) { return; }
rules = await response.json().catch(( ) => undefined);
}
if ( Array.isArray(rules) === false ) { return; }
const ruleset = new Map();
for ( const rule of rules ) {
const condition = rule.condition;
if ( condition ) {
if ( condition.requestDomains ) {
condition.requestDomains = pruneLongLists(condition.requestDomains);
}
if ( condition.initiatorDomains ) {
condition.initiatorDomains = pruneLongLists(condition.initiatorDomains);
}
}
const ruleId = rule.id;
rule.id = `${rulesetId}/${ruleId}`;
ruleset.set(ruleId, rule);
}
rulesets.set(rulesetId, ruleset);
return ruleset;
};
const getRuleDetails = async ruleInfo => {
const { rulesetId, ruleId } = ruleInfo.rule;
const ruleset = await getRuleset(rulesetId);
if ( ruleset === undefined ) { return; }
return { request: ruleInfo.request, rule: ruleset.get(ruleId) };
};
dnr.onRuleMatchedDebug.addListener(ruleInfo => {
matchedRules[writePtr] = ruleInfo;
writePtr = (writePtr + 1) % bufferSize;
});
return async tabId => { return async tabId => {
const promises = []; const promises = [];
@ -124,3 +110,19 @@ export const getMatchedRules = (( ) => {
})(); })();
/******************************************************************************/ /******************************************************************************/
const matchedRuleListener = ruleInfo => {
matchedRules[writePtr] = ruleInfo;
writePtr = (writePtr + 1) % bufferSize;
};
export const toggleDeveloperMode = state => {
if ( isSideloaded !== true ) { return; }
if ( state ) {
dnr.onRuleMatchedDebug.addListener(matchedRuleListener);
} else {
dnr.onRuleMatchedDebug.removeListener(matchedRuleListener);
}
};
/******************************************************************************/

View File

@ -331,6 +331,7 @@ async function init() {
dom.cl.toggle('#showMatchedRules', 'enabled', dom.cl.toggle('#showMatchedRules', 'enabled',
popupPanelData.isSideloaded === true && popupPanelData.isSideloaded === true &&
popupPanelData.developerMode &&
typeof currentTab.id === 'number' && typeof currentTab.id === 'number' &&
isNaN(currentTab.id) === false isNaN(currentTab.id) === false
); );

View File

@ -55,6 +55,15 @@ function renderWidgets() {
dom.attr(input, 'disabled', ''); dom.attr(input, 'disabled', '');
} }
} }
{
dom.prop('#developerMode input[type="checkbox"]', 'checked',
Boolean(cachedRulesetData.developerMode)
);
if ( cachedRulesetData.isSideloaded ) {
dom.attr('#developerMode', 'hidden', null);
}
}
} }
/******************************************************************************/ /******************************************************************************/
@ -126,6 +135,13 @@ dom.on('#showBlockedCount input[type="checkbox"]', 'change', ev => {
}); });
}); });
dom.on('#developerMode input[type="checkbox"]', 'change', ev => {
sendMessage({
what: 'setDeveloperMode',
state: ev.target.checked,
});
});
/******************************************************************************/ /******************************************************************************/
function renderTrustedSites() { function renderTrustedSites() {