diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 05:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 05:47:55 +0000 |
commit | 31d6ff6f931696850c348007241195ab3b2eddc7 (patch) | |
tree | 615cb1c57ce9f6611bad93326b9105098f379609 /src/js/support.js | |
parent | Initial commit. (diff) | |
download | ublock-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.js | 335 |
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'); + }); +})(); |