Skip to content

Commit 64fc95b

Browse files
[WPT] Move/merge COEP/COOP dispatcher framework to /common
To reduce duplication and prepare for using this framework for BFCache (#28950), this CL merges two sets of dispatcher/executor files under COEP and COOP and move them to `/common`. Most of the changes are simple path renaming, except for: - Service worker's scope is also moved to `/common/dispatcher/` in: /wpt/html/cross-origin-embedder-policy/credentialless/service-worker-coep-credentialless-proxy.tentative.https.html /wpt/html/cross-origin-embedder-policy/credentialless/service-worker-coep-none-proxy.tentative.https.html because the service workers should control executors. - Diffs between COEP and COOP dispatchers are merged, but are trivial (e.g. some functionality exists only one of them, like 6 concurrent accesses to the server, retrying on failure, timeout in receive(), Access-Control-Allow-Credentials in dispatcher, etc.). - README.md about the dispatcher is moved and added. - /wpt/html/cross-origin-embedder-policy/credentialless/resources/cacheable-response.py is also merged into dispatcher.py, because they should access the same stash and already have common code. - Stash paths are moved to '/common/dispatcher'. - `executer.js` and `sw_executer.js` are moved to `executer-worker.js` and `executer-service-worker.js`, respectively, to clarify they are worker scripts, rather than helpers. Bug: 1107415 Change-Id: I0d28e7f4b4cca6599562ac4766a326880139028d
1 parent ca5841f commit 64fc95b

File tree

87 files changed

+216
-308
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+216
-308
lines changed

common/dispatcher/README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Message passing API
2+
3+
`dispatcher.js` (and its server-side backend `dispatcher.py`) provide
4+
a universal queue-based message passing API.
5+
Each queue is identified by a UUID, and accessed via the following APIs:
6+
7+
- `send()` pushes a string.
8+
- `receive()` pops the first item.
9+
- `showRequestHeaders()` and `cacheableShowRequestHeaders()` return URLs,
10+
that push request headers upon fetching.
11+
- `reportToHeaders()` and `receiveReport()` for reporting API.
12+
13+
It works cross-origin, and even access different browser context groups.
14+
15+
Messages are queued, this means one doesn't need to wait for the receiver to
16+
listen, before sending the first message
17+
(but still need to wait for the resolution of the promise returned by `send()`
18+
to ensure the order between `send()`s).
19+
20+
# Executor framework
21+
22+
The message passing API can be used for sending arbitrary javascript to be
23+
evaluated in another page or worker (the "executor").
24+
25+
`executor.html` (as a Document) or `executor.js` (as a Web Worker) are examples
26+
of executors.
27+
Test can send arbitrary javascript to these executors to evaluate in its
28+
execution context.
29+
30+
This is universal and avoids introducing many specific `XXX-helper.html`
31+
resources.
32+
Moreover, tests are easier to read,
33+
because the whole logic of the test can be defined in a single file.
Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Define an universal message passing API. It works cross-origin and across
22
// browsing context groups.
3-
const dispatcher_path =
4-
"/html/cross-origin-embedder-policy/credentialless/resources/dispatcher.py";
3+
// It can also be used to receive reports.
4+
const dispatcher_path = "/common/dispatcher/dispatcher.py";
55
const dispatcher_url = new URL(dispatcher_path, location.href).href;
66

77
// Return a promise, limiting the number of concurrent accesses to a shared
@@ -56,8 +56,10 @@ const send = async function(uuid, message) {
5656
});
5757
}
5858

59-
const receive = async function(uuid) {
60-
while(1) {
59+
const receive = async function(uuid, maybe_timeout) {
60+
const timeout = maybe_timeout || Infinity;
61+
let start = performance.now();
62+
while(performance.now() - start < timeout) {
6163
let data = "not ready";
6264
try {
6365
data = await limiter(async () => {
@@ -73,11 +75,57 @@ const receive = async function(uuid) {
7375

7476
return data;
7577
}
78+
return "timeout";
7679
}
7780

7881
// Returns an URL. When called, the server sends toward the `uuid` queue the
7982
// request headers. Useful for determining if something was requested with
8083
// Cookies.
81-
const showRequestHeaders= function(origin, uuid) {
84+
const showRequestHeaders = function(origin, uuid) {
8285
return origin + dispatcher_path + `?uuid=${uuid}&show-headers`;
8386
}
87+
88+
// Same as above, except for the response is cacheable.
89+
const cacheableShowRequestHeaders = function(origin, uuid) {
90+
return origin + dispatcher_path + `?uuid=${uuid}&cacheable&show-headers`;
91+
}
92+
93+
const receiveReport = async function(uuid, type) {
94+
while(true) {
95+
let reports = await receive(uuid);
96+
if (reports == "timeout")
97+
return "timeout";
98+
reports = JSON.parse(reports);
99+
100+
for(report of reports) {
101+
if (report?.body?.type == type)
102+
return report;
103+
}
104+
}
105+
}
106+
107+
// Build a set of headers to tests the reporting API. This defines a set of
108+
// matching 'Report-To', 'Cross-Origin-Opener-Policy' and
109+
// 'Cross-Origin-Opener-Policy-Report-Only' headers.
110+
const reportToHeaders = function(uuid) {
111+
const report_endpoint_url = dispatcher_path + `?uuid=${uuid}`;
112+
let reportToJSON = {
113+
'group': `${uuid}`,
114+
'max_age': 3600,
115+
'endpoints': [
116+
{'url': report_endpoint_url.toString()},
117+
]
118+
};
119+
reportToJSON = JSON.stringify(reportToJSON)
120+
.replace(/,/g, '\\,')
121+
.replace(/\(/g, '\\\(')
122+
.replace(/\)/g, '\\\)=');
123+
124+
return {
125+
header: `|header(report-to,${reportToJSON})`,
126+
coopSameOriginHeader: `|header(Cross-Origin-Opener-Policy,same-origin%3Breport-to="${uuid}")`,
127+
coopSameOriginAllowPopupsHeader: `|header(Cross-Origin-Opener-Policy,same-origin-allow-popups%3Breport-to="${uuid}")`,
128+
coopReportOnlySameOriginHeader: `|header(Cross-Origin-Opener-Policy-Report-Only,same-origin%3Breport-to="${uuid}")`,
129+
coopReportOnlySameOriginAllowPopupsHeader: `|header(Cross-Origin-Opener-Policy-Report-Only,same-origin-allow-popups%3Breport-to="${uuid}")`,
130+
};
131+
};
Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,13 @@ def main(request, response):
99
response.headers.set(b"Access-Control-Allow-Credentials", b"true")
1010
response.headers.set(b'Access-Control-Allow-Methods', b'OPTIONS, GET, POST')
1111
response.headers.set(b'Access-Control-Allow-Headers', b'Content-Type')
12-
response.headers.set(b'Cache-Control', b'no-cache, no-store, must-revalidate')
1312
response.headers.set(b"Access-Control-Allow-Origin", request.headers.get(b"origin") or '*')
1413

14+
if b"cacheable" in request.GET:
15+
response.headers.set(b"Cache-Control", b"max-age=31536000")
16+
else:
17+
response.headers.set(b'Cache-Control', b'no-cache, no-store, must-revalidate')
18+
1519
# CORS preflight
1620
if request.method == u'OPTIONS':
1721
return b''
@@ -22,7 +26,7 @@ def main(request, response):
2226
# The stash is accessed concurrently by many clients. A lock is used to
2327
# avoid unterleaved read/write from different clients.
2428
with stash.lock:
25-
queue = stash.take(uuid, '/coep-credentialless') or [];
29+
queue = stash.take(uuid, '/common/dispatcher') or [];
2630

2731
# Push into the |uuid| queue, the requested headers.
2832
if b"show-headers" in request.GET:
@@ -45,5 +49,5 @@ def main(request, response):
4549
else:
4650
ret = queue.pop(0)
4751

48-
stash.put(uuid, queue, '/coep-credentialless')
52+
stash.put(uuid, queue, '/common/dispatcher')
4953
return ret;

html/cross-origin-opener-policy/resources/executor.html renamed to common/dispatcher/executor.html

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
const uuid = params.get('uuid');
66

77
let executeOrders = async function() {
8-
while(true)
9-
eval(await receive(uuid));
8+
while(true) {
9+
let task = await receive(uuid);
10+
eval(`(async () => {${task}})()`);
11+
}
1012
};
1113
executeOrders();
1214

html/cross-origin-embedder-policy/anonymous-iframe/cookie.tentative.https.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
<script src="/resources/testharnessreport.js"></script>
33
<script src="/common/get-host-info.sub.js"></script>
44
<script src="/common/utils.js"></script>
5+
<script src="/common/dispatcher/dispatcher.js"></script>
56
<script src="../credentialless/resources/common.js"></script>
6-
<script src="../credentialless/resources/dispatcher.js"></script>
77
<script src="./resources/common.js"></script>
88
<script>
99

html/cross-origin-embedder-policy/anonymous-iframe/local-storage.tentative.https.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
<script src="/resources/testharnessreport.js"></script>
33
<script src="/common/get-host-info.sub.js"></script>
44
<script src="/common/utils.js"></script>
5+
<script src="/common/dispatcher/dispatcher.js"></script>
56
<script src="../credentialless/resources/common.js"></script>
6-
<script src="../credentialless/resources/dispatcher.js"></script>
77
<script src="./resources/common.js"></script>
88
<script>
99

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,3 @@
1-
# Helper files:
2-
3-
- `resources/dispatcher.js` provides `send()` and `receive()`. This is an
4-
universal message passing API. It works cross-origin, and even access
5-
different browser context groups. Messages are queued, this means one doesn't
6-
need to wait for the receiver to listen, before sending the first message.
7-
8-
- `resources/executor.html` is a document. Test can send arbitrary javascript to evaluate
9-
in its execution context. This is universal and avoids introducing many
10-
specific `XXX-helper.html` resources. Moreover, tests are easier to read,
11-
because the whole logic of the test can be defined in a single file.
12-
131
# Related documents:
142
- https://github.com/mikewest/credentiallessness/
153
- https://github.com/w3ctag/design-reviews/issues/582

html/cross-origin-embedder-policy/credentialless/cache-storage.tentative.https.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
<script src=/resources/testharnessreport.js></script>
88
<script src="/common/get-host-info.sub.js"></script>
99
<script src="/common/utils.js"></script>
10+
<script src="/common/dispatcher/dispatcher.js"></script>
1011
<script src="./resources/common.js"></script>
11-
<script src="./resources/dispatcher.js"></script>
1212
<script>
1313

1414
// Fetch a resource and store it into CacheStorage from |storer| context. Then

0 commit comments

Comments
 (0)