← Commit history
v0.1.3/ext0.1.2: TITLE-based hwnd correlation (chrome.windows bounds are logical px, OS rects physical - broke badge on 150% scaled displays); title match is DPI-independent
7 files changed
+20−15
bridge/BRIDGE_VERSION+1−1@@ -1 +1 @@-0.1.2+0.1.3
bridge/bridge.json+2−2@@ -2,8 +2,8 @@ "manifest_version": 1, "name": "native-browser", "displayName": "Adom Native Browser (Chrome + Edge)",- "version": "0.1.2",- "expectedExtensionVersion": "0.1.1",+ "version": "0.1.3",+ "expectedExtensionVersion": "0.1.2", "description": "Drives the user's REAL signed-in Chrome/Edge via an installed extension (native-messaging transport). Mirrors the puppeteer bridge's verb surface as nbrowser_* but runs inside the actual logged-in profile, so cookies/SSO/saved-logins/captcha human-trust all work. The bridge binds an ephemeral loopback port (PORTS.md compliant) and writes a discovery file; the native-messaging host pumps stdio <-> this bridge; the extension never touches a TCP port.", "homepage": "https://wiki.adom.inc/adom/adom-browser-extension", "author": "Adom Inc.",
bridge/package.json+1−1@@ -1,6 +1,6 @@ { "name": "adom-native-browser-bridge",- "version": "0.1.2",+ "version": "0.1.3", "private": true, "description": "adom-desktop bridge for the Adom native-browser extension (Chrome + Edge)", "main": "server.js",
bridge/server.js+9−5@@ -444,8 +444,12 @@ async function chromeWindowsDetailed() { return ws.filter((w) => /Chrome_WidgetWin/.test(w.className || '') && !/for Testing/.test(w.title || '')); } function matchHwnd(list, bounds, title) {+ // TITLE first — DPI-INDEPENDENT. chrome.windows bounds are LOGICAL px, but the OS window rects are+ // PHYSICAL px, so on a scaled display (e.g. 150%) bounds won't match. The OS Chrome window title+ // contains the page title (and the profile email), so a title substring is a reliable correlation.+ if (title && String(title).trim().length >= 6) { const t = String(title).slice(0, 30); const m = list.find((w) => (w.title || '').includes(t)); if (m) return m.hwnd; }+ // Fallback: bounds (only reliable at 100% scaling). if (bounds) for (const w of list) { const r = w.rect || {}; if (r.left != null && r.top != null && Math.abs(r.left - bounds.left) <= 24 && Math.abs(r.top - bounds.top) <= 24) return w.hwnd; }- if (title) { const t = String(title).slice(0, 24); const m = list.find((w) => (w.title || '').includes(t)); if (m) return m.hwnd; } return null; } // (Re)paint the "Adom is driving" badge from a nbrowser_owned / nbrowser_list_windows payload, correlating@@ -458,8 +462,8 @@ async function badgeSpawnsIn(payload) { if (payload && Array.isArray(payload.spawned)) for (const s of payload.spawned) if (s.kind === 'window' && s.windowId != null) spawns.push({ windowId: s.windowId, bounds: s.bounds, title: s.title }); if (payload && Array.isArray(payload.sessions)) for (const s of payload.sessions) { if (s.windowId == null) continue;- if (s.owner === 'agent-spawned') spawns.push({ windowId: s.windowId, bounds: s.bounds, title: s.url });- else if (s.owner === 'agent-opened' && s.id) owned.push({ sid: s.id, bounds: s.bounds, title: s.url });+ if (s.owner === 'agent-spawned') spawns.push({ windowId: s.windowId, bounds: s.bounds, title: s.title || s.url });+ else if (s.owner === 'agent-opened' && s.id) owned.push({ sid: s.id, bounds: s.bounds, title: s.title || s.url }); } const fresh = spawns.filter((s) => !spawnHwnd.has(s.windowId)); if (!fresh.length && !owned.length) return;@@ -1291,8 +1295,8 @@ async function onHostFrame(frame) { const list = await chromeWindowsDetailed(); // Correlate by BOUNDS first (profile-independent + precise — the new-window DIFF can't tell // profiles apart and badged the WRONG profile's taskbar button). Diff only as a fallback.- if (payload.bounds) neu = matchHwnd(list, payload.bounds, null);- if (!neu) neu = list.map((w) => w.hwnd).find((h) => !preOpenHwnds.has(h)) || null;+ neu = matchHwnd(list, payload.bounds, payload.title); // title-first (DPI-safe), then bounds+ if (!neu) neu = list.map((w) => w.hwnd).find((h) => !preOpenHwnds.has(h)) || null; // diff fallback (title empty while loading) } catch {} if (neu) { lastHwnd = neu; if (sid) sessionHwnd.set(sid, neu); taskbar(neu, { overlay: { badge: 'adom', tooltip: 'Adom is driving this browser' } }); break; } await new Promise((r) => setTimeout(r, 250));
extension/manifest.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 3, "name": "Adom for Chrome & Edge", "short_name": "Adom",- "version": "0.1.1",+ "version": "0.1.2", "description": "Drive your real, logged-in Chrome/Edge from the Adom ecosystem \u2014 the native-browser counterpart to pup.", "minimum_chrome_version": "116", "background": {
extension/src/native.js+2−1@@ -501,7 +501,7 @@ export async function openWindow(args = {}) { // the taskbar badge — the old "new Chrome window" diff can't tell profiles apart and badged the wrong one. let bounds; try { const w2 = await chrome.windows.get(win.id); bounds = { left: w2.left, top: w2.top, width: w2.width, height: w2.height }; } catch { bounds = { left: win.left, top: win.top, width: win.width, height: win.height }; } const res = {- ok: true, sessionId: sid, tabId: String(tab.id), windowId: win.id, url: tab.url || args.url, bounds,+ ok: true, sessionId: sid, tabId: String(tab.id), windowId: win.id, url: tab.url || args.url, title: tab.title, bounds, _hint: 'New window opened in the BACKGROUND — the user\'s focus is deliberately NOT stolen. ' + POLITE_HINT + ' Screenshot it where it sits with nbrowser_screenshot (CDP) or AD desktop_screenshot_window (WGC); both capture a background/occluded window, so NEVER foreground it to grab a shot. To raise it you must justify it (userRequestedForeground:true + foregroundReason) AND warn the user first. Remember to nbrowser_close_window {sessionId:"' + sid + '"} when done so you don\'t leave abandoned windows.', };@@ -602,6 +602,7 @@ export async function listWindows(args = {}) { state: w.state, bounds: { left: w.left, top: w.top, width: w.width, height: w.height }, url: (w.tabs || []).find((t) => t.active)?.url,+ title: (w.tabs || []).find((t) => t.active)?.title, // for DPI-independent hwnd correlation (OS title match) }; }); if (args.mine) sessions = sessions.filter((s) => s.owner !== 'user'); // only windows an agent opened/spawned
native-browser-bridge-manifest.json+4−4@@ -1,8 +1,8 @@ { "manifest_version": 1,- "version": "0.1.2",- "url": "https://wiki.adom.inc/download/adom/adom-browser-extension/0.1.2/native-browser-bridge-v0.1.2.bin",- "sha256": "0742cfbb954e12600a8bc453401d88881dc636fc9da5aa95636151c06671e84c",- "size": 53867,+ "version": "0.1.3",+ "url": "https://wiki.adom.inc/download/adom/adom-browser-extension/0.1.3/native-browser-bridge-v0.1.3.bin",+ "sha256": "10124cf825d36e6c734c607b238d89705ddf4446b6d1b72f8f6886ae3cd3b4ec",+ "size": 54092, "released_at": "2026-07-14T00:00:00Z" }