Bug 1532318 - Part 2 : update changes of nsIHttpChannel in codebase r=smaug
authorThomas Nguyen <tnguyen@mozilla.com>
Thu, 02 May 2019 12:33:55 +0000
changeset 531090 9403b1da29331259303fb5b6c70ac8425e3c98bb
parent 531089 e36bb20f910c225ffe1ec9b93cfbeb6206a1271b
child 531091 59dc2743695d817f095bf76acce8de6073b26598
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1532318
milestone68.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 1532318 - Part 2 : update changes of nsIHttpChannel in codebase r=smaug Differential Revision: https://phabricator.services.mozilla.com/D22786
docshell/base/nsDocShell.cpp
docshell/base/nsPingListener.cpp
docshell/base/nsPingListener.h
dom/base/Document.cpp
dom/base/EventSource.cpp
dom/base/Navigator.cpp
dom/base/nsContentUtils.cpp
dom/base/nsObjectLoadingContent.cpp
dom/base/nsSyncLoadService.cpp
dom/fetch/FetchDriver.cpp
dom/fetch/FetchUtil.cpp
dom/html/HTMLMediaElement.cpp
dom/plugins/base/nsPluginHost.cpp
dom/script/ScriptLoader.cpp
dom/serviceworkers/ServiceWorkerPrivate.cpp
dom/webbrowserpersist/nsWebBrowserPersist.cpp
dom/xslt/xslt/txMozillaStylesheetCompiler.cpp
image/imgLoader.cpp
layout/style/FontFaceSet.cpp
layout/style/Loader.cpp
toolkit/components/url-classifier/nsUrlClassifierUtils.cpp
uriloader/prefetch/nsOfflineCacheUpdate.cpp
uriloader/prefetch/nsPrefetchService.cpp
widget/android/WebExecutorSupport.cpp
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -10078,21 +10078,19 @@ nsresult nsDocShell::DoURILoad(nsDocShel
     }
   }
 
   // hack
   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
   nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(
       do_QueryInterface(channel));
   nsCOMPtr<nsIURI> referrer;
-  uint32_t referrerPolicy = RP_Unset;
   nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo();
   if (referrerInfo) {
     referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer));
-    referrerInfo->GetReferrerPolicy(&referrerPolicy);
   }
   if (httpChannelInternal) {
     if (aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES)) {
       rv = httpChannelInternal->SetThirdPartyFlags(
           nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
       MOZ_ASSERT(NS_SUCCEEDED(rv));
     }
     if (aLoadState->FirstParty()) {
@@ -10180,20 +10178,19 @@ nsresult nsDocShell::DoURILoad(nsDocShel
     }
   }
 
   if (httpChannel) {
     if (aLoadState->HeadersStream()) {
       rv = AddHeadersToChannel(aLoadState->HeadersStream(), httpChannel);
     }
     // Set the referrer explicitly
-    if (referrer &&
-        !(aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))) {
-      // Referrer is currenly only set for link clicks here.
-      rv = httpChannel->SetReferrerWithPolicy(referrer, referrerPolicy);
+    // Referrer is currenly only set for link clicks here.
+    if (referrerInfo) {
+      rv = httpChannel->SetReferrerInfo(referrerInfo);
       MOZ_ASSERT(NS_SUCCEEDED(rv));
     }
   }
 
   nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(channel);
   if (scriptChannel) {
     // Allow execution against our context if the principals match
     scriptChannel->SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL);
@@ -10574,25 +10571,18 @@ nsresult nsDocShell::ScrollToAnchor(bool
   }
 
   return NS_OK;
 }
 
 void nsDocShell::SetupReferrerInfoFromChannel(nsIChannel* aChannel) {
   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
   if (httpChannel) {
-    nsCOMPtr<nsIURI> referrer;
-    nsresult rv = httpChannel->GetReferrer(getter_AddRefs(referrer));
-    if (NS_SUCCEEDED(rv)) {
-      uint32_t referrerPolicy;
-      rv = httpChannel->GetReferrerPolicy(&referrerPolicy);
-      if (NS_SUCCEEDED(rv)) {
-        SetReferrerInfo(new ReferrerInfo(referrer, referrerPolicy));
-      }
-    }
+    nsCOMPtr<nsIReferrerInfo> referrerInfo = httpChannel->GetReferrerInfo();
+    SetReferrerInfo(referrerInfo);
   }
 }
 
 bool nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel,
                           nsIPrincipal* aTriggeringPrincipal,
                           nsIPrincipal* aPrincipalToInherit, uint32_t aLoadType,
                           nsIContentSecurityPolicy* aCsp,
                           bool aFireOnLocationChange, bool aAddToGlobalHistory,
@@ -11350,18 +11340,17 @@ nsresult nsDocShell::AddToSessionHistory
     }
   }
 
   // Get the post data & referrer
   nsCOMPtr<nsIInputStream> inputStream;
   nsCOMPtr<nsIURI> originalURI;
   nsCOMPtr<nsIURI> resultPrincipalURI;
   bool loadReplace = false;
-  nsCOMPtr<nsIURI> referrerURI;
-  uint32_t referrerPolicy = RP_Unset;
+  nsCOMPtr<nsIReferrerInfo> referrerInfo;
   uint32_t cacheKey = 0;
   nsCOMPtr<nsIPrincipal> triggeringPrincipal = aTriggeringPrincipal;
   nsCOMPtr<nsIPrincipal> principalToInherit = aPrincipalToInherit;
   nsCOMPtr<nsIContentSecurityPolicy> csp = aCsp;
   bool expired = false;
   bool discardLayoutState = false;
   nsCOMPtr<nsICacheInfoChannel> cacheChannel;
   if (aChannel) {
@@ -11383,19 +11372,17 @@ nsresult nsDocShell::AddToSessionHistory
       nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
       if (uploadChannel) {
         uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
       }
       httpChannel->GetOriginalURI(getter_AddRefs(originalURI));
       uint32_t loadFlags;
       aChannel->GetLoadFlags(&loadFlags);
       loadReplace = loadFlags & nsIChannel::LOAD_REPLACE;
-      rv = httpChannel->GetReferrer(getter_AddRefs(referrerURI));
-      MOZ_ASSERT(NS_SUCCEEDED(rv));
-      rv = httpChannel->GetReferrerPolicy(&referrerPolicy);
+      rv = httpChannel->GetReferrerInfo(getter_AddRefs(referrerInfo));
       MOZ_ASSERT(NS_SUCCEEDED(rv));
 
       discardLayoutState = ShouldDiscardLayoutState(httpChannel);
     }
 
     nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
     if (!triggeringPrincipal) {
       triggeringPrincipal = loadInfo->TriggeringPrincipal();
@@ -11437,17 +11424,17 @@ nsresult nsDocShell::AddToSessionHistory
                 cacheKey,             // CacheKey
                 mContentTypeHint,     // Content-type
                 triggeringPrincipal,  // Channel or provided principal
                 principalToInherit, csp, mHistoryID, mDynamicallyCreated);
 
   entry->SetOriginalURI(originalURI);
   entry->SetResultPrincipalURI(resultPrincipalURI);
   entry->SetLoadReplace(loadReplace);
-  entry->SetReferrerInfo(new ReferrerInfo(referrerURI, referrerPolicy));
+  entry->SetReferrerInfo(referrerInfo);
   nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(aChannel);
   if (inStrmChan) {
     bool isSrcdocChannel;
     inStrmChan->GetIsSrcdocChannel(&isSrcdocChannel);
     if (isSrcdocChannel) {
       nsAutoString srcdoc;
       inStrmChan->GetSrcdocData(srcdoc);
       entry->SetSrcdocData(srcdoc);
@@ -12615,20 +12602,21 @@ nsDocShell::OnLinkClickSync(
     // CSP from the NodePrincipal(). After Bug 965637 we can fall back to
     // querying the CSP from the document (aContent->OwnerDoc()).
     aContent->NodePrincipal()->GetCsp(getter_AddRefs(csp));
   }
 
   uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
   if (IsElementAnchorOrArea(aContent)) {
     MOZ_ASSERT(aContent->IsHTMLElement());
-    nsAutoString referrer;
-    aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, referrer);
+    nsAutoString relString;
+    aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::rel,
+                                   relString);
     nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(
-        referrer);
+        relString);
 
     bool targetBlank = aTargetSpec.LowerCaseEqualsLiteral("_blank");
     bool explicitOpenerSet = false;
 
     // The opener behaviour follows a hierarchy, such that if a higher
     // priority behaviour is specified, it always takes priority. That
     // priority is currently: norefrerer > noopener > opener > default
 
@@ -12664,41 +12652,41 @@ nsDocShell::OnLinkClickSync(
     }
   }
 
   // Get the owner document of the link that was clicked, this will be
   // the document that the link is in, or the last document that the
   // link was in. From that document, we'll get the URI to use as the
   // referrer, since the current URI in this docshell may be a
   // new document that we're in the process of loading.
-  RefPtr<Document> refererDoc = aContent->OwnerDoc();
-  NS_ENSURE_TRUE(refererDoc, NS_ERROR_UNEXPECTED);
-
-  // Now check that the refererDoc's inner window is the current inner
+  RefPtr<Document> referrerDoc = aContent->OwnerDoc();
+  NS_ENSURE_TRUE(referrerDoc, NS_ERROR_UNEXPECTED);
+
+  // Now check that the referrerDoc's inner window is the current inner
   // window for mScriptGlobal.  If it's not, then we don't want to
   // follow this link.
-  nsPIDOMWindowInner* refererInner = refererDoc->GetInnerWindow();
-  NS_ENSURE_TRUE(refererInner, NS_ERROR_UNEXPECTED);
+  nsPIDOMWindowInner* referrerInner = referrerDoc->GetInnerWindow();
+  NS_ENSURE_TRUE(referrerInner, NS_ERROR_UNEXPECTED);
   if (!mScriptGlobal ||
-      mScriptGlobal->GetCurrentInnerWindow() != refererInner) {
+      mScriptGlobal->GetCurrentInnerWindow() != referrerInner) {
     // We're no longer the current inner window
     return NS_OK;
   }
 
-  nsCOMPtr<nsIURI> referrer = refererDoc->GetDocumentURI();
-  uint32_t refererPolicy = refererDoc->GetReferrerPolicy();
+  nsCOMPtr<nsIURI> referrer = referrerDoc->GetDocumentURI();
+  uint32_t referrerPolicy = referrerDoc->GetReferrerPolicy();
 
   // get referrer attribute from clicked link and parse it
   // if per element referrer is enabled, the element referrer overrules
   // the document wide referrer
   if (IsElementAnchorOrArea(aContent)) {
     net::ReferrerPolicy refPolEnum =
         aContent->AsElement()->GetReferrerPolicyAsEnum();
     if (refPolEnum != RP_Unset) {
-      refererPolicy = refPolEnum;
+      referrerPolicy = refPolEnum;
     }
   }
 
   // referrer could be null here in some odd cases, but that's ok,
   // we'll just load the link w/o sending a referrer in those cases.
 
   // If this is an anchor element, grab its type property to use as a hint
   nsAutoString typeHint;
@@ -12718,17 +12706,17 @@ nsDocShell::OnLinkClickSync(
   uint32_t loadType = inOnLoadHandler ? LOAD_NORMAL_REPLACE : LOAD_LINK;
 
   if (aIsUserTriggered) {
     flags |= INTERNAL_LOAD_FLAGS_IS_USER_TRIGGERED;
   }
 
   bool sendReferrer = !(flags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER);
   nsCOMPtr<nsIReferrerInfo> referrerInfo =
-      new ReferrerInfo(referrer, refererPolicy, sendReferrer);
+      new ReferrerInfo(referrer, referrerPolicy, sendReferrer);
   RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI);
   loadState->SetReferrerInfo(referrerInfo);
   loadState->SetTriggeringPrincipal(triggeringPrincipal);
   loadState->SetPrincipalToInherit(aContent->NodePrincipal());
   loadState->SetCsp(csp);
   loadState->SetLoadFlags(flags);
   loadState->SetTarget(aTargetSpec);
   loadState->SetTypeHint(NS_ConvertUTF16toUTF8(typeHint));
@@ -12736,18 +12724,17 @@ nsDocShell::OnLinkClickSync(
   loadState->SetPostDataStream(aPostDataStream);
   loadState->SetHeadersStream(aHeadersDataStream);
   loadState->SetLoadType(loadType);
   loadState->SetFirstParty(true);
   loadState->SetSourceDocShell(this);
   nsresult rv = InternalLoad(loadState, aDocShell, aRequest);
 
   if (NS_SUCCEEDED(rv)) {
-    nsPingListener::DispatchPings(this, aContent, aURI, referrer,
-                                  refererPolicy);
+    nsPingListener::DispatchPings(this, aContent, aURI, referrerInfo);
   }
   return rv;
 }
 
 NS_IMETHODIMP
 nsDocShell::OnOverLink(nsIContent* aContent, nsIURI* aURI,
                        const nsAString& aTargetSpec) {
   if (aContent->IsEditable()) {
--- a/docshell/base/nsPingListener.cpp
+++ b/docshell/base/nsPingListener.cpp
@@ -74,19 +74,18 @@ static void OnPingTimeout(nsITimer* aTim
   }
 }
 
 struct MOZ_STACK_CLASS SendPingInfo {
   int32_t numPings;
   int32_t maxPings;
   bool requireSameHost;
   nsIURI* target;
-  nsIURI* referrer;
+  nsIReferrerInfo* referrerInfo;
   nsIDocShell* docShell;
-  uint32_t referrerPolicy;
 };
 
 static void SendPing(void* aClosure, nsIContent* aContent, nsIURI* aURI,
                      nsIIOService* aIOService) {
   SendPingInfo* info = static_cast<SendPingInfo*>(aClosure);
   if (info->maxPings > -1 && info->numPings >= info->maxPings) {
     return;
   }
@@ -146,52 +145,54 @@ static void SendPing(void* aClosure, nsI
     rv = httpChan->SetRequestHeader(NS_LITERAL_CSTRING("Ping-To"), pingTo,
                                     false);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
   }
 
   nsCOMPtr<nsIScriptSecurityManager> sm =
       do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
 
-  if (sm && info->referrer) {
-    bool referrerIsSecure;
+  if (sm && info->referrerInfo) {
+    nsCOMPtr<nsIURI> referrer = info->referrerInfo->GetOriginalReferrer();
+    bool referrerIsSecure = false;
     uint32_t flags = nsIProtocolHandler::URI_IS_POTENTIALLY_TRUSTWORTHY;
-    rv = NS_URIChainHasFlags(info->referrer, flags, &referrerIsSecure);
+    if (referrer) {
+      rv = NS_URIChainHasFlags(referrer, flags, &referrerIsSecure);
+    }
 
     // Default to sending less data if NS_URIChainHasFlags() fails.
     referrerIsSecure = NS_FAILED(rv) || referrerIsSecure;
 
     bool isPrivateWin = false;
     if (doc) {
       isPrivateWin =
           doc->NodePrincipal()->OriginAttributesRef().mPrivateBrowsingId > 0;
     }
 
     bool sameOrigin = NS_SUCCEEDED(
-        sm->CheckSameOriginURI(info->referrer, aURI, false, isPrivateWin));
+        sm->CheckSameOriginURI(referrer, aURI, false, isPrivateWin));
 
     // If both the address of the document containing the hyperlink being
     // audited and "ping URL" have the same origin or the document containing
     // the hyperlink being audited was not retrieved over an encrypted
     // connection, send a Ping-From header.
     if (sameOrigin || !referrerIsSecure) {
       nsAutoCString pingFrom;
-      if (NS_SUCCEEDED(info->referrer->GetSpec(pingFrom))) {
+      if (NS_SUCCEEDED(referrer->GetSpec(pingFrom))) {
         rv = httpChan->SetRequestHeader(NS_LITERAL_CSTRING("Ping-From"),
                                         pingFrom, false);
         MOZ_ASSERT(NS_SUCCEEDED(rv));
       }
     }
 
     // If the document containing the hyperlink being audited was not retrieved
     // over an encrypted connection and its address does not have the same
     // origin as "ping URL", send a referrer.
-    if (!sameOrigin && !referrerIsSecure) {
-      rv =
-          httpChan->SetReferrerWithPolicy(info->referrer, info->referrerPolicy);
+    if (!sameOrigin && !referrerIsSecure && info->referrerInfo) {
+      rv = httpChan->SetReferrerInfo(info->referrerInfo);
       MOZ_ASSERT(NS_SUCCEEDED(rv));
     }
   }
 
   nsCOMPtr<nsIUploadChannel2> uploadChan = do_QueryInterface(httpChan);
   if (!uploadChan) {
     return;
   }
@@ -282,33 +283,32 @@ static void ForEachPing(nsIContent* aCon
     // Explicitly not allow loading data: URIs
     if (!net::SchemeIsData(uri)) {
       aCallback(aClosure, aContent, uri, ios);
     }
   }
 }
 
 // Spec: http://whatwg.org/specs/web-apps/current-work/#ping
-/*static*/
-void nsPingListener::DispatchPings(nsIDocShell* aDocShell, nsIContent* aContent,
-                                   nsIURI* aTarget, nsIURI* aReferrer,
-                                   uint32_t aReferrerPolicy) {
+/*static*/ void nsPingListener::DispatchPings(nsIDocShell* aDocShell,
+                                              nsIContent* aContent,
+                                              nsIURI* aTarget,
+                                              nsIReferrerInfo* aReferrerInfo) {
   SendPingInfo info;
 
   if (!PingsEnabled(&info.maxPings, &info.requireSameHost)) {
     return;
   }
   if (info.maxPings == 0) {
     return;
   }
 
   info.numPings = 0;
   info.target = aTarget;
-  info.referrer = aReferrer;
-  info.referrerPolicy = aReferrerPolicy;
+  info.referrerInfo = aReferrerInfo;
   info.docShell = aDocShell;
 
   ForEachPing(aContent, SendPing, &info);
 }
 
 nsPingListener::~nsPingListener() {
   if (mTimer) {
     mTimer->Cancel();
--- a/docshell/base/nsPingListener.h
+++ b/docshell/base/nsPingListener.h
@@ -3,17 +3,17 @@
 /* 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 nsPingListener_h__
 #define nsPingListener_h__
 
 #include "nsIStreamListener.h"
-
+#include "nsIReferrerInfo.h"
 #include "nsCOMPtr.h"
 
 namespace mozilla {
 namespace dom {
 class DocGroup;
 }
 }  // namespace mozilla
 
@@ -31,18 +31,17 @@ class nsPingListener final : public nsIS
 
   nsPingListener() {}
 
   void SetLoadGroup(nsILoadGroup* aLoadGroup) { mLoadGroup = aLoadGroup; }
 
   nsresult StartTimeout(mozilla::dom::DocGroup* aDocGroup);
 
   static void DispatchPings(nsIDocShell* aDocShell, nsIContent* aContent,
-                            nsIURI* aTarget, nsIURI* aReferrer,
-                            uint32_t aReferrerPolicy);
+                            nsIURI* aTarget, nsIReferrerInfo* aReferrerInfo);
 
  private:
   ~nsPingListener();
 
   nsCOMPtr<nsILoadGroup> mLoadGroup;
   nsCOMPtr<nsITimer> mTimer;
 };
 
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -211,16 +211,17 @@
 #include "mozilla/dom/Comment.h"
 #include "nsTextNode.h"
 #include "mozilla/dom/Link.h"
 #include "mozilla/dom/HTMLCollectionBinding.h"
 #include "mozilla/dom/HTMLElementBinding.h"
 #include "nsXULAppAPI.h"
 #include "mozilla/dom/Touch.h"
 #include "mozilla/dom/TouchEvent.h"
+#include "ReferrerInfo.h"
 
 #include "mozilla/Preferences.h"
 
 #include "imgILoader.h"
 #include "imgRequestProxy.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsSandboxFlags.h"
 #include "mozilla/dom/AnimatableBinding.h"
@@ -990,17 +991,19 @@ nsresult ExternalResourceMap::PendingLoa
                      nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS,
                      nsIContentPolicy::TYPE_OTHER,
                      nullptr,  // aPerformanceStorage
                      loadGroup);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
   if (httpChannel) {
-    rv = httpChannel->SetReferrerWithPolicy(aReferrer, aReferrerPolicy);
+    nsCOMPtr<nsIReferrerInfo> referrerInfo =
+        new ReferrerInfo(aReferrer, aReferrerPolicy);
+    rv = httpChannel->SetReferrerInfoWithoutClone(referrerInfo);
     Unused << NS_WARN_IF(NS_FAILED(rv));
   }
 
   mURI = aURI;
 
   return channel->AsyncOpen(this);
 }
 
--- a/dom/base/EventSource.cpp
+++ b/dom/base/EventSource.cpp
@@ -42,16 +42,17 @@
 #include "nsIContentSecurityPolicy.h"
 #include "nsContentUtils.h"
 #include "mozilla/Preferences.h"
 #include "xpcpublic.h"
 #include "nsWrapperCacheInlines.h"
 #include "mozilla/Attributes.h"
 #include "nsError.h"
 #include "mozilla/Encoding.h"
+#include "ReferrerInfo.h"
 
 namespace mozilla {
 namespace dom {
 
 static LazyLogModule gEventSourceLog("EventSource");
 
 #define SPACE_CHAR (char16_t)0x0020
 #define CR_CHAR (char16_t)0x000D
@@ -89,17 +90,17 @@ class EventSourceImpl final : public nsI
 
   void Close();
 
   void Init(nsIPrincipal* aPrincipal, const nsAString& aURL, ErrorResult& aRv);
 
   nsresult GetBaseURI(nsIURI** aBaseURI);
 
   void SetupHttpChannel();
-  nsresult SetupReferrerPolicy();
+  nsresult SetupReferrerInfo();
   nsresult InitChannelAndRequestEventSource();
   nsresult ResetConnection();
   void ResetDecoder();
   nsresult SetReconnectionTimeout();
 
   void AnnounceConnection();
   void DispatchAllMessageEvents();
   nsresult RestartConnection();
@@ -804,18 +805,18 @@ EventSourceImpl::AsyncOnChannelRedirect(
   }
 
   // update our channel
 
   mHttpChannel = do_QueryInterface(aNewChannel);
   NS_ENSURE_STATE(mHttpChannel);
 
   SetupHttpChannel();
-  // The HTTP impl already copies over the referrer and referrer policy on
-  // redirects, so we don't need to SetupReferrerPolicy().
+  // The HTTP impl already copies over the referrer info on
+  // redirects, so we don't need to SetupReferrerInfo().
 
   if ((aFlags & nsIChannelEventSink::REDIRECT_PERMANENT) != 0) {
     rv = NS_GetFinalChannelURI(mHttpChannel, getter_AddRefs(mSrc));
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   aCallback->OnRedirectVerifyCallback(NS_OK);
 
@@ -924,23 +925,24 @@ void EventSourceImpl::SetupHttpChannel()
   if (NS_FAILED(rv)) {
     MOZ_LOG(gEventSourceLog, LogLevel::Warning,
             ("SetupHttpChannel. rv=%x (%s)", uint32_t(rv), eventId.get()));
   }
 #endif
   Unused << rv;
 }
 
-nsresult EventSourceImpl::SetupReferrerPolicy() {
+nsresult EventSourceImpl::SetupReferrerInfo() {
   AssertIsOnMainThread();
   MOZ_ASSERT(!IsShutDown());
   nsCOMPtr<Document> doc = mEventSource->GetDocumentIfCurrent();
   if (doc) {
-    nsresult rv = mHttpChannel->SetReferrerWithPolicy(doc->GetDocumentURI(),
-                                                      doc->GetReferrerPolicy());
+    nsCOMPtr<nsIReferrerInfo> referrerInfo =
+        new ReferrerInfo(doc->GetDocumentURI(), doc->GetReferrerPolicy());
+    nsresult rv = mHttpChannel->SetReferrerInfoWithoutClone(referrerInfo);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
 nsresult EventSourceImpl::InitChannelAndRequestEventSource() {
   AssertIsOnMainThread();
@@ -996,17 +998,17 @@ nsresult EventSourceImpl::InitChannelAnd
   }
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   mHttpChannel = do_QueryInterface(channel);
   NS_ENSURE_TRUE(mHttpChannel, NS_ERROR_NO_INTERFACE);
 
   SetupHttpChannel();
-  rv = SetupReferrerPolicy();
+  rv = SetupReferrerInfo();
   NS_ENSURE_SUCCESS(rv, rv);
 
 #ifdef DEBUG
   {
     nsCOMPtr<nsIInterfaceRequestor> notificationCallbacks;
     mHttpChannel->GetNotificationCallbacks(
         getter_AddRefs(notificationCallbacks));
     MOZ_ASSERT(!notificationCallbacks);
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -68,16 +68,17 @@
 #include "nsICookieService.h"
 #include "nsIStringStream.h"
 #include "nsIHttpChannel.h"
 #include "nsIHttpChannelInternal.h"
 #include "nsStreamUtils.h"
 #include "WidgetUtils.h"
 #include "nsIPresentationService.h"
 #include "nsIScriptError.h"
+#include "ReferrerInfo.h"
 
 #include "nsIExternalProtocolHandler.h"
 #include "BrowserChild.h"
 #include "URIUtils.h"
 
 #include "mozilla/dom/MediaDevices.h"
 #include "MediaManager.h"
 
@@ -1146,18 +1147,20 @@ bool Navigator::SendBeaconInternal(const
   }
 
   nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
   if (!httpChannel) {
     // Beacon spec only supports HTTP requests at this time
     aRv.Throw(NS_ERROR_DOM_BAD_URI);
     return false;
   }
-  mozilla::net::ReferrerPolicy referrerPolicy = doc->GetReferrerPolicy();
-  rv = httpChannel->SetReferrerWithPolicy(documentURI, referrerPolicy);
+
+  nsCOMPtr<nsIReferrerInfo> referrerInfo =
+      new ReferrerInfo(doc->GetDocumentURI(), doc->GetReferrerPolicy());
+  rv = httpChannel->SetReferrerInfoWithoutClone(referrerInfo);
   MOZ_ASSERT(NS_SUCCEEDED(rv));
 
   nsCOMPtr<nsIInputStream> in;
   nsAutoCString contentTypeWithCharset;
   nsAutoCString charset;
   uint64_t length = 0;
 
   if (aBody) {
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -244,16 +244,17 @@
 #include "nsPluginHost.h"
 #include "nsIBrowser.h"
 #include "mozilla/HangAnnotations.h"
 #include "mozilla/Encoding.h"
 #include "nsXULElement.h"
 #include "mozilla/RecordReplay.h"
 #include "nsThreadManager.h"
 #include "nsIBidiKeyboard.h"
+#include "ReferrerInfo.h"
 
 #if defined(XP_WIN)
 // Undefine LoadImage to prevent naming conflict with Windows.
 #  undef LoadImage
 #endif
 
 extern "C" int MOZ_XMLTranslateEntity(const char* ptr, const char* end,
                                       const char** next, char16_t* result);
@@ -7975,18 +7976,20 @@ nsresult nsContentUtils::SetFetchReferre
   nsCOMPtr<nsIURI> principalURI;
 
   if (aPrincipal->IsSystemPrincipal()) {
     return NS_OK;
   }
 
   aPrincipal->GetURI(getter_AddRefs(principalURI));
 
+  nsCOMPtr<nsIReferrerInfo> referrerInfo;
   if (!aDoc) {
-    return aChannel->SetReferrerWithPolicy(principalURI, aReferrerPolicy);
+    referrerInfo = new ReferrerInfo(principalURI, aReferrerPolicy);
+    return aChannel->SetReferrerInfoWithoutClone(referrerInfo);
   }
 
   // If it weren't for history.push/replaceState, we could just use the
   // principal's URI here.  But since we want changes to the URI effected
   // by push/replaceState to be reflected in the XHR referrer, we have to
   // be more clever.
   //
   // If the document's original URI (before any push/replaceStates) matches
@@ -8005,17 +8008,18 @@ nsresult nsContentUtils::SetFetchReferre
       referrerURI = docCurURI;
     }
   }
 
   if (!referrerURI) {
     referrerURI = principalURI;
   }
 
-  return aChannel->SetReferrerWithPolicy(referrerURI, aReferrerPolicy);
+  referrerInfo = new ReferrerInfo(referrerURI, aReferrerPolicy);
+  return aChannel->SetReferrerInfoWithoutClone(referrerInfo);
 }
 
 // static
 net::ReferrerPolicy nsContentUtils::GetReferrerPolicyFromHeader(
     const nsAString& aHeader) {
   // Multiple headers could be concatenated into one comma-separated
   // list of policies. Need to tokenize the multiple headers.
   nsCharSeparatedTokenizer tokenizer(aHeader, ',');
@@ -9777,18 +9781,22 @@ bool nsContentUtils::AttemptLargeAllocat
   NS_ENSURE_TRUE(wbc3, false);
 
   nsCOMPtr<nsIURI> uri;
   rv = aChannel->GetURI(getter_AddRefs(uri));
   NS_ENSURE_SUCCESS(rv, false);
   NS_ENSURE_TRUE(uri, false);
 
   nsCOMPtr<nsIURI> referrer;
-  rv = aChannel->GetReferrer(getter_AddRefs(referrer));
+  nsCOMPtr<nsIReferrerInfo> referrerInfo;
+  rv = aChannel->GetReferrerInfo(getter_AddRefs(referrerInfo));
   NS_ENSURE_SUCCESS(rv, false);
+  if (referrerInfo) {
+    referrer = referrerInfo->GetComputedReferrer();
+  }
 
   nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
   nsCOMPtr<nsIPrincipal> triggeringPrincipal = loadInfo->TriggeringPrincipal();
 
   // Currently we query the CSP from the triggeringPrincipal within the
   // loadInfo. After Bug 965637, we can query the CSP from the loadInfo, which
   // internally queries the CSP from the Client.
   nsCOMPtr<nsIContentSecurityPolicy> csp;
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -89,16 +89,17 @@
 #include "mozilla/dom/HTMLObjectElementBinding.h"
 #include "mozilla/dom/HTMLEmbedElement.h"
 #include "mozilla/dom/HTMLObjectElement.h"
 #include "mozilla/net/UrlClassifierFeatureFactory.h"
 #include "mozilla/LoadInfo.h"
 #include "mozilla/PresShell.h"
 #include "nsChannelClassifier.h"
 #include "nsFocusManager.h"
+#include "ReferrerInfo.h"
 
 #ifdef XP_WIN
 // Thanks so much, Microsoft! :(
 #  ifdef CreateEvent
 #    undef CreateEvent
 #  endif
 #endif  // XP_WIN
 
@@ -2323,18 +2324,19 @@ nsresult nsObjectLoadingContent::OpenCha
   if (inherit) {
     nsCOMPtr<nsILoadInfo> loadinfo = chan->LoadInfo();
     loadinfo->SetPrincipalToInherit(thisContent->NodePrincipal());
   }
 
   // Referrer
   nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
   if (httpChan) {
-    rv = httpChan->SetReferrerWithPolicy(doc->GetDocumentURI(),
-                                         doc->GetReferrerPolicy());
+    nsCOMPtr<nsIReferrerInfo> referrerInfo =
+        new ReferrerInfo(doc->GetDocumentURI(), doc->GetReferrerPolicy());
+    rv = httpChan->SetReferrerInfoWithoutClone(referrerInfo);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
 
     // Set the initiator type
     nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(httpChan));
     if (timedChannel) {
       timedChannel->SetInitiatorType(thisContent->LocalName());
     }
 
--- a/dom/base/nsSyncLoadService.cpp
+++ b/dom/base/nsSyncLoadService.cpp
@@ -19,16 +19,17 @@
 #include "nsString.h"
 #include "nsWeakReference.h"
 #include "mozilla/dom/Document.h"
 #include "nsIPrincipal.h"
 #include "nsContentUtils.h"  // for kLoadAsData
 #include "nsThreadUtils.h"
 #include "nsNetUtil.h"
 #include "nsStreamUtils.h"
+#include "ReferrerInfo.h"
 #include <algorithm>
 
 using namespace mozilla;
 
 using mozilla::net::ReferrerPolicy;
 
 /**
  * This class manages loading a single XML document
@@ -132,17 +133,19 @@ nsresult nsSyncLoader::LoadDocument(nsIC
         NS_LITERAL_CSTRING(
             "text/xml,application/xml,application/xhtml+xml,*/*;q=0.1"),
         false);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
     nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
     nsCOMPtr<nsIURI> loaderUri;
     loadInfo->TriggeringPrincipal()->GetURI(getter_AddRefs(loaderUri));
     if (loaderUri) {
-      rv = http->SetReferrerWithPolicy(loaderUri, aReferrerPolicy);
+      nsCOMPtr<nsIReferrerInfo> referrerInfo =
+          new ReferrerInfo(loaderUri, aReferrerPolicy);
+      rv = http->SetReferrerInfoWithoutClone(referrerInfo);
       MOZ_ASSERT(NS_SUCCEEDED(rv));
     }
   }
 
   // Hook us up to listen to redirects and the like.
   // Do this before setting up the cross-site proxy since
   // that installs its own proxies.
   mChannel->SetNotificationCallbacks(this);
--- a/dom/fetch/FetchDriver.cpp
+++ b/dom/fetch/FetchDriver.cpp
@@ -601,17 +601,17 @@ nsresult FetchDriver::HttpFetch(
     }
     // Step 6 of https://fetch.spec.whatwg.org/#main-fetch
     // If request’s referrer policy is the empty string,
     // then set request’s referrer policy to the user-set default policy.
     if (mRequest->ReferrerPolicy_() == ReferrerPolicy::_empty) {
       nsCOMPtr<nsILoadInfo> loadInfo = httpChan->LoadInfo();
       bool isPrivate = loadInfo->GetOriginAttributes().mPrivateBrowsingId > 0;
       net::ReferrerPolicy referrerPolicy = static_cast<net::ReferrerPolicy>(
-          NS_GetDefaultReferrerPolicy(httpChan, uri, isPrivate));
+          ReferrerInfo::GetDefaultReferrerPolicy(httpChan, uri, isPrivate));
       mRequest->SetReferrerPolicy(referrerPolicy);
     }
 
     rv = FetchUtil::SetRequestReferrer(mPrincipal, mDocument, httpChan,
                                        mRequest);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Bug 1120722 - Authorization will be handled later.
--- a/dom/fetch/FetchUtil.cpp
+++ b/dom/fetch/FetchUtil.cpp
@@ -109,52 +109,56 @@ bool FetchUtil::ExtractHeader(nsACString
 }
 
 // static
 nsresult FetchUtil::SetRequestReferrer(nsIPrincipal* aPrincipal, Document* aDoc,
                                        nsIHttpChannel* aChannel,
                                        InternalRequest* aRequest) {
   MOZ_ASSERT(NS_IsMainThread());
 
+  nsresult rv = NS_OK;
   nsAutoString referrer;
   aRequest->GetReferrer(referrer);
+
   net::ReferrerPolicy policy = aRequest->GetReferrerPolicy();
-
-  nsresult rv = NS_OK;
+  nsCOMPtr<nsIReferrerInfo> referrerInfo;
   if (referrer.IsEmpty()) {
     // This is the case request’s referrer is "no-referrer"
-    rv = aChannel->SetReferrerWithPolicy(nullptr, net::RP_No_Referrer);
+    referrerInfo = new ReferrerInfo(nullptr, net::RP_No_Referrer);
+    rv = aChannel->SetReferrerInfoWithoutClone(referrerInfo);
     NS_ENSURE_SUCCESS(rv, rv);
   } else if (referrer.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR)) {
     rv = nsContentUtils::SetFetchReferrerURIWithPolicy(aPrincipal, aDoc,
                                                        aChannel, policy);
     NS_ENSURE_SUCCESS(rv, rv);
   } else {
     // From "Determine request's Referrer" step 3
     // "If request's referrer is a URL, let referrerSource be request's
     // referrer."
     nsCOMPtr<nsIURI> referrerURI;
     rv = NS_NewURI(getter_AddRefs(referrerURI), referrer, nullptr, nullptr);
     NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = aChannel->SetReferrerWithPolicy(referrerURI, policy);
+    referrerInfo = new ReferrerInfo(referrerURI, policy);
+    rv = aChannel->SetReferrerInfoWithoutClone(referrerInfo);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  nsCOMPtr<nsIURI> referrerURI;
-  Unused << aChannel->GetReferrer(getter_AddRefs(referrerURI));
+  nsCOMPtr<nsIURI> computedReferrer;
+  referrerInfo = aChannel->GetReferrerInfo();
+  if (referrerInfo) {
+    computedReferrer = referrerInfo->GetComputedReferrer();
+  }
 
   // Step 8 https://fetch.spec.whatwg.org/#main-fetch
   // If request’s referrer is not "no-referrer", set request’s referrer to
   // the result of invoking determine request’s referrer.
-  if (referrerURI) {
+  if (computedReferrer) {
     nsAutoCString spec;
-    rv = referrerURI->GetSpec(spec);
+    rv = computedReferrer->GetSpec(spec);
     NS_ENSURE_SUCCESS(rv, rv);
-
     aRequest->SetReferrer(NS_ConvertUTF8toUTF16(spec));
   } else {
     aRequest->SetReferrer(EmptyString());
   }
 
   return NS_OK;
 }
 
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -117,16 +117,17 @@
 #include "nsNodeInfoManager.h"
 #include "nsPresContext.h"
 #include "nsQueryObject.h"
 #include "nsRange.h"
 #include "nsSize.h"
 #include "nsThreadUtils.h"
 #include "nsURIHashKey.h"
 #include "nsVideoFrame.h"
+#include "ReferrerInfo.h"
 #include "xpcpublic.h"
 #include <algorithm>
 #include <cmath>
 #include <limits>
 
 mozilla::LazyLogModule gMediaElementLog("nsMediaElement");
 static mozilla::LazyLogModule gMediaElementEventsLog("nsMediaElementEvents");
 
@@ -6206,18 +6207,19 @@ void HTMLMediaElement::SetRequestHeaders
   // Content-Duration and a length spec in the container are not present either)
   // and from seeking. So, disable the standard "Accept-Encoding: gzip,deflate"
   // that we usually send. See bug 614760.
   DebugOnly<nsresult> rv = aChannel->SetRequestHeader(
       NS_LITERAL_CSTRING("Accept-Encoding"), EmptyCString(), false);
   MOZ_ASSERT(NS_SUCCEEDED(rv));
 
   // Set the Referer header
-  rv = aChannel->SetReferrerWithPolicy(OwnerDoc()->GetDocumentURI(),
-                                       OwnerDoc()->GetReferrerPolicy());
+  nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo(
+      OwnerDoc()->GetDocumentURI(), OwnerDoc()->GetReferrerPolicy());
+  rv = aChannel->SetReferrerInfoWithoutClone(referrerInfo);
   MOZ_ASSERT(NS_SUCCEEDED(rv));
 }
 
 void HTMLMediaElement::FireTimeUpdate(bool aPeriodic) {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
 
   TimeStamp now = TimeStamp::Now();
   double time = CurrentTime();
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -90,16 +90,17 @@
 #include "nsPluginNativeWindow.h"
 #include "nsIContentPolicy.h"
 #include "nsContentPolicyUtils.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Telemetry.h"
 #include "nsIImageLoadingContent.h"
 #include "mozilla/Preferences.h"
 #include "nsVersionComparator.h"
+#include "ReferrerInfo.h"
 
 #include "mozilla/dom/Promise.h"
 
 #if defined(XP_WIN)
 #  include "nsIWindowMediator.h"
 #  include "nsIBaseWindow.h"
 #  include "windows.h"
 #  include "winbase.h"
@@ -3130,18 +3131,19 @@ nsresult nsPluginHost::NewPluginURLStrea
 
       if (!referer) {
         if (!doc) {
           return NS_ERROR_FAILURE;
         }
         referer = doc->GetDocumentURI();
         referrerPolicy = doc->GetReferrerPolicy();
       }
-
-      rv = httpChannel->SetReferrerWithPolicy(referer, referrerPolicy);
+      nsCOMPtr<nsIReferrerInfo> referrerInfo =
+          new mozilla::dom::ReferrerInfo(referer, referrerPolicy);
+      rv = httpChannel->SetReferrerInfoWithoutClone(referrerInfo);
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
     if (aPostStream) {
       // XXX it's a bit of a hack to rewind the postdata stream
       // here but it has to be done in case the post data is
       // being reused multiple times.
       nsCOMPtr<nsISeekableStream> postDataSeekable(
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -59,16 +59,17 @@
 #include "nsContentCreatorFunctions.h"
 #include "nsProxyRelease.h"
 #include "nsSandboxFlags.h"
 #include "nsContentTypeParser.h"
 #include "nsINetworkPredictor.h"
 #include "nsMimeTypes.h"
 #include "mozilla/ConsoleReportCollector.h"
 #include "mozilla/LoadInfo.h"
+#include "ReferrerInfo.h"
 
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Unused.h"
 #include "nsIScriptError.h"
 #include "nsIAsyncOutputStream.h"
@@ -1349,18 +1350,19 @@ nsresult ScriptLoader::StartLoad(ScriptL
     if (nsJSUtils::BinASTEncodingEnabled() &&
         aRequest->ShouldAcceptBinASTEncoding()) {
       acceptTypes = APPLICATION_JAVASCRIPT_BINAST ", */*";
     }
     rv = httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
                                        acceptTypes, false);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
 
-    rv = httpChannel->SetReferrerWithPolicy(aRequest->mReferrer,
-                                            aRequest->ReferrerPolicy());
+    nsCOMPtr<nsIReferrerInfo> referrerInfo =
+        new ReferrerInfo(aRequest->mReferrer, aRequest->ReferrerPolicy());
+    rv = httpChannel->SetReferrerInfoWithoutClone(referrerInfo);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
 
     nsCOMPtr<nsIHttpChannelInternal> internalChannel(
         do_QueryInterface(httpChannel));
     if (internalChannel) {
       rv = internalChannel->SetIntegrityMetadata(
           aRequest->mIntegrity.GetIntegrityString());
       MOZ_ASSERT(NS_SUCCEEDED(rv));
--- a/dom/serviceworkers/ServiceWorkerPrivate.cpp
+++ b/dom/serviceworkers/ServiceWorkerPrivate.cpp
@@ -39,16 +39,17 @@
 #include "mozilla/dom/WorkerRef.h"
 #include "mozilla/dom/WorkerRunnable.h"
 #include "mozilla/dom/WorkerScope.h"
 #include "mozilla/dom/ipc/StructuredCloneData.h"
 #include "mozilla/net/CookieSettings.h"
 #include "mozilla/net/NeckoChannelParams.h"
 #include "mozilla/StaticPrefs.h"
 #include "mozilla/Unused.h"
+#include "nsIReferrerInfo.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 namespace mozilla {
 namespace dom {
 
 using mozilla::ipc::PrincipalInfo;
@@ -1249,31 +1250,27 @@ class FetchEventRunnable : public Extend
     rv = channel->GetLoadFlags(&loadFlags);
     NS_ENSURE_SUCCESS(rv, rv);
     nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
     mContentPolicyType = loadInfo->InternalContentPolicyType();
 
     nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
     MOZ_ASSERT(httpChannel, "How come we don't have an HTTP channel?");
 
-    nsAutoCString referrer;
-    // Ignore the return value since the Referer header may not exist.
-    Unused << httpChannel->GetRequestHeader(NS_LITERAL_CSTRING("Referer"),
-                                            referrer);
-    if (!referrer.IsEmpty()) {
-      mReferrer = referrer;
-    } else {
-      // If there's no referrer Header, means the header was omitted for
-      // security/privacy reason.
-      mReferrer = EmptyCString();
+    mReferrer = EmptyCString();
+    uint32_t referrerPolicy = 0;
+    nsCOMPtr<nsIReferrerInfo> referrerInfo = httpChannel->GetReferrerInfo();
+    if (referrerInfo) {
+      referrerPolicy = referrerInfo->GetReferrerPolicy();
+      nsCOMPtr<nsIURI> computedReferrer = referrerInfo->GetComputedReferrer();
+      if (computedReferrer) {
+        rv = computedReferrer->GetSpec(mReferrer);
+        NS_ENSURE_SUCCESS(rv, rv);
+      }
     }
-
-    uint32_t referrerPolicy = 0;
-    rv = httpChannel->GetReferrerPolicy(&referrerPolicy);
-    NS_ENSURE_SUCCESS(rv, rv);
     switch (referrerPolicy) {
       case nsIHttpChannel::REFERRER_POLICY_UNSET:
         mReferrerPolicy = ReferrerPolicy::_empty;
         break;
       case nsIHttpChannel::REFERRER_POLICY_NO_REFERRER:
         mReferrerPolicy = ReferrerPolicy::No_referrer;
         break;
       case nsIHttpChannel::REFERRER_POLICY_ORIGIN:
--- a/dom/webbrowserpersist/nsWebBrowserPersist.cpp
+++ b/dom/webbrowserpersist/nsWebBrowserPersist.cpp
@@ -59,16 +59,17 @@
 #include "WebBrowserPersistLocalDocument.h"
 
 #include "nsIContent.h"
 #include "nsIMIMEInfo.h"
 #include "mozilla/dom/HTMLInputElement.h"
 #include "mozilla/dom/HTMLSharedElement.h"
 #include "mozilla/net/CookieSettings.h"
 #include "mozilla/Printf.h"
+#include "ReferrerInfo.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 // Buffer file writes in 32kb chunks
 #define BUFFERED_OUTPUT_SIZE (1024 * 32)
 
 struct nsWebBrowserPersist::WalkData {
@@ -1268,17 +1269,19 @@ nsresult nsWebBrowserPersist::SaveURIInt
     }
   }
 
   // Set the referrer, post data and headers if any
   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(inputChannel));
   if (httpChannel) {
     // Referrer
     if (aReferrer) {
-      rv = httpChannel->SetReferrerWithPolicy(aReferrer, aReferrerPolicy);
+      nsCOMPtr<nsIReferrerInfo> referrerInfo =
+          new ReferrerInfo(aReferrer, aReferrerPolicy);
+      rv = httpChannel->SetReferrerInfoWithoutClone(referrerInfo);
       MOZ_ASSERT(NS_SUCCEEDED(rv));
     }
 
     // Post data
     if (aPostData) {
       nsCOMPtr<nsISeekableStream> stream(do_QueryInterface(aPostData));
       if (stream) {
         // Rewind the postdata stream
--- a/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp
+++ b/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp
@@ -33,16 +33,17 @@
 #include "nsIScriptError.h"
 #include "nsIURL.h"
 #include "nsError.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Text.h"
 #include "mozilla/Encoding.h"
 #include "mozilla/UniquePtr.h"
+#include "ReferrerInfo.h"
 
 using namespace mozilla;
 using mozilla::net::ReferrerPolicy;
 
 static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
 
 static void getSpec(nsIChannel* aChannel, nsAString& aSpec) {
   if (!aChannel) {
@@ -410,17 +411,19 @@ nsresult txCompileObserver::startLoad(ns
   channel->SetContentType(NS_LITERAL_CSTRING("text/xml"));
 
   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
   if (httpChannel) {
     nsCOMPtr<nsIURI> referrerURI;
     aReferrerPrincipal->GetURI(getter_AddRefs(referrerURI));
     if (referrerURI) {
       DebugOnly<nsresult> rv;
-      rv = httpChannel->SetReferrerWithPolicy(referrerURI, aReferrerPolicy);
+      nsCOMPtr<nsIReferrerInfo> referrerInfo =
+          new dom::ReferrerInfo(referrerURI, aReferrerPolicy);
+      rv = httpChannel->SetReferrerInfoWithoutClone(referrerInfo);
       MOZ_ASSERT(NS_SUCCEEDED(rv));
     }
   }
 
   nsCOMPtr<nsIParser> parser = do_CreateInstance(kCParserCID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   RefPtr<txStylesheetSink> sink = new txStylesheetSink(aCompiler, parser);
--- a/image/imgLoader.cpp
+++ b/image/imgLoader.cpp
@@ -52,16 +52,17 @@
 #include "nsIApplicationCache.h"
 #include "nsIApplicationCacheContainer.h"
 
 #include "nsIMemoryReporter.h"
 #include "DecoderFactory.h"
 #include "Image.h"
 #include "gfxPrefs.h"
 #include "prtime.h"
+#include "ReferrerInfo.h"
 
 // we want to explore making the document own the load group
 // so we can associate the document URI with the load group.
 // until this point, we have an evil hack:
 #include "nsIHttpChannelInternal.h"
 #include "nsILoadContext.h"
 #include "nsILoadGroupChild.h"
 #include "nsIDocShell.h"
@@ -879,17 +880,19 @@ static nsresult NewImageChannel(
                                           aAcceptHeader, false);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
 
     nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal =
         do_QueryInterface(newHttpChannel);
     NS_ENSURE_TRUE(httpChannelInternal, NS_ERROR_UNEXPECTED);
     rv = httpChannelInternal->SetDocumentURI(aInitialDocumentURI);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
-    rv = newHttpChannel->SetReferrerWithPolicy(aReferringURI, aReferrerPolicy);
+    nsCOMPtr<nsIReferrerInfo> referrerInfo =
+        new ReferrerInfo(aReferringURI, aReferrerPolicy);
+    rv = newHttpChannel->SetReferrerInfoWithoutClone(referrerInfo);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
   }
 
   // Image channels are loaded by default with reduced priority.
   nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(*aResult);
   if (p) {
     uint32_t priority = nsISupportsPriority::PRIORITY_LOW;
 
--- a/layout/style/FontFaceSet.cpp
+++ b/layout/style/FontFaceSet.cpp
@@ -50,16 +50,17 @@
 #include "nsNetUtil.h"
 #include "nsIProtocolHandler.h"
 #include "nsIInputStream.h"
 #include "nsLayoutUtils.h"
 #include "nsPresContext.h"
 #include "nsPrintfCString.h"
 #include "nsUTF8Utils.h"
 #include "nsDOMNavigationTiming.h"
+#include "ReferrerInfo.h"
 
 using namespace mozilla;
 using namespace mozilla::css;
 using namespace mozilla::dom;
 
 #define LOG(args) \
   MOZ_LOG(gfxUserFontSet::GetUserFontsLog(), mozilla::LogLevel::Debug, args)
 #define LOG_ENABLED() \
@@ -613,18 +614,19 @@ nsresult FontFaceSet::StartLoad(gfxUserF
          fontLoader.get(), aFontFaceSrc->mURI->GetSpecOrDefault().get(),
          aFontFaceSrc->mReferrer
              ? aFontFaceSrc->mReferrer->GetSpecOrDefault().get()
              : ""));
   }
 
   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
   if (httpChannel) {
-    rv = httpChannel->SetReferrerWithPolicy(aFontFaceSrc->mReferrer,
-                                            aFontFaceSrc->mReferrerPolicy);
+    nsCOMPtr<nsIReferrerInfo> referrerInfo = new mozilla::dom::ReferrerInfo(
+        aFontFaceSrc->mReferrer, aFontFaceSrc->mReferrerPolicy);
+    rv = httpChannel->SetReferrerInfoWithoutClone(referrerInfo);
     Unused << NS_WARN_IF(NS_FAILED(rv));
 
     nsAutoCString accept("application/font-woff;q=0.9,*/*;q=0.8");
     if (Preferences::GetBool(GFX_PREF_WOFF2_ENABLED)) {
       accept.InsertLiteral("application/font-woff2;q=1.0,", 0);
     }
     rv = httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"), accept,
                                        false);
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -49,16 +49,17 @@
 #include "mozilla/net/UrlClassifierFeatureFactory.h"
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/ServoBindings.h"
 #include "mozilla/StyleSheet.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/ConsoleReportCollector.h"
 #include "mozilla/ServoUtils.h"
 #include "mozilla/css/StreamLoader.h"
+#include "ReferrerInfo.h"
 
 #ifdef MOZ_XUL
 #  include "nsXULPrototypeCache.h"
 #endif
 
 #include "nsError.h"
 
 #include "nsIContentSecurityPolicy.h"
@@ -1449,18 +1450,19 @@ nsresult Loader::LoadSheet(SheetLoadData
       cos->AddClassFlags(nsIClassOfService::Leader);
     }
   }
 
   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
   if (httpChannel) {
     nsCOMPtr<nsIURI> referrerURI = aLoadData->GetReferrerURI();
     if (referrerURI) {
-      rv = httpChannel->SetReferrerWithPolicy(
+      nsCOMPtr<nsIReferrerInfo> referrerInfo = new mozilla::dom::ReferrerInfo(
           referrerURI, aLoadData->mSheet->GetReferrerPolicy());
+      rv = httpChannel->SetReferrerInfoWithoutClone(referrerInfo);
       Unused << NS_WARN_IF(NS_FAILED(rv));
     }
 
     nsCOMPtr<nsIHttpChannelInternal> internalChannel =
         do_QueryInterface(httpChannel);
     if (internalChannel) {
       rv = internalChannel->SetIntegrityMetadata(
           sriMetadata.GetIntegrityString());
--- a/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp
@@ -555,23 +555,25 @@ static nsresult AddThreatSourceFromChann
 
   nsCString spec;
   rv = GetSpecWithoutSensitiveData(uri, spec);
   NS_ENSURE_SUCCESS(rv, rv);
   matchingSource->set_url(spec.get());
 
   nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
   if (httpChannel) {
-    nsCOMPtr<nsIURI> referrer;
-    rv = httpChannel->GetReferrer(getter_AddRefs(referrer));
-    if (NS_SUCCEEDED(rv) && referrer) {
-      nsCString referrerSpec;
-      rv = GetSpecWithoutSensitiveData(referrer, referrerSpec);
-      NS_ENSURE_SUCCESS(rv, rv);
-      matchingSource->set_referrer(referrerSpec.get());
+    nsCOMPtr<nsIReferrerInfo> referrerInfo = httpChannel->GetReferrerInfo();
+    if (referrerInfo) {
+      nsAutoCString referrerSpec;
+      nsCOMPtr<nsIURI> referrer = referrerInfo->GetComputedReferrer();
+      if (referrer) {
+        rv = GetSpecWithoutSensitiveData(referrer, referrerSpec);
+        NS_ENSURE_SUCCESS(rv, rv);
+        matchingSource->set_referrer(referrerSpec.get());
+      }
     }
   }
 
   nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal =
       do_QueryInterface(aChannel);
   if (httpChannelInternal) {
     nsCString remoteIp;
     rv = httpChannelInternal->GetRemoteAddress(remoteIp);
--- a/uriloader/prefetch/nsOfflineCacheUpdate.cpp
+++ b/uriloader/prefetch/nsOfflineCacheUpdate.cpp
@@ -33,16 +33,17 @@
 #include "nsIConsoleService.h"
 #include "mozilla/Logging.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Attributes.h"
 #include "nsContentUtils.h"
 #include "nsIPrincipal.h"
 #include "nsDiskCacheDeviceSQL.h"
+#include "ReferrerInfo.h"
 
 #include "nsXULAppAPI.h"
 
 using namespace mozilla;
 
 static const uint32_t kRescheduleLimit = 3;
 // Max number of retries for every entry of pinned app.
 static const uint32_t kPinnedEntryRetriesLimit = 3;
@@ -172,17 +173,19 @@ nsresult nsManifestCheck::Begin() {
                      nullptr,  // aCallbacks
                      nsIRequest::LOAD_BYPASS_CACHE);
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   // configure HTTP specific stuff
   nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel);
   if (httpChannel) {
-    rv = httpChannel->SetReferrer(mReferrerURI);
+    nsCOMPtr<nsIReferrerInfo> referrerInfo =
+        new mozilla::dom::ReferrerInfo(mReferrerURI);
+    rv = httpChannel->SetReferrerInfoWithoutClone(referrerInfo);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
     rv = httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("X-Moz"),
                                        NS_LITERAL_CSTRING("offline-resource"),
                                        false);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
   }
 
   return mChannel->AsyncOpen(this);
@@ -352,17 +355,19 @@ nsresult nsOfflineCacheUpdateItem::OpenC
 
   // Set the new application cache as the target for write.
   rv = appCacheChannel->SetApplicationCacheForWrite(mApplicationCache);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // configure HTTP specific stuff
   nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel);
   if (httpChannel) {
-    rv = httpChannel->SetReferrer(mReferrerURI);
+    nsCOMPtr<nsIReferrerInfo> referrerInfo =
+        new mozilla::dom::ReferrerInfo(mReferrerURI);
+    rv = httpChannel->SetReferrerInfoWithoutClone(referrerInfo);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
     rv = httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("X-Moz"),
                                        NS_LITERAL_CSTRING("offline-resource"),
                                        false);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
   }
 
   rv = mChannel->AsyncOpen(this);
--- a/uriloader/prefetch/nsPrefetchService.cpp
+++ b/uriloader/prefetch/nsPrefetchService.cpp
@@ -8,16 +8,17 @@
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/CORSMode.h"
 #include "mozilla/Components.h"
 #include "mozilla/dom/ClientInfo.h"
 #include "mozilla/dom/HTMLLinkElement.h"
 #include "mozilla/dom/ServiceWorkerDescriptor.h"
 #include "mozilla/Preferences.h"
+#include "ReferrerInfo.h"
 
 #include "nsICacheEntry.h"
 #include "nsIServiceManager.h"
 #include "nsICategoryManager.h"
 #include "nsIObserverService.h"
 #include "nsIWebProgress.h"
 #include "nsICacheInfoChannel.h"
 #include "nsIHttpChannel.h"
@@ -133,17 +134,19 @@ nsresult nsPrefetchNode::OpenChannel() {
       this,       // aCallbacks
       nsIRequest::LOAD_BACKGROUND | nsICachingChannel::LOAD_ONLY_IF_MODIFIED);
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   // configure HTTP specific stuff
   nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel);
   if (httpChannel) {
-    rv = httpChannel->SetReferrerWithPolicy(mReferrerURI, referrerPolicy);
+    nsCOMPtr<nsIReferrerInfo> referrerInfo =
+        new mozilla::dom::ReferrerInfo(mReferrerURI, referrerPolicy);
+    rv = httpChannel->SetReferrerInfoWithoutClone(referrerInfo);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
     rv = httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("X-Moz"),
                                        NS_LITERAL_CSTRING("prefetch"), false);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
   }
 
   // Reduce the priority of prefetch network requests.
   nsCOMPtr<nsISupportsPriority> priorityChannel = do_QueryInterface(mChannel);
--- a/widget/android/WebExecutorSupport.cpp
+++ b/widget/android/WebExecutorSupport.cpp
@@ -22,16 +22,17 @@
 #include "nsIDNSRecord.h"
 
 #include "mozilla/net/DNS.h"  // for NetAddr
 #include "mozilla/net/CookieSettings.h"
 
 #include "nsNetUtil.h"  // for NS_NewURI, NS_NewChannel, NS_NewStreamLoader
 
 #include "InetAddress.h"  // for java::sdk::InetAddress and java::sdk::UnknownHostException
+#include "ReferrerInfo.h"
 
 namespace mozilla {
 using namespace net;
 
 namespace widget {
 
 static void CompleteWithError(java::GeckoResult::Param aResult,
                               nsresult aStatus) {
@@ -488,17 +489,18 @@ nsresult WebExecutorSupport::CreateStrea
   // Referrer
   RefPtr<nsIURI> referrerUri;
   const auto referrer = req->Referrer();
   if (referrer) {
     rv = NS_NewURI(getter_AddRefs(referrerUri), referrer->ToString());
     NS_ENSURE_SUCCESS(rv, NS_ERROR_MALFORMED_URI);
   }
 
-  rv = httpChannel->SetReferrer(referrerUri);
+  nsCOMPtr<nsIReferrerInfo> referrerInfo = new dom::ReferrerInfo(referrerUri);
+  rv = httpChannel->SetReferrerInfoWithoutClone(referrerInfo);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Cache mode
   nsCOMPtr<nsIHttpChannelInternal> internalChannel(
       do_QueryInterface(channel, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
   int32_t cacheMode;