请参阅本文件的勘误表,其中可能包含一些规范性更正。
另请参见译本。
版权 © 2012 W3C® (MIT, ERCIM, Keio), 保留所有权利。W3C 责任、商标和文档使用规则适用。
本规范定义了一个供 Web 应用访问与导航及元素相关的计时信息的接口。
本节描述本文档在发布时的状态。其他文档可能会取代本文档。当前的 W3C 出版物列表和本技术报告的最新修订版可在 https://w3org.cn/TR/ 的 W3C 技术报告索引中找到。
这是“导航计时规范”的 W3C 推荐稿。可在实现报告中查看 2012 年候选推荐阶段基于导航计时测试套件的实现情况。
请将评论发送至 public-web-perf@w3.org(归档),邮件主题行开头请加上 [NavigationTiming]。
本文件由Web Performance 工作组编写。可查看与上一稿的差异文档。
本文件已由 W3C 会员、软件开发人员以及其他 W3C 小组和利害关系方审阅,并由总干事认可为 W3C 推荐标准。这是一个稳定的文档,可以用作参考材料或从另一个文档中引用。W3C 发布推荐标准的角色是引起对规范的关注并促进其广泛部署。这增强了 Web 的功能和互操作性。
本文件由遵循2004 年 2 月 5 日 W3C 专利政策的组发布。W3C 维护一份公开专利披露列表,其中也包含披露专利的说明。若个人实际了解某项专利且认为其中含有关键权利要求,必须依据专利政策第 6 节进行披露。
本节是非规范性的。
用户延迟是 Web 应用的重要质量基准。虽然诸如[JSMEASURE] 中描述的脚本机制可以为应用内部的用户延迟测量提供完整的检测手段,但在很多情况下,它们无法提供完整的端到端延迟视图。
例如,下面的脚本展示了一种朴素的测量页面完整加载时间的尝试。
<html>
<head>
<script type="text/javascript">
var start = new Date().getTime();
function onLoad() {
var now = new Date().getTime();
var latency = now - start;
alert("page loading time: " + latency);
}
</script>
</head>
<body onload="onLoad()">
<!- Main page body goes from here. -->
</body>
</html>
该脚本在
中的第一段 JavaScript 执行后才开始计算页面加载时间,却没有提供从服务器获取页面所耗费的时间信息。为了解决获取完整用户体验信息的需求,本文档引入了PerformanceTiming 接口。该接口允许 JavaScript 机制在应用内部提供完整的客户端延迟测量。借助所提议的接口,前面的示例可被修改为测量用户感知的页面加载时间。
下面的脚本计算自最近一次导航开始以来加载页面所耗费的时间。
<html>
<head>
<script type="text/javascript">
function onLoad() {
var now = new Date().getTime();
var page_load_time = now - performance.timing.navigationStart;
alert("User-perceived page loading time: " + page_load_time);
}
</script>
</head>
<body onload="onLoad()">
<!- Main page body goes from here. -->
</body>
</html>
本工作提供的接口并不旨在作为用户代理的任何形式的性能基准。
本规范中的所有图表、示例和注释均为非规范性内容,明确标记为非规范性的章节亦如此。本规范中的所有其他内容均为规范性内容。
本文档规范部分中的关键字 “MUST”、 “MUST NOT”、 “REQUIRED”、 “SHOULD”、 “SHOULD NOT”、 “RECOMMENDED”、 “MAY” 与 “OPTIONAL” 应按照RFC 2119 中的描述进行解释。为便于阅读,这些词在本规范中未全部使用全大写形式。
作为算法一部分的祈使语气要求(例如“去除任何前导空格字符”或“返回 false 并中止这些步骤”)应根据引入算法时使用的关键词(“必须”、“应该”、“可以”等)进行解释。
某些合规性要求以属性、方法或对象的形式表述。这类要求应解释为对用户代理的要求。
以算法或具体步骤表述的一致性要求可以以任何方式实现,只要最终结果等效即可。(特别说明,本规范中定义的算法旨在易于遵循,而非旨在达到高性能。)
本规范中的 IDL 片段必须按符合 Web IDL 规范的要求进行解释。[Web IDL]
构造 “a Foo object”(其中 Foo 实际上是一个接口)有时会被用来代替更准确的 “实现接口 Foo 的对象”。
术语 “navigation” 指的是导航行为。
术语 “JavaScript” 用于指代ECMA‑262,而非官方术语 ECMAScript,因为 JavaScript 更为大众所熟知。
在本文档中,时间以自 1970 年 1 月 1 日午夜(UTC)起的毫秒为单位进行计量。请注意,Navigation Timing 2 规范允许使用亚毫秒分辨率来访问与导航相关的计时信息。
本节为非规范性内容
本规范引入了一个为 Web 应用提供计时相关信息的接口。它并不涉及 Web 应用如何利用这些接口收集、存储和报告所提供的信息。
PerformanceTiming 接口interface PerformanceTiming {
readonly attribute unsigned long long navigationStart;
readonly attribute unsigned long long unloadEventStart;
readonly attribute unsigned long long unloadEventEnd;
readonly attribute unsigned long long redirectStart;
readonly attribute unsigned long long redirectEnd;
readonly attribute unsigned long long fetchStart;
readonly attribute unsigned long long domainLookupStart;
readonly attribute unsigned long long domainLookupEnd;
readonly attribute unsigned long long connectStart;
readonly attribute unsigned long long connectEnd;
readonly attribute unsigned long long secureConnectionStart;
readonly attribute unsigned long long requestStart;
readonly attribute unsigned long long responseStart;
readonly attribute unsigned long long responseEnd;
readonly attribute unsigned long long domLoading;
readonly attribute unsigned long long domInteractive;
readonly attribute unsigned long long domContentLoadedEventStart;
readonly attribute unsigned long long domContentLoadedEventEnd;
readonly attribute unsigned long long domComplete;
readonly attribute unsigned long long loadEventStart;
readonly attribute unsigned long long loadEventEnd;
};
navigationStart 属性该属性必须返回用户代理在完成对前一个文档的卸载提示后立即的时间。如果不存在前一个文档,则该属性必须返回与fetchStart 相同的值。
unloadEventStart 属性如果前一个文档与当前文档拥有相同的源 [IETF RFC 6454],则该属性必须返回用户代理在启动前一个文档的unload 事件之前的时间。如果不存在前一个文档,或前一个文档的源与当前文档不同,则该属性必须返回 0。
unloadEventEnd 属性如果前一个文档与当前文档具有相同的同源,则该属性必须返回用户代理在完成前一个文档的unload 事件之后的时间。如果不存在前一个文档,或前一个文档的源不同,或 unload 尚未完成,则该属性必须返回 0。
如果在导航过程中出现 HTTP 重定向或等效行为,且所有重定向或等效行为并非来自同一源,则 unloadEventStart 与 unloadEventEnd 必须返回 0。
redirectStart 属性如果在导航过程中出现 HTTP 重定向或等效行为,且所有重定向或等效行为均来自同一源,则该属性必须返回发起重定向的fetchStart 时间。否则,该属性必须返回 0。
redirectEnd 属性如果在导航过程中出现 HTTP 重定向或等效行为,且所有重定向和等效行为均来自同一源,则该属性必须返回接收最后一次重定向响应的最后一个字节之后的时间。否则,该属性必须返回 0。
fetchStart 属性如果要使用 HTTP GET或等效方式获取新资源,则 fetchStart 必须返回用户代理在开始检查任何相关应用缓存之前的时间。否则,必须返回用户代理开始获取该资源的时间。
domainLookupStart 属性该属性必须返回用户代理在开始对当前文档进行域名解析之前的时间。如果使用了持久连接 [RFC 2616],或当前文档是从相关应用缓存或本地资源中获取的,则该属性必须返回与fetchStart 相同的值。
domainLookupEnd 属性该属性必须返回用户代理在完成对当前文档的域名解析之后的时间。如果使用了持久连接 [RFC 2616],或当前文档是从相关应用缓存或本地资源中获取的,则该属性必须返回与fetchStart 相同的值。
本节是非规范性的。
检查并从HTTP 缓存 [RFC 2616] 中检索内容是获取过程的一部分。它由 requestStart、responseStart 与 responseEnd 属性覆盖。
在用户代理已将域信息缓存在本地的情况下,domainLookupStart 与 domainLookupEnd 表示用户代理从缓存中开始并结束域数据检索的时间。
connectStart 属性该属性必须返回用户代理在开始与服务器建立连接以获取文档之前的时间。如果使用了持久连接 [RFC 2616],或当前文档是从相关应用缓存或本地资源中获取的,则该属性必须返回domainLookupEnd 的值。
connectEnd 属性该属性必须返回用户代理在完成与服务器建立连接以获取当前文档之后的时间。如果使用了持久连接 [RFC 2616],或当前文档是从相关应用缓存或本地资源中获取的,则该属性必须返回domainLookupEnd 的值。
如果传输连接失败且用户代理重新打开连接,connectStart 与 connectEnd 应返回新连接对应的数值。
connectEnd 必须同时包含建立传输连接的时间间隔以及诸如 SSL 握手和 SOCKS 认证等其他时间间隔。
secureConnectionStart 属性该属性为可选项。未提供此属性的用户代理必须将其设为 undefined。当属性可用且当前页面的方案为HTTPS 时,必须返回用户代理在开始对当前连接进行安全握手之前的时间。如果属性可用但未使用 HTTPS,则必须返回 0。
requestStart 属性该属性必须返回用户代理在开始向服务器(或相关应用缓存、本地资源)请求当前文档之前的时间。
如果在请求发送后传输连接失败且用户代理重新打开连接并重新发送请求,requestStart 应返回新请求对应的数值。
此接口不包含表示发送请求完成的属性,例如 requestEnd。
responseStart 属性该属性必须返回用户代理在收到服务器(或相关应用缓存、本地资源)响应的第一个字节之后的时间。
responseEnd 属性该属性必须返回用户代理在收到当前文档的最后一个字节之后,或在传输连接关闭之前(两者取先到者)的时间。此处的文档可以来自服务器、相关应用缓存或本地资源。
domLoading 属性该属性必须返回用户代理在将当前文档就绪状态设为“loading” 之前的时间。
domInteractive 属性该属性必须返回用户代理在将当前文档就绪状态设为“interactive” 之前的时间。
domContentLoadedEventStart 属性该属性必须返回用户代理在触发 DOMContentLoaded 事件于 Document 之前的时间。
domContentLoadedEventEnd 属性该属性必须返回文档的DOMContentLoaded 事件完成后的时间。
domComplete 属性该属性必须返回用户代理在将当前文档就绪状态设为“complete” 之前的时间。
如果当前文档就绪状态多次变更为相同的状态,则 domLoading、domInteractive、domContentLoadedEventStart、domContentLoadedEventEnd 与 domComplete 必须返回对应的首次就绪状态变更的时间。
loadEventStart 属性该属性必须返回用户代理在触发当前文档的 load 事件之前的时间。如果 load 事件尚未触发,则必须返回 0。
loadEventEnd 属性该属性必须返回当前文档的 load 事件完成时的时间。如果 load 事件未触发或尚未完成,则必须返回 0。
PerformanceNavigation 接口interface PerformanceNavigation {
const unsigned short TYPE_NAVIGATE = 0;
const unsigned short TYPE_RELOAD = 1;
const unsigned short TYPE_BACK_FORWARD = 2;
const unsigned short TYPE_RESERVED = 255;
readonly attribute unsigned short type;
readonly attribute unsigned short redirectCount;
};
type 属性该属性必须返回当前浏览上下文中最近一次非重定向导航的类型。其取值必须为以下导航类型之一。
用户点击链接、在地址栏输入 URL、表单提交,或通过脚本发起的除 TYPE_RELOAD 与 TYPE_BACK_FORWARD 之外的其他操作导致的导航。
通过刷新操作或 location.reload() 方法触发的导航。
通过历史记录遍历操作触发的导航。
未在上述值中定义的其他导航类型。
客户端重定向(例如使用Refresh 元指令)不被本规范视为 HTTP 重定向或等效行为。此类情况下,type 属性应返回合适的值,例如当前页面被重新加载时返回 TYPE_RELOAD,若导航至新 URL 则返回 TYPE_NAVIGATE。
redirectCount 属性该属性必须返回当前浏览上下文中自最近一次非重定向导航以来的重定向次数。如果没有重定向,或任意一次重定向的源不同于目标文档的源,则该属性必须返回 0。
window.performance 属性HTML5 规范定义了Window 接口[HTML5],本规范在其基础上进行扩展。
interface Performance {
readonly attribute PerformanceTiming timing;
readonly attribute PerformanceNavigation navigation;
};
partial interface Window {
[Replaceable] readonly attribute Performance performance;
};
window.performance 属性提供了一个用于托管与性能相关属性的空间。
timing 属性timing 属性表示自最近一次非重定向导航以来与浏览上下文相关的计时信息。该属性由PerformanceTiming 接口定义。
navigation 属性navigation 属性由PerformanceNavigation 接口定义。
在当前文档的 Window 对象创建完成之前,window.performance.timing 与 window.performance.navigation 中的所有属性均不应被写入,尽管在后续步骤中会引用这些属性以便描述。
用户代理可以为用户提供禁用 window.performance.timing 与 window.performance.navigation 接口的选项。当这些接口被禁用时,window.performance.timing 与 window.performance.navigation 必须返回 null。
用户代理可以在创建当前文档对应的 Window 对象之前维护 PerformanceTiming 与 PerformanceNavigation 实例;当 Window 对象创建完成后,用这些实例替换 window.performance.timing 与 window.performance.navigation。
此示意图为非规范性内容。
下图展示了由PerformanceTiming 接口和PerformanceNavigation 接口(带或不带重定向)定义的计时属性。带下划线的属性在涉及不同源的文档导航时可能不可用。用户代理可在计时点之间执行内部处理,从而导致非规范性的间隔。

如果用户代理发送请求或接收完整响应失败且需要重新打开连接,则返回步骤 11。
从 window 对象到其 window.performance.timing 与 window.performance.navigation 对象存在隐式强引用。
计时属性的值必须单调递增,以确保在导航期间系统时钟的调整不会导致计时属性出现偏差。任意两个按时间顺序记录的计时属性之间的差值永不为负。对于所有导航(包括子文档导航),用户代理必须在根文档导航开始时记录系统时钟,并以单调时钟(从导航开始算起的已逝时间)定义后续的计时属性。
不鼓励使用厂商专有的用户代理扩展。如需此类扩展(例如用于实验),厂商必须采用以下扩展机制。
本节是非规范性的。
通过精心构造的计时攻击,可能会泄露终端用户的浏览和活动历史。例如,卸载时间会透露前一个页面执行其 unload 处理程序所需的时长,从而可能推断用户的登录状态。通过在访问涉及前一次导航的计时信息时强制相同的 origin 策略,这类攻击已得到缓解。
宽松的同源策略无法为跨文档的未经授权访问提供足够的保护。在共享托管环境中,未受信任的第三方可以在相同的 IP 地址但不同端口上托管 HTTP 服务器。
不同页面共享同一主机名,例如在用户生成内容站点上由不同作者提供的内容,被视为同一来源,因为没有通过路径名限制访问的机制。在这些页面之间进行导航时,后续页面可以访问前一个页面的计时信息,例如重定向和卸载事件的时间。
本节是非规范性的。
如果在用户代理和 Web 服务器之间部署了代理,则 connectStart 与 connectEnd 属性之间的时间间隔表示用户代理与代理之间的延迟,而非与 Web 服务器之间的延迟。这样,Web 服务器可能推断出代理的存在。对于 SOCKS 代理,该时间间隔包括代理的身份验证时间以及代理连接到 Web 服务器所花费的时间,这会掩盖代理检测。若使用 HTTP 代理,用户代理可能根本不知道代理服务器的存在,因此并非总能缓解此类攻击。
window.performance 对象是可替换的,以避免与使用相同对象的现有页面产生冲突。这样,第三方可以替换该对象,而依赖本规范所描述接口的脚本将失效。
我要向所有在本草案上与我联系过的人员表达诚挚的谢意,包括 Anderson Quach、Alex Russell、Alois Reitbauer、Annie Sullivan、Christian Biesinger、Darin Fisher、Eric Lawrence、James Simonsen、Jatinder Mann、Jason Sobel、Jason Weber、Jonas Sicking、Kyle Scholz、Lenny Rachitsky、Nic Jansma、Richard Rabbat、Sergey Novikov、Sigbjørn Vik、Steve Souders、Tony Gentilcore,感谢他们的审阅和反馈。