diff --git a/src/wp-includes/media.php b/src/wp-includes/media.php index 4cd69ade6cbb7..70756fa4a9acf 100644 --- a/src/wp-includes/media.php +++ b/src/wp-includes/media.php @@ -6885,9 +6885,9 @@ function wp_get_media_library_upload_settings(): array { * browser honors Document-Isolation-Policy: without isolation the page never * becomes cross-origin isolated, the script would no-op, and the whole * wp-upload-media dependency chain would be loaded for nothing. The same - * goes for a screen wp_set_up_cross_origin_isolation() did not isolate, - * such as the Customizer or the Site Icon picker: the media frame loads - * there too, but its uploads stay on the classic path. + * goes for a screen wp_send_document_isolation_policy_header() did not + * isolate, such as the Customizer or the Site Icon picker: the media frame + * loads there too, but its uploads stay on the classic path. * * The screen script self-guards at runtime too: when the browser turns out * not to be isolated or lacks client-side media support, it no-ops and the @@ -6945,7 +6945,8 @@ function _wp_enqueue_media_upload_pipeline_script( string $handle ): void { * Covers every `wp.media` frame that uploads through `wp.Uploader`: the * Media Library grid and the media modal the block editor, the site editor * and the block widgets screen open. wp_enqueue_media() calls this on any - * screen that was cross-origin isolated, so it rarely needs calling directly. + * screen wp_send_document_isolation_policy_header() isolated, so it rarely + * needs calling directly. * * @since 7.2.0 */ @@ -6972,6 +6973,9 @@ function wp_enqueue_media_new_upload(): void { * Forcing `crossorigin="anonymous"` would turn those into CORS requests * and break any resource served without `Access-Control-Allow-Origin`. * + * Sending the header also opts the screen's media frames into client-side + * uploads, so call this before wp_enqueue_media() runs. + * * @since 7.2.0 * * @global bool $_wp_cross_origin_isolated Whether the Document-Isolation-Policy header was sent. @@ -6996,14 +7000,15 @@ function wp_send_document_isolation_policy_header(): bool { /** * Whether the current request has been set up for cross-origin isolation. * - * True once wp_set_up_cross_origin_isolation() has sent the + * True once wp_send_document_isolation_policy_header() has sent the * Document-Isolation-Policy header for the screen being rendered, which is * what lets scripts that need a cross-origin isolated page, such as the * client-side media upload integration, decide whether to load at all. * - * A plugin can isolate a screen on its own by sending the header directly, - * as the Gutenberg plugin does on the block editor screens, so a header - * already queued for the response counts too. + * A header a plugin sends itself does not count, since the plugin may + * isolate its screen for reasons of its own. To run the client-side + * pipeline on a screen core does not isolate, call + * wp_send_document_isolation_policy_header() before wp_enqueue_media(). * * @since 7.2.0 * @@ -7014,13 +7019,6 @@ function wp_send_document_isolation_policy_header(): bool { function wp_is_cross_origin_isolated_request(): bool { global $_wp_cross_origin_isolated; - if ( true === $_wp_cross_origin_isolated ) { - return true; - } - - return array_any( - headers_list(), - fn( $header ) => 0 === stripos( $header, 'Document-Isolation-Policy:' ) - ); + return true === $_wp_cross_origin_isolated; } diff --git a/tests/phpunit/tests/media/wpCrossOriginIsolation.php b/tests/phpunit/tests/media/wpCrossOriginIsolation.php index 64884b4e284f9..3722e1618a482 100644 --- a/tests/phpunit/tests/media/wpCrossOriginIsolation.php +++ b/tests/phpunit/tests/media/wpCrossOriginIsolation.php @@ -6,6 +6,7 @@ * @group media * @covers ::wp_set_up_cross_origin_isolation * @covers ::wp_send_document_isolation_policy_header + * @covers ::wp_is_cross_origin_isolated_request * @covers ::wp_is_client_side_media_processing_enabled */ class Tests_Media_wpCrossOriginIsolation extends WP_UnitTestCase { @@ -121,6 +122,32 @@ public function test_sends_header_for_chrome_137() { $this->assertTrue( wp_send_document_isolation_policy_header(), 'The Document-Isolation-Policy header should be sent for Chrome 137.' ); } + /** + * @ticket 66490 + * + * @runInSeparateProcess + * @preserveGlobalState disabled + */ + public function test_sending_header_marks_request_isolated(): void { + $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36'; + + $this->assertFalse( wp_is_cross_origin_isolated_request(), 'The request should not be isolated before the header is sent.' ); + + wp_send_document_isolation_policy_header(); + + $this->assertTrue( wp_is_cross_origin_isolated_request(), 'The request should be isolated once core sends the header.' ); + } + + /** + * @ticket 66490 + */ + public function test_request_not_isolated_when_header_not_sent(): void { + $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Windows NT 10.0; rv:128.0) Gecko/20100101 Firefox/128.0'; + + $this->assertFalse( wp_send_document_isolation_policy_header() ); + $this->assertFalse( wp_is_cross_origin_isolated_request(), 'The request should not be isolated when the header was not sent.' ); + } + /** * @ticket 64766 */ diff --git a/tests/phpunit/tests/media/wpEnqueueMediaFrameUpload.php b/tests/phpunit/tests/media/wpEnqueueMediaFrameUpload.php index 0b6a917e324ed..81f049fbd601c 100644 --- a/tests/phpunit/tests/media/wpEnqueueMediaFrameUpload.php +++ b/tests/phpunit/tests/media/wpEnqueueMediaFrameUpload.php @@ -56,7 +56,7 @@ public function set_up() { $this->original_wp_scripts = $wp_scripts; $wp_scripts = new WP_Scripts(); - // The screen was cross-origin isolated, as wp_set_up_cross_origin_isolation() records. + // The screen was cross-origin isolated, as wp_send_document_isolation_policy_header() records. $GLOBALS['_wp_cross_origin_isolated'] = true; } @@ -91,9 +91,9 @@ public function test_script_enqueued() { } /** - * A screen wp_set_up_cross_origin_isolation() did not isolate cannot run - * the pipeline, so the media frame there keeps its classic uploads and - * does not download the pipeline bundles. + * A screen wp_send_document_isolation_policy_header() did not isolate + * cannot run the pipeline, so the media frame there keeps its classic + * uploads and does not download the pipeline bundles. * * @ticket 65661 */ diff --git a/tests/phpunit/tests/media/wpEnqueueMediaNewUpload.php b/tests/phpunit/tests/media/wpEnqueueMediaNewUpload.php index 02d00b730c79d..afa75cf4fc12d 100644 --- a/tests/phpunit/tests/media/wpEnqueueMediaNewUpload.php +++ b/tests/phpunit/tests/media/wpEnqueueMediaNewUpload.php @@ -54,7 +54,7 @@ public function set_up() { $this->original_wp_scripts = $wp_scripts; $wp_scripts = new WP_Scripts(); - // The screen was cross-origin isolated, as wp_set_up_cross_origin_isolation() records. + // The screen was cross-origin isolated, as wp_send_document_isolation_policy_header() records. $GLOBALS['_wp_cross_origin_isolated'] = true; }