Skip to content

Conversation

@cderv
Copy link
Collaborator

@cderv cderv commented Feb 12, 2026

Summary

New quarto install chrome-headless-shell command that downloads Chrome Headless Shell from Google's Chrome for Testing API. This is a smaller, lighter headless browser purpose-built for automation — ideal for diagram rendering (Mermaid, Graphviz) to non-HTML formats.

Part of the Chrome Headless improvements epic (#11877).

What's included

  • Chrome for Testing download utilities that resolve platform-specific URLs via Google's JSON API (supports linux64, mac-arm64, mac-x64, win32, win64)
  • InstallableTool implementation registered in the tool system (quarto install, quarto uninstall, quarto update, quarto tools)
  • Browser discovery priority chain in getBrowserExecutablePath():
    1. QUARTO_CHROMIUM env var
    2. Quarto-installed chrome-headless-shell
    3. System Chrome/Edge
    4. Legacy puppeteer-managed Chromium revisions
  • quarto check integration showing chrome-headless-shell installation status
  • QUARTO_CHROMIUM validation — gracefully falls through when the path doesn't exist
  • 4 new smoke tests for Chrome-based diagram rendering (Mermaid PDF, Mermaid Typst, Mermaid multi-diagram, Graphviz PDF) with regex verification of screenshot output
  • 3 previously Linux-skipped smoke tests unlocked (no longer need setup-chrome in CI)
  • CI workflow updated: replaces setup-chrome action with quarto install chrome-headless-shell
  • Unit tests for both chrome-for-testing.ts and chrome-headless-shell.ts

Design rationale

Chrome Headless Shell is Google's recommended replacement for the --headless flag on full Chrome. It ships no UI, has fewer system dependencies, and is distributed through the stable Chrome for Testing API — making it more reliable than the legacy quarto install chromium approach which relied on Puppeteer's bundled Chromium revisions.

The priority chain preserves backward compatibility: users with QUARTO_CHROMIUM set or a system Chrome installed see no behavior change. The new tool slots in as a middle ground — lighter than system Chrome, more reliable than legacy chromium.

Test plan

  • Unit tests for CfT URL resolution and platform mapping
  • Unit tests for chrome-headless-shell install/uninstall lifecycle
  • Smoke tests: Mermaid → PDF, Mermaid → Typst, multi-diagram, Graphviz → PDF
  • quarto check displays chrome-headless-shell status
  • CI uses quarto install chrome-headless-shell instead of setup-chrome
  • CI smoke tests pass on Linux (this PR)

Part of #11877

Closes #10961, closes #6821, closes #13704

@posit-snyk-bot
Copy link
Collaborator

posit-snyk-bot commented Feb 12, 2026

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

cderv and others added 12 commits February 12, 2026 21:05
Shared infrastructure for downloading binaries from the Google Chrome
for Testing (CfT) API. Provides platform detection, API fetching,
binary search, and download+extract functions that will be used by
installable tool implementations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement quarto install/uninstall lifecycle for chrome-headless-shell
using Chrome for Testing (CfT) infrastructure. Stores binaries under
quartoDataDir("chrome-headless-shell") with a plain text version file
matching the tinytex/verapdf pattern.

Key exports for downstream tasks:
- chromeHeadlessShellInstallable: InstallableTool registration
- chromeHeadlessShellExecutablePath(): browser discovery
- chromeHeadlessShellInstallDir(): install location

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… quarto check

- Register chrome-headless-shell in kInstallableTools, enabling
  `quarto install/uninstall chrome-headless-shell`
- Fix installableTools() to return registry keys instead of lowercased
  display names (broken for multi-word tool names)
- Add WSL handling: allow chrome-headless-shell install with info note
  (unlike full chromium which blocks on WSL)
- Insert chrome-headless-shell as priority 2 in getBrowserExecutablePath()
  between system Chrome and legacy puppeteer revisions
- Update error message to recommend chrome-headless-shell over chromium
- Add chrome-headless-shell detection in `quarto check install`
- Fix pre-existing bug: chromium lookup in quarto check used display name
  comparison that never matched due to casing; now uses registry key lookup

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The chromium fallback branch in chromeCb() accessed binDir and
installedVersion as properties but they are async functions on the
InstallableTool interface. This was pre-existing dead code (the name
comparison never matched), but now reachable after the registry key
lookup fix. Properly await both methods.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add if (chromiumVersion) guard before displaying version, consistent
with the chrome-headless-shell branch. Prevents showing literal
"undefined" if the version file is missing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add smoke tests exercising mermaid and graphviz rendering through
chrome-headless-shell (PDF, Typst, multi-diagram). Remove not_os:linux
restrictions from existing mermaid SVG tests since Chrome is now
available on all CI platforms. Replace browser-actions/setup-chrome
with quarto install chrome-headless-shell in CI workflow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Check intermediate .tex/.typ files for \includegraphics and image()
references to mermaid-figure and dot-figure PNGs. This proves Chrome
actually produced screenshot images rather than only checking the
render didn't error.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Env var
- chrome-headless-shell
- system
- chromium
This should also close mermaid issues on CI
Extract browser detection logic into `detectChromeForCheck()` helper,
replacing the 4-branch if/else chain with a data object and single
formatting block. Fixes redundant `safeExistsSync` call and normalizes
JSON key from `QUARTO_CHROMIUM_invalid` to `warning`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@cderv cderv force-pushed the chrome-headless-improvement branch from 19fe5d7 to aa4b99d Compare February 12, 2026 20:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants