Ticket #28536: 28536.2.diff
File 28536.2.diff, 12.4 KB (added by , 9 years ago) |
---|
-
src/wp-admin/customize.php
diff --git src/wp-admin/customize.php src/wp-admin/customize.php index 1faf371..cdb7351 100644
define( 'IFRAME_REQUEST', true ); 12 12 /** Load WordPress Administration Bootstrap */ 13 13 require_once( dirname( __FILE__ ) . '/admin.php' ); 14 14 15 if ( ! current_user_can( 'edit_theme_options' ) ) 15 if ( ! current_user_can( 'edit_theme_options' ) ) { 16 16 wp_die( __( 'Cheatin’ uh?' ) ); 17 } 18 19 global $wp_scripts, $wp_customize; 17 20 18 21 wp_reset_vars( array( 'url', 'return' ) ); 19 22 $url = urldecode( $url ); 20 23 $url = wp_validate_redirect( $url, home_url( '/' ) ); 21 if ( $return ) 24 25 if ( $return ) { 22 26 $return = wp_validate_redirect( urldecode( $return ) ); 23 if ( ! $return ) 27 } elseif ( ! $wp_customize->is_theme_active() ) { 28 $return = admin_url( 'themes.php' ); 29 } else { 24 30 $return = $url; 25 26 global $wp_scripts, $wp_customize; 31 } 27 32 28 33 $registered = $wp_scripts->registered; 29 34 $wp_scripts = new WP_Scripts; -
src/wp-admin/js/customize-controls.js
diff --git src/wp-admin/js/customize-controls.js src/wp-admin/js/customize-controls.js index 4bfc252..11ef18a 100644
728 728 } 729 729 } 730 730 731 clearTimeout( timeout ); 732 timeout = setTimeout( callback, self.refreshBuffer ); 731 try { 732 clearTimeout( timeout ); 733 timeout = setTimeout( callback, self.refreshBuffer ); 734 } catch ( e ) { 735 // Handle Uncaught InvalidAccessError: Failed to execute 'setTimeout' on 'Window': No script context is available in which to execute the script. 736 return callback(); 737 } 733 738 }; 734 739 })( this ); 735 740 … … 794 799 795 800 // Update the URL when the iframe sends a URL message. 796 801 this.bind( 'url', this.previewUrl ); 802 803 this.addHistory(); 804 }, 805 806 /** 807 * Given a URL query string, return the query vars contained within it 808 * 809 * @param {String} queryString 810 * @returns {Object} 811 */ 812 parseQueryVars: function ( queryString ) { 813 var queryVars = {}; 814 if ( queryString ) { 815 $.each( queryString.split( '&' ), function () { 816 var key, value, pair; 817 pair = this.split( '=', 2 ); 818 key = decodeURIComponent( pair[0] ); 819 value = pair[1] ? decodeURIComponent( pair[1] ) : null; 820 queryVars[ key ] = value; 821 } ); 822 } 823 return queryVars; 824 }, 825 826 /** 827 * Add support for history for navigation in Customize preview 828 */ 829 addHistory: function () { 830 var self, backLink, pushStatePreviewUrl, popState; 831 if ( ! history.pushState ) { 832 return; 833 } 834 self = this; 835 backLink = $( '.back.button:first' ); 836 837 // Push state 838 pushStatePreviewUrl = function ( url ) { 839 var state, parentLocation, queryVars; 840 state = { customizePreviewUrl: url }; 841 parentLocation = location.pathname; 842 queryVars = self.parseQueryVars( location.search.substr( 1 ) ); 843 queryVars.url = url; 844 parentLocation += '?' + $.param( queryVars ); 845 parentLocation += location.hash; 846 847 // parent frame is for the sake of customizer loaded into iframe for Live Preview 848 if ( api.parent.targetWindow() ) { 849 api.parent.send( 'pushstate', [ state, '', parentLocation ] ); 850 } else { 851 window.history.pushState( state, '', parentLocation ); 852 } 853 854 if ( api.settings.theme.active ) { 855 backLink.prop( 'href', url ); 856 } 857 }; 858 this.previewUrl.bind( pushStatePreviewUrl ); 859 860 // Pop state 861 popState = function ( state, windowLocation ) { 862 var url, queryVars; 863 864 queryVars = self.parseQueryVars( windowLocation.search.substr( 1 ) ); 865 866 // Handle hitting back to themes page after having reloaded on a page in the Customizer 867 if ( ! state && /themes\.php$/.test( windowLocation.pathname ) ) { 868 location.replace( windowLocation.href ); 869 return; 870 } 871 872 if ( state && state.customizePreviewUrl ) { 873 url = state.customizePreviewUrl; 874 } else if ( queryVars.url ) { 875 /* 876 * When popped to initial state, then state is null and so 877 * we don't have customizePreviewUrl, so we can grab it from 878 * the URL query parameter. Note that the previewUrl value 879 * has a validator in place which will prevent illegal 880 * or malicious URLs from being injected into the preview. 881 */ 882 url = queryVars.url; 883 } else { 884 // Use the homepage as the preview URL as default 885 url = api.settings.url.home; 886 } 887 self.previewUrl.unbind( pushStatePreviewUrl ); 888 self.previewUrl( url ); 889 self.previewUrl.bind( pushStatePreviewUrl ); 890 891 if ( api.settings.theme.active ) { 892 backLink.prop( 'href', url ); 893 } 894 }; 895 896 if ( api.parent.targetWindow() ) { 897 api.parent.bind( 'popstate', function ( args ) { 898 popState.apply( null, args ); 899 } ); 900 } else { 901 $( window ).on( 'popstate', function ( e ) { 902 popState( e.originalEvent.state, window.location ); 903 } ); 904 } 797 905 }, 798 906 799 907 query: function() {}, … … 913 1021 if ( ! $.support.postMessage || ( ! $.support.cors && api.settings.isCrossDomain ) ) 914 1022 return window.location = api.settings.url.fallback; 915 1023 916 var previewer, parent,topFocus,1024 var previewer, topFocus, 917 1025 body = $( document.body ), 918 1026 overlay = body.children('.wp-full-overlay'); 919 1027 … … 927 1035 } 928 1036 }); 929 1037 1038 // Create a potential postMessage connection with the parent frame. 1039 api.parent = new api.Messenger( { 1040 url: api.settings.url.parent, 1041 channel: 'loader' 1042 } ); 1043 930 1044 // Initialize Previewer 931 1045 previewer = new api.Previewer({ 932 1046 container: '#customize-preview', … … 1113 1227 event.preventDefault(); 1114 1228 }); 1115 1229 1116 // Create a potential postMessage connection with the parent frame.1117 parent = new api.Messenger({1118 url: api.settings.url.parent,1119 channel: 'loader'1120 });1121 1122 1230 // If we receive a 'back' event, we're inside an iframe. 1123 1231 // Send any clicks to the 'Return' link to the parent page. 1124 parent.bind( 'back', function() {1232 api.parent.bind( 'back', function() { 1125 1233 $('.back').on( 'click.back', function( event ) { 1126 1234 event.preventDefault(); 1127 parent.send( 'close' );1235 api.parent.send( 'close' ); 1128 1236 }); 1129 1237 }); 1130 1238 1131 1239 // Pass events through to the parent. 1132 1240 api.bind( 'saved', function() { 1133 parent.send( 'saved' );1241 api.parent.send( 'saved' ); 1134 1242 }); 1135 1243 1136 1244 // When activated, let the loader handle redirecting the page. 1137 1245 // If no loader exists, redirect the page ourselves (if a url exists). 1138 1246 api.bind( 'activated', function() { 1139 if ( parent.targetWindow() )1140 parent.send( 'activated', api.settings.url.activated );1141 else if ( api.settings.url.activated )1247 if ( api.parent.targetWindow() ) { 1248 api.parent.send( 'activated', api.settings.url.activated ); 1249 } else if ( api.settings.url.activated ) { 1142 1250 window.location = api.settings.url.activated; 1251 } 1143 1252 }); 1144 1253 1145 1254 // Initialize the connection with the parent frame. 1146 parent.send( 'ready' );1255 api.parent.send( 'ready' ); 1147 1256 1148 1257 // Control visibility for default controls 1149 1258 $.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 db573b5..b2e32c9 100644
window.wp = window.wp || {}; 494 494 * @param {object} options Extend any instance parameter or method with this object. 495 495 */ 496 496 initialize: function( params, options ) { 497 // Target the parent frame by default, but only if a parent frame exists. 498 var defaultTarget = window.parent == window ? null : window.parent; 497 var defaultTarget; 498 try { 499 // Target the parent frame by default, but only if a parent frame exists. 500 defaultTarget = window.parent === window ? null : window.parent; 501 } catch ( e ) { 502 // Handle case where window goes away in race condition. Uncaught TypeError: Cannot read property 'parent' of null 503 defaultTarget = null; 504 } 499 505 500 506 $.extend( this, options || {} ); 501 507 -
src/wp-includes/js/customize-loader.js
diff --git src/wp-includes/js/customize-loader.js src/wp-includes/js/customize-loader.js index cccf71a..ce099e9 100644
window.wp = window.wp || {}; 36 36 }); 37 37 38 38 // Add navigation listeners. 39 if ( $.support.history ) 39 if ( $.support.history ) { 40 40 this.window.on( 'popstate', Loader.popstate ); 41 } 41 42 42 43 if ( $.support.hashchange ) { 43 44 this.window.on( 'hashchange', Loader.hashchange ); … … window.wp = window.wp || {}; 47 48 48 49 popstate: function( e ) { 49 50 var state = e.originalEvent.state; 50 if ( state && state.customize ) 51 if ( state && state.customize ) { 51 52 Loader.open( state.customize ); 52 else if ( Loader.active )53 } else if ( Loader.active && ( ! state || ! state.customizePreviewUrl ) ) { 53 54 Loader.close(); 55 } 54 56 }, 55 57 56 58 hashchange: function() { 57 59 var hash = window.location.toString().split('#')[1]; 58 60 59 61 if ( hash && 0 === hash.indexOf( 'wp_customize=on' ) ) 60 Loader.open( Loader.settings.url + '?' + hash );62 Loader.open( Loader.settings.url.customize + '?' + hash ); 61 63 62 64 if ( ! hash && ! $.support.history ) 63 65 Loader.close(); 64 66 }, 65 67 66 68 open: function( src ) { 67 var hash ;69 var hash, messenger; 68 70 69 71 if ( this.active ) 70 72 return; … … window.wp = window.wp || {}; 80 82 this.iframe.one( 'load', this.loaded ); 81 83 82 84 // Create a postMessage connection with the iframe. 83 this.messenger = new api.Messenger({85 this.messenger = messenger = new api.Messenger({ 84 86 url: src, 85 87 channel: 'loader', 86 88 targetWindow: this.iframe[0].contentWindow 87 89 }); 88 90 89 91 // Wait for the connection from the iframe before sending any postMessage events. 90 this.messenger.bind( 'ready', function() {92 messenger.bind( 'ready', function() { 91 93 Loader.messenger.send( 'back' ); 92 }); 93 94 this.messenger.bind( 'close', function() { 95 if ( $.support.history ) 94 } ); 95 96 messenger.bind( 'close', function() { 97 var goBackToThemesPage; 98 if ( $.support.history ) { 99 goBackToThemesPage = function ( e ) { 100 var state; 101 state = e.originalEvent.state; 102 if ( state && ( state.customize || state.customizePreviewUrl ) ) { 103 history.back(); 104 } else { 105 $( window ).off( 'popstate', goBackToThemesPage ); 106 } 107 }; 108 $( window ).on( 'popstate', goBackToThemesPage ); 96 109 history.back(); 97 else if ( $.support.hashchange )110 } else if ( $.support.hashchange ) { 98 111 window.location.hash = ''; 99 else112 } else { 100 113 Loader.close(); 114 } 101 115 }); 102 116 103 this.messenger.bind( 'activated', function( location ) {117 messenger.bind( 'activated', function( location ) { 104 118 if ( location ) 105 119 window.location = location; 106 120 }); 107 121 108 122 hash = src.split('?')[1]; 109 123 110 // Ensure we don't call pushState if the user hit the forward button. 111 if ( $.support.history && window.location.href !== src ) 112 history.pushState( { customize: src }, '', src ); 113 else if ( ! $.support.history && $.support.hashchange && hash ) 124 if ( $.support.history ) { 125 // Ensure we don't call pushState if the user hit the forward button. 126 if ( window.location.href !== src ) { 127 history.pushState( { customize: src }, '', src ); 128 } 129 130 // Allow customizer to control history of parent 131 messenger.bind( 'pushstate', function( args ) { 132 history.pushState.apply( history, args ); 133 } ); 134 135 // Forward popstate events to customizer 136 $( window ).on( 'popstate', function ( e ) { 137 messenger.send( 'popstate', [ e.originalEvent.state, window.location ] ); 138 } ); 139 140 } else if ( $.support.hashchange && hash ) { 114 141 window.location.hash = 'wp_customize=on&' + hash; 142 } 115 143 116 144 this.trigger( 'open' ); 117 145 }, … … window.wp = window.wp || {}; 121 149 }, 122 150 123 151 close: function() { 124 if ( ! this.active ) 152 if ( ! this.active ) { 125 153 return; 154 } 126 155 this.active = false; 127 156 128 157 this.trigger( 'close' ); 129 158 130 159 // Return focus to link that was originally clicked. 131 if ( this.link ) 160 if ( this.link ) { 132 161 this.link.focus(); 162 } 133 163 }, 134 164 135 165 closed: function() { -
src/wp-includes/theme.php
diff --git src/wp-includes/theme.php src/wp-includes/theme.php index 40acf6b..f27d79b 100644
function _wp_customize_loader_settings() { 1871 1871 ); 1872 1872 1873 1873 $settings = array( 1874 'url' => esc_url( admin_url( 'customize.php' ) ), 1874 'url' => array( 1875 'customize' => esc_url_raw( admin_url( 'customize.php' ) ), 1876 'home' => esc_url_raw( home_url( '/' ) ), 1877 ), 1875 1878 'isCrossDomain' => $cross_domain, 1876 1879 'browser' => $browser, 1877 1880 );