Module: Clacky::Utils::BrowserDetector
- Defined in:
- lib/clacky/utils/browser_detector.rb
Overview
Detects a running browser (Chrome/Edge) that has remote debugging enabled.
Detection strategy:
1. Scan known UserData directories for DevToolsActivePort file.
This file contains the exact port + WS path — most reliable.
Returns { mode: :ws_endpoint, value: "ws://127.0.0.1:PORT/PATH" }
2. Verify the port is actually reachable via TCP probe.
3. Nothing found or port unreachable → returns nil (browser not running).
Supported environments: WSL, Linux, macOS.
Class Method Summary collapse
-
.detect ⇒ Hash
Detect a running debuggable browser.
- .detect_via_active_port_file ⇒ Hash?
-
.user_data_dirs ⇒ Array<String>
Returns ordered list of candidate UserData dirs to check.
-
.verify_port(detected) ⇒ Boolean
Verify that the detected browser port is actually reachable.
Class Method Details
.detect ⇒ Hash
Detect a running debuggable browser. Scans for DevToolsActivePort file across all platforms (macOS/Linux/WSL). Returns the detected WebSocket endpoint only if the port is reachable.
26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/clacky/utils/browser_detector.rb', line 26 def self.detect os = EnvironmentDetector.os_type Clacky::Logger.debug("[BrowserDetector] Starting browser detection (OS: #{os})...") detected = detect_via_active_port_file unless detected Clacky::Logger.warn("[BrowserDetector] ✗ No reachable browser found") return { status: :not_found } end Clacky::Logger.info("[BrowserDetector] ✓ Browser detected and reachable: #{detected[:mode]} → #{detected[:value]}") detected.merge(status: :ok) end |
.detect_via_active_port_file ⇒ Hash?
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/clacky/utils/browser_detector.rb', line 46 def self.detect_via_active_port_file Clacky::Logger.debug("[BrowserDetector] Scanning UserData directories for DevToolsActivePort...") dirs = user_data_dirs Clacky::Logger.debug("[BrowserDetector] Candidate directories: #{dirs.size} found") dirs.each do |dir| port_file = File.join(dir, "DevToolsActivePort") next unless File.exist?(port_file) Clacky::Logger.debug("[BrowserDetector] Found DevToolsActivePort: #{port_file}") ws = parse_active_port_file(port_file) unless ws Clacky::Logger.debug("[BrowserDetector] ✗ Failed to parse #{port_file}") next end Clacky::Logger.debug("[BrowserDetector] Parsed WS endpoint: #{ws}") # ⭐️ Verify port BEFORE returning — skip stale files candidate = { mode: :ws_endpoint, value: ws } if verify_port(candidate) Clacky::Logger.debug("[BrowserDetector] ✓ Port is reachable, using this endpoint") return candidate else Clacky::Logger.debug("[BrowserDetector] ✗ Port not reachable, trying next directory...") end end Clacky::Logger.debug("[BrowserDetector] No reachable browser found") nil end |
.user_data_dirs ⇒ Array<String>
Returns ordered list of candidate UserData dirs to check.
106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/clacky/utils/browser_detector.rb', line 106 def self.user_data_dirs os = EnvironmentDetector.os_type Clacky::Logger.debug("[BrowserDetector] Detected OS: #{os}") case os when :wsl then wsl_user_data_dirs when :linux then linux_user_data_dirs when :macos then macos_user_data_dirs else Clacky::Logger.warn("[BrowserDetector] Unknown OS type: #{os}") [] end end |
.verify_port(detected) ⇒ Boolean
Verify that the detected browser port is actually reachable. Extracts port from ws:// URL and attempts TCP connection.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/clacky/utils/browser_detector.rb', line 84 def self.verify_port(detected) return false unless detected port = case detected[:mode] when :ws_endpoint # ws://127.0.0.1:9222/devtools/... detected[:value][/ws:\/\/127\.0\.0\.1:(\d+)/, 1]&.to_i end return false unless port && port > 0 reachable = tcp_open?("127.0.0.1", port) Clacky::Logger.debug("[BrowserDetector] Port #{port} reachable: #{reachable}") reachable end |