# Message Channels ```eval_rst .. contents:: Table of Contents :depth: 3 :local: :backlinks: none ``` Message channels provide a mechanism to communicate across globals, including in cases where there is no client-side mechanism to establish a communication channel (i.e. when the globals are in different browsing context groups). ## Markup ## ```html ``` Channels can be used in any global and are not specifically linked to `testharness.js`. ### High Level API ### The high level API provides a way to message another global, and to execute functions in that global and return the result. Globals wanting to receive messages using the high level API have to be loaded with a `uuid` query parameter in their URL, with a value that's a UUID. This will be used to identify the channel dedicated to messages sent to that context. The context must call either `global_channel` or `start_global_channel` when it's ready to receive messages. This returns a `RecvChannel` that can be used to add message handlers. ```eval_rst .. js:autofunction:: global_channel :short-name: .. js:autofunction:: start_global_channel :short-name: .. js:autoclass:: RemoteGlobalCommandRecvChannel :members: ``` Contexts wanting to communicate with the remote context do so using a `RemoteGlobal` object. ```eval_rst .. js:autoclass:: RemoteGlobal :members: ``` #### Remote Objects #### By default objects (e.g. script arguments) sent to the remote global are cloned. In order to support referencing objects owned by the originating global, there is a `RemoteObject` type which can pass a reference to an object across a channel. ```eval_rst .. js:autoclass:: RemoteObject :members: ``` #### Example #### test.html ```html call example ``` child.html ```html ``` ### Low Level API ### The high level API is implemented in terms of a channel abstraction. Each channel is identified by a UUID, and corresponds to a message queue hosted by the server. Channels are multiple producer, single consumer, so there's only only entity responsible for processing messages sent to the channel. This is designed to discourage race conditions where multiple consumers try to process the same message. On the client side, the read side of a channel is represented by a `RecvChannel` object, and the send side by `SendChannel`. An initial channel pair is created with the `channel()` function. ```eval_rst .. js:autofunction:: channel :members: .. js:autoclass:: Channel :members: .. js:autoclass:: SendChannel :members: .. js:autoclass:: RecvChannel :members: ``` ### Navigation and bfcache For specific use cases around bfcache, it's important to be able to ensure that no network connections (including websockets) remain open at the time of navigation, otherwise the page will be excluded from bfcache. This is handled as follows: * A `disconnectReader` method on `SendChannel`. This causes a server-initiated disconnect of the corresponding `RecvChannel` websocket. The idea is to allow a page to send a command that will initiate a navigation, then without knowing when the navigation is done, send further commands that will be processed when the `RecvChannel` reconnects. If the commands are sent before the navigation, but not processed, they can be buffered by the remote and then lost during navigation. * A `close_all_channel_sockets()` function. This just closes all the open websockets associated with channels in the global in which it's called. Any channel then has to be reconnected to be used again. Calling `closeAllChannelSockets()` right before navigating will leave you in a state with no open websocket connections (unless something happens to reopen one before the navigation starts). ```eval_rst .. js:autofunction:: close_all_channel_sockets :members: ```