mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 23:02:20 +00:00
20e77a0edd
Differential Revision: https://phabricator.services.mozilla.com/D178727
140 lines
3.0 KiB
JavaScript
140 lines
3.0 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
const lazy = {};
|
|
|
|
ChromeUtils.defineESModuleGetters(lazy, {
|
|
generateUUID: "chrome://remote/content/shared/UUID.sys.mjs",
|
|
UnsupportedError: "chrome://remote/content/cdp/Error.sys.mjs",
|
|
});
|
|
|
|
export class Stream {
|
|
#path;
|
|
#offset;
|
|
#length;
|
|
|
|
constructor(path) {
|
|
this.#path = path;
|
|
this.#offset = 0;
|
|
this.#length = null;
|
|
}
|
|
|
|
async destroy() {
|
|
await IOUtils.remove(this.#path);
|
|
}
|
|
|
|
async seek(seekTo) {
|
|
// To keep compatibility with Chrome clip invalid offsets
|
|
this.#offset = Math.max(0, Math.min(seekTo, await this.length()));
|
|
}
|
|
|
|
async readBytes(count) {
|
|
const bytes = await IOUtils.read(this.#path, {
|
|
offset: this.#offset,
|
|
maxBytes: count,
|
|
});
|
|
this.#offset += bytes.length;
|
|
return bytes;
|
|
}
|
|
|
|
async available() {
|
|
const length = await this.length();
|
|
return length - this.#offset;
|
|
}
|
|
|
|
async length() {
|
|
if (this.#length === null) {
|
|
const info = await IOUtils.stat(this.#path);
|
|
this.#length = info.size;
|
|
}
|
|
|
|
return this.#length;
|
|
}
|
|
|
|
get path() {
|
|
return this.#path;
|
|
}
|
|
}
|
|
|
|
export class StreamRegistry {
|
|
constructor() {
|
|
// handle => stream
|
|
this.streams = new Map();
|
|
|
|
// Register an async shutdown blocker to ensure all open IO streams are
|
|
// closed, and remaining temporary files removed. Needs to happen before
|
|
// IOUtils has been shutdown.
|
|
IOUtils.profileBeforeChange.addBlocker(
|
|
"Remote Agent: Clean-up of open streams",
|
|
async () => {
|
|
await this.destructor();
|
|
}
|
|
);
|
|
}
|
|
|
|
async destructor() {
|
|
for (const stream of this.streams.values()) {
|
|
await stream.destroy();
|
|
}
|
|
|
|
this.streams.clear();
|
|
}
|
|
|
|
/**
|
|
* Add a new stream to the registry.
|
|
*
|
|
* @param {Stream} stream
|
|
* The stream to use.
|
|
*
|
|
* @returns {string}
|
|
* Stream handle (uuid)
|
|
*/
|
|
add(stream) {
|
|
if (!(stream instanceof Stream)) {
|
|
// Bug 1602731 - Implement support for blob
|
|
throw new lazy.UnsupportedError(`Unknown stream type for ${stream}`);
|
|
}
|
|
|
|
const handle = lazy.generateUUID();
|
|
|
|
this.streams.set(handle, stream);
|
|
return handle;
|
|
}
|
|
|
|
/**
|
|
* Get a stream from the registry.
|
|
*
|
|
* @param {string} handle
|
|
* Handle of the stream to retrieve.
|
|
*
|
|
* @returns {Stream}
|
|
* The requested stream.
|
|
*/
|
|
get(handle) {
|
|
const stream = this.streams.get(handle);
|
|
|
|
if (!stream) {
|
|
throw new TypeError(`Invalid stream handle`);
|
|
}
|
|
|
|
return stream;
|
|
}
|
|
|
|
/**
|
|
* Remove a stream from the registry.
|
|
*
|
|
* @param {string} handle
|
|
* Handle of the stream to remove.
|
|
*
|
|
* @returns {boolean}
|
|
* true if successfully removed
|
|
*/
|
|
async remove(handle) {
|
|
const stream = this.get(handle);
|
|
await stream.destroy();
|
|
|
|
return this.streams.delete(handle);
|
|
}
|
|
}
|