summaryrefslogtreecommitdiffstats
path: root/src/js/support.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 05:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 05:47:55 +0000
commit31d6ff6f931696850c348007241195ab3b2eddc7 (patch)
tree615cb1c57ce9f6611bad93326b9105098f379609 /src/js/support.js
parentInitial commit. (diff)
downloadublock-origin-31d6ff6f931696850c348007241195ab3b2eddc7.tar.xz
ublock-origin-31d6ff6f931696850c348007241195ab3b2eddc7.zip
Adding upstream version 1.55.0+dfsg.upstream/1.55.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/js/support.js')
-rw-r--r--src/js/support.js335
1 files changed, 335 insertions, 0 deletions
diff --git a/src/js/support.js b/src/js/support.js
new file mode 100644
index 0000000..9bfd7cb
--- /dev/null
+++ b/src/js/support.js
@@ -0,0 +1,335 @@
+/*******************************************************************************
+
+ uBlock Origin - a comprehensive, efficient content blocker
+ 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
+*/
+
+/* global CodeMirror, uBlockDashboard */
+
+'use strict';
+
+import { onBroadcast } from './broadcast.js';
+import { dom, qs$ } from './dom.js';
+
+/******************************************************************************/
+
+const uselessKeys = [
+ 'hiddenSettings.benchmarkDatasetURL',
+ 'hiddenSettings.blockingProfiles',
+ 'hiddenSettings.consoleLogLevel',
+ 'hiddenSettings.uiPopupConfig',
+ 'userSettings.alwaysDetachLogger',
+ 'userSettings.firewallPaneMinimized',
+ 'userSettings.externalLists',
+ 'userSettings.importedLists',
+ 'userSettings.popupPanelSections',
+ 'userSettings.uiAccentCustom',
+ 'userSettings.uiAccentCustom0',
+ 'userSettings.uiTheme',
+];
+
+const sensitiveValues = [
+ 'filterset (user)',
+ 'userSettings.popupPanelSections',
+ 'hiddenSettings.userResourcesLocation',
+ 'trustedset.added',
+ 'hostRuleset.added',
+ 'switchRuleset.added',
+ 'urlRuleset.added',
+];
+
+const sensitiveKeys = [
+ 'listset.added',
+];
+
+/******************************************************************************/
+
+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];
+}
+
+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) ) {
+ if ( value.length !== 0 ) {
+ value = `[array of ${value.length} redacted]`;
+ } else {
+ value = '[empty]';
+ }
+ } 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 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);
+ }
+}
+
+function configToMarkdown(collapse = false) {
+ const text = cmEditor.getValue().trim();
+ return collapse
+ ? '<details>\n\n```yaml\n' + text + '\n```\n</details>'
+ : '```yaml\n' + text + '\n```\n';
+}
+
+function addDetailsToReportURL(id, collapse = false) {
+ const elem = qs$(`#${id}`);
+ const url = new URL(dom.attr(elem, 'data-url'));
+ url.searchParams.set('configuration', configToMarkdown(collapse));
+ dom.attr(elem, 'data-url', url);
+}
+
+function renderData(data, depth = 0) {
+ const indent = ' '.repeat(depth);
+ if ( Array.isArray(data) ) {
+ const out = [];
+ for ( const value of data ) {
+ out.push(renderData(value, depth));
+ }
+ return out.join('\n');
+ }
+ if ( typeof data !== 'object' || data === null ) {
+ return `${indent}${data}`;
+ }
+ const out = [];
+ for ( const [ name, value ] of Object.entries(data) ) {
+ if ( typeof value === 'object' && value !== null ) {
+ out.push(`${indent}${name}:`);
+ out.push(renderData(value, depth + 1));
+ continue;
+ }
+ out.push(`${indent}${name}: ${value}`);
+ }
+ return out.join('\n');
+}
+
+async function showSupportData() {
+ const supportData = await vAPI.messaging.send('dashboard', {
+ what: 'getSupportData',
+ });
+ const shownData = JSON.parse(JSON.stringify(supportData));
+ uselessKeys.forEach(prop => { removeKey(shownData, prop); });
+ const redacted = true;
+ if ( redacted ) {
+ sensitiveValues.forEach(prop => { redactValue(shownData, prop); });
+ sensitiveKeys.forEach(prop => { redactKeys(shownData, prop); });
+ }
+ for ( const prop in shownData ) {
+ patchEmptiness(shownData, prop);
+ }
+ if ( reportedPage !== null ) {
+ shownData.popupPanel = reportedPage.popupPanel;
+ }
+ const text = renderData(shownData);
+ cmEditor.setValue(text);
+ cmEditor.clearHistory();
+
+ addDetailsToReportURL('filterReport', true);
+ addDetailsToReportURL('bugReport', true);
+}
+
+/******************************************************************************/
+
+const reportedPage = (( ) => {
+ const url = new URL(window.location.href);
+ try {
+ const pageURL = url.searchParams.get('pageURL');
+ if ( pageURL === null ) { return null; }
+ const parsedURL = new URL(pageURL);
+ parsedURL.username = '';
+ parsedURL.password = '';
+ parsedURL.hash = '';
+ const select = qs$('select[name="url"]');
+ dom.text(select.options[0], parsedURL.href);
+ if ( parsedURL.search !== '' ) {
+ const option = dom.create('option');
+ parsedURL.search = '';
+ dom.text(option, parsedURL.href);
+ select.append(option);
+ }
+ if ( parsedURL.pathname !== '/' ) {
+ const option = dom.create('option');
+ parsedURL.pathname = '';
+ dom.text(option, parsedURL.href);
+ select.append(option);
+ }
+ const shouldUpdateLists = url.searchParams.get('shouldUpdateLists');
+ if ( shouldUpdateLists !== null ) {
+ dom.body.dataset.shouldUpdateLists = shouldUpdateLists;
+ }
+ dom.cl.add(dom.body, 'filterIssue');
+ return {
+ hostname: parsedURL.hostname.replace(/^(m|mobile|www)\./, ''),
+ popupPanel: JSON.parse(url.searchParams.get('popupPanel')),
+ };
+ } catch(ex) {
+ }
+ return null;
+})();
+
+function reportSpecificFilterType() {
+ return qs$('select[name="type"]').value;
+}
+
+function reportSpecificFilterIssue() {
+ const githubURL = new URL(
+ 'https://github.com/uBlockOrigin/uAssets/issues/new?template=specific_report_from_ubo.yml'
+ );
+ const issueType = reportSpecificFilterType();
+ let title = `${reportedPage.hostname}: ${issueType}`;
+ if ( qs$('#isNSFW').checked ) {
+ title = `[nsfw] ${title}`;
+ }
+ githubURL.searchParams.set('title', title);
+ githubURL.searchParams.set(
+ 'url_address_of_the_web_page',
+ '`' + qs$('select[name="url"]').value + '`'
+ );
+ githubURL.searchParams.set('category', issueType);
+ githubURL.searchParams.set('configuration', configToMarkdown(true));
+ vAPI.messaging.send('default', {
+ what: 'gotoURL',
+ details: { url: githubURL.href, select: true, index: -1 },
+ });
+}
+
+async function updateFilterLists() {
+ if ( dom.body.dataset.shouldUpdateLists === undefined ) { return false; }
+ dom.cl.add(dom.body, 'updating');
+ const assetKeys = JSON.parse(dom.body.dataset.shouldUpdateLists);
+ vAPI.messaging.send('dashboard', { what: 'supportUpdateNow', assetKeys });
+ return true;
+}
+
+/******************************************************************************/
+
+const cmEditor = new CodeMirror(qs$('#supportData'), {
+ autofocus: true,
+ readOnly: true,
+ styleActiveLine: true,
+});
+
+uBlockDashboard.patchCodeMirrorEditor(cmEditor);
+
+/******************************************************************************/
+
+(async ( ) => {
+ await showSupportData();
+
+ dom.on('[data-url]', 'click', ev => {
+ const elem = ev.target.closest('[data-url]');
+ const url = dom.attr(elem, 'data-url');
+ if ( typeof url !== 'string' || url === '' ) { return; }
+ vAPI.messaging.send('default', {
+ what: 'gotoURL',
+ details: { url, select: true, index: -1, shiftKey: ev.shiftKey },
+ });
+ ev.preventDefault();
+ });
+
+ if ( reportedPage !== null ) {
+ if ( dom.body.dataset.shouldUpdateLists ) {
+ dom.on('.supportEntry.shouldUpdate button', 'click', ev => {
+ if ( updateFilterLists() === false ) { return; }
+ ev.preventDefault();
+ });
+ }
+
+ dom.on('[data-i18n="supportReportSpecificButton"]', 'click', ev => {
+ reportSpecificFilterIssue();
+ ev.preventDefault();
+ });
+
+ dom.on('[data-i18n="supportFindSpecificButton"]', 'click', ev => {
+ const url = new URL('https://github.com/uBlockOrigin/uAssets/issues');
+ url.searchParams.set('q', `is:issue sort:updated-desc "${reportedPage.hostname}" in:title`);
+ vAPI.messaging.send('default', {
+ what: 'gotoURL',
+ details: { url: url.href, select: true, index: -1 },
+ });
+ ev.preventDefault();
+ });
+
+ dom.on('#showSupportInfo', 'click', ev => {
+ const button = ev.target.closest('#showSupportInfo');
+ dom.cl.add(button, 'hidden');
+ dom.cl.add('.a.b.c.d', 'e');
+ cmEditor.refresh();
+ });
+ }
+
+ onBroadcast(msg => {
+ if ( msg.what === 'assetsUpdated' ) {
+ dom.cl.remove(dom.body, 'updating');
+ dom.cl.add(dom.body, 'updated');
+ return;
+ }
+ if ( msg.what === 'staticFilteringDataChanged' ) {
+ showSupportData();
+ return;
+ }
+ });
+
+ dom.on('#selectAllButton', 'click', ( ) => {
+ cmEditor.focus();
+ cmEditor.execCommand('selectAll');
+ });
+})();