client-url-creation-url-iframe.html (3547B)
1 <!DOCTYPE html> 2 <title>Service Worker: Client.url is Window creation URL iframe resource</title> 3 <script> 4 // This is the iframe resource for the Client.url Window creation URL test. 5 // It supports the test page telling it to navigate in various ways, and then 6 // the iframe will post back that its done. 7 8 // Turn the next time an event is raised into a promise. 9 function wait_for_next_event(event_target, event_name) { 10 return new Promise(resolve => { 11 const event_handler = event => { 12 event_target.removeEventListener(event_name, event_handler); 13 resolve(event); 14 }; 15 event_target.addEventListener(event_name, event_handler); 16 }); 17 } 18 19 // Perform the navigation step sent to the iframe by the test page. 20 async function perform_navigation(navigation_kind) { 21 // This is true if the navigation results in a new document instance. 22 // For example, history.pushState() doesn't create a new document, but 23 // navigating to a URL with a different query does. We need to keep 24 // track of this so we can post a message back to the test page when the 25 // navigation completes without loading a new document. 26 let cross_document_navigation = false; 27 28 const query_params = new URLSearchParams(location.search.substring(1)); 29 const step = parseInt(query_params.get('step'), 10); 30 31 const next_url = `?step=${step + 1}`; 32 33 if (navigation_kind === 'pushstate') { 34 history.pushState({}, '', next_url); 35 } else if (navigation_kind === 'replacestate') { 36 history.replaceState({}, '', next_url); 37 } else if (navigation_kind === 'back-within-same-document') { 38 history.back(); 39 } else if (navigation_kind === 'fragment') { 40 location.href = '#fragment'; 41 await wait_for_next_event(window, 'hashchange'); 42 } else if (navigation_kind === 'back-cross-document') { 43 // Note there are two back navigation_kinds. Both call history.back(), 44 // but 'back-cross-document' is for when we go back to a different 45 // document instance and the new document will postMessage the parent 46 // that the navigation is done, and and 'back-within-same-document' is for 47 // when we go back but remain in the same document and so need to 48 // postMessage the parent that the navigation is done from this document. 49 history.back(); 50 cross_document_navigation = true; 51 } else if (navigation_kind === 'query') { 52 location.href = next_url; 53 cross_document_navigation = true; 54 } else if (navigation_kind === 'reload') { 55 location.reload(); 56 cross_document_navigation = true; 57 } else { 58 throw new Error('Unknown navigation kind: ' + navigation_kind); 59 } 60 return cross_document_navigation; 61 } 62 63 window.addEventListener('message', async message_event => { 64 try { 65 const navigation_kind = message_event.data; 66 67 // If its a cross document navigation, then we need to send the done 68 // message back to the test page when the navigation has started the 69 // new document. 70 const cross_document_navigation = await perform_navigation(navigation_kind); 71 if (!cross_document_navigation ) { 72 window.parent.postMessage('done'); 73 } 74 } catch (error) { 75 window.parent.postMessage('error: ' + error.message); 76 } 77 }); 78 79 // Navigation steps either result in a new document instance or not. The 80 // iframe needs to post a message back to the test page when the navigation 81 // completes regardless. If the navigation does create a new document, then 82 // the following postMessage informs the test page that the cross document 83 // navigation has completed. 84 window.parent.postMessage('done'); 85 </script>