From 2a85238443eec07ff4ee19ac594ec9cbe427a617 Mon Sep 17 00:00:00 2001 From: Antoine Rollin <66251236+antoinerollindev@users.noreply.github.com> Date: Thu, 23 Jan 2025 20:00:19 +0100 Subject: [PATCH] SDA-4657: Patch for OpenFin (#2271) --- spec/mainApiHandler.spec.ts | 21 +++++++++++++--- spec/openfinHandler.spec.ts | 33 +++++++++++++++++++------ src/app/main-api-handler.ts | 27 +++++++++----------- src/app/openfin-handler.ts | 42 +++++++++++++++++++------------ src/common/api-interface.ts | 3 ++- src/renderer/preload-main.ts | 4 +-- src/renderer/ssf-api.ts | 48 +++++++++++++++++++++++++----------- 7 files changed, 117 insertions(+), 61 deletions(-) diff --git a/spec/mainApiHandler.spec.ts b/spec/mainApiHandler.spec.ts index 2423be67b..f141eba00 100644 --- a/spec/mainApiHandler.spec.ts +++ b/spec/mainApiHandler.spec.ts @@ -21,6 +21,7 @@ jest.mock('../src/app/openfin-handler', () => { connect: jest.fn(), fireIntent: jest.fn(), joinContextGroup: jest.fn(), + joinSessionContextGroup: jest.fn(), getContextGroups: jest.fn(), getConnectionStatus: jest.fn(), getInfo: jest.fn(), @@ -28,7 +29,7 @@ jest.mock('../src/app/openfin-handler', () => { registerIntentHandler: jest.fn(), unregisterIntentHandler: jest.fn(), fireIntentForContext: jest.fn(), - removeClientFromContextGroup: jest.fn(), + removeFromContextGroup: jest.fn(), }, }; }); @@ -726,10 +727,22 @@ describe('main api handler', () => { expect(spy).toHaveBeenCalledTimes(1); }); - it('should call `removeClientFromContextGroup`', () => { - const spy = jest.spyOn(openfinHandler, 'removeClientFromContextGroup'); + it('should call `removeFromContextGroup`', () => { + const spy = jest.spyOn(openfinHandler, 'removeFromContextGroup'); const value = { - cmd: apiCmds.openfinRemoveClientFromContextGroup, + cmd: apiCmds.openfinRemoveFromContextGroup, + }; + + ipcMain.send(apiName.symphonyApi, value); + + expect(spy).toHaveBeenCalledTimes(1); + }); + + it('should call `joinSessionContextGroup`', () => { + const spy = jest.spyOn(openfinHandler, 'joinSessionContextGroup'); + const value = { + cmd: apiCmds.openfinJoinSessionContextGroup, + contextGroupId: 'group-id', }; ipcMain.send(apiName.symphonyApi, value); diff --git a/spec/openfinHandler.spec.ts b/spec/openfinHandler.spec.ts index d7322657a..3e80cfee9 100644 --- a/spec/openfinHandler.spec.ts +++ b/spec/openfinHandler.spec.ts @@ -13,9 +13,10 @@ jest.mock('@openfin/node-adapter', () => ({ registerIntentHandler: jest.fn(), getAllClientsInContextGroup: jest.fn(), joinContextGroup: jest.fn(), + joinSessionContextGroup: jest.fn(), getContextGroups: jest.fn(), fireIntentForContext: jest.fn(), - removeClientFromContextGroup: jest.fn(), + removeFromContextGroup: jest.fn(), }), }, }); @@ -185,6 +186,19 @@ describe('Openfin', () => { expect(joinContextGroupSpy).toHaveBeenCalledTimes(1); }); + it('should join a session context group', async () => { + const connectSyncMock = await connectMock.Interop.connectSync(); + const joinSessionContextGroupSpy = jest.spyOn( + connectSyncMock, + 'joinSessionContextGroup', + ); + + await openfinHandler.connect(); + await openfinHandler.joinSessionContextGroup('contextGroupId'); + + expect(joinSessionContextGroupSpy).toHaveBeenCalledTimes(1); + }); + it('should return all context groups', async () => { const connectSyncMock = await connectMock.Interop.connectSync(); const getContextGroupsSpy = jest.spyOn(connectSyncMock, 'getContextGroups'); @@ -210,7 +224,10 @@ describe('Openfin', () => { it('should fire an intent for a given context', async () => { const connectSyncMock = await connectMock.Interop.connectSync(); - const fireIntentSpy = jest.spyOn(connectSyncMock, 'fireIntentForContext'); + const fireIntentForContextSpy = jest.spyOn( + connectSyncMock, + 'fireIntentForContext', + ); await openfinHandler.connect(); const context = { @@ -222,18 +239,18 @@ describe('Openfin', () => { }; await openfinHandler.fireIntentForContext(context); - expect(fireIntentSpy).toHaveBeenCalledTimes(1); + expect(fireIntentForContextSpy).toHaveBeenCalledTimes(1); }); - it('should remove client from context group', async () => { + it('should remove from context group', async () => { const connectSyncMock = await connectMock.Interop.connectSync(); - const fireIntentSpy = jest.spyOn( + const removeFromContextGroupSpy = jest.spyOn( connectSyncMock, - 'removeClientFromContextGroup', + 'removeFromContextGroup', ); - await openfinHandler.removeClientFromContextGroup(); + await openfinHandler.removeFromContextGroup(); - expect(fireIntentSpy).toHaveBeenCalledTimes(1); + expect(removeFromContextGroupSpy).toHaveBeenCalledTimes(1); }); }); diff --git a/src/app/main-api-handler.ts b/src/app/main-api-handler.ts index 55d433722..5630bc79e 100644 --- a/src/app/main-api-handler.ts +++ b/src/app/main-api-handler.ts @@ -560,21 +560,6 @@ ipcMain.on( helpMenu.setValue(helpCenter); break; - case apiCmds.openfinFireIntent: - openfinHandler.fireIntent(arg.intent); - break; - case apiCmds.openfinJoinContextGroup: - openfinHandler.joinContextGroup(arg.contextGroupId, arg.target); - break; - case apiCmds.openfinUnregisterIntentHandler: - openfinHandler.unregisterIntentHandler(arg.intentName); - break; - case apiCmds.openfinFireIntentForContext: - openfinHandler.fireIntentForContext(arg.context); - break; - case apiCmds.openfinRemoveClientFromContextGroup: - openfinHandler.removeClientFromContextGroup(); - break; default: break; } @@ -657,6 +642,18 @@ ipcMain.handle( return openfinHandler.getAllClientsInContextGroup(arg.contextGroupId); case apiCmds.openfinGetClientInfo: return openfinHandler.getClientInfo(); + case apiCmds.openfinFireIntent: + return openfinHandler.fireIntent(arg.intent); + case apiCmds.openfinJoinContextGroup: + return openfinHandler.joinContextGroup(arg.contextGroupId, arg.target); + case apiCmds.openfinJoinSessionContextGroup: + return openfinHandler.joinSessionContextGroup(arg.contextGroupId); + case apiCmds.openfinUnregisterIntentHandler: + return openfinHandler.unregisterIntentHandler(arg.intentName); + case apiCmds.openfinFireIntentForContext: + return openfinHandler.fireIntentForContext(arg.context); + case apiCmds.openfinRemoveFromContextGroup: + return openfinHandler.removeFromContextGroup(); default: break; } diff --git a/src/app/openfin-handler.ts b/src/app/openfin-handler.ts index 60a8c0311..36c6348a0 100644 --- a/src/app/openfin-handler.ts +++ b/src/app/openfin-handler.ts @@ -1,20 +1,22 @@ +/// + import { connect } from '@openfin/node-adapter'; import { randomUUID, UUID } from 'crypto'; import { logger } from '../common/openfin-logger'; import { config, IConfig } from './config-handler'; import { windowHandler } from './window-handler'; -const OPENFIN_PROVIDER = 'Openfin'; +const OPENFIN_PROVIDER = 'OpenFin'; const TIMEOUT_THRESHOLD = 10000; export class OpenfinHandler { - private interopClient; + private interopClient: OpenFin.InteropClient | undefined; private intentHandlerSubscriptions: Map = new Map(); private isConnected: boolean = false; private fin: any; /** - * Connection to interop brocker + * Connection to interop broker */ public async connect() { const { openfin }: IConfig = config.getConfigFields(['openfin']); @@ -30,7 +32,8 @@ export class OpenfinHandler { const connectionTimeoutPromise = new Promise((_, reject) => setTimeout(() => { logger.error( - `openfin-handler: Connection timeout after ${timeoutValue / 1000 + `openfin-handler: Connection timeout after ${ + timeoutValue / 1000 } seconds`, ); return reject( @@ -61,7 +64,7 @@ export class OpenfinHandler { this.interopClient = this.fin.Interop.connectSync(openfin.channelName); this.isConnected = true; - this.interopClient.onDisconnection((event) => { + this.interopClient?.onDisconnection((event) => { const { brokerName } = event; logger.warn( `openfin-handler: Disconnected from Interop Broker ${brokerName}`, @@ -95,7 +98,7 @@ export class OpenfinHandler { * Sends an intent to the Interop Broker */ public fireIntent(intent) { - this.interopClient.fireIntent(intent); + return this.interopClient?.fireIntent(intent); } /** @@ -103,7 +106,7 @@ export class OpenfinHandler { */ public async registerIntentHandler(intentName: string): Promise { const unsubscriptionCallback = - await this.interopClient.registerIntentHandler( + await this.interopClient?.registerIntentHandler( this.intentHandler, intentName, ); @@ -125,21 +128,28 @@ export class OpenfinHandler { * Join all Interop Clients at the given identity to context group contextGroupId. If no target is specified, it adds the sender to the context group. */ public async joinContextGroup(contextGroupId: string, target?: any) { - await this.interopClient.joinContextGroup(contextGroupId, target); + return this.interopClient?.joinContextGroup(contextGroupId, target); + } + + /** + * Joins or create a context group that does not persist between runs and aren't present on snapshots. + */ + public async joinSessionContextGroup(contextGroupId: string) { + return this.interopClient?.joinSessionContextGroup(contextGroupId); } /** * Returns the Interop-Broker-defined context groups available for an entity to join. */ public async getContextGroups() { - return this.interopClient.getContextGroups(); + return this.interopClient?.getContextGroups(); } /** * Gets all clients for a context group. */ - public getAllClientsInContextGroup(contextGroupId: string) { - return this.interopClient.getAllClientsInContextGroup(contextGroupId); + public async getAllClientsInContextGroup(contextGroupId: string) { + return this.interopClient?.getAllClientsInContextGroup(contextGroupId); } /** @@ -178,7 +188,7 @@ export class OpenfinHandler { public getInfo() { return { provider: OPENFIN_PROVIDER, - fdc3Version: '', + fdc3Version: '2.0', optionalFeatures: { OriginatingAppMetadata: false, UserChannelMembershipAPIs: false, @@ -193,14 +203,14 @@ export class OpenfinHandler { * @param context */ public fireIntentForContext(context: any) { - this.interopClient.fireIntentForContext(context); + return this.interopClient?.fireIntentForContext(context); } /** - * Removes a client from current context group + * Leaves current context group */ - public removeClientFromContextGroup() { - this.interopClient.removeClientFromContextGroup(); + public removeFromContextGroup() { + return this.interopClient?.removeFromContextGroup(); } /** diff --git a/src/common/api-interface.ts b/src/common/api-interface.ts index 67e41f8a4..c36ee1377 100644 --- a/src/common/api-interface.ts +++ b/src/common/api-interface.ts @@ -91,10 +91,11 @@ export enum apiCmds { openfinGetConnectionStatus = 'openfin-get-connection-status', openfinGetInfo = 'openfin-get-info', openfinJoinContextGroup = 'openfin-join-context-group', + openfinJoinSessionContextGroup = 'openfin-join-session-context-group', openfinGetContextGroups = 'openfin-get-context-groups', openfinGetAllClientsInContextGroup = 'openfin-get-all-clients-in-context-group', openfinFireIntentForContext = 'openfin-fire-intent-for-context', - openfinRemoveClientFromContextGroup = 'openfin-remove-client-from-context-group', + openfinRemoveFromContextGroup = 'openfin-remove-from-context-group', openfinGetClientInfo = 'openfin-get-client-info', } diff --git a/src/renderer/preload-main.ts b/src/renderer/preload-main.ts index e1304c6e0..5cd3e1ce5 100644 --- a/src/renderer/preload-main.ts +++ b/src/renderer/preload-main.ts @@ -115,11 +115,11 @@ if (ssfWindow.ssf) { unregisterIntentHandler: ssfWindow.ssf.openfinUnregisterIntentHandler, getContextGroups: ssfWindow.ssf.openfinGetContextGroups, joinContextGroup: ssfWindow.ssf.openfinJoinContextGroup, + joinSessionContextGroup: ssfWindow.ssf.openfinJoinSessionContextGroup, getAllClientsInContextGroup: ssfWindow.ssf.openfinGetAllClientsInContextGroup, fireIntentForContext: ssfWindow.ssf.openfinFireIntentForContext, - removeClientFromContextGroup: - ssfWindow.ssf.openfinRemoveClientFromContextGroup, + removeFromContextGroup: ssfWindow.ssf.openfinRemoveFromContextGroup, getClientInfo: ssfWindow.ssf.openfinGetClientInfo, }); } diff --git a/src/renderer/ssf-api.ts b/src/renderer/ssf-api.ts index b85350be6..d7f5230d4 100644 --- a/src/renderer/ssf-api.ts +++ b/src/renderer/ssf-api.ts @@ -958,7 +958,7 @@ export class SSFApi { /** * Openfin Interop client initialization */ - public async openfinInit(): Promise { + public async openfinInit() { const connectionStatus = await local.ipcRenderer.invoke( apiName.symphonyApi, { @@ -981,31 +981,34 @@ export class SSFApi { /** * Fires an intent */ - public openfinFireIntent(intent: any): void { - local.ipcRenderer.send(apiName.symphonyApi, { + public async openfinFireIntent(intent: any): Promise { + const response = await local.ipcRenderer.invoke(apiName.symphonyApi, { cmd: apiCmds.openfinFireIntent, intent, }); + return response; } /** * Fires an intent for a given context * @param context */ - public openfinFireIntentForContext(context: any): void { - local.ipcRenderer.send(apiName.symphonyApi, { + public async openfinFireIntentForContext(context: any): Promise { + const response = await local.ipcRenderer.invoke(apiName.symphonyApi, { cmd: apiCmds.openfinFireIntentForContext, context, }); + return response; } /** - * Removes client from current context group + * Leaves current context group */ - public openfinRemoveClientFromContextGroup() { - local.ipcRenderer.send(apiName.symphonyApi, { - cmd: apiCmds.openfinRemoveClientFromContextGroup, + public async openfinRemoveFromContextGroup() { + const response = await local.ipcRenderer.invoke(apiName.symphonyApi, { + cmd: apiCmds.openfinRemoveFromContextGroup, }); + return response; } /** @@ -1057,7 +1060,7 @@ export class SSFApi { * Unregisters a handler based on a given intent handler callback id * @param UUID */ - public openfinUnregisterIntentHandler(callbackId: UUID): void { + public async openfinUnregisterIntentHandler(callbackId: UUID): Promise { for (const innerMap of local.intentsCallbacks.values()) { if (innerMap.has(callbackId)) { innerMap.delete(callbackId); @@ -1065,10 +1068,11 @@ export class SSFApi { } } - local.ipcRenderer.send(apiName.symphonyApi, { + const response = await local.ipcRenderer.invoke(apiName.symphonyApi, { cmd: apiCmds.openfinUnregisterIntentHandler, callbackId, }); + return response; } /** @@ -1086,22 +1090,36 @@ export class SSFApi { * @param contextGroupId * @param target */ - public openfinJoinContextGroup(contextGroupId: string, target?: any) { - local.ipcRenderer.send(apiName.symphonyApi, { + public async openfinJoinContextGroup(contextGroupId: string, target?: any) { + const response = await local.ipcRenderer.invoke(apiName.symphonyApi, { cmd: apiCmds.openfinJoinContextGroup, contextGroupId, target, }); + return response; + } + + /** + * Allows to join or create an Openfin session context group + * @param contextGroupId + */ + public async openfinJoinSessionContextGroup(contextGroupId: string) { + const response = await local.ipcRenderer.invoke(apiName.symphonyApi, { + cmd: apiCmds.openfinJoinSessionContextGroup, + contextGroupId, + }); + return response; } /** * Returns registered clients in a given context group */ - public openfinGetAllClientsInContextGroup(contextGroupId: string) { - return local.ipcRenderer.invoke(apiName.symphonyApi, { + public async openfinGetAllClientsInContextGroup(contextGroupId: string) { + const clients = await local.ipcRenderer.invoke(apiName.symphonyApi, { cmd: apiCmds.openfinGetAllClientsInContextGroup, contextGroupId, }); + return clients; } /**