Skip to content

Commit

Permalink
Add support for elemhide (through specifichide)
Browse files Browse the repository at this point in the history
Related documentation:
- https://help.eyeo.com/en/adblockplus/how-to-write-filters#element-hiding

Related feedback/discussion:
- https://www.reddit.com/r/uBlockOrigin/comments/d6vxzj/

The `elemhide` filter option as per ABP semantic is
now supported. Previously uBO would consider `elemhide`
to be an alias of `generichide`.

The support of `elemhide` is through the convenient
conversion of `elemhide` option into existing
`generichide` option and new `specifichide` option.

The purpose of the new `specifichide` filter option
is to disable all specific cosmetic filters, i.e.
those who target a specific site.

Additionally, for convenience purpose, the filter
options `generichide`, `specifichide` and `elemhide`
can be aliased using the shorter forms `ghide`,
`shide` and `ehide` respectively.
  • Loading branch information
gorhill committed Sep 21, 2019
1 parent 6033ebf commit 23c4c80
Show file tree
Hide file tree
Showing 9 changed files with 269 additions and 141 deletions.
12 changes: 6 additions & 6 deletions src/js/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ if ( vAPI.webextFlavor === undefined ) {

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

const µBlock = (function() { // jshint ignore:line
const µBlock = (( ) => { // jshint ignore:line

const hiddenSettingsDefault = {
allowGenericProceduralFilters: false,
Expand Down Expand Up @@ -84,7 +84,7 @@ const µBlock = (function() { // jshint ignore:line
requestLogMaxEntries: 1000,
showIconBadge: true,
tooltipsDisabled: false,
webrtcIPAddressHidden: false
webrtcIPAddressHidden: false,
},

hiddenSettingsDefault: hiddenSettingsDefault,
Expand Down Expand Up @@ -133,22 +133,22 @@ const µBlock = (function() { // jshint ignore:line

localSettings: {
blockedRequestCount: 0,
allowedRequestCount: 0
allowedRequestCount: 0,
},
localSettingsLastModified: 0,
localSettingsLastSaved: 0,

// Read-only
systemSettings: {
compiledMagic: 18, // Increase when compiled format changes
selfieMagic: 18 // Increase when selfie format changes
compiledMagic: 19, // Increase when compiled format changes
selfieMagic: 19, // Increase when selfie format changes
},

restoreBackupSettings: {
lastRestoreFile: '',
lastRestoreTime: 0,
lastBackupFile: '',
lastBackupTime: 0
lastBackupTime: 0,
},

commandShortcuts: new Map(),
Expand Down
66 changes: 41 additions & 25 deletions src/js/cosmetic-filtering.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

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

µBlock.cosmeticFilteringEngine = (function(){
µBlock.cosmeticFilteringEngine = (( ) => {

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

Expand Down Expand Up @@ -238,10 +238,12 @@ const FilterContainer = function() {
// is to prevent repeated allocation/deallocation overheads -- the
// constructors/destructors of javascript Set/Map is assumed to be costlier
// than just calling clear() on these.
this.setRegister0 = new Set();
this.setRegister1 = new Set();
this.setRegister2 = new Set();
this.mapRegister0 = new Map();
this.simpleSet$ = new Set();
this.complexSet$ = new Set();
this.specificSet$ = new Set();
this.exceptionSet$ = new Set();
this.proceduralSet$ = new Set();
this.dummySet$ = new Set();

this.reset();
};
Expand Down Expand Up @@ -830,11 +832,11 @@ FilterContainer.prototype.retrieveGenericSelectors = function(request) {

//console.time('cosmeticFilteringEngine.retrieveGenericSelectors');

const simpleSelectors = this.setRegister0;
const complexSelectors = this.setRegister1;
const simpleSelectors = this.simpleSet$;
const complexSelectors = this.complexSet$;

const cacheEntry = this.selectorCache.get(request.hostname);
const previousHits = cacheEntry && cacheEntry.cosmetic || this.setRegister2;
const previousHits = cacheEntry && cacheEntry.cosmetic || this.dummySet$;

for ( const type in this.lowlyGeneric ) {
const entry = this.lowlyGeneric[type];
Expand Down Expand Up @@ -891,6 +893,10 @@ FilterContainer.prototype.retrieveGenericSelectors = function(request) {
excepted,
};

// Important: always clear used registers before leaving.
simpleSelectors.clear();
complexSelectors.clear();

// Cache and inject (if user stylesheets supported) looked-up low generic
// cosmetic filters.
if (
Expand Down Expand Up @@ -931,10 +937,6 @@ FilterContainer.prototype.retrieveGenericSelectors = function(request) {
});
}

// Important: always clear used registers before leaving.
this.setRegister0.clear();
this.setRegister1.clear();

//console.timeEnd('cosmeticFilteringEngine.retrieveGenericSelectors');

return out;
Expand All @@ -946,8 +948,6 @@ FilterContainer.prototype.retrieveSpecificSelectors = function(
request,
options
) {
//console.time('cosmeticFilteringEngine.retrieveSpecificSelectors');

const hostname = request.hostname;
const cacheEntry = this.selectorCache.get(hostname);

Expand Down Expand Up @@ -976,7 +976,11 @@ FilterContainer.prototype.retrieveSpecificSelectors = function(
};

if ( options.noCosmeticFiltering !== true ) {
const specificSet = this.setRegister1;
const specificSet = this.specificSet$;
const proceduralSet = this.proceduralSet$;
const exceptionSet = this.exceptionSet$;
const dummySet = this.dummySet$;

// Cached cosmetic filters: these are always declarative.
if ( cacheEntry !== undefined ) {
cacheEntry.retrieve('cosmetic', specificSet);
Expand All @@ -986,17 +990,30 @@ FilterContainer.prototype.retrieveSpecificSelectors = function(
}
}

const exceptionSet = this.setRegister0;
const proceduralSet = this.setRegister2;

// Retrieve filters with a non-empty hostname
this.specificFilters.retrieve(
hostname,
[ specificSet, exceptionSet, proceduralSet, exceptionSet ]
options.noSpecificCosmeticFiltering !== true
? [ specificSet, exceptionSet, proceduralSet, exceptionSet ]
: [ dummySet, exceptionSet, dummySet, exceptionSet ],
1
);
// Retrieve filters with an empty hostname
this.specificFilters.retrieve(
hostname,
options.noGenericCosmeticFiltering !== true
? [ specificSet, exceptionSet, proceduralSet, exceptionSet ]
: [ dummySet, exceptionSet, dummySet, exceptionSet ],
2
);
// Retrieve filters with a non-empty entity
if ( request.entity !== '' ) {
this.specificFilters.retrieve(
`${hostname.slice(0, -request.domain.length)}${request.entity}`,
[ specificSet, exceptionSet, proceduralSet, exceptionSet ]
options.noSpecificCosmeticFiltering !== true
? [ specificSet, exceptionSet, proceduralSet, exceptionSet ]
: [ dummySet, exceptionSet, dummySet, exceptionSet ],
1
);
}

Expand Down Expand Up @@ -1060,9 +1077,10 @@ FilterContainer.prototype.retrieveSpecificSelectors = function(
}

// Important: always clear used registers before leaving.
this.setRegister0.clear();
this.setRegister1.clear();
this.setRegister2.clear();
specificSet.clear();
proceduralSet.clear();
exceptionSet.clear();
dummySet.clear();
}

// CSS selectors for collapsible blocked elements
Expand Down Expand Up @@ -1115,8 +1133,6 @@ FilterContainer.prototype.retrieveSpecificSelectors = function(
}
}

//console.timeEnd('cosmeticFilteringEngine.retrieveSpecificSelectors');

return out;
};

Expand Down
Loading

12 comments on commit 23c4c80

@uBlock-user
Copy link
Contributor

@uBlock-user uBlock-user commented on 23c4c80 Sep 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Activate AdGuard Annoyances
Open the logger, browse to https://en.wikipedia.org/wiki/Lee_Holloway in another tab
Add @@||wikipedia.org^$elemhide to my filters and switch to the logger tab, click on any cosmetic filter shown in the logger from the page load for example -- #mw-head-base

image

Filterlist will not be found just after adding that filter, before adding the filter it would show Adguard Annoyances.

@gorhill
Copy link
Owner Author

@gorhill gorhill commented on 23c4c80 Sep 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not getting any cosmetic filter reported in the logger when using @@||wikipedia.org^$elemhide.

A reminder that old entries in the logger may not be reverse-looked up properly if the state of uBO changed, this was discussed somewhere in the past, which led to adding the message you see about not finding the filter.

@gwarser
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm getting this in uBO debugger console:

23:20:44.393 TypeError: this.hostnameSlotsEx is undefined static-ext-filtering.js:563:13

after update to b13 and pages stopped loading at all.

I started fiddling with https://testpages.adblockplus.org/en/exceptions/elemhide, maybe related.

@uBlock-user
Copy link
Contributor

@uBlock-user uBlock-user commented on 23c4c80 Sep 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A reminder that old entries in the logger may not be reverse-looked up properly if the state of uBO changed, this was discussed somewhere in the past, which led to adding the message you see about not finding the filter.

So that msg is to be expected after I add that filter for older entries ?

after update to b13 and pages stopped loading at all.

Total amount of cosmetic filters became 0 after update in Chromium --

image

I am not getting any cosmetic filter reported in the logger when using @@||wikipedia.org^$elemhide.

Do not reload the page after adding that filter.

@gwarser
Copy link
Contributor

@gwarser gwarser commented on 23c4c80 Sep 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I added to "My filters" filters from ABP test page. Problem starts after removing/commenting-out exception filter: @@testpages.adblockplus.org/en/exceptions/elemhide^$elemhide


Just adding it is breaking uBO?!


😪 🛌

@uBlock-user
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Picker and Zapper won't work if $elemhide is used now, is that to be expected too ?

@gorhill
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gwarser Is this Chromium or Firefox? It's as if your uBO loaded from an invalid selfie, thus causing this.hostnameSlotsEx is undefined static-ext-filtering.js. But the selfie magic number has been modified so the invalid selfie should have been scrapped. It's working as expected on my side.

@gorhill
Copy link
Owner Author

@gorhill gorhill commented on 23c4c80 Sep 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gwarser I tested back from 1.22.3b12 to 1.22.3b13 and all went well. The ABP test page worked fine and commenting out the filter worked. It's as if your uBO is in a bad state, maybe the storage is corrupted? Try to purge all caches to force a recompile of all filter lists.

@uBlock-user Yes, disabling both generic and specific is the equivalent of toggling off cosmetic filtering and thus this leads to #3212. I expect elemhide to rarely occur, it's mostly for filter list purpose (it's easier to just click the no-cosmetic-filtering button), and I see only two instances in whole EasyList.

@gorhill
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ugh I think I see an issue, but that is not the new code here, it's the change to the selfie manager made in this commit: 915687f#diff-73ef8c4664f2ec8c02320d50b2908efdR1100-R1113.

I need to fix asap before more users suffer the same issues as you do.

@gwarser
Copy link
Contributor

@gwarser gwarser commented on 23c4c80 Sep 22, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I was sleepy, it was midnight.

Browser was Firefox Nightly. I had added these filters in b12, noticed I did not updated uBO to latest version, so I did it by checking manually and turning off -> on. I think I noticed higher CPU usage, so interrupting something by turning uBO off/on could caused DB corruption.

I did reproduced right now just by adding filters in b12 and updating to b13.

Side note: Refined GitHub displays number of downloads in Releases -> Assets section. It's now 1.5k for b14 and 6.7k for b12.

@gwarser
Copy link
Contributor

@gwarser gwarser commented on 23c4c80 Sep 22, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh. I turned off uBO to post above comment, and after turning it on again all is working fine. (still b13 compiled locally)


List update flushed corrupted selfie?

@gorhill
Copy link
Owner Author

@gorhill gorhill commented on 23c4c80 Sep 22, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

List update flushed corrupted selfie?

Yes, selfie is invalidated when filter lists are updated due to change. With b13 you could end up loading an obsolete selfie if there was one available, leading to the error message you saw. Updating to b14 should fix everything.

Please sign in to comment.