Subresource Filter

The subresource_filter component deals with code that tags and filters subresource requests based on:

  1. Some page-level activation signal (e.g. should sub-resource filtering take place on this page).
  2. A ruleset used to match URLs for filtering.

The primary consumer of this component is Chrome's ad filter, which filters ads on pages that violate the Better Ads Standard.

Additionally, Chrome will filter pages Safe Browsing determines are used for phishing (i.e. on pages after the user has proceeded through the security interstitial).

High Level Description

At a high level, the component uses a memory mapped file of filtering rules to filter subresource requests in Blink, as well as child frame navigations in the browser process.

For historical reasons (intention to support iOS), code is split into two components, core and content. The core code is code that we could share with a non-content client like iOS, while all the content code depends on the Content API.

Most of the logic in core deals with reading, indexing, and matching URLs off a ruleset.

Most of the logic in content deals with tracking navigations, communicating with the renderer, and interacting with the //chrome client code.

Detailed Architecture

In this section, ‘=>’ represents strong ownership, and ‘~>’ is a weak reference.



Code in core/browser is responsible for writing and indexing filtering rules. The class that does most of this work is the RulesetService.


The RulesetService is responsible for indexing filtering rules into a Flatbuffer format, and writing them to disk. These rules come from the RulesetServiceDelegate as an UnindexedRuleset which will be downloaded via the Component Updater. It also performs other tasks like deleting obsolete rulesets.

The code in this component also maintains a global ConfigurationList, which defines how the entire subresource_filter component behaves.


The code in core/common deals with logic involved in filtering subresources that is used in both browser and renderer processes. The most important class is the DocumentSubresourceFilter which contains logic to filter subresources in the scope of a given document.

In the browser process ownership looks like: ContentSubresourceFilterThrottleManager=>AsyncDocumentSubresourceFilter=>DocumentSubresourceFilter

In the renderer, ownership looks like: DocumentLoader=>SubresourceFilter=>WebDocumentSubresourceFilterImpl=>DocumentSubresourceFilter



The content/browser code generally orchestrates the whole component.

Safe Browsing Integration - Page-level activation

Filtering for a given page is (mostly) triggered via Safe Browsing. The core class that encapsulates that logic is the SubresourceFilterSafeBrowsingActivationThrottle.

SubresourceFilterSafeBrowsingActivationThrottle=>SubresourceFilterSafeBrowsingClient=>SubresourceFilterSafeBrowsingClientRequest The Safe Browsing client owns multiple Safe Browsing requests, and lives on the IO thread.

Currently, the SubresourceFilterSafeBrowsingActivationThrottle checks every redirect URL speculatively, but makes an activation decision based on the last URL.

Document-level activation

The ruleset has rules for allowlisting documents in specific ways. How a given document is activated is codified in the ActivationState struct.

In order to notify a document in the renderer about how it should be activated, we read from the ruleset in the browser process and send an IPC to the frame at ReadyToCommitNavigationTime.

This logic is Handled by the ActivationStateComputingNavigationThrottle. ActivationStateComputingNavigationThrottle=>AsyncDocumentSubresourceFilter This ownership is passed to the ContentSubresourceFilterThrottleManager at ReadyToCommitNavigation time.

Child frame filtering

This component also needs to filter child frames that match the ruleset. This is done by the ChildFrameNavigationFilteringThrottle, which consults its parent frame's AsyncDocumentSubresourceFilter.

The code uses “root frame” and “child frame” terminology distinguish from the FrameTree-centric “main frame” and “subframe”. Frame trees may be embedded so that a single “tab” may have multiple “main frames”. In some cases (fenced frames) an embedded main frame is treated by the filter like a subframe; a main frame in a fenced frame is thus a subresource filter “child frame”. In others (portals), the embedded main frame establishes a new subresource filter root so it is a subresource filter “root frame”.

Throttle management

The ContentSubresourceFilterThrottleManager is a WebContentsObserver, and manages both the ActivationStateComputingNavigationThrottle and the ChildFrameNavigationFilteringThrottle. It maintains a map of all the activated frames in the frame tree, along with that frame's current AsyncDocumentSubresourceFilter, taken from the ActivationStateComputingNavigationThrottle.


Ruleset management

Ruleset management in the browser process is done with handles that live on the UI thread and access the ruleset asynchronously on a thread that allows IO.

In order to avoid accessing a potentially corrupt mmapped flatbuffers file in the browser process, the handles also provide verification.

ContentRulesetService=>VerifiedRulesetDealer::Handle=>VerifiedRulesetDealer ContentSubresourceFilterThrottleManager=>VerifiedRuleset::Handle=>VerifiedRuleset


The code in content/renderer deals with using the ruleset to match and filter resource requests made in the render process.

The most important class in the renderer is the SubresourceFilterAgent, the RenderFrameObserver that communicates with the ContentSubresourceFilterThrottleManager.