tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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>