Class: Browserctl::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/browserctl/client.rb

Overview

Thin IPC client that wraps each browserd command as a Ruby method call.

Instance Method Summary collapse

Constructor Details

#initialize(socket_path = nil) ⇒ Client

Returns a new instance of Client.



12
13
14
# File 'lib/browserctl/client.rb', line 12

def initialize(socket_path = nil)
  @socket_path = socket_path || auto_discover_socket
end

Instance Method Details

#auth_check(name, include_cookies: false, state: nil, suggested_flow: nil) ⇒ Object

Runs the auth_required detector against a named page. Returns either ‘{ ok: true, auth_required: false }` or an AUTH_REQUIRED error response.

Parameters:

  • name (String)

    page name

  • include_cookies (Boolean) (defaults to: false)

    also feed the page’s current cookies into the detector (catches expired-cookie auth)

  • state (String, nil) (defaults to: nil)

    bundle name the caller was working with; passed back verbatim so callers can recover without bookkeeping

  • suggested_flow (String, nil) (defaults to: nil)

    flow name to surface when triggered



320
321
322
323
324
325
326
# File 'lib/browserctl/client.rb', line 320

def auth_check(name, include_cookies: false, state: nil, suggested_flow: nil)
  call("auth_check",
       name: name,
       include_cookies: include_cookies,
       state: state,
       suggested_flow: suggested_flow)
end

#call(cmd, **params) ⇒ Object



16
17
18
19
20
21
22
# File 'lib/browserctl/client.rb', line 16

def call(cmd, **params)
  result = communicate(JSON.generate({ cmd: cmd }.merge(params)))
  Recording.append(cmd, response: result, **params) if result[:ok]
  result
rescue Errno::ENOENT, Errno::ECONNREFUSED
  raise DaemonUnavailableError, "browserd is not running — start it with: browserd"
end

#click(name, selector = nil, ref: nil) ⇒ Hash

Clicks an element identified by CSS selector or snapshot ref.

Parameters:

  • name (String)

    logical page name

  • selector (String, nil) (defaults to: nil)

    CSS selector

  • ref (String, nil) (defaults to: nil)

    snapshot ref (e.g. “e3”)

Returns:

  • (Hash)

    ‘{ ok: true }` or `{ error: }`

Raises:

  • (ArgumentError)


50
51
52
53
54
55
# File 'lib/browserctl/client.rb', line 50

def click(name, selector = nil, ref: nil)
  raise ArgumentError, "click: provide selector or ref:" unless selector || ref

  call("click", name: name, selector: selector, ref: ref,
                capture_post_snapshot: Recording.active ? true : nil)
end

#cookies(name) ⇒ Hash

Returns all cookies for a named page.

Parameters:

  • name (String)

    logical page name

Returns:

  • (Hash)

    ‘{ ok: true, cookies: [Hash] }` or `{ error: }`



147
# File 'lib/browserctl/client.rb', line 147

def cookies(name)              = call("cookies", name: name)

#delete_cookies(name) ⇒ Hash

Deletes all cookies for a named page.

Parameters:

  • name (String)

    logical page name

Returns:

  • (Hash)

    ‘{ ok: true }` or `{ error: }`



164
# File 'lib/browserctl/client.rb', line 164

def delete_cookies(name) = call("delete_cookies", name: name)

#devtools(name) ⇒ Hash

Returns the Chrome DevTools URL for a named page.

Parameters:

  • name (String)

    logical page name

Returns:

  • (Hash)

    ‘{ ok: true, devtools_url: }` or `{ error: }`



126
# File 'lib/browserctl/client.rb', line 126

def devtools(name)             = call("devtools", name: name)

#dialog_accept(name, text: nil) ⇒ Hash

Pre-registers a one-shot handler to accept the next JS dialog on a page.

Parameters:

  • name (String)

    logical page name

  • text (String, nil) (defaults to: nil)

    prompt text for window.prompt dialogs (ignored for alert/confirm)

Returns:

  • (Hash)

    ‘{ ok: true }` or `{ error: }`



279
# File 'lib/browserctl/client.rb', line 279

def dialog_accept(name, text: nil) = call("dialog_accept", name: name, text: text)

#dialog_dismiss(name) ⇒ Hash

Pre-registers a one-shot handler to dismiss the next JS dialog on a page.

Parameters:

  • name (String)

    logical page name

Returns:

  • (Hash)

    ‘{ ok: true }` or `{ error: }`



284
# File 'lib/browserctl/client.rb', line 284

def dialog_dismiss(name)           = call("dialog_dismiss", name: name)

#evaluate(name, expression) ⇒ Hash

Evaluates a JavaScript expression and returns the result.

Parameters:

  • name (String)

    logical page name

  • expression (String)

    JavaScript expression

Returns:

  • (Hash)

    ‘{ ok: true, result: }` or `{ error: }`



102
# File 'lib/browserctl/client.rb', line 102

def evaluate(name, expression) = call("evaluate", name: name, expression: expression)

#export_cookies(name, path) ⇒ Hash

Exports all cookies for a named page to a JSON file. File I/O is client-side; daemon provides the cookie data.

Parameters:

  • name (String)

    logical page name

  • path (String)

    file path to write cookies to

Returns:

  • (Hash)

    ‘{ ok: true, path:, count: }` or `{ error: }`



171
172
173
174
175
176
177
178
# File 'lib/browserctl/client.rb', line 171

def export_cookies(name, path)
  result = call("cookies", name: name)
  return result unless result[:ok]

  FileUtils.mkdir_p(File.dirname(path))
  File.open(path, "w", 0o600) { |f| f.write(JSON.generate(result[:cookies])) }
  { ok: true, path: path, count: result[:cookies].length }
end

#fetch(key) ⇒ Hash

Retrieves a value from the daemon-scoped key-value store.

Parameters:

  • key (String)

    storage key

Returns:

  • (Hash)

    ‘{ ok: true, value: }` or `{ error:, code: “key_not_found” }`



142
# File 'lib/browserctl/client.rb', line 142

def fetch(key)                 = call("fetch", key: key)

#fill(name, selector = nil, value = nil, ref: nil) ⇒ Hash

Fills an input element with a value.

Parameters:

  • name (String)

    logical page name

  • selector (String, nil) (defaults to: nil)

    CSS selector

  • value (String, nil) (defaults to: nil)

    text to type

  • ref (String, nil) (defaults to: nil)

    snapshot ref

Returns:

  • (Hash)

    ‘{ ok: true }` or `{ error: }`

Raises:

  • (ArgumentError)


63
64
65
66
67
68
# File 'lib/browserctl/client.rb', line 63

def fill(name, selector = nil, value = nil, ref: nil)
  raise ArgumentError, "fill: provide selector or ref:" unless selector || ref

  call("fill", name: name, selector: selector, ref: ref, value: value,
               capture_post_snapshot: Recording.active ? true : nil)
end

#hover(name, selector = nil, ref: nil) ⇒ Hash

Moves the mouse to the centre of the element matched by selector.

Parameters:

  • name (String)

    logical page name

  • selector (String) (defaults to: nil)

    CSS selector

Returns:

  • (Hash)

    ‘{ ok: true }` or `{ error: }`

Raises:

  • (ArgumentError)


245
246
247
248
249
# File 'lib/browserctl/client.rb', line 245

def hover(name, selector = nil, ref: nil)
  raise ArgumentError, "hover: provide selector or ref:" unless selector || ref

  call("hover", name: name, selector: selector, ref: ref)
end

#import_cookies(name, path) ⇒ Hash

Imports cookies from a JSON file into a named page.

Parameters:

  • name (String)

    logical page name

  • path (String)

    file path to read cookies from

Returns:

  • (Hash)

    ‘{ ok: true, count: }` or `{ error: }`

Raises:



184
185
186
187
188
189
# File 'lib/browserctl/client.rb', line 184

def import_cookies(name, path)
  raise Browserctl::Error, "cookie file not found: #{path}" unless File.exist?(path)

  cookies = JSON.parse(File.read(path), symbolize_names: true)
  call("import_cookies", name: name, cookies: cookies)
end

Navigates a page to a URL. Returns ‘challenge: true` when Cloudflare is detected.

Parameters:

  • name (String)

    logical page name

  • url (String)

    destination URL

Returns:

  • (Hash)

    ‘{ ok: true, url:, challenge: }` or `{ error: }`



43
# File 'lib/browserctl/client.rb', line 43

def navigate(name, url)        = call("navigate", name: name, url: url)

#page_close(name) ⇒ Hash

Closes a named page and removes it from the session.

Parameters:

  • name (String)

    logical page name

Returns:

  • (Hash)

    ‘{ ok: true }` or `{ error: }`



33
# File 'lib/browserctl/client.rb', line 33

def page_close(name)           = call("page_close", name: name)

#page_focus(name) ⇒ Hash

Brings the named page’s tab to front. Only works when browserd was started with –headed.

Parameters:

  • name (String)

    logical page name

Returns:

  • (Hash)

    ‘{ ok: true }` or `{ error: }`



131
# File 'lib/browserctl/client.rb', line 131

def page_focus(name) = call("page_focus", name: name)

#page_listHash

Lists all open page names.

Returns:

  • (Hash)

    ‘{ pages: [String] }`



37
# File 'lib/browserctl/client.rb', line 37

def page_list                  = call("page_list")

#page_open(name, url: nil) ⇒ Hash

Opens or focuses a named browser page.

Parameters:

  • name (String)

    logical page name

  • url (String, nil) (defaults to: nil)

    optional URL to navigate to after opening

Returns:

  • (Hash)

    ‘{ ok: true, name: }` or `{ error: }`



28
# File 'lib/browserctl/client.rb', line 28

def page_open(name, url: nil)  = call("page_open",  name: name, url: url)

#pause(name, message: nil) ⇒ Hash

Pauses automation on a page so a human can interact directly.

Parameters:

  • name (String)

    logical page name

  • message (String, nil) (defaults to: nil)

    optional message displayed to the human

Returns:

  • (Hash)

    ‘{ ok: true, paused: true, message: }` or `{ error: }`



116
# File 'lib/browserctl/client.rb', line 116

def pause(name, message: nil)  = call("pause",  name: name, message: message)

#pingHash

Checks if browserd is alive.

Returns:

  • (Hash)

    ‘{ ok: true, pid: }` or raises if daemon is not running



106
# File 'lib/browserctl/client.rb', line 106

def ping                       = call("ping")

#press(name, key) ⇒ Hash

Fires a keydown + keyup event for the given key name on a page.

Parameters:

  • name (String)

    logical page name

  • key (String)

    key name e.g. “Enter”, “Tab”, “Escape”, “ArrowDown”

Returns:

  • (Hash)

    ‘{ ok: true }` or `{ error: }`



239
# File 'lib/browserctl/client.rb', line 239

def press(name, key) = call("press", name: name, key: key)

#resume(name) ⇒ Hash

Resumes automation on a paused page.

Parameters:

  • name (String)

    logical page name

Returns:

  • (Hash)

    ‘{ ok: true, paused: false }` or `{ error: }`



121
# File 'lib/browserctl/client.rb', line 121

def resume(name)               = call("resume", name: name)

#screenshot(name, path: nil, full: false) ⇒ Hash

Takes a screenshot of a named page.

Parameters:

  • name (String)

    logical page name

  • path (String, nil) (defaults to: nil)

    output path (default: ~/.browserctl/screenshots/)

  • full (Boolean) (defaults to: false)

    capture full page (default: false)

Returns:

  • (Hash)

    ‘{ ok: true, path: }` or `{ error: }`



75
# File 'lib/browserctl/client.rb', line 75

def screenshot(name, path: nil, full: false) = call("screenshot", name: name, path: path, full: full)

#select(name, selector = nil, value = nil, ref: nil) ⇒ Hash

Sets a <select> element’s value and fires a change event.

Parameters:

  • name (String)

    logical page name

  • selector (String, nil) (defaults to: nil)

    CSS selector for the select element

  • value (String, nil) (defaults to: nil)

    option value to select

  • ref (String, nil) (defaults to: nil)

    element ref from a prior snapshot

Returns:

  • (Hash)

    ‘{ ok: true }` or `{ error: }`

Raises:

  • (ArgumentError)


269
270
271
272
273
# File 'lib/browserctl/client.rb', line 269

def select(name, selector = nil, value = nil, ref: nil)
  raise ArgumentError, "select: provide selector or ref:" unless selector || ref

  call("select", name: name, selector: selector, ref: ref, value: value)
end

Sets a cookie on a named page.

Parameters:

  • name (String)

    logical page name

  • cookie_name (String)

    cookie name (e.g. “cf_clearance”)

  • value (String)

    cookie value

  • domain (String)

    cookie domain (e.g. “.example.com”)

  • path (String) (defaults to: "/")

    cookie path (default: “/”)

Returns:

  • (Hash)

    ‘{ ok: true }` or `{ error: }`



156
157
158
159
# File 'lib/browserctl/client.rb', line 156

def set_cookie(name, cookie_name, value, domain, path: "/")
  call("set_cookie", name: name, cookie_name: cookie_name,
                     value: value, domain: domain, path: path)
end

#shutdownHash

Shuts down browserd gracefully.

Returns:

  • (Hash)

    ‘{ ok: true }`



110
# File 'lib/browserctl/client.rb', line 110

def shutdown                   = call("shutdown")

#snapshot(name, format: "elements", diff: false) ⇒ Hash

Takes a DOM snapshot. Returns ‘challenge: true` when Cloudflare is detected.

Parameters:

  • name (String)

    logical page name

  • format (String) (defaults to: "elements")

    “elements” (interactable elements JSON) or “html” (raw HTML)

  • diff (Boolean) (defaults to: false)

    return only elements changed since last snapshot

Returns:

  • (Hash)

    ‘{ ok: true, snapshot:, challenge: }` or `{ ok: true, html:, challenge: }` or `{ error: }`



82
83
84
# File 'lib/browserctl/client.rb', line 82

def snapshot(name, format: "elements", diff: false)
  call("snapshot", name: name, format: format, diff: diff)
end

#state_delete(name) ⇒ Object

Permanently deletes a state bundle.



310
# File 'lib/browserctl/client.rb', line 310

def state_delete(name) = call("state_delete", name: name)

#state_info(name) ⇒ Object

Reads a single bundle’s manifest.



307
# File 'lib/browserctl/client.rb', line 307

def state_info(name) = call("state_info", name: name)

#state_listObject

Lists all stored state bundles (manifest only — no payload decryption).



304
# File 'lib/browserctl/client.rb', line 304

def state_list = call("state_list")

#state_load(name, passphrase: nil, skip_auth_check: false) ⇒ Object

Restores a .bctl bundle into the running daemon. The daemon runs the auth_required detector against the bundle’s cookies before applying; callers that have already verified the bundle (e.g. workflow ‘load_state` after a successful rotate) can pass `skip_auth_check: true` to bypass it.



299
300
301
# File 'lib/browserctl/client.rb', line 299

def state_load(name, passphrase: nil, skip_auth_check: false)
  call("state_load", name: name, passphrase: passphrase, skip_auth_check: skip_auth_check)
end

#state_save(name, origins: nil, flow: nil, flow_version: nil, passphrase: nil) ⇒ Hash

Saves browser state (cookies + storage) into a single .bctl bundle.

Returns:

  • (Hash)

    ‘{ ok:, path:, origins:, cookies:, encrypted: }` or `{ error: }`



288
289
290
291
292
# File 'lib/browserctl/client.rb', line 288

def state_save(name, origins: nil, flow: nil, flow_version: nil, passphrase: nil)
  call("state_save",
       name: name, origins: origins, flow: flow,
       flow_version: flow_version, passphrase: passphrase)
end

#storage_delete(name, stores: "all") ⇒ Hash

Clears localStorage and/or sessionStorage for the page.

Parameters:

  • name (String)

    logical page name

  • stores (String) (defaults to: "all")

    “local”, “session”, or “all” (default: “all”)

Returns:

  • (Hash)

    ‘{ ok: true }` or `{ error: }`



231
232
233
# File 'lib/browserctl/client.rb', line 231

def storage_delete(name, stores: "all")
  call("storage_delete", name: name, stores: stores)
end

#storage_export(name, path, stores: "all") ⇒ Hash

Exports localStorage and/or sessionStorage to a JSON file.

Parameters:

  • name (String)

    logical page name

  • path (String)

    destination file path

  • stores (String) (defaults to: "all")

    “local”, “session”, or “all” (default: “all”)

Returns:

  • (Hash)

    ‘{ ok: true, path:, key_count: }` or `{ error: }`



215
216
217
# File 'lib/browserctl/client.rb', line 215

def storage_export(name, path, stores: "all")
  call("storage_export", name: name, path: path, stores: stores)
end

#storage_get(name, key, store: "local") ⇒ Hash

Returns the value of a localStorage or sessionStorage key.

Parameters:

  • name (String)

    logical page name

  • key (String)

    storage key

  • store (String) (defaults to: "local")

    “local” or “session” (default: “local”)

Returns:

  • (Hash)

    ‘{ ok: true, value: }` or `{ error: }`



196
197
198
# File 'lib/browserctl/client.rb', line 196

def storage_get(name, key, store: "local")
  call("storage_get", name: name, key: key, store: store)
end

#storage_import(name, path) ⇒ Hash

Imports storage keys from a JSON file into the page’s localStorage.

Parameters:

  • name (String)

    logical page name

  • path (String)

    source file path

Returns:

  • (Hash)

    ‘{ ok: true, origins: N, key_count: M }` or `{ error: }`



223
224
225
# File 'lib/browserctl/client.rb', line 223

def storage_import(name, path)
  call("storage_import", name: name, path: path)
end

#storage_set(name, key, value, store: "local") ⇒ Hash

Sets a localStorage or sessionStorage key.

Parameters:

  • name (String)

    logical page name

  • key (String)

    storage key

  • value (String)

    storage value

  • store (String) (defaults to: "local")

    “local” or “session” (default: “local”)

Returns:

  • (Hash)

    ‘{ ok: true }` or `{ error: }`



206
207
208
# File 'lib/browserctl/client.rb', line 206

def storage_set(name, key, value, store: "local")
  call("storage_set", name: name, key: key, value: value, store: store)
end

#store(key, value) ⇒ Hash

Stores a value in the daemon-scoped key-value store.

Parameters:

  • key (String)

    storage key

  • value (Object)

    value to store (must be JSON-serialisable)

Returns:

  • (Hash)

    ‘{ ok: true }` or `{ error: }`



137
# File 'lib/browserctl/client.rb', line 137

def store(key, value)          = call("store", key: key, value: value)

#upload(name, selector = nil, path = nil, ref: nil) ⇒ Hash

Sets a file-input element to the given file path.

Parameters:

  • name (String)

    logical page name

  • selector (String, nil) (defaults to: nil)

    CSS selector for the file input

  • path (String, nil) (defaults to: nil)

    absolute or relative file path

  • ref (String, nil) (defaults to: nil)

    element ref from a prior snapshot

Returns:

  • (Hash)

    ‘{ ok: true }` or `{ error: }`

Raises:

  • (ArgumentError)


257
258
259
260
261
# File 'lib/browserctl/client.rb', line 257

def upload(name, selector = nil, path = nil, ref: nil)
  raise ArgumentError, "upload: provide selector or ref:" unless selector || ref

  call("upload", name: name, selector: selector, ref: ref, path: path)
end

#url(name) ⇒ Hash

Returns the current URL of a named page.

Parameters:

  • name (String)

    logical page name

Returns:

  • (Hash)

    ‘{ ok: true, url: }` or `{ error: }`



96
# File 'lib/browserctl/client.rb', line 96

def url(name)                  = call("url",      name: name)

#wait(name, selector, timeout: 30) ⇒ Hash

Waits for a CSS selector to appear within the given timeout.

Parameters:

  • name (String)

    logical page name

  • selector (String)

    CSS selector to wait for

  • timeout (Numeric) (defaults to: 30)

    seconds before giving up (default: 30)

Returns:

  • (Hash)

    ‘{ ok: true, selector: }` or `{ error: }`



91
# File 'lib/browserctl/client.rb', line 91

def wait(name, selector, timeout: 30) = call("wait", name: name, selector: selector, timeout: timeout)