Bug 1508292: Implement Sec-Fetch-*. r=baku
☠☠ backed out by e492baeecfa8 ☠ ☠
authorChristoph Kerschbaumer <ckerschb@christophkerschbaumer.com>
Sat, 14 Mar 2020 17:28:41 +0000
changeset 518805 a0508ae6c037928981ac2733860b6ec84d7069ec
parent 518804 f6b264818bbfc385da9010ed49dfecf2efd436f3
child 518806 0bd7b6fc23db7c5a9536dce865e742e7d6f7f7e8
push id37216
push usercsabou@mozilla.com
push dateSun, 15 Mar 2020 09:37:49 +0000
treeherdermozilla-central@7eedc316b2c7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1508292
milestone76.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 1508292: Implement Sec-Fetch-*. r=baku Differential Revision: https://phabricator.services.mozilla.com/D66283
dom/security/SecFetch.cpp
dom/security/SecFetch.h
dom/security/moz.build
modules/libpref/init/StaticPrefList.yaml
netwerk/protocol/http/nsHttpChannel.cpp
services/common/tests/unit/test_restrequest.js
testing/web-platform/meta/fetch/metadata/__dir__.ini
testing/web-platform/meta/fetch/metadata/embed.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/fetch-preflight.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/fetch-via-serviceworker--fallback.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/fetch-via-serviceworker--respondWith.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/fetch.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/fetch.sub.html.ini
testing/web-platform/meta/fetch/metadata/font.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/form.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/history.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/iframe.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/iframe.sub.html.ini
testing/web-platform/meta/fetch/metadata/img.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/navigation.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/object.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/redirect/__dir__.ini
testing/web-platform/meta/fetch/metadata/redirect/cross-site-redirect.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/redirect/multiple-redirect-cross-site.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/redirect/multiple-redirect-https-downgrade-upgrade.sub.html.ini
testing/web-platform/meta/fetch/metadata/redirect/multiple-redirect-same-site.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/redirect/redirect-http-upgrade.sub.html.ini
testing/web-platform/meta/fetch/metadata/redirect/same-origin-redirect.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/redirect/same-site-redirect.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/report.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/script.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/serviceworker.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/sharedworker.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/style.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/track.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/unload.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/window-open.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/worker.https.sub.html.ini
testing/web-platform/meta/fetch/metadata/xslt.https.sub.html.ini
new file mode 100644
--- /dev/null
+++ b/dom/security/SecFetch.cpp
@@ -0,0 +1,317 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "SecFetch.h"
+#include "nsIHttpChannel.h"
+#include "nsIRedirectHistoryEntry.h"
+#include "nsIReferrerInfo.h"
+#include "mozIThirdPartyUtil.h"
+#include "nsMixedContentBlocker.h"
+#include "nsNetUtil.h"
+
+// Helper function which maps an internal content policy type
+// to the corresponding destination for the context of SecFetch.
+nsCString MapInternalContentPolicyTypeToDest(nsContentPolicyType aType) {
+  switch (aType) {
+    case nsIContentPolicy::TYPE_OTHER:
+      return NS_LITERAL_CSTRING("empty");
+    case nsIContentPolicy::TYPE_INTERNAL_SCRIPT:
+    case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD:
+    case nsIContentPolicy::TYPE_INTERNAL_MODULE:
+    case nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD:
+    case nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS:
+    case nsIContentPolicy::TYPE_SCRIPT:
+      return NS_LITERAL_CSTRING("script");
+    case nsIContentPolicy::TYPE_INTERNAL_WORKER:
+      return NS_LITERAL_CSTRING("worker");
+    case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER:
+      return NS_LITERAL_CSTRING("sharedworker");
+    case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER:
+      return NS_LITERAL_CSTRING("serviceworker");
+    case nsIContentPolicy::TYPE_IMAGESET:
+    case nsIContentPolicy::TYPE_INTERNAL_IMAGE:
+    case nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD:
+    case nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON:
+    case nsIContentPolicy::TYPE_IMAGE:
+      return NS_LITERAL_CSTRING("image");
+    case nsIContentPolicy::TYPE_STYLESHEET:
+    case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET:
+    case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD:
+      return NS_LITERAL_CSTRING("style");
+    case nsIContentPolicy::TYPE_OBJECT:
+    case nsIContentPolicy::TYPE_INTERNAL_OBJECT:
+      return NS_LITERAL_CSTRING("object");
+    case nsIContentPolicy::TYPE_INTERNAL_EMBED:
+      return NS_LITERAL_CSTRING("embed");
+    case nsIContentPolicy::TYPE_DOCUMENT:
+      return NS_LITERAL_CSTRING("document");
+    case nsIContentPolicy::TYPE_SUBDOCUMENT:
+    case nsIContentPolicy::TYPE_INTERNAL_IFRAME:
+      return NS_LITERAL_CSTRING("iframe");
+    case nsIContentPolicy::TYPE_INTERNAL_FRAME:
+      return NS_LITERAL_CSTRING("frame");
+    case nsIContentPolicy::TYPE_REFRESH:
+      return NS_LITERAL_CSTRING("empty");
+    case nsIContentPolicy::TYPE_XBL:
+      return NS_LITERAL_CSTRING("empty");
+    case nsIContentPolicy::TYPE_PING:
+      return NS_LITERAL_CSTRING("empty");
+    case nsIContentPolicy::TYPE_XMLHTTPREQUEST:
+    case nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST:
+      return NS_LITERAL_CSTRING("empty");
+    case nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE:
+      return NS_LITERAL_CSTRING("empty");
+    case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST:
+      return NS_LITERAL_CSTRING("empty");
+    case nsIContentPolicy::TYPE_DTD:
+    case nsIContentPolicy::TYPE_INTERNAL_DTD:
+    case nsIContentPolicy::TYPE_INTERNAL_FORCE_ALLOWED_DTD:
+      return NS_LITERAL_CSTRING("empty");
+    case nsIContentPolicy::TYPE_FONT:
+      return NS_LITERAL_CSTRING("font");
+    case nsIContentPolicy::TYPE_MEDIA:
+      return NS_LITERAL_CSTRING("empty");
+    case nsIContentPolicy::TYPE_INTERNAL_AUDIO:
+      return NS_LITERAL_CSTRING("audio");
+    case nsIContentPolicy::TYPE_INTERNAL_VIDEO:
+      return NS_LITERAL_CSTRING("video");
+    case nsIContentPolicy::TYPE_INTERNAL_TRACK:
+      return NS_LITERAL_CSTRING("track");
+    case nsIContentPolicy::TYPE_WEBSOCKET:
+      return NS_LITERAL_CSTRING("websocket");
+    case nsIContentPolicy::TYPE_CSP_REPORT:
+      return NS_LITERAL_CSTRING("report");
+    case nsIContentPolicy::TYPE_XSLT:
+      return NS_LITERAL_CSTRING("xslt");
+    case nsIContentPolicy::TYPE_BEACON:
+      return NS_LITERAL_CSTRING("empty");
+    case nsIContentPolicy::TYPE_FETCH:
+      return NS_LITERAL_CSTRING("empty");
+    case nsIContentPolicy::TYPE_WEB_MANIFEST:
+      return NS_LITERAL_CSTRING("manifest");
+    case nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD:
+      return NS_LITERAL_CSTRING("empty");
+    case nsIContentPolicy::TYPE_SPECULATIVE:
+      return NS_LITERAL_CSTRING("empty");
+    default:
+      MOZ_CRASH("Unhandled nsContentPolicyType value");
+      break;
+  }
+
+  return NS_LITERAL_CSTRING("empty");
+}
+
+// Helper function to determine whether a request (including involved
+// redirects) is same-origin in the context of SecFetch.
+bool IsSameOrigin(nsIHttpChannel* aHTTPChannel) {
+  nsCOMPtr<nsIURI> channelURI;
+  NS_GetFinalChannelURI(aHTTPChannel, getter_AddRefs(channelURI));
+
+  nsCOMPtr<nsILoadInfo> loadInfo = aHTTPChannel->LoadInfo();
+  bool isPrivateWin = loadInfo->GetOriginAttributes().mPrivateBrowsingId > 0;
+  bool isSameOrigin = false;
+  nsresult rv = loadInfo->TriggeringPrincipal()->IsSameOrigin(
+      channelURI, isPrivateWin, &isSameOrigin);
+  Unused << NS_WARN_IF(NS_FAILED(rv));
+
+  // if the initial request is not same-origin, we can return here
+  // because we already know it's not a same-origin request
+  if (!isSameOrigin) {
+    return false;
+  }
+
+  // let's further check all the hoops in the redirectChain to
+  // ensure all involved redirects are same-origin
+  nsCOMPtr<nsIPrincipal> redirectPrincipal;
+  for (nsIRedirectHistoryEntry* entry : loadInfo->RedirectChain()) {
+    entry->GetPrincipal(getter_AddRefs(redirectPrincipal));
+    if (redirectPrincipal) {
+      rv = redirectPrincipal->IsSameOrigin(channelURI, isPrivateWin,
+                                           &isSameOrigin);
+      Unused << NS_WARN_IF(NS_FAILED(rv));
+      if (!isSameOrigin) {
+        return false;
+      }
+    }
+  }
+
+  // must be a same-origin request
+  return true;
+}
+
+// Helper function to determine whether a request (including involved
+// redirects) is same-site in the context of SecFetch.
+bool IsSameSite(nsIChannel* aHTTPChannel) {
+  nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
+      do_GetService(THIRDPARTYUTIL_CONTRACTID);
+  if (!thirdPartyUtil) {
+    return false;
+  }
+
+  nsAutoCString hostDomain;
+  nsCOMPtr<nsILoadInfo> loadInfo = aHTTPChannel->LoadInfo();
+  nsresult rv = loadInfo->TriggeringPrincipal()->GetBaseDomain(hostDomain);
+  Unused << NS_WARN_IF(NS_FAILED(rv));
+
+  nsAutoCString channelDomain;
+  nsCOMPtr<nsIURI> channelURI;
+  NS_GetFinalChannelURI(aHTTPChannel, getter_AddRefs(channelURI));
+  rv = thirdPartyUtil->GetBaseDomain(channelURI, channelDomain);
+  Unused << NS_WARN_IF(NS_FAILED(rv));
+
+  // if the initial request is not same-site, or not https, we can
+  // return here because we already know it's not a same-site request
+  if (!hostDomain.Equals(channelDomain) ||
+      !loadInfo->TriggeringPrincipal()->SchemeIs("https")) {
+    return false;
+  }
+
+  // let's further check all the hoops in the redirectChain to
+  // ensure all involved redirects are same-site and https
+  nsCOMPtr<nsIPrincipal> redirectPrincipal;
+  for (nsIRedirectHistoryEntry* entry : loadInfo->RedirectChain()) {
+    entry->GetPrincipal(getter_AddRefs(redirectPrincipal));
+    if (redirectPrincipal) {
+      redirectPrincipal->GetBaseDomain(hostDomain);
+      if (!hostDomain.Equals(channelDomain) ||
+          !redirectPrincipal->SchemeIs("https")) {
+        return false;
+      }
+    }
+  }
+
+  // must be a same-site request
+  return true;
+}
+
+// Helper function to determine whether a request was triggered
+// by the end user in the context of SecFetch.
+bool IsUserTriggeredForSecFetchSite(nsIHttpChannel* aHTTPChannel) {
+  nsCOMPtr<nsILoadInfo> loadInfo = aHTTPChannel->LoadInfo();
+  nsContentPolicyType contentType = loadInfo->InternalContentPolicyType();
+
+  // only requests wich result in type "document" are subject to
+  // user initiated actions in the context of SecFetch.
+  if (contentType != nsIContentPolicy::TYPE_DOCUMENT &&
+      contentType != nsIContentPolicy::TYPE_SUBDOCUMENT &&
+      contentType != nsIContentPolicy::TYPE_INTERNAL_IFRAME) {
+    return false;
+  }
+
+  // All web requests have a valid "original" referrer set in the
+  // ReferrerInfo which we can use to determine whether a request
+  // was triggered by a user or not.
+  nsCOMPtr<nsIReferrerInfo> referrerInfo = aHTTPChannel->GetReferrerInfo();
+  if (referrerInfo) {
+    nsCOMPtr<nsIURI> originalReferrer;
+    referrerInfo->GetOriginalReferrer(getter_AddRefs(originalReferrer));
+    if (originalReferrer) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+void SecFetch::AddSecFetchDest(nsIHttpChannel* aHTTPChannel) {
+  nsCOMPtr<nsILoadInfo> loadInfo = aHTTPChannel->LoadInfo();
+  nsContentPolicyType contentType = loadInfo->InternalContentPolicyType();
+  nsCString dest = MapInternalContentPolicyTypeToDest(contentType);
+
+  nsresult rv = aHTTPChannel->SetRequestHeader(
+      NS_LITERAL_CSTRING("Sec-Fetch-Dest"), dest, false);
+  Unused << NS_WARN_IF(NS_FAILED(rv));
+}
+
+void SecFetch::AddSecFetchMode(nsIHttpChannel* aHTTPChannel) {
+  nsAutoCString mode("no-cors");
+
+  nsCOMPtr<nsILoadInfo> loadInfo = aHTTPChannel->LoadInfo();
+  uint32_t securityMode = loadInfo->GetSecurityMode();
+  nsContentPolicyType externalType = loadInfo->GetExternalContentPolicyType();
+
+  if (securityMode == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS ||
+      securityMode == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED) {
+    mode = NS_LITERAL_CSTRING("same-origin");
+  } else if (securityMode == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
+    mode = NS_LITERAL_CSTRING("cors");
+  } else {
+    // If it's not one of the security modes above, then we ensure it's
+    // at least one of the others defined in nsILoadInfo
+    MOZ_ASSERT(
+        securityMode == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS ||
+            securityMode == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
+        "unhandled security mode");
+  }
+
+  if (externalType == nsIContentPolicy::TYPE_DOCUMENT ||
+      externalType == nsIContentPolicy::TYPE_SUBDOCUMENT ||
+      externalType == nsIContentPolicy::TYPE_REFRESH ||
+      externalType == nsIContentPolicy::TYPE_OBJECT) {
+    mode = NS_LITERAL_CSTRING("navigate");
+  } else if (externalType == nsIContentPolicy::TYPE_WEBSOCKET) {
+    mode = NS_LITERAL_CSTRING("websocket");
+  }
+
+  nsresult rv = aHTTPChannel->SetRequestHeader(
+      NS_LITERAL_CSTRING("Sec-Fetch-Mode"), mode, false);
+  Unused << NS_WARN_IF(NS_FAILED(rv));
+}
+
+void SecFetch::AddSecFetchSite(nsIHttpChannel* aHTTPChannel) {
+  nsAutoCString site("same-origin");
+
+  bool isSameOrigin = IsSameOrigin(aHTTPChannel);
+  if (!isSameOrigin) {
+    bool isSameSite = IsSameSite(aHTTPChannel);
+    if (isSameSite) {
+      site = NS_LITERAL_CSTRING("same-site");
+    } else {
+      site = NS_LITERAL_CSTRING("cross-site");
+    }
+  }
+
+  if (IsUserTriggeredForSecFetchSite(aHTTPChannel)) {
+    site = NS_LITERAL_CSTRING("none");
+  }
+
+  nsresult rv = aHTTPChannel->SetRequestHeader(
+      NS_LITERAL_CSTRING("Sec-Fetch-Site"), site, false);
+  Unused << NS_WARN_IF(NS_FAILED(rv));
+}
+
+void SecFetch::AddSecFetchUser(nsIHttpChannel* aHTTPChannel) {
+  // TODO: Bug 1621987: Implement Sec-Fetch-User
+
+  // nsAutoCString user("?1");
+  // nsresult rv = aHTTPChannel->SetRequestHeader(
+  //     NS_LITERAL_CSTRING("Sec-Fetch-User"), user, false);
+  // Unused << NS_WARN_IF(NS_FAILED(rv));
+}
+
+void SecFetch::AddSecFetchHeader(nsIHttpChannel* aHTTPChannel) {
+  // if sec-fetch-* is prefed off, then there is nothing to do
+  if (!StaticPrefs::dom_security_secFetch_enabled()) {
+    return;
+  }
+
+  nsCOMPtr<nsIURI> uri;
+  nsresult rv = aHTTPChannel->GetURI(getter_AddRefs(uri));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return;
+  }
+
+  // if we are not dealing with a potentially trustworthy URL, then
+  // there is nothing to do here
+  if (!nsMixedContentBlocker::IsPotentiallyTrustworthyOrigin(uri)) {
+    return;
+  }
+
+  AddSecFetchDest(aHTTPChannel);
+  AddSecFetchMode(aHTTPChannel);
+  AddSecFetchSite(aHTTPChannel);
+  AddSecFetchUser(aHTTPChannel);
+}
new file mode 100644
--- /dev/null
+++ b/dom/security/SecFetch.h
@@ -0,0 +1,29 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_SecFetch_h
+#define mozilla_dom_SecFetch_h
+
+class nsIHttpChannel;
+
+namespace mozilla {
+namespace dom {
+
+class SecFetch final {
+ public:
+  static void AddSecFetchHeader(nsIHttpChannel* aHTTPChannel);
+
+ private:
+  static void AddSecFetchDest(nsIHttpChannel* aHTTPChannel);
+  static void AddSecFetchMode(nsIHttpChannel* aHTTPChannel);
+  static void AddSecFetchSite(nsIHttpChannel* aHTTPChannel);
+  static void AddSecFetchUser(nsIHttpChannel* aHTTPChannel);
+};
+
+}  // namespace dom
+}  // namespace mozilla
+
+#endif  // mozilla_dom_SecFetch_h
--- a/dom/security/moz.build
+++ b/dom/security/moz.build
@@ -19,16 +19,17 @@ EXPORTS.mozilla.dom += [
     'nsContentSecurityManager.h',
     'nsContentSecurityUtils.h',
     'nsCSPContext.h',
     'nsCSPService.h',
     'nsCSPUtils.h',
     'nsMixedContentBlocker.h',
     'PolicyTokenizer.h',
     'ReferrerInfo.h',
+    'SecFetch.h',
     'SRICheck.h',
     'SRILogHelper.h',
     'SRIMetadata.h',
 ]
 
 EXPORTS += [
     'nsContentSecurityManager.h',
     'nsContentSecurityUtils.h',
@@ -45,16 +46,17 @@ UNIFIED_SOURCES += [
     'nsContentSecurityUtils.cpp',
     'nsCSPContext.cpp',
     'nsCSPParser.cpp',
     'nsCSPService.cpp',
     'nsCSPUtils.cpp',
     'nsMixedContentBlocker.cpp',
     'PolicyTokenizer.cpp',
     'ReferrerInfo.cpp',
+    'SecFetch.cpp',
     'SRICheck.cpp',
     'SRIMetadata.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
--- a/modules/libpref/init/StaticPrefList.yaml
+++ b/modules/libpref/init/StaticPrefList.yaml
@@ -2350,16 +2350,23 @@
 
 # This pref enables FeaturePolicy logic and the parsing of 'allow' attribute in
 # HTMLIFrameElement objects.
 - name: dom.security.featurePolicy.enabled
   type: bool
   value: true
   mirror: always
 
+# This pref enables Sec-Fetch-* logic and causes corresponding
+# request headers to be set.
+- name: dom.security.secFetch.enabled
+  type: RelaxedAtomicBool
+  value: @IS_NIGHTLY_BUILD@
+  mirror: always
+
 # This pref enables the featurePolicy header support.
 - name: dom.security.featurePolicy.header.enabled
   type: bool
   value: @IS_NIGHTLY_BUILD@
   mirror: always
 
 - name: dom.security.respect_document_nosniff
   type: RelaxedAtomicBool
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -123,16 +123,17 @@
 #include "mozilla/net/CookieJarSettings.h"
 #include "mozilla/net/NeckoChannelParams.h"
 #include "mozilla/net/UrlClassifierFeatureFactory.h"
 #include "HttpTrafficAnalyzer.h"
 #include "mozilla/dom/CanonicalBrowsingContext.h"
 #include "mozilla/dom/WindowGlobalParent.h"
 #include "mozilla/net/SocketProcessParent.h"
 #include "js/Conversions.h"
+#include "mozilla/dom/SecFetch.h"
 
 #ifdef MOZ_TASK_TRACER
 #  include "GeckoTaskTracer.h"
 #endif
 
 #ifdef MOZ_GECKO_PROFILER
 #  include "ProfilerMarkerPayload.h"
 #endif
@@ -579,16 +580,18 @@ nsresult nsHttpChannel::OnBeforeConnect(
 
   if (type == nsIContentPolicy::TYPE_DOCUMENT ||
       type == nsIContentPolicy::TYPE_SUBDOCUMENT) {
     rv = SetRequestHeader(NS_LITERAL_CSTRING("Upgrade-Insecure-Requests"),
                           NS_LITERAL_CSTRING("1"), false);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
+  SecFetch::AddSecFetchHeader(this);
+
   nsCOMPtr<nsIPrincipal> resultPrincipal;
   if (!mURI->SchemeIs("https")) {
     nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
         this, getter_AddRefs(resultPrincipal));
   }
   OriginAttributes originAttributes;
   if (!NS_GetOriginAttributes(this, originAttributes)) {
     return NS_ERROR_FAILURE;
--- a/services/common/tests/unit/test_restrequest.js
+++ b/services/common/tests/unit/test_restrequest.js
@@ -570,16 +570,20 @@ add_task(async function test_get_no_head
     "accept-language",
     "accept-encoding",
     "accept-charset",
     "keep-alive",
     "connection",
     "pragma",
     "cache-control",
     "content-length",
+    "sec-fetch-dest",
+    "sec-fetch-mode",
+    "sec-fetch-site",
+    "sec-fetch-user",
   ];
   let request = new RESTRequest(server.baseURI + "/resource");
   await request.get();
 
   Assert.equal(request.response.status, 200);
   Assert.equal(request.response.body, "");
 
   let server_headers = handler.request.headers;
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/fetch/metadata/__dir__.ini
@@ -0,0 +1,1 @@
+prefs: [dom.security.secFetch.enabled:true]
--- a/testing/web-platform/meta/fetch/metadata/embed.https.sub.html.ini
+++ b/testing/web-platform/meta/fetch/metadata/embed.https.sub.html.ini
@@ -1,83 +1,95 @@
 [embed.https.sub.html]
   expected:
     if os == "mac": TIMEOUT
     if os == "linux": TIMEOUT
   [Navigate to same-site embed: sec-fetch-mode]
-    expected: FAIL
+    expected:
+      if os == "mac": FAIL
+      if os == "linux": FAIL
 
   [Navigate to same-site embed: sec-fetch-dest]
     expected: FAIL
 
   [same-site embed: sec-fetch-dest]
-    expected: FAIL
-
-  [same-origin embed: sec-fetch-site]
-    expected: FAIL
+    expected:
+      if os == "mac": FAIL
+      if os == "linux": FAIL
 
   [same-site embed: sec-fetch-mode]
-    expected: FAIL
+    expected:
+      if os == "mac": FAIL
+      if os == "linux": FAIL
 
   [cross-site embed: sec-fetch-site]
-    expected: FAIL
+    expected:
+      if os == "mac": FAIL
+      if os == "linux": FAIL
 
   [Wrapper: Navigate to cross-site embed]
     expected:
       if os == "mac": NOTRUN
       if os == "linux": NOTRUN
 
   [Navigate to cross-site embed: sec-fetch-mode]
-    expected: FAIL
+    expected:
+      if os == "mac": FAIL
+      if os == "linux": FAIL
 
   [Wrapper: cross-site embed]
     expected:
       if os == "mac": NOTRUN
       if os == "linux": NOTRUN
 
   [Wrapper: Navigate to same-site embed]
     expected:
       if os == "mac": NOTRUN
       if os == "linux": NOTRUN
 
-  [Navigate to same-origin embed: sec-fetch-site]
-    expected: FAIL
-
   [Navigate to same-origin embed: sec-fetch-mode]
-    expected: FAIL
+    expected:
+      if os == "mac": FAIL
+      if os == "linux": FAIL
 
   [Navigate to cross-site embed: sec-fetch-dest]
     expected: FAIL
 
   [Navigate to same-site embed: sec-fetch-site]
-    expected: FAIL
-
-  [same-origin embed: sec-fetch-mode]
-    expected: FAIL
+    expected:
+      if os == "mac": FAIL
+      if os == "linux": FAIL
 
   [Navigate to same-origin embed: sec-fetch-dest]
-    expected: FAIL
+    expected:
+      if os == "win": FAIL
+      if os == "android": FAIL
 
   [Wrapper: same-site embed]
     expected:
       if os == "mac": NOTRUN
       if os == "linux": NOTRUN
 
   [Wrapper: Navigate to same-origin embed]
     expected:
       if os == "mac": TIMEOUT
       if os == "linux": TIMEOUT
 
   [cross-site embed: sec-fetch-dest]
-    expected: FAIL
-
-  [same-origin embed: sec-fetch-dest]
-    expected: FAIL
+    expected:
+      if os == "mac": FAIL
+      if os == "linux": FAIL
 
   [same-site embed: sec-fetch-site]
-    expected: FAIL
+    expected:
+      if os == "mac": FAIL
+      if os == "linux": FAIL
 
   [cross-site embed: sec-fetch-mode]
-    expected: FAIL
+    expected:
+      if os == "mac": FAIL
+      if os == "linux": FAIL
 
   [Navigate to cross-site embed: sec-fetch-site]
-    expected: FAIL
+    expected:
+      if os == "mac": FAIL
+      if os == "linux": FAIL
 
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/fetch-preflight.https.sub.html.ini
+++ /dev/null
@@ -1,7 +0,0 @@
-[fetch-preflight.https.sub.html]
-  [Same-site fetch with preflight]
-    expected: FAIL
-
-  [Cross-site fetch with preflight]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/fetch-via-serviceworker--fallback.https.sub.html.ini
+++ /dev/null
@@ -1,10 +0,0 @@
-[fetch-via-serviceworker--fallback.https.sub.html]
-  [undefined: sec-fetch-mode]
-    expected: FAIL
-
-  [undefined: sec-fetch-site]
-    expected: FAIL
-
-  [undefined: sec-fetch-dest]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/fetch-via-serviceworker--respondWith.https.sub.html.ini
+++ /dev/null
@@ -1,10 +0,0 @@
-[fetch-via-serviceworker--respondWith.https.sub.html]
-  [undefined: sec-fetch-mode]
-    expected: FAIL
-
-  [undefined: sec-fetch-site]
-    expected: FAIL
-
-  [undefined: sec-fetch-dest]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/fetch.https.sub.html.ini
+++ /dev/null
@@ -1,55 +0,0 @@
-[fetch.https.sub.html]
-  [CORS mode: sec-fetch-site]
-    expected: FAIL
-
-  [Same-origin mode: sec-fetch-dest]
-    expected: FAIL
-
-  [Cross-site fetch: sec-fetch-dest]
-    expected: FAIL
-
-  [Cross-site fetch: sec-fetch-site]
-    expected: FAIL
-
-  [Same-origin fetch: sec-fetch-mode]
-    expected: FAIL
-
-  [CORS mode: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-origin mode: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-origin mode: sec-fetch-site]
-    expected: FAIL
-
-  [Same-origin fetch: sec-fetch-site]
-    expected: FAIL
-
-  [Cross-site fetch: sec-fetch-mode]
-    expected: FAIL
-
-  [CORS mode: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-origin fetch: sec-fetch-dest]
-    expected: FAIL
-
-  [no-CORS mode: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-site fetch: sec-fetch-dest]
-    expected: FAIL
-
-  [no-CORS mode: sec-fetch-site]
-    expected: FAIL
-
-  [Same-site fetch: sec-fetch-site]
-    expected: FAIL
-
-  [no-CORS mode: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-site fetch: sec-fetch-mode]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/fetch.sub.html.ini
+++ /dev/null
@@ -1,10 +0,0 @@
-[fetch.sub.html]
-  [http->https fetch (cross-scheme => cross-site): sec-fetch-dest]
-    expected: FAIL
-
-  [http->https fetch (cross-scheme => cross-site): sec-fetch-site]
-    expected: FAIL
-
-  [http->https fetch (cross-scheme => cross-site): sec-fetch-mode]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/font.https.sub.html.ini
+++ /dev/null
@@ -1,28 +0,0 @@
-[font.https.sub.html]
-  [Cross-Site font: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-Site font: sec-fetch-site]
-    expected: FAIL
-
-  [Same-Site font: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-Origin font: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-Origin font: sec-fetch-site]
-    expected: FAIL
-
-  [Cross-Site font: sec-fetch-mode]
-    expected: FAIL
-
-  [Cross-Site font: sec-fetch-site]
-    expected: FAIL
-
-  [Same-Site font: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-Origin font: sec-fetch-dest]
-    expected: FAIL
-
--- a/testing/web-platform/meta/fetch/metadata/form.https.sub.html.ini
+++ b/testing/web-platform/meta/fetch/metadata/form.https.sub.html.ini
@@ -1,64 +1,9 @@
 [form.https.sub.html]
-  [web-platform.test -> www.web-platform.test:8443 iframe: forced: sec-fetch-site]
-    expected: FAIL
-
-  [web-platform.test -> www.not-web-platform.test:8443 iframe: user-activated: sec-fetch-mode]
-    expected: FAIL
-
-  [web-platform.test -> web-platform.test:8443 iframe: forced: sec-fetch-dest]
-    expected: FAIL
-
-  [web-platform.test -> www.not-web-platform.test:8443 iframe: forced: sec-fetch-mode]
-    expected: FAIL
-
-  [web-platform.test -> web-platform.test:8443 iframe: forced: sec-fetch-site]
-    expected: FAIL
-
-  [web-platform.test -> www.not-web-platform.test:8443 iframe: user-activated: sec-fetch-dest]
-    expected: FAIL
-
   [web-platform.test -> web-platform.test:8443 iframe: user-activated: sec-fetch-user]
     expected: FAIL
 
-  [web-platform.test -> www.not-web-platform.test:8443 iframe: user-activated: sec-fetch-site]
-    expected: FAIL
-
-  [web-platform.test -> www.web-platform.test:8443 iframe: user-activated: sec-fetch-mode]
-    expected: FAIL
-
-  [web-platform.test -> web-platform.test:8443 iframe: user-activated: sec-fetch-dest]
-    expected: FAIL
-
-  [web-platform.test -> web-platform.test:8443 iframe: user-activated: sec-fetch-mode]
-    expected: FAIL
-
-  [web-platform.test -> web-platform.test:8443 iframe: forced: sec-fetch-mode]
-    expected: FAIL
-
-  [web-platform.test -> www.not-web-platform.test:8443 iframe: forced: sec-fetch-dest]
-    expected: FAIL
-
-  [web-platform.test -> www.not-web-platform.test:8443 iframe: forced: sec-fetch-site]
-    expected: FAIL
-
-  [web-platform.test -> www.web-platform.test:8443 iframe: forced: sec-fetch-dest]
-    expected: FAIL
-
-  [web-platform.test -> www.web-platform.test:8443 iframe: forced: sec-fetch-mode]
-    expected: FAIL
-
   [web-platform.test -> www.web-platform.test:8443 iframe: user-activated: sec-fetch-user]
     expected: FAIL
 
-  [web-platform.test -> www.web-platform.test:8443 iframe: user-activated: sec-fetch-dest]
-    expected: FAIL
-
   [web-platform.test -> www.not-web-platform.test:8443 iframe: user-activated: sec-fetch-user]
     expected: FAIL
-
-  [web-platform.test -> www.web-platform.test:8443 iframe: user-activated: sec-fetch-site]
-    expected: FAIL
-
-  [web-platform.test -> web-platform.test:8443 iframe: user-activated: sec-fetch-site]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/history.https.sub.html.ini
+++ /dev/null
@@ -1,55 +0,0 @@
-[history.https.sub.html]
-  [back to same-origin-initiated navigation 2: sec-fetch-mode]
-    expected: FAIL
-
-  [back to same-site-initiated navigation 1: sec-fetch-dest]
-    expected: FAIL
-
-  [back to same-origin-initiated navigation 2: sec-fetch-dest]
-    expected: FAIL
-
-  [back to same-origin-initiated navigation 1: sec-fetch-mode]
-    expected: FAIL
-
-  [back to cross-site-initiated navigation 2: sec-fetch-site]
-    expected: FAIL
-
-  [back to same-site-initiated navigation 1: sec-fetch-site]
-    expected: FAIL
-
-  [back to same-site-initiated navigation 2: sec-fetch-mode]
-    expected: FAIL
-
-  [back to cross-site-initiated navigation 1: sec-fetch-mode]
-    expected: FAIL
-
-  [back to cross-site-initiated navigation 1: sec-fetch-site]
-    expected: FAIL
-
-  [back to cross-site-initiated navigation 1: sec-fetch-dest]
-    expected: FAIL
-
-  [back to same-site-initiated navigation 2: sec-fetch-dest]
-    expected: FAIL
-
-  [back to cross-site-initiated navigation 2: sec-fetch-dest]
-    expected: FAIL
-
-  [back to cross-site-initiated navigation 2: sec-fetch-mode]
-    expected: FAIL
-
-  [back to same-origin-initiated navigation 1: sec-fetch-dest]
-    expected: FAIL
-
-  [back to same-site-initiated navigation 1: sec-fetch-mode]
-    expected: FAIL
-
-  [back to same-site-initiated navigation 2: sec-fetch-site]
-    expected: FAIL
-
-  [back to same-origin-initiated navigation 2: sec-fetch-site]
-    expected: FAIL
-
-  [back to same-origin-initiated navigation 1: sec-fetch-site]
-    expected: FAIL
-
--- a/testing/web-platform/meta/fetch/metadata/iframe.https.sub.html.ini
+++ b/testing/web-platform/meta/fetch/metadata/iframe.https.sub.html.ini
@@ -1,64 +1,9 @@
 [iframe.https.sub.html]
-  [web-platform.test -> www.web-platform.test:8443 iframe: forced: sec-fetch-site]
-    expected: FAIL
-
-  [web-platform.test -> www.not-web-platform.test:8443 iframe: user-activated: sec-fetch-mode]
-    expected: FAIL
-
-  [web-platform.test -> web-platform.test:8443 iframe: forced: sec-fetch-dest]
-    expected: FAIL
-
-  [web-platform.test -> www.not-web-platform.test:8443 iframe: forced: sec-fetch-mode]
-    expected: FAIL
-
-  [web-platform.test -> web-platform.test:8443 iframe: forced: sec-fetch-site]
-    expected: FAIL
-
-  [web-platform.test -> www.not-web-platform.test:8443 iframe: user-activated: sec-fetch-dest]
-    expected: FAIL
-
   [web-platform.test -> web-platform.test:8443 iframe: user-activated: sec-fetch-user]
     expected: FAIL
 
-  [web-platform.test -> www.not-web-platform.test:8443 iframe: user-activated: sec-fetch-site]
-    expected: FAIL
-
-  [web-platform.test -> www.web-platform.test:8443 iframe: user-activated: sec-fetch-mode]
-    expected: FAIL
-
-  [web-platform.test -> web-platform.test:8443 iframe: user-activated: sec-fetch-dest]
-    expected: FAIL
-
-  [web-platform.test -> web-platform.test:8443 iframe: user-activated: sec-fetch-mode]
-    expected: FAIL
-
-  [web-platform.test -> web-platform.test:8443 iframe: forced: sec-fetch-mode]
-    expected: FAIL
-
-  [web-platform.test -> www.not-web-platform.test:8443 iframe: forced: sec-fetch-dest]
-    expected: FAIL
-
-  [web-platform.test -> www.not-web-platform.test:8443 iframe: forced: sec-fetch-site]
-    expected: FAIL
-
-  [web-platform.test -> www.web-platform.test:8443 iframe: forced: sec-fetch-dest]
-    expected: FAIL
-
-  [web-platform.test -> www.web-platform.test:8443 iframe: forced: sec-fetch-mode]
-    expected: FAIL
-
   [web-platform.test -> www.web-platform.test:8443 iframe: user-activated: sec-fetch-user]
     expected: FAIL
 
-  [web-platform.test -> www.web-platform.test:8443 iframe: user-activated: sec-fetch-dest]
-    expected: FAIL
-
   [web-platform.test -> www.not-web-platform.test:8443 iframe: user-activated: sec-fetch-user]
     expected: FAIL
-
-  [web-platform.test -> www.web-platform.test:8443 iframe: user-activated: sec-fetch-site]
-    expected: FAIL
-
-  [web-platform.test -> web-platform.test:8443 iframe: user-activated: sec-fetch-site]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/iframe.sub.html.ini
+++ /dev/null
@@ -1,10 +0,0 @@
-[iframe.sub.html]
-  [Secure, cross-site (cross-scheme, same-host) iframe: sec-fetch-dest]
-    expected: FAIL
-
-  [Secure, cross-site (cross-scheme, same-host) iframe: sec-fetch-site]
-    expected: FAIL
-
-  [Secure, cross-site (cross-scheme, same-host) iframe: sec-fetch-mode]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/img.https.sub.html.ini
+++ /dev/null
@@ -1,28 +0,0 @@
-[img.https.sub.html]
-  [Cross-site image: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-origin image: sec-fetch-mode]
-    expected: FAIL
-
-  [Cross-site image: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-site image: sec-fetch-mode]
-    expected: FAIL
-
-  [Cross-site image: sec-fetch-site]
-    expected: FAIL
-
-  [Same-site image: sec-fetch-site]
-    expected: FAIL
-
-  [Same-origin image: sec-fetch-site]
-    expected: FAIL
-
-  [Same-origin image: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-site image: sec-fetch-dest]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/navigation.https.sub.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[navigation.https.sub.html]
-  expected: ERROR
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/object.https.sub.html.ini
+++ /dev/null
@@ -1,28 +0,0 @@
-[object.https.sub.html]
-  [Same-Site object: sec-fetch-mode]
-    expected: FAIL
-
-  [Cross-Site object: sec-fetch-site]
-    expected: FAIL
-
-  [Same-Origin object: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-Origin object: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-Site object: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-Origin object: sec-fetch-site]
-    expected: FAIL
-
-  [Cross-Site object: sec-fetch-dest]
-    expected: FAIL
-
-  [Cross-Site object: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-Site object: sec-fetch-site]
-    expected: FAIL
-
--- a/testing/web-platform/meta/fetch/metadata/redirect/__dir__.ini
+++ b/testing/web-platform/meta/fetch/metadata/redirect/__dir__.ini
@@ -1,2 +1,3 @@
+prefs: [dom.security.secFetch.enabled:true]
 lsan-allowed: [Alloc, Create, Malloc, Realloc, mozilla::BasePrincipal::CreateContentPrincipal, mozilla::ContentPrincipal::Init, mozilla::SchedulerGroup::CreateEventTargetFor, mozilla::WeakPtr, mozilla::dom::HTMLLinkElement::TryDNSPrefetchOrPreconnectOrPrefetchOrPreloadOrPrerender, mozilla::net::CookieSettings::Create, mozilla::net::nsStandardURL::TemplatedMutator, nsNodeSupportsWeakRefTearoff::GetWeakReference, nsPermission::Create, nsPrefetchService::Preload]
 leak-threshold: [tab:51200]
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/redirect/cross-site-redirect.https.sub.html.ini
+++ /dev/null
@@ -1,28 +0,0 @@
-[cross-site-redirect.https.sub.html]
-  [Cross-Site -> Cross-Site redirect: sec-fetch-site]
-    expected: FAIL
-
-  [Cross-Site -> Same-Origin redirect: sec-fetch-mode]
-    expected: FAIL
-
-  [Cross-Site -> Cross-Site redirect: sec-fetch-mode]
-    expected: FAIL
-
-  [Cross-Site -> Same-Site redirect: sec-fetch-mode]
-    expected: FAIL
-
-  [Cross-Site -> Same-Site redirect: sec-fetch-site]
-    expected: FAIL
-
-  [Cross-Site -> Same-Site redirect: sec-fetch-dest]
-    expected: FAIL
-
-  [Cross-Site -> Cross-Site redirect: sec-fetch-dest]
-    expected: FAIL
-
-  [Cross-Site -> Same-Origin redirect: sec-fetch-dest]
-    expected: FAIL
-
-  [Cross-Site -> Same-Origin redirect: sec-fetch-site]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/redirect/multiple-redirect-cross-site.https.sub.html.ini
+++ /dev/null
@@ -1,10 +0,0 @@
-[multiple-redirect-cross-site.https.sub.html]
-  [Same-Origin -> Cross-Site -> Same-Origin redirect: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-Origin -> Cross-Site -> Same-Origin redirect: sec-fetch-site]
-    expected: FAIL
-
-  [Same-Origin -> Cross-Site -> Same-Origin redirect: sec-fetch-dest]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/redirect/multiple-redirect-https-downgrade-upgrade.sub.html.ini
+++ /dev/null
@@ -1,91 +0,0 @@
-[multiple-redirect-https-downgrade-upgrade.sub.html]
-  [Https downgrade-upgrade script => No headers: sec-fetch-dest]
-    expected: FAIL
-
-  [Https downgrade-upgrade iframe: sec-fetch-dest]
-    expected: FAIL
-
-  [Https downgrade-upgrade script => No headers: sec-fetch-site]
-    expected: FAIL
-
-  [Https downgrade-upgrade fetch() api: sec-fetch-mode]
-    expected: FAIL
-
-  [Https downgrade-upgrade stylesheet: sec-fetch-site]
-    expected: FAIL
-
-  [Https downgrade-upgrade stylesheet: sec-fetch-dest]
-    expected: FAIL
-
-  [Https downgrade-upgrade fetch() api: sec-fetch-dest]
-    expected: FAIL
-
-  [Https downgrade-upgrade font => No headers: sec-fetch-site]
-    expected: FAIL
-
-  [Https downgrade-upgrade track: sec-fetch-mode]
-    expected: FAIL
-
-  [Https downgrade-upgrade track: sec-fetch-dest]
-    expected: FAIL
-
-  [Https downgrade-upgrade object: sec-fetch-dest]
-    expected: FAIL
-
-  [Https downgrade-upgrade image => No headers: sec-fetch-mode]
-    expected: FAIL
-
-  [Https downgrade-upgrade embed: sec-fetch-dest]
-    expected: FAIL
-
-  [Https downgrade-upgrade image => No headers: sec-fetch-site]
-    expected: FAIL
-
-  [Https downgrade-upgrade embed: sec-fetch-site]
-    expected: FAIL
-
-  [Https downgrade-upgrade object: sec-fetch-mode]
-    expected: FAIL
-
-  [Https downgrade-upgrade script => No headers: sec-fetch-mode]
-    expected: FAIL
-
-  [Https downgrade-upgrade top level navigation: sec-fetch-site]
-    expected: FAIL
-
-  [Https downgrade-upgrade font => No headers: sec-fetch-mode]
-    expected: FAIL
-
-  [Https downgrade-upgrade top level navigation: sec-fetch-mode]
-    expected: FAIL
-
-  [Https downgrade-upgrade iframe: sec-fetch-site]
-    expected: FAIL
-
-  [Https downgrade-upgrade embed: sec-fetch-mode]
-    expected: FAIL
-
-  [Https downgrade-upgrade font => No headers: sec-fetch-dest]
-    expected: FAIL
-
-  [Https downgrade-upgrade fetch() api: sec-fetch-site]
-    expected: FAIL
-
-  [Https downgrade-upgrade object: sec-fetch-site]
-    expected: FAIL
-
-  [Https downgrade-upgrade track: sec-fetch-site]
-    expected: FAIL
-
-  [Https downgrade-upgrade top level navigation: sec-fetch-dest]
-    expected: FAIL
-
-  [Https downgrade-upgrade image => No headers: sec-fetch-dest]
-    expected: FAIL
-
-  [Https downgrade-upgrade stylesheet: sec-fetch-mode]
-    expected: FAIL
-
-  [Https downgrade-upgrade iframe: sec-fetch-mode]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/redirect/multiple-redirect-same-site.https.sub.html.ini
+++ /dev/null
@@ -1,10 +0,0 @@
-[multiple-redirect-same-site.https.sub.html]
-  [undefined: sec-fetch-mode]
-    expected: FAIL
-
-  [undefined: sec-fetch-site]
-    expected: FAIL
-
-  [undefined: sec-fetch-dest]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/redirect/redirect-http-upgrade.sub.html.ini
+++ /dev/null
@@ -1,91 +0,0 @@
-[redirect-http-upgrade.sub.html]
-  [Http upgrade iframe: sec-fetch-dest]
-    expected: FAIL
-
-  [Http upgrade embed: sec-fetch-dest]
-    expected: FAIL
-
-  [Http upgrade top level navigation: sec-fetch-dest]
-    expected: FAIL
-
-  [Http upgrade fetch() api: sec-fetch-site]
-    expected: FAIL
-
-  [Http upgrade track: sec-fetch-site]
-    expected: FAIL
-
-  [Http upgrade fetch() api: sec-fetch-dest]
-    expected: FAIL
-
-  [Http upgrade script => No headers: sec-fetch-dest]
-    expected: FAIL
-
-  [Http upgrade top level navigation: sec-fetch-site]
-    expected: FAIL
-
-  [Http upgrade stylesheet: sec-fetch-mode]
-    expected: FAIL
-
-  [Http upgrade font => No headers: sec-fetch-dest]
-    expected: FAIL
-
-  [Http upgrade top level navigation: sec-fetch-mode]
-    expected: FAIL
-
-  [Http upgrade image => No headers: sec-fetch-mode]
-    expected: FAIL
-
-  [Http upgrade iframe: sec-fetch-site]
-    expected: FAIL
-
-  [Http upgrade font => No headers: sec-fetch-mode]
-    expected: FAIL
-
-  [Http upgrade image => No headers: sec-fetch-site]
-    expected: FAIL
-
-  [Http upgrade image => No headers: sec-fetch-dest]
-    expected: FAIL
-
-  [Http upgrade embed: sec-fetch-site]
-    expected: FAIL
-
-  [Http upgrade object: sec-fetch-site]
-    expected: FAIL
-
-  [Http upgrade stylesheet: sec-fetch-dest]
-    expected: FAIL
-
-  [Http upgrade script => No headers: sec-fetch-mode]
-    expected: FAIL
-
-  [Http upgrade track: sec-fetch-dest]
-    expected: FAIL
-
-  [Http upgrade script => No headers: sec-fetch-site]
-    expected: FAIL
-
-  [Http upgrade object: sec-fetch-mode]
-    expected: FAIL
-
-  [Http upgrade track: sec-fetch-mode]
-    expected: FAIL
-
-  [Http upgrade object: sec-fetch-dest]
-    expected: FAIL
-
-  [Http upgrade embed: sec-fetch-mode]
-    expected: FAIL
-
-  [Http upgrade stylesheet: sec-fetch-site]
-    expected: FAIL
-
-  [Http upgrade font => No headers: sec-fetch-site]
-    expected: FAIL
-
-  [Http upgrade iframe: sec-fetch-mode]
-    expected: FAIL
-
-  [Http upgrade fetch() api: sec-fetch-mode]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/redirect/same-origin-redirect.https.sub.html.ini
+++ /dev/null
@@ -1,28 +0,0 @@
-[same-origin-redirect.https.sub.html]
-  [Same-Origin -> Cross-Site redirect: sec-fetch-site]
-    expected: FAIL
-
-  [Same-Origin -> Same-Site redirect: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-Origin -> Cross-Site redirect: sec-fetch-dest]
-    expected: FAIL
-
-  [undefined: sec-fetch-mode]
-    expected: FAIL
-
-  [undefined: sec-fetch-site]
-    expected: FAIL
-
-  [Same-Origin -> Cross-Site redirect: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-Origin -> Same-Site redirect: sec-fetch-site]
-    expected: FAIL
-
-  [Same-Origin -> Same-Site redirect: sec-fetch-dest]
-    expected: FAIL
-
-  [undefined: sec-fetch-dest]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/redirect/same-site-redirect.https.sub.html.ini
+++ /dev/null
@@ -1,28 +0,0 @@
-[same-site-redirect.https.sub.html]
-  [Same-Site -> Same-Site redirect: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-Site -> Same-Origin redirect: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-Site -> Same-Site redirect: sec-fetch-site]
-    expected: FAIL
-
-  [Same-Site -> Cross-Site redirect: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-Site -> Same-Origin redirect: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-Site -> Cross-Site redirect: sec-fetch-site]
-    expected: FAIL
-
-  [Same-Site -> Same-Origin redirect: sec-fetch-site]
-    expected: FAIL
-
-  [Same-Site -> Same-Site redirect: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-Site -> Cross-Site redirect: sec-fetch-mode]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/report.https.sub.html.ini
+++ /dev/null
@@ -1,28 +0,0 @@
-[report.https.sub.html]
-  [same-origin report: sec-fetch-site]
-    expected: FAIL
-
-  [same-origin report: sec-fetch-mode]
-    expected: FAIL
-
-  [same-site report: sec-fetch-site]
-    expected: FAIL
-
-  [cross-site report: sec-fetch-site]
-    expected: FAIL
-
-  [same-site report: sec-fetch-dest]
-    expected: FAIL
-
-  [cross-site report: sec-fetch-dest]
-    expected: FAIL
-
-  [same-site report: sec-fetch-mode]
-    expected: FAIL
-
-  [same-origin report: sec-fetch-dest]
-    expected: FAIL
-
-  [cross-site report: sec-fetch-mode]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/script.https.sub.html.ini
+++ /dev/null
@@ -1,37 +0,0 @@
-[script.https.sub.html]
-  [Cross-site script: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-site script: sec-fetch-dest]
-    expected: FAIL
-
-  [Cross-site script: sec-fetch-site]
-    expected: FAIL
-
-  [Same-origin script: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-site script: sec-fetch-site]
-    expected: FAIL
-
-  [Same-origin script: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-origin CORS script: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-origin CORS script: sec-fetch-site]
-    expected: FAIL
-
-  [Same-origin CORS script: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-origin script: sec-fetch-site]
-    expected: FAIL
-
-  [Same-site script: sec-fetch-mode]
-    expected: FAIL
-
-  [Cross-site script: sec-fetch-dest]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/serviceworker.https.sub.html.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[serviceworker.https.sub.html]
-  [Register service worker: sec-fetch-dest]
-    expected: FAIL
-
-  [Register service worker: sec-fetch-mode]
-    expected: FAIL
-
-  [Update service worker: sec-fetch-mode]
-    expected: FAIL
-
-  [Update service worker: sec-fetch-site]
-    expected: FAIL
-
-  [Update service worker: sec-fetch-dest]
-    expected: FAIL
-
-  [Register service worker: sec-fetch-site]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/sharedworker.https.sub.html.ini
+++ /dev/null
@@ -1,10 +0,0 @@
-[sharedworker.https.sub.html]
-  [undefined: sec-fetch-mode]
-    expected: FAIL
-
-  [undefined: sec-fetch-site]
-    expected: FAIL
-
-  [undefined: sec-fetch-dest]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/style.https.sub.html.ini
+++ /dev/null
@@ -1,37 +0,0 @@
-[style.https.sub.html]
-  [Cross-Site style: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-Site style: sec-fetch-dest]
-    expected: FAIL
-
-  [Cross-Site style: sec-fetch-site]
-    expected: FAIL
-
-  [Same-Origin style: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-Origin, cors style: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-Site style: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-Site style: sec-fetch-site]
-    expected: FAIL
-
-  [Same-Origin, cors style: sec-fetch-site]
-    expected: FAIL
-
-  [Same-Origin style: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-Origin, cors style: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-Origin style: sec-fetch-site]
-    expected: FAIL
-
-  [Cross-Site style: sec-fetch-mode]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/track.https.sub.html.ini
+++ /dev/null
@@ -1,37 +0,0 @@
-[track.https.sub.html]
-  [Same-Site track: sec-fetch-site]
-    expected: FAIL
-
-  [Same-Origin, CORS track: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-Site track: sec-fetch-dest]
-    expected: FAIL
-
-  [Cross-Site track: sec-fetch-mode]
-    expected: FAIL
-
-  [Cross-Site track: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-Origin track: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-Origin track: sec-fetch-site]
-    expected: FAIL
-
-  [Same-Origin track: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-Origin, CORS track: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-Site track: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-Origin, CORS track: sec-fetch-site]
-    expected: FAIL
-
-  [Cross-Site track: sec-fetch-site]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/unload.https.sub.html.ini
+++ /dev/null
@@ -1,10 +0,0 @@
-[unload.https.sub.html]
-  [undefined: sec-fetch-mode]
-    expected: FAIL
-
-  [undefined: sec-fetch-site]
-    expected: FAIL
-
-  [undefined: sec-fetch-dest]
-    expected: FAIL
-
--- a/testing/web-platform/meta/fetch/metadata/window-open.https.sub.html.ini
+++ b/testing/web-platform/meta/fetch/metadata/window-open.https.sub.html.ini
@@ -1,103 +1,22 @@
 [window-open.https.sub.html]
   expected:
     if os == "android": ERROR
   [Cross-site window, user-activated: sec-fetch-user]
     expected: FAIL
 
-  [Same-origin window, user-activated: sec-fetch-mode]
-    expected: FAIL
-
   [Cross-site window, forced, reloaded]
     expected:
       if os == "android": ["FAIL", "PASS"]
       [PASS, FAIL]
 
-  [Same-origin window, forced, reloaded: sec-fetch-site]
-    expected: FAIL
-
-  [Cross-site window, forced, reloaded: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-origin window, forced: sec-fetch-site]
-    expected: FAIL
-
-  [Same-site window, user-activated: sec-fetch-site]
-    expected: FAIL
-
-  [Cross-site window, user-activated: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-origin window, forced, reloaded: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-site window, forced: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-site window, user-activated: sec-fetch-dest]
-    expected: FAIL
-
-  [Cross-site window, forced: sec-fetch-dest]
-    expected: FAIL
-
-  [Cross-site window, user-activated: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-site window, forced, reloaded: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-origin window, user-activated: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-site window, forced: sec-fetch-mode]
-    expected: FAIL
-
-  [Cross-site window, forced: sec-fetch-site]
-    expected: FAIL
-
-  [Cross-site window, forced, reloaded: sec-fetch-mode]
-    expected: FAIL
-
-  [Cross-site window, forced: sec-fetch-mode]
-    expected: FAIL
-
-  [Cross-site window, forced, reloaded: sec-fetch-site]
-    expected: FAIL
-
   [Same-origin window, user-activated: sec-fetch-user]
     expected: FAIL
 
-  [Cross-site window, user-activated: sec-fetch-site]
-    expected: FAIL
-
-  [Same-origin window, forced: sec-fetch-dest]
-    expected: FAIL
-
-  [Same-site window, user-activated: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-origin window, forced: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-site window, forced, reloaded: sec-fetch-mode]
-    expected: FAIL
-
   [Same-site window, user-activated: sec-fetch-user]
     expected: FAIL
 
-  [Same-origin window, forced, reloaded: sec-fetch-mode]
-    expected: FAIL
-
-  [Same-site window, forced, reloaded: sec-fetch-site]
-    expected: FAIL
-
-  [Same-origin window, user-activated: sec-fetch-site]
-    expected: FAIL
-
   [Same-site window, forced, reloaded]
     expected:
       if (os == "android") and debug: ["PASS", "FAIL"]
       if (os == "android") and not debug: ["PASS", "FAIL"]
 
-  [Same-site window, forced: sec-fetch-site]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/metadata/worker.https.sub.html.ini
+++ /dev/null
@@ -1,10 +0,0 @@
-[worker.https.sub.html]
-  [undefined: sec-fetch-mode]
-    expected: FAIL
-
-  [undefined: sec-fetch-site]
-    expected: FAIL
-
-  [undefined: sec-fetch-dest]
-    expected: FAIL
-
--- a/testing/web-platform/meta/fetch/metadata/xslt.https.sub.html.ini
+++ b/testing/web-platform/meta/fetch/metadata/xslt.https.sub.html.ini
@@ -1,10 +1,3 @@
 [xslt.https.sub.html]
   [undefined: sec-fetch-mode]
-    expected: FAIL
-
-  [undefined: sec-fetch-site]
-    expected: FAIL
-
-  [undefined: sec-fetch-dest]
-    expected: FAIL
-
+    expected: FAIL # expected "same-origin" but got "cors"