diff --git a/playwriter/src/cdp-relay.ts b/playwriter/src/cdp-relay.ts index f38d383..fe455b7 100644 --- a/playwriter/src/cdp-relay.ts +++ b/playwriter/src/cdp-relay.ts @@ -884,10 +884,34 @@ export async function startPlayWriterCDPRelayServer({ if (method === 'Target.attachedToTarget') { const targetParams = params as Protocol.Target.AttachedToTargetEvent - // Filter out restricted targets (non-page types, extension pages, chrome:// URLs, etc.) + // Filter out restricted targets (unsupported types, extension pages, chrome:// URLs, etc.) // These targets can't be properly controlled through chrome.debugger API // and cause issues when Playwright tries to initialize them (issue #14) if (isRestrictedTarget(targetParams.targetInfo)) { + // NOTE: We auto-resume restricted targets that were auto-attached with + // waitForDebuggerOnStart=true. We still filter them out, but Chrome pauses + // these targets until Runtime.runIfWaitingForDebugger is sent; if we don’t + // resume, OOPIF navigations (e.g. Google RotateCookiesPage) can hang and the + // main tab spinner never finishes. + // + // To support iframes directly in the future, we’d need to forward + // Target.attachedToTarget for type==='iframe', wire child session routing + // (commands/events per session), and allow iframes in isRestrictedTarget, + // plus add tests for iframe navigation + network lifecycles. + if (targetParams.waitingForDebugger && targetParams.sessionId) { + void sendToExtension({ + method: 'forwardCDPCommand', + params: { + sessionId: targetParams.sessionId, + method: 'Runtime.runIfWaitingForDebugger', + params: {}, + source: 'server', + }, + }).catch((error) => { + const message = error instanceof Error ? error.message : String(error) + logger?.log(pc.yellow('[Server] Failed to resume restricted target:'), message) + }) + } logger?.log(pc.gray(`[Server] Ignoring restricted target: ${targetParams.targetInfo.type} (${targetParams.targetInfo.url})`)) return }