@@ -6400,234 +6400,3 @@ function wp_get_image_editor_output_format( $filename, $mime_type ) {
64006400 return apply_filters ( 'image_editor_output_format ' , $ output_format , $ filename , $ mime_type );
64016401}
64026402
6403- /**
6404- * Checks whether client-side media processing is enabled.
6405- *
6406- * Client-side media processing uses the browser's capabilities to handle
6407- * tasks like image resizing and compression before uploading to the server.
6408- *
6409- * @since 7.0.0
6410- *
6411- * @return bool Whether client-side media processing is enabled.
6412- */
6413- function wp_is_client_side_media_processing_enabled (): bool {
6414- // This is due to SharedArrayBuffer requiring a secure context.
6415- $ host = strtolower ( (string ) strtok ( $ _SERVER ['HTTP_HOST ' ] ?? '' , ': ' ) );
6416- $ enabled = ( is_ssl () || 'localhost ' === $ host || str_ends_with ( $ host , '.localhost ' ) );
6417-
6418- /**
6419- * Filters whether client-side media processing is enabled.
6420- *
6421- * @since 7.0.0
6422- *
6423- * @param bool $enabled Whether client-side media processing is enabled. Default true if the page is served in a secure context.
6424- */
6425- return (bool ) apply_filters ( 'wp_client_side_media_processing_enabled ' , $ enabled );
6426- }
6427-
6428- /**
6429- * Sets a global JS variable to indicate that client-side media processing is enabled.
6430- *
6431- * @since 7.0.0
6432- */
6433- function wp_set_client_side_media_processing_flag (): void {
6434- if ( ! wp_is_client_side_media_processing_enabled () ) {
6435- return ;
6436- }
6437-
6438- wp_add_inline_script ( 'wp-block-editor ' , 'window.__clientSideMediaProcessing = true; ' , 'before ' );
6439-
6440- $ chromium_version = wp_get_chromium_major_version ();
6441-
6442- if ( null !== $ chromium_version && $ chromium_version >= 137 ) {
6443- wp_add_inline_script ( 'wp-block-editor ' , 'window.__documentIsolationPolicy = true; ' , 'before ' );
6444- }
6445-
6446- /*
6447- * Register the @wordpress/vips/worker script module as a dynamic dependency
6448- * of the wp-upload-media classic script. This ensures it is included in the
6449- * import map so that the dynamic import() in upload-media.js can resolve it.
6450- */
6451- wp_scripts ()->add_data (
6452- 'wp-upload-media ' ,
6453- 'module_dependencies ' ,
6454- array ( '@wordpress/vips/worker ' )
6455- );
6456- }
6457-
6458- /**
6459- * Returns the major Chrome/Chromium version from the current request's User-Agent.
6460- *
6461- * Matches all Chromium-based browsers (Chrome, Edge, Opera, Brave).
6462- *
6463- * @since 7.0.0
6464- *
6465- * @return int|null The major Chrome version, or null if not a Chromium browser.
6466- */
6467- function wp_get_chromium_major_version (): ?int {
6468- if ( empty ( $ _SERVER ['HTTP_USER_AGENT ' ] ) ) {
6469- return null ;
6470- }
6471- if ( preg_match ( '#Chrome/(\d+)# ' , $ _SERVER ['HTTP_USER_AGENT ' ], $ matches ) ) {
6472- return (int ) $ matches [1 ];
6473- }
6474- return null ;
6475- }
6476-
6477- /**
6478- * Enables cross-origin isolation in the block editor.
6479- *
6480- * Required for enabling SharedArrayBuffer for WebAssembly-based
6481- * media processing in the editor. Uses Document-Isolation-Policy
6482- * on supported browsers (Chromium 137+).
6483- *
6484- * Skips setup when a third-party page builder overrides the block
6485- * editor via a custom `action` query parameter, as DIP would block
6486- * same-origin iframe access that these editors rely on.
6487- *
6488- * @since 7.0.0
6489- */
6490- function wp_set_up_cross_origin_isolation (): void {
6491- if ( ! wp_is_client_side_media_processing_enabled () ) {
6492- return ;
6493- }
6494-
6495- $ screen = get_current_screen ();
6496-
6497- if ( ! $ screen ) {
6498- return ;
6499- }
6500-
6501- if ( ! $ screen ->is_block_editor () && 'site-editor ' !== $ screen ->id && ! ( 'widgets ' === $ screen ->id && wp_use_widgets_block_editor () ) ) {
6502- return ;
6503- }
6504-
6505- /*
6506- * Skip when a third-party page builder overrides the block editor.
6507- * DIP isolates the document into its own agent cluster,
6508- * which blocks same-origin iframe access that these editors rely on.
6509- */
6510- if ( isset ( $ _GET ['action ' ] ) && 'edit ' !== $ _GET ['action ' ] ) {
6511- return ;
6512- }
6513-
6514- // Cross-origin isolation is not needed if users can't upload files anyway.
6515- if ( ! current_user_can ( 'upload_files ' ) ) {
6516- return ;
6517- }
6518-
6519- wp_start_cross_origin_isolation_output_buffer ();
6520- }
6521-
6522- /**
6523- * Sends the Document-Isolation-Policy header for cross-origin isolation.
6524- *
6525- * Uses an output buffer to add crossorigin="anonymous" where needed.
6526- *
6527- * @since 7.0.0
6528- */
6529- function wp_start_cross_origin_isolation_output_buffer (): void {
6530- $ chromium_version = wp_get_chromium_major_version ();
6531-
6532- if ( null === $ chromium_version || $ chromium_version < 137 ) {
6533- return ;
6534- }
6535-
6536- ob_start (
6537- static function ( string $ output ): string {
6538- header ( 'Document-Isolation-Policy: isolate-and-credentialless ' );
6539-
6540- return wp_add_crossorigin_attributes ( $ output );
6541- }
6542- );
6543- }
6544-
6545- /**
6546- * Adds crossorigin="anonymous" to relevant tags in the given HTML string.
6547- *
6548- * @since 7.0.0
6549- *
6550- * @param string $html HTML input.
6551- * @return string Modified HTML.
6552- */
6553- function wp_add_crossorigin_attributes ( string $ html ): string {
6554- $ site_url = site_url ();
6555-
6556- $ processor = new WP_HTML_Tag_Processor ( $ html );
6557-
6558- // See https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin.
6559- $ cross_origin_tag_attributes = array (
6560- 'AUDIO ' => array ( 'src ' => false ),
6561- 'LINK ' => array ( 'href ' => false ),
6562- 'SCRIPT ' => array ( 'src ' => false ),
6563- 'VIDEO ' => array (
6564- 'src ' => false ,
6565- 'poster ' => false ,
6566- ),
6567- 'SOURCE ' => array ( 'src ' => false ),
6568- );
6569-
6570- while ( $ processor ->next_tag () ) {
6571- $ tag = $ processor ->get_tag ();
6572-
6573- if ( ! isset ( $ cross_origin_tag_attributes [ $ tag ] ) ) {
6574- continue ;
6575- }
6576-
6577- if ( 'AUDIO ' === $ tag || 'VIDEO ' === $ tag ) {
6578- $ processor ->set_bookmark ( 'audio-video-parent ' );
6579- }
6580-
6581- $ processor ->set_bookmark ( 'resume ' );
6582-
6583- $ sought = false ;
6584-
6585- $ crossorigin = $ processor ->get_attribute ( 'crossorigin ' );
6586-
6587- $ is_cross_origin = false ;
6588-
6589- foreach ( $ cross_origin_tag_attributes [ $ tag ] as $ attr => $ is_srcset ) {
6590- if ( $ is_srcset ) {
6591- $ srcset = $ processor ->get_attribute ( $ attr );
6592- if ( is_string ( $ srcset ) ) {
6593- foreach ( explode ( ', ' , $ srcset ) as $ candidate ) {
6594- $ candidate_url = strtok ( trim ( $ candidate ), ' ' );
6595- if ( is_string ( $ candidate_url ) && '' !== $ candidate_url && ! str_starts_with ( $ candidate_url , $ site_url ) && ! str_starts_with ( $ candidate_url , '/ ' ) ) {
6596- $ is_cross_origin = true ;
6597- break ;
6598- }
6599- }
6600- }
6601- } else {
6602- $ url = $ processor ->get_attribute ( $ attr );
6603- if ( is_string ( $ url ) && ! str_starts_with ( $ url , $ site_url ) && ! str_starts_with ( $ url , '/ ' ) ) {
6604- $ is_cross_origin = true ;
6605- }
6606- }
6607-
6608- if ( $ is_cross_origin ) {
6609- break ;
6610- }
6611- }
6612-
6613- if ( $ is_cross_origin && ! is_string ( $ crossorigin ) ) {
6614- if ( 'SOURCE ' === $ tag ) {
6615- $ sought = $ processor ->seek ( 'audio-video-parent ' );
6616-
6617- if ( $ sought ) {
6618- $ processor ->set_attribute ( 'crossorigin ' , 'anonymous ' );
6619- }
6620- } else {
6621- $ processor ->set_attribute ( 'crossorigin ' , 'anonymous ' );
6622- }
6623-
6624- if ( $ sought ) {
6625- $ processor ->seek ( 'resume ' );
6626- $ processor ->release_bookmark ( 'audio-video-parent ' );
6627- }
6628- }
6629- }
6630-
6631- return $ processor ->get_updated_html ();
6632- }
6633-
0 commit comments