mirror of
https://github.com/hensm/fx_cast.git
synced 2026-06-09 09:09:58 +00:00
114 lines
3.7 KiB
TypeScript
114 lines
3.7 KiB
TypeScript
"use strict";
|
|
|
|
import { Message } from "../messaging";
|
|
|
|
import { BridgeInfo } from "../lib/bridge";
|
|
import { TypedMessagePort } from "../lib/TypedMessagePort";
|
|
|
|
import CastSDK from "./sdk";
|
|
|
|
import { PageEventMessenger, ExtensionEventMessenger } from "./eventMessaging";
|
|
|
|
// Create messengers manually instead of relying on getters
|
|
const eventMessaging = {
|
|
page: new PageEventMessenger(),
|
|
extension: new ExtensionEventMessenger()
|
|
};
|
|
|
|
let initializedBridgeInfo: BridgeInfo;
|
|
let initializedBackgroundPort: MessagePort;
|
|
|
|
/**
|
|
* To support exporting an API from a module, we need to
|
|
* retain the event-based message passing despite not
|
|
* actually crossing any context boundaries. The cast instance
|
|
* listens for and emits these messages, and changing that
|
|
* behavior is too messy.
|
|
*/
|
|
export function ensureInit(): Promise<TypedMessagePort<Message>> {
|
|
return new Promise(async (resolve, reject) => {
|
|
// If already initialized, just return existing bridge info
|
|
if (initializedBridgeInfo) {
|
|
if (initializedBridgeInfo.isVersionCompatible) {
|
|
resolve(initializedBackgroundPort);
|
|
} else {
|
|
reject();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
const channel = new MessageChannel();
|
|
initializedBackgroundPort = channel.port1;
|
|
|
|
/**
|
|
* If the module is imported into a background script
|
|
* context, the location will be the internal extension URL,
|
|
* whereas in a content script, it will be the content page
|
|
* URL.
|
|
*/
|
|
if (window.location.protocol === "moz-extension:") {
|
|
const { default: castManager } = await import(
|
|
"../background/castManager"
|
|
);
|
|
|
|
// port2 will post bridge messages to port 1
|
|
await castManager.init();
|
|
await castManager.createInstance(channel.port2);
|
|
|
|
// bridge -> cast instance
|
|
channel.port1.onmessage = ev => {
|
|
const message = ev.data as Message;
|
|
|
|
// Send message to cast instance
|
|
eventMessaging.extension.sendMessage(message);
|
|
handleIncomingMessageToCast(message);
|
|
};
|
|
|
|
// cast instance -> bridge
|
|
eventMessaging.extension.addListener(message =>
|
|
channel.port1.postMessage(message)
|
|
);
|
|
} else {
|
|
/**
|
|
* Import reference to message port created by contentBridge.
|
|
* Creation of the port triggers side-effects in the
|
|
* background script.
|
|
*/
|
|
const { backgroundPort } = await import("./contentBridge");
|
|
|
|
// backgroundPort -> channel.port2
|
|
backgroundPort.onMessage.addListener((message: Message) => {
|
|
channel.port2.postMessage(message);
|
|
});
|
|
|
|
// channel.port2 -> backgroundPort
|
|
channel.port2.onmessage = ev => {
|
|
const message = ev.data as Message;
|
|
backgroundPort.postMessage(message);
|
|
};
|
|
|
|
// Handle cast messages
|
|
eventMessaging.page.addListener(message =>
|
|
handleIncomingMessageToCast(message)
|
|
);
|
|
}
|
|
|
|
function handleIncomingMessageToCast(message: Message) {
|
|
switch (message.subject) {
|
|
case "cast:initialized": {
|
|
initializedBridgeInfo = message.data;
|
|
|
|
if (initializedBridgeInfo.isVersionCompatible) {
|
|
resolve(initializedBackgroundPort);
|
|
} else {
|
|
reject();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
export default new CastSDK();
|