-
Notifications
You must be signed in to change notification settings - Fork 135
/
Copy pathDesktopAgentPreloadLoader.ts
112 lines (99 loc) · 4.09 KB
/
DesktopAgentPreloadLoader.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import { AgentError, DesktopAgent, WebDesktopAgentType } from '@finos/fdc3-standard';
import { GetAgentParams } from '@finos/fdc3-standard';
import { DesktopAgentSelection, Loader } from './Loader';
import { Logger } from '../util/Logger';
import { DEFAULT_GETAGENT_TIMEOUT_MS } from './Timeouts';
/**
* This approach will resolve the loader promise if the fdc3Ready event occurs.
* This is done by Desktop Agent Preload implementations setting window.fdc3.
*/
export class DesktopAgentPreloadLoader implements Loader {
name = 'DesktopAgentPreloadLoader';
/** Reference to the handler for the fdc3Ready event (used to remove it) */
readyEventHandler: (() => void) | null = null;
/** Variable used to end polling */
done: boolean = false;
/** Overall timeout */
timeout: NodeJS.Timeout | null = null;
/** Timeout used in polling */
pollingTimeout: NodeJS.Timeout | null = null;
/** Reference to the get fn's Promise's reject call - used when cancelling. */
rejectFn: ((reason?: string) => void) | null = null;
async poll(resolve: (value: DesktopAgentSelection) => void) {
if (!this.done) {
if (globalThis.window.fdc3) {
Logger.debug(`DesktopAgentPreloadLoader.get(): Discovered DA through polling...`);
this.prepareSelection(globalThis.window.fdc3, resolve);
} else {
this.pollingTimeout = setTimeout(() => this.poll(resolve), 100);
}
}
}
async prepareSelection(fdc3: DesktopAgent, resolve: (value: DesktopAgentSelection) => void) {
Logger.debug('DesktopAgentPreloadLoader: Preparing selection');
//note that we've found an agent and will be settling our get promise
this.rejectFn = null;
//stop polling and listening for fdc3Ready
this.cancel();
//retrieve appId from DA
const implMetadata = await fdc3.getInfo();
const selection: DesktopAgentSelection = {
agent: fdc3,
details: {
agentType: WebDesktopAgentType.Preload,
identityUrl: globalThis.window.location.href,
actualUrl: globalThis.window.location.href,
appId: implMetadata.appMetadata.appId,
instanceId: implMetadata.appMetadata.instanceId ?? 'unknown',
instanceUuid: implMetadata.appMetadata.instanceId ?? 'unknown', // preload DAs don't issue these so repeat the instanceId
},
};
resolve(selection);
}
get(options: GetAgentParams): Promise<DesktopAgentSelection> {
Logger.debug(`DesktopAgentPreloadLoader.get(): Initiating search for Desktop Agent Preload`);
return new Promise<DesktopAgentSelection>((resolve, reject) => {
//save reject fn in case we get cancelled
this.rejectFn = reject;
//do an initial check
if (globalThis.window.fdc3) {
this.prepareSelection(globalThis.window.fdc3, resolve);
} else {
//setup a timeout so that we can reject if don't find anything
const timeoutMs = options.timeoutMs ?? DEFAULT_GETAGENT_TIMEOUT_MS;
this.timeout = setTimeout(() => {
Logger.debug(`DesktopAgentPreloadLoader.get(): timeout (${timeoutMs} ms) at ${new Date().toISOString()}`);
reject(AgentError.AgentNotFound);
this.cancel();
}, timeoutMs);
//listen for the fdc3Ready event
this.readyEventHandler = () => {
Logger.debug(`DesktopAgentPreloadLoader.get(): discovered DA through fdc3Ready event`);
if (globalThis.window.fdc3) {
this.prepareSelection(globalThis.window.fdc3, resolve);
}
};
globalThis.window.addEventListener('fdc3Ready', this.readyEventHandler);
//also do polling (just in case)
this.poll(resolve);
}
});
}
async cancel(): Promise<void> {
Logger.debug('DesktopAgentPreloadLoader: Cleaning up');
this.done = true;
if (this.timeout) {
clearTimeout(this.timeout);
}
if (this.pollingTimeout) {
clearTimeout(this.pollingTimeout);
}
if (this.readyEventHandler) {
globalThis.window.removeEventListener('fdc3Ready', this.readyEventHandler);
}
if (this.rejectFn) {
this.rejectFn(AgentError.AgentNotFound);
this.rejectFn = null;
}
}
}