Repository navigation
[Website] Rewrite COEP/COOP headers as Document-Isolation-Policy in supporting browsers - #3028
Conversation
…upporting browsers
…-Isolation-Policy When Document-Isolation-Policy is enabled, the parent frame can no longer access iframe.contentWindow.location.href due to cross-origin restrictions. This breaks Playground's URL bar synchronization. This commit adds a WordPress MU plugin that posts the current URL to the parent frame on page load, and updates the boot script to listen for these messages alongside the existing iframe load event handling.
|
Somehow I don't see the client-side media control. But at least the editor doesn't blow up. Still, I wonder what am I missing. |
|
The failing tests are more likely related to the test setup than a shortcoming of this PR. Let's fix them and let's also not block a review on these failures. |
|
@adamziel Nice! 👏 It bugs me that there is no way to indicate "ignore COOP/COEP headers when DIP is supported," not even an easier way to detect the feature, but here we are. After all, this might be temporary if DIP is generally adopted. |
| const newHeaders = new Headers(response.headers); | ||
| newHeaders.delete('cross-origin-embedder-policy'); | ||
| newHeaders.delete('cross-origin-opener-policy'); | ||
| newHeaders.set('document-isolation-policy', 'isolate-and-credentialless'); |
There was a problem hiding this comment.
Should we read the value of cross-origin-opener-policy and set either isolate-and-require-corp or isolate-and-credentialless accordingly?
There was a problem hiding this comment.
Oh good call! Yes, let's do that.
…lements The tests were failing in CI because they checked for the 'Add title' textbox before WordPress admin finished loading. In CI, loading takes longer than locally, so the tests would time out. This fix adds an explicit wait for the admin menu (#adminmenu) before checking for editor-specific elements. It also increases timeouts for tests that install Gutenberg, since plugin installation adds additional load time.
…nd-require-corp or isolate-and-credentialless accordingly
Skip Firefox/WebKit tests since Document-Isolation-Policy is only supported in Chromium. Simplify assertions to use body text content checks instead of specific element visibility which can be fragile across Gutenberg versions.
The Document-Isolation-Policy header on empty.html was being added unconditionally, which broke REST API authentication when the parent page didn't have COEP/COOP headers. The 'isolate-and-credentialless' policy causes cross-origin requests to be sent without credentials, resulting in "Session expired" errors. This change tracks which scopes have COEP headers rewritten to Document-Isolation-Policy, and only adds the header to empty.html when the scope requires cross-origin isolation. Also updated E2E test assertions to check for the admin menu visibility instead of "Add New Post" text, which may not be visible in the modern block editor.
Summary
This PR enables cross-origin isolation (required for SharedArrayBuffer) without breaking external embeds like YouTube videos.
Playground's client-side media processing experiment relies on SharedArrayBuffer, which requires cross-origin isolation. The traditional approach uses Cross-Origin-Embedder-Policy (COEP) and Cross-Origin-Opener-Policy (COOP) headers, but these are viral – once set, they affect the entire site and break external embeds that don't set matching headers.
Document-Isolation-Policy is a newer specification that provides cross-origin isolation on a per-document basis without these limitations. This PR feature-detects browser support for Document-Isolation-Policy and rewrites COEP/COOP headers to it automatically in supporting browsers.
Feature detection
This PR detects the
Document-Isolation-Policysupport by:As more browsers implement the specification, they'll automatically receive the better experience without code changes.
Handling cross-origin iframe restrictions
Document-Isolation-Policy introduces a side effect: the parent frame can no longer access
iframe.contentWindow.location.hrefdue to cross-origin restrictions. This would break Playground's URL bar synchronization.To work around this, a WordPress MU plugin now posts the current URL to the parent frame on each page load. The boot script listens for these messages and updates the address bar accordingly, alongside the existing iframe load event handling.
Test plan
Here's a Blueprint that takes you directly to the post editor with the Gutenberg plugin installed and the media processing experiment enabled:
{ "$schema": "https://playground.wordpress.net/blueprint-schema.json", "meta": { "title": "Enable all three Dataview Experiments in Gutenberg", "author": "bph", "description": "Blueprint example to enable multiple Experiments within the Gutenberg plugin ", "categories": ["Gutenberg", "Experiments"] }, "landingPage": "/wp-admin/post-new.php", "plugins": ["gutenberg"], "login": true, "steps": [ { "step": "runPHP", "code": "<?php require '/wordpress/wp-load.php'; update_option( 'gutenberg-experiments', array( 'gutenberg-media-processing' => true, 'gutenberg-new-posts-dashboard' => true, 'gutenberg-quick-edit-dataviews' => true ) );" } ] }Related to #2954