blob: dd46ba814f18d7e71e0b9439da3cc33a781de929 [file] [log] [blame]
// Copyright (C) 2022 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import {defer} from '../../base/deferred';
import {
ByteStream,
OnStreamCloseCallback,
OnStreamDataCallback,
} from './recording_interfaces_v2';
// A HostOsByteStream instantiates a websocket connection to the host OS.
// It exposes an API to write commands to this websocket and read its output.
export class HostOsByteStream implements ByteStream {
// handshakeSignal will be resolved with the stream when the websocket
// connection becomes open.
private handshakeSignal = defer<HostOsByteStream>();
private _isConnected: boolean = false;
private websocket: WebSocket;
private onStreamDataCallbacks: OnStreamDataCallback[] = [];
private onStreamCloseCallbacks: OnStreamCloseCallback[] = [];
private constructor(websocketUrl: string) {
this.websocket = new WebSocket(websocketUrl);
this.websocket.onmessage = this.onMessage.bind(this);
this.websocket.onopen = this.onOpen.bind(this);
}
addOnStreamDataCallback(onStreamData: OnStreamDataCallback): void {
this.onStreamDataCallbacks.push(onStreamData);
}
addOnStreamCloseCallback(onStreamClose: OnStreamCloseCallback): void {
this.onStreamCloseCallbacks.push(onStreamClose);
}
close(): void {
this.websocket.close();
for (const onStreamClose of this.onStreamCloseCallbacks) {
onStreamClose();
}
this.onStreamDataCallbacks = [];
this.onStreamCloseCallbacks = [];
}
async closeAndWaitForTeardown(): Promise<void> {
this.close();
}
isConnected(): boolean {
return this._isConnected;
}
write(msg: string|Uint8Array): void {
this.websocket.send(msg);
}
private async onMessage(evt: MessageEvent) {
for (const onStreamData of this.onStreamDataCallbacks) {
const arrayBufferResponse = await evt.data.arrayBuffer();
onStreamData(new Uint8Array(arrayBufferResponse));
}
}
private onOpen() {
this._isConnected = true;
this.handshakeSignal.resolve(this);
}
static create(websocketUrl: string): Promise<HostOsByteStream> {
return (new HostOsByteStream(websocketUrl)).handshakeSignal;
}
}