You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: add iframe support for Apollo Client detection (#1797)
### Summary
This PR enables `apollo-client-devtools` to detect and interact with
Apollo Clients running inside **same-origin iframes**, in addition to
the main window.
### Problem
Previously we only detected clients in the top-level window. If a page
had iframes with their own Apollo Client instances, those clients were
invisible to the extension.
### Solution
1. **Updated extension manifests**: Added `all_frames: true` to content
scripts so `tab.js` and `hook.js` run in every frame (main window +
iframes)
2. **Added multi-port architecture with frameId tracking**: Changed
`background.ts` from tracking a single `tab` port per tab to a
`Map<tabPorts, frameId>` per tab, enabling multiple frames to connect
while tracking which frame each port belongs to
3. **Introduced client --> frame mapping**: Added a `clientFrames:
Map<clientId, frameId>` to track which Apollo Client belongs to which
frame, enabling targeted message routing
4. **Implemented frameId-based message routing**: RPC requests for a
specific client are now routed only to the frame that owns that client,
eliminating broadcast overhead
5. **Added SKIP_RESPONSE pattern for discovery**: The `getClients`
handler in `hook.ts` uses `SKIP_RESPONSE` so frames without Apollo
Clients don't pollute discovery responses
## Files Changed
| File | Change |
|------|--------|
|
[src/extension/chrome/manifest.json](cci:7://file:///Users/camillelawrence/Desktop/repos/apollo-client-devtools/src/extension/chrome/manifest.json:0:0-0:0)
| Add `all_frames: true` |
|
[src/extension/firefox/manifest.json](cci:7://file:///Users/camillelawrence/Desktop/repos/apollo-client-devtools/src/extension/firefox/manifest.json:0:0-0:0)
| Add `all_frames: true` |
|
[src/extension/rpc.ts](cci:7://file:///Users/camillelawrence/Desktop/repos/apollo-client-devtools/src/extension/rpc.ts:0:0-0:0)
| Export `SKIP_RESPONSE` symbol + handler logic to skip sending
responses |
|
[src/extension/background/background.ts](cci:7://file:///Users/camillelawrence/Desktop/repos/apollo-client-devtools/src/extension/background/background.ts:0:0-0:0)
| `Set<tabPorts>` --> `Map<Port, frameId>`, add `clientFrames` mapping,
implement targeted routing |
|
[src/extension/tab/hook.ts](cci:7://file:///Users/camillelawrence/Desktop/repos/apollo-client-devtools/src/extension/tab/hook.ts:0:0-0:0)
| Add `SKIP_RESPONSE` to `getClients` handler for frames without clients
|
|
[src/extension/tab/handleExplorerRequests.ts](cci:7://file:///Users/camillelawrence/Desktop/repos/apollo-client-devtools/src/extension/tab/handleExplorerRequests.ts:0:0-0:0)
| Replace throw with silent return |
|
[development/client/public/iframe.html](cci:7://file:///Users/camillelawrence/Desktop/repos/apollo-client-devtools/development/client/public/iframe.html:0:0-0:0)
| Test page for iframe scenarios |
## Automated Tests Added
Two new unit tests in `src/extension/__tests__/rpc.test.ts`:
| Test | Description |
|------|-------------|
| `does not send response when handler returns SKIP_RESPONSE` | Verifies
that when a handler returns `SKIP_RESPONSE`, no RPC response message is
posted |
| `SKIP_RESPONSE allows handler to be re-registered after unsubscribe` |
Verifies that handlers using `SKIP_RESPONSE` can be properly
unsubscribed and re-registered |
## Manual Verification Steps
1. **Single frame (regression test)**
- Load a page with a single Apollo Client (no iframes)
- Open DevTools --> Apollo tab
- Verify the client is detected and all features (Queries, Mutations,
Cache) work normally
2. **Multi-frame detection**
- Start dev server: `npm run start:dev`
- Open Chrome with the extension loaded: `npm run chrome`
- Navigate to `http://localhost:3000`
- Add a client in the main window and a client inside the iframe
- Verify **both clients** appear in the DevTools client dropdown
3. **Targeted routing verification**
- With both clients (main window + iframe) registered from step 2
- Select the iframe's client in DevTools
- Run queries/mutations and inspect the cache
- In Chrome DevTools console for the **background script**, confirm RPC
requests are routed only to the correct frame (look for `frameId` in
console logs in dev mode)
## Limitations
- **Same-origin only**: Per browser security, `all_frames: true` only
works for same-origin iframes. Cross-origin iframes remain invisible.
## References
- Closes #380
- Related: PR #828, PR #997
---------
Co-authored-by: Jerel Miller <jerelmiller@gmail.com>
0 commit comments