将内容安全地嵌入到网页中,而不会共享跨网站数据。
实现状态
本文档简要介绍了一种新的 HTML 元素:<fencedframe>
。
- 围栏框架提案现已正式发布。
- Chrome 平台状态
Proposal | Status |
---|---|
Web API changes for urn to config Explainer |
Available in Chrome in Q1 2023. |
Creative Macros in Fenced Frames for Ads Reporting (FFAR) GitHub Issue |
Available in Chrome in Q3 2023. |
Send Automatic Beacons Once GitHub Issue |
Available in Chrome in Q3 2023. |
Serializable Fenced Frames Configs GitHub Issue |
Available in Chrome in Q3 2023. |
Additional Format Option for Protected Audience Ad Size Macros GitHub Issue |
Available in Chrome in Q4 2023. |
Automatic beacons sending to all registered URLs GitHub Issue | GitHub Issue |
Available in Chrome in Q4 2023. |
Enable Leaving Ad Interest Groups from Urn iFrames and Ad Component Frames
GitHub issue |
Available in Chrome in Q1 2024 |
Introduce reserved.top_navigation_start/commit
GitHub issue, GitHub issue |
Available in Chrome in Q1 2024 |
Do Not Disable Cookie Setting in ReportEvent until 3PCD
GitHub issue |
Available in Chrome in Q1 2024 |
Add support for automatic beacons in cross-origin subframes
GitHub issue |
Available in Chrome in Q1 2024 |
Allow Cross-Origin Subframes to Send reportEvent() Beacons
GitHub issue |
Available in Chrome in Q2 2024 |
为什么需要使用围栏帧?
围栏框架 (<fencedframe>
) 是一种用于嵌入内容的 HTML 元素,类似于 iframe。与 iframe 不同,围栏框架会限制与其嵌入上下文的通信,以允许该框架访问跨网站数据,而无需与嵌入上下文共享这些数据。某些 Privacy Sandbox API 可能要求在围栏框架中呈现部分文档。
同样,嵌入情境中的任何第一方数据都无法与围栏帧共享。
例如,如果 news.example
(嵌入上下文)在 fenced 框架中嵌入了 shoes.example
中的广告,则 news.example
无法从 shoes.example
广告中提取数据,而 shoes.example
也无法从 news.example
中学习第一方数据。
通过存储分区加强跨网站隐私保护
在浏览网页时,您可能曾在某个网站上查看过某些商品,然后又在完全不同的网站上的广告中看到了这些商品。
目前,这种广告技术主要通过跟踪技术实现,该技术使用第三方 Cookie 在各个网站之间共享信息。
Chrome 正在开发存储分区功能,该功能可按网站划分浏览器存储空间。如果不进行分区,如果 shoes.example
中的 iframe 嵌入在 news.example
上,并且该 iframe 将值存储到存储空间中,则可以从 shoes.example
网站读取该值。存储空间分区后,跨网站 iframe 将不再共享存储空间,因此 shoes.example
将无法访问 iframe 存储的信息。如果 iframe 从 *.shoes.example
提供并嵌入到 *.shoes.example
中,浏览器存储空间将会共享,因为它们被视为同一网站。
存储分区将应用于标准存储 API,包括 localStorage、IndexedDB 和 Cookie。在分区世界中,第一方存储空间中的信息泄露将大大减少。
处理跨网站数据
围栏框架是一项 Privacy Sandbox 功能,建议顶级网站应对数据进行分区。许多 Privacy Sandbox 提案和 API 旨在在不使用第三方 Cookie 或其他跟踪机制的情况下满足跨网站用例。例如:
- Protected Audience API 可让您以可保护隐私的方式投放针对用户兴趣的广告。
- 共享存储空间允许在安全环境中访问未分区的跨网站数据。
围栏帧专为与 Protected Audience API 搭配使用而设计。借助 Protected Audience API,用户的兴趣会在广告客户的网站上注册为兴趣群体,并与可能对用户感兴趣的广告一起注册。然后,在单独的网站(称为“发布商”)上,系统会对在相关兴趣群组中注册的广告进行竞价,并在受限框架中展示胜出的广告。
如果发布商在 iframe 中展示胜出的广告,并且脚本可以读取 iframe 的 src
属性,则发布商可以根据该广告的网址推断出访问者的兴趣。这无法保护隐私。
借助围栏框架,发布商可以展示与访问者兴趣相符的广告,但只有框架中的广告客户才知道 src
和兴趣群组。发布商无法访问此类信息。
围栏帧是如何运作的?
围栏帧使用 FencedFrameConfig
对象进行导航。此对象可以从 Protected Audience API 竞价或 Shared Storage 的网址选择操作返回。然后,将配置对象设置为封闭框架元素上的 config
属性。这与将网址或不透明 URN 分配给 src
属性的 iframe 不同。FencedFrameConfig
对象具有只读 url
属性;不过,由于当前用例要求隐藏内部资源的实际网址,因此此属性在读取时会返回字符串 opaque
。
围栏框架无法使用 postMessage
与其嵌入者通信。不过,围栏框可以将 postMessage
与围栏框内的 iframe 搭配使用。
系统会通过其他方式将围栏帧与发布商隔离。例如,发布商将无法访问围栏帧内的 DOM,而围栏帧也无法访问发布商的 DOM。此外,name
等属性(可设置为任意值并供发布商观察)在围栏帧中不可用。
围栏帧的行为方式类似于顶级浏览上下文(例如浏览器标签页)。虽然在某些用例(例如 opaque-ads
)中,围栏框架可以包含跨网站数据(例如 Protected Audience API 兴趣群体),但该框架无法访问未分区的存储空间或 Cookie。opaque-ads
围栏帧可以访问基于 Nonce 的唯一 Cookie 和存储分区。
说明文档中详细介绍了围栏帧的特性。
围栏框架与 iframe 相比如何?
现在,您已经了解了围栏框架的功能和限制,不妨与现有的 iframe 功能进行比较。
功能 | iframe |
fencedframe |
---|---|---|
嵌入内容 | 是 | 是 |
嵌入内容可以访问嵌入上下文 DOM | 是 | 否 |
嵌入上下文可以访问嵌入内容 DOM | 是 | 否 |
可观察的属性,例如 name |
是 | 否 |
网址 (http://example.com ) |
是 | 是(取决于用例) |
浏览器管理的不透明来源 (urn:uuid ) |
否 | 是 |
访问跨网站数据 | 否 | 是(取决于用例) |
为了保护隐私,围栏帧支持的外部通信选项较少。
封闭式框架会取代 iframe 吗?
最终,围栏框不会取代 iframe,您也不必使用它们。当需要在同一页面上显示来自不同顶级分区的不同数据时,可以使用封闭式帧,因为封闭式帧的私密性更高。
同一网站的 iframe(有时称为友好 iframe)会被视为可信内容。
使用 Fenced Frames
围栏帧将与其他 Privacy Sandbox API 结合使用,以便在单个网页中显示来自不同存储分区的文档。我们正在讨论可能使用的 API。
目前,此组合的候选人包括:
- 在 TURTLEDOVE API 系列(Protected Audience API 的基础)中,fenced 帧可以使用 Shared Storage 与转化次数提升幅度衡量搭配使用。
- 另一种方法是允许将围栏帧设为只读或访问未分区的存储空间。
如需了解详情,请参阅“围栏帧”用例说明。
示例
如需获取围栏框架 config
对象,您必须向 Protected Audience API 的 runAdAuction()
调用或 Shared Storage 的 selectURL()
调用传入 resolveToConfig: true
。如果未添加该属性(或将其设为 false
),生成的 promise 将解析为只能在 iframe 中使用的 URN。
const frameConfig = await navigator.runAdAuction({ // ...auction configuration resolveToConfig: true });
const frameConfig = await sharedStorage.selectURL('operation-name', { resolveToConfig: true });
获取配置后,您可以将其分配给围栏帧的 config
属性,以将帧导航到配置所代表的资源。较低版本的 Chrome 不支持 resolveToConfig
属性,因此您仍然必须在导航之前确认该 promise 是否已解析为 FencedFrameConfig
:
if (window.FencedFrameConfig && frameConfig instanceof FencedFrameConfig) { const frame = document.createElement('fencedframe'); frame.config = frameConfig; }
标头
浏览器会为从已设防的帧和嵌入到已设防的帧中的 iframe 发出的请求设置 Sec-Fetch-Dest: fencedframe
。
Sec-Fetch-Dest: fencedframe
服务器必须为要加载到围栏框架中的文档设置 Supports-Loading-Mode: fenced-frame
响应标头。封闭框架内的所有 iframe 也必须包含该标头。
Supports-Loading-Mode: fenced-frame
共享存储空间上下文
您可能需要使用“不公开汇总”功能,在与嵌入者提供的情境数据相关联的围栏框中报告事件级数据。通过使用 fencedFrameConfig.setSharedStorageContext()
方法,您可以将一些情境数据(例如事件 ID)从嵌入程序传递到 Protected Audience API 发起的共享存储工作流程。
在以下示例中,我们将嵌入页面上可用的数据和封闭框架中可用的数据存储在共享存储空间中。在嵌入页面中,模拟事件 ID 被设置为共享存储空间上下文。从围栏帧传入帧事件数据。
在嵌入程序页面中,您可以将情境数据设置为共享存储上下文:
const frameConfig = await navigator.runAdAuction({ resolveToConfig: true });
// Data from the embedder that you want to pass to the shared storage worklet
frameConfig.setSharedStorageContext('some-event-id');
const frame = document.createElement('fencedframe');
frame.config = frameConfig;
在围栏帧中,您可以将帧中的事件级数据传入共享存储工作流(与上文中嵌入程序提供的情境数据无关):
const frameData = {
// Data available only inside the fenced frame
}
await window.sharedStorage.worklet.addModule('reporting-worklet.js');
await window.sharedStorage.run('send-report', {
data: {
frameData
},
});
您可以从 sharedStorage.context
读取嵌入程序的情境信息,并从 data
对象读取框架的事件级数据,然后通过“不公开汇总”功能报告这些信息:
class ReportingOperation {
convertEventIdToBucket(eventId) { ... }
convertEventPayloadToValue(info) { ... }
async run(data) {
// Data from the embedder
const eventId = sharedStorage.context;
// Data from the fenced frame
const eventPayload = data.frameData;
privateAggregation.contributeToHistogram({
bucket: convertEventIdToBucket(eventId),
value: convertEventPayloadToValue(eventPayload)
});
}
}
register('send-report', ReportingOperation);
如需详细了解封闭帧配置对象中的嵌入程序上下文,请参阅说明文档。
试用 Fenced Frames
使用 Chrome 标志在 chrome://flags/#enable-fenced-frames
中启用 Fenced Frames API。
该对话框中有多种选择。我们强烈建议您选择*启用*,以便 Chrome 在有新架构可用时自动更新到新架构。
其他选项(已通过 ShadowDOM 启用和已通过多页面架构启用)提供不同的实现策略,仅与浏览器工程师相关。目前,启用的运作方式与启用 ShadowDOM 相同。未来,启用将映射到启用(采用多页面架构)。
功能检测
如需确定是否已定义围栏帧,请执行以下操作:
if (window.HTMLFencedFrameElement) {
// The fenced frame element is defined
}
如需确定是否有围栏帧配置可用,请执行以下操作:js
if (window.FencedFrameConfig && frameConfig instanceof FencedFrameConfig) {
// The fenced frame config is available
}
浏览器支持
互动和分享反馈
我们正在积极讨论围栏帧,未来可能会发生变化。如果您试用此 API 并有反馈,我们非常期待收到您的反馈。
- GitHub:阅读说明文档,提出问题并关注讨论。
- 开发者支持:在 Privacy Sandbox 开发者支持代码库中提问和参与讨论。