Bug 1886451: Add missing ifdef Nightly guards. r=dminor
[gecko.git] / remote / cdp / StreamRegistry.sys.mjs
blob9474f16a57ea2eb0a0ba2af509c22e4aeda98dd7
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 const lazy = {};
7 ChromeUtils.defineESModuleGetters(lazy, {
8   generateUUID: "chrome://remote/content/shared/UUID.sys.mjs",
9   UnsupportedError: "chrome://remote/content/cdp/Error.sys.mjs",
10 });
12 export class Stream {
13   #path;
14   #offset;
15   #length;
17   constructor(path) {
18     this.#path = path;
19     this.#offset = 0;
20     this.#length = null;
21   }
23   async destroy() {
24     await IOUtils.remove(this.#path);
25   }
27   async seek(seekTo) {
28     // To keep compatibility with Chrome clip invalid offsets
29     this.#offset = Math.max(0, Math.min(seekTo, await this.length()));
30   }
32   async readBytes(count) {
33     const bytes = await IOUtils.read(this.#path, {
34       offset: this.#offset,
35       maxBytes: count,
36     });
37     this.#offset += bytes.length;
38     return bytes;
39   }
41   async available() {
42     const length = await this.length();
43     return length - this.#offset;
44   }
46   async length() {
47     if (this.#length === null) {
48       const info = await IOUtils.stat(this.#path);
49       this.#length = info.size;
50     }
52     return this.#length;
53   }
55   get path() {
56     return this.#path;
57   }
60 export class StreamRegistry {
61   constructor() {
62     // handle => stream
63     this.streams = new Map();
65     // Register an async shutdown blocker to ensure all open IO streams are
66     // closed, and remaining temporary files removed. Needs to happen before
67     // IOUtils has been shutdown.
68     IOUtils.profileBeforeChange.addBlocker(
69       "Remote Agent: Clean-up of open streams",
70       async () => {
71         await this.destructor();
72       }
73     );
74   }
76   async destructor() {
77     for (const stream of this.streams.values()) {
78       await stream.destroy();
79     }
81     this.streams.clear();
82   }
84   /**
85    * Add a new stream to the registry.
86    *
87    * @param {Stream} stream
88    *      The stream to use.
89    *
90    * @returns {string}
91    *     Stream handle (uuid)
92    */
93   add(stream) {
94     if (!(stream instanceof Stream)) {
95       // Bug 1602731 - Implement support for blob
96       throw new lazy.UnsupportedError(`Unknown stream type for ${stream}`);
97     }
99     const handle = lazy.generateUUID();
101     this.streams.set(handle, stream);
102     return handle;
103   }
105   /**
106    * Get a stream from the registry.
107    *
108    * @param {string} handle
109    *      Handle of the stream to retrieve.
110    *
111    * @returns {Stream}
112    *      The requested stream.
113    */
114   get(handle) {
115     const stream = this.streams.get(handle);
117     if (!stream) {
118       throw new TypeError(`Invalid stream handle`);
119     }
121     return stream;
122   }
124   /**
125    * Remove a stream from the registry.
126    *
127    * @param {string} handle
128    *      Handle of the stream to remove.
129    *
130    * @returns {boolean}
131    *     true if successfully removed
132    */
133   async remove(handle) {
134     const stream = this.get(handle);
135     await stream.destroy();
137     return this.streams.delete(handle);
138   }