tor-browser

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

partitioned-utils.js (3228B)


      1 // The resolve function for the current pending event listener's promise.
      2 // It is nulled once the promise is resolved.
      3 var message_event_promise_resolve = null;
      4 
      5 function messageEventHandler(evt) {
      6  if (message_event_promise_resolve) {
      7    local_resolve = message_event_promise_resolve;
      8    message_event_promise_resolve = null;
      9    local_resolve(evt.data);
     10  }
     11 }
     12 
     13 function makeMessagePromise() {
     14  if (message_event_promise_resolve != null) {
     15    // Do not create a new promise until the previous is settled.
     16    return;
     17  }
     18 
     19  return new Promise(resolve => {
     20    message_event_promise_resolve = resolve;
     21  });
     22 }
     23 
     24 // Loads a url for the frame type and then returns a promise for
     25 // the data that was postMessage'd from the loaded frame.
     26 // If the frame type is 'window' then `url` is encoded into the search param
     27 // as the url the 3p window is meant to iframe.
     28 function loadAndReturnSwData(t, url, frame_type) {
     29  if (frame_type !== 'iframe' && frame_type !== 'window') {
     30    return;
     31  }
     32 
     33  const message_promise = makeMessagePromise();
     34 
     35  // Create the iframe or window and then return the promise for data.
     36  if ( frame_type === 'iframe' ) {
     37    const frame = with_iframe(url, false);
     38    t.add_cleanup(async () => {
     39      const f = await frame;
     40      f.remove();
     41    });
     42  }
     43  else {
     44    // 'window' case.
     45    const search_param = new URLSearchParams();
     46    search_param.append('target', url);
     47 
     48    const third_party_window_url = new URL(
     49    './resources/partitioned-service-worker-third-party-window.html' +
     50    '?' + search_param,
     51    get_host_info().HTTPS_NOTSAMESITE_ORIGIN + self.location.pathname);
     52 
     53    const w = window.open(third_party_window_url);
     54    t.add_cleanup(() => w.close());
     55  }
     56 
     57  return message_promise;
     58 }
     59 
     60 // Checks for an existing service worker registration. If not present,
     61 // registers and maintains a service worker. Used in windows or iframes
     62 // that will be partitioned from the main frame.
     63 async function setupServiceWorker() {
     64 
     65  const script = './partitioned-storage-sw.js';
     66  const scope = './partitioned-';
     67 
     68  var reg = await navigator.serviceWorker.register(script, { scope: scope });
     69 
     70  // We should keep track if we installed a worker or not. If we did then we
     71  // need to uninstall it. Otherwise we let the top level test uninstall it
     72  // (If partitioning is not working).
     73  var installed_a_worker = true;
     74  await new Promise(resolve => {
     75    // Check if a worker is already activated.
     76    var worker = reg.active;
     77    // If so, just resolve.
     78    if ( worker ) {
     79      installed_a_worker = false;
     80      resolve();
     81      return;
     82    }
     83 
     84    //Otherwise check if one is waiting.
     85    worker = reg.waiting;
     86    // If not waiting, grab the installing worker.
     87    if ( !worker ) {
     88      worker = reg.installing;
     89    }
     90 
     91    // Resolve once it's activated.
     92    worker.addEventListener('statechange', evt => {
     93      if (worker.state === 'activated') {
     94        resolve();
     95      }
     96    });
     97  });
     98 
     99  self.addEventListener('unload', async () => {
    100    // If we didn't install a worker then that means the top level test did, and
    101    // that test is therefore responsible for cleaning it up.
    102    if ( !installed_a_worker ) {
    103        return;
    104    }
    105 
    106    await reg.unregister();
    107  });
    108 
    109  return reg;
    110 }