3

I'm toying with adding web push notifications to a web app hosted with apps script. To do so, I need to register a service worker and I ran into an error with a cross-domain request. Raw content is hosted from *.googleusercontent.com while the script URL is script.google.com/*.

I was able to successfully create an inline worker using this post on creating inline URLs created from a blob with the script. Now I'm stuck at the point of registering the worker in the browser.

The following model works:

HTML

<!-- Display the worker status -->
<div id="log"></log>

Service Worker

<script id="worker" type="javascript/worker">
  self.onmessage = function(e) {
    self.postMessage('msg from worker');
  };
  console.log('[Service Worker] Process started');

  })
</script> 

Inline install

<script>
  function log(msg) {
    var fragment = document.createDocumentFragment();
    fragment.appendChild(document.createTextNode(msg));
    fragment.appendChild(document.createElement('br'));

    document.querySelector("#log").appendChild(fragment);
  }

  // Create the object with the script
  var blob = new Blob([ document.querySelector("#worker").textContent ]);

  // assign a absolute URL to the obejct for hosting
  var worker = new Worker(window.URL.createObjectURL(blob));
  worker.onmessage = function(e) {
    log("Received: " + e.data);
  }

  worker.postMessage('start');
  // navigator.serviceWorker.register(worker) this line fails
</script>

navigator.serviceWorker.register(worker); returns a 400: Bad HTTP response code error.

Can inline workers be installed? Or do all installed workers have to come from external scripts?

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Brian
  • 4,274
  • 2
  • 27
  • 55

1 Answers1

7

It's worth noting that Web Workers and Service Workers, which are used with push notifications, are different (see this SO response to read about the difference).

According to MDN Service Workers require a script URL. In Google Apps Script you could serve a service worker file with something like:

function doGet(e) {
  var file = e.parameter.file;
  if (file == 'service-worker.js'){
    return ContentService.createTextOutput(HtmlService.createHtmlOutputFromFile('service-worker.js').getContent())
                         .setMimeType(ContentService.MimeType.JAVASCRIPT);
  } else {
    return HtmlService.createHtmlOutputFromFile('index');
  }
}

But as in this example (source code here) because of the way web apps are served you'll encounter the error:

SecurityError: Failed to register a ServiceWorker: The script resource is behind a redirect, which is disallowed.

There was a proposal for Foreign Fetch for Service Workers but it's still in draft.

mhawksey
  • 2,013
  • 5
  • 23
  • 61
  • 2
    About Foreign Fetch, it was recently removed from Service Workers. See https://github.com/w3c/ServiceWorker/pull/1207 and the related issue at https://github.com/w3c/ServiceWorker/issues/1188 – sideshowbarker Nov 08 '17 at 00:30