Skip to content

Commit a91781a

Browse files
committed
Rewrite logger's "exceptor" feature
Related issue: - uBlockOrigin/uBlock-issues#1861 The "exceptor" feature has been rewritten, with the following changes as a result: - The excepted filters cease to exist when closing the logger - It's now possible to temporary except network filters When toggling on/off a temporary exception, filter lists are now fully reloaded. This simplified managing temporary exceptions, and made it easy to implement temporary exception for network filters, but this also means there might be a perceptible delay when adding/removing temporary exceptions. At this point I consider this an acceptable side-effect just to bring the ability to easily create temporary exception for network filters, while this simplified the existing temporary exception code throughout.
1 parent ce3f852 commit a91781a

13 files changed

+127
-255
lines changed

platform/common/vapi-background.js

+3
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,9 @@ vAPI.messaging = {
919919
this.onPortDisconnect(port);
920920
}
921921
}
922+
if ( this.defaultHandler ) {
923+
this.defaultHandler(message, null, ( ) => { });
924+
}
922925
},
923926

924927
onFrameworkMessage: function(request, port, callback) {

src/css/logger-ui.css

+3
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,9 @@ body[dir="rtl"] #netFilteringDialog > .panes > .details > div > span:nth-of-type
678678
background-color: rgb(var(--primary-50) / 50%);
679679
}
680680
#netFilteringDialog > .panes > .details .exceptor::before {
681+
content: '@@';
682+
}
683+
#netFilteringDialog.extendedRealm > .panes > .details .exceptor::before {
681684
content: '#@#';
682685
}
683686
#netFilteringDialog > div.panes > .dynamic > .toolbar {

src/js/background.js

+3
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,9 @@ const µBlock = { // jshint ignore:line
211211
availableFilterLists: {},
212212
badLists: new Map(),
213213

214+
inMemoryFilters: [],
215+
inMemoryFiltersCompiled: '',
216+
214217
// https://github.com/uBlockOrigin/uBlock-issues/issues/974
215218
// This can be used to defer filtering decision-making.
216219
readyToFilter: false,

src/js/cosmetic-filtering.js

+2-28
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,7 @@ import './utils.js';
2727
import logger from './logger.js';
2828
import µb from './background.js';
2929

30-
import {
31-
StaticExtFilteringHostnameDB,
32-
StaticExtFilteringSessionDB,
33-
} from './static-ext-filtering-db.js';
30+
import { StaticExtFilteringHostnameDB } from './static-ext-filtering-db.js';
3431

3532
/******************************************************************************/
3633
/******************************************************************************/
@@ -236,10 +233,7 @@ const FilterContainer = function() {
236233
// specific filters
237234
this.specificFilters = new StaticExtFilteringHostnameDB(2);
238235

239-
// temporary filters
240-
this.sessionFilterDB = new StaticExtFilteringSessionDB();
241-
242-
// low generic cosmetic filters: map of hash => array of selectors
236+
// low generic cosmetic filters: map of hash => stringified selector list
243237
this.lowlyGeneric = new Map();
244238

245239
// highly generic selectors sets
@@ -478,15 +472,6 @@ FilterContainer.prototype.compileSpecificSelector = function(
478472

479473
/******************************************************************************/
480474

481-
FilterContainer.prototype.compileTemporary = function(parser) {
482-
return {
483-
session: this.sessionFilterDB,
484-
selector: parser.result.compiled,
485-
};
486-
};
487-
488-
/******************************************************************************/
489-
490475
FilterContainer.prototype.fromCompiledContent = function(reader, options) {
491476
if ( options.skipCosmetic ) {
492477
this.skipCompiledContent(reader, 'SPECIFIC');
@@ -697,12 +682,6 @@ FilterContainer.prototype.disableSurveyor = function(details) {
697682

698683
/******************************************************************************/
699684

700-
FilterContainer.prototype.getSession = function() {
701-
return this.sessionFilterDB;
702-
};
703-
704-
/******************************************************************************/
705-
706685
FilterContainer.prototype.cssRuleFromProcedural = function(json) {
707686
const pfilter = JSON.parse(json);
708687
if ( pfilter.cssable !== true ) { return; }
@@ -831,11 +810,6 @@ FilterContainer.prototype.retrieveSpecificSelectors = function(
831810
}
832811
}
833812

834-
// Retrieve temporary filters
835-
if ( this.sessionFilterDB.isNotEmpty ) {
836-
this.sessionFilterDB.retrieve([ null, exceptionSet ]);
837-
}
838-
839813
// Retrieve filters with a non-empty hostname
840814
this.specificFilters.retrieve(
841815
hostname,

src/js/html-filtering.js

+1-19
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,14 @@ import logger from './logger.js';
2727
import µb from './background.js';
2828
import { sessionFirewall } from './filtering-engines.js';
2929

30-
import {
31-
StaticExtFilteringHostnameDB,
32-
StaticExtFilteringSessionDB,
33-
} from './static-ext-filtering-db.js';
30+
import { StaticExtFilteringHostnameDB } from './static-ext-filtering-db.js';
3431

3532
/******************************************************************************/
3633

3734
const pselectors = new Map();
3835
const duplicates = new Set();
3936

4037
const filterDB = new StaticExtFilteringHostnameDB(2);
41-
const sessionFilterDB = new StaticExtFilteringSessionDB();
4238

4339
let acceptedCount = 0;
4440
let discardedCount = 0;
@@ -347,13 +343,6 @@ htmlFilteringEngine.compile = function(parser, writer) {
347343
}
348344
};
349345

350-
htmlFilteringEngine.compileTemporary = function(parser) {
351-
return {
352-
session: sessionFilterDB,
353-
selector: parser.result.compiled,
354-
};
355-
};
356-
357346
htmlFilteringEngine.fromCompiledContent = function(reader) {
358347
// Don't bother loading filters if stream filtering is not supported.
359348
if ( µb.canFilterResponseData === false ) { return; }
@@ -373,20 +362,13 @@ htmlFilteringEngine.fromCompiledContent = function(reader) {
373362
}
374363
};
375364

376-
htmlFilteringEngine.getSession = function() {
377-
return sessionFilterDB;
378-
};
379-
380365
htmlFilteringEngine.retrieve = function(details) {
381366
const hostname = details.hostname;
382367

383368
const plains = new Set();
384369
const procedurals = new Set();
385370
const exceptions = new Set();
386371

387-
if ( sessionFilterDB.isNotEmpty ) {
388-
sessionFilterDB.retrieve([ null, exceptions ]);
389-
}
390372
filterDB.retrieve(
391373
hostname,
392374
[ plains, exceptions, procedurals, exceptions ]

src/js/httpheader-filtering.js

+1-19
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,12 @@ import µb from './background.js';
2828
import { entityFromDomain } from './uri-utils.js';
2929
import { sessionFirewall } from './filtering-engines.js';
3030

31-
import {
32-
StaticExtFilteringHostnameDB,
33-
StaticExtFilteringSessionDB,
34-
} from './static-ext-filtering-db.js';
31+
import { StaticExtFilteringHostnameDB } from './static-ext-filtering-db.js';
3532

3633
/******************************************************************************/
3734

3835
const duplicates = new Set();
3936
const filterDB = new StaticExtFilteringHostnameDB(1);
40-
const sessionFilterDB = new StaticExtFilteringSessionDB();
4137

4238
const $headers = new Set();
4339
const $exceptions = new Set();
@@ -123,13 +119,6 @@ httpheaderFilteringEngine.compile = function(parser, writer) {
123119
}
124120
};
125121

126-
httpheaderFilteringEngine.compileTemporary = function(parser) {
127-
return {
128-
session: sessionFilterDB,
129-
selector: parser.result.compiled.slice(15, -1),
130-
};
131-
};
132-
133122
// 01234567890123456789
134123
// responseheader(name)
135124
// ^ ^
@@ -152,10 +141,6 @@ httpheaderFilteringEngine.fromCompiledContent = function(reader) {
152141
}
153142
};
154143

155-
httpheaderFilteringEngine.getSession = function() {
156-
return sessionFilterDB;
157-
};
158-
159144
httpheaderFilteringEngine.apply = function(fctxt, headers) {
160145
if ( filterDB.size === 0 ) { return; }
161146

@@ -173,9 +158,6 @@ httpheaderFilteringEngine.apply = function(fctxt, headers) {
173158
$headers.clear();
174159
$exceptions.clear();
175160

176-
if ( sessionFilterDB.isNotEmpty ) {
177-
sessionFilterDB.retrieve([ null, $exceptions ]);
178-
}
179161
filterDB.retrieve(hostname, [ $headers, $exceptions ]);
180162
filterDB.retrieve(entity, [ $headers, $exceptions ], 1);
181163
if ( $headers.size === 0 ) { return; }

src/js/logger-ui.js

+13-19
Original file line numberDiff line numberDiff line change
@@ -1246,9 +1246,13 @@ const reloadTab = function(ev) {
12461246
// Toggle temporary exception filter
12471247
if ( tcl.contains('exceptor') ) {
12481248
ev.stopPropagation();
1249+
const filter = filterFromTargetRow();
1250+
const exceptedFilter = dom.cl.has(targetRow, 'extendedRealm')
1251+
? `#@#${filter.replace(/^.*?#@?#/, '')}`
1252+
: `@@${filter.replace(/^@@/, '')}`;
12491253
const status = await messaging.send('loggerUI', {
1250-
what: 'toggleTemporaryException',
1251-
filter: filterFromTargetRow(),
1254+
what: 'toggleInMemoryFilter',
1255+
filter: exceptedFilter,
12521256
});
12531257
const row = target.closest('div');
12541258
dom.cl.toggle(row, 'exceptored', status);
@@ -1477,26 +1481,16 @@ const reloadTab = function(ev) {
14771481
const toSummaryPaneFilterNode = async function(receiver, filter) {
14781482
receiver.children[1].textContent = filter;
14791483
if ( filterAuthorMode !== true ) { return; }
1480-
const match = /#@?#/.exec(filter);
1481-
if ( match === null ) { return; }
1482-
const fragment = document.createDocumentFragment();
1483-
const pos = match.index + match[0].length;
1484-
fragment.appendChild(document.createTextNode(filter.slice(0, pos)));
1485-
const selector = filter.slice(pos);
1486-
const span = document.createElement('span');
1487-
span.className = 'filter';
1488-
span.textContent = selector;
1489-
fragment.appendChild(span);
1484+
if ( dom.cl.has(targetRow, 'canLookup') === false ) { return; }
1485+
const exceptedFilter = dom.cl.has(targetRow, 'extendedRealm')
1486+
? `#@#${filter.replace(/^.*?#@?#/, '')}`
1487+
: `@@${filter.replace(/^@@/, '')}`;
14901488
const isTemporaryException = await messaging.send('loggerUI', {
1491-
what: 'hasTemporaryException',
1492-
filter,
1489+
what: 'hasInMemoryFilter',
1490+
filter: exceptedFilter,
14931491
});
14941492
dom.cl.toggle(receiver, 'exceptored', isTemporaryException);
1495-
if ( match[0] === '##' || isTemporaryException ) {
1496-
receiver.children[2].style.visibility = '';
1497-
}
1498-
receiver.children[1].textContent = '';
1499-
receiver.children[1].appendChild(fragment);
1493+
receiver.children[2].style.visibility = '';
15001494
};
15011495

15021496
const fillSummaryPaneFilterList = async function(rows) {

src/js/logger.js

+8-12
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,15 @@ let writePtr = 0;
3232
const logBufferObsoleteAfter = 30 * 1000;
3333

3434
const janitor = ( ) => {
35-
if (
36-
buffer !== null &&
37-
lastReadTime < (Date.now() - logBufferObsoleteAfter)
38-
) {
39-
logger.enabled = false;
40-
buffer = null;
41-
writePtr = 0;
42-
logger.ownerId = undefined;
43-
vAPI.messaging.broadcast({ what: 'loggerDisabled' });
44-
}
45-
if ( buffer !== null ) {
46-
vAPI.setTimeout(janitor, logBufferObsoleteAfter);
35+
if ( buffer === null ) { return; }
36+
if ( lastReadTime >= (Date.now() - logBufferObsoleteAfter) ) {
37+
return vAPI.setTimeout(janitor, logBufferObsoleteAfter);
4738
}
39+
logger.enabled = false;
40+
buffer = null;
41+
writePtr = 0;
42+
logger.ownerId = undefined;
43+
vAPI.messaging.broadcast({ what: 'loggerDisabled' });
4844
};
4945

5046
const boxEntry = function(details) {

src/js/messaging.js

+17-42
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ import logger from './logger.js';
3535
import lz4Codec from './lz4.js';
3636
import io from './assets.js';
3737
import scriptletFilteringEngine from './scriptlet-filtering.js';
38-
import staticExtFilteringEngine from './static-ext-filtering.js';
3938
import staticFilteringReverseLookup from './reverselookup.js';
4039
import staticNetFilteringEngine from './static-net-filtering.js';
4140
import µb from './background.js';
@@ -305,6 +304,10 @@ const onMessage = function(request, sender, callback) {
305304
µb.elementPickerExec(request.tabId, 0, request.targetURL, request.zap);
306305
break;
307306

307+
case 'loggerDisabled':
308+
µb.clearInMemoryFilters();
309+
break;
310+
308311
case 'gotoURL':
309312
µb.openNewTab(request.details);
310313
break;
@@ -1680,49 +1683,25 @@ const getURLFilteringData = function(details) {
16801683
return response;
16811684
};
16821685

1683-
const compileTemporaryException = function(filter) {
1684-
const parser = new StaticFilteringParser({
1685-
nativeCssHas: vAPI.webextFlavor.env.includes('native_css_has'),
1686-
});
1687-
parser.analyze(filter);
1688-
if ( parser.shouldDiscard() ) { return; }
1689-
return staticExtFilteringEngine.compileTemporary(parser);
1690-
};
1691-
1692-
const toggleTemporaryException = function(details) {
1693-
const result = compileTemporaryException(details.filter);
1694-
if ( result === undefined ) { return false; }
1695-
const { session, selector } = result;
1696-
if ( session.has(1, selector) ) {
1697-
session.remove(1, selector);
1698-
return false;
1699-
}
1700-
session.add(1, selector);
1701-
return true;
1702-
};
1703-
1704-
const hasTemporaryException = function(details) {
1705-
const result = compileTemporaryException(details.filter);
1706-
if ( result === undefined ) { return false; }
1707-
const { session, selector } = result;
1708-
return session && session.has(1, selector);
1709-
};
1710-
17111686
const onMessage = function(request, sender, callback) {
17121687
// Async
17131688
switch ( request.what ) {
17141689
case 'readAll':
1715-
if (
1716-
logger.ownerId !== undefined &&
1717-
logger.ownerId !== request.ownerId
1718-
) {
1690+
if ( logger.ownerId !== undefined && logger.ownerId !== request.ownerId ) {
17191691
return callback({ unavailable: true });
17201692
}
17211693
vAPI.tabs.getCurrent().then(tab => {
17221694
getLoggerData(request, tab && tab.id, callback);
17231695
});
17241696
return;
17251697

1698+
case 'toggleInMemoryFilter': {
1699+
const promise = µb.hasInMemoryFilter(request.filter)
1700+
? µb.removeInMemoryFilter(request.filter)
1701+
: µb.addInMemoryFilter(request.filter);
1702+
promise.then(status => { callback(status); });
1703+
return;
1704+
}
17261705
default:
17271706
break;
17281707
}
@@ -1731,14 +1710,14 @@ const onMessage = function(request, sender, callback) {
17311710
let response;
17321711

17331712
switch ( request.what ) {
1734-
case 'hasTemporaryException':
1735-
response = hasTemporaryException(request);
1713+
case 'hasInMemoryFilter':
1714+
response = µb.hasInMemoryFilter(request.filter);
17361715
break;
17371716

17381717
case 'releaseView':
1739-
if ( request.ownerId === logger.ownerId ) {
1740-
logger.ownerId = undefined;
1741-
}
1718+
if ( request.ownerId !== logger.ownerId ) { break; }
1719+
logger.ownerId = undefined;
1720+
µb.clearInMemoryFilters();
17421721
break;
17431722

17441723
case 'saveURLFilteringRules':
@@ -1761,10 +1740,6 @@ const onMessage = function(request, sender, callback) {
17611740
response = getURLFilteringData(request);
17621741
break;
17631742

1764-
case 'toggleTemporaryException':
1765-
response = toggleTemporaryException(request);
1766-
break;
1767-
17681743
default:
17691744
return vAPI.messaging.UNHANDLED;
17701745
}

0 commit comments

Comments
 (0)