diff --git a/NEWS.md b/NEWS.md index 22f406d..3c968e4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,11 @@ # chromote (development version) +* The headless mode used by Chrome can now be selected with the `chromote.headless` option or `CHROMOTE_HEADLESS` environment variable. + + In Chrome v128, a [new headless mode](https://developer.chrome.com/docs/chromium/new-headless) became the default. The new mode uses the same browser engine as the regular Chrome browser, whereas the old headless mode is built on a separate architecture. The old headless mode may be faster to launch and is still well-suited to many of the tasks for which chromote is used. + + For now, to avoid disruption, chromote defaults to using the old headless mode. In the future, chromote will follow Chrome and default to `"new"` headless mode. (And at some point, Chrome intends to remove the old headless mode which is now offered as [a separate binary](https://developer.chrome.com/blog/chrome-headless-shell).) To test the new headless mode, use `options(chromote.headless = "new")` or `CHROMOTE_HEADLESS="new"` (in `.Renviron` or via `Sys.setenv()`). (#172) + # chromote 0.2.0 ## Breaking changes diff --git a/R/chrome.R b/R/chrome.R index 5d5e9e2..ce2f380 100644 --- a/R/chrome.R +++ b/R/chrome.R @@ -160,6 +160,32 @@ inform_if_chrome_not_found <- function( NULL } +chrome_headless_mode <- function() { + opt <- getOption("chromote.headless", NULL) + env <- Sys.getenv("CHROMOTE_HEADLESS", NULL) + + # TODO Chrome v128 changed the default from --headless=old to --headless=new + # in 2024-08. Old headless mode was effectively a separate browser render, + # and while more performant did not share the same browser implementation as + # headful Chrome. New headless mode will likely be useful to some, but in most + # chromote use cases -- printing to PDF and testing -- we are not ready to + # move to the new mode. We'll use `--headless=old` as the default for now + # until the new mode is more stable, or until we add support for downloading + # specific versions of Chrome. (See rstudio/chromote#171) + default_mode <- "old" + mode <- tolower(opt %||% env %||% default_mode) + + if (!mode %in% c("old", "new")) { + used <- if (!is.null(opt)) "chromote.headless" else "CHROMOTE_HEADLESS" + rlang::inform( + sprintf('Invalid value for `%s`. Using `"%s"`.', used, default_mode) + ) + mode <- default_mode + } + + sprintf("--headless=%s", mode) +} + launch_chrome <- function(path = find_chrome(), args = get_chrome_args()) { if (is.null(path)) { stop("Invalid path to Chrome") @@ -173,14 +199,15 @@ launch_chrome_impl <- function(path, args, port) { p <- process$new( command = path, args = c( - "--headless", + chrome_headless_mode(), paste0("--remote-debugging-port=", port), paste0("--remote-allow-origins=http://127.0.0.1:", port), args ), supervise = TRUE, stdout = tempfile("chrome-stdout-", fileext = ".log"), - stderr = tempfile("chrome-stderr-", fileext = ".log") + stderr = tempfile("chrome-stderr-", fileext = ".log"), + echo_cmd = getOption("chromote.launch.echo_cmd", FALSE) ) connected <- FALSE diff --git a/R/chromote-package.R b/R/chromote-package.R index 808d369..9d0f2b1 100644 --- a/R/chromote-package.R +++ b/R/chromote-package.R @@ -1,6 +1,31 @@ #' @keywords internal "_PACKAGE" +#' chromote Options +#' +#' @description +#' These options and environment variables that are used by chromote. Options +#' are lowercase and can be set with `options()`. Environment variables are +#' uppercase and can be set in an `.Renviron` file, with `Sys.setenv()`, or in +#' the shell or process running R. If both an option or environment variable are +#' supported, chromote will use the option first. +#' +#' * `CHROMOTE_CHROME` \cr +#' Path to the Chrome executable. If not set, chromote will +#' attempt to find and use the system installation of Chrome. +#' * `chromote.headless`, `CHROMOTE_HEADLESS` \cr +#' Headless mode for Chrome. Can be `"old"` or `"new"`. See +#' [Chrome Headless mode](https://developer.chrome.com/docs/chromium/new-headless) +#' for more details. +#' * `chromote.timeout` \cr +#' Timeout (in seconds) for Chrome to launch or connect. Default is `10`. +#' * `chromote.launch.echo_cmd` \cr +#' Echo the command used to launch Chrome to the console for debugging. +#' Default is `FALSE`. +#' +#' @name chromote-options +NULL + ## usethis namespace: start #' @import promises later #' @importFrom fastmap fastmap diff --git a/man/chromote-options.Rd b/man/chromote-options.Rd new file mode 100644 index 0000000..c50702c --- /dev/null +++ b/man/chromote-options.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/chromote-package.R +\name{chromote-options} +\alias{chromote-options} +\title{chromote Options} +\description{ +These options and environment variables that are used by chromote. Options +are lowercase and can be set with \code{options()}. Environment variables are +uppercase and can be set in an \code{.Renviron} file, with \code{Sys.setenv()}, or in +the shell or process running R. If both an option or environment variable are +supported, chromote will use the option first. +\itemize{ +\item \code{CHROMOTE_CHROME} \cr +Path to the Chrome executable. If not set, chromote will +attempt to find and use the system installation of Chrome. +\item \code{chromote.headless}, \code{CHROMOTE_HEADLESS} \cr +Headless mode for Chrome. Can be \code{"old"} or \code{"new"}. See +\href{https://developer.chrome.com/docs/chromium/new-headless}{Chrome Headless mode} +for more details. +\item \code{chromote.timeout} \cr +Timeout (in seconds) for Chrome to launch or connect. Default is \code{10}. +\item \code{chromote.launch.echo_cmd} \cr +Echo the command used to launch Chrome to the console for debugging. +Default is \code{FALSE}. +} +} diff --git a/pkgdown/_pkgdown.yml b/pkgdown/_pkgdown.yml index 388e069..eb70c37 100644 --- a/pkgdown/_pkgdown.yml +++ b/pkgdown/_pkgdown.yml @@ -20,6 +20,7 @@ reference: - title: Default settings # desc: ~ contents: + - chromote-options - default_chrome_args - default_chromote_object