Index: wp-includes/class-wp-customize-manager.php
===================================================================
--- wp-includes/class-wp-customize-manager.php	(revision 21064)
+++ wp-includes/class-wp-customize-manager.php	(working copy)
@@ -72,10 +72,13 @@
 	 *
 	 * @since 3.4.0
 	 */
-	private function wp_die( $ajax_message, $message ) {
+	protected function wp_die( $ajax_message, $message = null ) {
 		if ( $this->doing_ajax() )
 			wp_die( $ajax_message );
 
+		if ( ! $message )
+			$message = __( 'Cheatin&#8217; uh?' );
+
 		wp_die( $message );
 	}
 
@@ -100,29 +103,44 @@
 	public function setup_theme() {
 		if ( is_admin() && ! $this->doing_ajax() )
 		    auth_redirect();
-		elseif ( $this->doing_ajax() && ! is_user_logged_in())
-		    wp_die( 0 );
+		elseif ( $this->doing_ajax() && ! is_user_logged_in() )
+		    $this->wp_die( 0 );
 
+		if ( ! current_user_can( 'edit_theme_options' ) )
+			$this->wp_die( -1 );
+
 		send_origin_headers();
+		show_admin_bar( false );
 
 		$this->original_stylesheet = get_stylesheet();
 
 		$this->theme = wp_get_theme( isset( $_REQUEST['theme'] ) ? $_REQUEST['theme'] : null );
 
-		// You can't preview a theme if it doesn't exist, or if it is not allowed (unless active).
-		if ( ! $this->theme->exists() )
-			$this->wp_die( -1, __( 'Cheatin&#8217; uh?' ) );
+		if ( $this->is_theme_active() ) {
+			// Once the theme is loaded, we'll validate it.
+			add_action( 'after_setup_theme', array( $this, 'after_setup_theme' ) );
+		} else {
+			if ( ! current_user_can( 'switch_themes' ) )
+				$this->wp_die( -1 );
 
-		if ( $this->theme->get_stylesheet() != get_stylesheet() && ( ! $this->theme()->is_allowed() || ! current_user_can( 'switch_themes' ) ) )
-			$this->wp_die( -1, __( 'Cheatin&#8217; uh?' ) );
+			// If the theme isn't active, you can't preview it if it is not allowed or has errors.
+			if ( $this->theme()->errors() )
+				$this->wp_die( -1 );
 
-		if ( ! current_user_can( 'edit_theme_options' ) )
-			$this->wp_die( -1, __( 'Cheatin&#8217; uh?' ) );
+			if ( ! $this->theme()->is_allowed() )
+				$this->wp_die( -1 );
+		}
 
 		$this->start_previewing_theme();
-		show_admin_bar( false );
 	}
 
+	function after_setup_theme() {
+		if ( ! $this->doing_ajax() && ! validate_current_theme() ) {
+			wp_redirect( 'themes.php?broken=true' );
+			exit;
+		}
+	}
+
 	/**
 	 * Start previewing the selected theme.
 	 *
@@ -137,18 +155,20 @@
 
 		$this->previewing = true;
 
-		add_filter( 'template', array( $this, 'get_template' ) );
-		add_filter( 'stylesheet', array( $this, 'get_stylesheet' ) );
-		add_filter( 'pre_option_current_theme', array( $this, 'current_theme' ) );
+		if ( ! $this->is_theme_active() ) {
+			add_filter( 'template', array( $this, 'get_template' ) );
+			add_filter( 'stylesheet', array( $this, 'get_stylesheet' ) );
+			add_filter( 'pre_option_current_theme', array( $this, 'current_theme' ) );
+	
+			// @link: http://core.trac.wordpress.org/ticket/20027
+			add_filter( 'pre_option_stylesheet', array( $this, 'get_stylesheet' ) );
+			add_filter( 'pre_option_template', array( $this, 'get_template' ) );
+	
+			// Handle custom theme roots.
+			add_filter( 'pre_option_stylesheet_root', array( $this, 'get_stylesheet_root' ) );
+			add_filter( 'pre_option_template_root', array( $this, 'get_template_root' ) );
+		}
 
-		// @link: http://core.trac.wordpress.org/ticket/20027
-		add_filter( 'pre_option_stylesheet', array( $this, 'get_stylesheet' ) );
-		add_filter( 'pre_option_template', array( $this, 'get_template' ) );
-
-		// Handle custom theme roots.
-		add_filter( 'pre_option_stylesheet_root', array( $this, 'get_stylesheet_root' ) );
-		add_filter( 'pre_option_template_root', array( $this, 'get_template_root' ) );
-
 		do_action( 'start_previewing_theme', $this );
 	}
 
@@ -165,18 +185,20 @@
 
 		$this->previewing = false;
 
-		remove_filter( 'template', array( $this, 'get_template' ) );
-		remove_filter( 'stylesheet', array( $this, 'get_stylesheet' ) );
-		remove_filter( 'pre_option_current_theme', array( $this, 'current_theme' ) );
+		if ( ! $this->is_theme_active() ) {
+			remove_filter( 'template', array( $this, 'get_template' ) );
+			remove_filter( 'stylesheet', array( $this, 'get_stylesheet' ) );
+			remove_filter( 'pre_option_current_theme', array( $this, 'current_theme' ) );
+	
+			// @link: http://core.trac.wordpress.org/ticket/20027
+			remove_filter( 'pre_option_stylesheet', array( $this, 'get_stylesheet' ) );
+			remove_filter( 'pre_option_template', array( $this, 'get_template' ) );
+	
+			// Handle custom theme roots.
+			remove_filter( 'pre_option_stylesheet_root', array( $this, 'get_stylesheet_root' ) );
+			remove_filter( 'pre_option_template_root', array( $this, 'get_template_root' ) );
+		}
 
-		// @link: http://core.trac.wordpress.org/ticket/20027
-		remove_filter( 'pre_option_stylesheet', array( $this, 'get_stylesheet' ) );
-		remove_filter( 'pre_option_template', array( $this, 'get_template' ) );
-
-		// Handle custom theme roots.
-		remove_filter( 'pre_option_stylesheet_root', array( $this, 'get_stylesheet_root' ) );
-		remove_filter( 'pre_option_template_root', array( $this, 'get_template_root' ) );
-
 		do_action( 'stop_previewing_theme', $this );
 	}
 
@@ -389,7 +411,7 @@
 	 * @return string Template name.
 	 */
 	public function get_template() {
-		return $this->theme->get_template();
+		return $this->theme()->get_template();
 	}
 
 	/**
@@ -400,7 +422,7 @@
 	 * @return string Stylesheet name.
 	 */
 	public function get_stylesheet() {
-		return $this->theme->get_stylesheet();
+		return $this->theme()->get_stylesheet();
 	}
 
 	/**
@@ -433,7 +455,7 @@
 	 * @return string Theme name.
 	 */
 	public function current_theme( $current_theme ) {
-		return $this->theme->display('Name');
+		return $this->theme()->display('Name');
 	}
 
 	/**
@@ -448,7 +470,7 @@
 		check_ajax_referer( 'customize_controls-' . $this->get_stylesheet(), 'nonce' );
 
 		// Do we have to switch themes?
-		if ( $this->get_stylesheet() != $this->original_stylesheet ) {
+		if ( ! $this->is_theme_active() ) {
 			// Temporarily stop previewing the theme to allow switch_themes()
 			// to operate properly.
 			$this->stop_previewing_theme();
@@ -462,23 +484,10 @@
 			$setting->save();
 		}
 
-		add_action( 'admin_notices', array( $this, '_save_feedback' ) );
-
 		die;
 	}
 
 	/**
-	 * Show an admin notice after settings are saved.
-	 *
-	 * @since 3.4.0
-	 */
-	public function _save_feedback() {
-		?>
-		<div class="updated"><p><?php printf( __( 'Settings saved and theme activated. <a href="%s">Visit site</a>.' ), home_url( '/' ) ); ?></p></div>
-		<?php
-	}
-
-	/**
 	 * Add a customize setting.
 	 *
 	 * @since 3.4.0
Index: wp-admin/customize.php
===================================================================
--- wp-admin/customize.php	(revision 21064)
+++ wp-admin/customize.php	(working copy)
@@ -161,7 +161,7 @@
 		'url'      => array(
 			'preview'       => esc_url( $url ? $url : home_url( '/' ) ),
 			'parent'        => esc_url( admin_url() ),
-			'activated'     => esc_url( admin_url( 'themes.php?activated=true' ) ),
+			'activated'     => admin_url( 'themes.php?activated=true&previewed' ),
 			'ajax'          => esc_url( admin_url( 'admin-ajax.php', 'relative' ) ),
 			'allowed'       => array_map( 'esc_url', $allowed_urls ),
 			'isCrossDomain' => $cross_domain,
Index: wp-admin/themes.php
===================================================================
--- wp-admin/themes.php	(revision 21064)
+++ wp-admin/themes.php	(working copy)
@@ -92,18 +92,6 @@
 require_once('./admin-header.php');
 ?>
 
-<?php if ( ! validate_current_theme() ) : ?>
-<div id="message1" class="updated"><p><?php _e('The active theme is broken. Reverting to the default theme.'); ?></p></div>
-<?php elseif ( isset($_GET['activated']) ) :
-		if ( isset($wp_registered_sidebars) && count( (array) $wp_registered_sidebars ) && current_user_can('edit_theme_options') ) { ?>
-<div id="message2" class="updated"><p><?php printf( __('New theme activated. This theme supports widgets, please visit the <a href="%s">widgets settings</a> screen to configure them.'), admin_url( 'widgets.php' ) ); ?></p></div><?php
-		} else { ?>
-<div id="message2" class="updated"><p><?php printf( __( 'New theme activated. <a href="%s">Visit site</a>' ), home_url( '/' ) ); ?></p></div><?php
-		}
-	elseif ( isset($_GET['deleted']) ) : ?>
-<div id="message3" class="updated"><p><?php _e('Theme deleted.') ?></p></div>
-<?php endif; ?>
-
 <div class="wrap"><?php
 screen_icon();
 if ( ! is_multisite() && current_user_can( 'install_themes' ) ) : ?>
@@ -114,6 +102,20 @@
 <?php endif; ?>
 </h2>
 <?php
+if ( ! validate_current_theme() || isset( $_GET['broken'] ) ) : ?>
+<div id="message1" class="updated"><p><?php _e('The active theme is broken. Reverting to the default theme.'); ?></p></div>
+<?php elseif ( isset($_GET['activated']) ) :
+		if ( isset( $_GET['previewed'] ) ) { ?>
+		<div id="message2" class="updated"><p><?php printf( __( 'Settings saved and theme activated. <a href="%s">Visit site</a>.' ), home_url( '/' ) ); ?></p></div>
+		<?php } elseif ( isset($wp_registered_sidebars) && count( (array) $wp_registered_sidebars ) && current_user_can('edit_theme_options') ) { ?>
+<div id="message2" class="updated"><p><?php printf( __('New theme activated. This theme supports widgets, please visit the <a href="%s">widgets settings</a> screen to configure them.'), admin_url( 'widgets.php' ) ); ?></p></div><?php
+		} else { ?>
+<div id="message2" class="updated"><p><?php printf( __( 'New theme activated. <a href="%s">Visit site</a>' ), home_url( '/' ) ); ?></p></div><?php
+		}
+	elseif ( isset($_GET['deleted']) ) : ?>
+<div id="message3" class="updated"><p><?php _e('Theme deleted.') ?></p></div>
+<?php
+endif;
 
 $ct = wp_get_theme();
 $screenshot = $ct->get_screenshot();
