Discover installed Chromium executable
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { ChildProcess, spawn } from "child_process";
|
||||
import { accessSync, constants } from "fs";
|
||||
import { mkdtemp, rm } from "fs/promises";
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
@@ -15,9 +16,26 @@ export class ChromiumFallback {
|
||||
|
||||
constructor(
|
||||
private readonly onExit: (url: string) => void = () => undefined,
|
||||
private readonly executable = process.env.QUEUECUBE_CHROME_BIN || "chromium",
|
||||
private readonly executable = process.env.QUEUECUBE_CHROME_BIN || ChromiumFallback.findExecutable(),
|
||||
) {}
|
||||
|
||||
private static findExecutable(): string {
|
||||
const directories = (process.env.PATH || "").split(path.delimiter);
|
||||
for (const name of ["chromium", "chromium-browser", "google-chrome"]) {
|
||||
for (const directory of directories) {
|
||||
if (!directory) continue;
|
||||
const candidate = path.join(directory, name);
|
||||
try {
|
||||
accessSync(candidate, constants.X_OK);
|
||||
return candidate;
|
||||
} catch {
|
||||
// Keep checking the remaining supported executable names.
|
||||
}
|
||||
}
|
||||
}
|
||||
return "chromium";
|
||||
}
|
||||
|
||||
public get isRunning(): boolean {
|
||||
return this.active !== null;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,32 @@ test("uses isolated profile and safe argv; stop kills only its process and clean
|
||||
}
|
||||
});
|
||||
|
||||
test("discovers chromium-browser when that is the installed executable", async () => {
|
||||
const fixture = await fs.mkdtemp(path.join(os.tmpdir(), "queuecube-browser-path-test-"));
|
||||
const argsFile = path.join(fixture, "argv.json");
|
||||
const executable = path.join(fixture, "chromium-browser");
|
||||
const previousPath = process.env.PATH;
|
||||
const previousOverride = process.env.QUEUECUBE_CHROME_BIN;
|
||||
await fs.writeFile(executable, `#!/usr/bin/env node\nconst fs=require('fs'); fs.writeFileSync(${JSON.stringify(argsFile)}, JSON.stringify(process.argv.slice(2))); setInterval(()=>{},1000);\n`);
|
||||
await fs.chmod(executable, 0o700);
|
||||
await fs.symlink(process.execPath, path.join(fixture, "node"));
|
||||
|
||||
try {
|
||||
process.env.PATH = fixture;
|
||||
delete process.env.QUEUECUBE_CHROME_BIN;
|
||||
const browser = new ChromiumFallback();
|
||||
assert.equal(await browser.start("https://example.test/browser-discovery", () => true), true);
|
||||
await waitFor(async () => { try { await fs.access(argsFile); return true; } catch { return false; } });
|
||||
assert.equal(JSON.parse(await fs.readFile(argsFile, "utf8")).at(-1), "https://example.test/browser-discovery");
|
||||
await browser.stop();
|
||||
} finally {
|
||||
process.env.PATH = previousPath;
|
||||
if (previousOverride === undefined) delete process.env.QUEUECUBE_CHROME_BIN;
|
||||
else process.env.QUEUECUBE_CHROME_BIN = previousOverride;
|
||||
await fs.rm(fixture, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("canceled startup cleans its profile without spawning", async () => {
|
||||
const browser = new ChromiumFallback(() => undefined, "/bin/false");
|
||||
assert.equal(await browser.start("https://example.test/", () => false), false);
|
||||
|
||||
Reference in New Issue
Block a user