diff --git a/common/refresh.py b/common/refresh.py new file mode 100644 index 00000000000000..0d309900d473c6 --- /dev/null +++ b/common/refresh.py @@ -0,0 +1,11 @@ +def main(request, response): + """ + Respond with a blank HTML document and a `Refresh` header which describes + an immediate redirect to the URL specified by the requests `location` query + string parameter + """ + headers = [ + (b'Content-Type', b'text/html'), + (b'Refresh', b'0; URL=' + request.GET.first(b'location')) + ] + return (200, headers, b'') diff --git a/fetch/api/resources/redirect.py b/fetch/api/resources/redirect.py index 2ff8b78f09539b..d52ab5f3eee757 100644 --- a/fetch/api/resources/redirect.py +++ b/fetch/api/resources/redirect.py @@ -35,6 +35,8 @@ def main(request, response): if b"redirect_status" in request.GET: status = int(request.GET[b'redirect_status']) + elif b"redirect_status" in request.POST: + status = int(request.POST[b'redirect_status']) stashed_data[b'count'] += 1 diff --git a/fetch/metadata/download.https.sub.html b/fetch/metadata/download.https.sub.html deleted file mode 100644 index a95d9d65f00580..00000000000000 --- a/fetch/metadata/download.https.sub.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - diff --git a/fetch/metadata/favicon.https.sub.html b/fetch/metadata/favicon.https.sub.html deleted file mode 100644 index 50ea5b27415826..00000000000000 --- a/fetch/metadata/favicon.https.sub.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/fetch/metadata/fetch-via-serviceworker--fallback.https.sub.html b/fetch/metadata/fetch-via-serviceworker--fallback.https.sub.html deleted file mode 100644 index 9f494461372d3a..00000000000000 --- a/fetch/metadata/fetch-via-serviceworker--fallback.https.sub.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - diff --git a/fetch/metadata/fetch-via-serviceworker--respondWith.https.sub.html b/fetch/metadata/fetch-via-serviceworker--respondWith.https.sub.html deleted file mode 100644 index 03d5fd1cc31b6f..00000000000000 --- a/fetch/metadata/fetch-via-serviceworker--respondWith.https.sub.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - diff --git a/fetch/metadata/fetch.sub.html b/fetch/metadata/fetch.sub.html deleted file mode 100644 index 1659a9fb6bf274..00000000000000 --- a/fetch/metadata/fetch.sub.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - diff --git a/fetch/metadata/font.https.sub.html b/fetch/metadata/font.https.sub.html deleted file mode 100644 index 2c705085d6a30c..00000000000000 --- a/fetch/metadata/font.https.sub.html +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - -
1
-
2
-
3
- - - - - - - - - - - diff --git a/fetch/metadata/form.https.sub.html b/fetch/metadata/form.https.sub.html deleted file mode 100644 index 2e6332c747f554..00000000000000 --- a/fetch/metadata/form.https.sub.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - diff --git a/fetch/metadata/generated/appcache-manifest.https.sub.html b/fetch/metadata/generated/appcache-manifest.https.sub.html new file mode 100644 index 00000000000000..cf322fd34bc9ab --- /dev/null +++ b/fetch/metadata/generated/appcache-manifest.https.sub.html @@ -0,0 +1,341 @@ + + + + + HTTP headers on request for Appcache manifest + + + + + + + diff --git a/fetch/metadata/generated/audioworklet.https.sub.html b/fetch/metadata/generated/audioworklet.https.sub.html new file mode 100644 index 00000000000000..64fb7607e26a17 --- /dev/null +++ b/fetch/metadata/generated/audioworklet.https.sub.html @@ -0,0 +1,271 @@ + + + + + HTTP headers on request for AudioWorklet module + + + + + + + + + diff --git a/fetch/metadata/generated/css-font-face.https.sub.tentative.html b/fetch/metadata/generated/css-font-face.https.sub.tentative.html new file mode 100644 index 00000000000000..332effeb1f80a5 --- /dev/null +++ b/fetch/metadata/generated/css-font-face.https.sub.tentative.html @@ -0,0 +1,230 @@ + + + + + HTTP headers on request for CSS font-face + + + + + + + diff --git a/fetch/metadata/generated/css-font-face.sub.tentative.html b/fetch/metadata/generated/css-font-face.sub.tentative.html new file mode 100644 index 00000000000000..8a0b90cee103db --- /dev/null +++ b/fetch/metadata/generated/css-font-face.sub.tentative.html @@ -0,0 +1,196 @@ + + + + + HTTP headers on request for CSS font-face + + + + + + + diff --git a/fetch/metadata/generated/css-images.https.sub.tentative.html b/fetch/metadata/generated/css-images.https.sub.tentative.html new file mode 100644 index 00000000000000..3fa240192894e0 --- /dev/null +++ b/fetch/metadata/generated/css-images.https.sub.tentative.html @@ -0,0 +1,1384 @@ + + + + + + HTTP headers on request for CSS image-accepting properties + + + + + + + diff --git a/fetch/metadata/generated/css-images.sub.tentative.html b/fetch/metadata/generated/css-images.sub.tentative.html new file mode 100644 index 00000000000000..f1ef27cf08730e --- /dev/null +++ b/fetch/metadata/generated/css-images.sub.tentative.html @@ -0,0 +1,1099 @@ + + + + + + HTTP headers on request for CSS image-accepting properties + + + + + + + diff --git a/fetch/metadata/generated/element-a.https.sub.html b/fetch/metadata/generated/element-a.https.sub.html new file mode 100644 index 00000000000000..dffd36c73ee373 --- /dev/null +++ b/fetch/metadata/generated/element-a.https.sub.html @@ -0,0 +1,482 @@ + + + + + + HTTP headers on request for HTML "a" element navigation + + + + + + + + + diff --git a/fetch/metadata/generated/element-a.sub.html b/fetch/metadata/generated/element-a.sub.html new file mode 100644 index 00000000000000..0661de3c871bb4 --- /dev/null +++ b/fetch/metadata/generated/element-a.sub.html @@ -0,0 +1,342 @@ + + + + + + HTTP headers on request for HTML "a" element navigation + + + + + + + diff --git a/fetch/metadata/generated/element-area.https.sub.html b/fetch/metadata/generated/element-area.https.sub.html new file mode 100644 index 00000000000000..be3f5f9b621176 --- /dev/null +++ b/fetch/metadata/generated/element-area.https.sub.html @@ -0,0 +1,482 @@ + + + + + + HTTP headers on request for HTML "area" element navigation + + + + + + + + + diff --git a/fetch/metadata/generated/element-area.sub.html b/fetch/metadata/generated/element-area.sub.html new file mode 100644 index 00000000000000..5f5c338324f001 --- /dev/null +++ b/fetch/metadata/generated/element-area.sub.html @@ -0,0 +1,342 @@ + + + + + + HTTP headers on request for HTML "area" element navigation + + + + + + + diff --git a/fetch/metadata/generated/element-audio.https.sub.html b/fetch/metadata/generated/element-audio.https.sub.html new file mode 100644 index 00000000000000..a9d951233e296f --- /dev/null +++ b/fetch/metadata/generated/element-audio.https.sub.html @@ -0,0 +1,325 @@ + + + + + HTTP headers on request for HTML "audio" element source + + + + + + + diff --git a/fetch/metadata/generated/element-audio.sub.html b/fetch/metadata/generated/element-audio.sub.html new file mode 100644 index 00000000000000..2b62632ac2eb8c --- /dev/null +++ b/fetch/metadata/generated/element-audio.sub.html @@ -0,0 +1,229 @@ + + + + + HTTP headers on request for HTML "audio" element source + + + + + + + diff --git a/fetch/metadata/generated/element-embed.https.sub.html b/fetch/metadata/generated/element-embed.https.sub.html new file mode 100644 index 00000000000000..819bed888ee4cb --- /dev/null +++ b/fetch/metadata/generated/element-embed.https.sub.html @@ -0,0 +1,224 @@ + + + + + HTTP headers on request for HTML "embed" element source + + + + + + + diff --git a/fetch/metadata/generated/element-embed.sub.html b/fetch/metadata/generated/element-embed.sub.html new file mode 100644 index 00000000000000..b6e14a55e4a549 --- /dev/null +++ b/fetch/metadata/generated/element-embed.sub.html @@ -0,0 +1,190 @@ + + + + + HTTP headers on request for HTML "embed" element source + + + + + + + diff --git a/fetch/metadata/generated/element-frame.https.sub.html b/fetch/metadata/generated/element-frame.https.sub.html new file mode 100644 index 00000000000000..17504ff5635c4b --- /dev/null +++ b/fetch/metadata/generated/element-frame.https.sub.html @@ -0,0 +1,309 @@ + + + + + HTTP headers on request for HTML "frame" element source + + + + + + + + + diff --git a/fetch/metadata/generated/element-frame.sub.html b/fetch/metadata/generated/element-frame.sub.html new file mode 100644 index 00000000000000..2d9a7ec97d7808 --- /dev/null +++ b/fetch/metadata/generated/element-frame.sub.html @@ -0,0 +1,250 @@ + + + + + HTTP headers on request for HTML "frame" element source + + + + + + + diff --git a/fetch/metadata/generated/element-iframe.https.sub.html b/fetch/metadata/generated/element-iframe.https.sub.html new file mode 100644 index 00000000000000..fba1c8b9e02f19 --- /dev/null +++ b/fetch/metadata/generated/element-iframe.https.sub.html @@ -0,0 +1,309 @@ + + + + + HTTP headers on request for HTML "frame" element source + + + + + + + + + diff --git a/fetch/metadata/generated/element-iframe.sub.html b/fetch/metadata/generated/element-iframe.sub.html new file mode 100644 index 00000000000000..6f71cc0d254737 --- /dev/null +++ b/fetch/metadata/generated/element-iframe.sub.html @@ -0,0 +1,250 @@ + + + + + HTTP headers on request for HTML "frame" element source + + + + + + + diff --git a/fetch/metadata/generated/element-img-environment-change.https.sub.html b/fetch/metadata/generated/element-img-environment-change.https.sub.html new file mode 100644 index 00000000000000..a19aa117c4f46e --- /dev/null +++ b/fetch/metadata/generated/element-img-environment-change.https.sub.html @@ -0,0 +1,357 @@ + + + + + HTTP headers on image request triggered by change to environment + + + + + + + diff --git a/fetch/metadata/generated/element-img-environment-change.sub.html b/fetch/metadata/generated/element-img-environment-change.sub.html new file mode 100644 index 00000000000000..96658726ba0c91 --- /dev/null +++ b/fetch/metadata/generated/element-img-environment-change.sub.html @@ -0,0 +1,270 @@ + + + + + HTTP headers on image request triggered by change to environment + + + + + + + diff --git a/fetch/metadata/generated/element-img.https.sub.html b/fetch/metadata/generated/element-img.https.sub.html new file mode 100644 index 00000000000000..51d6e082b0e336 --- /dev/null +++ b/fetch/metadata/generated/element-img.https.sub.html @@ -0,0 +1,645 @@ + + + + + HTTP headers on request for HTML "img" element source + + + + + + + diff --git a/fetch/metadata/generated/element-img.sub.html b/fetch/metadata/generated/element-img.sub.html new file mode 100644 index 00000000000000..5a4b152c5525b3 --- /dev/null +++ b/fetch/metadata/generated/element-img.sub.html @@ -0,0 +1,456 @@ + + + + + HTTP headers on request for HTML "img" element source + + + + + + + diff --git a/fetch/metadata/generated/element-input-image.https.sub.html b/fetch/metadata/generated/element-input-image.https.sub.html new file mode 100644 index 00000000000000..7fa674043e2517 --- /dev/null +++ b/fetch/metadata/generated/element-input-image.https.sub.html @@ -0,0 +1,229 @@ + + + + + HTTP headers on request for HTML "input" element with type="button" + + + + + + + diff --git a/fetch/metadata/generated/element-input-image.sub.html b/fetch/metadata/generated/element-input-image.sub.html new file mode 100644 index 00000000000000..fb2a146b199dba --- /dev/null +++ b/fetch/metadata/generated/element-input-image.sub.html @@ -0,0 +1,184 @@ + + + + + HTTP headers on request for HTML "input" element with type="button" + + + + + + + diff --git a/fetch/metadata/generated/element-link-icon.https.sub.html b/fetch/metadata/generated/element-link-icon.https.sub.html new file mode 100644 index 00000000000000..b2449607553e41 --- /dev/null +++ b/fetch/metadata/generated/element-link-icon.https.sub.html @@ -0,0 +1,371 @@ + + + + + + HTTP headers on request for HTML "link" element with rel="icon" + + + + + + + diff --git a/fetch/metadata/generated/element-link-icon.sub.html b/fetch/metadata/generated/element-link-icon.sub.html new file mode 100644 index 00000000000000..e9226c190a5089 --- /dev/null +++ b/fetch/metadata/generated/element-link-icon.sub.html @@ -0,0 +1,279 @@ + + + + + + HTTP headers on request for HTML "link" element with rel="icon" + + + + + + + diff --git a/fetch/metadata/generated/element-link-prefetch.https.optional.sub.html b/fetch/metadata/generated/element-link-prefetch.https.optional.sub.html new file mode 100644 index 00000000000000..bdd684a2679968 --- /dev/null +++ b/fetch/metadata/generated/element-link-prefetch.https.optional.sub.html @@ -0,0 +1,559 @@ + + + + + + HTTP headers on request for HTML "link" element with rel="prefetch" + + + + + + + + diff --git a/fetch/metadata/generated/element-link-prefetch.optional.sub.html b/fetch/metadata/generated/element-link-prefetch.optional.sub.html new file mode 100644 index 00000000000000..c2244883cc9077 --- /dev/null +++ b/fetch/metadata/generated/element-link-prefetch.optional.sub.html @@ -0,0 +1,275 @@ + + + + + + HTTP headers on request for HTML "link" element with rel="prefetch" + + + + + + + + diff --git a/fetch/metadata/generated/element-meta-refresh.https.optional.sub.html b/fetch/metadata/generated/element-meta-refresh.https.optional.sub.html new file mode 100644 index 00000000000000..3a1a8eb49af62a --- /dev/null +++ b/fetch/metadata/generated/element-meta-refresh.https.optional.sub.html @@ -0,0 +1,276 @@ + + + + + HTTP headers on request for HTML "meta" element with http-equiv="refresh" + + + + + + + diff --git a/fetch/metadata/generated/element-meta-refresh.optional.sub.html b/fetch/metadata/generated/element-meta-refresh.optional.sub.html new file mode 100644 index 00000000000000..df3e92e2c8fdeb --- /dev/null +++ b/fetch/metadata/generated/element-meta-refresh.optional.sub.html @@ -0,0 +1,225 @@ + + + + + HTTP headers on request for HTML "meta" element with http-equiv="refresh" + + + + + + + diff --git a/fetch/metadata/generated/element-picture.https.sub.html b/fetch/metadata/generated/element-picture.https.sub.html new file mode 100644 index 00000000000000..ba6636a019a304 --- /dev/null +++ b/fetch/metadata/generated/element-picture.https.sub.html @@ -0,0 +1,997 @@ + + + + + HTTP headers on request for HTML "picture" element source + + + + + + + + diff --git a/fetch/metadata/generated/element-picture.sub.html b/fetch/metadata/generated/element-picture.sub.html new file mode 100644 index 00000000000000..64f851c682b466 --- /dev/null +++ b/fetch/metadata/generated/element-picture.sub.html @@ -0,0 +1,721 @@ + + + + + HTTP headers on request for HTML "picture" element source + + + + + + + + diff --git a/fetch/metadata/generated/element-script.https.sub.html b/fetch/metadata/generated/element-script.https.sub.html new file mode 100644 index 00000000000000..dcdcba2792d5c3 --- /dev/null +++ b/fetch/metadata/generated/element-script.https.sub.html @@ -0,0 +1,593 @@ + + + + + HTTP headers on request for HTML "script" element source + + + + + + diff --git a/fetch/metadata/generated/element-script.sub.html b/fetch/metadata/generated/element-script.sub.html new file mode 100644 index 00000000000000..a2526698fbdaa4 --- /dev/null +++ b/fetch/metadata/generated/element-script.sub.html @@ -0,0 +1,488 @@ + + + + + HTTP headers on request for HTML "script" element source + + + + + + diff --git a/fetch/metadata/generated/element-video-poster.https.sub.html b/fetch/metadata/generated/element-video-poster.https.sub.html new file mode 100644 index 00000000000000..5805b46bd0cd67 --- /dev/null +++ b/fetch/metadata/generated/element-video-poster.https.sub.html @@ -0,0 +1,243 @@ + + + + + HTTP headers on request for HTML "video" element "poster" + + + + + + + diff --git a/fetch/metadata/generated/element-video-poster.sub.html b/fetch/metadata/generated/element-video-poster.sub.html new file mode 100644 index 00000000000000..e6cc5ee7e0695d --- /dev/null +++ b/fetch/metadata/generated/element-video-poster.sub.html @@ -0,0 +1,198 @@ + + + + + HTTP headers on request for HTML "video" element "poster" + + + + + + + diff --git a/fetch/metadata/generated/element-video.https.sub.html b/fetch/metadata/generated/element-video.https.sub.html new file mode 100644 index 00000000000000..971360dceea4a0 --- /dev/null +++ b/fetch/metadata/generated/element-video.https.sub.html @@ -0,0 +1,325 @@ + + + + + HTTP headers on request for HTML "video" element source + + + + + + + diff --git a/fetch/metadata/generated/element-video.sub.html b/fetch/metadata/generated/element-video.sub.html new file mode 100644 index 00000000000000..9707413ab68b17 --- /dev/null +++ b/fetch/metadata/generated/element-video.sub.html @@ -0,0 +1,229 @@ + + + + + HTTP headers on request for HTML "video" element source + + + + + + + diff --git a/fetch/metadata/generated/fetch-via-serviceworker.https.sub.html b/fetch/metadata/generated/fetch-via-serviceworker.https.sub.html new file mode 100644 index 00000000000000..1fd67e912d6326 --- /dev/null +++ b/fetch/metadata/generated/fetch-via-serviceworker.https.sub.html @@ -0,0 +1,683 @@ + + + + + HTTP headers on request using the "fetch" API and passing through a Serive Worker + + + + + + + + + diff --git a/fetch/metadata/generated/fetch.https.sub.html b/fetch/metadata/generated/fetch.https.sub.html new file mode 100644 index 00000000000000..dde1daede4ec3c --- /dev/null +++ b/fetch/metadata/generated/fetch.https.sub.html @@ -0,0 +1,302 @@ + + + + + HTTP headers on request using the "fetch" API + + + + + + + diff --git a/fetch/metadata/generated/fetch.sub.html b/fetch/metadata/generated/fetch.sub.html new file mode 100644 index 00000000000000..d28ea9bb9004f2 --- /dev/null +++ b/fetch/metadata/generated/fetch.sub.html @@ -0,0 +1,220 @@ + + + + + HTTP headers on request using the "fetch" API + + + + + + + diff --git a/fetch/metadata/generated/form-submission.https.sub.html b/fetch/metadata/generated/form-submission.https.sub.html new file mode 100644 index 00000000000000..a0f683add1789e --- /dev/null +++ b/fetch/metadata/generated/form-submission.https.sub.html @@ -0,0 +1,521 @@ + + + + + HTTP headers on request for HTML form navigation + + + + + + + + + diff --git a/fetch/metadata/generated/form-submission.sub.html b/fetch/metadata/generated/form-submission.sub.html new file mode 100644 index 00000000000000..c4a5e2fa7ba208 --- /dev/null +++ b/fetch/metadata/generated/form-submission.sub.html @@ -0,0 +1,399 @@ + + + + + HTTP headers on request for HTML form navigation + + + + + + + diff --git a/fetch/metadata/generated/header-link.https.sub.html b/fetch/metadata/generated/header-link.https.sub.html new file mode 100644 index 00000000000000..09f011389559bf --- /dev/null +++ b/fetch/metadata/generated/header-link.https.sub.html @@ -0,0 +1,529 @@ + + + + + HTTP headers on request for HTTP "Link" header + + + + + + + diff --git a/fetch/metadata/generated/header-link.https.sub.tentative.html b/fetch/metadata/generated/header-link.https.sub.tentative.html new file mode 100644 index 00000000000000..307c37fbf77c9a --- /dev/null +++ b/fetch/metadata/generated/header-link.https.sub.tentative.html @@ -0,0 +1,51 @@ + + + + + HTTP headers on request for HTTP "Link" header + + + + + + + diff --git a/fetch/metadata/generated/header-link.sub.html b/fetch/metadata/generated/header-link.sub.html new file mode 100644 index 00000000000000..8b6cdae0edad7b --- /dev/null +++ b/fetch/metadata/generated/header-link.sub.html @@ -0,0 +1,460 @@ + + + + + HTTP headers on request for HTTP "Link" header + + + + + + + diff --git a/fetch/metadata/generated/header-refresh.https.optional.sub.html b/fetch/metadata/generated/header-refresh.https.optional.sub.html new file mode 100644 index 00000000000000..c303d871413d5c --- /dev/null +++ b/fetch/metadata/generated/header-refresh.https.optional.sub.html @@ -0,0 +1,272 @@ + + + + + HTTP headers on request for HTTP "Refresh" header + + + + + + + diff --git a/fetch/metadata/generated/header-refresh.optional.sub.html b/fetch/metadata/generated/header-refresh.optional.sub.html new file mode 100644 index 00000000000000..56f24663e1d019 --- /dev/null +++ b/fetch/metadata/generated/header-refresh.optional.sub.html @@ -0,0 +1,221 @@ + + + + + HTTP headers on request for HTTP "Refresh" header + + + + + + + diff --git a/fetch/metadata/generated/script-module-import-dynamic.https.sub.html b/fetch/metadata/generated/script-module-import-dynamic.https.sub.html new file mode 100644 index 00000000000000..72d60fc30cb5f0 --- /dev/null +++ b/fetch/metadata/generated/script-module-import-dynamic.https.sub.html @@ -0,0 +1,254 @@ + + + + + HTTP headers on request for dynamic ECMAScript module import + + + + + diff --git a/fetch/metadata/generated/script-module-import-dynamic.sub.html b/fetch/metadata/generated/script-module-import-dynamic.sub.html new file mode 100644 index 00000000000000..088720c23e0db4 --- /dev/null +++ b/fetch/metadata/generated/script-module-import-dynamic.sub.html @@ -0,0 +1,214 @@ + + + + + HTTP headers on request for dynamic ECMAScript module import + + + + + diff --git a/fetch/metadata/generated/script-module-import-static.https.sub.html b/fetch/metadata/generated/script-module-import-static.https.sub.html new file mode 100644 index 00000000000000..cea3464f80701a --- /dev/null +++ b/fetch/metadata/generated/script-module-import-static.https.sub.html @@ -0,0 +1,288 @@ + + + + + HTTP headers on request for static ECMAScript module import + + + + + + diff --git a/fetch/metadata/generated/script-module-import-static.sub.html b/fetch/metadata/generated/script-module-import-static.sub.html new file mode 100644 index 00000000000000..0f94f71cf6f186 --- /dev/null +++ b/fetch/metadata/generated/script-module-import-static.sub.html @@ -0,0 +1,246 @@ + + + + + HTTP headers on request for static ECMAScript module import + + + + + + diff --git a/fetch/metadata/generated/serviceworker.https.sub.html b/fetch/metadata/generated/serviceworker.https.sub.html new file mode 100644 index 00000000000000..12e37369a422c5 --- /dev/null +++ b/fetch/metadata/generated/serviceworker.https.sub.html @@ -0,0 +1,170 @@ + + + + + + HTTP headers on request for Service Workers + + + + + + + diff --git a/fetch/metadata/generated/svg-image.https.sub.html b/fetch/metadata/generated/svg-image.https.sub.html new file mode 100644 index 00000000000000..b059eb31456dfc --- /dev/null +++ b/fetch/metadata/generated/svg-image.https.sub.html @@ -0,0 +1,367 @@ + + + + + + HTTP headers on request for SVG "image" element source + + + + + + + diff --git a/fetch/metadata/generated/svg-image.sub.html b/fetch/metadata/generated/svg-image.sub.html new file mode 100644 index 00000000000000..a28bbb12eb71ec --- /dev/null +++ b/fetch/metadata/generated/svg-image.sub.html @@ -0,0 +1,265 @@ + + + + + + HTTP headers on request for SVG "image" element source + + + + + + + diff --git a/fetch/metadata/generated/window-history.https.sub.html b/fetch/metadata/generated/window-history.https.sub.html new file mode 100644 index 00000000000000..c2b3079a6d3670 --- /dev/null +++ b/fetch/metadata/generated/window-history.https.sub.html @@ -0,0 +1,237 @@ + + + + + HTTP headers on request for navigation via the HTML History API + + + + + + + diff --git a/fetch/metadata/generated/window-history.sub.html b/fetch/metadata/generated/window-history.sub.html new file mode 100644 index 00000000000000..333d90c28609bd --- /dev/null +++ b/fetch/metadata/generated/window-history.sub.html @@ -0,0 +1,360 @@ + + + + + + HTTP headers on request for navigation via the HTML History API + + + + + + + diff --git a/fetch/metadata/generated/window-location.https.sub.html b/fetch/metadata/generated/window-location.https.sub.html new file mode 100644 index 00000000000000..4a0d2fdc068078 --- /dev/null +++ b/fetch/metadata/generated/window-location.https.sub.html @@ -0,0 +1,1184 @@ + + + + + + HTTP headers on request for navigation via the HTML Location API + + + + + + + + + diff --git a/fetch/metadata/generated/window-location.sub.html b/fetch/metadata/generated/window-location.sub.html new file mode 100644 index 00000000000000..bb3e6805cb0114 --- /dev/null +++ b/fetch/metadata/generated/window-location.sub.html @@ -0,0 +1,894 @@ + + + + + + HTTP headers on request for navigation via the HTML Location API + + + + + + + diff --git a/fetch/metadata/generated/worker-dedicated-constructor.https.sub.html b/fetch/metadata/generated/worker-dedicated-constructor.https.sub.html new file mode 100644 index 00000000000000..86f1760755453c --- /dev/null +++ b/fetch/metadata/generated/worker-dedicated-constructor.https.sub.html @@ -0,0 +1,118 @@ + + + + + HTTP headers on request for dedicated worker via the "Worker" constructor + + + + + diff --git a/fetch/metadata/generated/worker-dedicated-constructor.sub.html b/fetch/metadata/generated/worker-dedicated-constructor.sub.html new file mode 100644 index 00000000000000..69ac7682a5c5ff --- /dev/null +++ b/fetch/metadata/generated/worker-dedicated-constructor.sub.html @@ -0,0 +1,204 @@ + + + + + HTTP headers on request for dedicated worker via the "Worker" constructor + + + + + diff --git a/fetch/metadata/generated/worker-dedicated-importscripts.https.sub.html b/fetch/metadata/generated/worker-dedicated-importscripts.https.sub.html new file mode 100644 index 00000000000000..0cd9f35d582535 --- /dev/null +++ b/fetch/metadata/generated/worker-dedicated-importscripts.https.sub.html @@ -0,0 +1,268 @@ + + + + + HTTP headers on request for dedicated worker via the "importScripts" API + + + + + diff --git a/fetch/metadata/generated/worker-dedicated-importscripts.sub.html b/fetch/metadata/generated/worker-dedicated-importscripts.sub.html new file mode 100644 index 00000000000000..0555bbaf432696 --- /dev/null +++ b/fetch/metadata/generated/worker-dedicated-importscripts.sub.html @@ -0,0 +1,228 @@ + + + + + HTTP headers on request for dedicated worker via the "importScripts" API + + + + + diff --git a/fetch/metadata/history.https.sub.html b/fetch/metadata/history.https.sub.html deleted file mode 100644 index f0119e6c754d36..00000000000000 --- a/fetch/metadata/history.https.sub.html +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - diff --git a/fetch/metadata/iframe.https.sub.html b/fetch/metadata/iframe.https.sub.html deleted file mode 100644 index 1c793fd7e45990..00000000000000 --- a/fetch/metadata/iframe.https.sub.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - diff --git a/fetch/metadata/iframe.sub.html b/fetch/metadata/iframe.sub.html deleted file mode 100644 index e0d5b0b8cb824e..00000000000000 --- a/fetch/metadata/iframe.sub.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - diff --git a/fetch/metadata/img.https.sub.html b/fetch/metadata/img.https.sub.html deleted file mode 100644 index 93acffef11ae23..00000000000000 --- a/fetch/metadata/img.https.sub.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - diff --git a/fetch/metadata/prefetch.https.sub.html b/fetch/metadata/prefetch.https.sub.html deleted file mode 100644 index a0ff73c0d0868e..00000000000000 --- a/fetch/metadata/prefetch.https.sub.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - diff --git a/fetch/metadata/redirect/cross-site-redirect.https.sub.html b/fetch/metadata/redirect/cross-site-redirect.https.sub.html deleted file mode 100644 index 827eb982e47f3f..00000000000000 --- a/fetch/metadata/redirect/cross-site-redirect.https.sub.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - diff --git a/fetch/metadata/redirect/multiple-redirect-cross-site.https.sub.html b/fetch/metadata/redirect/multiple-redirect-cross-site.https.sub.html deleted file mode 100644 index fc986aaf4fdcff..00000000000000 --- a/fetch/metadata/redirect/multiple-redirect-cross-site.https.sub.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - diff --git a/fetch/metadata/redirect/multiple-redirect-https-downgrade-upgrade-prefetch.optional.sub.html b/fetch/metadata/redirect/multiple-redirect-https-downgrade-upgrade-prefetch.optional.sub.html deleted file mode 100644 index 970eb3373a04b6..00000000000000 --- a/fetch/metadata/redirect/multiple-redirect-https-downgrade-upgrade-prefetch.optional.sub.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - diff --git a/fetch/metadata/redirect/multiple-redirect-https-downgrade-upgrade.sub.html b/fetch/metadata/redirect/multiple-redirect-https-downgrade-upgrade.sub.html index 907cf5c617df56..0f8f3200165c63 100644 --- a/fetch/metadata/redirect/multiple-redirect-https-downgrade-upgrade.sub.html +++ b/fetch/metadata/redirect/multiple-redirect-https-downgrade-upgrade.sub.html @@ -6,68 +6,13 @@ - -
Downgraded then upgraded font
- - diff --git a/fetch/metadata/redirect/multiple-redirect-same-site.https.sub.html b/fetch/metadata/redirect/multiple-redirect-same-site.https.sub.html deleted file mode 100644 index f5483ac3fa2f3f..00000000000000 --- a/fetch/metadata/redirect/multiple-redirect-same-site.https.sub.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - diff --git a/fetch/metadata/redirect/redirect-http-upgrade-prefetch.optional.sub.html b/fetch/metadata/redirect/redirect-http-upgrade-prefetch.optional.sub.html deleted file mode 100644 index c69f0e92592723..00000000000000 --- a/fetch/metadata/redirect/redirect-http-upgrade-prefetch.optional.sub.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - diff --git a/fetch/metadata/redirect/redirect-http-upgrade.sub.html b/fetch/metadata/redirect/redirect-http-upgrade.sub.html index 133576cb0d7236..fa765b66d03898 100644 --- a/fetch/metadata/redirect/redirect-http-upgrade.sub.html +++ b/fetch/metadata/redirect/redirect-http-upgrade.sub.html @@ -6,62 +6,12 @@ - -
Upgraded font
- - - - diff --git a/fetch/metadata/redirect/redirect-https-downgrade-prefetch.optional.sub.html b/fetch/metadata/redirect/redirect-https-downgrade-prefetch.optional.sub.html deleted file mode 100644 index a446cbad840515..00000000000000 --- a/fetch/metadata/redirect/redirect-https-downgrade-prefetch.optional.sub.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - diff --git a/fetch/metadata/redirect/redirect-https-downgrade.sub.html b/fetch/metadata/redirect/redirect-https-downgrade.sub.html index 9eb04822b683bf..4e5a48e6f6e72e 100644 --- a/fetch/metadata/redirect/redirect-https-downgrade.sub.html +++ b/fetch/metadata/redirect/redirect-https-downgrade.sub.html @@ -6,64 +6,12 @@ - -
Downgraded font
- - - diff --git a/fetch/metadata/redirect/same-origin-redirect.https.sub.html b/fetch/metadata/redirect/same-origin-redirect.https.sub.html deleted file mode 100644 index 38921a71314a54..00000000000000 --- a/fetch/metadata/redirect/same-origin-redirect.https.sub.html +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - diff --git a/fetch/metadata/redirect/same-site-redirect.https.sub.html b/fetch/metadata/redirect/same-site-redirect.https.sub.html deleted file mode 100644 index f8709a14c0f0ff..00000000000000 --- a/fetch/metadata/redirect/same-site-redirect.https.sub.html +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - diff --git a/fetch/metadata/resources/appcache-iframe.sub.html b/fetch/metadata/resources/appcache-iframe.sub.html new file mode 100644 index 00000000000000..cea9a4feaec4d7 --- /dev/null +++ b/fetch/metadata/resources/appcache-iframe.sub.html @@ -0,0 +1,15 @@ + + + + diff --git a/fetch/metadata/resources/es-module.sub.js b/fetch/metadata/resources/es-module.sub.js new file mode 100644 index 00000000000000..f9668a3dc67807 --- /dev/null +++ b/fetch/metadata/resources/es-module.sub.js @@ -0,0 +1 @@ +import '{{GET[moduleId]}}'; diff --git a/fetch/metadata/resources/fetch-via-serviceworker--respondWith--frame.html b/fetch/metadata/resources/fetch-via-serviceworker--respondWith--frame.html deleted file mode 100644 index 98798025005497..00000000000000 --- a/fetch/metadata/resources/fetch-via-serviceworker--respondWith--frame.html +++ /dev/null @@ -1,3 +0,0 @@ - - -Page Title diff --git a/fetch/metadata/resources/fetch-via-serviceworker--fallback--frame.html b/fetch/metadata/resources/fetch-via-serviceworker-frame.html similarity index 100% rename from fetch/metadata/resources/fetch-via-serviceworker--fallback--frame.html rename to fetch/metadata/resources/fetch-via-serviceworker-frame.html diff --git a/fetch/metadata/resources/go-back.html b/fetch/metadata/resources/go-back.html deleted file mode 100644 index 002c4cea473885..00000000000000 --- a/fetch/metadata/resources/go-back.html +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/fetch/metadata/resources/header-link.py b/fetch/metadata/resources/header-link.py new file mode 100644 index 00000000000000..de891163a33b17 --- /dev/null +++ b/fetch/metadata/resources/header-link.py @@ -0,0 +1,15 @@ +def main(request, response): + """ + Respond with a blank HTML document and a `Link` header which describes + a link relation specified by the requests `location` and `rel` query string + parameters + """ + headers = [ + (b'Content-Type', b'text/html'), + ( + b'Link', + b'<' + request.GET.first(b'location') + b'>; rel=' + request.GET.first(b'rel') + ) + ] + return (200, headers, b'') + diff --git a/fetch/metadata/resources/helper.sub.js b/fetch/metadata/resources/helper.sub.js new file mode 100644 index 00000000000000..fd179fe6f25d6a --- /dev/null +++ b/fetch/metadata/resources/helper.sub.js @@ -0,0 +1,67 @@ +'use strict'; + +/** + * Construct a URL which, when followed, will trigger redirection through zero + * or more specified origins and ultimately resolve in the Python handler + * `record-headers.py`. + * + * @param {string} key - the WPT server "stash" name where the request's + * headers should be stored + * @param {string[]} [origins] - zero or more origin names through which the + * request should pass; see the function + * implementation for a completel list of names + * and corresponding origins; If specified, the + * final origin will be used to access the + * `record-headers.py` hander. + * @param {object} [params] - a collection of key-value pairs to include as + * URL "search" parameters in the final request to + * `record-headers.py` + * + * @returns {string} an absolute URL + */ +function makeRequestURL(key, origins, params) { + const byName = { + httpOrigin: 'http://{{host}}:{{ports[http][0]}}', + httpSameSite: 'http://{{hosts[][www]}}:{{ports[http][0]}}', + httpCrossSite: 'http://{{hosts[alt][]}}:{{ports[http][0]}}', + httpsOrigin: 'https://{{host}}:{{ports[https][0]}}', + httpsSameSite: 'https://{{hosts[][www]}}:{{ports[https][0]}}', + httpsCrossSite: 'https://{{hosts[alt][]}}:{{ports[https][0]}}' + }; + const redirectPath = '/fetch/api/resources/redirect.py?location='; + const path = '/fetch/metadata/resources/record-headers.py?key=' + key; + + let requestUrl = path; + if (params) { + requestUrl += '&' + new URLSearchParams(params).toString(); + } + + if (origins && origins.length) { + requestUrl = byName[origins.pop()] + requestUrl; + + while (origins.length) { + requestUrl = byName[origins.pop()] + redirectPath + + encodeURIComponent(requestUrl); + } + } else { + requestUrl = byName.httpsOrigin + requestUrl; + } + + return requestUrl; +} + +function retrieve(key, options) { + return fetch('/fetch/metadata/resources/record-headers.py?retrieve&key=' + key) + .then((response) => { + if (response.status === 204 && options && options.poll) { + return new Promise((resolve) => setTimeout(resolve, 300)) + .then(() => retrieve(key, options)); + } + + if (response.status !== 200) { + throw new Error('Failed to query for recorded headers.'); + } + + return response.text().then((text) => JSON.parse(text)); + }); +} diff --git a/fetch/metadata/resources/message-opener.html b/fetch/metadata/resources/message-opener.html new file mode 100644 index 00000000000000..eb2af7b250b9e7 --- /dev/null +++ b/fetch/metadata/resources/message-opener.html @@ -0,0 +1,17 @@ + diff --git a/fetch/metadata/resources/post-to-owner-onload.py b/fetch/metadata/resources/post-to-owner-onload.py deleted file mode 100644 index 8459edbd68a085..00000000000000 --- a/fetch/metadata/resources/post-to-owner-onload.py +++ /dev/null @@ -1,34 +0,0 @@ -import json - -from wptserve.utils import isomorphic_decode - -def main(request, response): - headers = [ - (b"Content-Type", b"text/html"), - (b"Cache-Control", b"no-cache, no-store, must-revalidate") - ] - key = request.GET.first(b"key", None) - - body = u""" - - - - """ % (json.dumps({ - u"dest": isomorphic_decode(request.headers.get(b"sec-fetch-dest", b"")), - u"mode": isomorphic_decode(request.headers.get(b"sec-fetch-mode", b"")), - u"site": isomorphic_decode(request.headers.get(b"sec-fetch-site", b"")), - u"user": isomorphic_decode(request.headers.get(b"sec-fetch-user", b"")), - }), json.dumps(key)) - return headers, body diff --git a/fetch/metadata/resources/record-header.py b/fetch/metadata/resources/record-header.py index f2e7273c53c075..a6b52e1e4b992e 100644 --- a/fetch/metadata/resources/record-header.py +++ b/fetch/metadata/resources/record-header.py @@ -138,3 +138,7 @@ def main(request, response): """ + + if key.startswith(b"script"): + response.headers.set(b"Content-Type", b"application/javascript") + return b"void 0;" diff --git a/fetch/metadata/resources/record-headers.py b/fetch/metadata/resources/record-headers.py new file mode 100644 index 00000000000000..0362fe228c203a --- /dev/null +++ b/fetch/metadata/resources/record-headers.py @@ -0,0 +1,73 @@ +import os +import uuid +import hashlib +import time +import json + + +def bytes_to_strings(d): + # Recursively convert bytes to strings in `d`. + if not isinstance(d, dict): + if isinstance(d, (tuple,list,set)): + v = [bytes_to_strings(x) for x in d] + return v + else: + if isinstance(d, bytes): + d = d.decode() + return d + + result = {} + for k,v in d.items(): + if isinstance(k, bytes): + k = k.decode() + if isinstance(v, dict): + v = bytes_to_strings(v) + elif isinstance(v, (tuple,list,set)): + v = [bytes_to_strings(x) for x in v] + elif isinstance(v, bytes): + v = v.decode() + result[k] = v + return result + + +def main(request, response): + # This condition avoids false positives from CORS preflight checks, where the + # request under test may be followed immediately by a request to the same URL + # using a different HTTP method. + if b'requireOPTIONS' in request.GET and request.method != b'OPTIONS': + return + + if b'key' in request.GET: + key = request.GET[b'key'] + elif b'key' in request.POST: + key = request.POST[b'key'] + + ## Convert the key from String to UUID valid String ## + testId = hashlib.md5(key).hexdigest() + + ## Handle the header retrieval request ## + if b'retrieve' in request.GET: + recorded_headers = request.server.stash.take(testId) + + if recorded_headers is None: + return (204, [], b'') + + return (200, [], recorded_headers) + + ## Record incoming fetch metadata header value + else: + try: + request.server.stash.put(testId, json.dumps(bytes_to_strings(request.headers))) + except KeyError: + ## The header is already recorded or it doesn't exist + pass + + ## Prevent the browser from caching returned responses and allow CORS ## + response.headers.set(b"Access-Control-Allow-Origin", b"*") + response.headers.set(b"Cache-Control", b"no-cache, no-store, must-revalidate") + response.headers.set(b"Pragma", b"no-cache") + response.headers.set(b"Expires", b"0") + if b"mime" in request.GET: + response.headers.set(b"Content-Type", request.GET.first(b"mime")) + + return request.GET.first(b"body", request.POST.first(b"body", b"")) diff --git a/fetch/metadata/resources/redirectTestHelper.sub.js b/fetch/metadata/resources/redirectTestHelper.sub.js index 0aec19d4ee78b1..1bfbbae70c2221 100644 --- a/fetch/metadata/resources/redirectTestHelper.sub.js +++ b/fetch/metadata/resources/redirectTestHelper.sub.js @@ -38,56 +38,9 @@ function downgradeRedirectTo(partialPath) { return secureRedirectURL + encodeURIComponent(insecureTestURL + partialPath); } -// Helper to test the behavior of the `prefetch` Link type [1]. Because the the -// behavior under test is optional [2], this function should only be used in -// tests which have been denoted as "optional" [3]. -// -// [1] https://html.spec.whatwg.org/#link-type-prefetch -// [2] https://w3c.github.io/resource-hints/#load-and-error-events -// [3] https://web-platform-tests.org/writing-tests/file-names.html -function testPrefetch(nonce, testNamePrefix, urlHelperMethod, expectedResults) { - async_test(t => { - let key = 'prefetch' + nonce; - let e = document.createElement('link'); - e.rel = 'prefetch'; - e.crossOrigin = 'anonymous'; - e.href = urlHelperMethod('resources/record-header.py?file=' + key) + '&simple=true'; - e.onload = t.step_func(e => { - let expectation = { ...expectedResults }; - if (expectation['mode'] != '') - expectation['mode'] = 'cors'; - fetch('/fetch/metadata/resources/record-header.py?retrieve=true&file=' + key) - .then(t.step_func(response => response.text())) - .then(t.step_func_done(text => assert_header_equals(text, expectation, testNamePrefix + ' prefetch => No headers'))) - .catch(t.unreached_func('Fetching and verifying the results should succeed.')); - }); - e.onerror = t.unreached_func(); - document.head.appendChild(e); - }, testNamePrefix + ' prefetch => No headers'); -} - // Helper to run common redirect test cases that don't require special setup on // the test page itself. function RunCommonRedirectTests(testNamePrefix, urlHelperMethod, expectedResults) { - async_test(t => { - let i = document.createElement('iframe'); - i.src = urlHelperMethod('resources/post-to-owner.py?iframe-navigation' + nonce); - window.addEventListener('message', t.step_func(e => { - if (e.source != i.contentWindow) { - return; - } - let expectation = { ...expectedResults }; - if (expectation['mode'] != '') - expectation['mode'] = 'navigate'; - if (expectation['dest'] == 'font') - expectation['dest'] = 'iframe'; - assert_header_equals(e.data, expectation, testNamePrefix + ' iframe'); - t.done(); - })); - - document.body.appendChild(i); - }, testNamePrefix + ' iframe'); - async_test(t => { let testWindow = window.open(urlHelperMethod('resources/post-to-owner.py?top-level-navigation' + nonce)); t.add_cleanup(_ => testWindow.close()); @@ -127,18 +80,6 @@ function RunCommonRedirectTests(testNamePrefix, urlHelperMethod, expectedResults }); }, testNamePrefix + ' embed'); - promise_test(t => { - let key = 'fetch-redirect' + nonce; - let expectation = { ...expectedResults }; - if (expectation['mode'] != '') - expectation['mode'] = 'cors'; - if (expectation['dest'] == 'font') - expectation['dest'] = 'empty'; - return fetch(urlHelperMethod('resources/echo-as-json.py?' + key)) - .then(r => r.json()) - .then(j => {assert_header_equals(j, expectation, testNamePrefix + ' fetch() api');}); - }, testNamePrefix + ' fetch() api'); - promise_test(t => { return new Promise((resolve, reject) => { let key = 'object-https-redirect' + nonce; diff --git a/fetch/metadata/script.https.sub.html b/fetch/metadata/script.https.sub.html deleted file mode 100644 index f66f663433443e..00000000000000 --- a/fetch/metadata/script.https.sub.html +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/fetch/metadata/script.sub.html b/fetch/metadata/script.sub.html deleted file mode 100644 index 9d6059abc177eb..00000000000000 --- a/fetch/metadata/script.sub.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/fetch/metadata/serviceworker.https.sub.html b/fetch/metadata/serviceworker.https.sub.html deleted file mode 100644 index 51bc7f29e59308..00000000000000 --- a/fetch/metadata/serviceworker.https.sub.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - diff --git a/fetch/metadata/tools/README.md b/fetch/metadata/tools/README.md new file mode 100644 index 00000000000000..678c09ac80005a --- /dev/null +++ b/fetch/metadata/tools/README.md @@ -0,0 +1,147 @@ +# Fetch Metadata test generation framework + +This directory defines a command-line tool for procedurally generating WPT +tests. + +## Motivation + +Many features of the web platform involve the browser making one or more HTTP +requests to remote servers. Only some aspects of these requests are specified +within the standard that defines the relevant feature. Other aspects are +specified by external standards which span the entire platform (e.g. [Fetch +Metadata Request Headers](https://w3c.github.io/webappsec-fetch-metadata/)). + +This state of affairs makes it difficult to maintain test coverage for two +reasons: + +- When a new feature introduces a new kind of web request, it must be verified + to integrate with every cross-cutting standard. +- When a new cross-cutting standard is introduced, it must be verified to + integrate with every kind of web request. + +The tool in this directory attempts to reduce this tension. It allows +maintainers to express instructions for making web requests in an abstract +sense. These generic instructions can be reused by to produce a different suite +of tests for each cross-cutting feature. + +When a new kind of request is proposed, a single generic template can be +defined here. This will provide the maintainers of all cross-cutting features +with clear instruction on how to extend their test suite with the new feature. + +Similarly, when a new cross-cutting feature is proposed, the authors can use +this tool to build a test suite which spans the entire platform. + +## Build script + +To generate the Fetch Metadata tests, use the `build.sh` script, which installs +the dependencies and runs `generate.py` with the Fetch Metadata tests +configuration file `fetch-metadata.conf.yml`, in a virtualenv. + + $ build.sh + +If you don't want to use virtualenv, see the next two sections. + +## Setup instructions + +- [Install Python 3](https://www.python.org/download/releases/3.0/) +- Install Python dependencies with the following command (issued from the + directory containing this document): + + $ pip install -r ./requirements.txt + +## Execution + +Execute the following command to generate tests, making sure to replace +`./path/to/configuration-file.yml` with a filesystem path to a valid +configuration file (described in greater detail below): + + $ python3 ./generate.py ./path/to/configuration-file.yml + +## Configuration + +The test generation tool requires a YAML-formatted configuration file as its +input. The file should define a dictionary with the following keys: + +- `templates` - a string describing the filesystem path from which template + files should be loaded +- `output_directory` - a string describing the filesystem path where the + generated test files should be written +- `cases` - a list of dictionaries describing how the test templates should be + expanded with individual subtests; each dictionary should have the following + keys: + - `all_subtests` - properties which should be defined for every expansion + - `common_axis` - a list of dictionaries + - `template_axes` - a dictionary relating template names to properties that + should be used when expanding that particular template + +Internally, the tool creates a set of "subtests" for each template. This set is +the Cartesian product of the `common_axis` and the given template's entry in +the `template_axes` dictionary. It uses this set of subtests to expand the +template, creating an output file. Refer to the next section for a concrete +example of how the expansion is performed. + +In general, the tool will output a single file for each template. However, the +`filename_flags` attribute has special semantics. It is used to separate +subtests for the same template file. This is intended to accommodate [the +web-platform-test's filename-based +conventions](https://web-platform-tests.org/writing-tests/file-names.html). + +For instance, when `.https` is present in a test file's name, the WPT test +harness will load that test using the HTTPS protocol. Subtests which include +the value `https` in the `filename_flags` property will be expanded using the +appropriate template but written to a distinct file whose name includes +`.https`. + +The generation tool requires that the configuration file references every +template in the `templates` directory. Because templates and configuration +files may be contributed by different people, this requirement ensures that +configuration authors are aware of all available templates. Some templates may +not be relevant for some features; in those cases, the configuration file can +include an empty array for the template's entry in the `template_axes` +dictionary (as in `template3.html` in the example which follows). + +## Expansion example + +In the following example configuration file, `a`, `b`, `s`, `w`, `x`, `y`, and +`z` all represent associative arrays. + +```yaml +templates: path/to/templates +output_directory: path/to/output +cases: + - every_subtest: s + common_axis: [a, b] + template_axes: + template1.html: [w] + template2.html: [x, y, z] + template3.html: [] +``` + +When run with such a configuration file, the tool would generate two files, +expanded with data as described below (where `(a, b)` represents the union of +`a` and `b`): + + template1.html: [(a, w), (b, w)] + template2.html: [(a, x), (b, x), (a, y), (b, y), (a, z), (b, z)] + template3.html: (zero tests; not expanded) + +## Design Considerations + +**Efficiency of generated output** The tool is capable of generating a large +number of tests given a small amount of input. Naively structured, this could +result in test suites which take large amount of time and computational +resources to complete. The tool has been designed to help authors structure the +generated output to reduce these resource requirements. + +**Literalness of generated output** Because the generated output is how most +people will interact with the tests, it is important that it be approachable. +This tool avoids outputting abstractions which would frustrate attempts to read +the source code or step through its execution environment. + +**Simplicity** The test generation logic itself was written to be approachable. +This makes it easier to anticipate how the tool will behave with new input, and +it lowers the bar for others to contribute improvements. + +Non-goals include conciseness of template files (verbosity makes the potential +expansions more predictable) and conciseness of generated output (verbosity +aids in the interpretation of results). diff --git a/fetch/metadata/tools/build.sh b/fetch/metadata/tools/build.sh new file mode 100755 index 00000000000000..a6f5afffe0d13e --- /dev/null +++ b/fetch/metadata/tools/build.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env sh +set -ex + +cd "${0%/*}" +virtualenv -p python3 .virtualenv +.virtualenv/bin/pip install -r ./requirements.txt +cd .. +tools/.virtualenv/bin/python ./tools/generate.py ./tools/fetch-metadata.conf.yml diff --git a/fetch/metadata/tools/fetch-metadata.conf.yml b/fetch/metadata/tools/fetch-metadata.conf.yml new file mode 100644 index 00000000000000..b277bcb7b53d54 --- /dev/null +++ b/fetch/metadata/tools/fetch-metadata.conf.yml @@ -0,0 +1,806 @@ +--- +templates: templates +output_directory: ../generated +cases: + - all_subtests: + expected: NULL + filename_flags: [] + common_axis: + - headerName: sec-fetch-site + origins: [httpOrigin] + description: Not sent to non-trustworthy same-origin destination + - headerName: sec-fetch-site + origins: [httpSameSite] + description: Not sent to non-trustworthy same-site destination + - headerName: sec-fetch-site + origins: [httpCrossSite] + description: Not sent to non-trustworthy cross-site destination + - headerName: sec-fetch-mode + origins: [httpOrigin] + description: Not sent to non-trustworthy same-origin destination + - headerName: sec-fetch-mode + origins: [httpSameSite] + description: Not sent to non-trustworthy same-site destination + - headerName: sec-fetch-mode + origins: [httpCrossSite] + description: Not sent to non-trustworthy cross-site destination + - headerName: sec-fetch-dest + origins: [httpOrigin] + description: Not sent to non-trustworthy same-origin destination + - headerName: sec-fetch-dest + origins: [httpSameSite] + description: Not sent to non-trustworthy same-site destination + - headerName: sec-fetch-dest + origins: [httpCrossSite] + description: Not sent to non-trustworthy cross-site destination + - headerName: sec-fetch-user + origins: [httpOrigin] + description: Not sent to non-trustworthy same-origin destination + - headerName: sec-fetch-user + origins: [httpSameSite] + description: Not sent to non-trustworthy same-site destination + - headerName: sec-fetch-user + origins: [httpCrossSite] + description: Not sent to non-trustworthy cross-site destination + template_axes: + # Unused + appcache-manifest.sub.https.html: [] + # The `audioWorklet` interface is only available in secure contexts + # https://webaudio.github.io/web-audio-api/#BaseAudioContext + audioworklet.https.sub.html: [] + # Service workers are only available in secure context + fetch-via-serviceworker.https.sub.html: [] + # Service workers are only available in secure context + serviceworker.https.sub.html: [] + + css-images.sub.html: + - filename_flags: [tentative] + css-font-face.sub.html: + - filename_flags: [tentative] + element-a.sub.html: [{}] + element-area.sub.html: [{}] + element-audio.sub.html: [{}] + element-embed.sub.html: [{}] + element-frame.sub.html: [{}] + element-iframe.sub.html: [{}] + element-img.sub.html: + - sourceAttr: src + - sourceAttr: srcset + element-img-environment-change.sub.html: [{}] + element-input-image.sub.html: [{}] + element-link-icon.sub.html: [{}] + element-link-prefetch.optional.sub.html: [{}] + element-meta-refresh.optional.sub.html: [{}] + element-picture.sub.html: [{}] + element-script.sub.html: + - {} + - elementAttrs: { type: module } + element-video.sub.html: [{}] + element-video-poster.sub.html: [{}] + fetch.sub.html: [{}] + form-submission.sub.html: + - method: GET + - method: POST + header-link.sub.html: + - rel: icon + - rel: stylesheet + header-refresh.optional.sub.html: [{}] + window-location.sub.html: [{}] + script-module-import-dynamic.sub.html: [{}] + script-module-import-static.sub.html: [{}] + svg-image.sub.html: [{}] + window-history.sub.html: [{}] + worker-dedicated-importscripts.sub.html: [{}] + worker-dedicated-constructor.sub.html: [{}] + + # Sec-Fetch-Site - direct requests + - all_subtests: + headerName: sec-fetch-site + filename_flags: [https] + common_axis: + - description: Same origin + origins: [httpsOrigin] + expected: same-origin + - description: Cross-site + origins: [httpsCrossSite] + expected: cross-site + - description: Same site + origins: [httpsSameSite] + expected: same-site + template_axes: + # Unused + # - the request mode of all "classic" worker scripts is set to + # "same-origin" + # https://html.spec.whatwg.org/#fetch-a-classic-worker-script + # - the request mode of all "top-level "module" worker scripts is set to + # "same-origin": + # https://html.spec.whatwg.org/#fetch-a-single-module-script + worker-dedicated-constructor.sub.html: [] + + appcache-manifest.sub.https.html: [{}] + audioworklet.https.sub.html: [{}] + css-images.sub.html: + - filename_flags: [tentative] + css-font-face.sub.html: + - filename_flags: [tentative] + element-a.sub.html: [{}] + element-area.sub.html: [{}] + element-audio.sub.html: [{}] + element-embed.sub.html: [{}] + element-frame.sub.html: [{}] + element-iframe.sub.html: [{}] + element-img.sub.html: + - sourceAttr: src + - sourceAttr: srcset + element-img-environment-change.sub.html: [{}] + element-input-image.sub.html: [{}] + element-link-icon.sub.html: [{}] + element-link-prefetch.optional.sub.html: [{}] + element-meta-refresh.optional.sub.html: [{}] + element-picture.sub.html: [{}] + element-script.sub.html: + - {} + - elementAttrs: { type: module } + element-video.sub.html: [{}] + element-video-poster.sub.html: [{}] + fetch.sub.html: [{ init: { mode: no-cors } }] + fetch-via-serviceworker.https.sub.html: [{ init: { mode: no-cors } }] + form-submission.sub.html: + - method: GET + - method: POST + header-link.sub.html: + - rel: icon + - rel: stylesheet + header-refresh.optional.sub.html: [{}] + window-location.sub.html: [{}] + script-module-import-dynamic.sub.html: [{}] + script-module-import-static.sub.html: [{}] + serviceworker.https.sub.html: [{}] + svg-image.sub.html: [{}] + window-history.sub.html: [{}] + worker-dedicated-importscripts.sub.html: [{}] + + # Sec-Fetch-Site - redirection from HTTP + - all_subtests: + headerName: sec-fetch-site + filename_flags: [] + common_axis: + - description: HTTPS downgrade (header not sent) + origins: [httpsOrigin, httpOrigin] + expected: NULL + - description: HTTPS upgrade + origins: [httpOrigin, httpsOrigin] + expected: cross-site + - description: HTTPS downgrade-upgrade + origins: [httpsOrigin, httpOrigin, httpsOrigin] + expected: cross-site + template_axes: + # Unused + # The `audioWorklet` interface is only available in secure contexts + # https://webaudio.github.io/web-audio-api/#BaseAudioContext + audioworklet.https.sub.html: [] + # Service workers are only available in secure context + fetch-via-serviceworker.https.sub.html: [] + # Service workers' redirect mode is "error" + serviceworker.https.sub.html: [] + # Interstitial locations in an HTTP redirect chain are not added to the + # session history, so these requests cannot be initiated using the + # History API. + window-history.sub.html: [] + # Unused + # - the request mode of all "classic" worker scripts is set to + # "same-origin" + # https://html.spec.whatwg.org/#fetch-a-classic-worker-script + # - the request mode of all "top-level "module" worker scripts is set to + # "same-origin": + # https://html.spec.whatwg.org/#fetch-a-single-module-script + worker-dedicated-constructor.sub.html: [] + + appcache-manifest.sub.https.html: [{}] + css-images.sub.html: + - filename_flags: [tentative] + css-font-face.sub.html: + - filename_flags: [tentative] + element-a.sub.html: [{}] + element-area.sub.html: [{}] + element-audio.sub.html: [{}] + element-embed.sub.html: [{}] + element-frame.sub.html: [{}] + element-iframe.sub.html: [{}] + element-img.sub.html: + - sourceAttr: src + - sourceAttr: srcset + element-img-environment-change.sub.html: [{}] + element-input-image.sub.html: [{}] + element-link-icon.sub.html: [{}] + element-link-prefetch.optional.sub.html: [{}] + element-meta-refresh.optional.sub.html: [{}] + element-picture.sub.html: [{}] + element-script.sub.html: + - {} + - elementAttrs: { type: module } + element-video.sub.html: [{}] + element-video-poster.sub.html: [{}] + fetch.sub.html: [{}] + form-submission.sub.html: + - method: GET + - method: POST + header-link.sub.html: + - rel: icon + - rel: stylesheet + header-refresh.optional.sub.html: [{}] + window-location.sub.html: [{}] + script-module-import-dynamic.sub.html: [{}] + script-module-import-static.sub.html: [{}] + svg-image.sub.html: [{}] + worker-dedicated-importscripts.sub.html: [{}] + + # Sec-Fetch-Site - redirection from HTTPS + - all_subtests: + headerName: sec-fetch-site + filename_flags: [https] + common_axis: + - description: Same-Origin -> Cross-Site -> Same-Origin redirect + origins: [httpsOrigin, httpsCrossSite, httpsOrigin] + expected: cross-site + - description: Same-Origin -> Same-Site -> Same-Origin redirect + origins: [httpsOrigin, httpsSameSite, httpsOrigin] + expected: same-site + - description: Cross-Site -> Same Origin + origins: [httpsCrossSite, httpsOrigin] + expected: cross-site + - description: Cross-Site -> Same-Site + origins: [httpsCrossSite, httpsSameSite] + expected: cross-site + - description: Cross-Site -> Cross-Site + origins: [httpsCrossSite, httpsCrossSite] + expected: cross-site + - description: Same-Origin -> Same Origin + origins: [httpsOrigin, httpsOrigin] + expected: same-origin + - description: Same-Origin -> Same-Site + origins: [httpsOrigin, httpsSameSite] + expected: same-site + - description: Same-Origin -> Cross-Site + origins: [httpsOrigin, httpsCrossSite] + expected: cross-site + - description: Same-Site -> Same Origin + origins: [httpsSameSite, httpsOrigin] + expected: same-site + - description: Same-Site -> Same-Site + origins: [httpsSameSite, httpsSameSite] + expected: same-site + - description: Same-Site -> Cross-Site + origins: [httpsSameSite, httpsCrossSite] + expected: cross-site + template_axes: + # Service Workers' redirect mode is "error" + serviceworker.https.sub.html: [] + # Interstitial locations in an HTTP redirect chain are not added to the + # session history, so these requests cannot be initiated using the + # History API. + window-history.sub.html: [] + # Unused + # - the request mode of all "classic" worker scripts is set to + # "same-origin" + # https://html.spec.whatwg.org/#fetch-a-classic-worker-script + # - the request mode of all "top-level "module" worker scripts is set to + # "same-origin": + # https://html.spec.whatwg.org/#fetch-a-single-module-script + worker-dedicated-constructor.sub.html: [] + + appcache-manifest.sub.https.html: [{}] + audioworklet.https.sub.html: [{}] + css-images.sub.html: + - filename_flags: [tentative] + css-font-face.sub.html: + - filename_flags: [tentative] + element-a.sub.html: [{}] + element-area.sub.html: [{}] + element-audio.sub.html: [{}] + element-embed.sub.html: [{}] + element-frame.sub.html: [{}] + element-iframe.sub.html: [{}] + element-img.sub.html: + - sourceAttr: src + - sourceAttr: srcset + element-img-environment-change.sub.html: [{}] + element-input-image.sub.html: [{}] + element-link-icon.sub.html: [{}] + element-link-prefetch.optional.sub.html: [{}] + element-meta-refresh.optional.sub.html: [{}] + element-picture.sub.html: [{}] + element-script.sub.html: + - {} + - elementAttrs: { type: module } + element-video.sub.html: [{}] + element-video-poster.sub.html: [{}] + fetch.sub.html: [{ init: { mode: no-cors } }] + fetch-via-serviceworker.https.sub.html: [{ init: { mode: no-cors } }] + form-submission.sub.html: + - method: GET + - method: POST + header-link.sub.html: + - rel: icon + - rel: stylesheet + header-refresh.optional.sub.html: [{}] + window-location.sub.html: [{}] + script-module-import-dynamic.sub.html: [{}] + script-module-import-static.sub.html: [{}] + svg-image.sub.html: [{}] + worker-dedicated-importscripts.sub.html: [{}] + + # Sec-Fetch-Site - redirection with mixed content + # These tests verify the effect that redirection has on the request's "site". + # The initial request must be made to a resource that is "same-site" with its + # origin. This avoids false positives because if the request were made to a + # cross-site resource, the value of "cross-site" would be assigned regardless + # of the subseqent redirection. + # + # Because these conditions necessarily warrant mixed content, only templates + # which can be configured to allow mixed content [1] can be used. + # + # [1] https://w3c.github.io/webappsec-mixed-content/#should-block-fetch + + - common_axis: + - description: HTTPS downgrade-upgrade + headerName: sec-fetch-site + origins: [httpsOrigin, httpOrigin, httpsOrigin] + expected: cross-site + filename_flags: [https] + template_axes: + # Mixed Content considers only a small subset of requests as + # "optionally-blockable." These are the only requests that can be tested + # for the "downgrade-upgrade" scenario, so all other templates must be + # explicitly ignored. + audioworklet.https.sub.html: [] + css-font-face.sub.html: [] + element-embed.sub.html: [] + element-frame.sub.html: [] + element-iframe.sub.html: [] + element-img-environment-change.sub.html: [] + element-link-icon.sub.html: [] + element-link-prefetch.optional.sub.html: [] + element-picture.sub.html: [] + element-script.sub.html: [] + fetch.sub.html: [] + fetch-via-serviceworker.https.sub.html: [] + header-link.sub.html: [] + script-module-import-static.sub.html: [] + script-module-import-dynamic.sub.html: [] + # Service Workers' redirect mode is "error" + serviceworker.https.sub.html: [] + # Interstitial locations in an HTTP redirect chain are not added to the + # session history, so these requests cannot be initiated using the + # History API. + window-history.sub.html: [] + worker-dedicated-constructor.sub.html: [] + worker-dedicated-importscripts.sub.html: [] + # Avoid duplicate subtest for 'sec-fetch-site - HTTPS downgrade-upgrade' + appcache-manifest.sub.https.html: [] + css-images.sub.html: + - filename_flags: [tentative] + element-a.sub.html: [{}] + element-area.sub.html: [{}] + element-audio.sub.html: [{}] + element-img.sub.html: + # srcset omitted because it is not "optionally-blockable" + # https://w3c.github.io/webappsec-mixed-content/#category-optionally-blockable + - sourceAttr: src + element-input-image.sub.html: [{}] + element-meta-refresh.optional.sub.html: [{}] + element-video.sub.html: [{}] + element-video-poster.sub.html: [{}] + form-submission.sub.html: + - method: GET + - method: POST + header-refresh.optional.sub.html: [{}] + svg-image.sub.html: [{}] + window-location.sub.html: [{}] + + # Sec-Fetch-Mode + # These tests are served over HTTPS so the induced requests will be both + # same-origin with the document [1] and a potentially-trustworthy URL [2]. + # + # [1] https://html.spec.whatwg.org/multipage/origin.html#same-origin + # [2] https://w3c.github.io/webappsec-secure-contexts/#potentially-trustworthy-url + - common_axis: + - headerName: sec-fetch-mode + filename_flags: [https] + origins: [] + template_axes: + appcache-manifest.sub.https.html: + - expected: no-cors + audioworklet.https.sub.html: + # https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script + - expected: cors + css-images.sub.html: + - expected: no-cors + filename_flags: [tentative] + css-font-face.sub.html: + - expected: cors + filename_flags: [tentative] + element-a.sub.html: + - expected: navigate + # https://html.spec.whatwg.org/multipage/links.html#downloading-hyperlinks + - elementAttrs: {download: ''} + expected: no-cors + element-area.sub.html: + - expected: navigate + # https://html.spec.whatwg.org/multipage/links.html#downloading-hyperlinks + - elementAttrs: {download: ''} + expected: no-cors + element-audio.sub.html: + - expected: no-cors + - expected: cors + elementAttrs: { crossorigin: '' } + - expected: cors + elementAttrs: { crossorigin: anonymous } + - expected: cors + elementAttrs: { crossorigin: use-credentials } + element-embed.sub.html: + - expected: no-cors + element-frame.sub.html: + - expected: navigate + element-iframe.sub.html: + - expected: navigate + element-img.sub.html: + - sourceAttr: src + expected: no-cors + - sourceAttr: src + expected: cors + elementAttrs: { crossorigin: '' } + - sourceAttr: src + expected: cors + elementAttrs: { crossorigin: anonymous } + - sourceAttr: src + expected: cors + elementAttrs: { crossorigin: use-credentials } + - sourceAttr: srcset + expected: no-cors + - sourceAttr: srcset + expected: cors + elementAttrs: { crossorigin: '' } + - sourceAttr: srcset + expected: cors + elementAttrs: { crossorigin: anonymous } + - sourceAttr: srcset + expected: cors + elementAttrs: { crossorigin: use-credentials } + element-img-environment-change.sub.html: + - expected: no-cors + - expected: cors + elementAttrs: { crossorigin: '' } + - expected: cors + elementAttrs: { crossorigin: anonymous } + - expected: cors + elementAttrs: { crossorigin: use-credentials } + element-input-image.sub.html: + - expected: no-cors + element-link-icon.sub.html: + - expected: no-cors + - expected: cors + elementAttrs: { crossorigin: '' } + - expected: cors + elementAttrs: { crossorigin: anonymous } + - expected: cors + elementAttrs: { crossorigin: use-credentials } + element-link-prefetch.optional.sub.html: + - expected: no-cors + - expected: cors + elementAttrs: { crossorigin: '' } + - expected: cors + elementAttrs: { crossorigin: anonymous } + - expected: cors + elementAttrs: { crossorigin: use-credentials } + element-meta-refresh.optional.sub.html: + - expected: navigate + element-picture.sub.html: + - expected: no-cors + - expected: cors + elementAttrs: { crossorigin: '' } + - expected: cors + elementAttrs: { crossorigin: anonymous } + - expected: cors + elementAttrs: { crossorigin: use-credentials } + element-script.sub.html: + - expected: no-cors + - expected: cors + elementAttrs: { type: module } + - expected: cors + elementAttrs: { crossorigin: '' } + - expected: cors + elementAttrs: { crossorigin: anonymous } + - expected: cors + elementAttrs: { crossorigin: use-credentials } + element-video.sub.html: + - expected: no-cors + - expected: cors + elementAttrs: { crossorigin: '' } + - expected: cors + elementAttrs: { crossorigin: anonymous } + - expected: cors + elementAttrs: { crossorigin: use-credentials } + element-video-poster.sub.html: + - expected: no-cors + fetch.sub.html: + - expected: cors + - expected: cors + init: { mode: cors } + - expected: no-cors + init: { mode: no-cors } + - expected: same-origin + init: { mode: same-origin } + fetch-via-serviceworker.https.sub.html: + - expected: cors + - expected: cors + init: { mode: cors } + - expected: no-cors + init: { mode: no-cors } + - expected: same-origin + init: { mode: same-origin } + form-submission.sub.html: + - method: GET + expected: navigate + - method: POST + expected: navigate + header-link.sub.html: + - rel: icon + expected: no-cors + - rel: stylesheet + expected: no-cors + header-refresh.optional.sub.html: + - expected: navigate + window-history.sub.html: + - expected: navigate + window-location.sub.html: + - expected: navigate + script-module-import-dynamic.sub.html: + - expected: cors + script-module-import-static.sub.html: + - expected: cors + # https://svgwg.org/svg2-draft/linking.html#processingURL-fetch + svg-image.sub.html: + - expected: no-cors + - expected: cors + elementAttrs: { crossorigin: '' } + - expected: cors + elementAttrs: { crossorigin: anonymous } + - expected: cors + elementAttrs: { crossorigin: use-credentials } + serviceworker.https.sub.html: + - expected: same-origin + options: { type: 'classic' } + # https://github.com/whatwg/html/pull/5875 + - expected: same-origin + worker-dedicated-constructor.sub.html: + - expected: same-origin + - options: { type: module } + expected: same-origin + worker-dedicated-importscripts.sub.html: + - expected: no-cors + + # Sec-Fetch-Dest + - common_axis: + - headerName: sec-fetch-dest + filename_flags: [https] + origins: [] + template_axes: + appcache-manifest.sub.https.html: + - expected: empty + audioworklet.https.sub.html: + # https://github.com/WebAudio/web-audio-api/issues/2203 + - expected: audioworklet + css-images.sub.html: + - expected: image + filename_flags: [tentative] + css-font-face.sub.html: + - expected: font + filename_flags: [tentative] + element-a.sub.html: + - expected: document + # https://html.spec.whatwg.org/multipage/links.html#downloading-hyperlinks + - elementAttrs: {download: ''} + expected: empty + element-area.sub.html: + - expected: document + # https://html.spec.whatwg.org/multipage/links.html#downloading-hyperlinks + - elementAttrs: {download: ''} + expected: empty + element-audio.sub.html: + - expected: audio + element-embed.sub.html: + - expected: embed + element-frame.sub.html: + # https://github.com/whatwg/html/pull/4976 + - expected: frame + element-iframe.sub.html: + # https://github.com/whatwg/html/pull/4976 + - expected: iframe + element-img.sub.html: + - sourceAttr: src + expected: image + - sourceAttr: srcset + expected: image + element-img-environment-change.sub.html: + - expected: image + element-input-image.sub.html: + - expected: image + element-link-icon.sub.html: + - expected: empty + element-link-prefetch.optional.sub.html: + - expected: empty + - elementAttrs: { as: audio } + expected: audio + - elementAttrs: { as: document } + expected: document + - elementAttrs: { as: embed } + expected: embed + - elementAttrs: { as: fetch } + expected: fetch + - elementAttrs: { as: font } + expected: font + - elementAttrs: { as: image } + expected: image + - elementAttrs: { as: object } + expected: object + - elementAttrs: { as: script } + expected: script + - elementAttrs: { as: style } + expected: style + - elementAttrs: { as: track } + expected: track + - elementAttrs: { as: video } + expected: video + - elementAttrs: { as: worker } + expected: worker + element-meta-refresh.optional.sub.html: + - expected: document + element-picture.sub.html: + - expected: image + element-script.sub.html: + - expected: script + element-video.sub.html: + - expected: video + element-video-poster.sub.html: + - expected: image + fetch.sub.html: + - expected: empty + fetch-via-serviceworker.https.sub.html: + - expected: empty + form-submission.sub.html: + - method: GET + expected: document + - method: POST + expected: document + header-link.sub.html: + - rel: icon + expected: empty + - rel: stylesheet + filename_flags: [tentative] + expected: style + header-refresh.optional.sub.html: + - expected: document + window-history.sub.html: + - expected: document + window-location.sub.html: + - expected: document + script-module-import-dynamic.sub.html: + - expected: script + script-module-import-static.sub.html: + - expected: script + serviceworker.https.sub.html: + - expected: serviceworker + # Implemented as "image" in Chromium and Firefox, but specified as + # "empty" + # https://github.com/w3c/svgwg/issues/782 + svg-image.sub.html: + - expected: empty + worker-dedicated-constructor.sub.html: + - expected: worker + - options: { type: module } + expected: worker + worker-dedicated-importscripts.sub.html: + - expected: script + + # Sec-Fetch-User + - common_axis: + - headerName: sec-fetch-user + filename_flags: [https] + origins: [] + template_axes: + appcache-manifest.sub.https.html: + - expected: NULL + audioworklet.https.sub.html: + - expected: NULL + css-images.sub.html: + - expected: NULL + filename_flags: [tentative] + css-font-face.sub.html: + - expected: NULL + filename_flags: [tentative] + element-a.sub.html: + - expected: NULL + - userActivated: TRUE + expected: ?1 + element-area.sub.html: + - expected: NULL + - userActivated: TRUE + expected: ?1 + element-audio.sub.html: + - expected: NULL + element-embed.sub.html: + - expected: NULL + element-frame.sub.html: + - expected: NULL + - userActivated: TRUE + expected: ?1 + element-iframe.sub.html: + - expected: NULL + - userActivated: TRUE + expected: ?1 + element-img.sub.html: + - sourceAttr: src + expected: NULL + - sourceAttr: srcset + expected: NULL + element-img-environment-change.sub.html: + - expected: NULL + element-input-image.sub.html: + - expected: NULL + element-link-icon.sub.html: + - expected: NULL + element-link-prefetch.optional.sub.html: + - expected: NULL + element-meta-refresh.optional.sub.html: + - expected: NULL + element-picture.sub.html: + - expected: NULL + element-script.sub.html: + - expected: NULL + element-video.sub.html: + - expected: NULL + element-video-poster.sub.html: + - expected: NULL + fetch.sub.html: + - expected: NULL + fetch-via-serviceworker.https.sub.html: + - expected: NULL + form-submission.sub.html: + - method: GET + expected: NULL + - method: GET + userActivated: TRUE + expected: ?1 + - method: POST + expected: NULL + - method: POST + userActivated: TRUE + expected: ?1 + header-link.sub.html: + - rel: icon + expected: NULL + - rel: stylesheet + expected: NULL + header-refresh.optional.sub.html: + - expected: NULL + window-history.sub.html: + - expected: NULL + window-location.sub.html: + - expected: NULL + - userActivated: TRUE + expected: ?1 + script-module-import-dynamic.sub.html: + - expected: NULL + script-module-import-static.sub.html: + - expected: NULL + serviceworker.https.sub.html: + - expected: NULL + svg-image.sub.html: + - expected: NULL + worker-dedicated-constructor.sub.html: + - expected: NULL + - options: { type: module } + expected: NULL + worker-dedicated-importscripts.sub.html: + - expected: NULL diff --git a/fetch/metadata/tools/generate.py b/fetch/metadata/tools/generate.py new file mode 100755 index 00000000000000..9475ab3e2b3fb9 --- /dev/null +++ b/fetch/metadata/tools/generate.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python3 + +import itertools +import os + +import jinja2 +import yaml + +HERE = os.path.abspath(os.path.dirname(__file__)) +PROJECT_ROOT = os.path.join(HERE, '..', '..', '..') + +def find_templates(starting_directory): + for directory, subdirectories, file_names in os.walk(starting_directory): + for file_name in file_names: + if file_name.startswith('.'): + continue + yield file_name, os.path.join(directory, file_name) + +def test_name(directory, template_name, subtest_flags): + ''' + Create a test name based on a template and the WPT file name flags [1] + required for a given subtest. This name is used to determine how subtests + may be grouped together. In order to promote grouping, the combination uses + a few aspects of how file name flags are interpreted: + + - repeated flags have no effect, so duplicates are removed + - flag sequence does not matter, so flags are consistently sorted + + directory | template_name | subtest_flags | result + ----------|------------------|-----------------|------- + cors | image.html | [] | cors/image.html + cors | image.https.html | [] | cors/image.https.html + cors | image.html | [https] | cors/image.https.html + cors | image.https.html | [https] | cors/image.https.html + cors | image.https.html | [https] | cors/image.https.html + cors | image.sub.html | [https] | cors/image.https.sub.html + cors | image.https.html | [sub] | cors/image.https.sub.html + + [1] docs/writing-tests/file-names.md + ''' + template_name_parts = template_name.split('.') + flags = set(subtest_flags) | set(template_name_parts[1:-1]) + test_name_parts = ( + [template_name_parts[0]] + + sorted(flags) + + [template_name_parts[-1]] + ) + return os.path.join(directory, '.'.join(test_name_parts)) + +def merge(a, b): + if type(a) != type(b): + raise Exception('Cannot merge disparate types') + if type(a) == list: + return a + b + if type(a) == dict: + merged = {} + + for key in a: + if key in b: + merged[key] = merge(a[key], b[key]) + else: + merged[key] = a[key] + + for key in b: + if not key in a: + merged[key] = b[key] + + return merged + + raise Exception('Cannot merge {} type'.format(type(a).__name__)) + +def product(a, b): + ''' + Given two lists of objects, compute their Cartesian product by merging the + elements together. For example, + + product( + [{'a': 1}, {'b': 2}], + [{'c': 3}, {'d': 4}, {'e': 5}] + ) + + returns the following list: + + [ + {'a': 1, 'c': 3}, + {'a': 1, 'd': 4}, + {'a': 1, 'e': 5}, + {'b': 2, 'c': 3}, + {'b': 2, 'd': 4}, + {'b': 2, 'e': 5} + ] + ''' + result = [] + + for a_object in a: + for b_object in b: + result.append(merge(a_object, b_object)) + + return result + +def make_provenance(project_root, cases, template): + return '\n'.join([ + 'This test was procedurally generated. Please do not modify it directly.', + 'Sources:', + '- {}'.format(os.path.relpath(cases, project_root)), + '- {}'.format(os.path.relpath(template, project_root)) + ]) + +def collection_filter(obj, title): + if not obj: + return 'no {}'.format(title) + + members = [] + for name, value in obj.items(): + if value is '': + members.append(name) + else: + members.append('{}={}'.format(name, value)) + + return '{}: {}'.format(title, ', '.join(members)) + +def pad_filter(value, side, padding): + if not value: + return '' + if side == 'start': + return padding + value + + return value + padding + +def main(config_file): + with open(config_file, 'r') as handle: + config = yaml.safe_load(handle.read()) + + templates_directory = os.path.normpath( + os.path.join(os.path.dirname(config_file), config['templates']) + ) + + environment = jinja2.Environment( + variable_start_string='[%', + variable_end_string='%]' + ) + environment.filters['collection'] = collection_filter + environment.filters['pad'] = pad_filter + templates = {} + subtests = {} + + for template_name, path in find_templates(templates_directory): + subtests[template_name] = [] + with open(path, 'r') as handle: + templates[template_name] = environment.from_string(handle.read()) + + for case in config['cases']: + unused_templates = set(templates) - set(case['template_axes']) + + # This warning is intended to help authors avoid mistakenly omitting + # templates. It can be silenced by extending the`template_axes` + # dictionary with an empty list for templates which are intentionally + # unused. + if unused_templates: + print( + 'Warning: case does not reference the following templates:' + ) + print('\n'.join('- {}'.format(name) for name in unused_templates)) + + common_axis = product( + case['common_axis'], [case.get('all_subtests', {})] + ) + + for template_name, template_axis in case['template_axes'].items(): + subtests[template_name].extend(product(common_axis, template_axis)) + + for template_name, template in templates.items(): + provenance = make_provenance( + PROJECT_ROOT, + config_file, + os.path.join(templates_directory, template_name) + ) + get_filename = lambda subtest: test_name( + config['output_directory'], + template_name, + subtest['filename_flags'] + ) + subtests_by_filename = itertools.groupby( + sorted(subtests[template_name], key=get_filename), + key=get_filename + ) + for filename, some_subtests in subtests_by_filename: + with open(filename, 'w') as handle: + handle.write(templates[template_name].render( + subtests=list(some_subtests), + provenance=provenance + ) + '\n') + +if __name__ == '__main__': + main('fetch-metadata.conf.yml') diff --git a/fetch/metadata/tools/requirements.txt b/fetch/metadata/tools/requirements.txt new file mode 100644 index 00000000000000..c28e0a8b96f501 --- /dev/null +++ b/fetch/metadata/tools/requirements.txt @@ -0,0 +1,3 @@ +Jinja2==2.10.3 +MarkupSafe==1.1.1 +PyYAML==5.2 diff --git a/fetch/metadata/tools/templates/appcache-manifest.sub.https.html b/fetch/metadata/tools/templates/appcache-manifest.sub.https.html new file mode 100644 index 00000000000000..0dfc084f2e3442 --- /dev/null +++ b/fetch/metadata/tools/templates/appcache-manifest.sub.https.html @@ -0,0 +1,63 @@ + + + + + HTTP headers on request for Appcache manifest + + + + + + + diff --git a/fetch/metadata/tools/templates/audioworklet.https.sub.html b/fetch/metadata/tools/templates/audioworklet.https.sub.html new file mode 100644 index 00000000000000..7be309c50685ec --- /dev/null +++ b/fetch/metadata/tools/templates/audioworklet.https.sub.html @@ -0,0 +1,53 @@ + + + + + HTTP headers on request for AudioWorklet module + + + + + + + + + diff --git a/fetch/metadata/tools/templates/css-font-face.sub.html b/fetch/metadata/tools/templates/css-font-face.sub.html new file mode 100644 index 00000000000000..94b33f4e6b004a --- /dev/null +++ b/fetch/metadata/tools/templates/css-font-face.sub.html @@ -0,0 +1,60 @@ + + + + + HTTP headers on request for CSS font-face + + + + + + + diff --git a/fetch/metadata/tools/templates/css-images.sub.html b/fetch/metadata/tools/templates/css-images.sub.html new file mode 100644 index 00000000000000..e394f9f5b06256 --- /dev/null +++ b/fetch/metadata/tools/templates/css-images.sub.html @@ -0,0 +1,137 @@ + + + + + {%- if subtests|length > 10 %} + + {%- endif %} + HTTP headers on request for CSS image-accepting properties + + + + + + + diff --git a/fetch/metadata/tools/templates/element-a.sub.html b/fetch/metadata/tools/templates/element-a.sub.html new file mode 100644 index 00000000000000..2bd8e8a40e08e4 --- /dev/null +++ b/fetch/metadata/tools/templates/element-a.sub.html @@ -0,0 +1,72 @@ + + + + + {%- if subtests|length > 10 %} + + {%- endif %} + HTTP headers on request for HTML "a" element navigation + + + {%- if subtests|selectattr('userActivated')|list %} + + + {%- endif %} + + + + + diff --git a/fetch/metadata/tools/templates/element-area.sub.html b/fetch/metadata/tools/templates/element-area.sub.html new file mode 100644 index 00000000000000..0cef5b2294118a --- /dev/null +++ b/fetch/metadata/tools/templates/element-area.sub.html @@ -0,0 +1,72 @@ + + + + + {%- if subtests|length > 10 %} + + {%- endif %} + HTTP headers on request for HTML "area" element navigation + + + {%- if subtests|selectattr('userActivated')|list %} + + + {%- endif %} + + + + + diff --git a/fetch/metadata/tools/templates/element-audio.sub.html b/fetch/metadata/tools/templates/element-audio.sub.html new file mode 100644 index 00000000000000..92bc22198e72a6 --- /dev/null +++ b/fetch/metadata/tools/templates/element-audio.sub.html @@ -0,0 +1,51 @@ + + + + + HTTP headers on request for HTML "audio" element source + + + + + + + diff --git a/fetch/metadata/tools/templates/element-embed.sub.html b/fetch/metadata/tools/templates/element-embed.sub.html new file mode 100644 index 00000000000000..18ce09e5fdc6e1 --- /dev/null +++ b/fetch/metadata/tools/templates/element-embed.sub.html @@ -0,0 +1,54 @@ + + + + + HTTP headers on request for HTML "embed" element source + + + + + + + diff --git a/fetch/metadata/tools/templates/element-frame.sub.html b/fetch/metadata/tools/templates/element-frame.sub.html new file mode 100644 index 00000000000000..ce90171779ab07 --- /dev/null +++ b/fetch/metadata/tools/templates/element-frame.sub.html @@ -0,0 +1,62 @@ + + + + + HTTP headers on request for HTML "frame" element source + + + {%- if subtests|selectattr('userActivated')|list %} + + + {%- endif %} + + + + + diff --git a/fetch/metadata/tools/templates/element-iframe.sub.html b/fetch/metadata/tools/templates/element-iframe.sub.html new file mode 100644 index 00000000000000..43a632a15cd3cb --- /dev/null +++ b/fetch/metadata/tools/templates/element-iframe.sub.html @@ -0,0 +1,62 @@ + + + + + HTTP headers on request for HTML "frame" element source + + + {%- if subtests|selectattr('userActivated')|list %} + + + {%- endif %} + + + + + diff --git a/fetch/metadata/tools/templates/element-img-environment-change.sub.html b/fetch/metadata/tools/templates/element-img-environment-change.sub.html new file mode 100644 index 00000000000000..5a65114f184a55 --- /dev/null +++ b/fetch/metadata/tools/templates/element-img-environment-change.sub.html @@ -0,0 +1,78 @@ + + + + + HTTP headers on image request triggered by change to environment + + + + + + + diff --git a/fetch/metadata/tools/templates/element-img.sub.html b/fetch/metadata/tools/templates/element-img.sub.html new file mode 100644 index 00000000000000..1dac5843ecda0c --- /dev/null +++ b/fetch/metadata/tools/templates/element-img.sub.html @@ -0,0 +1,52 @@ + + + + + HTTP headers on request for HTML "img" element source + + + + + + + diff --git a/fetch/metadata/tools/templates/element-input-image.sub.html b/fetch/metadata/tools/templates/element-input-image.sub.html new file mode 100644 index 00000000000000..3c50008433c385 --- /dev/null +++ b/fetch/metadata/tools/templates/element-input-image.sub.html @@ -0,0 +1,48 @@ + + + + + HTTP headers on request for HTML "input" element with type="button" + + + + + + + diff --git a/fetch/metadata/tools/templates/element-link-icon.sub.html b/fetch/metadata/tools/templates/element-link-icon.sub.html new file mode 100644 index 00000000000000..18ce12a6898711 --- /dev/null +++ b/fetch/metadata/tools/templates/element-link-icon.sub.html @@ -0,0 +1,75 @@ + + + + + {%- if subtests|length > 10 %} + + {%- endif %} + HTTP headers on request for HTML "link" element with rel="icon" + + + + + + + diff --git a/fetch/metadata/tools/templates/element-link-prefetch.optional.sub.html b/fetch/metadata/tools/templates/element-link-prefetch.optional.sub.html new file mode 100644 index 00000000000000..59d677d8d67f57 --- /dev/null +++ b/fetch/metadata/tools/templates/element-link-prefetch.optional.sub.html @@ -0,0 +1,71 @@ + + + + + {%- if subtests|length > 10 %} + + {%- endif %} + HTTP headers on request for HTML "link" element with rel="prefetch" + + + + + + + + diff --git a/fetch/metadata/tools/templates/element-meta-refresh.optional.sub.html b/fetch/metadata/tools/templates/element-meta-refresh.optional.sub.html new file mode 100644 index 00000000000000..5a8d8f8ecd270f --- /dev/null +++ b/fetch/metadata/tools/templates/element-meta-refresh.optional.sub.html @@ -0,0 +1,60 @@ + + + + + HTTP headers on request for HTML "meta" element with http-equiv="refresh" + + + + + + + diff --git a/fetch/metadata/tools/templates/element-picture.sub.html b/fetch/metadata/tools/templates/element-picture.sub.html new file mode 100644 index 00000000000000..903aeed1f376f3 --- /dev/null +++ b/fetch/metadata/tools/templates/element-picture.sub.html @@ -0,0 +1,101 @@ + + + + + HTTP headers on request for HTML "picture" element source + + + + + + + + diff --git a/fetch/metadata/tools/templates/element-script.sub.html b/fetch/metadata/tools/templates/element-script.sub.html new file mode 100644 index 00000000000000..4a281ae5192832 --- /dev/null +++ b/fetch/metadata/tools/templates/element-script.sub.html @@ -0,0 +1,54 @@ + + + + + HTTP headers on request for HTML "script" element source + + + + + + diff --git a/fetch/metadata/tools/templates/element-video-poster.sub.html b/fetch/metadata/tools/templates/element-video-poster.sub.html new file mode 100644 index 00000000000000..9cdaf063ace4ed --- /dev/null +++ b/fetch/metadata/tools/templates/element-video-poster.sub.html @@ -0,0 +1,62 @@ + + + + + HTTP headers on request for HTML "video" element "poster" + + + + + + + diff --git a/fetch/metadata/tools/templates/element-video.sub.html b/fetch/metadata/tools/templates/element-video.sub.html new file mode 100644 index 00000000000000..1b7b976d7c4d86 --- /dev/null +++ b/fetch/metadata/tools/templates/element-video.sub.html @@ -0,0 +1,51 @@ + + + + + HTTP headers on request for HTML "video" element source + + + + + + + diff --git a/fetch/metadata/tools/templates/fetch-via-serviceworker.https.sub.html b/fetch/metadata/tools/templates/fetch-via-serviceworker.https.sub.html new file mode 100644 index 00000000000000..fdd9f41940e1f0 --- /dev/null +++ b/fetch/metadata/tools/templates/fetch-via-serviceworker.https.sub.html @@ -0,0 +1,86 @@ + + + + + HTTP headers on request using the "fetch" API and passing through a Serive Worker + + + + + + + + + diff --git a/fetch/metadata/tools/templates/fetch.sub.html b/fetch/metadata/tools/templates/fetch.sub.html new file mode 100644 index 00000000000000..a8dc5368f8b545 --- /dev/null +++ b/fetch/metadata/tools/templates/fetch.sub.html @@ -0,0 +1,42 @@ + + + + + HTTP headers on request using the "fetch" API + + + + + + + diff --git a/fetch/metadata/tools/templates/form-submission.sub.html b/fetch/metadata/tools/templates/form-submission.sub.html new file mode 100644 index 00000000000000..cbf7b5ca7f3eab --- /dev/null +++ b/fetch/metadata/tools/templates/form-submission.sub.html @@ -0,0 +1,86 @@ + + + + + HTTP headers on request for HTML form navigation + + + {%- if subtests|selectattr('userActivated')|list %} + + + {%- endif %} + + + + + diff --git a/fetch/metadata/tools/templates/header-link.sub.html b/fetch/metadata/tools/templates/header-link.sub.html new file mode 100644 index 00000000000000..2831f221d5c8ac --- /dev/null +++ b/fetch/metadata/tools/templates/header-link.sub.html @@ -0,0 +1,56 @@ + + + + + HTTP headers on request for HTTP "Link" header + + + + + + + diff --git a/fetch/metadata/tools/templates/header-refresh.optional.sub.html b/fetch/metadata/tools/templates/header-refresh.optional.sub.html new file mode 100644 index 00000000000000..ff497b5915b969 --- /dev/null +++ b/fetch/metadata/tools/templates/header-refresh.optional.sub.html @@ -0,0 +1,56 @@ + + + + + HTTP headers on request for HTTP "Refresh" header + + + + + + + diff --git a/fetch/metadata/tools/templates/script-module-import-dynamic.sub.html b/fetch/metadata/tools/templates/script-module-import-dynamic.sub.html new file mode 100644 index 00000000000000..653d3cdec44ae4 --- /dev/null +++ b/fetch/metadata/tools/templates/script-module-import-dynamic.sub.html @@ -0,0 +1,35 @@ + + + + + HTTP headers on request for dynamic ECMAScript module import + + + + + diff --git a/fetch/metadata/tools/templates/script-module-import-static.sub.html b/fetch/metadata/tools/templates/script-module-import-static.sub.html new file mode 100644 index 00000000000000..c8d5f9532a94e6 --- /dev/null +++ b/fetch/metadata/tools/templates/script-module-import-static.sub.html @@ -0,0 +1,53 @@ + + + + + HTTP headers on request for static ECMAScript module import + + + + + + diff --git a/fetch/metadata/tools/templates/serviceworker.https.sub.html b/fetch/metadata/tools/templates/serviceworker.https.sub.html new file mode 100644 index 00000000000000..82843255469e9c --- /dev/null +++ b/fetch/metadata/tools/templates/serviceworker.https.sub.html @@ -0,0 +1,72 @@ + + + + + + HTTP headers on request for Service Workers + + + + + + + diff --git a/fetch/metadata/tools/templates/svg-image.sub.html b/fetch/metadata/tools/templates/svg-image.sub.html new file mode 100644 index 00000000000000..52f7806b33c300 --- /dev/null +++ b/fetch/metadata/tools/templates/svg-image.sub.html @@ -0,0 +1,75 @@ + + + + + {%- if subtests|length > 10 %} + + {%- endif %} + HTTP headers on request for SVG "image" element source + + + + + + + diff --git a/fetch/metadata/tools/templates/window-history.sub.html b/fetch/metadata/tools/templates/window-history.sub.html new file mode 100644 index 00000000000000..286d019887d466 --- /dev/null +++ b/fetch/metadata/tools/templates/window-history.sub.html @@ -0,0 +1,134 @@ + + + + + {%- if subtests|length > 10 %} + + {%- endif %} + HTTP headers on request for navigation via the HTML History API + + + {%- if subtests|selectattr('userActivated')|list %} + + + {%- endif %} + + + + + diff --git a/fetch/metadata/tools/templates/window-location.sub.html b/fetch/metadata/tools/templates/window-location.sub.html new file mode 100644 index 00000000000000..96f3912361633f --- /dev/null +++ b/fetch/metadata/tools/templates/window-location.sub.html @@ -0,0 +1,128 @@ + + + + + {%- if subtests|length > 10 %} + + {%- endif %} + HTTP headers on request for navigation via the HTML Location API + + + {%- if subtests|selectattr('userActivated')|list %} + + + {%- endif %} + + + + + diff --git a/fetch/metadata/tools/templates/worker-dedicated-constructor.sub.html b/fetch/metadata/tools/templates/worker-dedicated-constructor.sub.html new file mode 100644 index 00000000000000..fede5965d3aaa7 --- /dev/null +++ b/fetch/metadata/tools/templates/worker-dedicated-constructor.sub.html @@ -0,0 +1,49 @@ + + + + + HTTP headers on request for dedicated worker via the "Worker" constructor + + + + + diff --git a/fetch/metadata/tools/templates/worker-dedicated-importscripts.sub.html b/fetch/metadata/tools/templates/worker-dedicated-importscripts.sub.html new file mode 100644 index 00000000000000..93e6374d54baa6 --- /dev/null +++ b/fetch/metadata/tools/templates/worker-dedicated-importscripts.sub.html @@ -0,0 +1,54 @@ + + + + + HTTP headers on request for dedicated worker via the "importScripts" API + + + + + diff --git a/lint.ignore b/lint.ignore index ef36a259a6b1ed..fd01861553513e 100644 --- a/lint.ignore +++ b/lint.ignore @@ -153,6 +153,8 @@ SET TIMEOUT: css/selectors/selector-required-type-change-002.html SET TIMEOUT: encrypted-media/polyfill/chrome-polyfill.js SET TIMEOUT: encrypted-media/polyfill/clearkey-polyfill.js SET TIMEOUT: encrypted-media/scripts/playback-temporary-events.js +SET TIMEOUT: fetch/metadata/resources/helper.sub.js +SET TIMEOUT: fetch/metadata/resources/message-opener.html SET TIMEOUT: focus/support/iframe-focus-with-different-site-intermediate-frame-outer.sub.html SET TIMEOUT: focus/support/iframe-focus-with-different-site-intermediate-frame-middle.sub.html SET TIMEOUT: focus/support/iframe-contentwindow-focus-with-different-site-intermediate-frame-outer.sub.html diff --git a/tools/ci/requirements_build.txt b/tools/ci/requirements_build.txt index 645592da36f3c8..8e10a0f997c4ee 100644 --- a/tools/ci/requirements_build.txt +++ b/tools/ci/requirements_build.txt @@ -1,4 +1,5 @@ cairocffi==1.3.0 fonttools==4.33.2 genshi==0.7.7 +jinja2==3.1.1 pyyaml==6.0 diff --git a/tools/ci/update_built.py b/tools/ci/update_built.py index aadaba64f5db52..ffd6a280736bbc 100644 --- a/tools/ci/update_built.py +++ b/tools/ci/update_built.py @@ -20,6 +20,7 @@ # "css/css-text-decor/tools/generate-text-emphasis-position-property-tests.py", # "css/css-text-decor/tools/generate-text-emphasis-ruby-tests.py", # "css/css-text-decor/tools/generate-text-emphasis-style-property-tests.py"], + "fetch": ["fetch/metadata/tools/generate.py"], "html5lib": ["html/tools/update_html5lib_tests.py"], "infrastructure": ["infrastructure/assumptions/tools/ahem-generate-table.py"], "mimesniff": ["mimesniff/mime-types/resources/generated-mime-types.py"],