launcher

package
v0.1.0-rc.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 19, 2026 License: MIT Imports: 33 Imported by: 0

README

Overview

A lib helps to find, launch or download the browser. You can also use it as a standalone lib without wand.

Browser resolution

Launch looks for a browser in this order and takes the first it finds:

  1. Launcher.Bin() in code.
  2. The -wand=bin=<path> flag (lib/defaults).
  3. WAND_BROWSER_BIN.
  4. A System browser: Google Chrome, Chromium or Microsoft Edge at the paths LookPath searches on this OS, which are upstream's plus the Chrome for Testing app bundle and the Homebrew prefixes on macOS and /opt/google/chrome and /opt/microsoft/msedge on Linux. The first that exists wins; versions are not compared.
  5. The Managed browser already in the cache.
  6. A download of the Managed browser, unless WAND_BROWSER_DOWNLOAD=0 or Launcher.Download(false) switched it off. Then, and on a platform with nothing to download, the launch fails with launcher.ErrNoBrowser and an error that lists every step tried.

An explicit path is launched as it is, and wand never refuses a browser: once wand.Browser connects, a browser of another major version than the Target Chrome's gets one line through the browser's logger, with both versions. So a developer with Chrome installed runs wand without any download, a fresh container downloads the Target Chrome once, and CI pins the browser with WAND_BROWSER_BIN.

Launcher.ResolveBin() runs the same search and returns the path without launching anything, for a message, or so that one resolution (and at most one download) serves many launches through Launcher.Bin(); wand's own test suite does that once in TestMain.

Domestic platform browsers (lbrowser, the Qianxin, 360 and UOS browsers) are not in the discovery list: none is verified to accept --remote-debugging-port. If yours does, point WAND_BROWSER_BIN or Launcher.Bin() at its executable; on UOS and Kylin, browsers from the app store install under /opt/apps/<app id>/files/, and lbrowser comes as a package whose file list names the executable.

Environment variables

The WAND_BROWSER_* variables set the defaults for a whole process. Precedence is the option set in code, then the -wand= flag, then the variable, then discovery:

Variable Values In code
WAND_BROWSER_BIN path of the browser to launch Launcher.Bin(); the flag is -wand=bin=
WAND_BROWSER_CACHE the browser cache directory Browser.RootDir
WAND_BROWSER_HOSTS URL templates separated by commas Launcher.Hosts()
WAND_BROWSER_DOWNLOAD 0 switches the download off Launcher.Download()
WAND_BROWSER_SOURCE chrome (default) or chromium Launcher.Source()
WAND_BROWSER_BINARY chrome (default) or chrome-headless-shell Launcher.Binary()

Managed browser

When Browser resolution reaches its last step, the launcher downloads a Managed browser once and caches it:

  • Browser source: Chrome for Testing at the Target Chrome by default (chrome, or chrome-headless-shell on request), or a Chromium trunk build at the Companion Chromium. Both are pinned in lib/launcher/pins, hashes included, and every download is verified against those hashes before extraction, whichever host served it. A version or revision of your own has no recorded hash, so its download is not verified, and the log says so.
  • Download hosts: Google's buckets and npmmirror, probed concurrently; the first to answer serves the download and the others are fallbacks. A Download host of your own is a URL template with {version}, {platform} and {archive} placeholders, such as https://mirror.example/chrome-for-testing/{version}/{platform}/{archive}.
  • Cache: wand/browser under the user cache directory ($XDG_CACHE_HOME or ~/.cache on Linux, ~/Library/Caches on macOS, %LocalAppData% on Windows), one subdirectory per browser: chrome-<version>, chrome-headless-shell-<version> or chromium-<revision>.
  • Platforms: Chrome for Testing builds for linux64, linux-arm64, mac-x64, mac-arm64, win32 and win64, and Chromium trunk builds for all of those but linux-arm64; the table in the root README shows which of them the current pins have an archive for. A platform without one, and Windows on arm64, Linux on loong64 or Linux with the musl C library (Alpine) in any case, has nothing to download; there, point WAND_BROWSER_BIN or Launcher.Bin() at a System browser.

In code, Launcher.Source, Launcher.Binary, Launcher.Version, Launcher.Revision and Launcher.Hosts choose the browser and the hosts; launcher.NewBrowser() is the same download helper on its own, which WAND_BROWSER_DOWNLOAD does not switch off.

To download ahead of time, for a container image or an offline bundle, the command prints the path of the browser binary on stdout and its progress on stderr:

go run github.com/headlesslab/wand/cmd/wand-fetch-browser [-source chromium] [-binary chrome-headless-shell]

User mode

launcher.NewUserMode() drives a visible browser on a persistent profile wand owns, so that logins, extensions and settings survive between runs. The profile is wand/user-mode under the user's configuration directory ($XDG_CONFIG_HOME or ~/.config on Linux, ~/Library/Application Support on macOS, %AppData% on Windows), launcher.DefaultUserModeDir, made at the first launch; Launcher.UserDataDir() names another. The browser comes from Browser resolution like any other, so it is the Chrome you have installed unless you say otherwise. The first launch on the profile is the browser's first run, and wand passes --no-first-run: branded Chrome on Linux and macOS would otherwise hold the launch on a modal first-run dialog that nothing dismisses under automation.

User mode does not open Chrome's own profile, the one with your daily sign-ins: since Chrome 136 branded Google Chrome refuses remote debugging on its default profile and exits with "DevTools remote debugging requires a non-default data directory", which is what go-rod's user mode ran into (rod #1189); a launcher pointed at that directory with UserDataDir() gets the same refusal. Sign in once in the wand profile instead, and the session is there on the next run. The Orphan guard is off in User mode, so the browser outlives your program, and a launch finds a browser already listening on the port before starting another. After a browser the launcher started exits, Launcher.Cleanup() removes the profile like any user data directory; Launcher.Kill() leaves it. A launcher that found a browser already listening owns neither it nor the profile: its Kill() and Cleanup() have nothing to do and leave both alone.

Orphan guard

A browser Launcher.Launch() starts does not outlive the wand process, however that process dies: no helper process, no dropped binary, nothing written at launch. The switch is Launcher.Leakless(bool), on in launcher.New() and off in launcher.NewUserMode(), so that a browser you keep working in survives your program.

  • Windows: the browser joins a job object that the kernel closes, and so kills, with the wand process.
  • Linux: the browser is started with the parent-death signal SIGKILL, from a goroutine that holds its thread for the browser's lifetime.
  • Every POSIX platform, macOS included: the browser is started with --remote-debugging-pipe on descriptors 3 and 4 that wand opens and never speaks on, the Pipe tether; a Chromium of 89 or later exits by itself when they close. CDP stays on the WebSocket that Launch() returns. The flag is passed only with its descriptors, so Launcher.FormatArgs() never lists it: a command you build from those arguments yourself has no guard.

With the guard off, or on a browser that rejects the pipe, Launcher.Kill() and Launcher.Cleanup() still kill the browser's process group on the way out; a wand process that dies hard leaves such a browser running.

Under Launcher.XVFB() the tether reaches the browser through xvfb-run all the same; xvfb-run and its Xvfb server are outside it, so a wand process that dies hard leaves the Xvfb server behind.

Documentation

Overview

Package launcher for launching browser utils.

Example (Custom_launch)
package main

import (
	"fmt"
	"os/exec"

	"github.com/headlesslab/wand"
	"github.com/headlesslab/wand/lib/launcher"
	"github.com/headlesslab/wand/lib/utils"
)

func main() {
	// get the browser executable path
	path := launcher.NewBrowser().MustGet()

	l := launcher.New()
	defer l.Cleanup()

	// use the FormatArgs to construct args, this line is optional, you can construct the args manually
	args := l.FormatArgs()

	// A browser started this way has no Orphan guard: it outlives a wand
	// process that dies without killing it. launcher.New().Launch() adds the guard.
	cmd := exec.Command(path, args...)

	parser := launcher.NewURLParser()
	cmd.Stderr = parser
	utils.E(cmd.Start())

	// Reap the browser process once it has exited.
	defer func() { _ = cmd.Wait() }()

	u := launcher.MustResolveURL(<-parser.URL)

	browser := wand.New().ControlURL(u).MustConnect()
	defer browser.MustClose()

	fmt.Println(browser.MustVersion().ProtocolVersion)

}
Output:
1.3
Example (Print_browser_CLI_output)

This example has no output comment, so it is compiled but never run: what it prints is the browser's own command line output, which is not the same twice.

package main

import (
	"os"

	"github.com/headlesslab/wand"
	"github.com/headlesslab/wand/lib/launcher"
)

func main() {
	l := launcher.New().Logger(os.Stdout)
	defer l.Cleanup()

	// Pipe the browser stderr and stdout to os.Stdout .
	browser := wand.New().ControlURL(l.MustLaunch()).MustConnect()
	defer browser.MustClose()
}
Example (Use_system_browser)

This example has no output comment, so it is compiled but never run: it needs a System browser installed, which a machine may not have.

package main

import (
	"github.com/headlesslab/wand"
	"github.com/headlesslab/wand/lib/launcher"
)

func main() {
	if path, exists := launcher.LookPath(); exists {
		l := launcher.New().Bin(path)
		defer l.Cleanup()

		browser := wand.New().ControlURL(l.MustLaunch()).MustConnect()
		defer browser.MustClose()
	}
}

Index

Examples

Constants

View Source
const (
	// EnvBrowserBin is the browser binary to launch, as [Launcher.Bin] and
	// -wand=bin= name one; when set, Browser resolution goes no further.
	EnvBrowserBin = "WAND_BROWSER_BIN"

	// EnvBrowserCache sets the browser cache, DefaultBrowserDir, when the
	// process starts.
	EnvBrowserCache = "WAND_BROWSER_CACHE"

	// EnvBrowserHosts overrides the Download hosts: URL templates separated
	// by commas, in the form DefaultHosts describes.
	EnvBrowserHosts = "WAND_BROWSER_HOSTS"

	// EnvBrowserDownload set to "0" keeps Browser resolution from downloading
	// a Managed browser, as [Launcher.Download] does; any other value, or
	// none, leaves the download on.
	EnvBrowserDownload = "WAND_BROWSER_DOWNLOAD"

	// EnvBrowserSource selects the Browser source: "chrome" for Chrome for
	// Testing, the default, or "chromium" for Chromium trunk builds.
	EnvBrowserSource = "WAND_BROWSER_SOURCE"

	// EnvBrowserBinary selects the Chrome for Testing binary: "chrome", the
	// default, or "chrome-headless-shell".
	EnvBrowserBinary = "WAND_BROWSER_BINARY"
)

The WAND_BROWSER_* environment variables: the defaults, for a whole process, of the launcher options of the same name. The order of precedence is the option set in code, then the -wand= flag of lib/defaults, then these variables, then the launcher's own discovery (ADR-0005).

View Source
const (
	// HeaderName for remote launch.
	HeaderName = "Wand-Launcher"
)

Variables

View Source
var DefaultBrowserDir = cacheDir()

DefaultBrowserDir is the browser cache: EnvBrowserCache when set, otherwise wand/browser under os.UserCacheDir ($XDG_CACHE_HOME or ~/.cache on Linux, ~/Library/Caches on macOS, %LocalAppData% on Windows), or under the temporary directory for a user without a cache directory. Each Managed browser lives in its own subdirectory: chrome-<version>, chrome-headless-shell-<version> or chromium-<revision>.

View Source
var DefaultUserDataDirPrefix = filepath.Join(os.TempDir(), "wand", "user-data")

DefaultUserDataDirPrefix ...

View Source
var DefaultUserModeDir = userModeDir()

DefaultUserModeDir is the profile directory of User mode, the default of Launcher.UserDataDir in NewUserMode: wand/user-mode under os.UserConfigDir ($XDG_CONFIG_HOME or ~/.config on Linux, ~/Library/Application Support on macOS, %AppData% on Windows), or under the temporary directory for a user without a configuration directory. It is a persistent directory wand owns, apart from Chrome's own profile and from the browser cache: a profile is user data, not a re-downloadable artefact (ADR-0010).

View Source
var ErrAlreadyLaunched = errors.New("already launched")

ErrAlreadyLaunched is an error that indicates the launcher has already been launched.

View Source
var ErrNoBrowser = errors.New("[launcher] no browser found")

ErrNoBrowser is the error of a Browser resolution that found nothing: no explicit path, no System browser, no Managed browser in the cache and no download, either switched off or failed. The error wrapping it lists every step tried.

Functions

func DefaultHosts

func DefaultHosts(source Source) []string

DefaultHosts are the Download hosts of a Browser source: Google's bucket and npmmirror, as URL templates. A template names the archive with three placeholders: {version}, the Chrome for Testing version or the Chromium trunk position; {platform}, the Chrome for Testing platform such as linux64 or the Chromium bucket prefix such as Linux_x64; and {archive}, the file name such as chrome-linux64.zip or chrome-linux.zip. Every host is probed concurrently, the first to answer serves the download and the others are its fallbacks.

func LookPath

func LookPath() (found string, has bool)

LookPath searches for a System browser at the paths systemBrowsers lists for the current operating system: the first that exists wins, whatever its version.

func MustResolveURL

func MustResolveURL(u string) string

MustResolveURL is similar to ResolveURL.

func Open

func Open(url string)

Open tries to open the url via system's default browser.

func ResolveURL

func ResolveURL(u string) (string, error)

ResolveURL by requesting the u, it will try best to normalize the u. The format of u can be "9222", ":9222", "host:9222", "ws://host:9222", "wss://host:9222", "https://host:9222" "http://host:9222". The return string will look like: "ws://host:9222/devtools/browser/4371405f-84df-4ad6-9e0f-eab81f7521cc"

An answer that is not a browser's is an error: a status other than 200, as a proxy in the way of the port gives, or a body without a webSocketDebuggerUrl, as a web server that happens to listen on the port gives. The Snapshot took both for a browser and returned a URL with "<nil>" for a path (rod #1176).

Types

type Binary

type Binary string

Binary is the executable a Chrome for Testing archive holds.

const (
	// BinaryChrome is the full browser, the default.
	BinaryChrome Binary = "chrome"

	// BinaryHeadlessShell is chrome-headless-shell, the smaller build that
	// only runs headless.
	BinaryHeadlessShell Binary = "chrome-headless-shell"
)

type Browser

type Browser struct {
	Context context.Context

	// Source of the archive: SourceChrome, the default, or SourceChromium.
	// EnvBrowserSource sets the default.
	Source Source

	// Binary of a Chrome for Testing archive: BinaryChrome, the default, or
	// BinaryHeadlessShell. A Chromium trunk build holds only BinaryChrome.
	// EnvBrowserBinary sets the default.
	Binary Binary

	// Version of Chrome for Testing to use, the Target Chrome by default.
	Version string

	// Revision is the trunk position of the Chromium trunk build to use, the
	// Companion Chromium by default.
	Revision int

	// Hosts to download the archive from, as the URL templates DefaultHosts
	// describes; empty means DefaultHosts of the Source. EnvBrowserHosts
	// sets the default.
	Hosts []string

	// RootDir is the browser cache, DefaultBrowserDir by default.
	RootDir string

	// Logger to print output
	Logger utils.Logger

	// HTTPClient to download the browser
	HTTPClient *http.Client
}

Browser is a helper to download a Managed browser: the Target Chrome from Chrome for Testing by default, or the Companion Chromium from Chromium trunk builds, verified against the pins and cached under RootDir.

func NewBrowser

func NewBrowser() *Browser

NewBrowser with default values, the environment variables applied.

func (*Browser) BinPath

func (lc *Browser) BinPath() string

BinPath to download the browser executable.

func (*Browser) Dir

func (lc *Browser) Dir() string

Dir to download the browser.

func (*Browser) Download

func (lc *Browser) Download() error

Download the browser from the first of the Hosts to answer, verified against the pins before extraction, into Browser.Dir. When that directory exists already nothing is downloaded.

func (*Browser) Get

func (lc *Browser) Get() (string, error)

Get is a smart helper to get the browser executable path. If Browser.BinPath is not valid it will auto download the browser to Browser.BinPath. Concurrent downloads of the same browser, in this process or another, serialize behind a file lock next to Browser.Dir, and the ones that waited find it in place.

func (*Browser) MustGet

func (lc *Browser) MustGet() string

MustGet is similar with Get.

func (*Browser) Validate

func (lc *Browser) Validate() error

Validate returns nil if the browser executable is valid. If the executable is malformed it will return error.

type Launcher

type Launcher struct {
	Flags map[flags.Flag][]string `json:"flags"`
	// contains filtered or unexported fields
}

Launcher is a helper to launch browser binary smartly.

func MustNewManaged

func MustNewManaged(serviceURL string) *Launcher

MustNewManaged is similar to NewManaged.

func New

func New() *Launcher

New returns the default arguments to start browser. Headless will be enabled by default. The Orphan guard (Launcher.Leakless) will be enabled by default. UserDataDir will use OS tmp dir by default, this folder will usually be cleaned up by the OS after reboot. The browser comes from Browser resolution at launch: an explicit path, then a System browser, then a Managed browser, downloaded only as a last resort; check Launcher.Bin, LookPath, Launcher.Download and Launcher.Source for more info.

func NewAppMode

func NewAppMode(u string) *Launcher

NewAppMode is a preset to run the browser like a native application. The u should be a URL.

func NewManaged

func NewManaged(serviceURL string) (*Launcher, error)

NewManaged creates a default Launcher instance from launcher.Manager. The serviceURL must point to a launcher.Manager. It will send a http request to the serviceURL to get the default settings of the Launcher instance. For example if the launcher.Manager running on a Linux machine will return different default settings from the one on Mac. If Launcher.Leakless is enabled, the remote browser will be killed after the websocket is closed.

func NewUserMode

func NewUserMode() *Launcher

NewUserMode is the User mode preset: a visible browser on a persistent profile wand owns, so that logins, extensions and settings survive between runs; useful for the automation of a personal browser. The profile is DefaultUserModeDir, made at launch if missing, and Launcher.UserDataDir overrides it. Branded Google Chrome of 136 or later refuses remote debugging on its own default profile, so a launcher pointed at Chrome's profile directory gets that refusal (ADR-0010). The Orphan guard is off, so the browser survives the wand process; a browser already listening on the port is reused rather than launched again, and a launch that fails on a running browser's port is resolved by closing that browser. After a browser this launcher started exits, Launcher.Cleanup removes the profile like any user data directory; Launcher.Kill leaves it. The browser comes from the same Browser resolution as New, so a System browser is preferred to a Managed one, and in a container the sandbox is off for the same reason it is in New.

func (*Launcher) AlwaysOpenPDFExternally

func (l *Launcher) AlwaysOpenPDFExternally() *Launcher

AlwaysOpenPDFExternally switch. It will set chromium user preferences to enable the always_open_pdf_externally option.

func (*Launcher) Append

func (l *Launcher) Append(name flags.Flag, values ...string) *Launcher

Append values to the flag.

func (*Launcher) Bin

func (l *Launcher) Bin(path string) *Launcher

Bin of the browser binary to launch: the first step of Browser resolution, which then goes no further. It beats the -wand=bin= flag, which beats WAND_BROWSER_BIN; an empty path leaves the search to the steps below: a System browser from LookPath, then the Managed browser, cached or downloaded.

func (*Launcher) Binary

func (l *Launcher) Binary(binary Binary) *Launcher

Binary of the Chrome for Testing archive the Managed browser comes from: the full browser, the default, or chrome-headless-shell. WAND_BROWSER_BINARY sets the default.

func (*Launcher) Cleanup

func (l *Launcher) Cleanup()

Cleanup waits for the browser to exit and removes flags.UserDataDir. Neither wait is unbounded: a browser still running cleanupBound after the call is killed, and the removal, which the helper processes of a browser can hold up for a moment (a crash handler on Windows for seconds), is retried for as long. A launcher that never launched has nothing to wait for; it removes the temporary directory New made up, in case a failed launch wrote the preferences into it, and leaves a directory the caller named alone.

func (*Launcher) Client

func (l *Launcher) Client() (*cdp.Client, error)

Client for launching browser remotely via the launcher.Manager.

func (*Launcher) ClientHeader

func (l *Launcher) ClientHeader() (string, http.Header)

ClientHeader for launching browser remotely via the launcher.Manager.

func (*Launcher) Context

func (l *Launcher) Context(ctx context.Context) *Launcher

Context sets the context.

func (*Launcher) Delete

func (l *Launcher) Delete(name flags.Flag) *Launcher

Delete a flag.

func (*Launcher) Devtools

func (l *Launcher) Devtools(autoOpenForTabs bool) *Launcher

Devtools switch to auto open devtools for each tab.

func (*Launcher) Download

func (l *Launcher) Download(enable bool) *Launcher

Download switch: whether Browser resolution may download the Managed browser when no explicit path, System browser or cached Managed browser is found. On by default; WAND_BROWSER_DOWNLOAD=0 switches it off for a whole process. With it off, a launch that finds nothing fails with ErrNoBrowser. Like Launcher.Bin it is a flag, so it reaches a remote launcher too.

func (*Launcher) Env

func (l *Launcher) Env(env ...string) *Launcher

Env to launch the browser process. The default value is os.Environ(). Usually you use it to set the timezone env. Such as:

Env(append(os.Environ(), "TZ=Asia/Tokyo")...)

func (*Launcher) FormatArgs

func (l *Launcher) FormatArgs() []string

FormatArgs returns the formatted arg list for cli.

func (*Launcher) Get

func (l *Launcher) Get(name flags.Flag) string

Get flag's first value.

func (*Launcher) GetFlags

func (l *Launcher) GetFlags(name flags.Flag) ([]string, bool)

GetFlags from settings.

func (*Launcher) Has

func (l *Launcher) Has(name flags.Flag) bool

Has flag or not.

func (*Launcher) Headless

func (l *Launcher) Headless(enable bool) *Launcher

Headless switch. Whether to run browser in headless mode. A mode without visible UI.

func (*Launcher) HeadlessNew

func (l *Launcher) HeadlessNew(enable bool) *Launcher

HeadlessNew switch is the "--headless=new" switch: https://developer.chrome.com/docs/chromium/new-headless

func (*Launcher) Hosts

func (l *Launcher) Hosts(templates ...string) *Launcher

Hosts to download the Managed browser from, as the URL templates DefaultHosts describes, for Download hosts of your own. WAND_BROWSER_HOSTS sets the default.

func (*Launcher) IgnoreCerts

func (l *Launcher) IgnoreCerts(pks []crypto.PublicKey) error

IgnoreCerts configure the Chrome's ignore-certificate-errors-spki-list argument with the public keys.

func (*Launcher) JSON

func (l *Launcher) JSON() []byte

JSON serialization.

func (*Launcher) KeepUserDataDir

func (l *Launcher) KeepUserDataDir() *Launcher

KeepUserDataDir after remote browser is closed. By default launcher.FlagUserDataDir will be removed.

func (*Launcher) Kill

func (l *Launcher) Kill()

Kill the browser process.

func (*Launcher) Launch

func (l *Launcher) Launch() (string, error)

Launch a standalone temp browser instance and returns the debug url. bin and profileDir are optional, set them to empty to use the default values. If you want to reuse sessions, such as cookies, set the Launcher.UserDataDir to the same location.

With the Orphan guard off (Launcher.Leakless) and a browser already listening on Launcher.RemoteDebuggingPort, Launch attaches to it and returns its URL without starting anything. Such a browser is not the launcher's own: Launcher.PID is zero, and Launcher.Kill and Launcher.Cleanup have nothing to do, waiting for nothing and leaving it and its user data directory alone.

Please note launcher can only be used once.

func (*Launcher) Leakless

func (l *Launcher) Leakless(enable bool) *Launcher

Leakless switch is the Orphan guard: whether the browser dies with the wand process, however that process dies, with no helper process and nothing written at launch. It is on in New and off in NewUserMode. On Windows the browser joins a job object that the kernel closes, and so kills, with the wand process; on Linux it is started with the parent-death signal SIGKILL; on every POSIX platform it is also started with --remote-debugging-pipe on descriptors 3 and 4 that wand opens and never speaks on, so that a Chromium of 89 or later exits by itself when they close. CDP stays on the WebSocket Launcher.Launch returns. The pipe flag is added at launch, with its descriptors, and is not part of Launcher.FormatArgs. When disabled, Launcher.Kill and Launcher.Cleanup still kill the browser's process group.

func (*Launcher) Logger

func (l *Launcher) Logger(w io.Writer) *Launcher

Logger to handle stdout and stderr from browser. For example, pipe all browser output to stdout:

launcher.New().Logger(os.Stdout)

func (*Launcher) MustClient

func (l *Launcher) MustClient() *cdp.Client

MustClient similar to Launcher.Client.

func (*Launcher) MustLaunch

func (l *Launcher) MustLaunch() string

MustLaunch is similar to Launch.

func (*Launcher) NoSandbox

func (l *Launcher) NoSandbox(enable bool) *Launcher

NoSandbox switch. Whether to run browser in no-sandbox mode. Linux users may face "running as root without --no-sandbox is not supported" in some Linux/Chrome combinations. This function helps switch mode easily. Be aware disabling sandbox is not trivial. Use at your own risk. Related doc: https://bugs.chromium.org/p/chromium/issues/detail?id=638180

func (*Launcher) PID

func (l *Launcher) PID() int

PID returns the browser process pid.

func (*Launcher) Preferences

func (l *Launcher) Preferences(pref string) *Launcher

Preferences set chromium user preferences, such as set the default search engine or disable the pdf viewer. The pref is a json string, the doc is here https://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/pref_names.cc

func (*Launcher) ProfileDir

func (l *Launcher) ProfileDir(dir string) *Launcher

ProfileDir is the browser profile the browser will use. When set to empty, the profile 'Default' is used. Related article: https://superuser.com/a/377195

func (*Launcher) Proxy

func (l *Launcher) Proxy(host string) *Launcher

Proxy for the browser.

func (*Launcher) RemoteDebuggingPort

func (l *Launcher) RemoteDebuggingPort(port int) *Launcher

RemoteDebuggingPort to launch the browser. Zero for a random port. Zero is the default value. If it's not zero and the Launcher.Leakless is disabled, the launcher will try to reconnect to it first, if the reconnection fails it will launch a new browser.

func (*Launcher) ResolveBin

func (l *Launcher) ResolveBin() (string, error)

ResolveBin runs Browser resolution (ADR-0005) and returns the browser binary Launcher.Launch would start, without starting it: the explicit path from Launcher.Bin, the -wand=bin= flag or EnvBrowserBin, then a System browser from LookPath, then the Managed browser already in the cache, then its download unless Launcher.Download switched that off. An explicit path is taken as it is; nothing is compared by version. When every step finds nothing the error, wrapping ErrNoBrowser, lists them all. Launch runs it again, so a caller that wants the path for a message, or wants one download to serve many launches, calls it first and passes the result to Launcher.Bin.

func (*Launcher) Revision

func (l *Launcher) Revision(rev int) *Launcher

Revision of the Chromium trunk build the Managed browser is, the Companion Chromium by default. It selects the Chromium source. A revision other than the Companion Chromium has no recorded hash, so its download is not verified.

func (*Launcher) Set

func (l *Launcher) Set(name flags.Flag, values ...string) *Launcher

Set a command line argument when launching the browser. Be careful the first argument is a flag name, it shouldn't contain values. The values the will be joined with comma. A flag can have multiple values. If no values are provided the flag will be a boolean flag. You can use the Launcher.FormatArgs to debug the final CLI arguments. List of available flags: https://peter.sh/experiments/chromium-command-line-switches

func (*Launcher) Source

func (l *Launcher) Source(source Source) *Launcher

Source of the Managed browser, the last steps of Browser resolution, cached or downloaded: Chrome for Testing at the Target Chrome, the default, or Chromium trunk builds at the Companion Chromium. WAND_BROWSER_SOURCE sets the default.

func (*Launcher) StartURL

func (l *Launcher) StartURL(u string) *Launcher

StartURL to launch.

func (*Launcher) UserDataDir

func (l *Launcher) UserDataDir(dir string) *Launcher

UserDataDir is where the browser will look for all of its state, such as cookie and cache. When set to empty, browser will use current OS home dir. Related doc: https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md

func (*Launcher) Version

func (l *Launcher) Version(version string) *Launcher

Version of Chrome for Testing the Managed browser is, the Target Chrome by default. It selects the Chrome for Testing source. A version other than the Target Chrome has no recorded hash, so its download is not verified.

func (*Launcher) WindowPosition

func (l *Launcher) WindowPosition(x, y int) *Launcher

WindowPosition for the browser.

func (*Launcher) WindowSize

func (l *Launcher) WindowSize(x, y int) *Launcher

WindowSize for the browser.

func (*Launcher) WorkingDir

func (l *Launcher) WorkingDir(path string) *Launcher

WorkingDir to launch the browser process.

func (*Launcher) XVFB

func (l *Launcher) XVFB(args ...string) *Launcher

XVFB enables to run browser in by XVFB. Useful when you want to run headful mode on linux.

type Manager

type Manager struct {
	// Logger for key events
	Logger utils.Logger

	// Defaults should return the default Launcher settings
	Defaults func(http.ResponseWriter, *http.Request) *Launcher

	// BeforeLaunch hook is called right before the launching with the Launcher instance that will be used
	// to launch the browser.
	// Such as use it to filter malicious values of Launcher.UserDataDir, Launcher.Bin, or Launcher.WorkingDir.
	BeforeLaunch func(*Launcher, http.ResponseWriter, *http.Request)
}

Manager is used to launch browsers via http server on another machine. The reason why we have Manager is after we launcher a browser, we can't dynamically change its CLI arguments, such as "--headless". The Manager allows us to decide what CLI arguments to pass to the browser when launch it remotely. The work flow looks like:

|      Machine X       |                             Machine Y                                    |
| NewManaged("a.com") -|-> http.ListenAndServe("a.com", launcher.NewManager()) --> launch browser |

1. X send a http request to Y, Y respond default Launcher settings based the OS of Y.
2. X start a websocket connect to Y with the Launcher settings
3. Y launches a browser with the Launcher settings X
4. Y transparently proxy the websocket connect between X and the launched browser

func NewManager

func NewManager() *Manager

NewManager instance.

func (*Manager) ServeHTTP

func (m *Manager) ServeHTTP(w http.ResponseWriter, r *http.Request)

type Source

type Source string

Source is a Browser source: the archive family a Managed browser is downloaded from.

const (
	// SourceChrome is Chrome for Testing, the default: Google's build of the
	// Chrome stable branch, pinned to the Target Chrome.
	SourceChrome Source = "chrome"

	// SourceChromium is Chromium trunk builds from Google's continuous-build
	// archive, pinned to the Companion Chromium: BSD-licensed Chromium for
	// deployments that cannot accept Google Chrome's terms.
	SourceChromium Source = "chromium"
)

type URLParser

type URLParser struct {
	URL    chan string
	Buffer string // buffer for the browser stdout
	// contains filtered or unexported fields
}

URLParser to get control url from stderr.

func NewURLParser

func NewURLParser() *URLParser

NewURLParser instance.

func (*URLParser) Context

func (r *URLParser) Context(ctx context.Context) *URLParser

Context sets the context.

func (*URLParser) Err

func (r *URLParser) Err() error

Err returns the common error parsed from stdout and stderr.

func (*URLParser) Write

func (r *URLParser) Write(p []byte) (n int, err error)

Write interface.

Directories

Path Synopsis
fixtures
chrome-empty command
Package main ...
Package main ...
chrome-exit-err command
Package main ...
Package main ...
chrome-headless command
Package main is a fake browser that answers --dump-dom the way a headless browser does, for the launcher's validation test.
Package main is a fake browser that answers --dump-dom the way a headless browser does, for the launcher's validation test.
chrome-lib-missing command
Package main ...
Package main ...
Package flags ...
Package flags ...
Package pins holds the Target Chrome and everything that rolls with it: the Chrome for Testing Stable version wand is aligned to and its Chromium main branch position, the Protocol roll the protocol layer is generated from, the Companion Chromium trunk build, and the SHA-256 of every Managed browser archive the launcher may download.
Package pins holds the Target Chrome and everything that rolls with it: the Chrome for Testing Stable version wand is aligned to and its Chromium main branch position, the Protocol roll the protocol layer is generated from, the Companion Chromium trunk build, and the SHA-256 of every Managed browser archive the launcher may download.
generate command
Package main is the Roll tool: it computes everything lib/launcher/pins holds and rewrites every place the pins appear, so the launcher, the protocol generator, the Roll, the release workflow and the READMEs all carry the same numbers.
Package main is the Roll tool: it computes everything lib/launcher/pins holds and rewrites every place the pins appear, so the launcher, the protocol generator, the Roll, the release workflow and the READMEs all carry the same numbers.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL