Messages in server-sent events, Web
  sockets, cross-document messaging, and
  channel messaging use the message event.
  
  
The following interface is defined for this event:
[Constructor(DOMString type, optional MessageEventInit eventInitDict)] interface MessageEvent : Event { readonly attribute any data; readonly attribute DOMString origin; readonly attribute DOMString lastEventId; readonly attribute (WindowProxy or MessagePort)? source; readonly attribute MessagePort[]? ports; }; dictionary MessageEventInit : EventInit { any data; DOMString origin; DOMString lastEventId; WindowProxy? source; MessagePort[]? ports; };
dataReturns the data of the message.
originReturns the origin of the message, for server-sent events and cross-document messaging.
lastEventIdReturns the last event ID string, for server-sent events.
sourceReturns the WindowProxy of the source window, for
    cross-document messaging, and the
    MessagePort being attached, in the connect event fired at
    SharedWorkerGlobalScope objects.
portsReturns the MessagePort array sent with the
    message, for cross-document messaging and
    channel messaging.
The data
  attribute must return the value it was initialized to. When the
  object is created, this attribute must be initialized to null. It
  represents the message being sent.
The origin attribute
  must return the value it was initialized to. When the object is
  created, this attribute must be initialized to the empty string. It
  represents, in server-sent events and
  cross-document messaging, the origin of
  the document that sent the message (typically the scheme, hostname,
  and port of the document, but not its path or fragment
  identifier).
The lastEventId
  attribute must return the value it was initialized to. When the
  object is created, this attribute must be initialized to the empty
  string. It represents, in server-sent events, the last event ID
  string of the event source.
The source attribute
  must return the value it was initialized to. When the object is
  created, this attribute must be initialized to null. It represents,
  in cross-document messaging, the
  WindowProxy of the browsing context of the
  Window object from which the message came; and in the
  connect events used by shared workers, the newly
  connecting MessagePort.
The ports
  attribute must return the value it was initialized to. When the
  object is created, this attribute must be initialized to null.
  It represents, in cross-document messaging and
  channel messaging the MessagePort array
  being sent, if any.
This section is non-normative.
To enable servers to push data to Web pages over HTTP or using
  dedicated server-push protocols, this specification introduces the
  EventSource interface.
Using this API consists of creating an EventSource
  object and registering an event listener.
var source = new EventSource('updates.cgi');
source.onmessage = function (event) {
  alert(event.data);
};
  On the server-side, the script ("updates.cgi" in this case) sends messages in the
  following form, with the text/event-stream MIME
  type:
data: This is the first message. data: This is the second message, it data: has two lines. data: This is the third message.
Authors can separate events by using different event types. Here is a stream that has two event types, "add" and "remove":
event: add data: 73857293 event: remove data: 2153 event: add data: 113411
The script to handle such a stream would look like this (where
  addHandler and removeHandler are functions that take one argument,
  the event):
var source = new EventSource('updates.cgi');
source.addEventListener('add', addHandler, false);
source.addEventListener('remove', removeHandler, false);
  The default event type is "message".
Event streams requests can be redirected using HTTP 301 and 307 redirects as with normal HTTP requests. Clients will reconnect if the connection is closed; a client can be told to stop reconnecting using the HTTP 204 No Content response code.
Using this API rather than emulating it using
  XMLHttpRequest or an iframe allows the
  user agent to make better use of network resources in cases where
  the user agent implementor and the network operator are able to
  coordinate in advance. Amongst other benefits, this can result in
  significant savings in battery life on portable devices. This is
  discussed further in the section below on connectionless push.
EventSource interface[Constructor(DOMString url, optional EventSourceInit eventSourceInitDict)] interface EventSource : EventTarget { readonly attribute DOMString url; readonly attribute boolean withCredentials; // ready state const unsigned short CONNECTING = 0; const unsigned short OPEN = 1; const unsigned short CLOSED = 2; readonly attribute unsigned short readyState; // networking attribute EventHandler onopen; attribute EventHandler onmessage; attribute EventHandler onerror; void close(); }; dictionary EventSourceInit { boolean withCredentials = false; };
The EventSource()
  constructor takes one or two arguments. The first specifies the
  URL to which to connect. The second specifies the
  settings, if any, in the form of an EventSourceInit
  dictionary. When the EventSource() constructor is
  invoked, the UA must run these steps:
Resolve the URL specified in the first argument, relative to the entry script's base URL.
If the previous step failed, then throw a
   SyntaxError exception.
Create a new EventSource object.
Let CORS mode be Anonymous.
If the second argument is present, and the withCredentials
   dictionary member has the value true, then set CORS
   mode to Use
   Credentials and initialize the new EventSource
   object's withCredentials
   attribute to true.
Return the new EventSource object, and continue
   these steps in the background (without blocking scripts).
Do a potentially CORS-enabled fetch of the resulting absolute URL, with the mode being CORS mode, and the origin being the entry script's origin, and process the resource obtained in this fashion, if any, as described below.
The definition of the fetching algorithm (which is used by CORS) is such that if the browser is already fetching the resource identified by the given absolute URL, that connection can be reused, instead of a new connection being established. All messages received up to this point are dispatched immediately, in this case.
This constructor must be visible when the script's global
  object is either a Window object or an object
  implementing the WorkerUtils interface.
The url
  attribute must return the absolute URL that resulted
  from resolving the value that was
  passed to the constructor.
The withCredentials
  attribute must return the value to which it was last initialized.
  When the object is created, it must be initialized to false.
The readyState
  attribute represents the state of the connection. It can have the
  following values:
CONNECTING (numeric value 0)OPEN (numeric value 1)CLOSED (numeric value 2)close() method was
   invoked.When the object is created its readyState must be set to
  CONNECTING (0). The
  rules given below for handling the connection define when the value
  changes.
The close()
  method must abort any instances of the fetch algorithm
  started for this EventSource object, and must set the
  readyState attribute
  to CLOSED.
The following are the event handlers (and their
  corresponding event handler
  event types) that must be supported, as IDL attributes, by
  all objects implementing the EventSource interface:
| Event handler | Event handler event type | 
|---|---|
| onopen | open | 
| onmessage | message | 
| onerror | error | 
In addition to the above, each EventSource object
  has the following associated with it:
These values are not currently exposed on the interface.
The resource indicated in the argument to the EventSource constructor is fetched when the constructor is run.
For HTTP connections, the Accept header may
  be included; if included, it must contain only formats of event
  framing that are supported by the user agent (one of which must be
  text/event-stream, as described below).
If the event source's last event ID
  string is not the empty string, then a Last-Event-ID HTTP header must be
  included with the request, whose value is the value of the event
  source's last event
  ID string, encoded as UTF-8.
User agents should use the Cache-Control: no-cache
  header in requests to bypass any caches for requests of event
  sources. (This header is not a custom request header, so the user agent will still
  use the CORS simple cross-origin request mechanism.)
  User agents should ignore HTTP cache headers in the response, never
  caching event sources.
As data is received, the tasks queued by the networking task source to handle the data must act as follows.
HTTP 200 OK responses with a Content-Type header
  specifying the type text/event-stream, ignoring any
  MIME type parameters, must be processed line by line as described below.
When a successful response with a supported MIME type is received, such that the user agent begins parsing the contents of the stream, the user agent must announce the connection.
The task that the networking task source places on the task queue once the fetching algorithm for such a resource (with the correct MIME type) has completed must cause the user agent to asynchronously reestablish the connection. This applies whether the connection is closed gracefully or unexpectedly. It doesn't apply for the error conditions listed below.
HTTP 200 OK responses that have a Content-Type specifying an unsupported type, or that have no Content-Type at all, must cause the user agent to fail the connection.
HTTP 305 Use Proxy, 401 Unauthorized, and 407 Proxy Authentication Required should be treated transparently as for any other subresource.
HTTP 301 Moved Permanently, 302 Found, 303 See Other, and
  307 Temporary Redirect responses are handled by the fetching and CORS algorithms. In the case of
  301 redirects, the user agent must also remember the new URL so that
  subsequent requests for this resource for this
  EventSource object start with the URL given for the
  last 301 seen for requests for this object.
Any other HTTP response code not listed here, and any network error that prevents the HTTP connection from being established in the first place (e.g. DNS errors), must cause the user agent to fail the connection.
For non-HTTP protocols, UAs should act in equivalent ways.
When a user agent is to announce the connection, the
  user agent must queue a task which, if the readyState attribute is
  set to a value other than CLOSED, sets the readyState attribute to
  OPEN and fires a simple event named open at the EventSource
  object.
When a user agent is to reestablish the connection, the user agent must run the following steps. These steps are run asynchronously, not as part of a task. (The tasks that it queues, of course, are run like normal tasks and not asynchronously.)
Queue a task to run the following steps:
If the readyState attribute is
     set to CLOSED, abort
     the task.
Set the readyState attribute to
     CONNECTING.
Fire a simple event named error at the EventSource
     object.
Wait a delay equal to the reconnection time of the event source.
Wait until the aforementioned task has run, if it has not yet run.
Queue a task to run the following steps:
If the readyState attribute is
     not set to CONNECTING, abort these
     steps.
Perform a potentially CORS-enabled fetch of
     the absolute URL of the event source resource, with
     the mode and
     the origin being the same as those used in the
     original request triggered by the EventSource() constructor, and
     process the resource obtained in this fashion, if any, as
     described earlier in this section.
When a user agent is to fail the connection, the user
  agent must queue a task which, if the readyState attribute is
  set to a value other than CLOSED, sets the readyState attribute to
  CLOSED and fires a simple event named error at the EventSource
  object. Once the user agent has failed the connection, it does not
  attempt to reconnect!
The task source for any tasks that are queued by EventSource objects is the
  remote event task source.
This event stream format's MIME type is
  text/event-stream.
The event stream format is as described by the stream production of the following ABNF, the
  character set for which is Unicode. [ABNF]
stream        = [ bom ] *event
event         = *( comment / field ) end-of-line
comment       = colon *any-char end-of-line
field         = 1*name-char [ colon [ space ] *any-char ] end-of-line
end-of-line   = ( cr lf / cr / lf )
; characters
lf            = %x000A ; U+000A LINE FEED (LF)
cr            = %x000D ; U+000D CARRIAGE RETURN (CR)
space         = %x0020 ; U+0020 SPACE
colon         = %x003A ; U+003A COLON (:)
bom           = %xFEFF ; U+FEFF BYTE ORDER MARK
name-char     = %x0000-0009 / %x000B-000C / %x000E-0039 / %x003B-10FFFF
                ; a Unicode character other than U+000A LINE FEED (LF), U+000D CARRIAGE RETURN (CR), or U+003A COLON (:)
any-char      = %x0000-0009 / %x000B-000C / %x000E-10FFFF
                ; a Unicode character other than U+000A LINE FEED (LF) or U+000D CARRIAGE RETURN (CR)
  Event streams in this format must always be encoded as UTF-8. [RFC3629]
Lines must be separated by either a U+000D CARRIAGE RETURN U+000A LINE FEED (CRLF) character pair, a single U+000A LINE FEED (LF) character, or a single U+000D CARRIAGE RETURN (CR) character.
Since connections established to remote servers for such resources are expected to be long-lived, UAs should ensure that appropriate buffering is used. In particular, while line buffering with lines are defined to end with a single U+000A LINE FEED (LF) character is safe, block buffering or line buffering with different expected line endings can cause delays in event dispatch.
Streams must be decoded as UTF-8, with error handling.
One leading U+FEFF BYTE ORDER MARK character must be ignored if any are present.
The stream must then be parsed by reading everything line by line, with a U+000D CARRIAGE RETURN U+000A LINE FEED (CRLF) character pair, a single U+000A LINE FEED (LF) character not preceded by a U+000D CARRIAGE RETURN (CR) character, and a single U+000D CARRIAGE RETURN (CR) character not followed by a U+000A LINE FEED (LF) character being the ways in which a line can end.
When a stream is parsed, a data buffer, an event type buffer, and a last event ID buffer must be associated with it. They must be initialized to the empty string
Lines must be processed, in the order they are received, as follows:
Dispatch the event, as defined below.
Ignore the line.
Collect the characters on the line before the first U+003A COLON character (:), and let field be that string.
Collect the characters on the line after the first U+003A COLON character (:), and let value be that string. If value starts with a U+0020 SPACE character, remove it from value.
Process the field using the steps described below, using field as the field name and value as the field value.
Process the field using the steps described below, using the whole line as the field name, and the empty string as the field value.
Once the end of the file is reached, any pending data must be discarded. (If the file ends in the middle of an event, before the final empty line, the incomplete event is not dispatched.)
The steps to process the field given a field name and a field value depend on the field name, as given in the following list. Field names must be compared literally, with no case folding performed.
Set the event type buffer to field value.
Append the field value to the data buffer, then append a single U+000A LINE FEED (LF) character to the data buffer.
Set the last event ID buffer to the field value.
If the field value consists of only characters in the range U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9), then interpret the field value as an integer in base ten, and set the event stream's reconnection time to that integer. Otherwise, ignore the field.
The field is ignored.
When the user agent is required to dispatch the event, then the user agent must act as follows:
Set the last event ID string of the event source to value of the last event ID buffer. The buffer does not get reset, so the last event ID string of the event source remains set to this value until the next time it is set by the server.
If the data buffer is an empty string, set the data buffer and the event type buffer to the empty string and abort these steps.
If the data buffer's last character is a U+000A LINE FEED (LF) character, then remove the last character from the data buffer.
Create an event that uses the MessageEvent
   interface, with the event type message, which does not bubble, is not
   cancelable, and has no default action. The data attribute must be
   initialized to the value of the data buffer,
   the origin attribute
   must be initialized to the Unicode serialization of the origin of
   the event stream's final URL (i.e. the URL after redirects), and
   the lastEventId
   attribute must be initialized to the last event ID
   string of the event source.
If the event type buffer has a value other than the empty string, change the type of the newly created event to equal the value of the event type buffer.
Set the data buffer and the event type buffer to the empty string.
Queue a task which, if the readyState attribute is
   set to a value other than CLOSED, dispatches the newly
   created event at the EventSource object.
If an event doesn't have an "id" field, but an
  earlier event did set the event source's last event ID
  string, then the event's lastEventId field will
  be set to the value of whatever the last seen "id" field was.
The following event stream, once followed by a blank line:
data: YHOO data: +2 data: 10
...would cause an event message with the interface
   MessageEvent to be dispatched on the
   EventSource object. The event's data attribute would contain
   the string YHOO\n+2\n10 (where \n
   represents a newline).
This could be used as follows:
var stocks = new EventSource("http://stocks.example.com/ticker.php");
stocks.onmessage = function (event) {
  var data = event.data.split('\n');
  updateStocks(data[0], data[1], data[2]);
};
   ...where updateStocks() is a function defined as:
function updateStocks(symbol, delta, value) { ... }
   ...or some such.
The following stream contains four blocks. The first block has
   just a comment, and will fire nothing. The second block has two
   fields with names "data" and "id" respectively; an event will be
   fired for this block, with the data "first event", and will then
   set the last event ID to "1" so that if the connection died between
   this block and the next, the server would be sent a Last-Event-ID header with the
   value "1". The third block fires an event with data "second event",
   and also has an "id" field, this time with no value, which resets
   the last event ID to the empty string (meaning no Last-Event-ID header will now be
   sent in the event of a reconnection being attempted). Finally, the
   last block just fires an event with the data
   " third event" (with a single leading space character).
   Note that the last still has to end with a blank line, the end of
   the stream is not enough to trigger the dispatch of the last
   event.
: test stream data: first event id: 1 data:second event id data: third event
The following stream fires two events:
data data data data:
The first block fires events with the data set to the empty string, as would the last block if it was followed by a blank line. The middle block fires an event with the data set to a single newline character. The last block is discarded because it is not followed by a blank line.
The following stream fires two identical events:
data:test data: test
This is because the space after the colon is ignored if present.
Legacy proxy servers are known to, in certain cases, drop HTTP connections after a short timeout. To protect against such proxy servers, authors can include a comment line (one starting with a ':' character) every 15 seconds or so.
Authors wishing to relate event source connections to each other or to specific documents previously served might find that relying on IP addresses doesn't work, as individual clients can have multiple IP addresses (due to having multiple proxy servers) and individual IP addresses can have multiple clients (due to sharing a proxy server). It is better to include a unique identifier in the document when it is served and then pass that identifier as part of the URL when the connection is established.
Authors are also cautioned that HTTP chunking can have unexpected negative effects on the reliability of this protocol. Where possible, chunking should be disabled for serving event streams unless the rate of messages is high enough for this not to matter.
Clients that support HTTP's per-server connection limitation
  might run into trouble when opening multiple pages from a site if
  each page has an EventSource to the same
  domain. Authors can avoid this using the relatively complex
  mechanism of using unique domain names per connection, or by
  allowing the user to enable or disable the EventSource
  functionality on a per-page basis, or by sharing a single
  EventSource object using a shared worker.
  
  
User agents running in controlled environments, e.g. browsers on mobile handsets tied to specific carriers, may offload the management of the connection to a proxy on the network. In such a situation, the user agent for the purposes of conformance is considered to include both the handset software and the network proxy.
For example, a browser on a mobile device, after having established a connection, might detect that it is on a supporting network and request that a proxy server on the network take over the management of the connection. The timeline for such a situation might be as follows:
EventSource constructor.EventSource constructor (possibly
    including a Last-Event-ID
    HTTP header, etc).This can reduce the total data usage, and can therefore result in considerable power savings.
As well as implementing the existing API and
  text/event-stream wire format as defined by this
  specification and in more distributed ways as described above,
  formats of event framing defined by other applicable
  specifications may be supported. This specification does not
  define how they are to be parsed or processed.
While an EventSource object's readyState is CONNECTING, and the object
  has one or more event listeners registered for open, message or error events, there must be a strong
  reference from the Window or WorkerUtils
  object that the EventSource object's constructor was
  invoked from to the EventSource object itself.
While an EventSource object's readyState is OPEN, and the object has one or
  more event listeners registered for message or error events, there must be a strong
  reference from the Window or WorkerUtils
  object that the EventSource object's constructor was
  invoked from to the EventSource object itself.
While there is a task queued by an EventSource
  object on the remote event task source, there must be a
  strong reference from the Window or
  WorkerUtils object that the EventSource
  object's constructor was invoked from to that
  EventSource object.
If a user agent is to forcibly close an
  EventSource object (this happens when a
  Document object goes away permanently), the user agent
  must abort any instances of the fetch algorithm started
  for this EventSource object, and must set the readyState attribute to
  CLOSED.
If an EventSource object is garbage collected while
  its connection is still open, the user agent must abort any instance
  of the fetch algorithm opened by this
  EventSource.
It's possible for one active network connection to
  be shared by multiple EventSource objects and their
  fetch algorithms, which is why the above is phrased in
  terms of aborting the fetch algorithm and not the
  actual underlying download.
text/event-streamThis registration is for community review and will be submitted to the IESG for review, approval, and registration with IANA.
charsetThe charset parameter may be provided.
      The parameter's value must be "utf-8".
      This parameter serves no purpose; it is only allowed for
      compatibility with legacy servers.
An event stream from an origin distinct from the origin of the content consuming the event stream can result in information leakage. To avoid this, user agents are required to apply CORS semantics. [CORS]
Event streams can overwhelm a user agent; a user agent is expected to apply suitable restrictions to avoid depleting local resources because of an overabundance of information from an event stream.
Servers can be overwhelmed if a situation develops in which the server is causing clients to reconnect rapidly. Servers should use a 5xx status code to indicate capacity problems, as this will prevent conforming clients from reconnecting automatically.
Fragment identifiers have no meaning with
  text/event-stream resources.
Last-Event-IDThis section describes a header field for registration in the Permanent Message Header Field Registry. [RFC3864]
This section is non-normative.
To enable Web applications to maintain bidirectional
  communications with server-side processes, this specification
  introduces the WebSocket interface.
This interface does not allow for raw access to the underlying network. For example, this interface could not be used to implement an IRC client without proxying messages through a custom server.
WebSocket interface[Constructor(DOMString url, optional (DOMString or DOMString[]) protocols)] interface WebSocket : EventTarget { readonly attribute DOMString url; // ready state const unsigned short CONNECTING = 0; const unsigned short OPEN = 1; const unsigned short CLOSING = 2; const unsigned short CLOSED = 3; readonly attribute unsigned short readyState; readonly attribute unsigned long bufferedAmount; // networking attribute EventHandler onopen; attribute EventHandler onerror; attribute EventHandler onclose; readonly attribute DOMString extensions; readonly attribute DOMString protocol; void close([Clamp] optional unsigned short code, optional DOMString reason); // messaging attribute EventHandler onmessage; attribute DOMString binaryType; void send(DOMString data); void send(Blob data); void send(ArrayBuffer data); void send(ArrayBufferView data); };
The WebSocket(url, protocols)
  constructor takes one or two arguments. The first argument, url, specifies the URL to which to
  connect. The second, protocols, if present, is
  either a string or an array of strings. If it is a string, it is
  equivalent to an array consisting of just that string; if it is
  omitted, it is equivalent to the empty array. Each string in the
  array is a subprotocol name. The connection will only be established
  if the server reports that it has selected one of these
  subprotocols. The subprotocol names must all be strings that match
  the requirements for elements that comprise the value of Sec-WebSocket-Protocol
  header fields as defined by the WebSocket protocol specification. [WSP]
When the WebSocket() constructor is invoked, the UA
  must run these steps:
Parse a WebSocket URL's components from the url argument, to obtain host,
   port, resource name, and
   secure. If this fails, throw a
   SyntaxError exception and abort these steps. [WSP]
If secure is false but the
   origin of the entry script has a scheme
   component that is itself a secure protocol, e.g. HTTPS, then throw
   a SecurityError exception.
If port is a port to which the user agent
    is configured to block access, then throw a
    SecurityError exception. (User agents typically block
    access to well-known ports like SMTP.)
Access to ports 80 and 443 should not be blocked, including the unlikely cases when secure is false but port is 443 or secure is true but port is 80.
If protocols is absent, let protocols be an empty array.
Otherwise, if protocols is present and a string, let protocols instead be an array consisting of just that string.
If any of the values in protocols occur
   more than once or otherwise fail to match the requirements for
   elements that comprise the value of Sec-WebSocket-Protocol
   header fields as defined by the WebSocket protocol specification,
   then throw a SyntaxError exception and abort these
   steps. [WSP]
Let origin be the ASCII serialization of the origin of the entry script, converted to ASCII lowercase.
Return a new WebSocket object, and continue
   these steps in the background (without blocking scripts).
Establish a WebSocket connection given the set (host, port, resource name, secure), along
    with the protocols list, an empty list for the
    extensions, and origin. The headers to send
    appropriate cookies must be a Cookie header whose value is the
    cookie-string computed from the user's cookie store and the
    URL url; for these purposes this is
    not a "non-HTTP" API. [WSP] [COOKIES]
When the user agent validates the server's response during the "establish a WebSocket connection" algorithm, if the status code received from the server is not 101 (e.g. it is a redirect), the user agent must fail the websocket connection.
Following HTTP procedures here could introduce serious security problems in a Web browser context. For example, consider a host with a WebSocket server at one path and an open HTTP redirector at another. Suddenly, any script that can be given a particular WebSocket URL can be tricked into communicating to (and potentially sharing secrets with) any host on the Internet, even if the script checks that the URL has the right hostname.
If the establish a WebSocket connection
    algorithm fails, it triggers the fail the WebSocket
    connection algorithm, which then invokes the close the
    WebSocket connection algorithm, which then establishes that
    the WebSocket connection is closed, which fires the close event as described below.
This constructor must be visible when the script's global
  object is either a Window object or an object
  implementing the WorkerUtils interface.
The url
  attribute must return the result of resolving the URL that was passed to the
  constructor. (It doesn't matter what it is resolved relative to,
  since we already know it is an absolute URL.)
The readyState
  attribute represents the state of the connection. It can have the
  following values:
CONNECTING (numeric value 0)OPEN (numeric value 1)CLOSING (numeric value 2)CLOSED (numeric value 3)When the object is created its readyState must be set to
  CONNECTING (0).
The extensions
  attribute must initially return the empty string. After the
  WebSocket connection is established, its value might change, as
  defined below.
The extensions attribute returns
  the extensions selected by the server, if any. (Currently this will
  only ever be the empty string.)
The protocol attribute
  must initially return the empty string. After the WebSocket
  connection is established, its value might change, as defined
  below.
The protocol attribute returns the
  subprotocol selected by the server, if any. It can be used in
  conjunction with the array form of the constructor's second argument
  to perform subprotocol negotiation.
The close()
  method must run the following steps:
If the method's first argument is present but is not an
   integer equal to 1000 or in the range 3000 to 4999, throw an
   InvalidAccessError exception and abort these
   steps.
If the method's second argument is present, then run these substeps:
Let raw reason be the method's second argument.
Let Unicode reason be the result of converting raw reason to a sequence of Unicode characters.
Let reason be the result of encoding Unicode reason as UTF-8.
If reason is longer than 123 bytes,
     then throw a SyntaxError exception and abort these
     steps. [RFC3629]
Run the first matching steps from the following list:
readyState
     attribute is in the CLOSING (2) or CLOSED (3) stateDo nothing.
The connection is already closing or is already
      closed. If it has not already, a close event will eventually fire as described below.
Fail the WebSocket connection and set the readyState attribute's
      value to CLOSING (2).
      [WSP]
The fail the WebSocket connection
      algorithm invokes the close the WebSocket
      connection algorithm, which then establishes that 
      the WebSocket connection is closed, which fires the
      close event as described below.
Start the WebSocket closing handshake and set the
      readyState
      attribute's value to CLOSING (2). [WSP]
If the first argument is present, then the status code to use in the WebSocket Close message must be the integer given by the first argument. [WSP]
If the second argument is also present, then reason must be provided in the Close message after the status code. [RFC3629] [WSP]
The start the WebSocket closing handshake
      algorithm eventually invokes the close the WebSocket
      connection algorithm, which then establishes that the
      WebSocket connection is closed, which fires the close event as described below.
Set the readyState attribute's
      value to CLOSING
      (2).
The WebSocket closing handshake is
      started, and will eventually invoke the close the
      WebSocket connection algorithm, which will establish that
      the WebSocket connection is closed, and thus the close event will fire, as described below.
The bufferedAmount
  attribute must return the number of bytes of application data (UTF-8
  text and binary data) that have been queued using send() but that, as of the last
  time the event loop started executing a task, had not yet been transmitted to
  the network. (This thus includes any text sent during the execution
  of the current task, regardless of whether the user agent is able to
  transmit text asynchronously with script execution.) This does not
  include framing overhead incurred by the protocol, or buffering done
  by the operating system or network hardware. If the connection is
  closed, this attribute's value will only increase with each call to
  the send() method (the
  number does not reset to zero once the connection closes).
In this simple example, the bufferedAmount
   attribute is used to ensure that updates are sent either at the
   rate of one update every 50ms, if the network can handle that rate,
   or at whatever rate the network can handle, if that is too
   fast.
var socket = new WebSocket('ws://game.example.com:12010/updates');
socket.onopen = function () {
  setInterval(function() {
    if (socket.bufferedAmount == 0)
      socket.send(getUpdateData());
  }, 50);
};
   The bufferedAmount
   attribute can also be used to saturate the network without sending
   the data at a higher rate than the network can handle, though this
   requires more careful monitoring of the value of the attribute over
   time.
When a WebSocket object is created, its binaryType IDL
  attribute must be set to the string "blob". On
  getting, it must return the last value it was set to. On setting, if
  the new value is either the string "blob" or
  the string "arraybuffer", then set the IDL
  attribute to this new value. Otherwise, throw a
  SyntaxError exception.
This attribute allows authors to control how binary
  data is exposed to scripts. By setting the attribute to "blob", binary data is returned in Blob
  form; by setting it to "arraybuffer", it is
  returned in ArrayBuffer form. User agents can use this
  as a hint for how to handle incoming binary data: if the attribute
  is set to "blob", it is safe to spool it to
  disk, and if it is set to "arraybuffer", it is
  likely more efficient to keep the data in memory. Naturally, user
  agents are encouraged to use more subtle heuristics to decide
  whether to keep incoming data in memory or not, e.g. based on how
  big the data is or how common it is for a script to change the
  attribute at the last minute. This latter aspect is important in
  particular because it is quite possible for the attribute to be
  changed after the user agent has received the data but before the
  user agent has fired the event for it.
The send(data) method transmits data using the
  connection. If the readyState attribute is
  CONNECTING, it must
  throw an InvalidStateError exception. Otherwise, the
  user agent must run the appropriate set of steps from the following
  list:
Let data be the result of converting the data argument to a
    sequence of Unicode characters. If the WebSocket
    connection is established and the WebSocket closing handshake has not yet
    started, then the user agent must send a WebSocket
    Message comprised of data using a text
    frame opcode; if the data cannot be sent, e.g. because it would
    need to be buffered but the buffer is full, the user agent must
    close the WebSocket connection with prejudice. Any
    invocation of this method with a string argument that does not
    throw an exception must increase the bufferedAmount
    attribute by the number of bytes needed to express the argument as
    UTF-8. [UNICODE] [RFC3629] [WSP]
Blob objectIf the WebSocket connection is established, and the WebSocket
    closing handshake has not yet started, then the user agent
    must send a WebSocket Message comprised of data using a binary frame opcode; if the data
    cannot be sent, e.g. because it would need to be buffered but the
    buffer is full, the user agent must close the WebSocket
    connection with
    prejudice. The data to be sent is the raw data represented
    by the Blob object.  Any
    invocation of this method with a Blob argument that
    does not throw an exception must increase the bufferedAmount
    attribute by the size of the Blob object's raw data,
    in bytes.  [WSP] [FILEAPI]
ArrayBuffer objectIf the WebSocket connection is established, and the WebSocket
    closing handshake has not yet started, then the user agent
    must send a WebSocket Message comprised of data using a binary frame opcode; if the data
    cannot be sent, e.g. because it would need to be buffered but the
    buffer is full, the user agent must close the WebSocket
    connection with
    prejudice. The data to be sent is the data stored in the
    buffer described by the ArrayBuffer object.  Any invocation of
    this method with an ArrayBuffer argument that does
    not throw an exception must increase the bufferedAmount
    attribute by the length of the ArrayBuffer in bytes.
     [WSP] [TYPEDARRAY]
ArrayBufferView objectIf the WebSocket connection is established, and the WebSocket
    closing handshake has not yet started, then the user agent
    must send a WebSocket Message comprised of data using a binary frame opcode; if the data
    cannot be sent, e.g. because it would need to be buffered but the
    buffer is full, the user agent must close the WebSocket
    connection with
    prejudice. The data to be sent is the data stored in the
    section of the buffer described by the ArrayBuffer
    object that the ArrayBufferView object references.
     Any invocation
    of this method with an ArrayBufferView argument that
    does not throw an exception must increase the bufferedAmount
    attribute by the length of the ArrayBufferView in
    bytes.  [WSP] [TYPEDARRAY]
The following are the event handlers (and their
  corresponding event handler
  event types) that must be supported, as IDL attributes, by
  all objects implementing the WebSocket interface:
| Event handler | Event handler event type | 
|---|---|
| onopen | open | 
| onmessage | message | 
| onerror | error | 
| onclose | close | 
When the WebSocket connection is established, the user agent must queue a task to run these steps:
Change the readyState attribute's
   value to OPEN (1).
Change the extensions attribute's
   value to the extensions in use, if is not the null value. [WSP]
Change the protocol attribute's value to
   the subprotocol in use, if is not the null value. [WSP]
Act as if the user agent had received a set-cookie-string consisting
   of the cookies set during the server's opening handshake,
   for the URL url given to the WebSocket() constructor. [COOKIES] [RFC3629] [WSP]
Fire a simple event named open at the WebSocket
   object.
When a WebSocket message has been received with type type and data data, the user agent must queue a task to follow these steps: [WSP]
If the readyState
    attribute's value is not OPEN (1), then abort these
    steps.
Let event be an event that uses the
    MessageEvent interface, with the event type message, which does not bubble, is
    not cancelable, and has no default action.
    
    
Initialize event's origin attribute to the
   Unicode
   serialization of the origin of the
   URL that was passed to the WebSocket
   object's constructor.
If type indicates that the data is Text,
    then initialize event's data attribute to data.
    
If type indicates that the data is Binary,
    and binaryType is
    set to "blob", then initialize event's data attribute to a new
    Blob object that represents data
    as its raw data. [FILEAPI]
If type indicates that the data is Binary,
    and binaryType is
    set to "arraybuffer", then initialize event's data attribute to a new
    read-only ArrayBuffer object whose contents are data. [TYPEDARRAY]
Dispatch event at the
    WebSocket object.
User agents are encouraged to check if they can
  perform the above steps efficiently before they run the task,
  picking tasks from other task queues
  while they prepare the buffers if not. For example, if the binaryType attribute was set
  to "blob" when the data arrived, and the user
  agent spooled all the data to disk, but just before running the
  above task for this particular
  message the script switched binaryType to "arraybuffer", the user agent would want to page the
  data back to RAM before running this task so as to avoid stalling the main
  thread while it created the ArrayBuffer object.
Here is an example of how to define a handler for the message event in the case of text
   frames:
mysocket.onmessage = function (event) {
  if (event.data == 'on') {
    turnLampOn();
  } else if (event.data == 'off') {
    turnLampOff();
  }
};
   The protocol here is a trivial one, with the server just sending "on" or "off" messages.
When the WebSocket closing handshake is started, the user
  agent must queue a task to change the readyState attribute's value
  to CLOSING (2). (If the
  close() method was called,
  the readyState
  attribute's value will already be set to CLOSING (2) when this task
  runs.) [WSP]
When the WebSocket connection is closed, possibly cleanly, the user agent must queue a task to run the following substeps:
Change the readyState attribute's
   value to CLOSED
   (3).
If the user agent was required to fail the websocket
   connection or the WebSocket connection is closed with prejudice,
   fire a simple event named error
   at the WebSocket object. [WSP]
Create an event that uses the CloseEvent
   interface, with the event type close, which does not bubble, is not
   cancelable, has no default action, whose wasClean attribute is initialized to
   true if the connection closed cleanly and false
   otherwise, whose code
   attribute is initialized to the WebSocket connection close code, and
   whose reason attribute
   is initialized to the WebSocket connection close reason
   decoded as UTF-8, with error handling, and dispatch
   the event at the WebSocket object. [WSP]
User agents must not convey any failure information to scripts in a way that would allow a script to distinguish the following situations:
In all of these cases, the the WebSocket connection close code would be 1006, as required by the WebSocket Protocol specification. [WSP]
Allowing a script to distinguish these cases would allow a script to probe the user's local network in preparation for an attack.
In particular, this means the code 1015 is not used by the user agent (unless the server erroneously uses it in its close frame, of course).
The task source for all tasks queued in this section is the WebSocket task source.
The WebSocket protocol specification defines Ping and Pong frames that can be used for keep-alive, heart-beats, network status probing, latency instrumentation, and so forth. These are not currently exposed in the API.
User agents may send ping and unsolicited pong frames as desired, for example in an attempt to maintain local network NAT mappings, to detect failed connections, or to display latency metrics to the user. User agents must not use pings or unsolicited pongs to aid the server; it is assumed that servers will solicit pongs whenever appropriate for the server's needs.
The steps to parse a WebSocket URL's components from a string url are as follows. These steps return either a host, a port, a resource name, and a secure flag, or they fail.
If the url string is not an absolute URL, then fail this algorithm.
Resolve the url string, with the URL character encoding set to UTF-8. [RFC3629]
It doesn't matter what it is resolved relative to, since we already know it is an absolute URL at this point.
If url does not have a <scheme> component whose value,
   when converted to ASCII lowercase, is either "ws" or "wss", then fail this
   algorithm.
If url has a <fragment> component, then fail this algorithm.
If the <scheme>
   component of url is "ws",
   set secure to false; otherwise, the <scheme> component is "wss", set secure to
   true.
Let host be the value of the <host> component of url, converted to ASCII lowercase.
If url has a <port> component, then let port be that component's value; otherwise, there is no explicit port.
If there is no explicit port, then: if secure is false, let port be 80, otherwise let port be 443.
Let resource name be the value of the <path> component (which might be empty) of url.
If resource name is the empty string, set it to a single character U+002F SOLIDUS (/).
If url has a <query> component, then append a single U+003F QUESTION MARK character (?) to resource name, followed by the value of the <query> component.
Return host, port, resource name, and secure.
[Constructor(DOMString type, optional CloseEventInit eventInitDict)] interface CloseEvent : Event { readonly attribute boolean wasClean; readonly attribute unsigned short code; readonly attribute DOMString reason; }; dictionary CloseEventInit : EventInit { boolean wasClean; unsigned short code; DOMString reason; };
The wasClean
  attribute must return the value it was initialized to. When the
  object is created, this attribute must be initialized to false. It
  represents whether the connection closed cleanly or not.
The code
  attribute must return the value it was initialized to. When the
  object is created, this attribute must be initialized to zero. It
  represents the WebSocket connection close code provided by the
  server.
The reason
  attribute must return the value it was initialized to. When the
  object is created, this attribute must be initialized to empty
  string. It represents the WebSocket connection close reason provided
  by the server.
A WebSocket object whose readyState attribute's value
  was set to CONNECTING
  (0) as of the last time the event loop started
  executing a task must not be
  garbage collected if there are any event listeners registered for
  open events, message events, error events, or close events.
A WebSocket object whose readyState attribute's value
  was set to OPEN (1) as of
  the last time the event loop started executing a task must not be garbage collected if
  there are any event listeners registered for message events, error, or close events.
A WebSocket object whose readyState attribute's value
  was set to CLOSING (2) as
  of the last time the event loop started executing a
  task must not be garbage collected
  if there are any event listeners registered for error or close events.
A WebSocket object with an established connection that has
  data queued to be transmitted to the network must not be garbage
  collected. [WSP]
If a WebSocket object is garbage collected while its
  connection is still open, the user agent must start the
  WebSocket closing handshake, with no status code for the Close message. [WSP]
If a user agent is to make disappear a
  WebSocket object (this happens when a
  Document object goes away), the user agent must follow
  the first appropriate set of steps from the following list:
Start the WebSocket closing handshake, with the status code to use in the WebSocket Close message being 1001. [WSP]
Do nothing.
Web browsers, for security and privacy reasons, prevent documents in different domains from affecting each other; that is, cross-site scripting is disallowed.
While this is an important security feature, it prevents pages from different domains from communicating even when those pages are not hostile. This section introduces a messaging system that allows documents to communicate with each other regardless of their source domain, in a way designed to not enable cross-site scripting attacks.
The task source for the tasks in cross-document messaging is the posted message task source.
This section is non-normative.
For example, if document A contains an iframe
   element that contains document B, and script in document A calls
   postMessage() on the
   Window object of document B, then a message event will
   be fired on that object, marked as originating from the
   Window of document A. The script in document A might
   look like:
var o = document.getElementsByTagName('iframe')[0];
o.contentWindow.postMessage('Hello world', 'http://b.example.org/');
   To register an event handler for incoming events, the script
   would use addEventListener() (or similar
   mechanisms). For example, the script in document B might look
   like:
window.addEventListener('message', receiver, false);
function receiver(e) {
  if (e.origin == 'http://example.com') {
    if (e.data == 'Hello world') {
      e.source.postMessage('Hello', e.origin);
    } else {
      alert(e.data);
    }
  }
}
   This script first checks the domain is the expected domain, and then looks at the message, which it either displays to the user, or responds to by sending a message back to the document which sent the message in the first place.
Use of this API requires extra care to protect users from hostile entities abusing a site for their own purposes.
Authors should check the origin attribute to ensure
  that messages are only accepted from domains that they expect to
  receive messages from. Otherwise, bugs in the author's message
  handling code could be exploited by hostile sites.
Furthermore, even after checking the origin attribute, authors
  should also check that the data in question is of the expected
  format. Otherwise, if the source of the event has been attacked
  using a cross-site scripting flaw, further unchecked processing of
  information sent using the postMessage() method could
  result in the attack being propagated into the receiver.
Authors should not use the wildcard keyword (*) in the targetOrigin argument in messages that contain any confidential information, as otherwise there is no way to guarantee that the message is only delivered to the recipient to which it was intended.
Authors who accept messages from any origin are encouraged to consider the risks of a denial-of-service attack. An attacker could send a high volume of messages; if the receiving page performs expensive computation or causes network traffic to be sent for each such message, the attacker's message could be multplied into a denial-of-service attack. Authors are encouraged to employ rate limiting (only accepting a certain number of messages per minute) to make such attacks impractical.
The integrity of this API is based on the inability for scripts
  of one origin to post arbitrary events (using dispatchEvent() or otherwise) to objects in other
  origins (those that are not the same).
Implementors are urged to take extra care in the implementation of this feature. It allows authors to transmit information from one domain to another domain, which is normally disallowed for security reasons. It also requires that UAs be careful to allow access to certain properties but not others.
User agents are also encouraged to consider rate-limiting message traffic between different origins, to protect naïve sites from denial-of-service attacks.
postMessage(message, targetOrigin [, transfer ])Posts a message to the given window. Messages can be structured
    objects, e.g. nested objects and arrays, can contain JavaScript
    values (strings, numbers, Dates, etc), and can
    contain certain data objects such as File
    Blob, FileList, and
    ArrayBuffer objects.
Objects listed in transfer are transferred, not just cloned, meaning that they are no longer usable on the sending side.
If the origin of the target window doesn't match the given
    origin, the message is discarded, to avoid information leakage. To
    send the message to the target regardless of origin, set the
    target origin to "*". To restrict the
    message to same-origin targets only, without needing to explicitly
    state the origin, set the target origin to "/".
Throws a DataCloneError if transfer array contains duplicate objects or if
    message could not be cloned.
When posting a message to a Window of a
  browsing context that has just been navigated to a new
  Document is likely to result in the message not
  receiving its intended recipient: the scripts in the target
  browsing context have to have had time to set up
  listeners for the messages. Thus, for instance, in situations where
  a message is to be sent to the Window of newly created
  child iframe, authors are advised to have the child
  Document post a message to their parent announcing
  their readiness to receive messages, and for the parent to wait for
  this message before beginning posting messages.
When a script invokes the postMessage(message, targetOrigin, transfer) method (with two or three
  arguments) on a Window object, the user agent must
  follow these steps:
If the value of the targetOrigin argument
    is neither a single U+002A ASTERISK character (*), a single U+002F
    SOLIDUS character (/), nor an absolute URL, then
    throw a SyntaxError exception and abort the overall
    set of steps.
Let new ports be an empty array.
Let transfer map be an empty association
    list of Transferable objects to placeholder
    objects.
If the method was invoked with a third argument transfer, run these substeps:
If any object is listed in transfer more
      than once, or any of the Transferable objects
      listed in transfer are marked as neutered, then
      throw a DataCloneError exception and abort these
      steps.
For each object x in transfer in turn, add a mapping from x to a new unique placeholder object created for
      x to transfer map, and
      if x is a MessagePort object,
      also append the placeholder object to the new
      ports array.
Let message clone be the result of obtaining a structured clone of the message argument, with transfer map as the transfer map. If this throws an exception, then throw that exception and abort these steps.
If the method was invoked with a third argument transfer, run these substeps:
Let new owner be the Window
      object on which the method was invoked.
For each object x in transfer in turn, obtain a new object y by transferring the object x to new owner, and replace the placeholder object that was created for the object x by the new object y wherever the placeholder exists (i.e. in message clone and in new ports).
Make new ports into a read only array.
Return from the postMessage() method, but
    asynchronously continue running these steps.
If the targetOrigin argument is a single
    literal U+002F SOLIDUS character (/), and the
    Document of the Window object on which
    the method was invoked does not have the same origin
    as the entry script's document, then abort these steps silently.
Otherwise, if the targetOrigin argument is
    an absolute URL, and the Document of the
    Window object on which the method was invoked does
    not have the same origin as targetOrigin, then abort these steps silently.
Otherwise, the targetOrigin argument is a single literal U+002A ASTERISK character (*), and no origin check is made.
Create an event that uses the MessageEvent
    interface, with the event type message, which does not bubble, is
    not cancelable, and has no default action. The data attribute must be
    initialized to the value of message clone, the
    origin attribute must
    be initialized to the Unicode serialization of the origin of
    the script that invoked the method, the source attribute must be
    initialized to the script's global object's
    WindowProxy object, and the ports attribute must be
    initialized to the new ports array.
    
    
Queue a task to dispatch the event created in the
    previous step at the Window object on which the
    method was invoked. The task source for this task is the posted message task
    source.
This section is non-normative.
To enable independent pieces of code (e.g. running in different browsing contexts) to communicate directly, authors can use channel messaging.
Communication channels in this mechanism are implemented as two-ways pipes, with a port at each end. Messages sent in one port are delivered at the other port, and vice-versa. Messages are asynchronous, and delivered as DOM events.
To create a connection (two "entangled" ports), the MessageChannel() constructor is called:
var channel = new MessageChannel();
One of the ports is kept as the local port, and the other port is
  sent to the remote code, e.g. using postMessage():
otherWindow.postMessage('hello', 'http://example.com', [channel.port2]);
  To send messages, the postMessage() method on
  the port is used:
channel.port1.postMessage('hello');
  To receive messages, one listens to message events:
channel.port1.onmessage = handleMessage;
function handleMessage(event) {
  // message is in event.data
  // ...
}
  Data sent on a port can be structured data; for example here an array of strings is passed:
port1.postMessage(['hello', 'world'], 'http://example.com');
This section is non-normative.
In this example, two JavaScript libraries are connected to each
   other using MessagePorts. This allows the libraries to
   later be hosted in different frames, or in Worker
   objects, without any change to the APIs.
<script src="contacts.js"></script> <!-- exposes a contacts object --> <script src="compose-mail.js"></script> <!-- exposes a composer object --> <script> var channel = new MessageChannel(); composer.addContactsProvider(channel.port1); contacts.registerConsumer(channel.port2); </script>
Here's what the "addContactsProvider()" function's implementation could look like:
function addContactsProvider(port) {
  port.onmessage = function (event) {
    switch (event.data.messageType) {
      'search-result': handleSearchResult(event.data.results); break;
      'search-done': handleSearchDone(); break;
      'search-error': handleSearchError(event.data.message); break;
      // ...
    }
  };
};
   Alternatively, it could be implemented as follows:
function addContactsProvider(port) {
  port.addEventListener('message', function (event) {
    if (event.data.messageType == 'search-result')
      handleSearchResult(event.data.results);
  });
  port.addEventListener('message', function (event) {
    if (event.data.messageType == 'search-done')
      handleSearchDone();
  });
  port.addEventListener('message', function (event) {
    if (event.data.messageType == 'search-error')
      handleSearchError(event.data.message);
  });
  // ...
  port.start();
};
   The key difference is that when using addEventListener(),
   the start() method must
   also be invoked. When using onmessage, the call to
   start() is implied.
The start() method,
   whether called explicitly or implicitly (by setting onmessage), starts the
   flow of messages: messages posted on message ports are initially
   paused, so that they don't get dropped on the floor before the
   script has had a chance to set up its handlers.
This section is non-normative.
Ports can be viewed as a way to expose limited capabilities (in the object-capability model sense) to other actors in the system. This can either be a weak capability system, where the ports are merely used as a convenient model within a particular origin, or as a strong capability model, where they are provided by one origin provider as the only mechanism by which another origin consumer can effect change in or obtain information from provider.
For example, consider a situation in which a social Web site
  embeds in one iframe the user's e-mail contacts
  provider (an address book site, from a second origin), and in a
  second iframe a game (from a third origin). The outer
  social site and the game in the second iframe cannot
  access anything inside the first iframe; together they
  can only:
iframe to a new
   URL, such as the same URL but with a
   different fragment identifier, causing the Window in
   the iframe to receive a hashchange event.iframe, causing the Window
   in the iframe to receive a resize event.message event to 
   the Window in the iframe using the window.postMessage()
   API.The contacts provider can use these methods, most particularly
  the third one, to provide an API that can be accessed by other
  origins to manipulate the user's address book. For example, it could
  respond to a message "add-contact Guillaume Tell
  <tell@pomme.example.net>" by adding the given person and
  e-mail address to the user's address book.
To avoid any site on the Web being able to manipulate the user's contacts, the contacts provider might only allow certain trusted sites, such as the social site, to do this.
Now suppose the game wanted to add a contact to the user's address book, and that the social site was willing to allow it to do so on its behalf, essentially "sharing" the trust that the contacts provider had with the social site. There are several ways it could do this; most simply, it could just proxy messages between the game site and the contacts site. However, this solution has a number of difficulties: it requires the social site to either completely trust the game site not to abuse the privilege, or it requires that the social site verify each request to make sure it's not a request that it doesn't want to allow (such as adding multiple contacts, reading the contacts, or deleting them); it also requires some additional complexity if there's ever the possibility of multiple games simultaneously trying to interact with the contacts provider.
Using message channels and MessagePort objects,
  however, all of these problems can go away. When the game tells the
  social site that it wants to add a contact, the social site can ask
  the contacts provider not for it to add a contact, but for the
  capability to add a single contact. The contacts provider
  then creates a pair of MessagePort objects, and sends
  one of them back to the social site, who forwards it on to the game.
  The game and the contacts provider then have a direct connection,
  and the contacts provider knows to only honor a single "add contact"
  request, nothing else. In other words, the game has been granted the
  capability to add a single contact.
This section is non-normative.
Continuing the example from the previous section, consider the
  contacts provider in particular. While an initial implementation
  might have simply used XMLHttpRequest objects in the
  service's iframe, an evolution of the service might
  instead want to use a shared
  worker with a single WebSocket connection.
If the initial design used MessagePort objects to
  grant capabilities, or even just to allow multiple simultaneous
  independent sessions, the service implementation can switch from the
  XMLHttpRequests-in-each-iframe model to
  the shared-WebSocket model without changing the API at
  all: the ports on the service provider side can all be forwarded to
  the shared worker without it affecting the users of the API in the
  slightest.
[Constructor] interface MessageChannel { readonly attribute MessagePort port1; readonly attribute MessagePort port2; };
MessageChannel()Returns a new MessageChannel object with two new MessagePort objects.
port1Returns the first MessagePort object.
port2Returns the second MessagePort object.
When the MessageChannel()
  constructor is called, it must run the following algorithm:
Create a new MessagePort object
   owned by the script's global object, and let port1 be that object.
Create a new MessagePort object
   owned by the script's global object, and let port2 be that object.
Entangle the port1 and port2 objects.
Instantiate a new MessageChannel object, and
   let channel be that object.
Let the port1
   attribute of the channel object be port1.
Let the port2
   attribute of the channel object be port2.
Return channel.
This constructor must be visible when the script's global
  object is either a Window object or an object
  implementing the WorkerUtils interface.
The port1 and
  port2 attributes
  must return the values they were assigned when the
  MessageChannel object was created.
Each channel has two message ports. Data sent through one port is received by the other port, and vice versa.
interface MessagePort : EventTarget { void postMessage(any message, optional sequence<Transferable> transfer); void start(); void close(); // event handlers attribute EventHandler onmessage; }; MessagePort implements Transferable;
postMessage(message [, transfer] )Posts a message through the channel. Objects listed in transfer are transferred, not just cloned, meaning that they are no longer usable on the sending side.
Throws a DataCloneError if transfer array contains duplicate objects or the
    source or target ports, or if message could
    not be cloned.
start()Begins dispatching messages received on the port.
close()Disconnects the port, so that it is no longer active.
Each MessagePort object can be entangled with
  another (a symmetric relationship). Each MessagePort
  object also has a task source called the port
  message queue, initially empty. A port message
  queue can be enabled or disabled, and is initially
  disabled. Once enabled, a port can never be disabled again (though
  messages in the queue can get moved to another queue or removed
  altogether, which has much the same effect).
When the user agent is to create a new
  MessagePort object owned by a script's
  global object object owner, it must
  instantiate a new MessagePort object, and let its owner
  be owner.
When the user agent is to entangle two
  MessagePort objects, it must run the following
  steps:
If one of the ports is already entangled, then disentangle it and the port that it was entangled with.
If those two previously entangled ports were the
    two ports of a MessageChannel object, then that
    MessageChannel object no longer represents an actual
    channel: the two ports in that object are no longer entangled.
Associate the two ports to be entangled, so that they form
   the two parts of a new channel. (There is no
   MessageChannel object that represents this
   channel.)
When the user agent is to clone a port original port, with the clone being owned by owner, it must run the following steps, which return
  a new MessagePort object. These steps must be run
  atomically.
Create a new MessagePort object
   owned by owner, and let new
   port be that object.
Move all the events in the port message queue of original port to the port message queue of new port, if any, leaving the new port's port message queue in its initial disabled state.
If the original port is entangled with another port, then run these substeps:
Let the remote port be the port with which the original port is entangled.
Entangle the remote port and new port objects. The original port object will be disentangled by this process.
Return new port. It is the clone.
To transfer a MessagePort object old to a new owner owner, a user
  agent must clone the old object with the clone being owned by owner, thus obtaining new, must
  neuter the old port, and must finally return new.
The postMessage()
  method, when called on a port source port, must
  cause the user agent to run the following steps:
Let target port be the port with which source port is entangled, if any.
Let new ports be an empty array.
Let transfer map be an empty association
    list of Transferable objects to placeholder
    objects.
If the method was invoked with a second argument transfer, run these substeps:
If any object is listed in transfer more
      than once, or any of the Transferable objects
      listed in transfer are marked as neutered, then
      throw a DataCloneError exception and abort these
      steps.
If any of the objects in transfer are
      either the source port or the target port (if any), then throw a
      DataCloneError exception and abort these
      steps.
For each object x in transfer in turn, add a mapping from x to a new unique placeholder object created for
      x to transfer map, and
      if x is a MessagePort object,
      also append the placeholder object to the new
      ports array.
Let message clone be the result of obtaining a structured clone of the message argument, with transfer map as the transfer map. If this throws an exception, then throw that exception and abort these steps.
If the method was invoked with a second argument transfer, run these substeps:
Let new owner be the owner of target port, if there is a target
      port, or else some arbitrary owner. (This new owner is used when transfering objects below.
      If there is no target port, the
      Transferable objects given in the second argument,
      if any, are still transfered, but since they are then discarded, it
      doesn't matter where they are transfered to.)
For each object x in transfer in turn, obtain a new object y by transferring the object x to new owner, and replace the placeholder object that was created for the object x by the new object y wherever the placeholder exists (i.e. in message clone and in new ports).
Make new ports into a read only array.
If there is no target port (i.e. if source port is not entangled), then abort these steps.
Create an event that uses the MessageEvent
   interface, with the name message, which does not bubble, is not
   cancelable, and has no default action.
   
   
Let the data
   attribute of the event be initialized to the value of message clone.
Let the ports
   attribute of the event be initialized to the new
   ports array.
Add the event to the port message queue of target port.
The start()
  method must enable its port's port message queue, if it
  is not already enabled.
When a port's port message queue is enabled, the event loop must use it as one of its task sources.
If the Document of the port's event
  listeners' global object
  is not fully active, then the messages are lost.
The close()
  method, when called on a port local port that is
  entangled with another port, must cause the user agents to
  disentangle the two ports. If the method is called on a port that is
  not entangled, then the method must do nothing.
The following are the event handlers (and their
  corresponding event handler
  event types) that must be supported, as IDL attributes, by
  all objects implementing the MessagePort interface:
| Event handler | Event handler event type | 
|---|---|
| onmessage | message | 
The first time a MessagePort object's onmessage IDL attribute
  is set, the port's port message queue must be enabled,
  as if the start() method
  had been called.
When a MessagePort object o is
  entangled, user agents must either act as if o's
  entangled MessagePort object has a strong reference to
  o, or as if o's owner has a
  strong reference to o.
Thus, a message port can be received, given an event listener, and then forgotten, and so long as that event listener could receive a message, the channel will be maintained.
Of course, if this was to occur on both sides of the channel, then both ports could be garbage collected, since they would not be reachable from live code, despite having a strong reference to each other.
Furthermore, a MessagePort object must not be
  garbage collected while there exists a message in a task
  queue that is to be dispatched on that
  MessagePort object, or while the
  MessagePort object's port message queue is
  open and there exists a message
  event in that queue.
Authors are strongly encouraged to explicitly close
  MessagePort objects to disentangle them, so that their
  resources can be recollected. Creating many MessagePort
  objects and discarding them without closing them can lead to high
  memory usage.
This section is non-normative.
This specification introduces two related mechanisms, similar to HTTP session cookies, for storing structured data on the client side. [COOKIES]
The first is designed for scenarios where the user is carrying out a single transaction, but could be carrying out multiple transactions in different windows at the same time.
Cookies don't really handle this case well. For example, a user could be buying plane tickets in two different windows, using the same site. If the site used cookies to keep track of which ticket the user was buying, then as the user clicked from page to page in both windows, the ticket currently being purchased would "leak" from one window to the other, potentially causing the user to buy two tickets for the same flight without really noticing.
To address this, this specification introduces the sessionStorage IDL attribute.
  Sites can add data to the session storage, and it will be accessible
  to any page from the same site opened in that window.
For example, a page could have a checkbox that the user ticks to indicate that he wants insurance:
<label> <input type="checkbox" onchange="sessionStorage.insurance = checked ? 'true' : ''"> I want insurance on this trip. </label>
A later page could then check, from script, whether the user had checked the checkbox or not:
if (sessionStorage.insurance) { ... }
   If the user had multiple windows opened on the site, each one would have its own individual copy of the session storage object.
The second storage mechanism is designed for storage that spans multiple windows, and lasts beyond the current session. In particular, Web applications may wish to store megabytes of user data, such as entire user-authored documents or a user's mailbox, on the client side for performance reasons.
Again, cookies do not handle this case well, because they are transmitted with every request.
The localStorage IDL
  attribute is used to access a page's local storage area.
The site at example.com can display a count of how many times the user has loaded its page by putting the following at the bottom of its page:
<p>
  You have viewed this page
  <span id="count">an untold number of</span>
  time(s).
</p>
<script>
  if (!localStorage.pageLoadCount)
    localStorage.pageLoadCount = 0;
  localStorage.pageLoadCount = parseInt(localStorage.pageLoadCount) + 1;
  document.getElementById('count').textContent = localStorage.pageLoadCount;
</script>
  Each site has its own separate storage area.
Storage interfaceinterface Storage {
  readonly attribute unsigned long length;
  DOMString? key(unsigned long index);
  getter DOMString getItem(DOMString key);
  setter creator void setItem(DOMString key, DOMString value);
  deleter void removeItem(DOMString key);
  void clear();
};
  
  Each Storage object provides access to a list of
  key/value pairs, which are sometimes called items. Keys are
  strings. Any string (including the empty string) is a valid
  key. Values are similarly strings.
Each Storage object is associated with a list of
  key/value pairs when it is created, as defined in the sections on
  the sessionStorage and localStorage attributes. Multiple
  separate objects implementing the Storage interface can
  all be associated with the same list of key/value pairs
  simultaneously.
The length
  attribute must return the number of key/value pairs currently
  present in the list associated with the object.
The key(n) method must return the name of the
  nth key in the list. The order of keys is
  user-agent defined, but must be consistent within an object so long
  as the number of keys doesn't change. (Thus, adding or removing a key may change the
  order of the keys, but merely changing the value of an existing key
  must not.)  If n is  greater than or equal to the number of key/value pairs
  in the object, then this method must return null.
The supported property names on a
  Storage object are the keys of each key/value pair
  currently present in the list associated with the object.
The getItem(key) method must return
  the current value associated with
  the given key. If the given key does not exist in the list associated with the
  object then this method must return null.
  
The setItem(key, value) method
  must first check if a key/value pair
  with the given key already exists in the list
  associated with the object.
If it does not, then a new key/value pair must be added to the list, with the given key and with its value set to value.
If the given key does exist in the list, then it must have its value updated to value.
If it couldn't set the new value, the method must throw an
  QuotaExceededError exception. (Setting could fail if,
  e.g., the user has disabled storage for the site, or if the quota
  has been exceeded.)
The removeItem(key) method must cause the key/value
  pair with the given key to be removed from the
  list associated with the object, if it exists. If no item with that
  key exists, the method must do nothing.
The setItem() and removeItem() methods must be
  atomic with respect to failure. In the case of failure, the method
  does nothing. That is, changes to the data storage area must either
  be successful, or the data storage area must not be changed at
  all.
The clear()
  method must atomically cause the list associated with the object to
  be emptied of all key/value pairs, if there are any. If there are
  none, then the method must do nothing.
When the setItem(), removeItem(), and clear() methods are invoked, events
  are fired on other Document objects that can access the
  newly stored or removed data, as defined in the sections on the
  sessionStorage and localStorage attributes.
This specification does not require that the above methods wait until the data has been physically written to disk. Only consistency in what different scripts accessing the same underlying list of key/value pairs see is required.
sessionStorage attribute[NoInterfaceObject]
interface WindowSessionStorage {
  readonly attribute Storage sessionStorage;
};
Window implements WindowSessionStorage;
  The sessionStorage
  attribute represents the set of storage areas specific to the
  current top-level browsing context.
Each top-level browsing context has a unique set of session storage areas, one for each origin.
User agents should not expire data from a browsing context's session storage areas, but may do so when the user requests that such data be deleted, or when the UA detects that it has limited storage space, or for security reasons. User agents should always avoid deleting data while a script that could access that data is running. When a top-level browsing context is destroyed (and therefore permanently inaccessible to the user) the data stored in its session storage areas can be discarded with it, as the API described in this specification provides no way for that data to ever be subsequently retrieved.
The lifetime of a browsing context can be unrelated to the lifetime of the actual user agent process itself, as the user agent may support resuming sessions after a restart.
When a new Document is created in a browsing
  context which has a top-level browsing context,
  the user agent must check to see if that top-level browsing
  context has a session storage area for that document's
  origin. If it does, then that is the
  Document's assigned session storage area. If it does
  not, a new storage area for that document's origin must
  be created, and then that is the Document's
  assigned session storage area. A Document's assigned
  storage area does not change during the lifetime of a
  Document.
In the case of an iframe being moved to
  another Document, the nested browsing context is
  destroyed and a new one created.
The sessionStorage
  attribute must return a Storage object associated with
  the Document's assigned session storage area, if any,
  or null if there isn't one. Each Document object must
  have a separate object for its Window's sessionStorage attribute.
When a new top-level browsing context is created by cloning an existing browsing context, the new browsing context must start with the same session storage areas as the original, but the two sets must from that point on be considered separate, not affecting each other in any way.
When a new top-level browsing context is created by
  a script in an existing
  browsing context, or by the user following a link in an
  existing browsing context, or in some other way related to a
  specific Document, then the session storage area of the
  origin of that Document must be copied
  into the new browsing context when it is created. From that point
  on, however, the two session storage areas must be considered
  separate, not affecting each other in any way.
When the setItem(), removeItem(), and clear() methods are called on a
  Storage object x that is associated
  with a session storage area, if the methods did something, then in
  every Document object whose Window
  object's sessionStorage
  attribute's Storage object is associated with the same
  storage area, other than x, a storage event must be fired, as described below.
localStorage attribute[NoInterfaceObject]
interface WindowLocalStorage {
  readonly attribute Storage localStorage;
};
Window implements WindowLocalStorage;
  The localStorage
  object provides a Storage object for an
  origin.
  
  
User agents must have a set of local storage areas, one for each origin.
User agents should expire data from the local storage areas only for security reasons or when requested to do so by the user. User agents should always avoid deleting data while a script that could access that data is running.
When the localStorage
  attribute is accessed, the user agent must run the following steps,
  which are known as the Storage object
  initialization steps:
The user agent may throw a SecurityError
   exception instead of returning a Storage object if the
   request violates a policy decision (e.g. if the user agent is
   configured to not allow the page to persist data).
If the Document's origin is not a
   scheme/host/port tuple, then throw a SecurityError
   exception and abort these steps.
Check to see if the user agent has allocated a local storage
   area for the origin of the Document of
   the Window object on which the attribute was accessed.
   If it has not, create a new storage area for that
   origin.
Return the Storage object associated with that
   origin's local storage area. Each Document object must
   have a separate object for its Window's localStorage attribute.
When the setItem(), removeItem(), and clear() methods are called on a
  Storage object x that is associated
  with a local storage area, if the methods did something, then in
  every Document object whose Window
  object's localStorage
  attribute's Storage object is associated with the same
  storage area, other than x, a storage event must be fired, as described below.
Whenever the properties of a localStorage attribute's
  Storage object are to be examined, returned, set, or
  deleted, whether as part of a direct property access, when checking
  for the presence of a property, during property enumeration, when
  determining the number of properties present, or as part of the
  execution of any of the methods or attributes defined on the
  Storage interface, the user agent must first
  obtain the storage mutex.
User agents must throw a SecurityError exception
  whenever any of the members of a Storage object
  originally returned by the localStorage attribute are accessed
  by scripts whose effective script origin is not the
  same as the origin of
  the Document of the Window object on which
  the localStorage attribute was
  accessed.
This means Storage objects are neutered
  when the document.domain
  attribute is used.
storage eventThe storage event
  is fired when a storage area changes, as described in the previous
  two sections (for session
  storage, for local
  storage).
When this happens, the user agent must queue a task
  to fire an event with the name storage, which does not
  bubble and is not cancelable, and which uses the
  StorageEvent interface, at each Window
  object whose Document object has a Storage
  object that is affected.
This includes Document objects that are
  not fully active, but events fired on those are ignored
  by the event loop until the Document
  becomes fully active again.
The task source for this task is the DOM manipulation task source.
If the event is being fired due to an invocation of the setItem() or removeItem() methods, the
  event must have its key
  attribute initialized to the name of the key in question, its oldValue attribute initialized to
  the old value of the key in question, or null if the key is newly
  added, and its newValue attribute initialized to
  the new value of the key in question, or null if the key was
  removed.
Otherwise, if the event is being fired due to an invocation of
  the clear() method, the event
  must have its key, oldValue, and newValue attributes
  initialized to null.
In addition, the event must have its url attribute initialized to
  the address of the
  document whose Storage object was affected; and
  its storageArea
  attribute initialized to the Storage object from the
  Window object of the target Document that
  represents the same kind of Storage area as was
  affected (i.e. session or local).
[Constructor(DOMString type, optional StorageEventInit eventInitDict)] interface StorageEvent : Event { readonly attribute DOMString? key; readonly attribute DOMString? oldValue; readonly attribute DOMString? newValue; readonly attribute DOMString url; readonly attribute Storage? storageArea; }; dictionary StorageEventInit : EventInit { DOMString? key; DOMString? oldValue; DOMString? newValue; DOMString url; Storage? storageArea; };
The key
  attribute must return the value it was initialized to. When the
  object is created, this attribute must be initialized to null. It
  represents the key being changed.
The oldValue
  attribute must return the value it was initialized to. When the
  object is created, this attribute must be initialized to null. It
  represents the old value of the key being changed.
The newValue
  attribute must return the value it was initialized to. When the
  object is created, this attribute must be initialized to null. It
  represents the new value of the key being changed.
The url
  attribute must return the value it was initialized to. When the
  object is created, this attribute must be initialized to the empty
  string. It represents the address of the document whose key
  changed.
The storageArea
  attribute must return the value it was initialized to. When the
  object is created, this attribute must be initialized to null. It
  represents the Storage object that was affected.
Because of the use of the storage mutex, multiple browsing contexts will be able to access the local storage areas simultaneously in such a manner that scripts cannot detect any concurrent script execution.
Thus, the length
  attribute of a Storage object, and the value of the
  various properties of that object, cannot change while a script is
  executing, other than in a way that is predictable by the script
  itself.
User agents should limit the total amount of space allowed for storage areas.
User agents should guard against sites storing data under their origin's other affiliated sites, e.g. storing up to the limit in a1.example.com, a2.example.com, a3.example.com, etc, circumventing the main example.com storage limit.
User agents may prompt the user when quotas are reached, allowing the user to grant a site more space. This enables sites to store many user-created documents on the user's computer, for instance.
User agents should allow users to see how much space each domain is using.
A mostly arbitrary limit of five megabytes per origin is recommended. Implementation feedback is welcome and will be used to update this suggestion in the future.
A third-party advertiser (or any entity capable of getting content distributed to multiple sites) could use a unique identifier stored in its local storage area to track a user across multiple sessions, building a profile of the user's interests to allow for highly targeted advertising. In conjunction with a site that is aware of the user's real identity (for example an e-commerce site that requires authenticated credentials), this could allow oppressive groups to target individuals with greater accuracy than in a world with purely anonymous Web usage.
There are a number of techniques that can be used to mitigate the risk of user tracking:
User agents may restrict access to the localStorage objects to scripts
    originating at the domain of the top-level document of the
    browsing context, for instance denying access to the
    API for pages from other domains running in
    iframes.
User agents may, if so configured by the user, automatically delete stored data after a period of time.
For example, a user agent could be configured to treat third-party local storage areas as session-only storage, deleting the data once the user had closed all the browsing contexts that could access it.
This can restrict the ability of a site to track a user, as the site would then only be able to track the user across multiple sessions when he authenticates with the site itself (e.g. by making a purchase or logging in to a service).
However, this also reduces the usefulness of the API as a long-term storage mechanism. It can also put the user's data at risk, if the user does not fully understand the implications of data expiration.
If users attempt to protect their privacy by clearing cookies without also clearing data stored in the local storage area, sites can defeat those attempts by using the two features as redundant backup for each other. User agents should present the interfaces for clearing these in a way that helps users to understand this possibility and enables them to delete data in all persistent storage features simultaneously. [COOKIES]
User agents may allow sites to access session storage areas in an unrestricted manner, but require the user to authorize access to local storage areas.
User agents may record the origins of sites that contained content from third-party origins that caused data to be stored.
If this information is then used to present the view of data currently in persistent storage, it would allow the user to make informed decisions about which parts of the persistent storage to prune. Combined with a blacklist ("delete this data and prevent this domain from ever storing data again"), the user can restrict the use of persistent storage to sites that he trusts.
User agents may allow users to share their persistent storage domain blacklists.
This would allow communities to act together to protect their privacy.
While these suggestions prevent trivial use of this API for user tracking, they do not block it altogether. Within a single domain, a site can continue to track the user during a session, and can then pass all this information to the third party along with any identifying information (names, credit card numbers, addresses) obtained by the site. If a third party cooperates with multiple sites to obtain such information, a profile can still be created.
However, user tracking is to some extent possible even with no cooperation from the user agent whatsoever, for instance by using session identifiers in URLs, a technique already commonly used for innocuous purposes but easily repurposed for user tracking (even retroactively). This information can then be shared with other sites, using using visitors' IP addresses and other user-specific data (e.g. user-agent headers and configuration settings) to combine separate sessions into coherent user profiles.
User agents should treat persistently stored data as potentially sensitive; it's quite possible for e-mails, calendar appointments, health records, or other confidential documents to be stored in this mechanism.
To this end, user agents should ensure that when deleting data, it is promptly deleted from the underlying storage.
Because of the potential for DNS spoofing attacks, one cannot guarantee that a host claiming to be in a certain domain really is from that domain. To mitigate this, pages can use TLS. Pages using TLS can be sure that only the user, software working on behalf of the user, and other pages using TLS that have certificates identifying them as being from the same domain, can access their storage areas.
Different authors sharing one host name, for example users
  hosting content on geocities.com, all share one local
  storage object. There is no feature to restrict the access by
  pathname. Authors on shared hosts are therefore recommended to avoid
  using these features, as it would be trivial for other authors to
  read the data and overwrite it.
Even if a path-restriction feature was made available, the usual DOM scripting security model would make it trivial to bypass this protection and access the data from any path.
The two primary risks when implementing these persistent storage features are letting hostile sites read information from other domains, and letting hostile sites write information that is then read from other domains.
Letting third-party sites read data that is not supposed to be read from their domain causes information leakage, For example, a user's shopping wishlist on one domain could be used by another domain for targeted advertising; or a user's work-in-progress confidential documents stored by a word-processing site could be examined by the site of a competing company.
Letting third-party sites write data to the persistent storage of other domains can result in information spoofing, which is equally dangerous. For example, a hostile site could add items to a user's wishlist; or a hostile site could set a user's session identifier to a known ID that the hostile site can then use to track the user's actions on the victim site.
Thus, strictly following the origin model described in this specification is important for user security.