| <!DOCTYPE html> | |
| <title>WindowClient.navigate() on a prerendered iframe</title> | |
| <script src="/resources/testharness.js"></script> | |
| <script src="/resources/testharnessreport.js"></script> | |
| <script src="/speculation-rules/prerender/resources/utils.js"></script> | |
| <script src="/speculation-rules/prerender/resources/deferred-promise-utils.js"></script> | |
| <body> | |
| <script> | |
| // The main test page loads the initiator page, then the initiator page will | |
| // prerender itself with the `prerendering` parameter and add an iframe. Once | |
| // the prerendered iframe is ready, post a message to a service worker to call | |
| // WindowClient.navigate(). | |
| const params = new URLSearchParams(location.search); | |
| const prerendering = params.has('prerendering'); | |
| const navigationUrl = params.get('navigationUrl'); | |
| const uid = params.get('uid'); | |
| const IFRAME_URL = `prerendered-iframe.html?uid=${uid}`; | |
| function addIframe() { | |
| const iframe = document.createElement('iframe'); | |
| iframe.src = IFRAME_URL; | |
| document.body.appendChild(iframe); | |
| } | |
| // If the navigation is expected to be deferred, wait to navigate to | |
| // `navigationUrl` until a prerendered iframe is activated by | |
| // PrerenderEventCollector. The result of the navigation is sent to | |
| // "navigation-channel" PrerenderChannel and the prerendering states and events | |
| // is sent to "test-channel" PrerenderChannel by PrerenderEventCollector. | |
| async function startNavigationToCrossOriginUrl() { | |
| assert_not_equals(new URL(navigationUrl).origin, window.location.origin); | |
| const navigationPromise = new Promise(resolve => { | |
| const bc = new PrerenderChannel('navigation-channel', uid); | |
| bc.addEventListener('message', e => { | |
| assert_equals(e.data, 'navigate() succeeded'); | |
| resolve() | |
| bc.close(); | |
| }); | |
| bc.postMessage(JSON.stringify({ | |
| navigationUrl: navigationUrl, | |
| clientUrl: new URL(IFRAME_URL, window.location).toString(), | |
| respondTo: 'navigation-channel', | |
| })); | |
| }); | |
| const prerenderEventCollector = new PrerenderEventCollector(); | |
| prerenderEventCollector.start(navigationPromise, 'navigation on iframe'); | |
| } | |
| // If the navigation is expected to succeed without delay, the navigation result | |
| // is directly sent to "test-channel" PrerenderChannel. | |
| function startNavigationToSameOriginUrl() { | |
| assert_equals(new URL(navigationUrl).origin, window.location.origin); | |
| const bc = new PrerenderChannel('navigation-channel', uid); | |
| bc.postMessage(JSON.stringify({ | |
| navigationUrl: navigationUrl, | |
| clientUrl: new URL(IFRAME_URL, window.location).toString(), | |
| respondTo: 'test-channel', | |
| })); | |
| bc.close(); | |
| } | |
| if (prerendering) { | |
| assert_not_equals(null, navigator.serviceWorker.controller, | |
| 'should be controlled by a service worker'); | |
| const bc = new PrerenderChannel('iframe-channel', uid); | |
| const readyPromise = new Promise(resolve => { | |
| bc.addEventListener('message', e => { | |
| resolve(e.data); | |
| }, { | |
| once: true | |
| }); | |
| }); | |
| addIframe(); | |
| readyPromise.then(result => { | |
| assert_equals(result, 'prerender success'); | |
| if (new URL(navigationUrl).origin === window.location.origin) { | |
| startNavigationToSameOriginUrl(); | |
| } else { | |
| startNavigationToCrossOriginUrl(); | |
| } | |
| bc.close(); | |
| }); | |
| } else { | |
| loadInitiatorPage(); | |
| } | |
| </script> | |
| </body> |