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