Index: src/wp-admin/includes/ajax-actions.php
===================================================================
--- src/wp-admin/includes/ajax-actions.php	(revision 33249)
+++ src/wp-admin/includes/ajax-actions.php	(working copy)
@@ -3076,41 +3076,87 @@
 		wp_send_json_error( array( 'message' => __( 'Image could not be processed.' ) ) );
 	}
 
-	switch ( $context ) {
-		case 'site-icon':
-			require_once ABSPATH . '/wp-admin/includes/class-wp-site-icon.php';
-			global $wp_site_icon;
+	if ( 'site-icon' === $context ) {
+		require_once ABSPATH . '/wp-admin/includes/class-wp-site-icon.php';
+		global $wp_site_icon;
 
-			/** This filter is documented in wp-admin/custom-header.php */
-			$cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication.
-			$object  = $wp_site_icon->create_attachment_object( $cropped, $attachment_id );
-			unset( $object['ID'] );
+		/** This filter is documented in wp-admin/custom-header.php */
+		$cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication.
+		$object  = $wp_site_icon->create_attachment_object( $cropped, $attachment_id );
+		unset( $object['ID'] );
 
-			// Update the attachment.
-			add_filter( 'intermediate_image_sizes_advanced', array( $wp_site_icon, 'additional_sizes' ) );
-			$attachment_id = $wp_site_icon->insert_attachment( $object, $cropped );
-			remove_filter( 'intermediate_image_sizes_advanced', array( $wp_site_icon, 'additional_sizes' ) );
+		// Update the attachment.
+		add_filter( 'intermediate_image_sizes_advanced', array( $wp_site_icon, 'additional_sizes' ) );
+		$attachment_id = $wp_site_icon->insert_attachment( $object, $cropped );
+		remove_filter( 'intermediate_image_sizes_advanced', array( $wp_site_icon, 'additional_sizes' ) );
 
-			// Additional sizes in wp_prepare_attachment_for_js().
-			add_filter( 'image_size_names_choose', array( $wp_site_icon, 'additional_sizes' ) );
-			break;
+		// Additional sizes in wp_prepare_attachment_for_js().
+		add_filter( 'image_size_names_choose', array( $wp_site_icon, 'additional_sizes' ) );
 
-		default:
+	} elseif ( 'on' === $_POST[ 'wp_customize' ] ) {
+		// Customizer context. Handle attachment creation and allow modification via filters.
+		$parent     = get_post( $attachment_id );
+		$parent_url = $parent->guid;
+		$url        = str_replace( basename( $parent_url ), basename( $cropped ), $parent_url );
 
-			/**
-			 * Filter the attachment ID for a cropped image.
-			 *
-			 * @since 4.3.0
-			 *
-			 * @param int    $attachment_id The ID of the cropped image.
-			 * @param string $context       The feature requesting the cropped image.
-			 */
-			$attachment_id = apply_filters( 'wp_ajax_cropped_attachment_id', 0, $context );
+		$size       = @getimagesize( $cropped );
+		$image_type = ( $size ) ? $size['mime'] : 'image/jpeg';
 
-			if ( ! $attachment_id ) {
-				wp_send_json_error();
-			}
+		$object = array(
+			'post_title'     => basename( $cropped ),
+			'post_content'   => $url,
+			'post_mime_type' => $image_type,
+			'guid'           => $url,
+			'context'        => $context,
+		);
+
+		$cropped_attachment_id = wp_insert_attachment( $object, $cropped );
+		$metadata = wp_generate_attachment_metadata( $cropped_attachment_id, $cropped );
+
+		/**
+		 * Filter the Customizer-croppped image attachment metadata.
+		 *
+		 * @since 4.3.0
+		 *
+		 * @see wp_generate_attachment_metadata()
+		 *
+		 * @param array $metadata Attachment metadata.
+		 */
+		$metadata = apply_filters( 'customize_crop_image_attachment_metadata', $metadata );
+		wp_update_attachment_metadata( $cropped_attachment_id, $metadata );
+
+		/**
+		 * Filter the attachment ID for a cropped image.
+		 *
+		 * @since 4.3.0
+		 *
+		 * @param int    $attachment_id The attachment ID of the cropped image.
+		 * @param string $context       The Customizer control requesting the cropped image.
+		 */
+		$attachment_id = apply_filters( 'customize_ajax_cropped_attachment_id', $cropped_attachment_id, $context );
+
+	} else {
+		// Custom, non-Customizer context. Plugins must implement attachment handling.
+
+		/**
+		 * Filter the attachment ID for a cropped image.
+		 *
+		 * An attachment ID for the cropped image must be returned, but the original attachment id
+		 * is passed. The cropped image will not be returned from the ajax call if a new attachment
+		 * is not created with this filter.
+		 *
+		 * @since 4.3.0
+		 *
+		 * @param int    $attachment_id The ID of the original image attachment.
+		 * @param string $context       The feature requesting the cropped image.
+		 * @param string $cropped       The filepath of the cropped image.
+		 */
+		$attachment_id = apply_filters( 'wp_ajax_cropped_attachment_id', $attachment_id, $context, $cropped );
 	}
 
+	if ( ! $attachment_id ) {
+		wp_send_json_error();
+	}		
+
 	wp_send_json_success( wp_prepare_attachment_for_js( $attachment_id ) );
 }
Index: src/wp-includes/class-wp-customize-control.php
===================================================================
--- src/wp-includes/class-wp-customize-control.php	(revision 33249)
+++ src/wp-includes/class-wp-customize-control.php	(working copy)
@@ -1005,9 +1005,9 @@
  *
  * @since 4.3.0
  *
- * @see WP_Customize_Image_Control
+ * @see WP_Customize_Media_Control
  */
-class WP_Customize_Cropped_Image_Control extends WP_Customize_Image_Control {
+class WP_Customize_Cropped_Image_Control extends WP_Customize_Media_Control {
 
 	/**
 	 * Control type.
Index: src/wp-includes/script-loader.php
===================================================================
--- src/wp-includes/script-loader.php	(revision 33249)
+++ src/wp-includes/script-loader.php	(working copy)
@@ -410,7 +410,7 @@
 	$scripts->add( 'customize-loader',   "/wp-includes/js/customize-loader$suffix.js",   array( 'customize-base' ), false, 1 );
 	$scripts->add( 'customize-preview',  "/wp-includes/js/customize-preview$suffix.js",  array( 'customize-base' ), false, 1 );
 	$scripts->add( 'customize-models',   "/wp-includes/js/customize-models.js", array( 'underscore', 'backbone' ), false, 1 );
-	$scripts->add( 'customize-views',    "/wp-includes/js/customize-views.js",  array( 'jquery', 'underscore', 'imgareaselect', 'customize-models' ), false, 1 );
+	$scripts->add( 'customize-views',    "/wp-includes/js/customize-views.js",  array( 'jquery', 'underscore', 'imgareaselect', 'customize-models', 'media-editor', 'media-views' ), false, 1 );
 	$scripts->add( 'customize-controls', "/wp-admin/js/customize-controls$suffix.js", array( 'customize-base' ), false, 1 );
 	did_action( 'init' ) && $scripts->localize( 'customize-controls', '_wpCustomizeControlsL10n', array(
 		'activate'           => __( 'Save &amp; Activate' ),
