Fixing Gaps: Strengthening the
Chromium Platform for Content
Blocking
myid.shin@igalia.com
ltilve@igalia.com
Agenda
● About Igalia
● New features for Content Blocking
● The need for tabs.removeCSS and extending exension new API
● What is Shadow Root / Why we need to access “closed shadow root”?
● Implement in Blink / Intent to Ship: blink-dev@
● For new extension API
● Implement in chrome / Proposal document / How to use
● Release schedule
● Future plans
About Igalia
● Open Source Consultancy with HQ in Galicia, Spain
○ 90 employees all around the world
○ Mainly specialized on Browsers and Web Engines:
○ Chromium, Firefox, WebKit and WPE
○ Compilers, JavaScript engines, Graphics, Multimedia, Accessibility
New features for Content Blocking
Add a chrome.tabs.removeCSS (https://crbug.com/608854)
Add a chrome.dom.openOrClosedShadowRoot (https://crbug.com/778816)
Apply content scripts to about: and data: urls (https://crbug.com/55084)
The need for tabs.removeCSS
● A way to hide blocked ads is by adding new CSS rules through existing
chrome.tabs.insertCSS
○ https://developer.chrome.com/extensions/tabs#method-insertCSS
● However, as content changes dynamically, it was necessary to have a
mechanism in Chromium to modify the visibility of elements that vary over
time.
● A removeCSS method as already available on other engines:
○ https://bugzilla.mozilla.org/show_bug.cgi?id=1247455
The need for tabs.removeCSS
● There was an open upstream issue for it (https://crbug.com/608854)
● An initial CL for it had been started by Manish Jethani but got discontinued
○ https://crrev.com/c/918606
● The bug was taken over and work completed by Antonio Gomes
○ Updated original CL to use the new APIs
○ Created new issue for “Extension API Modification: chrome.tabs.removeCSS”
(https://crbug.com/1101473)
○ Added the necessary functional tests
○ Iterated the through the review process
○ Got it landed (https://crrev.com/c/2250506)
● Implementation adds security restriction that extensions can only remove their
own injected CSS.
The need for tabs.removeCSS
tabs.removeCSS new API
● The new API method definition is added to
chrome/common/extensions/api/tabs.json
"name": "removeCSS",
"type": "function",
"description" “Remove CSS injected by $(ref:tabs.insertCSS).",
"parameters":
"tabId" : “ID of the tab from which to remove the CSS; defaults to active one.”
"details" : “Details of the CSS text to remove.”
"callback" : “Called when all the CSS has been removed.”
● And the new extension types objects into
extensions/common/api/extension_types.json
"id": "DeleteInjectionDetails",
"type": "object",
"description": "CSS to remove. Either the code or the file property, but not both",
"properties": {
"code" : “CSS code to remove”,
"file" : “CSS file to remove”,
"allFrames" : “If should be removed from all frames or just the top one”,
"frameId": “The frame from where the CSS should be removed”
tabs.removeCSS new API
● Function
chrome/test/data/extensions/api_test/executescript/remove_css/*
async function removeCSSWithFileShouldSucceed() {
// When no frame ID is specified, the CSS is removed from the top frame.
await testRemoveCSS({file}, [originalColor, , , , , ]);
chrome.test.succeed();
},
async function removeCSSWithDifferentFileShouldDoNothing() {
// The CSS is not removed even though "/file.css" and "/other.css" are identical.
await testRemoveCSS({file: '/other.css' , allFrames: true});
chrome.test.succeed();
},
tabs.removeCSS new API
tabs.removeCSS new API
● API doc https://developer.chrome.com/extensions/tabs#method-removeCSS
Adding Shadow Root access API
What is Shadow Root
Encapsulation : a component to have its very own “shadow” DOM tree.
https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM
What is Shadow Root
mode options to attach a shadow root
let shadow1 = element1.attachShadow({mode: 'open'});
let shadow2 = element2.attachShadow({mode: 'closed'});
element1.shadowRoot === shadow1; // true
element2.shadowRoot === null; // true
Why we need to access “closed shadow root”?
● Ads hidden behind closed shadow root
● Extensions APIs on the user's behalf
● Existing workaround using Extensions APIs
● NOT a security issue
● Firefox supports Element.openOrClosedShadowRoot
Implement in Blink
● Element.prototype.openOrClosedShadowRoot
● Specify API with Web IDL.
● But,
○ Do not expose it to general Web
○ Expose it to only isolated content script of Extensions
[Affects=Nothing, ExposedPerWorld=IsolatedWorld , NotEnumerable,
CheckSecurity=ReturnValue, Custom=Getter] readonly attribute
ShadowRoot? openOrClosedShadowRoot;
third_party/blink/renderer/core/dom/element.idl
Intent to Ship: blink-dev@
● The Chromium process to launch a new feature in Blink
○ https://www.chromium.org/blink/launching-features
● Two main concerns
○ Web namespace pollution
○ Web IDL lack for custom
○ https://groups.google.com/a/chromium.org/g/blink-dev/c/VEVXgm83UXk/m/iiIBCA
kXAgAJ
Element.prototype.openOrClosedShadowRoot
For new extension API
● Proposal :
https://chromium.googlesource.com/chromium/src/+/master/extensions/docs/
new_api_proposal.md
● Implementing :
https://www.chromium.org/developers/design-documents/extensions/propose
d-changes/creating-new-apis
Proposal document
(extension-api-reviews@chromium.org)
https://docs.google.com/document
/d/1Uj1Ff-3Kdbgb1JnCcZVj7EcWv
8jXj8wW2AlPfVfCUdI/edit?usp=sh
aring
Implement in chrome
● chrome.dom.openOrClosedShadowRoot
● Specify API with json
● C++ implementation
"namespace": "dom",
"functions": [{
"name": "openOrClosedShadowRoot",
"parameters": [{"name": "element", "type": "object"} ],
"returns": { "name": "shadowRoot", "type": "object" }
}]
chrome/common/extensions/api/dom.json
extensions/renderer/dom_hooks_delegate.{cc, h}
Implement in chrome
● chrome.dom.openOrClosedShadowRoot
● Specify API availability : content scripts & blessed contexts
● Unnecessary to specify permission, manifest entry and behavior availabilities
"dom": {
"channel": "dev",
"contexts": ["blessed_extension", "content_script"]
},
chrome/common/extensions/api/_api_features.json
How to use
let shadow1 = element1.attachShadow({mode: 'open'});
let shadow2 = element2.attachShadow({mode: 'closed'});
element1.shadowRoot === shadow1; // true
element2.shadowRoot === null; // true
chrome.dom.openOrClosedShadowRoot (element1) === shadow1; // true
chrome.dom.openOrClosedShadowRoot (element2) === shadow2; // true
Release schedule and future plans
Release schedule
● For chrome.tabs.removeCSS on M87
● For chrome.dom.openOrClosedShadowRoot on M87 / M88
Future plans and ongoing work
● Moving forward implementation of new CSS selectors to ease element hiding
○ Working on a prototype for :has() pseudo selector
https://github.com/w3c/csswg-drafts/issues/4903
○ Intent to proto type and ship of :dir() pseudo class
(https://chromium-review.googlesource.com/c/chromium/src/+/2460849)
○ Intent to ship complex :not()
(https://groups.google.com/a/chromium.org/g/blink-dev/c/0alTkXvDCL8/m/-ClOGv
OJBAAJ)
● Ongoing progress on increasing Chromium capabilities for content-blocking useful
features as more selectors, or incoming JS spec implementations.
Thanks

Fixing Gaps. Strengthening the Chromium platform for content blocking

  • 1.
    Fixing Gaps: Strengtheningthe Chromium Platform for Content Blocking myid.shin@igalia.com ltilve@igalia.com
  • 2.
    Agenda ● About Igalia ●New features for Content Blocking ● The need for tabs.removeCSS and extending exension new API ● What is Shadow Root / Why we need to access “closed shadow root”? ● Implement in Blink / Intent to Ship: blink-dev@ ● For new extension API ● Implement in chrome / Proposal document / How to use ● Release schedule ● Future plans
  • 3.
    About Igalia ● OpenSource Consultancy with HQ in Galicia, Spain ○ 90 employees all around the world ○ Mainly specialized on Browsers and Web Engines: ○ Chromium, Firefox, WebKit and WPE ○ Compilers, JavaScript engines, Graphics, Multimedia, Accessibility
  • 5.
    New features forContent Blocking Add a chrome.tabs.removeCSS (https://crbug.com/608854) Add a chrome.dom.openOrClosedShadowRoot (https://crbug.com/778816) Apply content scripts to about: and data: urls (https://crbug.com/55084)
  • 6.
    The need fortabs.removeCSS ● A way to hide blocked ads is by adding new CSS rules through existing chrome.tabs.insertCSS ○ https://developer.chrome.com/extensions/tabs#method-insertCSS ● However, as content changes dynamically, it was necessary to have a mechanism in Chromium to modify the visibility of elements that vary over time. ● A removeCSS method as already available on other engines: ○ https://bugzilla.mozilla.org/show_bug.cgi?id=1247455
  • 7.
    The need fortabs.removeCSS ● There was an open upstream issue for it (https://crbug.com/608854) ● An initial CL for it had been started by Manish Jethani but got discontinued ○ https://crrev.com/c/918606
  • 8.
    ● The bugwas taken over and work completed by Antonio Gomes ○ Updated original CL to use the new APIs ○ Created new issue for “Extension API Modification: chrome.tabs.removeCSS” (https://crbug.com/1101473) ○ Added the necessary functional tests ○ Iterated the through the review process ○ Got it landed (https://crrev.com/c/2250506) ● Implementation adds security restriction that extensions can only remove their own injected CSS. The need for tabs.removeCSS
  • 9.
    tabs.removeCSS new API ●The new API method definition is added to chrome/common/extensions/api/tabs.json "name": "removeCSS", "type": "function", "description" “Remove CSS injected by $(ref:tabs.insertCSS).", "parameters": "tabId" : “ID of the tab from which to remove the CSS; defaults to active one.” "details" : “Details of the CSS text to remove.” "callback" : “Called when all the CSS has been removed.”
  • 10.
    ● And thenew extension types objects into extensions/common/api/extension_types.json "id": "DeleteInjectionDetails", "type": "object", "description": "CSS to remove. Either the code or the file property, but not both", "properties": { "code" : “CSS code to remove”, "file" : “CSS file to remove”, "allFrames" : “If should be removed from all frames or just the top one”, "frameId": “The frame from where the CSS should be removed” tabs.removeCSS new API
  • 11.
    ● Function chrome/test/data/extensions/api_test/executescript/remove_css/* async functionremoveCSSWithFileShouldSucceed() { // When no frame ID is specified, the CSS is removed from the top frame. await testRemoveCSS({file}, [originalColor, , , , , ]); chrome.test.succeed(); }, async function removeCSSWithDifferentFileShouldDoNothing() { // The CSS is not removed even though "/file.css" and "/other.css" are identical. await testRemoveCSS({file: '/other.css' , allFrames: true}); chrome.test.succeed(); }, tabs.removeCSS new API
  • 12.
    tabs.removeCSS new API ●API doc https://developer.chrome.com/extensions/tabs#method-removeCSS
  • 13.
  • 14.
    What is ShadowRoot Encapsulation : a component to have its very own “shadow” DOM tree. https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM
  • 15.
    What is ShadowRoot mode options to attach a shadow root let shadow1 = element1.attachShadow({mode: 'open'}); let shadow2 = element2.attachShadow({mode: 'closed'}); element1.shadowRoot === shadow1; // true element2.shadowRoot === null; // true
  • 16.
    Why we needto access “closed shadow root”? ● Ads hidden behind closed shadow root ● Extensions APIs on the user's behalf ● Existing workaround using Extensions APIs ● NOT a security issue ● Firefox supports Element.openOrClosedShadowRoot
  • 17.
    Implement in Blink ●Element.prototype.openOrClosedShadowRoot ● Specify API with Web IDL. ● But, ○ Do not expose it to general Web ○ Expose it to only isolated content script of Extensions [Affects=Nothing, ExposedPerWorld=IsolatedWorld , NotEnumerable, CheckSecurity=ReturnValue, Custom=Getter] readonly attribute ShadowRoot? openOrClosedShadowRoot; third_party/blink/renderer/core/dom/element.idl
  • 18.
    Intent to Ship:blink-dev@ ● The Chromium process to launch a new feature in Blink ○ https://www.chromium.org/blink/launching-features ● Two main concerns ○ Web namespace pollution ○ Web IDL lack for custom ○ https://groups.google.com/a/chromium.org/g/blink-dev/c/VEVXgm83UXk/m/iiIBCA kXAgAJ Element.prototype.openOrClosedShadowRoot
  • 19.
    For new extensionAPI ● Proposal : https://chromium.googlesource.com/chromium/src/+/master/extensions/docs/ new_api_proposal.md ● Implementing : https://www.chromium.org/developers/design-documents/extensions/propose d-changes/creating-new-apis
  • 20.
  • 21.
    Implement in chrome ●chrome.dom.openOrClosedShadowRoot ● Specify API with json ● C++ implementation "namespace": "dom", "functions": [{ "name": "openOrClosedShadowRoot", "parameters": [{"name": "element", "type": "object"} ], "returns": { "name": "shadowRoot", "type": "object" } }] chrome/common/extensions/api/dom.json extensions/renderer/dom_hooks_delegate.{cc, h}
  • 22.
    Implement in chrome ●chrome.dom.openOrClosedShadowRoot ● Specify API availability : content scripts & blessed contexts ● Unnecessary to specify permission, manifest entry and behavior availabilities "dom": { "channel": "dev", "contexts": ["blessed_extension", "content_script"] }, chrome/common/extensions/api/_api_features.json
  • 23.
    How to use letshadow1 = element1.attachShadow({mode: 'open'}); let shadow2 = element2.attachShadow({mode: 'closed'}); element1.shadowRoot === shadow1; // true element2.shadowRoot === null; // true chrome.dom.openOrClosedShadowRoot (element1) === shadow1; // true chrome.dom.openOrClosedShadowRoot (element2) === shadow2; // true
  • 24.
  • 25.
    Release schedule ● Forchrome.tabs.removeCSS on M87 ● For chrome.dom.openOrClosedShadowRoot on M87 / M88
  • 26.
    Future plans andongoing work ● Moving forward implementation of new CSS selectors to ease element hiding ○ Working on a prototype for :has() pseudo selector https://github.com/w3c/csswg-drafts/issues/4903 ○ Intent to proto type and ship of :dir() pseudo class (https://chromium-review.googlesource.com/c/chromium/src/+/2460849) ○ Intent to ship complex :not() (https://groups.google.com/a/chromium.org/g/blink-dev/c/0alTkXvDCL8/m/-ClOGv OJBAAJ) ● Ongoing progress on increasing Chromium capabilities for content-blocking useful features as more selectors, or incoming JS spec implementations.
  • 27.