Skip to content

Instantly share code, notes, and snippets.

@krisselden
Last active March 6, 2019 01:29
Show Gist options
  • Save krisselden/1e91fc3b889b7c921325913fc2d5617c to your computer and use it in GitHub Desktop.
Save krisselden/1e91fc3b889b7c921325913fc2d5617c to your computer and use it in GitHub Desktop.
const chromeFinder = require("chrome-launcher/dist/chrome-finder");
const { getPlatform } = require("chrome-launcher/dist/utils");
const execa = require("execa");
const { Transform } = require("stream");
const { inspect } = require("util");
let seq = 0;
function eachMessage() {
/** @type {Buffer[]} */
let chunks = [];
/** @type {number} */
let bytes = 0;
/**
* @param {Buffer} chunk
* @param {number} start
* @param {number=} end
*/
function append(chunk, start, end) {
const len = end - start;
if (len > 0) {
chunks.push(chunk.slice(start, end));
bytes += len;
}
}
function flush() {
let value;
if (chunks.length === 1) {
value = chunks[0].toString();
} else if (chunks.length > 1) {
value = Buffer.concat(chunks, bytes).toString();
}
chunks.length = 0;
bytes = 0;
return value;
}
return new Transform({
readableObjectMode: true,
transform(chunk, _encoding, done) {
let start = 0;
let end = chunk.indexOf(0);
while (end !== -1) {
append(chunk, start, end);
const message = flush();
if (message !== undefined) {
this.push(message);
}
start = end + 1;
end = chunk.indexOf(0, start);
}
append(chunk, start);
done();
},
flush(done) {
const message = flush();
if (message !== undefined) {
this.push(message);
}
done();
},
});
}
function findChrome() {
const platform = getPlatform();
let chromePath;
if (platform in chromeFinder) {
const paths = chromeFinder[platform]();
if (paths.length > 0) {
chromePath = paths[0];
}
}
if (chromePath === undefined) {
throw new Error("unable to find chrome installation");
}
return chromePath;
}
const exec = findChrome();
const child = execa(
exec,
[
"--remote-debugging-pipe",
"--no-sandbox",
"--no-experiments",
"--metrics-recording-only",
"--disable-background-networking",
"--disable-sync",
"--disable-extensions",
],
{
buffer: false,
stdio: ["inherit", "inherit", "inherit", "pipe", "pipe"],
},
);
child.on("error", err => {
console.log("PROCESS ERROR", inspect(err));
});
child.on("close", () => {
console.log("PROCESS CLOSE");
});
const output = child.stdio[4].pipe(eachMessage());
const input = child.stdio[3];
function send(method, params, sessionId) {
const id = ++seq;
const message = {
id,
method,
params,
sessionId,
};
console.log("SND", inspect(message));
input.write(JSON.stringify(message));
input.write("\0");
return id;
}
let createId;
output.on("data", data => {
// console.log("DATA", data);
const message = JSON.parse(data);
if ("id" in message) {
console.log("RSP", inspect(message));
if (message.id === createId) {
const targetId = message.result.targetId;
send("Target.attachToTarget", { targetId, flatten: true });
}
} else {
console.log("EVT", inspect(message));
}
});
send("Target.setDiscoverTargets", { discover: true });
createId = send("Target.createTarget", { url: "http://google.com" });
process.on("SIGINT", () => {
send("Browser.close");
});
output.on("close", () => {
console.log("PROCESS OUTPUT CLOSE");
});
input.on("close", () => {
console.log("PROCESS INPUT CLOSE");
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment