Problem
When SideButton's browser automation sends a Page.navigate CDP command to a page with a beforeunload handler (e.g., LinkedIn messaging with unsaved draft text), the browser shows a native "Leave site?" dialog. This dialog blocks ALL subsequent CDP commands indefinitely, causing every tool call to time out.
Screenshot of the blocking dialog:
The dialog shows "Leave site? Changes you made may not be saved." with Cancel/Leave buttons. While this dialog is open, snapshot, screenshot, evaluate, click, and all other browser tools return timeout errors.
Root Cause
The Chrome extension's debugger integration is missing two things:
Page.enable is never called after chrome.debugger.attach() — without this, CDP never emits Page.javascriptDialogOpening events
- No
chrome.debugger.onEvent listener exists for dialog events — even if Page domain were enabled, there's no handler to auto-dismiss dialogs
How Other Tools Handle This
| Tool |
Approach |
| Playwright |
Auto-dismisses all dialogs if no page.on('dialog') listener registered. Exposes Dialog class with accept()/dismiss() for explicit handling |
| Puppeteer |
Requires pre-registered page.on('dialog') listener. Dialog blocks if no handler |
| Browser Use |
Migrated from Playwright to raw CDP specifically because of dialog edge cases. Uses "watchdog" background services that auto-handle CDP events |
| OpenClaw |
Uses "arming call" pattern — dialog --accept command before the triggering action |
| Chrome DevTools Protocol |
Provides Page.javascriptDialogOpening event + Page.handleJavaScriptDialog method |
Proposed Solution
1. Enable Page domain events after debugger attach
In attachDebugger(), after chrome.debugger.attach():
await chrome.debugger.sendCommand({ tabId }, "Page.enable");
2. Add dialog event listener
Register a chrome.debugger.onEvent listener for Page.javascriptDialogOpening:
chrome.debugger.onEvent.addListener((source, method, params) => {
if (method === "Page.javascriptDialogOpening" && source.tabId === connectedTabId) {
// Auto-handle based on dialog type
const accept = params.type === "beforeunload" || params.type === "alert";
chrome.debugger.sendCommand(
{ tabId: source.tabId },
"Page.handleJavaScriptDialog",
{ accept }
).catch(() => {}); // Ignore "no dialog showing" race
}
});
3. Default handling policy
| Dialog Type |
Default Action |
Rationale |
beforeunload |
Accept (Leave) |
Automation intentionally triggered the navigation |
alert |
Accept (OK) |
Informational only, no decision needed |
confirm |
Accept (OK) |
Safe default for automation; can be made configurable |
prompt |
Accept (empty) |
Safe default; future: expose to LLM for input |
4. Future: Expose dialog events to MCP layer (optional)
For advanced use cases, expose dialog type/message to the workflow engine so agents can make informed decisions about confirm/prompt dialogs.
Files to Change
extension/background.js — attachDebugger() function + new chrome.debugger.onEvent listener
References
Problem
When SideButton's browser automation sends a
Page.navigateCDP command to a page with abeforeunloadhandler (e.g., LinkedIn messaging with unsaved draft text), the browser shows a native "Leave site?" dialog. This dialog blocks ALL subsequent CDP commands indefinitely, causing every tool call to time out.Screenshot of the blocking dialog:
The dialog shows "Leave site? Changes you made may not be saved." with Cancel/Leave buttons. While this dialog is open,
snapshot,screenshot,evaluate,click, and all other browser tools return timeout errors.Root Cause
The Chrome extension's debugger integration is missing two things:
Page.enableis never called afterchrome.debugger.attach()— without this, CDP never emitsPage.javascriptDialogOpeningeventschrome.debugger.onEventlistener exists for dialog events — even if Page domain were enabled, there's no handler to auto-dismiss dialogsHow Other Tools Handle This
page.on('dialog')listener registered. ExposesDialogclass withaccept()/dismiss()for explicit handlingpage.on('dialog')listener. Dialog blocks if no handlerdialog --acceptcommand before the triggering actionPage.javascriptDialogOpeningevent +Page.handleJavaScriptDialogmethodProposed Solution
1. Enable Page domain events after debugger attach
In
attachDebugger(), afterchrome.debugger.attach():2. Add dialog event listener
Register a
chrome.debugger.onEventlistener forPage.javascriptDialogOpening:3. Default handling policy
beforeunloadalertconfirmprompt4. Future: Expose dialog events to MCP layer (optional)
For advanced use cases, expose dialog type/message to the workflow engine so agents can make informed decisions about
confirm/promptdialogs.Files to Change
extension/background.js—attachDebugger()function + newchrome.debugger.onEventlistenerReferences