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