function get_query_params(url) {
  var search = (new URL(url)).search;
  if (!search) {
    return {};
  }
  var ret = {};
  var params = search.substring(1).split('&');
  params.forEach(function(param) {
      var element = param.split('=');
      ret[decodeURIComponent(element[0])] = decodeURIComponent(element[1]);
    });
  return ret;
}

function get_request_init(base, params) {
  var init = {};
  init['method'] = params['method'] || base['method'];
  init['mode'] = params['mode'] || base['mode'];
  init['credentials'] = params['credentials'] || base['credentials'];
  init['redirect'] = params['redirect'] || base['redirect'];
  return init;
}

self.addEventListener('fetch', function(event) {
    var params = get_query_params(event.request.url);
    var init = get_request_init(event.request, params);
    var url = params['url'];
    if (params['ignore']) {
      return;
    }
    if (params['reject']) {
      event.respondWith(new Promise(function(resolve, reject) {
          reject();
        }));
      return;
    }
    if (params['resolve-null']) {
      event.respondWith(new Promise(function(resolve) {
          resolve(null);
        }));
      return;
    }
    if (params['generate-png']) {
      var binary = atob(
          'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAA' +
          'RnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAhSURBVDhPY3wro/Kf' +
          'gQLABKXJBqMGjBoAAqMGDLwBDAwAEsoCTFWunmQAAAAASUVORK5CYII=');
      var array = new Uint8Array(binary.length);
      for(var i = 0; i < binary.length; i++) {
        array[i] = binary.charCodeAt(i)
      };
      event.respondWith(new Response(new Blob([array], {type: 'image/png'})));
      return;
    }
    event.respondWith(new Promise(function(resolve, reject) {
        var request = event.request;
        if (url) {
          request = new Request(url, init);
        }
        fetch(request).then(function(response) {
          var expectedType = params['expected_type'];
          if (expectedType && response.type !== expectedType) {
            // Resolve a JSON object with a failure instead of rejecting
            // in order to distinguish this from a NetworkError, which
            // may be expected even if the type is correct.
            resolve(new Response(JSON.stringify({
              result: 'failure',
              detail: 'got ' + response.type + ' Response.type instead of ' +
                      expectedType
            })));
          }
          resolve(response);
        }, reject)
      }));
  });
