Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[agiow] (0) New BroadcastChannel feature to send messages to other ta…
…bs in the same origin, so you don't have to abuse the onstorage event, and don't need to use a heavy shared worker for something otherwise trivial.

Fixing https://www.w3.org/Bugs/Public/show_bug.cgi?id=22628
Affected topics: DOM APIs, HTML

git-svn-id: http://svn.whatwg.org/webapps@8274 340c8d12-0b0e-0410-8428-c7bf67bfef74
  • Loading branch information
Hixie committed Nov 13, 2013
1 parent 3f221df commit 597f77e
Show file tree
Hide file tree
Showing 3 changed files with 609 additions and 7 deletions.
196 changes: 193 additions & 3 deletions complete.html
Expand Up @@ -298,7 +298,7 @@

<header class=head id=head><p><a href=http://www.whatwg.org/ class=logo><img width=101 src=/images/logo alt=WHATWG height=101></a></p>
<hgroup><h1 class=allcaps>HTML</h1>
<h2 class="no-num no-toc">Living Standard &mdash; Last Updated 12 November 2013</h2>
<h2 class="no-num no-toc">Living Standard &mdash; Last Updated 13 November 2013</h2>
</hgroup><dl><dt><strong>Web developer edition:</strong></dt>
<dd><strong><a href=http://developers.whatwg.org/>http://developers.whatwg.org/</a></strong></dd>
<dt>Multiple-page version:</dt>
Expand Down Expand Up @@ -1142,7 +1142,8 @@ <h2 class="no-num no-toc">Living Standard &mdash; Last Updated 12 November 2013<
<li><a href=#message-channels><span class=secno>9.5.2 </span>Message channels</a></li>
<li><a href=#message-ports><span class=secno>9.5.3 </span>Message ports</a></li>
<li><a href=#broadcasting-to-many-ports><span class=secno>9.5.4 </span>Broadcasting to many ports</a></li>
<li><a href=#ports-and-garbage-collection><span class=secno>9.5.5 </span>Ports and garbage collection</a></ol></ol></li>
<li><a href=#ports-and-garbage-collection><span class=secno>9.5.5 </span>Ports and garbage collection</a></ol></li>
<li><a href=#broadcasting-to-other-browsing-contexts><span class=secno>9.6 </span>Broadcasting to other browsing contexts</a></ol></li>
<li><a href=#workers><span class=secno>10 </span>Web workers</a>
<ol>
<li><a href=#introduction-11><span class=secno>10.1 </span>Introduction</a>
Expand Down Expand Up @@ -77896,7 +77897,7 @@ <h2 id=comms><span class=secno>9 </span>Communication</h2>
<h3 id=event-definitions-2><span class=secno>9.1 </span>Event definitions</h3>

<p>Messages in <a href=#server-sent-events>server-sent events</a>, <a href=#network>Web sockets</a>, <a href=#web-messaging>cross-document
messaging</a>, and <a href=#channel-messaging>channel messaging</a> use the <dfn id=event-message title=event-message><code>message</code></dfn> event. </p>
messaging</a>, <a href=#channel-messaging>channel messaging</a>, and <a href=#broadcasting-to-other-browsing-contexts>broadcast channels</a> use the <dfn id=event-message title=event-message><code>message</code></dfn> event. </p>

<p>The following interface is defined for this event:</p>

Expand All @@ -77905,6 +77906,7 @@ <h3 id=event-definitions-2><span class=secno>9.1 </span>Event definitions</h3>
readonly attribute any <a href=#dom-messageevent-data title=dom-MessageEvent-data>data</a>;
readonly attribute DOMString <a href=#dom-messageevent-origin title=dom-MessageEvent-origin>origin</a>;
readonly attribute DOMString <a href=#dom-messageevent-lasteventid title=dom-MessageEvent-lastEventId>lastEventId</a>;
readonly attribute DOMString <a href=#dom-messageevent-channel title=dom-MessageEvent-channel>channel</a>;
readonly attribute (<a href=#windowproxy>WindowProxy</a> or <a href=#messageport>MessagePort</a>)? <a href=#dom-messageevent-source title=dom-MessageEvent-source>source</a>;
readonly attribute <a href=#messageport>MessagePort</a>[]? <a href=#dom-messageevent-ports title=dom-MessageEvent-ports>ports</a>;
};
Expand All @@ -77913,6 +77915,7 @@ <h3 id=event-definitions-2><span class=secno>9.1 </span>Event definitions</h3>
any data;
DOMString origin;
DOMString lastEventId;
DOMString channel;
(<a href=#windowproxy>WindowProxy</a> or <a href=#messageport>MessagePort</a>)? source;
sequence&lt;<a href=#messageport>MessagePort</a>&gt; ports;
};</pre>
Expand Down Expand Up @@ -77943,6 +77946,14 @@ <h3 id=event-definitions-2><span class=secno>9.1 </span>Event definitions</h3>

</dd>

<dt><var title="">event</var> . <code title=dom-MessageEvent-channel><a href=#dom-messageevent-channel>channel</a></code></dt>

<dd>

<p>Returns the channel ID, for <a href=#broadcasting-to-other-browsing-contexts>broadcast channels</a>.</p>

</dd>

<dt><var title="">event</var> . <code title=dom-MessageEvent-source><a href=#dom-messageevent-source>source</a></code></dt>

<dd>
Expand Down Expand Up @@ -77978,6 +77989,10 @@ <h3 id=event-definitions-2><span class=secno>9.1 </span>Event definitions</h3>
return the value it was initialized to. When the object is created, this attribute must be
initialized to the empty string. It represents, in <a href=#server-sent-events>server-sent events</a>, the <a href=#concept-event-stream-last-event-id title=concept-event-stream-last-event-id>last event ID string</a> of the event source.</p>

<p>The <dfn id=dom-messageevent-channel title=dom-MessageEvent-channel><code>channel</code></dfn> 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 <a href=#broadcasting-to-other-browsing-contexts>broadcast channels</a>, the channel of the message.</p>

<p>The <dfn id=dom-messageevent-source title=dom-MessageEvent-source><code>source</code></dfn> attribute must return the
value it was initialized to. When the object is created, this attribute must be initialized to
null. It represents, in <a href=#web-messaging>cross-document messaging</a>, the <code><a href=#windowproxy>WindowProxy</a></code> of the
Expand Down Expand Up @@ -80589,6 +80604,180 @@ <h4 id=ports-and-garbage-collection><span class=secno>9.5.5 </span>Ports and gar
<!--POSTMSG-->


<h3 id=broadcasting-to-other-browsing-contexts><span class=secno>9.6 </span><dfn title="broadcast channels">Broadcasting to other browsing contexts</dfn></h3>

<p>Pages on a single <a href=#origin>origin</a> opened by the same user in the same user agent but in
different unrelated <a href=#browsing-context title="browsing context">browsing contexts</a> sometimes need to
send notifications to each other, for example "hey, the user logged in over here, check your
credentials again".</p>

<p>For elaborate cases, e.g. to manage locking of shared state, to manage synchronisation of
resources between a server and multiple local clients, to share a <code><a href=#websocket>WebSocket</a></code>
connection with a remote host, and so forth, <a href=#sharedworker title=SharedWorker>shared workers</a> are
the most appropriate solution.</p>

<p>For simple cases, though, where a shared worker would be an unreasonable overhead, authors can
use the simple channel-based broadcast mechanism described in this section.</p>

<pre class=idl>[<a href=#dom-broadcastchannel title=dom-BroadcastChannel>Constructor</a>(DOMString channel)] interface <dfn id=broadcastchannel>BroadcastChannel</dfn> {
void <a href=#dom-broadcastchannel-postmessage title=dom-BroadcastChannel-postMessage>postMessage</a>(DOMString message);
attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-broadcastchannel-onmessage title=handler-BroadcastChannel-onmessage>onmessage</a>;
};</pre>

<dl class=domintro><dt><var title="">broadcastChannel</var> = new <code title=dom-BroadcastChannel><a href=#dom-broadcastchannel>BroadcastChannel</a></code>(<var title="">channel</var>)</dt>

<dd>

<p>Returns a new <code><a href=#broadcastchannel>BroadcastChannel</a></code> object via which messages for the given channel can be sent and received.</p>

</dd>

<dt><var title="">broadcastChannel</var> . <code title=dom-BroadcastChannel-postMessage><a href=#dom-broadcastchannel-postmessage>postMessage</a></code>(<var title="">message</var>)</dt>

<dd>

<p>Sends the given message to other <code><a href=#broadcastchannel>BroadcastChannel</a></code> objects set up for this channel.</p>

</dd>

</dl><div class=impl>

<p>A <code><a href=#broadcastchannel>BroadcastChannel</a></code> object has a <dfn id=channel-name>channel name</dfn> and a
<dfn id=broadcastchannel-settings-object><code>BroadcastChannel</code> settings object</dfn>.</p>

<p>The <dfn id=dom-broadcastchannel title=dom-BroadcastChannel><code>BroadcastChannel()</code></dfn> constructor, when
invoked, must create and return a <code><a href=#broadcastchannel>BroadcastChannel</a></code> object whose <a href=#channel-name>channel
name</a> is the constructor's first argument, and whose <a href=#broadcastchannel-settings-object><code>BroadcastChannel</code>
settings object</a> is the <a href=#incumbent-settings-object>incumbent settings object</a>.</p>

<p>The <dfn id=dom-broadcastchannel-postmessage title=dom-BroadcastChannel-postMessage><code>postMessage()</code></dfn> method,
when invoked on a <code><a href=#broadcastchannel>BroadcastChannel</a></code> object <var title="">source</var> with an
argument <var title="">message</var>, must run the following steps:</p>

<ol><li><p>Let <var title="">source settings</var> be <var title="">source</var>'s
<a href=#broadcastchannel-settings-object><code>BroadcastChannel</code> settings object</a>.</p>

<li><p>Let <var title="">source channel</var> be <var title="">source</var>'s
<a href=#channel-name>channel name</a>.</p>

<li>

<p>Let <var title="">destinations</var> be a list of <code><a href=#broadcastchannel>BroadcastChannel</a></code> objects that
match the folllowing criteria:</p>

<ul><li><p>Their <a href=#broadcastchannel-settings-object><code>BroadcastChannel</code> settings object</a> specifies a
<a href=#responsible-document>responsible document</a> that is <a href=#fully-active>fully active</a>.</li>

<li><p>Their <a href=#broadcastchannel-settings-object><code>BroadcastChannel</code> settings object</a> specifies an
<a href=#origin>origin</a> that is the <a href=#same-origin>same origin</a> as the <a href=#origin>origin</a> specified
by <var title="">source settings</var>.</li>

<li><p>Their <a href=#channel-name>channel name</a> is a <a href=#case-sensitive>case-sensitive</a> match for <var title="">source channel</var>.</li>

</ul></li>

<li><p>Remove <var title="">source</var> from <var title="">destinations</var>.</li>

<li>

<p>Sort <var title="">destinations</var> such that:</p>

<ul><li><p>All <code><a href=#broadcastchannel>BroadcastChannel</a></code> objects whose <a href=#broadcastchannel-settings-object title="BroadcastChannel settings
object"><code>BroadcastChannel</code> settings objects</a> specify the same
<a href=#responsible-document>responsible document</a> must be sorted in creation order, oldest first.</li>

<li><p>All <code><a href=#broadcastchannel>BroadcastChannel</a></code> objects whose <a href=#broadcastchannel-settings-object title="BroadcastChannel settings
object"><code>BroadcastChannel</code> settings objects</a> specify a <a href=#responsible-document>responsible
document</a> contained within a particular <a href=#top-level-browsing-context>top-level browsing context</a> must be
sorted in the same relative order as the order that those <code><a href=#document>Document</a></code> objects are
listed in the <a href=#list-of-the-descendant-browsing-contexts>list of the descendant browsing contexts</a> for the <a href=#active-document>active
document</a> of that <a href=#top-level-browsing-context>top-level browsing context</a>.</li>

<li><p>All <code><a href=#broadcastchannel>BroadcastChannel</a></code> objects whose <a href=#broadcastchannel-settings-object title="BroadcastChannel settings
object"><code>BroadcastChannel</code> settings objects</a> specify a <a href=#responsible-document>responsible
document</a> whose <a href=#top-level-browsing-context>top-level browsing context</a> is an <a href=#auxiliary-browsing-context>auxiliary browsing
context</a> <var title="">X</var> must come <em>after</em> the
<code><a href=#broadcastchannel>BroadcastChannel</a></code> objects whose <a href=#broadcastchannel-settings-object title="BroadcastChannel settings
object"><code>BroadcastChannel</code> settings objects</a> specify a <a href=#responsible-document>responsible
document</a> whose <a href=#top-level-browsing-context>top-level browsing context</a> is <var title="">X</var>'s
<a href=#opener-browsing-context>opener browsing context</a>.</p>

</ul><p>This does not define a complete ordering. Within the constraints described above, user agents
may sort the list in any user-agent defined manner.</p>

</li>

<li>

<p>For each <code><a href=#broadcastchannel>BroadcastChannel</a></code> object in <var title="">destinations</var>,
<a href=#queue-a-task>queue a task</a> that runs the following steps:</p>

<ol><li><p>Create an event that uses the <code><a href=#messageevent>MessageEvent</a></code> interface, with the event type
<code title=event-message><a href=#event-message>message</a></code>, which does not bubble, is not cancelable, and has
no default action. The <code title=dom-MessageEvent-data><a href=#dom-messageevent-data>data</a></code> attribute must be
initialized to the value of the <var title="">message</var> argument, the <code title=dom-MessageEvent-origin><a href=#dom-messageevent-origin>origin</a></code> attribute must be initialized to the <a href=#unicode-serialization-of-an-origin title="Unicode serialization of an origin">Unicode serialization</a> of the
<a href=#origin>origin</a> specified by <var title="">source settings</var>, and the <code title=dom-MessageEvent-channel><a href=#dom-messageevent-channel>channel</a></code> attribute must be initialized to the <var title="">channel name</var>. This event is not <a href=#concept-events-trusted title=concept-events-trusted>trusted</a>.</li>

<li><p><a href=#concept-event-dispatch title=concept-event-dispatch>Dispatch</a> the event at the
<code><a href=#broadcastchannel>BroadcastChannel</a></code> object.</li>

</ol><p>The <a href=#concept-task title=concept-task>tasks</a> must be associated with the <a href=#responsible-document>responsible
document</a> specified by the <code><a href=#broadcastchannel>BroadcastChannel</a></code> object's
<a href=#broadcastchannel-settings-object><code>BroadcastChannel</code> settings object</a>, and must use the <a href=#dom-manipulation-task-source>DOM
manipulation task source</a>.</p>

</li>

</ol><p>While a <code><a href=#broadcastchannel>BroadcastChannel</a></code> object has an event listener registered for <code title=event-message><a href=#event-message>message</a></code> events, there must be a strong reference from <a href=#global-object>global
object</a> specified by the <code><a href=#broadcastchannel>BroadcastChannel</a></code> object's
<a href=#broadcastchannel-settings-object><code>BroadcastChannel</code> settings object</a> to the <code><a href=#broadcastchannel>BroadcastChannel</a></code>
object itself.</p>

<hr><p>The following are the <a href=#event-handlers>event handlers</a> (and their corresponding <a href=#event-handler-event-type title="event
handler event type">event handler event types</a>) that must be supported, as <a href=#event-handler-idl-attributes>event
handler IDL attributes</a>, by all objects implementing the <code><a href=#broadcastchannel>BroadcastChannel</a></code>
interface:</p>

<table><thead><tr><th><a href=#event-handlers title="event handlers">Event handler</a> <th><a href=#event-handler-event-type>Event handler event type</a>
<tbody><tr><td><dfn id=handler-broadcastchannel-onmessage title=handler-BroadcastChannel-onmessage><code>onmessage</code></dfn> <td> <code title=event-message><a href=#event-message>message</a></code>
</table></div>

<p class=note>Authors are strongly encouraged to explicitly close <code><a href=#messageport>MessagePort</a></code>
objects to disentangle them, so that their resources can be recollected. Creating many
<code><a href=#messageport>MessagePort</a></code> objects and discarding them without closing them can lead to high
transient memory usage since garbage collection is not necessarily performed promptly.</p>

<div class=example>

<p>Suppose a page wants to know when the user logs out, even when the user does so from another
tab at the same site:</p>

<pre>var authChannel = new BroadcastChannel('auth');
authChannel.onmessage = function (event) {
if (event.data == 'logout')
showLogout();
}

function logoutRequested() {
// called when the user asks us to log them out
doLogout();
showLogout();
authChannel.postMessage('logout');
}

function doLogout() {
// actually log the user out (e.g. clearing cookies)
// ...
}

function showLogout() {
// update the UI to indicate we're logged out
// ...
}</pre>

</div>



<!--ADD-TOPIC:Workers-->

Expand Down Expand Up @@ -100514,6 +100703,7 @@ <h3 class="no-num">Reflecting IDL attributes</h3>
<li><code><a href=#audiotracklist>AudioTrackList</a></code>
<li><code><a href=#barprop>BarProp</a></code>
<li><code><a href=#beforeunloadevent>BeforeUnloadEvent</a></code>
<li><code><a href=#broadcastchannel>BroadcastChannel</a></code>
<li><code><a href=#canvasdrawingstyles>CanvasDrawingStyles</a></code>
<li><code><a href=#canvasgradient>CanvasGradient</a></code>
<li><code><a href=#canvaspathmethods>CanvasPathMethods</a></code>
Expand Down

0 comments on commit 597f77e

Please sign in to comment.