Skip to content

Commit

Permalink
Refactor IFrameRequestBehavior to use a promise for the iframe and cl…
Browse files Browse the repository at this point in the history
…ient
  • Loading branch information
sisou committed Apr 17, 2020
1 parent ef854ce commit 289745c
Showing 1 changed file with 32 additions and 31 deletions.
63 changes: 32 additions & 31 deletions client/src/RequestBehavior.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,52 +64,53 @@ export class RedirectRequestBehavior extends RequestBehavior {
export class IFrameRequestBehavior extends RequestBehavior {
private static IFRAME_PATH_SUFFIX = '/request/iframe/';

private _iframe: HTMLIFrameElement | null;
private _client: PostMessageRpcClient | null;
private _iframeEndpoint: string | null = null;
private _iframePromise: Promise<HTMLIFrameElement> | null = null;
private _clientPromise: Promise<PostMessageRpcClient> | null = null;

constructor() {
super(BehaviorType.IFRAME);
this._iframe = null;
this._client = null;
}

public async request(endpoint: string, command: KeyguardCommand, args: any[]): Promise<any> {
if (this._iframe
&& this._iframe.src
&& this._iframe.src !== `${endpoint}${IFrameRequestBehavior.IFRAME_PATH_SUFFIX}`
) {
const openedSrc = this._iframe.src;
const expectedSrc = `${endpoint}${IFrameRequestBehavior.IFRAME_PATH_SUFFIX}`;
throw new Error('Keyguard iframe is already opened with another endpoint' +
`(opened: ${openedSrc}, expected: ${expectedSrc}`);
}

const origin = RequestBehavior.getAllowedOrigin(endpoint);

if (!this._iframe) {
this._iframe = await this.createIFrame(endpoint);
}
if (!this._iframe.contentWindow) {
throw new Error(`IFrame contentWindow is ${typeof this._iframe.contentWindow}`);
}

if (!this._client) {
this._client = new PostMessageRpcClient(this._iframe.contentWindow, origin);
await this._client.init();
}

return await this._client.call(command, ...args);
const client = await this._getClient(endpoint);
return client.call(command, ...args);
}

public async createIFrame(endpoint: string): Promise<HTMLIFrameElement> {
return new Promise((resolve, reject) => {
if (this._iframeEndpoint && this._iframeEndpoint !== endpoint) {
throw new Error('Keyguard iframe is already opened with another endpoint' +
`(opened: ${this._iframeEndpoint}, expected: ${endpoint})`);
}
this._iframeEndpoint = endpoint;

this._iframePromise = this._iframePromise || new Promise((resolve, reject) => {
const $iframe = document.createElement('iframe');
$iframe.name = 'NimiqKeyguardIFrame';
$iframe.style.display = 'none';
document.body.appendChild($iframe);
$iframe.src = `${endpoint}${IFrameRequestBehavior.IFRAME_PATH_SUFFIX}`;
$iframe.onload = () => resolve($iframe);
$iframe.onerror = reject;
}) as Promise<HTMLIFrameElement>;
});

return this._iframePromise;
}

private _getClient(endpoint: string): Promise<PostMessageRpcClient> {
this._clientPromise = this._clientPromise || new Promise(async (resolve) => {
const iframe = await this.createIFrame(endpoint);
if (!iframe.contentWindow) {
throw new Error(`IFrame contentWindow is ${typeof iframe.contentWindow}`);
}

const origin = RequestBehavior.getAllowedOrigin(endpoint);
const client = new PostMessageRpcClient(iframe.contentWindow, origin);
await client.init();

resolve(client);
});

return this._clientPromise;
}
}

0 comments on commit 289745c

Please sign in to comment.