Media: Skip cross-origin isolation on the classic-theme site editor home route#78404
Conversation
The site editor document is cross-origin isolated via Document-Isolation-Policy, which places it in its own agent cluster. For classic themes, the site editor embeds the front end in a same-origin `wp_site_preview` iframe. Without a matching policy on the framed document, that iframe is loaded credentialless in a separate agent cluster, so the editor can no longer reach its `contentDocument` and the preview's interactive-element handling throws. Send the same header on the `wp_site_preview` request so the iframe joins the editor's agent cluster, restoring same-origin DOM access. Gating mirrors core's wp_initialize_site_preview_hooks(). The shared Chromium/filter check is extracted into gutenberg_should_use_document_isolation_policy(). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| * | ||
| * @return bool Whether DIP is supported and should be used. | ||
| */ | ||
| function gutenberg_should_use_document_isolation_policy(): bool { |
There was a problem hiding this comment.
I created a new function to consolidate the same logic.
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
|
Flaky tests detected in cf04c31. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/26622386092
|
|
Thanks @t-hamano - code seems good. I'm also a little concerned sending this header on a preview could cause unexpected issues with the preview. We don't send these headers on the front end because we only need them in the editor. I wonder if we could we just avoid sending the headers on the outer frame for the preview screen? Some tests would be good here as well, ideally that catch the current breakage. |
|
Hi @t-hamano - I drafted the Core backport for this PR at wordpress-develop#12004 (kept in draft until this PR merges) and pushed the corresponding |
The Site Editor's SitePreview component neutralizes focusable elements inside the preview iframe (aria-hidden="true" and pointer-events: none) so the previewed front end is not interactive. This was previously untested. Verify the behavior on a classic theme across links, buttons, and form controls. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Size Change: 0 B Total Size: 8.21 MB ℹ️ View Unchanged
|
The classic-theme site editor home route embeds the front end in a same-origin `wp_site_preview` iframe and reads its `contentDocument` to neutralize interactive elements. Cross-origin isolation (DIP) on the editor puts it in its own agent cluster, blocking that access and breaking the preview. The previous fix sent a DIP header on the preview frame itself to realign the agent clusters, but `isolate-and-credentialless` strips credentials from cross-origin subresources, which can make the preview render differently from the live site. Instead, skip cross-origin isolation on the editor's classic-theme home route so both frames stay un-isolated and share an agent cluster, leaving the front end untouched. Other routes (pattern/template-part editors) still get isolation for client-side media processing. The home route is detected via the `p` query arg that core normalizes in _wp_get_site_editor_redirection_url(). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@adamsilverstein Thanks for the feedback!
This is a great idea. I've implemented it with f4932b0. The code changes are also minimal. |
| // Skip when rendering the classic-theme home route, which shows the site | ||
| // preview in an iframe and must reach its `contentDocument` to neutralize | ||
| // interactive elements — DIP would block that. | ||
| if ( 'site-editor' === $screen->id && ! wp_is_block_theme() && ( ! isset( $_GET['p'] ) || '/' === $_GET['p'] ) ) { |
There was a problem hiding this comment.
I don't fully understand why the 'p' GET paramater check is needed, but trust you added it for a reason!
There was a problem hiding this comment.
The classic theme allows can use the block editor within the Site Editor. For example, it includes template parts and patterns, and the URLs will look like site-editor.php?p=/wp_block/1&canvas=edit. In this case, we should not disable DIP. For this reason, the 'p' GET parameter check is necessary.
The site editor renders the front end of a classic theme in a same-origin iframe and must reach the iframe's `contentDocument` to neutralize its interactive elements. Document-Isolation-Policy isolates the editor into its own agent cluster, which blocks that same-origin access. Skip cross-origin isolation in `wp_set_up_cross_origin_isolation()` for the classic-theme site editor home route so the preview keeps working. Block themes and other routes are unaffected. Backport of WordPress/gutenberg#78404.
Follow up to #75991.
What? Why? How?
When a classic theme is active, the Site Editor displays a site preview. This is a preview of the site's front end, and it is expected that all interactive elements will be inactive, but as a result of #75991, this is no longer working.
Recording.2026-05-18.233505.mp4
This PR fixes it by sending theThis PR fixes it by skipping cross-origin isolation) on the classic-theme Site Editor home route, so the editor and its wp_site_preview iframe share an agent cluster and same-origin contentDocument access is restored.Document-Isolation-Policyheader on thewp_site_previewrequest.Testing Instructions
Use of AI Tools
Authored with assistance from Claude Code; reviewed by the contributor.