import Postis from 'postis'; /** * The default options for postis. * * @type {Object} */ const DEFAULT_POSTIS_OPTIONS = { window: window.opener || window.parent }; /** * The list of methods of incoming postis messages that we have to support for * backward compatibility for the users that are directly sending messages to * Jitsi Meet (without using external_api.js) * * @type {string[]} */ const LEGACY_INCOMING_METHODS = [ 'avatar-url', 'display-name', 'email', 'toggle-audio', 'toggle-chat', 'toggle-contact-list', 'toggle-film-strip', 'toggle-share-screen', 'toggle-video', 'video-hangup' ]; /** * The list of methods of outgoing postis messages that we have to support for * backward compatibility for the users that are directly listening to the * postis messages send by Jitsi Meet(without using external_api.js). * * @type {string[]} */ const LEGACY_OUTGOING_METHODS = [ 'display-name-change', 'incoming-message', 'outgoing-message', 'participant-joined', 'participant-left', 'video-conference-joined', 'video-conference-left', 'video-ready-to-close' ]; /** * The postis method used for all messages. * * @type {string} */ const POSTIS_METHOD_NAME = 'message'; /** * Implements message transport using the postMessage API. */ export default class PostMessageTransportBackend { /** * Creates new PostMessageTransportBackend instance. * * @param {Object} options - Optional parameters for configuration of the * transport. */ constructor({ enableLegacyFormat, postisOptions } = {}) { this.postis = Postis({ ...DEFAULT_POSTIS_OPTIONS, ...postisOptions }); /** * If true PostMessageTransportBackend will process and send messages * using the legacy format and in the same time the current format. * Otherwise all messages (outgoing and incoming) that are using the * legacy format will be ignored. * * @type {boolean} */ this._enableLegacyFormat = enableLegacyFormat; if (this._enableLegacyFormat) { // backward compatibility LEGACY_INCOMING_METHODS.forEach(method => this.postis.listen( method, params => this._legacyMessageReceivedCallback(method, params) ) ); } this._receiveCallback = () => { // Do nothing until a callback is set by the consumer of // PostMessageTransportBackend via setReceiveCallback. }; this.postis.listen( POSTIS_METHOD_NAME, message => this._receiveCallback(message)); } /** * Handles incoming legacy postis messages. * * @param {string} method - The method property from the postis message. * @param {Any} params - The params property from the postis message. * @returns {void} */ _legacyMessageReceivedCallback(method, params = {}) { this._receiveCallback({ data: { name: method, data: params } }); } /** * Sends the passed message via postis using the old format. * * @param {Object} legacyMessage - The message to be sent. * @returns {void} */ _sendLegacyMessage({ name, ...data }) { if (name && LEGACY_OUTGOING_METHODS.indexOf(name) !== -1) { this.postis.send({ method: name, params: data }); } } /** * Disposes the allocated resources. * * @returns {void} */ dispose() { this.postis.destroy(); } /** * Sends the passed message. * * @param {Object} message - The message to be sent. * @returns {void} */ send(message) { this.postis.send({ method: POSTIS_METHOD_NAME, params: message }); if (this._enableLegacyFormat) { // For the legacy use case we don't need any new fields defined in // Transport class. That's why we are passing only the original // object passed by the consumer of the Transport class which is // message.data. this._sendLegacyMessage(message.data); } } /** * Sets the callback for receiving data. * * @param {Function} callback - The new callback. * @returns {void} */ setReceiveCallback(callback) { this._receiveCallback = callback; } }