-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Resource Timing] Align transferSize to spec
Aligning transferSize to the spec means that response header sizes will no longer be directly exposed, even for same origin resources or resources with Timing-Allow-Origin headers. This is because it seems unsafe[1] to expose header sizes directly. It also means that redirect chains won't count towards the size exposed in `transferSize`. While we could specify and accumulate redirect body sizes, it seems like we'd be better off reporting redirects directly[2] in the future, in case it becomes a priority. PSA: https://groups.google.com/a/chromium.org/g/blink-dev/c/Sny4FO5_y5E [1] w3c/resource-timing#238 [2] https://w3c.github.io/web-performance/meetings/2021/2021-03-18/index.html Bug: 1185801 Change-Id: Iba071c6bb74c5522e3f1ed2586f082f11a7a68a0
- Loading branch information
1 parent
2474396
commit 717b855
Showing
9 changed files
with
229 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
def main(request, response): | ||
revalidation = 'Cache-Control' in request.headers | ||
content = request.GET.first(b'content') | ||
response.headers.set(b'Cache-Control', b'max-age=60') | ||
response.headers.set(b'ETag', b'assdfsdfe') | ||
if revalidation: | ||
response.status = (304, b'NotModified') | ||
else: | ||
response.status = (200, b'OK'); | ||
response.write_status_headers() | ||
response.writer.write(content); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
def main(request, response): | ||
location = request.GET.first(b"location") | ||
response.status = 302 | ||
response.headers.set(b"Location", location) | ||
|
||
if b"allow_origin" in request.GET: | ||
response.headers.set(b"Access-Control-Allow-Origin", request.GET.first(b"allow_origin")) | ||
|
||
if b"timing_allow_origin" in request.GET: | ||
response.headers.set(b"Timing-Allow-Origin", request.GET.first(b"timing_allow_origin")) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// Header size is a fixed constant. | ||
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-transfersize | ||
const headerSize = 300; | ||
|
||
const cacheBustUrl = url => { | ||
return url + '&unique=' + Math.random().toString().substring(2); | ||
} | ||
|
||
const checkSizeFields = (entry, bodySize, transferSize) => { | ||
assert_equals(entry.decodedBodySize, bodySize, | ||
'decodedBodySize'); | ||
assert_equals(entry.encodedBodySize, bodySize, | ||
'encodedBodySize'); | ||
assert_equals(entry.transferSize, transferSize, | ||
'transferSize'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// META: global=window,worker | ||
// META: script=/resource-timing/resources/sizes-helper.js | ||
// META: script=/resource-timing/resources/resource-loaders.js | ||
|
||
let url = new URL( | ||
'/resource-timing/resources/cacheable-and-validated.py' + | ||
'?content=loremipsumblablabla', | ||
location.href).href; | ||
const bodySize = 19; | ||
|
||
const accumulateEntry = () => { | ||
return new Promise(resolve => { | ||
const po = new PerformanceObserver(list => { | ||
resolve(list); | ||
}); | ||
po.observe({type: "resource", buffered: true}); | ||
}); | ||
}; | ||
|
||
const checkResourceSizes = list => { | ||
const entries = list.getEntriesByName(url); | ||
assert_equals(entries.length, 3, 'Wrong number of entries'); | ||
let seenCount = 0; | ||
for (let entry of entries) { | ||
if (seenCount === 0) { | ||
// 200 response | ||
checkSizeFields(entry, bodySize, bodySize + headerSize); | ||
} else if (seenCount === 1) { | ||
// from cache | ||
checkSizeFields(entry, bodySize, 0); | ||
} else if (seenCount === 2) { | ||
// 304 response | ||
checkSizeFields(entry, bodySize, headerSize); | ||
} else { | ||
assert_unreached('Too many matching entries'); | ||
} | ||
++seenCount; | ||
} | ||
}; | ||
|
||
promise_test(() => { | ||
// Use a different URL every time so that the cache behaviour does not | ||
// depend on execution order. | ||
url = load.cache_bust(url); | ||
const eatBody = response => response.arrayBuffer(); | ||
const mustRevalidate = {headers: {'Cache-Control': 'max-age=0'}}; | ||
return fetch(url) | ||
.then(eatBody) | ||
.then(() => fetch(url)) | ||
.then(eatBody) | ||
.then(() => fetch(url, mustRevalidate)) | ||
.then(eatBody) | ||
.then(accumulateEntry) | ||
.then(checkResourceSizes); | ||
}, 'PerformanceResourceTiming sizes caching test'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
<!DOCTYPE html> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<script src="/common/get-host-info.sub.js"></script> | ||
<script src="resources/sizes-helper.js"></script> | ||
<script src="resources/resource-loaders.js"></script> | ||
<script src="resources/entry-invariants.js"></script> | ||
<script> | ||
// Redirects for fetch() always apply CORS rules, whereas normal resources | ||
// don't, so this test covers extra code paths beyond those covered by | ||
// resource-timing-sizes-redirect.html. | ||
|
||
const baseUrl = new URL('/resource-timing/resources/TAOResponse.py?tao=wildcard&img=true', location.href).href; | ||
|
||
const expectedSize = 1010; | ||
|
||
const hostInfo = get_host_info(); | ||
|
||
const redirectUrl = (redirectSourceOrigin, targetUrl) => { | ||
return redirectSourceOrigin + | ||
'/resource-timing/resources/redirect-cors.py?timing_allow_origin=*' + | ||
'&location=' + encodeURIComponent(targetUrl); | ||
}; | ||
|
||
const verify_entry = entry => { | ||
assert_equals(entry.transferSize, expectedSize + headerSize); | ||
}; | ||
|
||
attribute_test(load.image, baseUrl, | ||
verify_entry, | ||
"PerformanceResourceTiming sizes redirect image - direct URL"); | ||
|
||
attribute_test(load.image, | ||
redirectUrl(hostInfo.HTTP_ORIGIN, baseUrl), | ||
verify_entry, | ||
"PerformanceResourceTiming sizes redirect image - same origin redirect"); | ||
|
||
attribute_test(load.image, | ||
redirectUrl(hostInfo.HTTP_REMOTE_ORIGIN, baseUrl), | ||
verify_entry, | ||
"PerformanceResourceTiming sizes redirect image - cross origin redirect"); | ||
|
||
attribute_test(load.image, | ||
redirectUrl(hostInfo.HTTP_REMOTE_ORIGIN, | ||
redirectUrl(hostInfo.HTTP_ORIGIN, baseUrl)), | ||
verify_entry, | ||
"PerformanceResourceTiming sizes redirect image - cross origin to same origin redirect"); | ||
|
||
attribute_test(load.image, | ||
redirectUrl(hostInfo.HTTP_ORIGIN, | ||
redirectUrl(hostInfo.HTTP_REMOTE_ORIGIN, | ||
redirectUrl(hostInfo.HTTP_ORIGIN, | ||
baseUrl))), | ||
verify_entry, | ||
"PerformanceResourceTiming sizes redirect image - same origin to remote " + | ||
"origin to same origin redirect"); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// META: global=window,worker | ||
// META: script=/common/get-host-info.sub.js | ||
// META: script=/resource-timing/resources/sizes-helper.js | ||
|
||
const baseUrl = | ||
new URL('/resource-timing/resources/TAOResponse.py?tao=wildcard', location.href).href; | ||
const expectedSize = 4; | ||
|
||
const hostInfo = get_host_info(); | ||
performance.clearResourceTimings(); | ||
|
||
const accumulateEntry = () => { | ||
return new Promise(resolve => { | ||
const po = new PerformanceObserver(list => { | ||
resolve(list); | ||
}); | ||
po.observe({type: "resource", buffered: true}); | ||
}); | ||
}; | ||
|
||
const checkResourceSizes = () => { | ||
const entries = performance.getEntriesByType('resource'); | ||
for (let entry of entries) { | ||
checkSizeFields(entry, expectedSize, expectedSize + headerSize); | ||
} | ||
} | ||
|
||
const redirectUrl = (redirectSourceOrigin, allowOrigin, targetUrl) => { | ||
return redirectSourceOrigin + | ||
'/resource-timing/resources/redirect-cors.py?allow_origin=' + | ||
encodeURIComponent(allowOrigin) + | ||
'&timing_allow_origin=*' + | ||
'&location=' + encodeURIComponent(targetUrl); | ||
} | ||
|
||
promise_test(() => { | ||
// Use a different URL every time so that the cache behaviour does not | ||
// depend on execution order. | ||
const directUrl = cacheBustUrl(baseUrl); | ||
const sameOriginRedirect = redirectUrl(hostInfo.ORIGIN, '*', directUrl); | ||
const crossOriginRedirect = redirectUrl(hostInfo.REMOTE_ORIGIN, | ||
hostInfo.ORIGIN, directUrl); | ||
const mixedRedirect = redirectUrl(hostInfo.REMOTE_ORIGIN, | ||
hostInfo.ORIGIN, sameOriginRedirect); | ||
const complexRedirect = redirectUrl(hostInfo.ORIGIN, | ||
hostInfo.REMOTE_ORIGIN, mixedRedirect); | ||
let eatBody = response => response.arrayBuffer(); | ||
return fetch(directUrl) | ||
.then(eatBody) | ||
.then(() => fetch(sameOriginRedirect)) | ||
.then(eatBody) | ||
.then(() => fetch(crossOriginRedirect)) | ||
.then(eatBody) | ||
.then(() => fetch(mixedRedirect)) | ||
.then(eatBody) | ||
.then(() => fetch(complexRedirect)) | ||
.then(eatBody) | ||
.then(accumulateEntry) | ||
.then(checkResourceSizes); | ||
}, 'PerformanceResourceTiming sizes Fetch with redirect test'); | ||
|
||
done(); |