From 03262a191f6d8b94ad55174c61870d2d0296d3ed Mon Sep 17 00:00:00 2001 From: desrosj Date: Mon, 17 Dec 2018 19:28:51 +0000 Subject: [PATCH] Block Editor: Refresh nonces used by `wp.apiFetch`. Adds heartbeat nonces refreshing support to `wp.apiFetch` requests. Props pento, adamsilverstein, dd32, desrosj, youknowriad. Merges [43939] into trunk. Fixes #45113. Built from https://develop.svn.wordpress.org/trunk@44275 git-svn-id: http://core.svn.wordpress.org/trunk@44105 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-admin/includes/admin-filters.php | 4 +++- wp-admin/includes/misc.php | 22 ++++++++++++++++++++-- wp-includes/js/heartbeat.js | 19 +++++++++++++++++++ wp-includes/js/heartbeat.min.js | 2 +- wp-includes/script-loader.php | 2 +- wp-includes/version.php | 2 +- 6 files changed, 45 insertions(+), 6 deletions(-) diff --git a/wp-admin/includes/admin-filters.php b/wp-admin/includes/admin-filters.php index 0816b2420b..16a51b2c53 100644 --- a/wp-admin/includes/admin-filters.php +++ b/wp-admin/includes/admin-filters.php @@ -68,9 +68,11 @@ add_action( 'update_option_new_admin_email', 'update_option_new_admin_email', 10 add_filter( 'heartbeat_received', 'wp_check_locked_posts', 10, 3 ); add_filter( 'heartbeat_received', 'wp_refresh_post_lock', 10, 3 ); -add_filter( 'wp_refresh_nonces', 'wp_refresh_post_nonces', 10, 3 ); add_filter( 'heartbeat_received', 'heartbeat_autosave', 500, 2 ); +add_filter( 'wp_refresh_nonces', 'wp_refresh_post_nonces', 10, 3 ); +add_filter( 'wp_refresh_nonces', 'wp_refresh_heartbeat_nonces' ); + add_filter( 'heartbeat_settings', 'wp_heartbeat_set_suspension' ); // Nav Menu hooks. diff --git a/wp-admin/includes/misc.php b/wp-admin/includes/misc.php index 6591cc5e1f..22434e4816 100644 --- a/wp-admin/includes/misc.php +++ b/wp-admin/includes/misc.php @@ -1054,20 +1054,38 @@ function wp_refresh_post_nonces( $response, $data, $screen_id ) { } $response['wp-refresh-post-nonces'] = array( - 'replace' => array( + 'replace' => array( 'getpermalinknonce' => wp_create_nonce( 'getpermalink' ), 'samplepermalinknonce' => wp_create_nonce( 'samplepermalink' ), 'closedpostboxesnonce' => wp_create_nonce( 'closedpostboxes' ), '_ajax_linking_nonce' => wp_create_nonce( 'internal-linking' ), '_wpnonce' => wp_create_nonce( 'update-post_' . $post_id ), ), - 'heartbeatNonce' => wp_create_nonce( 'heartbeat-nonce' ), ); } return $response; } +/** + * Add the latest Heartbeat and REST-API nonce to the Heartbeat response. + * + * @since 5.0.0 + * + * @param array $response The Heartbeat response. + * @return array The Heartbeat response. + */ +function wp_refresh_heartbeat_nonces( $response ) { + // Refresh the Rest API nonce. + $response['rest_nonce'] = wp_create_nonce( 'wp_rest' ); + // TEMPORARY: Compat with api-fetch library + $response['rest-nonce'] = $response['rest_nonce']; + + // Refresh the Heartbeat nonce. + $response['heartbeat_nonce'] = wp_create_nonce( 'heartbeat-nonce' ); + return $response; +} + /** * Disable suspension of Heartbeat on the Add/Edit Post screens. * diff --git a/wp-includes/js/heartbeat.js b/wp-includes/js/heartbeat.js index 03baeb6e00..3e51a72167 100644 --- a/wp-includes/js/heartbeat.js +++ b/wp-includes/js/heartbeat.js @@ -351,6 +351,7 @@ if ( trigger && ! hasConnectionError() ) { settings.connectionError = true; $document.trigger( 'heartbeat-connection-lost', [error, status] ); + wp.hooks.doAction( 'heartbeat.connection-lost', error, status ); } } } @@ -372,6 +373,7 @@ settings.errorcount = 0; settings.connectionError = false; $document.trigger( 'heartbeat-connection-restored' ); + wp.hooks.doAction( 'heartbeat.connection-restored' ); } } @@ -400,6 +402,7 @@ settings.queue = {}; $document.trigger( 'heartbeat-send', [ heartbeatData ] ); + wp.hooks.doAction( 'heartbeat.send', heartbeatData ); ajaxData = { data: heartbeatData, @@ -436,6 +439,7 @@ if ( response.nonces_expired ) { $document.trigger( 'heartbeat-nonces-expired' ); + wp.hooks.doAction( 'heartbeat.nonces-expired' ); } // Change the interval from PHP @@ -444,7 +448,21 @@ delete response.heartbeat_interval; } + // Update the heartbeat nonce if set. + if ( response.heartbeat_nonce && typeof window.heartbeatSettings === 'object' ) { + window.heartbeatSettings.nonce = response.heartbeat_nonce; + delete response.heartbeat_nonce; + } + + // Update the Rest API nonce if set and wp-api loaded. + if ( response.rest_nonce && typeof window.wpApiSettings === 'object' ) { + window.wpApiSettings.nonce = response.rest_nonce; + // This nonce is required for api-fetch through heartbeat.tick. + // delete response.rest_nonce; + } + $document.trigger( 'heartbeat-tick', [response, textStatus, jqXHR] ); + wp.hooks.doAction( 'heartbeat.tick', response, textStatus, jqXHR ); // Do this last. Can trigger the next XHR if connection time > 5 sec. and newInterval == 'fast'. if ( newInterval ) { @@ -453,6 +471,7 @@ }).fail( function( jqXHR, textStatus, error ) { setErrorState( textStatus || 'unknown', jqXHR.status ); $document.trigger( 'heartbeat-error', [jqXHR, textStatus, error] ); + wp.hooks.doAction( 'heartbeat.error', jqXHR, textStatus, error ); }); } diff --git a/wp-includes/js/heartbeat.min.js b/wp-includes/js/heartbeat.min.js index 945ec0c270..04425f86a6 100644 --- a/wp-includes/js/heartbeat.min.js +++ b/wp-includes/js/heartbeat.min.js @@ -1 +1 @@ -!function(a,b,c){var d=function(){function d(){var c,d,f,h;"string"==typeof b.pagenow&&(z.screenId=b.pagenow),"string"==typeof b.ajaxurl&&(z.url=b.ajaxurl),"object"==typeof b.heartbeatSettings&&(c=b.heartbeatSettings,!z.url&&c.ajaxurl&&(z.url=c.ajaxurl),c.interval&&(z.mainInterval=c.interval,z.mainInterval<15?z.mainInterval=15:z.mainInterval>120&&(z.mainInterval=120)),c.minimalInterval&&(c.minimalInterval=parseInt(c.minimalInterval,10),z.minimalInterval=c.minimalInterval>0&&c.minimalInterval<=600?1e3*c.minimalInterval:0),z.minimalInterval&&z.mainInterval2&&z.hasConnected&&(c=!0)}c&&!q()&&(z.connectionError=!0,y.trigger("heartbeat-connection-lost",[a,b]))}}function i(){z.hasConnected=!0,q()&&(z.errorcount=0,z.connectionError=!1,y.trigger("heartbeat-connection-restored"))}function j(){var c,d;z.connecting||z.suspend||(z.lastTick=e(),d=a.extend({},z.queue),z.queue={},y.trigger("heartbeat-send",[d]),c={data:d,interval:z.tempInterval?z.tempInterval/1e3:z.mainInterval/1e3,_nonce:"object"==typeof b.heartbeatSettings?b.heartbeatSettings.nonce:"",action:"heartbeat",screen_id:z.screenId,has_focus:z.hasFocus},"customize"===z.screenId&&(c.wp_customize="on"),z.connecting=!0,z.xhr=a.ajax({url:z.url,type:"post",timeout:3e4,data:c,dataType:"json"}).always(function(){z.connecting=!1,k()}).done(function(a,b,c){var d;return a?(i(),a.nonces_expired&&y.trigger("heartbeat-nonces-expired"),a.heartbeat_interval&&(d=a.heartbeat_interval,delete a.heartbeat_interval),y.trigger("heartbeat-tick",[a,b,c]),void(d&&t(d))):void h("empty")}).fail(function(a,b,c){h(b||"unknown",a.status),y.trigger("heartbeat-error",[a,b,c])}))}function k(){var a=e()-z.lastTick,c=z.mainInterval;z.suspend||(z.hasFocus?z.countdown>0&&z.tempInterval&&(c=z.tempInterval,z.countdown--,z.countdown<1&&(z.tempInterval=0)):c=12e4,z.minimalInterval&&c3e5&&z.hasFocus&&l(),(z.suspendEnabled&&b>6e5||b>36e5)&&(z.suspend=!0),z.userActivityEvents||(y.on("mouseover.wp-heartbeat-active keyup.wp-heartbeat-active touchend.wp-heartbeat-active",function(){n()}),a("iframe").each(function(b,c){f(c)&&a(c.contentWindow).on("mouseover.wp-heartbeat-active keyup.wp-heartbeat-active touchend.wp-heartbeat-active",function(){n()})}),z.userActivityEvents=!0)}function p(){return z.hasFocus}function q(){return z.connectionError}function r(){z.lastTick=0,k()}function s(){z.suspendEnabled=!1}function t(a,b){var c,d=z.tempInterval?z.tempInterval:z.mainInterval;if(a){switch(a){case"fast":case 5:c=5e3;break;case 15:c=15e3;break;case 30:c=3e4;break;case 60:c=6e4;break;case 120:c=12e4;break;case"long-polling":return z.mainInterval=0,0;default:c=z.originalInterval}z.minimalInterval&&c30?30:b,z.countdown=b,z.tempInterval=c):(z.countdown=0,z.tempInterval=0,z.mainInterval=c),c!==d&&k()}return z.tempInterval?z.tempInterval/1e3:z.mainInterval/1e3}function u(a,b,c){return!!a&&((!c||!this.isQueued(a))&&(z.queue[a]=b,!0))}function v(a){if(a)return z.queue.hasOwnProperty(a)}function w(a){a&&delete z.queue[a]}function x(a){if(a)return this.isQueued(a)?z.queue[a]:c}var y=a(document),z={suspend:!1,suspendEnabled:!0,screenId:"",url:"",lastTick:0,queue:{},mainInterval:60,tempInterval:0,originalInterval:0,minimalInterval:0,countdown:0,connecting:!1,connectionError:!1,errorcount:0,hasConnected:!1,hasFocus:!0,userActivity:0,userActivityEvents:!1,checkFocusTimer:0,beatTimer:0};return d(),{hasFocus:p,connectNow:r,disableSuspend:s,interval:t,hasConnectionError:q,enqueue:u,dequeue:w,isQueued:v,getQueuedItem:x}};b.wp=b.wp||{},b.wp.heartbeat=new d}(jQuery,window); \ No newline at end of file +!function(a,b,c){var d=function(){function d(){var c,d,f,h;"string"==typeof b.pagenow&&(z.screenId=b.pagenow),"string"==typeof b.ajaxurl&&(z.url=b.ajaxurl),"object"==typeof b.heartbeatSettings&&(c=b.heartbeatSettings,!z.url&&c.ajaxurl&&(z.url=c.ajaxurl),c.interval&&(z.mainInterval=c.interval,z.mainInterval<15?z.mainInterval=15:z.mainInterval>120&&(z.mainInterval=120)),c.minimalInterval&&(c.minimalInterval=parseInt(c.minimalInterval,10),z.minimalInterval=c.minimalInterval>0&&c.minimalInterval<=600?1e3*c.minimalInterval:0),z.minimalInterval&&z.mainInterval2&&z.hasConnected&&(c=!0)}c&&!q()&&(z.connectionError=!0,y.trigger("heartbeat-connection-lost",[a,b]),wp.hooks.doAction("heartbeat.connection-lost",a,b))}}function i(){z.hasConnected=!0,q()&&(z.errorcount=0,z.connectionError=!1,y.trigger("heartbeat-connection-restored"),wp.hooks.doAction("heartbeat.connection-restored"))}function j(){var c,d;z.connecting||z.suspend||(z.lastTick=e(),d=a.extend({},z.queue),z.queue={},y.trigger("heartbeat-send",[d]),wp.hooks.doAction("heartbeat.send",d),c={data:d,interval:z.tempInterval?z.tempInterval/1e3:z.mainInterval/1e3,_nonce:"object"==typeof b.heartbeatSettings?b.heartbeatSettings.nonce:"",action:"heartbeat",screen_id:z.screenId,has_focus:z.hasFocus},"customize"===z.screenId&&(c.wp_customize="on"),z.connecting=!0,z.xhr=a.ajax({url:z.url,type:"post",timeout:3e4,data:c,dataType:"json"}).always(function(){z.connecting=!1,k()}).done(function(a,c,d){var e;return a?(i(),a.nonces_expired&&(y.trigger("heartbeat-nonces-expired"),wp.hooks.doAction("heartbeat.nonces-expired")),a.heartbeat_interval&&(e=a.heartbeat_interval,delete a.heartbeat_interval),a.heartbeat_nonce&&"object"==typeof b.heartbeatSettings&&(b.heartbeatSettings.nonce=a.heartbeat_nonce,delete a.heartbeat_nonce),a.rest_nonce&&"object"==typeof b.wpApiSettings&&(b.wpApiSettings.nonce=a.rest_nonce),y.trigger("heartbeat-tick",[a,c,d]),wp.hooks.doAction("heartbeat.tick",a,c,d),void(e&&t(e))):void h("empty")}).fail(function(a,b,c){h(b||"unknown",a.status),y.trigger("heartbeat-error",[a,b,c]),wp.hooks.doAction("heartbeat.error",a,b,c)}))}function k(){var a=e()-z.lastTick,c=z.mainInterval;z.suspend||(z.hasFocus?z.countdown>0&&z.tempInterval&&(c=z.tempInterval,z.countdown--,z.countdown<1&&(z.tempInterval=0)):c=12e4,z.minimalInterval&&c3e5&&z.hasFocus&&l(),(z.suspendEnabled&&b>6e5||b>36e5)&&(z.suspend=!0),z.userActivityEvents||(y.on("mouseover.wp-heartbeat-active keyup.wp-heartbeat-active touchend.wp-heartbeat-active",function(){n()}),a("iframe").each(function(b,c){f(c)&&a(c.contentWindow).on("mouseover.wp-heartbeat-active keyup.wp-heartbeat-active touchend.wp-heartbeat-active",function(){n()})}),z.userActivityEvents=!0)}function p(){return z.hasFocus}function q(){return z.connectionError}function r(){z.lastTick=0,k()}function s(){z.suspendEnabled=!1}function t(a,b){var c,d=z.tempInterval?z.tempInterval:z.mainInterval;if(a){switch(a){case"fast":case 5:c=5e3;break;case 15:c=15e3;break;case 30:c=3e4;break;case 60:c=6e4;break;case 120:c=12e4;break;case"long-polling":return z.mainInterval=0,0;default:c=z.originalInterval}z.minimalInterval&&c30?30:b,z.countdown=b,z.tempInterval=c):(z.countdown=0,z.tempInterval=0,z.mainInterval=c),c!==d&&k()}return z.tempInterval?z.tempInterval/1e3:z.mainInterval/1e3}function u(a,b,c){return!!a&&((!c||!this.isQueued(a))&&(z.queue[a]=b,!0))}function v(a){if(a)return z.queue.hasOwnProperty(a)}function w(a){a&&delete z.queue[a]}function x(a){if(a)return this.isQueued(a)?z.queue[a]:c}var y=a(document),z={suspend:!1,suspendEnabled:!0,screenId:"",url:"",lastTick:0,queue:{},mainInterval:60,tempInterval:0,originalInterval:0,minimalInterval:0,countdown:0,connecting:!1,connectionError:!1,errorcount:0,hasConnected:!1,hasFocus:!0,userActivity:0,userActivityEvents:!1,checkFocusTimer:0,beatTimer:0};return d(),{hasFocus:p,connectNow:r,disableSuspend:s,interval:t,hasConnectionError:q,enqueue:u,dequeue:w,isQueued:v,getQueuedItem:x}};b.wp=b.wp||{},b.wp.heartbeat=new d}(jQuery,window); \ No newline at end of file diff --git a/wp-includes/script-loader.php b/wp-includes/script-loader.php index 3f9c1c04a4..5ce5d45557 100644 --- a/wp-includes/script-loader.php +++ b/wp-includes/script-loader.php @@ -893,7 +893,7 @@ function wp_default_scripts( &$scripts ) { $scripts->add( 'autosave', "/wp-includes/js/autosave$suffix.js", array( 'heartbeat' ), false, 1 ); - $scripts->add( 'heartbeat', "/wp-includes/js/heartbeat$suffix.js", array( 'jquery' ), false, 1 ); + $scripts->add( 'heartbeat', "/wp-includes/js/heartbeat$suffix.js", array( 'jquery', 'wp-hooks' ), false, 1 ); did_action( 'init' ) && $scripts->localize( 'heartbeat', 'heartbeatSettings', diff --git a/wp-includes/version.php b/wp-includes/version.php index 3c9fd73545..17adb51f56 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -13,7 +13,7 @@ * * @global string $wp_version */ -$wp_version = '5.1-alpha-44274'; +$wp_version = '5.1-alpha-44275'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.