HTML Standard Tracker

Filter

File a bug

SVNBugCommentTime (UTC)
5945[Gecko] [Internet Explorer] [Opera] [Webkit] Completely revamp how peer-to-peer networking works (and some minor typo fixes in other parts of the spec). This is only a second draft, and therefore this feature will likely evolve a lot over the coming months. Detailed responses to feedback on the topic will be sent out soon.2011-03-14 10:19
@@ -67,21 +67,21 @@
    href="http://lists.w3.org/Archives/Public/public-html/2010Jun/0001.html">a
    working group decision from June 2010</a>.</li>
 
   </ul>
 
   <p>Features that are considered part of the next generation of HTML
   beyond HTML5 (and that are therefore not included in the W3C version
   of HTML5) currently consist of:</p>
 
   <ul class="brief">
-   <li>The <code>device</code> element.</li> <!--DEVICE-->
+   <li>The <code>PeerConnection</code> API and related video-conferencing features.</li> <!--DEVICE-->
    <li>The <code title="attr-hyperlink-ping">ping</code> attribute and related <span>hyperlink auditing</span> features.</li> <!--PING-->
    <li>The <span>WebVTT</span> format and some <span>text track</span> API features.</li> <!--TT--> <!--TTVTT-->
    <li>Rules for <a href="#atom">converting HTML to Atom</a>.</li> <!--MD-->
    <li>The <code title="dom-document-cssElementMap">cssElementMap</code> feature for defining <span title="CSS element reference identifier">CSS element reference identifiers</span>.</li> <!--CSSREF-->
   </ul>
 
   <p>Features that are part of HTML (and this specification) but that
   are currently published as separate specifications as well, and are
   not included in the W3C HTML5 specification, consist of:</p>
 
@@ -26624,21 +26624,21 @@ href="?audio">audio&lt;/a> test instead.)&lt;/p></pre>
    <dd><span>Embedded content</span>.</dd>
    <dd>If the element has a <code title="attr-media-controls">controls</code> attribute: <span>Interactive content</span>.</dd>
    <dt>Contexts in which this element can be used:</dt>
    <dd>Where <span>embedded content</span> is expected.</dd>
    <dt>Content model:</dt>
    <dd>If the element has a <code title="attr-media-src">src</code> attribute:
 <!--KEEP-END w3c-html--><!--TT-->
  zero or more <code>track</code> elements, then
 <!--KEEP-START w3c-html--><!--TT-->
  <span>transparent</span>, but with no <span>media element</span> descendants.</dd>
-   <dd>If the element does not have a <code title="attr-media-src">src</code> attribute: one or more <code>source</code> elements, then
+   <dd>If the element does not have a <code title="attr-media-src">src</code> attribute: zero or more <code>source</code> elements, then
 <!--KEEP-END w3c-html--><!--TT-->
  zero or more <code>track</code> elements, then
 <!--KEEP-START w3c-html--><!--TT-->
  <span>transparent</span>, but with no <span>media element</span> descendants.</dd>
    <dt>Content attributes:</dt>
    <dd><span>Global attributes</span></dd>
    <dd><code title="attr-media-src">src</code></dd>
    <dd><code title="attr-video-poster">poster</code></dd>
    <dd><code title="attr-media-preload">preload</code></dd>
    <dd><code title="attr-media-autoplay">autoplay</code></dd>
@@ -29586,22 +29586,22 @@ interface <dfn>HTMLAudioElement</dfn> : <span>HTMLMediaElement</span> {};</pre>
     and the <span>media element</span>'s <code>Document</code>'s
     <span>browsing context</span> did not have the <span>sandboxed
     automatic features browsing context flag</span> set when the
     <code>Document</code> was created, then the user agent may also
     set the <code title="dom-media-paused">paused</code> attribute to
     false, <span>queue a task</span> to <span>fire a simple
     event</span> named <code title="event-media-play">play</code>, and
     <span>queue a task</span> to <span>fire a simple event</span>
     named <code title="event-media-playing">playing</code>.</p>
 
-    <p class="note">User agents are not required to autoplay, and it
-    is suggested that user agents honor user preferences on the
+    <p class="note">User agents do not need to support autoplay,
+    and it is suggested that user agents honor user preferences on the
     matter. Authors are urged to use the <code
     title="attr-media-autoplay">autoplay</code> attribute rather than
     using script to force the video to play, so as to allow the user
     to override the behavior if so desired.</p>
 
     <p>In any case, the user agent must finally <span>queue a
     task</span> to <span>fire a simple event</span> named <code
     title="event-media-canplaythrough">canplaythrough</code>.</p>
 
    </dd>
@@ -57090,268 +57090,20 @@ fur
 
    <li>Otherwise, if the element does not have a defined
    <span>activation behavior</span>, <span>fire a <code
    title="event-click">click</code> event</span> at the element.</li>
 
   </ol>
 
   </div>
 
 
-<!--END w3c-html--><!--DEVICE-->
-<div data-component="other Hixie drafts (editor: Ian Hickson)">
-<!--START html-device-->
-
-  <h4 id="devices">The <dfn><code>device</code></dfn> element</h4>
-
-  <dl class="element">
-   <dt>Categories</dt>
-   <dd><span>Flow content</span>.</dd>
-   <dd><span>Phrasing content</span>.</dd>
-   <dd><span>Interactive content</span>.</dd>
-   <dt>Contexts in which this element can be used:</dt>
-   <dd>Where <span>phrasing content</span> is expected.</dd>
-   <dt>Content model:</dt>
-   <dd>Empty.</dd>
-   <dt>Content attributes:</dt>
-   <dd><span>Global attributes</span></dd>
-   <dd><code title="attr-device-type">type</code></dd>
-   <dt>DOM interface:</dt>
-   <dd>
-<pre class="idl">interface <dfn>HTMLDeviceElement</dfn> : <span>HTMLElement</span> {
-           attribute DOMString <span title="dom-device-type">type</span>;
-  readonly attribute any <span title="dom-device-data">data</span>;
-};</pre>
-  </dl>
-
-  <p>The <code>device</code> element represents a device selector, to
-  allow the user to give the page access to a device, for example a
-  video camera.</p>
-
-  <p>The <dfn title="attr-device-type"><code>type</code></dfn>
-  attribute allows the author to specify which kind of device the page
-  would like access to. The attribute is an <span>enumerated
-  attribute</span> with the keywords given in the first column of the
-  following table, and their corresponding states given in the cell in
-  second column of the same row.</p>
-
-  <p class="XXX">RS232 and USB are only included below to give an idea
-  of where we could go with this. <strong>Should we instead just make
-  this only useful for audiovisual streams?</strong> Unless there are
-  compelling reasons, we probably should not be this generic. So far,
-  the reasons for RS232 aren't that compelling. For USB, slightly more
-  so.</p>
-
-  <table>
-   <thead>
-    <tr>
-     <th>Keyword
-     <th>State
-     <th>Device description
-     <th>Examples
-   <tbody>
-    <tr>
-     <td><dfn title="attr-device-type-keyword-media"><code>media</code></dfn>
-     <td><span title="attr-device-type-media">Media</span>
-     <td>Stream of audio and/or video data.
-     <td>A webcam.
-    <tr>
-     <td><dfn title="attr-device-type-keyword-fs"><code>fs</code></dfn>
-     <td><span title="attr-device-type-fs">File system</span>
-     <td>File system.
-     <td>A USB-connected media player.
-    <tr>
-     <td><dfn title="attr-device-type-keyword-rs232"><code>rs232</code></dfn>
-     <td><span title="attr-device-type-rs232">RS232</span>
-     <td>RS232 device.
-     <td>A serial port.
-    <tr>
-     <td><dfn title="attr-device-type-keyword-usb"><code>usb</code></dfn>
-     <td><span title="attr-device-type-usb">USB</span>
-     <td>USB device.
-     <td>A scanner, a music player, a disk jockey, a fish tank.
-  </table>
-
-  <p class="XXX">processing model: 'change' event fires once user
-  selects a new device; .data is set to new Stream, LocalFS, USB, or
-  RS232 object as appropriate.</p>
-
-  <div class="example">
-
-   <pre>&lt;p>To start chatting, select a video camera: &lt;device type=media onchange="update(this.data)">&lt;/p>
-&lt;video autoplay>&lt;/video>
-&lt;script>
- function update(stream) {
-   document.getElementsByTagName('video')[0].src = stream.url;
- }
-&lt;/script></pre>
-
-  </div>
-
-  <p class="XXX">The <code>device</code> element is intended to be a
-  void element, but the parser spec hasn't yet been updated. This
-  section of the spec is very much awaiting implementation
-  experience.</p>
-
-
-  <h5>Stream API</h5>
-
-  <p>The <code>Stream</code> interface is used to represent
-  streams.</p>
-
-  <pre class="idl">interface <dfn>Stream</dfn> {
-  readonly attribute DOMString <span title="dom-stream-url">url</span>;
-  <span>StreamRecorder</span> <span title="dom-stream-record">record</span>();
-};</pre>
-
-  <p>The <dfn title="dom-stream-url"><code>url</code></dfn> attribute
-  must return a <span title="fileURN">File URN</span> representing the
-  stream. <a href="#refsFILEAPI">[FILEAPI]</a></p>
-
-  <p>For audio and video streams, the stream must be in a format
-  supported by the user agent for use in <code>audio</code> and
-  <code>video</code> elements.</p>
-
-  <p class="XXX">This will be pinned down to a specific codec.</p>
-
-  <p>When the <dfn
-  title="dom-stream-record"><code>record()</code></dfn> method is
-  invoked, the user agent must return a new
-  <code>StreamRecorder</code> object associated with the stream.</p>
-
-  <pre class="idl">interface <dfn>StreamRecorder</dfn> {
-  <span>File</span> <span title="dom-StreamRecorder-stop">stop</span>();
-};</pre>
-
-  <p>The <dfn
-  title="dom-StreamRecorder-stop"><code>stop()</code></dfn> method
-  must return a new <code>File</code> object representing the data
-  that was streamed between the creation of the
-  <code>StreamRecorder</code> object and the invocation of the <code
-  title="dom-StreamRecorder-stop">stop()</code> method. <a
-  href="#refsFILEAPI">[FILEAPI]</a></p>
-
-  <p>For audio and video streams, the file must be in a format
-  supported by the user agent for use in <code>audio</code> and
-  <code>video</code> elements.</p>
-
-  <p class="XXX">This again will be pinned down to a specific codec.</p>
-
-
-  <h5>Peer-to-peer connections</h5>
-
-  <p class="XXX">This section will be moved to a more appropriate
-  location in due course; it is here currently to keep it near the
-  <code>device</code> element to allow reviewers to look at it.</p>
-
-  <pre class="idl">[Constructor(in DOMString serverConfiguration)]
-interface <dfn>ConnectionPeer</dfn> {
-  void sendText(in DOMString text, in optional boolean unimportant); // if second arg is true, then use unreliable low-latency transport (UDP-like), otherwise guarantee delivery (TCP-like)
-           attribute <span>Function</span> ontext; // receiving
-
-  void sendBitmap(in HTMLImageElement image);
-           attribute <span>Function</span> onbitmap; // receiving
-
-  void sendFile(in File file);
-           attribute <span>Function</span> onfile; // receiving
-
-  void addStream(in Stream stream);
-  void removeStream(in Stream stream);
-  readonly attribute Stream[] localStreams;
-  readonly attribute Stream[] remoteStreams;
-           attribute <span>Function</span> onstream; // receiving
-
-  void <span title="dom-ConnectionPeer-getLocalConfiguration">getLocalConfiguration</span>(in <span>ConnectionPeerConfigurationCallback</span> callback); // maybe this should be in the constructor, or be an event
-  void <span title="dom-ConnectionPeer-addRemoteConfiguration">addRemoteConfiguration</span>(in DOMString configuration, in optional DOMString remoteOrigin); // remote origin is assumed to be same-origin if not specified. If specified, has to match remote origin (checked in handshake). Should support leading "*." to mean "any subdomain of".
-  void close(); // disconnects and stops listening
-
-           attribute <span>Function</span> onconnect;
-           attribute <span>Function</span> onerror;
-           attribute <span>Function</span> ondisconnect;
-};
-<span>ConnectionPeer</span> implements <span>EventTarget</span>;
-
-[Callback=FunctionOnly, NoInterfaceObject]
-interface <dfn>ConnectionPeerConfigurationCallback</dfn> {
-  void <span title="dom-ConnectionPeerConfigurationCallback-handleEvent">handleEvent</span>(in <span>ConnectionPeer</span> server, in DOMString configuration);
-};</pre>
-
-  <p class="XXX">...</p>
-
-  <div class="XXX">
-
-   <p>This relies on some currently hypothetical other standard to
-   define:</p>
-
-   <ul>
-    <li>The format of server configuration strings.
-    <li>The format of client configuration strings.
-    <li>The protocols that clients use to talk to third-party servers mentioned in the server configuration strings.
-    <li>The protocols that clients use to talk to each other.
-   </ul>
-
-  </div>
-
-  <div class="example">
-
-   <p>When two peers decide they are going to set up a connection to
-   each other, they both go through these steps. The serverConfig
-   comes from a third-party server they can use to get things like
-   their public IP address or to set up NAT traversal. They also have
-   to send their respective configuration to each other using the same
-   out-of-band mechanism they used to establish that they were going
-   to communicate in the first place.</p>
-
-   <pre>var serverConfig = ...; // configuration string obtained from server
-// contains details such as the IP address of a server that can speak some
-// protocol to help the client determine its public IP address, route packets
-// if necessary, etc.
-
-var local = new ConnectionPeer(serverConfig);
-local.getLocalConfiguration(function (configuration) {
-  if (configuration != '') {
-    ...; // send configuration to other peer using out-of-band mechanism
-  } else {
-    // we've exhausted our options; wait for connection
-  }
-});
-
-function ... (configuration) {
-  // called whenever we get configuration information out-of-band
-  local.addRemoteConfiguration(configuration);
-}
-
-local.onconnect = function (event) {
-  // we are connected!
-  local.sendText('Hello');
-  local.addStream(...); // send video
-  local.onstream = function (event) {
-    // receive video
-    // (videoElement is some &lt;video> element)
-    if (local.remoteStreams.length > 0)
-      videoElement.src = local.remoteStreams[0].url;
-  };
-};</pre>
-
-  </div>
-
-  <p class="warning">To prevent network sniffing from allowing a
-  fourth party to establish a connection to a peer using the
-  information sent out-of-band to the other peer and thus spoofing the
-  client, the configuration information should always be transmitted
-  using an encrypted connection.</p>
-
-<!--END html-device-->
-</div>
-<!--START w3c-html--><!--DEVICE-->
-
-
 
 
   <h3 id="links">Links</h3>
 
   <h4>Introduction</h4>
 
   <p>Links are a conceptual construct, created by <code>a</code>,
   <code>area</code>, and <code>link</code> elements, that <span
   title="represents">represent</span> a connection between two
   resources, one of which is the current <code>Document</code>. There
@@ -75955,21 +75707,20 @@ interface <dfn>NavigatorStorageUtils</dfn> {
    method, when invoked, must, if the <span>storage mutex</span> is
    owned by the <span>event loop</span> of the <span
    title="concept-task">task</span> that resulted in the method being
    called, release the <span>storage mutex</span> so that it is once
    again free. Otherwise, it must do nothing.</p>
 
   </div>
 
 
 
-
   <h2 id="editing"><dfn>User interaction</dfn></h2>
 
 
   <h3>The <dfn title="attr-hidden"><code>hidden</code></dfn> attribute</h3>
 
   <p>All <span>HTML elements</span> may have the <code
   title="attr-hidden">hidden</code> content attribute set. The <code
   title="attr-hidden">hidden</code> attribute is a <span>boolean
   attribute</span>. When specified on an element, it indicates that
   the element is not yet, or is no longer, relevant. <span
@@ -81186,22 +80937,1724 @@ interface <dfn>FunctionObjectCallback</dfn> {
    <dd class="impl"><strong>Value</strong>: Always the string "<code title="">false</code>".</dd>
 
   </dl>
 
 <!--
 v2 (well, really v0):
  "forecolor", "hilitecolor", "fontname", "fontsize", "justifyleft",
  "justifycenter", "justifyright", "justifyfull", "indent", "outdent"
 -->
 
+<!--END w3c-html-->
+<div data-component="other Hixie drafts (editor: Ian Hickson)">
+
+  <h2>Video conferencing and peer-to-peer communication</h2>
+
+  <h3>Introduction</h3>
+
+  <!--END dev-html--><p><i>This section is non-normative.</i></p><!--START dev-html-->
+
+  <p>There are a number of facets to video-conferencing in HTML:</p>
+
+  <ul>
+
+   <li>Getting a multimedia stream (video, audio, or both) from local
+   devices (video cameras, microphones, Web cams) or from prerecorded
+   files provided by the user.</li>
+
+   <li>Recording such streams locally.</li>
+
+   <li>Connecting to remote peers using NAT-traversal technologies
+   such as ICE, STUN, and TURN.</li>
+
+   <li>Sending the locally-produced streams to remote peers and
+   receiving streams from remote peers.</li>
+
+   <li>Displaying such streams (both the locally-produced ones and the
+   remotely-obtained ones) locally using the <code>video</code> or
+   <code>audio</code> elements.</li>
+
+   <li>Sending arbitrary data to remote peers.</li>
+
+  </ul>
+
+  <p>This section defines the APIs used for these features.</p>
+
+
+  <h4>Obtaining local multimedia content</h4>
+
+  <pre class="idl">[Supplemental, NoInterfaceObject]
+interface <dfn>NavigatorUserMedia</dfn> {
+  void <span title="dom-navigator-getUserMedia">getUserMedia</span>(in DOMString options, in <span>NavigatorUserMediaSuccessCallback</span> successCallback, in optional <span>NavigatorUserMediaErrorCallback</span> errorCallback);
+};
+<span>Navigator</span> implements <span>NavigatorUserMedia</span>;
+
+[Callback=FunctionOnly, NoInterfaceObject]
+interface <dfn>NavigatorUserMediaSuccessCallback</dfn> {
+  void <span title="dom-NavigatorUserMediaSuccessCallback-handleEvent">handleEvent</span>(in <span>GeneratedStream</span> stream);
+};
+
+[NoInterfaceObject]<!-- this is based on PositionError in geolocation -->
+interface <dfn>NavigatorUserMediaError</dfn> {
+  const unsigned short <span title="dom-NavigatorUserMediaError-PERMISSION_DENIED">PERMISSION_DENIED</span> = 1;<!--
+  const unsigned short <span title="dom-NavigatorUserMediaError-UNAVAILABLE">UNAVAILABLE</span> = 2;
+  const unsigned short <span title="dom-NavigatorUserMediaError-TIMEOUT">TIMEOUT</span> = 3;-->
+  readonly attribute unsigned short <span title="dom-NavigatorUserMediaError-code">code</span>;<!--
+  readonly attribute DOMString <span title="dom-NavigatorUserMediaError-message">message</span>;-->
+};
+
+[Callback=FunctionOnly, NoInterfaceObject]
+interface <dfn>NavigatorUserMediaErrorCallback</dfn> {
+  void <span title="dom-NavigatorUserMediaSuccessCallback-handleEvent">handleEvent</span>(in <span>NavigatorUserMediaError</span> error);
+};</pre>
+
+  <dl class="domintro">
+
+   <dt><var title="">window</var> . <code title="dom-navigator">navigator</code> . <code title="dom-navigator-getUserMedia">getUserMedia</code>(<var title="">options</var>, <var title="">successCallback</var> [, <var title="">errorCallback</var> ] )</dt>
+
+   <dd>
+
+    <p>Prompts the user for permission to use their Web cam or other
+    video or audio input.</p>
+
+    <p>The <var title="">options</var> argument is a string of
+    comma-separated values from the following list:</p>
+
+    <dl>
+
+
+     <dt>"<code title="">audio</code>"</dt>
+
+     <dd>The provided media needs to include audio data.</dd>
+
+
+     <dt>"<code title="">video</code>"</dt>
+
+     <dd>The provided media needs to include video data.</dd>
+
+
+    </dl>
+
+    <p>If the user accepts, the <var title="">successCallback</var> is
+    invoked, with a suitable <code>GeneratedStream</code> object as
+    its argument.</p>
+
+    <p>If the user declines, the <var title="">errorCallback</var> (if
+    any) is invoked.</p>
+
+   </dd>
+
+
+   <dt><var title="">error</var> . <code title="dom-NavigatorUserMediaError-code">code</code></dt>
+
+   <dd>
+
+    <p>Returns the current error's error code. At this time, this will
+    always be 1, for which the constant <code
+    title="dom-NavigatorUserMediaError-PERMISSION_DENIED">PERMISSION_DENIED</code>
+    is defined.</p>
+
+   </dd>
+
+  </dl>
+
+  <div class="impl">
+
+  <p>When the <dfn
+  title="dom-navigator-getUserMedia"><code>getUserMedia()</code></dfn>
+  method is called, the user agent must run the following steps:</p>
+
+  <ol>
+
+   <li><p>Let <var title="">options</var> be the method's first
+   argument.</p></li>
+
+   <li><p>Let <var title="">successCallback</var> be the callback
+   indicated by the method's second argument.</p></li>
+
+   <li><p>Let <var title="">errorCallback</var> be the callback
+   indicated by the method's third argument, if any, or null
+   otherwise.</p></li>
+
+   <li><p>If <var title="">successCallback</var> is null, abort these
+   steps.</p></li> <!-- we could throw an exception instead (that's
+   why the method doesn't return until later: so that we can add an
+   exception here, or for /options/ below, without changing the
+   algorithm) -->
+
+   <li><p><span title="split a string on spaces">Split <var
+   title="">options</var> on spaces</span> to obtain <var
+   title="">list of options</var>.</p></li>
+
+   <li><p>If one of the tokens in <var title="">list of options</var>
+   is a <span>case-sensitive</span> match for the string "<code
+   title="">audio</code>", let <var title="">audio</var> be true.
+   Otherwise, let it be false.</p></li>
+
+   <li><p>If one of the tokens in <var title="">list of options</var>
+   is a <span>case-sensitive</span> match for the string "<code
+   title="">video</code>", let <var title="">video</var> be true.
+   Otherwise, let it be false.</p></li>
+
+   <!-- any error handling for /options/ should be done here (that's
+   why the method doesn't return until the next step: so we can add
+   exception throwing here) -->
+
+   <li><p>Return, and run the remaining steps asynchronously.</p></li>
+
+   <li><p>Optionally, e.g. based on a previously-established user
+   preference, for security reasons, or due to platform limitations,
+   jump to the step labeled <i>failure</i> below.</p></li>
+
+   <li>
+
+    <p>Prompt the user in a user-agent-specific manner for permission
+    to provide the <span>entry script</span>'s <span>origin</span>
+    with a <code>GeneratedStream</code> object representing a media
+    stream.</p>
+
+    <p>If <var title="">audio</var> is true, then the provided media
+    should include an audio component. If <var title="">audio</var>
+    is false, then the provided media must not include an audio
+    component.</p>
+
+    <p>If <var title="">video</var> is true, then the provided media
+    should include a video component. If <var title="">video</var> is
+    false, then the provided media must not include a video
+    component.</p>
+
+    <p>User agents are encouraged to default to using the user's
+    primary or system default camera and/or microphone (as
+    appropriate) to generate the media stream. User agents may allow
+    users to use any media source, including pre-recorded media
+    files.</p>
+
+    <p>If the user grants permission to use local recording devices,
+    user agents are encouraged to include a prominent indicator that
+    the devices are "hot" (i.e. an "on-air" or "recording"
+    indicator).</p>
+
+    <p>If the user denies permission, jump to the step labeled
+    <i>failure</i> below. If the user never responds, this algorithm
+    stalls on this step.</p>
+
+   </li>
+
+   <li><p>Let <var title="">stream</var> be the
+   <code>GeneratedStream</code> object for which the user granted
+   permission.</p></li>
+
+   <li><p><span>Queue a task</span> to invoke <var
+   title="">successCallback</var> with <var title="">stream</var> as
+   its argument.</p></li>
+
+   <li><p>Abort these steps.</p></li>
+
+   <li><p><i>Failure</i>: If <var title="">errorCallback</var> is
+   null, abort these steps.</p></li>
+
+   <li><p>Let <var title="">error</var> be a new
+   <code>NavigatorUserMediaError</code> object whose <code
+   title="dom-NavigatorUserMediaError-code">code</code> attribute has
+   the numeric value 1 (<code
+   title="dom-NavigatorUserMediaError-PERMISSION_DENIED">PERMISSION_DENIED</code>).</p></li>
+
+   <li><p><span>Queue a task</span> to invoke <var
+   title="">errorCallback</var> with <var title="">error</var> as its
+   argument.</p></li>
+
+  </ol>
+
+  <p>The <span>task source</span> for these <span
+  title="concept-task">tasks</span> is the <span>user interaction task
+  source</span>.</p>
+
+  <hr>
+
+  <p>The <dfn title="dom-NavigatorUserMediaError-code"><code>code</code></dfn>
+  attribute of a <code>NavigatorUserMediaError</code> object must return the code
+  for the error, which must be <!--one of--> the following:</p>
+
+  <dl>
+
+   <dt><dfn title="dom-NavigatorUserMediaError-PERMISSION_DENIED"><code>PERMISSION_DENIED</code></dfn> (numeric value 1)</dt>
+
+   <dd>The user denied the page permission to use the user's media devices.</dd>
+
+  </dl>
+
+  </div>
+
+  <div class="example">
+
+   <p>A voice chat feature in a game could attempt to get access to
+   the user's microphone by calling the API as follows:</p>
+
+   <pre>&lt;script>
+ navigator.getUserMedia('audio', gotAudio);
+ function gotAudio(stream) {
+   // ... use 'stream' ...
+ }
+&lt;/script></pre>
+
+  </div>
+
+  <div class="example">
+
+   <p>A video-conferencing system would ask for both audio and video:</p>
+
+   <pre>&lt;script>
+ function beginCall() {
+   navigator.getUserMedia('audio,video', gotStream);
+ }
+ function gotStream(stream) {
+   // ... use 'stream' ...
+ }
+&lt;/script></pre>
+
+  </div>
+
+
+
+  <h4>Stream API</h4>
+
+  <p>The <code>Stream</code> interface is used to represent streams,
+  typically (but not necessarily) of audio and/or video content, e.g.
+  from a local camera or a remote site.</p>
+
+  <p>The <code>GeneratedStream</code> interface is used when the user
+  agent is generating the stream's data (e.g. from a camera or
+  streaming it from a local video file). It allows authors to pause
+  the generation of the content, e.g. to allow the user to temporarily
+  disable a local camera during a video-conference chat.</p>
+
+  <p>When a <code>GeneratedStream</code> object is being generated
+  from a local file (as opposed to a live audio/video source), the
+  user agent should stream the data from the file in real time, not
+  all at once. This reduces the ease with which pages can distinguish
+  live video from pre-recorded video, which can help protect the
+  user's privacy.</p>
+
+  <!-- v2: support reading the bits from the stream directly, for use
+  with streaming over WebSocket? Or do we rely on FileReader for that? -->
+
+  <pre class="idl">interface <dfn>Stream</dfn> {
+  readonly attribute DOMString <span title="dom-stream-label">label</span>;
+  <span>StreamRecorder</span> <span title="dom-stream-record">record</span>();
+<!--
+  const unsigned short <span title="dom-stream-LOADING">LOADING</span> = 0; -->
+  const unsigned short <span title="dom-stream-LIVE">LIVE</span> = 1;
+  const unsigned short <span title="dom-stream-ENDED">ENDED</span> = 2;
+  readonly attribute unsigned short <span title="dom-stream-readyState">readyState</span>;
+           attribute <span>Function</span> <span title="handler-stream-onreadystatechange">onreadystatechange</span>;
+           attribute <span>Function</span> <span title="handler-stream-onended">onended</span>;
+};
+<span>Stream</span> implements <span>EventTarget</span>;
+
+interface <dfn>GeneratedStream</dfn> {
+  void <span title="dom-stream-stop">stop</span>();
+
+  // temporarily pausing the stream
+  const unsigned short <span title="dom-stream-PAUSED">PAUSED</span> = 3;
+  void <span title="dom-stream-pause">pause</span>();
+  void <span title="dom-stream-resume">resume</span>();
+           attribute <span>Function</span> <span title="handler-stream-onpause">onpause</span>;
+           attribute <span>Function</span> <span title="handler-stream-onplay">onplay</span>;
+};</pre>
+
+  <dl class="domintro">
+
+   <dt><var title="">stream</var> . <code title="dom-stream-label">label</code></dt>
+
+   <dd>
+
+    <p>Returns a label that is unique to this stream, so that streams
+    can be recognised after they are sent through the
+    <code>PeerConnection</code> API.</p>
+
+   </dd>
+
+
+   <dt><var title="">recorder</var> = <var title="">stream</var> . <code title="dom-stream-record">record</code>()</dt>
+
+   <dd>
+
+    <p>Begins recording the stream. The returned
+    <code>StreamRecorder</code> object provides access to the recorded
+    data.</p>
+
+   </dd>
+
+
+   <dt><var title="">stream</var> . <code title="dom-stream-stop">stop</code>()</dt>
+
+   <dd>
+
+    <p>Permanently stops the generation of media data for the stream.</p>
+
+   </dd>
+
+
+   <dt><var title="">stream</var> . <code title="dom-stream-paused">paused</code></dt>
+
+   <dd>
+
+    <p>Returns false if the stream is generating data; true if it is pause.</p>
+
+   </dd>
+
+
+   <dt><var title="">stream</var> . <code title="dom-stream-pause">pause</code>()</dt>
+
+   <dd>
+
+    <p>Temporarily stops the generation of media data for the stream.</p>
+
+   </dd>
+
+
+   <dt><var title="">stream</var> . <code title="dom-stream-resume">resume</code>()</dt>
+
+   <dd>
+
+    <p>Resumes the generation of media data for the stream if it was temporarily stopped.</p>
+
+   </dd>
+
+  </dl>
+
+  <div class="impl">
+
+  <p>The <dfn
+  title="dom-stream-readyState"><code>readyState</code></dfn>
+  attribute represents the state of the stream. It must return the
+  value to which the user agent last set it (as defined below). It can
+  have the following values:</p>
+
+  <dl>
+
+   <dt><dfn title="dom-stream-LIVE"><code>LIVE</code></dfn> (numeric value 1)</dt>
+
+   <dd>The stream is active (the user agent is making a best-effort
+   attempt to receive or generate data in real time).</dd>
+
+   <dt><dfn title="dom-stream-ENDED"><code>ENDED</code></dfn> (numeric value 2)</dt>
+
+   <dd>The stream has finished (the user agent is no longer receiving
+   or generating data, and will never receive or generate more data
+   for this stream).</dd>
+
+   <dt><dfn title="dom-stream-PAUSED"><code>PAUSED</code></dfn> (numeric value 3)</dt>
+
+   <dd>The stream is not generating data at this time, but could still
+   be resumed. Only <code>GeneratedStream</code> objects can be in
+   this state.</dd>
+
+  </dl>
+
+  <p>When a <code>Stream</code> object is created, its <code
+  title="dom-stream-readyState">readyState</code> attribute must be
+  set to <code title="dom-stream-LIVE">LIVE</code> (1).</p>
+
+  <p>When a <code>Stream</code> object ends for any reason other than
+  the <code title="dom-stream-stop">stop()</code> method being invoke
+  (e.g. because the user rescinds the permission for the page to use
+  the local camera, or because the data comes from a finite file and
+  the file's end has been reached and the user has not requested that
+  it be looped, or because the stream comes from a remote peer and the
+  remote peer has permanently stopped sending data), the user agent
+  must <span>queue a task</span> that runs the following steps:</p>
+
+  <ol>
+
+   <li><p>If the object's <code
+   title="dom-stream-readyState">readyState</code> attribute has the
+   value <code title="dom-stream-ENDED">ENDED</code> (2) already, then
+   abort these steps. (The <code title="dom-stream-stop">stop()</code>
+   method was probably called just before the stream stopped for other
+   reasons, e.g. the user clicked an in-page stop button and then the
+   user-agent-provided stop button.)</p></li>
+
+   <li><p>Set the object's <code
+   title="dom-stream-readyState">readyState</code> attribute to <code
+   title="dom-stream-ENDED">ENDED</code> (2).</p></li>
+
+   <li><p><span>Fire a simple event</span> named <code
+   title="event-readystatechange">readystatechange</code> at the
+   object.</p></li>
+
+   <li><p><span>Fire a simple event</span> named <code
+   title="event-stream-ended">ended</code> at the object.</p></li>
+
+  </ol>
+
+  <p>If the end of the stream was reached due to a user request, the
+  <span>task source</span> for this <span
+  title="concept-task">task</span> is the <span>user interaction task
+  source</span>. Otherwise the <span>task source</span> for this <span
+  title="concept-task">task</span> is the <span>networking task
+  source</span>.</p>
+
+  <hr>
+
+  <p>When a <code>GeneratedStream</code> object is created, the user
+  agent must generate a globally unique identifier string, and must
+  initialize the object's <code title="dom-stream-label">label</code>
+  attribute to that string. Such strings must only use characters in
+  the ranges U+0021, U+0023 to U+0027, U+002A to U+002B, U+002D to
+  U+002E, U+0030 to U+0039, U+0041 to U+005A, U+005E to U+007E, and
+  must be 36 characters long.</p> <!-- UUIDs have 36 characters
+  including hyphens; the ranges above comes from RFC4574 (the a=label:
+  thing in SDP) -->
+
+  <p>When a <code>Stream</code> is created to represent a stream
+  obtained from a remote peer, the <code
+  title="dom-stream-label">label</code> attribute is initialized from
+  information provided by the remote source.</p> <!-- described below
+  -->
+
+  <p>The <dfn title="dom-stream-label"><code>label</code></dfn>
+  attribute must return the value to which it was initialized when the
+  object was created.</p>
+
+  <hr>
+
+  <p>When the <dfn
+  title="dom-stream-record"><code>record()</code></dfn> method is
+  invoked, the user agent must return a new
+  <code>StreamRecorder</code> object associated with the stream.</p>
+
+  <hr>
+
+  <p>When a <code>GeneratedStream</code> object's <dfn
+  title="dom-stream-stop"><code>stop()</code></dfn> method is invoked,
+  the user agent must <span>queue a task</span> that runs the
+  following steps:</p>
+
+  <ol>
+
+   <li><p>If the object's <code
+   title="dom-stream-readyState">readyState</code> attribute is in the
+   <code title="dom-stream-ENDED">ENDED</code> (2) state, then abort
+   these steps.</p></li>
+
+   <li><p>Permanently stop the generation of data for the stream. If
+   the data is being generated from a live source (e.g. a microphone
+   or camera), and no other stream is being generated from a live
+   source, then the user agent should remove any active "on-air"
+   indicator. If the data is being generated from a prerecorded source
+   (e.g. a video file), any remaining content in the file is
+   ignored.</p></li>
+
+   <li><p>Set the object's <code
+   title="dom-stream-readyState">readyState</code> attribute to <code
+   title="dom-stream-ENDED">ENDED</code> (2).</p></li>
+
+   <li><p><span>Fire a simple event</span> named <code
+   title="event-readystatechange">readystatechange</code> at the
+   object.</p></li>
+
+   <li><p><span>Fire a simple event</span> named <code
+   title="event-stream-ended">ended</code> at the object.</p></li>
+
+  </ol>
+
+  <hr>
+
+  <p>When a <code>GeneratedStream</code> object's <dfn
+  title="dom-stream-pause"><code>pause()</code></dfn> method is
+  invoked, the user agent must <span>queue a task</span> that runs the
+  following steps:</p>
+
+  <ol>
+
+   <li><p>If the object's <code
+   title="dom-stream-readyState">readyState</code> attribute is not in
+   the <code title="dom-stream-LIVE">LIVE</code> (1) state, then abort
+   these steps.</p></li>
+
+   <li><p>Pause the generation of data for the stream. If the data is
+   being generated from a live source (e.g. a microphone or camera),
+   then data collected for this stream while the stream is paused must
+   be discarded. If the data is being generated from a prerecorded
+   source (e.g. a video file), the user agent should follow user
+   preferences for handling a pause (either skipping over data in real
+   time or resuming from the same point when the stream is later
+   resumed).</p></li>
+
+   <li><p>Set the object's <code
+   title="dom-stream-readyState">readyState</code> attribute to <code
+   title="dom-stream-PAUSED">PAUSED</code> (3).</p></li>
+
+   <li><p><span>Fire a simple event</span> named <code
+   title="event-readystatechange">readystatechange</code> at the
+   object.</p></li>
+
+   <li><p><span>Fire a simple event</span> named <code
+   title="event-stream-pause">pause</code> at the object.</p></li>
+
+  </ol>
+
+  <p>When a <code>GeneratedStream</code> object's <dfn
+  title="dom-stream-resume"><code>resume()</code></dfn> method is
+  invoked, the user agent must <span>queue a task</span> that runs the
+  following steps:</p>
+
+  <ol>
+
+   <li><p>If the object's <code
+   title="dom-stream-readyState">readyState</code> attribute is not in
+   the <code title="dom-stream-PAUSED">PAUSED</code> (3) state, then
+   abort these steps.</p></li>
+
+   <li><p>Resume the generation of data for the stream.</p></li>
+
+   <li><p>Set the object's <code
+   title="dom-stream-readyState">readyState</code> attribute to <code
+   title="dom-stream-LIVE">LIVE</code> (1).</p></li>
+
+   <li><p><span>Fire a simple event</span> named <code
+   title="event-readystatechange">readystatechange</code> at the
+   object.</p></li>
+
+   <li><p><span>Fire a simple event</span> named <code
+   title="event-stream-play">play</code> at the object.</p></li>
+
+  </ol>
+
+  <hr>
+
+  <p>The <span>task source</span> for the <span
+  title="concept-task">tasks</span> queued for the <code
+  title="dom-stream-stop">stop()</code>, <code
+  title="dom-stream-pause">pause()</code>, and <code
+  title="dom-stream-resume">resume()</code> methods is the <span>DOM
+  manipulation task source</span>.</p>
+
+  <hr>
+
+  <p>The following are the <span>event handlers</span> (and their
+  corresponding <span title="event handler event type">event handler
+  event types</span>) that must be supported, as IDL attributes, by
+  all objects implementing the <code>Stream</code> interface:</p>
+
+  <table>
+   <thead>
+    <tr><th><span title="event handlers">Event handler</span> <th><span>Event handler event type</span>
+   <tbody>
+    <tr><td><dfn title="handler-stream-onreadystatechange"><code>onreadystatechange</code></dfn> <td> <code title="event-stream-readystatechange">readystatechange</code>
+    <tr><td><dfn title="handler-stream-onended"><code>onended</code></dfn> <td> <code title="event-stream-ended">ended</code>
+  </table>
+
+  <p>The following are the additional <span>event handlers</span> (and
+  their corresponding <span title="event handler event type">event
+  handler event types</span>) that must be supported, as IDL
+  attributes, by all objects implementing the
+  <code>GeneratedStream</code> interface:</p>
+
+  <table>
+   <thead>
+    <tr><th><span title="event handlers">Event handler</span> <th><span>Event handler event type</span>
+   <tbody>
+    <tr><td><dfn title="handler-stream-onpause"><code>onpause</code></dfn> <td> <code title="event-stream-pause">pause</code>
+    <tr><td><dfn title="handler-stream-onplay"><code>onplay</code></dfn> <td> <code title="event-stream-play">play</code>
+  </table>
+
+  </div>
+
+  <div class="example">
+
+   <p>This sample code exposes a button. When clicked, the button is
+   disabled and the user is prompted to offer a stream. The user can
+   cause the button to be re-enabled by providing a stream (e.g.
+   giving the page access to the local camera) and then disabling the
+   stream (e.g. revoking that access).</p>
+
+   <pre>
+&lt;input type="button" value="Start" onclick="start()" id="startBtn">
+&lt;script>
+ var startBtn = document.getElementById('startBtn');
+ function start() {
+   navigator.getUserMedia('audio,video', gotStream);
+   startBtn.disabled = true;
+ }
+ function gotStream(stream) {
+   stream.onended = function () {
+     startBtn.disabled = false;
+   }
+ }
+&lt;/script></pre>
+
+  </div>
+
+  <pre class="idl">interface <dfn>StreamRecorder</dfn> {
+  <span>Blob</span> <span title="dom-StreamRecorder-getRecordedData">getRecordedData</span>(in <span>BlobCallback</span> callback);
+};
+
+[Callback=FunctionOnly, NoInterfaceObject]
+interface <dfn>BlobCallback</dfn> {
+  void <span title="dom-BlobCallback-handleEvent">handleEvent</span>(in <span>Blob</span> blob);
+};</pre>
+
+  <dl class="domintro">
+
+   <dt><var title="">recorder</var> . <code title="dom-StreamRecorder-getRecordedData">getRecordedData</code>(<var title="">callback</var>)</dt>
+
+   <dd>
+
+    <p>Creates a <code>Blob</code> of the recorded data, and invokes
+    the provided callback with that <code>Blob</code>.</p>
+
+   </dd>
+
+  </dl>
+
+  <div class="impl">
+
+  <p>When the <dfn
+  title="dom-StreamRecorder-getRecordedData"><code>getRecordedData()</code></dfn>
+  method is called, the user agent must run the following steps:</p>
+
+  <ol>
+
+   <li><p>Let <var title="">callback</var> be the callback
+   indicated by the method's first argument.</p></li>
+
+   <li><p>If <var title="">callback</var> is null, abort these
+   steps.</p></li> <!-- we could throw an exception instead (that's
+   why the method doesn't return until later: so that we can add an
+   exception here without changing the algorithm) -->
+
+   <li><p>Let <var title="">data</var> be the data that was streamed
+   by the <code>Stream</code> object from which the
+   <code>StreamRecorder</code> was created since the creation of the
+   <code>StreamRecorder</code> object.</li>
+
+   <li><p>Return, and run the remaining steps asynchronously.</p></li>
+
+   <li><p>Generate a file that containing <var title="">data</var> in
+   a format supported by the user agent for use in <code>audio</code>
+   and <code>video</code> elements.</p></li>
+
+   <li><p>Let <var title="">blob</var> be a <code>Blob</code> object
+   representing the contents of the file generated in the previous
+   step. <a href="#refsFILEAPI">[FILEAPI]</a></p>
+
+   <li><p><span>Queue a task</span> to invoke <var
+   title="">callback</var> with <var title="">blob</var> as its
+   argument.</p></li>
+
+  </ol>
+
+  <p class="note">The <code
+  title="dom-StreamRecorder-getRecordedData">getRecordedData()</code>
+  method can be called multiple times on one
+  <code>StreamRecorder</code> object; each time, it will create a new
+  file as if this was the first time the method was being called. In
+  particular, the method does not stop or reset the recording when the
+  method is called.</p>
+
+  </div>
+
+  <div class="example">
+
+   <p>This example allows people to record a short audio message and
+   upload it to the server. This example even shows rudimentary error
+   handling.</p>
+
+   <pre>&lt;input type="button" value="&#x26AB;" onclick="msgRecord()" id="recBtn">
+&lt;input type="button" value="&#x25FC;" onclick="msgStop()" id="stopBtn" disabled>
+&lt;p id="status">To start recording, press the &#x26AB; button.&lt;/p>
+&lt;script>
+ var recBtn = document.getElementById('recBtn');
+ var stopBtn = document.getElementById('stopBtn');
+ function report(s) {
+   document.getElementById('status').textContent = s;
+ }
+ function msgRecord() {
+   report('Attempting to access microphone...');
+   navigator.getUserMedia('audio', gotStream, noStream);
+   recBtn.disabled = true;
+ }
+ var msgStream;
+ function gotStream(stream) {
+   report('Recording... To stop, press to &#x25FC; button.');
+   msgStream = stream;
+   stopBtn.disabled = false;
+   stream.onended = function () {
+     msgStop();     
+   }
+ }
+ function msgStop() {
+   report('Creating file...');
+   stopBtn.disabled = true;
+   stream.onended = null;
+   stream.stop();
+   stream.getRecordedData(msgSave);
+ }
+ function msgSave(blob) {
+   report('Uploading file...');
+   var x = new XMLHttpRequest();
+   x.open('POST', 'uploadMessage');
+   x.send(blob);
+   x.onload = function () {
+     report('Done! To record a new message, press the &#x26AB; button.');
+     recBtn.disabled = false;
+   };
+   x.onerror = function () {
+     report('Failed to upload message. To try recording a message again, press the &#x26AB; button.');
+     recBtn.disabled = false;
+   };
+ }
+ funciton noStream() {
+   report('Could not obtain access to your microphone. To try again, press the &#x26AB; button.');
+   recBtn.disabled = false;
+ }
+&lt;/script></pre>
+
+  </div>
+
+  <pre class="idl">[Supplemental]
+interface <dfn title="dom-URL">URL</dfn> {
+  static DOMString <span title="dom-URL-createObjectURL">createObjectURL</span>(in <span>Stream</span> stream);
+};</pre>
+
+  <dl class="domintro">
+
+   <dt><var title="">window</var> . <code title="dom-URL">URL</code> . <code title="dom-URL-createObjectURL">createObjectURL</code>(<var title="">stream</var>)</dt>
+
+   <dd>
+
+    <p>Mints a <span>Blob URL</span> to refer to the given <code>Stream</code>.</p>
+
+   </dd>
+
+  </dl>
+
+  <div class="impl">
+
+  <p>When the <dfn
+  title="dom-URL-createObjectURL"><code>createObjectURL()</code></dfn>
+  method is called with a <code>Stream</code> argument, the user agent
+  must return a unique <span>Blob URL</span> for the given
+  <code>Stream</code>. <a href="#refsFILEAPI">[FILEAPI]</a></p>
+
+  <p>For audio and video streams, the data exposed on that stream must
+  be in a format supported by the user agent for use in
+  <code>audio</code> and <code>video</code> elements.</p>
+
+  <p class="bookkeeping">A <dfn>Blob URL</dfn> is the same as what the
+  File API specification calls a <span>Blob URI</span>, except that
+  anything in the definition of that feature that refers to
+  <code>File</code> and <code>Blob</code> objects is hereby extended
+  to also apply to <code>Stream</code> and
+  <code>GeneratedStream</code> objects.</p>
+
+  </div>
+
+  <div class="example">
+
+   <p>This example allows people to take photos of themselves from the
+   local video camera.</p>
+
+   <pre>&lt;article>
+ &lt;style scoped>
+  video { transform: scaleX(-1); }
+  p { text-align: center; }
+ &lt;/style>
+ &lt;h1>Snapshot Kiosk&lt;/h1>
+ &lt;section id="splash">
+  &lt;p id="errorMessage">Loading...&lt;/p>
+ &lt;/section>
+ &lt;section id="app" hidden>
+  &lt;p>&lt;video id="monitor">&lt;/video> &lt;canvas id="photo">&lt;/canvas>
+  &lt;p>&lt;input type=button value="&amp;#x1F4F7;" onclick="snapshot()">
+ &lt;/section>
+ &lt;script>
+  navigator.getUserMedia('video', gotStream, noStream);
+  var video = document.getElementById('monitor');
+  var canvas = document.getElementById('photo');
+  function gotStream(stream) {
+    video.src = URL.getObjectURL(stream);
+    video.onerror = function () {
+      stream.stop();
+      noStream();
+    }
+    video.onloadedmetadata = function () {
+      canvas.width = video.videoWidth;
+      canvas.height = video.videoHeight;
+      document.getElementById('splash').hidden = true;
+      document.getElementById('app').hidden = false;
+    }
+  }
+  function noStream() {
+    document.getElementById('errorMessage').textContent = 'No camera available.';
+  }
+  function snapshot() {
+    canvas.getContext('2d').drawImage(video, 0, 0);
+  }
+ &lt;/script>
+&lt;/article></pre>
+
+  </div>
+
+
+
+  <h4>Peer-to-peer connections</h4>
+
+  <pre class="idl">[<span title="dom-PeerConnection">Constructor</span>(in DOMString configuration, in <span>SignalingCallback</span> signalingCallback)]
+interface <dfn>PeerConnection</dfn> {
+  void <span title="dom-PeerConnection-signalingMessage">signalingMessage</span>(in DOMString message);
+
+  // <span class="XXX">readyState, etc</span>
+
+  void <span title="dom-PeerConnection-send">send</span>(in DOMString text);
+  void <span title="dom-PeerConnection-addStream">addStream</span>(in <span>Stream</span> stream);
+  void <span title="dom-PeerConnection-removeStream">removeStream</span>(in <span>Stream</span> stream);
+  readonly attribute <span>Stream</span>[] <span title="dom-PeerConnection-localStreams">localStreams</span>;
+  readonly attribute <span>Stream</span>[] <span title="dom-PeerConnection-remoteStreams">remoteStreams</span>;
+
+  // <span class="XXX">connection quality information</span>
+
+           attribute <span>Function</span> <span title="handler-PeerConnection-ontext">ontext</span>;
+           attribute <span>Function</span> <span title="handler-PeerConnection-onaddstream">onaddstream</span>;
+           attribute <span>Function</span> <span title="handler-PeerConnection-onremovestream">onremovestream</span>;
+};
+<span>PeerConnection</span> implements <span>EventTarget</span>;
+
+[Callback=FunctionOnly, NoInterfaceObject]
+interface <dfn>SignalingCallback</dfn> {
+  void <span title="dom-SignalingCallback-handleEvent">handleEvent</span>(in <span>PeerConnection</span> source, in DOMString message);
+};</pre>
+
+  <p>A <code>PeerConnection</code> allows two users to communicate
+  directly, browser-to-browser. Communications are coordinated via a
+  signaling channel provided by script in the page via the server,
+  e.g. using <code>XMLHttpRequest</code>.</p>
+
+  <dl class="domintro">
+
+   <dt><var title="">connection</var> = new <code title="dom-PeerConnection">PeerConnection</code>(<var title="">configuration</var>, <var title="">signalingCallback</var>)</dt>
+
+   <dd>
+
+    <p>Creates a <code>PeerConnection</code> object.</p>
+
+    <p>The <var title="">configuration</var> string gives the address
+    of a STUN or TURN server to use to establish the connection. <a
+    href="#refsSTUN">[STUN]</a> <a href="#refsTURN">[TURN]</a></p>
+
+    <p>The allowed formats for this string are:</p>
+
+    <dl>
+
+     <dt>"<code title=""><var title="">TYPE</var> 203.0.113.2:3478</code>"
+     <dd>
+      <p>Indicates a specific IP address and port for the server.</p>
+     </dd>
+
+     <dt>"<code title=""><var title="">TYPE</var> relay.example.net:3478</code>"
+     <dd>
+      <p>Indicates a specific host and port for the server; the user agent will look up the IP address in DNS.</p>
+     </dd>
+
+     <dt>"<code title=""><var title="">TYPE</var> example.net</code>"
+     <dd>
+      <p>Indicates a specific domain for the server; the user agent will look up the IP address and port in DNS.</p>
+     </dd>
+
+    </dl>
+
+    <p>The "<code title=""><var title="">TYPE</var></code>" is one of:</p>
+
+    <dl>
+
+     <dt><code title="">STUN</code></dt>
+     <dd>Indicates a STUN server
+
+     <dt><code title="">STUNS</code></dt>
+     <dd>Indicates a STUN server that is to be contacted using a TLS session.
+
+     <dt><code title="">TURN</code></dt>
+     <dd>Indicates a TURN server
+
+     <dt><code title="">TURNS</code></dt>
+     <dd>Indicates a TURN server that is to be contacted using a TLS session.
+
+    </dl>
+
+    <p>The <var title="">signalingCallback</var> argument is a method
+    that will be invoked when the user agent needs to send a message
+    to the other host over the signaling channel. When the callback
+    is invoked, convey its argument (a string) to the other peer using
+    whatever method is being used by the Web application to relay
+    signaling messages. (Messages returned from the other peer are
+    provided back to the user agent using the <code
+    title="dom-PeerConnection-signalingMessage">signalingMessage()</code>
+    method.)</p>
+
+   </dd>
+
+
+   <dt><var title="">connection</var> . <code title="dom-PeerConnection-signalingMessage">signalingMessage</code>(<var title="">message</var>)</dt>
+
+   <dd>
+
+    <p>When a message is relayed from the remote peer over the
+    signaling channel is received by the Web application, pass it to
+    the user agent by calling the <code
+    title="dom-PeerConnection-signalingMessage">signalingMessage()</code>
+    method.</p>
+
+    <p>The order of messages is important. Passing messages to the
+    user agent in a different order than they were generated by the
+    remote peer's user agent can prevent a successful connection from
+    being established or degrade the connection's quality if one is
+    established.</p>
+
+   </dd>
+
+   <dt><var title="">connection</var> . <code title="dom-PeerConnection-send">send</code>(<var title="">text</var>)</dt>
+
+   <dd>
+
+    <p>Attempts to send the given text to the remote peer. This uses
+    UDP, which is inherently unreliable; there is no guarantee that
+    every message will be received.</p>
+
+    <p>When a message sent in this manner from the other peer is
+    received, a <code title="event-PeerConnection-text">text</code>
+    event is dispatched at the <code>PeerConnection</code> object.</p>
+
+   </dd>
+
+   <dt><var title="">connection</var> . <code title="dom-PeerConnection-addStream">addStream</code>(<var title="">stream</var>)</dt>
+
+   <dd>
+
+    <p>Attempts to starting sending the given stream to the remote
+    peer.</p>
+
+    <p>When the other peer starts sending a stream in this manner, an
+    <code title="event-PeerConnection-addstream">addstream</code>
+    event is dispatched at the <code>PeerConnection</code> object.</p>
+
+   </dd>
+
+   <dt><var title="">connection</var> . <code title="dom-PeerConnection-removeStream">removeStream</code>(<var title="">stream</var>)</dt>
+
+   <dd>
+
+    <p>Steps sending the given stream to the remote peer.</p>
+
+    <p>When the other peer stops sending a stream in this manner, a
+    <code
+    title="event-PeerConnection-removestream">removestream</code>
+    event is dispatched at the <code>PeerConnection</code> object.</p>
+
+   </dd>
+
+   <dt><var title="">connection</var> . <code title="dom-PeerConnection-localStreams">localStreams</code></dt>
+
+   <dd>
+
+    <p>Returns a live array containing the streams that the user agent
+    is currently attempting to transmit to the remote peer (those that
+    were added with <code
+    title="dom-PeerConnection-addStream">addStream()</code>).</p>
+
+   </dd>
+
+   <dt><var title="">connection</var> . <code title="dom-PeerConnection-remoteStreams">remoteStreams</code></dt>
+
+   <dd>
+
+    <p>Returns a live array containing the streams that the user agent
+    is currently receiving from the remote peer.</p>
+
+    <p>This array is updated when <code
+    title="event-PeerConnection-addstream">addstream</code> and <code
+    title="event-PeerConnection-removestream">removestream</code>
+    events are fired.</p>
+
+   </dd>
+
+  </dl>
+
+  <div class="impl">
+
+  <p>A <code>PeerConnection</code> object has an associated
+  <dfn><code>PeerConnection</code> signaling callback</dfn>, a
+  <dfn><code>PeerConnection</code> ICE Agent</dfn>, a
+  <dfn><code>PeerConnection</code> data UDP media stream</dfn> and an
+  <dfn>ICE started flag</dfn>. These are initialized when the object
+  is created.</p>
+
+  <p>When the <dfn
+  title="dom-PeerConnection"><code>PeerConnection()</code></dfn>
+  constructor is invoked, the user agent must run the following steps.
+  This algorithm has a <span>synchronous section</span> (which is
+  triggered as part of the <span>event loop</span> algorithm). Steps
+  in the <span>synchronous section</span> are marked with
+  &#x231B;.</p>
+
+  <ol>
+
+   <li><p>Let <var title="">serverConfiguration</var> be the constructor's
+   first argument.</p></li>
+
+   <li><p>Let <var title="">signalingCallback</var> be the
+   constructor's second argument.</p></li>
+
+   <li><p>If <var title="">signalingCallback</var> is null, throw a
+   <code>TypeError</code> exception and abort these steps.</p></li>
+
+   <li><p>Let <var title="">connection</var> be a newly created
+   <code>PeerConnection</code> object.</p></li>
+
+   <li><p>Create an ICE Agent and let <var title="">connection</var>'s
+   <span><code>PeerConnection</code> ICE Agent</span> be that ICE
+   Agent. <a href="#refsICE">[ICE]</a></p></li>
+
+   <li><p>If <var title="">serverConfiguration</var> contains a U+000A LINE
+   FEED (LF) character or a U+000D CARRIAGE RETURN (CR) character (or
+   both), remove all characters from <var title="">serverConfiguration</var>
+   after the first such character.</p></li>
+
+   <li><p><span title="split a string on spaces">Split <var
+   title="">serverConfiguration</var> on spaces</span> to obtain <var
+   title="">configuration components</var>.</p></li>
+
+   <li>
+
+    <p>If <var title="">configuration components</var> has two or more
+    components, and the first component is a
+    <span>case-sensitive</span> match for one of the following
+    strings:</p>
+
+    <ul class="brief">
+     <li>"<code title="">STUN</code>"
+     <li>"<code title="">STUNS</code>"
+     <li>"<code title="">TURN</code>"
+     <li>"<code title="">TURNS</code>"
+    </ul>
+
+    <p>...then run the following substeps:</p>
+
+    <ol>
+
+     <li><p>Let <var title="">server type</var> be STUN if the first
+     component of <var title="">configuration components</var> is
+     "<code title="">STUN</code>" or "<code title="">STUNS</code>",
+     and TURN otherwise (the first component of <var
+     title="">configuration components</var> is "<code
+     title="">TURN</code>" or "<code title="">TURNS</code>").</p>
+
+     <li><p>Let <var title="">secure</var> be true if the first
+     component of <var title="">configuration components</var> is
+     "<code title="">STUNS</code>" or "<code title="">TURNS</code>",
+     and false otherwise.</p>
+
+     <li><p>Let <var title="">host</var> be the contents of the second
+     component of <var title="">configuration components</var> up to
+     the character before the first U+003A COLON character (:), if
+     any, or the entire string otherwise.</p></li>
+
+     <li><p>Let <var title="">port</var> be the contents of the second
+     component of <var title="">configuration components</var> from
+     the character after the first U+003A COLON character (:) up to
+     the end, if any, or the empty string otherwise.</p></li>
+
+     <li>
+
+      <p>Configure the <span><code>PeerConnection</code> ICE
+      Agent</span>'s STUN or TURN server as follows:</p>
+
+      <ul>
+
+       <li>If <var title="">server type</var> is STUN, the server is a
+       STUN server. Otherwise, <var title="">server type</var> is TURN
+       and the server is a TURN server.</li>
+
+       <li>If <var title="">secure</var> is true, the server is to be
+       contacted using TLS-over-TCP, otherwise, it is to be contacted
+       using UDP.</li>
+
+       <li>The IP address, host name, or domain name of the server is
+       <var title="">host</var>.</li>
+
+       <li>The port to use is <var title="">port</var>. If this is the
+       empty string, then only a domain name is configured (and the
+       ICE Agent will use DNS SRV requests to determine the IP address
+       and port).</li>
+
+       <li>The long-term username for the the STUN or TURN server is
+       the <span title="ASCII serialization of an origin">ASCII
+       serialization</span> of the <span>entry script</span>'s
+       <span>origin</span>; the long-term password is the empty
+       string.</li>
+
+      </ul>
+
+      <p>If the given IP address, host name, domain name, or port are
+      invalid, then the user agent must act as if no STUN or TURN
+      server is configured.</p>
+
+     </li>
+
+    </ol>
+
+   </li>
+
+   <li><p>Let the <var title="">connection</var>'s
+   <span><code>PeerConnection</code> signaling callback</span> be
+   <var title="">signalingCallback</var>.</p></li>
+
+   <li><p>Set <var title="">connection</var>'s <span>ICE started
+   flag</span> to false.</p></li>
+
+   <li><p>Let <var title="">connection</var>'s
+   <span><code>PeerConnection</code> data UDP media stream</span> be a
+   new <span>data UDP media stream</span>.</p></li>
+
+   <li><p>Let <var title="">connection</var>'s <code
+   title="dom-PeerConnection-localStreams">localStreams</code>
+   attribute be an empty read-only <code>Stream</code> array. <a
+   href="#refsWEBIDL">[WEBIDL]</a></p></li>
+
+   <li><p>Let <var title="">connection</var>'s <code
+   title="dom-PeerConnection-remoteStreams">remoteStreams</code>
+   attribute be an empty read-only <code>Stream</code> array. <a
+   href="#refsWEBIDL">[WEBIDL]</a></p></li>
+
+   <li><p>Return <var title="">connection</var>, but continue these
+   steps asynchronously.</p></li>
+
+   <li><p><span>Await a stable state</span>. The <span>synchronous
+   section</span> consists of the remaining steps of this
+   algorithm. (Steps in <span title="synchronous section">synchronous
+   sections</span> are marked with &#x231B;.)</p></li>
+
+   <li><p>&#x231B; If <var title="">connection</var>'s <span>ICE
+   started flag</span> is still false, start the
+   <span><code>PeerConnection</code> ICE Agent</span> and send the
+   initial offer. The initial offer must include a media description
+   for the <span><code>PeerConnection</code> data UDP media
+   stream</span> and for all the streams in <code
+   title="dom-PeerConnection-localStreams">localStreams</code>. <a
+   href="#refsICE">[ICE]</a></p></li>
+
+   <li><p>&#x231B; Let <var title="">connection</var>'s <span>ICE
+   started flag</span> be true.</p></li>
+
+  </ol>
+
+  <p>When a <span><code>PeerConnection</code> ICE Agent</span> is
+  required to send SDP offers or answers, the user agent must follow
+  these steps:</p>
+
+  <ol>
+
+   <li><p>Let <var title="">sdp</var> be the SDP offer or answer to be
+   sent. <a href="#refsSDPOFFERANSWER">[SDPOFFERANSWER]</a></p></li>
+
+   <li><p>Let <var title="">message</var> be the concatenation of the
+   string "<code title="">SDP</code>", a U+000A LINE FEED (LF)
+   character, and <var title="">sdp</var>, in that order.</p></li>
+
+   <li><p><span>Queue a task</span> to invoke that
+   <span><code>PeerConnection</code> ICE Agent</span>'s
+   <span><code>PeerConnection</code> signaling callback</span> with
+   <var title="">message</var> as its argument.</p></li>
+
+  </ol>
+
+  <p>All SDP media descriptions for streams represented by
+  <code>Stream</code> objects must include a label attribute ("<code
+  title="">a=label:</code>") whose value is the value of the
+  <code>Stream</code> object's <code
+  title="dom-stream-label">label</code> attribute. <a
+  href="#refsSDP">[SDP]</a> <a href="#refsSDPLABEL">[SDPLABEL]</a></p>
+
+  <p><span title="PeerConnection ICE
+  Agent"><code>PeerConnection</code> ICE Agents</span> must not
+  generate any candidates for media streams whose media descriptions
+  do not have a label attribute ("<code title="">a=label:</code>"). <a
+  href="#refsICE">[ICE]</a> <a href="#refsSDP">[SDP]</a> <a
+  href="#refsSDPLABEL">[SDPLABEL]</a></p>
+
+  <p>When a user agent starts receiving media for a component an a
+  candidate provided for that component by a
+  <span><code>PeerConnection</code> ICE Agent</span>, the user agent
+  must follow these steps:</p>
+
+  <ol>
+
+   <li><p>Let <var title="">connection</var> be the
+   <code>PeerConnection</code> whose ICE Agent is expecting this
+   media.</p></li>
+
+   <li><p>If there is already a <code>Stream</code> object for the
+   media stream to which this component belongs, then associate the
+   component with that media stream and abort these steps. (Some media
+   streams have multiple components; this API does not expose the
+   role of these individual components in ICE.)</p></li>
+
+   <li><p>Create a <code>Stream</code> object to represent the media
+   stream. Set its <code title="attr-stream-label">label</code>
+   attribute to the value of the SDP Label attribute for that
+   component's media stream.</p></li>
+
+   <li><p><span>Queue a task</span> to add the newly created
+   <code>Stream</code> object to the end of <var
+   title="">connection</var>'s <code
+   title="dom-PeerConnection-remoteStreams">remoteStreams</code>
+   array, then <span>fire a stream event</span> named <code
+   title="event-stream-addstream">addstream</code> with the newly
+   created <code>Stream</code> object at the <var
+   title="">connection</var> object.</p></li>
+
+  </ol>
+
+  <p>When a <span><code>PeerConnection</code> ICE Agent</span> finds
+  that a stream from the remote peer has been removed (its port has
+  been set to zero in a media description sent on the signaling
+  channel), the user agent must follow these steps:</p>
+
+  <ol>
+
+   <li><p>Let <var title="">connection</var> be the
+   <code>PeerConnection</code> whose <span><code>PeerConnection</code>
+   ICE Agent</span> has determined that a stream is being removed.</p></li>
+
+   <li><p>Let <var title="">stream</var> be the <code>Stream</code>
+   object that represents the media stream being removed, if any. If
+   there isn't one, then abort these steps.</p></li>
+
+   <li><p><span>Queue a task</span> to remove <var
+   title="">stream</var> from <var title="">connection</var>'s <code
+   title="dom-PeerConnection-remoteStreams">remoteStreams</code>
+   array, then <span>fire a stream event</span> named <code
+   title="event-stream-removestream">removestream</code> with <var
+   title="">stream</var> at the <var title="">connection</var>
+   object.</p></li>
+
+  </ol>
+
+  <p>When the <dfn title="dom-PeerConnection-signalingMessage"><code
+  title="">signalingMessage()</code></dfn> method is invoked, the
+  user agent must run the following steps:</p>
+
+  <ol>
+
+   <li><p>Let <var title="">message</var> be the method's
+   argument.</p></li>
+
+   <li>
+
+    <p>If the first four characters of <var title="">message</var> are
+    not "<code title="">SDP</code>" followed by a U+000A LINE FEED
+    (LF) character, then abort these steps. (This indicates an error
+    in the signaling channel implementation. User agents may report
+    such errors to their developer consoles to aid debugging.)</p>
+
+    <p class="note">Future extensions to the
+    <code>PeerConnection</code> interface might use other prefix
+    values to implement additional features.</p>
+
+   </li>
+
+   <li><p>Let <var title="">sdp</var> be the string consisting of all
+   but the first four characters of <var
+   title="">message</var>.</p></li>
+
+   <li>
+
+    <p>If <var title="">connection</var>'s <span>ICE started
+    flag</span> is still false, start the
+    <span><code>PeerConnection</code> ICE Agent</span> and pass it
+    <var title="">sdp</var> as the initial offer from the other peer;
+    the ICE Agent will then (asynchronously) construct the initial
+    answer and transmit it as described above. The initial answer must
+    include a media description for the
+    <span><code>PeerConnection</code> data UDP media stream</span> and
+    for all the streams in <code
+    title="dom-PeerConnection-localStreams">localStreams</code>. <a
+    href="#refsICE">[ICE]</a></p>
+
+    <p>If <var title="">connection</var>'s <span>ICE started
+    flag</span> is true, then pass <var title="">sdp</var> to the
+    <span><code>PeerConnection</code> ICE Agent</span> as a subsequent
+    offer or answer, to be interpreted as appropriate given the
+    current state of the ICE Agent. <a href="#refsICE">[ICE]</a></p>
+
+   </li>
+
+   <li><p>Let <var title="">connection</var>'s <span>ICE started
+   flag</span> be true.</p></li>
+
+  </ol>
+
+  <p>When the <dfn title="dom-PeerConnection-send"><code
+  title="">send()</code></dfn> method is invoked, the
+  user agent must run the following steps:</p>
+
+  <ol>
+
+   <li><p>Let <var title="">message</var> be the method's first
+   argument.</p></li>
+
+   <li><p>Let <var title="">data</var> be <var title="">message</var>
+   encoded as UTF-8. <a href="#refsRFC3629">[RFC3629]</a></p></li>
+
+   <li><p>If <var title="">data</var> is longer than 65470 bytes,
+   throw an <code>INVALID_ACCESS_ERR</code> exception and abort these
+   steps.</p></li>
+   <!-- 65470 = 65535 (64K, max IP size) - 40 (IP header) - 8 (UDP header) - 16 (nonce) - 1 (payload type byte) -->
+
+   <li><p>If the <code>PeerConnection</code>'s
+   <span><code>PeerConnection</code> data UDP media stream</span> is
+   not an <span>active data UDP media stream</span>, abort these
+   steps. No message is sent.</p></li>
+
+   <li><p><span>Transmit a data packet to a peer</span> using the
+   <code>PeerConnection</code>'s <span><code>PeerConnection</code>
+   data UDP media stream</span> with <var title="">data</var> as the
+   message.</p></li>
+
+  </ol>
+
+  <p>When the <dfn title="dom-PeerConnection-addStream"><code
+  title="">addStream()</code></dfn> method is invoked, the user agent
+  must run the following steps:</p>
+
+  <ol>
+
+   <li><p>Let <var title="">stream</var> be the method's
+   argument.</p></li>
+
+   <li><p>If <var title="">stream</var> is null, throw a
+   <code>TypeError</code> exception and abort these steps.</p></li>
+
+   <li><p>If <var title="">stream</var> is already in the
+   <code>PeerConnection</code> object's <code
+   title="dom-PeerConnection-localStreams">localStreams</code> object,
+   then abort these steps.</p></li>
+
+   <li><p>Add <var title="">stream</var> to the end of the
+   <code>PeerConnection</code> object's <code
+   title="dom-PeerConnection-localStreams">localStreams</code>
+   object.</p></li>
+
+   <li><p>If the <code>PeerConnection</code>'s <span>ICE
+   started flag</span> is false, then abort these steps.</p></li>
+
+   <li><p>Have the <code>PeerConnection</code>'s
+   <span><code>PeerConnection</code> ICE Agent</span> add a media
+   stream for <var title="">stream</var>. <a
+   href="#refsICE">[ICE]</a></p></li> <!-- section 9.1.1.3 -->
+
+  </ol>
+  
+  <p>When the <dfn title="dom-PeerConnection-removeStream"><code
+  title="">removeStream()</code></dfn> method is invoked, the user agent
+  must run the following steps:</p>
+
+  <ol>
+
+   <li><p>Let <var title="">stream</var> be the method's
+   argument.</p></li>
+
+   <li><p>If <var title="">stream</var> is null, throw a
+   <code>TypeError</code> exception and abort these steps.</p></li>
+
+   <li><p>If <var title="">stream</var> is not in the
+   <code>PeerConnection</code> object's <code
+   title="dom-PeerConnection-localStreams">localStreams</code> object,
+   then abort these steps.</p></li>
+
+   <li><p>Remove <var title="">stream</var> from the
+   <code>PeerConnection</code> object's <code
+   title="dom-PeerConnection-localStreams">localStreams</code>
+   object.</p></li>
+
+   <li><p>If the <code>PeerConnection</code>'s <span>ICE
+   started flag</span> is false, then abort these steps.</p></li>
+
+   <li><p>Have the <code>PeerConnection</code>'s
+   <span><code>PeerConnection</code> ICE Agent</span> remove the media
+   stream for <var title="">stream</var>. <a
+   href="#refsICE">[ICE]</a></p></li> <!-- section 9.1.1.2 -->
+
+  </ol>
+
+  <p>The <dfn
+  title="dom-PeerConnection-localStreams"><code>localStreams</code></dfn>
+  and <dfn
+  title="dom-PeerConnection-remoteStreams"><code>remoteStreams</code></dfn>
+  attributes must return the read-only <code>Stream</code> arrays that
+  the attributes were respectively set to when the
+  <code>PeerConnection</code>'s constructor ran.</p>
+
+  <hr>
+
+  <p>The following are the <span>event handlers</span> (and their
+  corresponding <span title="event handler event type">event handler
+  event types</span>) that must be supported, as IDL attributes, by
+  all objects implementing the <code>PeerConnection</code>
+  interface:</p>
+
+  <table>
+   <thead>
+    <tr><th><span title="event handlers">Event handler</span> <th><span>Event handler event type</span>
+   <tbody>
+    <tr><td><dfn title="handler-PeerConnection-ontext"><code>ontext</code></dfn> <td> <code title="event-stream-text">text</code>
+    <tr><td><dfn title="handler-PeerConnection-onaddstream"><code>onaddstream</code></dfn> <td> <code title="event-stream-addstream">addstream</code>
+    <tr><td><dfn title="handler-PeerConnection-onremovestream"><code>onremovestream</code></dfn> <td> <code title="event-stream-removestream">removestream</code>
+  </table>
+
+  <hr>
+
+  <p>The <span>task source</span> for the <span
+  title="concept-task">tasks</span> listed in this section is the
+  <span>networking task source</span>.</p>
+
+  </div>
+
+  <div class="example">
+
+   <p>When two peers decide they are going to set up a connection to
+   each other, they both go through these steps. The STUN/TURN server
+   configuration describes a server they can use to get things like
+   their public IP address or to set up NAT traversal. They also have
+   to send data for the signaling channel to each other using the same
+   out-of-band mechanism they used to establish that they were going
+   to communicate in the first place.</p>
+
+   <pre>// the first argument describes the STUN/TURN server configuration
+var local = new PeerConnection('TURNS example.net', sendSignalingChannel);
+local.signalingChannel(...); // if we have a message from the other side, pass it along here
+
+// (aLocalStream is some GeneratedStream object)
+local.addStream(aLocalStream); // start sending video
+
+function sendSignalingChannel(message) {
+  ... // send message to the other side via the signaling channel
+}
+
+function receiveSignalingChannel (message) {
+  // call this whenever we get a message on the signaling channel
+  local.signalingChannel(message);
+}
+
+local.onaddstream = function (event) {
+  // (videoElement is some &lt;video> element)
+  videoElement.src = URL.getObjectURL(event.stream);
+};</pre>
+
+  </div>
+
+  <p class="warning">To prevent network sniffing from allowing a
+  fourth party to establish a connection to a peer using the
+  information sent out-of-band to the other peer and thus spoofing the
+  client, the configuration information should always be transmitted
+  using an encrypted connection.</p>
+
+
+
+  <h4>The data stream</h4>
+
+  <p>All <code>PeerConnection</code> connections include a <dfn>data
+  UDP media stream</dfn>, which is used to send data packets
+  peer-to-peer, for instance game control packets. This data channel
+  is unreliable (packets are not guaranteed to be delivered, and are
+  not guaranteed to be delivered in the right order).</p>
+
+  <p>All SDP media descriptions for <span title="data UDP media
+  stream">data UDP media streams</span> must include a label attribute
+  ("<code title="">a=label:</code>") whose value is the string "<code
+  title="">data</code>". <a href="#refsSDP">[SDP]</a> <a
+  href="#refsSDPLABEL">[SDPLABEL]</a></p>
+
+  <p>All SDP media descriptions for <span title="data UDP media
+  stream">data UDP media streams</span> must also include a key field
+  ("<code title="">k=</code>"), with the value being a base64-encoded
+  representation of 16 cryptographically random bytes determined on a
+  per-ICE-Agent basis. <a href="#refsSDP">[SDP]</a></p>
+
+  <p><span title="PeerConnection ICE
+  Agent"><code>PeerConnection</code> ICE Agents</span> must attempt to
+  establish a connection for their <span><code>PeerConnection</code>
+  data UDP media stream</span> during the initial offer/answer
+  exchange, and must maintain that UDP media stream for the ICE
+  Agents' whole lifetime.</p>
+
+  <p>A <span>data UDP media stream</span> is an <dfn>active data UDP
+  media stream</dfn> if the <span><code>PeerConnection</code> ICE
+  Agent</span> has selected a destination for it. A <span>data UDP
+  media stream</span> can change active status many times during the
+  lifetime of its <code>PeerConnection</code> object (e.g. any time
+  the network topology changes and the ICE Agent performs an ICE
+  Restart). <a href="#refsICE">[ICE]</a></p>
+
+  <p>Bytes transmitted on a <span>data UDP media stream</span> are
+  masked so as to prevent cross-protocol attacks (<span>data UDP media
+  stream</span> always appear to contain random noise to other
+  protocols). For the purposes of masking, the <dfn>data UDP media
+  stream salt</dfn> is defined to be the following 16 bytes, described
+  here as hexadecimal numbers: DB 68 B5 FD 17 0E 15 77 56 AF 7A 3A 1A
+  57 75 02</p> <!-- obtained thusly: head -c 16 /dev/urandom |
+  hexdump -C -->
+
+  <p>When the user agent is to <dfn>transmit a data packet to a
+  peer</dfn> using a <span>data UDP media stream</span> and with a
+  byte string payload <var title="">data</var>, the user agent must
+  run the following steps:</p>
+
+  <ol>
+
+   <li><p>Let <var title="">nonce</var> be 16 cryptographically random
+   bytes.</p></li>
+
+   <li><p>Let <var title="">ice-key</var> be the 16 bytes given as the
+   encryption key for the <span>data UDP media stream</span> in its
+   media description, as defined above.</p></li>
+
+   <li><p>Let <var title="">key</var> be the first 16 bytes of the
+   HMAC-SHA1 of the 16 <var title="">nonce</var> bytes concatenated
+   with the 16 <var title="">ice-key</var> bytes concatenated with the
+   16 <span>data UDP media stream salt</span> bytes. <a
+   href="#refsHMAC">[HMAC]</a> <a href="#refsSHA1">[SHA1]</a></p></li>
+
+   <li><p>Let <var title="">message</var> be a 0x01 byte followed by
+   <var title="">data</var>.</p></li>
+
+   <li><p>Let <var title="">masked message</var> be the result of
+   encrypting <var title="">message</var> using AES-128-CTR keyed with
+   <var title="">key</var>. <a
+   href="#refsAES128CTR">[AES128CTR]</a></p></li>
+
+   <li><p>Send the concatenation of <var title="">nonce</var> and <var
+   title="">masked message</var> in a UDP packet to the destination
+   that the relevant <span><code>PeerConnection</code> ICE
+   Agent</span> has selected a destination for the <span>data UDP
+   media stream</span>.</p></li>
+
+  </ol>
+
+  <p>A <dfn>remote data UDP media stream</dfn> is the first UDP media
+  stream whose sender is the remote peer, whose label attribute
+  ("<code title="">a=label:</code>") has the value "<code
+  title="">data</code>", and for which a
+  <span><code>PeerConnection</code> ICE Agent</span> has selected a
+  destination, if that media stream has an encryption key advertised
+  in its media description, and if that encryption key is 16 bytes
+  long. A <span>remote data UDP media stream</span> is associated with
+  the <code>PeerConnection</code> object for which the
+  <span><code>PeerConnection</code> ICE Agent</span> in question is
+  operating.</p>
+
+  <p>When a packet from a <span>remote data UDP media stream</span> is
+  received, the user agent must run the following steps:</p>
+
+  <ol>
+
+   <li><p>Let <var title="">data</var> be the UDP packet's data.</p></li>
+
+   <li><p>If <var title="">data</var> is shorter than 17 bytes, then
+   abort these steps.</p></li>
+
+   <li><p>Let <var title="">nonce</var> be the first 16 bytes of the
+   <var title="">data</var>.</p></li>
+
+   <li><p>Let <var title="">ice-key</var> be the 16 bytes given as the
+   encryption key for the <span>remote data UDP media stream</span> in
+   the media description for this media stream. <a
+   href="#refsSDP">[SDP]</a></p></li>
+
+   <li><p>Let <var title="">key</var> be the first 16 bytes of the
+   HMAC-SHA1 of the 16 <var title="">nonce</var> bytes concatenated
+   with the 16 <var title="">ice-key</var> bytes concatenated with the
+   16 <span>data UDP media stream salt</span> bytes. <a
+   href="#refsHMAC">[HMAC]</a> <a href="#refsSHA1">[SHA1]</a></li>
+
+   <li><p>Let <var title="">unmasked data</var> be the result of
+   decrypting <var title="">message</var> using AES-128-CTR keyed with
+   <var title="">key</var>. <a
+   href="#refsAES128CTR">[AES128CTR]</a></p></li>
+
+   <li><p>If the first byte of <var title="">unmasked data</var> is
+   not 0x01, then abort these steps.</p></li>
+
+   <li><p>Let <var title="">raw message</var> be the string consisting
+   of all but the first character of <var title="">unmasked
+   message</var>.</p></li>
+
+   <li><p>Let <var title="">message</var> be <var title="">raw
+   message</var> <span>decoded as UTF-8, with error
+   handling</span>.</p></li>
+
+   <li><p>Create an event that uses the <code>MessageEvent</code>
+   interface, with the name <code title="event-text">text</code>,
+   which does not bubble, is not cancelable, has no default action,
+   and has a <code title="dom-MessageEvent-data">data</code> attribute
+   whose value is <var title="">message</var>, and <span>queue a
+   task</span> to dispatch the event at the
+   <code>PeerConnection</code> object that the <span>remote data UDP
+   media stream</span> is associated with.</p></li>
+
+  </ol>
+
+
+  <h4>Event definitions</h4>
+
+  <p>The <code title="event-stream-addstream">addstream</code> and
+  <code title="event-stream-removestream">removestream</code> events
+  use the <code>StreamEvent</code> interface:</p>
+
+  <pre class="idl">interface <dfn>StreamEvent</dfn> : <span>Event</span> {
+  readonly attribute <span>Stream</span> <span title="dom-StreamEvent-stream">stream</span>;
+  void <span title="dom-CloseEvent-initCloseEvent">initCloseEvent</span>(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in <span>Stream</span> streamArg);
+};</pre>
+
+  <p>The <dfn
+  title="dom-StreamEvent-initStreamEvent"><code>initStreamEvent()</code></dfn>
+  method must initialize the event in a manner analogous to the
+  similarly-named method in the DOM Events interfaces. <a
+  href="#refsDOMEVENTS">[DOMEVENTS]</a></p>
+
+  <p>The <dfn title="dom-StreamEvent-stream"><code>stream</code></dfn>
+  attribute represents the <code>Stream</code> object associated with
+  the event.</p>
+
+  <p><dfn title="fire a stream event">Firing a stream event named <var
+  title="">e</var></dfn> with a <code>Stream</code> <var
+  title="">stream</var> means that an event with the name <var
+  title="">e</var>, which does not bubble (except where otherwise
+  stated) and is not cancelable (except where otherwise stated), and
+  which uses the <code>StreamEvent</code> interface with the <code
+  title="dom-StreamEvent-stream">stream</code> attribute set to <var
+  title="">stream</var>, must be dispatched at the given target.</p>
+
+
+  <h4>Event Summary</h4>
+
+  <p class="XXX">...will add event summary for streams here...</p>
+
+</div>
+
+<!--END html--><!--END dev-html-->
+
+
+
+
 
-<!--END html--><!--END dev-html--><!--END w3c-html-->
 
   <div data-component="Web Workers (editor: Ian Hickson)">
 
   <h2 id="workers">Web workers</h2>
 
 <!--START whatwg-workers-->
 <!--START workers-->
 
   <h3>Introduction</h3>
 
@@ -81254,21 +82707,21 @@ v2 (well, really v0):
   representing that worker, which is used to communicate with the
   worker. That object's <code
   title="handler-Worker-onmessage">onmessage</code> event handler allows the code to receive messages from the worker.</p>
 
   <p>The worker itself is as follows:</p>
 
   <pre>EXAMPLE workers/primes/worker.js</pre>
 
   <p>The bulk of this code is simply an unoptimized search for a prime
   number. To send a message back to the page, the <code
-  title="dom-DedicatedWorkerGlobalScope-postMessage">postMessage()</code>
+  title="dom-DedicatedWorkerGlobalScope-send">send()</code>
   method is used to post a message when a prime is found.</p>
 
   <p><a href="http://www.whatwg.org/demos/workers/primes/page.html">View this example online</a>.</p>
 
 
 
   <h5>A worker for updating a client-side database</h5>
 
   <!--END dev-html--><p><i>This section is non-normative.</i></p><!--START dev-html-->
 
@@ -99089,21 +100542,21 @@ iframe:not([seamless]) { border: 2px inset; }
   square, or 1em by 1em if the images are scalable. In an audio
   environment, the icon could be a short bleep. The icons are intended
   to indicate to the user that they can be used to get to whatever
   options the UA provides for images, and, where appropriate, are
   expected to provide access to the context menu that would have come
   up if the user interacted with the actual image.</p>
 
   <hr>
 
   <p>All animated images with the same <span>absolute URL</span> and
-  the same image data are expected to be rendered synchronised to the
+  the same image data are expected to be rendered synchronized to the
   same timeline as a group, with the timeline starting at the time of
   the most recent addition to the group.</p>
 
   <p class="note">In other words, the animation loop of an animated
   image is restarted each time another image with the same
   <span>absolute URL</span> and image data begins to animate, e.g.
   after being inserted into the document.</p>
 
   <hr>
 
@@ -106870,20 +108323,23 @@ interface <span>HTMLDocument</span> {
    <dt id="refsABNF">[ABNF]</dt>
    <dd><cite><a href="http://www.ietf.org/rfc/std/std68.txt">Augmented
    BNF for Syntax Specifications: ABNF</a></cite>, D. Crocker,
    P. Overell. IETF.</dd>
 
    <dt id="refsABOUT">[ABOUT]</dt>
    <dd><cite><a
    href="http://tools.ietf.org/html/draft-holsten-about-uri-scheme">The
    'about' URI scheme</a></cite>, J. Holsten, L. Hunt. IETF.</dd>
 
+   <dt id="refsAES128CTR">[AES128CTR]</dt>
+   <dd><cite><a href="http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf">Advanced Encryption Standard (AES)</a></cite>. NIST.</dd>
+
    <dt id="refsARIA">[ARIA]</dt>
    <dd><cite><a href="http://www.w3.org/WAI/PF/aria/">Accessible Rich
    Internet Applications (WAI-ARIA)</a></cite>, J. Craig, M. Cooper, L. Pappas,
    R. Schwerdtfeger, L. Seeman. W3C.</dd>
 
    <dt id="refsARIAIMPL">[ARIAIMPL]</dt>
    <dd><cite><a
    href="http://www.w3.org/WAI/PF/aria-implementation/">WAI-ARIA 1.0
    User Agent Implementation Guide</a></cite>, A. Snow-Weaver,
    M. Cooper. W3C.</dd>
@@ -107103,20 +108559,23 @@ interface <span>HTMLDocument</span> {
 
    <dt id="refsGREGORIAN">[GREGORIAN]</dt>
    <dd>(Non-normative) <cite>Inter Gravissimas</cite>, A. Lilius,
    C. Clavius. Gregory XIII Papal Bulls, February 1582.</dd>
 
    <dt id="refsHATOM">[HATOM]</dt>
    <dd>(Non-normative) <cite><a
    href="http://microformats.org/wiki/hatom">hAtom</a></cite>, D
    Janes. Microformats.</dd>
 
+   <dt id="refsHMAC">[HMAC]</dt>
+   <dd><cite><a href="http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf">The Keyed-Hash Message Authentication Code (HMAC)</a></cite>. NIST.</dd>
+
    <dt id="refsHTML4">[HTML4]</dt>
    <dd>(Non-normative) <cite><a
    href="http://www.w3.org/TR/html4/">HTML 4.01
    Specification</a></cite>, D. Raggett, A. Le Hors, I. Jacobs.  W3C.</dd>
 
    <dt id="refsHTML">[HTML]</dt>
    <dd><cite><a
    href="http://www.whatwg.org/specs/web-apps/current-work/">HTML</a></cite>,
    I. Hickson. WHATWG.</dd>
 
@@ -107151,20 +108610,23 @@ interface <span>HTMLDocument</span> {
    <dt id="refsIANALINKTYPE">[IANALINKTYPE]</dt>
    <dd><cite><a
    href="http://www.iana.org/assignments/link-relations">Link
    Relations</a></cite>. IANA.</dd>
 
    <dt id="refsIANAPERMHEADERS">[IANAPERMHEADERS]</dt>
    <dd><cite><a
    href="http://www.iana.org/assignments/message-headers/perm-headers.html">Permanent
    Message Header Field Names</a></cite>. IANA.</dd>
 
+   <dt id="refsICE">[ICE]</dt>
+   <dd><cite><a href="http://tools.ietf.org/html/rfc5245">Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal for Offer/Answer Protocols</a></cite>, J. Rosenberg. IETF.</dd>
+
    <dt id="refsIEEE754">[IEEE754]</dt>
    <dd><cite><a
    href="http://ieeexplore.ieee.org/servlet/opac?punumber=4610933">IEEE
    Standard for Floating-Point Arithmetic (IEEE 754)</a></cite>. IEEE. ISBN 978-0-7381-5753-5.</dd>
 
    <dt id="refsISO8601">[ISO8601]</dt>
    <dd><cite><a href="http://isotc.iso.org/livelink/livelink/4021199/ISO_8601_2004_E.zip?func=doc.Fetch&amp;nodeid=4021199">ISO8601: Data elements and interchange formats &mdash; Information interchange &mdash; Representation of dates and times</a></cite>. ISO.</dd>
 
    <dt id="refsISO885911">[ISO885911]</dt>
    <dd><cite><a
@@ -107456,52 +108918,70 @@ interface <span>HTMLDocument</span> {
    <dd><cite><a href="http://tools.ietf.org/html/rfc5724">URI Scheme
    for Global System for Mobile Communications (GSM) Short Message
    Service (SMS)</a></cite>, E. Wilde, A. Vaha-Sipila. IETF.</dd>
 
    <dt id="refsSCSU">[SCSU]</dt>
    <dd>(Non-normative) <cite><a
    href="http://www.unicode.org/reports/tr6/">UTR #6: A Standard
    Compression Scheme For Unicode</a></cite>, M. Wolf, K. Whistler,
    C. Wicksteed, M. Davis, A. Freytag, M. Scherer. Unicode Consortium.</dd>
 
+   <dt id="refsSDP">[SDP]</dt>
+   <dd><cite><a href="http://tools.ietf.org/html/rfc4566">SDP: Session Description Protocol</a></cite>, M. Handley, V. Jacobson, C. Perkins. IETF.</dd>
+
+   <dt id="refsSDPLABEL">[SDPLABEL]</dt>
+   <dd><cite><a href="http://tools.ietf.org/html/rfc4574">The Session Description Protocol (SDP) Label Attribute</a></cite>, O. Levin, G. Camarillo. IETF.</dd>
+
+   <dt id="refsSDPOFFERANSWER">[SDPOFFERANSWER]</dt>
+   <dd><cite><a href="http://tools.ietf.org/html/rfc3264">An Offer/Answer Model with the Session Description Protocol (SDP)</a></cite>, J. Rosenberg, H. Schulzrinne. IETF.</dd>
+
    <dt id="refsSELECTORS">[SELECTORS]</dt>
    <dd><cite><a
    href="http://www.w3.org/TR/css3-selectors">Selectors</a></cite>,
    T. &Ccedil;elik, E. Etemad, D.  Glazman, I. Hickson, P. Linss,
    J. Williams. W3C.</dd>
 
+   <dt id="refsSHA1">[SHA1]</dt>
+   <dd><cite><a href="http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf">Secure Hash Standard</a></cite>. NIST.</dd>
+
    <dt id="refsSHIFTJIS">[SHIFTJIS]</dt>
    <dd><cite>JIS X0208: 7-bit and 8-bit double byte coded KANJI sets
    for information interchange</cite>. Japanese Industrial Standards Committee.</dd>
 
    <dt id="refsSRGB">[SRGB]</dt>
    <dd><cite lang="en-GB"><a
    href="http://webstore.iec.ch/webstore/webstore.nsf/artnum/025408!OpenDocument&amp;Click=">IEC
    61966-2-1: Multimedia systems and equipment &mdash; Colour measurement
    and management &mdash; Part 2-1: Colour management &mdash; Default RGB colour
    space &mdash; sRGB</a></cite>. IEC.</dd>
 
+   <dt id="refsSTUN">[STUN]</dt>
+   <dd><cite><a href="http://tools.ietf.org/html/rfc5389">Session Traversal Utilities for NAT (STUN)</a></cite>, J. Rosenberg, R. Mahy, P. Matthews, D. Wing. IETF.</dd>
+
    <dt id="refsSVG">[SVG]</dt>
    <dd><cite><a href="http://www.w3.org/TR/SVGTiny12/">Scalable Vector
    Graphics (SVG) Tiny 1.2 Specification</a></cite>, O. Andersson,
    R. Berjon, E. Dahlstr&ouml;m, A. Emmons, J. Ferraiolo, A. Grasso,
    V. Hardy, S. Hayman, D. Jackson, C. Lilley, C. McCormack,
    A. Neumann, C. Northway, A. Quint, N. Ramani, D. Schepers,
    A. Shellshear. W3C.</dd>
 
    <dt id="refsTIS620">[TIS620]</dt>
    <dd><cite><a
    href="http://www.nectec.or.th/it-standards/std620/std620.htm">UDC
    681.3.04:003.62</a></cite>. Thai Industrial Standards Institute,
    Ministry of Industry, Royal Thai Government. ISBN
    974-606-153-4.</dd>
 
+   <dt id="refsTURN">[TURN]</dt>
+   <dd><cite><a href="http://tools.ietf.org/html/rfc5766">Traversal Using Relays around NAT (TURN): Relay Extensions to Session Traversal Utilities for NAT (STUN)</a></cite>, R. Mahy, P. Matthews, J. Rosenberg. IETF.</dd>
+
    <dt id="refsUAAG">[UAAG]</dt>
    <dd>(Non-normative) <cite><a
    href="http://www.w3.org/TR/UAAG20/">Web Content Accessibility
    Guidelines (UAAG) 2.0</a></cite>, J. Allan, K. Ford, J. Richards,
    J. Spellman. W3C.</dd>
 
    <dt id="refsUNICODE">[UNICODE]</dt>
    <dd><cite><a href="http://www.unicode.org/versions/">The Unicode Standard</a></cite>. Unicode Consortium.</dd>
 
    <dt id="refsUNIVCHARDET">[UNIVCHARDET]</dt>

|