Implement header-based filtering
Background
We want to be able to filter requests based on the headers they return. (this has evolved from https://issues.adblockplus.org/ticket/7390)
Sometime the indication that content is an ad can only be found in the HTTP headers, so we want to be able to do that.
Filter syntax
Some research and test have shown that this can't be implemented as a snippet, as we can intercept resources loaded from <img>
or <script>
, and anything based on fetch()
might be secure as well and not expose the necessary information. So we need to have a filter syntax change, and a new matching strategy.
I propose the $header
option whose value is a key/value pair to match the header and a substring value of said header. The header name is always compared in a case insensitive manner.
||example.com/image/^$header=x-header=whatever
Spaces are allowed.
The comma (,
) is still used to separate the options in the filter syntax, so it is not allowed. A comma can be matched with \x2c
. To escape the escape the substring \\x2c
will be replaced by \x2c
to match as a substring.
An empty header name is invalid. An empty value mean the presence of the header.
Allowlisting: using @@
is allowed to signify allow all resource matching URL and header, or, with an empty $header
value, allow all resources matching URL that may have matched another $header
rule (this could be used to exclude a something that would have otherwise matched a rule with $header
, or to disable a rule). This type a allow filter can't be used to allow URL blocking filter that don't use HTTP filtering rule.
Filter with $header
will have the contentType of HEADER
. Matching in the Web Extension will be done against this contentType
. We don't need a different matcher. Care must be taken to check for allow list first.
Compatibility questions
Q: What if the option isn't supported
A: The filterClasses.js
code should reject the filter
Q: What if there is a match without the $header option on the same content? (ie the only difference between the two filters is the header option)
A: onBeforeRequest
occurs before onHeaderReceived
so the simpler blocking filter will match before the one with the $header
option.
What to change
- handle the new syntax in
filterClasses
- implement test for it
And then implement the necessary changes to adblockpluschrome
Integration notes
- The Web Extension will need to be updated to perform the header filtering. See issue adblockpluschrome#194 !256 (closed)
- The
contentTypes
constant have changed, so if you ever decided to use the values verbatim, you should change them accordingly (libadblockplus
)
Testing notes
TBD
Alternative
I have had a working alternative where the filter is a snippet filter that will simply send a message back to the background page that the content should be filtered based on header. It still requires changes in adblockpluschrome
, still requires a matcher strategy, but it doesn't require a filter syntax change and might introduce delays in the start of the content filtering.