Skip to content

Commit

Permalink
Add "Support" pane to dashboard
Browse files Browse the repository at this point in the history
The purpose is to allow users to make it easy to share
technical information about their uBO configuration, and
to make it easy for volunteers to diagnose issues.

This is a first step toward the goal of making it easier
for users to report issues with either uBO or filter
issues on websites.

Related issues:
- uBlockOrigin/uBlock-issues#1701
- uBlockOrigin/uBlock-issues#1541
  • Loading branch information
gorhill committed Oct 12, 2021
1 parent 8365984 commit a3a43c7
Show file tree
Hide file tree
Showing 10 changed files with 1,183 additions and 21 deletions.
4 changes: 4 additions & 0 deletions src/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@
"message": "About",
"description": "appears as tab name in dashboard"
},
"supportPageName": {
"message": "Support",
"description": "appears as tab name in dashboard"
},
"assetViewerPageName": {
"message": "uBlock₀ — Asset viewer",
"description": "Title for the asset viewer page"
Expand Down
8 changes: 0 additions & 8 deletions src/css/about.css
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
body {
margin-bottom: 6rem;
}
.entries {
margin: 0.5em 0;
margin-inline-start: 2em;
-webkit-margin-start: 2em;
}
.entry {
margin: 0.5em 0;
}
#dev {
align-items: flex-start;
display: none;
Expand Down
3 changes: 3 additions & 0 deletions src/css/support.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
body {
margin-bottom: 6rem;
}
1 change: 1 addition & 0 deletions src/dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
--><span class="tabButton" data-pane="dyna-rules.html" data-i18n="rulesPageName"></span><!--
--><span class="tabButton" data-pane="whitelist.html" data-i18n="whitelistPageName"></span><!--
--><span class="tabButton" data-pane="shortcuts.html" data-i18n="shortcutsPageName"></span><!--
--><span class="tabButton" data-pane="support.html" data-i18n="supportPageName"></span><!--
--><span class="tabButton" data-pane="about.html" data-i18n="aboutPageName"></span><!--
--><span class="tabButton" data-pane="no-dashboard.html"></span>
</div>
Expand Down
13 changes: 13 additions & 0 deletions src/js/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,19 @@ const µBlock = { // jshint ignore:line
hiddenSettingsAdmin: {},
hiddenSettings: Object.assign({}, hiddenSettingsDefault),

dynamicFilteringDefault: [
'behind-the-scene * * noop',
'behind-the-scene * image noop',
'behind-the-scene * 3p noop',
'behind-the-scene * inline-script noop',
'behind-the-scene * 1p-script noop',
'behind-the-scene * 3p-script noop',
'behind-the-scene * 3p-frame noop',
],
hostnameSwitchesDefault: [
'no-large-media: behind-the-scene false',
],

noDashboard: false,

// Features detection.
Expand Down
139 changes: 138 additions & 1 deletion src/js/messaging.js
Original file line number Diff line number Diff line change
Expand Up @@ -1170,7 +1170,7 @@ const modifyRuleset = function(details) {
}
};

// Shortcuts pane
// Shortcuts
const getShortcuts = function(callback) {
if ( µb.canUseShortcuts === false ) {
return callback([]);
Expand Down Expand Up @@ -1204,6 +1204,136 @@ const setShortcut = function(details) {
vAPI.storage.set({ commandShortcuts: Array.from(µb.commandShortcuts) });
};

// Support
const getSupportData = async function() {
const diffArrays = function(modified, original) {
const modifiedSet = new Set(modified);
const originalSet = new Set(original);
let added = [];
let removed = [];
for ( const item of modifiedSet ) {
if ( originalSet.has(item) ) { continue; }
added.push(item);
}
for ( const item of originalSet ) {
if ( modifiedSet.has(item) ) { continue; }
removed.push(item);
}
if ( added.length === 0 ) {
added = undefined;
}
if ( removed.length === 0 ) {
removed = undefined;
}
if ( added !== undefined || removed !== undefined ) {
return { added, removed };
}
};

let modifiedUserSettings = µb.getModifiedSettings(
µb.userSettings,
µb.userSettingsDefault
);
delete modifiedUserSettings.externalLists;
delete modifiedUserSettings.importedLists;
if ( Object.keys(modifiedUserSettings).length === 0 ) {
modifiedUserSettings = 'none';
}

let modifiedHiddenSettings = µb.getModifiedSettings(
µb.hiddenSettings,
µb.hiddenSettingsDefault
);
if ( Object.keys(modifiedHiddenSettings).length === 0 ) {
modifiedHiddenSettings = 'none';
}

let filterset = [];
const userFilters = await µb.loadUserFilters();
for ( const line of userFilters.content.split(/\s*\n+\s*/) ) {
if ( /^($|![^#])/.test(line) ) { continue; }
filterset.push(line);
}
if ( filterset.length === 0 ) {
filterset = undefined;
}

const lists = await io.metadata();
let defaultListset = {};
let addedListset = {};
let removedListset = {};
for ( const listKey in lists ) {
if ( lists.hasOwnProperty(listKey) === false ) { continue; }
const list = lists[listKey];
if ( list.content !== 'filters' ) { continue; }
const daysSinceUpdated = Math.floor((
Date.now() -
list.writeTime
) / 864000) / 100;
const daysBeforeNextUpdate = Math.floor((
list.writeTime +
list.updateAfter * 86400000 -
Date.now()
) / 864000) / 100;
const listDetails = {
title: list.title,
daysSinceUpdated,
daysBeforeNextUpdate,
};
const used = µb.selectedFilterLists.includes(listKey);
if ( list.isDefault ) {
if ( used ) {
defaultListset[listKey] = listDetails;
} else {
removedListset[listKey] = null;
}
} else if ( used ) {
addedListset[listKey] = listDetails;
}
}
if ( Object.keys(defaultListset).length === 0 ) {
defaultListset = undefined;
}
if ( Object.keys(addedListset).length === 0 ) {
addedListset = undefined;
}
if ( Object.keys(removedListset).length === 0 ) {
removedListset = undefined;
}

return {
browserFlavor: Array.from(vAPI.webextFlavor.soup).join(' '),
browserVersion: vAPI.webextFlavor.major,
extensionId: vAPI.i18n('@@extension_id'),
extensionName: vAPI.app.name,
extensionVersion: vAPI.app.version,
modifiedUserSettings,
modifiedHiddenSettings,
listset: {
'default': defaultListset,
added: addedListset,
removed: removedListset,
},
filterset,
trustedset: diffArrays(
µb.arrayFromWhitelist(µb.netWhitelist),
µb.netWhitelistDefault
),
hostRuleset: diffArrays(
sessionFirewall.toArray(),
µb.dynamicFilteringDefault
),
switchRuleset: diffArrays(
sessionSwitches.toArray(),
µb.hostnameSwitchesDefault
),
urlRuleset: diffArrays(
sessionURLFiltering.toArray(),
[]
),
};
};

const onMessage = function(request, sender, callback) {
// Async
switch ( request.what ) {
Expand All @@ -1223,6 +1353,13 @@ const onMessage = function(request, sender, callback) {
case 'getShortcuts':
return getShortcuts(callback);

case 'getSupportData': {
getSupportData().then(response => {
callback(response);
});
return;
}

case 'readUserFilters':
return µb.loadUserFilters().then(result => {
callback(result);
Expand Down
14 changes: 2 additions & 12 deletions src/js/start.js
Original file line number Diff line number Diff line change
Expand Up @@ -353,19 +353,9 @@ const fromFetch = function(to, fetched) {

const createDefaultProps = function() {
const fetchableProps = {
'dynamicFilteringString': [
'behind-the-scene * * noop',
'behind-the-scene * image noop',
'behind-the-scene * 3p noop',
'behind-the-scene * inline-script noop',
'behind-the-scene * 1p-script noop',
'behind-the-scene * 3p-script noop',
'behind-the-scene * 3p-frame noop',
].join('\n'),
'dynamicFilteringString': µb.dynamicFilteringDefault.join('\n'),
'urlFilteringString': '',
'hostnameSwitchesString': [
'no-large-media: behind-the-scene false',
].join('\n'),
'hostnameSwitchesString': µb.hostnameSwitchesDefault.join('\n'),
'lastRestoreFile': '',
'lastRestoreTime': 0,
'lastBackupFile': '',
Expand Down
43 changes: 43 additions & 0 deletions src/js/support.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*******************************************************************************
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
*/

/* global CodeMirror, uBlockDashboard */

'use strict';

/******************************************************************************/

(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', {
what: 'getSupportData',
});

cmEditor.setValue(JSON.stringify(supportData, null, 2));
})();
Loading

0 comments on commit a3a43c7

Please sign in to comment.