coi-serviceworker.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /*! coi-serviceworker v0.1.7 - Guido Zuidhof and contributors, licensed under MIT */
  2. let coepCredentialless = false;
  3. if (typeof window === 'undefined') {
  4. self.addEventListener("install", () => self.skipWaiting());
  5. self.addEventListener("activate", (event) => event.waitUntil(self.clients.claim()));
  6. self.addEventListener("message", (ev) => {
  7. if (!ev.data) {
  8. return;
  9. } else if (ev.data.type === "deregister") {
  10. self.registration
  11. .unregister()
  12. .then(() => {
  13. return self.clients.matchAll();
  14. })
  15. .then(clients => {
  16. clients.forEach((client) => client.navigate(client.url));
  17. });
  18. } else if (ev.data.type === "coepCredentialless") {
  19. coepCredentialless = ev.data.value;
  20. }
  21. });
  22. self.addEventListener("fetch", function (event) {
  23. const r = event.request;
  24. if (r.cache === "only-if-cached" && r.mode !== "same-origin") {
  25. return;
  26. }
  27. const request = (coepCredentialless && r.mode === "no-cors")
  28. ? new Request(r, {
  29. credentials: "omit",
  30. })
  31. : r;
  32. event.respondWith(
  33. fetch(request)
  34. .then((response) => {
  35. if (response.status === 0) {
  36. return response;
  37. }
  38. const newHeaders = new Headers(response.headers);
  39. newHeaders.set("Cross-Origin-Embedder-Policy",
  40. coepCredentialless ? "credentialless" : "require-corp"
  41. );
  42. if (!coepCredentialless) {
  43. newHeaders.set("Cross-Origin-Resource-Policy", "cross-origin");
  44. }
  45. newHeaders.set("Cross-Origin-Opener-Policy", "same-origin");
  46. return new Response(response.body, {
  47. status: response.status,
  48. statusText: response.statusText,
  49. headers: newHeaders,
  50. });
  51. })
  52. .catch((e) => console.error(e))
  53. );
  54. });
  55. } else {
  56. (() => {
  57. // You can customize the behavior of this script through a global `coi` variable.
  58. const coi = {
  59. shouldRegister: () => true,
  60. shouldDeregister: () => false,
  61. //coepCredentialless: () => (window.chrome !== undefined || window.netscape !== undefined),
  62. coepCredentialless: () => navigator.userAgentData?.brands?.some((b) => b.brand == "Chromium"),
  63. doReload: () => window.location.reload(),
  64. quiet: false,
  65. ...window.coi
  66. };
  67. const n = navigator;
  68. if (n.serviceWorker && n.serviceWorker.controller) {
  69. n.serviceWorker.controller.postMessage({
  70. type: "coepCredentialless",
  71. value: coi.coepCredentialless(),
  72. });
  73. if (coi.shouldDeregister()) {
  74. n.serviceWorker.controller.postMessage({ type: "deregister" });
  75. }
  76. }
  77. // If we're already coi: do nothing. Perhaps it's due to this script doing its job, or COOP/COEP are
  78. // already set from the origin server. Also if the browser has no notion of crossOriginIsolated, just give up here.
  79. if (window.crossOriginIsolated !== false || !coi.shouldRegister()) return;
  80. if (!window.isSecureContext) {
  81. !coi.quiet && console.log("COOP/COEP Service Worker not registered, a secure context is required.");
  82. return;
  83. }
  84. // In some environments (e.g. Chrome incognito mode) this won't be available
  85. if (n.serviceWorker) {
  86. n.serviceWorker.register(window.document.currentScript.src).then(
  87. (registration) => {
  88. !coi.quiet && console.log("COOP/COEP Service Worker registered", registration.scope);
  89. registration.addEventListener("updatefound", () => {
  90. !coi.quiet && console.log("Reloading page to make use of updated COOP/COEP Service Worker.");
  91. coi.doReload();
  92. });
  93. // If the registration is active, but it's not controlling the page
  94. if (registration.active && !n.serviceWorker.controller) {
  95. !coi.quiet && console.log("Reloading page to make use of COOP/COEP Service Worker.");
  96. coi.doReload();
  97. }
  98. },
  99. (err) => {
  100. !coi.quiet && console.error("COOP/COEP Service Worker failed to register:", err);
  101. }
  102. );
  103. }
  104. })();
  105. }