diff --git a/platform/mv3/extension/dashboard.html b/platform/mv3/extension/dashboard.html index 2169031eb..c8442cabc 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 0455b5a3c..fcbc9af60 100644 --- a/platform/mv3/extension/js/background.js +++ b/platform/mv3/extension/js/background.js @@ -50,6 +50,7 @@ import { import { getMatchedRules, isSideloaded, + toggleDeveloperMode, ubolLog, } from './debug.js'; @@ -207,6 +208,8 @@ function onMessage(request, sender, callback) { showBlockedCount: rulesetConfig.showBlockedCount, canShowBlockedCount, firstRun: process.firstRun, + isSideloaded, + developerMode: rulesetConfig.developerMode, }); process.firstRun = false; }); @@ -234,6 +237,14 @@ function onMessage(request, sender, callback) { }); return true; + case 'setDeveloperMode': + rulesetConfig.developerMode = request.state; + toggleDeveloperMode(rulesetConfig.developerMode); + saveRulesetConfig().then(( ) => { + callback(); + }); + return true; + case 'popupPanelData': { Promise.all([ getFilteringMode(request.hostname), @@ -248,6 +259,7 @@ function onMessage(request, sender, callback) { hasGreatPowers: results[2], rulesetDetails: results[3], isSideloaded, + developerMode: rulesetConfig.developerMode, }); }); return true; @@ -402,6 +414,8 @@ async function start() { process.firstRun = false; } } + + toggleDeveloperMode(rulesetConfig.developerMode); } // https://github.com/uBlockOrigin/uBOL-home/issues/199 diff --git a/platform/mv3/extension/js/config.js b/platform/mv3/extension/js/config.js index bb74a4416..71524e560 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, + developerMode: false, }; export const process = { @@ -47,12 +48,9 @@ export async function loadRulesetConfig() { if ( sessionData ) { rulesetConfig.version = sessionData.version; rulesetConfig.enabledRulesets = sessionData.enabledRulesets; - rulesetConfig.autoReload = typeof sessionData.autoReload === 'boolean' - ? sessionData.autoReload - : true; - rulesetConfig.showBlockedCount = typeof sessionData.showBlockedCount === 'boolean' - ? sessionData.showBlockedCount - : true; + rulesetConfig.autoReload = sessionData.autoReload ?? true; + rulesetConfig.showBlockedCount = sessionData.showBlockedCount ?? true; + rulesetConfig.developerMode = sessionData.developerMode ?? false; process.wakeupRun = true; return; } @@ -60,12 +58,9 @@ export async function loadRulesetConfig() { if ( localData ) { rulesetConfig.version = localData.version; rulesetConfig.enabledRulesets = localData.enabledRulesets; - rulesetConfig.autoReload = typeof localData.autoReload === 'boolean' - ? localData.autoReload - : true; - rulesetConfig.showBlockedCount = typeof localData.showBlockedCount === 'boolean' - ? localData.showBlockedCount - : true; + rulesetConfig.autoReload = localData.autoReload ?? true; + rulesetConfig.showBlockedCount = localData.showBlockedCount ?? true; + rulesetConfig.developerMode = localData.developerMode ?? false; sessionWrite('rulesetConfig', rulesetConfig); return; } diff --git a/platform/mv3/extension/js/debug.js b/platform/mv3/extension/js/debug.js index 9488260d8..0a6ecaffe 100644 --- a/platform/mv3/extension/js/debug.js +++ b/platform/mv3/extension/js/debug.js @@ -19,21 +19,11 @@ Home: https://github.com/gorhill/uBlock */ -import { browser, dnr } from './ext.js'; +import { dnr } from './ext.js'; /******************************************************************************/ -export const isSideloaded = (( ) => { - 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; -})(); +export const isSideloaded = dnr.onRuleMatchedDebug instanceof Object; /******************************************************************************/ @@ -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 = (( ) => { const noopFn = ( ) => Promise.resolve([]); 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 => { 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); + } +}; + +/******************************************************************************/ diff --git a/platform/mv3/extension/js/popup.js b/platform/mv3/extension/js/popup.js index 4242e5bac..9a62eca3f 100644 --- a/platform/mv3/extension/js/popup.js +++ b/platform/mv3/extension/js/popup.js @@ -331,6 +331,7 @@ async function init() { dom.cl.toggle('#showMatchedRules', 'enabled', popupPanelData.isSideloaded === true && + popupPanelData.developerMode && typeof currentTab.id === 'number' && isNaN(currentTab.id) === false ); diff --git a/platform/mv3/extension/js/settings.js b/platform/mv3/extension/js/settings.js index 81f55d03c..0233674d4 100644 --- a/platform/mv3/extension/js/settings.js +++ b/platform/mv3/extension/js/settings.js @@ -55,6 +55,15 @@ function renderWidgets() { 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() {