blob: 447e7247d778d456db5d197a9fec4d42b2eaaa06 [file] [log] [blame]
"""This module defines the google_chrome repository rule.
The google_chrome repository rule installs Google Chrome and the required fonts and fontconfig
settings to properly render webpages in Puppeteer-based[1] screenshot tests.
This rule does not install any of the runtime libraries required by Chrome or Chromium. Runtime
libraries must be provided by the host system, or by the RBE toolchain container image when
building on RBE. When building binaries with Bazel, it is important to hermetically provide all
required libraries, as this ensures reproducible builds. However, we only use Chrome and Chromium
(via Puppeteer) for tests, so exact library versions are less of a concern. This has the additional
benefit of keeping this rule small, as both Chrome and Chromium depend on a large number of runtime
libraries.
Puppeteer tests must set the FONTCONFIG_SYSROOT[2] environment variable to point to the repository
directory generated by this rule. This ensures that the correct fonts are used in screenshot tests.
Note that Puppeteer bundles its own Chromium binary, and therefore ignores the Chrome binary
provided by this rule. However, said binary is used by Karma tests.
Why is this rule necessary, when the browser_repositories[3] repository rule exists? The Chromium
binary provided by the browser_repositories repository rule is indeed sufficient for Karma tests
(see example here[4] and here[5]). However, it does not provide the fonts or fontconfig settings
needed to properly render webpages in Puppeteer-based screenshot tests. Given that the
google_chrome repository rule downloads a Debian package with the necessary fonts, downloading an
additional package to provide the Chrome binary seems marginally less complex than adding a
dependency on an additional external Bazel repository.
[1] https://pptr.dev
[2] https://www.freedesktop.org/software/fontconfig/fontconfig-user.html
[3] https://github.com/bazelbuild/rules_webtesting/blob/e9cf17123068b1123c68219edf9b274bf057b9cc/web/versioned/browsers-0.3.3.bzl#L18
[4] https://github.com/google/skia/blob/89fea08f6b16a73b3f824e37dbf1039bb08bf91d/WORKSPACE.bazel#L156-L174
[5] https://github.com/google/skia/blob/89fea08f6b16a73b3f824e37dbf1039bb08bf91d/bazel/karma_test.bzl#L75
"""
load("//bazel:gcs_mirror.bzl", "gcs_mirror_url")
_DEB_PACKAGES_LINUX_AMD64 = [
# Google Chrome's debian repository is found at https://dl.google.com/linux/chrome/deb. The URL
# and SHA256 hash below were taken on 2022-05-25 from the Release[1] file in the repository's
# stable channel. Said file is found at
# https://dl.google.com/linux/chrome/deb/dists/stable/Release.
#
# [1] https://wiki.debian.org/DebianRepository/Format
{
"url": "https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_102.0.5005.61-1_amd64.deb",
"sha256": "fb8386ad122b328c7166647ae7deeb14d452cd8b66b01c51c1abccd4c6441680",
},
# https://packages.debian.org/buster/all/fonts-liberation/download
{
"url": "https://ftp.debian.org/debian/pool/main/f/fonts-liberation/fonts-liberation_1.07.4-9_all.deb",
"sha256": "c936aebbfd0af7851399ae5ab08bb01744f5e3381f7678fb87cc77114f95ef53",
},
]
def _google_chrome_impl(repository_ctx):
is_linux = repository_ctx.os.name.lower().startswith("linux")
if not is_linux:
# Support for other operating systems can be added as needed.
fail("OS not yet supported: %s." % repository_ctx.os.name)
# Download and extract Debian packages.
repository_ctx.report_progress("Downloading and installing .deb packages.")
for deb in _DEB_PACKAGES_LINUX_AMD64:
repository_ctx.download_and_extract(
url = gcs_mirror_url(url = deb["url"], sha256 = deb["sha256"]),
output = "__tmp__",
sha256 = deb["sha256"],
)
repository_ctx.extract(
archive = "__tmp__/data.tar.xz",
output = ".",
)
repository_ctx.delete("__tmp__")
# Generate /etc/fonts/fonts.conf file.
#
# An alternative to providing our own /etc/fonts/fonts.conf file is to install the
# fontconfig[1] and fontconfig-config[2] Debian packages, which provide good default settings.
# These packages provide an /etc/fonts/fonts.conf file and a number of
# /etc/fonts/conf.d/*.conf files which are loaded from the former via an
# <include>conf.d</include> element. However, for some unknown reason (a bug, perhaps?) the
# fontconfig library fails to scan the /etc/fonts/conf.d directory when the
# FONTCONFIG_SYSROOT[3] environment variable is set (as is the case for Puppeteer and Karma
# tests). Thus, as a workaround, we provide our own /etc/fonts/fonts.conf file with a minimal
# set of settings based on the config files provided by the fontconfig-config Debian package.
# This is enough to guarantee good quality Puppeteer screenshots.
#
# The below file maps common font families, such as Times New Roman, Arial and Courier New, to
# their generic names, such as serif, sans-serif, and monospace, respectively. Then, it maps
# serif, sans-serif and monospace to Liberation Sans, Liberation Serif, and Liberation Mono,
# respectively. Finally, if an unknown font is requested, it defaults to sans-serif, i.e.
# Liberation Sans.
#
# [1] https://packages.debian.org/buster/fontconfig
# [2] https://packages.debian.org/buster/fontconfig-config
# [3] https://www.freedesktop.org/software/fontconfig/fontconfig-user.html
repository_ctx.file("etc/fonts/fonts.conf", content = """<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<dir>/usr/share/fonts</dir>
<cachedir>/var/cache/fontconfig</cachedir>
<!--
Mark common families with their generics so we'll get something reasonable.
Based on
https://gitlab.freedesktop.org/fontconfig/fontconfig/-/blob/d863f6778915f7dd224c98c814247ec292904e30/conf.d/45-latin.conf.
-->
<!--
Serif faces
-->
<alias>
<family>Bitstream Vera Serif</family>
<default><family>serif</family></default>
</alias>
<alias>
<family>Cambria</family>
<default><family>serif</family></default>
</alias>
<alias>
<family>Constantia</family>
<default><family>serif</family></default>
</alias>
<alias>
<family>DejaVu Serif</family>
<default><family>serif</family></default>
</alias>
<alias>
<family>Elephant</family>
<default><family>serif</family></default>
</alias>
<alias>
<family>Garamond</family>
<default><family>serif</family></default>
</alias>
<alias>
<family>Georgia</family>
<default><family>serif</family></default>
</alias>
<alias>
<family>Liberation Serif</family>
<default><family>serif</family></default>
</alias>
<alias>
<family>Luxi Serif</family>
<default><family>serif</family></default>
</alias>
<alias>
<family>MS Serif</family>
<default><family>serif</family></default>
</alias>
<alias>
<family>Nimbus Roman No9 L</family>
<default><family>serif</family></default>
</alias>
<alias>
<family>Nimbus Roman</family>
<default><family>serif</family></default>
</alias>
<alias>
<family>Palatino Linotype</family>
<default><family>serif</family></default>
</alias>
<alias>
<family>Thorndale AMT</family>
<default><family>serif</family></default>
</alias>
<alias>
<family>Thorndale</family>
<default><family>serif</family></default>
</alias>
<alias>
<family>Times New Roman</family>
<default><family>serif</family></default>
</alias>
<alias>
<family>Times</family>
<default><family>serif</family></default>
</alias>
<!--
Sans-serif faces
-->
<alias>
<family>Albany AMT</family>
<default><family>sans-serif</family></default>
</alias>
<alias>
<family>Albany</family>
<default><family>sans-serif</family></default>
</alias>
<alias>
<family>Arial Unicode MS</family>
<default><family>sans-serif</family></default>
</alias>
<alias>
<family>Arial</family>
<default><family>sans-serif</family></default>
</alias>
<alias>
<family>Bitstream Vera Sans</family>
<default><family>sans-serif</family></default>
</alias>
<alias>
<family>Britannic</family>
<default><family>sans-serif</family></default>
</alias>
<alias>
<family>Calibri</family>
<default><family>sans-serif</family></default>
</alias>
<alias>
<family>Candara</family>
<default><family>sans-serif</family></default>
</alias>
<alias>
<family>Century Gothic</family>
<default><family>sans-serif</family></default>
</alias>
<alias>
<family>Corbel</family>
<default><family>sans-serif</family></default>
</alias>
<alias>
<family>DejaVu Sans</family>
<default><family>sans-serif</family></default>
</alias>
<alias>
<family>Helvetica</family>
<default><family>sans-serif</family></default>
</alias>
<alias>
<family>Haettenschweiler</family>
<default><family>sans-serif</family></default>
</alias>
<alias>
<family>Liberation Sans</family>
<default><family>sans-serif</family></default>
</alias>
<alias>
<family>MS Sans Serif</family>
<default><family>sans-serif</family></default>
</alias>
<alias>
<family>Nimbus Sans L</family>
<default><family>sans-serif</family></default>
</alias>
<alias>
<family>Nimbus Sans</family>
<default><family>sans-serif</family></default>
</alias>
<alias>
<family>Luxi Sans</family>
<default><family>sans-serif</family></default>
</alias>
<alias>
<family>Tahoma</family>
<default><family>sans-serif</family></default>
</alias>
<alias>
<family>Trebuchet MS</family>
<default><family>sans-serif</family></default>
</alias>
<alias>
<family>Twentieth Century</family>
<default><family>sans-serif</family></default>
</alias>
<alias>
<family>Verdana</family>
<default><family>sans-serif</family></default>
</alias>
<!--
Monospace faces
-->
<alias>
<family>Andale Mono</family>
<default><family>monospace</family></default>
</alias>
<alias>
<family>Bitstream Vera Sans Mono</family>
<default><family>monospace</family></default>
</alias>
<alias>
<family>Consolas</family>
<default><family>monospace</family></default>
</alias>
<alias>
<family>Courier New</family>
<default><family>monospace</family></default>
</alias>
<alias>
<family>Courier</family>
<default><family>monospace</family></default>
</alias>
<alias>
<family>Cumberland AMT</family>
<default><family>monospace</family></default>
</alias>
<alias>
<family>Cumberland</family>
<default><family>monospace</family></default>
</alias>
<alias>
<family>DejaVu Sans Mono</family>
<default><family>monospace</family></default>
</alias>
<alias>
<family>Fixedsys</family>
<default><family>monospace</family></default>
</alias>
<alias>
<family>Inconsolata</family>
<default><family>monospace</family></default>
</alias>
<alias>
<family>Liberation Mono</family>
<default><family>monospace</family></default>
</alias>
<alias>
<family>Luxi Mono</family>
<default><family>monospace</family></default>
</alias>
<alias>
<family>Nimbus Mono L</family>
<default><family>monospace</family></default>
</alias>
<alias>
<family>Nimbus Mono</family>
<default><family>monospace</family></default>
</alias>
<alias>
<family>Nimbus Mono PS</family>
<default><family>monospace</family></default>
</alias>
<alias>
<family>Terminal</family>
<default><family>monospace</family></default>
</alias>
<!--
If the font still has no generic name, add sans-serif.
Based on
https://gitlab.freedesktop.org/fontconfig/fontconfig/-/blob/d863f6778915f7dd224c98c814247ec292904e30/conf.d/49-sansserif.conf.
-->
<match target="pattern">
<test qual="all" name="family" compare="not_eq">
<string>sans-serif</string>
</test>
<test qual="all" name="family" compare="not_eq">
<string>serif</string>
</test>
<test qual="all" name="family" compare="not_eq">
<string>monospace</string>
</test>
<edit name="family" mode="append_last">
<string>sans-serif</string>
</edit>
</match>
<!--
Default to the Liberation font family.
-->
<alias>
<family>sans-serif</family>
<prefer>
<family>Liberation Sans</family>
</prefer>
</alias>
<alias>
<family>monospace</family>
<prefer>
<family>Liberation Mono</family>
</prefer>
</alias>
<alias>
<family>serif</family>
<prefer>
<family>Liberation Serif</family>
</prefer>
</alias>
</fontconfig>
""")
# Generate BUILD.bazel file.
repository_ctx.file("BUILD.bazel", content = """
filegroup(
name = "all_files",
srcs = glob(
include = ["**/*"],
),
visibility = ["//visibility:public"],
)
""")
google_chrome = repository_rule(
implementation = _google_chrome_impl,
doc = "Hermetically installs Google Chrome, and all required libraries and fonts.",
)