glendam/chrome
An actor that manages an instance of the chrome browser.
Communication with Chrome uses either pipes (FD 3/4) or WebSocket,
selected via the TransportMode in BrowserConfig.
All messages to the browser are sent through this actor, and responses are returned to the sender. The actor manages associating responses with the correct request by adding auto-incrementing ids to the requests, so callers don’t need to worry about this.
When the browser managed by this actor is closed, the actor will also exit.
To start a browser, it’s preferable to use the launch functions from the root Glendam module, which perform additional checks and validations.
Types
A typed BrowserConfig value exposed by this module.
pub type BrowserConfig {
BrowserConfig(
path: String,
args: List(String),
start_timeout: Int,
log_level: LogLevel,
transport: TransportMode,
)
}
Constructors
-
BrowserConfig( path: String, args: List(String), start_timeout: Int, log_level: LogLevel, transport: TransportMode, )The
BrowserConfigvariant.
A typed BrowserInstance value exposed by this module.
pub opaque type BrowserInstance
A typed BrowserVersion value exposed by this module.
pub type BrowserVersion {
BrowserVersion(
protocol_version: String,
product: String,
revision: String,
user_agent: String,
js_version: String,
)
}
Constructors
-
BrowserVersion( protocol_version: String, product: String, revision: String, user_agent: String, js_version: String, )The
BrowserVersionvariant.
Errors that may occur during launch of the browser instance
pub type LaunchError {
UnknownOperatingSystem
CouldNotFindExecutable
FailedToStart(reason: String)
UnresponsiveAfterStart
ProtocolVersionMismatch(
supported_version: String,
got_version: String,
)
}
Constructors
-
UnknownOperatingSystemThe operating system has no configured Chrome search paths.
-
CouldNotFindExecutableThe
CouldNotFindExecutablevariant. -
FailedToStart(reason: String)The browser actor could not start.
-
UnresponsiveAfterStartThis is used by the launch functions of the root
glendammodule -
ProtocolVersionMismatch( supported_version: String, got_version: String, )The
ProtocolVersionMismatchvariant.Arguments
- supported_version
-
Version supported by the protocol
- got_version
-
Version the browser reported
The log level the browser is using.
pub type LogLevel {
LogLevelSilent
LogLevelWarnings
LogLevelInfo
LogLevelDebug
}
Constructors
-
LogLevelSilentLog nothing
-
LogLevelWarningsLog only warnings, this is the default
-
LogLevelInfoLog normal but uncommon events, like buffering a long message, shutdown
-
LogLevelDebugLog everything, including protocol payloads
A typed Message value exposed by this module.
pub type Message {
Shutdown(reply_with: process.Subject(Nil))
Kill
Call(
reply_with: process.Subject(
Result(dynamic.Dynamic, RequestError),
),
method: String,
params: option.Option(json.Json),
session_id: option.Option(String),
)
Send(method: String, params: option.Option(json.Json))
AddListener(
listener: process.Subject(dynamic.Dynamic),
method: String,
)
RemoveListener(listener: process.Subject(dynamic.Dynamic))
UnexpectedPortMessage(dynamic.Dynamic)
PortResponse(String)
SetLogLevel(LogLevel)
PortExit(Int)
WsResponse(String)
WsDown(dynamic.Dynamic)
}
Constructors
-
Shutdown(reply_with: process.Subject(Nil))Initiate graceful shutdown of the browser
-
KillKill by shutting down actor
-
Call( reply_with: process.Subject( Result(dynamic.Dynamic, RequestError), ), method: String, params: option.Option(json.Json), session_id: option.Option(String), )Make a protocol call and receive response
-
Send(method: String, params: option.Option(json.Json))Make a protocol call and ignore response
-
AddListener( listener: process.Subject(dynamic.Dynamic), method: String, )The
AddListenervariant. -
RemoveListener(listener: process.Subject(dynamic.Dynamic))The
RemoveListenervariant. -
UnexpectedPortMessage(dynamic.Dynamic)(From Port) Message that could not be matched
-
PortResponse(String)(From Port) Protocol Message
-
SetLogLevel(LogLevel)Allows you to set the log level of the running instance
-
PortExit(Int)(From Port) Port has exited
-
WsResponse(String)(From WebSocket) Complete JSON message from gun
-
WsDown(dynamic.Dynamic)(From WebSocket) gun connection down
Errors that may occur when a protocol request is made
pub type RequestError {
PortError(reason: String)
ChromeAgentTimeout
ChromeAgentDown
ProtocolError
BrowserError(code: Int, message: String, data: String)
NotFoundError
RuntimeException(text: String, line: Int, column: Int)
}
Constructors
-
PortError(reason: String)The browser transport rejected a request.
-
ChromeAgentTimeoutOTP actor timeout
-
ChromeAgentDownOTP actor down
-
ProtocolErrorThe ProtocolError variant is used by
/protocoldomains to return a homogeneous error type for all requests. -
BrowserError(code: Int, message: String, data: String)This is an error response from the browser itself
-
NotFoundErrorA requested resource could not be found
-
RuntimeException(text: String, line: Int, column: Int)A runtime exception thrown by JavaScript code being evaluated in the browser
The transport mode used to communicate with the Chrome browser.
pub type TransportMode {
Pipe
WebSocket
Auto
}
Constructors
-
PipeFD 3/4 pipe (default on non-Windows)
-
WebSocketWebSocket via –remote-debugging-port=0 (default on Windows)
-
AutoAuto-detect based on OS (Pipe on Unix, WebSocket on Windows)
Values
pub fn add_listener(
browser browser: process.Subject(Message),
method method: String,
) -> process.Subject(dynamic.Dynamic)
Add an event listener (Experimental! Event forwarding is not really supported yet)
pub fn call(
browser browser: process.Subject(Message),
method method: String,
params params: option.Option(json.Json),
session_id session_id: option.Option(String),
time_out time_out: Int,
) -> Result(dynamic.Dynamic, RequestError)
Issue a protocol call to the browser and expect a response
pub const default_timeout: Int
The default_timeout constant used by this module.
pub fn get_default_chrome_args() -> List(String)
Get the default arguments the browser should be started with,
to be used inside the launch_with_config function
pub fn get_local_chrome_path() -> Result(String, LaunchError)
Try to find a hermetic chrome installation in the current directory,
of the kind installed by browser_install or the puppeteer install script.
The installation must be in a directory called chrome.
pub fn get_system_chrome_path() -> Result(String, LaunchError)
Try to find a system chrome installation in some obvious places.
pub fn get_version(
browser browser: process.Subject(Message),
) -> Result(BrowserVersion, RequestError)
Hardcoded protocol call to get the browser version See: https://chromedevtools.github.io/devtools-protocol/tot/Browser/#method-getVersion
pub fn is_local_chrome_path(
relative_path relative_path: String,
os_family os_family: @internal OsFamily,
) -> Bool
Returns whether the given path is a local chrome installation, of the kind
created by browser_install or the puppeteer install script.
This can be used to scan a directory with simplifile.get_files.
pub fn launch() -> Result(process.Subject(Message), LaunchError)
Cleverly try to find a chrome installation and launch it with reasonable defaults.
- If
GLENDAM_BROWSER_PATHis set, use that - If a local chrome installation is found, use that
- If a system chrome installation is found, use that
- If none of the above, return an error
If you want to always use a specific chrome installation, take a look at launch_with_config or
launch_with_env to set the path explicitly.
Be aware that this function will not validate that the browser launched successfully, please use the higher level functions from the root Glendam module instead if you want these guarantees.
pub fn launch_window() -> Result(
process.Subject(Message),
LaunchError,
)
Like launch, but launches the browser with a visible window, not
in headless mode, which is useful for debugging and development.
pub fn launch_with_config(
cfg cfg: BrowserConfig,
) -> Result(process.Subject(Message), LaunchError)
Launch a browser with the given configuration,
to populate the arguments, use get_default_chrome_args.
Be aware that this function will not validate that the browser launched successfully, please use the higher level functions from the root Glendam module instead if you want these guarantees.
Example
let config =
BrowserConfig(
path: "chrome/linux-116.0.5793.0/chrome-linux64/chrome",
args: get_default_chrome_args(),
start_timeout: 5000,
log_level: LogLevelWarnings,
transport: Auto,
)
let browser_result = launch_with_config(config)
pub fn launch_with_env() -> Result(
process.Subject(Message),
LaunchError,
)
Launch a browser, and read the configuration from environment variables. The browser path variable must be set, all others will fall back to a default.
Be aware that this function will not validate that the browser launched successfully, please use the higher level functions from the root Glendam module instead if you want these guarantees.
Configuration variables:
GLENDAM_BROWSER_PATH- The path to the browser executableGLENDAM_BROWSER_ARGS- The arguments to pass to the browser, separated by spacesGLENDAM_BROWSER_TIMEOUT- The timeout in milliseconds to wait for the browser to start, must be an integerGLENDAM_LOG_LEVEL- The log level to use, one ofsilent,warnings,info,debug
pub fn listen_once(
browser browser: process.Subject(Message),
method method: String,
time_out time_out: Int,
) -> Result(dynamic.Dynamic, RequestError)
A blocking call that waits for a specified event to arrive once, and then resolves, removing the event listener.
pub fn quit(
browser browser: process.Subject(Message),
) -> Result(Nil, RequestError)
Quit the browser and shut down the actor.
This function will attempt graceful shutdown, if the browser does not respond in time,
it will also send a kill signal to the actor to force it to shut down.
The result typing reflects the success of graceful shutdown.
pub fn remove_listener(
browser browser: process.Subject(Message),
listener listener: process.Subject(dynamic.Dynamic),
) -> Nil
Remove an event listener (Experimental! Event forwarding is not really supported yet)
pub fn send(
browser browser: process.Subject(Message),
method method: String,
params params: option.Option(json.Json),
) -> Nil
Issue a protocol call to the browser without waiting for a response,
when the response arrives, it will be discarded.
It’s probably best to not use this and instead just use call and discard unneeded responses.
All protocol calls yield a response and can be used with call, even if they
don’t specify any response parameters.
pub fn set_log_level(
browser browser: process.Subject(Message),
level level: LogLevel,
) -> Nil
Allows you to set the log level of a running browser instance