Copyright © 2025 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
本规范定义了一个 API,使 Web 内容能够访问演示显示器,并使用它们来展示 Web 内容。
本节描述了本文档在发布时的状态。当前 W3C 出版物列表和本技术报告的最新修订版本可在 W3C 技术报告索引 中找到,网址为 https://www.w3.org/TR/。
本文档由 第二屏工作组 作为候选推荐标准草案发布,采用 推荐标准路线。
自 2017年6月1日发布候选推荐标准以来,工作组更新了构建 PresentationRequest
的步骤,以忽略不支持方案的 URL,并进一步限制接收浏览上下文的自我导航方式,取消了
BinaryType
枚举的定义,转而使用 HTML 规范中的定义。除 WebIDL 更新外,本文档中定义的其他接口没有改变。此外,还进行了各种澄清和编辑更新。详细信息请参见 变更列表。
没有任何功能被标识为有风险。
第二屏工作组将在候选推荐标准期间完善 Presentation API 的 测试套件,并更新 初步实现报告。要推进到建议标准,必须展示每个功能的两个独立且互操作的实现,具体见 候选推荐标准退出标准 部分。
发布为候选推荐标准并不意味着 W3C 及其成员的认可。候选推荐标准草案集成了工作组打算包含在后续候选推荐标准快照中的更改。
这是一个草案文件,可能随时被更新、替换或废弃。将本文档作为除正在进行的工作外的其他用途引用是不合适的。
本文档由一个依据 W3C 专利政策 运营的工作组产生。 W3C 维护着一份 与本工作组交付物相关的专利披露列表; 该页面还包括披露专利的说明。任何人如果知道某个专利包含必要声明,则必须根据 W3C 专利政策第 6 节 披露该信息。
本文档受 2023年11月3日 W3C 流程文档 管辖。
本节为非规范性内容。
演示 API 旨在使诸如演示显示器(如投影仪、连接的显示器和联网的电视)对 Web 可用。它考虑了使用有线(HDMI、DVI 或类似)和无线技术(Miracast、Chromecast、DLNA、AirPlay 或类似技术)连接的显示器。
屏幕尺寸有限的设备无法将 Web 内容展示给更大范围的观众,例如会议室中的同事或家中的朋友和家人。在更大的 演示显示器上展示的 Web 内容具有更高的感知质量、可读性和影响力。
演示 API 的核心是使 控制器 页面能够在 演示 页面上展示并与 演示显示器 交换消息。演示页面如何传输到显示器以及如何在其与控制器页面之间交换消息由实现决定;这允许使用各种显示技术。
例如,如果 演示显示器 通过 HDMI 或 Miracast 连接,它们仅允许传输音频和视频,则承载 控制器 的用户代理(UA)还将渲染 演示。 然后,它使用操作系统将生成的图形和音频输出发送到演示显示器。我们称这种情况为 1-UA 模式 的演示 API 实现。唯一的要求是用户代理能够从渲染的演示中发送图形和音频到演示显示器,并在控制器页面与演示页面之间内部交换消息。
如果 演示显示器 能够原生渲染 HTML 并通过网络与 控制器 通信,则承载控制器的用户代理无需渲染 演示。相反,用户代理作为代理,请求演示显示器自行加载并渲染演示页面。消息交换通过用户代理与演示显示器之间的网络连接进行。我们称这种情况为 2-UA 模式 的演示 API 实现。
演示 API 旨在与连接到 演示显示器 的用户代理一起使用,支持 1-UA 模式、2-UA 模式,以及可能的其他未列出的方式。为了提高用户代理与演示显示器之间的互操作性,浏览器与显示器之间的网络通信标准化正在由 第二屏社区组 考虑。
本节为非规范性内容。
用例和需求记录在一个单独的 演示 API 用例和需求 文档中。
除了标记为非规范性的章节外,本规范中的所有创作指南、图表、示例和注释均为非规范性内容。除此之外,本规范中的所有内容均为规范性内容。
本文档中的关键词 可以(MAY)、必须(MUST)、不得(MUST NOT)、可选(OPTIONAL)、应(SHOULD) 和 不应(SHOULD NOT) 应按照 BCP 14 [RFC2119] [RFC8174] 的描述进行解释,仅在这些词汇全部大写时才应按此解释。
作为算法一部分的要求(例如“删除任何前导空格字符”或“返回 false 并终止这些步骤”)应根据引入算法时使用的关键词(“必须(MUST)”、“应(SHOULD)”、“可以(MAY)”等)进行解释。
以算法或具体步骤表述的一致性要求可以以任何方式实现,只要结果是等效的。(特别是,本规范中定义的算法旨在易于理解,而非性能最佳。)
本规范描述了两类用户代理的一致性标准。
符合 控制用户代理 规范的 Web 浏览器必须能够通过提供 控制浏览上下文 来启动和控制演示,具体如本规范所述。此上下文实现了
Presentation
、
PresentationAvailability
、
PresentationConnection
、
PresentationConnectionAvailableEvent
、
PresentationConnectionCloseEvent
、
和
PresentationRequest
接口。
符合 接收用户代理 规范的 Web 浏览器必须能够通过提供 接收浏览上下文 来渲染演示,具体如本规范所述。此上下文实现了
Presentation
、
PresentationConnection
、
PresentationConnectionAvailableEvent
、
PresentationConnectionCloseEvent
、
PresentationConnectionList
、
和
PresentationReceiver
接口。
一个用户代理可以同时充当 控制用户代理 和 接收用户代理,如果它提供了两种浏览上下文并实现了它们所需的所有接口。当同一用户代理能够承载 控制浏览上下文 和 接收浏览上下文 时,例如在 API 的 1-UA 模式 实现中,就会发生这种情况。
术语 JavaScript 领域和当前领域的用法与 [ECMASCRIPT]
中的定义一致。在 Promise
对象的上下文中,术语 已解决和已拒绝的用法与 [ECMASCRIPT]
中的定义一致。
术语 Accept-Language 和 HTTP 身份验证 按照 [RFC9110] 中的定义使用。
术语 cookie 存储 按照 [RFC6265] 中的定义使用。
术语 重新加载文档 指的是在
[HTML] 中调用 reload
()
方法时运行的步骤。
术语 本地存储区域 指的是由 localStorage
属性公开的存储区域,术语 会话存储区域 指的是由 [HTML] 中的 sessionStorage
属性公开的存储区域。
本规范引用了其他规范中导出的术语,参见 B.2 引用定义的术语。它还引用了以下其他规范中的内部概念:
本节为非规范性内容。
本节展示了演示 API 主要功能的示例代码。在这些示例中,controller.html
实现了控制器,presentation.html
实现了演示。两个页面均从域名 https://example.org
提供服务(https://example.org/controller.html
和
https://example.org/presentation.html
)。这些示例假设控制页面一次只管理一个演示。有关更多详细信息,请参阅代码示例中的注释。
该代码渲染了一个按钮,当至少有一个兼容的 演示显示器 可以展示
https://example.com/presentation.html
或
https://example.net/alternate.html
时,该按钮可见。
通过首先使用您要展示的 URL 创建一个 PresentationRequest
来监控显示器的可用性,然后调用 getAvailability
来获取一个 PresentationAvailability
对象,当演示可用性状态更改时,其 change
事件将被触发。
<!-- controller.html -->
<button id="presentBtn" style="display: none;">开始演示</button>
<script>
// 当至少有一个演示显示器可用时,显示“开始演示”按钮
var presentBtn = document.getElementById("presentBtn");
// 也可以使用相对演示 URL,例如 "presentation.html"
var presUrls = ["https://example.com/presentation.html",
"https://example.net/alternate.html"];
// 根据显示器的可用性显示或隐藏“开始演示”按钮
var handleAvailabilityChange = function(available) {
presentBtn.style.display = available ? "inline" : "none";
};
// 一旦知道演示显示器的可用性,Promise 就会被解析。
var request = new PresentationRequest(presUrls);
request.getAvailability().then(function(availability) {
// 只要可用性对象存在,availability.value 可能会由控制用户代理保持更新。建议 Web 开发人员在对象不再需要时将其丢弃。
handleAvailabilityChange(availability.value);
availability.onchange = function() { handleAvailabilityChange(this.value); };
}).catch(function() {
// 平台不支持可用性监控,因此只有在调用 request.start() 后才会发现演示显示器。
// 为简单起见,假装设备可用;或者,也可以为按钮实现第三种状态。
handleAvailabilityChange(true);
});
</script>
当用户点击 presentBtn
时,此代码将请求展示 PresentationRequest
中的一个 URL。调用 start
时,浏览器通常会显示一个对话框,允许用户选择一个可用的兼容显示器。与所选显示器兼容的第一个 PresentationRequest
URL
将在该显示器上展示。
start
方法将返回一个 PresentationConnection
对象,用于跟踪演示的状态,并在演示页面加载到显示器后与其交换消息。
<!-- controller.html -->
<script>
presentBtn.onclick = function () {
// 启动新演示。
request.start()
// 演示连接将在成功时传递给 setConnection。
.then(setConnection);
// 否则,用户取消了选择对话框,或未找到显示器。
};
</script>
即使启动演示的原始页面关闭其 PresentationConnection
、导航或关闭,演示仍会继续运行。另一个页面可以使用
id
重新连接到现有演示并恢复对其的控制。此功能仅保证在启动演示的同一浏览器中可用。
<!-- controller.html -->
<button id="reconnectBtn" style="display: none;">重新连接</button>
<script>
var reconnect = function () {
// 如果存在,则从 localStorage 读取 presId
var presId = localStorage["presId"];
// presId 是重新连接到演示时的必需项。
if (!!presId) {
request.reconnect(presId)
// 新的演示连接将在成功时传递给 setConnection。
.then(setConnection);
// 未找到 presUrl 和 presId 的连接,或发生错误。
}
};
// 在控制器导航时,自动重新连接。
document.addEventListener("DOMContentLoaded", reconnect);
// 或允许手动重新连接。
const reconnectBtn = document.querySelector("#reconnectBtn");
reconnectBtn.onclick = reconnect;
</script>
某些浏览器提供了一种方式,允许用户在不直接与控制页面交互的情况下启动演示。控制页面可以通过设置 defaultRequest
属性来选择这种行为,并监听当以这种方式启动演示时触发的 connectionavailable
事件。事件传递的 PresentationConnection
行为与页面调用 start
时相同。
<!-- controller.html -->
<!-- 设置 presentation.defaultRequest 允许页面指定在控制用户代理启动演示时使用的 PresentationRequest。 -->
<script>
navigator.presentation.defaultRequest = new PresentationRequest(presUrls);
navigator.presentation.defaultRequest.onconnectionavailable = function(evt) {
setConnection(evt.connection);
};
</script>
一旦演示开始,返回的 PresentationConnection
用于监控其状态并与之交换消息。通常用户会在控制页面中选择断开或终止演示。
由于控制页面在其生命周期内可能会连接和断开多个演示,跟踪当前的 PresentationConnection
及其状态非常有帮助。仅当连接处于
connected
状态时,消息才能发送和接收。
<!-- controller.html -->
<button id="disconnectBtn" style="display: none;">断开连接</button>
<button id="stopBtn" style="display: none;">停止</button>
<script>
let connection;
// 如果有已连接的演示,显示断开连接和停止按钮
const stopBtn = document.querySelector("#stopBtn");
const disconnectBtn = document.querySelector("#disconnectBtn");
stopBtn.onclick = _ => {
connection && connection.terminate();
};
disconnectBtn.onclick = _ => {
connection && connection.close();
};
function setConnection(newConnection) {
// 如果不是尝试重新连接,则断开现有演示连接
if (connection && connection != newConnection && connection.state != 'closed') {
connection.onclose = undefined;
connection.close();
}
// 设置新连接并保存演示 ID
connection = newConnection;
localStorage["presId"] = connection.id;
function showConnectedUI() {
// 允许用户断开或终止演示
stopBtn.style.display = "inline";
disconnectBtn.style.display = "inline";
reconnectBtn.style.display = "none";
}
function showDisconnectedUI() {
disconnectBtn.style.display = "none";
stopBtn.style.display = "none";
reconnectBtn.style.display = localStorage["presId"] ? "inline" : "none";
}
// 监控连接状态
connection.onconnect = _ => {
showConnectedUI();
// 注册消息处理程序
connection.onmessage = message => {
console.log(`收到消息: ${message.data}`);
};
// 向演示页面发送初始消息
connection.send("Say hello");
};
connection.onclose = _ => {
connection = null;
showDisconnectedUI();
};
connection.onterminate = _ => {
// 如果存在,则从 localStorage 中删除 presId
delete localStorage["presId"];
connection = null;
showDisconnectedUI();
};
};
</script>
此代码运行在演示页面上(https://example.org/presentation.html
)。多个控制页面可能会连接到演示,因此演示页面必须在 connectionList
对象上监听传入的连接。
<!-- presentation.html -->
<script>
var addConnection = function(connection) {
connection.onmessage = function (message) {
if (message.data == "Say hello")
connection.send("hello");
};
};
navigator.presentation.receiver.connectionList.then(function (list) {
list.connections.map(function (connection) {
addConnection(connection);
});
list.onconnectionavailable = function (evt) {
addConnection(evt.connection);
};
});
</script>
<!-- controller.html -->
<script>
connection.send('{"string": "你好,世界!", "lang": "zh-CN"}');
connection.send('{"string": "こんにちは、世界!", "lang": "ja"}');
connection.send('{"string": "안녕하세요, 세계!", "lang": "ko"}');
connection.send('{"string": "Hello, world!", "lang": "en-US"}');
</script>
<!-- presentation.html -->
<script>
connection.onmessage = function (message) {
var messageObj = JSON.parse(message.data);
var spanElt = document.createElement("SPAN");
spanElt.lang = messageObj.lang;
spanElt.textContent = messageObj.string;
document.body.appendChild(spanElt);
};
</script>
控制页面可以在两个不同的演示显示器上启动和控制两个独立的演示。此代码展示了如何在前面的示例中添加第二个演示。
<!-- controller.html -->
<!-- 同一控制页面可以通过多次调用 start() 创建和管理多个演示。 -->
<button id="secondPresentBtn" style="display: none;">再次演示</button>
<script>
var secondPresentBtn = document.getElementById("secondPresentBtn");
var secondPresUrl = "https://example.com/second-presentation.html";
var secondRequest = new PresentationRequest(secondPresUrl);
// 为简便起见,省略了处理 secondRequest 屏幕可用性并更新 secondPresentBtn 状态的逻辑。
secondPresentBtn.onclick = function () {
// 启动新演示,可能会在与原始请求不同的屏幕上。
secondRequest.start().then(setSecondConnection);
};
function setSecondConnection(newConnection) {
// 处理 second-presentation.html 的消息逻辑。
};
</script>
演示显示器 指通过实现特定的连接技术,用户代理可以访问的图形和/或音频输出设备。
演示连接是一个将控制浏览上下文与其接收浏览上下文关联起来的对象,并启用它们之间的双向消息传递。每个演示连接都有一个演示连接状态、一个唯一的演示标识符(用于将其与其他演示区分开来),以及一个演示 URL,该 URL 是一个用于创建或重新连接到演示的 URL。有效的演示标识符仅包含字母数字 ASCII 字符,并且至少有 16 个字符长。
由于功能、安全或硬件限制,某些演示显示器可能只能显示 Web 内容的子集。例如机顶盒、智能电视或仅能呈现音频的网络扬声器。如果控制用户代理可以合理地保证在该显示器上演示 URL 会成功,我们就说这样的显示器是演示 URL 的可用演示显示器。
控制浏览上下文(或简称控制器)是一个通过调用 start
或 reconnect
连接到演示的浏览上下文,或者通过 connectionavailable
事件接收到演示连接的浏览上下文。在 PresentationRequest
的算法中,控制浏览上下文是其 JavaScript 领域用于构造 PresentationRequest
的浏览上下文。
接收浏览上下文(或简称演示文稿)是负责向演示显示器呈现内容的浏览上下文。接收浏览上下文可以与控制浏览上下文位于同一个用户代理中,也可以位于不同的用户代理中。通过执行创建接收浏览上下文的步骤来创建接收浏览上下文。
在一个过程中,当过程在控制浏览上下文处启动时,目标浏览上下文是接收浏览上下文;如果过程在接收浏览上下文处启动,则目标浏览上下文是控制浏览上下文。
受控演示集(初始为空)包含由控制用户代理(或该用户代理中的特定用户配置文件)的控制浏览上下文创建的演示连接。受控演示集由表示底层演示连接的 PresentationConnection
对象列表表示。该集合中的多个 PresentationConnection
对象可能共享相同的演示 URL 和演示标识符,但对于给定的控制浏览上下文,只能有一个具有特定演示 URL 和演示标识符的 PresentationConnection
。
演示控制器集(初始为空)包含由接收用户代理的接收浏览上下文创建的演示连接。演示控制器集由表示底层演示连接的 PresentationConnection
对象列表表示。此集合中的所有演示连接共享相同的演示 URL 和演示标识符。
在接收浏览上下文中,演示控制器监视器(初始设置为 null
)向接收应用程序公开当前的演示控制器集。演示控制器监视器由 PresentationConnectionList
表示。
在接收浏览上下文中,演示控制器承诺(初始设置为 null
)在建立初始演示连接后提供演示控制器监视器。演示控制器承诺由一个 Promise
表示,该 Promise 解析为演示控制器监视器。
在控制浏览上下文中,默认演示请求(初始设置为 null
)表示当用户希望从浏览器界面启动演示连接时要使用的请求。
本规范中提到的任务的任务源是演示任务源。
当算法将演示 API 任务 T 排队时,用户代理 必须使用当前领域的全局对象在演示任务源上将全局任务 T 排队。
除非另有说明,算法步骤构造的脚本对象的 JavaScript 域 是 当前域。
WebIDL
[SecureContext, Exposed=Window]
interface Presentation
{
};
presentation
属性用于检索 Presentation
接口的实例。它
必须 返回 Presentation
实例。
控制用户代理 必须 实现以下部分接口:
WebIDLpartial interface Presentation
{
attribute PresentationRequest
? defaultRequest
;
};
defaultRequest
属性 必须 返回 默认演示请求(如果有),否则返回 null
。当设置时,默认
演示请求 必须 被设置为新值。
控制用户代理 应 仅在用户通过用户手势明确表达意图时(例如点击浏览器界面的按钮)使用 默认演示请求 来启动演示。
要使用 默认演示请求 启动演示,控制用户代理 必须 遵循 从默认演示请求启动演示 的步骤。
支持使用 默认演示请求 启动演示是 可选的。
接收用户代理 必须 实现以下部分接口:
WebIDLpartial interface Presentation
{
readonly attribute PresentationReceiver
? receiver
;
};
receiver
属性必须返回与接收浏览上下文关联的 PresentationReceiver
实例,该实例由接收用户代理在接收浏览上下文被创建时创建。在任何其他浏览上下文(包括接收浏览上下文的子可导航对象)中,它必须返回
null
。
Web 开发者可以使用 navigator.presentation.receiver 来检测文档是否作为演示加载。
WebIDL[SecureContext, Exposed=Window]
interface PresentationRequest
: EventTarget {
constructor
(USVString url);
constructor
(sequence<USVString> urls);
Promise<PresentationConnection
> start
();
Promise<PresentationConnection
> reconnect
(USVString presentationId);
Promise<PresentationAvailability
> getAvailability
();
};
PresentationRequest
对象与由 控制浏览上下文 发起的演示请求或重新连接相关联。PresentationRequest
对象 必须 在由 控制浏览上下文 提供的
控制用户代理 中实现。
当构造 PresentationRequest
时,提供的
urls
必须 用作 演示请求
URL 的列表,
它们每一个都是该 PresentationRequest
实例的可能 演示 URL。
PresentationRequest
当调用 PresentationRequest
构造函数时,
控制用户代理 必须 执行以下步骤:
PresentationRequest
对象
SecurityError
并中止这些步骤。
NotSupportedError
并中止所有剩余步骤。
SyntaxError
异常并中止所有剩余步骤。
NotSupportedError
并中止所有剩余步骤。
SecurityError
并中止这些步骤。
PresentationRequest
对象,其演示文稿请求 URL 为
presentationUrls,并返回它。
当调用
start
方法时,
用户代理 必须 按以下步骤来 选择一个演示显示设备。
start
调用的
PresentationRequest
对象
Promise
InvalidAccessError
异常而被拒绝的 Promise
,并中止这些步骤。
start
时产生的未解决的 Promise
,则返回一个因 OperationError
异常而被拒绝的新
Promise
,并中止所有剩余步骤。
Promise
。
NotFoundError
异常拒绝 P。
NotAllowedError
异常拒绝 P,并中止所有剩余步骤。
当用户通过浏览器界面(通过专用按钮、用户手势或其他信号)表达在演示显示设备上开始演示文档的意图时,用户代理 必须 执行以下步骤来 从默认演示请求开始演示。 如果文档上未设置 默认演示请求,则不得运行这些步骤。
null
的值,由 navigator.presentation.defaultRequest 在
W 上设置
当 用户代理 要 启动演示连接 时,它 必须 执行以下步骤:
PresentationRequest
Promise
,它将被解析为一个新的演示连接
PresentationConnection
S。
connecting
。
connectionavailable
的事件,
该事件使用 PresentationConnectionAvailableEvent
接口,并将 connection
属性初始化为 S。
该事件不得冒泡且不得取消。
error
,并设置
closeMessage 为描述失败的可读信息。
http
或 https
协议的 presentationUrl 的行为;对于其他协议的行为,本规范未定义。
当调用 reconnect
方法时,用户代理 必须 运行以下步骤来重新连接到演示:
reconnect
的 PresentationRequest
对象
Promise
Promise
。
PresentationConnection
:
PresentationConnection
,则运行以下步骤:
PresentationConnection
。
connecting
或
connected
,则中止所有剩余步骤。
connecting
。
PresentationConnection
:
PresentationConnection
,则运行以下步骤:
PresentationConnection
。
PresentationConnection
newConnection。
connecting
。
connectionavailable
的事件,该事件使用
PresentationConnectionAvailableEvent
接口,并将 connection
属性初始化为 newConnection。该事件不得冒泡且不得取消。
NotFoundError
异常拒绝
P。
以下是对象实现 PresentationRequest
接口时必须支持的事件处理程序(及其对应的事件处理程序事件类型),作为事件处理程序 IDL 属性:
事件处理程序 | 事件处理程序事件类型 |
---|---|
onconnectionavailable
|
connectionavailable
|
每个 展示连接 都由一个 PresentationConnection
对象表示。控制用户代理 和
接收用户代理 必须
实现 PresentationConnection
。
WebIDLenum PresentationConnectionState
{ "connecting
", "connected
", "closed
", "terminated
" };
[SecureContext, Exposed=Window]
interface PresentationConnection
: EventTarget {
readonly attribute USVString id
;
readonly attribute USVString url
;
readonly attribute PresentationConnectionState
state
;
undefined close
();
undefined terminate
();
attribute EventHandler onconnect
;
attribute EventHandler onclose
;
attribute EventHandler onterminate
;
// Communication
attribute BinaryType binaryType
;
attribute EventHandler onmessage
;
undefined send
(DOMString message);
undefined send
(Blob data);
undefined send
(ArrayBuffer data);
undefined send
(ArrayBufferView data);
};
state
属性表示
展示连接 的当前状态。它可以是
PresentationConnectionState
中的值,具体取决于连接状态:
connecting
表示用户代理正在尝试与
目标浏览上下文
建立展示连接。这是创建
PresentationConnection
对象时的初始状态。
connected
表示
展示连接 已建立,可以进行通信。
closed
表示
展示连接 已关闭或无法打开。可以通过调用
reconnect
重新打开。无法进行通信。
terminated
表示
接收浏览上下文 已终止。与该
展示
的任何
展示连接 也已终止,且无法重新打开。无法进行通信。
connected
状态并不意味着发送或接收消息一定会成功,因为通信通道可能会随时突然关闭。希望尽早检测到此类情况的应用程序应实现自己的保活机制。
当调用 close
方法时,PresentationConnection
S
的
用户代理
必须 开始关闭展示连接 S,
closeReason 设置为 closed
,closeMessage
为空。
当调用 terminate
方法时,
PresentationConnection
S
在 控制浏览上下文中,用户代理 必须 运行算法以
终止控制浏览上下文中的展示。
当调用 terminate
方法时,
PresentationConnection
S
在 接收浏览上下文中,用户代理 必须 运行算法以
终止接收浏览上下文中的展示。
binaryType
属性可以取
BinaryType
中的一个值。当创建 PresentationConnection
对象时,其 binaryType
属性必须设置为字符串 "arraybuffer
"。获取时,它必须返回最后设置的值。设置时,用户代理必须将属性设置为新值。
binaryType
属性允许开发者控制二进制数据如何暴露给脚本。通过将该属性设置为 "blob
",二进制数据以 Blob
形式返回;通过将其设置为
"arraybuffer
",则以 ArrayBuffer
形式返回。
该属性默认为 "arraybuffer
"。此属性对以字符串形式发送的数据没有影响。
当在 PresentationConnection
S
上调用 send
方法时,
用户代理必须运行通过 S 发送消息的算法。
当 PresentationConnection
对象
S 被丢弃(因为拥有它的文档正在导航或已关闭),而 S 的演示连接状态为 connecting
或 connected
时,用户代理
必须以 wentaway
作为
closeReason 并使用空的 closeMessage 来开始关闭演示连接 S。
如果用户代理从目标浏览上下文接收到要关闭 PresentationConnection
S 的信号,它必须以 closed
或 wentaway
作为
closeReason 并使用空的 closeMessage 来关闭演示连接 S。
当 用户代理 需要使用 展示连接 来 建立展示连接 时,它 必须 执行以下步骤:
PresentationConnection
对象
connecting
,则终止所有后续步骤。
error
作为
closeReason,并提供描述故障的可读消息作为 closeMessage。
PresentationConnection
发送消息
send
,必须确保消息能够可靠且按顺序地传递到另一端。
该传输应具有与可靠模式下的 RTCDataChannel
等效的功能。
设 展示消息数据 为在两个浏览上下文之间传输的有效数据。设 展示消息类型 为该数据的类型,可以是
text
或 binary
。
当 用户代理 需要通过 展示连接 发送消息 时,它 必须 执行以下步骤:
state
属性不是 connected
,则抛出一个
InvalidStateError
异常。
ArrayBuffer
、ArrayBufferView
或 Blob
,则令演示消息类型
messageType 为 binary
。如果 messageOrData 的类型是
DOMString
,则令 messageType 为 text
。
error
作为
closeReason,并使用描述所遇到错误的 closeMessage 立即关闭演示连接
presentationConnection。
为了帮助应用程序从通过 展示连接 发送消息时发生的错误中恢复,用户代理应在 closeMessage 中包括有关哪个尝试失败的详细信息,并提供一个可读字符串来解释失败的原因。closeMessage 的示例:
Unable to send text message (network_error): "hello"
对于
DOMString
消息,其中 "hello"
是失败消息的前 256 个字符。
ArrayBuffer
、ArrayBufferView
和 Blob
消息,提示“无法发送二进制消息
(invalid_message)”。
PresentationConnection
接收消息
当 用户代理 从远程端接收到包含 展示消息数据
和 展示消息类型 的传输内容时,它 必须
按以下步骤通过 PresentationConnection
接收消息:
state
属性不是 connected
,则中止这些步骤。
MessageEvent
接口创建事件的结果,事件类型为
message
,该事件不冒泡且不可取消。
text
,则将 event 的 data
属性初始化为类型为 DOMString
的 messageData。
binary
,并且 binaryType
属性设置为 "blob
",则将 event 的 data
属性初始化为一个新的 Blob
对象,其原始数据为
messageData。
binary
,并且 binaryType
属性设置为 "arraybuffer
",则将 event 的 data
属性初始化为一个新的 ArrayBuffer
对象,其内容为
messageData。
如果 用户代理 在通过 presentationConnection 接收消息 时遇到不可恢复的错误,它 必须 立即 关闭展示连接
presentationConnection,并将 error
作为
closeReason。它 应该 使用人类可读的描述来解释遇到的错误,作为 closeMessage。
WebIDLenum PresentationConnectionCloseReason
{ "error
", "closed
", "wentaway
" };
[SecureContext, Exposed=Window]
interface PresentationConnectionCloseEvent
: Event {
constructor
(DOMString type, PresentationConnectionCloseEventInit
eventInitDict);
readonly attribute PresentationConnectionCloseReason
reason
;
readonly attribute DOMString message
;
};
dictionary PresentationConnectionCloseEventInit
: EventInit {
required PresentationConnectionCloseReason
reason
;
DOMString message
= "";
};
当一个 PresentationConnectionCloseEvent
在展示连接进入 closed
状态时触发。 reason
属性提供了连接关闭的原因。它可以取以下值之一 PresentationConnectionCloseReason
:
error
表示连接或通信机制遇到了不可恢复的错误。
closed
表示连接的 控制浏览上下文 或 接收浏览上下文 调用了 close()
。
wentaway
表示浏览器关闭了连接,例如,因为拥有连接的浏览上下文已导航或被丢弃。
当 reason
属性为 error
时,用户代理 SHOULD 设置 message
属性为一个人类可读的描述,说明通信通道如何遇到错误。
当 PresentationConnectionCloseEvent
构造函数被调用时,用户代理 MUST 构造一个新的 PresentationConnectionCloseEvent
对象,其 reason
属性应设置为传递给构造函数的 PresentationConnectionCloseEventInit
对象的 reason
成员,其 message
属性应设置为该对象的
message
成员(如果已设置),否则应为空字符串。
PresentationConnection
当 用户代理 要 开始关闭展示连接 时,它 MUST 执行以下步骤:
PresentationConnectionCloseReason
connecting
或 connected
,则中止剩余步骤。
closed
。
PresentationConnection
的意图,并将
closeReason 传递给该上下文。用户代理不需要等待确认相应的 PresentationConnection
实际关闭即可继续下一步。
wentaway
,则本地执行关闭展示连接的步骤,使用
presentationConnection、closeReason 和 closeMessage。
当 用户代理 要 关闭展示连接 时,它 MUST 执行以下步骤:
PresentationConnectionCloseReason
connecting
、connected
或 closed
,则中止剩余步骤。
closed
,则将其设置为
closed
。
close
,
该事件使用
PresentationConnectionCloseEvent
接口,并将
reason
属性初始化为 closeReason,并将
message
属性初始化为 closeMessage,目标为
presentationConnection。该事件不得冒泡且不得取消。
当 控制用户代理 要 在控制浏览上下文中终止展示 时使用 connection,它 MUST 执行以下步骤:
connected
或 connecting
,则中止这些步骤。
connected
或
connecting
,则在给定
known connection 的相关全局对象的演示任务源上将全局任务排队以运行以下步骤:
terminated
。
terminate
的事件。
当以下任意情况发生时,接收用户代理 MUST 终止在接收浏览上下文中的展示:
这可能是用户的显式操作,也可能是用户代理的策略。例如,接收用户代理 可能配置为终止所有 PresentationConnection
对象已关闭 30 分钟的展示。
当 接收用户代理 要 终止在接收浏览上下文中的展示 时,它 MUST 执行以下步骤:
connected
,则将
connection 添加到 connectedControllers。
terminated
。
每个 控制用户代理 只需发送一次终止确认。
当 接收用户代理 发送展示 P 的终止确认,并且该确认由 控制用户代理 接收时,控制用户代理 MUST 运行以下步骤:
connected
或
connecting
,则中止以下步骤。
terminated
。
terminate
的事件。
以下是必须支持的事件处理程序(及其对应的事件处理程序事件类型),作为实现 PresentationConnection
接口的对象的事件处理程序
IDL 属性:
事件处理程序 | 事件处理程序事件类型 |
---|---|
onmessage |
message |
onconnect |
connect |
onclose |
close |
onterminate |
terminate |
WebIDL[SecureContext, Exposed=Window]
interface PresentationReceiver
{
readonly attribute Promise<PresentationConnectionList
> connectionList
;
};
PresentationReceiver
接口允许 接收浏览上下文 访问 控制浏览上下文 并与其通信。PresentationReceiver
接口 MUST 实现在由 接收用户代理 提供的 接收浏览上下文 中。
当获取时,connectionList
属性 MUST 返回运行以下步骤的结果:
null
,则返回
展示控制器的 promise 并中止所有剩余步骤。
Promise
,它在此 PresentationReceiver
对象的JavaScript 领域中构造。
null
,则使用 展示控制器监视器 解析 展示控制器的 promise。
当 用户代理 要 创建一个接收浏览上下文 时,它 MUST 运行以下步骤:
"denied"
。
Cache
对象集合。
由呈现的文档创建的所有子可导航对象,即以接收浏览上下文作为其顶层浏览上下文的子可导航对象,必须也具有上述限制 2-4。此外,它们必须设置无用户激活的沙盒顶层导航浏览上下文标志。所有这些浏览上下文必须也为上面列出的功能 5-10 共享相同的浏览状态(存储)。
当顶层浏览上下文尝试导航到新资源并运行导航步骤时,它必须遵循步骤 1 来确定是否允许导航。此外,它不得允许将自身导航到新资源,除非通过导航到片段标识符或通过重新加载其文档。
这允许用户根据选择演示显示器时显示的演示 URL 的来源授予权限。
如果顶层浏览上下文不允许导航,则它不应提供在新顶层浏览上下文中打开资源的功能,但否则应与导航步骤保持一致。
与接收浏览上下文及其后代可导航对象关联的窗口客户端和工作者客户端不得暴露给相互关联的服务工作者。
当接收浏览上下文终止时,与其关联的任何服务工作者以及其后代可导航对象中的浏览上下文必须被注销和终止。与接收浏览上下文及其后代可导航对象中的浏览上下文关联的任何浏览状态,包括会话历史、Cookie 存储、任何HTTP 身份验证状态、任何数据库、会话存储区域、本地存储区域、服务工作者注册列表和Cache
对象必须被丢弃,并且不得用于任何其他浏览上下文。
接收用户代理应在接收浏览上下文中使用反映控制用户代理语言首选项的 HTTP Accept-Language 标头获取资源(即,使用控制用户代理本应发送的相同 Accept-Language)。这将有助于接收用户代理使用反映用户首选项的字体和特定于区域设置的属性来呈现演示。
WebIDL[SecureContext, Exposed=Window]
interface PresentationConnectionList
: EventTarget {
readonly attribute FrozenArray<PresentationConnection
> connections
;
};
connections
属性 MUST
返回在 展示控制器集合 中的非终止 展示连接 集合。
当 接收用户代理 开始在 接收浏览上下文 中 监控传入的展示连接 来自 控制浏览上下文 时,必须 监听并接受来自 控制浏览上下文 的传入连接请求,使用实现特定的机制。当收到来自 控制浏览上下文 的新连接请求时,接收用户代理 必须 运行以下步骤:
PresentationConnection
S。
connected
。否则,设置
S 的 展示连接状态 为 closed
,并终止所有剩余步骤。
null
,则并行运行以下步骤。
PresentationConnectionList
,构建在
JavaScript 环境 中的 PresentationReceiver
对象。
null
,队列一个展示API任务,并 解决 展示控制器承诺
与 展示控制器监视器。
connectionavailable
的事件,该事件使用 PresentationConnectionAvailableEvent
接口,并将 connection
属性初始化为 S。该事件不得冒泡且不得取消。
以下是由实现 PresentationConnectionList
接口的对象支持的事件处理程序(及其对应的事件处理程序事件类型),作为事件处理程序的IDL属性:
事件处理程序 | 事件处理程序事件类型 |
---|---|
onconnectionavailable
|
connectionavailable
|
本节是非规范性的。
change
事件在 PresentationAvailability
对象上触发,揭示了关于通过浏览器的局域网发现的 演示显示器 存在或不存在的一个信息位。
这可以与其他信息结合使用来对用户进行指纹识别。然而,该信息也依赖于用户的本地网络环境,因此风险最小化。
API 允许 监视可用演示显示器的列表。用户代理如何确定给定 URL 与 演示显示器 的兼容性和可用性是实现细节。如果 控制用户代理 将 演示请求 URL 与 DIAL 应用程序匹配以确定其可用性,则此功能可以用来探测关于用户未同意的情况下在 演示显示器 上安装的哪些 DIAL 应用程序的信息。
一个 演示 允许跨域访问; 演示 URL 和 演示标识符 是唯一需要的信息,可用于从控制用户代理的任何源重新连接到演示。 换句话说,演示并不与特定的打开源绑定。
这种设计允许来自不同来源的控制上下文连接到共享的演示资源。 演示标识符的安全性防止任意来源连接到现有的演示。
本规范还允许 接收用户代理
发布有关其 受控演示集
的信息,并允许 控制用户代理
重新连接到从其他设备启动的演示。 这在控制浏览上下文通过用户、本地存储或服务器获取正在运行的演示的
演示 URL
和 演示标识符 后成为可能,
然后通过 reconnect
连接到演示。
本规范不保证任何连接到演示的方的身份。 一旦连接,演示可以通过应用程序特定的方式进一步验证连接方的身份。 例如,演示可以要求控制器通过
send
提供一个令牌,
演示将使用该令牌来验证身份和授权。
当在选择演示显示器的步骤中,要求用户允许使用演示显示器时,控制用户代理应明确指出哪个来源正在请求演示以及将呈现哪个来源。
显示请求演示的来源将帮助用户理解是哪个内容发出的请求,尤其是在请求由子可导航对象发起时。例如,嵌入式内容可能会试图诱使用户点击以触发启动不需要的演示的请求。
无用户激活的沙盒顶层导航浏览上下文标志设置在接收浏览上下文上,以强制演示的顶层来源在演示的整个生命周期内保持不变。
当用户启动演示时,用户最初将独占控制演示。然而,Presentation API 允许其他设备(可能属于不同用户)连接并因此也控制演示。当第二台设备连接到演示时,建议所有已连接的控制用户代理通过浏览器通知其用户,原始用户已失去独占访问权限,现在有多个控制器控制演示。
此外,接收用户代理可能能够接收用户输入并充当演示显示。在这种情况下,当接收浏览上下文受远程方控制时(即有一个或多个已连接的控制器),接收用户代理应通过浏览器通知其用户。
Presentation API 抽象了显示设备的“本地”含义,这意味着它将网络可访问的显示设备暴露为仿佛它们直接连接到用户的设备。Presentation API 要求页面访问任何显示设备时必须获得用户许可,以减轻可能出现的问题,例如在他人可见的显示设备上显示不需要的内容。
演示中显示的内容与控制器不同。特别是,如果用户在两个上下文中都登录,然后从控制浏览上下文中注销,他们不会自动从接收浏览上下文中注销。使用身份验证的应用程序在设备之间通信时应格外小心。
当用户请求“清除浏览数据”时,用户代理已知的演示集应被清除。
当处于私密浏览模式(“隐身”)时,该浏览会话中的初始受控演示集必须为空。会话终止时,添加到其中的任何演示连接必须被丢弃。
WebIDLpartial interface Navigator {
[SecureContext, SameObject] readonly attribute Presentation
presentation
;
};
[SecureContext, Exposed=Window]
interface Presentation
{
};
partial interface Presentation
{
attribute PresentationRequest
? defaultRequest
;
};
partial interface Presentation
{
readonly attribute PresentationReceiver
? receiver
;
};
[SecureContext, Exposed=Window]
interface PresentationRequest
: EventTarget {
constructor
(USVString url);
constructor
(sequence<USVString> urls);
Promise<PresentationConnection
> start
();
Promise<PresentationConnection
> reconnect
(USVString presentationId);
Promise<PresentationAvailability
> getAvailability
();
attribute EventHandler onconnectionavailable
;
};
[SecureContext, Exposed=Window]
interface PresentationAvailability
: EventTarget {
readonly attribute boolean value
;
attribute EventHandler onchange
;
};
[SecureContext, Exposed=Window]
interface PresentationConnectionAvailableEvent
: Event {
constructor
(DOMString type, PresentationConnectionAvailableEventInit
eventInitDict);
[SameObject] readonly attribute PresentationConnection
connection
;
};
dictionary PresentationConnectionAvailableEventInit
: EventInit {
required PresentationConnection
connection
;
};
enum PresentationConnectionState
{ "connecting
", "connected
", "closed
", "terminated
" };
[SecureContext, Exposed=Window]
interface PresentationConnection
: EventTarget {
readonly attribute USVString id
;
readonly attribute USVString url
;
readonly attribute PresentationConnectionState
state
;
undefined close
();
undefined terminate
();
attribute EventHandler onconnect
;
attribute EventHandler onclose
;
attribute EventHandler onterminate
;
// Communication
attribute BinaryType binaryType
;
attribute EventHandler onmessage
;
undefined send
(DOMString message);
undefined send
(Blob data);
undefined send
(ArrayBuffer data);
undefined send
(ArrayBufferView data);
};
enum PresentationConnectionCloseReason
{ "error
", "closed
", "wentaway
" };
[SecureContext, Exposed=Window]
interface PresentationConnectionCloseEvent
: Event {
constructor
(DOMString type, PresentationConnectionCloseEventInit
eventInitDict);
readonly attribute PresentationConnectionCloseReason
reason
;
readonly attribute DOMString message
;
};
dictionary PresentationConnectionCloseEventInit
: EventInit {
required PresentationConnectionCloseReason
reason
;
DOMString message
= "";
};
[SecureContext, Exposed=Window]
interface PresentationReceiver
{
readonly attribute Promise<PresentationConnectionList
> connectionList
;
};
[SecureContext, Exposed=Window]
interface PresentationConnectionList
: EventTarget {
readonly attribute FrozenArray<PresentationConnection
> connections
;
attribute EventHandler onconnectionavailable
;
};
binaryType
PresentationConnection
的属性
§6.5
close
PresentationConnection
的方法
§6.5
"connected"
PresentationConnectionState
的枚举值
§6.5
"connecting"
PresentationConnectionState
的枚举值
§6.5
connectionList
PresentationReceiver
的属性
§6.6
connections
PresentationConnectionList
的属性
§6.7
defaultRequest
Presentation
的属性
§6.2.1
"error"
PresentationConnectionCloseReason
的枚举值
§6.5.4
getAvailability
PresentationRequest
的方法
§6.4.3
id
PresentationConnection
的属性
§6.5
onchange
PresentationAvailability
的属性
§6.4
onclose
PresentationConnection
的属性
§6.5.9
onconnect
PresentationConnection
的属性
§6.5.9
PresentationRequest
的属性
§6.3.6
PresentationConnectionList
的属性
§6.7.2
onmessage
PresentationConnection
的属性
§6.5.9
onterminate
PresentationConnection
的属性
§6.5.9
presentation
Navigator
的属性
§6.2
Presentation
接口
§6.2
PresentationAvailability
接口
§6.4
PresentationConnection
接口
§6.5
PresentationConnectionAvailableEvent
接口
§6.4.5
PresentationConnectionAvailableEventInit
字典
§6.4.5
PresentationConnectionCloseEvent
接口
§6.5.4
PresentationConnectionCloseEventInit
字典
§6.5.4
PresentationConnectionCloseReason
枚举
§6.5.4
PresentationConnectionList
接口
§6.7
PresentationConnectionState
枚举
§6.5
PresentationReceiver
接口
§6.6
PresentationRequest
接口
§6.3
receiver
Presentation
的属性
§6.2.2
reconnect
PresentationRequest
的方法
§6.3.5
send
PresentationConnection
的方法
§6.5
start
PresentationRequest
的方法
§6.3.2
state
PresentationConnection
的属性
§6.5
terminate
PresentationConnection
的方法
§6.5
"terminated"
PresentationConnectionState
的枚举值
§6.5
url
PresentationConnection
的属性
§6.5
value
PresentationAvailability
的属性
§6.4
"wentaway"
PresentationConnectionCloseReason
的枚举值
§6.5.4
Event
接口
EventInit
EventTarget
接口
Blob
接口
Document
)
EventHandler
localStorage
属性(用于
WindowLocalStorage
)
MessageEvent
接口
reload()
(用于 Location
)
sessionStorage
属性(用于
WindowSessionStorage
)
Cache
接口
ArrayBuffer
接口
ArrayBufferView
boolean
类型
DOMString
接口
[Exposed]
扩展属性
FrozenArray
接口
InvalidAccessError
异常
InvalidStateError
异常
NotAllowedError
异常
NotFoundError
异常
NotSupportedError
异常
OperationError
异常
Promise
接口
[SameObject]
扩展属性
[SecureContext]
扩展属性
SecurityError
异常
SyntaxError
异常
exception
)
undefined
类型
USVString
接口
RTCDataChannel
接口
BinaryType
枚举
感谢 Addison Phillips、Anne Van Kesteren、Anssi Kostiainen、Anton Vayvod、Chris Needham、Christine Runnegar、Daniel Davis、Domenic Denicola、Erik Wilde、François Daoust、闵洪波 (Hongbo Min)、Hongki CHA、Hubert Sablonnière、Hyojin Song、Hyun June Kim、Jean-Claude Dufourd、Joanmarie Diggs、Jonas Sicking、Louay Bassbouss、Mark Watson、Martin Dürst、Matt Hammond、Mike West、Mounir Lamouri、Nick Doty、Oleg Beletski、Philip Jägenstedt、Richard Ishida、Shih-Chiang Chien、Takeshi Kanai、Tobie Langel、Tomoyuki Shimizu、Travis Leithead、Wayne Carr 对本草案的编辑、审阅和反馈的帮助。
AirPlay、HDMI、Chromecast、DLNA 和 Miracast 分别是 Apple Inc.、HDMI Licensing LLC.、Google Inc.、数字生活网络联盟 (Digital Living Network Alliance) 和 Wi-Fi 联盟的注册商标。它们仅作为背景信息引用,且实施此规范时不需要使用这些商标。
要将此规范推进到建议推荐状态,每个符合性类别(控制用户代理 和 接收用户代理)至少需要两个独立的、可互操作的实现。每个功能的实现可以来自不同的产品,并且不要求所有功能由单个产品实现。此外,控制用户代理的实现必须包括至少一个1-UA 模式的实现,以及一个2-UA 模式的实现。2-UA 模式的实现可能只支持非 http/https 的演示 URL。接收用户代理的实现可能不包括2-UA 模式的实现。
API 最近限制为仅适用于安全上下文。在早期实现中,弃用非安全上下文中的 API 需要时间。如果存在计划在未来限制这些实现,工作组可能会请求在非安全上下文中暴露 API 的实现转变为建议推荐状态。
为了符合这些标准,我们定义了以下术语:
本节为非规范性内容。
本节列出了自2016年7月首次发布为候选推荐以来对规范所做的更改,并提供了与工作组问题跟踪器上的相关问题的链接。
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: