text: /*
   Copyright 2014 Google Inc. All Rights Reserved.
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at
   http://www.apache.org/licenses/LICENSE-2.0
   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
   */
  
  // While overkill for this specific sample in which there is only one cache,
  // this is one best practice that can be followed in general to keep track of
  // multiple caches used by a given service worker, and keep them all versioned.
  // It maps a shorthand identifier for a cache to a specific, versioned cache name.
  
  // Note that since global state is discarded in between service worker restarts, these
  // variables will be reinitialized each time the service worker handles an event, and you
  // should not attempt to change their values inside an event handler. (Treat them as constants.)
  
  // If at any point you want to force pages that use this service worker to start using a fresh
  // cache, then increment the CACHE_VERSION value. It will kick off the service worker update
  // flow and the old cache(s) will be purged as part of the activate event handler when the
  // updated service worker is activated.
  var CACHE_VERSION = 2;
  var CURRENT_CACHES = {
    prefetch: 'prefetch-cache-v' + CACHE_VERSION
  };
  
  self.addEventListener('install', function(event) {
    var urlsToPrefetch = [
      './',
      'index.js',
      '../../styles/main.css',
      'static/poster.jpg',
      // The videos are stored remotely with CORS enabled.
      'https://storage.googleapis.com/media-session/sample.webm',
    ];
  
    // All of these logging statements should be visible via the "Inspect" interface
    // for the relevant SW accessed via chrome://serviceworker-internals
    console.log('Handling install event. Resources to prefetch:', urlsToPrefetch);
  
    self.skipWaiting();
  
    event.waitUntil(
      caches.open(CURRENT_CACHES.prefetch).then(function(cache) {
        return cache.addAll(urlsToPrefetch);
      })
    );
  });
  
  self.addEventListener('activate', function(event) {
    // Delete all caches that aren't named in CURRENT_CACHES.
    // While there is only one cache in this example, the same logic will handle the case where
    // there are multiple versioned caches.
    var expectedCacheNames = Object.keys(CURRENT_CACHES).map(function(key) {
      return CURRENT_CACHES[key];
    });
  
    event.waitUntil(
      caches.keys().then(function(cacheNames) {
        return Promise.all(
          cacheNames.map(function(cacheName) {
            if (expectedCacheNames.indexOf(cacheName) === -1) {
              // If this cache name isn't present in the array of "expected" cache names, then delete it.
              console.log('Deleting out of date cache:', cacheName);
              return caches.delete(cacheName);
            }
          })
          );
      })
      );
  });
  
  self.addEventListener('fetch', function(event) {
    console.log('Handling fetch event for', event.request.url);
  
    if (event.request.headers.get('range')) {
      var pos =
      Number(/^bytes\=(\d+)\-$/g.exec(event.request.headers.get('range'))[1]);
      console.log('Range request for', event.request.url,
        ', starting position:', pos);
      event.respondWith(
        caches.open(CURRENT_CACHES.prefetch)
        .then(function(cache) {
          return cache.match(event.request.url);
        }).then(function(res) {
          if (!res) {
            return fetch(event.request)
            .then(res => {
              return res.arrayBuffer();
            });
          }
          return res.arrayBuffer();
        }).then(function(ab) {
          return new Response(
            ab.slice(pos),
            {
              status: 206,
              statusText: 'Partial Content',
              headers: [
                // ['Content-Type', 'video/webm'],
                ['Content-Range', 'bytes ' + pos + '-' +
                  (ab.byteLength - 1) + '/' + ab.byteLength]]
            });
        }));
    } else {
      console.log('Non-range request for', event.request.url);
      event.respondWith(
      // caches.match() will look for a cache entry in all of the caches available to the service worker.
      // It's an alternative to first opening a specific named cache and then matching on that.
      caches.match(event.request).then(function(response) {
        if (response) {
          console.log('Found response in cache:', response);
          return response;
        }
        console.log('No response found in cache. About to fetch from network...');
        // event.request will always have the proper mode set ('cors, 'no-cors', etc.) so we don't
        // have to hardcode 'no-cors' like we do when fetch()ing in the install handler.
        return fetch(event.request).then(function(response) {
          console.log('Response from network is:', response);
  
          return response;
        }).catch(function(error) {
          // This catch() will handle exceptions thrown from the fetch() operation.
          // Note that a HTTP error response (e.g. 404) will NOT trigger an exception.
          // It will return a normal response object that has the appropriate error code set.
          console.error('Fetching failed:', error);
  
          throw error;
        });
      })
      );
    }
  });
  
  