tor-browser

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

basic-service-worker.js (3610B)


      1 const originalSwOption = new URL(location.href).searchParams.get('sw');
      2 let swOption = originalSwOption;
      3 
      4 if (swOption === 'fetch-handler-navigation-preload') {
      5  self.addEventListener('activate', event => {
      6    if (self.registration.navigationPreload) {
      7      event.waitUntil(self.registration.navigationPreload.enable());
      8    }
      9  });
     10 }
     11 
     12 if (swOption === 'race-fetch-handler' ||
     13  swOption === 'race-fetch-handler-to-fallback' ||
     14  swOption === 'race-fetch-handler-modify-url') {
     15  swOption = swOption.substring('race-'.length);
     16  self.addEventListener('install', event => {
     17    event.addRoutes([{
     18      condition: { urlPattern: { pathname: '/**/counting-executor.py' } },
     19      source: 'race-network-and-fetch-handler'
     20    }]);
     21  });
     22 }
     23 
     24 const interceptedRequests = [];
     25 
     26 self.addEventListener('message', event => {
     27  if (event.data === 'getInterceptedRequests') {
     28    event.source.postMessage(interceptedRequests);
     29  }
     30 });
     31 
     32 if (swOption !== 'no-fetch-handler') {
     33  self.addEventListener('fetch', event => {
     34 
     35    // Intercept the prefetched and navigated URLs only (e.g. do not intercept
     36    // subresource requests related to `/common/dispatcher/dispatcher.js`).
     37    if (!event.request.url.includes('counting-executor.py')) {
     38      return;
     39    }
     40 
     41    const headers = {};
     42    event.request.headers.forEach((value, key) => {
     43      headers[key] = value;
     44    });
     45    const interceptedRequest = {
     46      request: {
     47        url: event.request.url,
     48        headers: headers,
     49      },
     50      clientId: event.clientId,
     51      resultingClientId: event.resultingClientId
     52    };
     53    interceptedRequests.push(interceptedRequest);
     54 
     55    if (swOption === 'fetch-handler') {
     56      event.respondWith(fetch(event.request));
     57    } else if (swOption === 'fetch-handler-synthetic') {
     58      const finalUrl = new URL(event.request.url).searchParams.get('location');
     59      if (finalUrl) {
     60        event.respondWith(Response.redirect(finalUrl));
     61      } else {
     62        // Fallback to the network.
     63      }
     64    } else if (swOption === 'fetch-handler-modify-url') {
     65      // The "Sec-Purpose: prefetch" header is dropped in fetch-handler-modify-*
     66      // cases in Step 33 of // https://fetch.spec.whatwg.org/#dom-request
     67      // because it's a https://fetch.spec.whatwg.org/#forbidden-request-header
     68      const url = new URL(event.request.url);
     69      url.searchParams.set('intercepted', 'true');
     70      if (originalSwOption === 'race-fetch-handler-modify-url') {
     71        // See the comment in `basic.sub.https.html` for delay value.
     72        url.searchParams.set('delay', '500');
     73      }
     74      event.respondWith(fetch(url, {headers: event.request.headers}));
     75    } else if (swOption === 'fetch-handler-modify-referrer') {
     76      event.respondWith(fetch(event.request,
     77          {referrer: new URL('/intercepted', location.href).href}));
     78    } else if (swOption === 'fetch-handler-navigation-preload') {
     79      event.respondWith((async () => {
     80        try {
     81          if (event.preloadResponse === 'undefined') {
     82            interceptedRequest.preloadResponse = 'undefined';
     83            return fetch(event.request);
     84          }
     85          const response = await event.preloadResponse;
     86          if (response) {
     87            interceptedRequest.preloadResponse = 'resolved';
     88            return response;
     89          } else {
     90            interceptedRequest.preloadResponse = 'resolved to undefined';
     91            return fetch(event.request);
     92          }
     93        } catch(e) {
     94          interceptedRequest.preloadResponse = 'rejected';
     95          throw e;
     96        }
     97      })());
     98    } else {
     99      // Do nothing to fallback to the network.
    100    }
    101  });
    102 }