Skip to content

Feature: Send Document-Isolation-Policy header [ED-24218] - #35976

Merged
louiswol94 merged 6 commits into
elementor:mainfrom
adamsilverstein:feat/document-isolation-policy-support
May 22, 2026
Merged

louiswol94 merged 6 commits into
elementor:mainfrom
adamsilverstein:feat/document-isolation-policy-support

Conversation

@adamsilverstein

@adamsilverstein adamsilverstein commented May 20, 2026 •

Copy link
Copy Markdown
Contributor

PR Checklist

PR Type

  • Feature

Summary

This PR can be summarized in the following changelog entry:

  • Send Document-Isolation-Policy: isolate-and-credentialless on the Elementor editor screen and preview iframe so Elementor sites can take advantage of WordPress 7.1's client-side media processing (and any future capability gated on cross-origin isolation).

Closes #35975.

Description

WordPress 7.1 introduces Document-Isolation-Policy: isolate-and-credentialless (DIP) on the block editor to enable cross-origin isolation, which is the prerequisite for SharedArrayBuffer and therefore for core's new client-side media processing feature (HEIC/AVIF in-browser, sub-size generation, Ultra HDR, etc.).

When DIP is applied to a parent document but not to its same-origin preview iframe, the browser places them in separate agent clusters and blocks synchronous DOM access between them. Elementor's editor relies on iframe.contentWindow.elementorFrontend.* to drive the preview, so applying DIP only on the editor surfaces as:

Uncaught SecurityError: Failed to read a named property 'elementorFrontend' from 'Window':
Blocked a frame with origin "..." from accessing a cross-origin frame.

(Originally reported by the Elementor team in WordPress/wordpress-develop#11170 against WordPress 7.0-beta3.)

What this PR does

  1. Adds two static helpers on Elementor\Core\Editor\Editor:
    • should_use_document_isolation_policy() — secure-context gate (HTTPS or localhost) plus an elementor/editor/use_document_isolation_policy filter for opt-out (defaults to true).
    • send_document_isolation_policy_header() — emits Document-Isolation-Policy: isolate-and-credentialless when the gate allows it.
  2. Calls the helper from Editor::init() (the editor screen) right after the Content-Type header.
  3. Calls the helper from Preview::init() (the preview iframe) before any output.

Because both the editor parent and the preview iframe send the same DIP header, they join the same agent cluster - synchronous DOM access between them is preserved, and the editor continues to work unchanged.

What this PR does not change

  • The existing filter_replace_editor() workaround from Fix: Elementor Editor Broken on WordPress 7.0 beta [ED-23138] #34900 is left in place. It signals to WordPress that Elementor is replacing the block editor and serves purposes beyond the DIP gate. WordPress core's DIP code is keyed on the action=edit query parameter (see WordPress/wordpress-develop#11170), so for action=elementor core does not send DIP at all - Elementor needs to send it itself, which is what this PR does.
  • No changes to the editor UI, preview lifecycle, or any other behavior.

Why default to enabled

  • The header is only honored by browsers on a secure context, so insecure origins are unaffected.
  • Non-Chromium browsers and Chrome < 137 ignore the header.
  • Sites that hit an edge case can opt out via add_filter( 'elementor/editor/use_document_isolation_policy', '__return_false' );.

Filing this issue first: #35975.

Test instructions

Automated

composer test -- --filter Elementor_Test_Editor

New tests cover:

  • DIP enabled on HTTPS
  • DIP enabled on localhost, *.localhost, and localhost:port
  • DIP disabled on insecure non-localhost origins
  • elementor/editor/use_document_isolation_policy filter can disable
  • Filter cannot force DIP on an insecure context (secure-context check wins)

Manual

  1. Install WordPress 7.1 nightly (via the WordPress Beta Tester plugin set to "Bleeding edge").
  2. Install Elementor with this branch applied. Serve the site over HTTPS or localhost.
  3. Open an Elementor edit page in Chrome 137+ and verify:
    • DevTools > Network: the editor response has Document-Isolation-Policy: isolate-and-credentialless.
    • DevTools > Network: the preview iframe response also has Document-Isolation-Policy: isolate-and-credentialless.
    • DevTools > Console: window.crossOriginIsolated === true.
    • The Elementor editor loads, previews render, and editing/dragging/dropping all work as before.
    • No SecurityError: Failed to read a named property 'elementorFrontend' from 'Window' errors.
  4. In the WordPress media library inside the Elementor editor, upload an image and confirm client-side media processing kicks in (look for the wasm-vips worker in DevTools > Sources, and the wp_client_side_media_processing_enabled filter response in the REST schema).
  5. Opt-out path: add add_filter( 'elementor/editor/use_document_isolation_policy', '__return_false' ); to a mu-plugin. Reload the editor and confirm the DIP header is no longer sent.
  6. Insecure context: load the editor over plain HTTP (non-localhost) and confirm no DIP header is sent (the secure-context gate short-circuits).

Quality assurance

  • I have tested this code to the best of my abilities
  • I have added unittests to verify the code works as intended

References

✨ PR Description

1. Problem & Context

Elementor editor and preview iframe need Document-Isolation-Policy (DIP) header to enable cross-origin isolation for SharedArrayBuffer and synchronous DOM access. DIP enforcement is only meaningful on secure contexts (HTTPS/localhost), so the implementation guards against sending headers browsers ignore.

2. What Changed (Where)

  • core/editor/editor.php: Added should_use_document_isolation_policy() (validates secure context, applies filter) and send_document_isolation_policy_header() (sends DIP header); calls header function in editor initialization.
  • includes/preview.php: Imported Editor class, calls send_document_isolation_policy_header() during preview setup.
  • tests/phpunit/elementor/test-editor.php: Added comprehensive test suite covering HTTPS, localhost variants, port handling, insecure contexts, filter disable/override logic.

3. How It Works

Editor calls send_document_isolation_policy_header() during init (line 120); preview calls same method during setup (line 100). Both check should_use_document_isolation_policy() which validates secure context (SSL or localhost), sanitizes $_SERVER['HTTP_HOST'], respects filter override, then conditionally sends Document-Isolation-Policy: isolate-and-credentialless header. No-op if headers already sent.

4. Risks

Filter at line 585 can disable DIP on secure contexts (acceptable), but intentionally cannot force-enable on insecure contexts (tested, correct). Header safety check via headers_sent() prevents issues from duplicate calls. Minor: strtok() modifies state but safe here since return value captured immediately.

Generated by LinearB AI and added by gitStream.
AI-generated content may contain inaccuracies. Please verify before using.
💡 Tip: You can customize your AI Description using Guidelines Learn how

WordPress 7.1 introduces `Document-Isolation-Policy: isolate-and-credentialless`
on the block editor to enable cross-origin isolation for `SharedArrayBuffer`,
which is required by core's new client-side media processing feature.

When DIP is applied to a parent document but not to its same-origin preview
iframe, the browser places them in separate agent clusters and blocks
synchronous DOM access between them. The Elementor editor relies on
`iframe.contentWindow.elementorFrontend.*` to drive its preview, so applying
DIP only on the editor would surface as:

    Uncaught SecurityError: Failed to read a named property 'elementorFrontend'
    from 'Window': Blocked a frame with origin "..." from accessing a
    cross-origin frame.

Emit `Document-Isolation-Policy: isolate-and-credentialless` on both the
Elementor editor screen and the preview iframe so they share an agent
cluster and DOM access keeps working. Gate the header behind a secure-context
check (HTTPS or localhost) so it's only sent when the browser will honor it,
and expose an `elementor/editor/use_document_isolation_policy` filter for
site owners who need to opt out.

This lets Elementor users on WordPress 7.1+ benefit from client-side media
processing (HEIC/AVIF in-browser, sub-size generation, Ultra HDR, etc.) and
any future capability gated on cross-origin isolation.

Refs: elementor#35975
Refs: https://developer.chrome.com/blog/document-isolation-policy
@CLAassistant

CLAassistant commented May 20, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Comment thread core/editor/editor.php Outdated
Co-authored-by: Weston Ruter <westonruter@gmail.com>
Comment thread core/editor/editor.php Outdated
Comment thread core/editor/editor.php Outdated
Comment thread core/editor/editor.php Outdated
@louiswol94

Copy link
Copy Markdown
Contributor

Thank you @adamsilverstein

@louiswol94 louiswol94 changed the title Feat: Send Document-Isolation-Policy header on editor and preview iframe Feat: Send Document-Isolation-Policy header on editor and preview iframe [ED-24218] May 21, 2026
@louiswol94 louiswol94 changed the title Feat: Send Document-Isolation-Policy header on editor and preview iframe [ED-24218] Internal: Send Document-Isolation-Policy header [ED-24218] May 21, 2026
@louiswol94 louiswol94 changed the title Internal: Send Document-Isolation-Policy header [ED-24218] New: Send Document-Isolation-Policy header [ED-24218] May 21, 2026
@louiswol94 louiswol94 changed the title New: Send Document-Isolation-Policy header [ED-24218] Feature: Send Document-Isolation-Policy header [ED-24218] May 21, 2026
@louiswol94 louiswol94 closed this May 22, 2026
@louiswol94 louiswol94 reopened this May 22, 2026
@louiswol94
louiswol94 merged commit ac69f8d into elementor:main May 22, 2026
175 of 182 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

✅ 🚀 Add support for Document-Isolation-Policy (DIP) so Elementor users can use WordPress 7.1 client-side media

6 participants