Copyright © 2015 W3C® (MIT, ERCIM, Keio, Beihang). W3C liability, trademark and document use rules apply.
This specification defines an API to enable web content to access external presentation-type displays and use them for presenting web content.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.
This document was published by the Second Screen Presentation Working Group as a First Public Working Draft. If you wish to make comments regarding this document, please send them to public-secondscreen@w3.org (subscribe, archives). All comments are welcome.
This document is a work in progress and is subject to change. It builds on the final report (dated 18 November 2014) produced by the Second Screen Presentation Community Group. Algorithms have been drafted in particular. Most sections are still incomplete or underspecified. Privacy and security considerations are missing. A few open issues are noted inline. Please check the group's issue tracker on GitHub for an accurate list. Feedback from early experimentations is encouraged to allow the Second Screen Presentation Working Group to evolve the specification based on implementation issues.
Publication as a First Public Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
This document is governed by the 1 August 2014 W3C Process Document.
This specification aims to make secondary displays such as a projector or a connected TV 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 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 requesting page and a presentation page shown in the secondary display. How those messages are transmitted is left to the UA in order to allow for use of display devices that can be attached in a wide variety of ways. For example, when a display device is attached using HDMI or MiraCast, the UA on the requesting device can render the requested presentation page in that same UA, but instead of displaying in a window on that same device, it can use whatever means the operating system provides for using those external displays. In that case, both the requesting page and the presentation page run on the requesting device and the operating system is used to route the presentation display output to the other display device. The second display device doesn't need to know anything about this spec or that the content involves HTML5.
Alternately, some types of external displays may be able to render HTML5 themselves and may have defined their own way to send messages to that content. In that case, the UA on the requesting device would not need to render the presentation page itself. Instead, the UA could act as a proxy translating the request to show a page and the messages into the form understood by the display device.
This way of attaching to displays could be enhanced in the future through definition of a standard protocol for delivering these types of messages that display devices could choose to implement.
The API defined here is intended be used with UAs that attach to display devices through any of the above means.
ISSUE 40: Screen availability mechanism for multiple sessions
The requirements enumerated in this section are derived from the use cases.
Multi-screen enumeration and named identification requirement was removed after discussion on the mailing list.
All diagrams, examples, and notes in this specification are non-normative, as are all sections explicitly marked non-normative. Everything else in this specification is normative.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119. For readability, these words do not appear in all uppercase letters in this specification. [RFC2119]
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 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.)
The terms browsing context, event handlers, event handler event types, firing an event, navigate, queing a task are defined in [HTML5].
The term Promise is defined in [ES6]. 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].
This document provides interface definitions using the [WEBIDL] standard.
ISSUE 42: Make the Example section more concise
        Running in a compliant user agent, code for presenting a page
        http://example.org/presentation.html on the presentation
        display looks as follows:
      
/* controller.html */
<button disabled id=show>Show</button>
<button disabled id=stop>Stop</button>
<script>
var presentation = navigator.presentation,
    showButton = document.getElementById('show'),
    stopButton = document.getElementById('stop');
var session = null;
var screenAvailable = false;
var presentationUrl = 'http://example.org/presentation.html';
var presentationId = localStorage['presentationId'] ||
    new String((Math.random() * 10000).toFixed(0));
// Join an existing presentation if one exists.
presentation.joinSession(presentationUrl, presentationId).then(
    function(existingSession) {
      setSession(existingSession);
      updateButtons();
    },
    function() {
      // No session to join.
    });
presentation.onavailablechange = function(e) {
  screenAvailable = e.available;
  updateButtons();
};
function updateButtons() {
  stopButton.disabled = !session;
  stopButton.onClick = session ? stopPresent : null;
  showButton.disabled = !screenAvailable;
  showButton.onclick = screenAvailable ? startPresent : null;
};
function startPresent() {
  presentation.startSession(presentationUrl, presentationId).then(
      function(newSession) {
        setSession(newSession);
        updateButtons();
      },
      function() {
        // User cancelled, etc.
      });
};
function stopPresent() {
  if (!session) return;
  session.close();
  delete localStorage['presentationId'];
};
function setSession(theSession) {
  // NOTE: We could instead close the current session.
  if (session) return;
  session = theSession;
  localStorage['presentationId'] = session.id;
  session.onstatechange = function() {
    switch (session.state) {
      case 'connected':
        session.postMessage(/*...*/);
        session.onmessage = function() { /*...*/ };
        break;
      case 'disconnected':
        console.log('Disconnected.');
        break;
    }
  };
}
</script>
      
        The availability monitoring for secondary screens begins when the page
        adds an event listener for the availablechange event on
        the navigator.presentation object. If there are already
        available screens when the page adds the first event listener for the
        event, the UA synthesizes a single availablechange event
        to signal the availability.
      
ISSUE 8: Timing of availablechange event to signal screen availability
ISSUE 9: How to filter available screens according to the content being presented
          The "Show" button's state (initially disabled) informs the user of
          the availability of secondary screen(s), and the button's state is
          updated if the availability changes. (The rationale of putting the
          actual boolean information into a property of the event
          e.available is to allow the implementation to optimize
          power consumption for network discovery of remote wireless screens.
          If this information was provided in a globally accessible flag, the
          network discovery could never be suspended for keeping the flag up to
          date.)
        
          Clicking the "Show" button calls
          navigator.presentation.startSession(), which causes the
          user agent to request from the user a screen to show the
          presentation. The url argument indicates the content to
          be presented. The presentationId argument (optional)
          allows the page to identify this presentation instance, and control
          which other pages may connect to it by setting a hard-to-guess id.
        
As previously discussed on the mailing list - we can add convenience here by default-generating an ID.
          If the user selects a screen with an existing presentation showing
          the same url under the same presentationId,
          the opening browsing context is connected to that
          existing presentation. If the user selects a screen without an
          existing presentation, or a screen presenting a different
          url or presentationId, the UA connects to
          the selected screen, brings up a new presentation window on it, and
          starts to show the content denoted by the url argument.
          The UA then connects the opening browsing context to
          this new presentation and allows the opening browsing
          context to exchange messages with it.
        
          navigator.presentation.startSession(url, presentationId)
          returns a Promise to the opening browsing
          context. When the user selects a screen, the presentation page
          is shown and a communication channel has been established the
          Promise resolves to a PresentationSession
          object, which acts as a handle to the presentation for communication
          and state handling. Initially, the state of the
          PresentationSession is "connected". At this
          point, the opening browsing context can communicate with
          the presentation page using the session's postMessage()
          to send messages and its onmessage event handler to
          receive messages. The presentation page will also have access to
          PresentationSession that it can use to send and receive
          messages with the opening browsing context (see Usage on remote screen).
        
          If the user cancels screen selection, the Promise
          returned by startSession(url, presentationId) remains
          unresolved.
        
          ISSUE 20:
          Define return value for cancelled/missing session for
          startSession()/joinSession()
        
          While there is a pending call to startSession asking the
          user to select a screen (that the user has not yet accepted or
          canceled), the browser may choose to reject subsequent calls to
          startSession from the same page, by returning a
          Promise that never resolves. This will prevent the
          browser from needing to 'queue up' requests to present to the user.
        
          ISSUE 21:
          Define whether multiple simultaneous calls are permitted to
          startSession()
        
          The opening browsing context may wish to reconnect to an
          existing presentation without prompting the user to select a screen.
          For example, the site could allow media items from different pages to
          be shown on the same presentation page, and does not want to prompt
          the user on each page to reconnect to that presentation. To reconnect
          automatically, the page may call joinSession(url,
          presentationId), which returns a Promise that
          resolves to an existing PresentationSession if one
          exists that is presenting the same url with the same
          presentationId as was passed originally into
          startSession. The opening browsing context
          can then communicate with the presentation as if the user had
          manually connected to it via startSession.
        
          At the time the joinSession(url, presentationId) method
          is called, if the browser is not aware of any
          PresentationSession with a matching url and
          presentationId, the Promise should remain
          unresolved. The browser may become aware of such a session at a later
          time (for example, by switching to a WiFi network that has a screen
          showing that URL). In this case, the browser may resolve the Promise
          to allow the page to connect to the running session.
        
          If the browser knows of multiple matching sessions, it should connect
          the page to the session that was most recently connected to; if that
          cannot be determined by the browser (for example, if the matching
          sessions have never been connected), then the Promise
          should remain unresolved.
        
ISSUE 39: Resumption of multiple sessions
          If the page calls startSession(url, presentationId) and
          there is a pending Promise from a call to
          joinSession(url, presentationId) (with the same
          url and presentationId, and the user
          selects a screen in response to startSession, then the
          Promise from startSession will be resolved
          and the Promise from joinSession will not.
        
ISSUE 10: Is user permission required to prompt for screen availability information?
ISSUE 12: Necessity of an additional state to indicate a session was resumed
          For addressing the requirement of communication between originating
          page and presentation page/screen, the presenting page can now use
          the same session object. It accesses this object through
          the navigator.presentation.session property, which is
          only non-null for the page on the presentation screen.
        
if (navigator.presentation.session) {
  var session = navigator.presentation.session;
  // Communicate with opening browsing context
  session.postMessage(/*...*/);
  session.onmessage = function() {/*...*/};
  session.onstatechange = function() {
    switch (this.state) {
      case "disconnected":
        // Handle disconnection from opening browsing context
    }
  };
};
        
          When the content denoted by the url argument in the
          startSession() example above is loaded, the page on the
          presentation screen will have its
          navigator.presentation.session property set to the
          session. This session is a similar object as in the first example.
          Here, its initial state is "connected", which means we
          can use it to communicate with the opening browsing
          context using postMessage() and
          onmessage.
        
          The presentation page can also monitor the connection state by
          listening for statechange events. When the state changes
          to "disconnected" the page is made aware of the fact
          that communication with the opening browsing context was
          lost, but it can continue to display the current content. The
          communication can be re-established when a statechange
          event fires with a new state of "connected".
        
ISSUE 19: Specify behavior when multiple controlling pages are connected to the session
ISSUE 18: Define reconnection for cross-page navigation on presenting user agent
ISSUE 14: Define user agent context for rendering the presentation
A presentation display refers to an external screen available to the user agent via an implementation specific connection technology.
A presentation is an active connection between a user agent and a presentation display for displaying web content on the latter at the request of the former.
A presentation session is an object relating an opening browsing context to its presentation display and enabling two-way-messaging between them. Each such object has a presentation session state and a presentation session identifier to distinguish it from other presentation sessions.
          An opening browsing context is a browsing context that has initiated or resumed a
          presentation session by calling
          startSession() or
          joinSession().
        
          Let D be the set of presentations that are currently known
          to the user agent (regardles of their state). D is
          represented as a set of tuples (U, I, S) where U is
          the URL that is being presented;
          I is an alphanumeric identifier for the presentation; and
          S is the user agent's PresentationSession for
          the presentation. U and I together uniquely
          identify the PresentationSession of the corresponding
          presentation.
        
PresentationSession
        
          Each presentation
          session is represented by a PresentationSession
          object.
        
enum PresentationSessionState { "connected", "disconnected" /*, "resumed" */ };
interface PresentationSession : EventTarget {
  readonly DOMString? id;
  readonly attribute PresentationSessionState state;
  void postMessage(DOMString message);
  void close();
  attribute EventHandler onmessage;
  attribute EventHandler onstatechange;
};
        
          The id attribute holds the alphanumeric
          presentation session identifier.
        
          The state attribute represents the
          presentation session's current state. It can take one of
          the values of PresentationSessionState
          depending on connection state.
        
          When the postMessage() method is called on a
          PresentationSession object with a message,
          the user agent must run the algorithm to post a message through a
          PresentationSession.
        
          When the close() method is called on a
          PresentationSession, the user agent must run the
          algorithm to close a presentation
          session.
        
ISSUE 34: Specify the presentation initialization algorithm
PresentationSession
          
            When the user agent is to post
            a message through a PresentationSession S, it
            must run the following steps:
          
PresentationSession
          When the user agent is to close a presentation session S, it must run the following steps:
connected, then:
              disconnected.
            statechange at s.onstatechange.
                        ISSUE 35: Refine how to do session teardown/disconnect/closing
            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
            PresentationSession interface:
          
| Event handler | Event handler event type | 
|---|---|
| onmessage | message | 
| onstatechange | statechange | 
NavigatorPresentation
      partial interface Navigator {
  readonly attribute NavigatorPresentation presentation;
};
      
        The presentation attribute is used to retrieve
        an instance of the NavigatorPresentation interface, the
        main interface of Presentation API.
      
interface NavigatorPresentation : EventTarget {
  readonly attribute PresentationSession? session;
  Promise<PresentationSession> startSession(DOMString url, DOMString? presentationId);
  Promise<PresentationSession> joinSession(DOMString url, DOMString? presentationId);
  attribute EventHandler onavailablechange;
};
      ISSUE 52: Specify the NavigatorPresentation.session attribute and its related algorithms
          When the startSession(presentationUrl,
          presentationId) method is called, the user agent must run the
          following steps:
        
presentationUrl, the URL of the document to be presented
          presentationId, an optional identifier for the
            presentation
          presentationId is not undefined,
                  assign I to that that presentationId.
                  presentationId is undefined,
                  let I be a random alphanumeric value of at least 16
                  characters drawn from the characters
                  [A-Za-z0-9].
                  PresentationSession S.
                  S.url to presentationUrl,
                  set S.id to I, and set
                  S.state to disconnected.
                  presentationUrl in it.
                    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 screen (granting permission), or cancel the selection (denying permission).
          ISSUE: Do we want to distinguish the permission-denied outcome from
          the no-screens-available outcome? Developers would be able to infer
          it anyway from onavailablechange.
        
          When the joinSession(presentationUrl,
          presentationId) method is called, the user agent must run the
          following steps:
        
presentationUrl, the URL of the document being presented
          presentationId, the identifier for the presentation
          presentationUrl
                  and i is equal to presentationId, run
                  the following steps:
                    ISSUE: If no matching presentation is found, we could leave the Promise pending in case a matching presentation is started in the future.
When the user agent is to establish a presentation connection using a presentation session S, it must run the following steps:
connected, then:
            connected.
              statechange at
                            s.onstatechange.
                          
          The mechanism that is used to present on the remote display and
          connect the opening 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 Message and Receive
          Message steps below.
        
If T does not complete successfully, the user agent may choose to re-execute the Presentation Connection algorithm at a later time.
ISSUE: Do we want to notify the caller of a failure to connect, i.e. with an "error" onstatechange?
ISSUE: Do we want to pass the new state as a property of the statechange event?
onavailablechange EventHandler
        
          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
          PresentationSession interface:
        
| Event handler | Event handler event type | 
|---|---|
| onavailablechange | availablechange | 
          In order to satisfy the power saving non-functionional
          requirements the user agent must keep track of the number of
          EventHandlers registered to the onavailable
          event. Using this information, implementation specific discovery of
          presentation displays can
          be resumed or suspended, in order to save power.
        
onavailablechange, the user agent must also keep the list
        up to date by running the algorithm for monitoring the list of available
        presentation displays.
      EventHandler to onavailablechange
        
          When an event handler is added to the list of event handlers
          registered for the onavailablechange event, the user
          agent must run the algorithm to monitor the list of
          available presentation displays.
        
EventHandler
        
          When an event handler is removed from the list of event handlers
          registered to the onavailablechange event, the user
          agent must run the following steps:
        
When the user agent is to monitor the list of available presentation displays, it must run the following steps:
While there are event handlers added to NavigatorPresentation.onavailablechange, the user agent must continuously keep track the list of available presentation displays and repeat the following steps:
availablechange at with the event's
                available property set to true.
              availablechange with the event's
                available property set to false.
              
          The mechanism used to monitor presention displays availability is left
          to the user agent. The user agent may choose search for screens at
          any time, not just when event handlers are added to
          NavigatorPresentation.onavailablechange.
        
When the user agent is to cancel monitoring the list of available presentation displays, it must run the following steps:
availablechange at E
            (and only E) with the event's available
            property set to false.
          AvailableChangeEvent
      [Constructor(DOMString type, optional AvailableChangeEventInit eventInitDict)]
interface AvailableChangeEvent : Event {
  readonly attribute boolean available;
};
dictionary AvailableChangeEventInit : EventInit {
  boolean available;
};
      
        An event named availablechange is fired during the
        execution of the monitoring presentation display
        availability algorithm when the presentation display
        availability changes. It is fired at the
        PresentationSession object, using the
        AvailableChangeEvent interface, with the
        available attribute set to the boolean value that the
        algorithm determined.
      
Thanks to Wayne Carr, Louay Bassbous, Anssi Kostiainen, 闵洪波 (Hongbo Min), Anton Vayvod, and Mark Foltz for help with editing, reviews and feedback to this draft.