windowclient-navigate-on-iframe.html (3270B)
1 <!DOCTYPE html> 2 <title>WindowClient.navigate() on a prerendered iframe</title> 3 <script src="/resources/testharness.js"></script> 4 <script src="/resources/testharnessreport.js"></script> 5 <script src="/speculation-rules/prerender/resources/utils.js"></script> 6 <script src="/speculation-rules/prerender/resources/deferred-promise-utils.js"></script> 7 <body> 8 <script> 9 // The main test page loads the initiator page, then the initiator page will 10 // prerender itself with the `prerendering` parameter and add an iframe. Once 11 // the prerendered iframe is ready, post a message to a service worker to call 12 // WindowClient.navigate(). 13 14 const params = new URLSearchParams(location.search); 15 const prerendering = params.has('prerendering'); 16 const navigationUrl = params.get('navigationUrl'); 17 const uid = params.get('uid'); 18 19 const IFRAME_URL = `prerendered-iframe.html?uid=${uid}`; 20 21 function addIframe() { 22 const iframe = document.createElement('iframe'); 23 iframe.src = IFRAME_URL; 24 document.body.appendChild(iframe); 25 } 26 27 // If the navigation is expected to be deferred, wait to navigate to 28 // `navigationUrl` until a prerendered iframe is activated by 29 // PrerenderEventCollector. The result of the navigation is sent to 30 // "navigation-channel" PrerenderChannel and the prerendering states and events 31 // is sent to "test-channel" PrerenderChannel by PrerenderEventCollector. 32 async function startNavigationToCrossOriginUrl() { 33 assert_not_equals(new URL(navigationUrl).origin, window.location.origin); 34 35 const navigationPromise = new Promise(resolve => { 36 const bc = new PrerenderChannel('navigation-channel', uid); 37 bc.addEventListener('message', e => { 38 assert_equals(e.data, 'navigate() succeeded'); 39 resolve() 40 bc.close(); 41 }); 42 bc.postMessage(JSON.stringify({ 43 navigationUrl: navigationUrl, 44 clientUrl: new URL(IFRAME_URL, window.location).toString(), 45 respondTo: 'navigation-channel', 46 })); 47 }); 48 49 const prerenderEventCollector = new PrerenderEventCollector(); 50 prerenderEventCollector.start(navigationPromise, 'navigation on iframe'); 51 } 52 53 // If the navigation is expected to succeed without delay, the navigation result 54 // is directly sent to "test-channel" PrerenderChannel. 55 function startNavigationToSameOriginUrl() { 56 assert_equals(new URL(navigationUrl).origin, window.location.origin); 57 58 const bc = new PrerenderChannel('navigation-channel', uid); 59 bc.postMessage(JSON.stringify({ 60 navigationUrl: navigationUrl, 61 clientUrl: new URL(IFRAME_URL, window.location).toString(), 62 respondTo: 'test-channel', 63 })); 64 bc.close(); 65 } 66 67 if (prerendering) { 68 assert_not_equals(null, navigator.serviceWorker.controller, 69 'should be controlled by a service worker'); 70 71 const bc = new PrerenderChannel('iframe-channel', uid); 72 const readyPromise = new Promise(resolve => { 73 bc.addEventListener('message', e => { 74 resolve(e.data); 75 }, { 76 once: true 77 }); 78 }); 79 80 addIframe(); 81 82 readyPromise.then(result => { 83 assert_equals(result, 'prerender success'); 84 85 if (new URL(navigationUrl).origin === window.location.origin) { 86 startNavigationToSameOriginUrl(); 87 } else { 88 startNavigationToCrossOriginUrl(); 89 } 90 91 bc.close(); 92 }); 93 } else { 94 loadInitiatorPage(); 95 } 96 </script> 97 </body>