2021-10-12 09:19:56 -06:00
|
|
|
/*******************************************************************************
|
|
|
|
|
|
|
|
uBlock Origin - a browser extension to block requests.
|
|
|
|
Copyright (C) 2014-present Raymond Hill
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
|
|
|
|
|
|
|
Home: https://github.com/gorhill/uBlock
|
|
|
|
*/
|
|
|
|
|
2021-10-13 09:18:23 -06:00
|
|
|
/* global CodeMirror, uBlockDashboard, uDom */
|
2021-10-12 09:19:56 -06:00
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2021-10-13 09:18:23 -06:00
|
|
|
let supportData;
|
|
|
|
|
2021-10-15 12:50:34 -06:00
|
|
|
const uselessKeys = [
|
2021-11-11 10:49:55 -07:00
|
|
|
'modifiedHiddenSettings.benchmarkDatasetURL',
|
2021-10-15 12:50:34 -06:00
|
|
|
'modifiedUserSettings.popupPanelSections',
|
|
|
|
'modifiedUserSettings.externalLists',
|
|
|
|
'modifiedUserSettings.importedLists',
|
|
|
|
];
|
|
|
|
|
2021-10-13 09:18:23 -06:00
|
|
|
const sensitiveValues = [
|
2021-11-11 12:06:59 -07:00
|
|
|
'filterset (user)',
|
2021-10-15 12:50:34 -06:00
|
|
|
'modifiedUserSettings.popupPanelSections',
|
2021-10-13 09:18:23 -06:00
|
|
|
'modifiedHiddenSettings.userResourcesLocation',
|
|
|
|
'trustedset.added',
|
|
|
|
'hostRuleset.added',
|
|
|
|
'switchRuleset.added',
|
|
|
|
'urlRuleset.added',
|
|
|
|
];
|
|
|
|
|
|
|
|
const sensitiveKeys = [
|
|
|
|
'listset.added',
|
|
|
|
];
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2021-10-15 12:50:34 -06:00
|
|
|
function removeKey(data, prop) {
|
|
|
|
if ( data instanceof Object === false ) { return; }
|
|
|
|
const pos = prop.indexOf('.');
|
|
|
|
if ( pos !== -1 ) {
|
|
|
|
const key = prop.slice(0, pos);
|
|
|
|
return removeKey(data[key], prop.slice(pos + 1));
|
|
|
|
}
|
|
|
|
delete data[prop];
|
|
|
|
}
|
|
|
|
|
2021-10-13 09:18:23 -06:00
|
|
|
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) ) {
|
2021-10-15 12:50:34 -06:00
|
|
|
if ( value.length !== 0 ) {
|
|
|
|
value = `[array of ${value.length} redacted]`;
|
|
|
|
} else {
|
|
|
|
value = '[empty]';
|
|
|
|
}
|
2021-10-13 09:18:23 -06:00
|
|
|
} 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-15 12:50:34 -06:00
|
|
|
function patchEmptiness(data, prop) {
|
|
|
|
const entry = data[prop];
|
|
|
|
if ( Array.isArray(entry) && entry.length === 0 ) {
|
|
|
|
data[prop] = '[empty]';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ( entry instanceof Object === false ) { return; }
|
|
|
|
if ( Object.keys(entry).length === 0 ) {
|
|
|
|
data[prop] = '[none]';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for ( const key in entry ) {
|
|
|
|
patchEmptiness(entry, key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-11 10:49:55 -07:00
|
|
|
function configToMarkdown(collapse = false) {
|
2021-11-14 11:40:00 -07:00
|
|
|
const text = cmEditor.getValue();
|
2021-11-11 10:49:55 -07:00
|
|
|
return collapse
|
|
|
|
? '<details>\n\n```yaml\n' + text + '\n```\n</details>'
|
|
|
|
: '```yaml\n' + text + '\n```\n';
|
|
|
|
}
|
|
|
|
|
|
|
|
function addDetailsToReportURL(id, collapse = false) {
|
2021-10-15 12:50:34 -06:00
|
|
|
const elem = uDom.nodeFromId(id);
|
|
|
|
const url = new URL(elem.getAttribute('data-url'));
|
2021-11-11 10:49:55 -07:00
|
|
|
url.searchParams.set('configuration', configToMarkdown(collapse));
|
2021-10-15 12:50:34 -06:00
|
|
|
elem.setAttribute('data-url', url);
|
|
|
|
}
|
|
|
|
|
2021-10-13 09:18:23 -06:00
|
|
|
function showData() {
|
|
|
|
const shownData = JSON.parse(JSON.stringify(supportData));
|
2021-10-15 12:50:34 -06:00
|
|
|
uselessKeys.forEach(prop => { removeKey(shownData, prop); });
|
2021-11-11 10:49:55 -07:00
|
|
|
const redacted = document.body.classList.contains('redacted');
|
2021-11-14 06:13:43 -07:00
|
|
|
// If the report is for a specific site, report per-site switches which
|
|
|
|
// are triggered on the reported site.
|
|
|
|
if (
|
|
|
|
reportURL !== null &&
|
|
|
|
shownData.switchRuleset instanceof Object &&
|
|
|
|
Array.isArray(shownData.switchRuleset.added)
|
|
|
|
) {
|
|
|
|
const hostname = reportURL.hostname;
|
|
|
|
const added = [];
|
|
|
|
const triggered = [];
|
|
|
|
for ( const rule of shownData.switchRuleset.added ) {
|
|
|
|
const match = /^[^:]+:\s+(\S+)/.exec(rule);
|
|
|
|
if (
|
|
|
|
match[1] === '*' ||
|
|
|
|
hostname === match[1] ||
|
|
|
|
hostname.endsWith(`.${match[1]}`)
|
|
|
|
) {
|
|
|
|
triggered.push(rule);
|
|
|
|
} else {
|
|
|
|
added.push(rule);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( triggered.length !== 0 ) {
|
|
|
|
shownData.switchRuleset.triggered = triggered;
|
|
|
|
shownData.switchRuleset.added = added;
|
|
|
|
}
|
|
|
|
}
|
2021-11-11 10:49:55 -07:00
|
|
|
if ( redacted ) {
|
2021-10-13 09:18:23 -06:00
|
|
|
sensitiveValues.forEach(prop => { redactValue(shownData, prop); });
|
|
|
|
sensitiveKeys.forEach(prop => { redactKeys(shownData, prop); });
|
2021-10-15 12:50:34 -06:00
|
|
|
}
|
|
|
|
for ( const prop in shownData ) {
|
|
|
|
patchEmptiness(shownData, prop);
|
2021-10-13 09:18:23 -06:00
|
|
|
}
|
2021-10-14 06:54:38 -06:00
|
|
|
const text = JSON.stringify(shownData, null, 2)
|
|
|
|
.split('\n')
|
|
|
|
.slice(1, -1)
|
|
|
|
.map(v => {
|
|
|
|
return v
|
2021-11-11 10:49:55 -07:00
|
|
|
.replace( /^( *?) "/, '$1')
|
|
|
|
.replace( /^( *.*[^\\])(?:": "|": \{$|": \[$|": )/, '$1: ')
|
2021-10-16 06:43:31 -06:00
|
|
|
.replace( /(?:",?|\},?|\],?|,)$/, '');
|
2021-10-14 06:54:38 -06:00
|
|
|
})
|
|
|
|
.filter(v => v.trim() !== '')
|
2021-10-15 12:50:34 -06:00
|
|
|
.join('\n') + '\n';
|
|
|
|
|
|
|
|
cmEditor.setValue(text);
|
2021-10-14 06:54:38 -06:00
|
|
|
cmEditor.clearHistory();
|
2021-10-15 12:50:34 -06:00
|
|
|
|
2021-11-11 10:49:55 -07:00
|
|
|
addDetailsToReportURL('filterReport', redacted === false);
|
|
|
|
addDetailsToReportURL('bugReport', redacted === false);
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
const reportURL = (( ) => {
|
|
|
|
const url = new URL(window.location.href);
|
|
|
|
try {
|
|
|
|
const reportURL = url.searchParams.get('reportURL');
|
|
|
|
if ( reportURL !== null ) {
|
|
|
|
document.body.classList.add('filterIssue');
|
|
|
|
}
|
|
|
|
document.querySelector('[data-i18n="supportS6URL"] ~ input').value = reportURL;
|
|
|
|
return new URL(reportURL);
|
|
|
|
} catch(ex) {
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
})();
|
|
|
|
|
|
|
|
function reportSpecificFilterHostname() {
|
|
|
|
return reportURL.hostname.replace(/^www\./, '');
|
|
|
|
}
|
|
|
|
|
|
|
|
function reportSpecificFilterType() {
|
|
|
|
return document.querySelector('[data-i18n="supportS6Select1"] ~ select').value;
|
|
|
|
}
|
|
|
|
|
|
|
|
function reportSpecificFilterIssue(ev) {
|
2021-11-12 07:11:28 -07:00
|
|
|
const githubURL = new URL('https://github.com/uBlockOrigin/uAssets/issues/new?template=specific_report_from_ubo.yml');
|
|
|
|
const issueType = reportSpecificFilterType();
|
|
|
|
githubURL.searchParams.set('title', `${reportSpecificFilterHostname()}: ${issueType}`);
|
|
|
|
githubURL.searchParams.set('url_address_of_the_web_page', '`' + reportURL.href + '`');
|
|
|
|
githubURL.searchParams.set('category', issueType);
|
|
|
|
githubURL.searchParams.set('configuration', configToMarkdown(false));
|
2021-11-11 10:49:55 -07:00
|
|
|
vAPI.messaging.send('default', {
|
|
|
|
what: 'gotoURL',
|
|
|
|
details: { url: githubURL.href, select: true, index: -1 },
|
|
|
|
});
|
|
|
|
ev.preventDefault();
|
2021-10-13 09:18:23 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
const cmEditor = new CodeMirror(document.getElementById('supportData'), {
|
|
|
|
autofocus: true,
|
2021-11-11 10:49:55 -07:00
|
|
|
readOnly: true,
|
2021-10-13 09:18:23 -06:00
|
|
|
styleActiveLine: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
uBlockDashboard.patchCodeMirrorEditor(cmEditor);
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2021-10-12 09:19:56 -06:00
|
|
|
(async ( ) => {
|
2021-10-13 09:18:23 -06:00
|
|
|
supportData = await vAPI.messaging.send('dashboard', {
|
|
|
|
what: 'getSupportData',
|
2021-10-12 09:19:56 -06:00
|
|
|
});
|
|
|
|
|
2021-10-13 09:18:23 -06:00
|
|
|
showData();
|
|
|
|
|
2021-10-14 06:54:38 -06:00
|
|
|
uDom('[data-url]').on('click', ev => {
|
2021-10-15 12:50:34 -06:00
|
|
|
const elem = ev.target.closest('[data-url]');
|
|
|
|
const url = elem.getAttribute('data-url');
|
2021-10-13 09:18:23 -06:00
|
|
|
if ( typeof url !== 'string' || url === '' ) { return; }
|
|
|
|
vAPI.messaging.send('default', {
|
|
|
|
what: 'gotoURL',
|
2021-10-15 12:50:34 -06:00
|
|
|
details: { url, select: true, index: -1 },
|
2021-10-13 09:18:23 -06:00
|
|
|
});
|
2021-10-14 06:54:38 -06:00
|
|
|
ev.preventDefault();
|
2021-10-12 09:19:56 -06:00
|
|
|
});
|
|
|
|
|
2021-11-11 10:49:55 -07:00
|
|
|
uDom('[data-i18n="supportReportSpecificButton"]').on('click', ev => {
|
|
|
|
reportSpecificFilterIssue(ev);
|
|
|
|
});
|
|
|
|
|
|
|
|
uDom('[data-i18n="supportFindSpecificButton"]').on('click', ev => {
|
|
|
|
const url = new URL('https://github.com/uBlockOrigin/uAssets/issues');
|
|
|
|
url.searchParams.set('q', `is:issue "${reportSpecificFilterHostname()}" in:title`);
|
|
|
|
vAPI.messaging.send('default', {
|
|
|
|
what: 'gotoURL',
|
|
|
|
details: { url: url.href, select: true, index: -1 },
|
|
|
|
});
|
|
|
|
ev.preventDefault();
|
|
|
|
});
|
|
|
|
|
2021-10-13 09:18:23 -06:00
|
|
|
uDom('#redactButton').on('click', ( ) => {
|
|
|
|
document.body.classList.add('redacted');
|
|
|
|
showData();
|
|
|
|
});
|
|
|
|
|
|
|
|
uDom('#unredactButton').on('click', ( ) => {
|
|
|
|
document.body.classList.remove('redacted');
|
|
|
|
showData();
|
|
|
|
});
|
|
|
|
|
|
|
|
uDom('#selectAllButton').on('click', ( ) => {
|
2021-10-14 10:00:24 -06:00
|
|
|
cmEditor.focus();
|
2021-10-13 09:18:23 -06:00
|
|
|
cmEditor.execCommand('selectAll');
|
|
|
|
});
|
2021-10-12 09:19:56 -06:00
|
|
|
})();
|