mirror of
https://github.com/hensm/fx_cast.git
synced 2026-06-12 10:39:57 +00:00
Adjust CastManager naming and add comments
This commit is contained in:
@@ -25,39 +25,48 @@ export interface CastInstance {
|
|||||||
appId?: string;
|
appId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keeps track of cast API instances and provides bridge
|
||||||
|
* messaging.
|
||||||
|
*/
|
||||||
export default new (class CastManager {
|
export default new (class CastManager {
|
||||||
private activeInstances = new Set<CastInstance>();
|
private activeInstances = new Set<CastInstance>();
|
||||||
|
|
||||||
public async init() {
|
public async init() {
|
||||||
// Wait for "cast" ports
|
// Handle incoming instance connections
|
||||||
messaging.onConnect.addListener(async port => {
|
messaging.onConnect.addListener(async port => {
|
||||||
if (port.name === "cast") {
|
if (port.name === "cast") {
|
||||||
this.createInstance(port);
|
this.createInstance(port);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Forward receiver eventes to cast instances
|
||||||
receiverDevices.addEventListener("receiverDeviceUp", ev => {
|
receiverDevices.addEventListener("receiverDeviceUp", ev => {
|
||||||
for (const instance of this.activeInstances) {
|
for (const instance of this.activeInstances) {
|
||||||
instance.contentPort.postMessage({
|
instance.contentPort.postMessage({
|
||||||
subject: "cast:serviceUp",
|
subject: "cast:receiverDeviceUp",
|
||||||
data: { receiverDevice: ev.detail.deviceInfo }
|
data: { receiverDevice: ev.detail.deviceInfo }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
receiverDevices.addEventListener("receiverDeviceDown", ev => {
|
receiverDevices.addEventListener("receiverDeviceDown", ev => {
|
||||||
for (const instance of this.activeInstances) {
|
for (const instance of this.activeInstances) {
|
||||||
instance.contentPort.postMessage({
|
instance.contentPort.postMessage({
|
||||||
subject: "cast:serviceDown",
|
subject: "cast:receiverDeviceDown",
|
||||||
data: { receiverDeviceId: ev.detail.deviceId }
|
data: { receiverDeviceId: ev.detail.deviceId }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a cast instance at the given tab (and optionally
|
||||||
|
* frame) ID.
|
||||||
|
*/
|
||||||
public getInstance(tabId: number, frameId?: number) {
|
public getInstance(tabId: number, frameId?: number) {
|
||||||
for (const instance of this.activeInstances) {
|
for (const instance of this.activeInstances) {
|
||||||
if (instance.contentTabId === tabId) {
|
if (instance.contentTabId === tabId) {
|
||||||
|
// If frame ID doesn't match go to next instance
|
||||||
if (frameId && instance.contentFrameId !== frameId) {
|
if (frameId && instance.contentFrameId !== frameId) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -67,19 +76,28 @@ export default new (class CastManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a cast instance with a given port and connects
|
||||||
|
* messaging correctly depending on the type of port.
|
||||||
|
*/
|
||||||
public async createInstance(port: AnyPort) {
|
public async createInstance(port: AnyPort) {
|
||||||
const instance = await (port instanceof MessagePort
|
const instance = await (port instanceof MessagePort
|
||||||
? this.createInstanceFromBackground(port)
|
? this.createInstanceFromBackground(port)
|
||||||
: this.createInstanceFromContent(port));
|
: this.createInstanceFromContent(port));
|
||||||
|
|
||||||
|
this.activeInstances.add(instance);
|
||||||
|
|
||||||
instance.contentPort.postMessage({
|
instance.contentPort.postMessage({
|
||||||
subject: "cast:initialized",
|
subject: "cast:initialized",
|
||||||
data: await bridge.getInfo()
|
data: await bridge.getInfo()
|
||||||
});
|
});
|
||||||
|
|
||||||
this.activeInstances.add(instance);
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a cast instance with a `MessagePort` content port.
|
||||||
|
*/
|
||||||
private async createInstanceFromBackground(
|
private async createInstanceFromBackground(
|
||||||
contentPort: MessagePort
|
contentPort: MessagePort
|
||||||
): Promise<CastInstance> {
|
): Promise<CastInstance> {
|
||||||
@@ -93,10 +111,12 @@ export default new (class CastManager {
|
|||||||
this.activeInstances.delete(instance);
|
this.activeInstances.delete(instance);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// bridge -> content
|
||||||
instance.bridgePort.onMessage.addListener(message => {
|
instance.bridgePort.onMessage.addListener(message => {
|
||||||
contentPort.postMessage(message);
|
contentPort.postMessage(message);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// content -> (any)
|
||||||
contentPort.addEventListener("message", ev => {
|
contentPort.addEventListener("message", ev => {
|
||||||
this.handleContentMessage(instance, ev.data);
|
this.handleContentMessage(instance, ev.data);
|
||||||
});
|
});
|
||||||
@@ -104,7 +124,13 @@ export default new (class CastManager {
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createInstanceFromContent(contentPort: Port): Promise<CastInstance> {
|
/**
|
||||||
|
* Creates a cast instance with a WebExtension `Port` content
|
||||||
|
* port.
|
||||||
|
*/
|
||||||
|
private async createInstanceFromContent(
|
||||||
|
contentPort: Port
|
||||||
|
): Promise<CastInstance> {
|
||||||
if (
|
if (
|
||||||
contentPort.sender?.tab?.id === undefined ||
|
contentPort.sender?.tab?.id === undefined ||
|
||||||
contentPort.sender?.frameId === undefined
|
contentPort.sender?.frameId === undefined
|
||||||
@@ -117,6 +143,8 @@ export default new (class CastManager {
|
|||||||
/**
|
/**
|
||||||
* If there's already an active instance for the sender
|
* If there's already an active instance for the sender
|
||||||
* tab/frame ID, disconnect it.
|
* tab/frame ID, disconnect it.
|
||||||
|
*
|
||||||
|
* TODO: Fix this behaviour!
|
||||||
*/
|
*/
|
||||||
for (const instance of this.activeInstances) {
|
for (const instance of this.activeInstances) {
|
||||||
if (
|
if (
|
||||||
@@ -134,10 +162,11 @@ export default new (class CastManager {
|
|||||||
contentFrameId: contentPort.sender.frameId
|
contentFrameId: contentPort.sender.frameId
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// content -> (any)
|
||||||
const onContentPortMessage = (message: Message) => {
|
const onContentPortMessage = (message: Message) => {
|
||||||
this.handleContentMessage(instance, message);
|
this.handleContentMessage(instance, message);
|
||||||
};
|
};
|
||||||
|
// bridge -> content
|
||||||
const onBridgePortMessage = (message: Message) => {
|
const onBridgePortMessage = (message: Message) => {
|
||||||
contentPort.postMessage(message);
|
contentPort.postMessage(message);
|
||||||
};
|
};
|
||||||
@@ -161,19 +190,28 @@ export default new (class CastManager {
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async handleContentMessage(instance: CastInstance, message: Message) {
|
/**
|
||||||
|
* Handle content messages from the cast instance. These will
|
||||||
|
* either be handled here in the background script or forwarded
|
||||||
|
* to the bridge associated with the cast instance.
|
||||||
|
*/
|
||||||
|
private async handleContentMessage(
|
||||||
|
instance: CastInstance,
|
||||||
|
message: Message
|
||||||
|
) {
|
||||||
const [destination] = message.subject.split(":");
|
const [destination] = message.subject.split(":");
|
||||||
if (destination === "bridge") {
|
if (destination === "bridge") {
|
||||||
instance.bridgePort.postMessage(message);
|
instance.bridgePort.postMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (message.subject) {
|
switch (message.subject) {
|
||||||
case "main:castReady": {
|
// Cast API has been initialized
|
||||||
|
case "main:initializeCast": {
|
||||||
instance.appId = message.data.appId;
|
instance.appId = message.data.appId;
|
||||||
|
|
||||||
for (const receiverDevice of receiverDevices.getDevices()) {
|
for (const receiverDevice of receiverDevices.getDevices()) {
|
||||||
instance.contentPort.postMessage({
|
instance.contentPort.postMessage({
|
||||||
subject: "cast:serviceUp",
|
subject: "cast:receiverDeviceUp",
|
||||||
data: { receiverDevice }
|
data: { receiverDevice }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -181,6 +219,7 @@ export default new (class CastManager {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// User has triggered receiver selection via the cast API
|
||||||
case "main:selectReceiver": {
|
case "main:selectReceiver": {
|
||||||
if (
|
if (
|
||||||
instance.contentTabId === undefined ||
|
instance.contentTabId === undefined ||
|
||||||
@@ -262,7 +301,7 @@ export default new (class CastManager {
|
|||||||
* TODO: If we're closing a selector, make sure it's the same
|
* TODO: If we're closing a selector, make sure it's the same
|
||||||
* one that caused the session creation.
|
* one that caused the session creation.
|
||||||
*/
|
*/
|
||||||
case "main:sessionCreated": {
|
case "main:closeReceiverSelector": {
|
||||||
const selector = await ReceiverSelectorManager.getSelector();
|
const selector = await ReceiverSelectorManager.getSelector();
|
||||||
const shouldClose = await options.get(
|
const shouldClose = await options.get(
|
||||||
"receiverSelectorWaitForConnection"
|
"receiverSelectorWaitForConnection"
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ export function initialize(
|
|||||||
apiConfig = newApiConfig;
|
apiConfig = newApiConfig;
|
||||||
|
|
||||||
sendMessageResponse({
|
sendMessageResponse({
|
||||||
subject: "main:castReady",
|
subject: "main:initializeCast",
|
||||||
data: { appId: apiConfig.sessionRequest.appId }
|
data: { appId: apiConfig.sessionRequest.appId }
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -255,7 +255,7 @@ onMessage(message => {
|
|||||||
case "cast:sessionCreated": {
|
case "cast:sessionCreated": {
|
||||||
// Notify background to close UI
|
// Notify background to close UI
|
||||||
sendMessageResponse({
|
sendMessageResponse({
|
||||||
subject: "main:sessionCreated"
|
subject: "main:closeReceiverSelector"
|
||||||
});
|
});
|
||||||
|
|
||||||
const status = message.data;
|
const status = message.data;
|
||||||
@@ -360,7 +360,7 @@ onMessage(message => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case "cast:serviceUp": {
|
case "cast:receiverDeviceUp": {
|
||||||
const { receiverDevice } = message.data;
|
const { receiverDevice } = message.data;
|
||||||
if (receiverDevices.has(receiverDevice.id)) {
|
if (receiverDevices.has(receiverDevice.id)) {
|
||||||
break;
|
break;
|
||||||
@@ -376,7 +376,7 @@ onMessage(message => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case "cast:serviceDown": {
|
case "cast:receiverDeviceDown": {
|
||||||
const { receiverDeviceId } = message.data;
|
const { receiverDeviceId } = message.data;
|
||||||
|
|
||||||
receiverDevices.delete(receiverDeviceId);
|
receiverDevices.delete(receiverDeviceId);
|
||||||
|
|||||||
@@ -51,18 +51,18 @@ type ExtMessageDefinitions = {
|
|||||||
"receiverSelector:selected": ReceiverSelection;
|
"receiverSelector:selected": ReceiverSelection;
|
||||||
"receiverSelector:stop": ReceiverSelection;
|
"receiverSelector:stop": ReceiverSelection;
|
||||||
|
|
||||||
"main:castReady": { appId: string };
|
|
||||||
|
|
||||||
"main:selectReceiver": {};
|
"main:selectReceiver": {};
|
||||||
"cast:selectReceiver/selected": ReceiverSelectionCast;
|
"cast:selectReceiver/selected": ReceiverSelectionCast;
|
||||||
"cast:selectReceiver/stopped": ReceiverSelectionStop;
|
"cast:selectReceiver/stopped": ReceiverSelectionStop;
|
||||||
"cast:selectReceiver/cancelled": {};
|
"cast:selectReceiver/cancelled": {};
|
||||||
|
|
||||||
"main:sessionCreated": {};
|
"main:closeReceiverSelector": {};
|
||||||
|
|
||||||
|
"main:initializeCast": { appId: string };
|
||||||
"cast:initialized": BridgeInfo;
|
"cast:initialized": BridgeInfo;
|
||||||
"cast:serviceUp": { receiverDevice: ReceiverDevice };
|
|
||||||
"cast:serviceDown": { receiverDeviceId: ReceiverDevice["id"] };
|
"cast:receiverDeviceUp": { receiverDevice: ReceiverDevice };
|
||||||
|
"cast:receiverDeviceDown": { receiverDeviceId: ReceiverDevice["id"] };
|
||||||
"cast:launchApp": { receiver: ReceiverDevice };
|
"cast:launchApp": { receiver: ReceiverDevice };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user