Index: src/wp-admin/css/customize-controls.css
===================================================================
--- src/wp-admin/css/customize-controls.css	(revision 31433)
+++ src/wp-admin/css/customize-controls.css	(working copy)
@@ -831,7 +831,177 @@
 	float: right;
 }
 
+/**
+ * Themes
+ */
+@-webkit-keyframes customize-reload {
+	0%   { opacity: 0; }
+	100% { opacity: 1; }
+}
 
+@-moz-keyframes customize-reload {
+	0%   { opacity: 0; }
+	100% { opacity: 1; }
+}
+
+@keyframes customize-reload {
+	0%   { opacity: 0; }
+	100% { opacity: 1; }
+}
+
+/* #customize-container is reused from customize-loader.js, hence the naming. */
+.wp-customizer.customize-loading #customize-container {
+	display: block;
+	-webkit-animation: customize-reload .75s; /* Can't use `transition` because `display` changes here. */
+	-moz-animation: customize-reload .75s;
+	animation: customize-reload .75s;
+}
+
+.customize-themes-panel {
+	display: none;
+	padding: 0 8px;
+	background: #f1f1f1;
+	box-sizing: border-box;
+	-webkit-box-sizing: border-box;
+	-moz-box-sizing: border-box;
+}
+
+.control-section.open .customize-themes-panel {
+	display: block;
+}
+
+#customize-theme-controls .customize-themes-panel .accordion-section-content {
+	background: transparent;
+	display: block;
+}
+
+.customize-control.customize-control-theme {
+	margin-bottom: 8px;
+}
+
+.wp-customizer .theme-browser .themes {
+	padding-bottom: 8px;
+}
+
+.wp-customizer .theme-browser .theme {
+	margin: 0;
+	width: 100%;
+}
+
+.wp-customizer .theme-browser .theme .theme-actions {
+	-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
+	opacity: 1;
+}
+
+#customize-controls h3.theme-name {
+	font-size: 15px;
+}
+
+.wp-customizer .theme-browser .theme.active .theme-name {
+	padding-right: 15px;
+}
+
+.wp-customizer #themes-filter {
+	width: 100%;
+}
+
+/* Panel-like behavior */
+#accordion-section-themes .accordion-section-title:after {
+	content: "\f148";
+}
+
+.rtl #accordion-section-themes .accordion-section-title:after {
+	-webkit-transform: rotate(180deg);
+	-ms-transform: rotate(180deg);
+	transform: rotate(180deg);
+}
+
+#customize-theme-controls .control-section.current-panel > h3.accordion-section-title {
+	left: 0;
+}
+
+.customize-themes-panel.control-panel-content {
+	position: absolute;
+	left: -100%;
+	top: 0;
+	width: 100%;
+	border-top: 1px solid #ddd;
+}
+
+.in-themes-panel #customize-info,
+.in-themes-panel #customize-theme-controls > ul > .accordion-section {
+	left: 100%;
+}
+
+.themes-panel-back:before {
+	top: 13px;
+	left: 14px;
+}
+
+.in-themes-panel .themes-panel-back {
+	left: 0;
+}
+
+.in-sub-panel .themes-panel-back {
+	display: none;
+}
+
+.control-panel-back.themes-panel-back:before {
+	content: "\f345";
+}
+
+.rtl .control-panel-back.themes-panel-back:before {
+	content: "\f341";
+}
+
+/* Details View */
+.wp-customizer .theme-overlay {
+	display: none;
+}
+
+.wp-customizer.modal-open .theme-overlay {
+	position: fixed;
+	left: 0;
+	top: 0;
+	right: 0;
+	bottom: 0;
+	z-index: 109;
+}
+
+.wp-customizer .theme-overlay .theme-backdrop {
+	background: rgba( 238, 238, 238, 0.75 );
+	position: fixed;
+	z-index: 110;
+}
+
+.wp-customizer .theme-overlay .theme-wrap {
+	left: 90px;
+	right: 90px;
+	top: 45px;
+	bottom: 45px;
+	z-index: 120;
+	max-width: 1740px; /* To ensure that theme screenshots are not displayed larger than 880px wide. */
+}
+
+.wp-customizer .theme-overlay .theme-actions {
+	text-align: right; /* Because there's only one action, match the pattern of media modals and right-align the action. */
+}
+
+.modal-open .in-themes-panel #customize-controls .wp-full-overlay-sidebar-content {
+	overflow: visible; /* Prevent the top-level Customizer controls from becoming visible when elements on the right of the details modal are focused.
+}
+
+/* Small Screens */
+@media (max-width:850px), (max-height:472px) {
+	.wp-customizer .theme-overlay .theme-wrap {
+		left: 0;
+		right: 0;
+		top: 0;
+		bottom: 0;
+	}	
+}
+
+
 /** Handle cheaters. */
 body.cheatin {
 	font-size: medium;
Index: src/wp-admin/includes/theme.php
===================================================================
--- src/wp-admin/includes/theme.php	(revision 31433)
+++ src/wp-admin/includes/theme.php	(working copy)
@@ -486,3 +486,58 @@
 	$prepared_themes = apply_filters( 'wp_prepare_themes_for_js', $prepared_themes );
 	return array_values( $prepared_themes );
 }
+
+/**
+ * Print JS templates for the theme-browsing UI in the Customizer.
+ *
+ * @since 4.2.0
+ */
+function customize_themes_print_templates() {
+	?>
+	<script type="text/html" id="tmpl-customize-themes-details-view">
+		<div class="theme-backdrop"></div>
+		<div class="theme-wrap">
+			<div class="theme-header">
+				<button type="button" class="left dashicons dashicons-no"><span class="screen-reader-text"><?php _e( 'Show previous theme' ); ?></span></button>
+				<button type="button" class="right dashicons dashicons-no"><span class="screen-reader-text"><?php _e( 'Show next theme' ); ?></span></button>
+				<button type="button" class="close dashicons dashicons-no"><span class="screen-reader-text"><?php _e( 'Close details dialog' ); ?></span></button>
+			</div>
+			<div class="theme-about">
+				<div class="theme-screenshots">
+				<# if ( data.screenshot[0] ) { #>
+					<div class="screenshot"><img src="{{ data.screenshot[0] }}" alt="" /></div>
+				<# } else { #>
+					<div class="screenshot blank"></div>
+				<# } #>
+				</div>
+
+				<div class="theme-info">
+					<# if ( data.active ) { #>
+						<span class="current-label"><?php _e( 'Current Theme' ); ?></span>
+					<# } #>
+					<h3 class="theme-name">{{{ data.name }}}<span class="theme-version"><?php printf( __( 'Version: %s' ), '{{ data.version }}' ); ?></span></h3>
+					<h4 class="theme-author"><?php printf( __( 'By %s' ), '{{{ data.authorAndUri }}}' ); ?></h4>
+					<p class="theme-description">{{{ data.description }}}</p>
+
+					<# if ( data.parent ) { #>
+						<p class="parent-theme"><?php printf( __( 'This is a child theme of %s.' ), '<strong>{{{ data.parent }}}</strong>' ); ?></p>
+					<# } #>
+
+					<# if ( data.tags ) { #>
+						<p class="theme-tags"><span><?php _e( 'Tags:' ); ?></span> {{ data.tags }}</p>
+					<# } #>
+				</div>
+			</div>
+
+			<div class="theme-actions">
+				<# if ( ! data.active ) { #>
+					<div class="inactive-theme">
+						<a href="<?php echo add_query_arg( 'theme', '{{ data.id }}', remove_query_arg( 'theme' ) ); ?>" target="_top" class="button button-primary"><?php _e( 'Live Preview' ); ?></a>
+					</div>
+				<# } #>
+			</div>
+		</div>
+	</script>
+	<?php
+}
+add_action( 'customize_controls_print_footer_scripts', 'customize_themes_print_templates' );
Index: src/wp-admin/js/customize-controls.js
===================================================================
--- src/wp-admin/js/customize-controls.js	(revision 31433)
+++ src/wp-admin/js/customize-controls.js	(working copy)
@@ -521,6 +521,351 @@
 	});
 
 	/**
+	 * wp.customize.ThemesSection
+	 *
+	 * Custom section for themes that functions similarly to a backwards panel,
+	 * and also handles the theme-details view rendering and navigation.
+	 *
+	 * @constructor
+	 * @augments wp.customize.Section
+	 * @augments wp.customize.Container
+	 */
+	api.ThemesSection = api.Section.extend({
+		currentTheme: '',
+		overlay: '',
+		template: '',
+
+		/**
+		 * @since 4.2.0
+		 */
+		ready: function () {
+			var section = this;
+			section.overlay = section.container.find( '.theme-overlay' );
+			section.template = wp.template( 'customize-themes-details-view' );
+
+			// Bind global keyboard events.
+			$( 'body' ).on( 'keyup', function( event ) {
+				if ( ! section.overlay.find( '.theme-wrap' ).is( ':visible' ) ) {
+					return;
+				}
+
+				// Pressing the right arrow key fires a theme:next event
+				if ( 39 === event.keyCode ) {
+					section.nextTheme();
+				}
+
+				// Pressing the left arrow key fires a theme:previous event
+				if ( 37 === event.keyCode ) {
+					section.previousTheme();
+				}
+
+				// Pressing the escape key fires a theme:collapse event
+				if ( 27 === event.keyCode ) {
+					section.closeDetails();
+				}
+			});
+		},
+
+		/**
+		 * @since 4.2.0
+		 */
+		attachEvents: function () {
+			var meta, section = this;
+
+			// Expand/Collapse section/panel.
+			section.container.find( '.accordion-section-title' ).on( 'click keydown', function( event ) {
+				if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+					return;
+				}
+				event.preventDefault(); // Keep this AFTER the key filter above
+
+				if ( section.expanded() ) {
+					section.collapse();
+				} else {
+					section.expand();
+				}
+			});
+
+			section.container.find( '.themes-panel-back' ).on( 'click keydown', function( event ) {
+				if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+					return;
+				}
+
+				event.preventDefault(); // Keep this AFTER the key filter above
+
+				section.collapse();
+			});
+
+			// Theme navigation in details view.
+			section.container.on( 'click keydown', '.left', function( event ) {
+				if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+					return;
+				}
+
+				event.preventDefault(); // Keep this AFTER the key filter above
+
+				section.previousTheme();
+			});
+
+			section.container.on( 'click keydown', '.right', function( event ) {
+				if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+					return;
+				}
+
+				event.preventDefault(); // Keep this AFTER the key filter above
+
+				section.nextTheme();
+			});
+
+			section.container.on( 'click keydown', '.theme-backdrop, .close', function( event ) {
+				if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+					return;
+				}
+
+				event.preventDefault(); // Keep this AFTER the key filter above
+
+				section.closeDetails();
+			});
+
+			section.container.on( 'click keydown', '.theme-actions .button', function( event ) {
+				if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+					return;
+				}
+
+				$( 'body' ).addClass( 'customize-loading' ); // @todo if they get a `confirm()`, remove the class if they stay (core patch).
+			});
+
+			section.container.on( 'input', '#themes-filter', function( event ) {
+				var term = event.currentTarget.value.toLowerCase().trim().replace( '-', ' ' ),
+					controls = section.controls();
+				controls.pop(); // Remove the last control (the add-new control).
+				_.each( controls, function( control ) {
+					control.filter( term );
+				});
+				// Update theme count. Note that the add-theme tile is a div.customize-control.
+				count = section.container.find( 'li.customize-control:visible' ).length;
+				section.container.find( '.theme-count' ).text( count );
+			});
+		},
+
+		/**
+		 * Update UI to reflect expanded state
+		 *
+		 * @since 4.2.0
+		 *
+		 * @param {Boolean}  expanded
+		 * @param {Object}   args
+		 * @param {Boolean}  args.unchanged
+		 * @param {Callback} args.completeCallback
+		 */
+		onChangeExpanded: function ( expanded, args ) {
+
+			// Immediately call the complete callback if there were no changes
+			if ( args.unchanged ) {
+				if ( args.completeCallback ) {
+					args.completeCallback();
+				}
+				return;
+			}
+
+			// Note: there is a second argument 'args' passed
+			var position, scroll,
+				panel = this,
+				section = panel.container.closest( '.accordion-section' ),
+				overlay = section.closest( '.wp-full-overlay' ),
+				container = section.closest( '.accordion-container' ),
+				siblings = container.find( '.open' ),
+				topPanel = overlay.find( '#customize-theme-controls > ul > .accordion-section > .accordion-section-title' ).add( '#customize-info > .accordion-section-title' ),
+				backBtn = overlay.find( '.themes-panel-back' ),
+				panelTitle = section.find( '.accordion-section-title' ).first(),
+				content = section.find( '.control-panel-content' );
+
+			if ( expanded ) {
+
+				// Collapse any sibling sections/panels
+				api.section.each( function ( otherSection ) {
+					if ( otherSection !== panel ) {
+						otherSection.collapse( { duration: args.duration } );
+					}
+				});
+				api.panel.each( function ( otherPanel ) {
+					if ( panel !== otherPanel ) {
+						otherPanel.collapse( { duration: 0 } );
+					}
+				});
+
+				content.show( 0, function() {
+					position = content.offset().top;
+					scroll = container.scrollTop();
+					content.css( 'margin-top', ( 45 - position - scroll ) );
+					section.addClass( 'current-panel' );
+					overlay.addClass( 'in-themes-panel' );
+					container.scrollTop( 0 );
+					if ( args.completeCallback ) {
+						args.completeCallback();
+					}
+				} );
+				topPanel.attr( 'tabindex', '-1' );
+				backBtn.attr( 'tabindex', '0' );
+				backBtn.focus();
+			} else {
+				siblings.removeClass( 'open' );
+				section.removeClass( 'current-panel' );
+				overlay.removeClass( 'in-themes-panel' );
+				content.delay( 180 ).hide( 0, function() {
+					content.css( 'margin-top', 'inherit' ); // Reset
+					if ( args.completeCallback ) {
+						args.completeCallback();
+					}
+				} );
+				topPanel.attr( 'tabindex', '0' );
+				backBtn.attr( 'tabindex', '-1' );
+				panelTitle.focus();
+				container.scrollTop( 0 );
+			}
+		},
+
+		/**
+		 * Advance the modal to the next theme.
+		 *
+		 * @since 4.2.0
+		 */
+		nextTheme: function () {
+			var section = this;
+			if ( section.getNextTheme() ) {
+				section.showDetails( section.getNextTheme(), function() {
+					section.overlay.find( '.right' ).focus();
+				} );
+			}
+		},
+
+		/**
+		 * Get the next theme model.
+		 *
+		 * @since 4.2.0
+		 */
+		getNextTheme: function () {
+			var control, next;
+			control = api.control( 'theme_' + this.currentTheme );
+			next = control.container.next( 'li.customize-control-theme' );
+			if ( ! next.length ) {
+				return false;
+			}
+			next = next[0].id.replace( 'customize-control-', '' );
+			control = api.control( next );
+
+			return control.params.theme;
+		},
+
+		/**
+		 * Advance the modal to the previous theme.
+		 *
+		 * @since 4.2.0
+		 */
+		previousTheme: function () {
+			var section = this;
+			if ( section.getPreviousTheme() ) {
+				section.showDetails( section.getPreviousTheme(), function() {
+					section.overlay.find( '.left' ).focus();
+				} );
+			}
+		},
+
+		/**
+		 * Get the previous theme model.
+		 *
+		 * @since 4.2.0
+		 */
+		getPreviousTheme: function () {
+			var control, previous;
+			control = api.control( 'theme_' + this.currentTheme );
+			previous = control.container.prev( 'li.customize-control-theme' );
+			if ( ! previous.length ) {
+				return false;
+			}
+			previous = previous[0].id.replace( 'customize-control-', '' );
+			control = api.control( previous );
+
+			return control.params.theme;
+		},
+
+		/**
+		 * Disable buttons when we're viewing the first or last theme.
+		 *
+		 * @since 4.2.0
+		 */
+		updateLimits: function () {
+			if ( ! this.getNextTheme() ) {
+				this.overlay.find( '.right' ).addClass( 'disabled' );
+			}
+			if ( ! this.getPreviousTheme() ) {
+				this.overlay.find( '.left' ).addClass( 'disabled' );
+			}
+		},
+
+		/**
+		 * Render & show the theme details for a given theme model.
+		 *
+		 * @since 4.2.0
+		 *
+		 * @param {Object}   theme
+		 */
+		showDetails: function ( theme, callback ) {
+			var section = this;
+			callback = callback || function(){};
+			section.currentTheme = theme.id;
+			section.overlay.html( section.template( theme ) )
+			               .fadeIn( 'fast' )
+			               .focus();
+			$( 'body' ).addClass( 'modal-open' );
+			section.containFocus( section.overlay );
+			section.updateLimits();
+			callback();
+		},
+
+		/**
+		 * Close the theme details modal.
+		 *
+		 * @since 4.2.0
+		 */
+		closeDetails: function ( theme ) {
+			$( 'body' ).removeClass( 'modal-open' );
+			this.overlay.fadeOut( 'fast' );
+			api.control( 'theme_' + this.currentTheme ).focus();
+		},
+
+		/**
+		 * Keep tab focus within the theme details modal.
+		 *
+		 * @since 4.2.0
+		 */
+		containFocus: function( el ) {
+			var tabbables;
+
+			el.on( 'keydown', function( event ) {
+
+				// Return if it's not the tab key
+				// When navigating with prev/next focus is already handled
+				if ( 9 !== event.keyCode ) {
+					return;
+				}
+
+				// uses jQuery UI to get the tabbable elements
+				tabbables = $( ':tabbable', el );
+
+				// Keep focus within the overlay
+				if ( tabbables.last()[0] === event.target && ! event.shiftKey ) {
+					tabbables.first().focus();
+					return false;
+				} else if ( tabbables.first()[0] === event.target && event.shiftKey ) {
+					tabbables.last().focus();
+					return false;
+				}
+			});
+		}
+	});
+
+	/**
 	 * @since 4.1.0
 	 *
 	 * @class
@@ -1409,6 +1754,63 @@
 
 	});
 
+	/**
+	 * wp.customize.ThemeControl
+	 *
+	 * @constructor
+	 * @augments wp.customize.Control
+	 * @augments wp.customize.Class
+	 */
+	api.ThemeControl = api.Control.extend({
+
+		/**
+		 * @since 4.2.0
+		 */
+		ready: function() {
+			var control = this;
+
+			// Bind details view trigger.
+			control.container.on( 'click keydown', '.theme', function( event ) {
+				if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+					return;
+				}
+
+				if ( 'button' === event.target.className ) {
+					return;
+				}
+
+				api.section( control.section() ).showDetails( control.params.theme );
+			});
+
+			control.container.on( 'click keydown', '.theme-actions .button', function( event ) {
+				if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+					return;
+				}
+
+				$( 'body' ).addClass( 'customize-loading' );
+			});
+		},
+
+		/**
+		 * Show or hide the theme based on the presence of the term in the title, description, and author.
+		 *
+		 * @since 4.2.0
+		 */
+		filter: function( term ) {
+			var control = this,
+			    haystack = control.params.theme.name + ' '
+				           + control.params.theme.description + ' '
+				           + control.params.theme.tags + ' '
+				           + control.params.theme.author;
+			haystack = haystack.toLowerCase().replace( '-', ' ' );
+			if ( -1 !== haystack.search( term ) ) {
+				control.activate();
+			} else {
+				control.deactivate();
+			}
+		}
+	});
+
 	// Change objects contained within the main customize object to Settings.
 	api.defaultConstructor = api.Setting;
 
@@ -1853,14 +2255,17 @@
 	});
 
 	api.controlConstructor = {
-		color:  api.ColorControl,
-		upload: api.UploadControl,
-		image:  api.ImageControl,
-		header: api.HeaderControl,
-		background: api.BackgroundControl
+		color:      api.ColorControl,
+		upload:     api.UploadControl,
+		image:      api.ImageControl,
+		header:     api.HeaderControl,
+		background: api.BackgroundControl,
+		theme:      api.ThemeControl
 	};
 	api.panelConstructor = {};
-	api.sectionConstructor = {};
+	api.sectionConstructor = {
+		themes: api.ThemesSection
+	};
 
 	$( function() {
 		api.settings = window._wpCustomizeSettings;
Index: src/wp-includes/class-wp-customize-control.php
===================================================================
--- src/wp-includes/class-wp-customize-control.php	(revision 31433)
+++ src/wp-includes/class-wp-customize-control.php	(working copy)
@@ -1101,6 +1101,101 @@
 }
 
 /**
+ * Customize Theme Control Class
+ *
+ * @package WordPress
+ * @subpackage Customize
+ * @since 4.2.0
+ */
+class WP_Customize_Theme_Control extends WP_Customize_Control {
+
+	public $type = 'theme';
+	public $theme;
+
+	/**
+	 * Refresh the parameters passed to the JavaScript via JSON.
+	 *
+	 * @since 4.2.0
+	 * @uses WP_Customize_Control::to_json()
+	 */
+	public function to_json() {
+		parent::to_json();
+		$this->json['theme'] = $this->theme;
+	}
+
+	/**
+	 * Don't render the control content from PHP, as it's rendered via JS on load.
+	 *
+	 * @since 4.2.0
+	 */
+	public function render_content() {}
+
+	/**
+	 * Render a JS template for theme display.
+	 *
+	 * @since 4.2.0
+	 */
+	public function content_template() {
+	?>
+		<div class="theme<# if ( data.theme.active ) { #> active<# } #>" tabindex="0" aria-describedby="{{ data.theme.id }}-action {{ data.theme.id }}-name">
+			<# if ( data.theme.screenshot[0] ) { #>
+				<div class="theme-screenshot">
+					<img src="{{ data.theme.screenshot[0] }}" alt="" />
+				</div>
+			<# } else { #>
+				<div class="theme-screenshot blank"></div>
+			<# } #>
+			<span class="more-details" id="{{ data.theme.id }}-action"><?php _e( 'Theme Details' ); ?></span>
+			<div class="theme-author"><?php printf( __( 'By %s' ), '{{ data.theme.author }}' ); ?></div>
+
+			<# if ( data.theme.active ) { #>
+				<h3 class="theme-name" id="{{ data.theme.id }}-name"><span><?php _ex( 'Previewing:', 'theme' ); ?></span> {{ data.theme.name }}</h3>
+			<# } else { #>
+				<h3 class="theme-name" id="{{ data.theme.id }}-name">{{ data.theme.name }}</h3>
+			<# } #>
+
+			<# if ( ! data.theme.active ) { #>
+				<div class="theme-actions">
+					<a class="button" href="<?php echo add_query_arg( 'theme', '{{ data.theme.id }}', remove_query_arg( 'theme' ) ); ?>" target="_top"><?php _e( 'Live Preview' ); ?></a>
+				</div>
+			<# } #>
+		</div>
+	<?php
+	}
+}
+
+/**
+ * Customize New Theme Control Class
+ *
+ * @package WordPress
+ * @subpackage Customize
+ * @since 4.2.0
+ */
+class WP_Customize_New_Theme_Control extends WP_Customize_Control {
+
+	/**
+	 * Render the new control.
+	 *
+	 * @since 4.2.0
+	 */
+	public function render() {
+		if ( is_multisite() || ! current_user_can( 'install_themes') ) {
+			return;
+		}
+		?>
+		<div class="theme add-new-theme">
+			<a href="<?php echo admin_url( 'theme-install.php' ); ?>" target="_top">
+				<div class="theme-screenshot">
+					<span></span>
+				</div>
+				<h3 class="theme-name"><?php _e( 'Add New Theme' ); ?></h3>
+			</a>
+		</div>
+		<?php
+	}
+}
+
+/**
  * Widget Area Customize Control Class
  *
  * @since 3.9.0
Index: src/wp-includes/class-wp-customize-manager.php
===================================================================
--- src/wp-includes/class-wp-customize-manager.php	(revision 31433)
+++ src/wp-includes/class-wp-customize-manager.php	(working copy)
@@ -1110,7 +1110,39 @@
 		$this->register_control_type( 'WP_Customize_Upload_Control' );
 		$this->register_control_type( 'WP_Customize_Image_Control' );
 		$this->register_control_type( 'WP_Customize_Background_Image_Control' );
+		$this->register_control_type( 'WP_Customize_Theme_Control' );
 
+		/* Themes */
+
+		$this->add_section( new WP_Customize_Themes_Section( $this, 'themes', array(
+			'title' => sprintf( __( 'Theme: %s' ), $this->theme()->display('Name') ),
+			'capability' => 'switch_themes',
+			'priority' => 0,
+		) ) );
+
+		// Themes Setting (unused - the theme is considerably more fundamental to the Customizer experience).
+		$this->add_setting( new WP_Customize_Filter_Setting( $this, 'active_theme', array(
+			'capability' => 'switch_themes',
+		) ) );
+
+		require_once( ABSPATH . 'wp-admin/includes/theme.php' );
+
+		// Theme Controls.
+		$themes = wp_prepare_themes_for_js();
+		foreach ( $themes as $theme ) {
+			$theme_id = 'theme_' . $theme['id'];
+			$this->add_control( new WP_Customize_Theme_Control( $this, $theme_id, array(
+				'theme' => $theme,
+				'section' => 'themes',
+				'settings' => 'active_theme',
+			) ) );
+		}
+
+		$this->add_control( new WP_Customize_New_Theme_Control( $this, 'add_theme', array(
+			'section' => 'themes',
+			'settings' => 'active_theme',
+		) ) );
+
 		/* Site Title & Tagline */
 
 		$this->add_section( 'title_tagline', array(
Index: src/wp-includes/class-wp-customize-section.php
===================================================================
--- src/wp-includes/class-wp-customize-section.php	(revision 31433)
+++ src/wp-includes/class-wp-customize-section.php	(working copy)
@@ -312,6 +312,57 @@
 }
 
 /**
+ * Customize Themes Section Class.
+ *
+ * A UI container for theme controls, which behaves like a backwards Panel.
+ *
+ * @package WordPress
+ * @subpackage Customize
+ * @since 4.2.0
+ */
+class WP_Customize_Themes_Section extends WP_Customize_Section {
+
+	public $type = 'themes';
+
+	/**
+	 * Render the themes section, which behaves like a panel.
+	 *
+	 * @since 4.2.0
+	 */
+	protected function render() {
+		$classes = 'accordion-section control-section control-section-' . $this->type;
+		?>
+		<li id="accordion-section-<?php echo esc_attr( $this->id ); ?>" class="<?php echo esc_attr( $classes ); ?>">
+			<h3 class="accordion-section-title" tabindex="0">
+				<?php echo esc_html( $this->title ); ?>
+				<span class="screen-reader-text"><?php _e( 'Press return or enter to expand' ); ?></span>
+			</h3>
+			<span class="control-panel-back themes-panel-back" tabindex="-1"><span class="screen-reader-text"><?php _e( 'Back' ); ?></span></span>
+			<div class="customize-themes-panel control-panel-content themes-php">
+				<h2><?php esc_html_e( 'Themes' ); ?>
+					<span class="title-count theme-count"><?php echo count( $this->controls ) - 1; ?></span>
+				<?php if ( ! is_multisite() && current_user_can( 'install_themes' ) ) : ?>
+					<a href="<?php echo admin_url( 'theme-install.php' ); ?>" target="_top" class="add-new-h2"><?php echo esc_html_x( 'Add New', 'Add new theme' ); ?></a>
+				<?php endif; ?>
+				</h2>
+				<div class="theme-overlay" tabindex="0" role="dialog" aria-label="<?php esc_attr_e( 'Theme details' ); ?>"></div>
+				<div id="customize-container"></div>
+				<?php if ( 6 < count( $this->controls ) ) : ?>
+					<p><label for="themes-filter">
+						<span class="screen-reader-text"><?php _e( 'Search installed themes...' ); ?></span>
+						<input type="search" id="themes-filter" placeholder="<?php esc_attr_e( 'Search installed themes...' ); ?>" />
+					</label></p>
+				<?php endif; ?>
+				<div class="theme-browser rendered">
+					<ul class="themes accordion-section-content">
+					</ul>
+				</div>
+			</div>
+		</li>
+<?php }
+}
+
+/**
  * Customizer section representing widget area (sidebar).
  *
  * @package WordPress
