Ticket #28536: 28536.4.diff
File 28536.4.diff, 11.4 KB (added by , 10 years ago) |
---|
-
src/wp-admin/customize.php
diff --git src/wp-admin/customize.php src/wp-admin/customize.php index 3cfa0c7..2a3fb57 100644
if ( ! current_user_can( 'customize' ) ) { 16 16 wp_die( __( 'Cheatin’ uh?' ) ); 17 17 } 18 18 19 global $wp_scripts, $wp_customize; 20 19 21 wp_reset_vars( array( 'url', 'return' ) ); 20 22 $url = wp_unslash( $url ); 21 23 $url = wp_validate_redirect( $url, home_url( '/' ) ); 24 22 25 if ( $return ) { 23 26 $return = wp_unslash( $return ); 24 27 $return = wp_validate_redirect( $return ); 25 28 } 26 29 if ( ! $return ) { 27 if ( $url ) { 30 if ( ! $wp_customize->is_theme_active() ) { 31 $return = admin_url( 'themes.php' ); 32 } elseif ( $url ) { 28 33 $return = $url; 29 34 } elseif ( current_user_can( 'edit_theme_options' ) || current_user_can( 'switch_themes' ) ) { 30 35 $return = admin_url( 'themes.php' ); … … if ( ! $return ) { 33 38 } 34 39 } 35 40 36 global $wp_scripts, $wp_customize;37 38 41 $registered = $wp_scripts->registered; 39 42 $wp_scripts = new WP_Scripts; 40 43 $wp_scripts->registered = $registered; -
src/wp-admin/js/customize-controls.js
diff --git src/wp-admin/js/customize-controls.js src/wp-admin/js/customize-controls.js index 85b171d..af082c5 100644
811 811 } 812 812 } 813 813 814 clearTimeout( timeout ); 815 timeout = setTimeout( callback, self.refreshBuffer ); 814 try { 815 clearTimeout( timeout ); 816 timeout = setTimeout( callback, self.refreshBuffer ); 817 } catch ( e ) { 818 // Handle Uncaught InvalidAccessError: Failed to execute 'setTimeout' on 'Window': No script context is available in which to execute the script. 819 return callback(); 820 } 816 821 }; 817 822 })( this ); 818 823 … … 877 882 878 883 // Update the URL when the iframe sends a URL message. 879 884 this.bind( 'url', this.previewUrl ); 885 886 this.addHistory(); 887 }, 888 889 /** 890 * Given a URL query string, return the query vars contained within it 891 * 892 * @param {String} queryString 893 * @returns {Object} 894 */ 895 parseQueryVars: function ( queryString ) { 896 var queryVars = {}; 897 if ( queryString ) { 898 $.each( queryString.split( '&' ), function () { 899 var key, value, pair; 900 pair = this.split( '=', 2 ); 901 key = decodeURIComponent( pair[0] ); 902 value = pair[1] ? decodeURIComponent( pair[1] ) : null; 903 queryVars[ key ] = value; 904 } ); 905 } 906 return queryVars; 907 }, 908 909 /** 910 * Add support for history for navigation in Customize preview 911 */ 912 addHistory: function () { 913 var self, backLink, pushStatePreviewUrl, popState; 914 if ( ! history.pushState ) { 915 return; 916 } 917 self = this; 918 backLink = $( '.back.button:first' ); 919 920 // Push state 921 pushStatePreviewUrl = function ( url ) { 922 var state, parentLocation, queryVars; 923 state = { customizePreviewUrl: url }; 924 parentLocation = location.pathname; 925 queryVars = self.parseQueryVars( location.search.substr( 1 ) ); 926 queryVars.url = url; 927 parentLocation += '?' + $.param( queryVars ); 928 parentLocation += location.hash; 929 930 // parent frame is for the sake of customizer loaded into iframe for Live Preview 931 if ( api.parent.targetWindow() ) { 932 api.parent.send( 'pushstate', [ state, '', parentLocation ] ); 933 } else { 934 window.history.pushState( state, '', parentLocation ); 935 } 936 937 if ( api.settings.theme.active ) { 938 backLink.prop( 'href', url ); 939 } 940 }; 941 this.previewUrl.bind( pushStatePreviewUrl ); 942 943 // Pop state 944 popState = function ( state, windowLocation ) { 945 var url, queryVars; 946 947 queryVars = self.parseQueryVars( windowLocation.search.substr( 1 ) ); 948 949 // Handle hitting back to themes page after having reloaded on a page in the Customizer 950 if ( ! state && /themes\.php$/.test( windowLocation.pathname ) ) { 951 location.replace( windowLocation.href ); 952 return; 953 } 954 955 if ( state && state.customizePreviewUrl ) { 956 url = state.customizePreviewUrl; 957 } else if ( queryVars.url ) { 958 /* 959 * When popped to initial state, then state is null and so 960 * we don't have customizePreviewUrl, so we can grab it from 961 * the URL query parameter. Note that the previewUrl value 962 * has a validator in place which will prevent illegal 963 * or malicious URLs from being injected into the preview. 964 */ 965 url = queryVars.url; 966 } else { 967 // Use the homepage as the preview URL as default 968 url = api.settings.url.home; 969 } 970 self.previewUrl.unbind( pushStatePreviewUrl ); 971 self.previewUrl( url ); 972 self.previewUrl.bind( pushStatePreviewUrl ); 973 974 if ( api.settings.theme.active ) { 975 backLink.prop( 'href', url ); 976 } 977 }; 978 979 if ( api.parent.targetWindow() ) { 980 api.parent.bind( 'popstate', function ( args ) { 981 popState.apply( null, args ); 982 } ); 983 } else { 984 $( window ).on( 'popstate', function ( e ) { 985 popState( e.originalEvent.state, window.location ); 986 } ); 987 } 880 988 }, 881 989 882 990 query: function() {}, … … 992 1100 if ( ! $.support.postMessage || ( ! $.support.cors && api.settings.isCrossDomain ) ) 993 1101 return window.location = api.settings.url.fallback; 994 1102 995 var parent,topFocus,1103 var topFocus, 996 1104 body = $( document.body ), 997 1105 overlay = body.children( '.wp-full-overlay' ), 998 1106 title = $( '#customize-info .theme-name.site-title' ), … … 1009 1117 } 1010 1118 }); 1011 1119 1120 // Create a potential postMessage connection with the parent frame. 1121 api.parent = new api.Messenger( { 1122 url: api.settings.url.parent, 1123 channel: 'loader' 1124 } ); 1125 1012 1126 // Initialize Previewer 1013 1127 api.previewer = new api.Previewer({ 1014 1128 container: '#customize-preview', … … 1200 1314 } ); 1201 1315 } 1202 1316 1203 // Create a potential postMessage connection with the parent frame.1204 parent = new api.Messenger({1205 url: api.settings.url.parent,1206 channel: 'loader'1207 });1208 1209 1317 // If we receive a 'back' event, we're inside an iframe. 1210 1318 // Send any clicks to the 'Return' link to the parent page. 1211 parent.bind( 'back', function() {1319 api.parent.bind( 'back', function() { 1212 1320 closeBtn.on( 'click.customize-controls-close', function( event ) { 1213 1321 event.preventDefault(); 1214 parent.send( 'close' );1322 api.parent.send( 'close' ); 1215 1323 }); 1216 1324 }); 1217 1325 … … 1225 1333 // Pass events through to the parent. 1226 1334 $.each( [ 'saved', 'change' ], function ( i, event ) { 1227 1335 api.bind( event, function() { 1228 parent.send( event);1336 api.parent.send( 'saved' ); 1229 1337 }); 1230 1338 } ); 1231 1339 1232 1340 // When activated, let the loader handle redirecting the page. 1233 1341 // If no loader exists, redirect the page ourselves (if a url exists). 1234 1342 api.bind( 'activated', function() { 1235 if ( parent.targetWindow() )1236 parent.send( 'activated', api.settings.url.activated );1237 else if ( api.settings.url.activated )1343 if ( api.parent.targetWindow() ) { 1344 api.parent.send( 'activated', api.settings.url.activated ); 1345 } else if ( api.settings.url.activated ) { 1238 1346 window.location = api.settings.url.activated; 1347 } 1239 1348 }); 1240 1349 1241 1350 // Initialize the connection with the parent frame. 1242 parent.send( 'ready' );1351 api.parent.send( 'ready' ); 1243 1352 1244 1353 // Control visibility for default controls 1245 1354 $.each({ -
src/wp-includes/js/customize-base.js
diff --git src/wp-includes/js/customize-base.js src/wp-includes/js/customize-base.js index 6c41b40..a4ddc11 100644
window.wp = window.wp || {}; 524 524 * @param {object} options Extend any instance parameter or method with this object. 525 525 */ 526 526 initialize: function( params, options ) { 527 // Target the parent frame by default, but only if a parent frame exists. 528 var defaultTarget = window.parent == window ? null : window.parent; 527 var defaultTarget; 528 try { 529 // Target the parent frame by default, but only if a parent frame exists. 530 defaultTarget = window.parent === window ? null : window.parent; 531 } catch ( e ) { 532 // Handle case where window goes away in race condition. Uncaught TypeError: Cannot read property 'parent' of null 533 defaultTarget = null; 534 } 529 535 530 536 $.extend( this, options || {} ); 531 537 -
src/wp-includes/js/customize-loader.js
diff --git src/wp-includes/js/customize-loader.js src/wp-includes/js/customize-loader.js index 2ee0c0f..14d6661 100644
window.wp = window.wp || {}; 66 66 var state = e.originalEvent.state; 67 67 if ( state && state.customize ) { 68 68 Loader.open( state.customize ); 69 } else if ( Loader.active ) {69 } else if ( Loader.active && ( ! state || ! state.customizePreviewUrl ) ) { 70 70 Loader.close(); 71 71 } 72 72 }, … … window.wp = window.wp || {}; 75 75 var hash = window.location.toString().split('#')[1]; 76 76 77 77 if ( hash && 0 === hash.indexOf( 'wp_customize=on' ) ) { 78 Loader.open( Loader.settings.url + '?' + hash );78 Loader.open( Loader.settings.url.customize + '?' + hash ); 79 79 } 80 80 81 81 if ( ! hash && ! $.support.history ){ … … window.wp = window.wp || {}; 95 95 * @param string src URL to load in the Customizer. 96 96 */ 97 97 open: function( src ) { 98 99 98 if ( this.active ) { 100 99 return; 101 100 } … … window.wp = window.wp || {}; 124 123 // Wait for the connection from the iframe before sending any postMessage events. 125 124 this.messenger.bind( 'ready', function() { 126 125 Loader.messenger.send( 'back' ); 127 } );126 } ); 128 127 129 128 this.messenger.bind( 'close', function() { 129 var goBackToThemesPage; 130 130 if ( $.support.history ) { 131 goBackToThemesPage = function ( e ) { 132 var state; 133 state = e.originalEvent.state; 134 if ( state && ( state.customize || state.customizePreviewUrl ) ) { 135 history.back(); 136 } else { 137 $( window ).off( 'popstate', goBackToThemesPage ); 138 } 139 }; 140 $( window ).on( 'popstate', goBackToThemesPage ); 131 141 history.back(); 132 142 } else if ( $.support.hashchange ) { 133 143 window.location.hash = ''; … … window.wp = window.wp || {}; 160 170 pushState: function ( src ) { 161 171 var hash; 162 172 163 // Ensure we don't call pushState if the user hit the forward button. 164 if ( $.support.history && window.location.href !== src ) { 165 history.pushState( { customize: src }, '', src ); 166 } else if ( ! $.support.history && $.support.hashchange && hash ) { 173 if ( $.support.history ) { 174 // Ensure we don't call pushState if the user hit the forward button. 175 if ( window.location.href !== src ) { 176 history.pushState( { customize: src }, '', src ); 177 } 178 179 // Allow customizer to control history of parent 180 this.messenger.bind( 'pushstate', function( args ) { 181 history.pushState.apply( history, args ); 182 } ); 183 184 // Forward popstate events to customizer 185 $( window ).on( 'popstate', function ( e ) { 186 Loader.messenger.send( 'popstate', [ e.originalEvent.state, window.location ] ); 187 } ); 188 189 } else if ( $.support.hashchange && hash ) { 167 190 hash = src.split( '?' )[1]; 168 191 window.location.hash = 'wp_customize=on&' + hash; 169 192 } -
src/wp-includes/theme.php
diff --git src/wp-includes/theme.php src/wp-includes/theme.php index 85119ed..1c9b3c0 100644
function _wp_customize_loader_settings() { 1927 1927 ); 1928 1928 1929 1929 $settings = array( 1930 'url' => esc_url( admin_url( 'customize.php' ) ), 1930 'url' => array( 1931 'customize' => esc_url_raw( admin_url( 'customize.php' ) ), 1932 'home' => esc_url_raw( home_url( '/' ) ), 1933 ), 1931 1934 'isCrossDomain' => $cross_domain, 1932 1935 'browser' => $browser, 1933 1936 'l10n' => array(