1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-12-04 13:44:00 +01:00
bitwarden-browser/apps/desktop/src/proxy/nativemessage.ts

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

96 lines
2.7 KiB
TypeScript
Raw Normal View History

2022-02-24 20:50:19 +01:00
/* eslint-disable no-console */
2020-11-23 18:37:04 +01:00
import IPC from "./ipc";
// Mostly based on the example from MDN,
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging
export default class NativeMessage {
ipc: IPC;
2021-12-20 15:47:17 +01:00
constructor(ipc: IPC) {
this.ipc = ipc;
}
2021-12-20 15:47:17 +01:00
send(message: object) {
const messageBuffer = Buffer.from(JSON.stringify(message));
2021-12-20 15:47:17 +01:00
const headerBuffer = Buffer.alloc(4);
headerBuffer.writeUInt32LE(messageBuffer.length, 0);
2021-12-20 15:47:17 +01:00
process.stdout.write(Buffer.concat([headerBuffer, messageBuffer]));
}
2021-12-20 15:47:17 +01:00
listen() {
let payloadSize: number = null;
2021-12-20 15:47:17 +01:00
// A queue to store the chunks as we read them from stdin.
// This queue can be flushed when `payloadSize` data has been read
const chunks: any = [];
2021-12-20 15:47:17 +01:00
// Only read the size once for each payload
const sizeHasBeenRead = () => Boolean(payloadSize);
2021-12-20 15:47:17 +01:00
// All the data has been read, reset everything for the next message
const flushChunksQueue = () => {
payloadSize = null;
chunks.splice(0);
};
2021-12-20 15:47:17 +01:00
const processData = () => {
// Create one big buffer with all all the chunks
const stringData = Buffer.concat(chunks);
console.error(stringData);
2021-12-20 15:47:17 +01:00
// The browser will emit the size as a header of the payload,
// if it hasn't been read yet, do it.
// The next time we'll need to read the payload size is when all of the data
// of the current payload has been read (ie. data.length >= payloadSize + 4)
if (!sizeHasBeenRead()) {
try {
payloadSize = stringData.readUInt32LE(0);
} catch (e) {
console.error(e);
return;
}
2021-12-20 15:47:17 +01:00
}
// If the data we have read so far is >= to the size advertised in the header,
// it means we have all of the data sent.
// We add 4 here because that's the size of the bytes that old the payloadSize
if (stringData.length >= payloadSize + 4) {
// Remove the header
const contentWithoutSize = stringData.slice(4, payloadSize + 4).toString();
2021-12-20 15:47:17 +01:00
// Reset the read size and the queued chunks
flushChunksQueue();
2021-12-20 15:47:17 +01:00
const json = JSON.parse(contentWithoutSize);
2021-12-20 15:47:17 +01:00
// Forward to desktop application
this.ipc.send(json);
}
};
2021-12-20 15:47:17 +01:00
process.stdin.on("readable", () => {
// A temporary variable holding the nodejs.Buffer of each
// chunk of data read off stdin
let chunk = null;
2021-12-20 15:47:17 +01:00
// Read all of the available data
// tslint:disable-next-line:no-conditional-assignment
while ((chunk = process.stdin.read()) !== null) {
chunks.push(chunk);
}
2021-12-20 15:47:17 +01:00
try {
processData();
2020-12-22 17:16:12 +01:00
} catch (e) {
console.error(e);
}
});
2021-12-20 15:47:17 +01:00
process.stdin.on("end", () => {
process.exit(0);
});
}
}