Run separate instances of the filtering engine
Using multiple filtering configurations
In the previous section you've learned how to configure ad-filtering. But the underlying filtering engine is more capable.
It could, for example:
- block intrusive trackers,
- block age-sensitive material,
- filter geo-limited content,
- remove arbitrary unwanted content from the user's browsing experience
As long as you can express the filtering demands via the filtering language, you can probably use the SDK to implement the behavior.
This section describes how to introduce new aspects of content filtering independently of ad-filtering.
A filtering configuration is a named, independent set of filtering options that are applied to network requests and website content.
Each filtering configuration has the following parameters:
Parameter | Description |
---|---|
Name | Unique name of this configuration |
Enabled | Whether this entire configuration is currently enabled and active |
Filter lists | List of currently selected filter lists, typically identified by URLs |
Allowed domains | List of domains exempt from filtering |
Custom filters | List of individual filters installed in addition to those from filter lists |
These parameters are very similar to the ones you encountered in the previous section. In fact, the ad-filtering settings are implemented as a filtering configuration - with the name
adblock
. It is created by default in the SDK. You can redundantly access it via the filtering configuration API if you want.The
AdblockController
or adblock_private
APIs, described previously, expose courtesy functions to enable or disable Acceptable Ads. In the more generic filtering configuration APIs, the Acceptable Ads filter list is just a filter list, it can be added or removed as such.Filtering configurations are independent, meaning each can be enabled, disabled or reconfigured separately from the others. Each maintains its own list of installed filter lists, custom filters and allowed domains.
What happens when one filtering configuration classifies a resource as blocked while another classifies it as allowed?
The blocking decision always wins.
This is a design decision. An example to rationalize it:
- Perhaps filtering configuration
adblock
is an ad-filtering configuration and has a blanket rule to block every URL with anad
substring. - However, the user has allowlisted
example.com
by adding it toadblock
's allowed domains, therefore filtering configurationadblock
classifieshttps://example.com/ad.png
as an allowed resource. - Filtering configuration
sfw
is an age-restricting configuration and it has a blocking filter forhttps://example.com/ad.png
- not because it's an ad, but because it contains inappropriate content. - The blocking decision from filtering configuration
sfw
"wins", the inappropriate ad is blocked.
Each filtering configuration must be installed on each browser start.
The configuration's settings are persistent and will be loaded upon installation.
Java
JavaScript
C++
import org.chromium.components.adblock.FilteringConfiguration;
// Only needed once per browser start.
// FilteringConfiguration's constructor installs the configuration if needed.
FilteringConfiguration myConfiguration = new FilteringConfiguration("my_configuration");
// Only needed once per browser start.
// No-op if configuration already exists.
chrome.eyeoFilteringPrivate.createConfiguration("my_configuration")
#include "chrome/browser/adblock/subscription_service_factory.h"
#include "components/adblock/core/configuration/persistent_filtering_configuration.h"
#include "components/adblock/core/subscription/subscription_service.h"
// Only needed once per browser start.
auto my_configuration =
std::make_unique<PersistentFilteringConfiguration>(profile()->GetPrefs(),
"my_configuration");
SubscriptionServiceFactory::GetForBrowserContext(profile())
->InstallFilteringConfiguration(std::move(configuration));
Java
JavaScript
C++
// Currently no API
// Without promises:
chrome.eyeoFilteringPrivate.getConfigurations(function(configs) {
// configs = ['adblock', 'my_configuration']
// 'adblock' installed by default by AdblockController.
// 'my_configuration' installed by previous example.
});
// With promises:
await chrome.eyeoFilteringPrivate.getConfigurations().then(
configs => {
// configs = ['adblock', 'my_configuration']
});
#include "chrome/browser/adblock/subscription_service_factory.h"
#include "components/adblock/core/configuration/filtering_configuration.h"
#include "components/adblock/core/subscription/subscription_service.h"
SubscriptionService* subscription_service =
SubscriptionServiceFactory::GetForBrowserContext(profile());
const std::vector<FilteringConfiguration*> configurations =
subscription_service->GetInstalledFilteringConfigurations();
// "adblock" installed by default by AdblockController.
// "my_configuration" installed by previous example.
configurations[0]->GetName(); // "adblock"
configurations[1]->GetName(); // "my_configuration"
By default, each configuration starts as enabled. If you disable it, the state persists and the configuration starts as disabled next time the browser runs.
The following example disables
my_configuraion
:Java
JavaScript
C++
import org.chromium.components.adblock.FilteringConfiguration;
// myConfiguration created by previous example.
myConfiguration.isEnabled(); // true
myConfiguration.setEnabled(false);
myConfiguration.isEnabled(); // false
// "my_configuration" created by previous example.
// Without promises:
chrome.eyeoFilteringPrivate.isEnabled('my_configuration', function(enabled) {
// enabled == true
});
// With promises:
chrome.eyeoFilteringPrivate.setEnabled('my_configuration', false)
.then(
() => {chrome.eyeoFilteringPrivate.isEnabled('my_configuration')
.then(
enabled => {
// enabled == false;
})});
#include "components/adblock/core/configuration/filtering_configuration.h"
FilteringConfiguration* my_configuration =
...; // Created or retrieved by previous examples.
my_configuration->IsEnabled(); // true
my_configuration->SetEnabled(false);
my_configuration->IsEnabled(); // false
Filter lists are identified by URLs from which they are downloaded.
When you add a new filter list, a download starts, the list is then converted and installed. When you remove a filter list, it is uninstalled and removed from disk.
All changes to the filter lists configuration happen immediately, synchronously. The actual installation is asynchronous. You may observe installation progress separately.
Java
JavaScript
C++
import org.chromium.components.adblock.FilteringConfiguration;
// myConfiguration created by previous example.
List<URL> filterLists = myConfiguration.getFilterLists();
// filterLists == []
URL filterList = new URL("http://filters.com/list.txt");
myConfiguration.addFilterList(filterList);
filterLists = myConfiguration.getFilterLists();
// filterLists == ["http://filters.com/list.txt"]
myConfiguration.removeFilterList(filterList);
filterLists = myConfiguration.getFilterLists();
// filterLists == []
// "my_configuration" created by previous example.
// Without promises:
chrome.eyeoFilteringPrivate.getFilterLists(
'my_configuration', function(subscriptions) {
// subscriptions == []
});
// With promises:
const filterList = 'http://filters.com/list.txt';
await chrome.eyeoFilteringPrivate
.subscribeToFilterList('my_configuration', filterList)
.then(
() => {chrome.eyeoFilteringPrivate.getFilterLists('my_configuration')
.then(
subscriptions => {
// subscriptions = ['http://filters.com/list.txt']
})});
await chrome.eyeoFilteringPrivate
.unsubscribeFromFilterList('my_configuration', filterList)
.then(
() => {chrome.eyeoFilteringPrivate.getFilterLists('my_configuration')
.then(
subscriptions => {
// subscriptions = []
})});
#include "components/adblock/core/configuration/filtering_configuration.h"
FilteringConfiguration* my_configuration =
...; // Created or retrieved by previous examples.
std::vector<GURL> filter_lists = my_configuration->GetFilterLists();
// filter_lists == []
const GURL filter_list("http://filters.com/list.txt");
my_configuration->AddFilterList(filter_list);
filter_lists = my_configuration->GetFilterLists();
// filter_lists == ["http://filters.com/list.txt"]
my_configuration->RemoveFilterList(filter_list);
filter_lists = my_configuration->GetFilterLists();
// filter_lists == []
When you add a filter list to a configuration, the configuration is updated instantly but the download and installation may take several seconds. If you want to be notified when an installation completes, you can register an observer.
Java
JavaScript
C++
import org.chromium.components.adblock.FilteringConfiguration;
public class MySubscriptionUpdateObserver
implements FilteringConfiguration.SubscriptionUpdateObserver {
@Override
public void onSubscriptionDownloaded(final URL url) {
// url == "http://filters.com/list.txt"
}
}
MySubscriptionUpdateObserver observer = new MySubscriptionUpdateObserver();
// myConfiguration created by previous example.
myConfiguration.addSubscriptionUpdateObserver(observer);
URL filterList = new URL("http://filters.com/list.txt");
myConfiguration.addFilterList(filterList);
// Wait until download completes
// observer.onSubscriptionDownloaded("http://filters.com/list.txt") is called
// "my_configuration" created by previous example.
const filterList = 'http://filters.com/list.txt';
chrome.eyeoFilteringPrivate.onSubscriptionUpdated.addListener(function(url) {
// url == 'http://filters.com/list.txt'
});
await chrome.eyeoFilteringPrivate.subscribeToFilterList(
'my_configuration', filterList);
// Wait until download completes
// the listener is called
#include "components/adblock/core/configuration/filtering_configuration.h"
#include "components/adblock/core/subscription/subscription_service.h"
class Observer : public SubscriptionService::SubscriptionObserver {
public:
void OnSubscriptionInstalled(const GURL& subscription_url) override {
// subscription_url == "http://filters.com/list.txt"
}
};
FilteringConfiguration* my_configuration =
...; // Created or retrieved by previous examples.
Observer observer;
SubscriptionServiceFactory::GetForBrowserContext(profile())->AddObserver(
&observer);
const GURL filter_list("http://filters.com/list.txt");
my_configuration->AddFilterList(filter_list);
// Wait until download completes
// Observer::OnSubscriptionInstalled is called
The SDK will also trigger this notification every time it successfully installs an update to the filter list, for example as a result of a scheduled, periodic update check.
To effectively disable all content filtering on a specific domain, add an allowed domain.
Remember, this allows all content on the domain, not from the domain. Adding
trusted.org
will let ads appear while the user is browsing https://www.trusted.org
. But when the user is browsing https://example.com
which attempts to load https://www.trusted.org/ads.js
, the filtering still applies and the script might be blocked.Java
JavaScript
C++
import org.chromium.components.adblock.FilteringConfiguration;
String allowedDomain = "trusted.org";
// myConfiguration created by previous example.
myConfiguration.addAllowedDomain(allowedDomain);
List<String> allowedDomains = myConfiguration.getAllowedDomains();
// allowedDomains = ["trusted.org"]
// The SDK will not filter any content on trusted.org.
// "my_configuration" created by previous example.
const allowed_domain = 'trusted.org';
chrome.eyeoFilteringPrivate.addAllowedDomain(
'my_configuration', allowed_domain);
chrome.eyeoFilteringPrivate.getAllowedDomains(
'my_configuration', function(domains) {
// domains == ['trusted.org']
});
// The SDK will not filter any content on trusted.org.
#include "components/adblock/core/configuration/filtering_configuration.h"
FilteringConfiguration* my_configuration =
...; // Created or retrieved by previous examples.
const std::string allowed_domain = "trusted.org";
my_configuration->AddAllowedDomain(allowed_domain);
std::vector<std::string> allowed_domains =
my_configuration->GetAllowedDomains();
// allowed_domains = ["trusted.org"]
// The SDK will not filter any content on trusted.org.
Custom filters are filters that are not present on any of the installed filter list but are added individually, via the following API. The SDK treats custom filters the same way as ordinary filters.
Java
JavaScript
C++
import org.chromium.components.adblock.FilteringConfiguration;
// Filter that allows every resource from trusted.org or its subdomains.
String filter = "@@||trusted.org";
// myConfiguration created by previous example.
myConfiguration.addCustomFilter(filter);
List<String> customFilters = myConfiguration.getCustomFilters();
// customFilters = ["@@||trusted.org"]
// Filter that allows every resource from trusted.org or its subdomains.
const filter = '@@||trusted.org';
// "my_configuration" created by previous example.
chrome.eyeoFilteringPrivate.addCustomFilter(
'my_configuration', filter);
chrome.eyeoFilteringPrivate.getCustomFilters(
'my_configuration', function(filters) {
// filters == ['@@||trusted.org']
});
#include "components/adblock/core/configuration/filtering_configuration.h"
FilteringConfiguration* my_configuration =
...; // Created or retrieved by previous examples.
const std::string filter = "@@||trusted.org";
my_configuration->AddCustomFilter(filter);
std::vector<std::string> custom_filters =
my_configuration->GetCustomFilters();
// custom_filters = ["@@||trusted.org"]
If you'd like to be notified when some piece of code changes a filtering configuration, you may register an observer:
Java
JavaScript
C++
import org.chromium.components.adblock.FilteringConfiguration;
public class MyConfigurationChangeObserver
implements FilteringConfiguration.ConfigurationChangeObserver {
@Override
public void onEnabledStateChanged() {
// runs when someone calls setEnabled() to set a new state
}
@Override
public void onFilterListsChanged() {
// runs when someone adds or removes filter lists
}
@Override
public void onAllowedDomainsChanged() {
// runs when someone adds or removes allowed domains
}
@Override
public void onCustomFiltersChanged() {
// runs when someone adds or removes custom filters
}
}
MyConfigurationChangeObserver observer = new MyConfigurationChangeObserver();
// myConfiguration created by previous example.
myConfiguration.addObserver(observer);
URL filterList = new URL("http://filters.com/list.txt");
myConfiguration.addFilterList(filterList);
// observer.onFilterListsChanged() is called
// "my_configuration" created by previous example.
chrome.eyeoFilteringPrivate.onEnabledStateChanged.addListener(
'my_configuration', function() {
// runs when someone calls setEnabled() to set a new state
});
chrome.eyeoFilteringPrivate.onFilterListsChanged.addListener(
'my_configuration', function() {
// runs when someone adds or removes filter lists
});
chrome.eyeoFilteringPrivate.onAllowedDomainsChanged.addListener(
'my_configuration', function() {
// runs when someone adds or removes allowed domains
});
chrome.eyeoFilteringPrivate.onCustomFiltersChanged.addListener(
'my_configuration', function() {
// runs when someone adds or removes custom filters
});
const filterList = 'http://filters.com/list.txt';
await chrome.eyeoFilteringPrivate.subscribeToFilterList(
'my_configuration', filterList);
// the second listener is called
#include "components/adblock/core/configuration/filtering_configuration.h"
class Observer : public FilteringConfiguration::Observer {
public:
void OnEnabledStateChanged(FilteringConfiguration* config) override {
// runs when someone calls SetEnabled() to set a new state
}
void OnFilterListsChanged(FilteringConfiguration* config) override {
// runs when someone adds or removes filter lists
}
void OnAllowedDomainsChanged(FilteringConfiguration* config) override {
// runs when someone adds or removes allowed domains
}
void OnCustomFiltersChanged(FilteringConfiguration* config) override {
// runs when someone adds or removes custom filters
}
};
FilteringConfiguration* my_configuration =
...; // Created or retrieved by previous examples.
Observer observer;
my_configuration->AddObserver(&observer);
const GURL filter_list("http://filters.com/list.txt");
my_configuration->AddFilterList(filter_list);
// Observer::OnFilterListsChanged is called
If you wish to be notified when network resources are blocked or allowed, register as an observer.
You don't observe a single filtering configuration because all installed filtering configurations take part in classification - see Interactions between filtering configurations.
Java
JavaScript
C++
import org.chromium.components.adblock.ResourceClassificationNotifier;
public class MyClassificationObserver implements ResourceClassificationNotifier.AdBlockedObserver {
@Override
public void onAdAllowed(AdblockCounters.ResourceInfo info) {
// Runs when a resource is specifically allowed by an
// allowing filter from a filtering configuration
// and isn't blocked by other filtering configurations.
}
@Override
public void onAdBlocked(AdblockCounters.ResourceInfo info) {
// Runs when a resource is blocked by a blocking filter
// from at least one enabled filtering configuration.
}
@Override
public void onPageAllowed(AdblockCounters.ResourceInfo info) {
// Runs when every enabled filtering configuration exempts
// this domain from filtering via allowed domains.
}
@Override
public void onPopupAllowed(AdblockCounters.ResourceInfo info) {
// Runs when a popup window is specifically allowed by an
// allowing filter from a filtering configuration
// and isn't blocked by other filtering configurations.
}
@Override
public void onPopupBlocked(AdblockCounters.ResourceInfo info) {
// Runs when a popup window is blocked by a blocking filter
// from at least one enabled filtering configuration.
}
}
MyClassificationObserver observer = new MyClassificationObserver();
ResourceClassificationNotifier.getInstance().addOnAdBlockedObserver(observer);
chrome.eyeoFilteringPrivate.onRequestAllowed.addListener(function(info) {
// Runs when a resource is specifically allowed by an
// allowing filter from a filtering configuration
// and isn't blocked by other filtering configurations.
});
chrome.eyeoFilteringPrivate.onRequestBlocked.addListener(function(info) {
// Runs when a resource is blocked by a blocking filter
// from at least one enabled filtering configuration.
});
chrome.eyeoFilteringPrivate.onPageAllowed.addListener(function(info) {
// Runs when every enabled filtering configuration exempts
// this domain from filtering via allowed domains.
});
chrome.eyeoFilteringPrivate.onPopupAllowed.addListener(function(info) {
// Runs when a popup window is specifically allowed by an
// allowing filter from a filtering configuration
// and isn't blocked by other filtering configurations.
});
chrome.eyeoFilteringPrivate.onPopupBlocked.addListener(function(info) {
// Runs when a popup window is blocked by a blocking filter
// from at least one enabled filtering configuration.
});
#include "chrome/browser/adblock/resource_classification_runner_factory.h"
#include "components/adblock/content/browser/resource_classification_runner.h"
class MyClassificationObserver : public ResourceClassificationRunner::Observer {
public:
void void OnAdMatched(const GURL& url,
FilterMatchResult match_result,
const std::vector<GURL>& parent_frame_urls,
ContentType content_type,
content::RenderFrameHost* render_frame_host,
const GURL& subscription) override {
if (match_result == FilterMatchResult::kAllowRule) {
// Runs when a resource is specifically allowed by an
// allowing filter from a filtering configuration
// and isn't blocked by other filtering configurations.
}
if (match_result == FilterMatchResult::kBlockRule) {
// Runs when a resource is blocked by a blocking filter
// from at least one enabled filtering configuration.
}
}
void void OnPageAllowed(const GURL& url,
content::RenderFrameHost* render_frame_host,
const GURL& subscription) override {
// Runs when every enabled filtering configuration exempts
// this domain from filtering via allowed domains.
}
void void OnPopupMatched(const GURL& url,
FilterMatchResult match_result,
const GURL& opener_url,
content::RenderFrameHost* render_frame_host,
const GURL& subscription) override {
if (match_result == FilterMatchResult::kAllowRule) {
// Runs when a popup window is specifically allowed by an
// allowing filter from a filtering configuration
// and isn't blocked by other filtering configurations.
}
if (match_result == FilterMatchResult::kBlockRule) {
// Runs when a popup window is blocked by a blocking filter
// from at least one enabled filtering configuration.
}
}
};
MyClassificationObserver observer;
ResourceClassificationRunnerFactory::GetForBrowserContext(profile())
->AddObserver(&observer);
Last modified 18d ago