← Commit history

v2.0.739 (insiders): Never a bare Chrome taskbar button during recovery (pup-bridge#143): an OS-level health-tick safety net stamps a pup identity on any pup Chrome-for-Testing window that has no session yet (the gap after a restart or worker-reload cycle while the extension channel re-handshakes), so a pup window never falls back to the stock Chrome button; it reads+stamps only and never touches the lane/kill paths, and the real per-thread tile upgrades it once adopt_stray re-adopts the window.

John Lauer ·f222edafd0 ·8d ago ·parent 8fb8524
4 files changed +64−13
rust/Cargo.lock+12−12
@@ -10,7 +10,7 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"  [[package]] name = "adom-pup-bridge"-version = "2.0.738"+version = "2.0.739" dependencies = [  "pup-browser",  "pup-cdp",@@ -781,7 +781,7 @@ dependencies = [  [[package]] name = "pup-browser"-version = "2.0.738"+version = "2.0.739" dependencies = [  "pup-core",  "pup-host",@@ -793,7 +793,7 @@ dependencies = [  [[package]] name = "pup-cdp"-version = "2.0.738"+version = "2.0.739" dependencies = [  "serde_json",  "thiserror",@@ -803,7 +803,7 @@ dependencies = [  [[package]] name = "pup-core"-version = "2.0.738"+version = "2.0.739" dependencies = [  "serde",  "serde_json",@@ -813,7 +813,7 @@ dependencies = [  [[package]] name = "pup-dashboard"-version = "2.0.738"+version = "2.0.739" dependencies = [  "pup-cdp",  "pup-core",@@ -826,7 +826,7 @@ dependencies = [  [[package]] name = "pup-host"-version = "2.0.738"+version = "2.0.739" dependencies = [  "serde",  "serde_json",@@ -835,7 +835,7 @@ dependencies = [  [[package]] name = "pup-host-mac"-version = "2.0.738"+version = "2.0.739" dependencies = [  "core-foundation",  "core-graphics",@@ -851,7 +851,7 @@ dependencies = [  [[package]] name = "pup-host-win"-version = "2.0.738"+version = "2.0.739" dependencies = [  "pup-core",  "pup-host",@@ -861,7 +861,7 @@ dependencies = [  [[package]] name = "pup-identity"-version = "2.0.738"+version = "2.0.739" dependencies = [  "fontdue",  "image",@@ -871,7 +871,7 @@ dependencies = [  [[package]] name = "pup-session"-version = "2.0.738"+version = "2.0.739" dependencies = [  "pup-core",  "serde",@@ -881,7 +881,7 @@ dependencies = [  [[package]] name = "pup-vault"-version = "2.0.738"+version = "2.0.739" dependencies = [  "pup-core",  "pup-host",@@ -892,7 +892,7 @@ dependencies = [  [[package]] name = "pup-verbs"-version = "2.0.738"+version = "2.0.739" dependencies = [  "base64",  "png 0.17.16",
rust/Cargo.toml+1−1
@@ -4,7 +4,7 @@ members = ["core", "host", "host-win", "host-mac", "cdp", "browser", "session",  # One version for the whole bridge, in lockstep with src/BRIDGE_VERSION (tools/ship.sh bumps both). [workspace.package]-version = "2.0.738"+version = "2.0.739" edition = "2021" license = "MIT" 
rust/verbs/src/identity.rs+50
@@ -397,3 +397,53 @@ pub fn audit(ctx: &Ctx) -> Value {     pup_core::ok(json!({ "mode": mode(ctx), "windows": rows, "ok": true, "findings": findings, "_hint": if findings.is_empty() { "What pup believes each window is stamped with, read back from Windows." } else { "One or more windows cannot carry pup identity; see findings." } })) } ++/// 2.0.739 (pup-bridge#143): the "never a bare Chrome button" safety net.+///+/// After a bridge restart or a worker-reload cycle there is a gap where a pup-profile Chrome-for-Testing+/// window exists but has no session yet: the extension control channel is still re-handshaking, so+/// `adopt_stray_windows` (which drives the extension) cannot run, and the window sits on the taskbar wearing+/// Chrome's stock button with no thread tile. This recurs on John's laptop on every insiders ship.+///+/// This runs on every health tick and works at the OS level, independent of the extension channel, so it+/// closes the gap even while the channel is down. It enumerates pup CfT windows by PID (never the user's own+/// Chrome, never a CDP browser pup drives), and on any that a session does not already own and that is not+/// already carrying a pup AUMID, it stamps a grouped `Adom Pup` identity. That identity upgrades to the real+/// per-thread tile the moment `adopt_stray_windows` re-adopts the window and its own stamp runs. Read + stamp+/// only; it never touches the lane or kill paths that caused the 2.0.723 / 2.0.646 regressions.+pub fn stamp_stray_cft_windows(ctx: &Ctx) {+    if !cfg!(windows) { return; }+    if mode(ctx) == "plain" { return; }   // the user asked for stock icons; respect it+    let pup_pids: std::collections::HashSet<u32> = crate::pup_browser_pids_by_profile(ctx).into_values().flatten().collect();+    if pup_pids.is_empty() { return; }+    let cdp: std::collections::HashSet<u32> = ctx.browsers.lock().unwrap().values().map(|b| b.launched.pid).filter(|p| *p > 0).collect();+    let owned: std::collections::HashSet<i64> = ctx.sessions.all().iter().filter_map(|s| s.hwnd).collect();+    let caller = internal_caller();+    static DONE: Mutex<Option<std::collections::HashSet<i64>>> = Mutex::new(None);+    let mut done = DONE.lock().unwrap();+    let done = done.get_or_insert_with(Default::default);+    let wins: Vec<pup_host::HostWindow> = ctx.host.frame_windows_all(Some("Chrome_WidgetWin_1")).into_iter()+        .filter(|w| pup_pids.contains(&w.pid) && !cdp.contains(&w.pid) && w.title.ends_with("Google Chrome for Testing"))+        .collect();+    let live: std::collections::HashSet<i64> = wins.iter().map(|w| w.hwnd).collect();+    done.retain(|h| live.contains(h));   // forget closed windows+    // the generic grouped pup identity (one button for every not-yet-adopted pup window)+    let app_id = id::category_aumid("default");+    let display = "Adom Pup".to_string();+    let icon = icons_dir(ctx).join("adom-pup.ico");+    for w in wins {+        if owned.contains(&w.hwnd) { continue; }          // a session owns it: its own stamp carries the real tile+        if done.contains(&w.hwnd) { continue; }           // stamped once already; the session upgrade re-stamps later+        if w.title.starts_with("PUPBIRTH-") { continue; } // a window being born: its birth stamps it+        // already a pup button? read the live AUMID back from Windows before stamping+        let cur = ctx.ab.call("desktop_get_window_identity", json!({ "hwnd": w.hwnd }), &caller, AB_T).ok()+            .and_then(|r| { let o = r.get("output").and_then(|o| o.as_str()).and_then(|t| serde_json::from_str::<Value>(t).ok()).unwrap_or(r); o["data"]["windows"][0]["appId"].as_str().map(|s| s.to_string()) });+        if cur.as_deref().map(|a| a.starts_with(id::APP_ID)).unwrap_or(false) { done.insert(w.hwnd); continue; }+        if !preregister(ctx, &caller, &app_id, &display, &icon) { continue; }+        let launch = exe_launch();+        match ctx.ab.call("desktop_set_window_identity", json!({ "hwnd": w.hwnd, "appId": app_id, "displayName": display, "iconPath": icon.to_string_lossy(), "relaunchCommand": id::relaunch_command(&launch, &format!("stray-{}", w.hwnd)), "relaunchDisplayName": display, "relaunchIconResource": icon.to_string_lossy() }), &caller, AB_T) {+            Ok(_) => { done.insert(w.hwnd); pup_core::log(format!("[identity] safety net: stamped a pup identity on an unadopted CfT window (hwnd {}, \"{}\") so it never shows a bare Chrome button while recovery catches up", w.hwnd, w.title)); }+            Err(e) => pup_core::log(format!("[identity] safety net: could not stamp hwnd {}: {e}", w.hwnd)),+        }+    }+}
rust/verbs/src/recovery.rs+1
@@ -766,6 +766,7 @@ pub fn health_tick(ctx: &Ctx) {     crate::extdrive::rescue_birth_tabs(ctx);   // 2.0.724: a window stuck on its birth page (PUPBIRTH-... on the taskbar)     crate::extdrive::adopt_stray_windows(ctx);   // 2.0.694: windows Chrome made outside pup (a dragged-out tab, a page's popup)     crate::extdrive::rebind_unbound(ctx);   // ext sessions whose birth outran the hwnd wait: bind + stamp now+    crate::identity::stamp_stray_cft_windows(ctx);   // 2.0.739 (#143): no pup window wears a bare Chrome button while recovery catches up     crate::extdrive::reload_stale_worker(ctx);   // a bridge_install must not wait for every thread's window to close     crate::extdrive::close_orphan_blank_windows(ctx, None);   // and any about:blank window no session owns     // 2.0.542: a lane browser that outlived a pup update keeps running the OLD extension until it cycles