Skip to content

[Exploration] Fix editor iframe loading by disabling DIP header rewriting - #3314

Closed
bgrgicak wants to merge 1 commit into
fix/editor-iframe-scoped-urlfrom
fix/editor-iframe-disable-dip-rewriting
Closed

bgrgicak wants to merge 1 commit into
fix/editor-iframe-scoped-urlfrom
fix/editor-iframe-disable-dip-rewriting

Conversation

@bgrgicak

@bgrgicak bgrgicak commented Feb 27, 2026 •

Copy link
Copy Markdown
Collaborator

Motivation for the change, related issues

This PR explores fixing the Gutenberg editor iframe loading in Playground when cross-origin isolation headers are in play. This is an exploration, not intended to be merged as-is — it's meant to document the problem, the interactions between DIP/COEP/COOP and service workers, and a working fix that can inform a proper solution.

When Gutenberg's client-side media processing experiment is enabled, WordPress sends Cross-Origin-Embedder-Policy: credentialless on wp-admin pages. Playground's service worker rewrites this to Document-Isolation-Policy: isolate-and-credentialless (DIP). This creates a new agent cluster, causing child iframes to lose their service worker controller — the browser restarts the navigation in a different browsing context group.

The result: the editor iframe (/wp-includes/empty.html, a synthetic page served by the service worker) gets a second request that bypasses the SW entirely, hits the dev server, and 404s. The block editor fails to load.

Implementation details

All changes are in packages/playground/remote/service-worker.ts.

1. Disable DIP rewriting

rewriteCoopHeadersToDocumentIsolationPolicy() now records the COEP value in a Map but returns the response unchanged — no more rewriting COEP/COOP → DIP. The DIP code path is left in place (dead code after an early return) so it can be re-enabled later.

With plain COEP (no COOP), same-origin child iframes keep their service worker controller.

2. Serve matching COEP on empty.html

emptyHtml() now mirrors the parent page's COEP value (from the scopesWithCrossOriginIsolation map). Without this, the browser blocks the iframe with ERR_BLOCKED_BY_RESPONSE because a COEP parent requires children to also have COEP. We intentionally use COEP only — not COOP (which would swap browsing context groups) and not DIP (which would lose the SW controller).

Trade-off

Without DIP, crossOriginIsolated is false on wp-admin pages, so SharedArrayBuffer isn't available. Gutenberg handles this gracefully — it falls back to server-side media processing. The DIP feature detection code is still in place and can be re-enabled when Chrome fixes the DIP + service worker interaction.

Open questions

  • Is disabling DIP entirely the right trade-off, or should we find a way to make DIP work with same-origin iframes?
  • Should the dead DIP code path be removed or kept for future re-enablement?
  • Does this affect any other cross-origin isolation consumers beyond Gutenberg's media processing?

Testing Instructions

  1. Run npm run dev to start the dev server
  2. Open the Playground website with the Gutenberg plugin installed http://127.0.0.1:5400/website-server/?plugin=gutenberg&url=%2Fwp-admin%2Fpost-new.php
  3. Confirm the block editor loads correctly (the iframe renders the editor canvas)
  4. Try inserting an image block and uploading a file — confirm media upload works

🤖 Generated with Claude Code

@bgrgicak bgrgicak changed the title Fix editor iframe loading by disabling DIP header rewriting [Exploration] Fix editor iframe loading by disabling DIP header rewriting Feb 27, 2026
@bgrgicak

Copy link
Copy Markdown
Collaborator Author

This won't work because it breaks embeds like YouTube, which was the original reason for implementing #3028

@bgrgicak bgrgicak closed this Feb 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant