fix: Chrome relay extension auto-reattach after SPA navigation#19766
fix: Chrome relay extension auto-reattach after SPA navigation#19766steipete merged 3 commits intoopenclaw:mainfrom
Conversation
| async function onDebuggerDetach(source, reason) { | ||
| const tabId = source.tabId | ||
| if (!tabId) return | ||
| if (!tabs.has(tabId)) return | ||
| void detachTab(tabId, reason) | ||
|
|
There was a problem hiding this comment.
Missing check for canceled_by_user and replaced_with_devtools detach reasons
Chrome's onDetach provides a reason parameter with values "target_closed", "canceled_by_user", and "replaced_with_devtools". When the user explicitly dismisses the debugger infobar (canceled_by_user) or opens DevTools (replaced_with_devtools), the tab still exists and the URL won't be chrome://, so the current code will attempt to re-attach — fighting the user's explicit intent.
This creates a frustrating UX: the user cancels the debugger bar, it reappears 300ms later, they cancel again, it comes back at 700ms, etc., for 3 cycles before giving up. For replaced_with_devtools, re-attaching would conflict with DevTools.
| async function onDebuggerDetach(source, reason) { | |
| const tabId = source.tabId | |
| if (!tabId) return | |
| if (!tabs.has(tabId)) return | |
| void detachTab(tabId, reason) | |
| async function onDebuggerDetach(source, reason) { | |
| const tabId = source.tabId | |
| if (!tabId) return | |
| if (!tabs.has(tabId)) return | |
| // User explicitly cancelled or DevTools replaced the connection — respect their intent | |
| if (reason === 'canceled_by_user' || reason === 'replaced_with_devtools') { | |
| void detachTab(tabId, reason) | |
| return | |
| } |
Prompt To Fix With AI
This is a comment left during a code review.
Path: assets/chrome-extension/background.js
Line: 458-462
Comment:
**Missing check for `canceled_by_user` and `replaced_with_devtools` detach reasons**
Chrome's `onDetach` provides a `reason` parameter with values `"target_closed"`, `"canceled_by_user"`, and `"replaced_with_devtools"`. When the user explicitly dismisses the debugger infobar (`canceled_by_user`) or opens DevTools (`replaced_with_devtools`), the tab still exists and the URL won't be `chrome://`, so the current code will attempt to re-attach — fighting the user's explicit intent.
This creates a frustrating UX: the user cancels the debugger bar, it reappears 300ms later, they cancel again, it comes back at 700ms, etc., for 3 cycles before giving up. For `replaced_with_devtools`, re-attaching would conflict with DevTools.
```suggestion
async function onDebuggerDetach(source, reason) {
const tabId = source.tabId
if (!tabId) return
if (!tabs.has(tabId)) return
// User explicitly cancelled or DevTools replaced the connection — respect their intent
if (reason === 'canceled_by_user' || reason === 'replaced_with_devtools') {
void detachTab(tabId, reason)
return
}
```
How can I resolve this? If you propose a fix, please make it concise.|
The |
When Chrome's debugger detaches during page navigation (common in SPAs like Gmail, Google Calendar), the extension now automatically re-attaches instead of permanently losing the connection. Changes: - onDebuggerDetach: detect navigation vs tab close, attempt re-attach with 3 retries and exponential backoff (300ms, 700ms, 1500ms) - Add reattachPending guard to prevent concurrent re-attach races - connectOrToggleForActiveTab: handle pending re-attach state - onRelayClosed: clear reattachPending on relay disconnect - Add chrome.tabs.onRemoved listener for proper cleanup Fixes openclaw#19744
Skip re-attach when user explicitly dismisses debugger bar or opens DevTools. Prevents frustrating re-attach loop that fights user intent. Addresses review feedback from greptile-apps.
cd402ad to
df2c47e
Compare
|
Landed via temp rebase onto main.
Thanks @nishantkabra77! |
…hanks @nishantkabra77) (cherry picked from commit 004a610)
…hanks @nishantkabra77) (cherry picked from commit 004a610)
Summary
Fixes #19744 — The Chrome Browser Relay extension loses its CDP connection after any click that triggers SPA in-page navigation (Gmail, Google Calendar, etc.), making it effectively read-only for SPAs.
Root Cause
onDebuggerDetachinbackground.jsunconditionally callsdetachTab()on any debugger detach event — including navigations where the tab still exists. It never attempts to re-attach, so the connection is permanently lost until the user manually clicks the extension badge again.Changes
Core fix —
onDebuggerDetachrewritten:chrome.tabs.get)chrome://and extension pagesTarget.detachedFromTargetfor old session before re-attaching (clean session handoff)chrome://extensionsservice worker console)Race condition fixes:
reattachPendingSet prevents concurrent re-attach loops for the same tabconnectOrToggleForActiveTab: if user clicks badge during re-attach, cancels cleanlyonRelayClosed: clearsreattachPendingso in-flight retries bail out immediatelyNew:
chrome.tabs.onRemovedlistener:reattachPendingandtabsmap on tab closeTesting
Tested with:
Files Changed
assets/chrome-extension/background.js— 143 insertions, 2 deletionsGreptile Summary
This PR fixes the Chrome Browser Relay extension losing its CDP connection after SPA in-page navigations (Gmail, Google Calendar, etc.) by rewriting
onDebuggerDetachto detect whether the tab still exists and attempt automatic re-attachment with exponential backoff retries.The approach is sound: it distinguishes navigation from tab close, cleans up old session state, notifies the relay, and retries with proper guards against races (concurrent re-attach, user toggle, relay disconnect, tab removal).
reasonparameter fromchrome.debugger.onDetachis not checked forcanceled_by_userorreplaced_with_devtools, which means the extension will fight the user's explicit action to dismiss the debugger bar by re-attaching 3 times before giving up.onRemovedandonDebuggerDetachis correctly implemented.chrome.tabs.onRemovedlistener properly cleans up stale state.Confidence Score: 3/5
canceled_by_userandreplaced_with_devtoolsdetach reasons is a real UX issue that will frustrate users who manually dismiss the debugger bar.assets/chrome-extension/background.js— theonDebuggerDetachfunction needs to check thereasonparameter before attempting re-attachLast reviewed commit: 0643000
(2/5) Greptile learns from your feedback when you react with thumbs up/down!