← Commit history

Self-detecting host: walks its process ancestry (node<-cmd<-chrome|msedge) to tag the browser, so a browser registers correctly even when an old extension's hello omits it — Edge proven live in parallel with Chrome (0.3.3)

John Lauer ·47c862bb6b ·4mo ago ·parent 4c24e7d
2 files changed +43−5
host/native-host.js+42−4
@@ -101,6 +101,40 @@ function writeToExtension(obj) {   process.stdout.write(json); } +// Which browser launched THIS host? The extension's hello carries `browser` on new builds — prefer it.+// Otherwise (old extension mid-upgrade) detect it from our process ancestry: the host is+// node.exe <- (native-host.bat) cmd.exe <- chrome.exe | msedge.exe. Walk parents until we hit a browser.+// Result is cached; only runs at all for an extension that didn't report its browser.+let _hostBrowser = null;+function hostBrowser(msg) {+  if (msg && msg.browser) return msg.browser;+  if (_hostBrowser) return _hostBrowser;+  _hostBrowser = detectBrowserFromTree();+  return _hostBrowser;+}+function detectBrowserFromTree() {+  try {+    const out = require('child_process').execSync(+      'powershell -NoProfile -Command "Get-CimInstance Win32_Process | Select-Object ProcessId,ParentProcessId,Name | ConvertTo-Csv -NoTypeInformation"',+      { timeout: 5000, windowsHide: true }+    ).toString();+    const byPid = new Map();+    for (const line of out.split(/\r?\n/)) {+      const m = line.match(/^"?(\d+)"?,"?(\d+)"?,"?([^"]+)"?$/);+      if (m) byPid.set(Number(m[1]), { ppid: Number(m[2]), name: String(m[3]).toLowerCase() });+    }+    let pid = process.ppid, hops = 0;+    while (pid && hops++ < 8) {+      const p = byPid.get(pid);+      if (!p) break;+      if (p.name.includes('msedge')) return 'edge';+      if (p.name.includes('chrome')) return 'chrome';+      pid = p.ppid;+    }+  } catch { /* fall through to default */ }+  return 'chrome';+}+ // ---- stdin (from the extension) -> bridge ---------------------------------- let bridge = null; let inbuf = Buffer.alloc(0);@@ -117,11 +151,15 @@ function pumpStdin() {     // the bridge registers the connection under this profile.     if (msg && msg.type === 'hello') {       clearTimeout(helloFallback);-      // Key the singleton by BROWSER + profile so the same account in Chrome AND Edge each get their-      // own host (instead of the 2nd browser's host exiting on a shared lock — the "Native host has-      // exited" collision). The bridge keys connections the same way, so all coexist in parallel.+      // BROWSER + profile keying so the same account in Chrome AND Edge each get their own host (instead+      // of the 2nd browser's host exiting on a shared lock — the "Native host has exited" collision).+      // Prefer the browser the extension reported; else detect it from THIS host's process ancestry+      // (chrome.exe vs msedge.exe) so an OLD extension that doesn't send `browser` still tags correctly.+      // TAG the hello with it so the bridge keys the connection the SAME way (all coexist in parallel).+      const browser = hostBrowser(msg);+      msg.browser = browser;       const _id = (msg.profile && (msg.profile.email || msg.profile.id)) || 'default';-      acquireSingleton(`${msg.browser || 'chrome'}:${_id}`);+      acquireSingleton(`${browser}:${_id}`);     }     sendToBridge(msg);   }
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "adom-browser-extension",-  "version": "0.3.2",+  "version": "0.3.3",   "type": "app",   "title": "Adom Browser Extension (Chrome + Edge)",   "description": "Drive your real, logged-in Chrome/Edge from the Adom ecosystem \u2014 the nbrowser_* native-browser bridge (counterpart to pup). Multi-profile driving, a read-only credential-library query over the browser's own saved logins (Chrome + Edge), and hands-free vendor login automation, so chip CAD / datasheets download past every login wall in your real signed-in session.",