mirror of
https://github.com/hensm/fx_cast.git
synced 2026-06-10 01:29:58 +00:00
Restructure shim/bridge initialization steps
This commit is contained in:
@@ -168,7 +168,7 @@ async function handleMessage (message) {
|
||||
|
||||
browser.on("serviceUp", service => {
|
||||
transforms.encode.write({
|
||||
subject: "shim:serviceUp"
|
||||
subject: "serviceUp"
|
||||
, data: {
|
||||
address: service.addresses[0]
|
||||
, port: service.port
|
||||
@@ -181,7 +181,7 @@ browser.on("serviceUp", service => {
|
||||
|
||||
browser.on("serviceDown", service => {
|
||||
transforms.encode.write({
|
||||
subject:"shim:serviceDown"
|
||||
subject:"serviceDown"
|
||||
, data: {
|
||||
id: service.txt.id
|
||||
}
|
||||
|
||||
@@ -1,12 +1,37 @@
|
||||
"use strict";
|
||||
|
||||
document.addEventListener("__castMessageResponse", ev => {
|
||||
browser.runtime.sendMessage(ev.detail);
|
||||
})
|
||||
|
||||
browser.runtime.onMessage.addListener(message => {
|
||||
const event = new CustomEvent("__castMessage", {
|
||||
detail: JSON.stringify(message)
|
||||
});
|
||||
document.dispatchEvent(event);
|
||||
const backgroundPort = browser.runtime.connect({
|
||||
name: "shim"
|
||||
});
|
||||
|
||||
backgroundPort.onMessage.addListener(message => {
|
||||
const event = new CustomEvent("__castMessage", {
|
||||
detail: JSON.stringify(message)
|
||||
});
|
||||
document.dispatchEvent(event);
|
||||
});
|
||||
|
||||
let popupPort;
|
||||
browser.runtime.onConnect.addListener(port => {
|
||||
if (port.name === "popup") {
|
||||
popupPort = port;
|
||||
}
|
||||
|
||||
port.onMessage.addListener(message => {
|
||||
const event = new CustomEvent("__castMessage", {
|
||||
detail: JSON.stringify(message)
|
||||
});
|
||||
document.dispatchEvent(event);
|
||||
})
|
||||
});
|
||||
|
||||
document.addEventListener("__castMessageResponse", ev => {
|
||||
if (ev.detail.destination === "popup") {
|
||||
if (popupPort) {
|
||||
popupPort.postMessage(ev.detail);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
backgroundPort.postMessage(ev.detail);
|
||||
});
|
||||
|
||||
220
ext/src/main.js
220
ext/src/main.js
@@ -319,60 +319,15 @@ browser.menus.onClicked.addListener(async (info, tab) => {
|
||||
});
|
||||
|
||||
|
||||
const bridgeMap = new Map();
|
||||
|
||||
/**
|
||||
* Initializes native application and handles message
|
||||
* forwarding.
|
||||
*/
|
||||
function initBridge (tabId, frameId) {
|
||||
const existingPort = bridgeMap.get(tabId);
|
||||
|
||||
if (existingPort) {
|
||||
existingPort.disconnect();
|
||||
bridgeMap.delete(tabId);
|
||||
}
|
||||
|
||||
const port = browser.runtime.connectNative(APPLICATION_NAME);
|
||||
|
||||
if (port.error) {
|
||||
console.error(`Failed connect to ${APPLICATION_NAME}:`, port.error.message);
|
||||
} else {
|
||||
bridgeMap.set(tabId, port);
|
||||
}
|
||||
|
||||
port.onDisconnect.addListener(p => {
|
||||
if (p.error) {
|
||||
console.error(`${APPLICATION_NAME} disconnected:`, p.error.message);
|
||||
} else {
|
||||
console.log(`${APPLICATION_NAME} disconnected`);
|
||||
}
|
||||
|
||||
bridgeMap.delete(tabId);
|
||||
});
|
||||
|
||||
port.onMessage.addListener(message => {
|
||||
// Forward shim: messages
|
||||
// TODO: Integrate into messageRouter
|
||||
if (message.subject.startsWith("shim:")) {
|
||||
browser.tabs.sendMessage(tabId, message, { frameId });
|
||||
} else {
|
||||
messageRouter.handleMessage(message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
let popupWinId;
|
||||
let popupOpenerTabId;
|
||||
let popupOpenerFrameId;
|
||||
let popupShimId;
|
||||
|
||||
/**
|
||||
* Creates popup window for cast destination selection.
|
||||
* Refocusing other browser windows causes the popup window
|
||||
* to close and returns an API error (TODO).
|
||||
*/
|
||||
async function openPopup (tabId, frameId) {
|
||||
async function openPopup (shimId) {
|
||||
const width = 350;
|
||||
const height = 200;
|
||||
|
||||
@@ -397,8 +352,7 @@ async function openPopup (tabId, frameId) {
|
||||
|
||||
// Store popup details for message forwarding
|
||||
popupWinId = popup.id;
|
||||
popupOpenerTabId = tabId;
|
||||
popupOpenerFrameId = frameId;
|
||||
popupShimId = shimId;
|
||||
|
||||
// Size/position not set correctly on creation (bug?)
|
||||
await browser.windows.update(popup.id, {
|
||||
@@ -422,80 +376,138 @@ async function openPopup (tabId, frameId) {
|
||||
browser.windows.onRemoved.addListener(id => {
|
||||
if (id === popupWinId) {
|
||||
messageRouter.handleMessage({
|
||||
subject: "shim:popupClosed"
|
||||
subject: "popupClosed"
|
||||
});
|
||||
|
||||
popupWinId = null;
|
||||
popupOpenerTabId = null;
|
||||
|
||||
popupShimId = null;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Extension scripts make a connection to the background script
|
||||
* with a destination name to be registered as message route.
|
||||
*/
|
||||
browser.runtime.onConnect.addListener(port => {
|
||||
messageRouter.register(port.name, message => {
|
||||
const shimMap = new Map();
|
||||
|
||||
browser.runtime.onMessage.addListener(message => {
|
||||
if (message.subject === "getPopupShimInfo") {
|
||||
return new Promise(resolve => {
|
||||
const { tabId, frameId } = shimMap.get(popupShimId);
|
||||
|
||||
resolve({
|
||||
tabId
|
||||
, frameId
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
async function onConnectShim (port) {
|
||||
const bridgeInfo = await getBridgeInfo();
|
||||
if (bridgeInfo && !bridgeInfo.isVersionCompatible) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const tabId = port.sender.tab.id;
|
||||
const frameId = port.sender.frameId;
|
||||
const shimId = `${tabId}:${frameId}`;
|
||||
|
||||
// Disconnect existing shim
|
||||
if (shimMap.has(shimId)) {
|
||||
shimMap.get(shimId).port.disconnect();
|
||||
shimMap.delete(shimId);
|
||||
}
|
||||
|
||||
// Spawn bridge app instance
|
||||
const bridgePort = browser.runtime.connectNative(APPLICATION_NAME);
|
||||
|
||||
if (bridgePort.error) {
|
||||
console.error(`Failed connect to ${APPLICATION_NAME}:`
|
||||
, bridgePort.error.message);
|
||||
}
|
||||
|
||||
shimMap.set(shimId, {
|
||||
port
|
||||
, bridgePort
|
||||
, tabId
|
||||
, frameId
|
||||
});
|
||||
|
||||
bridgePort.onDisconnect.addListener(() => {
|
||||
if (bridgePort.error) {
|
||||
console.error(`${APPLICATION_NAME} disconnected:`
|
||||
, bridgePort.error.message);
|
||||
} else {
|
||||
console.log(`${APPLICATION_NAME} disconnected`);
|
||||
}
|
||||
});
|
||||
|
||||
// Handle disconnect
|
||||
port.onDisconnect.addListener(() => {
|
||||
bridgePort.disconnect();
|
||||
shimMap.delete(shimId);
|
||||
});
|
||||
|
||||
|
||||
bridgePort.onMessage.addListener(message => {
|
||||
port.postMessage(message);
|
||||
});
|
||||
port.onMessage.addListener(message => {
|
||||
messageRouter.handleMessage(message);
|
||||
})
|
||||
});
|
||||
|
||||
messageRouter.register("main", async (message, sender) => {
|
||||
const tabId = sender && sender.tab.id;
|
||||
port.onMessage.addListener(async message => {
|
||||
if (message.subject.startsWith("bridge")) {
|
||||
bridgePort.postMessage(message);
|
||||
}
|
||||
|
||||
switch (message.subject) {
|
||||
case "main:initialize": {
|
||||
const bridgeInfo = await getBridgeInfo();
|
||||
if (bridgeInfo && bridgeInfo.isVersionCompatible) {
|
||||
initBridge(tabId, sender.frameId);
|
||||
}
|
||||
switch (message.subject) {
|
||||
case "openPopup": {
|
||||
/**
|
||||
* If popup already open, reassign to new shim,
|
||||
* otherwise create a new popup.
|
||||
*/
|
||||
if (popupWinId) {
|
||||
/**
|
||||
* Notify shim that existing popup has closed and
|
||||
* to re-populate receiver list for new popup.
|
||||
*/
|
||||
port.postMessage({ subject: "popupClosed" });
|
||||
port.postMessage({ subject: "popupReady" });
|
||||
} else {
|
||||
await openPopup(shimId);
|
||||
}
|
||||
|
||||
browser.tabs.sendMessage(sender.tab.id, {
|
||||
subject: "shim:initialized"
|
||||
, data: bridgeInfo
|
||||
}, { frameId: sender.frameId });
|
||||
break;
|
||||
};
|
||||
|
||||
break;
|
||||
};
|
||||
|
||||
case "main:openPopup": {
|
||||
// If popup already open, reassign opener tab to new shim
|
||||
if (popupWinId) {
|
||||
|
||||
// Notify shim that existing popup is gone
|
||||
messageRouter.handleMessage({
|
||||
subject: "shim:popupClosed"
|
||||
case "discover": {
|
||||
bridgePort.postMessage({
|
||||
subject: "bridge:discover"
|
||||
});
|
||||
|
||||
popupOpenerTabId = tabId;
|
||||
popupOpenerFrameId = sender.frameId;
|
||||
break;
|
||||
};
|
||||
|
||||
// Notify shim to re-populate receiver list
|
||||
messageRouter.handleMessage({
|
||||
subject: "shim:popupReady"
|
||||
});
|
||||
} else {
|
||||
await openPopup(tabId, sender.frameId);
|
||||
default: {
|
||||
// TODO: Remove need for this
|
||||
messageRouter.handleMessage(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
port.postMessage({
|
||||
subject: "shimInitialized"
|
||||
, data: bridgeInfo
|
||||
});
|
||||
}
|
||||
|
||||
browser.runtime.onConnect.addListener(port => {
|
||||
switch (port.name) {
|
||||
case "shim": {
|
||||
onConnectShim(port);
|
||||
break;
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
messageRouter.register("bridge", (message, sender) => {
|
||||
console.log(message);
|
||||
bridgeMap.get(sender.tab.id).postMessage(message);
|
||||
});
|
||||
|
||||
messageRouter.register("shim", (message, sender) => {
|
||||
browser.tabs.sendMessage(popupOpenerTabId, message
|
||||
, { frameId: popupOpenerFrameId })
|
||||
});
|
||||
|
||||
messageRouter.register("mirrorCast", message => {
|
||||
browser.tabs.sendMessage(mirrorCastTabId, message
|
||||
@@ -507,8 +519,12 @@ messageRouter.register("mediaCast", message => {
|
||||
});
|
||||
|
||||
|
||||
// Forward messages into messageRouter
|
||||
browser.runtime.onMessage.addListener((message, sender) => {
|
||||
messageRouter.handleMessage(message, sender);
|
||||
messageRouter.handleMessage(message, {
|
||||
tabId: sender.tab.id
|
||||
, frameId: sender.frameId
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@ function deregister (routeName) {
|
||||
routeMap.delete(routeName);
|
||||
}
|
||||
|
||||
function handleMessage (message, sender) {
|
||||
function handleMessage (message, details) {
|
||||
const destination = message.subject.split(":")[0];
|
||||
if (routeMap.has(destination)) {
|
||||
routeMap.get(destination)(message, sender);
|
||||
routeMap.get(destination)(message, details);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,18 +42,23 @@ class App extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
this.port = browser.runtime.connect({
|
||||
async componentDidMount () {
|
||||
const { tabId, frameId } = await browser.runtime.sendMessage({
|
||||
subject: "getPopupShimInfo"
|
||||
});
|
||||
|
||||
this.port = browser.tabs.connect(tabId, {
|
||||
name: "popup"
|
||||
, frameId
|
||||
});
|
||||
|
||||
this.port.postMessage({
|
||||
subject: "shim:popupReady"
|
||||
subject: "popupReady"
|
||||
});
|
||||
|
||||
this.port.onMessage.addListener(message => {
|
||||
switch (message.subject) {
|
||||
case "popup:populate": {
|
||||
case "populateReceiverList": {
|
||||
this.setState({
|
||||
receivers: message.data.receivers
|
||||
, selectedMedia: message.data.selectedMedia
|
||||
@@ -70,8 +75,9 @@ class App extends Component {
|
||||
break;
|
||||
}
|
||||
|
||||
case "popup:close": {
|
||||
case "close": {
|
||||
window.close();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -84,7 +90,7 @@ class App extends Component {
|
||||
});
|
||||
|
||||
this.port.postMessage({
|
||||
subject: "shim:selectReceiver"
|
||||
subject: "selectReceiver"
|
||||
, data: {
|
||||
receiver
|
||||
, selectedMedia: this.state.selectedMedia
|
||||
|
||||
@@ -44,7 +44,7 @@ export default class Session {
|
||||
this.status = SessionStatus.CONNECTED;
|
||||
this.statusText = null;
|
||||
|
||||
if (receiver) {
|
||||
if (receiver) {
|
||||
this._sendMessage("bridge:bridgesession/initialize", {
|
||||
address: receiver._address
|
||||
, port: receiver._port
|
||||
|
||||
@@ -91,7 +91,7 @@ cast.initialize = (
|
||||
state.apiConfig = apiConfig;
|
||||
|
||||
sendMessage({
|
||||
subject: "bridge:discover"
|
||||
subject: "discover"
|
||||
});
|
||||
|
||||
apiConfig.receiverListener(state.receiverList.length
|
||||
@@ -146,7 +146,7 @@ cast.requestSession = (
|
||||
|
||||
// Open destination chooser
|
||||
sendMessage({
|
||||
subject: "main:openPopup"
|
||||
subject: "openPopup"
|
||||
});
|
||||
};
|
||||
|
||||
@@ -175,11 +175,9 @@ onMessage(message => {
|
||||
* Cast destination found (serviceUp). Set the API availability
|
||||
* property and call the page event function (__onGCastApiAvailable).
|
||||
*/
|
||||
case "shim:serviceUp": {
|
||||
case "serviceUp": {
|
||||
const receiver = message.data;
|
||||
|
||||
console.log(receiver);
|
||||
|
||||
if (state.receiverList.find(r => r.id === receiver.id)) {
|
||||
break;
|
||||
}
|
||||
@@ -196,7 +194,7 @@ onMessage(message => {
|
||||
* Cast destination lost (serviceDown). Remove from the receiver list
|
||||
* and update availability state.
|
||||
*/
|
||||
case "shim:serviceDown": {
|
||||
case "serviceDown": {
|
||||
state.receiverList = state.receiverList.filter(
|
||||
receiver => receiver.id !== message.data.id);
|
||||
|
||||
@@ -208,7 +206,7 @@ onMessage(message => {
|
||||
break;
|
||||
};
|
||||
|
||||
case "shim:selectReceiver": {
|
||||
case "selectReceiver": {
|
||||
console.info("Caster (Debug): Selected receiver");
|
||||
|
||||
const selectedReceiver = new Receiver(
|
||||
@@ -226,7 +224,8 @@ onMessage(message => {
|
||||
, selectedReceiver // receiver
|
||||
, (session) => {
|
||||
sendMessage({
|
||||
subject: "popup:close"
|
||||
subject: "close"
|
||||
, destination: "popup"
|
||||
});
|
||||
|
||||
state.apiConfig.sessionListener(session);
|
||||
@@ -258,9 +257,10 @@ onMessage(message => {
|
||||
* Popup is ready to receive data to populate the cast destination
|
||||
* chooser.
|
||||
*/
|
||||
case "shim:popupReady": {
|
||||
case "popupReady": {
|
||||
sendMessage({
|
||||
subject: "popup:populate"
|
||||
subject: "populateReceiverList"
|
||||
, destination: "popup"
|
||||
, data: {
|
||||
receivers: state.receiverList
|
||||
, selectedMedia: state.apiConfig._selectedMedia
|
||||
@@ -273,7 +273,7 @@ onMessage(message => {
|
||||
/**
|
||||
* Popup closed before session established.
|
||||
*/
|
||||
case "shim:popupClosed": {
|
||||
case "popupClosed": {
|
||||
if (state.sessionRequestInProgress) {
|
||||
state.sessionRequestInProgress = false;
|
||||
sessionErrorCallback(new Error_(ErrorCode.CANCEL));
|
||||
|
||||
@@ -16,7 +16,7 @@ window.chrome.cast.media = media;
|
||||
|
||||
onMessage(message => {
|
||||
switch (message.subject) {
|
||||
case "shim:initialized": {
|
||||
case "shimInitialized": {
|
||||
const bridgeInfo = message.data;
|
||||
|
||||
// Call page's API loaded function if defined
|
||||
@@ -28,8 +28,3 @@ onMessage(message => {
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// Trigger bridge mDNS discovery
|
||||
sendMessage({
|
||||
subject: "main:initialize"
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user