This specification defines an interface for web applications to access the complete timing information for resources in a document.

Implementers SHOULD be aware that this document is not stable. Implementers who are not taking part in the discussions are likely to find the specification changing out from under them in incompatible ways. Vendors interested in implementing this document before it eventually reaches the Candidate Recommendation stage SHOULD join the aforementioned mailing lists and take part in the discussions.

Introduction

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 PerformanceResourceTiming 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.

For example, the following JavaScript shows a simple attempt to measure the time it takes to fetch a resource:

<!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>

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.

To address the need for complete information on user experience, this document introduces the PerformanceResourceTiming 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.

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 PerformanceResourceTiming interface.

<!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>

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.

Some conformance requirements are phrased as requirements on attributes, methods or objects. Such requirements are to be interpreted as requirements on user agents.

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.)

Terminology

The construction "a Foo object", where Foo is actually an interface, is sometimes used instead of the more accurate "an object implementing the interface Foo.

The term DOM is used to refer to the API set made available to scripts in Web applications, and does not necessarily imply the existence of an actual Document object or of any other Node objects as defined in the [[DOM]] specification.

A DOM attribute is said to be getting when its value is being retrieved (such as by author script), and is said to be setting when a new value is assigned to it.

The term JavaScript is used to refer to ECMA262, rather than the official term ECMAScript, since the term JavaScript is more widely known. [[ECMASCRIPT]]

The term resource is used to refer to elements and any other user-initiated fetches throughout this specification. For example, a resource could originate from XMLHttpRequest objects [[XHR]], HTML elements [[HTML]] such as iframe, img, script, object, embed, and link with the link type of stylesheet, and SVG elements [[SVG11]] such as svg.

The term cross-origin is used to mean non same origin.

The term current document refers to the document associated with the Window object's newest Document object.

Throughout this work, all time values are measured in milliseconds since the start of navigation of the document [[HR-TIME-2]]. For example, the start of navigation of the document occurs at time 0.

The term current time refers to the number of milliseconds since the start of navigation of the document until the current moment in time.

This definition of time is based on the High Resolution Time specification [[HR-TIME-2]] 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).

Resource Timing

Introduction

The PerformanceResourceTiming interface facilitates timing measurement of downloadable 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 stylesheet, and SVG elements [[SVG11]] such as svg.

Resources Included in the PerformanceResourceTiming Interface

All resource Requests fetched by a non-null client MUST be included as PerformanceResourceTiming objects in the client's global object's Performance Timeline, unless excluded from the timeline as part of the processing model. Resources that are retrieved from relevant application caches or local resources MUST be included as PerformanceResourceTiming objects in the Performance Timeline [[PERFORMANCE-TIMELINE-2]]. Resources for which the fetch was initiated, but was later aborted (e.g. due to a network error) MAY be included as PerformanceResourceTiming objects in the Performance Timeline and MUST contain initialized attribute values for processed substeps of the processing model.

The rest of this section is non-normative.

Examples:

The PerformanceResourceTiming Interface

The PerformanceResourceTiming interface participates in the Performance Timeline and extends the following attributes of the PerformanceEntry interface:

name
This attribute MUST return the resolved URL of the requested resource. This attribute MUST NOT change even if the fetch redirected to a different URL.
entryType
The entryType attribute MUST return the DOMString "resource".
startTime
The startTime attribute MUST return a DOMHighResTimeStamp [[HR-TIME-2]] with the time immediately before the user agent starts to queue the resource for fetching. If there are HTTP redirects or equivalent when fetching the resource, and if the timing allow check algorithm passes, this attribute MUST return the same value as redirectStart. Otherwise, this attribute MUST return the same value as fetchStart.
duration
The duration attribute MUST return a DOMHighResTimeStamp equal to the difference between responseEnd and startTime, respectively.
[Exposed=(Window,Worker)]
interface PerformanceResourceTiming : PerformanceEntry {
    readonly        attribute DOMString           initiatorType;
    readonly        attribute DOMString           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 responseStart;
    readonly        attribute DOMHighResTimeStamp responseEnd;
    readonly        attribute unsigned long long  transferSize;
    readonly        attribute unsigned long long  encodedBodySize;
    readonly        attribute unsigned long long  decodedBodySize;
    [Default] object toJSON();
};

When toJSON is called, run [[WEBIDL]]'s default toJSON operation.

On getting, the initiatorType attribute MUST return one of the following DOMString values:

On getting, the attribute nextHopProtocol returns the network protocol used to fetch the resource, as identified by the ALPN Protocol ID [[RFC7301]]; resources retrieved from relevant application caches or local resources, return an empty string. When a proxy is configured, if a tunnel connection is established then this attribute MUST return the ALPN Protocol ID of the tunneled protocol, otherwise it MUST return the ALPN Protocol ID of the first hop to the proxy. In order to have precisely one way to represent any ALPN protocol ID, the following additional constraints apply: octets in the ALPN protocol MUST NOT be percent-encoded if they are valid token characters except "%", and when using percent-encoding, uppercase hex digits MUST be used.

Formally registered ALPN protocol IDs are documented by IANA. In case the user agent is using an experimental, non-registered protocol, the user agent MUST use the ALPN negotiated value if any. If ALPN was not used for protocol negotiations, the user agent MAY use another descriptive string.

The "h3" ALPN ID is defined for the final version of the HTTP/3 protocol in the HTTP/3 Internet Draft.

Note that the nextHopProtocol attribute is intended to identify the network protocol in use for the fetch regardless of how it was actually negotiated; that is, even if ALPN is not used to negotiate the network protocol, this attribute still uses the ALPN Protocol ID's to indicate the protocol in use.

On getting, the workerStart attribute MUST return as follows:

  1. If the current browsing or worker context's have an active worker [[service-workers-1]]:

    1. the time immediately before the user agent fires an event named `fetch` at the active worker if the worker is available.
    2. the time immediately before the user agent runs the worker required to service the request.
  2. zero, otherwise.

Note that according to the definition of time origin in workers, it is possible that some attributes of navigation preload requests will have negative DOMHighResTimeStamp values.

On getting, the redirectStart attribute MUST return as follows:

  1. The time immediately before the user agent starts to fetch the resource that initiates the redirect, if there are HTTP redirects or equivalent when fetching the resource and the resource passes the timing allow check algorithm.
  2. zero, otherwise.

On getting, the redirectEnd attribute MUST return as follows:

  1. The time immediately after receiving the last byte of the response of the last redirect, if there are HTTP redirects or equivalent when fetching the resource and the resource passes the timing allow check algorithm.
  2. zero, otherwise.

On getting, the fetchStart attribute MUST return as follows:

  1. The time immediately before the user agent starts to fetch the final resource in the redirection, if there are HTTP redirects or equivalent.
  2. The time immediately before the user agent starts to fetch the resource otherwise.

On getting, the domainLookupStart attribute MUST return as follows:

  1. Zero, if the resource fails the timing allow check algorithm.
  2. The same value as fetchStart, if no domain lookup was required to fetch the resources (e.g. if a persistent connection [[RFC7230]] was used or in case the resource was retrieved from relevant application caches or local resources).
  3. The time immediately after the user agent starts the domain data retrieval from the domain information cache, if the user agent has the domain information in cache.
  4. The time immediately before the user agent starts the domain name lookup for the resource, otherwise.

On getting, the domainLookupEnd attribute MUST return as follows:

  1. Zero, if the resource fails the timing allow check algorithm.
  2. The same value as fetchStart, if no domain lookup was required to fetch the resources (e.g. if a persistent connection [[RFC7230]] was used or in case the resource was retrieved from relevant application caches or local resources).
  3. The time immediately after the user agent ends the domain data retrieval from the domain information cache, if the user agent has the domain information in cache.
  4. The time immediately after the user agent finishes the domain name lookup for the resource, otherwise.

On getting, the connectStart attribute MUST return as follows:

  1. Zero, if the resource fails the timing allow check algorithm.
  2. The same value as fetchStart, if a persistent connection [[RFC7230]] is used or the resource is retrieved from relevant application caches or local resources.
  3. The time immediately before the user agent start establishing the connection to the server to retrieve the resource, otherwise.

    If the transport connection fails and the user agent reopens a connection, connectStart SHOULD return the corresponding value of the new connection.

On getting, the connectEnd attribute MUST return as follows:

  1. Zero, if the resource fails the timing allow check algorithm.
  2. The same value as fetchStart, if a persistent connection [[RFC7230]] is used or the resource is retrieved from relevant application caches or local resources.
  3. The time immediately after the user agent finish establishing the connection to the server to retrieve the resource, otherwise.

    The returned time MUST include the time interval to establish the transport connection, as well as other time intervals such as SSL handshake and SOCKS authentication.

    If the transport connection fails and the user agent reopens a connection, connectEnd SHOULD return the corresponding value of the new connection.

On getting, the secureConnectionStart attribute MUST return as follows:

  1. Zero, if a secure transport is not used or if the resource fails the timing allow check algorithm.
  2. The same value as fetchStart, if a persistent connection [[RFC7230]] is used or the resource is retrieved from relevant application caches or local resources.
  3. The time immediately before the user agent starts the handshake process to secure the current connection, otherwise.

On getting, the requestStart attribute MUST return as follows:

  1. The time immediately before the user agent starts requesting the resource from the server, or from relevant application caches or from local resources, if the resource passes the timing allow check algorithm.

    If the transport connection fails after a request is sent and the user agent reopens a connection and resend the request, requestStart MUST return the corresponding values of the new request.

  2. zero, otherwise.

On getting, the responseStart attribute MUST return as follows:

  1. The time immediately after the user agent's HTTP parser receives the first byte of the response (e.g. frame header bytes for HTTP/2, or response status line for HTTP/1.x) from relevant application caches, or from local resources or from the server, if the resource passes the timing allow check algorithm.
  2. zero, otherwise.

On getting, the responseEnd attribute MUST return as follows:

  1. The time immediately after the user agent receives the last byte of the response or immediately before the transport connection is closed, whichever comes first. The resource here can be received either from relevant application caches, local resources, or from the server.
  2. The time immediately before the user agent aborts the fetch due to a network error.

On getting, the transferSize attribute MUST return as follows:

  1. the size, in octets received from a HTTP-network fetch, consumed by the response header fields and the response payload body [[RFC7230]], if the resource passes the timing allow check algorithm.

    If there are HTTP redirects or equivalent when navigating and if all the redirects or equivalent are same origin, this attribute SHOULD include the HTTP overhead of incurred redirects.

    This attribute SHOULD include HTTP overhead (such as HTTP/1.1 chunked encoding and whitespace around header fields, including newlines, and HTTP/2 frame overhead, along with other server-to-client frames on the same stream), but SHOULD NOT include lower-layer protocol overhead (such as TLS [[RFC5246]]or TCP).

  2. zero otherwise, including for resources retrieved from relevant application caches or from local resources.

On getting, the encodedBodySize attribute MUST return as follows:

  1. The size, in octets, received from a HTTP-network-or-cache fetch, of the payload body [[RFC7230]], prior to removing any applied content-codings [[RFC7231]], if the resource passes the timing allow check algorithm.
  2. The size, in octets, of the payload body prior to removing any applied content-codings if the resource is retrieved from relevant application caches or from local resources.
  3. zero, otherwise.

On getting, the decodedBodySize attribute MUST return as follows:

  1. The size, in octets, received from a HTTP-network-or-cache fetch, of the message body [[RFC7230]], after removing any applied content-codings [[RFC7231]], if the resource passes the timing allow check algorithm.
  2. The size, in octets, of the payload after removing any applied content-codings, if the resource is retrieved from relevant application caches or from local resources.
  3. zero, otherwise.

A user agent implementing PerformanceResourceTiming MUST run the register a performance entry type algorithm with "resource" as input.

Extensions to the Performance Interface

The user agent MAY choose to limit how many resources are included as PerformanceResourceTiming objects in the Performance Timeline [[PERFORMANCE-TIMELINE-2]]. This section extends the Performance interface to allow controls over the number of PerformanceResourceTiming objects stored.

The recommended minimum number of PerformanceResourceTiming objects is 250, though this may be changed by the user agent. setResourceTimingBufferSize can be called to request a change to this limit.

Each ECMAScript global environment has:

partial interface Performance {
  void clearResourceTimings ();
  void setResourceTimingBufferSize (unsigned long maxSize);
              attribute EventHandler onresourcetimingbufferfull;
};

The Performance interface is defined in [[HR-TIME-2]].

The method clearResourceTimings runs the following steps:

  1. Remove all PerformanceResourceTiming objects in the performance entry buffer.
  2. Set resource timing buffer current size to 0.

The setResourceTimingBufferSize method runs the following steps:

  1. Set resource timing buffer size limit to the maxSize parameter. If the maxSize parameter is less than resource timing buffer current size, no PerformanceResourceTiming objects are to be removed from the performance entry buffer.

The attribute onresourcetimingbufferfull is the event handler for the resourcetimingbufferfull event described below.

To check if can add resource timing entry, run the following steps:

  1. If resource timing buffer current size is smaller than resource timing buffer size limit, return true.
  2. Return false.

To add a PerformanceResourceTiming entry into the performance entry buffer, run the following steps:

  1. Let new entry be the input PerformanceEntry to be added.
  2. If can add resource timing entry returns true and resource timing buffer full event pending flag is false, run the following substeps:
    1. Add new entry to the performance entry buffer.
    2. Increase resource timing buffer current size by 1.
    3. Return.
  3. If resource timing buffer full event pending flag is false, run the following substeps:
    1. Set resource timing buffer full event pending flag to true.
    2. Queue a task to run fire a buffer full event.
  4. Add new entry to the resource timing secondary buffer.
  5. Increase resource timing secondary buffer current size by 1.

To copy secondary buffer, run the following steps:

  1. While resource timing secondary buffer is not empty and can add resource timing entry returns true, run the following substeps:
    1. Let entry be the oldest PerformanceResourceTiming in resource timing secondary buffer.
    2. Add entry to the end of performance entry buffer.
    3. Increment resource timing buffer current size by 1.
    4. Remove entry from resource timing secondary buffer.
    5. Decrement resource timing secondary buffer current size by 1.

To fire a buffer full event, run the following steps:

  1. While resource timing secondary buffer is not empty, run the following substeps:
    1. Let number of excess entries before be resource timing secondary buffer current size.
    2. If can add resource timing entry returns false, then fire an event named resourcetimingbufferfull at the Performance object.
    3. Run copy secondary buffer.
    4. Let number of excess entries after be resource timing secondary buffer current size.
    5. If number of excess entries before is lower than or equals number of excess entries after, then remove all entries from resource timing secondary buffer, set resource timing secondary buffer current size to 0, and abort these steps.
  2. Set resource timing buffer full event pending flag to false.

    This means that if the resourcetimingbufferfull 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 resourcetimingbufferfull event handlers call clearResourceTimings or extend the buffer sufficiently (by calling setResourceTimingBufferSize).

Cross-origin Resources

Cross-origin resources MUST be included as PerformanceResourceTiming objects in the Performance Timeline. If the timing allow check algorithm fails for a resource, these attributes of its PerformanceResourceTiming object MUST be set to zero: redirectStart, redirectEnd, domainLookupStart, domainLookupEnd, connectStart, connectEnd, requestStart, responseStart, secureConnectionStart, transferSize, encodedBodySize and decodedBodySize.

Server-side applications may return the Timing-Allow-Origin 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 the cross-origin restrictions previously specified in this section.

Timing-Allow-Origin Response Header

The Timing-Allow-Origin HTTP response header field can be used to communicate a policy indicating origin(s) that are 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 List Extension, [[RFC7230]]):

      Timing-Allow-Origin = 1#( origin-or-null / wildcard )
    

The sender MAY generate multiple Timing-Allow-Origin header fields. The recipient MAY combine multiple Timing-Allow-Origin header fields by appending each subsequent field value to the combined field value in order, separated by a comma.

The timing allow check algorithm, which checks whether a resource's timing information can be shared with the current document, is as follows:

  1. If the resource's Request's window is not an environment settings object, return fail.

  2. For each request in the resource fetch redirection-chain:

    1. If request's origin is same-origin when compared to the resource's Request's window's origin, continue to the next request.

    2. If the Timing-Allow-Origin header value list does not contain a value which is byte-for-byte identical to the serialization of the current document's origin, nor a wildcard ("*"), return fail.

  3. Return pass.

The above definition does not fully align Timing-Allow-Origin's processing with CORS processing. Specifically, if a redirection chain includes a cross-origin resource followed by same-origin resources without an explicit opt-in, TAO will pass while CORS will fail. Future iterations of this specification may attempt to unite those definitions.

IANA Considerations

This section registers Timing-Allow-Origin as a Provisional Message Header.

Header field name:
Timing-Allow-Origin
Applicable protocol:
http
Status:
provisional
Author/Change controller:
W3C
Specification document:

Process

Processing Model

The following graph illustrates the timing attributes defined by the PerformanceResourceTiming interface. Attributes in parenthesis may not be available when fetching cross-origin resources. User agents may perform internal processing in between timings, which allow for non-normative intervals between timings.

This figure illustrates the timing attributes defined by the PerformanceResourceTiming interface. Attributes in parenthesis indicate that they may not be available if the resource fails the timing allow check algorithm.
Resource Timing attributes

For each resource whose Request has a non-null client, perform the following steps:

  1. If the resource is fetched by a cross-origin stylesheet which was fetched with no-cors policy, abort the remaining steps.

    Above cross-origin exclusion should be defined via Fetch registry: CSS needs to be defined in terms of Fetch and set some kind of "opaque request flag" for no-CORS CSS subresources. In turn, Resource Timing should interface with Fetch registry to surface resource fetch events.

    The above resource exclusion is at risk as currently only one implementation passes the related test.

  2. If the resource's Request's destination equals to "document", and the Request was not triggered by process the iframe attributes or process the frame attributes, abort the remaining steps.
  3. Create a new PerformanceResourceTiming object and set entryType to the DOMString resource.
  4. Immediately before the user agent starts to queue the resource for retrieval, record the current time in startTime, and set nextHopProtocol to the empty DOMString.
  5. Record the initiator of the resource in initiatorType.
  6. Record the resolved URL of the requested resource in name. If there is an active worker ([[service-workers-1]]) matching the current browsing or worker context's, immediately before the user agent runs the worker record the time as workerStart, or if the worker is already available, immediately before the event named `fetch` is fired at the active worker record the time as workerStart. Otherwise, if there is no matching service worker registration, set workerStart value to zero.
  7. Fetch start: Immediately before a user agent starts the fetching process, record the current time as fetchStart. Let domainLookupStart, domainLookupEnd, connectStart and connectEnd be the same value as fetchStart.
  8. If the user agent is to reuse the data from another existing or completed fetch initiated from the current document, abort the remaining steps.
  9. If the resource fails the timing allow check algorithm, the user agent MUST set redirectStart, redirectEnd, domainLookupStart, domainLookupEnd, connectStart, connectEnd, requestStart, responseStart and secureConnectionStart to zero and go to the step labeled response end.
  10. Let domainLookupStart, domainLookupEnd, connectStart and connectEnd be the same value as fetchStart.
  11. If the resource is fetched from the relevant application cache or local resources, including the HTTP cache [[RFC7234]], go to the step labeled request start.
  12. If no domain lookup is required, go to the step labeled connect start. Otherwise, immediately before a user agent starts the domain name lookup, record the time as domainLookupStart.
  13. Record the time as domainLookupEnd immediately after the domain name lookup is successfully done. A user agent may need multiple retries before that. If the domain name lookup fails and resource passes the timing allow check record the time as domainLookupEnd and go to the step labeledfinal record.
  14. Connect start: If a persistent transport connection is used to fetch the resource, let connectStart and connectEnd be the same value of domainLookupEnd. Otherwise, record the time as connectStart immediately before initiating a successful connection to the server and record the time as connectEnd immediately after the successful connection to the server or proxy is established. A user agent may need multiple retries to establish a successful connection and should reflect the timestamps for the successful connection only. Once connection is established set the value of nextHopProtocol to the ALPN ID used by the connection. If a connection can not be established, record the time up to the connection failure as connectEnd and go to the step labeled final record.
  15. The user agent MUST set the secureConnectionStart attribute as follows:
    1. When a secure transport is used, the user agent MUST record the time as secureConnectionStart immediately before the handshake process to secure the connection.
    2. When a secure transport is not used, the user agent MUST set the value of secureConnectionStart to 0.
  16. Request start: Immediately before a user agent starts sending the request for the resource, record the current time as requestStart. If a user agent needed multiple retries to send the request, record the current time of the last attempt.

    Network protocols may not perform the connection establishment, secure connection establishment and request sending in a sequential manner. Therefore, developers should not expect these values to always be in a particular order.

  17. Record the time as responseStart immediately after the user agent receives the first byte of the response.
  18. Response end: Record the time as responseEnd immediately after receiving the last byte of the response.
    1. Return to the step labeled connect start if the user agent fails to send the request or receive the entire response, and needs to reopen the connection.
    2. Set the value of transferSize, encodedBodySize, decodedBodySize to corresponding values, subject to timing allow check algorithm.
  19. Final record: If responseEnd is not set, set it to the current time. Record the difference between responseEnd and startTime in duration.
  20. If the fetched resource results in an HTTP redirect or equivalent, then
    1. If the current resource fails the timing allow check algorithm, set redirectStart and redirectEnd to 0. Then, return to the step labeled Fetch start with the redirected resource.
    2. If the value of redirectStart is not set, let it be the value of fetchStart.
    3. Let redirectEnd be the value of responseEnd.
    4. Set all the attributes in the PerformanceResourceTiming object to 0 except startTime, redirectStart, redirectEnd, and initiatorType.
    5. Return to the step labeled Fetch start with the redirected resource.
  21. Queue the PerformanceResourceTiming object.
  22. Add the PerformanceResourceTiming object to the Request's client's global object's performance entry buffer.

This specification does not specify whether steps 20 and 21 should run before or after the load event of the resource—see issue 82 for related discussion.

Monotonic Clock

The value of the timing attributes MUST monotonically increase to ensure timing attributes are not skewed by adjustments to the system clock while fetching the resource. The difference between any two chronologically recorded timing attributes MUST never be negative. For all resources, including subdocument resources, the user agent MUST record the system clock at the beginning of the root document navigation and define subsequent timing attributes in terms of a monotonic clock measuring time elapsed from the beginning of the navigation.

Privacy and Security

The PerformanceResourceTiming interface exposes timing information for a resource to any web page or worker that has requested that resource. To limit the access to the PerformanceResourceTiming interface, the same origin policy is enforced by default and certain attributes are set to zero, as described in . Resource providers can explicitly allow all timing information to be collected for a resource by adding the Timing-Allow-Origin HTTP response header, which specifies the domains that are allowed to access the timing information.

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 PerformanceResourceTiming interface gives timing information for resources in a document, the cross-origin restrictions prevent making this privacy concern any worse than it is today using the load event on resources to measure timing to determine cache hits and misses.

Acknowledgments

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 and William Chan for their contributions to this work.