Skip to content

Commit 06e3858

Browse files
Guohui Dengmoz-wptsync-bot
Guohui Deng
authored andcommitted
Bug 1941991 [wpt PR 50115] - Expose contentEncoding in PerformanceResourceTiming, a=testonly
Automatic update from web-platform-tests Expose contentEncoding in PerformanceResourceTiming This CL introduce a contentEncoding field to Performance resource timing object. This field is behind a feature flag. PR to resource timing specification: w3c/resource-timing#411 PR to fetch specification: whatwg/fetch#1796 Bug: 327941462 Change-Id: I70cad190fe658fb3dbf8b401ff8393bc1d0782f0 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6098321 Commit-Queue: Guohui Deng <[email protected]> Reviewed-by: Noam Rosenthal <[email protected]> Reviewed-by: Matthew Denton <[email protected]> Reviewed-by: Yoav Weiss (@Shopify) <[email protected]> Cr-Commit-Position: refs/heads/main@{#1407331} -- wpt-commits: 1df2c3e47bcb6379ecf3a07735bd967101d02a5b wpt-pr: 50115
1 parent b366572 commit 06e3858

12 files changed

+215
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<meta charset="utf-8">
6+
<meta name="variant" , content="?pipe=gzip">
7+
<title>contentEncoding in navigation timing</title>
8+
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
9+
<link rel="help" href="http://www.w3.org/TR/navigation-timing/#sec-navigation-timing-interface" />
10+
<script src="/resources/testharness.js"></script>
11+
<script src="/resources/testharnessreport.js"></script>
12+
13+
<script>
14+
async_test(function (t) {
15+
var observer = new PerformanceObserver(
16+
t.step_func(function (entryList) {
17+
assert_equals(entryList.getEntries()[0].contentEncoding, "gzip",
18+
"Expected contentEncoding to be gzip.");
19+
observer.disconnect();
20+
t.done();
21+
})
22+
);
23+
observer.observe({ entryTypes: ["navigation"] });
24+
25+
}, "contentEncoding should be gzip.");
26+
</script>
27+
</head>
28+
29+
<body>
30+
<h1>
31+
Description</h1>
32+
<p>
33+
This test validates that when a html is compressed with gzip, navigation timing reports contentEncoding as gzip</p>
34+
</body>
35+
36+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<meta charset="utf-8">
6+
<title>contentEncoding in resource timing</title>
7+
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
8+
<link rel="help" href="https://www.w3.org/TR/resource-timing-2/#sec-performanceresourcetiming" />
9+
<script src="/common/get-host-info.sub.js"></script>
10+
<script src="/resources/testharness.js"></script>
11+
<script src="/resources/testharnessreport.js"></script>
12+
<script src="resources/entry-invariants.js"></script>
13+
<script src="resources/resource-loaders.js"></script>
14+
<script>
15+
16+
const { ORIGIN, REMOTE_ORIGIN } = get_host_info();
17+
18+
const run_same_origin_test = (path, contentEncoding) => {
19+
const url = new URL(path, ORIGIN);
20+
attribute_test(
21+
fetch, url,
22+
entry => {
23+
assert_equals(entry.contentEncoding, contentEncoding,
24+
`run_same_origin_test failed, unexpected contentEncoding value.`);
25+
});
26+
}
27+
28+
run_same_origin_test("/resource-timing/resources/compressed-data.py?content_encoding=dcb", "dcb");
29+
run_same_origin_test("/resource-timing/resources/compressed-data.py?content_encoding=dcz", "dcz");
30+
run_same_origin_test("/resource-timing/resources/gzip_xml.py", "gzip");
31+
run_same_origin_test("/resource-timing/resources/foo.text.br", "br");
32+
run_same_origin_test("/resource-timing/resources/foo.text.gz", "gzip");
33+
run_same_origin_test("/resource-timing/resources/foo.text.zst", "zstd");
34+
run_same_origin_test("/resource-timing/resources/compressed-js.py?content_encoding=deflate", "deflate");
35+
run_same_origin_test("/resource-timing/resources/compressed-js.py?content_encoding=gzip", "gzip");
36+
run_same_origin_test("/resource-timing/resources/compressed-js.py?content_encoding=identity", "identity");
37+
// Unrecognized content encoding value should be transformed to "unknown".
38+
run_same_origin_test("/resource-timing/resources/compressed-js.py?content_encoding=unrecognizedname", "unknown");
39+
40+
41+
const run_cross_origin_test = (path) => {
42+
const url = new URL(path, REMOTE_ORIGIN);
43+
attribute_test(
44+
load.xhr_async, url,
45+
entry => {
46+
assert_equals(entry.contentEncoding, "",
47+
`run_cross_origin_test failed, contentEncoding should be empty.`);
48+
});
49+
}
50+
51+
run_cross_origin_test("/resource-timing/resources/compressed-data.py?content_encoding=dcb");
52+
run_cross_origin_test("/resource-timing/resources/gzip_xml.py");
53+
run_cross_origin_test("/resource-timing/resources/compressed-data.py?content_encoding=dcz");
54+
run_cross_origin_test("/resource-timing/resources/foo.text.br");
55+
run_cross_origin_test("/resource-timing/resources/foo.text.gz");
56+
run_cross_origin_test("/resource-timing/resources/foo.text.zst");
57+
run_cross_origin_test("/resource-timing/resources/compressed-js.py?content_encoding=deflate");
58+
run_cross_origin_test("/resource-timing/resources/compressed-js.py?content_encoding=gzip");
59+
60+
const run_cross_origin_allowed_test = (path, contentEncoding) => {
61+
const url = new URL(path, REMOTE_ORIGIN);
62+
url.searchParams.set("allow_origin", ORIGIN);
63+
attribute_test(
64+
load.xhr_async, url,
65+
entry => {
66+
assert_equals(entry.contentEncoding, contentEncoding,
67+
`run_cross_origin_allowed_test failed, unexpected contentEncoding value.`);
68+
});
69+
}
70+
71+
run_cross_origin_allowed_test("/resource-timing/resources/compressed-data.py?content_encoding=dcb", "dcb");
72+
run_cross_origin_allowed_test("/resource-timing/resources/compressed-data.py?content_encoding=dcz", "dcz");
73+
run_cross_origin_allowed_test("/resource-timing/resources/gzip_xml.py", "gzip");
74+
run_cross_origin_allowed_test("/resource-timing/resources/compressed-js.py?content_encoding=deflate", "deflate");
75+
run_cross_origin_allowed_test("/resource-timing/resources/compressed-js.py?content_encoding=gzip", "gzip");
76+
77+
// Content-Encoding for iframes is empty when cross origin redirects are present.
78+
const multiRedirect = new URL(`${ORIGIN}/resource-timing/resources/multi_redirect.py`);
79+
multiRedirect.searchParams.append("page_origin", ORIGIN);
80+
multiRedirect.searchParams.append("cross_origin", REMOTE_ORIGIN);
81+
multiRedirect.searchParams.append("final_resource", "/resource-timing/resources/compressed-js.py?content_encoding=gzip");
82+
attribute_test(load.iframe, multiRedirect, (entry) => {
83+
assert_equals(entry.contentEncoding, "",
84+
`content-encoding should be empty for iframes having cross origin redirects`);
85+
});
86+
87+
88+
// Content-Encoding for iframes is exposed for same origin redirects.
89+
const redirectCORS = new URL(`${ORIGIN}/resource-timing/resources/redirect-cors.py`);
90+
const dest = `${ORIGIN}/resource-timing/resources/compressed-js.py?content_encoding=gzip`;
91+
redirectCORS.searchParams.append("location", dest)
92+
attribute_test(load.iframe, redirectCORS, (entry) => {
93+
assert_equals(entry.contentEncoding, "gzip",
94+
`content-encoding should be exposed for iframes having only same origin redirects`);
95+
});
96+
97+
</script>
98+
</head>
99+
100+
<body>
101+
<h1>
102+
Description</h1>
103+
<p>
104+
This test validates contentEncoding in resource timing.</p>
105+
</body>
106+
107+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
def main(request, response):
2+
response.headers.set(b"Content-Type", b"text/plain")
3+
4+
# `dcb_data` and `dcz_data` are generated using the following commands:
5+
#
6+
# $ echo "This is a test dictionary." > /tmp/dict
7+
# $ echo -n "This is compressed test data using a test dictionary" \
8+
# > /tmp/data
9+
#
10+
# $ echo -en '\xffDCB' > /tmp/out.dcb
11+
# $ openssl dgst -sha256 -binary /tmp/dict >> /tmp/out.dcb
12+
# $ brotli --stdout -D /tmp/dict /tmp/data >> /tmp/out.dcb
13+
# $ xxd -p /tmp/out.dcb | tr -d '\n' | sed 's/\(..\)/\\x\1/g'
14+
dcb_data = b"\xff\x44\x43\x42\x53\x96\x9b\xcf\x5e\x96\x0e\x0e\xdb\xf0\xa4\xbd\xde\x6b\x0b\x3e\x93\x81\xe1\x56\xde\x7f\x5b\x91\xce\x83\x91\x62\x42\x70\xf4\x16\xa1\x98\x01\x80\x62\xa4\x4c\x1d\xdf\x12\x84\x8c\xae\xc2\xca\x60\x22\x07\x6e\x81\x05\x14\xc9\xb7\xc3\x44\x8e\xbc\x16\xe0\x15\x0e\xec\xc1\xee\x34\x33\x3e\x0d"
15+
# $ echo -en '\x5e\x2a\x4d\x18\x20\x00\x00\x00' > /tmp/out.dcz
16+
# $ openssl dgst -sha256 -binary /tmp/dict >> /tmp/out.dcz
17+
# $ zstd -D /tmp/dict -f -o /tmp/tmp.zstd /tmp/data
18+
# $ cat /tmp/tmp.zstd >> /tmp/out.dcz
19+
# $ xxd -p /tmp/out.dcz | tr -d '\n' | sed 's/\(..\)/\\x\1/g'
20+
dcz_data = b"\x5e\x2a\x4d\x18\x20\x00\x00\x00\x53\x96\x9b\xcf\x5e\x96\x0e\x0e\xdb\xf0\xa4\xbd\xde\x6b\x0b\x3e\x93\x81\xe1\x56\xde\x7f\x5b\x91\xce\x83\x91\x62\x42\x70\xf4\x16\x28\xb5\x2f\xfd\x24\x34\xf5\x00\x00\x98\x63\x6f\x6d\x70\x72\x65\x73\x73\x65\x64\x61\x74\x61\x20\x75\x73\x69\x6e\x67\x03\x00\x59\xf9\x73\x54\x46\x27\x26\x10\x9e\x99\xf2\xbc"
21+
22+
if b'content_encoding' in request.GET:
23+
content_encoding = request.GET.first(b"content_encoding")
24+
response.headers.set(b"Content-Encoding", content_encoding)
25+
if content_encoding == b"dcb":
26+
# Send the pre compressed file
27+
response.content = dcb_data
28+
if content_encoding == b"dcz":
29+
# Send the pre compressed file
30+
response.content = dcz_data
31+
32+
if b'allow_origin' in request.GET:
33+
response.headers.set(b'access-control-allow-origin', request.GET.first(b'allow_origin'))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import os.path
2+
import zlib
3+
import gzip
4+
5+
def read(file):
6+
path = os.path.join(os.path.dirname(__file__), file)
7+
return open(path, u"rb").read()
8+
9+
def main(request, response):
10+
response.headers.set(b"Content-Type", b"text/javascript")
11+
12+
if b'allow_origin' in request.GET:
13+
response.headers.set(
14+
b'access-control-allow-origin',
15+
request.GET.first(b'allow_origin'))
16+
17+
if b'content_encoding' in request.GET:
18+
content_encoding = request.GET.first(b"content_encoding")
19+
response.headers.set(b"Content-Encoding", content_encoding)
20+
if content_encoding == b"deflate":
21+
response.content = zlib.compress(read(u"./dummy.js"))
22+
if content_encoding == b"gzip":
23+
response.content = gzip.compress(read(u"./dummy.js"))
24+
if content_encoding == b"identity":
25+
# Uncompressed
26+
response.content = read(u"./dummy.js")
27+
if content_encoding == b"unrecognizedname":
28+
# Just return something
29+
response.content = gzip.compress(read(u"./dummy.js"))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// A dummy js file to be compressed and transferred.
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Content-type: text/plain
2+
Content-Encoding: br
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Content-type: text/plain
2+
Content-Encoding: gzip
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Content-type: text/plain
2+
Content-Encoding: zstd

testing/web-platform/tests/resource-timing/resources/gzip_xml.py

+3
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,7 @@ def main(request, response):
2020
(b"Content-Encoding", b"gzip"),
2121
(b"Content-Length", len(output))]
2222

23+
if b'allow_origin' in request.GET:
24+
headers.append((b'access-control-allow-origin', request.GET.first(b'allow_origin')))
25+
2326
return headers, output

0 commit comments

Comments
 (0)