#65399 closed defect (bug) (fixed)
Skip Document-Isolation-Policy on the classic-theme site preview
| Reported by: | adamsilverstein | Owned by: | adamsilverstein |
|---|---|---|---|
| Priority: | normal | Milestone: | 7.1 |
| Component: | Media | Version: | |
| Severity: | normal | Keywords: | has-patch has-unit-tests commit gutenberg-merge |
| Cc: | Focuses: |
Description
The site editor renders the front end of a classic theme inside a same-origin ?wp_site_preview=1 iframe. To neutralize the interactive elements of that preview (links, forms, etc.), the editor reads and manipulates the iframe's contentDocument.
WordPress 7.1 sends a Document-Isolation-Policy: isolate-and-credentialless (DIP) header on block-editor screens (including the site editor) so that client-side media processing has access to SharedArrayBuffer and high-resolution timers. On Chromium 137+, DIP places the document into its own agent cluster. When the parent editor document is isolated but the same-origin preview iframe is not (or vice versa), the browser refuses cross-document contentDocument access, and neutralizing the classic-theme preview fails.
Steps to reproduce
- Activate a classic theme (for example, Twenty Twenty-One).
- In Chrome 137 or newer, open the Site Editor (
wp-admin/site-editor.php). - Observe the front-end site preview rendered in the iframe.
Expected: The preview loads and its interactive elements are neutralized by the editor.
Actual: The editor cannot reach the iframe's contentDocument because DIP has placed the editor in a separate agent cluster, so neutralization fails.
Proposed fix
Skip cross-origin isolation in wp_set_up_cross_origin_isolation() for the classic-theme site editor home route only. The output buffer / DIP header is not started for that request, restoring same-origin contentDocument access.
The guard is scoped narrowly:
<?php if ( 'site-editor' === $screen->id && ! wp_is_block_theme() && ( ! isset( $_GET['p'] ) || '/' === $_GET['p'] ) ) { return; }
Behavior matrix:
| Theme | Screen | Route | DIP |
| Classic | Site editor | Home (p unset or /) | Skipped |
| Classic | Site editor | Non-home (e.g. p=/page/about) | Applied |
| Block | Site editor | Any route | Applied |
Block themes do not render the classic site preview iframe, so they are unaffected. All non-home routes continue to receive DIP.
Patch
src/wp-includes/media.php— early return inwp_set_up_cross_origin_isolation()for the classic-theme site editor home route.tests/phpunit/tests/media/wpCrossOriginIsolation.php— coverage for the skip (home route,punset andp=/), and for DIP still being applied on classic-theme non-home routes and on block-theme routes.
GitHub PR: https://github.com/WordPress/wordpress-develop/pull/12004
Related
- Backport of WordPress/gutenberg#78404.
- Part of the 7.1 client-side media reintroduction: #11324.
Change History (7)
This ticket was mentioned in PR #12004 on WordPress/wordpress-develop by @adamsilverstein.
7 weeks ago
#1
- Keywords has-patch has-unit-tests added
#2
@
6 weeks ago
Tested on WordPress 7.0 + Chrome 147 with Twenty Twenty-One active. Simulated the DIP header locally since 7.1 is not yet released.
Bug confirmed: With DIP active, iframe.contentDocument returns null — editor cannot neutralize the classic theme preview iframe.
Fix verified: Skipping DIP on the classic-theme site editor home route restores contentDocument access. Block theme and non-home routes continue receiving DIP as expected.
Patch and unit tests look good.
#3
@
4 weeks ago
Thanks for testing @manhar - this one is reviewed and approved in GitHub, marking it for commit.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)
## Summary
wp_set_up_cross_origin_isolation().## Why
The site editor renders the front end of a classic theme in a same-origin
?wp_site_preview=1iframe and must reach the iframe'scontentDocumentto neutralize its interactive elements. Document-Isolation-Policy isolates the editor into its own agent cluster, which blocks that same-origin access.Skipping cross-origin isolation for the classic-theme site editor home route keeps the preview working. The new early return is scoped narrowly:
punset or/)p=/page/about)Block themes do not render the classic site preview iframe, so they are unaffected.
## Changes
###
src/wp-includes/media.phpwp_set_up_cross_origin_isolation()— early return for the classic-theme site editor home route so DIP / the cross-origin isolation output buffer is not applied there.###
tests/phpunit/tests/media/wpCrossOriginIsolation.phptest_skips_cross_origin_isolation_for_classic_theme_site_editor_home()(data-provided: nop, andp=/).test_sets_up_cross_origin_isolation_for_classic_theme_site_editor_non_home_route().test_sets_up_cross_origin_isolation_for_block_theme_site_editor_home().## Backport scope
Backport of WordPress/gutenberg#78404. Server-side only.
## Test plan
vendor/bin/phpunit tests/phpunit/tests/media/wpCrossOriginIsolation.php— all existing + new tests pass.## Related