v155 · privacy sandbox · feature removal
An element with nowhere left to go
A fenced frame could not be given a URL. That was the whole design: the embedder hands over an opaque config it cannot read, and the frame renders something the page can neither address nor talk to. Chrome 152 removes the only two APIs that produced those configs, which leaves an element that renders a box, occupies no frame slot, and can never load anything. Chrome 154 and 155 finish the job.
concepts
-
The frame that cannot navigate
Call every route to a
FencedFrameConfigfor real and count how many hand one back. Then attach an element next to an ordinary iframe and measure what it costs: a layout box, no frame slot, no content window. -
What is left of window.fence
Enumerate
Fence.prototypeat runtime, call every method it declares, and read the exact refusal. Then sweep four browsing contexts to see where the property is anything other thannull. -
Shipping through the removal
Six feature-detection candidates graded against what each will report once the element is gone, and a slot that keeps filling because it asks for a config rather than for the element.
why it shipped
Fenced frames were the rendering half of Protected Audience and Shared Storage. An auction ran on the device, picked an ad, and returned a config; the page put that config on a <fencedframe> and the ad appeared without the page learning which one it was. Reporting from inside used window.fence, which routed through the browser because the frame had no channel to its embedder by design.
Those two APIs are removed in Chrome 152, and with them every way to produce a config. A <fencedframe> after that point is a well-specified element that nothing can fill: the constructor of FencedFrameConfig is not exposed to script, so a page cannot mint one itself. The removal proceeds in stages so nothing throws in the meantime — stubs in Chrome 154, where window.fence also goes, and then a field-trialled removal of the element in Chrome 155, after which the tag parses to an HTMLUnknownElement.
the three stages
| milestone | change | what breaks |
|---|---|---|
| 152 | Protected Audience and sharedStorage.selectURL() removed or stubbed | No new configs. Existing code gets null or a rejection rather than an exception. |
| 154 | window.fence removed; the element and FencedFrameConfig kept as stubs | Nothing, in practice — the API was only callable from inside a fenced frame, and no fenced frame can be loaded. |
| 155 | The element itself removed, behind a field trial first | <fencedframe> becomes HTMLUnknownElement. Code that checked for the element rather than for a config renders an empty box. |
what these pages measure
Built and driven on Chrome 150, which is before every stage of this removal, so the pages record the before side and are explicit about it. The element is present, Fence.prototype declares three methods, and all five config routes exist. What is also true on this build, and is the point: every one of those routes refuses. runAdAuction demands an https seller, selectURL demands a worklet module, new FencedFrameConfig() is an illegal constructor, and assigning a plain object to config is a TypeError. Zero configs, on a browser where nothing has been removed yet.
Every page reads the platform rather than the version string, so on a Chrome 152, 154 or 155 the same pages report the later state without modification — the route census returns "not present", the interface enumeration finds no Fence, and the detection matrix flips the two checks it says will flip.