Skip to content

pepicrft/browse

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Browse

Hex.pm Hex Docs CI License: MIT

Shared browser automation contract and pool implementation for Elixir browser backends.

Browse defines a transport-agnostic contract for browser automation packages such as a Chrome implementation, a Servo implementation, or any future engine backend. The goal is to expose browser capabilities without leaking implementation details such as CDP sessions or engine-specific RPC handles.

Installation

Add browse to your list of dependencies in mix.exs:

def deps do
  [
    {:browse, "~> 0.1.0"}
  ]
end

Browser Implementations

Browse provides the shared contract and pool implementation. To drive a real browser, use a backend package such as:

Design

Browse is not a browser engine and it does not speak a wire protocol itself, but it does provide the shared pool implementation and browser capability contract that engine backends plug into.

It provides:

  • Browse.Browser as the shared browser capability behavior
  • Browse as the actual pool implementation and facade

This lets packages like Chrona and a future Servo implementation expose the same API while keeping CDP or any other backend protocol as an implementation detail.

Example

Configure your pools and the default pool:

config :browse,
  default_pool: MyApp.ChromePool,
  pools: [
    MyApp.ChromePool: [implementation: MyApp.Chrome, pool_size: 4],
    MyApp.SecondaryChromePool: [implementation: MyApp.Chrome, pool_size: 2]
  ]

Start the configured pools under your application supervisor:

children = Browse.children()

Or start one configured pool directly:

{:ok, _pid} = Browse.start_link(MyApp.ChromePool)

Then use the pool through the unified API:

Browse.checkout(fn browser ->
  :ok = Browse.navigate(browser, "https://example.com")
  Browse.capture_screenshot(browser, format: "jpeg", quality: 90)
end)

If you have multiple pools, you can still target one explicitly:

Browse.checkout(MyApp.SecondaryChromePool, fn browser ->
  Browse.current_url(browser)
end)

You can also override config at startup time if needed:

{:ok, _pid} =
  Browse.start_link(MyApp.ChromePool,
    implementation: MyApp.Chrome,
    pool_size: 1
  )

Behavior

Implementations are expected to satisfy Browse.Browser.

Browse owns pool startup, checkout, and worker lifecycle. Implementations are configured per pool and only provide browser initialization, termination, and browser operations such as navigation and screenshots.

Pooling is not a behavior. It is a concrete concern of this package, implemented by Browse itself. Backends plug into that runtime by implementing Browse.Browser.

The browser handle passed around by the behavior is intentionally opaque. Each implementation is free to represent it however it needs.

Telemetry

Browse emits telemetry for the lifecycle it owns:

  • [:browse, :pool, :start, :start | :stop | :exception]
  • [:browse, :checkout, :start | :stop | :exception]
  • [:browse, :worker, :init, :start | :stop | :exception]
  • [:browse, :worker, :remove]
  • [:browse, :worker, :terminate]

Attach handlers with :telemetry.attach_many/4:

events = [
  [:browse, :pool, :start, :stop],
  [:browse, :checkout, :stop],
  [:browse, :worker, :terminate]
]

:telemetry.attach_many(
  "browse-metrics",
  events,
  fn event, measurements, metadata, _config ->
    IO.inspect({event, measurements, metadata}, label: "browse telemetry")
  end,
  nil
)

See Browse.Telemetry for the full event contract, measurements, and metadata.

License

MIT License. See LICENSE for details.

About

Shared browser automation behaviour for Elixir renderers

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages