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() {