CDPEx.Connection (CDPEx v0.4.0)

Copy Markdown View Source

A GenServer owning a single CDP WebSocket connection.

This is the heart of cdp_ex's OTP model. It connects and upgrades a Mint.WebSocket in init/1, then runs in :active mode so every inbound frame arrives as a process message in handle_info/2. The GenServer:

  • matches command replies back to the caller by JSON-RPC id (concurrent callers are fine — each call/4 blocks only its own caller),
  • routes unsolicited events to subscribers and one-shot waiters,
  • answers WebSocket pings with pongs,
  • fails every pending caller with {:error, {:ws_closed, reason}} and stops if the socket drops — no caller is left hanging.

One connection backs one socket: the browser endpoint, or a page endpoint at /devtools/page/<targetId>. A single connection may carry both untagged browser/page frames and many flattened sessions' frames, demultiplexed by sessionId. CDPEx.Browser starts and monitors these.

Summary

Types

Error reasons from call/5 — and from every Network/Page op layered on it. Precisely specced (not term()) so Dialyzer flags drift at the source.

t()

Functions

Blocks until an event for which matcher.(params) returns true, or timeout.

Sends a CDP command and blocks until its reply (or timeout).

Returns a specification to start this module under a supervisor.

Closes the WebSocket and stops the connection.

Starts a connection to the given ws://host:port/path URL.

Subscribes the calling process to a CDP event method (e.g. "Page.lifecycleEvent") or to :all events. Delivered as {:cdp_event, conn_pid, method, params, session_id}session_id is nil for browser/page-level events.

Removes a subscription created with subscribe/2.

Types

call_error()

@type call_error() ::
  {:cdp_error, String.t(), term()}
  | {:timeout, String.t()}
  | {:ws_closed, term()}
  | :noproc

Error reasons from call/5 — and from every Network/Page op layered on it. Precisely specced (not term()) so Dialyzer flags drift at the source.

t()

@type t() :: %CDPEx.Connection{
  all_subscribers: term(),
  conn: term(),
  monitors: term(),
  next_id: term(),
  pending: term(),
  ref: term(),
  subscribers: term(),
  waiters: term(),
  websocket: term(),
  ws_send_error: term()
}

Functions

await_event(conn, matcher, timeout \\ 10000, opts \\ [])

@spec await_event(GenServer.server(), (map() -> boolean()), timeout(), keyword()) ::
  {:ok, map()}
  | {:error, {:timeout, :await_event} | :noproc | {:ws_closed, term()}}

Blocks until an event for which matcher.(params) returns true, or timeout.

matcher receives the event params map. Returns {:ok, params} (the matched event's params) on a match, or {:error, reason} where reason is {:timeout, :await_event} (no matching event in time) or :noproc / {:ws_closed, _} (the connection itself went away) — callers must be able to tell those apart.

Pass opts with session_id: sid to only match events from that session.

call(conn, method, params \\ %{}, timeout \\ 10000, opts \\ [])

@spec call(GenServer.server(), String.t(), map(), timeout(), keyword()) ::
  {:ok, map()} | {:error, call_error()}

Sends a CDP command and blocks until its reply (or timeout).

Returns {:ok, result}, {:error, {:cdp_error, method, error}} on a protocol error, {:error, {:timeout, method}}, or {:error, {:ws_closed, reason}} / {:error, :noproc} if the connection drops or is already gone.

Pass opts with session_id: sid to address a flattened CDP session.

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

close(conn)

@spec close(GenServer.server()) :: :ok

Closes the WebSocket and stops the connection.

start_link(ws_url, opts \\ [])

@spec start_link(
  String.t(),
  keyword()
) :: GenServer.on_start()

Starts a connection to the given ws://host:port/path URL.

Options: :upgrade_timeout (ms, default 15_000) and :name (registers the GenServer). Returns {:ok, pid} once the WebSocket handshake completes.

subscribe(conn, method)

@spec subscribe(GenServer.server(), String.t() | :all) :: :ok

Subscribes the calling process to a CDP event method (e.g. "Page.lifecycleEvent") or to :all events. Delivered as {:cdp_event, conn_pid, method, params, session_id}session_id is nil for browser/page-level events.

The subscription is removed automatically if the subscribing process exits, so a crashed subscriber can't accumulate in the connection.

unsubscribe(conn, method)

@spec unsubscribe(GenServer.server(), String.t() | :all) :: :ok

Removes a subscription created with subscribe/2.