From 0192da77e06b6ee3d0ce04e9d43ea387372281ca Mon Sep 17 00:00:00 2001 From: Tianren Dong Date: Mon, 28 Sep 2026 20:18:03 -0400 Subject: Report hidden Pi tab in /chrome doctor (#26) Chrome ignores clicks and typing in hidden pages. Doctor now asks the worker whether this session's own tab is visible (automation.status includeVisibility, which never creates or activates a tab) and reports the reason and fix when it is hidden. --- .../browser-extension/service_worker.js | 19 ++++++++++++++++++- extensions/chrome-profile-bridge/index.ts | 19 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) (limited to 'extensions') diff --git a/extensions/chrome-profile-bridge/browser-extension/service_worker.js b/extensions/chrome-profile-bridge/browser-extension/service_worker.js index ac48579..64ed8a9 100644 --- a/extensions/chrome-profile-bridge/browser-extension/service_worker.js +++ b/extensions/chrome-profile-bridge/browser-extension/service_worker.js @@ -1985,7 +1985,24 @@ async function dispatch(action, params) { // Report this session's owned automation target (ids only). Used for diagnostics/tests. await hydrateAutomationTargets(); const t = automationTargets.get(sessionKeyOf(params)); - return { windowId: t?.windowId ?? null, tabId: t?.tabId ?? null }; + const status = { windowId: t?.windowId ?? null, tabId: t?.tabId ?? null }; + if (!params.includeVisibility || !t) return status; + // For /chrome doctor: is this session's own tab visible? Never creates or activates anything. + const tab = await chrome.tabs.get(t.tabId).catch(() => null); + if (!tab) return { ...status, tabId: null }; + const results = await executeScriptWithFallback({ + target: { tabId: tab.id, frameIds: [0] }, + world: "MAIN", + func: () => document.visibilityState, + }, `read visibility of tab ${tab.id}`).catch(() => null); + const visibility = typeof results?.[0]?.result === "string" ? results[0].result : "unknown"; + const win = typeof chrome.windows?.get === "function" ? await chrome.windows.get(tab.windowId).catch(() => null) : null; + return { + ...status, + visibility, + url: tab.url, + hiddenReason: visibility === "hidden" ? hiddenTabReason(tab, win) : undefined, + }; } case "automation.cleanup": // Close recorded creations, and only ungroup user tabs still in their adopted group. diff --git a/extensions/chrome-profile-bridge/index.ts b/extensions/chrome-profile-bridge/index.ts index adfe6cf..fd12dac 100644 --- a/extensions/chrome-profile-bridge/index.ts +++ b/extensions/chrome-profile-bridge/index.ts @@ -1219,6 +1219,25 @@ Usage rules: } catch (error) { lines.push(`⚠ Couldn't inspect the active tab: ${(error as Error).message}`); } + + // Pi's own tab for this session: hidden pages ignore clicks and typing, so say so up front. + try { + const own = (await bridge.send("automation.status", { sessionKey: sessionKeyFor(ctx), includeVisibility: true }, 10_000)) as + | { tabId?: number | null; visibility?: string; hiddenReason?: string } + | undefined; + if (own?.tabId === null || own?.tabId === undefined) { + lines.push(`• Pi hasn't opened its own tab in this session yet.`); + } else if (own.visibility === "hidden") { + lines.push( + `⚠ Pi's tab is hidden because ${own.hiddenReason ?? "its window is not visible"}. Chrome ignores clicks and typing in hidden tabs, so those tools will fail until it's visible.`, + ` Fix: bring Pi's window forward or uncover it, or run /chrome background off to let Pi bring it forward.`, + ); + } else if (own.visibility === "visible") { + lines.push(`✓ Pi's tab is visible, so clicks and typing will reach it.`); + } + } catch { + // Older extensions or a closed tab: nothing useful to add. + } } else if (versionMismatch) { lines.push(`… Skipped the remaining checks until you reload the Chrome extension.`); } -- cgit v1.2.3