bitwarden-estensione-browser/libs/common/src/auth/iframe-component.ts

95 lines
2.5 KiB
TypeScript

export abstract class IFrameComponent {
iframe: HTMLIFrameElement;
private connectorLink: HTMLAnchorElement;
private parseFunction = this.parseMessage.bind(this);
constructor(
private win: Window,
protected webVaultUrl: string,
private path: string,
private iframeId: string,
public successCallback?: (message: string) => any,
public errorCallback?: (message: string) => any,
public infoCallback?: (message: string) => any,
) {
this.connectorLink = win.document.createElement("a");
}
stop() {
this.sendMessage("stop");
}
start() {
this.sendMessage("start");
}
sendMessage(message: any) {
if (!this.iframe || !this.iframe.src || !this.iframe.contentWindow) {
return;
}
this.iframe.contentWindow.postMessage(message, this.iframe.src);
}
base64Encode(str: string): string {
return btoa(
encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (match, p1) => {
return String.fromCharCode(("0x" + p1) as any);
}),
);
}
cleanup() {
this.win.removeEventListener("message", this.parseFunction, false);
}
protected createParams(data: any, version: number) {
return new URLSearchParams({
data: this.base64Encode(JSON.stringify(data)),
parent: encodeURIComponent(this.win.document.location.href),
v: version.toString(),
});
}
protected initComponent(params: URLSearchParams): void {
this.connectorLink.href = `${this.webVaultUrl}/${this.path}?${params}`;
this.iframe = this.win.document.getElementById(this.iframeId) as HTMLIFrameElement;
this.iframe.src = this.connectorLink.href;
this.win.addEventListener("message", this.parseFunction, false);
}
private parseMessage(event: MessageEvent) {
if (!this.validMessage(event)) {
return;
}
const parts: string[] = event.data.split("|");
if (parts[0] === "success" && this.successCallback) {
this.successCallback(parts[1]);
} else if (parts[0] === "error" && this.errorCallback) {
this.errorCallback(parts[1]);
} else if (parts[0] === "info" && this.infoCallback) {
this.infoCallback(parts[1]);
}
}
private validMessage(event: MessageEvent) {
if (
event.origin == null ||
event.origin === "" ||
event.origin !== (this.connectorLink as any).origin ||
event.data == null ||
typeof event.data !== "string"
) {
return false;
}
return (
event.data.indexOf("success|") === 0 ||
event.data.indexOf("error|") === 0 ||
event.data.indexOf("info|") === 0
);
}
}