@eyeo/webext-ad-filtering-solution
v1.17.1
Published
eyeo's WebExtension Ad-Filtering Solution
Downloads
13,131
Maintainers
Keywords
Readme
eyeo's WebExtension Ad-Filtering Solution
This is a library that provides integration of eyeo's Ad Blocking Core
for Chromium and Firefox extensions (like Adblock Plus). The Ad
Blocking Core is in the core
directory. See the content of that directory
for further information.
Table of contents
Code of Conduct
All contributors to this project are required to read, and follow, our code of conduct.
Getting started
The library comes in two parts, ewe-api.js
to be included in the extension's
background page, and ewe-content.js
to be loaded as a content script. Please
download the latest build (or build the library yourself).
Additionally, the SDK provides standalone utilities that can work in both browser extension contexts, as well as other Javascript contexts.
With two versions of the API, Manifest V2 and Manifest V3, there are two different manifest that are needed depending on which API you target.
Supported browsers
The webext-ad-filtering-solution (as a short term we use 'engine') is tested on the following versions:
Manifest V2:
- Chromium 77 and latest
- Firefox 68 and latest
- Edge latest
Chromium 129 and newer do not support MV2 web extensions, so version "128.0.6613.0" is used for MV2 testing.
Manifest V3:
- Chromium 124 and latest
- Edge latest
Manifest for V2
For Manifest V2, the extension's manifest.json
is required to
include the following configuration:
{
"manifest_version": 2,
"background": {
"scripts": [
"ewe-api.js"
]
},
"content_scripts": [
{
"all_frames": true,
"js": [
"ewe-content.js"
],
"match_about_blank": true,
"matches": [
"http://*/*",
"https://*/*"
],
"run_at": "document_start"
}
],
"permissions": [
"webNavigation",
"webRequest",
"webRequestBlocking",
"scripting",
"storage",
"unlimitedStorage",
"tabs",
"<all_urls>"
]
}
Manifest for V3
For Manifest V3, the extension's manifest.json
is required to
include the following configuration:
{
"manifest_version": 3,
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"all_frames": true,
"js": [
"ewe-content.js"
],
"match_about_blank": true,
"matches": [
"http://*/*",
"https://*/*"
],
"run_at": "document_start"
}
],
"permissions": [
"declarativeNetRequest",
"scripting",
"storage",
"tabs",
"webNavigation",
"webRequest",
"unlimitedStorage"
],
"host_permissions": [
"<all_urls>"
],
"declarative_net_request": <output from "subs-generate" script>
}
The example above requires a couple of changes and can't be used as-is.
The service_worker
value needs be set to your built file for the
background script, that includes ewe-api.js
.
Please note that for the sample above, you need to make sure to set
the value of declarative_net_request
properly, as shown in the
decalrativeNetRequest
documentation.
This mean you also need to add to your extension build the files that contains
the rulesets declared in this section, as well as the text filter lists. Refer
to the Manifest V3 documentation for more details.
The permission declarativeNetRequestWithHostAccess
requires the
host_permissions
to be <all_urls>
. You could use the
declarativeNetRequest
permission without setting
host_permissions
. But it would have the effect of preventing the
filtering of content and limiting the blocking to network requests to
those specified in host_permissions
. The default configuration
provided offers the most functionality.
Required permissions and why we need them
We require several permissions for the WebExt Ad-Filtering Solution to function correctly. The manifest file templates above include the required permissions. Here is why we need each one:
webNavigation
: Gives access to the Web Navigation API, which we use to apply document-level allowing filters and to block popups.webRequest
: Gives access to the Web Request API. Used to apply URL filters in MV2, and to report on URL filters in MV3. Also used to retrieve sitekeys for a site.webRequestBlocking
(MV2 only): Allows blocking request based on URL filters in MV2.declarativeNetRequest
(MV3 only): Gives access to the Declarative Net Request API, which we use to apply URL filters in MV3.storage
: Gives access to storage APIs, which we use to store downloaded subscriptions, user's custom filters, etc.unlimitedStorage
: By default, extensions are only allowed 5MB of storage, which isn't enough for larger subscriptions. This permission removes that limit.tabs
: Gives access to some tab metadata, including the tab's URL, which is used to apply document-level allowing filters to the tab.scripting
: (MV3 and Firefox MV2 only) Used to apply content filters, including element hiding filters and snippet filters.<all_urls>
: Allows the WebExt Ad-Filtering Solution to act on all websites. Note that in MV2 manifests this goes in thepermissions
, but in MV3 manifests this goes in the newhost_permissions
section.
You can read more about browser extension permissions and their effects in Google's docs for MV2 permissions and MV3 permissions
API
The API will be available in your own background scripts through the
global EWE
object. Please call EWE.start()
to start blocking ads.
Note that in MV3 extensions, EWE.start()
must be called in the first
turn of the event loop so that it can attach event listeners.
Module bundlers (optional)
ewe-api.js
is built as a UMD module (Universal Module Definition),
and so it can also be used with module bundlers.
If using a module bundler do not add ewe-api.js
to your manifest.json
.
Consequently, there won't be a global EWE
object.
CommonJS
const EWE = require("@eyeo/webext-ad-filtering-solution");
EWE.start();
ESM
import * as EWE from "@eyeo/webext-ad-filtering-solution";
EWE.start();
You can also import the content script. This should only be included once by an extension, since it starts running the content scripts without the need to call any sort of "start" function.
import "@eyeo/webext-ad-filtering-solution/content";
Individual utilities that can be used in any context can also be imported.
import {Scheduler} from "@eyeo/webext-ad-filtering-solution/all/scheduler.js";
Snippet filters support
In order to enable support for snippet filters you have to get
the snippets library separately and make it available to EWE
:
import * as snippets from "@eyeo/snippets";
EWE.snippets.setLibrary({
injectedCode: snippets.main,
isolatedCode: snippets.isolated
});
The integration of the machine learning models is expected to be done by clients of the snippet library.
Shared resources
There are some shared resources that are used by both webext-ad-filtering-solution & production code:
browser
- Global is set by webextension-polyfill version 0.8.0.
browser.runtime.connect()
/browser.runtime.onConnect
- Channel name is prefixed with "ewe:".
browser.runtime.sendMessage()
/browser.runtime.onMessage
- Our messages are objects with a "type" property whose value is prefixed with "ewe:".
indexedDB.open()
- Database name is prefixed with "EWE".
- Web page links
- Links used by module are prefixed with "abp:" or "https://subscribe.adblockplus.org/".
browser.storage.local
andbrowser.storage.session
- Storage keys are prefixed with either "ewe:" or "abp:pref:".
During initialization the engine migrates legacy data from
local storage to indexedDB. Files migrated have to be prefixed: file:
.
Files prefixed with file:///
will be ignored.
Notifications support
Using the notifications module is optional. To start using it, an initialisation is required:
EWE.notifications.start();
One Click Allowlisting support
To enable One Click Allowlisting, you need to set the list of authorized public keys that can be used to authenticate allowlisting requests.
EWE.allowlisting.setAuthorizedKeys(keys);
See the allowlisting module docs for more detail.
New keypairs can be created with the correct algorithm and settings by using our keypair creation script.
npm run create-allowlisting-keypair
See the Development section below for details on running our scripts
and other EWE development tasks. Keys can also be generated using
other programs like OpenSSL. The keys use the RSASSA-PKCS1-v1_5
algorithm, SHA512 hash and 4096 bit long modulus. Additionally, when
passed to setAuthorizedKeys
, the keys should be base64 encoded
strings, in SPKI format.
Documentation
For more information, please refer to the API documention.
Development
Prerequisites
- Node >= 18.16
- npm >= 9
Installing/Updating dependencies
npm install
Building the library
npm run build
Running Locally (and watch for changes)
npx webpack --watch
Custom builds
Our build script is a CLI program with a few additional flags that can
be passed to it. It can list the options available if you ask for
--help
.
npm run build -- --help
There are some specific flags which might be useful to customise the build:
# Build only engine, no test extensions
npm run build -- --config-name engine
# Don't generate any sourcemaps
npm run build -- --no-devtool
In the background, this script is using Webpack. You can also see the webpack command line options for further information on these flags.
Managing Bundled Subscriptions in the test build
In MV3 extensions (and the MV3 test extension), subscriptions are bundled statically at build time. The bundled subscriptions are based on the custom subscriptions file. Bundled subscriptions are updated by the build script if this file changes.
One case to look out for when working with bundled subscriptions in
tests is that subscriptions are NOT re-fetched if their filters have
changed. If you need to re-fetch new filters and the list of
subscriptions hasn't changed, you can use the
--force-subscription-update
flag to the build script.
npm run build -- --force-subscription-update
Using your own test-server instance
By default, the build script will start up the test server for
updating bundled subscriptions. If you prefer to use a test server
which is already running, you can use the --use-external-server
flag.
npm run test-server&
npm run build -- --use-external-server
Release builds
By default, debug builds are created. If building the library to be used in another project you would want to create a release build.
npm run build:release
Building the documentation
npm run docs
Linting the code
npm run lint
Events
The library provides the listeners to observe the events:
EWE.allowlisting.onUnauthorized
: Emitted when an allowlisting request is rejectedEWE.filters
:onAdded
: Emitted when a new filter is addedonChanged
: Emitted when a filter is either enabled or disabled or metadata changedonRemoved
: Emitted when a filter is removed
EWE.subscriptions
:onAdded
: Emitted when a new subscription is addedonChanged
: Emitted when any property of the subscription has changedonRemoved
: Emitted when a subscription is removed
EWE.debugging.onLogEvent
: Emitted when having debug outputEWE.reporting.onBlockableItem
: Emitted when any blockable item is matchedEWE.cdp.onCdpItem
: Emitted when any CDP event happened
Use addListener(...)
to subscribe and removeListener(...)
to unsubscribe.
Manifest V3
See the Manifest V3 documentation for further explanations.
Testing
For full documentation about testing please refer to our testing document.