The subresource_filter component deals with code that tags and filters subresource requests based on:
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).
At a high level, the component uses a memory mapped file of filtering rules to filter subresource requests in Blink, as well as subframe 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.
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.
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:
In the renderer, ownership looks like:
The content/browser code generally orchestrates the whole component.
Filtering for a given page is (mostly) triggered via Safe Browsing. The core class that encapsulates that logic is the
SubresourceFilterSafeBrowsingClientRequest The Safe Browsing client owns multiple Safe Browsing requests, and lives on the IO thread.
SubresourceFilterSafeBrowsingActivationThrottle checks every redirect URL speculatively, but makes an activation decision based on the last URL.
The ruleset has rules for allowlisting documents in specific ways. How a given document is activated is codified in the
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
AsyncDocumentSubresourceFilter This ownership is passed to the
This component also needs to filter subframes that match the ruleset. This is done by the
SubframeNavigationFilteringThrottle, which consults its parent frame's
ContentSubresourceFilterThrottleManager is a
WebContentsObserver, and manages both the
ActivationStateComputingNavigationThrottle and the
SubframeNavigationFilteringThrottle. It maintains a map of all the activated frames in the frame tree, along with that frame's current
AsyncDocumentSubresourceFilter, taken from the
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.
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
RenderFrameObserver that communicates with the