feat(macos): capture URL from Firefox-based browsers via accessibility tree - #134
feat(macos): capture URL from Firefox-based browsers via accessibility tree#134rrogerc wants to merge 2 commits into
Conversation
…y tree Chromium browsers and Safari already report the active tab URL through their scripting interfaces, but Gecko-based browsers (Firefox, Zen, LibreWolf, ...) have no such interface. Read the URL from the AXURL attribute of the window's AXWebArea accessibility node instead, the same mechanism used by other macOS time trackers. This needs no new permission: the watcher already holds Accessibility for window titles. The tree walk is breadth-first and bounded (384 elements); in practice the web area is reached within the first ~70 elements. Private windows are not blanked like the Chrome incognito branch, since Gecko does not expose private-browsing state via accessibility; their window titles carry a Private Browsing suffix that title rules and --exclude-titles can match.
Greptile SummaryAdds URL capture for recognized Gecko-based browsers on macOS.
Confidence Score: 3/5This PR should not merge until excluded Gecko windows also suppress their captured URLs. The new branch writes private Gecko URLs into heartbeat data before exclusion processing, while exclusion replaces only the title, allowing sensitive URLs to be persisted despite a matching privacy rule. aw_watcher_window/macos.swift
|
| Filename | Overview |
|---|---|
| aw_watcher_window/macos.swift | Adds bounded accessibility-tree URL extraction for Gecko browsers, but matching title-exclusion rules do not redact the captured URL. |
Sequence Diagram
sequenceDiagram
participant G as Gecko Browser
participant W as Window Watcher
participant A as ActivityWatch Server
G->>W: AX window event
W->>G: Traverse AX tree
G-->>W: AXWebArea AXURL
W->>W: Apply title exclusion only
W->>A: POST heartbeat with title and URL
Reviews (1): Last reviewed commit: "feat(macos): capture URL from Firefox-ba..." | Re-trigger Greptile
| // note: private windows are not hidden here (unlike the Chrome incognito | ||
| // branch) — Gecko does not mark them in the accessibility tree, and their | ||
| // window titles carry a "Private Browsing" suffix for rules to match | ||
| data.url = geckoURL(window: axElement) |
There was a problem hiding this comment.
There was a problem hiding this comment.
Good catch — fixed in e99e221: when title exclusion matches, the URL is now cleared as well. This also closes the same pre-existing gap in the Chromium and Safari branches, whose URLs were likewise retained when an exclusion rule matched the title.
Title exclusion replaced only data.title, so a browser window matching --exclude-title or an --exclude-titles pattern still reported its URL, which identifies the page at least as precisely as the title. Clear the URL as well; this also closes the same pre-existing gap for the Chromium and Safari branches.
What
Captures the current page URL from Gecko-based browsers (Firefox, Firefox Developer Edition/Nightly, Zen, LibreWolf, Waterfox, Floorp) on macOS, filling the gap where Chromium browsers and Safari already report URLs via their scripting interfaces. Gecko has no scripting interface for tabs, but exposes the loaded page's URL on the
AXURLattribute of the window'sAXWebAreaaccessibility node — the same mechanism other macOS time trackers use.How
On each window event for a known Gecko browser, a breadth-first search of the focused window's accessibility tree finds the first
AXWebAreanode and returns itsAXURL. The top-level document's web area sits shallow in Gecko's tree and is reached before any iframe web areas, so the first hit is the current page. The traversal is bounded (384 elements) so a pathological tree can't stall the watcher; in testing the web area is found within the first ~70 elements.No new permission is required — the watcher already holds Accessibility for window titles. Runs in-process via the HIServices C API (no AppleScript).
Relation to #109
Same goal, different mechanism. #109 reads the URL bar's displayed text through a System Events AppleScript path (
combo box 1 of group 1 of toolbar "Navigation" of ...), which depends on the toolbar layout (breaks in browsers with customized UIs such as Zen), returns the displayed/typed text rather than the loaded URL (Firefox hides the scheme by default), and requires a separate Automation permission grant for System Events. ReadingAXURLoff the web area avoids all three: it is the canonical loaded-page URL, layout-independent, and covered by the existing Accessibility permission.Testing
arm64-apple-macosx12.0target.Limitations
--exclude-titlescan match — and as of the second commit, a matching exclusion rule clears the URL as well as the title (previously the Chromium/Safari branches retained their URLs on excluded windows too). (Same situation as the existing Safari branch, which cannot detect private windows either.)accessibility.force_disabled=1), no URL is recorded and behavior falls back to title-only, as today.