(
chromeArgs: string[],
config?: Partial<
Pick<EngineConfig, "browserTimeout" | "protocolTimeout" | "chromePath" | "forceScreenshot">
>,
)
| 419 | |
| 420 | // fallow-ignore-next-line complexity |
| 421 | async function launchBrowser( |
| 422 | chromeArgs: string[], |
| 423 | config?: Partial< |
| 424 | Pick<EngineConfig, "browserTimeout" | "protocolTimeout" | "chromePath" | "forceScreenshot"> |
| 425 | >, |
| 426 | ): Promise<AcquiredBrowser> { |
| 427 | // Config chromePath overrides env var / auto-detection. |
| 428 | const headlessShell = resolveHeadlessShellPath(config); |
| 429 | |
| 430 | // BeginFrame requires chrome-headless-shell AND Linux (crashes on |
| 431 | // macOS/Windows — crbug.com/40656275). |
| 432 | const isLinux = process.platform === "linux"; |
| 433 | const forceScreenshot = config?.forceScreenshot ?? DEFAULT_CONFIG.forceScreenshot; |
| 434 | let captureMode: CaptureMode; |
| 435 | let executablePath: string | undefined; |
| 436 | |
| 437 | if (headlessShell && isLinux && !forceScreenshot) { |
| 438 | captureMode = "beginframe"; |
| 439 | executablePath = headlessShell; |
| 440 | } else { |
| 441 | // Screenshot mode with renderSeek: works on all platforms. |
| 442 | captureMode = "screenshot"; |
| 443 | executablePath = headlessShell ?? undefined; |
| 444 | } |
| 445 | |
| 446 | const ppt = await getPuppeteer(); |
| 447 | const browserTimeout = config?.browserTimeout ?? DEFAULT_CONFIG.browserTimeout; |
| 448 | const protocolTimeout = config?.protocolTimeout ?? DEFAULT_CONFIG.protocolTimeout; |
| 449 | let browser = await ppt.launch({ |
| 450 | headless: true, |
| 451 | args: chromeArgs, |
| 452 | defaultViewport: null, |
| 453 | executablePath, |
| 454 | timeout: browserTimeout, |
| 455 | protocolTimeout, |
| 456 | }); |
| 457 | |
| 458 | const browserVersion = await browser.version().catch(() => "unknown"); |
| 459 | const gpuFlags = chromeArgs.filter( |
| 460 | (a) => a.startsWith("--use-gl=") || a.startsWith("--use-angle="), |
| 461 | ); |
| 462 | console.log( |
| 463 | `[BrowserManager] Browser launched (${browserVersion}, ${captureMode}, gl=${gpuFlags.join(" ") || "default"}, headlessShell=${!!headlessShell}, platform=${process.platform})`, |
| 464 | ); |
| 465 | |
| 466 | if (captureMode === "beginframe") { |
| 467 | const supported = await probeBeginFrameSupport(browser).catch(() => true); |
| 468 | if (!supported) { |
| 469 | await browser.close().catch(() => {}); |
| 470 | console.warn( |
| 471 | "[BrowserManager] HeadlessExperimental.beginFrame unavailable in this Chromium build; falling back to screenshot mode.", |
| 472 | ); |
| 473 | captureMode = "screenshot"; |
| 474 | browser = await ppt.launch({ |
| 475 | headless: true, |
| 476 | args: stripBeginFrameFlags(chromeArgs), |
| 477 | defaultViewport: null, |
| 478 | executablePath, |
no test coverage detected