← Commit history

Fix issue #22 Finding 4 (AdityaAngajala): a stalled background Chrome-for-Testing prewarm blocked EVERY browser_open_window on a machine that had system Chrome AND Edge, while browser_readiness simultaneously reported browserSource:'system' with a valid chrome.exe. Two defects, both mine from the native-first change: (1) getOrLaunchBrowser still kicked the retired v1.8.71 'converge this box to CfT' background prewarm on a native launch — I removed that same kick from chrome.warmup() in v1.9.90 and missed this one, so a native launch still started a ~150 MB download nobody asked for. Removed; native-first fetches CfT only as the genuine last resort. (2) chrome.readiness() computed ready = found && !installing, conflating 'a background download is in flight' with 'nothing is drivable' — so an in-flight or STALLED last-resort download made the whole subsystem not-ready and the open gate refused on !rd.ready. ready now means only 'a drivable browser exists'; installing stays a separate informational field and never gates drivability.

John Lauer ·1cb633acd3 ·3mo ago ·parent 21be85e
5 files changed +27−17
adom-bridge-puppeteer-manifest.json+4−4
@@ -1,10 +1,10 @@ {   "manifest_version": 1,   "name": "puppeteer",-  "version": "1.9.93",-  "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.9.93/adom-bridge-puppeteer-v1.9.93.zip",-  "sha256": "10226a5310997d022261358bf5e28edcedcef9a1dcbd4dc7291b501d659e8128",-  "size": 367447,+  "version": "1.9.94",+  "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.9.94/adom-bridge-puppeteer-v1.9.94.zip",+  "sha256": "daa095bbbe58ded5fd855d7f2b5a2b81ae3e53f1993dd88a21df7dcdcaaa6a7e",+  "size": 368040,   "verbPrefixes": [     "browser_",     "desktop_recorder_",
src/BRIDGE_VERSION+1−1
@@ -1 +1 @@-1.9.93+1.9.94
src/bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "puppeteer",   "displayName": "Puppeteer (Chrome for Testing + Native)",-  "version": "1.9.93",+  "version": "1.9.94",   "description": "Drives a browser ALREADY on the machine \u2014 installed Chrome, else Microsoft Edge (every Windows PC ships with Edge) \u2014 launched with a FRESH isolated profile, so the common case has NO ~150 MB Chrome-for-Testing download and it never touches the user's real tabs/logins. Binds its local server to LOOPBACK (127.0.0.1) only, so no Windows Firewall 'allow Node through the firewall' prompt ever pops. Chrome for Testing is fetched only as a LAST RESORT if the machine has no Chromium browser at all. SPAWN-VERIFIED fallback: pup tries each detected browser (Chrome \u2192 Edge \u2192 CfT) and actually launches it, falling through to the next if one won't start (and handling browsers like Edge that relaunch onto another PID), so a corrupt/partial install never hard-fails an open. The browser that launches is cached as the default (persisted across restarts) so it isn't re-probed each time. On spawn the bridge SELF-WARMS: detects browsers + disk, and only if the box has no Chrome/Edge and no cached CfT does it background-fetch CfT so the first open is instant. browser_use pins a specific browser (chrome | edge | cft | auto); {browser:'chrome',install:true} downloads & installs REAL Google Chrome (user-scoped, no admin) on an Edge-only box. browser_readiness (READ-ONLY) reports which browser will be used + the full candidate list + the default + free disk. Every failure returns a specific errorCode + _hint (chrome_install_no_disk, chrome_download_network, chrome_install_permission, chrome_stable_not_detected, \u2026). Launches with FULL browser permissions by default for full debug (strictPermissions:true opts out). Headful automation: open/close windows+tabs, navigate, screenshot, eval JS, record. pup is a GENERIC, non-profile browser only \u2014 every session is a fresh isolated Chrome/Edge process, never the user's real signed-in browser; profile defaults to sessionId. To drive the user's REAL Chrome/Edge (their profile, cookies, SSO), use the Adom browser EXTENSION's nbrowser_* verbs \u2014 a separate bridge, not pup's job. macOS (v1.9.74+): full parity with mac-native mechanics \u2014 background-by-default is the app-level hide (windows stay drivable/screenshottable while hidden), raise/lower map to unhide+activate/hide, browser_alert_window posts a native toast whose click focuses the window, browser_use {browser:'chrome',install:true} installs Chrome from the official dmg, and taskbar identity/badging remains Windows-only.",   "homepage": "https://wiki.adom.inc/adom/adom-desktop",   "author": "Adom Inc.",
src/chrome.js+9−1
@@ -457,7 +457,15 @@ function readiness() {   const b = resolveBrowser();   const det = detectChrome();   const installing = !!_installInFlight || state.phase === 'installing';-  const ready = b.found && !installing;   // a drivable browser is available (system OR cached CfT)+  // v1.9.94 (issue #22 Finding 4) — `ready` means "a drivable browser EXISTS", nothing more. The old+  // `&& !installing` conflated "a background CfT download is in flight" with "nothing is drivable", so+  // an in-flight (or STALLED) last-resort download reported the whole subsystem not-ready even on a box+  // with system Chrome AND Edge sitting right there — and browser_open_window's gate refuses on+  // `!rd.ready`, so every open failed with chrome_for_testing_installing while readiness itself+  // reported browserSource:"system" with a valid executable path. Self-contradictory and blocking.+  // `installing` is still returned as its own field for callers that care about download progress;+  // it must never gate drivability. (Native-first also means we rarely download CfT at all now.)+  const ready = b.found;                  // a drivable browser is available (system OR cached CfT)   const d = readDefault();   return {     ready,
src/server.js+12−10
@@ -4825,16 +4825,18 @@ async function getOrLaunchBrowser(profileName, { freshProfile = false, strictPer       // Record what actually launched so the open response + hints are accurate, and       // cache it as the auto-default so we don't re-probe next time.       browser._pupChosen = { kind: chosen.kind, source: chosen.source, executablePath: chosen.executablePath || null };-      // v1.8.71 (#202): a BRANDED-browser launch means CfT wasn't cached — kick a background-      // CfT install (once per bridge process) so this box converges to the deterministic-      // CfT-first order by its next session. Never blocks or stalls the current open.-      if (chosen.kind !== 'chrome-for-testing' && !global._cftPrewarmKicked && (process.platform === 'win32' || process.platform === 'darwin')) {-        global._cftPrewarmKicked = true;-        try {-          console.log(`[prewarm] branded fallback (${chosen.kind}) — starting background CfT install so future opens use Chrome for Testing`);-          chrome.ensureChromeReady({ background: true });-        } catch (e) {}-      }+      // v1.9.94 (issue #22 Finding 4, AdityaAngajala) — REMOVED: the v1.8.71 "converge this box to+      // CfT" background prewarm. It was the CfT-FIRST doctrine's convergence step, and native-first+      // (v1.9.90) retired that doctrine — I removed the same kick from chrome.warmup() then and MISSED+      // this one, so a native launch still started a ~150 MB CfT download nobody asked for. Worse, it+      // was actively BLOCKING: while that download is in flight, chrome.readiness() reported the whole+      // browser subsystem as not-ready (see the `ready` fix in chrome.js), and browser_open_window's+      // gate refuses on `!rd.ready` — so a stalled prewarm made EVERY open fail with+      // chrome_for_testing_installing on a machine that had a perfectly good system Chrome AND Edge.+      // Measured live on H2O (AD 1.9.177): readiness simultaneously reported browserSource:"system"+      // with a valid chrome.exe AND blocked opens at 0%. Native-first means we do not fetch CfT when a+      // native browser works — CfT is fetched only as the last resort (no Chromium at all), which+      // chrome.warmup() already handles at spawn. Do NOT reintroduce a convergence prewarm here.       _lastChosenBrowser = { ...browser._pupChosen, fallbackFrom: triedList.map(t => `${t.kind}(${t.source})`) };       if (chosen.executablePath) chrome.markVerified(chosen);       if (triedList.length) console.log(`[launch] launched ${chosen.kind}(${chosen.source}) after ${triedList.length} browser(s) failed to spawn`);