This specification defines an API to enable web content to access external presentation-type displays and use them for presenting web content.

Since publication as Working Draft on 11 February 2016, the Working Group has further refined some of the procedures, notably those linked to the receiving user agent, specified the algorithm for generating a presentation identifier, clarified the expected behavior when a presentation is started using the default presentation request, added recommendations for reusing the locale settings of the controller in presentations, and further refined text to ease testing. The Working Group also conducted horizontal reviews on accessibility, internationalization, privacy, security and technical architecture principles with the help of relevant groups at W3C.

The Working Group intends to publish a Candidate Recommendation once it has fixed remaining issues and made initial progress on the test suite. Wide reviews of this document are encouraged.

Introduction

This specification aims to make presentation displays such as projectors or connected TVs, available to the Web and takes into account displays that are attached using wired (HDMI, DVI, or similar) and wireless technologies (Miracast, Chromecast, DLNA, AirPlay, or similar).

Devices with limited screen size lack the ability to show content to a larger audience, for example, a group of colleagues in a conference room, or friends and family at home. Showing content on an external large presentation display helps to improve the perceived quality and impact of the presented content.

At its core, this specification enables an exchange of messages between a page that acts as the controller and another page that represents the presentation shown in the presentation display. How the messages are transmitted is left to the UA in order to allow the use of presentation display devices that can be attached in a wide variety of ways. For example, when a presentation display device is attached using HDMI or Miracast, the same UA that acts as the controller renders the presentation. Instead of displaying the presentation in another window on the same device, however, it can use whatever means the operating system provides for using the external presentation displays. In such a case, both the controller and presentation run on the same UA and the operating system is used to route the presentation display output to the presentation display. This is commonly referred to as the 1-UA case. This specification imposes no requirements on the presentation display devices connected in such a manner.

If the presentation display is able to render HTML documents and communicate with the controller, the controller does not need to render the presentation. In this case, the UA acts as a proxy that requests the presentation display to show and render the presentation itself. This is commonly referred to as the 2-UA case. This way of attaching to displays could be enhanced in the future by defining a standard protocol for delivering these types of messages that display devices could choose to implement.

The API defined here is intended to be used with UAs that attach to presentation display devices through any of the above means.

Use cases and requirements

Use cases and requirements are captured in a separate Presentation API Use Cases and Requirements document.

Requirements phrased in the imperative as part of algorithms (such as "strip any leading space characters" or "return false and terminate these steps") are to be interpreted with the meaning of the key word ("MUST", "SHOULD", "MAY", etc.) used in introducing the algorithm.

Conformance requirements phrased as algorithms or specific steps may be implemented in any manner, so long as the result is equivalent. (In particular, the algorithms defined in this specification are intended to be easy to follow, and not intended to be performant.)

Conformance Classes

This specification describes the conformance criteria for two classes of user agents.

Controlling user agent

Web browsers that conform to the specifications of a controlling user agent must be able to start and control presentations by providing a controlling browsing context as described in this specification. This context implements the Presentation, PresentationConnection, PresentationConnectionAvailableEvent, and PresentationRequest interfaces.

Receiving user agent

Web browsers that conform to the specifications of a receiving user agent must be able to render presentations by providing a receiving browsing context as described in this specification. This context implements the Presentation, PresentationConnection, PresentationConnectionAvailableEvent, and PresentationReceiver interfaces.

One user agent may act both as a controlling user agent and as a receiving user agent, if it provides both browsing contexts and implements all of their required interfaces. This can happen when the same user agent is able to host the controlling browsing context and the receiving browsing context for a presentation, as in the 1-UA implementation of the API.

Conformance requirements phrased against a user agent apply either to a controlling user agent, a receiving user agent or to both classes, depending on the context.

Terminology

The terms browsing context, nested browsing context, event handler, event handler event type, firing an event, firing a simple event, navigate, queue a task, trusted event, allowed to show a popup, top-level browsing context, unload a document, session history, sandboxing flag set, active sandboxing flag set, parse a sandboxing directive, sandboxed auxiliary navigation browsing context flag, sandboxed top-level navigation browsing context flag, and settings object are defined in [[!HTML5]].

The term in parallel is defined in [[!HTML51]].

This document provides interface definitions using the Web IDL standard ([[!WEBIDL]]). The terms Promise, ArrayBuffer, ArrayBufferView are defined in [[!WEBIDL]].

The term throw in this specification is used as defined in [[!WEBIDL]]. The following exception names are defined by WebIDL and used by this specification:

The terms resolving a Promise and rejecting a Promise are used as explained in [[!PROMGUIDE]].

The term URL is defined in the WHATWG URL standard [[!URL]].

The term Blob is defined in the File API specification [[!FILEAPI]].

The header Accept-Language is defined in HTTP 1/.1 [[!rfc7231]].

The term RTCDataChannel is defined in the WebRTC API specification [[WEBRTC]].

The term cookie store is defined in RFC 6265 [[COOKIES]].

The term UUID is defined in RFC 4122 [[rfc4122]].

The terms permission and permission state are defined in [[PERMISSIONS]].

The term database is defined in [[INDEXEDDB]].

The terms localStorage and sessionStorage are defined in [[WEBSTORAGE]].

The terms potentially secure, a priori unauthenticated URL, and prohibits mixed security contexts algorithm are defined in [[!MIXED-CONTENT]].

The term DIAL is defined in [[DIAL]].

Examples

This section shows example codes that highlight the usage of main features of the Presentation API. In these examples, controller.html implements the controller and presentation.html implements the presentation. Both pages are served from the domain http://example.org (http://example.org/controller.html and http://example.org/presentation.html). These examples assume that the controlling page is managing one presentation at a time. Please refer to the comments in the code examples for further details.

Monitor availability of presentation displays example

<!-- controller.html -->
<button id="presentBtn" style="display: none;">Present</button>
<script>
  // The Present button is visible if at least one presentation display is available
  var presentBtn = document.getElementById("presentBtn");
  // It is also possible to use relative presentation URL e.g. "presentation.html"
  var presUrl = "http://example.com/presentation.html";
  // show or hide present button depending on display availability
  var handleAvailabilityChange = function(available) {
    presentBtn.style.display = available ? "inline" : "none";
  };
  // Promise is resolved as soon as the presentation display availability is
  // known.
  var request = new PresentationRequest(presUrl);
  request.getAvailability().then(function(availability) {
    // availability.value may be kept up-to-date by the controlling UA as long
    // as the availability object is alive. It is advised for the web developers
    // to discard the object as soon as it's not needed.
    handleAvailabilityChange(availability.value);
    availability.onchange = function() { handleAvailabilityChange(this.value); };
  }).catch(function() {
    // Availability monitoring is not supported by the platform, so discovery of
    // presentation displays will happen only after request.start() is called.
    // Pretend the devices are available for simplicity; or, one could implement
    // a third state for the button.
    handleAvailabilityChange(true);
  });
</script>

Starting a new presentation example

<!-- controller.html -->
<script>
  presentBtn.onclick = function () {
    // Start new presentation.
    request.start()
      // The connection to the presentation will be passed to setConnection on
      // success.
      .then(setConnection);
      // Otherwise, the user canceled the selection dialog or no screens were
      // found.
  };
</script>

Reconnect to a presentation example

<!-- controller.html -->
<button id="reconnectBtn" style="display: none;">Reconnect</button>
<script>
  var reconnect = function () {
    // read presId from localStorage if exists
    var presId = localStorage["presId"];
    // presId is mandatory when reconnecting to a presentation.
    if (!!presId) {
      request.reconnect(presId)
        // The new connection to the presentation will be passed to
        // setConnection on success.
        .then(setConnection);
        // No connection found for presUrl and presId, or an error occurred.
    }
  };
  // On navigation of the controller, reconnect automatically.
  document.addEventListener("DOMContentLoaded", reconnect);
  // Or allow manual reconnection.
  reconnectBtn.onclick = reconnect;
</script>

Presentation initation by the controlling UA example

<!-- controller.html -->
<!-- Setting presentation.defaultRequest allows the page to specify the
     PresentationRequest to use when the controlling UA initiates a
     presentation. -->
<script>
  navigator.presentation.defaultRequest = new PresentationRequest(defaultUrl);
  navigator.presentation.defaultRequest.onconnectionavailable = function(evt) {
    setConnection(evt.connection);
  };
</script>

Monitor connection's state and exchange data example

<!-- controller.html -->
<button id="disconnectBtn" style="display: none;">Disconnect</button>
<button id="terminateBtn" style="display: none;">Stop</button>
<script>
  var connection;

  // The Disconnect and Stop buttons are visible if there is a connected presentation
  var disconnectBtn = document.getElementById("disconnectBtn");
  var stopBtn = document.getElementById("stopBtn");
  stopBtn.onclick = function () { connection && connection.terminate(); };

  var setConnection = function (theConnection) {
    // Disconnect from existing presentation, if any
    close();
    // Set the new connection and save the presentation ID
    connection = theConnection;
    localStorage["presId"] = connection.id;

    // monitor connection's state
    connection.onconnect = function () {
      // Allow the user to disconnect from or terminate the presentation
      disconnectBtn.style.display = "inline";
      stopBtn.style.display = "inline";
      reconnectBtn.style.display = "none";

      // register message handler
      this.onmessage = function (message) {
        console.log("receive message", message.data);
      };
      // send initial message to presentation page
      this.send("say hello");
    };
    connection.onclose = reset;
    connection.onterminate = function () {
      // remove presId from localStorage if exists
      delete localStorage["presId"];
      // Reset the UI
      reset();
    };
  };

  var reset = function () {
    connection = null;
    disconnectBtn.style.display = "none";
    stopBtn.style.display = "none";
    reconnectBtn.style.display = localStorage["presId"] ? "inline" : "none";
  };

  var close = function () { connection && connection.close(); };
  disconnectBtn.onclick = close;
</script>

Monitor available connection(s) and say hello

<!-- receiver.html -->
<script>
  var addConnection = function(connection) {
    connection.onconnect = function () {
      this.onmessage = function (message) {
        if (message.data == "say hello")
          this.send("hello");
      };
    };
  };

  navigator.presentation.receiver.connectionList.then(function (list) {
    list.connections.map(function (connection) {
      addConnection(connection);
    });
    list.connections.onconnectionavailable = function (connections) {
      addConnection(connections[connections.length - 1]);
    };
  });
</script>

Passing locale information with a message

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

<!-- receiver.html -->
<script>
  connection.onmessage = function (message) {
    var messageObj = JSON.parse(message);
    var spanElt = document.createElement("SPAN");
    spanElt.lang = messageObj.lang;
    spanElt.textContent = messageObj.string;
    document.appendChild(spanElt);
  };
</script>

API

Common idioms

A presentation display refers to an external screen available to the user agent via an implementation specific connection technology.

A presentation connection is an object relating a controlling browsing context to its receiving browsing context and enables two-way-messaging between them. Each presentation connection has a presentation connection state, a unique presentation identifier to distinguish it from other presentations, and a presentation URL that is a URL used to create or reconnect to the presentation. A valid presentation identifier consists of alphanumeric ASCII characters only and is at least 16 characters long.

A controlling browsing context (or controller for short) is a browsing context that has connected to a presentation by calling start() or reconnect(), or received a presentation connection via a connectionavailable event.

The receiving browsing context (or presentation for short) is the browsing context responsible for rendering to a presentation display. A receiving browsing context can reside in the same user agent as the controlling browsing context or a different one. A receiving browsing context is created by following the steps to create a receiving browsing context.

In a procedure, the destination browsing context is the receiving browsing context when the procedure is initiated at the controlling browsing context, or the controlling browsing context if it is initiated at the receiving browsing context.

The set of controlled presentations, initially empty, contains the presentation connections created by the controlling browsing contexts for the controlling user agent (or a specific user profile within that user agent). The set of controlled presentations is represented by a list of PresentationConnection objects that represent the underlying presentation connections. Several PresentationConnection objects may share the same presentation URL and presentation identifier in that set, but there can be only one PresentationConnection with a specific presentation URL and presentation identifier for a given controlling browsing context.

The set of presentation controllers, initially empty, contains the presentation connections created by a receiving browsing context for the receiving user agent. The set of presentation controllers is represented by a list of PresentationConnection objects that represent the underlying presentation connections. All presentation connections in this set share the same presentation URL and presentation identifier.

In a receiving browsing context, the presentation controllers monitor, initially set to null, exposes the current set of presentation controllers to the receiving application. The presentation controllers monitor is represented by a PresentationConnectionList.

In a receiving browsing context, the presentation controllers promise, which is initially set to null, provides the presentation controllers monitor once the initial presentation connection is established. The presentation controllers promise is represented by a Promise that resolves with the presentation controllers monitor.

Interface Presentation

          partial interface Navigator {
            [SameObject] readonly attribute Presentation? presentation;
          };
          
          interface Presentation {
          };
        

The presentation attribute is used to retrieve an instance of the Presentation interface. It MUST return the Presentation instance.

Controlling user agent

            partial interface Presentation {
              attribute PresentationRequest? defaultRequest;
            };
          

In a controlling user agent, the defaultRequest attribute MUST return the default presentation request if any, null otherwise. In a receiving browsing context, it MUST return null.

If set by the controller, the value of the defaultRequest attribute SHOULD be used by the controlling user agent as the default presentation request for that controlling browsing context. When the controlling user agent wishes to initiate a PresentationConnection on the behalf of that browsing context, it MUST start a presentation using the default presentation request for the controller (as if the controller had called defaultRequest.start()).

The controlling user agent SHOULD initiate presentation using the default presentation request only when the user has expressed an intention to do so via a user gesture, for example by clicking a button in the browser.

If a controlling user agent does not support initiation of a presentation connection from the browser chrome, setting defaultRequest will have no effect.
Some controlling user agents may allow the user to initiate a default presentation connection and select a presentation display with the same user gesture. For example, the browser chrome could allow the user to pick a display from a menu, or allow the user to tap on an Near Field Communications (NFC) enabled display. In this case, when the controlling user agent asks for permission while starting a presentation, the browser could offer that display as the default choice, or consider the gesture as granting permission for the display and bypass display selection entirely.

Receiving user agent

            partial interface Presentation {
              [SameObject] readonly attribute PresentationReceiver? receiver;
            };
          

In a receiving user agent, the receiver attribute MUST return the PresentationReceiver instance associated with the receiving browsing context and created by the receiving user agent when the receiving browsing context is created. In any other browsing context, it MUST return null.

A user agent that is a receiving user agent but not a controlling user agent MUST always return null for the defaultRequest attribute. It MUST treat setting the defaultRequest attribute as a no-op.

A user agent that is a controlling user agent but not a receiving user agent MUST always return null for the receiver attribute.

Interface PresentationRequest

          [Constructor(DOMString url)]
          interface PresentationRequest : EventTarget {
            Promise<PresentationConnection> start();
            Promise<PresentationConnection> reconnect(DOMString presentationId);
            Promise<PresentationAvailability> getAvailability();

            attribute EventHandler onconnectionavailable;
          };


A PresentationRequest object is associated with a request to initiate or reconnect to a presentation made by a controlling browsing context. The PresentationRequest object MUST be implemented in a controlling browsing context provided by a controlling user agent.

When a PresentationRequest is constructed, the given url MUST be used as the presentation request URL which is the presentation URL for the PresentationRequest instance.

Constructing a PresentationRequest

When the PresentationRequest constructor is called, the controlling user agent MUST run these steps:

Input
url, the presentation request URL
Output
A PresentationRequest object
  1. Resolve url relative to the API base URL specified by the entry settings object, and let presentationUrl be the resulting absolute URL, if any.
  2. If the resolve a URL algorithm failed, then throw a SyntaxError exception and abort the remaining steps.
  3. Construct a new PresentationRequest object with presentationUrl as the constructor argument and return it.

Starting a presentation

When the start method is called, the user agent MUST run the following steps to start a presentation:

Input
presentationRequest, the PresentationRequest object
presentationUrl, the presentation request URL
Output
A Promise
  1. If the algorithm isn't allowed to show a popup, return a Promise rejected with an InvalidAccessError exception and abort these steps.
  2. Using the document's settings object, run the prohibits mixed security contexts algorithm.
  3. If the result of the algorithm is "Prohibits Mixed Security Contexts" and presentationUrl is an a priori unauthenticated URL, then return a Promise rejected with a SecurityError and abort these steps.
  4. If the document object's active sandboxing flag set has the sandboxed presentation browsing context flag set, then return a Promise rejected with a SecurityError and abort these steps.
  5. If there is already an unsettled Promise from a previous call to start for the same controlling browsing context, return a Promise rejected with an OperationError exception and abort all remaining steps.
  6. Let P be a new Promise.
  7. Return P, but continue running these steps in parallel.
  8. If the user agent is not monitoring the list of available presentation displays, run the steps to monitor the list of available presentation displays in parallel.
  9. Request user permission for the use of a presentation display and selection of one presentation display.
  10. If either of the following is true:
    1. The list of available presentation displays is empty and will remain so before the request for user permission is completed.
    2. No member in the list of available presentation displays is a compatible presentation display for presentationUrl.
    Then run the following steps:
    1. Reject P with a NotFoundError exception.
    2. Abort all remaining steps.
  11. If the user denied permission to use a display, reject P with an NotAllowedError exception, and abort all remaining steps.
  12. Otherwise, the user granted permission to use a display; let D be that display and U the user agent connected to D.
  13. Let I be a new valid presentation identifier unique among all presentation identifiers for known presentation connections in the set of controlled presentations. To avoid fingerprinting, it is recommended that the presentation identifier be set to a UUID generated following forms 4.4 or 4.5 of [[rfc4122]].
  14. Create a new PresentationConnection S.
  15. Set the presentation identifier of S to I.
  16. Set the presentation URL of S to presentationUrl.
  17. Set the presentation connection state of S to connecting.
  18. Add S to the set of controlled presentations.
  19. Resolve P with S.
  20. Queue a task to fire a trusted event with the name connectionavailable, that uses the PresentationConnectionAvailableEvent interface, with the connection attribute initialized to S, at presentationRequest. The event must not bubble, must not be cancelable, and has no default action.
  21. If any of the following steps fails, abort all remaining steps and close the presentation connection S with error as closeReason, and a human readable message describing the failure as closeMessage.
  22. Using an implementation specific mechanism, tell U to create a receiving browsing context with D, presentationUrl, and I as parameters.
  23. Establish a presentation connection with S.
The details of implementing the permission request and display selection are left to the user agent; for example it may show the user a dialog and allow the user to select an available display (granting permission), or cancel the selection (denying permission). Implementers are encouraged to show the user whether an available display is currently in use, to facilitate presentations that can make use of multiple displays.
The presentationUrl should name a resource accessible to the local or a remote user agent. This specification defines behavior for presentationUrl using the http or https schemes; behavior for other schemes is not defined by this specification.

Reconnecting to a presentation

When the reconnect(presentationId) method is called on a PresentationRequest presentationRequest, the user agent MUST run the following steps to reconnect to a presentation:

Input
presentationRequest, the PresentationRequest object that reconnect() was called on.
presentationId, a valid presentation identifier
Output
P, a Promise
  1. Using the document's settings object, run the prohibits mixed security contexts algorithm.
  2. If the result of the algorithm is "Prohibits Mixed Security Contexts" and the presentation request URL of presentationRequest is an a priori unauthenticated URL, then return a Promise rejected with a SecurityError and abort these steps.
  3. If the document object's active sandboxing flag set has the sandboxed presentation browsing context flag set, then return a Promise rejected with a SecurityError and abort these steps.
  4. Let P be a new Promise.
  5. Return P, but continue running these steps in parallel.
  6. Search the set of controlled presentations for a PresentationConnection that meets the following criteria: its controlling browsing context is the current browsing context, its presentation connection state is not terminated, its presentation URL is equal to the presentation request URL of presentationRequest, and its presentation identifier is equal to presentationId.
  7. If such a PresentationConnection exists, run the following steps:
    1. Let S be that PresentationConnection.
    2. Resolve P with S.
    3. If the presentation connection state of S is connecting or connected, then abort all remaining steps.
    4. Set the presentation connection state of S to connecting.
    5. Establish a presentation connection with S.
    6. Abort all remaining steps.
  8. Search the set of controlled presentations for the first PresentationConnection that meets the following criteria: its presentation connection state is not terminated, its presentation URL is equal to the presentation request URL of presentationRequest, and its presentation identifier is equal to presentationId.
  9. If such a PresentationConnection exists, run the following steps:
    1. Create a new PresentationConnection S.
    2. Set the presentation identifier of S to presentationId.
    3. Set the presentation URL of S to the presentation request URL of presentationRequest.
    4. Set the presentation connection state of S to connecting.
    5. Add S to the set of controlled presentations.
    6. Resolve P with S.
    7. Queue a task to fire a trusted event with the name connectionavailable, that uses the PresentationConnectionAvailableEvent interface, with the connection attribute initialized to S, at presentationRequest. The event must not bubble, must not be cancelable, and has no default action.
    8. Establish a presentation connection with S.
    9. Abort all remaining steps.
  10. Reject P with a NotFoundError exception.
If no matching presentation is found, we could leave the Promise pending in case a matching presentation is started in the future.

Event Handlers

The following are the event handlers (and their corresponding event handler event types) that must be supported, as event handler IDL attributes, by objects implementing the PresentationRequest interface:

Event handler Event handler event type
onconnectionavailable connectionavailable

Interface PresentationAvailability

          interface PresentationAvailability : EventTarget {
            readonly attribute boolean value;

            attribute EventHandler onchange;
          };

A PresentationAvailability object is associated with available presentation displays and represents the presentation display availability for a presentation request. If the controlling user agent can monitor the list of available presentation displays in the background (without a pending request to start()), the PresentationAvailability object MUST be implemented in a controlling browsing context.

The value attribute MUST return the last value it was set to. The value is updated by the monitor the list of available presentation displays algorithm.

The onchange attribute is an event handler whose corresponding event handler event type is change.

The set of availability objects

The user agent MUST keep track of the set of availability objects requested through the getAvailability() method. The set of availability objects is represented as a set of tuples (A, availabilityUrl), initially empty, where:

  1. A is a live PresentationAvailability object;
  2. availabilityUrl is the presentation request URL when getAvailability() is called to create A.

The list of available presentation displays

The user agent MUST keep a list of available presentation displays. This current list of presentation displays may be used for starting new presentations, and is populated based on an implementation specific discovery mechanism. It is set to the most recent result of the algorithm to monitor the list of available presentation displays.

While there are live PresentationAvailability objects, the user agent MAY monitor the list of available presentation displays continuously, so that pages can use the value property of a PresentationAvailability object to offer presentation only when there are available displays. However, the user agent may not support continuous availability monitoring; for example, because of platform or power consumption restrictions. In this case the Promise returned by getAvailability() MUST be rejected and the algorithm to monitor the list of available presentation displays will only run as part of the start a presentation algorithm.

When there are no live PresentationAvailability objects (that is, the set of availability objects is empty), user agents SHOULD NOT monitor the list of available presentation displays to satisfy the power saving non-functional requirement. To further save power, the user agent MAY also keep track of whether the page holding a PresentationAvailability object is in the foreground. Using this information, implementation specific discovery of presentation displays can be resumed or suspended.

Some presentation displays may only be able to display a subset of Web content because of functional, security or hardware limitations. Examples are set-top boxes, smart TVs or networked speakers capable of rendering only audio. We say that such a display is a compatible presentation display for a presentation request URL if the user agent can reasonably guarantee that the presentation of the URL on that display will succeed.

Getting the presentation displays availability information

When the getAvailability() method is called, the user agent MUST run the following steps:

Input
presentationUrl, the presentation request URL
Output
P, a Promise
  1. If one of the following conditions is true: Run the following substeps:
    1. Return a Promise rejected with a SecurityError.
    2. Abort these steps.
  2. Let P be a new Promise.
  3. Return P, but continue running these steps in parallel.
  4. If the user agent is unable to monitor the list of available presentation displays for the entire duration of the controlling browsing context (e.g., because the user has disabled this feature), then:
    1. Resolve P with a new PresentationAvailability object with its value property set to false.
    2. Abort all the remaining steps.
  5. If the user agent is unable to continuously monitor the list of available presentation displays but can find presentation displays in order to start a connection, then:
    1. Reject P with a NotSupportedError exception.
    2. Abort all the remaining steps.
  6. If there exists a tuple (A, presentationUrl) in the set of availability objects, then:
    1. Resolve P with A.
    2. Abort all the remaining steps.
  7. Let A be a new PresentationAvailability object with its value property set to false if the list of available presentation displays is empty or none of them is a compatible presentation display, true otherwise.
  8. Create a tuple (A, presentationUrl) and add it to the set of availability objects.
  9. Run the algorithm to monitor the list of available presentation displays.
  10. Resolve P with A.

Monitoring the list of available presentation displays

If the set of availability objects is non-empty, or there is a pending request to start a presentation, the user agent MUST monitor the list of available presentation displays by running the following steps.

  1. Retrieve available presentation displays (using an implementation specific mechanism) and let newDisplays be this list.
  2. For each member (A, availabilityUrl) of the set of availability objects:
    1. Set previousAvailability to the value of A's value property.
    2. Let newAvailability be true if newDisplays is not empty and at least one display in newDisplays is a compatible presentation display for availabilityUrl. Otherwise, set newAvailability to false.
    3. If previousAvailability is not equal to newAvailability, then queue a task to run the following steps:
      1. Set A's value property to newAvailability.
      2. Fire a simple event named change at A.
  3. Set the list of available presentation displays to the value of newDisplays.

When a PresentationAvailability object is no longer alive (i.e., is eligible for garbage collection), the user agent SHOULD run the following steps:

  1. Find and remove any entry (A, availabilityUrl) in the set of availability objects for the newly deceased A.
  2. If the set of availability objects is now empty and there is no pending request to start a presentation, cancel any pending task to monitor the list of available presentation displays for power saving purposes.
The mechanism used to monitor presentation displays availability and determine the compatibility of a presentation display with a given URL is left to the user agent.

Interface PresentationConnectionAvailableEvent

            [Constructor(DOMString type, PresentationConnectionAvailableEventInit eventInitDict)]
            interface PresentationConnectionAvailableEvent : Event {
              [SameObject] readonly attribute PresentationConnection connection;
            };

            dictionary PresentationConnectionAvailableEventInit : EventInit {
              required PresentationConnection connection;
            };


A controlling user agent fires a trusted event named connectionavailable on a PresentationRequest when a connection associated with the object is created. It is fired at the PresentationRequest instance, using the PresentationConnectionAvailableEvent interface, with the connection attribute set to the PresentationConnection object that was created. The event is fired for each connection that is created for the controller, either by the controller calling start() or reconnect(), or by the controlling user agent creating a connection on the controller's behalf via defaultRequest.

A receiving user agent fires a trusted event named connectionavailable on a PresentationReceiver when an incoming connection is created. It is fired at the presentation controllers monitor, using the PresentationConnectionAvailableEvent interface, with the connection attribute set to the PresentationConnection object that was created. The event is fired for all connections that are created when monitoring incoming presentation connections.

Interface PresentationConnection

Each presentation connection is represented by a PresentationConnection object. Both the controlling user agent and receiving user agent MUST implement PresentationConnection.

          enum PresentationConnectionState { "connecting", "connected", "closed", "terminated" };
          enum BinaryType { "blob", "arraybuffer" };

          interface PresentationConnection : EventTarget {
            readonly attribute DOMString? id;
            readonly attribute PresentationConnectionState state;
            void close();
            void terminate();
            attribute EventHandler onconnect;
            attribute EventHandler onclose;
            attribute EventHandler onterminate;

            // Communication
            attribute BinaryType binaryType;
            attribute EventHandler onmessage;
            void send (DOMString message);
            void send (Blob data);
            void send (ArrayBuffer data);
            void send (ArrayBufferView data);
          };

The id attribute specifies the presentation connection's presentation identifier.

The state attribute represents the presentation connection's current state. It can take one of the values of PresentationConnectionState depending on the connection state:

When the close() method is called on a PresentationConnection S, the user agent MUST start closing the presentation connection S with closed as closeReason and an empty message as closeMessage.

When the terminate() method is called on a PresentationConnection S in a controlling browsing context, the user agent MUST run the algorithm to terminate a presentation in a controlling browsing context using S.

When the terminate() method is called on a PresentationConnection S in a receiving browsing context, the user agent MUST run the algorithm to terminate a presentation in a controlling browsing context using S.

When a PresentationConnection object is created, its binaryType IDL attribute MUST be set to the string "arraybuffer". On getting, it MUST return the last value it was set to. On setting, the user agent MUST set the IDL attribute to the new value.

The binaryType attribute allows authors to control how binary data is exposed to scripts. By setting the attribute to "blob", binary data is returned in Blob form; by setting it to "arraybuffer", it is returned in ArrayBuffer form. The attribute defaults to "arraybuffer". This attribute has no effect on data sent in a string form.

When the send() method is called on a PresentationConnection S, the user agent MUST run the algorithm to send a message through S.

When a PresentationConnection object S is discarded (because the document owning it is navigating or is closed) while the presentation connection state of S is connecting or connected, the user agent SHOULD start closing the presentation connection S with wentaway as closeReason and an empty closeMessage.

If the user agent receives a signal from the destination browsing context that a PresentationConnection S is to be closed, it SHOULD close the presentation connection S with closed or wentaway as closeReason and an empty closeMessage.

Establishing a presentation connection

When the user agent is to establish a presentation connection using a presentation connection, it MUST run the following steps:

Input
presentationConnection, the PresentationConnection object that is to be connected. The presentation connection state of presentationConnection must be connecting.
  1. Request connection of presentationConnection to the receiving browsing context. The presentation identifier of presentationConnection MUST be sent with this request.
  2. If connection completes successfully, queue a task to run the following steps:
    1. Set the presentation connection state of presentationConnection to connected.
    2. Fire a simple event named connect at presentationConnection.
The mechanism that is used to present on the remote display and connect the controlling browsing context with the presented document is an implementation choice of the user agent. The connection must provide a two-way messaging abstraction capable of carrying DOMString payloads in a reliable and in-order fashion as described in the Send a Message and Receive a Message steps below.
If the connection step does not complete successfully, the user agent may choose to re-execute the Presentation Connection algorithm at a later time.

Sending a message through PresentationConnection

No specific transport for the connection between the controlling browsing context and the receiving browsing context is mandated, except that for multiple calls to send() it has to be ensured that messages are delivered to the other end reliably and in sequence. The transport should function equivalently to an RTCDataChannel in reliable mode.

Let presentation message data be the payload data to be transmitted between two browsing contexts. Let presentation message type be the type of that data, one of text or binary.

When the user agent is to send a message through a presentation connection, it MUST run the following steps:

Input
presentationConnection, the presentation connection connected to the other browsing context
messageOrData, the presentation message data to send to the other browsing context
  1. If the state property of presentationConnection is not connected, throw an InvalidStateError exception.
  2. If the closing procedure of presentationConnection has started, then abort these steps.
  3. Let presentation message type messageType be binary if messageOrData is of type ArrayBuffer, ArrayBufferView, or Blob. Let messageType be text if messageOrData is of type DOMString.
  4. Using an implementation specific mechanism, transmit the contents of messageOrData as the presentation message data and messageType as the presentation message type to the destination browsing context.
  5. If the previous step encounters an unrecoverable error, then abruptly close the presentation connection presentationConnection with error as closeReason, and a closeMessage describing the error encountered.

To assist applications in recovery from an error sending a message through a presentation connection, the user agent should include details of which attempt failed in closeMessage. Example renditions of closeMessage:

  • Unable to send message: "hello" for DOMString messages, where "hello" is the first 256 characters of the failed message.
  • Unable to send binary message for ArrayBuffer, ArrayBufferView and Blob messages.
When sending a user-visible string via a presentation connection, the page author should take care to ensure that locale information is also propagated so that the destination user agent can know how to best render the string. See the examples for one solution.

Receiving a message through PresentationConnection

When the user agent has received a transmission from the remote side consisting of presentation message data and presentation message type, it MUST run the following steps to receive a message through a PresentationConnection:

Input
presentationConnection, the presentation connection receiving the message
messageType, the presentation message type of the message
messageData, the presentation message data of the message
  1. If the state property of presentationConnection is not connected, abort these steps.
  2. Let event be a newly created trusted event that uses the MessageEvent interface, with the event type message, which does not bubble, is not cancelable, and has no default action.
  3. Initialize the event's data attribute as follows:
    1. If messageType is text, then initialize event's data attribute to messageData with type DOMString.
    2. If messageType is binary, and binaryType attribute is set to "blob", then initialize event's data attribute to a new Blob object with messageData as its raw data.
    3. If messageType is binary, and binaryType attribute is set to "arraybuffer", then initialize event's data attribute to a new ArrayBuffer object whose contents are messageData.
  4. Queue a task to fire event at presentationConnection.

If the user agent encounters an unrecoverable error while receiving a message through presentationConnection, it SHOULD abruptly close the presentation connection presentationConnection with error as closeReason, and a human readable description of the error encountered as closeMessage.

Interface PresentationConnectionClosedEvent

            enum PresentationConnectionClosedReason { "error", "closed", "wentaway" };

            [Constructor(DOMString type, PresentationConnectionClosedEventInit eventInitDict)]
            interface PresentationConnectionClosedEvent : Event {
              readonly attribute PresentationConnectionClosedReason reason;
              readonly attribute DOMString message;
            };

            dictionary PresentationConnectionClosedEventInit : EventInit {
              required PresentationConnectionClosedReason reason;
              DOMString message = "";
            };


A PresentationConnectionClosedEvent is fired when a presentation connection enters a closed state. The reason attribute provides the reason why the connection was closed:

  • error means that the mechanism for connecting or communicating with a presentation entered an unrecoverable error.
  • closed means that either the controlling browsing context or the receiving browsing context that were connected by the PresentationConnection called close().
  • wentaway means that the browser closed the connection, for example, because the browsing context that owned the connection navigated or was discarded.

When the reason attribute is error, the user agent SHOULD set the error message to a human readable description of how the communication channel encountered an error.

Closing a PresentationConnection

When the user agent is to start closing a presentation connection, it MUST do the following:

Input
presentationConnection, the presentation connection to be closed
closeReason, the PresentationConnectionClosedReason describing why the connection is to be closed
closeMessage, a human-readable message with details of why the connection was closed.
  1. If the presentation connection state of presentationConnection is not connecting or connected then abort the remaining steps.
  2. Set the presentation connection state of presentationConnection to closed.
  3. Start to signal to the destination browsing context the intention to close the corresponding PresentationConnection, passing the closeReason to that context. The user agent does not need to wait for acknowledgement that the corresponding PresentationConnection was actually closed before proceeding to the next step.
  4. If closeReason is not wentaway, then locally run the steps to close the presentation connection with presentationConnection, closeReason, and closeMessage.

When the user agent is to close a presentation connection, it MUST do the following:

Input
presentationConnection, the presentation connection to be closed
closeReason, the PresentationConnectionClosedReason describing why the connection is to be closed
closeMessage, a human-readable message with details of why the connection was closed.
  1. If there is a pending close the presentation connection task for presentationConnection, or a close the presentation connection task has already run for presentationConnection, then abort the remaining steps.
  2. Queue a task to run the following steps:
    1. If the presentation connection state of presentationConnection is not connecting, connected, or closed, then abort the remaining steps.
    2. If the presentation connection state of presentationConnection is not closed, set it to closed.
    3. Fire a trusted event with the name close, that uses the PresentationConnectionClosedEvent interface, with the reason attribute initialized to closeReason and the message attribute initialized to closeMessage, at presentationConnection. The event must not bubble, must not be cancelable, and has no default action.
Refine this procedure to specify handling of messages in-flight when the connection is being closed.

Terminating a presentation in a controlling browsing context

When a controlling user agent is to terminate a presentation in a controlling browsing context using connection, it MUST run the following steps:

  1. If the presentation connection state of connection is not connected, then abort these steps.
  2. Otherwise, for each known connection in the set of controlled presentations in the controlling user agent:
    1. If the presentation identifier of known connection and connection are equal, and the presentation connection state of known connection is connected, then queue a task to run the following steps:
      1. Set the presentation connection state of known connection to terminated.
      2. Fire a simple event named terminate at known connection.
  3. Send a termination request for the presentation to its receiving user agent using an implementation specific mechanism.

Terminating a presentation in a receiving browsing context

When any of the following occur, the receiving user agent MUST terminate a presentation in a receiving browsing context:

  1. The receiving user agent is to unload a document corresponding to the receiving browsing context, e.g. in response to a call to window.close() in the top-level browsing context or to a request to navigate that context to a new resource.
  2. The user requests to terminate the presentation via the receiving user agent.

    This could happen by an explicit user action, or as a policy of the user agent. For example, the receiving user agent could be configured to terminate presentations that have no PresentationConnection objects whose presentation connection state is in the connected state after 30 minutes.

  3. A controlling user agent sends a termination request to the receiving user agent for that presentation.

When a receiving user agent is to terminate a presentation in a receiving browsing context, it MUST run the following steps:

  1. Let P be the presentation to be terminated.
  2. If there is a receiving browsing context for P, and it has a document for P that is not unloaded, unload a document corresponding to that browsing context.
  3. For each connection in the set of presentation controllers that were created for P, queue a task to run the following steps:
    1. If the presentation connection state of connection is not connected, then abort the following steps.
    2. Send a termination confirmation for P using an implementation specific mechanism to the controlling user agent that owns the destination browsing context for connection.

      Only one termination confirmation needs to be sent per controlling user agent.

Handling a termination confirmation in a controlling user agent

When a receiving user agent is to send a termination confirmation for a presentation P, and that confirmation was received by a controlling user agent, the controlling user agent SHOULD run the following steps:

  1. For each connection in the set of controlled presentations that was connected to P, queue a task to run the following steps:
    1. If the presentation connection state of connection is not connected, then abort the following steps.
    2. Set the presentation connection state of connection to terminated.
    3. Fire a simple event named terminate at connection.

Event Handlers

The following are the event handlers (and their corresponding event handler event types) that must be supported, as event handler IDL attributes, by objects implementing the PresentationConnection interface:

Event handler Event handler event type
onmessage message
onconnect connect
onclose close
onterminate terminate

Interface PresentationReceiver

          interface PresentationReceiver {
            [SameObject] readonly attribute Promise<PresentationConnectionList> connectionList;
          };


The PresentationReceiver interface allows a receiving browsing context to access the controlling browsing contexts and communicate with them. The PresentationReceiver interface MUST be implemented in a receiving browsing context provided by a receiving user agent.

On getting, the connectionList attribute MUST return the result of running the following steps:

  1. If the presentation controllers promise is not null, return the presentation controllers promise and abort all remaining steps.
  2. Otherwise, let the presentation controllers promise be a new Promise.
  3. Return the presentation controllers promise.
  4. If the presentation controllers monitor is not null, resolve the presentation controllers promise with the presentation controllers monitor.

Creating a receiving browsing context

When the user agent is to create a receiving browsing context, it MUST run the following steps:

Input
D, a presentation display chosen by the user
presentationUrl, the presentation request URL
presentationId, the presentation identifier
  1. Create a new top-level browsing context C, set to display content on D.
  2. Set the session history of C to be the empty list.
  3. Set the sandboxed auxiliary navigation browsing context flag on C.
  4. Set the sessionStorage attribute for the Window object associated with C to a new, empty storage area.
  5. Set the localStorage attribute for the Window object associated with C to a new, empty storage area.
  6. Set the cookie store for C to an empty cookie store.
  7. Set the permission state of all Permissions for C to "denied".
  8. Set the IndexedDB databases for C to an empty set of databases.
  9. Navigate C to presentationUrl.
  10. Start monitoring incoming presentation connections for C with presentationId.

The receiving user agent SHOULD fetch resources in a receiving browsing context with an HTTP Accept-Language header that reflects the language preferences of the controlling user agent (i.e., with the same Accept-Language that the controlling user agent would have sent). This will help the receiving user agent render the presentation with fonts and locale-specific attributes that reflect the user's preferences.

When the receiving browsing context is closed, any associated browsing state, including session history, sessionStorage, localStorage, the cookie store, and databases MUST be discarded and not used for any other receiving browsing context.

Interface PresentationConnectionList

          interface PresentationConnectionList : EventTarget {
            readonly attribute FrozenArray<PresentationConnection> connections;
            attribute EventHandler onconnectionavailable;
          };


The connections attribute MUST return the non-terminated set of presentation connections in the set of presentation controllers.

Monitoring incoming presentation connections

When the receiving user agent is to start monitoring incoming presentation connections in a receiving browsing context from controlling browsing contexts, it MUST listen to and accept incoming connection requests from a controlling browsing context using an implementation specific mechanism. When a new connection request is received from a controlling browsing context, the receiving user agent MUST run the following steps:

Input
I, the presentation identifier passed by the controlling browsing context with the incoming connection request.
presentationId, the presentation identifier used to create the receiving browsing context.
  1. If presentationId and I are not equal, refuse the connection and abort all remaining steps.
  2. Create a new PresentationConnection S.
  3. Set the presentation identifier of S to I.
  4. Establish the connection between the controlling and receiving browsing contexts using an implementation specific mechanism.
  5. Set the presentation connection state of S to connected.
  6. Add S to the set of presentation controllers.
  7. If the presentation controllers monitor is null, run the following steps in parallel.
    1. Let the presentation controllers monitor be a new PresentationConnectionList.
    2. Populate the presentation controllers monitor with the set of presentation controllers.
    3. If the presentation controllers promise is not null, resolve the presentation controllers promise with the presentation controllers monitor.
    4. Abort all remaining steps.
  8. Otherwise, run the following steps in parallel.
    1. Populate the presentation controllers monitor with the set of presentation controllers.
    2. Queue a task to fire a trusted event with the name connectionavailable, that uses the PresentationConnectionAvailableEvent interface, with the connection attribute initialized to S, at the presentation controllers monitor. The event must not bubble, must not be cancelable, and has no default action.

Event Handlers

The following are the event handlers (and their corresponding event handler event types) that must be supported, as event handler IDL attributes, by objects implementing the PresentationConnectionList interface:

Event handler Event handler event type
onconnectionavailable connectionavailable

Sandboxing and the allow-presentation keyword

This specification adds a new token, allow-presentation, to the set of tokens allowed in the sandbox attribute of an iframe. It adds a corresponding new flag to the sandboxing flag set:

The sandboxed presentation browsing context flag
This flag disables the Presentation API.

It amends the parse a sandboxing directive algorithm by adding an item to step 3:

Security and privacy considerations

Personally identifiable information

The change event fired on the PresentationAvailability object reveals one bit of information about the presence (or non-presence) of a presentation display typically discovered through the local area network. This could be used in conjunction with other information for fingerprinting the user. However, this information is also dependent on the user's local network context, so the risk is minimized.

The API enables monitoring the list of available presentation displays. How the user agent determines the compatibility and availability of a presentation display with a given URL is an implementation detail. If a controlling user agent matches a presentation request URL to a DIAL application to determine its availability, this feature can be used to probe information about which DIAL applications the user has installed on the presentation display without user consent.

Cross-origin access

A presentation is allowed to be accessed across origins; the presentation URL and presentation ID used to create the presentation are the only information needed to reconnect to a connection from any origin in that user agent. In other words, a presentation is not tied to a particular opening origin.

This design allows controlling contexts from different domains to connect to a shared presentation resource. The security of the presentation ID prevents arbitrary pages from connecting to an existing presentation.

This specification allows a user agent to publish information about its set of controlled presentations, and allows a browsing context on another user agent to connect to a running presentation via reconnect(). To connect, the additional browsing context must discover the presentation URL and presentation ID of the presentation, either provided by the user, or via a shared service.

However, this specification makes no guarantee as to the identity of the connecting party. Once connected, the receiving application may wish to further verify the identity of the connecting party through application-specific means. For example, the connecting application could provide a token via send() that the receiving application could verify corresponds an authorized entity.

User interface guidelines

Origin display

When the user is asked permission to use a presentation display during the steps to start a presentation, the controlling user agent should make it clear what origin is requesting presentation and what origin will be presented.

Display of the origin requesting presentation will help the user understand what content is making the request, especially when the request is initiated from a nested browsing context. For example, embedded content may try to convince the user to click to trigger a request to start an unwanted presentation.

Showing the origin that will be presented will help the user know if that content is from an potentially secure (e.g., https:) origin, and corresponds to a known or expected site. For example, a malicious site may attempt to convince the user to enter login credentials into a presentation page that imitates a legimitate site. Examination of the requested origin will help the user detect these cases.

Cross-device access

When a user starts a presentation, the user will begin with exclusive control of the presentation. However, the Presentation API allows additional devices (likely belonging to distinct users) to connect and thereby control the presentation as well. When a second device connects to a presentation, it is recommended that all connected controlling user agents notify their users via the browser chrome that the original user has lost exclusive access, and there are now multiple controllers for the presentation.

In addition, it may be the case that the receiving user agent is capable of receiving user input, as well as acting as a presentation display. In this case, the receiving user agent should notify its user via browser chrome when a receiving browsing context is under the control of a remote party (i.e., it has one or more connected controllers).

Device Access

The presentation API abstracts away what "local" means for displays, meaning that it exposes network-accessible displays as though they were local displays. The Presentation API requires user permission for a page to access any display to mitigate issues that could arise, such as showing unwanted content on a display viewable by others.

Temporary identifiers and browser state

The presentation URL and presentation ID can be used to connect to a presentation from another browsing context. They can be intercepted if an attacker can inject content into the controlling page.

Incognito mode and clearing of browsing data

The content displayed on the presentation is different from the controller. In particular, if the user is logged in in both contexts, then logs out of the controlling browsing context, she will not be automatically logged out from the receiving browsing context. Applications that use authentication should pay extra care when communicating between devices.

The set of presentations known to the user agent should be cleared when the user requests to "clear browsing data."

When in private browsing mode ("incognito"), the initial set of controlled presentations in that browsing session must be empty. Any presentation connections added to it must be discarded when the session terminates.

Messaging between presentation connections

This spec will not mandate communication protocols between the controlling browsing context and the receiving browsing context, but it should set some guarantees of message confidentiality and authenticity between corresponding presentation connections.

Acknowledgments

Thanks to Wayne Carr, Louay Bassbouss, Anssi Kostiainen, 闵洪波 (Hongbo Min), Anton Vayvod, and Mark Foltz for help with editing, reviews and feedback to this draft.