Bug 1597342 [wpt PR 20300] - refactoring the fetch metadata tests, a=testonly
authorBlink WPT Bot <blink-w3c-test-autoroller@chromium.org>
Tue, 26 Nov 2019 11:03:56 +0000
changeset 504556 cfce63b63347ff47355f925f5b6fef334e86b4a0
parent 504555 8018f71ccdc6b99ff8fee6cbc88c6d0ea476430a
child 504557 91a06d5c5d1e8701b225d167a2f0a65692681ed2
push id36862
push useraciure@mozilla.com
push dateFri, 29 Nov 2019 21:26:53 +0000
treeherdermozilla-central@b4b10ae558b9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstestonly
bugs1597342, 20300, 1012190, 1917778, 716123
milestone72.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1597342 [wpt PR 20300] - refactoring the fetch metadata tests, a=testonly Automatic update from web-platform-tests refactoring the fetch metadata tests (#20300) TBR=alexmos@chromium.org Bug: 1012190 Change-Id: Ie0baad25c88fd5552cc7e440d438d26606ec9be1 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1917778 Commit-Queue: Yifan Luo <lyf@google.com> Reviewed-by: Mike West <mkwst@chromium.org> Cr-Commit-Position: refs/heads/master@{#716123} -- wpt-commits: d7bdce750674c33f475d82314fd1caf1cb971554 wpt-pr: 20300
testing/web-platform/tests/fetch/metadata/appcache.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/fetch-preflight.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/fetch-via-serviceworker--fallback.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/fetch-via-serviceworker--respondWith.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/fetch.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/fetch.tentative.sub.html
testing/web-platform/tests/fetch/metadata/font.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/history.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/iframe.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/iframe.tentative.sub.html
testing/web-platform/tests/fetch/metadata/img.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/navigation.https.sub.html
testing/web-platform/tests/fetch/metadata/object.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/portal.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/prefetch.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/preload.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/redirect/cross-site-redirect.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/redirect/multiple-redirect-cross-site.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/redirect/multiple-redirect-https-downgrade-upgrade.tentative.sub.html
testing/web-platform/tests/fetch/metadata/redirect/multiple-redirect-same-site.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/redirect/redirect-http-upgrade.tentative.sub.html
testing/web-platform/tests/fetch/metadata/redirect/redirect-https-downgrade.tentative.sub.html
testing/web-platform/tests/fetch/metadata/redirect/same-origin-redirect.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/redirect/same-site-redirect.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/report.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/resources/helper.js
testing/web-platform/tests/fetch/metadata/resources/redirectTestHelper.sub.js
testing/web-platform/tests/fetch/metadata/script.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/script.tentative.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/appcache.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/embed.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/fetch-preflight.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/fetch-via-serviceworker--fallback.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/fetch-via-serviceworker--respondWith.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/fetch.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/fetch.tentative.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/font.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/frame.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/frame.tentative.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/history.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/iframe.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/iframe.tentative.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/img.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/navigation.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/object.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/portal.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/prefetch.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/preload.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/redirect/cross-site-redirect.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/redirect/multiple-redirect-cross-site.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/redirect/multiple-redirect-https-downgrade-upgrade.tentative.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/redirect/multiple-redirect-same-site.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/redirect/redirect-http-upgrade.tentative.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/redirect/redirect-https-downgrade.tentative.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/redirect/same-origin-redirect.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/redirect/same-site-redirect.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/report.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/report.tentative.https.sub.html.sub.headers
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/script.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/script.tentative.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/serviceworker.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/sharedworker.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/style.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/track.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/trailing-dot.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/unload.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/window-open.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/worker.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sec-fetch-dest/xslt.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/serviceworker.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/sharedworker.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/style.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/track.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/trailing-dot.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/unload.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/window-open.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/worker.tentative.https.sub.html
testing/web-platform/tests/fetch/metadata/xslt.tentative.https.sub.html
--- a/testing/web-platform/tests/fetch/metadata/appcache.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/appcache.tentative.https.sub.html
@@ -9,14 +9,15 @@
 <script>
   async_test(t => {
     window.applicationCache.oncached = window.applicationCache.onnoupdate = window.applicationCache.onerror = t.step_func(e => {
         fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=appcache-manifest{{$id}}")
           .then(t.step_func(response => response.text()))
           .then(t.step_func_done(text => assert_header_equals(text, {
             "site": "same-origin",
             "user": "",
-            "mode": "no-cors"
+            "mode": "no-cors",
+            "dest": ""
           })))
           .catch(t.unreached_func("Fetching and verifying the results should succeed."));
 });
 }, "Appcache!");
 </script>
--- a/testing/web-platform/tests/fetch/metadata/fetch-preflight.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/fetch-preflight.tentative.https.sub.html
@@ -1,38 +1,32 @@
 <!DOCTYPE html>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
 <script src=/fetch/metadata/resources/helper.js></script>
 <script>
   // Site
   promise_test(t => {
-    return fetch("https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py",
+    return validate_expectations_custom_url("https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py",
                  {
                    mode: "cors",
                    headers: { 'x-test': 'testing' }
-                 })
-        .then(r => r.json())
-        .then(j => {
-          assert_header_equals(j, {
+                 }, {
             "site": "same-site",
             "user": "",
             "mode": "cors",
-          });
-        });
+            "dest": "empty"
+          }, "Same-site fetch with preflight");
   }, "Same-site fetch with preflight");
 
   promise_test(t => {
-    return fetch("https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py",
+    return validate_expectations_custom_url("https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py",
                  {
                    mode: "cors",
                    headers: { 'x-test': 'testing' }
-                 })
-        .then(r => r.json())
-        .then(j => {
-          assert_header_equals(j, {
+                 }, {
             "site": "cross-site",
             "user": "",
             "mode": "cors",
-          });
-        });
+            "dest": "empty"
+          }, "Cross-site fetch with preflight");
   }, "Cross-site fetch with preflight");
 </script>
--- a/testing/web-platform/tests/fetch/metadata/fetch-via-serviceworker--fallback.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/fetch-via-serviceworker--fallback.tentative.https.sub.html
@@ -39,12 +39,12 @@
         // fetch a special URL that records request headers.
         await frame.contentWindow.fetch(URL, {mode:'no-cors'});
 
         // Retrieve the request headers that have been recorded in the previous step.
         const response = await fetch(RETRIEVAL_URL);
         const text = await response.text();
 
         // Verify presence of the expected Sec-Fetch-... request headers.
-        let expected = {"site":"same-origin", "user":"", "mode": "no-cors"};
+        let expected = {"site":"same-origin", "user":"", "mode": "no-cors", "dest": "empty"};
         assert_header_equals(text, expected);
       }, 'Sec-Fetch headers after SW fallback');
 </script>
--- a/testing/web-platform/tests/fetch/metadata/fetch-via-serviceworker--respondWith.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/fetch-via-serviceworker--respondWith.tentative.https.sub.html
@@ -40,12 +40,12 @@
         // fetch a special URL that records request headers.
         await frame.contentWindow.fetch(URL, {mode:'no-cors'});
 
         // Retrieve the request headers that have been recorder in the previous step.
         const response = await fetch(RETRIEVAL_URL);
         const text = await response.text();
 
         // Verify presence of the expected Sec-Fetch-... request headers.
-        let expected = {"site":"same-origin", "user":"", "mode": "no-cors"};
+        let expected = {"site":"same-origin", "user":"", "mode": "no-cors", "dest": "empty"};
         assert_header_equals(text, expected);
       }, 'Sec-Fetch headers after SW fallback');
 </script>
--- a/testing/web-platform/tests/fetch/metadata/fetch.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/fetch.tentative.https.sub.html
@@ -1,79 +1,61 @@
 <!DOCTYPE html>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
 <script src=/fetch/metadata/resources/helper.js></script>
 <script>
   // Site
   promise_test(t => {
-    return fetch("https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py")
-        .then(r => r.json())
-        .then(j => {
-          assert_header_equals(j, {
+    return validate_expectations_custom_url("https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py", {}, {
             "site": "same-origin",
             "user": "",
             "mode": "cors",
-          });
-        });
+            "dest": "empty"
+          }, "Same-origin fetch");
   }, "Same-origin fetch");
 
   promise_test(t => {
-    return fetch("https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py")
-        .then(r => r.json())
-        .then(j => {
-          assert_header_equals(j, {
+    return validate_expectations_custom_url("https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py", {}, {
             "site": "same-site",
             "user": "",
             "mode": "cors",
-          });
-        });
+            "dest": "empty"
+          }, "Same-site fetch");
   }, "Same-site fetch");
 
   promise_test(t => {
-    return fetch("https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py")
-        .then(r => r.json())
-        .then(j => {
-          assert_header_equals(j, {
+    return validate_expectations_custom_url("https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py", {}, {
             "site": "cross-site",
             "user": "",
             "mode": "cors",
-          });
-        });
+            "dest": "empty"
+          }, "Cross-site fetch");
   }, "Cross-site fetch");
 
   // Mode
   promise_test(t => {
-    return fetch("https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py", {mode: "same-origin"})
-        .then(r => r.json())
-        .then(j => {
-          assert_header_equals(j, {
+    return validate_expectations_custom_url("https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py", {mode: "same-origin"}, {
             "site": "same-origin",
             "user": "",
             "mode": "same-origin",
-          });
-        });
+            "dest": "empty"
+          }, "Same-origin mode");
   }, "Same-origin mode");
 
   promise_test(t => {
-    return fetch("https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py", {mode: "cors"})
-        .then(r => r.json())
-        .then(j => {
-          assert_header_equals(j, {
+    return validate_expectations_custom_url("https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py", {mode: "cors"}, {
             "site": "same-origin",
             "user": "",
             "mode": "cors",
-          });
-        });
+            "dest": "empty"
+          }, "CORS mode");
   }, "CORS mode");
 
   promise_test(t => {
-    return fetch("https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py", {mode: "no-cors"})
-        .then(r => r.json())
-        .then(j => {
-          assert_header_equals(j, {
+    return validate_expectations_custom_url("https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py", {mode: "no-cors"}, {
             "site": "same-origin",
             "user": "",
             "mode": "no-cors",
-          });
-        });
+            "dest": "empty"
+          }, "no-CORS mode");
   }, "no-CORS mode");
 </script>
--- a/testing/web-platform/tests/fetch/metadata/fetch.tentative.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/fetch.tentative.sub.html
@@ -3,33 +3,27 @@
 <script src=/resources/testharnessreport.js></script>
 <script src=/fetch/metadata/resources/helper.js></script>
 <script>
   // http -> https should see `Sec-Fetch-Site: cross-site`.
   // This is a regression test for
   // https://github.com/w3c/webappsec-fetch-metadata/issues/34
   promise_test(t => {
     assert_equals(location.protocol, "http:");
-    return fetch("https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py")
-        .then(r => r.json())
-        .then(j => {
-          assert_header_equals(j, {
+    return validate_expectations_custom_url("https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py", {}, {
             "site": "cross-site",
             "user": "",
             "mode": "cors",
-          });
-        });
+            "dest": "empty"
+          }, "http->https fetch (cross-scheme => cross-site)");
   }, "http->https fetch (cross-scheme => cross-site)");
 
   // http -> http should see no `Sec-Fetch-Site`.
   promise_test(t => {
     assert_equals(location.protocol, "http:");
-    return fetch("resources/echo-as-json.py")
-        .then(r => r.json())
-        .then(j => {
-          assert_header_equals(j, {
+    return validate_expectations_custom_url("resources/echo-as-json.py", {}, {
             "site": "",
             "user": "",
             "mode": "",
-          });
-        });
+            "dest": ""
+          }, "http->http fetch (non-trustworthy destination => no metadata)");
   }, "http->http fetch (non-trustworthy destination => no metadata)");
 </script>
--- a/testing/web-platform/tests/fetch/metadata/font.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/font.tentative.https.sub.html
@@ -41,44 +41,38 @@
     }
   </style>
 </body>
 <script>
   document.fonts.ready.then(function () {
     promise_test(t => {
       return new Promise((resolve, reject) => {
         let key = "font-same-origin";
-        let expected = {"site":"same-origin", "user":"", "mode": "cors"};
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        let expected = {"site":"same-origin", "user":"", "mode": "cors", "dest": "font"};
+        validate_expectations(key, expected, "Same-Origin font")
           .then(_ => resolve())
           .catch(e => reject(e));
         });
     }, "Same-Origin font");
 
     promise_test(t => {
       return new Promise((resolve, reject) => {
         let key = "font-same-site";
-        let expected = {"site":"same-site", "user":"", "mode": "cors"};
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        let expected = {"site":"same-site", "user":"", "mode": "cors", "dest": "font"};
+        validate_expectations(key, expected, "Same-Site font")
           .then(_ => resolve())
           .catch(e => reject(e));
         });
     }, "Same-Site font");
 
     promise_test(t => {
       return new Promise((resolve, reject) => {
         let key = "font-cross-site";
-        let expected = {"site":"cross-site", "user":"", "mode": "cors"};
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        let expected = {"site":"cross-site", "user":"", "mode": "cors", "dest": "font"};
+        validate_expectations(key, expected, "Cross-Site font")
           .then(_ => resolve())
           .catch(e => reject(e));
         });
     }, "Cross-Site font");
 
   });
 </script>
 </html>
--- a/testing/web-platform/tests/fetch/metadata/history.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/history.tentative.https.sub.html
@@ -5,45 +5,45 @@
 <script src=/fetch/metadata/resources/helper.js></script>
 <script>
 
 // Test that correct `Sec-Fetch-Site` (and other `Sec-Fetch-...` request
 /// headers) are used in navigations triggered by |history.back()|.
 function add_test(description, report_host, go_back_host, expectations) {
   async_test(t => {
     // STEP1: Navigate a new window to report_host/post-to-owner.py
-    const url_suffix = '/fetch/metadata/resources/post-to-owner.py'
+    const url_suffix = '/fetch/metadata/resources/post-to-owner.py';
     const url = `https://${report_host}${url_suffix}`;
     const w = window.open(url, '_blank');
 
     var msg_counter = 0;
     window.addEventListener('message', t.step_func(e => {
       if (e.source != w)
         return;
       msg_counter = msg_counter + 1;
       if (msg_counter == 1) {
         // STEP2: Verify the headers (this is a sanity check that the same
         // headers are used here and in STEP5).
-        assert_header_equals(e.data, expectations);
+        assert_header_equals(e.data, expectations, description + " 1");
 
         // STEP3: Go to go_back_host/go-back.html (postponing this via
         // step_timeout ensures that go-back.html will get a separate
         // history entry - otherwise it might be treated as a client-side
         // redirect and we might end up with nowhere to go back to).
         t.step_timeout(() => {
-          const url_suffix = '/fetch/metadata/resources/go-back.html'
+          const url_suffix = '/fetch/metadata/resources/go-back.html';
           const url = `https://${go_back_host}${url_suffix}`;
           w.location = url;
         });
 
         // STEP4 (elsewhere - inside go-back.html): Call history.back().
       } else if (msg_counter == 2) {
         // STEP5: Verify the headers (this is the main verification and focus
         // of the test).
-        assert_header_equals(e.data, expectations);
+        assert_header_equals(e.data, expectations, description + " 2");
 
         // STEP6: Finish the test.
         t.done();
       }
     }));
   }, description);
 }
 
@@ -52,27 +52,33 @@ const same_site_host = "{{hosts[][www]}}
 const cross_site_host = "{{hosts[alt][www]}}:{{ports[https][0]}}";
 
 add_test(
   "back to same-origin-initiated navigation",
   same_origin_host,  // report_host
   cross_site_host,  // go_back_host
   { "site": "same-origin",
     "user": "",
-    "mode": "navigate" });
+    "mode": "navigate",
+    "dest": "document"
+  });
 
 add_test(
   "back to same-site-initiated navigation",
   same_site_host,  // report_host
   cross_site_host,  // go_back_host
   { "site": "same-site",
     "user": "",
-    "mode": "navigate" });
+    "mode": "navigate",
+    "dest": "document"
+  });
 
 add_test(
   "back to cross-site-initiated navigation",
   cross_site_host,  // report_host
   cross_site_host,  // go_back_host
   { "site": "cross-site",
     "user": "",
-    "mode": "navigate" });
+    "mode": "navigate",
+    "dest": "document"
+  });
 
 </script>
--- a/testing/web-platform/tests/fetch/metadata/iframe.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/iframe.tentative.https.sub.html
@@ -12,17 +12,17 @@
 
   function create_test(host, user_activated, expectations) {
     async_test(t => {
       let i = document.createElement('iframe');
       window.addEventListener('message', t.step_func(e => {
         if (e.source != i.contentWindow)
           return;
 
-        assert_header_equals(e.data, expectations);
+        assert_header_equals(e.data, expectations, `{{host}} -> ${host} iframe: ${user_activated ? "user-activated" : "forced"}`);
         t.done();
       }));
 
       let url = `https://${host}/fetch/metadata/resources/post-to-owner.py`;
       if (user_activated == FORCED) {
         i.src = url;
         document.body.appendChild(i);
       } else if (user_activated == USER) {
@@ -39,41 +39,47 @@
         test_driver.click(a);
       }
     }, `{{host}} -> ${host} iframe: ${user_activated ? "user-activated" : "forced"}`);
   }
 
   create_test("{{host}}:{{ports[https][0]}}", FORCED, {
     "site": "same-origin",
     "user": "",
-    "mode": "navigate"
+    "mode": "navigate",
+    "dest": "iframe"
   });
 
   create_test("{{hosts[][www]}}:{{ports[https][0]}}", FORCED, {
     "site": "same-site",
     "user": "",
-    "mode": "navigate"
+    "mode": "navigate",
+    "dest": "iframe"
   });
 
   create_test("{{hosts[alt][www]}}:{{ports[https][0]}}", FORCED, {
     "site": "cross-site",
     "user": "",
-    "mode": "navigate"
+    "mode": "navigate",
+    "dest": "iframe"
   });
 
   create_test("{{host}}:{{ports[https][0]}}", USER, {
     "site": "same-origin",
     "user": "?1",
-    "mode": "navigate"
+    "mode": "navigate",
+    "dest": "iframe"
   });
 
   create_test("{{hosts[][www]}}:{{ports[https][0]}}", USER, {
     "site": "same-site",
     "user": "?1",
-    "mode": "navigate"
+    "mode": "navigate",
+    "dest": "iframe"
   });
 
   create_test("{{hosts[alt][www]}}:{{ports[https][0]}}", USER, {
     "site": "cross-site",
     "user": "?1",
-    "mode": "navigate"
+    "mode": "navigate",
+    "dest": "iframe"
   });
 </script>
--- a/testing/web-platform/tests/fetch/metadata/iframe.tentative.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/iframe.tentative.sub.html
@@ -10,17 +10,18 @@
     window.addEventListener('message', t.step_func(e => {
       if (e.source != i.contentWindow)
         return;
 
       assert_header_equals(e.data, {
         "site": "",
         "user": "",
         "mode": "",
-      });
+        "dest": ""
+      }, "Non-secure same-origin iframe => No headers");
       t.done();
     }));
 
     document.body.appendChild(i);
   }, "Non-secure same-origin iframe => No headers");
 
   async_test(t => {
     let i = document.createElement('iframe');
@@ -28,17 +29,18 @@
     window.addEventListener('message', t.step_func(e => {
       if (e.source != i.contentWindow)
         return;
 
       assert_header_equals(e.data, {
         "site": "",
         "user": "",
         "mode": "",
-      });
+        "dest": ""
+      }, "Non-secure same-site iframe => No headers");
       t.done();
     }));
 
     document.body.appendChild(i);
   }, "Non-secure same-site iframe => No headers");
 
   async_test(t => {
     let i = document.createElement('iframe');
@@ -46,17 +48,18 @@
     window.addEventListener('message', t.step_func(e => {
       if (e.source != i.contentWindow)
         return;
 
       assert_header_equals(e.data, {
         "site": "",
         "user": "",
         "mode": "",
-      });
+        "dest": ""
+      }, "Non-secure cross-site iframe => No headers.");
       t.done();
     }));
 
     document.body.appendChild(i);
   }, "Non-secure cross-site iframe => No headers.");
 
   async_test(t => {
     let i = document.createElement('iframe');
@@ -64,15 +67,16 @@
     window.addEventListener('message', t.step_func(e => {
       if (e.source != i.contentWindow)
         return;
 
       assert_header_equals(e.data, {
         "site": "cross-site",
         "user": "",
         "mode": "navigate",
-      });
+        "dest": "iframe"
+      }, "Secure, cross-site (cross-scheme, same-host) iframe");
       t.done();
     }));
 
     document.body.appendChild(i);
   }, "Secure, cross-site (cross-scheme, same-host) iframe");
 </script>
--- a/testing/web-platform/tests/fetch/metadata/img.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/img.tentative.https.sub.html
@@ -10,60 +10,66 @@
   promise_test(() =>
     requestViaImage(
       "https://{{host}}:{{ports[https][0]}}/common/security-features/subresource/image.py")
     .then(result => {
         headers = result.headers;
         got = {
           "mode": headers["sec-fetch-mode"],
           "site": headers["sec-fetch-site"],
-          "user": headers["sec-fetch-user"]
+          "user": headers["sec-fetch-user"],
+          "dest": headers["sec-fetch-dest"]
         };
         assert_header_equals(got, {
           "site": "same-origin",
           // Note that we're using `undefined` here, as opposed to "" elsewhere because of the way
           // that `image.py` encodes data.
           "user": undefined,
           "mode": "cors", // Because `loadImageInWindow` tacks on `crossorigin`
-        });
+          "dest": "image"
+        }, "Same-origin image");
       }),
     "Same-origin image");
 
   promise_test(() =>
     requestViaImage(
       "https://{{hosts[][www]}}:{{ports[https][0]}}/common/security-features/subresource/image.py")
     .then(result => {
         headers = result.headers;
         got = {
           "mode": headers["sec-fetch-mode"],
           "site": headers["sec-fetch-site"],
-          "user": headers["sec-fetch-user"]
+          "user": headers["sec-fetch-user"],
+          "dest": headers["sec-fetch-dest"]
         };
         assert_header_equals(got, {
           "site": "same-site",
           // Note that we're using `undefined` here, as opposed to "" elsewhere because of the way
           // that `image.py` encodes data.
           "user": undefined,
           "mode": "cors", // Because `loadImageInWindow` tacks on `crossorigin`
-        });
+          "dest": "image"
+        }, "Same-site image");
       }),
     "Same-site image");
 
   promise_test(() =>
     requestViaImage(
       "https://{{hosts[alt][www]}}:{{ports[https][0]}}/common/security-features/subresource/image.py")
     .then(result => {
         headers = result.headers;
         got = {
           "mode": headers["sec-fetch-mode"],
           "site": headers["sec-fetch-site"],
-          "user": headers["sec-fetch-user"]
+          "user": headers["sec-fetch-user"],
+          "dest": headers["sec-fetch-dest"]
         };
         assert_header_equals(got, {
           "site": "cross-site",
           // Note that we're using `undefined` here, as opposed to "" elsewhere because of the way
           // that `image.py` encodes data.
           "user": undefined,
           "mode": "cors", // Because `loadImageInWindow` tacks on `crossorigin`
-        });
+          "dest": "image"
+        }, "Cross-site image");
       }),
     "Cross-site image");
 </script>
--- a/testing/web-platform/tests/fetch/metadata/navigation.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/navigation.https.sub.html
@@ -3,19 +3,21 @@
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
 <script src=/fetch/metadata/resources/helper.js></script>
 <script>
   test(t => {
     let expected = {
       "mode": "navigate",
       "site": "none",
+      "dest": "document"
     };
 
     let actual = {
       "mode": "{{headers[sec-fetch-mode]}}",
       "site": "{{headers[sec-fetch-site]}}",
       // Skipping `Sec-Fetch-User`, as the test harness isn't consistent here.
+      "dest": "{{headers[sec-fetch-dest]}}"
     };
 
     assert_header_equals(actual, expected);
   }, "This page's top-level navigation.");
 </script>
--- a/testing/web-platform/tests/fetch/metadata/object.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/object.tentative.https.sub.html
@@ -11,58 +11,52 @@
 
   promise_test(t => {
     return new Promise((resolve, reject) => {
       let key = "object-same-origin" + nonce;
 
       let e = document.createElement('object');
       e.data = "https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
       e.onload = e => {
-        let expected = {"site":"same-origin", "user":"", "mode":"navigate"};
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        let expected = {"site":"same-origin", "user":"", "mode":"navigate", "dest": "object"};
+        validate_expectations(key, expected, "Same-Origin object")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
 
       document.body.appendChild(e);
     })
   }, "Same-Origin object");
 
   promise_test(t => {
     return new Promise((resolve, reject) => {
       let key = "object-same-site" + nonce;
 
       let e = document.createElement('object');
       e.data = "https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
       e.onload = e => {
-        let expected = {"site":"same-site", "user":"", "mode":"navigate"};
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        let expected = {"site":"same-site", "user":"", "mode":"navigate", "dest": "object"};
+        validate_expectations(key, expected, "Same-Site object")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
 
       document.body.appendChild(e);
     })
   }, "Same-Site object");
 
   promise_test(t => {
     return new Promise((resolve, reject) => {
       let key = "object-cross-site" + nonce;
 
       let e = document.createElement('object');
       e.data = "https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
       e.onload = e => {
-        let expected = {"site":"cross-site", "user":"", "mode":"navigate"};
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        let expected = {"site":"cross-site", "user":"", "mode":"navigate", "dest": "object"};
+        validate_expectations(key, expected, "Cross-Site object")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
 
       document.body.appendChild(e);
     })
   }, "Cross-Site object");
 </script>
--- a/testing/web-platform/tests/fetch/metadata/portal.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/portal.tentative.https.sub.html
@@ -9,36 +9,39 @@
 <script>
   const USER = true;
   const FORCED = false;
 
   function create_test(host, expectations) {
     async_test(t => {
       let p = document.createElement('portal');
       p.addEventListener('message', t.step_func(e => {
-        assert_header_equals(e.data, expectations);
+        assert_header_equals(e.data, expectations, `{{host}} -> ${host} portal`);
         t.done();
       }));
 
       let url = `https://${host}/fetch/metadata/resources/post-to-owner.py`;
       p.src = url;
       document.body.appendChild(p);
     }, `{{host}} -> ${host} portal`);
   }
 
   create_test("{{host}}:{{ports[https][0]}}", {
     "site": "same-origin",
     "user": "",
-    "mode": "navigate"
+    "mode": "navigate",
+    "dest": "document"
   });
 
   create_test("{{hosts[][www]}}:{{ports[https][0]}}", {
     "site": "same-site",
     "user": "",
-    "mode": "navigate"
+    "mode": "navigate",
+    "dest": "document"
   });
 
   create_test("{{hosts[alt][www]}}:{{ports[https][0]}}", {
     "site": "cross-site",
     "user": "",
-    "mode": "navigate"
+    "mode": "navigate",
+    "dest": "document"
   });
 </script>
--- a/testing/web-platform/tests/fetch/metadata/prefetch.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/prefetch.tentative.https.sub.html
@@ -16,21 +16,21 @@
 
       let e = document.createElement('link');
       e.rel = "prefetch";
       e.href = `https://${host}/fetch/metadata/resources/record-header.py?file=${key}`;
       e.setAttribute("crossorigin", "crossorigin");
       e.onload = t.step_func(e => {
         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, expected)))
+          .then(t.step_func_done(text => assert_header_equals(text, expected, `<link rel='prefetch' href='https://${host}/...'>`)))
           .catch(t.unreached_func("Fetching and verifying the results should succeed."));
       });
       e.onerror = t.unreached_func();
 
       document.head.appendChild(e);
     }, `<link rel='prefetch' href='https://${host}/...'>`);
   }
 
-  create_test("{{host}}:{{ports[https][0]}}", {"site":"same-origin", "user":"", "mode": "cors"});
-  create_test("{{hosts[][www]}}:{{ports[https][0]}}", {"site":"same-site", "user":"", "mode": "cors"});
-  create_test("{{hosts[alt][www]}}:{{ports[https][0]}}", {"site":"cross-site", "user":"", "mode": "cors"});
+  create_test("{{host}}:{{ports[https][0]}}", {"site":"same-origin", "user":"", "mode": "cors", "dest": "empty"});
+  create_test("{{hosts[][www]}}:{{ports[https][0]}}", {"site":"same-site", "user":"", "mode": "cors", "dest": "empty"});
+  create_test("{{hosts[alt][www]}}:{{ports[https][0]}}", {"site":"cross-site", "user":"", "mode": "cors", "dest": "empty"});
 </script>
--- a/testing/web-platform/tests/fetch/metadata/preload.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/preload.tentative.https.sub.html
@@ -39,13 +39,13 @@
     [ "font", "font" ],
     [ "image", "image" ],
     [ "script", "script" ],
     [ "style", "style" ],
     [ "track", "track" ],
   ];
 
   as_tests.forEach(item => {
-    create_test("{{host}}:{{ports[https][0]}}", item[0], {"site":"same-origin", "user":"", "mode": "cors"});
-    create_test("{{hosts[][www]}}:{{ports[https][0]}}", item[0], {"site":"same-site", "user":"", "mode": "cors"});
-    create_test("{{hosts[alt][www]}}:{{ports[https][0]}}", item[0], {"site":"cross-site", "user":"", "mode": "cors"});
+    create_test("{{host}}:{{ports[https][0]}}", item[0], {"site":"same-origin", "user":"", "mode": "cors", "dest": item[1]});
+    create_test("{{hosts[][www]}}:{{ports[https][0]}}", item[0], {"site":"same-site", "user":"", "mode": "cors", "dest": item[1]});
+    create_test("{{hosts[alt][www]}}:{{ports[https][0]}}", item[0], {"site":"cross-site", "user":"", "mode": "cors", "dest": item[1]});
   });
 </script>
--- a/testing/web-platform/tests/fetch/metadata/redirect/cross-site-redirect.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/redirect/cross-site-redirect.tentative.https.sub.html
@@ -10,80 +10,68 @@
   let nonce = token();
 
   promise_test(t => {
     return new Promise((resolve, reject) => {
       let key = "redirect-cross-site-same-origin" + nonce;
 
       let e = document.createElement('img');
       e.src = "https://{{hosts[alt][www]}}:{{ports[https][0]}}/xhr/resources/redirect.py?location=https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      let expected = {"site":"cross-site", "user":"", "mode": "no-cors"};
+      let expected = {"site":"cross-site", "user":"", "mode": "no-cors", "dest": "image"};
       e.onload = e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected, "Cross-Site -> Same-Origin redirect")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
       e.onerror = e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected, "Cross-Site -> Same-Origin redirect")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
 
       document.body.appendChild(e);
     })
   }, "Cross-Site -> Same-Origin redirect");
 
   promise_test(t => {
     return new Promise((resolve, reject) => {
       let key = "redirect-cross-site-same-site" + nonce;
 
       let e = document.createElement('img');
       e.src = "https://{{hosts[alt][www]}}:{{ports[https][0]}}/xhr/resources/redirect.py?location=https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      let expected = {"site":"cross-site", "user":"", "mode": "no-cors"};
+      let expected = {"site":"cross-site", "user":"", "mode": "no-cors", "dest": "image"};
       e.onload = e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected, "Cross-Site -> Same-Site redirect")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
       e.onerror = e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected, "Cross-Site -> Same-Site redirect")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
 
       document.body.appendChild(e);
     })
   }, "Cross-Site -> Same-Site redirect");
 
   promise_test(t => {
     return new Promise((resolve, reject) => {
       let key = "redirect-cross-site-cross-site" + nonce;
 
       let e = document.createElement('img');
       e.src = "https://{{hosts[alt][www]}}:{{ports[https][0]}}/xhr/resources/redirect.py?location=https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      let expected = {"site":"cross-site", "user":"", "mode": "no-cors"};
+      let expected = {"site":"cross-site", "user":"", "mode": "no-cors", "dest": "image"};
       e.onload = e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected, "Cross-Site -> Cross-Site redirect")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
       e.onerror = e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected, "Cross-Site -> Cross-Site redirect")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
 
       document.body.appendChild(e);
     })
   }, "Cross-Site -> Cross-Site redirect");
 </script>
--- a/testing/web-platform/tests/fetch/metadata/redirect/multiple-redirect-cross-site.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/redirect/multiple-redirect-cross-site.tentative.https.sub.html
@@ -12,29 +12,25 @@
   promise_test(t => {
     return new Promise((resolve, reject) => {
       let key = "redirect-multiple-cross-site" + nonce;
 
       let e = document.createElement('img');
       e.src = "https://{{host}}:{{ports[https][0]}}/xhr/resources/redirect.py?location=" +// same-origin
       "https://{{hosts[alt][www]}}:{{ports[https][0]}}/xhr/resources/redirect.py?location=" +// cross-site
       "https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;// same-origin
-      let expected = {"site":"cross-site", "user":"", "mode": "no-cors"};
+      let expected = {"site":"cross-site", "user":"", "mode": "no-cors", "dest": "image"};
 
       e.onload = e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected, "Same-Origin -> Cross-Site -> Same-Origin redirect")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
       e.onerror = e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected, "Same-Origin -> Cross-Site -> Same-Origin redirect")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
 
       document.body.appendChild(e);
     })
   }, "Same-Origin -> Cross-Site -> Same-Origin redirect");
 </script>
--- a/testing/web-platform/tests/fetch/metadata/redirect/multiple-redirect-https-downgrade-upgrade.tentative.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/redirect/multiple-redirect-https-downgrade-upgrade.tentative.sub.html
@@ -11,57 +11,63 @@
     font-family: myDowngradeUpgradeFont;
     src: url(https://{{host}}:{{ports[https][0]}}/fetch/api/resources/redirect.py?location=http%3A%2F%2F{{host}}%3A{{ports[http][0]}}%2Ffetch%2Fapi%2Fresources%2Fredirect.py%3Flocation%3Dhttps%253A%252F%252F{{host}}%253A{{ports[https][0]}}%252Ffetch%252Fmetadata%252Fresources%252Frecord-header.py%253Ffile%253Dfont-https-downgrade-upgrade{{$id:uuid()}});
   }
   #fontTest {
     font-family: myDowngradeUpgradeFont;
   }
 </style>
 <body>
-    <div id="fontTest">Downgraded then upgraded font</div>
-    <script>
+<div id="fontTest">Downgraded then upgraded font</div>
+<script>
   let nonce = "{{$id}}";
-  let expected = { "site": "cross-site", "user": "", "mode": "cors" };
+  let expected = {"site": "cross-site", "user": "", "mode": "cors", "dest": ""};
 
   // Validate various scenarios handle a request that redirects from https => http
   // correctly and avoids disclosure of any Sec- headers.
   RunCommonRedirectTests("Https downgrade-upgrade", MultipleRedirectTo, expected);
 
   document.fonts.ready.then(function () {
     promise_test(t => {
       return new Promise((resolve, reject) => {
         let key = "font-https-downgrade-upgrade{{$id}}";
-        return fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
-          .then(_ => resolve())
-          .catch(e => reject(e));
+        return validate_expectations(key, expected, "Https downgrade-upgrade font => No headers")
+            .then(_ => resolve())
+            .catch(e => reject(e));
       });
     }, "Https downgrade-upgrade font => No headers");
   });
 
   promise_test(() => {
-    return requestViaImage(secureRedirectURL + encodeURIComponent(insecureRedirectURL + encodeURIComponent("https://{{host}}:{{ports[https][0]}}/common/security-features/subresource/image.py")))
-      .then(result => {
-         headers = result.headers;
-         got = {
-           "mode": headers["sec-fetch-mode"],
-           "site": headers["sec-fetch-site"],
-           "user": headers["sec-fetch-user"]
-         };
-         assert_header_equals(got, {
-           // Note that we're using `undefined` here, as opposed to "" elsewhere because of the way
-           // that `image.py` encodes data.
-           "site": "cross-site",
-           "user": undefined,
-           "mode": "cors",
-         });
-      });
+    return requestViaImage(secureRedirectURL + encodeURIComponent(
+        insecureRedirectURL + encodeURIComponent(
+        "https://{{host}}:{{ports[https][0]}}/common/security-features/subresource/image.py")))
+        .then(result => {
+          headers = result.headers;
+          got = {
+            "mode": headers["sec-fetch-mode"],
+            "site": headers["sec-fetch-site"],
+            "user": headers["sec-fetch-user"],
+            "dest": headers["sec-fetch-dest"]
+          };
+          assert_header_equals(got, {
+            // Note that we're using `undefined` here, as opposed to "" elsewhere because of the way
+            // that `image.py` encodes data.
+            "site": "cross-site",
+            "user": undefined,
+            "mode": "cors",
+            "dest": undefined
+          }, "Https downgrade-upgrade image => No headers");
+        });
   }, "Https downgrade-upgrade image => No headers");
 </script>
-<script src="https://{{host}}:{{ports[https][0]}}/fetch/api/resources/redirect.py?location=http%3A%2F%2F{{host}}%3A{{ports[http][0]}}%2Ffetch%2Fapi%2Fresources%2Fredirect.py%3Flocation%3Dhttps%253A%252F%252F{{host}}%253A{{ports[https][0]}}%252Ffetch%252Fmetadata%252Fresources%252Fecho-as-script.py"></script>
+<script
+    src="https://{{host}}:{{ports[https][0]}}/fetch/api/resources/redirect.py?location=http%3A%2F%2F{{host}}%3A{{ports[http][0]}}%2Ffetch%2Fapi%2Fresources%2Fredirect.py%3Flocation%3Dhttps%253A%252F%252F{{host}}%253A{{ports[https][0]}}%252Ffetch%252Fmetadata%252Fresources%252Fecho-as-script.py"></script>
 <script>
   test(t => {
-    t.add_cleanup(_ => { header = null; });
-    assert_header_equals(header, { "site": "cross-site", "user": "", "mode": "no-cors" });
+    t.add_cleanup(_ => {
+      header = null;
+    });
+    assert_header_equals(header, {"site": "cross-site", "user": "", "mode": "no-cors", "dest": ""},
+        "Https downgrade-upgrade script => No headers");
   }, "Https downgrade-upgrade script => No headers");
 </script>
 </body>
--- a/testing/web-platform/tests/fetch/metadata/redirect/multiple-redirect-same-site.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/redirect/multiple-redirect-same-site.tentative.https.sub.html
@@ -12,29 +12,25 @@
   promise_test(t => {
     return new Promise((resolve, reject) => {
       let key = "redirect-multiple-same-site" + nonce;
 
       let e = document.createElement('img');
       e.src = "https://{{host}}:{{ports[https][0]}}/xhr/resources/redirect.py?location=" +// same-origin
       "https://{{hosts[][www]}}:{{ports[https][0]}}/xhr/resources/redirect.py?location=" +// same-site
       "https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;// same-origin
-      let expected = {"site":"same-site", "user":"", "mode": "no-cors"};
+      let expected = {"site":"same-site", "user":"", "mode": "no-cors", "dest": "image"};
 
       e.onload = e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected)
           .then(_ => resolve())
           .catch(e => reject(e));
       };
       e.onerror = e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected)
           .then(_ => resolve())
           .catch(e => reject(e));
       };
 
       document.body.appendChild(e);
     })
   }, "Same-Origin -> Same-Site -> Same-Origin redirect");
 </script>
--- a/testing/web-platform/tests/fetch/metadata/redirect/redirect-http-upgrade.tentative.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/redirect/redirect-http-upgrade.tentative.sub.html
@@ -14,54 +14,54 @@
   #fontTest {
     font-family: myUpgradedFont;
   }
 </style>
 <body>
     <div id="fontTest">Upgraded font</div>
     <script>
   let nonce = "{{$id}}";
-  let expected = { "site": "cross-site", "user": "", "mode": "cors" };
+  let expected = { "site": "cross-site", "user": "", "mode": "cors", "dest": "" };
 
   // Validate various scenarios handle a request that redirects from http => https correctly and add the proper Sec- headers.
   RunCommonRedirectTests("Http upgrade", upgradeRedirectTo, expected);
 
   document.fonts.ready.then(function () {
     promise_test(t => {
       return new Promise((resolve, reject) => {
         let key = "font-https-upgrade{{$id}}";
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected, "Http upgrade font => No headers")
           .then(_ => resolve())
           .catch(e => reject(e));
       });
     }, "Http upgrade font => No headers");
   });
 
   promise_test(() => {
     return requestViaImage(insecureRedirectURL + encodeURIComponent("https://{{host}}:{{ports[https][0]}}/common/security-features/subresource/image.py"))
       .then(result => {
          headers = result.headers;
          got = {
            "mode": headers["sec-fetch-mode"],
            "site": headers["sec-fetch-site"],
-           "user": headers["sec-fetch-user"]
+           "user": headers["sec-fetch-user"],
+           "dest": headers["sec-fetch-dest"]
          };
          assert_header_equals(got, {
            // Note that we're using `undefined` here, as opposed to "" elsewhere because of the way
            // that `image.py` encodes data.
            "site": "cross-site",
            "user": undefined,
            "mode": "cors",
-         });
+           "dest": undefined,
+         }, "Http upgrade image => No headers");
       });
   }, "Http upgrade image => No headers");
 </script>
 
 <script src="http://{{host}}:{{ports[http][0]}}/fetch/api/resources/redirect.py?location=https%3A%2F%2F{{host}}%3A{{ports[https][0]}}%2Ffetch%2Fmetadata%2Fresources%2Fecho-as-script.py"></script>
 <script>
   test(t => {
     t.add_cleanup(_ => { header = null; });
-    assert_header_equals(header, { "site": "cross-site", "user": "", "mode": "no-cors" });
+    assert_header_equals(header, { "site": "cross-site", "user": "", "mode": "no-cors", "dest": "" }, "Http upgrade script => No headers");
   }, "Http upgrade script => No headers");
 </script>
 </body>
--- a/testing/web-platform/tests/fetch/metadata/redirect/redirect-https-downgrade.tentative.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/redirect/redirect-https-downgrade.tentative.sub.html
@@ -14,54 +14,56 @@
   #fontTest {
     font-family: myDowngradedFont;
   }
 </style>
 <body>
   <div id="fontTest">Downgraded font</div>
   <script>
   let nonce = token();
-  let expected = { "site": "", "user": "", "mode": "" };
+  let expected = { "site": "", "user": "", "mode": "", "dest": "" };
 
   // Validate various scenarios handle a request that redirects from https => http correctly and avoids disclosure of any Sec- headers.
   RunCommonRedirectTests("Https downgrade", downgradeRedirectTo, expected);
 
   document.fonts.ready.then(function () {
     promise_test(t => {
       return new Promise((resolve, reject) => {
         let key = "font-https-downgrade";
         fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
           .then(response => response.text())
-          .then(text => assert_no_headers(text))
+          .then(text => assert_no_headers(text, "Https downgrade font => No headers"))
           .then(_ => resolve())
           .catch(e => reject(e));
       });
     }, "Https downgrade font => No headers");
   });
 
   promise_test(() => {
     return requestViaImage(secureRedirectURL + encodeURIComponent("http://{{host}}:{{ports[http][0]}}/common/security-features/subresource/image.py"))
       .then(result => {
          headers = result.headers;
          got = {
            "mode": headers["sec-fetch-mode"],
            "site": headers["sec-fetch-site"],
-           "user": headers["sec-fetch-user"]
+           "user": headers["sec-fetch-user"],
+           "dest": headers["sec-fetch-dest"]
          };
          assert_header_equals(got, {
            // Note that we're using `undefined` here, as opposed to "" elsewhere because of the way
            // that `image.py` encodes data.
            "site": undefined,
            "user": undefined,
            "mode": undefined,
-         });
+           "dest": undefined,
+         }, "Https downgrade image => No headers");
       });
   }, "Https downgrade image => No headers");
 </script>
 
 <script src="https://{{host}}:{{ports[https][0]}}/fetch/api/resources/redirect.py?location=http%3A%2F%2F{{host}}%3A{{ports[http][0]}}%2Ffetch%2Fmetadata%2Fresources%2Fecho-as-script.py"></script>
 <script>
   test(t => {
     t.add_cleanup(_ => { header = null; });
-    assert_no_headers(header);
+    assert_no_headers(header, "Https downgrade script => No headers");
   }, "Https downgrade script => No headers");
 </script>
 </body>
--- a/testing/web-platform/tests/fetch/metadata/redirect/same-origin-redirect.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/redirect/same-origin-redirect.tentative.https.sub.html
@@ -10,83 +10,71 @@
   let nonce = token();
 
   promise_test(t => {
     return new Promise((resolve, reject) => {
       let key = "redirect-same-origin-same-origin" + nonce;
 
       let e = document.createElement('img');
       e.src = "/xhr/resources/redirect.py?location=https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      let expected = {"site":"same-origin", "user":"", "mode": "no-cors"};
+      let expected = {"site":"same-origin", "user":"", "mode": "no-cors", "dest": "image"};
 
       e.onload = e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected)
           .then(_ => resolve())
           .catch(e => reject(e));
       };
       e.onerror = e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected)
           .then(_ => resolve())
           .catch(e => reject(e));
       };
 
       document.body.appendChild(e);
     })
   }, "Same-Origin -> Same-Origin redirect");
 
 promise_test(t => {
     return new Promise((resolve, reject) => {
       let key = "redirect-same-origin-same-site" + nonce;
 
       let e = document.createElement('img');
       e.src = "/xhr/resources/redirect.py?location=https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      let expected = {"site":"same-site", "user":"", "mode": "no-cors"};
+      let expected = {"site":"same-site", "user":"", "mode": "no-cors", "dest": "image"};
 
       e.onload = e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected, "Same-Origin -> Same-Site redirect")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
       e.onerror = e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected, "Same-Origin -> Same-Site redirect")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
 
       document.body.appendChild(e);
     })
   }, "Same-Origin -> Same-Site redirect");
 
 promise_test(t => {
     return new Promise((resolve, reject) => {
       let key = "redirect-same-origin-cross-site" + nonce;
 
       let e = document.createElement('img');
       e.src = "/xhr/resources/redirect.py?location=https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      let expected = {"site":"cross-site", "user":"", "mode": "no-cors"};
+      let expected = {"site":"cross-site", "user":"", "mode": "no-cors", "dest": "image"};
 
       e.onload = e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected, "Same-Origin -> Cross-Site redirect")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
       e.onerror = e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected, "Same-Origin -> Cross-Site redirect")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
 
       document.body.appendChild(e);
     })
   }, "Same-Origin -> Cross-Site redirect");
 </script>
--- a/testing/web-platform/tests/fetch/metadata/redirect/same-site-redirect.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/redirect/same-site-redirect.tentative.https.sub.html
@@ -10,83 +10,71 @@
   let nonce = token();
 
   promise_test(t => {
     return new Promise((resolve, reject) => {
       let key = "redirect-same-site-same-origin" + nonce;
 
       let e = document.createElement('img');
       e.src = "https://{{hosts[][www]}}:{{ports[https][0]}}/xhr/resources/redirect.py?location=https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      let expected = {"site":"same-site", "user":"", "mode": "no-cors"};
+      let expected = {"site":"same-site", "user":"", "mode": "no-cors", "dest": "image"};
 
       e.onload = e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected, "Same-Site -> Same-Origin redirect")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
       e.onerror = e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected, "Same-Site -> Same-Origin redirect")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
 
       document.body.appendChild(e);
     })
   }, "Same-Site -> Same-Origin redirect");
 
 promise_test(t => {
     return new Promise((resolve, reject) => {
       let key = "redirect-same-site-same-site" + nonce;
 
       let e = document.createElement('img');
       e.src = "https://{{hosts[][www]}}:{{ports[https][0]}}/xhr/resources/redirect.py?location=https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      let expected = {"site":"same-site", "user":"", "mode": "no-cors"};
+      let expected = {"site":"same-site", "user":"", "mode": "no-cors", "dest": "image"};
 
       e.onload = e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected, "Same-Site -> Same-Site redirect")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
       e.onerror = e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected, "Same-Site -> Same-Site redirect")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
 
       document.body.appendChild(e);
     })
   }, "Same-Site -> Same-Site redirect");
 
 promise_test(t => {
     return new Promise((resolve, reject) => {
       let key = "redirect-same-site-cross-site" + nonce;
 
       let e = document.createElement('img');
       e.src = "https://{{hosts[][www]}}:{{ports[https][0]}}/xhr/resources/redirect.py?location=https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      let expected = {"site":"cross-site", "user":"", "mode": "no-cors"};
+      let expected = {"site":"cross-site", "user":"", "mode": "no-cors", "dest": "image"};
 
       e.onload = e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected, "Same-Site -> Cross-Site redirect")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
       e.onerror = e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected, "Same-Site -> Cross-Site redirect")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
 
       document.body.appendChild(e);
     })
   }, "Same-Site -> Cross-Site redirect");
 </script>
--- a/testing/web-platform/tests/fetch/metadata/report.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/report.tentative.https.sub.html
@@ -5,28 +5,26 @@
 <script src=/fetch/metadata/resources/helper.js></script>
 <link id="style" href="https://foo.bar" rel="stylesheet">
 <body></body>
 <script>
   setup({ explicit_done: true });
   function generate_test(expected, name) {
     async_test(t => {
       t.step_timeout(_ => {
-        return fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=report-" + name)
-            .then(response => response.text())
-            .then(text => assert_header_equals(text, expected))
+        return validate_expectations("report-" + name, expected, name + " report")
             .then(_ => t.done());
       }, 1000);
     }, name + " report");
   }
 
   let counter = 0;
   document.addEventListener("securitypolicyviolation", (e) => {
     counter++;
     if (counter == 3) {
-      generate_test({"site":"same-origin", "user":"", "mode": "no-cors"}, "same-origin");
-      generate_test({"site":"same-site", "user":"", "mode": "no-cors"}, "same-site");
-      generate_test({"site":"cross-site", "user":"", "mode": "no-cors"}, "cross-site");
+      generate_test({"site":"same-origin", "user":"", "mode": "no-cors", "dest": "report"}, "same-origin");
+      generate_test({"site":"same-site", "user":"", "mode": "no-cors", "dest": "report"}, "same-site");
+      generate_test({"site":"cross-site", "user":"", "mode": "no-cors", "dest": "report"}, "cross-site");
 
       done();
     }
   });
 </script>
--- a/testing/web-platform/tests/fetch/metadata/resources/helper.js
+++ b/testing/web-platform/tests/fetch/metadata/resources/helper.js
@@ -8,95 +8,56 @@ function validate_expectations(key, expe
     .then(text => {
       assert_not_equals(text, "No header has been recorded");
       let value = JSON.parse(text);
       test(t => assert_equals(value.dest, expected.dest), `${tag}: sec-fetch-dest`);
       test(t => assert_equals(value.mode, expected.mode), `${tag}: sec-fetch-mode`);
       test(t => assert_equals(value.site, expected.site), `${tag}: sec-fetch-site`);
       test(t => assert_equals(value.user, expected.user), `${tag}: sec-fetch-user`);
     });
-};
+}
+
+function validate_expectations_custom_url(url, header, expected, tag) {
+  return fetch(url, header)
+    .then(response => response.text())
+    .then(text => {
+      assert_not_equals(text, "No header has been recorded");
+      let value = JSON.parse(text);
+      test(t => assert_equals(value.dest, expected.dest), `${tag}: sec-fetch-dest`);
+      test(t => assert_equals(value.mode, expected.mode), `${tag}: sec-fetch-mode`);
+      test(t => assert_equals(value.site, expected.site), `${tag}: sec-fetch-site`);
+      test(t => assert_equals(value.user, expected.user), `${tag}: sec-fetch-user`);
+    });
+}
 
 /**
  * @param {object} value
  * @param {object} expected
  * @param {string} tag
  **/
 function assert_header_equals(value, expected, tag) {
   if (typeof(value) === "string"){
     assert_not_equals(value, "No header has been recorded");
     value = JSON.parse(value);
   }
 
-  assert_equals(value.mode, expected.mode, wrap_by_tag(tag, "mode"));
-  assert_equals(value.site, expected.site, wrap_by_tag(tag, "site"));
-  if (expected.hasOwnProperty("user"))
-    assert_equals(value.user, expected.user, wrap_by_tag(tag, "user"));
+  test(t => assert_equals(value.dest, expected.dest), `${tag}: sec-fetch-dest`);
+  test(t => assert_equals(value.mode, expected.mode), `${tag}: sec-fetch-mode`);
+  test(t => assert_equals(value.site, expected.site), `${tag}: sec-fetch-site`);
+  test(t => assert_equals(value.user, expected.user), `${tag}: sec-fetch-user`);
 }
 
 /**
  * @param {object} value
  * @param {string} tag
  **/
 function assert_no_headers(value, tag) {
   if (typeof(value) === "string"){
     if (value == "No header has been recorded") return;
     value = JSON.parse(value);
   }
 
-  assert_equals(value.mode, "", wrap_by_tag(tag, "mode"));
-  assert_equals(value.site, "", wrap_by_tag(tag, "site"));
+  test(t => assert_equals(value.mode, ""), `${tag}: sec-fetch-mode`);
+  test(t => assert_equals(value.site, ""), `${tag}: sec-fetch-site`);
   if (expected.hasOwnProperty("user"))
-    assert_equals(value.user, "", wrap_by_tag(tag, "user"));
-}
-
-/**
- * @param {string} header
- * @param {object} value
- * @param {string} expected
- * @param {string} tag
- **/
-function assert_header(header, value, expected, tag) {
-  if (typeof(value) === "string"){
-    assert_not_equals(value, "No header has been recorded");
-    value = JSON.parse(value);
-  }
-
-  assert_equals(value[header], expected, wrap_by_tag(tag, header));
+    test(t => assert_equals(value.user, ""), `${tag}: sec-fetch-user`);
+  test(t => assert_equals(value.dest, ""), `${tag}: sec-fetch-dest`);
 }
-
-/**
- *
- * @param {object} value
- * @param {string} expected
- * @param {string} tag
- **/
-function assert_header_dest_equals(value, expected, tag) {
-  assert_header("dest", value, expected, tag);
-}
-
-/**
- * Test fetch record-header.py
- * @param {string} key
- * @param {string} expected
- * @param {function} assert
- * @return {Promise<string | never>}
- */
-function fetch_record_header(key, expected, assert) {
-  return fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-      .then(response => response.text())
-      .then(text => assert(text, expected));
-}
-
-/**
- *
- * @param {string} key
- * @param {string} expected
- * @param {function} assert
- * @param {function} resolve
- * @param {function} reject
- * @return {Promise<any>}
- */
-function fetch_record_header_with_catch(key, expected, assert, resolve, reject) {
-  return fetch_record_header(key, expected, assert, resolve)
-      .then(_ => resolve())
-      .catch(e => reject(e));
-}
--- a/testing/web-platform/tests/fetch/metadata/resources/redirectTestHelper.sub.js
+++ b/testing/web-platform/tests/fetch/metadata/resources/redirectTestHelper.sub.js
@@ -46,17 +46,17 @@ function RunCommonRedirectTests(testName
     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';
-      assert_header_equals(e.data, expectation);
+      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));
@@ -64,62 +64,64 @@ function RunCommonRedirectTests(testName
     window.addEventListener('message', t.step_func(e => {
       if (e.source != testWindow) {
         return;
       }
 
       let expectation = { ...expectedResults };
       if (expectation['mode'] != '')
         expectation['mode'] = 'navigate';
-      assert_header_equals(e.data, expectation);
+      assert_header_equals(e.data, expectation, testNamePrefix + ' top level navigation');
       t.done();
     }));
   }, testNamePrefix + ' top level navigation');
 
   promise_test(t => {
     return new Promise((resolve, reject) => {
       let key = 'embed-https-redirect' + nonce;
       let e = document.createElement('embed');
       e.src = urlHelperMethod('resources/record-header.py?file=' + key);
       e.onload = e => {
         let expectation = { ...expectedResults };
         if (expectation['mode'] != '')
           expectation['mode'] = 'navigate';
         fetch('/fetch/metadata/resources/record-header.py?retrieve=true&file=' + key)
           .then(response => response.text())
-          .then(t.step_func(text => assert_header_equals(text, expectation)))
+          .then(t.step_func(text => assert_header_equals(text, expectation, testNamePrefix + ' embed')))
           .then(resolve)
           .catch(e => reject(e));
       };
       document.body.appendChild(e);
     });
   }, testNamePrefix + ' embed');
 
   promise_test(t => {
     let key = 'fetch-redirect' + nonce;
     let expectation = { ...expectedResults };
     if (expectation['mode'] != '')
       expectation['mode'] = 'cors';
+    if (expectation['dest'] == '' && testNamePrefix != "Https downgrade")
+      expectation['dest'] = 'empty';
     return fetch(urlHelperMethod('resources/echo-as-json.py?' + key))
       .then(r => r.json())
-      .then(j => {assert_header_equals(j, expectation);});
+      .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;
       let e = document.createElement('object');
       e.data = urlHelperMethod('resources/record-header.py?file=' + key);
       e.onload = e => {
         let expectation = { ...expectedResults };
         if (expectation['mode'] != '')
           expectation['mode'] = 'navigate';
         fetch('/fetch/metadata/resources/record-header.py?retrieve=true&file=' + key)
           .then(response => response.text())
-          .then(t.step_func(text => assert_header_equals(text, expectation)))
+          .then(t.step_func(text => assert_header_equals(text, expectation, testNamePrefix + ' object')))
           .then(resolve)
           .catch(e => reject(e));
       };
       document.body.appendChild(e);
     });
   }, testNamePrefix + ' object');
 
   if (document.createElement('link').relList.supports('prefetch')) {
@@ -130,17 +132,17 @@ function RunCommonRedirectTests(testName
       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)))
+          .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');
   }
 
   if (document.createElement('link').relList.supports('preload')) {
@@ -151,17 +153,17 @@ function RunCommonRedirectTests(testName
       e.href = urlHelperMethod('resources/record-header.py?file=' + key);
       e.setAttribute('as', 'track');
       e.onload = e.onerror = t.step_func_done(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)))
+          .then(t.step_func_done(text => assert_header_equals(text, expectation, testNamePrefix + ' preload')))
           .catch(t.unreached_func());
       });
       document.head.appendChild(e);
     }, testNamePrefix + ' preload');
   }
 
   promise_test(t => {
     return new Promise((resolve, reject) => {
@@ -170,17 +172,17 @@ function RunCommonRedirectTests(testName
       e.rel = 'stylesheet';
       e.href = urlHelperMethod('resources/record-header.py?file=' + key);
       e.onload = e => {
         let expectation = { ...expectedResults };
         if (expectation['mode'] != '')
           expectation['mode'] = 'no-cors';
         fetch('/fetch/metadata/resources/record-header.py?retrieve=true&file=' + key)
           .then(response => response.text())
-          .then(t.step_func(text => assert_header_equals(text, expectation)))
+          .then(t.step_func(text => assert_header_equals(text, expectation, testNamePrefix + ' stylesheet')))
           .then(resolve)
           .catch(e => reject(e));
       };
       document.body.appendChild(e);
     });
   }, testNamePrefix + ' stylesheet');
 
   promise_test(t => {
@@ -190,16 +192,16 @@ function RunCommonRedirectTests(testName
       let el = createTrack();
       el.src = urlHelperMethod('resources/record-header.py?file=' + key);
       el.onload = t.step_func(_ => {
         let expectation = { ...expectedResults };
         if (expectation['mode'] != '')
           expectation['mode'] = 'cors';
         fetch('/fetch/metadata/resources/record-header.py?retrieve=true&file=' + key)
           .then(response => response.text())
-          .then(t.step_func(text => assert_header_equals(text, expectedResults)))
+          .then(t.step_func(text => assert_header_equals(text, expectedResults, testNamePrefix + ' track')))
           .then(resolve);
       });
       video.appendChild(el);
       document.body.appendChild(video);
     });
   }, testNamePrefix + ' track');
 }
--- a/testing/web-platform/tests/fetch/metadata/script.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/script.tentative.https.sub.html
@@ -8,53 +8,57 @@
 <script>
   test(t => {
     t.add_cleanup(_ => { header = null; });
 
     assert_header_equals(header, {
       "site": "same-origin",
       "user": "",
       "mode": "no-cors",
-    });
+      "dest": "script"
+    }, "Same-origin script");
   }, "Same-origin script");
 </script>
 
 <!-- Same-site script -->
 <script src="https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-script.py"></script>
 <script>
   test(t => {
     t.add_cleanup(_ => { header = null; });
 
     assert_header_equals(header, {
       "site": "same-site",
       "user": "",
       "mode": "no-cors",
-    });
+      "dest": "script"
+    }, "Same-site script");
   }, "Same-site script");
 </script>
 
 <!-- Cross-site script -->
 <script src="https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-script.py"></script>
 <script>
   test(t => {
     t.add_cleanup(_ => { header = null; });
 
     assert_header_equals(header, {
       "site": "cross-site",
       "user": "",
       "mode": "no-cors",
-    });
+      "dest": "script"
+    }, "Cross-site script");
   }, "Cross-site script");
 </script>
 
 <!-- Same-origin script, CORS mode -->
 <script src="https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-script.py" crossorigin="anonymous"></script>
 <script>
   test(t => {
     t.add_cleanup(_ => { header = null; });
 
     assert_header_equals(header, {
       "site": "same-origin",
       "user": "",
       "mode": "cors",
-    });
+      "dest": "script"
+    }, "Same-origin CORS script");
   }, "Same-origin CORS script");
 </script>
--- a/testing/web-platform/tests/fetch/metadata/script.tentative.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/script.tentative.sub.html
@@ -8,39 +8,42 @@
 <script>
   test(t => {
     t.add_cleanup(_ => { header = null; });
 
     assert_header_equals(header, {
       "site": "",
       "user": "",
       "mode": "",
-    });
+      "dest": ""
+    }, "Non-secure same-origin script => No headers");
   }, "Non-secure same-origin script => No headers");
 </script>
 
 <!-- Same-site script -->
 <script src="http://{{hosts[][www]}}:{{ports[http][0]}}/fetch/metadata/resources/echo-as-script.py"></script>
 <script>
   test(t => {
     t.add_cleanup(_ => { header = null; });
 
     assert_header_equals(header, {
       "site": "",
       "user": "",
       "mode": "",
-    });
+      "dest": ""
+    }, "Non-secure same-site script => No headers");
   }, "Non-secure same-site script => No headers");
 </script>
 
 <!-- Cross-site script -->
 <script src="http://{{hosts[alt][www]}}:{{ports[http][0]}}/fetch/metadata/resources/echo-as-script.py"></script>
 <script>
   test(t => {
     t.add_cleanup(_ => { header = null; });
 
     assert_header_equals(header, {
       "site": "",
       "user": "",
       "mode": "",
-    });
+      "dest": ""
+    }, "Non-secure cross-site script => No headers");
   }, "Non-secure cross-site script => No headers");
 </script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/appcache.tentative.https.sub.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<html manifest="/fetch/metadata/resources/record-header.py?file=appcache-manifest{{$id:uuid()}}">
-<meta name="timeout" content="long">
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/common/utils.js></script>
-<body></body>
-<script>
-  async_test(t => {
-    window.applicationCache.oncached = window.applicationCache.onnoupdate = window.applicationCache.onerror = t.step_func(e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=appcache-manifest{{$id}}")
-          .then(t.step_func(response => response.text()))
-          .then(t.step_func_done(text => assert_header_dest_equals(text, "")))
-          .catch(t.unreached_func("Fetching and verifying the results should succeed."));
-});
-}, "Appcache!");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/embed.tentative.https.sub.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8"/>
-<link rel="author" href="mtrzos@google.com" title="Maciek Trzos">
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/common/utils.js></script>
-<body>
-<script>
-  let nonce = token();
-
-  promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "embed-same-origin" + nonce;
-
-      let e = document.createElement('embed');
-      e.src = "https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      e.onload = e => {
-        fetch_record_header_with_catch(key, "embed", assert_header_dest_equals, resolve, reject);
-      };
-
-      document.body.appendChild(e);
-    })
-  }, "Same-Origin embed");
-
-  promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "embed-same-site" + nonce;
-
-      let e = document.createElement('embed');
-      e.src = "https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      e.onload = e => {
-        fetch_record_header_with_catch(key, "embed", assert_header_dest_equals, resolve, reject);
-      };
-
-      document.body.appendChild(e);
-    })
-  }, "Same-Site embed");
-
-  promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "embed-cross-site" + nonce;
-
-      let e = document.createElement('embed');
-      e.src = "https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      e.onload = e => {
-        fetch_record_header_with_catch(key, "embed", assert_header_dest_equals, resolve, reject);
-      };
-
-      document.body.appendChild(e);
-    })
-  }, "Cross-Site embed");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/fetch-preflight.tentative.https.sub.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script>
-  // Site
-  promise_test(t => {
-    return fetch("https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py",
-                 {
-                   mode: "cors",
-                   headers: { 'x-test': 'testing' }
-                 })
-        .then(r => r.json())
-        .then(j => assert_header_dest_equals(j, "empty"));
-  }, "Same-site fetch with preflight");
-
-  promise_test(t => {
-    return fetch("https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py",
-                 {
-                   mode: "cors",
-                   headers: { 'x-test': 'testing' }
-                 })
-        .then(r => r.json())
-        .then(j => assert_header_dest_equals(j, "empty"));
-  }, "Cross-site fetch with preflight");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/fetch-via-serviceworker--fallback.tentative.https.sub.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!DOCTYPE html>
-<!--
-  This test verifies presence of Sec-Fetch-... request headers on a request
-  handled by a service worker - this test covers the scenario when the service
-  worker doesn't do anything and the request falls back to the network.
--->
-<meta charset="utf-8"/>
-<link rel="author" href="lukasza@chromium.org" title="Lukasz Anforowicz">
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/service-workers/service-worker/resources/test-helpers.sub.js></script>
-<script src=/common/utils.js></script>
-<script>
-    const nonce = token();
-    const key = "fetch-via-serviceworker--fallback--" + nonce;
-
-    promise_test(async function(t) {
-        const SCOPE = '/fetch/metadata/resources/fetch-via-serviceworker--fallback--frame.html';
-        const SCRIPT = '/fetch/metadata/resources/fetch-via-serviceworker--fallback--sw.js';
-        const URL = '/fetch/metadata/resources/record-header.py?file=' + key;
-        const RETRIEVAL_URL = "/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key;
-
-        const reg = await service_worker_unregister_and_register(t, SCRIPT, SCOPE);
-        t.add_cleanup(async () => {
-          if (reg)
-            await reg.unregister();
-        });
-
-        await wait_for_state(t, reg.installing, 'activated');
-
-        const frame = await with_iframe(SCOPE);
-        t.add_cleanup(async () => {
-          if (frame)
-            frame.remove();
-        });
-
-        // Trigger a fetch that 1) will go through the service worker and 2) will
-        // fetch a special URL that records request headers.
-        await frame.contentWindow.fetch(URL, {mode:'no-cors'});
-
-        // Retrieve the request headers that have been recorded in the previous step.
-        const response = await fetch(RETRIEVAL_URL);
-        const text = await response.text();
-
-        // Verify presence of the expected Sec-Fetch-... request headers.
-        assert_header_dest_equals(text, "empty");
-      }, 'Sec-Fetch headers after SW fallback');
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/fetch-via-serviceworker--respondWith.tentative.https.sub.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!DOCTYPE html>
-<!--
-  This test verifies presence of Sec-Fetch-... request headers on a request
-  handled by a service worker - this test covers the scenario when the service
-  worker responds to the `fetch` event with:
-      event.respondWith(fetch(event.request));
--->
-<meta charset="utf-8"/>
-<link rel="author" href="lukasza@chromium.org" title="Lukasz Anforowicz">
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/service-workers/service-worker/resources/test-helpers.sub.js></script>
-<script src=/common/utils.js></script>
-<script>
-    const nonce = token();
-    const key = "fetch-via-serviceworker--respondWith--" + nonce;
-
-    promise_test(async function(t) {
-        const SCOPE = '/fetch/metadata/resources/fetch-via-serviceworker--respondWith--frame.html';
-        const SCRIPT = '/fetch/metadata/resources/fetch-via-serviceworker--respondWith--sw.js';
-        const URL = '/fetch/metadata/resources/record-header.py?file=' + key;
-        const RETRIEVAL_URL = "/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key;
-
-        const reg = await service_worker_unregister_and_register(t, SCRIPT, SCOPE);
-        t.add_cleanup(async () => {
-          if (reg)
-            await reg.unregister();
-        });
-
-        await wait_for_state(t, reg.installing, 'activated');
-
-        const frame = await with_iframe(SCOPE);
-        t.add_cleanup(async () => {
-          if (frame)
-            frame.remove();
-        });
-
-        // Trigger a fetch that 1) will go through the service worker and 2) will
-        // fetch a special URL that records request headers.
-        await frame.contentWindow.fetch(URL, {mode:'no-cors'});
-
-        // Retrieve the request headers that have been recorder in the previous step.
-        const response = await fetch(RETRIEVAL_URL);
-        const text = await response.text();
-
-        // Verify presence of the expected Sec-Fetch-... request headers.
-        assert_header_dest_equals(text, "empty");
-      }, 'Sec-Fetch headers after SW fallback');
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/fetch.tentative.https.sub.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<!DOCTYPE html>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script>
-  // Site
-  promise_test(t => {
-    return fetch("https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py")
-        .then(r => r.json())
-        .then(j => assert_header_dest_equals(j, "empty"));
-  }, "Same-origin fetch");
-
-  promise_test(t => {
-    return fetch("https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py")
-        .then(r => r.json())
-        .then(j => assert_header_dest_equals(j, "empty"));
-  }, "Same-site fetch");
-
-  promise_test(t => {
-    return fetch("https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py")
-        .then(r => r.json())
-        .then(j => assert_header_dest_equals(j, "empty"));
-  }, "Cross-site fetch");
-
-  // Mode
-  promise_test(t => {
-    return fetch("https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py", {mode: "same-origin"})
-        .then(r => r.json())
-        .then(j => assert_header_dest_equals(j, "empty"));
-  }, "Same-origin mode");
-
-  promise_test(t => {
-    return fetch("https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py", {mode: "cors"})
-        .then(r => r.json())
-        .then(j => assert_header_dest_equals(j, "empty"));
-  }, "CORS mode");
-
-  promise_test(t => {
-    return fetch("https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py", {mode: "no-cors"})
-        .then(r => r.json())
-        .then(j => assert_header_dest_equals(j, "empty"));
-  }, "no-CORS mode");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/fetch.tentative.sub.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script>
-  // http -> https should see `Sec-Fetch-Site: cross-site`.
-  // This is a regression test for
-  // https://github.com/w3c/webappsec-fetch-metadata/issues/34
-  promise_test(t => {
-    assert_equals(location.protocol, "http:");
-    return fetch("https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py")
-        .then(r => r.json())
-        .then(j => assert_header_dest_equals(j, "empty"));
-  }, "http->https fetch (cross-scheme => cross-site)");
-
-  // http -> http should see no `Sec-Fetch-Site`.
-  promise_test(t => {
-    assert_equals(location.protocol, "http:");
-    return fetch("/fetch/metadata/resources/echo-as-json.py")
-        .then(r => r.json())
-        .then(j => assert_header_dest_equals(j, ""));
-  }, "http->http fetch (non-trustworthy destination => no metadata)");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/font.tentative.https.sub.html
+++ /dev/null
@@ -1,69 +0,0 @@
-<!DOCTYPE html>
-<html>
-<link rel="author" href="mtrzos@google.com" title="Maciek Trzos">
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<body>
-  <div id="test1">1</div>
-  <div id="test2">2</div>
-  <div id="test3">3</div>
-  <!-- Same-Origin request -->
-  <style>
-    @font-face {
-      font-family: myFirstFont;
-      src: url(https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=font-same-origin);
-    }
-    #test1 {
-      font-family: myFirstFont;
-    }
-  </style>
-
-  <!-- Same-Site request -->
-  <style>
-    @font-face {
-      font-family: mySecondFont;
-      src: url(https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=font-same-site);
-    }
-    #test2 {
-      font-family: mySecondFont;
-    }
-  </style>
-
-  <!-- Cross-Site request -->
-  <style>
-    @font-face {
-      font-family: myThirdFont;
-      src: url(https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=font-cross-site);
-    }
-    #test3 {
-      font-family: myThirdFont;
-    }
-  </style>
-</body>
-<script>
-  document.fonts.ready.then(function () {
-    promise_test(t => {
-      return new Promise((resolve, reject) => {
-        let key = "font-same-origin";
-        fetch_record_header_with_catch(key, "font", assert_header_dest_equals, resolve, reject);
-        });
-    }, "Same-Origin font");
-
-    promise_test(t => {
-      return new Promise((resolve, reject) => {
-        let key = "font-same-site";
-        fetch_record_header_with_catch(key, "font", assert_header_dest_equals, resolve, reject);
-        });
-    }, "Same-Site font");
-
-    promise_test(t => {
-      return new Promise((resolve, reject) => {
-        let key = "font-cross-site";
-        fetch_record_header_with_catch(key, "font", assert_header_dest_equals, resolve, reject);
-        });
-    }, "Cross-Site font");
-
-  });
-</script>
-</html>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/frame.tentative.https.sub.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<!DOCTYPE html>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/resources/testdriver.js></script>
-<script src=/resources/testdriver-vendor.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/common/utils.js></script>
-<body>
-<script>
-  const USER = true;
-  const FORCED = false;
-
-  function create_test(host, user_activated, expectations) {
-    async_test(t => {
-      let i = document.createElement('frame');
-      window.addEventListener('message', t.step_func(e => {
-        if (e.source != i.contentWindow)
-          return;
-
-        assert_header_dest_equals(e.data, expectations);
-        t.done();
-      }));
-
-      let url = `https://${host}/fetch/metadata/resources/post-to-owner.py`;
-      if (user_activated == FORCED) {
-        i.src = url;
-        document.body.appendChild(i);
-      } else if (user_activated == USER) {
-        let uuid = token();
-        i.name = uuid;
-        let a = document.createElement('a');
-        a.href = url;
-        a.target = uuid;
-        a.text = "This is a link!";
-
-        document.body.appendChild(i);
-        document.body.appendChild(a);
-
-        test_driver.click(a);
-      }
-    }, `{{host}} -> ${host} iframe: ${user_activated ? "user-activated" : "forced"}`);
-  }
-
-  create_test("{{host}}:{{ports[https][0]}}", FORCED, "frame");
-
-  create_test("{{hosts[][www]}}:{{ports[https][0]}}", FORCED, "frame");
-
-  create_test("{{hosts[alt][www]}}:{{ports[https][0]}}", FORCED, "frame");
-
-  create_test("{{host}}:{{ports[https][0]}}", USER, "frame");
-
-  create_test("{{hosts[][www]}}:{{ports[https][0]}}", USER, "frame");
-
-  create_test("{{hosts[alt][www]}}:{{ports[https][0]}}", USER, "frame");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/frame.tentative.sub.html
+++ /dev/null
@@ -1,62 +0,0 @@
-<!DOCTYPE html>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<body>
-<script>
-  async_test(t => {
-    let i = document.createElement('frame');
-    i.src = "http://{{host}}:{{ports[http][0]}}/fetch/metadata/resources/post-to-owner.py";
-    window.addEventListener('message', t.step_func(e => {
-      if (e.source != i.contentWindow)
-        return;
-
-      assert_header_dest_equals(e.data, "");
-      t.done();
-    }));
-
-    document.body.appendChild(i);
-  }, "Non-secure same-origin iframe => No headers");
-
-  async_test(t => {
-    let i = document.createElement('frame');
-    i.src = "http://{{hosts[][www]}}:{{ports[http][0]}}/fetch/metadata/resources/post-to-owner.py";
-    window.addEventListener('message', t.step_func(e => {
-      if (e.source != i.contentWindow)
-        return;
-
-      assert_header_dest_equals(e.data, "");
-      t.done();
-    }));
-
-    document.body.appendChild(i);
-  }, "Non-secure same-site iframe => No headers");
-
-  async_test(t => {
-    let i = document.createElement('frame');
-    i.src = "http://{{hosts[alt][www]}}:{{ports[http][0]}}/fetch/metadata/resources/post-to-owner.py";
-    window.addEventListener('message', t.step_func(e => {
-      if (e.source != i.contentWindow)
-        return;
-
-      assert_header_dest_equals(e.data, "");
-      t.done();
-    }));
-
-    document.body.appendChild(i);
-  }, "Non-secure cross-site iframe => No headers.");
-
-  async_test(t => {
-    let i = document.createElement('frame');
-    i.src = "https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/post-to-owner.py";
-    window.addEventListener('message', t.step_func(e => {
-      if (e.source != i.contentWindow)
-        return;
-
-      assert_header_dest_equals(e.data, "frame");
-      t.done();
-    }));
-
-    document.body.appendChild(i);
-  }, "Secure, cross-site (cross-scheme, same-host) frame");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/history.tentative.https.sub.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<!DOCTYPE html>
-<html>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script>
-
-// Test that correct `Sec-Fetch-Site` (and other `Sec-Fetch-...` request
-/// headers) are used in navigations triggered by |history.back()|.
-function add_test(description, report_host, go_back_host, expectation) {
-  async_test(t => {
-    // STEP1: Navigate a new window to report_host/post-to-owner.py
-    const url_suffix = '/fetch/metadata/resources/post-to-owner.py'
-    const url = `https://${report_host}${url_suffix}`;
-    const w = window.open(url, '_blank');
-
-    var msg_counter = 0;
-    window.addEventListener('message', t.step_func(e => {
-      if (e.source != w)
-        return;
-      msg_counter = msg_counter + 1;
-      if (msg_counter == 1) {
-        // STEP2: Verify the headers (this is a sanity check that the same
-        // headers are used here and in STEP5).
-        assert_header_dest_equals(e.data, expectation);
-
-        // STEP3: Go to go_back_host/go-back.html (postponing this via
-        // step_timeout ensures that go-back.html will get a separate
-        // history entry - otherwise it might be treated as a client-side
-        // redirect and we might end up with nowhere to go back to).
-        t.step_timeout(() => {
-          const url_suffix = '/fetch/metadata/resources/go-back.html'
-          const url = `https://${go_back_host}${url_suffix}`;
-          w.location = url;
-        });
-
-        // STEP4 (elsewhere - inside go-back.html): Call history.back().
-      } else if (msg_counter == 2) {
-        // STEP5: Verify the headers (this is the main verification and focus
-        // of the test).
-        assert_header_dest_equals(e.data, expectation);
-
-        // STEP6: Finish the test.
-        t.done();
-      }
-    }));
-  }, description);
-}
-
-const same_origin_host = "{{host}}:{{ports[https][0]}}";
-const same_site_host = "{{hosts[][www]}}:{{ports[https][0]}}";
-const cross_site_host = "{{hosts[alt][www]}}:{{ports[https][0]}}";
-
-add_test(
-  "back to same-origin-initiated navigation",
-  same_origin_host,  // report_host
-  cross_site_host,  // go_back_host
-  "document");
-
-add_test(
-  "back to same-site-initiated navigation",
-  same_site_host,  // report_host
-  cross_site_host,  // go_back_host
-  "document");
-
-add_test(
-  "back to cross-site-initiated navigation",
-  cross_site_host,  // report_host
-  cross_site_host,  // go_back_host
-  "document");
-
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/iframe.tentative.https.sub.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<!DOCTYPE html>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/resources/testdriver.js></script>
-<script src=/resources/testdriver-vendor.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/common/utils.js></script>
-<body>
-<script>
-  const USER = true;
-  const FORCED = false;
-
-  function create_test(host, user_activated, expectations) {
-    async_test(t => {
-      let i = document.createElement('iframe');
-      window.addEventListener('message', t.step_func(e => {
-        if (e.source != i.contentWindow)
-          return;
-
-        assert_header_dest_equals(e.data, expectations);
-        t.done();
-      }));
-
-      let url = `https://${host}/fetch/metadata/resources/post-to-owner.py`;
-      if (user_activated == FORCED) {
-        i.src = url;
-        document.body.appendChild(i);
-      } else if (user_activated == USER) {
-        let uuid = token();
-        i.name = uuid;
-        let a = document.createElement('a');
-        a.href = url;
-        a.target = uuid;
-        a.text = "This is a link!";
-
-        document.body.appendChild(i);
-        document.body.appendChild(a);
-
-        test_driver.click(a);
-      }
-    }, `{{host}} -> ${host} iframe: ${user_activated ? "user-activated" : "forced"}`);
-  }
-
-  create_test("{{host}}:{{ports[https][0]}}", FORCED, "iframe");
-
-  create_test("{{hosts[][www]}}:{{ports[https][0]}}", FORCED, "iframe");
-
-  create_test("{{hosts[alt][www]}}:{{ports[https][0]}}", FORCED, "iframe");
-
-  create_test("{{host}}:{{ports[https][0]}}", USER, "iframe");
-
-  create_test("{{hosts[][www]}}:{{ports[https][0]}}", USER, "iframe");
-
-  create_test("{{hosts[alt][www]}}:{{ports[https][0]}}", USER, "iframe");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/iframe.tentative.sub.html
+++ /dev/null
@@ -1,62 +0,0 @@
-<!DOCTYPE html>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<body>
-<script>
-  async_test(t => {
-    let i = document.createElement('iframe');
-    i.src = "http://{{host}}:{{ports[http][0]}}/fetch/metadata/resources/post-to-owner.py";
-    window.addEventListener('message', t.step_func(e => {
-      if (e.source != i.contentWindow)
-        return;
-
-      assert_header_dest_equals(e.data, "");
-      t.done();
-    }));
-
-    document.body.appendChild(i);
-  }, "Non-secure same-origin iframe => No headers");
-
-  async_test(t => {
-    let i = document.createElement('iframe');
-    i.src = "http://{{hosts[][www]}}:{{ports[http][0]}}/fetch/metadata/resources/post-to-owner.py";
-    window.addEventListener('message', t.step_func(e => {
-      if (e.source != i.contentWindow)
-        return;
-
-      assert_header_dest_equals(e.data, "");
-      t.done();
-    }));
-
-    document.body.appendChild(i);
-  }, "Non-secure same-site iframe => No headers");
-
-  async_test(t => {
-    let i = document.createElement('iframe');
-    i.src = "http://{{hosts[alt][www]}}:{{ports[http][0]}}/fetch/metadata/resources/post-to-owner.py";
-    window.addEventListener('message', t.step_func(e => {
-      if (e.source != i.contentWindow)
-        return;
-
-      assert_header_dest_equals(e.data, "");
-      t.done();
-    }));
-
-    document.body.appendChild(i);
-  }, "Non-secure cross-site iframe => No headers.");
-
-  async_test(t => {
-    let i = document.createElement('iframe');
-    i.src = "https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/post-to-owner.py";
-    window.addEventListener('message', t.step_func(e => {
-      if (e.source != i.contentWindow)
-        return;
-
-      assert_header_dest_equals(e.data, "iframe");
-      t.done();
-    }));
-
-    document.body.appendChild(i);
-  }, "Secure, cross-site (cross-scheme, same-host) iframe");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/img.tentative.https.sub.html
+++ /dev/null
@@ -1,45 +0,0 @@
-<!DOCTYPE html>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/common/security-features/resources/common.sub.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<body>
-<script>
-  // These tests reuse the `referrer-policy` infrastructure to load images that
-  // encode their request headers in their pixels. Fun stuff!
-  promise_test(() =>
-    requestViaImage(
-      "https://{{host}}:{{ports[https][0]}}/common/security-features/subresource/image.py")
-    .then(result => {
-        headers = result.headers;
-        got = {
-          "dest": headers["sec-fetch-dest"]
-        };
-        assert_header_dest_equals(got, "image");
-      }),
-    "Same-origin image");
-
-  promise_test(() =>
-    requestViaImage(
-      "https://{{hosts[][www]}}:{{ports[https][0]}}/common/security-features/subresource/image.py")
-    .then(result => {
-        headers = result.headers;
-        got = {
-          "dest": headers["sec-fetch-dest"]
-        };
-        assert_header_dest_equals(got, "image");
-      }),
-    "Same-site image");
-
-  promise_test(() =>
-    requestViaImage(
-      "https://{{hosts[alt][www]}}:{{ports[https][0]}}/common/security-features/subresource/image.py")
-    .then(result => {
-        headers = result.headers;
-        got = {
-          "dest": headers["sec-fetch-dest"]
-        };
-        assert_header_dest_equals(got, "image");
-      }),
-    "Cross-site image");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/navigation.https.sub.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<html>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script>
-  test(t => {
-    let actual = {
-      "dest": "{{headers[sec-fetch-dest]}}"
-    };
-
-    assert_header_dest_equals(actual, "document");
-  }, "This page's top-level navigation.");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/object.tentative.https.sub.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8"/>
-<link rel="author" href="mtrzos@google.com" title="Maciek Trzos">
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/common/utils.js></script>
-<body>
-<script>
-  let nonce = token();
-
-  promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "object-same-origin" + nonce;
-
-      let e = document.createElement('object');
-      e.data = "https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      e.onload = e => {
-        fetch_record_header_with_catch(key, "object", assert_header_dest_equals, resolve, reject);
-      };
-
-      document.body.appendChild(e);
-    })
-  }, "Same-Origin object");
-
-  promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "object-same-site" + nonce;
-
-      let e = document.createElement('object');
-      e.data = "https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      e.onload = e => {
-        fetch_record_header_with_catch(key, "object", assert_header_dest_equals, resolve, reject);
-      };
-
-      document.body.appendChild(e);
-    })
-  }, "Same-Site object");
-
-  promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "object-cross-site" + nonce;
-
-      let e = document.createElement('object');
-      e.data = "https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      e.onload = e => {
-        fetch_record_header_with_catch(key, "object", assert_header_dest_equals, resolve, reject);
-      };
-
-      document.body.appendChild(e);
-    })
-  }, "Cross-Site object");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/portal.tentative.https.sub.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!DOCTYPE html>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/resources/testdriver.js></script>
-<script src=/resources/testdriver-vendor.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/common/utils.js></script>
-<body>
-<script>
-  const USER = true;
-  const FORCED = false;
-
-  function create_test(host, expectation) {
-    async_test(t => {
-      let p = document.createElement('portal');
-      p.addEventListener('message', t.step_func(e => {
-        assert_header_dest_equals(e.data, expectation);
-        t.done();
-      }));
-
-      let url = `https://${host}/fetch/metadata/resources/post-to-owner.py`;
-      p.src = url;
-      document.body.appendChild(p);
-    }, `{{host}} -> ${host} portal`);
-  }
-
-  // TODO(mkwst): 'document' seems right, I guess? Perhaps a portal-specific destination would be better?
-  create_test("{{host}}:{{ports[https][0]}}", "document");
-
-  create_test("{{hosts[][www]}}:{{ports[https][0]}}", "document");
-
-  create_test("{{hosts[alt][www]}}:{{ports[https][0]}}", "document");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/prefetch.tentative.https.sub.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/common/utils.js></script>
-<body></body>
-<script>
-  test(t => {
-    assert_true(document.createElement('link').relList.supports('prefetch'));
-  }, "Browser supports prefetch.");
-
-  function create_test(host, expected) {
-    async_test(t => {
-      let nonce = token();
-      let key = "prefetch" + nonce;
-
-      let e = document.createElement('link');
-      e.rel = "prefetch";
-      e.href = `https://${host}/fetch/metadata/resources/record-header.py?file=${key}`;
-      e.setAttribute("crossorigin", "crossorigin");
-      e.onload = t.step_func(e => {
-        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_dest_equals(text, expected)))
-          .catch(t.unreached_func("Fetching and verifying the results should succeed."));
-      });
-      e.onerror = t.unreached_func();
-
-      document.head.appendChild(e);
-    }, `<link rel='prefetch' href='https://${host}/...'>`);
-  }
-
-  create_test("{{host}}:{{ports[https][0]}}", "empty");
-  create_test("{{hosts[][www]}}:{{ports[https][0]}}", "empty");
-  create_test("{{hosts[alt][www]}}:{{ports[https][0]}}", "empty");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/preload.tentative.https.sub.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!DOCTYPE html>
-<meta name="timeout" content="long">
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/common/utils.js></script>
-<body></body>
-<script>
-  test(t => {
-    assert_true(document.createElement('link').relList.supports('preload'));
-  }, "Browser supports preload.");
-
-  function create_test(host, as, expected) {
-    async_test(t => {
-      let nonce = "{{uuid()}}";
-      let key = as + nonce;
-
-      let e = document.createElement('link');
-      e.rel = "preload";
-      e.href = `https://${host}/fetch/metadata/resources/record-header.py?file=${key}`;
-      e.setAttribute("crossorigin", "crossorigin");
-      if (as !== undefined) {
-        e.setAttribute("as", as);
-      }
-      e.onload = e.onerror = t.step_func_done(e => {
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(t.step_func(response => response.text()))
-          .then(t.step_func(text => assert_header_dest_equals(text, expected)))
-          .then(t.step_func_done(_ => resolve()))
-          .catch(t.unreached_func());
-      });
-
-      document.head.appendChild(e);
-    }, `<link rel='preload' as='${as}' href='https://${host}/...'>`);
-  }
-
-  let as_tests = [
-    [ "fetch", "empty" ],
-    [ "font", "font" ],
-    [ "image", "image" ],
-    [ "script", "script" ],
-    [ "style", "style" ],
-    [ "track", "track" ],
-  ];
-
-  as_tests.forEach(item => {
-    create_test("{{host}}:{{ports[https][0]}}", item[0], item[1]);
-    create_test("{{hosts[][www]}}:{{ports[https][0]}}", item[0], item[1]);
-    create_test("{{hosts[alt][www]}}:{{ports[https][0]}}", item[0], item[1]);
-  });
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/redirect/cross-site-redirect.tentative.https.sub.html
+++ /dev/null
@@ -1,62 +0,0 @@
-<!DOCTYPE html>
-
-<link rel="author" href="mtrzos@google.com" title="Maciek Trzos">
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/common/utils.js></script>
-<body></body>
-<script>
-  let nonce = token();
-
-  promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "redirect-cross-site-same-origin" + nonce;
-
-      let e = document.createElement('img');
-      e.src = "https://{{hosts[alt][www]}}:{{ports[https][0]}}/xhr/resources/redirect.py?location=https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      e.onload = e => {
-        fetch_record_header_with_catch(key, "image", assert_header_dest_equals, resolve, reject);
-      };
-      e.onerror = e => {
-        fetch_record_header_with_catch(key, "image", assert_header_dest_equals, resolve, reject);
-      };
-
-      document.body.appendChild(e);
-    })
-  }, "Cross-Site -> Same-Origin redirect");
-
-  promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "redirect-cross-site-same-site" + nonce;
-
-      let e = document.createElement('img');
-      e.src = "https://{{hosts[alt][www]}}:{{ports[https][0]}}/xhr/resources/redirect.py?location=https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      e.onload = e => {
-        fetch_record_header_with_catch(key, "image", assert_header_dest_equals, resolve, reject);
-      };
-      e.onerror = e => {
-        fetch_record_header_with_catch(key, "image", assert_header_dest_equals, resolve, reject);
-      };
-
-      document.body.appendChild(e);
-    })
-  }, "Cross-Site -> Same-Site redirect");
-
-  promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "redirect-cross-site-cross-site" + nonce;
-
-      let e = document.createElement('img');
-      e.src = "https://{{hosts[alt][www]}}:{{ports[https][0]}}/xhr/resources/redirect.py?location=https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      e.onload = e => {
-        fetch_record_header_with_catch(key, "image", assert_header_dest_equals, resolve, reject);
-      };
-      e.onerror = e => {
-        fetch_record_header_with_catch(key, "image", assert_header_dest_equals, resolve, reject);
-      };
-
-      document.body.appendChild(e);
-    })
-  }, "Cross-Site -> Cross-Site redirect");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/redirect/multiple-redirect-cross-site.tentative.https.sub.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE html>
-
-<link rel="author" href="mtrzos@google.com" title="Maciek Trzos">
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/common/utils.js></script>
-<body></body>
-<script>
-  let nonce = token();
-
-  promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "redirect-multiple-cross-site" + nonce;
-
-      let e = document.createElement('img');
-      e.src = "https://{{host}}:{{ports[https][0]}}/xhr/resources/redirect.py?location=" +// same-origin
-      "https://{{hosts[alt][www]}}:{{ports[https][0]}}/xhr/resources/redirect.py?location=" +// cross-site
-      "https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;// same-origin
-
-      e.onload = e => {
-        fetch_record_header_with_catch(key, "image", assert_header_dest_equals, resolve, reject);
-      };
-      e.onerror = e => {
-        fetch_record_header_with_catch(key, "image", assert_header_dest_equals, resolve, reject);
-      };
-
-      document.body.appendChild(e);
-    })
-  }, "Same-Origin -> Cross-Site -> Same-Origin redirect");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/redirect/multiple-redirect-https-downgrade-upgrade.tentative.sub.html
+++ /dev/null
@@ -1,57 +0,0 @@
-<!DOCTYPE html>
-<html>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/fetch/metadata/resources/redirectTestHelper.sub.js></script>
-<script src=/common/security-features/resources/common.sub.js></script>
-<script src=/common/utils.js></script>
-<style>
-  @font-face {
-    font-family: myDowngradeUpgradeFont;
-    src: url(https://{{host}}:{{ports[https][0]}}/fetch/api/resources/redirect.py?location=http%3A%2F%2F{{host}}%3A{{ports[http][0]}}%2Ffetch%2Fapi%2Fresources%2Fredirect.py%3Flocation%3Dhttps%253A%252F%252F{{host}}%253A{{ports[https][0]}}%252Ffetch%252Fmetadata%252Fresources%252Frecord-header.py%253Ffile%253Dfont-https-downgrade-upgrade{{$id:uuid()}});
-  }
-  #fontTest {
-    font-family: myDowngradeUpgradeFont;
-  }
-</style>
-<body>
-    <div id="fontTest">Downgraded then upgraded font</div>
-    <script>
-  let nonce = "{{$id}}";
-  let expected = { "dest": "", "site": "cross-site", "user": "", "mode": "cors" };
-
-  // Validate various scenarios handle a request that redirects from https => http
-  // correctly and avoids disclosure of any Sec- headers.
-  RunCommonRedirectTests("Https downgrade-upgrade", MultipleRedirectTo, expected);
-
-  document.fonts.ready.then(function () {
-    promise_test(t => {
-      return new Promise((resolve, reject) => {
-        let key = "font-https-downgrade-upgrade{{$id}}";
-        return fetch_record_header_with_catch(key, "", assert_header_dest_equals, resolve, reject);
-      });
-    }, "Https downgrade-upgrade font => No headers");
-  });
-
-  promise_test(() => {
-    return requestViaImage(secureRedirectURL + encodeURIComponent(insecureRedirectURL + encodeURIComponent("https://{{host}}:{{ports[https][0]}}/common/security-features/subresource/image.py")))
-      .then(result => {
-         headers = result.headers;
-         got = {
-           "dest": headers["sec-fetch-dest"]
-         };
-         // Note that we're using `undefined` here, as opposed to "" elsewhere because of the way
-         // that `image.py` encodes data.
-         assert_header_dest_equals(got, undefined);
-      });
-  }, "Https downgrade-upgrade image => No headers");
-</script>
-<script src="https://{{host}}:{{ports[https][0]}}/fetch/api/resources/redirect.py?location=http%3A%2F%2F{{host}}%3A{{ports[http][0]}}%2Ffetch%2Fapi%2Fresources%2Fredirect.py%3Flocation%3Dhttps%253A%252F%252F{{host}}%253A{{ports[https][0]}}%252Ffetch%252Fmetadata%252Fresources%252Fecho-as-script.py"></script>
-<script>
-  test(t => {
-    t.add_cleanup(_ => { header = null; });
-    assert_header_dest_equals(header, "");
-  }, "Https downgrade-upgrade script => No headers");
-</script>
-</body>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/redirect/multiple-redirect-same-site.tentative.https.sub.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE html>
-
-<link rel="author" href="mtrzos@google.com" title="Maciek Trzos">
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/common/utils.js></script>
-<body></body>
-<script>
-  let nonce = token();
-
-  promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "redirect-multiple-same-site" + nonce;
-
-      let e = document.createElement('img');
-      e.src = "https://{{host}}:{{ports[https][0]}}/xhr/resources/redirect.py?location=" +// same-origin
-      "https://{{hosts[][www]}}:{{ports[https][0]}}/xhr/resources/redirect.py?location=" +// same-site
-      "https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;// same-origin
-
-      e.onload = e => {
-        return fetch_record_header_with_catch(key, "image", assert_header_dest_equals, resolve, reject);
-      };
-      e.onerror = e => {
-        return fetch_record_header_with_catch(key, "image", assert_header_dest_equals, resolve, reject);
-      };
-
-      document.body.appendChild(e);
-    })
-  }, "Same-Origin -> Same-Site -> Same-Origin redirect");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/redirect/redirect-http-upgrade.tentative.sub.html
+++ /dev/null
@@ -1,57 +0,0 @@
-<!DOCTYPE html>
-<html>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/fetch/metadata/resources/redirectTestHelper.sub.js></script>
-<script src=/common/security-features/resources/common.sub.js></script>
-<script src=/common/utils.js></script>
-<style>
-  @font-face {
-    font-family: myUpgradedFont;
-    src: url(http://{{host}}:{{ports[http][0]}}/fetch/api/resources/redirect.py?location=https%3A%2F%2F{{host}}%3A{{ports[https][0]}}%2Ffetch%2Fmetadata%2Fresources%2Frecord-header.py%3Ffile%3Dfont-https-upgrade{{$id:uuid()}});
-  }
-  #fontTest {
-    font-family: myUpgradedFont;
-  }
-</style>
-<body>
-    <div id="fontTest">Upgraded font</div>
-    <script>
-  let nonce = "{{$id}}";
-  let expected = { "dest": "", "site": "cross-site", "user": "", "mode": "cors" };
-
-  // Validate various scenarios handle a request that redirects from http => https correctly and add the proper Sec- headers.
-  RunCommonRedirectTests("Http upgrade", upgradeRedirectTo, expected);
-
-  document.fonts.ready.then(function () {
-    promise_test(t => {
-      return new Promise((resolve, reject) => {
-        let key = "font-https-upgrade{{$id}}";
-        fetch_record_header_with_catch(key, "", assert_header_dest_equals, resolve, reject);
-      });
-    }, "Http upgrade font => No headers");
-  });
-
-  promise_test(() => {
-    return requestViaImage(insecureRedirectURL + encodeURIComponent("https://{{host}}:{{ports[https][0]}}/common/security-features/subresource/image.py"))
-      .then(result => {
-         headers = result.headers;
-         got = {
-           "dest": headers["sec-fetch-dest"]
-         };
-         // Note that we're using `undefined` here, as opposed to "" elsewhere because of the way
-         // that `image.py` encodes data.
-         assert_header_dest_equals(got, undefined);
-      });
-  }, "Http upgrade image => No headers");
-</script>
-
-<script src="http://{{host}}:{{ports[http][0]}}/fetch/api/resources/redirect.py?location=https%3A%2F%2F{{host}}%3A{{ports[https][0]}}%2Ffetch%2Fmetadata%2Fresources%2Fecho-as-script.py"></script>
-<script>
-  test(t => {
-    t.add_cleanup(_ => { header = null; });
-    assert_header_dest_equals(header, "");
-  }, "Http upgrade script => No headers");
-</script>
-</body>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/redirect/redirect-https-downgrade.tentative.sub.html
+++ /dev/null
@@ -1,58 +0,0 @@
-<!DOCTYPE html>
-<html>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/fetch/metadata/resources/redirectTestHelper.sub.js></script>
-<script src=/common/security-features/resources/common.sub.js></script>
-<script src=/common/utils.js></script>
-<style>
-  @font-face {
-    font-family: myDowngradedFont;
-    src: url(https://{{host}}:{{ports[https][0]}}/fetch/api/resources/redirect.py?location=http%3A%2F%2F{{host}}%3A{{ports[http][0]}}%2Ffetch%2Fmetadata%2Fresources%2Frecord-header.py%3Ffile%3Dfont-https-downgrade);
-  }
-  #fontTest {
-    font-family: myDowngradedFont;
-  }
-</style>
-<body>
-  <div id="fontTest">Downgraded font</div>
-  <script>
-  let nonce = token();
-  let expected = { "dest": "", "site": "", "user": "", "mode": "" };
-
-  // Validate various scenarios handle a request that redirects from https => http correctly and avoids disclosure of any Sec- headers.
-  RunCommonRedirectTests("Https downgrade", downgradeRedirectTo, expected);
-
-  document.fonts.ready.then(function () {
-    promise_test(t => {
-      return new Promise((resolve, reject) => {
-        let key = "font-https-downgrade";
-        fetch_record_header_with_catch(key, "", assert_header_dest_equals, resolve, reject);
-      });
-    }, "Https downgrade font => No headers");
-  });
-
-  promise_test(() => {
-    return requestViaImage(secureRedirectURL + encodeURIComponent(
-        "http://{{host}}:{{ports[http][0]}}/common/security-features/subresource/image.py"))
-        .then(result => {
-          headers = result.headers;
-          got = {
-            "dest": headers["sec-fetch-dest"]
-          };
-          // Note that we're using `undefined` here, as opposed to "" elsewhere because of the way
-          // that `image.py` encodes data.
-          assert_header_dest_equals(got, undefined);
-        });
-  }, "Https downgrade image => No headers");
-</script>
-
-<script src="https://{{host}}:{{ports[https][0]}}/fetch/api/resources/redirect.py?location=http%3A%2F%2F{{host}}%3A{{ports[http][0]}}%2Ffetch%2Fmetadata%2Fresources%2Fecho-as-script.py"></script>
-<script>
-  test(t => {
-    t.add_cleanup(_ => { header = null; });
-    assert_no_headers(header);
-  }, "Https downgrade script => No headers");
-</script>
-</body>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/redirect/same-origin-redirect.tentative.https.sub.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!DOCTYPE html>
-
-<link rel="author" href="mtrzos@google.com" title="Maciek Trzos">
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/common/utils.js></script>
-<body></body>
-<script>
-  let nonce = token();
-
-  promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "redirect-same-origin-same-origin" + nonce;
-
-      let e = document.createElement('img');
-      e.src = "/xhr/resources/redirect.py?location=https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-
-      e.onload = e => {
-        fetch_record_header_with_catch(key, "image", assert_header_dest_equals, resolve, reject);
-      };
-      e.onerror = e => {
-        fetch_record_header_with_catch(key, "image", assert_header_dest_equals, resolve, reject);
-      };
-
-      document.body.appendChild(e);
-    })
-  }, "Same-Origin -> Same-Origin redirect");
-
-promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "redirect-same-origin-same-site" + nonce;
-
-      let e = document.createElement('img');
-      e.src = "/xhr/resources/redirect.py?location=https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-
-      e.onload = e => {
-        fetch_record_header_with_catch(key, "image", assert_header_dest_equals, resolve, reject);
-      };
-      e.onerror = e => {
-        fetch_record_header_with_catch(key, "image", assert_header_dest_equals, resolve, reject);
-      };
-
-      document.body.appendChild(e);
-    })
-  }, "Same-Origin -> Same-Site redirect");
-
-promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "redirect-same-origin-cross-site" + nonce;
-
-      let e = document.createElement('img');
-      e.src = "/xhr/resources/redirect.py?location=https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-
-      e.onload = e => {
-        fetch_record_header_with_catch(key, "image", assert_header_dest_equals, resolve, reject);
-      };
-      e.onerror = e => {
-        fetch_record_header_with_catch(key, "image", assert_header_dest_equals, resolve, reject);
-      };
-
-      document.body.appendChild(e);
-    })
-  }, "Same-Origin -> Cross-Site redirect");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/redirect/same-site-redirect.tentative.https.sub.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!DOCTYPE html>
-
-<link rel="author" href="mtrzos@google.com" title="Maciek Trzos">
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/common/utils.js></script>
-<body></body>
-<script>
-  let nonce = token();
-
-  promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "redirect-same-site-same-origin" + nonce;
-
-      let e = document.createElement('img');
-      e.src = "https://{{hosts[][www]}}:{{ports[https][0]}}/xhr/resources/redirect.py?location=https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-
-      e.onload = e => {
-        fetch_record_header_with_catch(key, "image", assert_header_dest_equals, resolve, reject);
-      };
-      e.onerror = e => {
-        fetch_record_header_with_catch(key, "image", assert_header_dest_equals, resolve, reject);
-      };
-
-      document.body.appendChild(e);
-    })
-  }, "Same-Site -> Same-Origin redirect");
-
-promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "redirect-same-site-same-site" + nonce;
-
-      let e = document.createElement('img');
-      e.src = "https://{{hosts[][www]}}:{{ports[https][0]}}/xhr/resources/redirect.py?location=https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-
-      e.onload = e => {
-        fetch_record_header_with_catch(key, "image", assert_header_dest_equals, resolve, reject);
-      };
-      e.onerror = e => {
-        fetch_record_header_with_catch(key, "image", assert_header_dest_equals, resolve, reject);
-      };
-
-      document.body.appendChild(e);
-    })
-  }, "Same-Site -> Same-Site redirect");
-
-promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "redirect-same-site-cross-site" + nonce;
-
-      let e = document.createElement('img');
-      e.src = "https://{{hosts[][www]}}:{{ports[https][0]}}/xhr/resources/redirect.py?location=https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-
-      e.onload = e => {
-        fetch_record_header_with_catch(key, "image", assert_header_dest_equals, resolve, reject);
-      };
-      e.onerror = e => {
-        fetch_record_header_with_catch(key, "image", assert_header_dest_equals, resolve, reject);
-      };
-
-      document.body.appendChild(e);
-    })
-  }, "Same-Site -> Cross-Site redirect");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/report.tentative.https.sub.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE html>
-<link rel="author" href="mtrzos@google.com" title="Maciek Trzos">
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<link id="style" href="https://foo.bar" rel="stylesheet">
-<body></body>
-<script>
-  setup({ explicit_done: true });
-  function generate_test(expected, name) {
-    async_test(t => {
-      t.step_timeout(_ => {
-        return fetch_record_header("report-" + name, expected, assert_header_dest_equals)
-            .then(_ => t.done());
-      }, 1000);
-    }, name + " report");
-  }
-
-  let counter = 0;
-  document.addEventListener("securitypolicyviolation", (e) => {
-    counter++;
-    if (counter == 3) {
-      generate_test("report", "same-origin");
-      generate_test("report", "same-site");
-      generate_test("report", "cross-site");
-
-      done();
-    }
-  });
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/report.tentative.https.sub.html.sub.headers
+++ /dev/null
@@ -1,3 +0,0 @@
-Content-Security-Policy: style-src 'self' 'unsafe-inline'; report-uri /fetch/metadata/resources/record-header.py?file=report-same-origin
-Content-Security-Policy: style-src 'self' 'unsafe-inline'; report-uri https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=report-same-site
-Content-Security-Policy: style-src 'self' 'unsafe-inline'; report-uri https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=report-cross-site
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/script.tentative.https.sub.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE html>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-
-<!-- Same-origin script -->
-<script src="https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-script.py"></script>
-<script>
-  test(t => {
-    t.add_cleanup(_ => { header = null; });
-
-    assert_header_dest_equals(header, "script");
-  }, "Same-origin script");
-</script>
-
-<!-- Same-site script -->
-<script src="https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-script.py"></script>
-<script>
-  test(t => {
-    t.add_cleanup(_ => { header = null; });
-
-    assert_header_dest_equals(header, "script");
-  }, "Same-site script");
-</script>
-
-<!-- Cross-site script -->
-<script src="https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-script.py"></script>
-<script>
-  test(t => {
-    t.add_cleanup(_ => { header = null; });
-
-    assert_header_dest_equals(header, "script");
-  }, "Cross-site script");
-</script>
-
-<!-- Same-origin script, CORS mode -->
-<script src="https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/echo-as-script.py" crossorigin="anonymous"></script>
-<script>
-  test(t => {
-    t.add_cleanup(_ => { header = null; });
-
-    assert_header_dest_equals(header, "script");
-  }, "Same-origin CORS script");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/script.tentative.sub.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE html>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-
-<!-- Same-origin script -->
-<script src="http://{{host}}:{{ports[http][0]}}/fetch/metadata/resources/echo-as-script.py"></script>
-<script>
-  test(t => {
-    t.add_cleanup(_ => { header = null; });
-
-    assert_header_dest_equals(header, "");
-  }, "Non-secure same-origin script => No headers");
-</script>
-
-<!-- Same-site script -->
-<script src="http://{{hosts[][www]}}:{{ports[http][0]}}/fetch/metadata/resources/echo-as-script.py"></script>
-<script>
-  test(t => {
-    t.add_cleanup(_ => { header = null; });
-
-    assert_header_dest_equals(header, "");
-  }, "Non-secure same-site script => No headers");
-</script>
-
-<!-- Cross-site script -->
-<script src="http://{{hosts[alt][www]}}:{{ports[http][0]}}/fetch/metadata/resources/echo-as-script.py"></script>
-<script>
-  test(t => {
-    t.add_cleanup(_ => { header = null; });
-
-    assert_header_dest_equals(header, "");
-  }, "Non-secure cross-site script => No headers");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/serviceworker.tentative.https.sub.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!DOCTYPE html>
-<!--
-  This test verifies presence of Sec-Fetch-... request headers on a request
-  that fetches the service worker script itself (i.e. the script at the URL
-  passed as an argument to navigator.serviceWorker.register).
--->
-<meta charset="utf-8"/>
-<link rel="author" href="mtrzos@google.com" title="Maciek Trzos">
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/common/utils.js></script>
-<body>
-  <script>
-    promise_test(async t => {
-      const nonce = token();
-      const key = "serviceworker-same-origin" + nonce;
-
-      // Register a service worker and check the request header.
-      const registration = await navigator.serviceWorker.register('https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=' + key);
-      t.add_cleanup(() => registration.unregister());
-      await retrieve_and_assert_headers(key, 'Register service worker');
-
-      // Trigger an update check and check the request header again.
-      await registration.update();
-      await retrieve_and_assert_headers(key, 'Update service worker');
-    }, 'metadata for service worker scripts');
-
-    async function retrieve_and_assert_headers(key, tag) {
-      const response = await fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-      const text = await response.text();
-      assert_header_dest_equals(text, "serviceworker", tag);
-    }
-  </script>
-</body>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/sharedworker.tentative.https.sub.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html>
-
-<link rel="author" href="mtrzos@google.com" title="Maciek Trzos">
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/common/utils.js></script>
-<script>
-  let nonce = token();
-  let key = "sharedworker-same-origin" + nonce;
-
-  // TESTS //
-  if (window.Worker) {
-
-      //  Same-Origin test
-      var sharedWorker = new SharedWorker('/fetch/metadata/resources/record-header.py?file=' + key);
-      sharedWorker.port.start();
-
-      sharedWorker.onerror = function(){
-        test_same_origin();
-      }
-      sharedWorker.port.onmessage = function(e) {
-        test_same_origin();
-      }
-      sharedWorker.port.postMessage("Ready");
-    }
-
-  function test_same_origin(){
-    promise_test(t => {
-      return new Promise((resolve, reject) => {
-        fetch_record_header_with_catch(key, "sharedworker", assert_header_dest_equals, resolve, reject);
-      })
-    }, "Same-Origin sharedworker")
-  }
-</script>
-<body></body>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/style.tentative.https.sub.html
+++ /dev/null
@@ -1,74 +0,0 @@
-<!DOCTYPE html>
-<html>
-<link rel="author" href="mtrzos@google.com" title="Maciek Trzos">
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/common/utils.js></script>
-<body></body>
-<script>
-  let nonce = token();
-
-  promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "style-same-origin" + nonce;
-
-      let e = document.createElement('link');
-      e.rel = "stylesheet";
-      e.href = "https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      e.onload = e => {
-        fetch_record_header_with_catch(key, "style", assert_header_dest_equals, resolve, reject);
-      };
-
-      document.body.appendChild(e);
-    })
-  }, "Same-Origin style");
-
-  promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "style-same-site" + nonce;
-
-      let e = document.createElement('link');
-      e.rel = "stylesheet";
-      e.href = "https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      e.onload = e => {
-        fetch_record_header_with_catch(key, "style", assert_header_dest_equals, resolve, reject);
-      };
-
-      document.body.appendChild(e);
-    })
-  }, "Same-Site style");
-
-  promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "style-cross-site" + nonce;
-
-      let e = document.createElement('link');
-      e.rel = "stylesheet";
-      e.href = "https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      e.onload = e => {
-        fetch_record_header_with_catch(key, "style", assert_header_dest_equals, resolve, reject);
-      };
-
-      document.body.appendChild(e);
-    })
-  }, "Cross-Site style");
-
-  promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "style-same-origin-cors" + nonce;
-
-      let e = document.createElement('link');
-      e.rel = "stylesheet";
-      e.href = "https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      e.crossOrigin = "anonymous";
-      e.onload = e => {
-        fetch_record_header_with_catch(key, "style", assert_header_dest_equals, resolve, reject);
-      };
-
-      document.body.appendChild(e);
-    })
-  }, "Same-Origin, cors style");
-</script>
-</html>
-
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/track.tentative.https.sub.html
+++ /dev/null
@@ -1,88 +0,0 @@
-<!DOCTYPE html>
-
-<link rel="author" href="mtrzos@google.com" title="Maciek Trzos">
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/common/utils.js></script>
-<body>
-</body>
-<script>
-  let nonce = token();
-
-  function createVideoElement() {
-    let el = document.createElement('video');
-    el.src = "/media/movie_5.mp4";
-    el.setAttribute("controls", "");
-    el.setAttribute("crossorigin", "");
-    return el;
-  }
-
-  function createTrack() {
-    let el = document.createElement("track");
-    el.setAttribute("default", "");
-    el.setAttribute("kind", "captions");
-    el.setAttribute("srclang", "en");
-    return el;
-  }
-
-  promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "track-same-origin" + nonce;
-      let video = createVideoElement();
-      let el = createTrack();
-      el.src = "https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      el.onload = t.step_func(_ => {
-        fetch_record_header_with_catch(key, "track", assert_header_dest_equals, resolve, reject);
-      });
-      video.appendChild(el);
-      document.body.appendChild(video);
-    });
-  }, "Same-Origin track");
-
-  promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "track-same-site" + nonce;
-      let video = createVideoElement();
-      let el = createTrack();
-      el.src = "https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      el.onload = t.step_func(_ => {
-        fetch_record_header_with_catch(key, "track", assert_header_dest_equals, resolve, reject);
-      });
-      video.appendChild(el);
-      document.body.appendChild(video);
-    });
-  }, "Same-Site track");
-
-  promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "track-cross-site" + nonce;
-      let video = createVideoElement();
-      let el = createTrack();
-      el.src = "https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      el.onload = t.step_func(_ => {
-        fetch_record_header_with_catch(key, "track", assert_header_dest_equals, resolve, reject);
-      });
-      video.appendChild(el);
-      document.body.appendChild(video);
-    });
-  }, "Cross-Site track");
-
-  promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "track-same-origin-cors" + nonce;
-      let video = createVideoElement();
-
-      // Unset `crossorigin` to change the CORS mode:
-      video.crossOrigin = undefined;
-
-      let el = createTrack();
-      el.src = "https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
-      el.onload = t.step_func(_ => {
-        fetch_record_header_with_catch(key, "track", assert_header_dest_equals, resolve, reject);
-      });
-      video.appendChild(el);
-      document.body.appendChild(video);
-    });
-  }, "Same-Origin, CORS track");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/trailing-dot.tentative.https.sub.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE html>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script>
-  // Site
-  promise_test(t => {
-    return fetch("https://{{host}}.:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py")
-        .then(r => r.json())
-        .then(j => {
-          assert_header_dest_equals(j, "empty");
-        });
-  }, "Fetching a resource from the same origin, but spelled with a trailing dot.");
-
-  promise_test(t => {
-    return fetch("https://{{hosts[][www]}}.:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py")
-        .then(r => r.json())
-        .then(j => {
-          assert_header_dest_equals(j, "empty");
-        });
-  }, "Fetching a resource from the same site, but spelled with a trailing dot.");
-
-  promise_test(t => {
-    return fetch("https://{{hosts[alt][www]}}.:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py")
-        .then(r => r.json())
-        .then(j => {
-          assert_header_dest_equals(j, "empty");
-        });
-  }, "Fetching a resource from a cross-site host, spelled with a trailing dot.");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/unload.tentative.https.sub.html
+++ /dev/null
@@ -1,58 +0,0 @@
-<!DOCTYPE html>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/resources/testdriver.js></script>
-<script src=/resources/testdriver-vendor.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/common/utils.js></script>
-<body>
-<script>
-  // The test
-  // 1. Creates a same-origin iframe
-  // 2. Adds to the iframe an unload handler that will
-  //    trigger a request to <unload_request_url>/.../record-header.py...
-  // 3. Navigate the iframe to a cross-origin url (to data: url)
-  // 4. Waits until the request goes through
-  // 5. Verifies Sec-Fetch-Site request header of the request.
-  //
-  // This is a regression test for https://crbug.com/986577.
-  function create_test(unload_request_origin, expectation) {
-    async_test(t => {
-      // STEP 1: Create an iframe.
-      let nonce = token();
-      let key = "unload-test-" + nonce;
-      let url = unload_request_origin +
-          "/fetch/metadata/resources/record-header.py?file=" + key;
-      let i = document.createElement('iframe');
-      i.src = '/fetch/metadata/resources/unload-with-beacon.html';
-      i.onload = () => {
-          // STEP 2: Ask the iframe to add an unload handler.
-          i.contentWindow.postMessage(url, '*');
-      };
-      window.addEventListener('message', e => {
-          // STEP 3: Navigate the iframe away
-          i.contentWindow.location = 'data:text/html,DONE';
-      });
-      document.body.appendChild(i);
-
-      // STEPS 4 and 5: Wait for the beacon to go through and verify
-      // the request headers.
-      function wait_and_verify() {
-          t.step_timeout(() => {
-              let callback_method = text => t.step(() => {
-                if (text == "No header has been recorded") {
-                  wait_and_verify();
-                  return;
-                }
-                assert_header_dest_equals(text, expectation);
-                t.done();
-              });
-              fetch_record_header(key, expectation, callback_method);
-          }, 200);
-      }
-      wait_and_verify();
-    }, "Fetch from an unload handler");
-  }
-
-  create_test("https://{{host}}:{{ports[https][0]}}", "empty");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/window-open.tentative.https.sub.html
+++ /dev/null
@@ -1,154 +0,0 @@
-<!DOCTYPE html>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/resources/testdriver.js></script>
-<script src=/resources/testdriver-vendor.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<body>
-<script>
-  // Forced navigations:
-  async_test(t => {
-    let w = window.open("https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/post-to-owner.py");
-    t.add_cleanup(_ => w.close());
-    window.addEventListener('message', t.step_func(e => {
-      if (e.source != w)
-        return;
-
-      assert_header_dest_equals(e.data, "document");
-      t.done();
-    }));
-  }, "Same-origin window, forced");
-
-  async_test(t => {
-    let w = window.open("https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/post-to-owner.py");
-    t.add_cleanup(_ => w.close());
-    window.addEventListener('message', t.step_func(e => {
-      if (e.source != w)
-        return;
-
-      assert_header_dest_equals(e.data, "document");
-      t.done();
-    }));
-  }, "Same-site window, forced");
-
-  async_test(t => {
-    let w = window.open("https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/post-to-owner.py");
-    t.add_cleanup(_ => w.close());
-    window.addEventListener('message', t.step_func(e => {
-      if (e.source != w)
-        return;
-
-      assert_header_dest_equals(e.data, "document");
-      t.done();
-    }));
-  }, "Cross-site window, forced");
-
-  async_test(t => {
-    let w = window.open("https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/post-to-owner.py");
-    t.add_cleanup(_ => w.close());
-    let messages = 0;
-    window.addEventListener('message', t.step_func(e => {
-      messages++;
-      if (e.source != w)
-        return;
-
-      assert_header_dest_equals(e.data, "document");
-
-      if (messages == 1) {
-        w.location.reload();
-      } else {
-        t.done();
-      }
-    }));
-  }, "Same-origin window, forced, reloaded");
-
-  async_test(t => {
-    let w = window.open("https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/post-to-owner.py");
-    t.add_cleanup(_ => w.close());
-    let messages = 0;
-    window.addEventListener('message', t.step_func(e => {
-      messages++;
-      if (e.source != w)
-        return;
-
-      assert_header_dest_equals(e.data, "document");
-
-      if (messages == 1) {
-        w.location.reload();
-      } else {
-        t.done();
-      }
-    }));
-  }, "Same-site window, forced, reloaded");
-
-  async_test(t => {
-    let w = window.open("https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/post-to-owner.py");
-    t.add_cleanup(_ => w.close());
-    let messages = 0;
-    window.addEventListener('message', t.step_func(e => {
-      messages++;
-      if (e.source != w)
-        return;
-
-      assert_header_dest_equals(e.data, "document");
-
-      if (messages == 1) {
-        w.location.reload();
-      } else {
-        t.done();
-      }
-    }));
-  }, "Cross-site window, forced, reloaded");
-
-  // User-activated navigations:
-  async_test(t => {
-    let b = document.createElement('button');
-    b.onclick = t.step_func(_ => {
-      let w = window.open("https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/post-to-owner.py");
-      t.add_cleanup(_ => w.close());
-      window.addEventListener('message', t.step_func(e => {
-        if (e.source != w)
-          return;
-
-        assert_header_dest_equals(e.data, "document");
-        t.done();
-      }));
-    });
-    document.body.appendChild(b);
-    test_driver.click(b);
-  }, "Same-origin window, user-activated");
-
-  async_test(t => {
-    let b = document.createElement('button');
-    b.onclick = t.step_func(_ => {
-      let w = window.open("https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/post-to-owner.py");
-      t.add_cleanup(_ => w.close());
-      window.addEventListener('message', t.step_func(e => {
-        if (e.source != w)
-          return;
-
-        assert_header_dest_equals(e.data, "document");
-        t.done();
-      }));
-    });
-    document.body.appendChild(b);
-    test_driver.click(b);
-  }, "Same-site window, user-activated");
-
-  async_test(t => {
-    let b = document.createElement('button');
-    b.onclick = t.step_func(_ => {
-      let w = window.open("https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/post-to-owner.py");
-      t.add_cleanup(_ => w.close());
-      window.addEventListener('message', t.step_func(e => {
-        if (e.source != w)
-          return;
-
-        assert_header_dest_equals(e.data, "document");
-        t.done();
-      }));
-    });
-    document.body.appendChild(b);
-    test_driver.click(b);
-  }, "Cross-site window, user-activated");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/worker.tentative.https.sub.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-
-<link rel="author" href="mtrzos@google.com" title="Maciek Trzos">
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/common/utils.js></script>
-<script>
-  let nonce = token();
-
-  promise_test(t => {
-    return new Promise((resolve, reject) => {
-      let key = "worker-same-origin" + nonce;
-      let w = new Worker("/fetch/metadata/resources/record-header.py?file=" + key);
-      w.onmessage = e => {
-        fetch_record_header_with_catch(key, "worker", assert_header_dest_equals, resolve, reject);
-      };
-    });
-  }, "Same-Origin worker");
-</script>
-<body></body>
deleted file mode 100644
--- a/testing/web-platform/tests/fetch/metadata/sec-fetch-dest/xslt.tentative.https.sub.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-
-<link rel="author" href="mtrzos@google.com" title="Maciek Trzos">
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/fetch/metadata/resources/helper.js></script>
-<script src=/common/utils.js></script>
-<script>
-  // Open a window with XML document which loads resources via <?xml-stylesheet/> tag
-  let nonce = token();
-  let w = window.open("/fetch/metadata/resources/xslt-test.sub.xml?token=" + nonce);
-  window.addEventListener('message', function(e) {
-    if (e.source != w)
-      return;
-
-    promise_test(t => {
-      return fetch_record_header("xslt-same-origin" + nonce, "xslt", assert_header_dest_equals);
-    }, "Same-Origin xslt");
-
-    w.close();
-  });
-
-</script>
--- a/testing/web-platform/tests/fetch/metadata/serviceworker.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/serviceworker.tentative.https.sub.html
@@ -22,15 +22,15 @@
       await retrieve_and_assert_headers(key, 'Register service worker');
 
       // Trigger an update check and check the request header again.
       await registration.update();
       await retrieve_and_assert_headers(key, 'Update service worker');
     }, 'metadata for service worker scripts');
 
     async function retrieve_and_assert_headers(key, tag) {
-      let expected = { "site": "same-origin", "user": "", "mode": "same-origin" };
+      let expected = { "site": "same-origin", "user": "", "mode": "same-origin", "dest": "serviceworker" };
       const response = await fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key);
       const text = await response.text();
       assert_header_equals(text, expected, tag);
     }
   </script>
 </body>
--- a/testing/web-platform/tests/fetch/metadata/sharedworker.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/sharedworker.tentative.https.sub.html
@@ -23,20 +23,18 @@
         test_same_origin();
       }
       sharedWorker.port.postMessage("Ready");
     }
 
   function test_same_origin(){
     promise_test(t => {
       return new Promise((resolve, reject) => {
-        let expected = {"site":"same-origin", "user":"", "mode": "same-origin"};
+        let expected = {"site":"same-origin", "user":"", "mode": "same-origin", "dest": "sharedworker"};
 
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected)
           .then(_ => resolve())
           .catch(e => reject(e));
       })
     }, "Same-Origin sharedworker")
   }
 </script>
 <body></body>
--- a/testing/web-platform/tests/fetch/metadata/style.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/style.tentative.https.sub.html
@@ -12,60 +12,54 @@
   promise_test(t => {
     return new Promise((resolve, reject) => {
       let key = "style-same-origin" + nonce;
 
       let e = document.createElement('link');
       e.rel = "stylesheet";
       e.href = "https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
       e.onload = e => {
-        let expected = {"site":"same-origin", "user":"", "mode": "no-cors"};
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        let expected = {"site":"same-origin", "user":"", "mode": "no-cors", "dest": "style"};
+        validate_expectations(key, expected, "Same-Origin style")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
 
       document.body.appendChild(e);
     })
   }, "Same-Origin style");
 
   promise_test(t => {
     return new Promise((resolve, reject) => {
       let key = "style-same-site" + nonce;
 
       let e = document.createElement('link');
       e.rel = "stylesheet";
       e.href = "https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
       e.onload = e => {
-        let expected = {"site":"same-site", "user":"", "mode": "no-cors"};
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        let expected = {"site":"same-site", "user":"", "mode": "no-cors", "dest": "style"};
+        validate_expectations(key, expected, "Same-Site style")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
 
       document.body.appendChild(e);
     })
   }, "Same-Site style");
 
   promise_test(t => {
     return new Promise((resolve, reject) => {
       let key = "style-cross-site" + nonce;
 
       let e = document.createElement('link');
       e.rel = "stylesheet";
       e.href = "https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
       e.onload = e => {
-        let expected = {"site":"cross-site", "user":"", "mode": "no-cors"};
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        let expected = {"site":"cross-site", "user":"", "mode": "no-cors", "dest": "style"};
+        validate_expectations(key, expected, "Cross-Site style")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
 
       document.body.appendChild(e);
     })
   }, "Cross-Site style");
 
@@ -73,20 +67,18 @@
     return new Promise((resolve, reject) => {
       let key = "style-same-origin-cors" + nonce;
 
       let e = document.createElement('link');
       e.rel = "stylesheet";
       e.href = "https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
       e.crossOrigin = "anonymous";
       e.onload = e => {
-        let expected = {"site":"same-origin", "user":"", "mode": "cors"};
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        let expected = {"site":"same-origin", "user":"", "mode": "cors", "dest": "style"};
+        validate_expectations(key, expected, "Same-Origin, cors style")
           .then(_ => resolve())
           .catch(e => reject(e));
       };
 
       document.body.appendChild(e);
     })
   }, "Same-Origin, cors style");
 </script>
--- a/testing/web-platform/tests/fetch/metadata/track.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/track.tentative.https.sub.html
@@ -31,21 +31,20 @@
       let key = "track-same-origin" + nonce;
       let video = createVideoElement();
       let el = createTrack();
       el.src = "https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
       el.onload = t.step_func(_ => {
         expected = {
           "site": "same-origin",
           "user": "",
-          "mode": "cors" // Because the `video` element has `crossorigin`
+          "mode": "cors", // Because the `video` element has `crossorigin`
+          "dest": "track"
         };
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-            .then(response => response.text())
-            .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected, "Same-Origin track")
             .then(_ => resolve());
       });
       video.appendChild(el);
       document.body.appendChild(video);
     });
   }, "Same-Origin track");
 
   promise_test(t => {
@@ -53,21 +52,20 @@
       let key = "track-same-site" + nonce;
       let video = createVideoElement();
       let el = createTrack();
       el.src = "https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
       el.onload = t.step_func(_ => {
         expected = {
           "site": "same-site",
           "user": "",
-          "mode": "cors" // Because the `video` element has `crossorigin`
+          "mode": "cors", // Because the `video` element has `crossorigin`
+          "dest": "track"
         };
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-            .then(response => response.text())
-            .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected, "Same-Site track")
             .then(resolve)
             .catch(reject);
 
       });
       video.appendChild(el);
       document.body.appendChild(video);
     });
   }, "Same-Site track");
@@ -77,21 +75,20 @@
       let key = "track-cross-site" + nonce;
       let video = createVideoElement();
       let el = createTrack();
       el.src = "https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
       el.onload = t.step_func(_ => {
         expected = {
           "site": "cross-site",
           "user": "",
-          "mode": "cors" // Because the `video` element has `crossorigin`
+          "mode": "cors", // Because the `video` element has `crossorigin`
+          "dest": "track"
         };
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-            .then(response => response.text())
-            .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected,"Cross-Site track")
             .then(resolve)
             .catch(reject);
       });
       video.appendChild(el);
       document.body.appendChild(video);
     });
   }, "Cross-Site track");
 
@@ -104,20 +101,19 @@
       video.crossOrigin = undefined;
 
       let el = createTrack();
       el.src = "https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/record-header.py?file=" + key;
       el.onload = t.step_func(_ => {
         expected = {
           "site":"same-origin",
           "user":"",
-          "mode": "same-origin"
+          "mode": "same-origin",
+          "dest": "track"
         };
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-            .then(response => response.text())
-            .then(text => assert_header_equals(text, expected))
+        validate_expectations(key, expected, "Same-Origin, CORS track")
             .then(_ => resolve());
       });
       video.appendChild(el);
       document.body.appendChild(video);
     });
   }, "Same-Origin, CORS track");
 </script>
--- a/testing/web-platform/tests/fetch/metadata/trailing-dot.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/trailing-dot.tentative.https.sub.html
@@ -1,42 +1,33 @@
 <!DOCTYPE html>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
 <script src=/fetch/metadata/resources/helper.js></script>
 <script>
   // Site
   promise_test(t => {
-    return fetch("https://{{host}}.:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py")
-        .then(r => r.json())
-        .then(j => {
-          assert_header_equals(j, {
+    return validate_expectations_custom_url("https://{{host}}.:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py", {}, {
             "site": "cross-site",
             "user": "",
             "mode": "cors",
-          });
-        });
+            "dest": "empty"
+          }, "Fetching a resource from the same origin, but spelled with a trailing dot.");
   }, "Fetching a resource from the same origin, but spelled with a trailing dot.");
 
   promise_test(t => {
-    return fetch("https://{{hosts[][www]}}.:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py")
-        .then(r => r.json())
-        .then(j => {
-          assert_header_equals(j, {
+    return validate_expectations_custom_url("https://{{hosts[][www]}}.:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py", {}, {
             "site": "cross-site",
             "user": "",
             "mode": "cors",
-          });
-        });
+            "dest": "empty"
+          }, "Fetching a resource from the same site, but spelled with a trailing dot.");
   }, "Fetching a resource from the same site, but spelled with a trailing dot.");
 
   promise_test(t => {
-    return fetch("https://{{hosts[alt][www]}}.:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py")
-        .then(r => r.json())
-        .then(j => {
-          assert_header_equals(j, {
+    return validate_expectations_custom_url("https://{{hosts[alt][www]}}.:{{ports[https][0]}}/fetch/metadata/resources/echo-as-json.py", {}, {
             "site": "cross-site",
             "user": "",
             "mode": "cors",
-          });
-        });
+            "dest": "empty"
+          }, "Fetching a resource from a cross-site host, spelled with a trailing dot.");
   }, "Fetching a resource from a cross-site host, spelled with a trailing dot.");
 </script>
--- a/testing/web-platform/tests/fetch/metadata/unload.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/unload.tentative.https.sub.html
@@ -53,11 +53,12 @@
       }
       wait_and_verify();
     }, "Fetch from an unload handler");
   }
 
   create_test("https://{{host}}:{{ports[https][0]}}", {
     "site": "same-origin",
     "user": "",
-    "mode": "no-cors"
+    "mode": "no-cors",
+    "dest": "empty"
   });
 </script>
--- a/testing/web-platform/tests/fetch/metadata/window-open.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/window-open.tentative.https.sub.html
@@ -13,49 +13,52 @@
     window.addEventListener('message', t.step_func(e => {
       if (e.source != w)
         return;
 
       assert_header_equals(e.data, {
         "site": "same-origin",
         "user": "",
         "mode": "navigate",
-      });
+        "dest": "document"
+      }, "Same-origin window, forced");
       t.done();
     }));
   }, "Same-origin window, forced");
 
   async_test(t => {
     let w = window.open("https://{{hosts[][www]}}:{{ports[https][0]}}/fetch/metadata/resources/post-to-owner.py");
     t.add_cleanup(_ => w.close());
     window.addEventListener('message', t.step_func(e => {
       if (e.source != w)
         return;
 
       assert_header_equals(e.data, {
         "site": "same-site",
         "user": "",
         "mode": "navigate",
-      });
+        "dest": "document"
+      }, "Same-site window, forced");
       t.done();
     }));
   }, "Same-site window, forced");
 
   async_test(t => {
     let w = window.open("https://{{hosts[alt][www]}}:{{ports[https][0]}}/fetch/metadata/resources/post-to-owner.py");
     t.add_cleanup(_ => w.close());
     window.addEventListener('message', t.step_func(e => {
       if (e.source != w)
         return;
 
       assert_header_equals(e.data, {
         "site": "cross-site",
         "user": "",
         "mode": "navigate",
-      });
+        "dest": "document"
+      }, "Cross-site window, forced");
       t.done();
     }));
   }, "Cross-site window, forced");
 
   async_test(t => {
     let w = window.open("https://{{host}}:{{ports[https][0]}}/fetch/metadata/resources/post-to-owner.py");
     t.add_cleanup(_ => w.close());
     let messages = 0;
@@ -63,17 +66,18 @@
       messages++;
       if (e.source != w)
         return;
 
       assert_header_equals(e.data, {
         "site": "same-origin",
         "user": "",
         "mode": "navigate",
-      });
+        "dest": "document"
+      }, "Same-origin window, forced, reloaded");
 
       if (messages == 1) {
         w.location.reload();
       } else {
         t.done();
       }
     }));
   }, "Same-origin window, forced, reloaded");
@@ -86,17 +90,18 @@
       messages++;
       if (e.source != w)
         return;
 
       assert_header_equals(e.data, {
         "site": "same-site",
         "user": "",
         "mode": "navigate",
-      });
+        "dest": "document"
+      }, "Same-site window, forced, reloaded");
 
       if (messages == 1) {
         w.location.reload();
       } else {
         t.done();
       }
     }));
   }, "Same-site window, forced, reloaded");
@@ -109,17 +114,18 @@
       messages++;
       if (e.source != w)
         return;
 
       assert_header_equals(e.data, {
         "site": "cross-site",
         "user": "",
         "mode": "navigate",
-      });
+        "dest": "document"
+      }, "Cross-site window, forced, reloaded");
 
       if (messages == 1) {
         w.location.reload();
       } else {
         t.done();
       }
     }));
   }, "Cross-site window, forced, reloaded");
@@ -133,17 +139,18 @@
       window.addEventListener('message', t.step_func(e => {
         if (e.source != w)
           return;
 
         assert_header_equals(e.data, {
           "site": "same-origin",
           "user": "?1",
           "mode": "navigate",
-        });
+          "dest": "document"
+        }, "Same-origin window, user-activated");
         t.done();
       }));
     });
     document.body.appendChild(b);
     test_driver.click(b);
   }, "Same-origin window, user-activated");
 
   async_test(t => {
@@ -154,17 +161,18 @@
       window.addEventListener('message', t.step_func(e => {
         if (e.source != w)
           return;
 
         assert_header_equals(e.data, {
           "site": "same-site",
           "user": "?1",
           "mode": "navigate",
-        });
+          "dest": "document"
+        }, "Same-site window, user-activated");
         t.done();
       }));
     });
     document.body.appendChild(b);
     test_driver.click(b);
   }, "Same-site window, user-activated");
 
   async_test(t => {
@@ -175,16 +183,17 @@
       window.addEventListener('message', t.step_func(e => {
         if (e.source != w)
           return;
 
         assert_header_equals(e.data, {
           "site": "cross-site",
           "user": "?1",
           "mode": "navigate",
-        });
+          "dest": "document"
+        }, "Cross-site window, user-activated");
         t.done();
       }));
     });
     document.body.appendChild(b);
     test_driver.click(b);
   }, "Cross-site window, user-activated");
 </script>
--- a/testing/web-platform/tests/fetch/metadata/worker.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/worker.tentative.https.sub.html
@@ -8,19 +8,17 @@
 <script>
   let nonce = token();
 
   promise_test(t => {
     return new Promise((resolve, reject) => {
       let key = "worker-same-origin" + nonce;
       let w = new Worker("/fetch/metadata/resources/record-header.py?file=" + key);
       w.onmessage = e => {
-        let expected = {"site":"same-origin", "user":"", "mode": "same-origin"};
-        fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=" + key)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected))
+        let expected = {"site":"same-origin", "user":"", "mode": "same-origin", "dest": "worker"};
+        validate_expectations(key, expected)
           .then(_ => resolve())
           .catch(e => reject(e));
       };
     });
   }, "Same-Origin worker");
 </script>
 <body></body>
--- a/testing/web-platform/tests/fetch/metadata/xslt.tentative.https.sub.html
+++ b/testing/web-platform/tests/fetch/metadata/xslt.tentative.https.sub.html
@@ -10,18 +10,16 @@
   let nonce = token();
   let w = window.open("resources/xslt-test.sub.xml?token=" + nonce);
   window.addEventListener('message', function(e) {
     if (e.source != w)
       return;
 
     // Only testing same-origin XSLT because same-site and cross-site XSLT is blocked.
     promise_test(t => {
-      let expected = {"site":"same-origin", "user":"", "mode": "same-origin"};
-      return fetch("/fetch/metadata/resources/record-header.py?retrieve=true&file=xslt-same-origin" + nonce)
-          .then(response => response.text())
-          .then(text => assert_header_equals(text, expected));
+      let expected = {"site":"same-origin", "user":"", "mode": "same-origin", "dest": "xslt"};
+      return validate_expectations("xslt-same-origin" + nonce, expected);
     }, "Same-Origin xslt");
 
     w.close();
   });
 
 </script>