Reworked the BrowserIPC module
parent
a1e1df6a2d
commit
b9310b3fec
|
@ -13,7 +13,7 @@ loader.register_task(Stage.JAVASCRIPT_INITIALIZING, {
|
|||
priority: 10,
|
||||
function: async () => {
|
||||
await i18n.initialize();
|
||||
ipc.setup();
|
||||
ipc.setupIpcHandler();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -352,7 +352,7 @@ class LocalAvatarManagerFactory extends AbstractAvatarManagerFactory {
|
|||
constructor() {
|
||||
super();
|
||||
|
||||
this.ipcChannel = ipc.getIpcInstance().createChannel(undefined, kIPCAvatarChannel);
|
||||
this.ipcChannel = ipc.getIpcInstance().createChannel(kIPCAvatarChannel);
|
||||
this.ipcChannel.messageHandler = this.handleIpcMessage.bind(this);
|
||||
|
||||
server_connections.events().on("notify_handler_created", event => this.handleHandlerCreated(event.handler));
|
||||
|
|
|
@ -68,7 +68,7 @@ class IconManager extends AbstractIconManager {
|
|||
constructor() {
|
||||
super();
|
||||
|
||||
this.ipcChannel = ipc.getIpcInstance().createChannel(undefined, kIPCIconChannel);
|
||||
this.ipcChannel = ipc.getIpcInstance().createChannel(kIPCIconChannel);
|
||||
this.ipcChannel.messageHandler = this.handleIpcMessage.bind(this);
|
||||
|
||||
server_connections.events().on("notify_handler_created", event => {
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
kIPCAvatarChannel,
|
||||
setGlobalAvatarManagerFactory, uniqueId2AvatarId
|
||||
} from "../file/Avatars";
|
||||
import {IPCChannel} from "../ipc/BrowserIPC";
|
||||
import {getIpcInstance, IPCChannel} from "../ipc/BrowserIPC";
|
||||
import {AppParameters} from "../settings";
|
||||
import {ChannelMessage} from "../ipc/BrowserIPC";
|
||||
import {guid} from "../crypto/uid";
|
||||
|
@ -159,7 +159,7 @@ class RemoteAvatarManagerFactory extends AbstractAvatarManagerFactory {
|
|||
constructor() {
|
||||
super();
|
||||
|
||||
this.ipcChannel = ipc.getIpcInstance().createChannel(AppParameters.getValue(AppParameters.KEY_IPC_REMOTE_ADDRESS, "invalid"), kIPCAvatarChannel);
|
||||
this.ipcChannel = ipc.getIpcInstance().createCoreControlChannel(kIPCAvatarChannel);
|
||||
this.ipcChannel.messageHandler = this.handleIpcMessage.bind(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ import * as loader from "tc-loader";
|
|||
import {Stage} from "tc-loader";
|
||||
import {ChannelMessage, IPCChannel} from "tc-shared/ipc/BrowserIPC";
|
||||
import * as ipc from "tc-shared/ipc/BrowserIPC";
|
||||
import {AppParameters} from "tc-shared/settings";
|
||||
import {LogCategory, logWarn} from "tc-shared/log";
|
||||
|
||||
class RemoteRemoteIcon extends RemoteIcon {
|
||||
|
@ -33,7 +32,7 @@ class RemoteIconManager extends AbstractIconManager {
|
|||
constructor() {
|
||||
super();
|
||||
|
||||
this.ipcChannel = ipc.getIpcInstance().createChannel(AppParameters.getValue(AppParameters.KEY_IPC_REMOTE_ADDRESS, "invalid"), kIPCIconChannel);
|
||||
this.ipcChannel = ipc.getIpcInstance().createCoreControlChannel(kIPCIconChannel);
|
||||
this.ipcChannel.messageHandler = this.handleIpcMessage.bind(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,150 +1,131 @@
|
|||
import "broadcastchannel-polyfill";
|
||||
import {LogCategory, logDebug, logError, logWarn} from "../log";
|
||||
import {LogCategory, logDebug, logError, logTrace, logWarn} from "../log";
|
||||
import {ConnectHandler} from "../ipc/ConnectHandler";
|
||||
import {tr} from "tc-shared/i18n/localize";
|
||||
import {guid} from "tc-shared/crypto/uid";
|
||||
import {AppParameters} from "tc-shared/settings";
|
||||
|
||||
export interface BroadcastMessage {
|
||||
timestamp: number;
|
||||
receiver: string;
|
||||
sender: string;
|
||||
interface IpcRawMessage {
|
||||
timestampSend: number,
|
||||
|
||||
type: string;
|
||||
data: any;
|
||||
}
|
||||
sourcePeerId: string,
|
||||
targetPeerId: string,
|
||||
|
||||
function uuidv4() {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||
const r = Math.random() * 16 | 0;
|
||||
const v = c == 'x' ? r : (r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
targetChannelId: string,
|
||||
|
||||
interface ProcessQuery {
|
||||
timestamp: number
|
||||
query_id: string;
|
||||
message: ChannelMessage
|
||||
}
|
||||
|
||||
export interface ChannelMessage {
|
||||
channel_id: string;
|
||||
type: string;
|
||||
data: any;
|
||||
type: string,
|
||||
data: any
|
||||
}
|
||||
|
||||
export interface ProcessQueryResponse {
|
||||
request_timestamp: number
|
||||
request_query_id: string;
|
||||
|
||||
device_id: string;
|
||||
protocol: number;
|
||||
}
|
||||
|
||||
export interface CertificateAcceptCallback {
|
||||
request_id: string;
|
||||
}
|
||||
export interface CertificateAcceptSucceeded { }
|
||||
|
||||
export abstract class BasicIPCHandler {
|
||||
protected static readonly BROADCAST_UNIQUE_ID = "00000000-0000-4000-0000-000000000000";
|
||||
protected static readonly PROTOCOL_VERSION = 1;
|
||||
|
||||
protected readonly applicationChannelId: string;
|
||||
protected readonly localPeerId: string;
|
||||
|
||||
protected registeredChannels: IPCChannel[] = [];
|
||||
protected localUniqueId: string;
|
||||
|
||||
protected constructor() { }
|
||||
|
||||
setup() {
|
||||
this.localUniqueId = uuidv4();
|
||||
protected constructor(applicationChannelId: string) {
|
||||
this.applicationChannelId = applicationChannelId;
|
||||
this.localPeerId = guid();
|
||||
}
|
||||
|
||||
getLocalAddress() : string { return this.localUniqueId; }
|
||||
setup() { }
|
||||
|
||||
abstract sendMessage(type: string, data: any, target?: string);
|
||||
getApplicationChannelId() : string { return this.applicationChannelId; }
|
||||
|
||||
protected handleMessage(message: BroadcastMessage) {
|
||||
//log.trace(LogCategory.IPC, tr("Received message %o"), message);
|
||||
getLocalPeerId() : string { return this.localPeerId; }
|
||||
|
||||
if(message.receiver === BasicIPCHandler.BROADCAST_UNIQUE_ID) {
|
||||
if(message.type == "process-query") {
|
||||
logDebug(LogCategory.IPC, tr("Received a device query from %s."), message.sender);
|
||||
this.sendMessage("process-query-response", {
|
||||
request_query_id: (<ProcessQuery>message.data).query_id,
|
||||
request_timestamp: (<ProcessQuery>message.data).timestamp,
|
||||
abstract sendMessage(message: IpcRawMessage);
|
||||
|
||||
device_id: this.localUniqueId,
|
||||
protocol: BasicIPCHandler.PROTOCOL_VERSION
|
||||
} as ProcessQueryResponse, message.sender);
|
||||
return;
|
||||
}
|
||||
} else if(message.receiver === this.localUniqueId) {
|
||||
if(message.type == "process-query-response") {
|
||||
const response: ProcessQueryResponse = message.data;
|
||||
if(this._query_results[response.request_query_id])
|
||||
this._query_results[response.request_query_id].push(response);
|
||||
else {
|
||||
logWarn(LogCategory.IPC, tr("Received a query response for an unknown request."));
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if(message.type == "certificate-accept-callback") {
|
||||
const data: CertificateAcceptCallback = message.data;
|
||||
if(!this._cert_accept_callbacks[data.request_id]) {
|
||||
logWarn(LogCategory.IPC, tr("Received certificate accept callback for an unknown request ID."));
|
||||
return;
|
||||
}
|
||||
this._cert_accept_callbacks[data.request_id]();
|
||||
delete this._cert_accept_callbacks[data.request_id];
|
||||
protected handleMessage(message: IpcRawMessage) {
|
||||
logTrace(LogCategory.IPC, tr("Received message %o"), message);
|
||||
|
||||
this.sendMessage("certificate-accept-succeeded", {
|
||||
|
||||
} as CertificateAcceptSucceeded, message.sender);
|
||||
return;
|
||||
}
|
||||
else if(message.type == "certificate-accept-succeeded") {
|
||||
if(!this._cert_accept_succeeded[message.sender]) {
|
||||
logWarn(LogCategory.IPC, tr("Received certificate accept succeeded, but haven't a callback."));
|
||||
return;
|
||||
}
|
||||
this._cert_accept_succeeded[message.sender]();
|
||||
return;
|
||||
}
|
||||
if(message.targetPeerId !== this.localPeerId && message.targetPeerId !== BasicIPCHandler.BROADCAST_UNIQUE_ID) {
|
||||
/* The message isn't for us */
|
||||
return;
|
||||
}
|
||||
if(message.type === "channel") {
|
||||
const data: ChannelMessage = message.data;
|
||||
|
||||
let channel_invoked = false;
|
||||
for(const channel of this.registeredChannels) {
|
||||
if(channel.channelId === data.channel_id && (typeof(channel.targetClientId) === "undefined" || channel.targetClientId === message.sender)) {
|
||||
if(channel.messageHandler)
|
||||
channel.messageHandler(message.sender, message.receiver === BasicIPCHandler.BROADCAST_UNIQUE_ID, data);
|
||||
channel_invoked = true;
|
||||
}
|
||||
let channelInvokeCount = 0;
|
||||
for(const channel of this.registeredChannels) {
|
||||
if(channel.channelId !== message.targetChannelId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!channel_invoked) {
|
||||
/* Seems like we're not the only web/teaclient instance */
|
||||
/* console.warn(tr("Received channel message for unknown channel (%s)"), data.channel_id); */
|
||||
if(typeof channel.targetPeerId === "string" && channel.targetPeerId !== message.sourcePeerId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(channel.messageHandler) {
|
||||
channel.messageHandler(message.sourcePeerId, message.targetPeerId === BasicIPCHandler.BROADCAST_UNIQUE_ID, message.message);
|
||||
}
|
||||
|
||||
channelInvokeCount++;
|
||||
}
|
||||
|
||||
if(!channelInvokeCount) {
|
||||
/* Seems like we're not the only web/teaclient instance */
|
||||
/* console.warn(tr("Received channel message for unknown channel (%s)"), data.channelId); */
|
||||
}
|
||||
}
|
||||
|
||||
createChannel(targetId?: string, channelId?: string) : IPCChannel {
|
||||
/**
|
||||
* @param channelId
|
||||
* @param remotePeerId The peer to receive messages from. If empty messages will be broadcasted
|
||||
*/
|
||||
createChannel(channelId: string, remotePeerId?: string) : IPCChannel {
|
||||
let channel: IPCChannel = {
|
||||
targetClientId: targetId,
|
||||
channelId: channelId || uuidv4(),
|
||||
channelId: channelId,
|
||||
targetPeerId: remotePeerId,
|
||||
messageHandler: undefined,
|
||||
sendMessage: (type: string, data: any, target?: string) => {
|
||||
if(typeof target !== "undefined") {
|
||||
if(typeof channel.targetClientId === "string" && target != channel.targetClientId) {
|
||||
sendMessage: (type: string, data: any, remotePeerId?: string) => {
|
||||
if(typeof remotePeerId !== "undefined") {
|
||||
if(typeof channel.targetPeerId === "string" && remotePeerId != channel.targetPeerId) {
|
||||
throw "target id does not match channel target";
|
||||
}
|
||||
}
|
||||
|
||||
this.sendMessage("channel", {
|
||||
type: type,
|
||||
data: data,
|
||||
channel_id: channel.channelId
|
||||
} as ChannelMessage, target || channel.targetClientId || BasicIPCHandler.BROADCAST_UNIQUE_ID);
|
||||
remotePeerId = remotePeerId || channel.targetPeerId || BasicIPCHandler.BROADCAST_UNIQUE_ID;
|
||||
this.sendMessage({
|
||||
timestampSend: Date.now(),
|
||||
|
||||
sourcePeerId: this.localPeerId,
|
||||
targetPeerId: remotePeerId,
|
||||
|
||||
targetChannelId: channelId,
|
||||
|
||||
message: {
|
||||
data,
|
||||
type,
|
||||
}
|
||||
});
|
||||
|
||||
if(remotePeerId === this.localPeerId || remotePeerId === BasicIPCHandler.BROADCAST_UNIQUE_ID) {
|
||||
for(const localChannel of this.registeredChannels) {
|
||||
if(localChannel.channelId !== channel.channelId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(typeof localChannel.targetPeerId === "string" && localChannel.targetPeerId !== this.localPeerId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(localChannel === channel) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(localChannel.messageHandler) {
|
||||
localChannel.messageHandler(this.localPeerId, remotePeerId === BasicIPCHandler.BROADCAST_UNIQUE_ID, {
|
||||
type: type,
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -152,77 +133,42 @@ export abstract class BasicIPCHandler {
|
|||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a channel which only communicates with the TeaSpeak - Core.
|
||||
* @param channelId
|
||||
*/
|
||||
createCoreControlChannel(channelId: string) : IPCChannel {
|
||||
return this.createChannel(channelId, AppParameters.getValue(AppParameters.KEY_IPC_CORE_PEER_ADDRESS, this.localPeerId));
|
||||
}
|
||||
|
||||
channels() : IPCChannel[] { return this.registeredChannels; }
|
||||
|
||||
deleteChannel(channel: IPCChannel) {
|
||||
this.registeredChannels = this.registeredChannels.filter(e => e !== channel);
|
||||
}
|
||||
|
||||
private _query_results: {[key: string]:ProcessQueryResponse[]} = {};
|
||||
async queryProcesses(timeout?: number) : Promise<ProcessQueryResponse[]> {
|
||||
const query_id = uuidv4();
|
||||
this._query_results[query_id] = [];
|
||||
|
||||
this.sendMessage("process-query", {
|
||||
query_id: query_id,
|
||||
timestamp: Date.now()
|
||||
} as ProcessQuery);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, timeout || 250));
|
||||
const result = this._query_results[query_id];
|
||||
delete this._query_results[query_id];
|
||||
return result;
|
||||
}
|
||||
|
||||
private _cert_accept_callbacks: {[key: string]:(() => any)} = {};
|
||||
register_certificate_accept_callback(callback: () => any) : string {
|
||||
const id = uuidv4();
|
||||
this._cert_accept_callbacks[id] = callback;
|
||||
return this.localUniqueId + ":" + id;
|
||||
}
|
||||
|
||||
private _cert_accept_succeeded: {[sender: string]:(() => any)} = {};
|
||||
post_certificate_accpected(id: string, timeout?: number) : Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const data = id.split(":");
|
||||
const timeout_id = setTimeout(() => {
|
||||
delete this._cert_accept_succeeded[data[0]];
|
||||
clearTimeout(timeout_id);
|
||||
reject("timeout");
|
||||
}, timeout || 250);
|
||||
this._cert_accept_succeeded[data[0]] = () => {
|
||||
delete this._cert_accept_succeeded[data[0]];
|
||||
clearTimeout(timeout_id);
|
||||
resolve();
|
||||
};
|
||||
this.sendMessage("certificate-accept-callback", {
|
||||
request_id: data[1]
|
||||
} as CertificateAcceptCallback, data[0]);
|
||||
})
|
||||
this.registeredChannels.remove(channel);
|
||||
}
|
||||
}
|
||||
|
||||
export interface IPCChannel {
|
||||
/** Channel id */
|
||||
readonly channelId: string;
|
||||
targetClientId?: string;
|
||||
/** Target peer id. If set only messages from that process will be processed */
|
||||
targetPeerId?: string;
|
||||
|
||||
messageHandler: (remoteId: string, broadcast: boolean, message: ChannelMessage) => void;
|
||||
sendMessage(type: string, message: any, target?: string);
|
||||
messageHandler: (sourcePeerId: string, broadcast: boolean, message: ChannelMessage) => void;
|
||||
sendMessage(type: string, data: any, remotePeerId?: string);
|
||||
}
|
||||
|
||||
class BroadcastChannelIPC extends BasicIPCHandler {
|
||||
private static readonly CHANNEL_NAME = "TeaSpeak-Web";
|
||||
|
||||
private channel: BroadcastChannel;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
constructor(applicationChannelId: string) {
|
||||
super(applicationChannelId);
|
||||
}
|
||||
|
||||
setup() {
|
||||
super.setup();
|
||||
|
||||
this.channel = new BroadcastChannel(BroadcastChannelIPC.CHANNEL_NAME);
|
||||
this.channel = new BroadcastChannel(this.applicationChannelId);
|
||||
this.channel.onmessage = this.onMessage.bind(this);
|
||||
this.channel.onmessageerror = this.onError.bind(this);
|
||||
}
|
||||
|
@ -233,7 +179,7 @@ class BroadcastChannelIPC extends BasicIPCHandler {
|
|||
return;
|
||||
}
|
||||
|
||||
let message: BroadcastMessage;
|
||||
let message: IpcRawMessage;
|
||||
try {
|
||||
message = JSON.parse(event.data);
|
||||
} catch(error) {
|
||||
|
@ -247,52 +193,31 @@ class BroadcastChannelIPC extends BasicIPCHandler {
|
|||
logWarn(LogCategory.IPC, tr("Received error: %o"), event);
|
||||
}
|
||||
|
||||
sendMessage(type: string, data: any, target?: string) {
|
||||
const message: BroadcastMessage = {} as any;
|
||||
|
||||
message.sender = this.localUniqueId;
|
||||
message.receiver = target ? target : BasicIPCHandler.BROADCAST_UNIQUE_ID;
|
||||
message.timestamp = Date.now();
|
||||
message.type = type;
|
||||
message.data = data;
|
||||
|
||||
if(message.receiver === this.localUniqueId) {
|
||||
this.handleMessage(message);
|
||||
} else {
|
||||
this.channel.postMessage(JSON.stringify(message));
|
||||
}
|
||||
sendMessage(message: IpcRawMessage) {
|
||||
this.channel.postMessage(JSON.stringify(message));
|
||||
}
|
||||
}
|
||||
|
||||
let handler: BasicIPCHandler;
|
||||
let connect_handler: ConnectHandler;
|
||||
let handlerInstance: BasicIPCHandler;
|
||||
let connectHandler: ConnectHandler;
|
||||
|
||||
export function setup() {
|
||||
if(!supported())
|
||||
return;
|
||||
export function setupIpcHandler() {
|
||||
if(handlerInstance) {
|
||||
throw "IPC handler already initialized";
|
||||
}
|
||||
|
||||
if(handler)
|
||||
throw "bipc already started";
|
||||
handlerInstance = new BroadcastChannelIPC(AppParameters.getValue(AppParameters.KEY_IPC_APP_ADDRESS, guid()));
|
||||
handlerInstance.setup();
|
||||
logDebug(LogCategory.IPC, tr("Application IPC started for %s. Local peer address: %s"), handlerInstance.getApplicationChannelId(), handlerInstance.getLocalPeerId());
|
||||
|
||||
handler = new BroadcastChannelIPC();
|
||||
handler.setup();
|
||||
|
||||
connect_handler = new ConnectHandler(handler);
|
||||
connect_handler.setup();
|
||||
connectHandler = new ConnectHandler(handlerInstance);
|
||||
connectHandler.setup();
|
||||
}
|
||||
|
||||
export function getIpcInstance() {
|
||||
return handler;
|
||||
return handlerInstance;
|
||||
}
|
||||
|
||||
export function getInstanceConnectHandler() {
|
||||
return connect_handler;
|
||||
}
|
||||
|
||||
export function supported() {
|
||||
/* we've a polyfill now */
|
||||
return true;
|
||||
|
||||
/* ios does not support this */
|
||||
return typeof(window.BroadcastChannel) !== "undefined";
|
||||
return connectHandler;
|
||||
}
|
|
@ -76,7 +76,7 @@ export class ConnectHandler {
|
|||
}
|
||||
|
||||
public setup() {
|
||||
this.ipc_channel = this.ipc_handler.createChannel(undefined, ConnectHandler.CHANNEL_NAME);
|
||||
this.ipc_channel = this.ipc_handler.createChannel(ConnectHandler.CHANNEL_NAME);
|
||||
this.ipc_channel.messageHandler = this.onMessage.bind(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,217 +0,0 @@
|
|||
import {LogCategory, logDebug, logInfo, logWarn} from "../log";
|
||||
import {BasicIPCHandler, ChannelMessage, IPCChannel} from "../ipc/BrowserIPC";
|
||||
import {guid} from "../crypto/uid";
|
||||
import {tr} from "tc-shared/i18n/localize";
|
||||
|
||||
export interface MethodProxyInvokeData {
|
||||
method_name: string;
|
||||
arguments: any[];
|
||||
promise_id: string;
|
||||
}
|
||||
export interface MethodProxyResultData {
|
||||
promise_id: string;
|
||||
result: any;
|
||||
success: boolean;
|
||||
}
|
||||
export interface MethodProxyCallback {
|
||||
promise: Promise<any>;
|
||||
promise_id: string;
|
||||
|
||||
resolve: (object: any) => any;
|
||||
reject: (object: any) => any;
|
||||
}
|
||||
|
||||
export type MethodProxyConnectParameters = {
|
||||
channel_id: string;
|
||||
client_id: string;
|
||||
}
|
||||
export abstract class MethodProxy {
|
||||
readonly ipc_handler: BasicIPCHandler;
|
||||
private _ipc_channel: IPCChannel;
|
||||
private _ipc_parameters: MethodProxyConnectParameters;
|
||||
|
||||
private readonly _local: boolean;
|
||||
private readonly _slave: boolean;
|
||||
|
||||
private _connected: boolean;
|
||||
private _proxied_methods: {[key: string]:() => Promise<any>} = {};
|
||||
private _proxied_callbacks: {[key: string]:MethodProxyCallback} = {};
|
||||
|
||||
protected constructor(ipc_handler: BasicIPCHandler, connect_params?: MethodProxyConnectParameters) {
|
||||
this.ipc_handler = ipc_handler;
|
||||
this._ipc_parameters = connect_params;
|
||||
this._connected = false;
|
||||
this._slave = typeof(connect_params) !== "undefined";
|
||||
this._local = typeof(connect_params) !== "undefined" && connect_params.channel_id === "local" && connect_params.client_id === "local";
|
||||
}
|
||||
|
||||
protected setup() {
|
||||
if(this._local) {
|
||||
this._connected = true;
|
||||
this.on_connected();
|
||||
} else {
|
||||
if(this._slave)
|
||||
this._ipc_channel = this.ipc_handler.createChannel(this._ipc_parameters.client_id, this._ipc_parameters.channel_id);
|
||||
else
|
||||
this._ipc_channel = this.ipc_handler.createChannel();
|
||||
|
||||
this._ipc_channel.messageHandler = this._handle_message.bind(this);
|
||||
if(this._slave)
|
||||
this._ipc_channel.sendMessage("initialize", {});
|
||||
}
|
||||
}
|
||||
|
||||
protected finalize() {
|
||||
if(!this._local) {
|
||||
if(this._connected)
|
||||
this._ipc_channel.sendMessage("finalize", {});
|
||||
|
||||
this.ipc_handler.deleteChannel(this._ipc_channel);
|
||||
this._ipc_channel = undefined;
|
||||
}
|
||||
for(const promise of Object.values(this._proxied_callbacks))
|
||||
promise.reject("disconnected");
|
||||
this._proxied_callbacks = {};
|
||||
|
||||
this._connected = false;
|
||||
this.on_disconnected();
|
||||
}
|
||||
|
||||
protected register_method<R>(method: (...args: any[]) => Promise<R> | string) {
|
||||
let method_name: string;
|
||||
if(typeof method === "function") {
|
||||
logDebug(LogCategory.IPC, tr("Registering method proxy for %s"), method.name);
|
||||
method_name = method.name;
|
||||
} else {
|
||||
logDebug(LogCategory.IPC, tr("Registering method proxy for %s"), method);
|
||||
method_name = method;
|
||||
}
|
||||
|
||||
if(!this[method_name])
|
||||
throw "method is missing in current object";
|
||||
|
||||
this._proxied_methods[method_name] = this[method_name];
|
||||
if(!this._local) {
|
||||
this[method_name] = (...args: any[]) => {
|
||||
if(!this._connected)
|
||||
return Promise.reject("not connected");
|
||||
|
||||
const proxy_callback = {
|
||||
promise_id: guid()
|
||||
} as MethodProxyCallback;
|
||||
this._proxied_callbacks[proxy_callback.promise_id] = proxy_callback;
|
||||
proxy_callback.promise = new Promise((resolve, reject) => {
|
||||
proxy_callback.resolve = resolve;
|
||||
proxy_callback.reject = reject;
|
||||
});
|
||||
|
||||
this._ipc_channel.sendMessage("invoke", {
|
||||
promise_id: proxy_callback.promise_id,
|
||||
arguments: [...args],
|
||||
method_name: method_name
|
||||
} as MethodProxyInvokeData);
|
||||
return proxy_callback.promise;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _handle_message(remote_id: string, boradcast: boolean, message: ChannelMessage) {
|
||||
if(message.type === "finalize") {
|
||||
this._handle_finalize();
|
||||
} else if(message.type === "initialize") {
|
||||
this._handle_remote_callback(remote_id);
|
||||
} else if(message.type === "invoke") {
|
||||
this._handle_invoke(message.data);
|
||||
} else if(message.type === "result") {
|
||||
this._handle_result(message.data);
|
||||
}
|
||||
}
|
||||
|
||||
private _handle_finalize() {
|
||||
this.on_disconnected();
|
||||
this.finalize();
|
||||
this._connected = false;
|
||||
}
|
||||
|
||||
private _handle_remote_callback(remote_id: string) {
|
||||
if(!this._ipc_channel.targetClientId) {
|
||||
if(this._slave)
|
||||
throw "initialize wrong state!";
|
||||
|
||||
this._ipc_channel.targetClientId = remote_id; /* now we're able to send messages */
|
||||
this.on_connected();
|
||||
this._ipc_channel.sendMessage("initialize", true);
|
||||
} else {
|
||||
if(!this._slave)
|
||||
throw "initialize wrong state!";
|
||||
|
||||
this.on_connected();
|
||||
}
|
||||
this._connected = true;
|
||||
}
|
||||
|
||||
private _send_result(promise_id: string, success: boolean, message: any) {
|
||||
this._ipc_channel.sendMessage("result", {
|
||||
promise_id: promise_id,
|
||||
result: message,
|
||||
success: success
|
||||
} as MethodProxyResultData);
|
||||
}
|
||||
|
||||
private _handle_invoke(data: MethodProxyInvokeData) {
|
||||
if(this._proxied_methods[data.method_name])
|
||||
throw "we could not invoke a local proxied method!";
|
||||
|
||||
if(!this[data.method_name]) {
|
||||
this._send_result(data.promise_id, false, "missing method");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
logInfo(LogCategory.IPC, tr("Invoking method %s with arguments: %o"), data.method_name, data.arguments);
|
||||
|
||||
const promise = this[data.method_name](...data.arguments);
|
||||
promise.then(result => {
|
||||
logInfo(LogCategory.IPC, tr("Result: %o"), result);
|
||||
this._send_result(data.promise_id, true, result);
|
||||
}).catch(error => {
|
||||
this._send_result(data.promise_id, false, error);
|
||||
});
|
||||
} catch(error) {
|
||||
this._send_result(data.promise_id, false, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private _handle_result(data: MethodProxyResultData) {
|
||||
if(!this._proxied_callbacks[data.promise_id]) {
|
||||
logWarn(LogCategory.IPC, tr("Received proxy method result for unknown promise"));
|
||||
return;
|
||||
}
|
||||
const callback = this._proxied_callbacks[data.promise_id];
|
||||
delete this._proxied_callbacks[data.promise_id];
|
||||
|
||||
if(data.success)
|
||||
callback.resolve(data.result);
|
||||
else
|
||||
callback.reject(data.result);
|
||||
}
|
||||
|
||||
generate_connect_parameters() : MethodProxyConnectParameters {
|
||||
if(this._slave)
|
||||
throw "only masters can generate connect parameters!";
|
||||
if(!this._ipc_channel)
|
||||
throw "please call setup() before";
|
||||
|
||||
return {
|
||||
channel_id: this._ipc_channel.channelId,
|
||||
client_id: this.ipc_handler.getLocalAddress()
|
||||
};
|
||||
}
|
||||
|
||||
is_slave() { return this._local || this._slave; } /* the popout modal */
|
||||
is_master() { return this._local || !this._slave; } /* the host (teaweb application) */
|
||||
|
||||
protected abstract on_connected();
|
||||
protected abstract on_disconnected();
|
||||
}
|
|
@ -64,7 +64,7 @@ async function initialize() {
|
|||
return;
|
||||
}
|
||||
|
||||
bipc.setup();
|
||||
bipc.setupIpcHandler();
|
||||
}
|
||||
|
||||
async function initializeApp() {
|
||||
|
|
|
@ -252,16 +252,22 @@ export namespace AppParameters {
|
|||
};
|
||||
|
||||
|
||||
export const KEY_IPC_REMOTE_ADDRESS: RegistryKey<string> = {
|
||||
export const KEY_IPC_APP_ADDRESS: RegistryKey<string> = {
|
||||
key: "ipc-address",
|
||||
valueType: "string",
|
||||
description: "Address of the apps IPC channel"
|
||||
};
|
||||
|
||||
export const KEY_IPC_REMOTE_POPOUT_CHANNEL: RegistryKey<string> = {
|
||||
key: "ipc-channel",
|
||||
export const KEY_IPC_CORE_PEER_ADDRESS: RegistryKey<string> = {
|
||||
key: "ipc-core-peer",
|
||||
valueType: "string",
|
||||
description: "The channel name of the popout channel communication id"
|
||||
description: "Peer address of the apps core",
|
||||
};
|
||||
|
||||
export const KEY_MODAL_IDENTITY_CODE: RegistryKey<string> = {
|
||||
key: "modal-identify",
|
||||
valueType: "string",
|
||||
description: "An authentication code used to register the new process as the modal"
|
||||
};
|
||||
|
||||
export const KEY_MODAL_TARGET: RegistryKey<string> = {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as loader from "tc-loader";
|
||||
import {ChannelMessage, getIpcInstance, IPCChannel} from "tc-shared/ipc/BrowserIPC";
|
||||
import {AppParameters, UrlParameterParser} from "tc-shared/settings";
|
||||
import {UrlParameterParser} from "tc-shared/settings";
|
||||
import {IpcInviteInfo} from "tc-shared/text/bbcode/InviteDefinitions";
|
||||
import {LogCategory, logError} from "tc-shared/log";
|
||||
import {clientServiceInvite, clientServices} from "tc-shared/clientservice";
|
||||
|
@ -10,7 +10,7 @@ let ipcChannel: IPCChannel;
|
|||
loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
|
||||
name: "Invite controller init",
|
||||
function: async () => {
|
||||
ipcChannel = getIpcInstance().createChannel(AppParameters.getValue(AppParameters.KEY_IPC_REMOTE_ADDRESS, undefined), "invite-info");
|
||||
ipcChannel = getIpcInstance().createChannel("invite-info");
|
||||
ipcChannel.messageHandler = handleIpcMessage;
|
||||
},
|
||||
priority: 10
|
||||
|
|
|
@ -208,7 +208,7 @@ let ipcChannel: IPCChannel;
|
|||
loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
|
||||
name: "Invite controller init",
|
||||
function: async () => {
|
||||
ipcChannel = getIpcInstance().createChannel(AppParameters.getValue(AppParameters.KEY_IPC_REMOTE_ADDRESS, undefined), "invite-info");
|
||||
ipcChannel = getIpcInstance().createCoreControlChannel("invite-info");
|
||||
ipcChannel.messageHandler = handleIpcMessage;
|
||||
},
|
||||
priority: 10
|
||||
|
|
|
@ -95,7 +95,7 @@ loader.register_task(Stage.JAVASCRIPT_INITIALIZING, {
|
|||
name: "entry tags",
|
||||
priority: 10,
|
||||
function: async () => {
|
||||
const channel = getIpcInstance().createChannel(undefined, kIpcChannel);
|
||||
const channel = getIpcInstance().createChannel(kIpcChannel);
|
||||
channel.messageHandler = (_remoteId, _broadcast, message) => handleIpcMessage(message.type, message.data);
|
||||
}
|
||||
});
|
|
@ -1,9 +1,10 @@
|
|||
import {LogCategory, logDebug, logTrace, logWarn} from "../../../log";
|
||||
import {LogCategory, logDebug, logTrace} from "../../../log";
|
||||
import * as ipc from "../../../ipc/BrowserIPC";
|
||||
import {ChannelMessage} from "../../../ipc/BrowserIPC";
|
||||
import {Registry} from "../../../events";
|
||||
import {Registry} from "tc-events";
|
||||
import {
|
||||
EventControllerBase,
|
||||
kPopoutIPCChannelId,
|
||||
Popout2ControllerMessages,
|
||||
PopoutIPCMessage
|
||||
} from "../../../ui/react-elements/external-modal/IPCMessage";
|
||||
|
@ -21,13 +22,13 @@ export abstract class AbstractExternalModalController extends EventControllerBas
|
|||
private callbackWindowInitialized: (error?: string) => void;
|
||||
|
||||
protected constructor(modalType: string, constructorArguments: any[]) {
|
||||
super();
|
||||
super(guid());
|
||||
this.modalType = modalType;
|
||||
this.constructorArguments = constructorArguments;
|
||||
|
||||
this.modalEvents = new Registry<ModalEvents>();
|
||||
|
||||
this.ipcChannel = ipc.getIpcInstance().createChannel(undefined, "modal-" + guid());
|
||||
this.ipcChannel = ipc.getIpcInstance().createChannel(kPopoutIPCChannelId);
|
||||
this.ipcChannel.messageHandler = this.handleIPCMessage.bind(this);
|
||||
|
||||
this.documentUnloadListener = () => this.destroy();
|
||||
|
@ -121,51 +122,46 @@ export abstract class AbstractExternalModalController extends EventControllerBas
|
|||
}
|
||||
|
||||
protected handleIPCMessage(remoteId: string, broadcast: boolean, message: ChannelMessage) {
|
||||
if(broadcast)
|
||||
if(!broadcast && remoteId !== this.ipcRemotePeerId) {
|
||||
logDebug(LogCategory.IPC, tr("Received direct IPC message for popout controller from unknown source: %s"), remoteId);
|
||||
return;
|
||||
|
||||
if(this.ipcRemoteId === undefined) {
|
||||
logDebug(LogCategory.IPC, tr("Remote window connected with id %s"), remoteId);
|
||||
this.ipcRemoteId = remoteId;
|
||||
} else if(this.ipcRemoteId !== remoteId) {
|
||||
this.ipcRemoteId = remoteId;
|
||||
}
|
||||
|
||||
super.handleIPCMessage(remoteId, broadcast, message);
|
||||
this.handleTypedIPCMessage(remoteId, broadcast, message.type as any, message.data);
|
||||
}
|
||||
|
||||
protected handleTypedIPCMessage<T extends Popout2ControllerMessages>(type: T, payload: PopoutIPCMessage[T]) {
|
||||
super.handleTypedIPCMessage(type, payload);
|
||||
protected handleTypedIPCMessage<T extends Popout2ControllerMessages>(remoteId: string, isBroadcast: boolean, type: T, payload: PopoutIPCMessage[T]) {
|
||||
super.handleTypedIPCMessage(remoteId, isBroadcast, type, payload);
|
||||
|
||||
switch (type) {
|
||||
case "hello-popout": {
|
||||
const tpayload = payload as PopoutIPCMessage["hello-popout"];
|
||||
logTrace(LogCategory.IPC, "Received Hello World from popup with version %s (expected %s).", tpayload.version, __build.version);
|
||||
if(tpayload.version !== __build.version) {
|
||||
this.sendIPCMessage("hello-controller", { accepted: false, message: tr("version miss match") });
|
||||
if(this.callbackWindowInitialized) {
|
||||
this.callbackWindowInitialized(tr("version miss match"));
|
||||
this.callbackWindowInitialized = undefined;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(this.callbackWindowInitialized) {
|
||||
this.callbackWindowInitialized();
|
||||
this.callbackWindowInitialized = undefined;
|
||||
}
|
||||
|
||||
this.sendIPCMessage("hello-controller", { accepted: true, constructorArguments: this.constructorArguments });
|
||||
break;
|
||||
if(type === "hello-popout") {
|
||||
const messageHello = payload as PopoutIPCMessage["hello-popout"];
|
||||
if(messageHello.authenticationCode !== this.ipcAuthenticationCode) {
|
||||
/* most likely not for us */
|
||||
return;
|
||||
}
|
||||
|
||||
case "invoke-modal-action":
|
||||
/* must be handled by the underlying handler */
|
||||
break;
|
||||
if(this.ipcRemotePeerId) {
|
||||
logTrace(LogCategory.IPC, tr("Modal popout slave changed from %s to %s. Side reload?"), this.ipcRemotePeerId, remoteId);
|
||||
/* TODO: Send a good by to the old modal */
|
||||
}
|
||||
this.ipcRemotePeerId = remoteId;
|
||||
|
||||
default:
|
||||
logWarn(LogCategory.IPC, "Received unknown message type from popup window: %s", type);
|
||||
logTrace(LogCategory.IPC, "Received Hello World from popup (peer id %s) with version %s (expected %s).", remoteId, messageHello.version, __build.version);
|
||||
if(messageHello.version !== __build.version) {
|
||||
this.sendIPCMessage("hello-controller", { accepted: false, message: tr("version miss match") });
|
||||
if(this.callbackWindowInitialized) {
|
||||
this.callbackWindowInitialized(tr("version miss match"));
|
||||
this.callbackWindowInitialized = undefined;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(this.callbackWindowInitialized) {
|
||||
this.callbackWindowInitialized();
|
||||
this.callbackWindowInitialized = undefined;
|
||||
}
|
||||
|
||||
this.sendIPCMessage("hello-controller", { accepted: true, constructorArguments: this.constructorArguments });
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
import {ChannelMessage, IPCChannel} from "../../../ipc/BrowserIPC";
|
||||
import {IPCChannel} from "../../../ipc/BrowserIPC";
|
||||
|
||||
export const kPopoutIPCChannelId = "popout-channel";
|
||||
|
||||
export interface PopoutIPCMessage {
|
||||
"hello-popout": { version: string },
|
||||
"hello-popout": { version: string, authenticationCode: string },
|
||||
"hello-controller": { accepted: boolean, message?: string, constructorArguments?: any[] },
|
||||
"invoke-modal-action": {
|
||||
action: "close" | "minimize"
|
||||
|
@ -22,28 +24,24 @@ export interface ReceivedIPCMessage {
|
|||
}
|
||||
|
||||
export abstract class EventControllerBase<Type extends "controller" | "popout"> {
|
||||
protected readonly ipcAuthenticationCode: string;
|
||||
protected ipcRemotePeerId: string;
|
||||
protected ipcChannel: IPCChannel;
|
||||
protected ipcRemoteId: string;
|
||||
|
||||
protected constructor() { }
|
||||
|
||||
protected handleIPCMessage(remoteId: string, broadcast: boolean, message: ChannelMessage) {
|
||||
if(this.ipcRemoteId !== remoteId) {
|
||||
console.warn("Received message from unknown end: %s. Expected: %s", remoteId, this.ipcRemoteId);
|
||||
return;
|
||||
}
|
||||
|
||||
this.handleTypedIPCMessage(message.type as any, message.data);
|
||||
protected constructor(ipcAuthenticationCode: string) {
|
||||
this.ipcAuthenticationCode = ipcAuthenticationCode;
|
||||
}
|
||||
|
||||
protected sendIPCMessage<T extends SendIPCMessage[Type]>(type: T, payload: PopoutIPCMessage[T]) {
|
||||
this.ipcChannel.sendMessage(type, payload, this.ipcRemoteId);
|
||||
this.ipcChannel.sendMessage(type, payload, this.ipcRemotePeerId);
|
||||
}
|
||||
|
||||
protected handleTypedIPCMessage<T extends ReceivedIPCMessage[Type]>(type: T, payload: PopoutIPCMessage[T]) {}
|
||||
protected handleTypedIPCMessage<T extends ReceivedIPCMessage[Type]>(remoteId: string, isBroadcast: boolean, type: T, payload: PopoutIPCMessage[T]) {
|
||||
|
||||
}
|
||||
|
||||
protected destroyIPC() {
|
||||
this.ipcChannel = undefined;
|
||||
this.ipcRemoteId = undefined;
|
||||
this.ipcRemotePeerId = undefined;
|
||||
}
|
||||
}
|
|
@ -2,8 +2,8 @@ import {getIpcInstance as getIPCInstance} from "../../../ipc/BrowserIPC";
|
|||
import {AppParameters} from "../../../settings";
|
||||
import {
|
||||
Controller2PopoutMessages,
|
||||
EventControllerBase,
|
||||
PopoutIPCMessage
|
||||
EventControllerBase, kPopoutIPCChannelId,
|
||||
PopoutIPCMessage,
|
||||
} from "../../../ui/react-elements/external-modal/IPCMessage";
|
||||
|
||||
let controller: PopoutController;
|
||||
|
@ -21,11 +21,12 @@ class PopoutController extends EventControllerBase<"popout"> {
|
|||
private callbackControllerHello: (accepted: boolean | string) => void;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.ipcRemoteId = AppParameters.getValue(AppParameters.KEY_IPC_REMOTE_ADDRESS, "invalid");
|
||||
super(AppParameters.getValue(AppParameters.KEY_MODAL_IDENTITY_CODE, "invalid"));
|
||||
|
||||
this.ipcChannel = getIPCInstance().createChannel(this.ipcRemoteId, AppParameters.getValue(AppParameters.KEY_IPC_REMOTE_POPOUT_CHANNEL, "invalid"));
|
||||
this.ipcChannel.messageHandler = this.handleIPCMessage.bind(this);
|
||||
this.ipcChannel = getIPCInstance().createChannel(kPopoutIPCChannelId);
|
||||
this.ipcChannel.messageHandler = (sourcePeerId, broadcast, message) => {
|
||||
this.handleTypedIPCMessage(sourcePeerId, broadcast, message.type as any, message.data);
|
||||
};
|
||||
}
|
||||
|
||||
getConstructorArguments() : any[] {
|
||||
|
@ -33,7 +34,7 @@ class PopoutController extends EventControllerBase<"popout"> {
|
|||
}
|
||||
|
||||
async initialize() {
|
||||
this.sendIPCMessage("hello-popout", { version: __build.version });
|
||||
this.sendIPCMessage("hello-popout", { version: __build.version, authenticationCode: this.ipcAuthenticationCode });
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
const timeout = setTimeout(() => {
|
||||
|
@ -55,13 +56,14 @@ class PopoutController extends EventControllerBase<"popout"> {
|
|||
});
|
||||
}
|
||||
|
||||
protected handleTypedIPCMessage<T extends Controller2PopoutMessages>(type: T, payload: PopoutIPCMessage[T]) {
|
||||
super.handleTypedIPCMessage(type, payload);
|
||||
protected handleTypedIPCMessage<T extends Controller2PopoutMessages>(remoteId: string, isBroadcast: boolean, type: T, payload: PopoutIPCMessage[T]) {
|
||||
super.handleTypedIPCMessage(remoteId, isBroadcast, type, payload);
|
||||
|
||||
switch (type) {
|
||||
case "hello-controller": {
|
||||
const tpayload = payload as PopoutIPCMessage["hello-controller"];
|
||||
console.log("Received Hello World from controller. Window instance accpected: %o", tpayload.accepted);
|
||||
this.ipcRemotePeerId = remoteId;
|
||||
console.log("Received Hello World from controller (peer id %s). Window instance accepted: %o", this.ipcRemotePeerId, tpayload.accepted);
|
||||
if(!this.callbackControllerHello) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ loader.register_task(Stage.JAVASCRIPT_INITIALIZING, {
|
|||
function: async () => {
|
||||
await import("tc-shared/proto");
|
||||
await i18n.initialize();
|
||||
ipc.setup();
|
||||
ipc.setupIpcHandler();
|
||||
|
||||
setupJSRender();
|
||||
}
|
||||
|
|
|
@ -84,7 +84,6 @@ loader.register_task(Stage.JAVASCRIPT_INITIALIZING, {
|
|||
name: "entry tags",
|
||||
priority: 10,
|
||||
function: async () => {
|
||||
const ipc = getIpcInstance();
|
||||
ipcChannel = ipc.createChannel(AppParameters.getValue(AppParameters.KEY_IPC_REMOTE_ADDRESS, ipc.getLocalAddress()), kIpcChannel);
|
||||
ipcChannel = getIpcInstance().createCoreControlChannel(kIpcChannel);
|
||||
}
|
||||
});
|
|
@ -1 +1 @@
|
|||
Subproject commit 336077435bbb09bb25f6efdcdac36956288fd3ca
|
||||
Subproject commit d1a1b51f61c0dce71ebd856208964581ba6fecc7
|
|
@ -6,6 +6,9 @@ import {LogCategory, logDebug, logWarn} from "tc-shared/log";
|
|||
import {Popout2ControllerMessages, PopoutIPCMessage} from "tc-shared/ui/react-elements/external-modal/IPCMessage";
|
||||
import {tr, tra} from "tc-shared/i18n/localize";
|
||||
import {ModalOptions} from "tc-shared/ui/react-elements/modal/Definitions";
|
||||
import {assertMainApplication} from "tc-shared/ui/utils";
|
||||
|
||||
assertMainApplication();
|
||||
|
||||
export class ExternalModalController extends AbstractExternalModalController {
|
||||
private readonly options: ModalOptions;
|
||||
|
@ -87,8 +90,9 @@ export class ExternalModalController extends AbstractExternalModalController {
|
|||
"loader-target": "manifest",
|
||||
"chunk": "modal-external",
|
||||
"modal-target": this.modalType,
|
||||
"ipc-channel": this.ipcChannel.channelId,
|
||||
"ipc-address": ipc.getIpcInstance().getLocalAddress(),
|
||||
"modal-identify": this.ipcAuthenticationCode,
|
||||
"ipc-address": ipc.getIpcInstance().getApplicationChannelId(),
|
||||
"ipc-core-peer": ipc.getIpcInstance().getLocalPeerId(),
|
||||
"disableGlobalContextMenu": __build.mode === "debug" ? 1 : 0,
|
||||
"loader-abort": __build.mode === "debug" ? 1 : 0,
|
||||
};
|
||||
|
@ -113,7 +117,7 @@ export class ExternalModalController extends AbstractExternalModalController {
|
|||
}
|
||||
|
||||
protected handleIPCMessage(remoteId: string, broadcast: boolean, message: ChannelMessage) {
|
||||
if(!broadcast && this.ipcRemoteId !== remoteId) {
|
||||
if(!broadcast && this.ipcRemotePeerId !== remoteId) {
|
||||
if(this.windowClosedTestInterval > 0) {
|
||||
clearInterval(this.windowClosedTestInterval);
|
||||
this.windowClosedTestInterval = 0;
|
||||
|
@ -127,8 +131,12 @@ export class ExternalModalController extends AbstractExternalModalController {
|
|||
super.handleIPCMessage(remoteId, broadcast, message);
|
||||
}
|
||||
|
||||
protected handleTypedIPCMessage<T extends Popout2ControllerMessages>(type: T, payload: PopoutIPCMessage[T]) {
|
||||
super.handleTypedIPCMessage(type, payload);
|
||||
protected handleTypedIPCMessage<T extends Popout2ControllerMessages>(remoteId: string, isBroadcast: boolean, type: T, payload: PopoutIPCMessage[T]) {
|
||||
super.handleTypedIPCMessage(remoteId, isBroadcast, type, payload);
|
||||
|
||||
if(isBroadcast) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case "invoke-modal-action":
|
||||
|
|
|
@ -26,7 +26,7 @@ class IPCContextMenu implements ContextMenuFactory {
|
|||
private closeCallback: () => void;
|
||||
|
||||
constructor() {
|
||||
this.ipcChannel = ipc.getIpcInstance().createChannel(undefined, kIPCContextMenuChannel);
|
||||
this.ipcChannel = ipc.getIpcInstance().createChannel(kIPCContextMenuChannel);
|
||||
this.ipcChannel.messageHandler = this.handleIpcMessage.bind(this);
|
||||
|
||||
/* if we're just created we're the focused window ;) */
|
||||
|
|
Loading…
Reference in New Issue