diff --git a/src/css/support.css b/src/css/support.css index 8e1b3b7e3..c264f157f 100644 --- a/src/css/support.css +++ b/src/css/support.css @@ -2,6 +2,36 @@ body { margin-bottom: 6rem; } +.supportEntry { + display: flex; + margin-top: 1em; + } +.supportEntry > div:first-of-type { + flex-grow: 1; + } +.supportEntry > div:last-of-type { + align-items: center; + display: flex; + } +.supportEntry h3 { + margin-top: 0; + } + +button { + margin-inline-end: 1em; + -webkit-margin-end: 1em; + } + +body.redacted #redactButton { + display: none; + } +#unredactButton { + display: none; + } +body.redacted #unredactButton { + display: inline; + } + .cm-string.cm-property { color: black; } diff --git a/src/js/messaging.js b/src/js/messaging.js index 980f8adb0..7128da5a5 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -1276,7 +1276,9 @@ const getSupportData = async function() { Date.now() ) / 864000) / 100; const listDetails = { - title: list.title, + title: list.title !== '' && list.title !== listKey + ? list.title + : undefined, daysSinceUpdated, daysBeforeNextUpdate, }; diff --git a/src/js/support.js b/src/js/support.js index 700ec5767..2fd7d47d5 100644 --- a/src/js/support.js +++ b/src/js/support.js @@ -19,25 +19,121 @@ Home: https://github.com/gorhill/uBlock */ -/* global CodeMirror, uBlockDashboard */ +/* global CodeMirror, uBlockDashboard, uDom */ 'use strict'; /******************************************************************************/ +let supportData; + +const sensitiveValues = [ + 'filterset', + 'modifiedHiddenSettings.userResourcesLocation', + 'trustedset.added', + 'hostRuleset.added', + 'switchRuleset.added', + 'urlRuleset.added', +]; + +const sensitiveKeys = [ + 'listset.added', +]; + +/******************************************************************************/ + +function redactValue(data, prop) { + if ( data instanceof Object === false ) { return; } + const pos = prop.indexOf('.'); + if ( pos !== -1 ) { + return redactValue(data[prop.slice(0, pos)], prop.slice(pos + 1)); + } + let value = data[prop]; + if ( value === undefined ) { return; } + if ( Array.isArray(value) ) { + value = `[array of ${value.length} redacted]`; + } else { + value = '[redacted]'; + } + data[prop] = value; +} + +function redactKeys(data, prop) { + if ( data instanceof Object === false ) { return; } + const pos = prop.indexOf('.'); + if ( pos !== -1 ) { + return redactKeys(data[prop.slice(0, pos)], prop.slice(pos + 1)); + } + const obj = data[prop]; + if ( obj instanceof Object === false ) { return; } + let count = 1; + for ( const key in obj ) { + if ( key.startsWith('file://') === false ) { continue; } + const newkey = `[list name ${count} redacted]`; + obj[newkey] = obj[key]; + obj[key] = undefined; + count += 1; + } +} + +function showData() { + const shownData = JSON.parse(JSON.stringify(supportData)); + if ( document.body.classList.contains('redacted') ) { + sensitiveValues.forEach(prop => { redactValue(shownData, prop); }); + sensitiveKeys.forEach(prop => { redactKeys(shownData, prop); }); + + // Redact list entries which could be hosted locally + + } + cmEditor.setValue(JSON.stringify(shownData, null, 2)); +} + +/******************************************************************************/ + +const cmEditor = new CodeMirror(document.getElementById('supportData'), { + autofocus: true, + lineWrapping: true, + mode: { name: 'javascript', json: true }, + styleActiveLine: true, +}); + +uBlockDashboard.patchCodeMirrorEditor(cmEditor); + +/******************************************************************************/ + (async ( ) => { - const cmEditor = new CodeMirror(document.getElementById('supportData'), { - autofocus: true, - lineWrapping: true, - mode: { name: 'javascript', json: true }, - styleActiveLine: true, - }); - - uBlockDashboard.patchCodeMirrorEditor(cmEditor); - - const supportData = await vAPI.messaging.send('dashboard', { + supportData = await vAPI.messaging.send('dashboard', { what: 'getSupportData', }); - cmEditor.setValue(JSON.stringify(supportData, null, 2)); + // Remove unnecessary information + if ( supportData.modifiedHiddenSettings instanceof Object ) { + const o = supportData.modifiedHiddenSettings; + o.benchmarkDatasetURL = undefined; + } + + showData(); + + uDom('button[data-url]').on('click', ev => { + const url = ev.target.getAttribute('data-url'); + if ( typeof url !== 'string' || url === '' ) { return; } + vAPI.messaging.send('default', { + what: 'gotoURL', + details: { url, select: true }, + }); + }); + + uDom('#redactButton').on('click', ( ) => { + document.body.classList.add('redacted'); + showData(); + }); + + uDom('#unredactButton').on('click', ( ) => { + document.body.classList.remove('redacted'); + showData(); + }); + + uDom('#selectAllButton').on('click', ( ) => { + cmEditor.execCommand('selectAll'); + }); })(); diff --git a/src/support.html b/src/support.html index 8891be134..ccb9ca412 100644 --- a/src/support.html +++ b/src/support.html @@ -14,10 +14,53 @@ -
+This page contains technical information which is useful to investigate issues.
Important: you may want to redact private or sensitive information before posting the support data to a public forum.
Read the documentation to learn more about all of uBlock Origin's features. +
Answers to questions and other kinds of help support is provided on the subreddit /r/uBlockOrigin. +
Report any issues with specific websites to uAssets issue tracker. +
Important: Avoid using other similarly-purposed blockers along with uBlock Origin, as this may cause filter issues on specific websites. +
File a bug report. +
Below is technical information that might be useful when volunteers are trying to help you solve a problem.
Important: you may want to redact private or sensitive information before posting to a public forum. Redacted technical information may make it more difficult to solve a problem. +