# `CDPEx.Browser`
[🔗](https://github.com/patrols/cdp_ex/blob/v0.9.0/lib/cdp_ex/browser.ex#L1)

A GenServer owning a headless Chrome OS process and its CDP connections.

`CDPEx.Browser` launches Chrome (via `CDPEx.Chrome`), opens a browser-level
`CDPEx.Connection`, and creates pages on demand. It is the lifecycle owner:

  * It **traps exits** and links every connection, so a page connection crash
    is isolated (the page is dropped; the browser and other pages survive),
    while a browser-connection or Chrome death stops the browser cleanly.
  * For a **launched** browser, `terminate/2` always runs `CDPEx.Chrome.stop/1`
    — the no-orphan guarantee. Because that relies on `terminate/2`, supervise a
    launched browser with a `:shutdown` timeout, **not** `:brutal_kill`.

A browser started via `CDPEx.connect/2` (connect-mode, `chrome: nil`) is the
exception: it never launched Chrome, so `terminate/2` only closes the pages it
opened and never reaps the remote process — `:brutal_kill` is harmless there.
That target cleanup is **best-effort**: each `Target.closeTarget` is bounded by
the call timeout, and against a slow-but-alive remote with several open pages the
supervised shutdown budget can elapse before every tab is closed, leaving some
open on the remote Chrome (it never affects the local process, which holds no
Chrome to reap).

Most callers use the `CDPEx` facade rather than this module directly.

# `t`

```elixir
@type t() :: %CDPEx.Browser{
  auths: term(),
  browser_conn: term(),
  chrome: term(),
  connected: term(),
  host: term(),
  intercepts: term(),
  opts: term(),
  pages: term(),
  parent: term(),
  pending_auth: term(),
  port: term(),
  proxy_auth: term(),
  sessions: term()
}
```

# `close_page`

```elixir
@spec close_page(GenServer.server(), CDPEx.Page.t()) :: :ok | {:error, :unknown_page}
```

Closes a page opened with `new_page/2`.

Returns `{:error, :unknown_page}` if the page does not belong to this browser
(a handle from a different browser, or one that was already closed).

# `new_page`

```elixir
@spec new_page(
  GenServer.server(),
  keyword()
) :: {:ok, CDPEx.Page.t()} | {:error, term()}
```

Opens a new page (tab) and returns a `CDPEx.Page` handle.

Options:
  * `:transport` — `:dedicated` (one WebSocket per page, strong crash isolation)
    or `:session` (multiplexed over the browser socket via a flattened CDP
    session — fewer sockets, but all session pages share the browser
    connection's fate: if it drops, they all go). A **launched** browser
    defaults to `:dedicated`; a **connected** browser (`CDPEx.connect/2`)
    defaults to `:session` and rejects `:dedicated` with
    `{:error, {:unsupported_transport, :dedicated}}`. Any other value returns
    `{:error, {:invalid_transport, value}}`.
  * `:prevent_alerts` — inject no-op `alert`/`confirm`/`prompt` (default `true`)

# `start_link`

```elixir
@spec start_link(keyword()) :: GenServer.on_start()
```

Starts a browser. See `CDPEx.Chrome` for launch options.

Pass `:owner` (a pid) to set the process whose death triggers the browser's cleanup,
overriding the default (the calling process). `CDPEx.Pool` uses this when adopting a
browser it launched in a short-lived task.

# `stop`

```elixir
@spec stop(GenServer.server()) :: :ok
```

Stops the browser, closing all pages.

A launched browser also kills its Chrome; a connected one (`CDPEx.connect/2`)
closes only the pages it opened and leaves the remote Chrome running.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
