CINXE.COM
Resource Timing
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="color-scheme" content="light dark"> <title> Resource Timing </title> <script src='https://www.w3.org/Tools/respec/respec-w3c' class='remove' defer></script> <script class='remove'> var respecConfig = { shortName: "resource-timing", specStatus: "ED", editors: [{ name: "Yoav Weiss", url: "https://blog.yoav.ws/", company: "Google", companyURL: "https://google.com/", w3cid: "58673" }, { name: "Noam Rosenthal", mailto: "nrosenthal@chromium.org", company: "Google", w3cid: "121539" }], formerEditors: [{ name: "Ilya Grigorik", url: "https://www.igvita.com/", company: "Google", companyURL: "https://google.com/", note: "Until January 2021", w3cid: "56102" }, { name: "Todd Reifsteck", mailto: "toddreif@microsoft.com", company: "Microsoft Corp.", note: "Until January 2021", w3cid: "76565" }, { name: "Arvind Jain", mailto: "arvind@google.com", company: "Google Inc.", note: "Until December 2014", w3cid: "45188" }, { name: "Jatinder Mann", mailto: "jmann@microsoft.com", company: "Microsoft Corp.", note: "Until February 2014", w3cid: "44357" }, { name: "Zhiheng Wang", company: "Google Inc.", note: "Until July 2012", w3cid: "43685" }, { name: "Anderson Quach", company: "Microsoft Corp.", note: "Until March 2011", w3cid: "45288" }], group:"webperf", wgPublicList: "public-web-perf", subjectPrefix: "[ResourceTiming]", github: "https://github.com/w3c/resource-timing/", caniuse: "resource-timing", xref: { specs: ["hr-time-3", "performance-timeline", "xhr"], profile: "web-platform", } }; </script> </head> <body> <section id="abstract"> <p> This specification defines an interface for web applications to access the complete timing information for resources in a document. </p> </section> <section id="sotd"></section> <section id="introduction" class='informative'> <h2> Introduction </h2> <p> User latency is an important quality benchmark for Web Applications. While JavaScript-based mechanisms can provide comprehensive instrumentation for user latency measurements within an application, in many cases, they are unable to provide a complete end-to-end latency picture. This document introduces the <a>PerformanceResourceTiming</a> interface to allow JavaScript mechanisms to collect complete timing information related to resources on a document. Navigation Timing 2 [[NAVIGATION-TIMING-2]] extends this specification to provide additional timing information associated with a navigation. </p> <p> For example, the following JavaScript shows a simple attempt to measure the time it takes to fetch a resource: </p> <pre class='example html'> <!doctype html> <html> <head> </head> <body onload="loadResources()"> <script> function loadResources() { var start = new Date().getTime(); var image1 = new Image(); var resourceTiming = function() { var now = new Date().getTime(); var latency = now - start; alert("End to end resource fetch: " + latency); }; image1.onload = resourceTiming; image1.src = 'https://www.w3.org/Icons/w3c_main.png'; } </script> <img src="https://www.w3.org/Icons/w3c_home.png"> </body> </html> </pre> <p> Though this script can measure the time it takes to fetch a resource, it cannot break down the time spent in various phases. Further, the script cannot easily measure the time it takes to fetch resources described in markup. </p> <p> To address the need for complete information on user experience, this document introduces the <a>PerformanceResourceTiming</a> interface. This interface allows JavaScript mechanisms to provide complete client-side latency measurements within applications. With this interface, the previous example can be modified to measure a user's perceived load time of a resource. </p> <p> The following script calculates the amount of time it takes to fetch every resource in the page, even those defined in markup. This example assumes that this page is hosted on https://www.w3.org. One could further measure the amount of time it takes in every phase of fetching a resource with the <a>PerformanceResourceTiming</a> interface. </p> <pre class='example html'> <!doctype html> <html> <head> </head> <body onload="loadResources()"> <script> function loadResources() { var image1 = new Image(); image1.onload = resourceTiming; image1.src = 'https://www.w3.org/Icons/w3c_main.png'; } function resourceTiming() { var resourceList = window.performance.getEntriesByType("resource"); for (i = 0; i < resourceList.length; i++) { if (resourceList[i].initiatorType == "img") { alert("End to end resource fetch: " + (resourceList[i].responseEnd - resourceList[i].startTime)); } } } </script> <img id="image0" src="https://www.w3.org/Icons/w3c_home.png"> </body> </html> </pre> </section> <section id="conformance"> <p> Requirements phrased in the imperative as part of algorithms (such as "strip any leading space characters" or "return false and abort these steps") are to be interpreted with the meaning of the key word ("MUST", "SHOULD", "MAY", etc) used in introducing the algorithm. </p> <p> Some conformance requirements are phrased as requirements on attributes, methods or objects. Such requirements are to be interpreted as requirements on user agents. </p> <p> Conformance requirements phrased as algorithms or specific steps may be implemented in any manner, so long as the end result is equivalent. (In particular, the algorithms defined in this specification are intended to be easy to follow, and not intended to be performant.) </p> </section> <section id="terminology"> <h2> Terminology </h2> <p> The construction "a <code>Foo</code> object", where <code>Foo</code> is actually an interface, is sometimes used instead of the more accurate "an object implementing the interface <code>Foo</code>. </p> <p> Throughout this work, all time values are measured in milliseconds since the start of navigation of the document [[HR-TIME]]. For example, the <a data-cite="NAVIGATION-TIMING-2#performanceentry">start of navigation of the document</a> occurs at time 0. </p> <p class='note'> This definition of time is based on the High Resolution Time specification [[HR-TIME]] and is different from the definition of time used in the Navigation Timing specification [[NAVIGATION-TIMING-2]], where time is measured in milliseconds since midnight of January 1, 1970 (UTC). </p> </section> <section id="sec-resource-timing"> <h2> Resource Timing </h2> <section class='informative'> <h3> Introduction </h3> <p data-fn-for="html"> The <a>PerformanceResourceTiming</a> interface facilitates timing measurement of [=fetch|fetched=] [=http(s) scheme|http(s)=] resources. For example, this interface is available for {{XMLHttpRequest}} objects [[XHR]], HTML elements [[HTML]] such as [^iframe^], [^img^], [^script^], [^object^], [^embed^] and [^link^] with the link type of [^link/rel/stylesheet^], SVG elements [[SVG11]] such as <a data-cite="SVG11/struct.html#SVGElement">svg</a>, and {{EventSource}}. </p> </section> <section> <h3> Resources Included in the <a>PerformanceResourceTiming</a> Interface </h3> <p> This section is non-normative. </p> <p> Resource [=Request=]s [=fetch=]ed by a non-null [=request/client=] are included as <a>PerformanceResourceTiming</a> objects in the [=request/client=]'s [=environment settings object/global object=]'s <a data-cite= "PERFORMANCE-TIMELINE-2#performance-timeline">Performance Timeline</a>, unless excluded from the timeline as part of the [=fetch|fetching process=]. Resources that are retrieved from HTTP cache are included as <a>PerformanceResourceTiming</a> objects in the <a data-cite= "PERFORMANCE-TIMELINE-2#performance-timeline">Performance Timeline</a>. Resources for which the [=fetch=] was initiated, but was later aborted (e.g. due to a network error) are included as <a>PerformanceResourceTiming</a> objects in the <a data-cite= "PERFORMANCE-TIMELINE-2#performance-timeline">Performance Timeline</a>, with their start and end timing. </p> <p> Examples: </p> <ul> <li>If the same canonical URL is used as the <code>src</code> attribute of two HTML <code>IMG</code> elements, the [=fetch=] of the resource initiated by the first HTML <code>IMG</code> element would be included as a <a>PerformanceResourceTiming</a> object in the <a data-cite= "PERFORMANCE-TIMELINE-2#performance-timeline">Performance Timeline</a>. The user agent might not re-request the URL for the second HTML <code>IMG</code> element, instead using the existing download it initiated for the first HTML <code>IMG</code> element. In this case, the [=fetch=] of the resource by the first <code>IMG</code> element would be the only occurrence in the <a data-cite= "PERFORMANCE-TIMELINE-2#performance-timeline">Performance Timeline</a>. </li> <li>If the <code>src</code> attribute of a HTML <code>IMG</code> element is changed via script, both the [=fetch=] of the original resource as well as the [=fetch=] of the new URL would be included as <a>PerformanceResourceTiming</a> objects in the <a data-cite= "PERFORMANCE-TIMELINE-2#performance-timeline">Performance Timeline</a>. </li> <li>If an HTML <code>IFRAME</code> element is added via markup without specifying a <code>src</code> attribute, the user agent may load the <code>about:blank</code> document for the <code>IFRAME</code>. If at a later time the <code>src</code> attribute is changed dynamically via script, the user agent may [=fetch=] the new URL resource for the <code>IFRAME</code>. In this case, only the [=fetch=] of the new URL would be included as a <a>PerformanceResourceTiming</a> object in the <a data-cite= "PERFORMANCE-TIMELINE-2#performance-timeline">Performance Timeline</a>. </li> <li>If an <code>XMLHttpRequest</code> is generated twice for the same canonical URL, both [=fetches=] of the resource would be included as a <a>PerformanceResourceTiming</a> object in the <a data-cite= "PERFORMANCE-TIMELINE-2#performance-timeline">Performance Timeline</a>. This is because the [=fetch=] of the resource for the second <code>XMLHttpRequest</code> cannot reuse the download issued for the first <code>XMLHttpRequest</code>. </li> <li>If an HTML <code>IFRAME</code> element is included on the page, then only the resource requested by <code>IFRAME</code> <code>src</code> attribute is included as a <a>PerformanceResourceTiming</a> object in the <a data-cite= "PERFORMANCE-TIMELINE-2#performance-timeline">Performance Timeline</a>. Sub-resources requested by the <code>IFRAME</code> document will be included in the <code>IFRAME</code> document's <a data-cite= "PERFORMANCE-TIMELINE-2#performance-timeline">Performance Timeline</a> and not the parent document's <a data-cite= "PERFORMANCE-TIMELINE-2#performance-timeline">Performance Timeline</a>. </li> <li>If an HTML <code>IMG</code> element has a <code><a href= "https://tools.ietf.org/html/rfc2397">data: URI</a></code> as its source [[RFC2397]], then this resource will not be included as a <a> PerformanceResourceTiming</a> object in the <a data-cite= "PERFORMANCE-TIMELINE-2#performance-timeline">Performance Timeline</a>. <a>PerformanceResourceTiming</a> entries are only reported for [=http(s) scheme|http(s)=] resources. </li> <li>If a resource <a data-cite="FETCH#concept-fetch">fetch</a> was aborted due to a networking error (e.g. DNS, TCP, or TLS error), then the fetch will be included as a <a>PerformanceResourceTiming</a> object in the <a data-cite= "PERFORMANCE-TIMELINE-2#performance-timeline">Performance Timeline</a> with only the `startTime`, `fetchStart`, `duration` and `responseEnd` set. </li> <li>If a resource <a data-cite="FETCH#concept-fetch">fetch</a> is aborted because it failed a fetch precondition (e.g. mixed content, CORS restriction, CSP policy, etc), then this resource will not be included as a <a>PerformanceResourceTiming</a> object in the <a data-cite= "PERFORMANCE-TIMELINE-2#performance-timeline">Performance Timeline</a>. </li> </ul> </section> <section data-dfn-for="PerformanceResourceTiming" id= "sec-performanceresourcetiming"> <h3> The <dfn>PerformanceResourceTiming</dfn> Interface </h3> <pre class='idl'> [Exposed=(Window,Worker)] interface PerformanceResourceTiming : PerformanceEntry { readonly attribute DOMString initiatorType; readonly attribute DOMString deliveryType; readonly attribute ByteString nextHopProtocol; readonly attribute DOMHighResTimeStamp workerStart; readonly attribute DOMHighResTimeStamp redirectStart; readonly attribute DOMHighResTimeStamp redirectEnd; readonly attribute DOMHighResTimeStamp fetchStart; readonly attribute DOMHighResTimeStamp domainLookupStart; readonly attribute DOMHighResTimeStamp domainLookupEnd; readonly attribute DOMHighResTimeStamp connectStart; readonly attribute DOMHighResTimeStamp connectEnd; readonly attribute DOMHighResTimeStamp secureConnectionStart; readonly attribute DOMHighResTimeStamp requestStart; readonly attribute DOMHighResTimeStamp finalResponseHeadersStart; readonly attribute DOMHighResTimeStamp firstInterimResponseStart; readonly attribute DOMHighResTimeStamp responseStart; readonly attribute DOMHighResTimeStamp responseEnd; readonly attribute unsigned long long transferSize; readonly attribute unsigned long long encodedBodySize; readonly attribute unsigned long long decodedBodySize; readonly attribute unsigned short responseStatus; readonly attribute RenderBlockingStatusType renderBlockingStatus; readonly attribute DOMString contentType; [Default] object toJSON(); }; </pre> <p> A <a>PerformanceResourceTiming</a> has an associated DOMString <a data-dfn-for="PerformanceResourceTiming"><dfn>initiator type</dfn></a>. </p> <p> A <a>PerformanceResourceTiming</a> has an associated DOMString <a data-dfn-for="PerformanceResourceTiming"><dfn>delivery type</dfn></a>. </p> <p> A <a>PerformanceResourceTiming</a> has an associated DOMString <a data-dfn-for="PerformanceResourceTiming"><dfn>requested URL</dfn></a>. </p> <p> A <a>PerformanceResourceTiming</a> has an associated DOMString <a data-dfn-for="PerformanceResourceTiming"><dfn>cache mode</dfn></a> (the empty string, "<code>local</code>", or "<code>validated</code>"). </p> <p> A <a>PerformanceResourceTiming</a> has an associated [=fetch timing info=] <a data-dfn-for="PerformanceResourceTiming"><dfn>timing info</dfn></a>. </p> <p> A <a>PerformanceResourceTiming</a> has an associated [=response body info=] <a data-dfn-for="PerformanceResourceTiming"><dfn>resource info</dfn></a>. </p> <p> A <a>PerformanceResourceTiming</a> has an associated <a data-cite= "FETCH#concept-status">status</a> <a data-dfn-for= "PerformanceResourceTiming"><dfn>response status</dfn></a>. </p> <p> A <a>PerformanceResourceTiming</a> has an associated {{RenderBlockingStatusType}} <a data-dfn-for= "PerformanceResourceTiming"><dfn>render-blocking status</dfn></a>. </p> <p data-dfn-for="PerformanceResourceTiming"> When <dfn>toJSON</dfn> is called, run the [=default toJSON steps=] for {{PerformanceResourceTiming}}. </p> <p data-dfn-for="PerformanceResourceTiming"> <dfn>initiatorType</dfn> getter steps are to return the <a data-for= "PerformanceResourceTiming">initiator type</a> for <a>this</a>. </p> <div class='note'> <p> `initiatorType` returns one of the following values: </p> <ul> <li> <code>"navigation"</code>, if the request is a [=navigation request=]; </li> <li> <code>"css"</code>, if the request is a result of processing a CSS <a data-cite="css-values-4" data-xref-type= "css-function">url()</a> directive such as <code>@import url()</code> or <code>background: url()</code>; [[CSS-VALUES]] </li> <li> <code>"script"</code>, if the request is a result of loading any <a data-cite="HTML#concept-script">script</a> (a classic [^script^], a [=module script=], or a {{Worker}}). </li> <li> <code>"xmlhttprequest"</code>, if the request is a result of processing an {{XMLHttpRequest}}; </li> <li> <code>"fetch"</code>, if the request is the result of processing the {{WindowOrWorkerGlobalScope/fetch()}} method; </li> <li> <code>"beacon"</code>, if the request is the result of processing the {{Navigator/sendBeacon()}} method; [[BEACON]] </li> <li> <code>"video"</code>, if the request is the result of processing the [^video^] element's [^video/poster^] or [^video/src^]. </li> <li> <code>"audio"</code>, if the request is the result of processing the [^audio^] element's [^audio/src^]. </li> <li> <code>"track"</code>, if the request is the result of processing the [^track^] element's [^track/src^]. </li> <li> <code>"img"</code>, if the request is the result of processing the [^img^] element's [^img/src^] or [^img/srcset^]. </li> <li> <code>"image"</code>, if the request is the result of processing the <a data-cite="SVG2/embedded.html#ImageElement">image</a> element. [[SVG2]] </li> <li> <code>"input"</code>, if the request is the result of processing an [^input^] element of [^input/type^] [^input/type/image^]. </li> <li> <code>"a"</code>, if the request is the result of processing an [^a^] element's [^a/download^] or [^a/ping^]. </li> <li> <code>"iframe"</code>, if the request is the result of processing an [^iframe^]'s [^iframe/src^]. </li> <li> <code>"frame"</code>, if the request is the result of loading a [^frame^]. </li> <li> <code>"other"</code>, if none of the above conditions match. </li> </ul> </div> <p class='note'> The setting of `initiatorType` is done at the different places where a resource timing entry is reported, such as the [=fetch=] standard. </p> <p data-dfn-for="PerformanceResourceTiming"> <dfn>deliveryType</dfn> getter steps are to return the <a data-for= "PerformanceResourceTiming">delivery type</a> for <a>this</a>. </p> <div class='note'> <p> `deliveryType` returns one of the following values: </p> <ul> <li> <code>"cache"</code>, if the <a data-for= "PerformanceResourceTiming">cache mode</a> is not the empty string. </li> <li>the empty string <code>""</code>, if none of the above conditions match. </li> </ul> <p> This is expected to be expanded by future updates to this specification, e.g. to describe consuming preloaded resources and prefetched navigation requests. </p> </div> <p data-dfn-for="PerformanceResourceTiming"> The <dfn>workerStart</dfn> getter steps are to <a>convert fetch timestamp</a> for <a>this</a>'s <a data-for= "PerformanceResourceTiming">timing info</a>'s [=fetch timing info/final service worker start time=] and the <a>relevant global object</a> for <a>this</a>. See [=/HTTP fetch=] for more info. </p> <p data-dfn-for="PerformanceResourceTiming"> The <dfn>redirectStart</dfn> getter steps are to <a>convert fetch timestamp</a> for <a>this</a>'s <a data-for= "PerformanceResourceTiming">timing info</a>'s [=fetch timing info/redirect start time=] and the <a>relevant global object</a> for <a>this</a>. See [=/HTTP-redirect fetch=] for more info. </p> <p data-dfn-for="PerformanceResourceTiming"> The <dfn>redirectEnd</dfn> getter steps are to <a>convert fetch timestamp</a> for <a>this</a>'s <a data-for= "PerformanceResourceTiming">timing info</a>'s [=fetch timing info/redirect end time=] and the <a>relevant global object</a> for <a>this</a>. See [=/HTTP-redirect fetch=] for more info. </p> <p data-dfn-for="PerformanceResourceTiming"> The <dfn>fetchStart</dfn> getter steps are to <a>convert fetch timestamp</a> for <a>this</a>'s <a data-for= "PerformanceResourceTiming">timing info</a>'s [=fetch timing info/post-redirect start time=] and the <a>relevant global object</a> for <a>this</a>. See [=/HTTP fetch=] for more info. </p> <p data-for="PerformanceResourceTiming"> The <dfn>domainLookupStart</dfn> getter steps are to <a>convert fetch timestamp</a> for <a>this</a>'s <a data-for= "PerformanceResourceTiming">timing info</a>'s [=fetch timing info/final connection timing info=]'s [=connection timing info/domain lookup start time=] and the <a>relevant global object</a> for <a>this</a>. See <a data-cite= "FETCH#record-connection-timing-info">Recording connection timing info</a> for more info. </p> <p data-dfn-for="PerformanceResourceTiming"> The <dfn>domainLookupEnd</dfn> getter steps are to <a>convert fetch timestamp</a> for <a>this</a>'s <a data-for= "PerformanceResourceTiming">timing info</a>'s [=fetch timing info/final connection timing info=]'s [=connection timing info/domain lookup end time=] and the <a>relevant global object</a> for <a>this</a>. See <a data-cite= "FETCH#record-connection-timing-info">Recording connection timing info</a> for more info. </p> <p data-dfn-for="PerformanceResourceTiming"> The <dfn>connectStart</dfn> getter steps are to <a>convert fetch timestamp</a> for <a>this</a>'s <a data-for= "PerformanceResourceTiming">timing info</a>'s [=fetch timing info/final connection timing info=]'s [=connection timing info/connection start time=] and the <a>relevant global object</a> for <a>this</a>. See <a data-cite= "FETCH#record-connection-timing-info">Recording connection timing info</a> for more info. </p> <p data-dfn-for="PerformanceResourceTiming"> The <dfn>connectEnd</dfn> getter steps are to <a>convert fetch timestamp</a> for <a>this</a>'s <a data-for= "PerformanceResourceTiming">timing info</a>'s [=fetch timing info/final connection timing info=]'s [=connection timing info/connection end time=] and the <a>relevant global object</a> for <a>this</a>. See <a data-cite= "FETCH#record-connection-timing-info">Recording connection timing info</a> for more info. </p> <p data-dfn-for="PerformanceResourceTiming"> The <dfn>secureConnectionStart</dfn> getter steps are to <a>convert fetch timestamp</a> for <a>this</a>'s <a data-for= "PerformanceResourceTiming">timing info</a>'s [=fetch timing info/final connection timing info=]'s [=connection timing info/secure connection start time=] and the <a>relevant global object</a> for <a>this</a>. See <a data-cite= "FETCH#record-connection-timing-info">Recording connection timing info</a> for more info. </p> <p data-dfn-for="PerformanceResourceTiming"> The <dfn>nextHopProtocol</dfn> getter steps are to [=/isomorphic decode=] <a>this</a>'s [=PerformanceResourceTiming/timing info=]'s [=fetch timing info/final connection timing info=]'s [=connection timing info/ALPN negotiated protocol=]. See <a data-cite= "FETCH#record-connection-timing-info">Recording connection timing info</a> for more info. </p> <p class="note"> Issue <a href= "https://github.com/w3c/resource-timing/issues/221">221</a> suggests to remove support for nextHopProtocol, as it can reveal details about the user's network configuration. </p> <p data-dfn-for="PerformanceResourceTiming"> The <dfn>requestStart</dfn> getter steps are to <a>convert fetch timestamp</a> for <a>this</a>'s <a data-for= "PerformanceResourceTiming">timing info</a>'s [=fetch timing info/final network-request start time=] and the <a>relevant global object</a> for <a>this</a>. See [=/HTTP fetch=] for more info. </p> <p data-dfn-for="PerformanceResourceTiming"> The <dfn>firstInterimResponseStart</dfn> getter steps are to <a>convert fetch timestamp</a> for <a>this</a>'s <a data-for= "PerformanceResourceTiming">timing info</a>'s [=fetch timing info/first interim network-response start time=] and the <a>relevant global object</a> for <a>this</a>. See [=/HTTP fetch=] for more info. </p> <p data-dfn-for="PerformanceResourceTiming"> The <dfn>finalResponseHeadersStart</dfn> getter steps are to <a>convert fetch timestamp</a> for <a>this</a>'s <a data-for= "PerformanceResourceTiming">timing info</a>'s [=fetch timing info/final network-response start time=] and the <a>relevant global object</a> for <a>this</a>. See [=/HTTP fetch=] for more info. </p> <p data-dfn-for="PerformanceResourceTiming"> The <dfn>responseStart</dfn> getter steps are to return <a>this</a>'s {{PerformanceResourceTiming/firstInterimResponseStart}} if it is not 0; Otherwise <a>this</a>'s {{PerformanceResourceTiming/finalResponseHeadersStart}}. </p> <p data-dfn-for="PerformanceResourceTiming"> The <dfn>responseEnd</dfn> getter steps are to <a>convert fetch timestamp</a> for <a>this</a>'s <a data-for= "PerformanceResourceTiming">timing info</a>'s [=fetch timing info/end time=] and the <a>relevant global object</a> for <a>this</a>. See [=/fetch=] for more info. </p> <p data-dfn-for="PerformanceResourceTiming"> The <dfn>encodedBodySize</dfn> getter steps are to return <a>this</a>'s <a data-for="PerformanceResourceTiming">resource info</a>'s [=response body info/encoded size=]. </p> <p data-dfn-for="PerformanceResourceTiming"> The <dfn>decodedBodySize</dfn> getter steps are to return <a>this</a>'s <a data-for="PerformanceResourceTiming">resource info</a>'s [=response body info/decoded size=]. </p> <p data-dfn-for="PerformanceResourceTiming"> The <dfn>transferSize</dfn> getter steps are to perform the following steps: </p> <ol> <li> <p> If <a>this</a>'s <a data-for="PerformanceResourceTiming">cache mode</a> is "<code>local</code>", then return 0. </p> </li> <li> <p> If <a>this</a>'s <a data-for="PerformanceResourceTiming">cache mode</a> is "<code>validated</code>", then return 300. </p> </li> <li> <p> Return <a>this</a>'s <a data-for= "PerformanceResourceTiming">response body info</a>'s [=response body info/encoded size=] plus 300. </p> <p class='note'> The constant number added to `transferSize` replaces exposing the total byte size of the HTTP headers, as that may expose the presence of certain cookies. See <a href= "https://github.com/w3c/resource-timing/issues/238">this issue</a>. </p> </li> </ol> <p data-dfn-for="PerformanceResourceTiming"> The <dfn>responseStatus</dfn> getter steps are to return <a>this</a>'s <a data-for="PerformanceResourceTiming">response status</a>. </p> <p class='note'> `responseStatus` is determined in [=Fetch=]. For a cross-origin <a data-cite="FETCH#dom-requestmode-no-cors">no-cors</a> request it would be 0 because the response would be an <a data-cite= "FETCH#concept-filtered-response-opaque">opaque filtered response</a>. </p> <p data-dfn-for="PerformanceResourceTiming"> The <dfn>contentType</dfn> getter steps are to return <a>this</a>'s <a data-for="PerformanceResourceTiming">resource info</a>'s [=response body info/content type=]. </p> <p data-dfn-for="PerformanceResourceTiming"> The <dfn>renderBlockingStatus</dfn> getter steps are to return <a data-link-for="RenderBlockingStatusType">blocking</a> if <a>this</a>'s <a data-for="PerformanceResourceTiming">timing info</a>'s [=fetch timing info/render-blocking=] is true; otherwise <a data-link-for="RenderBlockingStatusType">non-blocking</a>. </p> <p class='note'> A user agent implementing <a>PerformanceResourceTiming</a> would need to include <code>"resource"</code> in {{PerformanceObserver/supportedEntryTypes}}. This allows developers to detect support for Resource Timing. </p> <section id="sec-render-blocking-status-types"> <h4> <dfn>RenderBlockingStatusType</dfn> enum </h4> <pre class='idl'> enum RenderBlockingStatusType { "blocking", "non-blocking" }; </pre> <p> The values are defined as follows: </p> <dl data-dfn-for='RenderBlockingStatusType'> <dt> <dfn>blocking</dfn> </dt> <dd> The resource can potentially block rendering. </dd> <dt> <dfn>non-blocking</dfn> </dt> <dd> The resource will not block rendering. </dd> </dl> </section> </section> <section id="sec-extensions-performance-interface" data-dfn-for= "Performance"> <h3> Extensions to the <code>Performance</code> Interface </h3> <p> The user agent MAY choose to limit how many resources are included as <a>PerformanceResourceTiming</a> objects in the <a data-cite= "PERFORMANCE-TIMELINE-2#performance-timeline">Performance Timeline</a> [[PERFORMANCE-TIMELINE-2]]. This section extends the <a data-cite="HR-TIME#dom-performance"><code>Performance</code></a> interface to allow controls over the number of <a>PerformanceResourceTiming</a> objects stored. </p> <p> The recommended minimum number of <a>PerformanceResourceTiming</a> objects is 250, though this may be changed by the user agent. <a data-link-for="Performance">setResourceTimingBufferSize</a> can be called to request a change to this limit. </p> <p> Each <a data-cite="WEBIDL#es-environment">ECMAScript global environment</a> has: </p> <ul> <li>A <dfn>resource timing buffer size limit</dfn> which should initially be 250 or greater. </li> <li>A <dfn>resource timing buffer current size</dfn> which is initially 0. </li> <li>A <dfn>resource timing buffer full event pending flag</dfn> which is initially false. </li> <li>A <dfn>resource timing secondary buffer current size</dfn> which is initially 0. </li> <li>A <dfn>resource timing secondary buffer</dfn> to store <a>PerformanceResourceTiming</a> objects that is initially empty. </li> </ul> <pre class="idl" data-cite="HTML">partial interface Performance { undefined clearResourceTimings (); undefined setResourceTimingBufferSize (unsigned long maxSize); attribute EventHandler onresourcetimingbufferfull; }; </pre> <p> The <dfn>Performance</dfn> interface is defined in [[HR-TIME]]. </p> <p> The method <dfn>clearResourceTimings</dfn> runs the following steps: </p> <ol> <li>Remove all <a>PerformanceResourceTiming</a> objects in the <a data-cite= 'PERFORMANCE-TIMELINE-2#dfn-performance-entry-buffer'>performance entry buffer</a>. </li> <li>Set <a>resource timing buffer current size</a> to 0. </li> </ol> <p> The <dfn>setResourceTimingBufferSize</dfn> method runs the following steps: </p> <ol> <li>Set <a>resource timing buffer size limit</a> to the <i>maxSize</i> parameter. If the <i>maxSize</i> parameter is less than <a>resource timing buffer current size</a>, no <a>PerformanceResourceTiming</a> objects are to be removed from the <a data-cite= 'PERFORMANCE-TIMELINE-2#dfn-performance-entry-buffer'>performance entry buffer</a>. </li> </ol> <p> The attribute <dfn>onresourcetimingbufferfull</dfn> is the event handler for the <code>resourcetimingbufferfull</code> event described below. </p> <p> To check if <dfn>can add resource timing entry</dfn>, run the following steps: </p> <ol> <li>If <a>resource timing buffer current size</a> is smaller than <a> resource timing buffer size limit</a>, return true. </li> <li>Return false. </li> </ol> <p> To <dfn>add a PerformanceResourceTiming entry</dfn> <i>new entry</i> into the <a data-cite= 'PERFORMANCE-TIMELINE-2/#dfn-performance-entry-buffer'>performance entry buffer</a>, run the following steps: </p> <ol> <li>If <a>can add resource timing entry</a> returns true and <a>resource timing buffer full event pending flag</a> is false, run the following substeps: <ol style="list-style-type: lower-latin;"> <li>Add <i>new entry</i> to the <a data-cite= 'PERFORMANCE-TIMELINE-2#dfn-performance-entry-buffer'>performance entry buffer</a>. </li> <li>Increase <a>resource timing buffer current size</a> by 1. </li> <li>Return. </li> </ol> </li> <li>If <a>resource timing buffer full event pending flag</a> is false, run the following substeps: <ol style="list-style-type: lower-latin;"> <li>Set <a>resource timing buffer full event pending flag</a> to true. </li> <li> <a>Queue a task</a> on the <a href= "https://w3c.github.io/performance-timeline/#dfn-performance-timeline-task-source"> performance timeline task source</a> to run <a>fire a buffer full event</a>. </li> </ol> </li> <li>Add <i>new entry</i> to the <a>resource timing secondary buffer</a>. </li> <li>Increase <a>resource timing secondary buffer current size</a> by 1. </li> </ol> <p> To <dfn>copy secondary buffer</dfn>, run the following steps: </p> <ol> <li>While <a>resource timing secondary buffer</a> is not empty and <a>can add resource timing entry</a> returns true, run the following substeps: <ol> <li>Let <i>entry</i> be the oldest <a>PerformanceResourceTiming</a> in <a>resource timing secondary buffer</a>. </li> <li>Add <i>entry</i> to the end of <a data-cite= "PERFORMANCE-TIMELINE-2/#dfn-performance-entry-buffer">performance entry buffer</a>. </li> <li>Increment <a>resource timing buffer current size</a> by 1. </li> <li>Remove <i>entry</i> from <a>resource timing secondary buffer</a>. </li> <li>Decrement <a>resource timing secondary buffer current size</a> by 1. </li> </ol> </li> </ol> <p> To <dfn>fire a buffer full event</dfn>, run the following steps: </p> <ol> <li>While <a>resource timing secondary buffer</a> is not empty, run the following substeps: <ol> <li>Let <i>number of excess entries before</i> be <a>resource timing secondary buffer current size</a>. </li> <li>If <a>can add resource timing entry</a> returns false, then [=fire an event=] named <code>resourcetimingbufferfull</code> at the {{Performance}} object. </li> <li>Run <a>copy secondary buffer</a>. </li> <li>Let <i>number of excess entries after</i> be <a>resource timing secondary buffer current size</a>. </li> <li>If <i>number of excess entries before</i> is lower than or equals <i>number of excess entries after</i>, then remove all entries from <a>resource timing secondary buffer</a>, set <a>resource timing secondary buffer current size</a> to 0, and abort these steps. </li> </ol> </li> <li>Set <a>resource timing buffer full event pending flag</a> to false. <p class="note"> This means that if the <code>resourcetimingbufferfull</code> event handler does not add more room in the buffer than it adds resources to it, excess entries will be dropped from the buffer. Developers should make sure that <code>resourcetimingbufferfull</code> event handlers call <code>clearResourceTimings</code> or extend the buffer sufficiently (by calling <code>setResourceTimingBufferSize</code>). </p> </li> </ol> </section> <section id="sec-cross-origin-resources"> <h3> Cross-origin Resources </h3> <p class="note" data-dfn-for="PerformanceResourceTiming"> As detailed in [=Fetch=], requests for cross-origin resources are included as <a>PerformanceResourceTiming</a> objects in the <a data-cite= "PERFORMANCE-TIMELINE-2#performance-timeline">Performance Timeline</a>. If the <a data-cite="FETCH#concept-tao-check">timing allow check</a> algorithm fails for a cross-origin resource, the entry will be an [=create an opaque timing info|opaque entry=]. Such entries have most of their attributes masked in order to prevent leaking cross-origin data that isn't otherwise exposed. So, for an [=create an opaque timing info|opaque entry=], the following attributes will be set to zero: {{PerformanceResourceTiming/redirectStart}}, {{PerformanceResourceTiming/redirectEnd}}, {{PerformanceResourceTiming/workerStart}}, {{PerformanceResourceTiming/domainLookupStart}}, {{PerformanceResourceTiming/domainLookupEnd}}, {{PerformanceResourceTiming/connectStart}}, {{PerformanceResourceTiming/connectEnd}}, {{PerformanceResourceTiming/requestStart}}, {{PerformanceResourceTiming/firstInterimResponseStart}}, {{PerformanceResourceTiming/finalResponseHeadersStart}}, {{PerformanceResourceTiming/responseStart}}, {{PerformanceResourceTiming/secureConnectionStart}}, {{PerformanceResourceTiming/transferSize}}, {{PerformanceResourceTiming/encodedBodySize}}, and {{PerformanceResourceTiming/decodedBodySize}}. Further, the {{PerformanceResourceTiming/nextHopProtocol}} attribute will be set to the empty string. </p> <p> Server-side applications may return the <a>Timing-Allow-Origin</a> HTTP response header to allow the User Agent to fully expose, to the document origin(s) specified, the values of attributes that would have been zero due to those cross-origin restrictions. </p> <section id="sec-timing-allow-origin"> <h4> <code>Timing-Allow-Origin</code> Response Header </h4> <p> The <dfn>Timing-Allow-Origin</dfn> HTTP response header field can be used to communicate a policy indicating origin(s) that may be allowed to see values of attributes that would have been zero due to the cross-origin restrictions. The header's value is represented by the following ABNF [[RFC5234]] (using <a data-cite= "RFC9110#rfc.section.5.6.1">List Extension</a>, [[RFC9110]]): </p><code class="abnf">Timing-Allow-Origin = 1#( <a data-cite= "FETCH#origin-header">origin-or-null</a> / <a data-cite= "FETCH#http-new-header-syntax">wildcard</a> )</code> <p> The sender MAY generate multiple <a>Timing-Allow-Origin</a> header fields. The recipient MAY combine multiple <a>Timing-Allow-Origin</a> header fields by appending each subsequent field value to the combined field value in order, separated by a comma. </p> <p> The user agent MAY still enforce cross-origin restrictions and set transferSize, encodedBodySize, and decodedBodySize attributes to zero, even with Timing-Allow-Origin HTTP response header fields. If it does, it MAY also set deliveryType to "". </p> <p> The <a>Timing-Allow-Origin</a> headers are processed in <a data-cite="FETCH#tao-check">FETCH</a> to compute the attributes accordingly. </p> <p class="note"> The Timing-Allow-Origin header may arrive as part of a cached response. In case of cache revalidation, according to <a href= "https://tools.ietf.org/html/rfc7234#section-4.3.4">RFC 7234</a>, the header's value may come from the revalidation response, or if not present there, from the original cached resource. </p> <p class="note"> Issues <a href= "https://github.com/w3c/resource-timing/issues/222">222</a> and <a href="https://github.com/w3c/resource-timing/issues/223">223</a> suggest to remove wildcard support from Timing-Allow-Origin in order to restrict its use. </p> </section> <section id="sec-iana-considerations"> <h4> IANA Considerations </h4> <p> This section registers <a>Timing-Allow-Origin</a> as a <a href= "https://tools.ietf.org/html/rfc3864#section-4.2.2">Provisional Message Header</a>. </p> <dl> <dt> Header field name: </dt> <dd> <pre class="abnf">Timing-Allow-Origin</pre> </dd> <dt> Applicable protocol: </dt> <dd> http </dd> <dt> Status: </dt> <dd> provisional </dd> <dt> Author/Change controller: </dt> <dd> <a href="https://www.w3.org/">W3C</a> </dd> <dt> Specification document: </dt> <dd> <a href="#sec-timing-allow-origin"></a> </dd> </dl> </section> </section> <section id="attribute-descriptions"> <h3> Resource Timing Attributes </h3> <p> This section is non-normative. </p> <p> The following graph illustrates the timing attributes defined by the PerformanceResourceTiming interface. Attributes in parenthesis may not be available when [=fetch|fetching=] cross-origin resources. User agents may perform internal processing in between timings, which allow for non-normative intervals between timings. </p> <figure data-lt='Timing attributes'> <figcaption> This figure illustrates the timing attributes defined by the <a>PerformanceResourceTiming</a> interface. Attributes in parenthesis indicate that they may not be available if the resource fails the <a data-cite="FETCH#concept-tao-check">timing allow check</a> algorithm. </figcaption> <!-- Source: https://docs.google.com/document/d/1I7XGNJ57Qgjkg9pL11s7MK7zGEcwAgdNj1W5f7NKbW8/ --> <img src="timestamp-diagram.svg" alt="Resource Timing attributes" style='margin-top: 1em' width="1000"> </figure> </section> <section id="marking-resource-timing"> <h2> Creating a resource timing entry </h2> <p> To <dfn data-export="">mark resource timing</dfn> given a [=/fetch timing info=] |timingInfo|, a DOMString |requestedURL|, a DOMString |initiatorType| a <a>global object</a> |global|, a string |cacheMode|, a [=/response body info=] |bodyInfo|, a <a data-cite= "FETCH#concept-status">status</a> |responseStatus|, and an optional [=string=] |deliveryType| (by default, the empty string), perform the following steps: </p> <ol> <li>Create a <a>PerformanceResourceTiming</a> object |entry| in |global|'s [=global object/realm=]. </li> <li> <a>Setup the resource timing entry</a> for |entry|, given |initiatorType|, |requestedURL|, |timingInfo|, |cacheMode|, |bodyInfo|, |responseStatus|, and |deliveryType|. </li> <li> <a data-cite= "PERFORMANCE-TIMELINE-2#dfn-queue-a-performanceentry">Queue</a> |entry|. </li> <li>[=Add a PerformanceResourceTiming entry|Add=] |entry| to |global|'s <a data-cite= "PERFORMANCE-TIMELINE-2#dfn-performance-entry-buffer">performance entry buffer</a>. </li> </ol> <p> To <dfn data-export="">setup the resource timing entry</dfn> for <a>PerformanceResourceTiming</a> |entry| given DOMString |initiatorType|, DOMString |requestedURL|, [=/fetch timing info=] |timingInfo|, a DOMString |cacheMode|, a [=response body info=] |bodyInfo|, a <a data-cite="FETCH#concept-status">status</a> |responseStatus|, and an optional DOMString |deliveryType| (by default, the empty string), perform the following steps: </p> <ol> <li>Assert that |cacheMode| is the empty string, "<code>local</code>", or "<code>validated</code>". </li> <li>Let |global| be |entry|'s [=relevant global object=]. </li> <li>[=initialize a PerformanceEntry|Initialize=] |entry| given the result of <a data-lt="convert fetch timestamp">converting</a> |timingInfo|'s [=fetch timing info/start time=] given |global|, "<code>resource</code>", |requestedURL|, and the result of <a data-lt="convert fetch timestamp">converting</a> |timingInfo|'s [=fetch timing info/end time=] given |global|. </li> <li>Set |entry|'s <a data-for="PerformanceResourceTiming">initiator type</a> to |initiatorType|. </li> <li>Set |entry|'s <a data-for="PerformanceResourceTiming">requested URL</a> to |requestedURL|. </li> <li>Set |entry|'s <a data-for="PerformanceResourceTiming">timing info</a> to |timingInfo|. </li> <li>Set |entry|'s <a data-for="PerformanceResourceTiming">response body info</a> to |bodyInfo|. </li> <li>Set |entry|'s <a data-for="PerformanceResourceTiming">cache mode</a> to |cacheMode|. </li> <li>Set |entry|'s <a data-for="PerformanceResourceTiming">response status</a> to |responseStatus|. </li> <li>If |deliveryType| is the empty string and |cacheMode| is not, then set |deliveryType| to "<code>cache</code>". </li> <li>Set |entry|'s <a data-for="PerformanceResourceTiming">delivery type</a> to |deliveryType|. </li> </ol> <p> To <dfn>convert fetch timestamp</dfn> given {{DOMHighResTimeStamp}} |ts| and <a>global object</a> |global|, do the following: </p> <ol> <li>If |ts| is zero, return zero. </li> <li>Otherwise, return the [=relative high resolution coarse time=] given |ts| and |global|. </li> </ol> </section> <section id="sec-security" class='informative'> <h2> Security Considerations </h2> <p> The <a>PerformanceResourceTiming</a> interface exposes timing information for a resource to any web page or worker that has requested that resource. To limit the access to the <a>PerformanceResourceTiming</a> interface, the <a data-cite= "HTML#same-origin">same origin</a> policy is enforced by default and certain attributes are set to zero, as described in [=/HTTP fetch=]. Resource providers can explicitly allow all timing information to be collected for a resource by adding the <a>Timing-Allow-Origin</a> HTTP response header, which specifies the domains that are allowed to access the timing information. </p> </section> <section id="sec-privacy" class='informative'> <h2> Privacy Considerations </h2> <p> Statistical fingerprinting is a privacy concern where a malicious web site may determine whether a user has visited a third-party web site by measuring the timing of cache hits and misses of resources in the third-party web site. Though the <a>PerformanceResourceTiming</a> interface gives timing information for resources in a document, the load event on resources can already measure timing to determine cache hits and misses in a limited fashion, and the cross-origin restrictions in [=/HTTP Fetch=] prevent the leakage of any additional information. </p> </section> <section id="acknowledgements" class="appendix"> <h2> Acknowledgments </h2> <p> Thanks to Anne Van Kesteren, Annie Sullivan, Arvind Jain, Boris Zbarsky, Darin Fisher, Jason Weber, Jonas Sicking, James Simonsen, Karen Anderson, Kyle Scholz, Nic Jansma, Philippe Le Hegaret, Sigbj酶rn Vik, Steve Souders, Todd Reifsteck, Tony Gentilcore, William Chan, and Alex Christensen for their contributions to this work. </p> </section> </section> </body> </html>