Support: x-doc-messagingChrome for Android 78+Chrome 4+iOS Safari 3.2+Firefox 3+Safari 4+Samsung Internet 4+UC Browser for Android 12.12+Edge 12+IE (limited) 8+Opera Mini all+Opera 9.5+KaiOS Browser 2.5+
Source: caniuse.com
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.
This API has some privacy implications that might not be immediately obvious.
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', 'https://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 == 'https://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 multiplied 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 [, options ] )Posts a message to the given window. Messages can be structured objects, e.g. nested objects
    and arrays, can contain JavaScript values (strings, numbers, Date
    objects, etc), and can contain certain data objects such as File Blob,
    FileList, and ArrayBuffer objects.
Objects listed in the transfer member of options are
    transferred, not just cloned, meaning that they are no longer usable on the sending side.
A target origin can be specified using the targetOrigin member of
    options. If not provided, it defaults to "/". This default
    restricts the message to same-origin targets only.
If the origin of the target window doesn't match the given target origin, the message is
    discarded, to avoid information leakage. To send the message to the target regardless of origin,
    set the target origin to "*".
Throws a "DataCloneError" DOMException if
    transfer array contains duplicate objects or if message could not be
    cloned.
postMessage(message, targetOrigin [, transfer ] )This is an alternate version of postMessage() where the target origin is specified
   as a parameter. Calling window.postMessage(message, target, transfer) is
   equivalent to window.postMessage(message, {targetOrigin, transfer}).
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.
The window post message steps, given a targetWindow, message, and options, are as follows:
Let targetRealm be targetWindow's Realm.
Let incumbentSettings be the incumbent settings object.
Let targetOrigin be options["targetOrigin"].
If targetOrigin is a single U+002F SOLIDUS character (/), then set targetOrigin to incumbentSettings's origin.
Otherwise, if targetOrigin is not a single U+002A ASTERISK character (*), then:
Let parsedURL be the result of running the URL parser on targetOrigin.
If parsedURL is failure, then throw a "SyntaxError"
     DOMException.
Set targetOrigin to parsedURL's origin.
Let transfer be options["transfer"].
Let serializeWithTransferResult be StructuredSerializeWithTransfer(message, transfer). Rethrow any exceptions.
Queue a task on the posted message task source of targetWindow's relevant agent's event loop to run the following steps:
If the targetOrigin argument is not a single literal U+002A ASTERISK character
     (*) and targetWindow's associated
     Document's origin is not same origin with
     targetOrigin, then return.
Let origin be the serialization of incumbentSettings's origin.
Let source be the WindowProxy object corresponding to
     incumbentSettings's global
     object (a Window object).
Let deserializeRecord be StructuredDeserializeWithTransfer(serializeWithTransferResult, targetRealm).
If this throws an exception, catch it, fire an
      event named messageerror at
      targetWindow, using MessageEvent, with the origin attribute initialized to origin and
      the source attribute initialized to
      source, and then return.
Let messageClone be deserializeRecord.[[Deserialized]].
Let newPorts be a new frozen array consisting of all
     MessagePort objects in deserializeRecord.[[TransferredValues]], if any,
     maintaining their relative order.
Fire an event named message at targetWindow, using
     MessageEvent, with the origin
     attribute initialized to origin, the source attribute initialized to source, the
     data attribute initialized to
     messageClone, and the ports attribute
     initialized to newPorts.
The postMessage(message,
  options) method, when invoked on a
  Window object, must run the following steps:
Let targetWindow be this Window object.
Run the window post message steps providing targetWindow, message, and options.
The postMessage(message,
  targetOrigin, transfer) method, when invoked on a
  Window object, must run the following steps:
Let targetWindow be this Window object.
Let options be «[ "targetOrigin" →
   targetOrigin, "transfer" → transfer ]».
Run the window post message steps providing targetWindow, message, and options.
Support: channel-messagingChrome for Android 78+Chrome 4+iOS Safari 5.0+Firefox 41+Safari 5+Samsung Internet 4+UC Browser for Android 12.12+Edge 12+IE 10+Opera Mini NoneOpera 10.6+KaiOS Browser 2.5+
Source: caniuse.com
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 delivered as DOM events, without interrupting or blocking running tasks.
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', 'https://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 on a
  MessagePort:
port1.postMessage(['hello', 'world']);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,
   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, Exposed=(Window,Worker)]
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 whose owner is the incumbent settings object, and let
   port1 be that object.
Create a new MessagePort object whose owner is the incumbent settings 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.
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.
[Exposed=(Window,Worker,AudioWorklet), Transferable]
interface MessagePort : EventTarget {
  void postMessage(any message, sequence<object> transfer);
  void postMessage(any message, optional PostMessageOptions options = {});
  void start();
  void close();
  // event handlers
  attribute EventHandler onmessage;
  attribute EventHandler onmessageerror;
};
dictionary PostMessageOptions {
  sequence<object> transfer = [];
};postMessage(message [, transfer] )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" DOMException if
    transfer contains duplicate objects or port, 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). A MessagePort also has a has been shipped flag, which must
  initially be false, and an owner, which is a settings
  object set when the object is created, as described below.
When a port's port message queue is enabled, the event loop must use it as one of its task sources. When a port's owner's responsible event loop is a window event loop, all tasks queued on its port message queue must be associated with the port's owner's responsible document.
If the port's owner's responsible document is fully active, but the event listeners all have scripts whose settings objects specify responsible documents that are not fully active, then the messages will be lost.
Each event loop has a task source called the unshipped port
  message queue. This is a virtual task source: it must act as if it contained
  the tasks of each port message queue of each
  MessagePort whose has been shipped flag is false, whose port
  message queue is enabled, and whose owner's
  responsible event loop is that event loop, in the order in which they
  were added to their respective task source. When a task would be removed from the unshipped port message
  queue, it must instead be removed from its port message queue.
When a MessagePort's has been shipped flag is false, its port
  message queue must be ignored for the purposes of the event loop. (The
  unshipped port message queue is used instead.)
The has been shipped flag is set to true when a port, its twin, or
  the object it was cloned from, is or has been transferred. When a MessagePort's
  has been shipped flag is true, its port message queue acts as a
  first-class task source, unaffected to any unshipped port message
  queue.
When the user agent is to create a new MessagePort object with a
  particular environment settings object as its 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.)
Two ports A and B that have gone through this step are now said to be entangled; one is entangled to the other, and vice versa.
While this specification describes this process as instantaneous, implementations are more likely to implement it via message passing. As with all algorithms, the key is "merely" that the end result be indistinguishable, in a black-box sense, from the specification.
MessagePort objects are transferable
  objects. Their transfer steps, given value and
  dataHolder, are:
Set value's has been shipped flag to true.
Set dataHolder.[[PortMessageQueue]] to value's port message queue.
If value is entangled with another port remotePort, then:
Set remotePort's has been shipped flag to true.
Set dataHolder.[[RemotePort]] to remotePort.
Otherwise, set dataHolder.[[RemotePort]] to null.
Their transfer-receiving steps, given dataHolder and value, are:
Set value's has been shipped flag to true.
Set value's owner to value's relevant settings object.
Move all the tasks that are to fire message events in dataHolder.[[PortMessageQueue]] to the
   port message queue of value, if any, leaving
   value's port message queue in its initial disabled state, and, if
   value's owner's responsible event
   loop is a window event loop, associating the moved tasks with value's owner's responsible document.
If dataHolder.[[RemotePort]] is not null, then entangle dataHolder.[[RemotePort]] and value. (This will disentangle dataHolder.[[RemotePort]] from the original port that was transferred.)
The message port post message steps, given a targetPort, message and options are as follows:
Let transfer be options["transfer"].
If transfer contains this
   MessagePort, then throw a "DataCloneError"
   DOMException.
Let doomed be false.
If targetPort is not null and transfer contains targetPort, then set doomed to true and optionally report to a developer console that the target port was posted to itself, causing the communication channel to be lost.
Let serializeWithTransferResult be StructuredSerializeWithTransfer(message, transfer). Rethrow any exceptions.
If targetPort is null, or if doomed is true, then return.
Add a task that runs the following steps to the port message queue of targetPort:
Let finalTargetPort be the MessagePort in whose port message
      queue the task now finds itself.
This can be different from targetPort, if targetPort itself was transferred and thus all its tasks moved along with it.
Let targetRealm be finalTargetPort's relevant Realm.
Let deserializeRecord be StructuredDeserializeWithTransfer(serializeWithTransferResult, targetRealm).
If this throws an exception, catch it, fire an
      event named messageerror at
      finalTargetPort, using MessageEvent, and then return.
     
Let messageClone be deserializeRecord.[[Deserialized]].
Let newPorts be a new frozen array consisting of all
     MessagePort objects in deserializeRecord.[[TransferredValues]], if any,
     maintaining their relative order.
Fire an event named message at finalTargetPort, using
     MessageEvent, with the data attribute
     initialized to messageClone and the ports attribute initialized to
     newPorts.
The postMessage(message,
  options) method, when invoked on a MessagePort object must
  run the following steps:
Let targetPort be the port with which this MessagePort is
   entangled, if any; otherwise let it be null.
Run the message port post message steps providing targetPort, message and options.
The postMessage(message,
  transfer) method, when invoked on a MessagePort object
  must run the following steps:
Let targetPort be the port with which this MessagePort is
   entangled, if any; otherwise let it be null.
Let options be «[ "transfer" → transfer
   ]».
Run the message port post message steps providing targetPort, message and options.
The start() method, when invoked, must
  enable this MessagePort object's port message queue, if it is not
  already enabled.
The close() method, when invoked, must
  run these steps:
Set this MessagePort object's [[Detached]] internal slot value
   to true.
If this MessagePort object is entangled, disentangle it.
The following are the event handlers (and their corresponding event handler event types) that must be supported,
  as event handler IDL attributes, by all objects implementing the
  MessagePort interface:
| Event handler | Event handler event type | 
|---|---|
| onmessage | message | 
| onmessageerror | messageerror | 
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.
This section is non-normative.
Broadcasting to many ports is in principle relatively simple: keep an array of
  MessagePort objects to send messages to, and iterate through the array to send a
  message. However, this has one rather unfortunate effect: it prevents the ports from being garbage
  collected, even if the other side has gone away. To avoid this problem, implement a simple
  protocol whereby the other side acknowledges it still exists. If it doesn't do so after a certain
  amount of time, assume it's gone, close the MessagePort object, and let it be garbage
  collected.
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 the global
  object specified by 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
  an event referenced by a task in a task queue that is to be dispatched on that MessagePort
  object, or while the MessagePort object's port message queue is enabled
  and not empty.
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
  transient memory usage since garbage collection is not necessarily performed promptly, especially
  for MessagePorts where garbage collection can involve cross-process coordination.
Support: broadcastchannelChrome for Android 78+Chrome 54+iOS Safari NoneFirefox 38+Safari NoneSamsung Internet 7.2+UC Browser for Android 12.12+Edge 76+IE NoneOpera Mini NoneOpera 41+KaiOS Browser 2.5+
Source: caniuse.com
Pages on a single origin opened by the same user in the same user agent but in different unrelated browsing contexts sometimes need to send notifications to each other, for example "hey, the user logged in over here, check your credentials again".
For elaborate cases, e.g. to manage locking of shared state, to manage synchronization of
  resources between a server and multiple local clients, to share a WebSocket
  connection with a remote host, and so forth, shared workers are
  the most appropriate solution.
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.
[Exposed=(Window,Worker)]
interface BroadcastChannel : EventTarget {
  constructor(DOMString name);
  readonly attribute DOMString name;
  void postMessage(any message);
  void close();
  attribute EventHandler onmessage;
  attribute EventHandler onmessageerror;
};BroadcastChannel(name)Returns a new BroadcastChannel object via which messages for the given channel
    name can be sent and received.
nameReturns the channel name (as passed to the constructor).
postMessage(message)Sends the given message to other BroadcastChannel objects set up for this channel. Messages can be structured objects, e.g. nested objects and arrays.
close()Closes the BroadcastChannel object, opening it up to garbage collection.
A BroadcastChannel object has a channel name, a
  BroadcastChannel settings object, and a closed flag.
The BroadcastChannel() constructor, when
  invoked, must create and return a BroadcastChannel object whose channel
  name is the constructor's first argument, whose BroadcastChannel
  settings object is the incumbent settings object, and whose closed flag is false.
The name attribute must return the
  channel name.
The postMessage(message) method,
  when invoked on a BroadcastChannel object, must run the following steps:
Let source be this BroadcastChannel.
Let sourceSettings be source's BroadcastChannel
   settings object.
If source's closed flag
   is true, then throw an "InvalidStateError" DOMException.
Let sourceChannel be source's channel name.
Let targetRealm be a user-agent defined Realm.
Let serialized be StructuredSerialize(message). Rethrow any exceptions.
Let destinations be a list of BroadcastChannel objects that
    match the following criteria:
Their BroadcastChannel settings object specifies either:
a global object that is a
       Window object whose associated
       Document is fully active, or
a global object that is a
       WorkerGlobalScope object whose closing flag is false and whose
       worker is not a suspendable worker.
Their BroadcastChannel settings object's origin is same origin with
     sourceSettings's origin.
Their channel name is a case-sensitive match for sourceChannel.
Their closed flag is false.
Remove source from destinations.
Sort destinations such that all BroadcastChannel objects whose
   BroadcastChannel settings
   objects specify the same responsible event loop are sorted in creation
   order, oldest first. (This does not define a complete ordering. Within this constraint, user
   agents may sort the list in any user-agent defined manner.)
For each BroadcastChannel object destination in
    destinations, queue a task on the DOM manipulation task
    source of destination's relevant agent's event loop
    that runs the following steps. If that event loop is a window event loop, then the
    task's document
    must be set to destination's BroadcastChannel settings
    object's responsible document.
Let targetRealm be destination's relevant Realm.
Let data be StructuredDeserialize(serialized, targetRealm).
If this throws an exception, catch it, fire an
      event named messageerror at
      destination, using MessageEvent, with the origin attribute initialized to the serialization of sourceSettings's origin, and then return.
Fire an event named message at destination, using
     MessageEvent, with the data attribute
     initialized to data and the origin
     attribute initialized to the serialization of
     sourceSettings's origin.
While a BroadcastChannel object whose closed flag is false has an event listener
  registered for message events, there must be a strong
  reference from global object specified by
  the BroadcastChannel object's BroadcastChannel settings
  object to the BroadcastChannel object itself.
The close() method must set the
  closed flag of the
  BroadcastChannel object on which it was invoked to true.
Authors are strongly encouraged to explicitly close BroadcastChannel
  objects when they are no longer needed, so that they can be garbage collected. Creating many
  BroadcastChannel objects and discarding them while leaving them with an event
  listener and without closing them can lead to an apparent memory leak, since the objects will
  continue to live for as long as they have an event listener (or until their page or worker is
  closed).
The following are the event handlers (and their corresponding event handler event types) that must be supported,
  as event handler IDL attributes, by all objects implementing the
  BroadcastChannel interface:
| Event handler | Event handler event type | 
|---|---|
| onmessage | message | 
| onmessageerror | messageerror | 
Suppose a page wants to know when the user logs out, even when the user does so from another tab at the same site:
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
  // ...
}