Skip to content

Commit 328f46a

Browse files
committed
[sandbox] reuse controller.sw.js for service worker, use MessagePorts to send directly between chrome and sandbox worker
1 parent 1ed41cd commit 328f46a

File tree

2 files changed

+27
-135
lines changed

2 files changed

+27
-135
lines changed

packages/sandbox/controller.html

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<title>Proxy Sandbox Controller</title>
22
<script>
3-
function wake(controller) {
4-
controller.postMessage({ $sandboxsw$type: "wake" });
3+
function notifyReady(controller) {
4+
parent.postMessage({ $sandboxsw$type: "ready" }, "*");
55
}
66
navigator.serviceWorker
77
.register("/sw.js", {
@@ -10,11 +10,11 @@
1010
.then((registration) => {
1111
if (navigator.serviceWorker.controller) {
1212
// there's probably already a service worker
13-
wake(navigator.serviceWorker.controller);
13+
notifyReady(navigator.serviceWorker.controller);
1414
} else {
1515
// there's no service worker, wait until we're controlled
1616
navigator.serviceWorker.addEventListener("controllerchange", () => {
17-
wake(navigator.serviceWorker.controller);
17+
notifyReady(navigator.serviceWorker.controller);
1818
});
1919
}
2020
})
@@ -25,34 +25,28 @@
2525
"*"
2626
);
2727
});
28+
29+
// forward service worker -> chrome
2830
navigator.serviceWorker.addEventListener("message", (event) => {
29-
let data = event.data;
30-
if ("$sandboxsw$type" in data) {
31-
let transfer;
32-
if (data.$sandboxsw$message?.body) {
33-
let body = data.$sandboxsw$message.body;
34-
if (body instanceof ArrayBuffer || body instanceof ReadableStream) {
35-
transfer = [body];
36-
}
37-
}
38-
window.parent.postMessage(event.data, "*", transfer);
39-
}
31+
if (typeof event.data !== "object" || event.data === null) return;
32+
const data = event.data.$sandboxsw;
33+
if (typeof data !== "object" || data === null) return;
34+
35+
window.parent.postMessage(event.data, "*");
4036
});
37+
38+
// chrome -> controller -> service worker
4139
window.addEventListener("message", (event) => {
42-
let data = event.data;
43-
if ("$sandboxsw$type" in data) {
44-
if (navigator.serviceWorker.controller) {
45-
let transfer;
46-
if (data.$sandboxsw$message?.body) {
47-
let body = data.$sandboxsw$message.body;
48-
if (body instanceof ArrayBuffer || body instanceof ReadableStream) {
49-
transfer = [body];
50-
}
51-
}
52-
navigator.serviceWorker.controller.postMessage(data, transfer);
53-
} else {
54-
console.error("No service worker controller to send message to.");
55-
}
40+
if (typeof event.data !== "object" || event.data === null) return;
41+
const data = event.data.$sandboxsw;
42+
if (typeof data !== "object" || data === null) return;
43+
44+
if (!navigator.serviceWorker.controller) {
45+
console.error("No service worker controller to send message to.");
46+
return;
5647
}
48+
49+
// forward messageport
50+
navigator.serviceWorker.controller.postMessage(data, event.ports);
5751
});
5852
</script>

packages/sandbox/sw.js

Lines changed: 4 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,9 @@
1-
class SandboxThing {
2-
counter = 0;
3-
promises = new Map();
1+
importScripts("./controller.sw.js");
42

5-
async find() {
6-
let swclients = await clients.matchAll({ includeUncontrolled: true });
7-
for (const client of swclients) {
8-
if (new URL(client.url).pathname.startsWith("/controller")) {
9-
return client;
10-
}
11-
}
12-
return null;
3+
addEventListener("fetch", (event) => {
4+
if (shouldRoute(event)) {
5+
event.respondWith(route(event));
136
}
14-
15-
async request(domain, message, transfer) {
16-
let controller = await this.find();
17-
if (!controller) throw new Error("couldn't find controller");
18-
return new Promise((resolve, reject) => {
19-
this.promises.set(this.counter, { resolve, reject });
20-
controller.postMessage(
21-
{
22-
$sandboxsw$type: "request",
23-
$sandboxsw$token: this.counter++,
24-
$sandboxsw$domain: domain,
25-
$sandboxsw$message: message,
26-
},
27-
transfer
28-
);
29-
});
30-
}
31-
32-
handleMessage(token, message, error) {
33-
if (this.promises.has(token)) {
34-
let { resolve, reject } = this.promises.get(token);
35-
this.promises.delete(token);
36-
if (error) {
37-
reject(error);
38-
} else {
39-
resolve(message);
40-
}
41-
}
42-
}
43-
}
44-
45-
let sb = new SandboxThing();
46-
47-
async function handleFetch(event) {
48-
const client = await self.clients.get(event.clientId);
49-
50-
let resp = await sb.request(
51-
"fetch",
52-
{
53-
rawUrl: event.request.url,
54-
destination: event.request.destination,
55-
mode: event.request.mode,
56-
referrer: event.request.referrer,
57-
method: event.request.method,
58-
body: event.request.body,
59-
cache: event.request.cache,
60-
forceCrossOriginIsolated: false,
61-
initialHeaders: Object.fromEntries([...event.request.headers.entries()]),
62-
rawClientUrl: client ? client.url : undefined,
63-
},
64-
event.request.body instanceof ReadableStream ||
65-
event.request.body instanceof ArrayBuffer
66-
? [event.request.body]
67-
: undefined
68-
);
69-
70-
return new Response(resp.body, {
71-
status: resp.status,
72-
statusText: resp.statusText,
73-
headers: resp.headers,
74-
});
75-
}
76-
77-
self.addEventListener("fetch", (event) => {
78-
let url = new URL(event.request.url);
79-
if (url.origin == location.origin && url.pathname.startsWith("/controller")) {
80-
return;
81-
}
82-
event.respondWith(
83-
(async () => {
84-
try {
85-
return await handleFetch(event);
86-
} catch (e) {
87-
console.error(e);
88-
return new Response("SandboxSW Error: " + e + e.stack, {
89-
status: 500,
90-
});
91-
}
92-
})()
93-
);
947
});
958

969
self.addEventListener("install", () => {
@@ -102,18 +15,3 @@ self.addEventListener("activate", (e) => {
10215
});
10316

10417
console.log("sw initialized");
105-
self.addEventListener("message", (e) => {
106-
let data = e.data;
107-
if (!("$sandboxsw$type" in data)) return;
108-
if (data.$sandboxsw$type === "wake") {
109-
e.source.postMessage({
110-
$sandboxsw$type: "confirm",
111-
});
112-
} else if (data.$sandboxsw$type === "response") {
113-
sb.handleMessage(
114-
data.$sandboxsw$token,
115-
data.$sandboxsw$message,
116-
data.$sandboxsw$error
117-
);
118-
}
119-
});

0 commit comments

Comments
 (0)