diff --git a/src/wp-admin/js/customize-controls.js b/src/wp-admin/js/customize-controls.js index e35ec4fdd8..4f04de4c0f 100644 --- a/src/wp-admin/js/customize-controls.js +++ b/src/wp-admin/js/customize-controls.js @@ -2358,11 +2358,23 @@ messenger.targetWindow( iframe[0].contentWindow ); - messenger.bind( 'login', function() { - iframe.remove(); - messenger.destroy(); - delete previewer._login; - deferred.resolve(); + messenger.bind( 'login', function () { + var refreshNonces = previewer.refreshNonces(); + + refreshNonces.always( function() { + iframe.remove(); + messenger.destroy(); + delete previewer._login; + }); + + refreshNonces.done( function() { + deferred.resolve(); + }); + + refreshNonces.fail( function() { + previewer.cheatin(); + deferred.reject(); + }); }); return this._login; @@ -2370,6 +2382,28 @@ cheatin: function() { $( document.body ).empty().addClass('cheatin').append( '

' + api.l10n.cheatin + '

' ); + }, + + refreshNonces: function() { + var request, deferred = $.Deferred(); + + deferred.promise(); + + request = wp.ajax.post( 'customize_refresh_nonces', { + wp_customize: 'on', + theme: api.settings.theme.stylesheet + }); + + request.done( function( response ) { + api.trigger( 'nonce-refresh', response ); + deferred.resolve(); + }); + + request.fail( function() { + deferred.reject(); + }); + + return deferred; } }); @@ -2538,6 +2572,12 @@ $.extend( this.nonce, nonce ); }); + // Refresh the nonces if login sends updated nonces over. + api.bind( 'nonce-refresh', function( nonce ) { + $.extend( api.settings.nonce, nonce ); + $.extend( api.previewer.nonce, nonce ); + }); + // Create Settings $.each( api.settings.settings, function( id, data ) { api.create( id, id, data.value, { diff --git a/src/wp-admin/js/customize-widgets.js b/src/wp-admin/js/customize-widgets.js index 8134a984d3..20c695b621 100644 --- a/src/wp-admin/js/customize-widgets.js +++ b/src/wp-admin/js/customize-widgets.js @@ -1898,6 +1898,11 @@ sidebar_widgets: api.Widgets.SidebarControl }); + // Refresh the nonce if login sends updated nonces over. + api.bind( 'nonce-refresh', function( nonces ) { + api.Widgets.data.nonce = nonces['update-widget']; + }); + /** * Init Customizer for widgets. */ diff --git a/src/wp-includes/class-wp-customize-manager.php b/src/wp-includes/class-wp-customize-manager.php index d24c283a4b..9fadd741c2 100644 --- a/src/wp-includes/class-wp-customize-manager.php +++ b/src/wp-includes/class-wp-customize-manager.php @@ -91,8 +91,8 @@ final class WP_Customize_Manager { add_filter( 'wp_die_handler', array( $this, 'wp_die_handler' ) ); - add_action( 'setup_theme', array( $this, 'setup_theme' ) ); - add_action( 'wp_loaded', array( $this, 'wp_loaded' ) ); + add_action( 'setup_theme', array( $this, 'setup_theme' ) ); + add_action( 'wp_loaded', array( $this, 'wp_loaded' ) ); // Run wp_redirect_status late to make sure we override the status last. add_action( 'wp_redirect_status', array( $this, 'wp_redirect_status' ), 1000 ); @@ -105,7 +105,8 @@ final class WP_Customize_Manager { remove_action( 'admin_init', '_maybe_update_plugins' ); remove_action( 'admin_init', '_maybe_update_themes' ); - add_action( 'wp_ajax_customize_save', array( $this, 'save' ) ); + add_action( 'wp_ajax_customize_save', array( $this, 'save' ) ); + add_action( 'wp_ajax_customize_refresh_nonces', array( $this, 'refresh_nonces' ) ); add_action( 'customize_register', array( $this, 'register_controls' ) ); add_action( 'customize_register', array( $this, 'register_dynamic_settings' ), 11 ); // allow code to create settings first @@ -783,6 +784,34 @@ final class WP_Customize_Manager { wp_send_json_success( $response ); } + /** + * Refresh nonces for the current preview. + * + * @since 4.2.0 + */ + public function refresh_nonces() { + if ( ! $this->is_preview() ) { + wp_send_json_error( 'not_preview' ); + } + + $nonces = array( + 'save' => wp_create_nonce( 'save-customize_' . $this->get_stylesheet() ), + 'preview' => wp_create_nonce( 'preview-customize_' . $this->get_stylesheet() ), + ); + + /** + * Filter nonces for a customize_refresh_nonces AJAX request. + * + * @since 4.2.0 + * + * @param array $nonces Array of refreshed nonces for save and + * preview actions. + * @param WP_Customize_Manager $this WP_Customize_Manager instance. + */ + $nonces = apply_filters( 'customize_refresh_nonces', $nonces, $this ); + wp_send_json_success( $nonces ); + } + /** * Add a customize setting. * diff --git a/src/wp-includes/class-wp-customize-widgets.php b/src/wp-includes/class-wp-customize-widgets.php index 966c853f9c..fe54d4cfd2 100644 --- a/src/wp-includes/class-wp-customize-widgets.php +++ b/src/wp-includes/class-wp-customize-widgets.php @@ -95,6 +95,7 @@ final class WP_Customize_Widgets { add_action( 'customize_controls_print_footer_scripts', array( $this, 'print_footer_scripts' ) ); add_action( 'customize_controls_print_footer_scripts', array( $this, 'output_widget_control_templates' ) ); add_action( 'customize_preview_init', array( $this, 'customize_preview_init' ) ); + add_filter( 'customize_refresh_nonces', array( $this, 'refresh_nonces' ) ); add_action( 'dynamic_sidebar', array( $this, 'tally_rendered_widgets' ) ); add_filter( 'is_active_sidebar', array( $this, 'tally_sidebars_via_is_active_sidebar_calls' ), 10, 2 ); @@ -888,6 +889,20 @@ final class WP_Customize_Widgets { add_action( 'wp_footer', array( $this, 'export_preview_data' ), 20 ); } + /** + * Refresh nonce for widget updates. + * + * @since 4.2.0 + * @access public + * + * @param array $nonces Array of nonces. + * @return array $nonces Array of nonces. + */ + public function refresh_nonces( $nonces ) { + $nonces['update-widget'] = wp_create_nonce( 'update-widget' ); + return $nonces; + } + /** * When previewing, make sure the proper previewing widgets are used. *