Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/wp-admin/edit-form-blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ static function ( $classes ) {
'description',
'gmt_offset',
'home',
'image_sizes',
'image_size_threshold',
'image_output_formats',
'jpeg_interlaced',
'png_interlaced',
'gif_interlaced',
'name',
'site_icon',
'site_icon_url',
Expand Down
6 changes: 6 additions & 0 deletions src/wp-admin/site-editor.php
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,12 @@ static function ( $classes ) {
'description',
'gmt_offset',
'home',
'image_sizes',
'image_size_threshold',
'image_output_formats',
'jpeg_interlaced',
'png_interlaced',
'gif_interlaced',
'name',
'site_icon',
'site_icon_url',
Expand Down
8 changes: 8 additions & 0 deletions src/wp-includes/default-filters.php
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,14 @@
add_action( 'plugins_loaded', '_wp_add_additional_image_sizes', 0 );
add_filter( 'plupload_default_settings', 'wp_show_heic_upload_error' );

// Cross-origin isolation for client-side media processing.
add_action( 'load-post.php', 'wp_set_up_cross_origin_isolation' );
add_action( 'load-post-new.php', 'wp_set_up_cross_origin_isolation' );
add_action( 'load-site-editor.php', 'wp_set_up_cross_origin_isolation' );
add_action( 'load-widgets.php', 'wp_set_up_cross_origin_isolation' );
add_filter( 'mod_rewrite_rules', 'wp_filter_mod_rewrite_rules_for_wasm' );
add_action( 'wp_enqueue_media', 'wp_override_media_templates' );

// Nav menu.
add_filter( 'nav_menu_item_id', '_nav_menu_item_id_use_once', 10, 2 );
add_filter( 'nav_menu_css_class', 'wp_nav_menu_remove_menu_item_has_children_class', 10, 4 );
Expand Down
176 changes: 176 additions & 0 deletions src/wp-includes/media.php
Original file line number Diff line number Diff line change
Expand Up @@ -6359,3 +6359,179 @@ function wp_get_image_editor_output_format( $filename, $mime_type ) {
*/
return apply_filters( 'image_editor_output_format', $output_format, $filename, $mime_type );
}

/**
* Enables cross-origin isolation in the block editor.
*
* Required for enabling SharedArrayBuffer for WebAssembly-based
* media processing in the editor.
*
* @since 7.0.0
*
* @link https://web.dev/coop-coep/
*/
function wp_set_up_cross_origin_isolation() {
$screen = get_current_screen();

if ( ! $screen ) {
return;
}

if ( ! $screen->is_block_editor() && 'site-editor' !== $screen->id && ! ( 'widgets' === $screen->id && wp_use_widgets_block_editor() ) ) {
return;
}

$user_id = get_current_user_id();
if ( ! $user_id ) {
return;
}

// Cross-origin isolation is not needed if users can't upload files anyway.
if ( ! user_can( $user_id, 'upload_files' ) ) {
return;
}

wp_start_cross_origin_isolation_output_buffer();
}

/**
* Starts an output buffer to send cross-origin isolation headers.
*
* Sends headers and uses an output buffer to add crossorigin="anonymous"
* attributes where needed.
*
* @since 7.0.0
*
* @link https://web.dev/coop-coep/
*
* @global bool $is_safari
*/
function wp_start_cross_origin_isolation_output_buffer() {
global $is_safari;

$coep = $is_safari ? 'require-corp' : 'credentialless';

ob_start(
static function ( string $output ) use ( $coep ): string {
header( 'Cross-Origin-Opener-Policy: same-origin' );
header( "Cross-Origin-Embedder-Policy: $coep" );

return wp_add_crossorigin_attributes( $output );
}
);
}

/**
* Adds crossorigin="anonymous" to relevant tags in the given HTML string.
*
* @since 7.0.0
*
* @param string $html HTML input.
* @return string Modified HTML.
*/
function wp_add_crossorigin_attributes( string $html ): string {
$site_url = site_url();

$processor = new WP_HTML_Tag_Processor( $html );

// See https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin.
$tags = array(
'AUDIO' => 'src',
'IMG' => 'src',
'LINK' => 'href',
'SCRIPT' => 'src',
'VIDEO' => 'src',
'SOURCE' => 'src',
);

$tag_names = array_keys( $tags );

while ( $processor->next_tag() ) {
$tag = $processor->get_tag();

if ( ! in_array( $tag, $tag_names, true ) ) {
continue;
}

if ( 'AUDIO' === $tag || 'VIDEO' === $tag ) {
$processor->set_bookmark( 'audio-video-parent' );
}

$processor->set_bookmark( 'resume' );

$sought = false;

$crossorigin = $processor->get_attribute( 'crossorigin' );

$url = $processor->get_attribute( $tags[ $tag ] );

if ( is_string( $url ) && ! str_starts_with( $url, $site_url ) && ! str_starts_with( $url, '/' ) && ! is_string( $crossorigin ) ) {
if ( 'SOURCE' === $tag ) {
$sought = $processor->seek( 'audio-video-parent' );

if ( $sought ) {
$processor->set_attribute( 'crossorigin', 'anonymous' );
}
} else {
$processor->set_attribute( 'crossorigin', 'anonymous' );
}

if ( $sought ) {
$processor->seek( 'resume' );
$processor->release_bookmark( 'audio-video-parent' );
}
}
}

return $processor->get_updated_html();
}

/**
* Filters the list of rewrite rules formatted for output to an .htaccess file.
*
* Adds support for serving WebAssembly files used by client-side media processing.
*
* @since 7.0.0
*
* @param string $rules mod_rewrite Rewrite rules formatted for .htaccess.
* @return string Filtered rewrite rules.
*/
function wp_filter_mod_rewrite_rules_for_wasm( string $rules ): string {
$rules .= "\n# BEGIN WordPress client-side media processing\n" .
"AddType application/wasm wasm\n" .
"# END WordPress client-side media processing\n";

return $rules;
}

/**
* Overrides templates from wp_print_media_templates with custom ones.
*
* Adds `crossorigin` attribute to all tags that could have assets
* loaded from a different domain for cross-origin isolation support.
*
* @since 7.0.0
*/
function wp_override_media_templates() {
remove_action( 'admin_footer', 'wp_print_media_templates' );
add_action(
'admin_footer',
static function () {
ob_start();
wp_print_media_templates();
$html = (string) ob_get_clean();

$tags = array(
'audio',
'img',
'video',
);

foreach ( $tags as $tag ) {
$html = (string) str_replace( "<$tag", "<$tag crossorigin=\"anonymous\"", $html );
}

echo $html;
}
);
}
32 changes: 32 additions & 0 deletions src/wp-includes/rest-api/class-wp-rest-server.php
Original file line number Diff line number Diff line change
Expand Up @@ -1368,6 +1368,38 @@ public function get_index( $request ) {
'routes' => $this->get_data_for_routes( $this->get_routes(), $request['context'] ),
);

// Add media processing settings for users who can upload files.
if ( current_user_can( 'upload_files' ) ) {
// Image sizes with normalized data.
$sizes = wp_get_registered_image_subsizes();
foreach ( $sizes as $name => &$size ) {
$size['height'] = (int) $size['height'];
$size['width'] = (int) $size['width'];
$size['name'] = $name;
}
unset( $size );
$available['image_sizes'] = $sizes;

/** This filter is documented in wp-admin/includes/image.php */
$available['image_size_threshold'] = (int) apply_filters( 'big_image_size_threshold', 2560, array( 0, 0 ), '', 0 );

// Image output formats.
$input_formats = array( 'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/avif', 'image/heic' );
$output_formats = array();
foreach ( $input_formats as $mime_type ) {
/** This filter is documented in wp-includes/class-wp-image-editor.php */
$output_formats = apply_filters( 'image_editor_output_format', $output_formats, '', $mime_type );
}
$available['image_output_formats'] = (object) $output_formats;

/** This filter is documented in wp-includes/class-wp-image-editor-imagick.php */
$available['jpeg_interlaced'] = (bool) apply_filters( 'image_save_progressive', false, 'image/jpeg' );
/** This filter is documented in wp-includes/class-wp-image-editor-imagick.php */
$available['png_interlaced'] = (bool) apply_filters( 'image_save_progressive', false, 'image/png' );
/** This filter is documented in wp-includes/class-wp-image-editor-imagick.php */
$available['gif_interlaced'] = (bool) apply_filters( 'image_save_progressive', false, 'image/gif' );
}

$response = new WP_REST_Response( $available );

$fields = $request['_fields'] ?? '';
Expand Down
Loading
Loading