brave / adblock-rust

Brave's Rust-based adblock engine
Mozilla Public License 2.0
1.41k stars 122 forks source link

Proposal: Browser-level element hiding #318

Open MasterKia opened 12 months ago

MasterKia commented 12 months ago

Currently sites can easily detect if elements (e.g. ads) are hidden (display: none, clip-path: circle(0), etc) using "getComputedStyle".

I did spoof the result of "getComputedStyle" using a Proxy and object.defineProperty but sites can still detect object tampering.

So my proposal is browser-level element hiding: Instead of "hiding" the element, add an option to prevent an element from rendering to the user's screen and GPU.

This way, sites can't detect hidden elements using Javascript.

0x416c69 commented 12 months ago

+1 This is absolutely necessary for the ad blocking community. They need a higher level of access to combat web developers, currently everyone hides ad related elements using unconventional detectable methods.

antonok-edm commented 11 months ago

It's an interesting idea, although I'm currently against it for a couple of reasons:

Implementation difficulties

Instead of "hiding" the element, add an option to prevent an element from rendering to the user's screen and GPU.

This way, sites can't detect hidden elements using Javascript.

I'm not 100% sure what's envisioned for the empty space left by hidden elements, but I see two potential options:

  1. Leave the empty space where the element would have rendered
    • This is technically feasible. In practice though, nobody wants to see the leftover empty spaces, and there will be pressure to develop corresponding (detectable) filters to collapse those spaces. For that reason, this doesn't sound like a useful option to me.
  2. Collapse the space where the element would have rendered
    • Faking the collapsed elements is going to be extremely difficult to implement, if it is even possible. Consider the methods getBoundingClientRect and getClientRects - these allow a webpage to determine the on-screen position and sizing of an HTML element. We can lie about the blocked element's dimensions, but what about its parent? What about its parent's parent? Collapsing rectangular sections of the page into "singularities" will necessarily affect the flow of the rest of the page, causing parts that wouldn't normally be visible to enter the screen. Lying about the coordinates will have cascading effects, and is likely to either be a leaky abstraction (i.e. detectable and therefore not useful) or result in page breakage.

Applicability to the broader community

absolutely necessary for the ad blocking community.

If such a syntax/feature were to be developed, there's no chance it'd be useful to anyone other than Brave at the moment. The wider adblocking community uses extensions. Such a capability will require deep integration with the renderer process. That isn't even possible on Mv2 extensions, let alone Mv3. I'd prefer to work on solutions that reduce, rather than increase, the fragmentation in the space already so that we can share more of the filter list development effort.

I'm reminded of a previous capability in adblock-rust called $explicitcancel. Without being restricted to extension APIs, it was possible to block network requests while still returning an apparent 200 OK status to the page context. This was viewed as an enhancement, since pages could no longer check for the failure of network requests to trigger anti-adblock mechanisms, so it became the default behavior unless opted-out with the $explicitcancel option. In practice, many sites would behave differently depending on the status of a blocked request, in a way that lead to breakage. Plus, it was still technically possible to detect that a request had been tampered with by checking side effects (e.g. the content of the request). The filter lists Brave uses from uBO were never developed to account for the feature, so it wasn't really their problem either. It was live for some time, but ultimately we removed it to improve compatibility (see https://github.com/brave/adblock-rust/issues/141 for more details).

0x416c69 commented 11 months ago

In practice though, nobody wants to see the leftover empty spaces

Certainly, as you mentioned the difficulties in altering the page layout, having only this functionality would benefit ad-blocking on persistent websites that constantly find various ways to detect modifications made by ad blockers. You may consider this as a hypothetical scenario, but @MasterKia was consistently trying to hide ads on a website and facing constant challenges. He even developed his own user script and extension, yet, as you mentioned, the extension API lacks in this regard. Therefore, I believe that this new API, which excludes an element from rendering, should only be used in the most extreme cases, and we already have such cases.

If such a syntax/feature were to be developed, there's no chance it'd be useful to anyone other than Brave at the moment

I don't mean to be rude or anything, but why would Brave want to be just another mainstream browser? In my opinion, this feature alone could attract many new users to Brave due to its more professional ad-blocking capabilities. I understand that deviating from the standard set by mv3 may not seem like a good idea, but this custom browser implementation could potentially inspire other major players like Mozilla to adopt a similar approach or improve upon the idea. However, every great initiative has to start somewhere.

This needs to stop: chrome_2023-10-10_14-50-35

JobcenterTycoon commented 5 months ago

Just to show how many sites do this already:

  1. Ad-Shield protected sites (15+ sites, many of them bigger like ygosu.com)
  2. dropgalaxy.com
  3. soft98.ir
  4. aternos.org
  5. decrypt.day
  6. megaup.net
  7. puzzle-loop.com group
  8. techcyan.com
  9. dragontea.ink
  10. ylilauta.org (removed at the moment but the results are unstable)
  11. t.hi098123.com issue

Most of these sites also using heavy script obfuscation, tampering/integrity checks, randomized function and variable names or even a tight CSP to hinder execution of scriptlets and custom userscripts.