1
0
mirror of https://github.com/gorhill/uBlock.git synced 2024-07-08 12:57:57 +02:00

Work toward modernizing code base: promisification

Swathes of code have been converted to use
Promises/async/await.

Related commits:
- 26235d80d0
- 0051f3b5c7
- eec53c0154
- 915687fddb
- 55cc0c6997
- e27328f931
This commit is contained in:
Raymond Hill 2019-09-17 15:15:01 -04:00
parent 26235d80d0
commit 3224d9b5cc
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
26 changed files with 883 additions and 1099 deletions

View File

@ -137,10 +137,10 @@ vAPI.messaging = {
// Response to specific message previously sent
if ( details.auxProcessId ) {
const listener = this.pending.get(details.auxProcessId);
if ( listener !== undefined ) {
const resolver = this.pending.get(details.auxProcessId);
if ( resolver !== undefined ) {
this.pending.delete(details.auxProcessId);
listener(details.msg);
resolver(details.msg);
return;
}
}
@ -222,10 +222,8 @@ vAPI.messaging = {
if ( this.pending.size !== 0 ) {
const pending = this.pending;
this.pending = new Map();
for ( const callback of pending.values() ) {
if ( typeof callback === 'function' ) {
callback(null);
}
for ( const resolver of pending.values() ) {
resolver();
}
}
},
@ -264,7 +262,7 @@ vAPI.messaging = {
return this.port !== null ? this.port : this.createPort();
},
send: function(channelName, message, callback) {
send: function(channelName, msg) {
// Too large a gap between the last request and the last response means
// the main process is no longer reachable: memory leaks and bad
// performance become a risk -- especially for long-lived, dynamic
@ -274,19 +272,14 @@ vAPI.messaging = {
}
const port = this.getPort();
if ( port === null ) {
if ( typeof callback === 'function' ) { callback(); }
return;
return Promise.resolve();
}
let auxProcessId;
if ( callback ) {
auxProcessId = this.auxProcessId++;
this.pending.set(auxProcessId, callback);
}
port.postMessage({
channelName: channelName,
auxProcessId: auxProcessId,
msg: message
const auxProcessId = this.auxProcessId++;
const promise = new Promise(resolve => {
this.pending.set(auxProcessId, resolve);
});
port.postMessage({ channelName, auxProcessId, msg });
return promise;
},
connectTo: function(from, to, handler) {

View File

@ -38,8 +38,11 @@ vAPI.userStylesheet = {
vAPI.messaging.send('vapi', {
what: 'userCSS',
add: Array.from(this.added),
remove: Array.from(this.removed)
}, callback);
remove: Array.from(this.removed),
}).then(( ) => {
if ( callback instanceof Function === false ) { return; }
callback();
});
this.added.clear();
this.removed.clear();
},

View File

@ -29,14 +29,13 @@
/******************************************************************************/
const messaging = vAPI.messaging;
const cmEditor = new CodeMirror(
document.getElementById('userFilters'),
{
autofocus: true,
lineNumbers: true,
lineWrapping: true,
styleActiveLine: true
styleActiveLine: true,
}
);
@ -72,30 +71,31 @@ const userFiltersChanged = function(changed) {
/******************************************************************************/
const renderUserFilters = function(first) {
const onRead = function(details) {
if ( details.error ) { return; }
let content = details.content.trim();
cachedUserFilters = content;
if ( content.length !== 0 ) {
content += '\n';
}
cmEditor.setValue(content);
if ( first ) {
cmEditor.clearHistory();
try {
const line = JSON.parse(
vAPI.localStorage.getItem('myFiltersCursorPosition')
);
if ( typeof line === 'number' ) {
cmEditor.setCursor(line, 0);
}
} catch(ex) {
const renderUserFilters = async function(first) {
const details = await vAPI.messaging.send('dashboard', {
what: 'readUserFilters',
});
if ( details instanceof Object === false || details.error ) { return; }
let content = details.content.trim();
cachedUserFilters = content;
if ( content.length !== 0 ) {
content += '\n';
}
cmEditor.setValue(content);
if ( first ) {
cmEditor.clearHistory();
try {
const line = JSON.parse(
vAPI.localStorage.getItem('myFiltersCursorPosition')
);
if ( typeof line === 'number' ) {
cmEditor.setCursor(line, 0);
}
} catch(ex) {
}
userFiltersChanged(false);
};
messaging.send('dashboard', { what: 'readUserFilters' }, onRead);
}
userFiltersChanged(false);
};
/******************************************************************************/
@ -170,20 +170,18 @@ const exportUserFiltersToFile = function() {
/******************************************************************************/
const applyChanges = function() {
messaging.send(
'dashboard',
{
what: 'writeUserFilters',
content: cmEditor.getValue()
},
details => {
if ( details.error ) { return; }
cachedUserFilters = details.content.trim();
userFiltersChanged(false);
messaging.send('dashboard', { what: 'reloadAllFilters' });
}
);
const applyChanges = async function() {
const details = await vAPI.messaging.send('dashboard', {
what: 'writeUserFilters',
content: cmEditor.getValue(),
});
if ( details instanceof Object === false || details.error ) { return; }
cachedUserFilters = details.content.trim();
userFiltersChanged(false);
vAPI.messaging.send('dashboard', {
what: 'reloadAllFilters',
});
};
const revertChanges = function() {
@ -223,7 +221,7 @@ self.hasUnsavedData = function() {
uDom('#importUserFiltersFromFile').on('click', startImportFilePicker);
uDom('#importFilePicker').on('change', handleImportFilePicker);
uDom('#exportUserFiltersToFile').on('click', exportUserFiltersToFile);
uDom('#userFiltersApply').on('click', applyChanges);
uDom('#userFiltersApply').on('click', ( ) => { applyChanges(); });
uDom('#userFiltersRevert').on('click', revertChanges);
renderUserFilters(true);

View File

@ -306,7 +306,11 @@ const renderFilterLists = function(soft) {
renderWidgets();
};
messaging.send('dashboard', { what: 'getLists' }, onListsReceived);
messaging.send('dashboard', {
what: 'getLists',
}).then(details => {
onListsReceived(details);
});
};
/******************************************************************************/
@ -402,7 +406,10 @@ const onPurgeClicked = function(ev) {
const listKey = liEntry.attr('data-listkey');
if ( !listKey ) { return; }
messaging.send('dashboard', { what: 'purgeCache', assetKey: listKey });
messaging.send('dashboard', {
what: 'purgeCache',
assetKey: listKey,
});
// If the cached version is purged, the installed version must be assumed
// to be obsolete.
@ -419,17 +426,17 @@ const onPurgeClicked = function(ev) {
/******************************************************************************/
const selectFilterLists = function(callback) {
const selectFilterLists = async function() {
// Cosmetic filtering switch
messaging.send('dashboard', {
what: 'userSettings',
name: 'parseAllABPHideFilters',
value: document.getElementById('parseCosmeticFilters').checked
value: document.getElementById('parseCosmeticFilters').checked,
});
messaging.send('dashboard', {
what: 'userSettings',
name: 'ignoreGenericCosmeticFilters',
value: document.getElementById('ignoreGenericCosmeticFilters').checked
value: document.getElementById('ignoreGenericCosmeticFilters').checked,
});
// Filter lists to select
@ -454,67 +461,53 @@ const selectFilterLists = function(callback) {
externalListsElem.value = '';
uDom.nodeFromId('importLists').checked = false;
messaging.send(
'dashboard',
{
what: 'applyFilterListSelection',
toSelect: toSelect,
toImport: toImport,
toRemove: toRemove
},
callback
);
await messaging.send('dashboard', {
what: 'applyFilterListSelection',
toSelect: toSelect,
toImport: toImport,
toRemove: toRemove,
});
filteringSettingsHash = hashFromCurrentFromSettings();
};
/******************************************************************************/
const buttonApplyHandler = function() {
const buttonApplyHandler = async function() {
uDom('#buttonApply').removeClass('enabled');
selectFilterLists(( ) => {
messaging.send('dashboard', { what: 'reloadAllFilters' });
});
renderWidgets();
await selectFilterLists();
messaging.send('dashboard', { what: 'reloadAllFilters' });
};
/******************************************************************************/
const buttonUpdateHandler = function() {
selectFilterLists(( ) => {
document.body.classList.add('updating');
messaging.send('dashboard', { what: 'forceUpdateAssets' });
renderWidgets();
});
const buttonUpdateHandler = async function() {
await selectFilterLists();
document.body.classList.add('updating');
renderWidgets();
messaging.send('dashboard', { what: 'forceUpdateAssets' });
};
/******************************************************************************/
const buttonPurgeAllHandler = function(ev) {
const buttonPurgeAllHandler = async function(hard) {
uDom('#buttonPurgeAll').removeClass('enabled');
messaging.send(
'dashboard',
{
what: 'purgeAllCaches',
hard: ev.ctrlKey && ev.shiftKey
},
( ) => {
renderFilterLists(true);
}
);
await messaging.send('dashboard', {
what: 'purgeAllCaches',
hard,
});
renderFilterLists(true);
};
/******************************************************************************/
const autoUpdateCheckboxChanged = function() {
messaging.send(
'dashboard',
{
what: 'userSettings',
name: 'autoUpdate',
value: this.checked
}
);
messaging.send('dashboard', {
what: 'userSettings',
name: 'autoUpdate',
value: this.checked,
});
};
/******************************************************************************/
@ -675,9 +668,11 @@ self.hasUnsavedData = function() {
uDom('#autoUpdate').on('change', autoUpdateCheckboxChanged);
uDom('#parseCosmeticFilters').on('change', onFilteringSettingsChanged);
uDom('#ignoreGenericCosmeticFilters').on('change', onFilteringSettingsChanged);
uDom('#buttonApply').on('click', buttonApplyHandler);
uDom('#buttonUpdate').on('click', buttonUpdateHandler);
uDom('#buttonPurgeAll').on('click', buttonPurgeAllHandler);
uDom('#buttonApply').on('click', ( ) => { buttonApplyHandler(); });
uDom('#buttonUpdate').on('click', ( ) => { buttonUpdateHandler(); });
uDom('#buttonPurgeAll').on('click', ev => {
buttonPurgeAllHandler(ev.ctrlKey && ev.shiftKey);
});
uDom('#lists').on('change', '.listEntry > input', onFilteringSettingsChanged);
uDom('#lists').on('click', '.listEntry > a.remove', onRemoveExternalList);
uDom('#lists').on('click', 'span.cache', onPurgeClicked);

View File

@ -1,7 +1,7 @@
/*******************************************************************************
uBlock Origin - a browser extension to block requests.
Copyright (C) 2014-2016 Raymond Hill
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
@ -25,12 +25,7 @@
/******************************************************************************/
(( ) => {
vAPI.messaging.send('dashboard', { what: 'getAppData' }, appData => {
uDom('#aboutNameVer').text(appData.name + ' v' + appData.version);
});
(async ( ) => {
document.querySelector(
'[href="logger-ui.html"]'
).addEventListener(
@ -38,4 +33,8 @@
self.uBlockDashboard.openOrSelectPage
);
const appData = await vAPI.messaging.send('dashboard', {
what: 'getAppData',
});
uDom('#aboutNameVer').text(appData.name + ' v' + appData.version);
})();

View File

@ -25,12 +25,11 @@
/******************************************************************************/
(function() {
(( ) => {
// >>>> Start of private namespace
/******************************************************************************/
const messaging = vAPI.messaging;
const noopFunc = function(){};
let beforeHash = '';
@ -57,18 +56,19 @@ const hashFromAdvancedSettings = function(raw) {
// This is to give a visual hint that the content of user blacklist has changed.
const advancedSettingsChanged = (function () {
let timer = null;
const advancedSettingsChanged = (( ) => {
let timer;
const handler = ( ) => {
timer = null;
let changed = hashFromAdvancedSettings(cmEditor.getValue()) !== beforeHash;
timer = undefined;
const changed =
hashFromAdvancedSettings(cmEditor.getValue()) !== beforeHash;
uDom.nodeFromId('advancedSettingsApply').disabled = !changed;
CodeMirror.commands.save = changed ? applyChanges : noopFunc;
};
return function() {
if ( timer !== null ) { clearTimeout(timer); }
if ( timer !== undefined ) { clearTimeout(timer); }
timer = vAPI.setTimeout(handler, 100);
};
})();
@ -77,42 +77,40 @@ cmEditor.on('changes', advancedSettingsChanged);
/******************************************************************************/
const renderAdvancedSettings = function(first) {
const onRead = function(raw) {
beforeHash = hashFromAdvancedSettings(raw);
let pretty = [],
whitespaces = ' ',
lines = raw.split('\n'),
max = 0;
for ( let line of lines ) {
let pos = line.indexOf(' ');
if ( pos > max ) { max = pos; }
}
for ( let line of lines ) {
let pos = line.indexOf(' ');
pretty.push(whitespaces.slice(0, max - pos) + line);
}
cmEditor.setValue(pretty.join('\n') + '\n');
if ( first ) {
cmEditor.clearHistory();
}
advancedSettingsChanged();
cmEditor.focus();
};
messaging.send('dashboard', { what: 'readHiddenSettings' }, onRead);
const renderAdvancedSettings = async function(first) {
const raw = await vAPI.messaging.send('dashboard', {
what: 'readHiddenSettings',
});
beforeHash = hashFromAdvancedSettings(raw);
let pretty = [],
whitespaces = ' ',
lines = raw.split('\n'),
max = 0;
for ( let line of lines ) {
let pos = line.indexOf(' ');
if ( pos > max ) { max = pos; }
}
for ( let line of lines ) {
let pos = line.indexOf(' ');
pretty.push(whitespaces.slice(0, max - pos) + line);
}
cmEditor.setValue(pretty.join('\n') + '\n');
if ( first ) {
cmEditor.clearHistory();
}
advancedSettingsChanged();
cmEditor.focus();
};
/******************************************************************************/
const applyChanges = function() {
messaging.send(
'dashboard',
{
what: 'writeHiddenSettings',
content: cmEditor.getValue()
},
renderAdvancedSettings
);
const applyChanges = async function() {
await vAPI.messaging.send('dashboard', {
what: 'writeHiddenSettings',
content: cmEditor.getValue(),
});
renderAdvancedSettings();
};
/******************************************************************************/
@ -121,10 +119,9 @@ uDom.nodeFromId('advancedSettings').addEventListener(
'input',
advancedSettingsChanged
);
uDom.nodeFromId('advancedSettingsApply').addEventListener(
'click',
applyChanges
);
uDom.nodeFromId('advancedSettingsApply').addEventListener('click', ( ) => {
applyChanges();
});
renderAdvancedSettings(true);

View File

@ -25,27 +25,11 @@
/******************************************************************************/
(( ) => {
(async ( ) => {
const params = new URL(document.location).searchParams;
const assetKey = params.get('url');
if ( assetKey === null ) { return; }
vAPI.messaging.send(
'default',
{
what : 'getAssetContent',
url: assetKey,
},
details => {
cmEditor.setValue(details && details.content || '');
if ( details.sourceURL ) {
const a = document.querySelector('.cm-search-widget .sourceURL');
a.setAttribute('href', details.sourceURL);
a.setAttribute('title', details.sourceURL);
}
}
);
const cmEditor = new CodeMirror(
document.getElementById('content'),
{
@ -58,4 +42,15 @@
);
uBlockDashboard.patchCodeMirrorEditor(cmEditor);
const details = await vAPI.messaging.send('default', {
what : 'getAssetContent',
url: assetKey,
});
cmEditor.setValue(details && details.content || '');
if ( details.sourceURL ) {
const a = document.querySelector('.cm-search-widget .sourceURL');
a.setAttribute('href', details.sourceURL);
a.setAttribute('title', details.sourceURL);
}
})();

View File

@ -21,11 +21,11 @@
/* global uDom */
'use strict';
/******************************************************************************/
(function() {
'use strict';
(( ) => {
/******************************************************************************/
@ -39,31 +39,27 @@ self.cloud = {
/******************************************************************************/
var widget = uDom.nodeFromId('cloudWidget');
if ( widget === null ) {
return;
}
const widget = uDom.nodeFromId('cloudWidget');
if ( widget === null ) { return; }
self.cloud.datakey = widget.getAttribute('data-cloud-entry') || '';
if ( self.cloud.datakey === '' ) {
return;
}
var messaging = vAPI.messaging;
if ( self.cloud.datakey === '' ) { return; }
/******************************************************************************/
var onCloudDataReceived = function(entry) {
if ( entry instanceof Object === false ) {
return;
}
const fetchCloudData = async function() {
const entry = await vAPI.messaging.send('cloudWidget', {
what: 'cloudPull',
datakey: self.cloud.datakey,
});
if ( entry instanceof Object === false ) { return; }
self.cloud.data = entry.data;
uDom.nodeFromId('cloudPull').removeAttribute('disabled');
uDom.nodeFromId('cloudPullAndMerge').removeAttribute('disabled');
var timeOptions = {
const timeOptions = {
weekday: 'short',
year: 'numeric',
month: 'short',
@ -74,7 +70,7 @@ var onCloudDataReceived = function(entry) {
timeZoneName: 'short'
};
var time = new Date(entry.tstamp);
const time = new Date(entry.tstamp);
widget.querySelector('#cloudInfo').textContent =
entry.source + '\n' +
time.toLocaleString('fullwide', timeOptions);
@ -82,40 +78,21 @@ var onCloudDataReceived = function(entry) {
/******************************************************************************/
var fetchCloudData = function() {
messaging.send(
'cloudWidget',
{
what: 'cloudPull',
datakey: self.cloud.datakey
},
onCloudDataReceived
);
};
const pushData = async function() {
if ( typeof self.cloud.onPush !== 'function' ) { return; }
/******************************************************************************/
var pushData = function() {
if ( typeof self.cloud.onPush !== 'function' ) {
return;
}
messaging.send(
'cloudWidget',
{
what: 'cloudPush',
datakey: self.cloud.datakey,
data: self.cloud.onPush()
},
function(error) {
var failed = typeof error === 'string';
document.getElementById('cloudPush')
.classList
.toggle('error', failed);
document.querySelector('#cloudError')
.textContent = failed ? error : '';
fetchCloudData();
}
);
const error = await vAPI.messaging.send('cloudWidget', {
what: 'cloudPush',
datakey: self.cloud.datakey,
data: self.cloud.onPush(),
});
const failed = typeof error === 'string';
document.getElementById('cloudPush')
.classList
.toggle('error', failed);
document.querySelector('#cloudError')
.textContent = failed ? error : '';
fetchCloudData();
};
/******************************************************************************/
@ -155,46 +132,34 @@ var closeOptions = function(ev) {
/******************************************************************************/
var submitOptions = function() {
var onOptions = function(options) {
if ( options instanceof Object === false ) {
return;
}
self.cloud.options = options;
};
messaging.send(
'cloudWidget',
{
what: 'cloudSetOptions',
options: {
deviceName: uDom.nodeFromId('cloudDeviceName').value
}
},
onOptions
);
const submitOptions = async function() {
uDom.nodeFromId('cloudOptions').classList.remove('show');
const options = await vAPI.messaging.send('cloudWidget', {
what: 'cloudSetOptions',
options: {
deviceName: uDom.nodeFromId('cloudDeviceName').value
},
});
if ( options instanceof Object ) {
self.cloud.options = options;
}
};
/******************************************************************************/
var onInitialize = function(options) {
if ( typeof options !== 'object' || options === null ) {
return;
}
if ( !options.enabled ) {
return;
}
const onInitialize = function(options) {
if ( options instanceof Object === false ) { return; }
if ( !options.enabled ) { return; }
self.cloud.options = options;
var xhr = new XMLHttpRequest();
const xhr = new XMLHttpRequest();
xhr.open('GET', 'cloud-ui.html', true);
xhr.overrideMimeType('text/html;charset=utf-8');
xhr.responseType = 'text';
xhr.onload = function() {
this.onload = null;
var parser = new DOMParser(),
const parser = new DOMParser(),
parsed = parser.parseFromString(this.responseText, 'text/html'),
fromParent = parsed.body;
while ( fromParent.firstElementChild !== null ) {
@ -206,12 +171,12 @@ var onInitialize = function(options) {
vAPI.i18n.render(widget);
widget.classList.remove('hide');
uDom('#cloudPush').on('click', pushData);
uDom('#cloudPush').on('click', ( ) => { pushData(); });
uDom('#cloudPull').on('click', pullData);
uDom('#cloudPullAndMerge').on('click', pullAndMergeData);
uDom('#cloudCog').on('click', openOptions);
uDom('#cloudOptions').on('click', closeOptions);
uDom('#cloudOptionsSubmit').on('click', submitOptions);
uDom('#cloudOptionsSubmit').on('click', ( ) => { submitOptions(); });
// Patch 2018-01-05: Must not assume this XHR will always be faster
// than messaging
@ -220,10 +185,12 @@ var onInitialize = function(options) {
xhr.send();
};
messaging.send('cloudWidget', { what: 'cloudGetOptions' }, onInitialize);
vAPI.messaging.send('cloudWidget', {
what: 'cloudGetOptions',
}).then(options => {
onInitialize(options);
});
/******************************************************************************/
// https://www.youtube.com/watch?v=aQFp67VoiDA
})();

View File

@ -207,19 +207,15 @@ vAPI.SafeAnimationFrame.prototype = {
let timer;
const send = function() {
vAPI.messaging.send(
'scriptlets',
{
what: 'securityPolicyViolation',
type: 'net',
docURL: document.location.href,
violations: Array.from(newEvents),
},
response => {
if ( response === true ) { return; }
stop();
}
);
vAPI.messaging.send('scriptlets', {
what: 'securityPolicyViolation',
type: 'net',
docURL: document.location.href,
violations: Array.from(newEvents),
}).then(response => {
if ( response === true ) { return; }
stop();
});
for ( const event of newEvents ) {
allEvents.add(event);
}
@ -230,7 +226,7 @@ vAPI.SafeAnimationFrame.prototype = {
if ( timer !== undefined ) { return; }
timer = self.requestIdleCallback(
( ) => { timer = undefined; send(); },
{ timeout: 2000 }
{ timeout: 2063 }
);
};
@ -908,7 +904,8 @@ vAPI.domCollapser = (function() {
// https://github.com/chrisaljoudi/uBlock/issues/174
// Do not remove fragment from src URL
const onProcessed = function(response) {
if ( !response ) { // This happens if uBO is disabled or restarted.
// This happens if uBO is disabled or restarted.
if ( response instanceof Object === false ) {
toCollapse.clear();
return;
}
@ -964,29 +961,27 @@ vAPI.domCollapser = (function() {
}
if ( selectors.length !== 0 ) {
messaging.send(
'contentscript',
{
what: 'cosmeticFiltersInjected',
type: 'net',
hostname: window.location.hostname,
selectors: selectors
}
);
messaging.send('contentscript', {
what: 'cosmeticFiltersInjected',
type: 'net',
hostname: window.location.hostname,
selectors,
});
}
};
const send = function() {
processTimer = undefined;
toCollapse.set(resquestIdGenerator, toProcess);
const msg = {
messaging.send('contentscript', {
what: 'getCollapsibleBlockedRequests',
id: resquestIdGenerator,
frameURL: window.location.href,
resources: toFilter,
hash: cachedBlockedSetHash
};
messaging.send('contentscript', msg, onProcessed);
hash: cachedBlockedSetHash,
}).then(response => {
onProcessed(response);
});
toProcess = [];
toFilter = [];
resquestIdGenerator += 1;
@ -1256,18 +1251,16 @@ vAPI.domSurveyor = (function() {
//console.info(`domSurveyor> Surveyed ${processed} nodes in ${(t1-t0).toFixed(2)} ms`);
// Phase 2: Ask main process to lookup relevant cosmetic filters.
if ( ids.length !== 0 || classes.length !== 0 ) {
messaging.send(
'contentscript',
{
what: 'retrieveGenericCosmeticSelectors',
hostname: hostname,
ids: ids,
classes: classes,
exceptions: domFilterer.exceptions,
cost: surveyCost
},
surveyPhase3
);
messaging.send('contentscript', {
what: 'retrieveGenericCosmeticSelectors',
hostname,
ids,
classes,
exceptions: domFilterer.exceptions,
cost: surveyCost,
}).then(response => {
surveyPhase3(response);
});
} else {
surveyPhase3(null);
}
@ -1408,10 +1401,9 @@ vAPI.bootstrap = (function() {
if ( window.location === null ) { return; }
if ( vAPI instanceof Object === false ) { return; }
vAPI.messaging.send(
'contentscript',
{ what: 'shouldRenderNoscriptTags' }
);
vAPI.messaging.send('contentscript', {
what: 'shouldRenderNoscriptTags',
});
if ( vAPI.domWatcher instanceof Object ) {
vAPI.domWatcher.start();
@ -1437,15 +1429,12 @@ vAPI.bootstrap = (function() {
while ( elem !== null && elem.localName !== 'a' ) {
elem = elem.parentElement;
}
vAPI.messaging.send(
'contentscript',
{
what: 'mouseClick',
x: ev.clientX,
y: ev.clientY,
url: elem !== null && ev.isTrusted !== false ? elem.href : ''
}
);
vAPI.messaging.send('contentscript', {
what: 'mouseClick',
x: ev.clientX,
y: ev.clientY,
url: elem !== null && ev.isTrusted !== false ? elem.href : '',
});
};
document.addEventListener('mousedown', onMouseClick, true);
@ -1546,16 +1535,14 @@ vAPI.bootstrap = (function() {
};
return function() {
vAPI.messaging.send(
'contentscript',
{
what: 'retrieveContentScriptParameters',
url: window.location.href,
isRootFrame: window === window.top,
charset: document.characterSet,
},
bootstrapPhase1
);
vAPI.messaging.send('contentscript', {
what: 'retrieveContentScriptParameters',
url: window.location.href,
isRootFrame: window === window.top,
charset: document.characterSet,
}).then(response => {
bootstrapPhase1(response);
});
};
})();

View File

@ -225,7 +225,10 @@ self.uBlockDashboard.openOrSelectPage = function(url, options = {}) {
url = ev.target.getAttribute('href');
}
const details = Object.assign({ url, select: true, index: -1 }, options);
vAPI.messaging.send('default', { what: 'gotoURL', details });
vAPI.messaging.send('default', {
what: 'gotoURL',
details,
});
if ( ev ) {
ev.preventDefault();
}

View File

@ -115,7 +115,9 @@ const onTabClickHandler = function(ev) {
};
// https://github.com/uBlockOrigin/uBlock-issues/issues/106
vAPI.messaging.send('dashboard', { what: 'canUpdateShortcuts' }, response => {
vAPI.messaging.send('dashboard', {
what: 'canUpdateShortcuts',
}).then(response => {
document.body.classList.toggle('canUpdateShortcuts', response === true);
});

View File

@ -41,44 +41,42 @@ let details = {};
/******************************************************************************/
messaging.send(
'documentBlocked',
{
(async ( ) => {
const response = await messaging.send('documentBlocked', {
what: 'listsFromNetFilter',
compiledFilter: details.fc,
rawFilter: details.fs
},
response => {
if ( response instanceof Object === false ) { return; }
rawFilter: details.fs,
});
if ( response instanceof Object === false ) { return; }
let lists;
for ( const rawFilter in response ) {
if ( response.hasOwnProperty(rawFilter) === false ) { continue; }
let lists;
for ( const rawFilter in response ) {
if ( response.hasOwnProperty(rawFilter) ) {
lists = response[rawFilter];
break;
}
if ( Array.isArray(lists) === false || lists.length === 0 ) { return; }
const parent = uDom.nodeFromSelector('#whyex > span:nth-of-type(2)');
for ( const list of lists ) {
const elem = document.querySelector('#templates .filterList')
.cloneNode(true);
const source = elem.querySelector('.filterListSource');
source.href += encodeURIComponent(list.assetKey);
source.textContent = list.title;
if (
typeof list.supportURL === 'string' &&
list.supportURL !== ''
) {
elem.querySelector('.filterListSupport')
.setAttribute('href', list.supportURL);
}
parent.appendChild(elem);
}
uDom.nodeFromId('whyex').style.removeProperty('display');
}
);
if ( Array.isArray(lists) === false || lists.length === 0 ) { return; }
const parent = uDom.nodeFromSelector('#whyex > span:nth-of-type(2)');
for ( const list of lists ) {
const elem = document.querySelector('#templates .filterList')
.cloneNode(true);
const source = elem.querySelector('.filterListSource');
source.href += encodeURIComponent(list.assetKey);
source.textContent = list.title;
if (
typeof list.supportURL === 'string' &&
list.supportURL !== ''
) {
elem.querySelector('.filterListSupport')
.setAttribute('href', list.supportURL);
}
parent.appendChild(elem);
}
uDom.nodeFromId('whyex').style.removeProperty('display');
})();
/******************************************************************************/
@ -219,10 +217,9 @@ if ( window.history.length > 1 ) {
uDom('#bye').on(
'click',
( ) => {
messaging.send(
'documentBlocked',
{ what: 'closeThisTab', }
);
messaging.send('documentBlocked', {
what: 'closeThisTab',
});
}
);
uDom('#back').css('display', 'none');
@ -240,30 +237,24 @@ const proceedToURL = function() {
window.location.replace(details.url);
};
const proceedTemporary = function() {
messaging.send(
'documentBlocked',
{
what: 'temporarilyWhitelistDocument',
hostname: getTargetHostname()
},
proceedToURL
);
const proceedTemporary = async function() {
await messaging.send('documentBlocked', {
what: 'temporarilyWhitelistDocument',
hostname: getTargetHostname(),
});
proceedToURL();
};
const proceedPermanent = function() {
messaging.send(
'documentBlocked',
{
what: 'toggleHostnameSwitch',
name: 'no-strict-blocking',
hostname: getTargetHostname(),
deep: true,
state: true,
persist: true
},
proceedToURL
);
const proceedPermanent = async function() {
await messaging.send('documentBlocked', {
what: 'toggleHostnameSwitch',
name: 'no-strict-blocking',
hostname: getTargetHostname(),
deep: true,
state: true,
persist: true,
});
proceedToURL();
};
uDom('#proceedTemporary').attr('href', details.url).on('click', proceedTemporary);

View File

@ -29,8 +29,6 @@
/******************************************************************************/
const messaging = vAPI.messaging;
const mergeView = new CodeMirror.MergeView(
document.querySelector('.codeMirrorMergeContainer'),
{
@ -105,7 +103,7 @@ let differ;
const updateOverlay = (function() {
let reFilter;
let mode = {
const mode = {
token: function(stream) {
if ( reFilter !== undefined ) {
reFilter.lastIndex = stream.pos;
@ -190,8 +188,8 @@ const rulesToDoc = function(clearHistory) {
/******************************************************************************/
const filterRules = function(key) {
const filter = uDom.nodeFromSelector('#ruleFilter input').value;
let rules = unfilteredRules[key].rules;
let filter = uDom.nodeFromSelector('#ruleFilter input').value;
if ( filter !== '' ) {
rules = rules.slice();
let i = rules.length;
@ -235,17 +233,14 @@ const renderRules = (( ) => {
/******************************************************************************/
const applyDiff = function(permanent, toAdd, toRemove) {
messaging.send(
'dashboard',
{
what: 'modifyRuleset',
permanent: permanent,
toAdd: toAdd,
toRemove: toRemove
},
renderRules
);
const applyDiff = async function(permanent, toAdd, toRemove) {
const details = await vAPI.messaging.send('dashboard', {
what: 'modifyRuleset',
permanent: permanent,
toAdd: toAdd,
toRemove: toRemove,
});
renderRules(details);
};
/******************************************************************************/
@ -266,13 +261,13 @@ mergeView.options.revertChunk = function(
}
if ( typeof fromStart.ch !== 'number' ) { fromStart.ch = 0; }
if ( fromEnd.ch !== 0 ) { fromEnd.line += 1; }
let toAdd = from.getRange(
const toAdd = from.getRange(
{ line: fromStart.line, ch: 0 },
{ line: fromEnd.line, ch: 0 }
);
if ( typeof toStart.ch !== 'number' ) { toStart.ch = 0; }
if ( toEnd.ch !== 0 ) { toEnd.line += 1; }
let toRemove = to.getRange(
const toRemove = to.getRange(
{ line: toStart.line, ch: 0 },
{ line: toEnd.line, ch: 0 }
);
@ -282,7 +277,7 @@ mergeView.options.revertChunk = function(
/******************************************************************************/
function handleImportFilePicker() {
let fileReaderOnLoadHandler = function() {
const fileReaderOnLoadHandler = function() {
if ( typeof this.result !== 'string' || this.result === '' ) { return; }
// https://github.com/chrisaljoudi/uBlock/issues/757
// Support RequestPolicy rule syntax
@ -295,10 +290,10 @@ function handleImportFilePicker() {
}
applyDiff(false, result, '');
};
let file = this.files[0];
const file = this.files[0];
if ( file === undefined || file.name === '' ) { return; }
if ( file.type.indexOf('text') !== 0 ) { return; }
let fr = new FileReader();
const fr = new FileReader();
fr.onload = fileReaderOnLoadHandler;
fr.readAsText(file);
}
@ -306,7 +301,7 @@ function handleImportFilePicker() {
/******************************************************************************/
const startImportFilePicker = function() {
let input = document.getElementById('importFilePicker');
const input = document.getElementById('importFilePicker');
// Reset to empty string, this will ensure an change event is properly
// triggered if the user pick a file, even if it is the same as the last
// one picked.
@ -317,7 +312,7 @@ const startImportFilePicker = function() {
/******************************************************************************/
function exportUserRulesToFile() {
let filename = vAPI.i18n('rulesDefaultFileName')
const filename = vAPI.i18n('rulesDefaultFileName')
.replace('{{datetime}}', uBlockDashboard.dateNowToSensibleString())
.replace(/ +/g, '_');
vAPI.download({
@ -339,7 +334,7 @@ const onFilterChanged = (function() {
const process = function() {
timer = undefined;
if ( mergeView.editor().isClean(cleanEditToken) === false ) { return; }
let filter = uDom.nodeFromSelector('#ruleFilter input').value;
const filter = uDom.nodeFromSelector('#ruleFilter input').value;
if ( filter === last ) { return; }
last = filter;
if ( overlay !== null ) {
@ -401,15 +396,15 @@ const onTextChanged = (( ) => {
/******************************************************************************/
const revertAllHandler = function() {
let toAdd = [], toRemove = [];
let left = mergeView.leftOriginal(),
edit = mergeView.editor();
for ( let chunk of mergeView.leftChunks() ) {
let addedLines = left.getRange(
const toAdd = [], toRemove = [];
const left = mergeView.leftOriginal();
const edit = mergeView.editor();
for ( const chunk of mergeView.leftChunks() ) {
const addedLines = left.getRange(
{ line: chunk.origFrom, ch: 0 },
{ line: chunk.origTo, ch: 0 }
);
let removedLines = edit.getRange(
const removedLines = edit.getRange(
{ line: chunk.editFrom, ch: 0 },
{ line: chunk.editTo, ch: 0 }
);
@ -422,15 +417,15 @@ const revertAllHandler = function() {
/******************************************************************************/
const commitAllHandler = function() {
let toAdd = [], toRemove = [];
let left = mergeView.leftOriginal(),
edit = mergeView.editor();
for ( let chunk of mergeView.leftChunks() ) {
let addedLines = edit.getRange(
const toAdd = [], toRemove = [];
const left = mergeView.leftOriginal();
const edit = mergeView.editor();
for ( const chunk of mergeView.leftChunks() ) {
const addedLines = edit.getRange(
{ line: chunk.editFrom, ch: 0 },
{ line: chunk.editTo, ch: 0 }
);
let removedLines = left.getRange(
const removedLines = left.getRange(
{ line: chunk.origFrom, ch: 0 },
{ line: chunk.origTo, ch: 0 }
);
@ -443,16 +438,16 @@ const commitAllHandler = function() {
/******************************************************************************/
const editSaveHandler = function() {
let editor = mergeView.editor();
let editText = editor.getValue().trim();
const editor = mergeView.editor();
const editText = editor.getValue().trim();
if ( editText === cleanEditText ) {
onTextChanged(true);
return;
}
if ( differ === undefined ) { differ = new diff_match_patch(); }
let toAdd = [], toRemove = [];
let diffs = differ.diff_main(cleanEditText, editText);
for ( let diff of diffs ) {
const toAdd = [], toRemove = [];
const diffs = differ.diff_main(cleanEditText, editText);
for ( const diff of diffs ) {
if ( diff[0] === 1 ) {
toAdd.push(diff[1]);
} else if ( diff[0] === -1 ) {
@ -485,7 +480,11 @@ self.hasUnsavedData = function() {
/******************************************************************************/
messaging.send('dashboard', { what: 'getRules' }, renderRules);
vAPI.messaging.send('dashboard', {
what: 'getRules',
}).then(details => {
renderRules(details);
});
// Handle user interaction
uDom('#importButton').on('click', startImportFilePicker);

View File

@ -25,7 +25,7 @@
/******************************************************************************/
(function() {
(( ) => {
/******************************************************************************/
@ -385,9 +385,15 @@ const startDialog = (function() {
ev.stopPropagation();
if ( target.id === 'createCosmeticFilters' ) {
messaging.send('loggerUI', { what: 'createUserFilter', filters: textarea.value });
messaging.send('loggerUI', {
what: 'createUserFilter',
filters: textarea.value,
});
// Force a reload for the new cosmetic filter(s) to take effect
messaging.send('loggerUI', { what: 'reloadTab', tabId: inspectedTabId });
messaging.send('loggerUI', {
what: 'reloadTab',
tabId: inspectedTabId,
});
return stop();
}
};
@ -561,8 +567,8 @@ const injectInspector = function() {
inspectedTabId = tabId;
messaging.send('loggerUI', {
what: 'scriptlet',
tabId: tabId,
scriptlet: 'dom-inspector'
tabId,
scriptlet: 'dom-inspector',
});
};

View File

@ -25,7 +25,7 @@
/******************************************************************************/
(function() {
(( ) => {
/******************************************************************************/
@ -975,7 +975,7 @@ const onLogBufferRead = function(response) {
const readLogBuffer = (( ) => {
let timer;
const readLogBufferNow = function() {
const readLogBufferNow = async function() {
if ( logger.ownerId === undefined ) { return; }
const msg = {
@ -1002,11 +1002,11 @@ const readLogBuffer = (( ) => {
msg.popupLoggerBoxChanged = true;
}
vAPI.messaging.send('loggerUI', msg, response => {
timer = undefined;
onLogBufferRead(response);
readLogBufferLater();
});
const response = await vAPI.messaging.send('loggerUI', msg);
timer = undefined;
onLogBufferRead(response);
readLogBufferLater();
};
const readLogBufferLater = function() {
@ -1078,7 +1078,7 @@ const reloadTab = function(ev) {
messaging.send('loggerUI', {
what: 'reloadTab',
tabId: tabId,
bypassCache: ev && (ev.ctrlKey || ev.metaKey || ev.shiftKey)
bypassCache: ev && (ev.ctrlKey || ev.metaKey || ev.shiftKey),
});
};
@ -1144,17 +1144,14 @@ const reloadTab = function(ev) {
}
};
const colorize = function() {
messaging.send(
'loggerUI',
{
what: 'getURLFilteringData',
context: selectValue('select.dynamic.origin'),
urls: targetURLs,
type: uglyTypeFromSelector('dynamic')
},
onColorsReady
);
const colorize = async function() {
const response = await messaging.send('loggerUI', {
what: 'getURLFilteringData',
context: selectValue('select.dynamic.origin'),
urls: targetURLs,
type: uglyTypeFromSelector('dynamic'),
});
onColorsReady(response);
};
const parseStaticInputs = function() {
@ -1228,16 +1225,13 @@ const reloadTab = function(ev) {
}
createdStaticFilters[value] = true;
if ( value !== '' ) {
messaging.send(
'loggerUI',
{
what: 'createUserFilter',
autoComment: true,
filters: value,
origin: targetPageDomain,
pageDomain: targetPageDomain,
}
);
messaging.send('loggerUI', {
what: 'createUserFilter',
autoComment: true,
filters: value,
origin: targetPageDomain,
pageDomain: targetPageDomain,
});
}
updateWidgets();
ev.stopPropagation();
@ -1246,16 +1240,14 @@ const reloadTab = function(ev) {
// Save url filtering rule(s)
if ( target.id === 'saveRules' ) {
messaging.send(
'loggerUI',
{
what: 'saveURLFilteringRules',
context: selectValue('select.dynamic.origin'),
urls: targetURLs,
type: uglyTypeFromSelector('dynamic')
},
colorize
);
messaging.send('loggerUI', {
what: 'saveURLFilteringRules',
context: selectValue('select.dynamic.origin'),
urls: targetURLs,
type: uglyTypeFromSelector('dynamic'),
}).then(( ) => {
colorize();
});
ev.stopPropagation();
return;
}
@ -1264,100 +1256,86 @@ const reloadTab = function(ev) {
// Remove url filtering rule
if ( tcl.contains('action') ) {
messaging.send(
'loggerUI',
{
what: 'setURLFilteringRule',
context: selectValue('select.dynamic.origin'),
url: target.getAttribute('data-url'),
type: uglyTypeFromSelector('dynamic'),
action: 0,
persist: persist
},
colorize
);
messaging.send('loggerUI', {
what: 'setURLFilteringRule',
context: selectValue('select.dynamic.origin'),
url: target.getAttribute('data-url'),
type: uglyTypeFromSelector('dynamic'),
action: 0,
persist: persist,
}).then(( ) => {
colorize();
});
ev.stopPropagation();
return;
}
// add "allow" url filtering rule
if ( tcl.contains('allow') ) {
messaging.send(
'loggerUI',
{
what: 'setURLFilteringRule',
context: selectValue('select.dynamic.origin'),
url: target.parentNode.getAttribute('data-url'),
type: uglyTypeFromSelector('dynamic'),
action: 2,
persist: persist
},
colorize
);
messaging.send('loggerUI', {
what: 'setURLFilteringRule',
context: selectValue('select.dynamic.origin'),
url: target.parentNode.getAttribute('data-url'),
type: uglyTypeFromSelector('dynamic'),
action: 2,
persist: persist,
}).then(( ) => {
colorize();
});
ev.stopPropagation();
return;
}
// add "block" url filtering rule
if ( tcl.contains('noop') ) {
messaging.send(
'loggerUI',
{
what: 'setURLFilteringRule',
context: selectValue('select.dynamic.origin'),
url: target.parentNode.getAttribute('data-url'),
type: uglyTypeFromSelector('dynamic'),
action: 3,
persist: persist
},
colorize
);
messaging.send('loggerUI', {
what: 'setURLFilteringRule',
context: selectValue('select.dynamic.origin'),
url: target.parentNode.getAttribute('data-url'),
type: uglyTypeFromSelector('dynamic'),
action: 3,
persist: persist,
}).then(( ) => {
colorize();
});
ev.stopPropagation();
return;
}
// add "block" url filtering rule
if ( tcl.contains('block') ) {
messaging.send(
'loggerUI',
{
what: 'setURLFilteringRule',
context: selectValue('select.dynamic.origin'),
url: target.parentNode.getAttribute('data-url'),
type: uglyTypeFromSelector('dynamic'),
action: 1,
persist: persist
},
colorize
);
messaging.send('loggerUI', {
what: 'setURLFilteringRule',
context: selectValue('select.dynamic.origin'),
url: target.parentNode.getAttribute('data-url'),
type: uglyTypeFromSelector('dynamic'),
action: 1,
persist: persist,
}).then(( ) => {
colorize();
});
ev.stopPropagation();
return;
}
// Force a reload of the tab
if ( tcl.contains('reload') ) {
messaging.send(
'loggerUI',
{
what: 'reloadTab',
tabId: targetTabId
}
);
messaging.send('loggerUI', {
what: 'reloadTab',
tabId: targetTabId,
});
ev.stopPropagation();
return;
}
// Hightlight corresponding element in target web page
if ( tcl.contains('picker') ) {
messaging.send(
'loggerUI',
{
what: 'launchElementPicker',
tabId: targetTabId,
targetURL: 'img\t' + targetURLs[0],
select: true
}
);
messaging.send('loggerUI', {
what: 'launchElementPicker',
tabId: targetTabId,
targetURL: 'img\t' + targetURLs[0],
select: true,
});
ev.stopPropagation();
return;
}
@ -1450,7 +1428,7 @@ const reloadTab = function(ev) {
return urls;
};
const fillSummaryPaneFilterList = function(rows) {
const fillSummaryPaneFilterList = async function(rows) {
const rawFilter = targetRow.children[1].textContent;
const compiledFilter = targetRow.getAttribute('data-filter');
@ -1509,25 +1487,19 @@ const reloadTab = function(ev) {
};
if ( targetRow.classList.contains('networkRealm') ) {
messaging.send(
'loggerUI',
{
what: 'listsFromNetFilter',
compiledFilter: compiledFilter,
rawFilter: rawFilter
},
handleResponse
);
const response = await messaging.send('loggerUI', {
what: 'listsFromNetFilter',
compiledFilter: compiledFilter,
rawFilter: rawFilter,
});
handleResponse(response);
} else if ( targetRow.classList.contains('cosmeticRealm') ) {
messaging.send(
'loggerUI',
{
what: 'listsFromCosmeticFilter',
url: targetRow.children[6].textContent,
rawFilter: rawFilter,
},
handleResponse
);
const response = await messaging.send('loggerUI', {
what: 'listsFromCosmeticFilter',
url: targetRow.children[6].textContent,
rawFilter: rawFilter,
});
handleResponse(response);
}
};
@ -1789,7 +1761,7 @@ const reloadTab = function(ev) {
modalDialog.show();
};
const toggleOn = function(ev) {
const toggleOn = async function(ev) {
targetRow = ev.target.closest('.canDetails');
if ( targetRow === null ) { return; }
ev.stopPropagation();
@ -1800,24 +1772,21 @@ const reloadTab = function(ev) {
targetFrameHostname = targetRow.getAttribute('data-dochn') || '';
// We need the root domain names for best user experience.
messaging.send(
'loggerUI',
{
what: 'getDomainNames',
targets: [
targetURLs[0],
targetPageHostname,
targetFrameHostname
]
},
fillDialog
);
const domains = await messaging.send('loggerUI', {
what: 'getDomainNames',
targets: [
targetURLs[0],
targetPageHostname,
targetFrameHostname
],
});
fillDialog(domains);
};
uDom('#netInspector').on(
'click',
'.canDetails > span:nth-of-type(2),.canDetails > span:nth-of-type(3),.canDetails > span:nth-of-type(5)',
toggleOn
ev => { toggleOn(ev); }
);
})();
@ -2766,10 +2735,10 @@ const grabView = function() {
const releaseView = function() {
if ( logger.ownerId === undefined ) { return; }
vAPI.messaging.send(
'loggerUI',
{ what: 'releaseView', ownerId: logger.ownerId }
);
vAPI.messaging.send('loggerUI', {
what: 'releaseView',
ownerId: logger.ownerId,
});
logger.ownerId = undefined;
};

View File

@ -362,11 +362,35 @@ const popupDataFromRequest = async function(request) {
return popupDataFromTabId(tabId, tabTitle);
};
const getDOMStats = async function(tabId) {
const results = await vAPI.tabs.executeScript(tabId, {
allFrames: true,
file: '/js/scriptlets/dom-survey.js',
runAt: 'document_end',
});
let elementCount = 0;
let scriptCount = 0;
results.forEach(result => {
if ( result instanceof Object === false ) { return; }
elementCount += result.elementCount;
scriptCount += result.scriptCount;
});
return { elementCount, scriptCount };
};
const onMessage = function(request, sender, callback) {
let pageStore;
// Async
switch ( request.what ) {
case 'getPopupLazyData':
getDOMStats(request.tabId).then(results => {
callback(results);
});
return;
case 'getPopupData':
popupDataFromRequest(request).then(popupData => {
callback(popupData);
@ -381,19 +405,6 @@ const onMessage = function(request, sender, callback) {
let response;
switch ( request.what ) {
case 'getPopupLazyData':
pageStore = µb.pageStoreFromTabId(request.tabId);
if ( pageStore !== null ) {
pageStore.hiddenElementCount = 0;
pageStore.scriptCount = 0;
vAPI.tabs.executeScript(request.tabId, {
allFrames: true,
file: '/js/scriptlets/dom-survey.js',
runAt: 'document_end'
});
}
break;
case 'hasPopupContentChanged':
pageStore = µb.pageStoreFromTabId(request.tabId);
var lastModified = pageStore ? pageStore.contentLastModified : 0;
@ -792,14 +803,13 @@ const µb = µBlock;
const getLocalData = async function() {
const data = Object.assign({}, µb.restoreBackupSettings);
data.storageUsed = await µb.getBytesInUse();
data.cloudStorageSupported = µb.cloudStorageSupported;
data.privacySettingsSupported = µb.privacySettingsSupported;
return data;
};
const backupUserData = async function() {
const [ userFilters, localData ] = await Promise.all([
µb.loadUserFilters(),
getLocalData(),
]);
const userFilters = await µb.loadUserFilters();
const userData = {
timeStamp: Date.now(),
@ -823,6 +833,8 @@ const backupUserData = async function() {
µb.restoreBackupSettings.lastBackupTime = Date.now();
vAPI.storage.set(µb.restoreBackupSettings);
const localData = await getLocalData();
return { localData, userData };
};
@ -1348,21 +1360,6 @@ vAPI.messaging.listen({
// >>>>> start of local scope
const µb = µBlock;
const broadcastTimers = new Map();
const domSurveyFinalReport = function(tabId) {
broadcastTimers.delete(tabId + '-domSurveyReport');
const pageStore = µb.pageStoreFromTabId(tabId);
if ( pageStore === null ) { return; }
vAPI.messaging.broadcast({
what: 'domSurveyFinalReport',
tabId: tabId,
affectedElementCount: pageStore.hiddenElementCount,
scriptCount: pageStore.scriptCount,
});
};
const logCosmeticFilters = function(tabId, details) {
if ( µb.logger.enabled === false ) { return; }
@ -1488,24 +1485,6 @@ const onMessage = function(request, sender, callback) {
response = µb.applyFilterListSelection(request);
break;
case 'domSurveyTransientReport':
if ( pageStore !== null ) {
if ( request.filteredElementCount ) {
pageStore.hiddenElementCount += request.filteredElementCount;
}
if ( request.scriptCount ) {
pageStore.scriptCount += request.scriptCount;
}
const broadcastKey = `${tabId}-domSurveyReport`;
if ( broadcastTimers.has(broadcastKey) === false ) {
broadcastTimers.set(broadcastKey, vAPI.setTimeout(
( ) => { domSurveyFinalReport(tabId); },
103
));
}
}
break;
case 'inlinescriptFound':
if ( µb.logger.enabled && pageStore !== null ) {
const fctxt = µb.filteringContext.duplicate();

View File

@ -257,9 +257,7 @@ const PageStore = class {
this.logData = undefined;
this.perLoadBlockedRequestCount = 0;
this.perLoadAllowedRequestCount = 0;
this.hiddenElementCount = ''; // Empty string means "unknown"
this.remoteFontCount = 0;
this.scriptCount = 0;
this.popupBlockedCount = 0;
this.largeMediaCount = 0;
this.largeMediaTimer = null;

View File

@ -668,49 +668,36 @@ let renderOnce = function() {
/******************************************************************************/
const renderPopupLazy = function() {
messaging.send(
'popupPanel',
{ what: 'getPopupLazyData', tabId: popupData.tabId }
);
const renderPopupLazy = async function() {
const result = await messaging.send('popupPanel', {
what: 'getPopupLazyData',
tabId: popupData.tabId,
});
if ( result instanceof Object === false ) { return; }
let count = result.elementCount || 0;
uDom.nodeFromSelector('#no-cosmetic-filtering > span.fa-icon-badge')
.textContent = count !== 0
? Math.min(count, 99).toLocaleString()
: '';
count = result.scriptCount || 0;
uDom.nodeFromSelector('#no-scripting > span.fa-icon-badge')
.textContent = count !== 0
? Math.min(count, 99).toLocaleString()
: '';
};
const onPopupMessage = function(data) {
if ( !data ) { return; }
if ( data.tabId !== popupData.tabId ) { return; }
switch ( data.what ) {
case 'domSurveyFinalReport':
let count = data.affectedElementCount || '';
uDom.nodeFromSelector('#no-cosmetic-filtering > span.fa-icon-badge')
.textContent = typeof count === 'number'
? Math.min(count, 99).toLocaleString()
: count;
count = data.scriptCount || '';
uDom.nodeFromSelector('#no-scripting > span.fa-icon-badge')
.textContent = typeof count === 'number'
? Math.min(count, 99).toLocaleString()
: count;
break;
}
};
messaging.addChannelListener('popup', onPopupMessage);
/******************************************************************************/
const toggleNetFilteringSwitch = function(ev) {
if ( !popupData || !popupData.pageURL ) { return; }
messaging.send(
'popupPanel',
{
what: 'toggleNetFiltering',
url: popupData.pageURL,
scope: ev.ctrlKey || ev.metaKey ? 'page' : '',
state: !uDom('body').toggleClass('off').hasClass('off'),
tabId: popupData.tabId
}
);
messaging.send('popupPanel', {
what: 'toggleNetFiltering',
url: popupData.pageURL,
scope: ev.ctrlKey || ev.metaKey ? 'page' : '',
state: !uDom('body').toggleClass('off').hasClass('off'),
tabId: popupData.tabId,
});
renderTooltips('#switch');
hashFromPopupData();
};
@ -718,14 +705,11 @@ const toggleNetFilteringSwitch = function(ev) {
/******************************************************************************/
const gotoZap = function() {
messaging.send(
'popupPanel',
{
what: 'launchElementPicker',
tabId: popupData.tabId,
zap: true
}
);
messaging.send('popupPanel', {
what: 'launchElementPicker',
tabId: popupData.tabId,
zap: true,
});
vAPI.closePopup();
};
@ -733,13 +717,10 @@ const gotoZap = function() {
/******************************************************************************/
const gotoPick = function() {
messaging.send(
'popupPanel',
{
what: 'launchElementPicker',
tabId: popupData.tabId
}
);
messaging.send('popupPanel', {
what: 'launchElementPicker',
tabId: popupData.tabId,
});
vAPI.closePopup();
};
@ -759,18 +740,15 @@ const gotoURL = function(ev) {
url += '+' + popupData.tabId;
}
messaging.send(
'popupPanel',
{
what: 'gotoURL',
details: {
url: url,
select: true,
index: -1,
shiftKey: ev.shiftKey
}
}
);
messaging.send('popupPanel', {
what: 'gotoURL',
details: {
url: url,
select: true,
index: -1,
shiftKey: ev.shiftKey
},
});
vAPI.closePopup();
};
@ -780,14 +758,11 @@ const gotoURL = function(ev) {
const toggleFirewallPane = function() {
popupData.dfEnabled = !popupData.dfEnabled;
messaging.send(
'popupPanel',
{
what: 'userSettings',
name: 'dynamicFilteringEnabled',
value: popupData.dfEnabled
}
);
messaging.send('popupPanel', {
what: 'userSettings',
name: 'dynamicFilteringEnabled',
value: popupData.dfEnabled,
});
// https://github.com/chrisaljoudi/uBlock/issues/996
// Remember the last state of the firewall pane. This allows to
@ -817,7 +792,7 @@ const mouseleaveCellHandler = function() {
/******************************************************************************/
const setFirewallRule = function(src, des, type, action, persist) {
const setFirewallRule = async function(src, des, type, action, persist) {
// This can happen on pages where uBlock does not work
if (
typeof popupData.pageHostname !== 'string' ||
@ -826,24 +801,20 @@ const setFirewallRule = function(src, des, type, action, persist) {
return;
}
messaging.send(
'popupPanel',
{
what: 'toggleFirewallRule',
tabId: popupData.tabId,
pageHostname: popupData.pageHostname,
srcHostname: src,
desHostname: des,
requestType: type,
action: action,
persist: persist
},
response => {
cachePopupData(response);
updateAllFirewallCells();
hashFromPopupData();
}
);
const response = await messaging.send('popupPanel', {
what: 'toggleFirewallRule',
tabId: popupData.tabId,
pageHostname: popupData.pageHostname,
srcHostname: src,
desHostname: des,
requestType: type,
action: action,
persist: persist,
});
cachePopupData(response);
updateAllFirewallCells();
hashFromPopupData();
};
/******************************************************************************/
@ -889,15 +860,12 @@ const setFirewallRuleHandler = function(ev) {
/******************************************************************************/
const reloadTab = function(ev) {
messaging.send(
'popupPanel',
{
what: 'reloadTab',
tabId: popupData.tabId,
select: vAPI.webextFlavor.soup.has('mobile'),
bypassCache: ev.ctrlKey || ev.metaKey || ev.shiftKey
}
);
messaging.send('popupPanel', {
what: 'reloadTab',
tabId: popupData.tabId,
select: vAPI.webextFlavor.soup.has('mobile'),
bypassCache: ev.ctrlKey || ev.metaKey || ev.shiftKey,
});
// Polling will take care of refreshing the popup content
// https://github.com/chrisaljoudi/uBlock/issues/748
@ -930,17 +898,14 @@ const toggleMinimize = function(ev) {
// Useful to take snapshots of the whole list of domains -- example:
// https://github.com/gorhill/uBlock/issues/736#issuecomment-178879944
if ( ev.shiftKey && ev.ctrlKey ) {
messaging.send(
'popupPanel',
{
what: 'gotoURL',
details: {
url: 'popup.html?tabId=' + popupData.tabId + '&responsive=1',
select: true,
index: -1
}
}
);
messaging.send('popupPanel', {
what: 'gotoURL',
details: {
url: 'popup.html?tabId=' + popupData.tabId + '&responsive=1',
select: true,
index: -1
},
});
vAPI.closePopup();
return;
}
@ -948,76 +913,62 @@ const toggleMinimize = function(ev) {
popupData.firewallPaneMinimized =
uDom.nodeFromId('firewallContainer').classList.toggle('minimized');
messaging.send(
'popupPanel',
{
what: 'userSettings',
name: 'firewallPaneMinimized',
value: popupData.firewallPaneMinimized
}
);
messaging.send('popupPanel', {
what: 'userSettings',
name: 'firewallPaneMinimized',
value: popupData.firewallPaneMinimized,
});
positionRulesetTools();
};
/******************************************************************************/
const saveFirewallRules = function() {
messaging.send(
'popupPanel',
{
what: 'saveFirewallRules',
srcHostname: popupData.pageHostname,
desHostnames: popupData.hostnameDict
}
);
messaging.send('popupPanel', {
what: 'saveFirewallRules',
srcHostname: popupData.pageHostname,
desHostnames: popupData.hostnameDict,
});
uDom.nodeFromId('firewallContainer').classList.remove('dirty');
};
/******************************************************************************/
const revertFirewallRules = function() {
messaging.send(
'popupPanel',
{
what: 'revertFirewallRules',
srcHostname: popupData.pageHostname,
desHostnames: popupData.hostnameDict,
tabId: popupData.tabId
},
response => {
cachePopupData(response);
updateAllFirewallCells();
updateHnSwitches();
hashFromPopupData();
}
);
const revertFirewallRules = async function() {
uDom.nodeFromId('firewallContainer').classList.remove('dirty');
const response = await messaging.send('popupPanel', {
what: 'revertFirewallRules',
srcHostname: popupData.pageHostname,
desHostnames: popupData.hostnameDict,
tabId: popupData.tabId,
});
cachePopupData(response);
updateAllFirewallCells();
updateHnSwitches();
hashFromPopupData();
};
/******************************************************************************/
const toggleHostnameSwitch = function(ev) {
const toggleHostnameSwitch = async function(ev) {
const target = ev.currentTarget;
const switchName = target.getAttribute('id');
if ( !switchName ) { return; }
target.classList.toggle('on');
messaging.send(
'popupPanel',
{
what: 'toggleHostnameSwitch',
name: switchName,
hostname: popupData.pageHostname,
state: target.classList.contains('on'),
tabId: popupData.tabId,
persist: popupData.dfEnabled === false || ev.ctrlKey || ev.metaKey
},
response => {
cachePopupData(response);
updateAllFirewallCells();
hashFromPopupData();
}
);
renderTooltips('#' + switchName);
const response = await messaging.send('popupPanel', {
what: 'toggleHostnameSwitch',
name: switchName,
hostname: popupData.pageHostname,
state: target.classList.contains('on'),
tabId: popupData.tabId,
persist: popupData.dfEnabled === false || ev.ctrlKey || ev.metaKey,
});
cachePopupData(response);
updateAllFirewallCells();
hashFromPopupData();
};
/******************************************************************************/
@ -1040,20 +991,17 @@ const toggleHostnameSwitch = function(ev) {
// on demand rather than forcing the main process to assume a client may need
// it and thus having to push it all the time unconditionally.
const pollForContentChange = (function() {
const pollForContentChange = (( ) => {
let pollTimer;
const pollCallback = function() {
const pollCallback = async function() {
pollTimer = undefined;
messaging.send(
'popupPanel',
{
what: 'hasPopupContentChanged',
tabId: popupData.tabId,
contentLastModified: popupData.contentLastModified
},
queryCallback
);
const response = await messaging.send('popupPanel', {
what: 'hasPopupContentChanged',
tabId: popupData.tabId,
contentLastModified: popupData.contentLastModified,
});
queryCallback(response);
};
const queryCallback = function(response) {
@ -1074,20 +1022,18 @@ const pollForContentChange = (function() {
/******************************************************************************/
const getPopupData = function(tabId) {
const onDataReceived = function(response) {
cachePopupData(response);
renderOnce();
renderPopup();
renderPopupLazy(); // low priority rendering
hashFromPopupData(true);
pollForContentChange();
};
messaging.send(
'popupPanel',
{ what: 'getPopupData', tabId: tabId },
onDataReceived
);
const getPopupData = async function(tabId) {
const response = await messaging.send('popupPanel', {
what: 'getPopupData',
tabId,
});
cachePopupData(response);
renderOnce();
renderPopup();
renderPopupLazy(); // low priority rendering
hashFromPopupData(true);
pollForContentChange();
};
/******************************************************************************/
@ -1151,9 +1097,9 @@ uDom('#switch').on('click', toggleNetFilteringSwitch);
uDom('#gotoZap').on('click', gotoZap);
uDom('#gotoPick').on('click', gotoPick);
uDom('h2').on('click', toggleFirewallPane);
uDom('.hnSwitch').on('click', toggleHostnameSwitch);
uDom('.hnSwitch').on('click', ev => { toggleHostnameSwitch(ev); });
uDom('#saveRules').on('click', saveFirewallRules);
uDom('#revertRules').on('click', revertFirewallRules);
uDom('#revertRules').on('click', ( ) => { revertFirewallRules(); });
uDom('[data-i18n="popupAnyRulePrompt"]').on('click', toggleMinimize);
uDom('body').on('mouseenter', '[data-tip]', onShowTooltip)

View File

@ -195,15 +195,12 @@ const processTimer = new vAPI.SafeAnimationFrame(( ) => {
if ( toLog.length === 0 ) { return; }
vAPI.messaging.send(
'scriptlets',
{
what: 'logCosmeticFilteringData',
frameURL: window.location.href,
frameHostname: window.location.hostname,
matchedSelectors: toLog,
}
);
vAPI.messaging.send('scriptlets', {
what: 'logCosmeticFilteringData',
frameURL: window.location.href,
frameHostname: window.location.hostname,
matchedSelectors: toLog,
});
//console.timeEnd('dom logger/scanning for matches');
});

View File

@ -49,37 +49,15 @@
const scriptTags = document.querySelectorAll('script[src]');
let filteredElementCount = 0;
let elementCount = 0;
if ( vAPI.domFilterer ) {
filteredElementCount = vAPI.domFilterer.getFilteredElementCount();
elementCount = vAPI.domFilterer.getFilteredElementCount();
}
vAPI.messaging.send(
'scriptlets',
{
what: 'domSurveyTransientReport',
filteredElementCount: filteredElementCount,
scriptCount: inlineScriptCount + scriptTags.length,
}
);
// IMPORTANT: This is returned to the injector, so this MUST be
// the last statement.
return {
elementCount,
scriptCount: inlineScriptCount + scriptTags.length,
};
})();
/*******************************************************************************
DO NOT:
- Remove the following code
- Add code beyond the following code
Reason:
- https://github.com/gorhill/uBlock/pull/3721
- uBO never uses the return value from injected content scripts
**/
void 0;

View File

@ -371,15 +371,12 @@ const netFilterFromUnion = function(toMergeURL, out) {
) {
lastNetFilterHostname = parsedURL.host;
lastNetFilterUnion = toMergeURL;
vAPI.messaging.send(
'elementPicker',
{
what: 'elementPickerEprom',
lastNetFilterSession: lastNetFilterSession,
lastNetFilterHostname: lastNetFilterHostname,
lastNetFilterUnion: lastNetFilterUnion
}
);
vAPI.messaging.send('elementPicker', {
what: 'elementPickerEprom',
lastNetFilterSession: lastNetFilterSession,
lastNetFilterHostname: lastNetFilterHostname,
lastNetFilterUnion: lastNetFilterUnion,
});
return;
}
@ -398,15 +395,12 @@ const netFilterFromUnion = function(toMergeURL, out) {
lastNetFilterUnion = mergedURL;
// Remember across element picker sessions
vAPI.messaging.send(
'elementPicker',
{
what: 'elementPickerEprom',
lastNetFilterSession: lastNetFilterSession,
lastNetFilterHostname: lastNetFilterHostname,
lastNetFilterUnion: lastNetFilterUnion
}
);
vAPI.messaging.send('elementPicker', {
what: 'elementPickerEprom',
lastNetFilterSession: lastNetFilterSession,
lastNetFilterHostname: lastNetFilterHostname,
lastNetFilterUnion: lastNetFilterUnion,
});
};
/******************************************************************************/
@ -854,7 +848,7 @@ const filterToDOMInterface = (( ) => {
applied = false,
previewing = false;
const queryAll = function(filter, callback) {
const queryAll = async function(filter, callback) {
filter = filter.trim();
if ( filter === lastFilter ) {
callback(lastResultset);
@ -883,15 +877,13 @@ const filterToDOMInterface = (( ) => {
return;
}
// Procedural cosmetic filter
vAPI.messaging.send(
'elementPicker',
{ what: 'compileCosmeticFilterSelector', selector: selector },
response => {
lastResultset = fromCompiledCosmeticFilter(response);
if ( previewing ) { apply(); }
callback(lastResultset);
}
);
const response = await vAPI.messaging.send('elementPicker', {
what: 'compileCosmeticFilterSelector',
selector,
});
lastResultset = fromCompiledCosmeticFilter(response);
if ( previewing ) { apply(); }
callback(lastResultset);
};
// https://github.com/gorhill/uBlock/issues/1629
@ -1190,17 +1182,14 @@ const onDialogClicked = function(ev) {
filterToDOMInterface.preview(false);
userFilterFromCandidate((filter = undefined, isCosmetic = false) => {
if ( filter === undefined ) { return; }
vAPI.messaging.send(
'elementPicker',
{
what: 'createUserFilter',
autoComment: true,
filters: filter,
origin: window.location.origin,
pageDomain: window.location.hostname,
killCache: isCosmetic === false,
}
);
vAPI.messaging.send('elementPicker', {
what: 'createUserFilter',
autoComment: true,
filters: filter,
origin: window.location.origin,
pageDomain: window.location.hostname,
killCache: isCosmetic === false,
});
filterToDOMInterface.preview(rawFilterFromTextarea(), true);
stopPicker();
});
@ -1697,14 +1686,12 @@ const startPicker = function(details) {
/******************************************************************************/
const bootstrapPicker = function() {
pickerRoot.removeEventListener('load', bootstrapPicker);
const bootstrapPicker = async function() {
vAPI.shutdown.add(stopPicker);
vAPI.messaging.send(
'elementPicker',
{ what: 'elementPickerArguments' },
startPicker
);
const details = await vAPI.messaging.send('elementPicker', {
what: 'elementPickerArguments',
});
startPicker(details);
};
/******************************************************************************/
@ -1762,7 +1749,11 @@ vAPI.userStylesheet.apply();
// https://github.com/gorhill/uBlock/issues/2060
vAPI.domFilterer.excludeNode(pickerRoot);
pickerRoot.addEventListener('load', bootstrapPicker);
pickerRoot.addEventListener(
'load',
( ) => { bootstrapPicker(); },
{ once: true }
);
document.documentElement.appendChild(pickerRoot);
/******************************************************************************/

View File

@ -1,7 +1,7 @@
/*******************************************************************************
uBlock Origin - a browser extension to block requests.
Copyright (C) 2015-2018 Raymond Hill
Copyright (C) 2015-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
@ -19,11 +19,11 @@
Home: https://github.com/gorhill/uBlock
*/
'use strict';
/******************************************************************************/
(function() {
'use strict';
(( ) => {
/******************************************************************************/
@ -34,19 +34,18 @@ if ( typeof vAPI !== 'object' || vAPI.loadLargeMediaInteractive === true ) {
/******************************************************************************/
var largeMediaElementAttribute = 'data-' + vAPI.sessionId;
var largeMediaElementSelector =
const largeMediaElementAttribute = 'data-' + vAPI.sessionId;
const largeMediaElementSelector =
':root audio[' + largeMediaElementAttribute + '],\n' +
':root img[' + largeMediaElementAttribute + '],\n' +
':root video[' + largeMediaElementAttribute + ']';
/******************************************************************************/
var mediaNotLoaded = function(elem) {
var src = elem.getAttribute('src') || '';
if ( src === '' ) {
return false;
}
const mediaNotLoaded = function(elem) {
const src = elem.getAttribute('src') || '';
if ( src === '' ) { return false; }
switch ( elem.localName ) {
case 'audio':
case 'video':
@ -55,7 +54,7 @@ var mediaNotLoaded = function(elem) {
if ( elem.naturalWidth !== 0 || elem.naturalHeight !== 0 ) {
break;
}
var style = window.getComputedStyle(elem);
const style = window.getComputedStyle(elem);
// For some reason, style can be null with Pale Moon.
return style !== null ?
style.getPropertyValue('display') !== 'none' :
@ -74,7 +73,7 @@ var mediaNotLoaded = function(elem) {
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
var surveyMissingMediaElements = function() {
const surveyMissingMediaElements = function() {
var largeMediaElementCount = 0;
var elems = document.querySelectorAll('audio,img,video');
var i = elems.length, elem;
@ -95,7 +94,7 @@ if ( surveyMissingMediaElements() === 0 ) {
vAPI.loadLargeMediaInteractive = true;
// Insert custom style tag.
var styleTag = document.createElement('style');
let styleTag = document.createElement('style');
styleTag.setAttribute('type', 'text/css');
styleTag.textContent = [
largeMediaElementSelector + ' {',
@ -114,10 +113,10 @@ document.head.appendChild(styleTag);
/******************************************************************************/
var stayOrLeave = (function() {
var timer = null;
const stayOrLeave = (( ) => {
let timer = null;
var timeoutHandler = function(leaveNow) {
const timeoutHandler = function(leaveNow) {
timer = null;
if ( leaveNow !== true ) {
if (
@ -151,15 +150,26 @@ var stayOrLeave = (function() {
/******************************************************************************/
var onMouseClick = function(ev) {
if ( ev.button !== 0 ) {
return;
}
const loadImage = async function(elem) {
const src = elem.getAttribute('src');
elem.removeAttribute('src');
var elem = ev.target;
if ( elem.matches(largeMediaElementSelector) === false ) {
return;
}
await vAPI.messaging.send('scriptlets', {
what: 'temporarilyAllowLargeMediaElement',
});
elem.setAttribute('src', src);
elem.removeAttribute(largeMediaElementAttribute);
stayOrLeave();
};
/******************************************************************************/
const onMouseClick = function(ev) {
if ( ev.button !== 0 ) { return; }
const elem = ev.target;
if ( elem.matches(largeMediaElementSelector) === false ) { return; }
if ( mediaNotLoaded(elem) === false ) {
elem.removeAttribute(largeMediaElementAttribute);
@ -167,20 +177,7 @@ var onMouseClick = function(ev) {
return;
}
var src = elem.getAttribute('src');
elem.removeAttribute('src');
var onLargeMediaElementAllowed = function() {
elem.setAttribute('src', src);
elem.removeAttribute(largeMediaElementAttribute);
stayOrLeave();
};
vAPI.messaging.send(
'scriptlets',
{ what: 'temporarilyAllowLargeMediaElement' },
onLargeMediaElementAllowed
);
loadImage(elem);
ev.preventDefault();
ev.stopPropagation();
@ -190,8 +187,8 @@ document.addEventListener('click', onMouseClick, true);
/******************************************************************************/
var onLoad = function(ev) {
var elem = ev.target;
const onLoad = function(ev) {
const elem = ev.target;
if ( elem.hasAttribute(largeMediaElementAttribute) ) {
elem.removeAttribute(largeMediaElementAttribute);
stayOrLeave();
@ -202,8 +199,8 @@ document.addEventListener('load', onLoad, true);
/******************************************************************************/
var onLoadError = function(ev) {
var elem = ev.target;
const onLoadError = function(ev) {
const elem = ev.target;
if ( mediaNotLoaded(elem) ) {
elem.setAttribute(largeMediaElementAttribute, '');
}

View File

@ -1,7 +1,7 @@
/*******************************************************************************
uBlock Origin - a browser extension to block requests.
Copyright (C) 2015-2018 Raymond Hill
Copyright (C) 2015-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
@ -30,7 +30,7 @@
/******************************************************************************/
(function() {
(( ) => {
/******************************************************************************/
@ -48,61 +48,57 @@ if ( typeof vAPI !== 'object' ) {
/******************************************************************************/
var onMaybeAbpLinkClicked = function(ev) {
if ( ev.button !== 0 ) {
return;
}
const processSubscription = async function(location, title) {
const details = await vAPI.messaging.send('scriptlets', {
what: 'subscriberData',
});
const confirmStr = details.confirmStr
.replace('{{url}}', location)
.replace('{{title}}', title);
if ( window.confirm(confirmStr) === false ) { return; }
await vAPI.messaging.send('scriptlets', {
what: 'applyFilterListSelection',
toImport: location,
});
vAPI.messaging.send('scriptlets', {
what: 'reloadAllFilters',
});
};
/******************************************************************************/
const onMaybeAbpLinkClicked = function(ev) {
if ( ev.button !== 0 ) { return; }
// This addresses https://github.com/easylist/EasyListHebrew/issues/89
// Also, as per feedback to original fix:
// https://github.com/gorhill/uBlock/commit/99a3d9631047d33dc7a454296ab3dd0a1e91d6f1
var target = ev.target;
const target = ev.target;
if (
ev.isTrusted === false ||
target instanceof HTMLAnchorElement === false
) {
return;
}
var href = target.href || '';
if ( href === '' ) {
return;
}
var matches = /^(?:abp|ubo):\/*subscribe\/*\?location=([^&]+).*title=([^&]+)/.exec(href);
const href = target.href || '';
if ( href === '' ) { return; }
let matches = /^(?:abp|ubo):\/*subscribe\/*\?location=([^&]+).*title=([^&]+)/.exec(href);
if ( matches === null ) {
matches = /^https?:\/\/.*?[&?]location=([^&]+).*?&title=([^&]+)/.exec(href);
if ( matches === null ) { return; }
}
var location = decodeURIComponent(matches[1]);
var title = decodeURIComponent(matches[2]);
var messaging = vAPI.messaging;
const location = decodeURIComponent(matches[1]);
const title = decodeURIComponent(matches[2]);
processSubscription(location, title);
ev.stopPropagation();
ev.preventDefault();
var onListsSelectionDone = function() {
messaging.send('scriptlets', { what: 'reloadAllFilters' });
};
var onSubscriberDataReady = function(details) {
var confirmStr = details.confirmStr
.replace('{{url}}', location)
.replace('{{title}}', title);
if ( !window.confirm(confirmStr) ) { return; }
messaging.send(
'scriptlets',
{
what: 'applyFilterListSelection',
toImport: location
},
onListsSelectionDone
);
};
messaging.send(
'scriptlets',
{ what: 'subscriberData' },
onSubscriberDataReady
);
};
/******************************************************************************/

View File

@ -1,7 +1,7 @@
/*******************************************************************************
uBlock Origin - a browser extension to block requests.
Copyright (C) 2014-2017 Raymond Hill
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
@ -29,10 +29,6 @@
/******************************************************************************/
const messaging = vAPI.messaging;
/******************************************************************************/
const handleImportFilePicker = function() {
const file = this.files[0];
if ( file === undefined || file.name === '' ) { return; }
@ -74,16 +70,12 @@ const handleImportFilePicker = function() {
const msg = vAPI.i18n('aboutRestoreDataConfirm')
.replace('{{time}}', time.toLocaleString());
const proceed = window.confirm(msg);
if ( proceed ) {
messaging.send(
'dashboard',
{
what: 'restoreUserData',
userData: userData,
file: filename
}
);
}
if ( proceed !== true ) { return; }
vAPI.messaging.send('dashboard', {
what: 'restoreUserData',
userData,
file: filename,
});
};
const fr = new FileReader();
@ -104,21 +96,22 @@ const startImportFilePicker = function() {
/******************************************************************************/
const exportToFile = function() {
messaging.send('dashboard', { what: 'backupUserData' }, response => {
if (
response instanceof Object === false ||
response.userData instanceof Object === false
) {
return;
}
vAPI.download({
'url': 'data:text/plain;charset=utf-8,' +
encodeURIComponent(JSON.stringify(response.userData, null, ' ')),
'filename': response.localData.lastBackupFile
});
onLocalDataReceived(response.localData);
const exportToFile = async function() {
const response = await vAPI.messaging.send('dashboard', {
what: 'backupUserData',
});
if (
response instanceof Object === false ||
response.userData instanceof Object === false
) {
return;
}
vAPI.download({
'url': 'data:text/plain;charset=utf-8,' +
encodeURIComponent(JSON.stringify(response.userData, null, ' ')),
'filename': response.localData.lastBackupFile
});
onLocalDataReceived(response.localData);
};
/******************************************************************************/
@ -175,9 +168,10 @@ const onLocalDataReceived = function(details) {
const resetUserData = function() {
const msg = vAPI.i18n('aboutResetDataConfirm');
const proceed = window.confirm(msg);
if ( proceed ) {
messaging.send('dashboard', { what: 'resetUserData' });
}
if ( proceed !== true ) { return; }
vAPI.messaging.send('dashboard', {
what: 'resetUserData',
});
};
/******************************************************************************/
@ -192,14 +186,11 @@ const synchronizeDOM = function() {
/******************************************************************************/
const changeUserSettings = function(name, value) {
messaging.send(
'dashboard',
{
what: 'userSettings',
name: name,
value: value
}
);
vAPI.messaging.send('dashboard', {
what: 'userSettings',
name,
value,
});
};
/******************************************************************************/
@ -253,7 +244,7 @@ const onUserSettingsReceived = function(details) {
.on('click', onPreventDefault);
});
uDom('#export').on('click', exportToFile);
uDom('#export').on('click', ( ) => { exportToFile(); });
uDom('#import').on('click', startImportFilePicker);
uDom('#reset').on('click', resetUserData);
uDom('#restoreFilePicker').on('change', handleImportFilePicker);
@ -263,8 +254,13 @@ const onUserSettingsReceived = function(details) {
/******************************************************************************/
messaging.send('dashboard', { what: 'userSettings' }, onUserSettingsReceived);
messaging.send('dashboard', { what: 'getLocalData' }, onLocalDataReceived);
Promise.all([
vAPI.messaging.send('dashboard', { what: 'userSettings' }),
vAPI.messaging.send('dashboard', { what: 'getLocalData' }),
]).then(results => {
onUserSettingsReceived(results[0]);
onLocalDataReceived(results[1]);
});
// https://github.com/uBlockOrigin/uBlock-issues/issues/591
document.querySelector(

View File

@ -21,14 +21,14 @@
'use strict';
(function() {
(( ) => {
// https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/commands#Shortcut_values
let validStatus0Keys = new Map([
const validStatus0Keys = new Map([
[ 'alt', 'Alt' ],
[ 'control', 'Ctrl' ],
]);
let validStatus1Keys = new Map([
const validStatus1Keys = new Map([
[ 'a', 'A' ],
[ 'b', 'B' ],
[ 'c', 'C' ],
@ -93,42 +93,43 @@
[ 'shift', 'Shift' ],
]);
let commandNameFromElement = function(elem) {
const commandNameFromElement = function(elem) {
while ( elem !== null ) {
let name = elem.getAttribute('data-name');
const name = elem.getAttribute('data-name');
if ( typeof name === 'string' && name !== '' ) { return name; }
elem = elem.parentElement;
}
};
let captureShortcut = function(ev) {
let input = ev.target;
let name = commandNameFromElement(input);
const captureShortcut = function(ev) {
const input = ev.target;
const name = commandNameFromElement(input);
if ( name === undefined ) { return; }
let before = input.value;
let after = new Set();
const before = input.value;
const after = new Set();
let status = 0;
let updateCapturedShortcut = function() {
const updateCapturedShortcut = function() {
return (input.value = Array.from(after).join('+'));
};
let blurHandler = function() {
const blurHandler = function() {
input.removeEventListener('blur', blurHandler, true);
input.removeEventListener('keydown', keydownHandler, true);
input.removeEventListener('keyup', keyupHandler, true);
if ( status === 2 ) {
vAPI.messaging.send(
'dashboard',
{ what: 'setShortcut', name: name, shortcut: updateCapturedShortcut() }
);
vAPI.messaging.send('dashboard', {
what: 'setShortcut',
name,
shortcut: updateCapturedShortcut(),
});
} else {
input.value = before;
}
};
let keydownHandler = function(ev) {
const keydownHandler = function(ev) {
ev.preventDefault();
ev.stopImmediatePropagation();
if ( ev.code === 'Escape' ) {
@ -136,7 +137,7 @@
return;
}
if ( status === 0 ) {
let keyName = validStatus0Keys.get(ev.key.toLowerCase());
const keyName = validStatus0Keys.get(ev.key.toLowerCase());
if ( keyName !== undefined ) {
after.add(keyName);
updateCapturedShortcut();
@ -161,11 +162,11 @@
}
};
let keyupHandler = function(ev) {
const keyupHandler = function(ev) {
ev.preventDefault();
ev.stopImmediatePropagation();
if ( status !== 1 ) { return; }
let keyName = validStatus0Keys.get(ev.key.toLowerCase());
const keyName = validStatus0Keys.get(ev.key.toLowerCase());
if ( keyName !== undefined && after.has(keyName) ) {
after.clear();
updateCapturedShortcut();
@ -185,29 +186,29 @@
input.addEventListener('keyup', keyupHandler, true);
};
let resetShortcut = function(ev) {
let name = commandNameFromElement(ev.target);
const resetShortcut = function(ev) {
const name = commandNameFromElement(ev.target);
if ( name === undefined ) { return; }
let input = document.querySelector('[data-name="' + name + '"] input');
const input = document.querySelector('[data-name="' + name + '"] input');
if ( input === null ) { return; }
input.value = '';
vAPI.messaging.send(
'dashboard',
{ what: 'setShortcut', name: name }
);
vAPI.messaging.send('dashboard', {
what: 'setShortcut',
name,
});
};
let onShortcutsReady = function(commands) {
const onShortcutsReady = function(commands) {
if ( Array.isArray(commands) === false ) { return; }
let template = document.querySelector('#templates .commandEntry');
let tbody = document.querySelector('.commandEntries tbody');
for ( let command of commands ) {
const template = document.querySelector('#templates .commandEntry');
const tbody = document.querySelector('.commandEntries tbody');
for ( const command of commands ) {
if ( command.description === '' ) { continue; }
let tr = template.cloneNode(true);
const tr = template.cloneNode(true);
tr.setAttribute('data-name', command.name);
tr.querySelector('.commandDesc').textContent = command.description;
let input = tr.querySelector('.commandShortcut input');
const input = tr.querySelector('.commandShortcut input');
input.setAttribute('data-name', command.name);
input.value = command.shortcut;
input.addEventListener('focus', captureShortcut);
@ -216,6 +217,9 @@
}
};
vAPI.messaging.send('dashboard', { what: 'getShortcuts' }, onShortcutsReady);
vAPI.messaging.send('dashboard', {
what: 'getShortcuts',
}).then(commands => {
onShortcutsReady(commands);
});
})();

View File

@ -114,44 +114,45 @@ cmEditor.on('changes', whitelistChanged);
/******************************************************************************/
const renderWhitelist = function() {
const onRead = details => {
const first = reBadHostname === undefined;
if ( first ) {
reBadHostname = new RegExp(details.reBadHostname);
reHostnameExtractor = new RegExp(details.reHostnameExtractor);
whitelistDefaultSet = new Set(details.whitelistDefault);
const renderWhitelist = async function() {
const details = await messaging.send('dashboard', {
what: 'getWhitelist',
});
const first = reBadHostname === undefined;
if ( first ) {
reBadHostname = new RegExp(details.reBadHostname);
reHostnameExtractor = new RegExp(details.reHostnameExtractor);
whitelistDefaultSet = new Set(details.whitelistDefault);
}
const toAdd = new Set(whitelistDefaultSet);
for ( const line of details.whitelist ) {
const directive = directiveFromLine(line);
if ( whitelistDefaultSet.has(directive) === false ) { continue; }
toAdd.delete(directive);
if ( toAdd.size === 0 ) { break; }
}
if ( toAdd.size !== 0 ) {
details.whitelist.push(...Array.from(toAdd).map(a => `# ${a}`));
}
details.whitelist.sort((a, b) => {
const ad = directiveFromLine(a);
const bd = directiveFromLine(b);
const abuiltin = whitelistDefaultSet.has(ad);
if ( abuiltin !== whitelistDefaultSet.has(bd) ) {
return abuiltin ? -1 : 1;
}
const toAdd = new Set(whitelistDefaultSet);
for ( const line of details.whitelist ) {
const directive = directiveFromLine(line);
if ( whitelistDefaultSet.has(directive) === false ) { continue; }
toAdd.delete(directive);
if ( toAdd.size === 0 ) { break; }
}
if ( toAdd.size !== 0 ) {
details.whitelist.push(...Array.from(toAdd).map(a => `# ${a}`));
}
details.whitelist.sort((a, b) => {
const ad = directiveFromLine(a);
const bd = directiveFromLine(b);
const abuiltin = whitelistDefaultSet.has(ad);
if ( abuiltin !== whitelistDefaultSet.has(bd) ) {
return abuiltin ? -1 : 1;
}
return ad.localeCompare(bd);
});
let whitelistStr = details.whitelist.join('\n').trim();
cachedWhitelist = whitelistStr;
if ( whitelistStr !== '' ) {
whitelistStr += '\n';
}
cmEditor.setValue(whitelistStr);
if ( first ) {
cmEditor.clearHistory();
}
};
messaging.send('dashboard', { what: 'getWhitelist' }, onRead);
return ad.localeCompare(bd);
});
let whitelistStr = details.whitelist.join('\n').trim();
cachedWhitelist = whitelistStr;
if ( whitelistStr !== '' ) {
whitelistStr += '\n';
}
cmEditor.setValue(whitelistStr);
if ( first ) {
cmEditor.clearHistory();
}
};
/******************************************************************************/
@ -201,16 +202,13 @@ const exportWhitelistToFile = function() {
/******************************************************************************/
const applyChanges = function() {
const applyChanges = async function() {
cachedWhitelist = cmEditor.getValue().trim();
messaging.send(
'dashboard',
{
what: 'setWhitelist',
whitelist: cachedWhitelist
},
renderWhitelist
);
await messaging.send('dashboard', {
what: 'setWhitelist',
whitelist: cachedWhitelist,
});
renderWhitelist();
};
const revertChanges = function() {
@ -247,7 +245,7 @@ self.hasUnsavedData = function() {
uDom('#importWhitelistFromFile').on('click', startImportFilePicker);
uDom('#importFilePicker').on('change', handleImportFilePicker);
uDom('#exportWhitelistToFile').on('click', exportWhitelistToFile);
uDom('#whitelistApply').on('click', applyChanges);
uDom('#whitelistApply').on('click', ( ) => { applyChanges(); });
uDom('#whitelistRevert').on('click', revertChanges);
renderWhitelist();