Path: blob/main/components/gitpod-protocol/src/messaging/browser/window-connection.ts
2501 views
/**1* Copyright (c) 2020 Gitpod GmbH. All rights reserved.2* Licensed under the GNU Affero General Public License (AGPL).3* See License.AGPL.txt in the project root for license information.4*/56import { Message } from "vscode-jsonrpc/lib/messages";7import { AbstractMessageWriter, MessageWriter } from "vscode-jsonrpc/lib/messageWriter";8import { AbstractMessageReader, MessageReader, DataCallback } from "vscode-jsonrpc/lib/messageReader";9import { MessageConnection, createMessageConnection } from "vscode-jsonrpc/lib/main";10import { ConsoleLogger } from "vscode-ws-jsonrpc";1112interface WindowMessage extends Message {13serviceId: string;14}15function isWindowMessage(value: any): value is WindowMessage {16return (17!!value &&18typeof value === "object" &&19"jsonrpc" in value &&20typeof value["jsonrpc"] === "string" &&21"serviceId" in value &&22typeof value["serviceId"] === "string"23);24}2526export class WindowMessageWriter extends AbstractMessageWriter implements MessageWriter {27constructor(readonly serviceId: string, readonly window: Window, readonly targetOrigin: string) {28super();29}3031write(msg: Message): void {32const { serviceId } = this;33this.window.postMessage(Object.assign(msg, { serviceId }), this.targetOrigin);34}35}3637export class WindowMessageReader extends AbstractMessageReader implements MessageReader {38protected callback?: DataCallback;39protected readonly buffer: Message[] = [];4041constructor(readonly serviceId: string, readonly sourceOrigin: string) {42super();43window.addEventListener(44"message",45(event) => {46if (this.sourceOrigin !== "*" && event.origin !== this.sourceOrigin) {47return;48}49if (!isWindowMessage(event.data) || event.data.serviceId !== this.serviceId) {50return;51}52if (this.callback) {53this.callback(event.data);54} else {55this.buffer.push(event.data);56}57},58false,59);60}6162listen(callback: DataCallback): void {63let message;64while ((message = this.buffer.pop())) {65callback(message);66}67Object.freeze(this.buffer);68this.callback = callback;69}70}7172export function createWindowMessageConnection(73serviceId: string,74window: Window,75sourceOrigin: string,76targetOrigin = sourceOrigin,77): MessageConnection {78const reader = new WindowMessageReader(serviceId, sourceOrigin);79const writer = new WindowMessageWriter(serviceId, window, targetOrigin);80return createMessageConnection(reader, writer, new ConsoleLogger());81}828384