8000 chromium-bin: source from Chrome for Testing Stable 155.0.8059.84 (both arches) — licensing review needed by bryan-minimal · Pull Request #928 · gominimal/pkgs · GitHub
[go: up one dir, main page]

Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 43 additions & 14 deletions packages/chromium-bin/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,29 @@
# chromium-bin

Prebuilt full Chromium browser binary, used in headed mode. amd64 comes
from Chromium's official snapshot bucket (true Chromium — Chrome for
Testing is a branded-Chrome build whose ToS forbids redistribution);
arm64 comes from Playwright's
own arm64 build hosted on Microsoft's CDN (Google does not publish
arm64 builds at all).
Prebuilt full Chrome browser binary, used in headed mode (or headless via
`--headless=new`). Both arches come from **Chrome for Testing (CfT)
Stable** — the `chrome` bundle for `linux64` and `linux-arm64`, at the same
version as [`chromium-headless-shell-bin`](../chromium-headless-shell-bin/).

## Licensing

CfT's `chrome` bundle is Google's branded **Google Chrome for Testing**
build: it ships with no BSD license grant (its `ABOUT` reads "All rights
reserved" and points at the Chrome Terms of Service). It also bundles the
proprietary Widevine CDM (`libwidevinecdm.so`, "not open source software",
no distribution without a separate agreement with Google).

- `build.sh` **deletes the Widevine CDM** and fails the build if any
Widevine file survives. Chrome runs without it; only DRM (EME) media
playback is lost.
- `license_spdx` is `LicenseRef-Google-Chrome-for-Testing-ToS`, not
`BSD-3-Clause`.
- The package is **not served from the public binary cache**: installing it
fetches the zip from Google's CfT bucket and unpacks it locally.

The headless shell (`chromium-headless-shell-bin`) and chromedriver are
different: their CfT zips carry the Chromium BSD-3-Clause grant and no
Widevine, so they are cache-served as usual.

Sibling package: [`chromium-headless-shell-bin`](../chromium-headless-shell-bin/)
ships the stripped headless-shell variant used by Playwright/Puppeteer
Expand All @@ -15,8 +33,10 @@ zip, so consumers that need only one variant don't pay for both.
Provides:

- `/bin/chromium` — full browser
- `/usr/share/playwright-browsers/chromium-<rev>/...` — Playwright's
registry layout, shared with `chromium-headless-shell-bin`
- `/usr/share/playwright-browsers/chromium-<rev>/chrome-linux64/chrome`
(amd64) or `.../chrome-linux-arm64/chrome` (arm64, plus a `chrome-linux`
compat symlink) — Playwright's registry layout, shared with
`chromium-headless-shell-bin`

## Using with Playwright

Expand All @@ -35,11 +55,13 @@ npx playwright test

This works for both `playwright-core` and `@playwright/test`. The two
pkgs share the `playwright-browsers` directory and Playwright's
registry walks it for `chromium{,_headless_shell}-<rev>/`. The
revision shipped here (currently **1217 ↔ Chrome 147.0.7727.15 ↔
playwright-core ^1.58.0**) must match the installed `playwright-core`
version — there is no `*_EXECUTABLE_PATH` env override for browsers,
so revision drift can't be papered over with env vars alone.
registry walks it for `chromium{,_headless_shell}-<rev>/`. The directory
key shipped here is **revision 1243 (playwright-core 1.63.x)**; the
browser inside is the current CfT Stable, not the Chrome 153 that
playwright-core 1.63 was rolled against. CfT's zip layout is exactly what
playwright-core ≥ 1.63 expects on both arches. A different playwright-core
version looks for a different `chromium-<rev>` directory, and there is no
`*_EXECUTABLE_PATH` env override for browsers — use Route B.

### Route B: `executablePath` (works regardless of revision)

Expand All @@ -58,11 +80,18 @@ const browser = await chromium.launch({
// playwright.config.{ts,mjs} — for @playwright/test
export default {
use: {
launchOptions: { executablePath: '/bin/chromium-headless-shell' },
launchOptions: { executablePath: '/bin/chromium' },
},
};
```

## Selenium / chromedriver

ChromeDriver is version-locked to the browser major. `chromedriver-bin`
pins the same CfT Stable version as `chromium-headless-shell-bin`, and this
package moves in lockstep with that one, so the same driver works with
`/bin/chromium` (set Selenium's browser binary / `SE_BROWSER_PATH` to it).

## Why prebuilt?

Building Chromium from source requires depot_tools, a hermetic clang
Expand Down
149 changes: 101 additions & 48 deletions packages/chromium-bin/build.ncl
< 8000 td id="diff-25e42658547efd649324af79b3cb04c641afad75547f44fa739a260d4056de98L73" data-line-number="73" class="blob-num blob-num-deletion js-linkable-line-number">
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
let { standaloneTest, Attrs, BuildSpec, Local, OutputBin, OutputData, Source, Test, .. } = import "minimal.ncl" in
let { Attrs, BuildSpec, Local, OutputBin, OutputData, Source, Test, .. } = import "minimal.ncl" in
let { target, .. } = import "config.ncl" in
let base = import "../base/build.ncl" in
let unzip = import "../unzip/build.ncl" in
Expand Down Expand Up @@ -38,7 +38,7 @@ let at-spi2-core = import "../at-spi2-core/build.ncl" in
let eudev = import "../eudev/build.ncl" in
let liberation-fonts = import "../liberation-fonts/build.ncl" in

# Prebuilt full chromium browser (headed mode), named with the
# Prebuilt full Chrome browser (headed mode), named with the
# Gentoo/AUR `-bin` convention. The headless-shell variant ships in a
# sibling pkg `chromium-headless-shell-bin` so consumers (and download
# size) only pay for the variant they need. Building chromium from
Expand All @@ -48,61 +48,84 @@ let liberation-fonts = import "../liberation-fonts/build.ncl" in
# this case. The bare `chromium` name is intentionally left available
# for a future source-built pkg.
#
# ⚠ CHANNEL: pre-stable BY DESIGN (pkgmgr-rs#646). This pair tracks
# Playwright's pinned Chromium, which rides ahead of the stable channel
# (the arm64 legs exist only for Playwright's revisions). CVEs are
# published only against stable, so a 0/0/0 scan here means "ahead of
# the published feed", NOT "audited clean" — and a held pin ages into
# known-vulnerable as its major reaches stable. pkgmgr's nightly sweep
# bumps the pair and alerts from the day that happens.
# ⚠ CHANNEL: Chrome for Testing **Stable**, the same channel and version
# as chromium-headless-shell-bin. This retires the "pre-stable BY DESIGN"
# posture of pkgmgr-rs#646: that existed only because we tracked
# Playwright's pinned Chromium, which rode ahead of Stable. On Stable a
# CVE match is an ordinary version-tracking question. Do NOT retarget
# this at Beta — Beta matches ~0 CVEs today and a few hundred the day
# its major goes stable. The security win is the channel.
#
# Source mix — both legs are true open-source Chromium (BSD-3-Clause),
# deliberately NOT Chrome for Testing: CfT is a *branded Google Chrome*
# build governed by the Chrome ToS, which does not permit redistribution
# — and our binary cache redistributes (gominimal/inbox#284). Playwright
# itself stopped publishing its own linux-x64 Chromium (its registry now
# fetches CfT directly for x64), so:
# amd64 → Chromium's official snapshot bucket
# (chromium-browser-snapshots), pinned to `snapshot_position` — the
# main-branch position Chrome `browser_version` branched from
# (chromiumdash fetch_version), i.e. the same code the arm64 build
# was cut from, minus branch cherry-picks.
# arm64 → Playwright's own arm64 Chromium build on cdn.playwright.dev
# (Google publishes no linux-arm64; Playwright still builds arm64).
# SOURCE: Chrome for Testing `chrome`, one zip per arch, no grafting.
# WHY WE MOVED: Playwright stopped building linux-arm64 Chromium. r1243
# was the last one (r1245/1250/1260/1270 -> HTTP 400, re-verified
# 2026-09-18; r1249 -> 400 on 2026-10-18), so the old arm64 leg was a
# dead end and pkgmgr refused every newer target. CfT now publishes the
# full `chrome` bundle for linux-arm64 as well as linux64 (supported
# since 153.0.8001.0), so both legs come from one source at one version
# and `snapshot_position` is gone (also retiring the pkgmgr-rs#540
# re-derivation trap).
#
# `revision` is the Playwright browser-revision number from
# packages/playwright-core/browsers.json. Revision 1243 ↔ Chrome 153.0.8010.12
# ↔ playwright-core ^1.59. `snapshot_position` must be re-derived whenever
# `browser_version` bumps. Keep all three in lockstep with
# chromium-headless-shell-bin.
# ⚠ LICENSING — this is NOT the headless-shell situation. Verified
# 2026-10-18 against both CfT `chrome` zips at 155.0.8059.84:
# * each ships WidevineCdm/_platform_specific/linux_<arch>/libwidevinecdm.so
# under WidevineCdm/LICENSE: "You may not use, modify, sell, or
# otherwise distribute the Software without a separate license
# agreement with Google. The Software is not open source software."
# build.sh DELETES WidevineCdm/ and fails the build if any Widevine
# file survives. Chrome runs fine without it (no EME/DRM playback,
# which nothing headless needs).
# * unlike chrome-headless-shell (LICENSE.headless_shell, the Chromium
# BSD-3-Clause grant) and chromedriver (LICENSE.chromedriver), the
# `chrome` bundle carries NO license file. Its ABOUT reads "Google
# Chrome / Copyright 2026 Google LLC. All rights reserved. ... See
# the Terms of Service at chrome://terms", the binary brands itself
# "Google Chrome for Testing", and its strings point at the "Chrome
# and ChromeOS Additional Terms of Service". That is the branded-Chrome
# ToS posture gominimal/inbox#284 ruled non-redistributable.
# So `license_spdx` names the Google terms rather than claiming
# BSD-3-Clause, and this package must stay OUT of the public binary
# cache (consumers fetch the zip from Google and unpack it locally).
# The exclusion is build-infra policy: the build-servers
# NON_REDISTRIBUTABLE_NAMES denylist (the `redistributable = false`
# attr was withdrawn in pkgs#536), which must list `chromium-bin`
# BEFORE this recipe reaches main.
#
# Consumer note (Playwright): files are laid out under
# /usr/share/playwright-browsers/chromium-<rev>/ in Playwright's
# registry layout, so installing both this pkg and
# chromium-headless-shell-bin and setting
# `PLAYWRIGHT_BROWSERS_PATH=/usr/share/playwright-browsers` lets
# @playwright/test discover both binaries with zero further config —
# provided the installed playwright-core revision matches `revision`.
# If it doesn't, pass `executablePath: '/bin/chromium'` (or
# '/bin/chromium-headless-shell' from the headless-shell pkg) to
# bypass the registry lookup. See packages/chromium-bin/README.md.
# `revision` is retained ONLY as the Playwright registry directory key
# (`chromium-<revision>` under /usr/share/playwright-browsers), kept in
# lockstep with chromium-headless-shell-bin. It no longer names a
# Playwright build. `browser_version` is the CfT Stable version and is
# the only pin to bump (pkgmgr's chromium resolver does so, together
# with both sha256s).
#
# Consumer note (Playwright): CfT's zip layout (chrome-linux64/chrome,
# chrome-linux-arm64/chrome) is exactly what playwright-core >= 1.63
# expects on both arches, so installing this pkg and setting
# `PLAYWRIGHT_BROWSERS_PATH=/usr/share/playwright-browsers` lets a
# playwright-core 1.63.x (revision 1243) consumer discover it with no
# further config. Any other playwright-core version: pass
# `executablePath: '/bin/chromium'`. See packages/chromium-bin/README.md.
let revision = "1243" in
let browser_ 8000 version = "153.0.8010.12" in
let snapshot_position = "1681086" in
let browser_version = "155.0.8059.84" in
{
name = "chromium-bin",
build_deps = [
{ file = "build.sh" } | Local,
# One complete CfT bundle per arch. Both extract to a single
# top-level dir matching Playwright's registry layout
# (chrome-linux64 / chrome-linux-arm64, binary `chrome`), so build.sh
# needs no renames. CfT publishes no checksum file; the sha256s were
# computed from the downloads.
match {
{ arch = 'Amd64, .. } =>
{
url = "https://commondatastorage.googleapis.com/chromium-browser-snapshots/Linux_x64/%{snapshot_position}/chrome-linux.zip",
sha256 = "4cd65eb42af4eb7942b0af2a328af13b3808db672ad62b2d4af84e27aa17ba3b",
url = "https://storage.googleapis.com/chrome-for-testing-public/%{browser_version}/linux64/chrome-linux64.zip",
sha256 = "cf0f049892dea22e6a6db26d47ed0d7776b7158edcbec4634086633df8bafcbc",
} | Source,
{ arch = 'Arm64, .. } =>
{
url = "https://cdn.playwright.dev/dbazure/download/playwright/builds/chromium/%{revision}/chromium-linux-arm64.zip",
sha256 = "f144b7f58b61c6bea2c192c4c178faa9b606bdf758e2d47ca99fa03f759a13e4",
url = "https://storage.googleapis.com/chrome-for-testing-public/%{browser_version}/linux-arm64/chrome-linux-arm64.zip",
sha256 = "1692a407908867de88eb1f1b2a93ca47c348d8fb2e3c04752d966e0f2e0344b4",
} | Source,
} target,
base,
Expand Down Expand Up @@ -158,27 +181,57 @@ let snapshot_position = "1681086" in
attrs =
{
upstream_version = browser_version,
license_spdx = "BSD-3-Clause",
# Google's terms, not BSD-3-Clause: see LICENSING above. The
# Chromium sources are BSD-3-Clause, but these are Google's
# branded binaries and ship without that grant.
license_spdx = "LicenseRef-Google-Chrome-for-Testing-ToS",
# NOT the origin of these bytes (`binary_from` says where they come
# from), but LOAD-BEARING for vulnerability scanning: supply-chain's
# cpe_remap maps pkg:github/microsoft/playwright -> google:chrome, which
# is how BOTH chromium packages see Chrome's CVEs at all. Removing it
# (or changing it) without a matching cpe_remap/cpe_identity entry
# makes this package scan 0/0/0 — a silent false negative. Kept in
# lockstep with chromium-headless-shell-bin; re-identifying the pair
# is a separate, coordinated change (pkgmgr-rs#825).
source_provenance = {
category = 'GithubRepo,
owner = "microsoft",
repo = "playwright",
},
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
binary_from =
match {
{ arch = 'Amd64, .. } => "https://commondatastorage.googleapis.com/chromium-browser-snapshots/Linux_x64/%{snapshot_position}/chrome-linux.zip",
{ arch = 'Arm64, .. } => "https://cdn.playwright.dev/dbazure/download/playwright/builds/chromium/%{revision}/chromium-linux-arm64.zip",
{ arch = 'Amd64, .. } => "https://storage.googleapis.com/chrome-for-testing-public/%{browser_version}/linux64/chrome-linux64.zip",
{ arch = 'Arm64, .. } => "https://storage.googleapis.com/chrome-for-testing-public/%{browser_version}/linux-arm64/chrome-linux-arm64.zip",
} target,
} | Attrs,

tests = {
smoketest = standaloneTest "/bin/chromium --version",
# The exact pinned version, not just "it runs": CfT prints
# "Google Chrome for Testing <version>".
smoketest =
{
class = 'Standalone,
test_deps = [base],
cmds = [
["/bin/bash", "-c", "/bin/chromium --version | grep -qF ' %{browser_version}'"],
],
} | Test,
launch_check =
{
class = 'Standalone,
test_deps = [base],
cmds = [
["/bin/bash", "-c", "/bin/chromium --headless --no-sandbox --disable-gpu --disable-dev-shm-usage --dump-dom 'data:text/html,<title>chromium-launch-ok</title>' | grep -q chromium-launch-ok"],
["/bin/bash", "-c", "/bin/chromium --headless=new --no-sandbox --disable-gpu --disable-dev-shm-usage --dump-dom 'data:text/html,<title>chromium-launch-ok</title>' | grep -q chromium-launch-ok"],
],
} | Test,
# Playwright registry layout (PLAYWRIGHT_BROWSERS_PATH discovery) is
# in place, and the proprietary Widevine CDM is NOT shipped.
layout_check =
{
class = 'Standalone,
test_deps = [base],
cmds = [
["/bin/bash", "-c", "d=/usr/share/playwright-browsers/chromium-%{revision}; case \"$(uname -m)\" in x86_64) i=chrome-linux64 ;; *) i=chrome-linux-arm64 ;; esac; test -x \"$d/$i/chrome\" && test -e \"$d/INSTALLATION_COMPLETE\" && test ! -e \"$d/$i/WidevineCdm\""],
],
} | Test,
},
Expand Down
58 changes: 44 additions & 14 deletions packages/chromium-bin/build.sh
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
#!/bin/bash
set -euo pipefail

# One zip arrives in the cwd. Extract into a scratch dir so we can
# discover its (arch-dependent) top-level directory name.
# One complete Chrome for Testing `chrome` zip arrives in the cwd — a
# straight extract. (Before the CfT move amd64 came from the
# chromium-browser-snapshots bucket and arm64 from Playwright's CDN, which
# stopped publishing arm64 builds after r1243.)
mkdir -p _full
# amd64 zip from the chromium-browser-snapshots bucket is named
# chrome-linux.zip; arm64 zip from Playwright's CDN is
# chromium-linux-arm64.zip. Each build fetches exactly one zip into
# the cwd, so a broad glob is fine.
unzip -q chrom*-linux*.zip -d _full
if [ "$(uname -m)" = "x86_64" ]; then
unzip -q chrome-linux64.zip -d _full
else
unzip -q chrome-linux-arm64.zip -d _full
fi

# The zip is expected to extract to exactly one top-level directory —
# fail loudly if that ever changes.
Expand All @@ -19,13 +21,31 @@ if [ "${#entries[@]}" -ne 1 ] || [ ! -d "${entries[0]}" ]; then
fi
FULL_INNER=$(basename "${entries[0]}")

# Both zips extract to chrome-linux/, but Playwright's x64 registry
# expects chrome-linux64/chrome (its arm64 registry expects
# chrome-linux/chrome) — normalize on x86_64 so registry discovery via
# PLAYWRIGHT_BROWSERS_PATH keeps working on both arches.
if [ "$(uname -m)" = "x86_64" ] && [ "$FULL_INNER" = "chrome-linux" ]; then
mv _full/chrome-linux _full/chrome-linux64
FULL_INNER=chrome-linux64
if [ ! -x "_full/$FULL_INNER/chrome" ]; then
echo "expected an executable _full/$FULL_INNER/chrome in the CfT bundle" >&2
exit 1
fi

# Fail closed on runtime files whose absence would surface only at first
# launch (a FATAL on missing icudtl.dat / v8 snapshot, or --dump-dom
# quietly returning nothing).
for required in icudtl.dat v8_context_snapshot.bin resources.pak chrome_100_percent.pak; do
if [ ! -s "_full/$FULL_INNER/$required" ]; then
echo "CfT bundle is missing $required — refusing to ship an incomplete browser" >&2
exit 1
fi
done

# LICENSING: the CfT `chrome` bundle ships Google's Widevine CDM
# (WidevineCdm/_platform_specific/linux_<arch>/libwidevinecdm.so) under a
# license that forbids distribution without a separate agreement with
# Google ("The Software is not open source software"). Never ship it.
# Chrome runs without it; only EME/DRM media playback is lost.
rm -rf "_full/$FULL_INNER/WidevineCdm"
if find "_full/$FULL_INNER" -iname '*widevine*' | grep -q .; then
echo "Widevine files survived the strip — refusing to ship them:" >&2
find "_full/$FULL_INNER" -iname '*widevine*' >&2
exit 1
fi

REV="${MINIMAL_ARG_REVISION}"
Expand All @@ -38,6 +58,16 @@ FULL_DEST="$SHARE/chromium-${REV}"
install -d "$FULL_DEST"
cp -R "_full/$FULL_INNER" "$FULL_DEST/$FULL_INNER"

# COMPAT (arm64): the pre-CfT arm64 leg (Playwright's own build) extracted
# to `chrome-linux/chrome`, which playwright-core <= 1.62 looked for on
# arm64. CfT (and playwright-core >= 1.63) use `chrome-linux-arm64/chrome`.
# Keep the old name as a symlink so anything that hardcoded the previous
# path keeps resolving. amd64 is unaffected: `chrome-linux64` was already
# its directory name.
if [ "$FULL_INNER" != "chrome-linux" ] && [ "$FULL_INNER" != "chrome-linux64" ]; then
ln -s "$FULL_INNER" "$FULL_DEST/chrome-linux"
fi

# Playwright's installer writes this marker after a successful download;
# without it @playwright/test treats the install as incomplete and tries
# to re-download.
Expand Down
Loading
0