From d806bfcf0c74e882f5721be40ac793986b4260cd Mon Sep 17 00:00:00 2001 From: hensm Date: Sat, 24 Apr 2021 02:37:51 +0100 Subject: [PATCH] Reformat extension message definitions --- app/src/bridge/components/chromecast/Media.ts | 2 +- .../bridge/components/chromecast/Session.ts | 2 +- app/src/bridge/components/chromecast/index.ts | 8 +- ext/src/lib/Messenger.ts | 2 +- ext/src/lib/TypedPort.ts | 18 +- ext/src/lib/bridge.ts | 2 +- ext/src/messaging.ts | 367 +++++++----------- ext/src/shim/cast/classes/Session.ts | 38 +- ext/src/shim/cast/media/classes/Media.ts | 6 +- ext/src/ui/popup/index.tsx | 2 +- 10 files changed, 197 insertions(+), 250 deletions(-) diff --git a/app/src/bridge/components/chromecast/Media.ts b/app/src/bridge/components/chromecast/Media.ts index f6ad152..7b57fec 100644 --- a/app/src/bridge/components/chromecast/Media.ts +++ b/app/src/bridge/components/chromecast/Media.ts @@ -88,10 +88,10 @@ export default class Media { } private sendMessage (subject: string, data: any) { + data._id = this.referenceId; (sendMessage as any)({ subject , data - , _id: this.referenceId }); } } diff --git a/app/src/bridge/components/chromecast/Session.ts b/app/src/bridge/components/chromecast/Session.ts index 144ebbd..b8ca90d 100644 --- a/app/src/bridge/components/chromecast/Session.ts +++ b/app/src/bridge/components/chromecast/Session.ts @@ -168,11 +168,11 @@ export default class Session { } private sendMessage (subject: string, data: any = {}) { + data._id = this.referenceId; sendMessage({ // @ts-ignore subject , data - , _id: this.referenceId }); } diff --git a/app/src/bridge/components/chromecast/index.ts b/app/src/bridge/components/chromecast/index.ts index f998809..e4b5554 100644 --- a/app/src/bridge/components/chromecast/index.ts +++ b/app/src/bridge/components/chromecast/index.ts @@ -12,12 +12,12 @@ const existingSessions: Map = new Map(); const existingMedia: Map = new Map(); export function handleSessionMessage (message: any) { - if (!message._id) { + if (!message.data._id) { console.error("Session message missing _id"); return; } - const sessionId = message._id; + const sessionId = message.data._id; if (existingSessions.has(sessionId)) { // Forward message to instance message handler @@ -35,12 +35,12 @@ export function handleSessionMessage (message: any) { } export function handleMediaMessage (message: any) { - if (!message._id) { + if (!message.data._id) { console.error("Media message missing _id"); return; } - const mediaId = message._id; + const mediaId = message.data._id; if (existingMedia.has(mediaId)) { // Forward message to instance message handler diff --git a/ext/src/lib/Messenger.ts b/ext/src/lib/Messenger.ts index 4303c0b..eea670a 100644 --- a/ext/src/lib/Messenger.ts +++ b/ext/src/lib/Messenger.ts @@ -11,7 +11,7 @@ interface TabConnectInfo { frameId: number; } -export default class Messenger { +export default class Messenger { connect (connectInfo: RuntimeConnectInfo) { return browser.runtime.connect(connectInfo) as unknown as TypedPort; diff --git a/ext/src/lib/TypedPort.ts b/ext/src/lib/TypedPort.ts index 701f674..c7ef03c 100644 --- a/ext/src/lib/TypedPort.ts +++ b/ext/src/lib/TypedPort.ts @@ -1,11 +1,11 @@ "use strict"; -const portMap = new WeakMap(); +const portMap = new WeakMap, browser.runtime.Port>(); /** * Allows typed access to a runtime.Port object. */ -export class TypedPort { +export class TypedPort { public name: string; public error?: { message: string }; public sender?: browser.runtime.MessageSender; @@ -36,18 +36,18 @@ export class TypedPort { }; public onMessage = { - addListener: (cb: (message: T[number]) => void) => { - portMap.get(this)?.onMessage.addListener(cb); + addListener: (cb: (message: T) => void) => { + portMap.get(this)?.onMessage.addListener(cb as any); } - , removeListener: (cb: (message: T[number]) => void) => { - portMap.get(this)?.onMessage.removeListener(cb); + , removeListener: (cb: (message: T) => void) => { + portMap.get(this)?.onMessage.removeListener(cb as any); } - , hasListener: (cb: (message: T[number]) => void) => { + , hasListener: (cb: (message: T) => void) => { return portMap.get(this)?.onMessage.hasListener(cb as any) ?? false; } }; - public postMessage (message: T[number]) { - portMap.get(this)?.postMessage(message); + public postMessage (message: T) { + portMap.get(this)?.postMessage(message as any); } } diff --git a/ext/src/lib/bridge.ts b/ext/src/lib/bridge.ts index 31f9f07..8facb32 100644 --- a/ext/src/lib/bridge.ts +++ b/ext/src/lib/bridge.ts @@ -5,7 +5,7 @@ import semver from "semver"; import { TypedPort } from "./TypedPort"; import logger from "./logger"; -import { Messages, Message, Port } from "../messaging"; +import { Message, Port } from "../messaging"; import nativeMessaging from "./nativeMessaging"; import options from "./options"; diff --git a/ext/src/messaging.ts b/ext/src/messaging.ts index 98c3830..c150ea5 100644 --- a/ext/src/messaging.ts +++ b/ext/src/messaging.ts @@ -6,262 +6,197 @@ import { TypedPort } from "./lib/TypedPort"; import { BridgeInfo } from "./lib/bridge"; import { Receiver, ReceiverStatus } from "./types"; import { ReceiverSelectorMediaType } from "./background/receiverSelector"; -import { ReceiverSelection - , ReceiverSelectionCast - , ReceiverSelectionStop } from "./background/receiverSelector/ReceiverSelector"; +import { ReceiverSelection, ReceiverSelectionCast, ReceiverSelectionStop } + from "./background/receiverSelector/ReceiverSelector"; import Volume from "./shim/cast/classes/Volume"; import { MediaInfo } from "./shim/cast/media"; -// TODO: Document messages properly -export type Messages = [ - { - subject: "popup:/sendRequestedAppId" - , data: { - requestedAppId?: string; - } +type MessagesBase = { + "popup:/sendRequestedAppId": { + requestedAppId?: string } - , { - subject: "popup:/populateReceiverList" - , data: { - receivers: Receiver[] - , defaultMediaType?: ReceiverSelectorMediaType - , availableMediaTypes?: ReceiverSelectorMediaType - } - } - , { - subject: "popup:/close" + , "popup:/populateReceiverList": { + receivers: Receiver[] + , defaultMediaType?: ReceiverSelectorMediaType + , availableMediaTypes?: ReceiverSelectorMediaType } + , "popup:/close": {} - , { - subject: "receiverSelector:/selected" - , data: ReceiverSelection - } - , { - subject: "receiverSelector:/stop" - , data: ReceiverSelection - } - , { - subject: "main:/shimInitialized" - , data: { appId: string; } - } - , { - subject: "main:/selectReceiverBegin" - } - , { - subject: "shim:/selectReceiverEnd" - , data: ReceiverSelectionCast - } - , { - subject: "shim:/selectReceiverStop" - , data: ReceiverSelectionStop - } - , { - subject: "shim:/selectReceiverCancelled" - } - , { - subject: "main:/sessionCreated" - } - , { - subject: "shim:/serviceUp" - , data: { id: Receiver["id"] } - } - , { - subject: "shim:/serviceDown" - , data: { id: Receiver["id"] } - } - , { - subject: "shim:/initialized" - , data: BridgeInfo - } - , { - subject: "shim:/launchApp" - , data: { receiver: Receiver } - } + , "receiverSelector:/selected": ReceiverSelection + , "receiverSelector:/stop": ReceiverSelection + + , "main:/shimInitialized": { appId: string } + + , "main:/selectReceiverBegin": {} + , "shim:/selectReceiverEnd": ReceiverSelectionCast + , "shim:/selectReceiverStop": ReceiverSelectionStop + , "shim:/selectReceiverCancelled": {} + + , "main:/sessionCreated": {} + + , "shim:/serviceUp": { id: Receiver["id"] } + , "shim:/serviceDown": { id: Receiver["id"] } + + , "shim:/initialized": BridgeInfo + , "shim:/launchApp": { receiver: Receiver } // Session messages - , { - subject: "shim:/session/stopped" + , "shim:/session/stopped": {} + , "shim:/session/connected": { + sessionId: string + , namespaces: Array<{ name: string }> + , displayName: string + , statusText: string } - , { - subject: "shim:/session/connected" - , data: { - sessionId: string; - namespaces: Array<{ name: string }>; - displayName: string; - statusText: string; - } + , "shim:/session/updateStatus": { volume: Volume } + , "shim:/session/impl_addMessageListener": { + namespace: string + , data: string } - , { - subject: "shim:/session/updateStatus" - , data: { volume: Volume } + , "shim:/session/impl_sendMessage": { + messageId: string + , error: boolean } - , { - subject: "shim:/session/impl_addMessageListener" - , data: { namespace: string, data: string } + , "shim:/session/impl_setReceiverMuted": { + volumeId: string + , error: boolean } - , { - subject: "shim:/session/impl_sendMessage" - , data: { messageId: string, error: boolean } + , "shim:/session/impl_setReceiverVolumeLevel": { + volumeId: string + , error: boolean } - , { - subject: "shim:/session/impl_setReceiverMuted" - , data: { volumeId: string, error: boolean } - } - , { - subject: "shim:/session/impl_setReceiverVolumeLevel" - , data: { volumeId: string, error: boolean } - } - , { - subject: "shim:/session/impl_stop" - , data: { stopId: string, error: boolean } + , "shim:/session/impl_stop": { + stopId: string + , error: boolean } // Bridge session messages - , { - subject: "bridge:/session/initialize" - , data: { - address: string - , port: number - , appId: string - , sessionId: string - } - , _id: string; - } - , { - subject: "bridge:/session/impl_leave" - , data: { id: string } + , "bridge:/session/initialize": { + address: string + , port: number + , appId: string + , sessionId: string , _id: string } - , { - subject: "bridge:/session/impl_sendMessage" - , data: { namespace: string, message: any, messageId: string } + , "bridge:/session/impl_leave": { + id: string , _id: string } - , { - subject: "bridge:/session/impl_setReceiverMuted" - , data: { muted: boolean, volumeId: string } + , "bridge:/session/impl_sendMessage": { + namespace: string + , message: any + , messageId: string , _id: string } - , { - subject: "bridge:/session/impl_setReceiverVolumeLevel" - , data: { newLevel: number, volumeId: string } + , "bridge:/session/impl_setReceiverMuted": { + muted: boolean + , volumeId: string , _id: string } - , { - subject: "bridge:/session/impl_stop" - , data: { stopId: string } + , "bridge:/session/impl_setReceiverVolumeLevel": { + newLevel: number + , volumeId: string , _id: string } - , { - subject: "bridge:/session/impl_addMessageListener" - , data: { namespace: string } - , _id: string + , "bridge:/session/impl_stop": { + stopId: string; + _id: string; + } + , "bridge:/session/impl_addMessageListener": { + namespace: string; + _id: string; } // Media messages - , { - subject: "shim:/media/update" - , data: { - currentTime: number - , _lastCurrentTime: number - , customData: any - , playbackRate: number - , playerState: string - , repeatMode: string - , _volumeLevel: number - , _volumeMuted: boolean - , media: MediaInfo - , mediaSessionId: number - } + , "shim:/media/update": { + currentTime: number + , _lastCurrentTime: number + , customData: any + , playbackRate: number + , playerState: string + , repeatMode: string + , _volumeLevel: number + , _volumeMuted: boolean + , media: MediaInfo + , mediaSessionId: number } - , { - subject: "shim:/media/sendMediaMessageResponse" - , data: { messageId: string, error: boolean } + , "shim:/media/sendMediaMessageResponse": { + messageId: string + , error: boolean } // Bridge media messages - , { - subject: "bridge:/media/initialize" - , data: { - sessionId: string - , mediaSessionId: number - , _internalSessionId: string - } - , _id: string; + , "bridge:/media/initialize": { + sessionId: string + , mediaSessionId: number + , _internalSessionId: string + , _id: string } - , { - subject: "bridge:/media/sendMediaMessage" - , data: { message: any, messageId: string } - , _id: string; + , "bridge:/media/sendMediaMessage": { + message: any + , messageId: string + , _id: string } // Bridge messages - , { - subject: "main:/receiverSelector/selected" - , data: ReceiverSelectionCast - } - , { - subject: "main:/receiverSelector/error" - , data: string - } - , { - subject: "main:/receiverSelector/close" - } - , { - subject: "main:/receiverSelector/stop" - , data: ReceiverSelectionStop - } - , { - subject: "bridge:/initialize" - , data: { shouldWatchStatus: boolean } - } - , { - subject: "bridge:/receiverSelector/open" - , data: any } - , { - subject: "bridge:/receiverSelector/close" - } - , { - subject: "bridge:/stopReceiverApp" - , data: { receiver: Receiver } - } - , { - subject: "bridge:/mediaServer/start" - , data: { filePath: string, port: number } - } + , "main:/receiverSelector/selected": ReceiverSelectionCast + , "main:/receiverSelector/error": string + , "main:/receiverSelector/close": {} + , "main:/receiverSelector/stop": ReceiverSelectionStop - , { - subject: "mediaCast:/mediaServer/started" - , data: { - mediaPath: string - , subtitlePaths: string[] - , localAddress: string - } - } - , { - subject: "mediaCast:/mediaServer/stopped" - } - , { - subject: "mediaCast:/mediaServer/error" - } + , "bridge:/initialize": { shouldWatchStatus: boolean } - , { - subject: "main:/serviceUp" - , data: Receiver - } - , { - subject: "main:/serviceDown" - , data: { id: string } - } - , { - subject: "main:/receiverStatus" - , data: { id: string, status: ReceiverStatus } - } -]; + , "bridge:/receiverSelector/open": any + , "bridge:/receiverSelector/close": {} -export type Port = TypedPort; -export type Message = Messages[number]; + , "bridge:/stopReceiverApp": { receiver: Receiver } -export default new Messenger(); + , "bridge:/mediaServer/start": { + filePath: string + , port: number + } + , "mediaCast:/mediaServer/started": { + mediaPath: string + , subtitlePaths: string[] + , localAddress: string + } + , "mediaCast:/mediaServer/stopped": {} + , "mediaCast:/mediaServer/error": {} + + , "main:/serviceUp": Receiver + , "main:/serviceDown": { id: string } + + , "main:/receiverStatus": { + id: string + , status: ReceiverStatus + } +} + +interface MessageBase { + subject: K; + data: MessagesBase[K]; +} + +type Messages = { + [K in keyof MessagesBase]: MessageBase; +} + +/** + * For better call semantics, make message data key optional if + * specified as blank or with all-optional keys. + */ +type NarrowedMessage> = + L extends any + ? {} extends L["data"] + ? Omit & Partial + : L + : never; + + +export type Port = TypedPort; +export type Message = NarrowedMessage; + + +export default new Messenger(); diff --git a/ext/src/shim/cast/classes/Session.ts b/ext/src/shim/cast/classes/Session.ts index 85f19bd..8b7ec04 100755 --- a/ext/src/shim/cast/classes/Session.ts +++ b/ext/src/shim/cast/classes/Session.ts @@ -50,7 +50,7 @@ export default class Session { #listener = onMessage(message => { // Filter other session messages - if ((message as any)._id !== this.#id) { + if ((message as any).data._id !== this.#id) { return; } @@ -233,8 +233,8 @@ export default class Session { , port: (receiver as any)._port , appId , sessionId + , _id: this.#id } - , _id: this.#id }); } } @@ -256,8 +256,10 @@ export default class Session { sendMessageResponse({ subject: "bridge:/session/impl_addMessageListener" - , data: { namespace } - , _id: this.#id + , data: { + namespace + , _id: this.#id + } }); } @@ -273,8 +275,10 @@ export default class Session { sendMessageResponse({ subject: "bridge:/session/impl_leave" - , data: { id } - , _id: this.#id + , data: { + id + , _id: this.#id + } }); this.#leaveCallbacks.set(id, [ @@ -381,8 +385,8 @@ export default class Session { namespace , message , messageId + , _id: this.#id } - , _id: this.#id }); this.#sendMessageCallbacks.set(messageId, [ @@ -400,8 +404,11 @@ export default class Session { sendMessageResponse({ subject: "bridge:/session/impl_setReceiverMuted" - , data: { muted, volumeId } - , _id: this.#id + , data: { + muted + , volumeId + , _id: this.#id + } }); this.#setReceiverMutedCallbacks.set(volumeId, [ @@ -419,8 +426,11 @@ export default class Session { sendMessageResponse({ subject: "bridge:/session/impl_setReceiverVolumeLevel" - , data: { newLevel, volumeId } - , _id: this.#id + , data: { + newLevel + , volumeId + , _id: this.#id + } }); this.#setReceiverVolumeLevelCallbacks.set(volumeId, [ @@ -437,8 +447,10 @@ export default class Session { sendMessageResponse({ subject: "bridge:/session/impl_stop" - , data: { stopId } - , _id: this.#id + , data: { + stopId + , _id: this.#id + } }); this.#stopCallbacks.set(stopId, [ diff --git a/ext/src/shim/cast/media/classes/Media.ts b/ext/src/shim/cast/media/classes/Media.ts index 5c465d5..ae956ea 100644 --- a/ext/src/shim/cast/media/classes/Media.ts +++ b/ext/src/shim/cast/media/classes/Media.ts @@ -45,7 +45,7 @@ export default class Media { #lastCurrentTime?: number; #listener = onMessage(message => { - if ((message as any)._id !== this.#id) { + if ((message as any).data._id !== this.#id) { return; } @@ -130,8 +130,8 @@ export default class Media { sessionId , mediaSessionId , _internalSessionId + , _id: this.#id } - , _id: this.#id }); } @@ -348,8 +348,8 @@ export default class Media { , data: { message , messageId + , _id: this.#id } - , _id: this.#id }); } } diff --git a/ext/src/ui/popup/index.tsx b/ext/src/ui/popup/index.tsx index 33fdd0a..a55c99c 100755 --- a/ext/src/ui/popup/index.tsx +++ b/ext/src/ui/popup/index.tsx @@ -75,7 +75,7 @@ class PopupApp extends Component<{}, PopupAppState> { switch (message.subject) { case "popup:/sendRequestedAppId": { this.setState({ - requestedAppId: message.data.requestedAppId + requestedAppId: message.data?.requestedAppId }); break;