Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filter cost cumulates on endless scrolling sites (facebook) and end up being disabled until reload #3335

Closed
stephen304 opened this issue Dec 10, 2017 · 11 comments

Comments

@stephen304
Copy link

stephen304 commented Dec 10, 2017

Filter issues MUST NOT be reported here. Read first: https://github.com/gorhill/uBlock/blob/master/CONTRIBUTING.md

Describe the issue

Adding a custom filter to filter facebook posts in my feed doesn't "stick", it stops working after reloading the page or also if you keep scrolling - you will see more sponsored posts that can be blocked by the exact same filter but were not blocked presumably because they loaded after uBlock checked.

One or more specific URLs where the issue occurs

https://www.facebook.com/

Screenshot in which the issue can be seen

2017-12-10-090517_514x657_scrot

Steps for anyone to reproduce the issue

  1. Go to facebook and find a sponsored post ("Sponsored" under the poster's name)
  2. Right click and hit block
  3. Paste in this filter ##body div[role="feed"] div[id^="hyperfeed_story_id_"]:if(div[id^="feed_subtitle_"] a:matches-css-after(content: "Sponsored"))
  4. It should highlight just the sponsored story
  5. Hit create
  6. Reload page
  7. Find another sponsored post
  8. Paste in the same filter
  9. Hit create
  10. Check custom filters - the same filter added twice and sponsored posts only filter right after clicking create, and stop working after the page reloads.

Your settings

100% Default settings

  • OS/version: Arch Linux
  • Browser/version: FF 57.02
  • uBlock Origin version: 1.14.20
Your filter lists

100% Default filters

Your custom filters (if any)
! 12/10/2017, 8:46:01 AM https://www.facebook.com/
facebook.com##body div[role="feed"] div[id^="hyperfeed_story_id_"]:if(div[id^="feed_subtitle_"] a:matches-css-after(content: "Sponsored"))
@ghost
Copy link

ghost commented Dec 10, 2017

I am not sure if this is a bug or just how XHR works (which the whole FB feed is based on and which probably relates to your step 7). If the XHR response loads a new DOM object (sponsored post) uBO may not be able to detect it the same way as loading the initial DOM. So if you want not to see sponsored posts perhaps there should be a way to block the XHR itself.

Personally I don't see any sponsored posts on FB at all. I use uMatrix with the following settings:

image

In uBO I have all the lists enabled (except those which are already in uMatrix). I also have 3 additional lists (remaining from older versions of uBO). You may want to have look at them, they are related to FB annoyances:

https://easylist-downloads.adblockplus.org/fb_annoyances_full.txt
https://easylist-downloads.adblockplus.org/fb_annoyances_newsfeed.txt
https://easylist-downloads.adblockplus.org/fb_annoyances_sidebar.txt

@stephen304
Copy link
Author

The curious thing to me though is that the feed initially loads via xhr as well, so I'm not sure if there's some timeout after which uBlock stops checking the page or if there's some bug in uBlock.

It seems to me that uBlock should be able to block content that's loaded after the fact, so I think it's something that should be supported since not supporting this provides a super easy way for advertisers to circumvent uBlock.

I tried adding the annoyances list but that doesn't seem to have any affect on the sponsored posts. The frustrating thing for me is that blocking via these css-style filters is clearly an intended function of uBlock, and I have a rule that works perfectly to pick out sponsored posts, but it just won't apply 100% of the time, so I think that's a bug.

@ghost
Copy link

ghost commented Dec 10, 2017

It is fairly easy to test if uBO applies cosmetic filtering to newly loaded (via XHR) DOM elements. Still it is better to block the loading of content rather than hiding it post-factum. That's why I use the combination uMatrix + uBO as explained. My rules in uBO are:

no-csp-reports: * true
behind-the-scene cello.client-channel.google.com * block
behind-the-scene facebook.com * block
behind-the-scene plus.google.com * block
behind-the-scene twimg.com * block
behind-the-scene twitter.com * block
behind-the-scene youtube.com * block
// I have added those because I have noticed that in Chromium some behind-the-scene requests are sent to these hosts

plus all the 3rd party lists. So whatever succeeds to pass through uMatrix has to pass through these too which is not an easy thing.

If you would like to stick with uBO you may try as a first step to enable all filters one by one and see if enabling any particular one results in not seeing sponsored posts any more. That would indicate that the particular list includes a static rule for that. If they still show up, you could try putting uBO in hard mode (check wiki). The third step would be to try my setting. And ultimately we should all stop using FB, block it on a DNS or even TCP level. Forever :)

@gorhill
Copy link
Owner

gorhill commented Dec 10, 2017

I tried your filter and I got this at the developer console for the page:

a

So this means the procedural filter is deemed CPU-expensive and uBO disables it.

@stephen304
Copy link
Author

Blocking at the request level would only work if only the sponsored post is loaded in that request. The feed loads a whole set of posts in a single request, so blocking the request would prevent the feed from loading any additional items.

@stephen304
Copy link
Author

stephen304 commented Dec 10, 2017

@gorhill I see, I wasn't checking the console. Do I just need to make the rule more specific? Add more direct ancestor operators perhaps, to avoid expensive exhaustive searches?

Looks like it wasn't disabling the filter for me until I scrolled down for a few more ajax requests.

@ghost
Copy link

ghost commented Dec 10, 2017

so blocking the request would prevent the feed from loading any additional items.

I tried turning off cosmetic filtering in FB, refreshing and still I don't see any sponsored posts when I scroll down. I haven't really investigated in depth. I was just trying to help by suggesting what works for me.

@gorhill
Copy link
Owner

gorhill commented Dec 10, 2017

I think I need to calculate the cost in a better way than how it is now. The current approach is quite naive (but easy to implement), and I put it in there as a quick fix to address the performance issue reported in #2984 (comment).

Your filter is not that bad, but the current way of computing cost needs to be better, it needs to assess the cost for the last say, 10 seconds, rather than compute the cost cumulatively forever.

@stephen304
Copy link
Author

Ah, that explains why it gets disabled after a few requests for me. I'll update the issue title to more accurately represent what the core issue is.

@T33REX I didn't mean to dismiss what works for you, it's a valid solution for some people. Unfortunately, facebook is really inconsistent about showing ads - I just had to scroll down about 20 or 30 ajax requests to get another one to show, so maybe if you keep scrolling you'll hit one. Or maybe your setup is somehow blocking it. I don't really have much desire to add uMatrix to my addons, since I like to avoid configured addons as much as possible (which is why I only run uBlock with default settings + a couple facebook custom rules).

@stephen304 stephen304 changed the title Custom filter doesn't work after page reload - only immediately after create is pressed Filter cost cumulates on endless scrolling sites (facebook) and end up being disabled until reload Dec 10, 2017
@stephen304
Copy link
Author

stephen304 commented Dec 10, 2017

So I actually noticed that uBlock's main filters file has several filters that get disabled due to this issue, so the filter's I've been adding are redundant I think:

facebook.com##div[id^="hyperfeed_story_id_"]:if(a:has-text(Chartered))
facebook.com##div[id^="hyperfeed_story_id_"]:if(a:has-text(Sponsored))
! https://forums.lanik.us/viewtopic.php?p=128997#p128997
facebook.com##[id^="hyperfeed_story_id_"]:if([id^="feed_subtitle_"] a[href]:matches-css-after(content:/Sponsored/))

@gorhill
Copy link
Owner

gorhill commented Dec 10, 2017

Alright, upon investigating all this, turns out things are much more complicated than I thought.

  • On Firefox, the cost of the div[id^="hyperfeed_story_id_"] filter is proportional to the size of the timeline. This of course makes sense, but the cost can become really high at some point.
  • Fluke cost times: with Chromium, I will sometimes see fluke high cost that bust the budget. These are rare, but they do happen. Could be caused by internal garbage collection, and this may have nothing to do with executing the filter itself.
  • When uBO disables a procedural cosmetic filters, it will cause all the previously targeted DOM elements by that filter to become visible. This should not happen.
  • It may happen that a procedural cosmetic filter which has become expensive, stops being expensive because large part of the DOM is simplified, for example if you navigate away from a long timeline in Facebook to a shorter one. This means that no procedural filter should be disabled forever, it should be temporary, and the recess should be proportional to the cost.

So I will come up with solution which addresses all these points.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants