mirror of https://github.com/vector-im/riot-web
Implement widget API for signaling the widget to gracefully terminate
In theory, widgets could use iframe unload/beforeunload events for cleanup, but in practice browsers have restrictions on what can be done in those events which may not give sufficient time for clean termination. Signed-off-by: Pauli Virtanen <pav@iki.fi>pull/21833/head
parent
355539feb5
commit
1f2bf0485e
|
@ -87,6 +87,19 @@ export default class WidgetMessaging {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells the widget that it should terminate now.
|
||||||
|
* It is not necessarily called in all instances before the widget is removed,
|
||||||
|
* and the client may force termination with a timeout.
|
||||||
|
* @returns {Promise<*>} Resolves when widget has acknowledged the message.
|
||||||
|
*/
|
||||||
|
terminate() {
|
||||||
|
return this.messageToWidget({
|
||||||
|
api: OUTBOUND_API_NAME,
|
||||||
|
action: KnownWidgetActions.Terminate,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request a screenshot from a widget
|
* Request a screenshot from a widget
|
||||||
* @return {Promise} To be resolved with screenshot data when it has been generated
|
* @return {Promise} To be resolved with screenshot data when it has been generated
|
||||||
|
|
|
@ -34,6 +34,7 @@ export enum KnownWidgetActions {
|
||||||
ReceiveOpenIDCredentials = "openid_credentials",
|
ReceiveOpenIDCredentials = "openid_credentials",
|
||||||
SetAlwaysOnScreen = "set_always_on_screen",
|
SetAlwaysOnScreen = "set_always_on_screen",
|
||||||
ClientReady = "im.vector.ready",
|
ClientReady = "im.vector.ready",
|
||||||
|
Terminate = "im.vector.terminate",
|
||||||
}
|
}
|
||||||
|
|
||||||
export type WidgetAction = KnownWidgetActions | string;
|
export type WidgetAction = KnownWidgetActions | string;
|
||||||
|
@ -68,6 +69,8 @@ export class WidgetApi {
|
||||||
private inFlightRequests: { [requestId: string]: (reply: FromWidgetRequest) => void } = {};
|
private inFlightRequests: { [requestId: string]: (reply: FromWidgetRequest) => void } = {};
|
||||||
private readyPromise: Promise<any>;
|
private readyPromise: Promise<any>;
|
||||||
private readyPromiseResolve: () => void;
|
private readyPromiseResolve: () => void;
|
||||||
|
private terminatePromise: Promise<any>;
|
||||||
|
private terminatePromiseResolve: () => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set this to true if your widget is expecting a ready message from the client. False otherwise (default).
|
* Set this to true if your widget is expecting a ready message from the client. False otherwise (default).
|
||||||
|
@ -78,6 +81,7 @@ export class WidgetApi {
|
||||||
this.origin = new URL(currentUrl).origin;
|
this.origin = new URL(currentUrl).origin;
|
||||||
|
|
||||||
this.readyPromise = new Promise<any>(resolve => this.readyPromiseResolve = resolve);
|
this.readyPromise = new Promise<any>(resolve => this.readyPromiseResolve = resolve);
|
||||||
|
this.terminatePromise = new Promise<any>(resolve => this.terminatePromiseResolve = resolve);
|
||||||
|
|
||||||
window.addEventListener("message", event => {
|
window.addEventListener("message", event => {
|
||||||
if (event.origin !== this.origin) return; // ignore: invalid origin
|
if (event.origin !== this.origin) return; // ignore: invalid origin
|
||||||
|
@ -98,6 +102,12 @@ export class WidgetApi {
|
||||||
|
|
||||||
// Automatically acknowledge so we can move on
|
// Automatically acknowledge so we can move on
|
||||||
this.replyToRequest(<ToWidgetRequest>payload, {});
|
this.replyToRequest(<ToWidgetRequest>payload, {});
|
||||||
|
} else if (payload.action === KnownWidgetActions.Terminate) {
|
||||||
|
// Reply after resolving
|
||||||
|
this.terminatePromise.then(() => {
|
||||||
|
this.replyToRequest(<ToWidgetRequest>payload, {});
|
||||||
|
});
|
||||||
|
this.terminatePromiseResolve();
|
||||||
} else {
|
} else {
|
||||||
console.warn(`[WidgetAPI] Got unexpected action: ${payload.action}`);
|
console.warn(`[WidgetAPI] Got unexpected action: ${payload.action}`);
|
||||||
}
|
}
|
||||||
|
@ -116,6 +126,10 @@ export class WidgetApi {
|
||||||
return this.readyPromise;
|
return this.readyPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public addTerminateCallback(action) {
|
||||||
|
this.terminatePromise = this.terminatePromise.then(action);
|
||||||
|
}
|
||||||
|
|
||||||
private replyToRequest(payload: ToWidgetRequest, reply: any) {
|
private replyToRequest(payload: ToWidgetRequest, reply: any) {
|
||||||
if (!window.parent) return;
|
if (!window.parent) return;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue