Bug 1546334 - Use referrerInfo in style system. r=heycam
authorThomas Nguyen <tnguyen@mozilla.com>
Tue, 16 Jul 2019 11:43:56 +0000
changeset 482943 e0b3cfeb4ed404b3eb281dc4aa47f3225976c1e2
parent 482942 d22508da0fde27ef6993a2fcaca73ead45332118
child 482944 80128e172025774491b954db5fe2dd827f774c77
push id113703
push userarchaeopteryx@coole-files.de
push dateWed, 17 Jul 2019 16:57:18 +0000
treeherdermozilla-inbound@d9fb61d918f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1546334
milestone70.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 1546334 - Use referrerInfo in style system. r=heycam Differential Revision: https://phabricator.services.mozilla.com/D36478
dom/base/Document.cpp
dom/base/Document.h
dom/base/FragmentOrElement.cpp
dom/base/IDTracker.cpp
dom/base/IDTracker.h
dom/base/nsAttrValue.cpp
dom/base/nsContentSink.cpp
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
dom/base/nsIStyleSheetLinkingElement.h
dom/base/nsImageLoadingContent.cpp
dom/base/nsStyleLinkElement.cpp
dom/base/nsStyleLinkElement.h
dom/base/nsTreeSanitizer.cpp
dom/canvas/CanvasRenderingContext2D.cpp
dom/html/HTMLLinkElement.cpp
dom/html/HTMLStyleElement.cpp
dom/security/ReferrerInfo.cpp
dom/svg/SVGAnimationElement.cpp
dom/svg/SVGElement.cpp
dom/svg/SVGMPathElement.cpp
dom/svg/SVGStyleElement.cpp
dom/svg/SVGUseElement.cpp
dom/xml/XMLStylesheetProcessingInstruction.cpp
dom/xul/nsXULElement.cpp
gfx/thebes/gfxUserFontSet.h
layout/style/FontFace.cpp
layout/style/FontFaceSet.cpp
layout/style/GeckoBindings.cpp
layout/style/ImageLoader.cpp
layout/style/Loader.cpp
layout/style/Loader.h
layout/style/ServoCSSParser.cpp
layout/style/nsLayoutStylesheetCache.cpp
layout/style/test/gtest/StyloParsingBench.cpp
layout/svg/SVGObserverUtils.cpp
layout/svg/SVGObserverUtils.h
layout/svg/nsSVGFilterInstance.cpp
layout/xul/nsImageBoxFrame.cpp
layout/xul/tree/nsTreeBodyFrame.cpp
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -678,24 +678,24 @@ OnloadBlocker::SetLoadFlags(nsLoadFlags 
 
 // ==================================================================
 
 namespace dom {
 
 ExternalResourceMap::ExternalResourceMap() : mHaveShutDown(false) {}
 
 Document* ExternalResourceMap::RequestResource(
-    nsIURI* aURI, nsIURI* aReferrer, uint32_t aReferrerPolicy,
-    nsINode* aRequestingNode, Document* aDisplayDocument,
-    ExternalResourceLoad** aPendingLoad) {
+    nsIURI* aURI, nsIReferrerInfo* aReferrerInfo, nsINode* aRequestingNode,
+    Document* aDisplayDocument, ExternalResourceLoad** aPendingLoad) {
   // If we ever start allowing non-same-origin loads here, we might need to do
   // something interesting with aRequestingPrincipal even for the hashtable
   // gets.
   MOZ_ASSERT(aURI, "Must have a URI");
   MOZ_ASSERT(aRequestingNode, "Must have a node");
+  MOZ_ASSERT(aReferrerInfo, "Must have a referrerInfo");
   *aPendingLoad = nullptr;
   if (mHaveShutDown) {
     return nullptr;
   }
 
   // First, make sure we strip the ref from aURI.
   nsCOMPtr<nsIURI> clone;
   nsresult rv = NS_GetURIWithoutRef(aURI, getter_AddRefs(clone));
@@ -714,18 +714,17 @@ Document* ExternalResourceMap::RequestRe
     RefPtr<PendingLoad> load(loadEntry);
     load.forget(aPendingLoad);
     return nullptr;
   }
 
   RefPtr<PendingLoad> load(new PendingLoad(aDisplayDocument));
   loadEntry = load;
 
-  if (NS_FAILED(load->StartLoad(clone, aReferrer, aReferrerPolicy,
-                                aRequestingNode))) {
+  if (NS_FAILED(load->StartLoad(clone, aReferrerInfo, aRequestingNode))) {
     // Make sure we don't thrash things by trying this load again, since
     // chances are it failed for good reasons (security check, etc).
     AddExternalResource(clone, nullptr, nullptr, aDisplayDocument);
   } else {
     load.forget(aPendingLoad);
   }
 
   return nullptr;
@@ -993,40 +992,37 @@ ExternalResourceMap::PendingLoad::OnStop
     nsCOMPtr<nsIStreamListener> listener;
     mTargetListener.swap(listener);
     return listener->OnStopRequest(aRequest, aStatus);
   }
 
   return NS_OK;
 }
 
-nsresult ExternalResourceMap::PendingLoad::StartLoad(nsIURI* aURI,
-                                                     nsIURI* aReferrer,
-                                                     uint32_t aReferrerPolicy,
-                                                     nsINode* aRequestingNode) {
+nsresult ExternalResourceMap::PendingLoad::StartLoad(
+    nsIURI* aURI, nsIReferrerInfo* aReferrerInfo, nsINode* aRequestingNode) {
   MOZ_ASSERT(aURI, "Must have a URI");
   MOZ_ASSERT(aRequestingNode, "Must have a node");
+  MOZ_ASSERT(aReferrerInfo, "Must have a referrerInfo");
 
   nsCOMPtr<nsILoadGroup> loadGroup =
       aRequestingNode->OwnerDoc()->GetDocumentLoadGroup();
 
   nsresult rv = NS_OK;
   nsCOMPtr<nsIChannel> channel;
   rv = NS_NewChannel(getter_AddRefs(channel), aURI, aRequestingNode,
                      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) {
-    nsCOMPtr<nsIReferrerInfo> referrerInfo =
-        new dom::ReferrerInfo(aReferrer, aReferrerPolicy);
-    rv = httpChannel->SetReferrerInfoWithoutClone(referrerInfo);
+    rv = httpChannel->SetReferrerInfo(aReferrerInfo);
     Unused << NS_WARN_IF(NS_FAILED(rv));
   }
 
   mURI = aURI;
 
   return channel->AsyncOpen(this);
 }
 
@@ -5729,24 +5725,25 @@ void Document::SetBaseURI(nsIURI* aURI) 
 
   mDocumentBaseURI = aURI;
   RefreshLinkHrefs();
 }
 
 URLExtraData* Document::DefaultStyleAttrURLData() {
   MOZ_ASSERT(NS_IsMainThread());
   nsIURI* baseURI = GetDocBaseURI();
-  nsIURI* docURI = GetDocumentURI();
   nsIPrincipal* principal = NodePrincipal();
-  mozilla::net::ReferrerPolicy policy = GetReferrerPolicy();
+  bool equals;
   if (!mCachedURLData || mCachedURLData->BaseURI() != baseURI ||
-      mCachedURLData->GetReferrer() != docURI ||
-      mCachedURLData->GetReferrerPolicy() != policy ||
-      mCachedURLData->Principal() != principal) {
-    mCachedURLData = new URLExtraData(baseURI, docURI, principal, policy);
+      mCachedURLData->Principal() != principal || !mCachedReferrerInfo ||
+      NS_FAILED(mCachedURLData->ReferrerInfo()->Equals(mCachedReferrerInfo,
+                                                       &equals)) ||
+      !equals) {
+    mCachedReferrerInfo = ReferrerInfo::CreateForInternalCSSResources(this);
+    mCachedURLData = new URLExtraData(baseURI, mCachedReferrerInfo, principal);
   }
   return mCachedURLData;
 }
 
 void Document::SetDocumentCharacterSet(NotNull<const Encoding*> aEncoding) {
   if (mCharacterSet != aEncoding) {
     mCharacterSet = aEncoding;
     mEncodingMenuDisabled = aEncoding == UTF_8_ENCODING;
@@ -8522,27 +8519,28 @@ void Document::TryCancelFrameLoaderIniti
 }
 
 void Document::SetPrototypeDocument(nsXULPrototypeDocument* aPrototype) {
   mPrototypeDocument = aPrototype;
   mSynchronousDOMContentLoaded = true;
 }
 
 Document* Document::RequestExternalResource(
-    nsIURI* aURI, nsIURI* aReferrer, uint32_t aReferrerPolicy,
-    nsINode* aRequestingNode, ExternalResourceLoad** aPendingLoad) {
+    nsIURI* aURI, nsIReferrerInfo* aReferrerInfo, nsINode* aRequestingNode,
+    ExternalResourceLoad** aPendingLoad) {
   MOZ_ASSERT(aURI, "Must have a URI");
   MOZ_ASSERT(aRequestingNode, "Must have a node");
+  MOZ_ASSERT(aReferrerInfo, "Must have a referrerInfo");
   if (mDisplayDocument) {
     return mDisplayDocument->RequestExternalResource(
-        aURI, aReferrer, aReferrerPolicy, aRequestingNode, aPendingLoad);
+        aURI, aReferrerInfo, aRequestingNode, aPendingLoad);
   }
 
   return mExternalResourceMap.RequestResource(
-      aURI, aReferrer, aReferrerPolicy, aRequestingNode, this, aPendingLoad);
+      aURI, aReferrerInfo, aRequestingNode, this, aPendingLoad);
 }
 
 void Document::EnumerateExternalResources(SubDocEnumFunc aCallback,
                                           void* aData) {
   mExternalResourceMap.EnumerateResources(aCallback, aData);
 }
 
 SMILAnimationController* Document::GetAnimationController() {
@@ -11331,22 +11329,23 @@ void Document::MaybePreLoadImage(
   nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL |
                           nsContentUtils::CORSModeToLoadImageFlags(
                               Element::StringToCORSMode(aCrossOriginAttr));
 
   nsContentPolicyType policyType =
       aIsImgSet ? nsIContentPolicy::TYPE_IMAGESET
                 : nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD;
 
+  nsCOMPtr<nsIReferrerInfo> referrerInfo =
+      ReferrerInfo::CreateFromDocumentAndPolicyOverride(this, aReferrerPolicy);
+
   // Image not in cache - trigger preload
   RefPtr<imgRequestProxy> request;
   nsresult rv = nsContentUtils::LoadImage(
-      uri, static_cast<nsINode*>(this), this, NodePrincipal(), 0,
-      GetDocumentURIAsReferrer(),  // uri of document used as referrer
-      aReferrerPolicy,
+      uri, static_cast<nsINode*>(this), this, NodePrincipal(), 0, referrerInfo,
       nullptr,  // no observer
       loadFlags, NS_LITERAL_STRING("img"), getter_AddRefs(request), policyType);
 
   // Pin image-reference to avoid evicting it from the img-cache before
   // the "real" load occurs. Unpinned in DispatchContentLoadedEvents and
   // unlink
   if (NS_SUCCEEDED(rv)) {
     mPreloadingImages.Put(uri, request.forget());
@@ -11457,20 +11456,23 @@ NS_IMPL_ISUPPORTS(StubCSSLoaderObserver,
 
 void Document::PreloadStyle(
     nsIURI* uri, const Encoding* aEncoding, const nsAString& aCrossOriginAttr,
     const enum mozilla::net::ReferrerPolicy aReferrerPolicy,
     const nsAString& aIntegrity) {
   // The CSSLoader will retain this object after we return.
   nsCOMPtr<nsICSSLoaderObserver> obs = new StubCSSLoaderObserver();
 
+  nsCOMPtr<nsIReferrerInfo> referrerInfo =
+      ReferrerInfo::CreateFromDocumentAndPolicyOverride(this, aReferrerPolicy);
+
   // Charset names are always ASCII.
-  CSSLoader()->LoadSheet(uri, true, NodePrincipal(), aEncoding, obs,
-                         Element::StringToCORSMode(aCrossOriginAttr),
-                         aReferrerPolicy, aIntegrity);
+  CSSLoader()->LoadSheet(uri, true, NodePrincipal(), aEncoding, referrerInfo,
+                         obs, Element::StringToCORSMode(aCrossOriginAttr),
+                         aIntegrity);
 }
 
 RefPtr<StyleSheet> Document::LoadChromeSheetSync(nsIURI* uri) {
   RefPtr<StyleSheet> sheet;
   CSSLoader()->LoadSheetSync(uri, css::eAuthorSheetFeatures, false, &sheet);
   return sheet;
 }
 
--- a/dom/base/Document.h
+++ b/dom/base/Document.h
@@ -315,18 +315,18 @@ class ExternalResourceMap {
   };
 
   ExternalResourceMap();
 
   /**
    * Request an external resource document.  This does exactly what
    * Document::RequestExternalResource is documented to do.
    */
-  Document* RequestResource(nsIURI* aURI, nsIURI* aReferrer,
-                            uint32_t aReferrerPolicy, nsINode* aRequestingNode,
+  Document* RequestResource(nsIURI* aURI, nsIReferrerInfo* aReferrerInfo,
+                            nsINode* aRequestingNode,
                             Document* aDisplayDocument,
                             ExternalResourceLoad** aPendingLoad);
 
   /**
    * Enumerate the resource documents.  See
    * Document::EnumerateExternalResources.
    */
   void EnumerateResources(SubDocEnumFunc aCallback, void* aData);
@@ -373,18 +373,18 @@ class ExternalResourceMap {
     NS_DECL_ISUPPORTS
     NS_DECL_NSISTREAMLISTENER
     NS_DECL_NSIREQUESTOBSERVER
 
     /**
      * Start aURI loading.  This will perform the necessary security checks and
      * so forth.
      */
-    nsresult StartLoad(nsIURI* aURI, nsIURI* aReferrer,
-                       uint32_t aReferrerPolicy, nsINode* aRequestingNode);
+    nsresult StartLoad(nsIURI* aURI, nsIReferrerInfo* aReferrerInfo,
+                       nsINode* aRequestingNode);
     /**
      * Set up an nsIContentViewer based on aRequest.  This is guaranteed to
      * put null in *aViewer and *aLoadGroup on all failures.
      */
     nsresult SetupViewer(nsIRequest* aRequest, nsIContentViewer** aViewer,
                          nsILoadGroup** aLoadGroup);
 
    private:
@@ -2797,23 +2797,22 @@ class Document : public nsINode,
    * resource document if available.  If one is not available yet, it will
    * start loading as needed, and the pending load object will be returned in
    * aPendingLoad so that the caller can register an observer to wait for the
    * load.  If this function returns null and doesn't return a pending load,
    * that means that there is no resource document for this URI and won't be
    * one in the future.
    *
    * @param aURI the URI to get
-   * @param aReferrer the referrer of the request
-   * @param aReferrerPolicy the referrer policy of the request
+   * @param aReferrerInfo the referrerInfo of the request
    * @param aRequestingNode the node making the request
    * @param aPendingLoad the pending load for this request, if any
    */
-  Document* RequestExternalResource(nsIURI* aURI, nsIURI* aReferrer,
-                                    uint32_t aReferrerPolicy,
+  Document* RequestExternalResource(nsIURI* aURI,
+                                    nsIReferrerInfo* aReferrerInfo,
                                     nsINode* aRequestingNode,
                                     ExternalResourceLoad** aPendingLoad);
 
   /**
    * Enumerate the external resource documents associated with this document.
    * The enumerator callback should return true to continue enumerating, or
    * false to stop.  This callback will never get passed a null aDocument.
    */
@@ -4403,16 +4402,17 @@ class Document : public nsINode,
   nsCOMPtr<nsIURI> mDocumentBaseURI;
   nsCOMPtr<nsIURI> mChromeXHRDocBaseURI;
 
   // The base domain of the document for third-party checks.
   nsCString mBaseDomain;
 
   // A lazily-constructed URL data for style system to resolve URL value.
   RefPtr<URLExtraData> mCachedURLData;
+  nsCOMPtr<nsIReferrerInfo> mCachedReferrerInfo;
 
   nsWeakPtr mDocumentLoadGroup;
 
   bool mBlockAllMixedContent;
   bool mBlockAllMixedContentPreloads;
   bool mUpgradeInsecureRequests;
   bool mUpgradeInsecurePreloads;
 
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -352,19 +352,20 @@ already_AddRefed<URLExtraData> nsIConten
     nsIPrincipal* aSubjectPrincipal) const {
   if (SVGUseElement* use = GetContainingSVGUseShadowHost()) {
     if (URLExtraData* data = use->GetContentURLData()) {
       return do_AddRef(data);
     }
   }
   if (aSubjectPrincipal && aSubjectPrincipal != NodePrincipal()) {
     // TODO: Cache this?
-    return MakeAndAddRef<URLExtraData>(
-        OwnerDoc()->GetDocBaseURI(), OwnerDoc()->GetDocumentURI(),
-        aSubjectPrincipal, OwnerDoc()->GetReferrerPolicy());
+    nsCOMPtr<nsIReferrerInfo> referrerInfo =
+        ReferrerInfo::CreateForInternalCSSResources(OwnerDoc());
+    return MakeAndAddRef<URLExtraData>(OwnerDoc()->GetDocBaseURI(),
+                                       referrerInfo, aSubjectPrincipal);
   }
   // This also ignores the case that SVG inside XBL binding.
   // But it is probably fine.
   return do_AddRef(OwnerDoc()->DefaultStyleAttrURLData());
 }
 
 void nsIContent::ConstructUbiNode(void* storage) {
   JS::ubi::Concrete<nsIContent>::construct(storage, this);
--- a/dom/base/IDTracker.cpp
+++ b/dom/base/IDTracker.cpp
@@ -4,16 +4,17 @@
  * 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 "IDTracker.h"
 
 #include "mozilla/Encoding.h"
 #include "nsContentUtils.h"
 #include "nsIURI.h"
+#include "nsIReferrerInfo.h"
 #include "nsBindingManager.h"
 #include "nsEscape.h"
 #include "nsXBLPrototypeBinding.h"
 #include "nsCycleCollectionParticipant.h"
 
 namespace mozilla {
 namespace dom {
 
@@ -28,19 +29,18 @@ static DocumentOrShadowRoot* DocOrShadow
   if (shadow) {
     return shadow;
   }
 
   return aContent.OwnerDoc();
 }
 
 void IDTracker::ResetToURIFragmentID(nsIContent* aFromContent, nsIURI* aURI,
-                                     nsIURI* aReferrer,
-                                     uint32_t aReferrerPolicy, bool aWatch,
-                                     bool aReferenceImage) {
+                                     nsIReferrerInfo* aReferrerInfo,
+                                     bool aWatch, bool aReferenceImage) {
   MOZ_ASSERT(aFromContent,
              "ResetToURIFragmentID() expects non-null content pointer");
 
   Unlink();
 
   if (!aURI) return;
 
   nsAutoCString refPart;
@@ -107,18 +107,18 @@ void IDTracker::ResetToURIFragmentID(nsI
       }
     }
   }
 
   bool isEqualExceptRef;
   rv = aURI->EqualsExceptRef(doc->GetDocumentURI(), &isEqualExceptRef);
   if (NS_FAILED(rv) || !isEqualExceptRef) {
     RefPtr<Document::ExternalResourceLoad> load;
-    doc = doc->RequestExternalResource(aURI, aReferrer, aReferrerPolicy,
-                                       aFromContent, getter_AddRefs(load));
+    doc = doc->RequestExternalResource(aURI, aReferrerInfo, aFromContent,
+                                       getter_AddRefs(load));
     docOrShadow = doc;
     if (!doc) {
       if (!load || !aWatch) {
         // Nothing will ever happen here
         return;
       }
 
       DocumentLoadNotification* observer =
--- a/dom/base/IDTracker.h
+++ b/dom/base/IDTracker.h
@@ -10,16 +10,17 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ShadowRoot.h"
 #include "nsAtom.h"
 #include "mozilla/dom/Document.h"
 #include "nsThreadUtils.h"
 
 class nsIURI;
+class nsIReferrerInfo;
 
 namespace mozilla {
 namespace dom {
 
 /**
  * Class to track what element is referenced by a given ID.
  *
  * To use it, call one of the Reset methods to set it up to watch a given ID.
@@ -50,26 +51,25 @@ class IDTracker {
   Element* get() { return mElement; }
 
   /**
    * Set up the reference. This can be called multiple times to
    * change which reference is being tracked, but these changes
    * do not trigger ElementChanged.
    * @param aFrom the source element for context
    * @param aURI the URI containing a hash-reference to the element
-   * @param aReferrer the referrer URI for loading external resource
-   * @param aReferrerPolicy the referrer policy for loading external resource
+   * @param aReferrerInfo the referrerInfo for loading external resource
    * @param aWatch if false, then we do not set up the notifications to track
    * changes, so ElementChanged won't fire and get() will always return the same
    * value, the current element for the ID.
    * @param aReferenceImage whether the ID references image elements which are
    * subject to the document's mozSetImageElement overriding mechanism.
    */
-  void ResetToURIFragmentID(nsIContent* aFrom, nsIURI* aURI, nsIURI* aReferrer,
-                            uint32_t aReferrerPolicy, bool aWatch = true,
+  void ResetToURIFragmentID(nsIContent* aFrom, nsIURI* aURI,
+                            nsIReferrerInfo* aReferrerInfo, bool aWatch = true,
                             bool aReferenceImage = false);
 
   /**
    * A variation on ResetToURIFragmentID() to set up a reference that consists
    * of the ID of an element in the same document as aFrom.
    * @param aFrom the source element for context
    * @param aID the ID of the element
    * @param aWatch if false, then we do not set up the notifications to track
--- a/dom/base/nsAttrValue.cpp
+++ b/dom/base/nsAttrValue.cpp
@@ -1618,18 +1618,20 @@ bool nsAttrValue::ParseStyleAttribute(co
     if (cont) {
       // Set our MiscContainer to the cached one.
       NS_ADDREF(cont);
       SetPtrValueAndType(cont, eOtherBase);
       return true;
     }
   }
 
-  RefPtr<URLExtraData> data = new URLExtraData(baseURI, docURI, principal,
-                                               ownerDoc->GetReferrerPolicy());
+  nsCOMPtr<nsIReferrerInfo> referrerInfo =
+      ReferrerInfo::CreateForInternalCSSResources(ownerDoc);
+  RefPtr<URLExtraData> data =
+      new URLExtraData(baseURI, referrerInfo, principal);
   RefPtr<DeclarationBlock> decl = DeclarationBlock::FromCssText(
       aString, data, ownerDoc->GetCompatibilityMode(), ownerDoc->CSSLoader());
   if (!decl) {
     return false;
   }
   decl->SetHTMLCSSStyleSheet(sheet);
   SetTo(decl.forget(), &aString);
 
--- a/dom/base/nsContentSink.cpp
+++ b/dom/base/nsContentSink.cpp
@@ -743,22 +743,29 @@ nsresult nsContentSink::ProcessStyleLink
   nsresult rv = NS_NewURI(getter_AddRefs(url), aHref, nullptr,
                           mDocument->GetDocBaseURI());
 
   if (NS_FAILED(rv)) {
     // The URI is bad, move along, don't propagate the error (for now)
     return NS_OK;
   }
 
+  // Link header is working like a <link> node, so referrerPolicy attr should
+  // have higher priority than referrer policy from document.
+  net::ReferrerPolicy policy =
+      net::AttributeReferrerPolicyFromString(aReferrerPolicy);
+  nsCOMPtr<nsIReferrerInfo> referrerInfo =
+      ReferrerInfo::CreateFromDocumentAndPolicyOverride(mDocument, policy);
+
   Loader::SheetInfo info{
       *mDocument,
       nullptr,
       url.forget(),
       nullptr,
-      net::AttributeReferrerPolicyFromString(aReferrerPolicy),
+      referrerInfo.forget(),
       CORS_NONE,
       aTitle,
       aMedia,
       aAlternate ? Loader::HasAlternateRel::Yes : Loader::HasAlternateRel::No,
       Loader::IsInline::No,
       Loader::IsExplicitlyEnabled::No,
   };
 
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -3362,20 +3362,20 @@ int32_t nsContentUtils::CORSModeToLoadIm
       return 0;
   }
 }
 
 // static
 nsresult nsContentUtils::LoadImage(
     nsIURI* aURI, nsINode* aContext, Document* aLoadingDocument,
     nsIPrincipal* aLoadingPrincipal, uint64_t aRequestContextID,
-    nsIURI* aReferrer, net::ReferrerPolicy aReferrerPolicy,
-    imgINotificationObserver* aObserver, int32_t aLoadFlags,
-    const nsAString& initiatorType, imgRequestProxy** aRequest,
-    uint32_t aContentPolicyType, bool aUseUrgentStartForChannel) {
+    nsIReferrerInfo* aReferrerInfo, imgINotificationObserver* aObserver,
+    int32_t aLoadFlags, const nsAString& initiatorType,
+    imgRequestProxy** aRequest, uint32_t aContentPolicyType,
+    bool aUseUrgentStartForChannel) {
   MOZ_ASSERT(aURI, "Must have a URI");
   MOZ_ASSERT(aContext, "Must have a context");
   MOZ_ASSERT(aLoadingDocument, "Must have a document");
   MOZ_ASSERT(aLoadingPrincipal, "Must have a principal");
   MOZ_ASSERT(aRequest, "Null out param");
 
   imgLoader* imgLoader = GetImgLoaderForDocument(aLoadingDocument);
   if (!imgLoader) {
@@ -3387,20 +3387,23 @@ nsresult nsContentUtils::LoadImage(
 
   nsIURI* documentURI = aLoadingDocument->GetDocumentURI();
 
   NS_ASSERTION(loadGroup || IsFontTableURI(documentURI),
                "Could not get loadgroup; onload may fire too early");
 
   // XXXbz using "documentURI" for the initialDocumentURI is not quite
   // right, but the best we can do here...
+  nsCOMPtr<nsIURI> referrer = aReferrerInfo->GetOriginalReferrer();
+  auto referrerPolicy = static_cast<mozilla::net::ReferrerPolicy>(
+      aReferrerInfo->GetReferrerPolicy());
   return imgLoader->LoadImage(aURI,               /* uri to load */
                               documentURI,        /* initialDocumentURI */
-                              aReferrer,          /* referrer */
-                              aReferrerPolicy,    /* referrer policy */
+                              referrer,           /* referrerInfo */
+                              referrerPolicy,     /* referrer policy */
                               aLoadingPrincipal,  /* loading principal */
                               aRequestContextID,  /* request context ID */
                               loadGroup,          /* loadgroup */
                               aObserver,          /* imgINotificationObserver */
                               aContext,           /* loading context */
                               aLoadingDocument,   /* uniquification key */
                               aLoadFlags,         /* load flags */
                               nullptr,            /* cache key */
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -104,16 +104,17 @@ class nsStringHashKey;
 class nsTextFragment;
 class nsView;
 class nsViewportInfo;
 class nsWrapperCache;
 class nsAttrValue;
 class nsITransferable;
 class nsPIWindowRoot;
 class nsIWindowProvider;
+class nsIReferrerInfo;
 
 struct JSRuntime;
 
 template <class E>
 class nsCOMArray;
 template <class K, class V>
 class nsDataHashtable;
 template <class K, class V>
@@ -862,33 +863,31 @@ class nsContentUtils {
    * This method will attempt to make aURI immutable; a caller that wants to
    * keep a mutable version around should pass in a clone.
    *
    * @param aURI uri of the image to be loaded
    * @param aContext element of document where the result of this request
    *                 will be used.
    * @param aLoadingDocument the document we belong to
    * @param aLoadingPrincipal the principal doing the load
-   * @param aReferrer the referrer URI
-   * @param aReferrerPolicy the referrer-sending policy to use on channel
-   *         creation
+   * @param aReferrerInfo the referrerInfo use on channel creation
    * @param aObserver the observer for the image load
    * @param aLoadFlags the load flags to use.  See nsIRequest
    * @param [aContentPolicyType=nsIContentPolicy::TYPE_INTERNAL_IMAGE]
    * (Optional) The CP content type to use
    * @param aUseUrgentStartForChannel,(Optional) a flag to mark on channel if it
    *        is triggered by user input events.
    * @return the imgIRequest for the image load
    */
   static nsresult LoadImage(
       nsIURI* aURI, nsINode* aContext, Document* aLoadingDocument,
       nsIPrincipal* aLoadingPrincipal, uint64_t aRequestContextID,
-      nsIURI* aReferrer, mozilla::net::ReferrerPolicy aReferrerPolicy,
-      imgINotificationObserver* aObserver, int32_t aLoadFlags,
-      const nsAString& initiatorType, imgRequestProxy** aRequest,
+      nsIReferrerInfo* aReferrerInfo, imgINotificationObserver* aObserver,
+      int32_t aLoadFlags, const nsAString& initiatorType,
+      imgRequestProxy** aRequest,
       uint32_t aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE,
       bool aUseUrgentStartForChannel = false);
 
   /**
    * Obtain an image loader that respects the given document/channel's privacy
    * status. Null document/channel arguments return the public image loader.
    */
   static imgLoader* GetImgLoaderForDocument(Document* aDoc);
--- a/dom/base/nsIStyleSheetLinkingElement.h
+++ b/dom/base/nsIStyleSheetLinkingElement.h
@@ -88,32 +88,33 @@ class nsIStyleSheetLinkingElement : publ
   struct MOZ_STACK_CLASS SheetInfo {
     nsIContent* mContent;
     // FIXME(emilio): do these really need to be strong refs?
     nsCOMPtr<nsIURI> mURI;
 
     // The principal of the scripted caller that initiated the load, if
     // available. Otherwise null.
     nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
-    mozilla::net::ReferrerPolicy mReferrerPolicy;
+    nsCOMPtr<nsIReferrerInfo> mReferrerInfo;
     mozilla::CORSMode mCORSMode;
     nsString mTitle;
     nsString mMedia;
     nsString mIntegrity;
 
     bool mHasAlternateRel;
     bool mIsInline;
     IsExplicitlyEnabled mIsExplicitlyEnabled;
 
     SheetInfo(const mozilla::dom::Document&, nsIContent*,
               already_AddRefed<nsIURI> aURI,
               already_AddRefed<nsIPrincipal> aTriggeringPrincipal,
-              mozilla::net::ReferrerPolicy aReferrerPolicy, mozilla::CORSMode,
-              const nsAString& aTitle, const nsAString& aMedia, HasAlternateRel,
-              IsInline, IsExplicitlyEnabled);
+              already_AddRefed<nsIReferrerInfo> aReferrerInfo,
+              mozilla::CORSMode, const nsAString& aTitle,
+              const nsAString& aMedia, HasAlternateRel, IsInline,
+              IsExplicitlyEnabled);
 
     ~SheetInfo();
   };
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISTYLESHEETLINKINGELEMENT_IID)
 
   /**
    * Used to make the association between a style sheet and
--- a/dom/base/nsImageLoadingContent.cpp
+++ b/dom/base/nsImageLoadingContent.cpp
@@ -1162,20 +1162,18 @@ nsresult nsImageLoadingContent::LoadImag
              : PolicyTypeForLoad(aImageLoadType);
 
   nsCOMPtr<nsINode> thisNode =
       do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
   nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo();
   referrerInfo->InitWithNode(thisNode);
   nsCOMPtr<nsIURI> referrer = referrerInfo->GetOriginalReferrer();
   nsresult rv = nsContentUtils::LoadImage(
-      aNewURI, thisNode, aDocument, triggeringPrincipal, 0, referrer,
-      static_cast<mozilla::net::ReferrerPolicy>(
-          referrerInfo->GetReferrerPolicy()),
-      this, loadFlags, content->LocalName(), getter_AddRefs(req), policyType,
+      aNewURI, thisNode, aDocument, triggeringPrincipal, 0, referrerInfo, this,
+      loadFlags, content->LocalName(), getter_AddRefs(req), policyType,
       mUseUrgentStartForChannel);
 
   // Reset the flag to avoid loading from XPCOM or somewhere again else without
   // initiated by user interaction.
   mUseUrgentStartForChannel = false;
 
   // Tell the document to forget about the image preload, if any, for
   // this URI, now that we might have another imgRequestProxy for it.
--- a/dom/base/nsStyleLinkElement.cpp
+++ b/dom/base/nsStyleLinkElement.cpp
@@ -33,36 +33,33 @@
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 nsStyleLinkElement::SheetInfo::SheetInfo(
     const Document& aDocument, nsIContent* aContent,
     already_AddRefed<nsIURI> aURI,
     already_AddRefed<nsIPrincipal> aTriggeringPrincipal,
-    mozilla::net::ReferrerPolicy aReferrerPolicy, mozilla::CORSMode aCORSMode,
-    const nsAString& aTitle, const nsAString& aMedia,
-    HasAlternateRel aHasAlternateRel, IsInline aIsInline,
-    IsExplicitlyEnabled aIsExplicitlyEnabled)
+    already_AddRefed<nsIReferrerInfo> aReferrerInfo,
+    mozilla::CORSMode aCORSMode, const nsAString& aTitle,
+    const nsAString& aMedia, HasAlternateRel aHasAlternateRel,
+    IsInline aIsInline, IsExplicitlyEnabled aIsExplicitlyEnabled)
     : mContent(aContent),
       mURI(aURI),
       mTriggeringPrincipal(aTriggeringPrincipal),
-      mReferrerPolicy(aReferrerPolicy),
+      mReferrerInfo(aReferrerInfo),
       mCORSMode(aCORSMode),
       mTitle(aTitle),
       mMedia(aMedia),
       mHasAlternateRel(aHasAlternateRel == HasAlternateRel::Yes),
       mIsInline(aIsInline == IsInline::Yes),
       mIsExplicitlyEnabled(aIsExplicitlyEnabled) {
   MOZ_ASSERT(!mIsInline || aContent);
   MOZ_ASSERT_IF(aContent, aContent->OwnerDoc() == &aDocument);
-
-  if (mReferrerPolicy == net::ReferrerPolicy::RP_Unset) {
-    mReferrerPolicy = aDocument.GetReferrerPolicy();
-  }
+  MOZ_ASSERT(mReferrerInfo);
 
   if (!mIsInline && aContent && aContent->IsElement()) {
     aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::integrity,
                                    mIntegrity);
   }
 }
 
 nsStyleLinkElement::SheetInfo::~SheetInfo() = default;
@@ -306,18 +303,16 @@ nsStyleLinkElement::DoUpdateStyleSheet(D
 
     nsStyleLinkElement::SetStyleSheet(nullptr);
   }
 
   if (!info) {
     return Update{};
   }
 
-  MOZ_ASSERT(info->mReferrerPolicy != net::RP_Unset ||
-             info->mReferrerPolicy == doc->GetReferrerPolicy());
   if (!info->mURI && !info->mIsInline) {
     // If href is empty and this is not inline style then just bail
     return Update{};
   }
 
   if (info->mIsInline) {
     nsAutoString text;
     if (!nsContentUtils::GetNodeTextContent(thisContent, false, text,
--- a/dom/base/nsStyleLinkElement.h
+++ b/dom/base/nsStyleLinkElement.h
@@ -12,17 +12,16 @@
 
 #ifndef nsStyleLinkElement_h___
 #define nsStyleLinkElement_h___
 
 #include "mozilla/Attributes.h"
 #include "mozilla/CORSMode.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/Unused.h"
-#include "mozilla/net/ReferrerPolicy.h"
 #include "nsCOMPtr.h"
 #include "nsIStyleSheetLinkingElement.h"
 #include "nsTArray.h"
 
 class nsIURI;
 
 namespace mozilla {
 class CSSStyleSheet;
--- a/dom/base/nsTreeSanitizer.cpp
+++ b/dom/base/nsTreeSanitizer.cpp
@@ -1071,29 +1071,33 @@ bool nsTreeSanitizer::SanitizeStyleSheet
                                          Document* aDocument,
                                          nsIURI* aBaseURI) {
   nsresult rv = NS_OK;
   aSanitized.Truncate();
   // aSanitized will hold the permitted CSS text.
   // -moz-binding is blacklisted.
   bool didSanitize = false;
   // Create a sheet to hold the parsed CSS
-  RefPtr<StyleSheet> sheet =
-      new StyleSheet(mozilla::css::eAuthorSheetFeatures, CORS_NONE,
-                     aDocument->GetReferrerPolicy(), SRIMetadata());
+  RefPtr<StyleSheet> sheet = new StyleSheet(mozilla::css::eAuthorSheetFeatures,
+                                            CORS_NONE, SRIMetadata());
   sheet->SetURIs(aDocument->GetDocumentURI(), nullptr, aBaseURI);
   sheet->SetPrincipal(aDocument->NodePrincipal());
   sheet->ParseSheetSync(aDocument->CSSLoader(),
                         NS_ConvertUTF16toUTF8(aOriginal),
                         /* aLoadData = */ nullptr,
                         /* aLineNumber = */ 0);
   NS_ENSURE_SUCCESS(rv, true);
   // Mark the sheet as complete.
   MOZ_ASSERT(!sheet->HasForcedUniqueInner(),
              "should not get a forced unique inner during parsing");
+
+  // This should be an inline stylesheet
+  nsCOMPtr<nsIReferrerInfo> referrerInfo =
+      ReferrerInfo::CreateForInternalCSSResources(aDocument);
+  sheet->SetReferrerInfo(referrerInfo);
   sheet->SetComplete();
   // Loop through all the rules found in the CSS text
   ErrorResult err;
   RefPtr<dom::CSSRuleList> rules =
       sheet->GetCssRules(*nsContentUtils::GetSystemPrincipal(), err);
   err.SuppressException();
   if (!rules) {
     return true;
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -2177,19 +2177,21 @@ void CanvasRenderingContext2D::SetShadow
 
 //
 // filters
 //
 
 static already_AddRefed<RawServoDeclarationBlock> CreateDeclarationForServo(
     nsCSSPropertyID aProperty, const nsAString& aPropertyValue,
     Document* aDocument) {
+  nsCOMPtr<nsIReferrerInfo> referrerInfo =
+      ReferrerInfo::CreateForInternalCSSResources(aDocument);
+
   RefPtr<URLExtraData> data = new URLExtraData(
-      aDocument->GetDocBaseURI(), aDocument->GetDocumentURI(),
-      aDocument->NodePrincipal(), aDocument->GetReferrerPolicy());
+      aDocument->GetDocBaseURI(), referrerInfo, aDocument->NodePrincipal());
 
   ServoCSSParser::ParsingEnvironment env(
       data, aDocument->GetCompatibilityMode(), aDocument->CSSLoader());
   RefPtr<RawServoDeclarationBlock> servoDeclarations =
       ServoCSSParser::ParseProperty(aProperty, aPropertyValue, env);
 
   if (!servoDeclarations) {
     // We got a syntax error.  The spec says this value must be ignored.
--- a/dom/html/HTMLLinkElement.cpp
+++ b/dom/html/HTMLLinkElement.cpp
@@ -448,22 +448,24 @@ Maybe<nsStyleLinkElement::SheetInfo> HTM
   nsAutoString href;
   GetAttr(kNameSpaceID_None, nsGkAtoms::href, href);
   if (href.IsEmpty()) {
     return Nothing();
   }
 
   nsCOMPtr<nsIURI> uri = Link::GetURI();
   nsCOMPtr<nsIPrincipal> prin = mTriggeringPrincipal;
+  nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo();
+  referrerInfo->InitWithNode(this);
   return Some(SheetInfo{
       *OwnerDoc(),
       this,
       uri.forget(),
       prin.forget(),
-      GetReferrerPolicyAsEnum(),
+      referrerInfo.forget(),
       GetCORSMode(),
       title,
       media,
       alternate ? HasAlternateRel::Yes : HasAlternateRel::No,
       IsInline::No,
       mExplicitlyEnabled ? IsExplicitlyEnabled::Yes : IsExplicitlyEnabled::No,
   });
 }
--- a/dom/html/HTMLStyleElement.cpp
+++ b/dom/html/HTMLStyleElement.cpp
@@ -167,23 +167,25 @@ Maybe<nsStyleLinkElement::SheetInfo> HTM
   if (!IsCSSMimeTypeAttribute(*this)) {
     return Nothing();
   }
 
   nsAutoString title;
   nsAutoString media;
   GetTitleAndMediaForElement(*this, title, media);
 
+  nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo();
+  referrerInfo->InitWithNode(this);
   nsCOMPtr<nsIPrincipal> prin = mTriggeringPrincipal;
   return Some(SheetInfo{
       *OwnerDoc(),
       this,
       nullptr,
       prin.forget(),
-      net::ReferrerPolicy::RP_Unset,
+      referrerInfo.forget(),
       CORS_NONE,
       title,
       media,
       HasAlternateRel::No,
       IsInline::Yes,
       IsExplicitlyEnabled::No,
   });
 }
--- a/dom/security/ReferrerInfo.cpp
+++ b/dom/security/ReferrerInfo.cpp
@@ -924,17 +924,17 @@ already_AddRefed<nsIReferrerInfo> Referr
 
 void ReferrerInfo::GetReferrerPolicyFromAtribute(nsINode* aNode,
                                                  uint32_t& aPolicy) const {
   aPolicy = mozilla::net::RP_Unset;
   mozilla::dom::Element* element = aNode->AsElement();
 
   if (!element->IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area,
                                     nsGkAtoms::script, nsGkAtoms::iframe,
-                                    nsGkAtoms::img)) {
+                                    nsGkAtoms::link, nsGkAtoms::img)) {
     return;
   }
 
   aPolicy = element->GetReferrerPolicyAsEnum();
 }
 
 bool ReferrerInfo::HasRelNoReferrer(nsINode* aNode) const {
   mozilla::dom::Element* element = aNode->AsElement();
--- a/dom/svg/SVGAnimationElement.cpp
+++ b/dom/svg/SVGAnimationElement.cpp
@@ -8,16 +8,17 @@
 #include "mozilla/dom/SVGSVGElement.h"
 #include "mozilla/dom/BindContext.h"
 #include "mozilla/dom/ElementInlines.h"
 #include "mozilla/SMILAnimationController.h"
 #include "mozilla/SMILAnimationFunction.h"
 #include "mozilla/SMILTimeContainer.h"
 #include "nsContentUtils.h"
 #include "nsIContentInlines.h"
+#include "nsIReferrerInfo.h"
 #include "nsIURI.h"
 #include "prtime.h"
 
 namespace mozilla {
 namespace dom {
 
 //----------------------------------------------------------------------
 // nsISupports methods
@@ -353,20 +354,20 @@ void SVGAnimationElement::EndElementAt(f
 bool SVGAnimationElement::IsEventAttributeNameInternal(nsAtom* aName) {
   return nsContentUtils::IsEventAttributeName(aName, EventNameType_SMIL);
 }
 
 void SVGAnimationElement::UpdateHrefTarget(const nsAString& aHrefStr) {
   nsCOMPtr<nsIURI> targetURI;
   nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI), aHrefStr,
                                             OwnerDoc(), GetBaseURI());
-  // Bug 1415044 to investigate which referrer we should use
-  mHrefTarget.ResetToURIFragmentID(this, targetURI,
-                                   OwnerDoc()->GetDocumentURI(),
-                                   OwnerDoc()->GetReferrerPolicy());
+  nsCOMPtr<nsIReferrerInfo> referrerInfo =
+      ReferrerInfo::CreateForSVGResources(OwnerDoc());
+
+  mHrefTarget.ResetToURIFragmentID(this, targetURI, referrerInfo);
   AnimationTargetChanged();
 }
 
 void SVGAnimationElement::AnimationTargetChanged() {
   mTimedElement.HandleTargetElementChange(GetTargetElementContent());
   AnimationNeedsResample();
 }
 
--- a/dom/svg/SVGElement.cpp
+++ b/dom/svg/SVGElement.cpp
@@ -1058,17 +1058,17 @@ bool SVGElement::UpdateDeclarationBlockF
 
 //------------------------------------------------------------------------
 // Helper class: MappedAttrParser, for parsing values of mapped attributes
 
 namespace {
 
 class MOZ_STACK_CLASS MappedAttrParser {
  public:
-  MappedAttrParser(css::Loader* aLoader, nsIURI* aDocURI, nsIURI* aBaseURI,
+  MappedAttrParser(css::Loader* aLoader, nsIURI* aBaseURI,
                    SVGElement* aElement);
   ~MappedAttrParser();
 
   // Parses a mapped attribute value.
   void ParseMappedAttrValue(nsAtom* aMappedAttrName,
                             const nsAString& aMappedAttrValue);
 
   void TellStyleAlreadyParsedResult(nsAtom const* aAtom,
@@ -1079,33 +1079,28 @@ class MOZ_STACK_CLASS MappedAttrParser {
   // values. Otherwise, this method returns null.
   already_AddRefed<DeclarationBlock> GetDeclarationBlock();
 
  private:
   // MEMBER DATA
   // -----------
   css::Loader* mLoader;
 
-  // Arguments for nsCSSParser::ParseProperty
-  nsIURI* mDocURI;
   nsCOMPtr<nsIURI> mBaseURI;
 
   // Declaration for storing parsed values (lazily initialized)
   RefPtr<DeclarationBlock> mDecl;
 
   // For reporting use counters
   SVGElement* mElement;
 };
 
-MappedAttrParser::MappedAttrParser(css::Loader* aLoader, nsIURI* aDocURI,
-                                   nsIURI* aBaseURI, SVGElement* aElement)
-    : mLoader(aLoader),
-      mDocURI(aDocURI),
-      mBaseURI(aBaseURI),
-      mElement(aElement) {}
+MappedAttrParser::MappedAttrParser(css::Loader* aLoader, nsIURI* aBaseURI,
+                                   SVGElement* aElement)
+    : mLoader(aLoader), mBaseURI(aBaseURI), mElement(aElement) {}
 
 MappedAttrParser::~MappedAttrParser() {
   MOZ_ASSERT(!mDecl,
              "If mDecl was initialized, it should have been returned via "
              "GetDeclarationBlock (and had its pointer cleared)");
 }
 
 void MappedAttrParser::ParseMappedAttrValue(nsAtom* aMappedAttrName,
@@ -1117,19 +1112,21 @@ void MappedAttrParser::ParseMappedAttrVa
   // Get the nsCSSPropertyID ID for our mapped attribute.
   nsCSSPropertyID propertyID =
       nsCSSProps::LookupProperty(nsDependentAtomString(aMappedAttrName));
   if (propertyID != eCSSProperty_UNKNOWN) {
     bool changed = false;  // outparam for ParseProperty.
     NS_ConvertUTF16toUTF8 value(aMappedAttrValue);
     // FIXME (bug 1343964): Figure out a better solution for sending the base
     // uri to servo
+    nsCOMPtr<nsIReferrerInfo> referrerInfo =
+        ReferrerInfo::CreateForSVGResources(mElement->OwnerDoc());
+
     RefPtr<URLExtraData> data =
-        new URLExtraData(mBaseURI, mDocURI, mElement->NodePrincipal(),
-                         mElement->OwnerDoc()->GetReferrerPolicy());
+        new URLExtraData(mBaseURI, referrerInfo, mElement->NodePrincipal());
     changed = Servo_DeclarationBlock_SetPropertyById(
         mDecl->Raw(), propertyID, &value, false, data,
         ParsingMode::AllowUnitlessLength,
         mElement->OwnerDoc()->GetCompatibilityMode(), mLoader, {});
 
     if (changed) {
       // The normal reporting of use counters by the nsCSSParser won't happen
       // since it doesn't have a sheet.
@@ -1187,18 +1184,17 @@ void SVGElement::UpdateContentDeclaratio
 
   uint32_t attrCount = mAttrs.AttrCount();
   if (!attrCount) {
     // nothing to do
     return;
   }
 
   Document* doc = OwnerDoc();
-  MappedAttrParser mappedAttrParser(doc->CSSLoader(), doc->GetDocumentURI(),
-                                    GetBaseURI(), this);
+  MappedAttrParser mappedAttrParser(doc->CSSLoader(), GetBaseURI(), this);
 
   bool lengthAffectsStyle =
       SVGGeometryProperty::ElementMapsLengthsToStyle(this);
 
   for (uint32_t i = 0; i < attrCount; ++i) {
     const nsAttrName* attrName = mAttrs.AttrNameAt(i);
     if (!attrName->IsAtom() || !IsAttributeMapped(attrName->Atom())) continue;
 
--- a/dom/svg/SVGMPathElement.cpp
+++ b/dom/svg/SVGMPathElement.cpp
@@ -6,16 +6,17 @@
 
 #include "mozilla/dom/SVGMPathElement.h"
 
 #include "nsDebug.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/dom/SVGAnimateMotionElement.h"
 #include "mozilla/dom/SVGPathElement.h"
 #include "nsContentUtils.h"
+#include "nsIReferrerInfo.h"
 #include "mozilla/dom/SVGMPathElementBinding.h"
 #include "nsIURI.h"
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(MPath)
 
 namespace mozilla {
 namespace dom {
 
@@ -198,20 +199,20 @@ void SVGMPathElement::UpdateHrefTarget(n
   if (mPathTracker.get()) {
     mPathTracker.get()->RemoveMutationObserver(this);
   }
 
   if (aParent) {
     // Pass in |aParent| instead of |this| -- first argument is only used
     // for a call to GetComposedDoc(), and |this| might not have a current
     // document yet (if our caller is BindToTree).
-    // Bug 1415044 to investigate which referrer we should use
-    mPathTracker.ResetToURIFragmentID(aParent, targetURI,
-                                      OwnerDoc()->GetDocumentURI(),
-                                      OwnerDoc()->GetReferrerPolicy());
+    nsCOMPtr<nsIReferrerInfo> referrerInfo =
+        ReferrerInfo::CreateForSVGResources(OwnerDoc());
+
+    mPathTracker.ResetToURIFragmentID(aParent, targetURI, referrerInfo);
   } else {
     // if we don't have a parent, then there's no animateMotion element
     // depending on our target, so there's no point tracking it right now.
     mPathTracker.Unlink();
   }
 
   // Start observing new target (if any)
   if (mPathTracker.get()) {
--- a/dom/svg/SVGStyleElement.cpp
+++ b/dom/svg/SVGStyleElement.cpp
@@ -174,27 +174,29 @@ void SVGStyleElement::SetTitle(const nsA
 Maybe<nsStyleLinkElement::SheetInfo> SVGStyleElement::GetStyleSheetInfo() {
   if (!IsCSSMimeTypeAttribute(*this)) {
     return Nothing();
   }
 
   nsAutoString title;
   nsAutoString media;
   GetTitleAndMediaForElement(*this, title, media);
+  nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo();
+  referrerInfo->InitWithNode(this);
 
   return Some(SheetInfo{
       *OwnerDoc(),
       this,
       nullptr,
       // FIXME(bug 1459822): Why doesn't this need a principal, but
       // HTMLStyleElement does?
       nullptr,
-      net::ReferrerPolicy::RP_Unset,
       // FIXME(bug 1459822): Why does this need a crossorigin attribute, but
       // HTMLStyleElement doesn't?
+      referrerInfo.forget(),
       AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin)),
       title,
       media,
       HasAlternateRel::No,
       IsInline::Yes,
       IsExplicitlyEnabled::No,
   });
 }
--- a/dom/svg/SVGUseElement.cpp
+++ b/dom/svg/SVGUseElement.cpp
@@ -331,21 +331,23 @@ void SVGUseElement::UpdateShadowTree() {
     auto* newSVGElement = static_cast<SVGElement*>(newElement.get());
     if (mLengthAttributes[ATTR_WIDTH].IsExplicitlySet())
       newSVGElement->SetLength(nsGkAtoms::width, mLengthAttributes[ATTR_WIDTH]);
     if (mLengthAttributes[ATTR_HEIGHT].IsExplicitlySet())
       newSVGElement->SetLength(nsGkAtoms::height,
                                mLengthAttributes[ATTR_HEIGHT]);
   }
 
-  // The specs do not say which referrer policy we should use, pass RP_Unset for
-  // now
-  mContentURLData = new URLExtraData(
-      baseURI.forget(), do_AddRef(OwnerDoc()->GetDocumentURI()),
-      do_AddRef(NodePrincipal()), mozilla::net::RP_Unset);
+  // Bug 1415044 the specs do not say which referrer information we should use.
+  // This may change if there's any spec comes out.
+  nsCOMPtr<nsIReferrerInfo> referrerInfo = new mozilla::dom::ReferrerInfo();
+  referrerInfo->InitWithNode(this);
+
+  mContentURLData = new URLExtraData(baseURI.forget(), referrerInfo.forget(),
+                                     do_AddRef(NodePrincipal()));
 
   targetElement->AddMutationObserver(this);
 }
 
 nsIURI* SVGUseElement::GetSourceDocURI() {
   nsIContent* targetElement = mReferencedElementTracker.get();
   if (!targetElement) {
     return nullptr;
@@ -417,20 +419,20 @@ void SVGUseElement::LookupHref() {
   nsCOMPtr<nsIURI> baseURI =
       nsContentUtils::IsLocalRefURL(href)
           ? SVGObserverUtils::GetBaseURLForLocalRef(this, originURI)
           : originURI;
 
   nsCOMPtr<nsIURI> targetURI;
   nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI), href,
                                             GetComposedDoc(), baseURI);
-  // Bug 1415044 to investigate which referrer we should use
-  mReferencedElementTracker.ResetToURIFragmentID(
-      this, targetURI, OwnerDoc()->GetDocumentURI(),
-      OwnerDoc()->GetReferrerPolicy());
+  nsCOMPtr<nsIReferrerInfo> referrerInfo =
+      ReferrerInfo::CreateForSVGResources(OwnerDoc());
+
+  mReferencedElementTracker.ResetToURIFragmentID(this, targetURI, referrerInfo);
 }
 
 void SVGUseElement::TriggerReclone() {
   if (Document* doc = GetComposedDoc()) {
     doc->ScheduleSVGUseElementShadowTreeUpdate(*this);
   }
 }
 
--- a/dom/xml/XMLStylesheetProcessingInstruction.cpp
+++ b/dom/xml/XMLStylesheetProcessingInstruction.cpp
@@ -119,22 +119,25 @@ XMLStylesheetProcessingInstruction::GetS
   }
 
   Document* doc = OwnerDoc();
   nsIURI* baseURL =
       mOverriddenBaseURI ? mOverriddenBaseURI.get() : doc->GetDocBaseURI();
   auto encoding = doc->GetDocumentCharacterSet();
   nsCOMPtr<nsIURI> uri;
   NS_NewURI(getter_AddRefs(uri), href, encoding, baseURL);
+  nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo();
+  referrerInfo->InitWithDocument(doc);
+
   return Some(SheetInfo{
       *doc,
       this,
       uri.forget(),
       nullptr,
-      net::RP_Unset,
+      referrerInfo.forget(),
       CORS_NONE,
       title,
       media,
       alternate ? HasAlternateRel::Yes : HasAlternateRel::No,
       IsInline::No,
       IsExplicitlyEnabled::No,
   });
 }
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -1791,18 +1791,21 @@ nsresult nsXULPrototypeElement::SetAttrA
 
     // This is basically duplicating what nsINode::NodePrincipal() does
     nsIPrincipal* principal = mNodeInfo->NodeInfoManager()->DocumentPrincipal();
     // XXX Get correct Base URI (need GetBaseURI on *prototype* element)
     // TODO: If we implement Content Security Policy for chrome documents
     // as has been discussed, the CSP should be checked here to see if
     // inline styles are allowed to be applied.
     // XXX No specific specs talk about xul and referrer policy, pass Unset
-    RefPtr<URLExtraData> data = new URLExtraData(
-        aDocumentURI, aDocumentURI, principal, mozilla::net::RP_Unset);
+    nsCOMPtr<nsIReferrerInfo> referrerInfo =
+        new mozilla::dom::ReferrerInfo(aDocumentURI, mozilla::net::RP_Unset);
+
+    RefPtr<URLExtraData> data =
+        new URLExtraData(aDocumentURI, referrerInfo, principal);
     RefPtr<DeclarationBlock> declaration = DeclarationBlock::FromCssText(
         aValue, data, eCompatibility_FullStandards, nullptr);
     if (declaration) {
       mAttributes[aPos].mValue.SetTo(declaration.forget(), &aValue);
 
       return NS_OK;
     }
     // Don't abort if parsing failed, it could just be malformed css.
--- a/gfx/thebes/gfxUserFontSet.h
+++ b/gfx/thebes/gfxUserFontSet.h
@@ -14,20 +14,20 @@
 #include "nsRefPtrHashtable.h"
 #include "nsCOMPtr.h"
 #include "nsIFontLoadCompleteCallback.h"
 #include "nsIMemoryReporter.h"
 #include "nsIPrincipal.h"
 #include "nsIRunnable.h"
 #include "nsIScriptError.h"
 #include "nsIURI.h"
+#include "nsIReferrerInfo.h"
 #include "nsURIHashKey.h"
 #include "mozilla/FontPropertyTypes.h"
 #include "mozilla/ServoStyleConsts.h"
-#include "mozilla/net/ReferrerPolicy.h"
 #include "gfxFontConstants.h"
 #include "mozilla/LazyIdleThread.h"
 #include "mozilla/StaticPtr.h"
 
 class gfxFont;
 
 namespace mozilla {
 class PostTraversalTask;
@@ -57,18 +57,17 @@ struct gfxFontFaceSrc {
 
   // format hint flags, union of all possible formats
   // (e.g. TrueType, EOT, SVG, etc.)
   // see FLAG_FORMAT_* enum values below
   uint32_t mFormatFlags;
 
   nsCString mLocalName;        // full font name if local
   RefPtr<gfxFontSrcURI> mURI;  // uri if url
-  nsCOMPtr<nsIURI> mReferrer;  // referrer url if url
-  mozilla::net::ReferrerPolicy mReferrerPolicy;
+  nsCOMPtr<nsIReferrerInfo> mReferrerInfo;       // referrer info if url
   RefPtr<gfxFontSrcPrincipal> mOriginPrincipal;  // principal if url
 
   RefPtr<gfxFontFaceBufferSource> mBuffer;
 
   // The principal that should be used for the load. Should only be used for
   // URL sources.
   gfxFontSrcPrincipal* LoadPrincipal(const gfxUserFontSet&) const;
 };
@@ -83,19 +82,18 @@ inline bool operator==(const gfxFontFace
   switch (a.mSourceType) {
     case gfxFontFaceSrc::eSourceType_Local:
       return a.mLocalName == b.mLocalName;
     case gfxFontFaceSrc::eSourceType_URL: {
       bool equals;
       return a.mUseOriginPrincipal == b.mUseOriginPrincipal &&
              a.mFormatFlags == b.mFormatFlags &&
              (a.mURI == b.mURI || a.mURI->Equals(b.mURI)) &&
-             NS_SUCCEEDED(a.mReferrer->Equals(b.mReferrer, &equals)) &&
-             equals && a.mReferrerPolicy == b.mReferrerPolicy &&
-             a.mOriginPrincipal->Equals(b.mOriginPrincipal);
+             NS_SUCCEEDED(a.mReferrerInfo->Equals(b.mReferrerInfo, &equals)) &&
+             equals && a.mOriginPrincipal->Equals(b.mOriginPrincipal);
     }
     case gfxFontFaceSrc::eSourceType_Buffer:
       return a.mBuffer == b.mBuffer;
   }
   NS_WARNING("unexpected mSourceType");
   return false;
 }
 
--- a/layout/style/FontFace.cpp
+++ b/layout/style/FontFace.cpp
@@ -473,20 +473,22 @@ void FontFace::DoReject(nsresult aResult
 already_AddRefed<URLExtraData> FontFace::GetURLExtraData() const {
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mParent);
   nsCOMPtr<nsIPrincipal> principal = global->PrincipalOrNull();
 
   nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(mParent);
   nsCOMPtr<nsIURI> docURI = window->GetDocumentURI();
   nsCOMPtr<nsIURI> base = window->GetDocBaseURI();
 
-  // We pass RP_Unset when creating URLExtraData object here because it's not
+  // We pass RP_Unset when creating ReferrerInfo object here because it's not
   // going to result to change referer policy in a resource request.
-  RefPtr<URLExtraData> url =
-      new URLExtraData(base, docURI, principal, net::RP_Unset);
+  nsCOMPtr<nsIReferrerInfo> referrerInfo =
+      new mozilla::dom::ReferrerInfo(docURI, net::RP_Unset);
+
+  RefPtr<URLExtraData> url = new URLExtraData(base, referrerInfo, principal);
   return url.forget();
 }
 
 // Boolean result indicates whether the value of the descriptor was actually
 // changed.
 bool FontFace::SetDescriptor(nsCSSFontDesc aFontDesc, const nsAString& aValue,
                              ErrorResult& aRv) {
   // FIXME We probably don't need to distinguish between this anymore
--- a/layout/style/FontFaceSet.cpp
+++ b/layout/style/FontFaceSet.cpp
@@ -599,30 +599,30 @@ nsresult FontFaceSet::StartLoad(gfxUserF
       loadGroup);
   NS_ENSURE_SUCCESS(rv, rv);
 
   RefPtr<nsFontFaceLoader> fontLoader = new nsFontFaceLoader(
       aUserFontEntry, aFontFaceSrc->mURI->get(), this, channel);
   mLoaders.PutEntry(fontLoader);
 
   if (LOG_ENABLED()) {
+    nsCOMPtr<nsIURI> referrer =
+        aFontFaceSrc->mReferrerInfo
+            ? aFontFaceSrc->mReferrerInfo->GetOriginalReferrer()
+            : nullptr;
     LOG(
         ("userfonts (%p) download start - font uri: (%s) "
          "referrer uri: (%s)\n",
          fontLoader.get(), aFontFaceSrc->mURI->GetSpecOrDefault().get(),
-         aFontFaceSrc->mReferrer
-             ? aFontFaceSrc->mReferrer->GetSpecOrDefault().get()
-             : ""));
+         referrer ? referrer->GetSpecOrDefault().get() : ""));
   }
 
   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
   if (httpChannel) {
-    nsCOMPtr<nsIReferrerInfo> referrerInfo = new mozilla::dom::ReferrerInfo(
-        aFontFaceSrc->mReferrer, aFontFaceSrc->mReferrerPolicy);
-    rv = httpChannel->SetReferrerInfoWithoutClone(referrerInfo);
+    rv = httpChannel->SetReferrerInfo(aFontFaceSrc->mReferrerInfo);
     Unused << NS_WARN_IF(NS_FAILED(rv));
 
     rv = httpChannel->SetRequestHeader(
         NS_LITERAL_CSTRING("Accept"),
         NS_LITERAL_CSTRING("application/font-woff2;q=1.0,application/"
                            "font-woff;q=0.9,*/*;q=0.8"),
         false);
     NS_ENSURE_SUCCESS(rv, rv);
@@ -1053,42 +1053,39 @@ FontFaceSet::FindOrCreateUserFontEntryFr
   if (aFontFace->HasFontData()) {
     gfxFontFaceSrc* face = srcArray.AppendElement();
     if (!face) {
       return nullptr;
     }
 
     face->mSourceType = gfxFontFaceSrc::eSourceType_Buffer;
     face->mBuffer = aFontFace->CreateBufferSource();
-    face->mReferrerPolicy = mozilla::net::RP_Unset;
   } else {
     AutoTArray<StyleFontFaceSourceListComponent, 8> sourceListComponents;
     aFontFace->GetSources(sourceListComponents);
     size_t len = sourceListComponents.Length();
     for (size_t i = 0; i < len; ++i) {
       gfxFontFaceSrc* face = srcArray.AppendElement();
       const auto& component = sourceListComponents[i];
       switch (component.tag) {
         case StyleFontFaceSourceListComponent::Tag::Local: {
           nsAtom* atom = component.AsLocal();
           face->mLocalName.Append(nsAtomCString(atom));
           face->mSourceType = gfxFontFaceSrc::eSourceType_Local;
           face->mURI = nullptr;
           face->mFormatFlags = 0;
-          face->mReferrerPolicy = mozilla::net::RP_Unset;
           break;
         }
         case StyleFontFaceSourceListComponent::Tag::Url: {
           face->mSourceType = gfxFontFaceSrc::eSourceType_URL;
           const StyleCssUrl* url = component.AsUrl();
           nsIURI* uri = url->GetURI();
           face->mURI = uri ? new gfxFontSrcURI(uri) : nullptr;
           const URLExtraData& extraData = url->ExtraData();
-          face->mReferrer = extraData.GetReferrer();
-          face->mReferrerPolicy = extraData.GetReferrerPolicy();
+          face->mReferrerInfo = extraData.ReferrerInfo();
           face->mOriginPrincipal =
               new gfxFontSrcPrincipal(extraData.Principal());
 
           // agent and user stylesheets are treated slightly differently,
           // the same-site origin check and access control headers are
           // enforced against the sheet principal rather than the document
           // principal to allow user stylesheets to include @font-face rules
           face->mUseOriginPrincipal =
--- a/layout/style/GeckoBindings.cpp
+++ b/layout/style/GeckoBindings.cpp
@@ -1791,16 +1791,19 @@ static already_AddRefed<StyleSheet> Load
         aParent->CreateEmptyChildSheet(media.forget());
     // Make a dummy URI if we don't have one because some methods assume
     // non-null URIs.
     if (!uri) {
       NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("about:invalid"));
     }
     emptySheet->SetURIs(uri, uri, uri);
     emptySheet->SetPrincipal(aURL.ExtraData().Principal());
+    nsCOMPtr<nsIReferrerInfo> referrerInfo =
+        ReferrerInfo::CreateForExternalCSSResources(emptySheet);
+    emptySheet->SetReferrerInfo(referrerInfo);
     emptySheet->SetComplete();
     aParent->PrependStyleSheet(emptySheet);
     return emptySheet.forget();
   }
 
   RefPtr<StyleSheet> sheet = static_cast<StyleSheet*>(aParent->GetFirstChild());
   return sheet.forget();
 }
--- a/layout/style/ImageLoader.cpp
+++ b/layout/style/ImageLoader.cpp
@@ -451,19 +451,18 @@ void ImageLoader::LoadImage(const StyleC
   int32_t loadFlags =
       nsIRequest::LOAD_NORMAL |
       nsContentUtils::CORSModeToLoadImageFlags(aImage.CorsMode());
 
   const URLExtraData& data = aImage.ExtraData();
 
   RefPtr<imgRequestProxy> request;
   nsresult rv = nsContentUtils::LoadImage(
-      uri, &aLoadingDoc, &aLoadingDoc, data.Principal(), 0, data.GetReferrer(),
-      data.GetReferrerPolicy(), nullptr, loadFlags, NS_LITERAL_STRING("css"),
-      getter_AddRefs(request));
+      uri, &aLoadingDoc, &aLoadingDoc, data.Principal(), 0, data.ReferrerInfo(),
+      nullptr, loadFlags, NS_LITERAL_STRING("css"), getter_AddRefs(request));
 
   if (NS_FAILED(rv) || !request) {
     return;
   }
 
   entry->mCanonicalRequest = std::move(request);
 }
 
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -125,23 +125,22 @@ static mozilla::LazyLogModule gSriPRLog(
 
 // And some convenience strings...
 static const char* const gStateStrings[] = {
     "eSheetStateUnknown", "eSheetNeedsParser", "eSheetPending", "eSheetLoading",
     "eSheetComplete"};
 
 namespace mozilla {
 
-URIPrincipalReferrerPolicyAndCORSModeHashKey::
-    URIPrincipalReferrerPolicyAndCORSModeHashKey(css::SheetLoadData* aLoadData)
+SheetLoadDataHashKey::SheetLoadDataHashKey(css::SheetLoadData* aLoadData)
     : nsURIHashKey(aLoadData->mURI),
       mPrincipal(aLoadData->mLoaderPrincipal),
       mCORSMode(aLoadData->mSheet->GetCORSMode()),
-      mReferrerPolicy(aLoadData->mSheet->GetReferrerPolicy()) {
-  MOZ_COUNT_CTOR(URIPrincipalReferrerPolicyAndCORSModeHashKey);
+      mReferrerInfo(aLoadData->ReferrerInfo()) {
+  MOZ_COUNT_CTOR(SheetLoadDataHashKey);
 }
 }  // namespace mozilla
 
 namespace mozilla {
 namespace css {
 
 /********************************
  * SheetLoadData implementation *
@@ -512,38 +511,16 @@ NotNull<const Encoding*> SheetLoadData::
   if (mLoader->mDocument) {
     // Use the document charset.
     return mLoader->mDocument->GetDocumentCharacterSet();
   }
 
   return UTF_8_ENCODING;
 }
 
-already_AddRefed<nsIURI> SheetLoadData::GetReferrerURI() {
-  nsCOMPtr<nsIURI> uri;
-  if (mParentData) uri = mParentData->mSheet->GetSheetURI();
-  if (!uri && mLoader->mDocument) uri = mLoader->mDocument->GetDocumentURI();
-  return uri.forget();
-}
-
-void SheetLoadData::SetReferrerPolicyFromHeader(nsIChannel* aChannel) {
-  net::ReferrerPolicy policy =
-      nsContentUtils::GetReferrerPolicyFromChannel(aChannel);
-  if (policy == net::RP_Unset || policy == mSheet->GetReferrerPolicy()) {
-    return;
-  }
-
-  URIPrincipalReferrerPolicyAndCORSModeHashKey oldKey(
-      mURI, mLoaderPrincipal, mSheet->GetCORSMode(),
-      mSheet->GetReferrerPolicy());
-
-  mSheet->SetReferrerPolicy(policy);
-  mLoader->UpdateLoadingData(&oldKey, this);
-}
-
 static nsresult VerifySheetIntegrity(const SRIMetadata& aMetadata,
                                      nsIChannel* aChannel,
                                      const nsACString& aFirst,
                                      const nsACString& aSecond,
                                      const nsACString& aSourceFileURI,
                                      nsIConsoleReportCollector* aReporter) {
   NS_ENSURE_ARG_POINTER(aReporter);
 
@@ -725,17 +702,17 @@ nsresult SheetLoadData::VerifySheetReady
       errorMessage = "MimeNotCss";
       errorFlag = nsIScriptError::errorFlag;
     }
 
     AutoTArray<nsString, 2> strings;
     CopyUTF8toUTF16(channelURI->GetSpecOrDefault(), *strings.AppendElement());
     CopyASCIItoUTF16(contentType, *strings.AppendElement());
 
-    nsCOMPtr<nsIURI> referrer = GetReferrerURI();
+    nsCOMPtr<nsIURI> referrer = ReferrerInfo()->GetOriginalReferrer();
     nsContentUtils::ReportToConsole(
         errorFlag, NS_LITERAL_CSTRING("CSS Loader"), mLoader->mDocument,
         nsContentUtils::eCSS_PROPERTIES, errorMessage, strings, referrer);
 
     if (errorFlag == nsIScriptError::errorFlag) {
       LOG_WARN(
           ("  Ignoring sheet with improper MIME type %s", contentType.get()));
       mLoader->SheetComplete(this, NS_ERROR_NOT_AVAILABLE);
@@ -765,21 +742,26 @@ nsresult SheetLoadData::VerifySheetReady
       LOG(("  Load was blocked by SRI"));
       MOZ_LOG(gSriPRLog, mozilla::LogLevel::Debug,
               ("css::Loader::OnStreamComplete, bad metadata"));
       mLoader->SheetComplete(this, NS_ERROR_SRI_CORRUPT);
       return NS_OK;
     }
   }
 
-  SetReferrerPolicyFromHeader(aChannel);
-
   // Enough to set the URIs on mSheet, since any sibling datas we have share
   // the same mInner as mSheet and will thus get the same URI.
   mSheet->SetURIs(channelURI, originalURI, channelURI);
+
+  net::ReferrerPolicy policy =
+      nsContentUtils::GetReferrerPolicyFromChannel(aChannel);
+  nsCOMPtr<nsIReferrerInfo> referrerInfo =
+      ReferrerInfo::CreateForExternalCSSResources(mSheet, policy);
+
+  mSheet->SetReferrerInfo(referrerInfo);
   return NS_OK_PARSE_SHEET;
 }
 
 Loader::IsAlternate Loader::IsAlternateSheet(const nsAString& aTitle,
                                              bool aHasAlternateRel) {
   // A sheet is alternate if it has a nonempty title that doesn't match the
   // currently selected style set.  But if there _is_ no currently selected
   // style set, the sheet wasn't marked as an alternate explicitly, and aTitle
@@ -804,29 +786,16 @@ Loader::IsAlternate Loader::IsAlternateS
     if (aTitle.Equals(currentSheetSet)) {
       return IsAlternate::No;
     }
   }
 
   return IsAlternate::Yes;
 }
 
-void Loader::UpdateLoadingData(
-    URIPrincipalReferrerPolicyAndCORSModeHashKey* aOldKey,
-    SheetLoadData* aData) {
-  MOZ_ASSERT(mSheets, "Must have sheets!");
-  MOZ_ASSERT(aData->mIsLoading, "data must be loading");
-
-  DebugOnly<bool> removed = mSheets->mLoadingDatas.Remove(aOldKey);
-  MOZ_ASSERT(removed, "Can't find data to remove!!!");
-
-  URIPrincipalReferrerPolicyAndCORSModeHashKey newKey(aData);
-  mSheets->mLoadingDatas.Put(&newKey, aData);
-}
-
 nsresult Loader::CheckContentPolicy(nsIPrincipal* aLoadingPrincipal,
                                     nsIPrincipal* aTriggeringPrincipal,
                                     nsIURI* aTargetURI,
                                     nsINode* aRequestingNode, bool aIsPreload) {
   // When performing a system load (e.g. aUseSystemPrincipal = true)
   // then aLoadingPrincipal == null; don't consult content policies.
   if (!aLoadingPrincipal) {
     return NS_OK;
@@ -864,23 +833,21 @@ nsresult Loader::CheckContentPolicy(nsIP
  * CreateSheet() creates a CSSStyleSheet object for the given URI,
  * if any.  If there is no URI given, we just create a new style sheet
  * object.  Otherwise, we check for an existing style sheet object for
  * that uri in various caches and clone it if we find it.  Cloned
  * sheets will have the title/media/enabled state of the sheet they
  * are clones off; make sure to call PrepareSheet() on the result of
  * CreateSheet().
  */
-nsresult Loader::CreateSheet(nsIURI* aURI, nsIContent* aLinkingContent,
-                             nsIPrincipal* aLoaderPrincipal,
-                             css::SheetParsingMode aParsingMode,
-                             CORSMode aCORSMode, ReferrerPolicy aReferrerPolicy,
-                             const nsAString& aIntegrity, bool aSyncLoad,
-                             StyleSheetState& aSheetState,
-                             RefPtr<StyleSheet>* aSheet) {
+nsresult Loader::CreateSheet(
+    nsIURI* aURI, nsIContent* aLinkingContent, nsIPrincipal* aLoaderPrincipal,
+    css::SheetParsingMode aParsingMode, CORSMode aCORSMode,
+    nsIReferrerInfo* aLoadingReferrerInfo, const nsAString& aIntegrity,
+    bool aSyncLoad, StyleSheetState& aSheetState, RefPtr<StyleSheet>* aSheet) {
   LOG(("css::Loader::CreateSheet"));
   MOZ_ASSERT(aSheet, "Null out param!");
 
   if (!mSheets) {
     mSheets = MakeUnique<Sheets>();
   }
 
   *aSheet = nullptr;
@@ -899,18 +866,18 @@ nsresult Loader::CreateSheet(nsIURI* aUR
         LOG(("  From XUL cache: %p", sheet.get()));
       }
     }
 #endif
 
     bool fromCompleteSheets = false;
     if (!sheet) {
       // Then our per-document complete sheets.
-      URIPrincipalReferrerPolicyAndCORSModeHashKey key(
-          aURI, aLoaderPrincipal, aCORSMode, aReferrerPolicy);
+      SheetLoadDataHashKey key(aURI, aLoaderPrincipal, aCORSMode,
+                               aLoadingReferrerInfo);
 
       StyleSheet* completeSheet = nullptr;
       mSheets->mCompleteSheets.Get(&key, &completeSheet);
       sheet = completeSheet;
       LOG(("  From completed: %p", sheet.get()));
 
       fromCompleteSheets = !!sheet;
     }
@@ -936,18 +903,18 @@ nsresult Loader::CreateSheet(nsIURI* aUR
         fromCompleteSheets = false;
       }
     }
 
     // Then loading sheets
     if (!sheet && !aSyncLoad) {
       aSheetState = eSheetLoading;
       SheetLoadData* loadData = nullptr;
-      URIPrincipalReferrerPolicyAndCORSModeHashKey key(
-          aURI, aLoaderPrincipal, aCORSMode, aReferrerPolicy);
+      SheetLoadDataHashKey key(aURI, aLoaderPrincipal, aCORSMode,
+                               aLoadingReferrerInfo);
       mSheets->mLoadingDatas.Get(&key, &loadData);
       if (loadData) {
         sheet = loadData->mSheet;
         LOG(("  From loading: %p", sheet.get()));
 
 #ifdef DEBUG
         bool debugEqual;
         NS_ASSERTION((!aLoaderPrincipal && !loadData->mLoaderPrincipal) ||
@@ -993,18 +960,18 @@ nsresult Loader::CreateSheet(nsIURI* aUR
           sheet->Clone(nullptr, nullptr, nullptr, nullptr);
       *aSheet = std::move(clonedSheet);
       if (*aSheet && fromCompleteSheets && !sheet->GetOwnerNode() &&
           !sheet->GetParentSheet()) {
         // The sheet we're cloning isn't actually referenced by
         // anyone.  Replace it in the cache, so that if our CSSOM is
         // later modified we don't end up with two copies of our inner
         // hanging around.
-        URIPrincipalReferrerPolicyAndCORSModeHashKey key(
-            aURI, aLoaderPrincipal, aCORSMode, aReferrerPolicy);
+        SheetLoadDataHashKey key(aURI, aLoaderPrincipal, aCORSMode,
+                                 aLoadingReferrerInfo);
         NS_ASSERTION((*aSheet)->IsComplete(),
                      "Should only be caching complete sheets");
         mSheets->mCompleteSheets.Put(&key, *aSheet);
       }
     }
   }
 
   if (!*aSheet) {
@@ -1034,19 +1001,27 @@ nsresult Loader::CreateSheet(nsIURI* aUR
       nsAutoCString sourceUri;
       if (mDocument && mDocument->GetDocumentURI()) {
         mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
       }
       SRICheck::IntegrityMetadata(aIntegrity, sourceUri, mReporter,
                                   &sriMetadata);
     }
 
-    *aSheet =
-        new StyleSheet(aParsingMode, aCORSMode, aReferrerPolicy, sriMetadata);
+    *aSheet = new StyleSheet(aParsingMode, aCORSMode, sriMetadata);
     (*aSheet)->SetURIs(sheetURI, originalURI, baseURI);
+    nsCOMPtr<nsIReferrerInfo> referrerInfo;
+    if ((*aSheet)->IsInline()) {
+      referrerInfo = ReferrerInfo::CreateForInternalCSSResources(
+          aLinkingContent->OwnerDoc());
+    } else {
+      referrerInfo = ReferrerInfo::CreateForExternalCSSResources(*aSheet);
+    }
+
+    (*aSheet)->SetReferrerInfo(referrerInfo);
   }
 
   NS_ASSERTION(*aSheet, "We should have a sheet by now!");
   NS_ASSERTION(aSheetState != eSheetStateUnknown, "Have to set a state!");
   LOG(("  State: %s", gStateStrings[aSheetState]));
 
   return NS_OK;
 }
@@ -1326,17 +1301,17 @@ nsresult Loader::LoadSheet(SheetLoadData
     // and thence to ParseSheet.  Regardless of whether this fails,
     // SheetComplete has been called.
     return nsSyncLoadService::PushSyncStreamToListener(stream.forget(),
                                                        streamLoader, channel);
   }
 
   SheetLoadData* existingData = nullptr;
 
-  URIPrincipalReferrerPolicyAndCORSModeHashKey key(aLoadData);
+  SheetLoadDataHashKey key(aLoadData);
 
   if (aSheetState == eSheetLoading) {
     mSheets->mLoadingDatas.Get(&key, &existingData);
     NS_ASSERTION(existingData, "CreateSheet lied about the state");
   } else if (aSheetState == eSheetPending) {
     mSheets->mPendingDatas.Get(&key, &existingData);
     NS_ASSERTION(existingData, "CreateSheet lied about the state");
   }
@@ -1449,21 +1424,19 @@ nsresult Loader::LoadSheet(SheetLoadData
     nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
     if (cos) {
       cos->AddClassFlags(nsIClassOfService::Leader);
     }
   }
 
   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
   if (httpChannel) {
-    nsCOMPtr<nsIURI> referrerURI = aLoadData->GetReferrerURI();
-    if (referrerURI) {
-      nsCOMPtr<nsIReferrerInfo> referrerInfo = new mozilla::dom::ReferrerInfo(
-          referrerURI, aLoadData->mSheet->GetReferrerPolicy());
-      rv = httpChannel->SetReferrerInfoWithoutClone(referrerInfo);
+    nsCOMPtr<nsIReferrerInfo> referrerInfo = aLoadData->ReferrerInfo();
+    if (referrerInfo) {
+      rv = httpChannel->SetReferrerInfo(referrerInfo);
       Unused << NS_WARN_IF(NS_FAILED(rv));
     }
 
     nsCOMPtr<nsIHttpChannelInternal> internalChannel =
         do_QueryInterface(httpChannel);
     if (internalChannel) {
       rv = internalChannel->SetIntegrityMetadata(
           sriMetadata.GetIntegrityString());
@@ -1676,17 +1649,17 @@ void Loader::DoSheetComplete(SheetLoadDa
   MOZ_ASSERT(aLoadData->mSheet, "Must have a sheet");
   NS_ASSERTION(mSheets, "mLoadingDatas should be initialized by now.");
 
   // Twiddle the hashtables
   if (aLoadData->mURI) {
     LOG_URI("  Finished loading: '%s'", aLoadData->mURI);
     // Remove the data from the list of loading datas
     if (aLoadData->mIsLoading) {
-      URIPrincipalReferrerPolicyAndCORSModeHashKey key(aLoadData);
+      SheetLoadDataHashKey key(aLoadData);
 #ifdef DEBUG
       SheetLoadData* loadingData;
       NS_ASSERTION(mSheets->mLoadingDatas.Get(&key, &loadingData) &&
                        loadingData == aLoadData,
                    "Bad loading table");
 #endif
 
       mSheets->mLoadingDatas.Remove(&key);
@@ -1757,17 +1730,17 @@ void Loader::DoSheetComplete(SheetLoadDa
           LOG(("  Putting sheet in XUL prototype cache"));
           NS_ASSERTION(sheet->IsComplete(),
                        "Should only be caching complete sheets");
           cache->PutStyleSheet(sheet);
         }
       }
     } else {
 #endif
-      URIPrincipalReferrerPolicyAndCORSModeHashKey key(aLoadData);
+      SheetLoadDataHashKey key(aLoadData);
       NS_ASSERTION(sheet->IsComplete(),
                    "Should only be caching complete sheets");
       mSheets->mCompleteSheets.Put(&key, sheet);
 #ifdef MOZ_XUL
     }
 #endif
   }
 
@@ -1838,17 +1811,17 @@ Result<Loader::LoadSheetResult, nsresult
     // stylesheet. So treat this as principal inheritance, and downgrade if
     // necessary.
     principal =
         BasePrincipal::Cast(aInfo.mTriggeringPrincipal)->PrincipalToInherit();
   }
 
   SheetLoadData* data = new SheetLoadData(
       this, aInfo.mTitle, nullptr, sheet, false, owningElement, isAlternate,
-      matched, aObserver, nullptr, aInfo.mContent);
+      matched, aObserver, nullptr, aInfo.mReferrerInfo, aInfo.mContent);
 
   // We never actually load this, so just set its principal directly
   sheet->SetPrincipal(principal);
 
   NS_ADDREF(data);
   data->mLineNumber = aLineNumber;
   // Parse completion releases the load data.
   //
@@ -1938,42 +1911,42 @@ Result<Loader::LoadSheetResult, nsresult
 
   nsCOMPtr<nsIStyleSheetLinkingElement> owningElement(
       do_QueryInterface(aInfo.mContent));
 
   if (state == eSheetComplete) {
     LOG(("  Sheet already complete: 0x%p", sheet.get()));
     if (aObserver || !mObservers.IsEmpty() || owningElement) {
       rv = PostLoadEvent(aInfo.mURI, sheet, aObserver, isAlternate, matched,
-                         owningElement);
+                         aInfo.mReferrerInfo, owningElement);
       if (NS_FAILED(rv)) {
         return Err(rv);
       }
     }
 
     // The load hasn't been completed yet, will be done in PostLoadEvent.
     return LoadSheetResult{Completed::No, isAlternate, matched};
   }
 
   // Now we need to actually load it.
   SheetLoadData* data = new SheetLoadData(
       this, aInfo.mTitle, aInfo.mURI, sheet, syncLoad, owningElement,
-      isAlternate, matched, aObserver, principal, context);
+      isAlternate, matched, aObserver, principal, aInfo.mReferrerInfo, context);
   NS_ADDREF(data);
 
   auto result = LoadSheetResult{Completed::No, isAlternate, matched};
 
   MOZ_ASSERT(result.ShouldBlock() == !data->ShouldDefer(),
              "These should better match!");
 
   // If we have to parse and it's a non-blocking non-inline sheet, defer it.
   if (!syncLoad && state == eSheetNeedsParser &&
       mSheets->mLoadingDatas.Count() != 0 && !result.ShouldBlock()) {
     LOG(("  Deferring sheet load"));
-    URIPrincipalReferrerPolicyAndCORSModeHashKey key(data);
+    SheetLoadDataHashKey key(data);
     mSheets->mPendingDatas.Put(&key, data);
 
     data->mMustNotify = true;
     return result;
   }
 
   // Load completion will free the data
   rv = LoadSheet(data, state, false);
@@ -2087,17 +2060,17 @@ nsresult Loader::LoadChildSheet(StyleShe
   RefPtr<StyleSheet> sheet;
   StyleSheetState state;
   if (aReusableSheets && aReusableSheets->FindReusableStyleSheet(aURL, sheet)) {
     state = eSheetComplete;
   } else {
     const nsAString& empty = EmptyString();
     // For now, use CORS_NONE for child sheets
     rv = CreateSheet(aURL, nullptr, principal, aParentSheet->ParsingMode(),
-                     CORS_NONE, aParentSheet->GetReferrerPolicy(),
+                     CORS_NONE, aParentSheet->GetReferrerInfo(),
                      EmptyString(),  // integrity is only checked on main sheet
                      aParentData ? aParentData->mSyncLoad : false, state,
                      &sheet);
     NS_ENSURE_SUCCESS(rv, rv);
 
     PrepareSheet(sheet, empty, empty, aMedia, IsAlternate::No,
                  IsExplicitlyEnabled::No);
   }
@@ -2108,18 +2081,19 @@ nsresult Loader::LoadChildSheet(StyleShe
   if (state == eSheetComplete) {
     LOG(("  Sheet already complete"));
     // We're completely done.  No need to notify, even, since the
     // @import rule addition/modification will trigger the right style
     // changes automatically.
     return NS_OK;
   }
 
-  SheetLoadData* data = new SheetLoadData(this, aURL, sheet, aParentData,
-                                          observer, principal, context);
+  SheetLoadData* data =
+      new SheetLoadData(this, aURL, sheet, aParentData, observer, principal,
+                        aParentSheet->GetReferrerInfo(), context);
 
   NS_ADDREF(data);
   bool syncLoad = data->mSyncLoad;
 
   // Load completion will release the data
   rv = LoadSheet(data, state, false);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -2129,56 +2103,59 @@ nsresult Loader::LoadChildSheet(StyleShe
   }
   return rv;
 }
 
 nsresult Loader::LoadSheetSync(nsIURI* aURL, SheetParsingMode aParsingMode,
                                bool aUseSystemPrincipal,
                                RefPtr<StyleSheet>* aSheet) {
   LOG(("css::Loader::LoadSheetSync"));
+  nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo(nullptr);
   return InternalLoadNonDocumentSheet(aURL, false, aParsingMode,
                                       aUseSystemPrincipal, nullptr, nullptr,
-                                      aSheet, nullptr);
+                                      aSheet, referrerInfo, nullptr);
 }
 
 nsresult Loader::LoadSheet(nsIURI* aURL, SheetParsingMode aParsingMode,
                            bool aUseSystemPrincipal,
                            nsICSSLoaderObserver* aObserver,
                            RefPtr<StyleSheet>* aSheet) {
   LOG(
       ("css::Loader::LoadSheet(aURL, aParsingMode, aUseSystemPrincipal, "
        "aObserver, aSheet)"));
+  nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo(nullptr);
   return InternalLoadNonDocumentSheet(aURL, false, aParsingMode,
                                       aUseSystemPrincipal, nullptr, nullptr,
-                                      aSheet, aObserver);
+                                      aSheet, referrerInfo, aObserver);
 }
 
 nsresult Loader::LoadSheet(nsIURI* aURL, bool aIsPreload,
                            nsIPrincipal* aOriginPrincipal,
                            const Encoding* aPreloadEncoding,
+                           nsIReferrerInfo* aReferrerInfo,
                            nsICSSLoaderObserver* aObserver, CORSMode aCORSMode,
-                           ReferrerPolicy aReferrerPolicy,
                            const nsAString& aIntegrity) {
   LOG(("css::Loader::LoadSheet(aURL, aObserver) api call"));
   return InternalLoadNonDocumentSheet(aURL, aIsPreload, eAuthorSheetFeatures,
                                       false, aOriginPrincipal, aPreloadEncoding,
-                                      nullptr, aObserver, aCORSMode,
-                                      aReferrerPolicy, aIntegrity);
+                                      nullptr, aReferrerInfo, aObserver,
+                                      aCORSMode, aIntegrity);
 }
 
 nsresult Loader::InternalLoadNonDocumentSheet(
     nsIURI* aURL, bool aIsPreload, SheetParsingMode aParsingMode,
     bool aUseSystemPrincipal, nsIPrincipal* aOriginPrincipal,
     const Encoding* aPreloadEncoding, RefPtr<StyleSheet>* aSheet,
-    nsICSSLoaderObserver* aObserver, CORSMode aCORSMode,
-    ReferrerPolicy aReferrerPolicy, const nsAString& aIntegrity) {
+    nsIReferrerInfo* aReferrerInfo, nsICSSLoaderObserver* aObserver,
+    CORSMode aCORSMode, const nsAString& aIntegrity) {
   MOZ_ASSERT(aURL, "Must have a URI to load");
   MOZ_ASSERT(aSheet || aObserver, "Sheet and observer can't both be null");
   MOZ_ASSERT(!aUseSystemPrincipal || !aObserver,
              "Shouldn't load system-principal sheets async");
+  MOZ_ASSERT(aReferrerInfo, "Must have referrerInfo");
 
   LOG_URI("  Non-document sheet uri: '%s'", aURL);
 
   if (aSheet) {
     *aSheet = nullptr;
   }
 
   if (!mEnabled) {
@@ -2192,37 +2169,37 @@ nsresult Loader::InternalLoadNonDocument
                                    mDocument, aIsPreload);
   NS_ENSURE_SUCCESS(rv, rv);
 
   StyleSheetState state;
   RefPtr<StyleSheet> sheet;
   bool syncLoad = (aObserver == nullptr);
   const nsAString& empty = EmptyString();
   rv = CreateSheet(aURL, nullptr, aOriginPrincipal, aParsingMode, aCORSMode,
-                   aReferrerPolicy, aIntegrity, syncLoad, state, &sheet);
+                   aReferrerInfo, aIntegrity, syncLoad, state, &sheet);
   NS_ENSURE_SUCCESS(rv, rv);
 
   PrepareSheet(sheet, empty, empty, nullptr, IsAlternate::No,
                IsExplicitlyEnabled::No);
 
   if (state == eSheetComplete) {
     LOG(("  Sheet already complete"));
     if (aObserver || !mObservers.IsEmpty()) {
       rv = PostLoadEvent(aURL, sheet, aObserver, IsAlternate::No,
-                         MediaMatched::Yes, nullptr);
+                         MediaMatched::Yes, aReferrerInfo, nullptr);
     }
     if (aSheet) {
       sheet.swap(*aSheet);
     }
     return rv;
   }
 
   SheetLoadData* data = new SheetLoadData(
       this, aURL, sheet, syncLoad, aUseSystemPrincipal, aPreloadEncoding,
-      aObserver, aOriginPrincipal, mDocument);
+      aObserver, aOriginPrincipal, aReferrerInfo, mDocument);
 
   NS_ADDREF(data);
   rv = LoadSheet(data, state, aIsPreload);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aSheet) {
     sheet.swap(*aSheet);
   }
@@ -2232,27 +2209,28 @@ nsresult Loader::InternalLoadNonDocument
 
   return rv;
 }
 
 nsresult Loader::PostLoadEvent(nsIURI* aURI, StyleSheet* aSheet,
                                nsICSSLoaderObserver* aObserver,
                                IsAlternate aWasAlternate,
                                MediaMatched aMediaMatched,
+                               nsIReferrerInfo* aReferrerInfo,
                                nsIStyleSheetLinkingElement* aElement) {
   LOG(("css::Loader::PostLoadEvent"));
   MOZ_ASSERT(aSheet, "Must have sheet");
   MOZ_ASSERT(aObserver || !mObservers.IsEmpty() || aElement,
              "Must have observer or element");
 
-  RefPtr<SheetLoadData> evt =
-      new SheetLoadData(this,
-                        EmptyString(),  // title doesn't matter here
-                        aURI, aSheet, false, aElement, aWasAlternate,
-                        aMediaMatched, aObserver, nullptr, mDocument);
+  RefPtr<SheetLoadData> evt = new SheetLoadData(
+      this,
+      EmptyString(),  // title doesn't matter here
+      aURI, aSheet, false, aElement, aWasAlternate, aMediaMatched, aObserver,
+      nullptr, aReferrerInfo, mDocument);
 
   if (!mPostedEvents.AppendElement(evt)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   nsresult rv;
   RefPtr<SheetLoadData> runnable(evt);
   if (mDocument) {
@@ -2303,18 +2281,17 @@ void Loader::HandleLoadEvent(SheetLoadDa
     NS_ADDREF(aEvent);
     SheetComplete(aEvent, NS_OK);
   }
 
   UnblockOnload(true);
 }
 
 static void StopLoadingSheets(
-    nsDataHashtable<URIPrincipalReferrerPolicyAndCORSModeHashKey,
-                    SheetLoadData*>& aDatas,
+    nsDataHashtable<SheetLoadDataHashKey, SheetLoadData*>& aDatas,
     Loader::LoadDataArray& aArr) {
   for (auto iter = aDatas.Iter(); !iter.Done(); iter.Next()) {
     SheetLoadData* data = iter.Data();
     MOZ_ASSERT(data, "Must have a data!");
 
     data->mIsLoading = false;  // we will handle the removal right here
     data->mIsCancelled = true;
 
--- a/layout/style/Loader.h
+++ b/layout/style/Loader.h
@@ -37,108 +37,94 @@ namespace mozilla {
 namespace dom {
 class DocGroup;
 class Element;
 }  // namespace dom
 }  // namespace mozilla
 
 namespace mozilla {
 
-class URIPrincipalReferrerPolicyAndCORSModeHashKey : public nsURIHashKey {
+class SheetLoadDataHashKey : public nsURIHashKey {
  public:
-  typedef URIPrincipalReferrerPolicyAndCORSModeHashKey* KeyType;
-  typedef const URIPrincipalReferrerPolicyAndCORSModeHashKey* KeyTypePointer;
-  typedef mozilla::net::ReferrerPolicy ReferrerPolicy;
+  typedef SheetLoadDataHashKey* KeyType;
+  typedef const SheetLoadDataHashKey* KeyTypePointer;
 
-  explicit URIPrincipalReferrerPolicyAndCORSModeHashKey(
-      const URIPrincipalReferrerPolicyAndCORSModeHashKey* aKey)
+  explicit SheetLoadDataHashKey(const SheetLoadDataHashKey* aKey)
       : nsURIHashKey(aKey->mKey),
         mPrincipal(aKey->mPrincipal),
         mCORSMode(aKey->mCORSMode),
-        mReferrerPolicy(aKey->mReferrerPolicy) {
-    MOZ_COUNT_CTOR(URIPrincipalReferrerPolicyAndCORSModeHashKey);
+        mReferrerInfo(aKey->mReferrerInfo) {
+    MOZ_COUNT_CTOR(SheetLoadDataHashKey);
   }
 
-  URIPrincipalReferrerPolicyAndCORSModeHashKey(nsIURI* aURI,
-                                               nsIPrincipal* aPrincipal,
-                                               CORSMode aCORSMode,
-                                               ReferrerPolicy aReferrerPolicy)
+  SheetLoadDataHashKey(nsIURI* aURI, nsIPrincipal* aPrincipal,
+                       CORSMode aCORSMode, nsIReferrerInfo* aReferrerInfo)
       : nsURIHashKey(aURI),
         mPrincipal(aPrincipal),
         mCORSMode(aCORSMode),
-        mReferrerPolicy(aReferrerPolicy) {
-    MOZ_COUNT_CTOR(URIPrincipalReferrerPolicyAndCORSModeHashKey);
+        mReferrerInfo(aReferrerInfo) {
+    MOZ_COUNT_CTOR(SheetLoadDataHashKey);
   }
 
-  URIPrincipalReferrerPolicyAndCORSModeHashKey(
-      URIPrincipalReferrerPolicyAndCORSModeHashKey&& toMove)
+  SheetLoadDataHashKey(SheetLoadDataHashKey&& toMove)
       : nsURIHashKey(std::move(toMove)),
         mPrincipal(std::move(toMove.mPrincipal)),
         mCORSMode(std::move(toMove.mCORSMode)),
-        mReferrerPolicy(std::move(toMove.mReferrerPolicy)) {
-    MOZ_COUNT_CTOR(URIPrincipalReferrerPolicyAndCORSModeHashKey);
+        mReferrerInfo(std::move(toMove.mReferrerInfo)) {
+    MOZ_COUNT_CTOR(SheetLoadDataHashKey);
   }
 
-  explicit URIPrincipalReferrerPolicyAndCORSModeHashKey(
-      css::SheetLoadData* aLoadData);
+  explicit SheetLoadDataHashKey(css::SheetLoadData* aLoadData);
 
-  ~URIPrincipalReferrerPolicyAndCORSModeHashKey() {
-    MOZ_COUNT_DTOR(URIPrincipalReferrerPolicyAndCORSModeHashKey);
-  }
+  ~SheetLoadDataHashKey() { MOZ_COUNT_DTOR(SheetLoadDataHashKey); }
 
-  URIPrincipalReferrerPolicyAndCORSModeHashKey* GetKey() const {
-    return const_cast<URIPrincipalReferrerPolicyAndCORSModeHashKey*>(this);
+  SheetLoadDataHashKey* GetKey() const {
+    return const_cast<SheetLoadDataHashKey*>(this);
   }
-  const URIPrincipalReferrerPolicyAndCORSModeHashKey* GetKeyPointer() const {
-    return this;
-  }
+  const SheetLoadDataHashKey* GetKeyPointer() const { return this; }
 
-  bool KeyEquals(
-      const URIPrincipalReferrerPolicyAndCORSModeHashKey* aKey) const {
+  bool KeyEquals(const SheetLoadDataHashKey* aKey) const {
     if (!nsURIHashKey::KeyEquals(aKey->mKey)) {
       return false;
     }
 
     if (!mPrincipal != !aKey->mPrincipal) {
       // One or the other has a principal, but not both... not equal
       return false;
     }
 
     if (mCORSMode != aKey->mCORSMode) {
       // Different CORS modes; we don't match
       return false;
     }
 
-    if (mReferrerPolicy != aKey->mReferrerPolicy) {
-      // Different ReferrerPolicy; we don't match
+    bool eq;
+    if (NS_FAILED(mReferrerInfo->Equals(aKey->mReferrerInfo, &eq)) || !eq) {
       return false;
     }
 
-    bool eq;
     return !mPrincipal ||
            (NS_SUCCEEDED(mPrincipal->Equals(aKey->mPrincipal, &eq)) && eq);
   }
 
-  static const URIPrincipalReferrerPolicyAndCORSModeHashKey* KeyToPointer(
-      URIPrincipalReferrerPolicyAndCORSModeHashKey* aKey) {
+  static const SheetLoadDataHashKey* KeyToPointer(SheetLoadDataHashKey* aKey) {
     return aKey;
   }
-  static PLDHashNumber HashKey(
-      const URIPrincipalReferrerPolicyAndCORSModeHashKey* aKey) {
+  static PLDHashNumber HashKey(const SheetLoadDataHashKey* aKey) {
     return nsURIHashKey::HashKey(aKey->mKey);
   }
 
   nsIURI* GetURI() const { return nsURIHashKey::GetKey(); }
 
   enum { ALLOW_MEMMOVE = true };
 
  protected:
   nsCOMPtr<nsIPrincipal> mPrincipal;
   CORSMode mCORSMode;
-  ReferrerPolicy mReferrerPolicy;
+  nsCOMPtr<nsIReferrerInfo> mReferrerInfo;
 };
 
 namespace css {
 
 class SheetLoadData;
 class ImportRule;
 
 /*********************
@@ -322,16 +308,17 @@ class Loader final {
    * sheet is loaded and marked complete.  This method can be used to load
    * sheets not associated with a document.
    *
    * @param aURL the URL of the sheet to load
    * @param aParsingMode the mode in which to parse the sheet
    *        (see comments at enum SheetParsingMode, above).
    * @param aUseSystemPrincipal if true, give the resulting sheet the system
    * principal no matter where it's being loaded from.
+   * @param aReferrerInfo referrer information of the sheet.
    * @param aObserver the observer to notify when the load completes.
    *                  Must not be null.
    * @param [out] aSheet the sheet to load. Note that the sheet may well
    *              not be loaded by the time this method returns.
    *
    * NOTE: At the moment, this method assumes the sheet will be UTF-8, but
    * ideally it would allow arbitrary encodings.  Callers should NOT depend on
    * non-UTF8 sheets being treated as UTF-8 by this method.
@@ -342,19 +329,19 @@ class Loader final {
 
   /**
    * Same as above, to be used when the caller doesn't care about the
    * not-yet-loaded sheet.
    */
   nsresult LoadSheet(nsIURI* aURL, bool aIsPreload,
                      nsIPrincipal* aOriginPrincipal,
                      const Encoding* aPreloadEncoding,
+                     nsIReferrerInfo* aReferrerInfo,
                      nsICSSLoaderObserver* aObserver,
                      CORSMode aCORSMode = CORS_NONE,
-                     ReferrerPolicy aReferrerPolicy = mozilla::net::RP_Unset,
                      const nsAString& aIntegrity = EmptyString());
 
   /**
    * Stop loading all sheets.  All nsICSSLoaderObservers involved will be
    * notified with NS_BINDING_ABORTED as the status, possibly synchronously.
    */
   void Stop();
 
@@ -436,27 +423,27 @@ class Loader final {
                               nsIURI* aTargetURI, nsINode* aRequestingNode,
                               bool aIsPreload);
 
   nsresult CreateSheet(const SheetInfo& aInfo, nsIPrincipal* aLoaderPrincipal,
                        css::SheetParsingMode aParsingMode, bool aSyncLoad,
                        StyleSheetState& aSheetState,
                        RefPtr<StyleSheet>* aSheet) {
     return CreateSheet(aInfo.mURI, aInfo.mContent, aLoaderPrincipal,
-                       aParsingMode, aInfo.mCORSMode, aInfo.mReferrerPolicy,
+                       aParsingMode, aInfo.mCORSMode, aInfo.mReferrerInfo,
                        aInfo.mIntegrity, aSyncLoad, aSheetState, aSheet);
   }
 
   // For inline style, the aURI param is null, but the aLinkingContent
   // must be non-null then.  The loader principal must never be null
   // if aURI is not null.
   nsresult CreateSheet(nsIURI* aURI, nsIContent* aLinkingContent,
                        nsIPrincipal* aLoaderPrincipal,
                        css::SheetParsingMode aParsingMode, CORSMode aCORSMode,
-                       ReferrerPolicy aReferrerPolicy,
+                       nsIReferrerInfo* aLoadingReferrerInfo,
                        const nsAString& aIntegrity, bool aSyncLoad,
                        StyleSheetState& aSheetState,
                        RefPtr<StyleSheet>* aSheet);
 
   // Pass in either a media string or the MediaList from the CSSParser.  Don't
   // pass both.
   //
   // This method will set the sheet's enabled state based on aIsAlternate
@@ -468,30 +455,31 @@ class Loader final {
   void InsertSheetInTree(StyleSheet& aSheet, nsIContent* aLinkingContent);
   // Inserts a style sheet into a parent style sheet.
   void InsertChildSheet(StyleSheet& aSheet, StyleSheet& aParentSheet);
 
   nsresult InternalLoadNonDocumentSheet(
       nsIURI* aURL, bool aIsPreload, SheetParsingMode aParsingMode,
       bool aUseSystemPrincipal, nsIPrincipal* aOriginPrincipal,
       const Encoding* aPreloadEncoding, RefPtr<StyleSheet>* aSheet,
-      nsICSSLoaderObserver* aObserver, CORSMode aCORSMode = CORS_NONE,
-      ReferrerPolicy aReferrerPolicy = mozilla::net::RP_Unset,
+      nsIReferrerInfo* aReferrerInfo, nsICSSLoaderObserver* aObserver,
+      CORSMode aCORSMode = CORS_NONE,
       const nsAString& aIntegrity = EmptyString());
 
   // Post a load event for aObserver to be notified about aSheet.  The
   // notification will be sent with status NS_OK unless the load event is
   // canceled at some point (in which case it will be sent with
   // NS_BINDING_ABORTED).  aWasAlternate indicates the state when the load was
   // initiated, not the state at some later time.  aURI should be the URI the
   // sheet was loaded from (may be null for inline sheets).  aElement is the
   // owning element for this sheet.
   nsresult PostLoadEvent(nsIURI* aURI, StyleSheet* aSheet,
                          nsICSSLoaderObserver* aObserver,
                          IsAlternate aWasAlternate, MediaMatched aMediaMatched,
+                         nsIReferrerInfo* aReferrerInfo,
                          nsIStyleSheetLinkingElement* aElement);
 
   // Start the loads of all the sheets in mPendingDatas
   void StartDeferredLoads();
 
   // Handle an event posted by PostLoadEvent
   void HandleLoadEvent(SheetLoadData* aEvent);
 
@@ -524,29 +512,23 @@ class Loader final {
   // datas whose observers need to be notified can be added to it.
   void DoSheetComplete(SheetLoadData* aLoadData, LoadDataArray& aDatasToNotify);
 
   // Mark the given SheetLoadData, as well as any of its siblings, parents, etc
   // transitively, as failed.  The idea is to mark as failed any load that was
   // directly or indirectly @importing the sheet this SheetLoadData represents.
   void MarkLoadTreeFailed(SheetLoadData* aLoadData);
 
-  // If there's Referrer-Policy reponse header, the loading data and key should
-  // be updated with the referer policy parsed from the header.
-  void UpdateLoadingData(URIPrincipalReferrerPolicyAndCORSModeHashKey* aOldKey,
-                         SheetLoadData* aData);
-
   struct Sheets {
-    nsBaseHashtable<URIPrincipalReferrerPolicyAndCORSModeHashKey,
-                    RefPtr<StyleSheet>, StyleSheet*>
+    nsBaseHashtable<SheetLoadDataHashKey, RefPtr<StyleSheet>, StyleSheet*>
         mCompleteSheets;
-    nsDataHashtable<URIPrincipalReferrerPolicyAndCORSModeHashKey,
+    nsDataHashtable<SheetLoadDataHashKey,
                     SheetLoadData*>
         mLoadingDatas;  // weak refs
-    nsDataHashtable<URIPrincipalReferrerPolicyAndCORSModeHashKey,
+    nsDataHashtable<SheetLoadDataHashKey,
                     SheetLoadData*>
         mPendingDatas;  // weak refs
   };
   UniquePtr<Sheets> mSheets;
 
   // The array of posted stylesheet loaded events (SheetLoadDatas) we have.
   // Note that these are rare.
   LoadDataArray mPostedEvents;
--- a/layout/style/ServoCSSParser.cpp
+++ b/layout/style/ServoCSSParser.cpp
@@ -64,20 +64,22 @@ bool ServoCSSParser::ParseFontShorthandF
                                              &aStretch, &aWeight);
 }
 
 /* static */
 already_AddRefed<URLExtraData> ServoCSSParser::GetURLExtraData(
     Document* aDocument) {
   MOZ_ASSERT(aDocument);
 
+  nsCOMPtr<nsIReferrerInfo> referrerInfo =
+      ReferrerInfo::CreateForInternalCSSResources(aDocument);
+
   // FIXME this is using the wrong base uri (bug 1343919)
   RefPtr<URLExtraData> url = new URLExtraData(
-      aDocument->GetDocumentURI(), aDocument->GetDocumentURI(),
-      aDocument->NodePrincipal(), aDocument->GetReferrerPolicy());
+      aDocument->GetDocumentURI(), referrerInfo, aDocument->NodePrincipal());
   return url.forget();
 }
 
 /* static */ ServoCSSParser::ParsingEnvironment
 ServoCSSParser::GetParsingEnvironment(Document* aDocument) {
   return ParsingEnvironment(GetURLExtraData(aDocument),
                             aDocument->GetCompatibilityMode(),
                             aDocument->CSSLoader());
--- a/layout/style/nsLayoutStylesheetCache.cpp
+++ b/layout/style/nsLayoutStylesheetCache.cpp
@@ -287,27 +287,30 @@ nsLayoutStylesheetCache::nsLayoutStylesh
   }
 }
 
 void nsLayoutStylesheetCache::LoadSheetFromSharedMemory(
     const char* aURL, RefPtr<StyleSheet>* aSheet, SheetParsingMode aParsingMode,
     Shm* aSharedMemory, Header* aHeader, UserAgentStyleSheetID aSheetID) {
   auto i = size_t(aSheetID);
 
-  auto sheet = MakeRefPtr<StyleSheet>(
-      aParsingMode, CORS_NONE, mozilla::net::RP_Unset, dom::SRIMetadata());
+  auto sheet =
+      MakeRefPtr<StyleSheet>(aParsingMode, CORS_NONE, dom::SRIMetadata());
 
   nsCOMPtr<nsIURI> uri;
   MOZ_ALWAYS_SUCCEEDS(NS_NewURI(getter_AddRefs(uri), aURL));
 
   sheet->SetPrincipal(nsContentUtils::GetSystemPrincipal());
   sheet->SetURIs(uri, uri, uri);
   sheet->SetSharedContents(aSharedMemory, aHeader->mSheets[i]);
   sheet->SetComplete();
 
+  nsCOMPtr<nsIReferrerInfo> referrerInfo =
+      dom::ReferrerInfo::CreateForExternalCSSResources(sheet);
+  sheet->SetReferrerInfo(referrerInfo);
   URLExtraData::sShared[i] = sheet->URLData();
 
   *aSheet = sheet.forget();
 }
 
 void nsLayoutStylesheetCache::InitSharedSheetsInParent() {
   MOZ_ASSERT(XRE_IsParentProcess());
 
@@ -529,18 +532,17 @@ void nsLayoutStylesheetCache::Invalidate
   if (gStyleCache) {
     gStyleCache->mContentPreferenceSheet = nullptr;
     gStyleCache->mChromePreferenceSheet = nullptr;
   }
 }
 
 void nsLayoutStylesheetCache::BuildPreferenceSheet(
     RefPtr<StyleSheet>* aSheet, const PreferenceSheet::Prefs& aPrefs) {
-  *aSheet = new StyleSheet(eAgentSheetFeatures, CORS_NONE,
-                           mozilla::net::RP_Unset, dom::SRIMetadata());
+  *aSheet = new StyleSheet(eAgentSheetFeatures, CORS_NONE, dom::SRIMetadata());
 
   StyleSheet* sheet = *aSheet;
 
   nsCOMPtr<nsIURI> uri;
   NS_NewURI(getter_AddRefs(uri), "about:PreferenceStyleSheet");
   MOZ_ASSERT(uri, "URI creation shouldn't fail");
 
   sheet->SetURIs(uri, uri, uri);
--- a/layout/style/test/gtest/StyloParsingBench.cpp
+++ b/layout/style/test/gtest/StyloParsingBench.cpp
@@ -7,17 +7,17 @@
 #include "gtest/gtest.h"
 #include "gtest/MozGTestBench.h"
 #include "nsString.h"
 #include "ExampleStylesheet.h"
 #include "ServoBindings.h"
 #include "mozilla/Encoding.h"
 #include "mozilla/NullPrincipalURI.h"
 #include "mozilla/css/SheetParsingMode.h"
-#include "mozilla/net/ReferrerPolicy.h"
+#include "ReferrerInfo.h"
 #include "nsCSSValue.h"
 
 using namespace mozilla;
 using namespace mozilla::css;
 using namespace mozilla::dom;
 using namespace mozilla::net;
 
 // Bug 1436018 - Disable Stylo microbenchmark on Windows
@@ -28,50 +28,54 @@ using namespace mozilla::net;
 #  define GETPROPERTY_REPETITIONS (1000 * 1000)
 
 static void ServoParsingBench(const StyleUseCounters* aCounters) {
   auto css = AsBytes(MakeStringSpan(EXAMPLE_STYLESHEET));
   nsCString cssStr;
   cssStr.Append(css);
   ASSERT_EQ(Encoding::UTF8ValidUpTo(css), css.Length());
 
-  RefPtr<URLExtraData> data = new URLExtraData(
-      NullPrincipalURI::Create(), nullptr,
-      NullPrincipal::CreateWithoutOriginAttributes(), mozilla::net::RP_Unset);
+  nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo(nullptr);
+  RefPtr<URLExtraData> data =
+      new URLExtraData(NullPrincipalURI::Create(), referrerInfo.forget(),
+                       NullPrincipal::CreateWithoutOriginAttributes());
   for (int i = 0; i < PARSING_REPETITIONS; i++) {
     RefPtr<RawServoStyleSheetContents> stylesheet =
         Servo_StyleSheet_FromUTF8Bytes(
             nullptr, nullptr, nullptr, &cssStr, eAuthorSheetFeatures, data, 0,
             eCompatibility_FullStandards, nullptr, aCounters)
             .Consume();
   }
 }
 
 static void ServoSetPropertyByIdBench(const nsACString& css) {
   RefPtr<RawServoDeclarationBlock> block =
       Servo_DeclarationBlock_CreateEmpty().Consume();
-  RefPtr<URLExtraData> data = new URLExtraData(
-      NullPrincipalURI::Create(), nullptr,
-      NullPrincipal::CreateWithoutOriginAttributes(), mozilla::net::RP_Unset);
+  nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo(nullptr);
+  RefPtr<URLExtraData> data =
+      new URLExtraData(NullPrincipalURI::Create(), referrerInfo.forget(),
+                       NullPrincipal::CreateWithoutOriginAttributes());
   ASSERT_TRUE(IsUTF8(css));
 
   for (int i = 0; i < SETPROPERTY_REPETITIONS; i++) {
     Servo_DeclarationBlock_SetPropertyById(
         block, eCSSProperty_width, &css,
         /* is_important = */ false, data, ParsingMode::Default,
         eCompatibility_FullStandards, nullptr, {});
   }
 }
 
 static void ServoGetPropertyValueById() {
   RefPtr<RawServoDeclarationBlock> block =
       Servo_DeclarationBlock_CreateEmpty().Consume();
-  RefPtr<URLExtraData> data = new URLExtraData(
-      NullPrincipalURI::Create(), nullptr,
-      NullPrincipal::CreateWithoutOriginAttributes(), mozilla::net::RP_Unset);
+
+  nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo(nullptr);
+  RefPtr<URLExtraData> data =
+      new URLExtraData(NullPrincipalURI::Create(), referrerInfo.forget(),
+                       NullPrincipal::CreateWithoutOriginAttributes());
   NS_NAMED_LITERAL_CSTRING(css_, "10px");
   const nsACString& css = css_;
   Servo_DeclarationBlock_SetPropertyById(
       block, eCSSProperty_width, &css,
       /* is_important = */ false, data, ParsingMode::Default,
       eCompatibility_FullStandards, nullptr, {});
 
   for (int i = 0; i < GETPROPERTY_REPETITIONS; i++) {
--- a/layout/svg/SVGObserverUtils.cpp
+++ b/layout/svg/SVGObserverUtils.cpp
@@ -33,20 +33,19 @@
 #include "SVGUseElement.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 bool URLAndReferrerInfo::operator==(const URLAndReferrerInfo& aRHS) const {
   bool uriEqual = false, referrerEqual = false;
   this->mURI->Equals(aRHS.mURI, &uriEqual);
-  this->mReferrer->Equals(aRHS.mReferrer, &referrerEqual);
+  this->mReferrerInfo->Equals(aRHS.mReferrerInfo, &referrerEqual);
 
-  return uriEqual && referrerEqual &&
-         this->mReferrerPolicy == aRHS.mReferrerPolicy;
+  return uriEqual && referrerEqual;
 }
 
 class URLAndReferrerInfoHashKey : public PLDHashEntryHdr {
  public:
   using KeyType = const URLAndReferrerInfo*;
   using KeyTypePointer = const URLAndReferrerInfo*;
 
   explicit URLAndReferrerInfoHashKey(const URLAndReferrerInfo* aKey)
@@ -76,19 +75,19 @@ class URLAndReferrerInfoHashKey : public
   static PLDHashNumber HashKey(const URLAndReferrerInfo* aKey) {
     if (!aKey) {
       // If the key is null, return hash for empty string.
       return HashString(EmptyCString());
     }
     nsAutoCString urlSpec, referrerSpec;
     // nsURIHashKey ignores GetSpec() failures, so we do too:
     Unused << aKey->GetURI()->GetSpec(urlSpec);
-    Unused << aKey->GetReferrer()->GetSpec(referrerSpec);
-    auto refPolicy = aKey->GetReferrerPolicy();
-    return AddToHash(HashString(urlSpec), HashString(referrerSpec), refPolicy);
+    return AddToHash(
+        HashString(urlSpec),
+        static_cast<ReferrerInfo*>(aKey->GetReferrerInfo())->Hash());
   }
 
   enum { ALLOW_MEMMOVE = true };
 
  protected:
   RefPtr<const URLAndReferrerInfo> mKey;
 };
 
@@ -323,26 +322,24 @@ class SVGIDRenderingObserver : public SV
  * benefits/necessity of maintaining a second observer list.
  */
 SVGIDRenderingObserver::SVGIDRenderingObserver(URLAndReferrerInfo* aURI,
                                                nsIContent* aObservingContent,
                                                bool aReferenceImage)
     : mObservedElementTracker(this) {
   // Start watching the target element
   nsCOMPtr<nsIURI> uri;
-  nsCOMPtr<nsIURI> referrer;
-  uint32_t referrerPolicy = mozilla::net::RP_Unset;
+  nsCOMPtr<nsIReferrerInfo> referrerInfo;
   if (aURI) {
     uri = aURI->GetURI();
-    referrer = aURI->GetReferrer();
-    referrerPolicy = aURI->GetReferrerPolicy();
+    referrerInfo = aURI->GetReferrerInfo();
   }
 
   mObservedElementTracker.ResetToURIFragmentID(
-      aObservingContent, uri, referrer, referrerPolicy, true, aReferenceImage);
+      aObservingContent, uri, referrerInfo, true, aReferenceImage);
   StartObserving();
 }
 
 void SVGIDRenderingObserver::OnRenderingChange() {
   if (mObservedElementTracker.get() && mInObserverSet) {
     SVGObserverUtils::RemoveRenderingObserver(mObservedElementTracker.get(),
                                               this);
     mInObserverSet = false;
@@ -1373,19 +1370,20 @@ SVGGeometryElement* SVGObserverUtils::Ge
 
     nsCOMPtr<nsIURI> targetURI;
     nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI), href,
                                               content->GetUncomposedDoc(),
                                               content->GetBaseURI());
 
     // There's no clear refererer policy spec about non-CSS SVG resource
     // references Bug 1415044 to investigate which referrer we should use
+    nsCOMPtr<nsIReferrerInfo> referrerInfo =
+        ReferrerInfo::CreateForSVGResources(content->OwnerDoc());
     RefPtr<URLAndReferrerInfo> target =
-        new URLAndReferrerInfo(targetURI, content->OwnerDoc()->GetDocumentURI(),
-                               content->OwnerDoc()->GetReferrerPolicy());
+        new URLAndReferrerInfo(targetURI, referrerInfo);
 
     property =
         GetEffectProperty(target, aTextPathFrame, HrefAsTextPathProperty());
     if (!property) {
       return nullptr;
     }
   }
 
@@ -1423,19 +1421,20 @@ nsIFrame* SVGObserverUtils::GetAndObserv
     nsIContent* content = aFrame->GetContent();
     nsCOMPtr<nsIURI> targetURI;
     nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI), href,
                                               content->GetUncomposedDoc(),
                                               content->GetBaseURI());
 
     // There's no clear refererer policy spec about non-CSS SVG resource
     // references.  Bug 1415044 to investigate which referrer we should use.
+    nsCOMPtr<nsIReferrerInfo> referrerInfo =
+        ReferrerInfo::CreateForSVGResources(content->OwnerDoc());
     RefPtr<URLAndReferrerInfo> target =
-        new URLAndReferrerInfo(targetURI, content->OwnerDoc()->GetDocumentURI(),
-                               content->OwnerDoc()->GetReferrerPolicy());
+        new URLAndReferrerInfo(targetURI, referrerInfo);
 
     observer = GetEffectProperty(target, aFrame, HrefToTemplateProperty());
   }
 
   return observer ? observer->GetAndObserveReferencedFrame() : nullptr;
 }
 
 void SVGObserverUtils::RemoveTemplateObserver(nsIFrame* aFrame) {
@@ -1456,19 +1455,20 @@ Element* SVGObserverUtils::GetAndObserve
 
   nsAutoString elementId =
       NS_LITERAL_STRING("#") + nsDependentAtomString(aHref);
   nsCOMPtr<nsIURI> targetURI;
   nsContentUtils::NewURIWithDocumentCharset(
       getter_AddRefs(targetURI), elementId,
       aFrame->GetContent()->GetUncomposedDoc(),
       aFrame->GetContent()->GetBaseURI());
-  RefPtr<URLAndReferrerInfo> url = new URLAndReferrerInfo(
-      targetURI, aFrame->GetContent()->OwnerDoc()->GetDocumentURI(),
-      aFrame->GetContent()->OwnerDoc()->GetReferrerPolicy());
+  nsCOMPtr<nsIReferrerInfo> referrerInfo =
+      ReferrerInfo::CreateForSVGResources(aFrame->GetContent()->OwnerDoc());
+  RefPtr<URLAndReferrerInfo> url =
+      new URLAndReferrerInfo(targetURI, referrerInfo);
 
   SVGMozElementObserver* observer =
       static_cast<SVGMozElementObserver*>(hashtable->GetWeak(url));
   if (!observer) {
     observer = new SVGMozElementObserver(url, aFrame, /* aWatchImage */ true);
     hashtable->Put(url, observer);
   }
   return observer->GetAndObserveReferencedElement();
--- a/layout/svg/SVGObserverUtils.h
+++ b/layout/svg/SVGObserverUtils.h
@@ -11,16 +11,17 @@
 #include "mozilla/dom/IDTracker.h"
 #include "FrameProperties.h"
 #include "mozilla/dom/Element.h"
 #include "nsID.h"
 #include "nsIFrame.h"
 #include "nsIMutationObserver.h"
 #include "nsISupportsBase.h"
 #include "nsISupportsImpl.h"
+#include "nsIReferrerInfo.h"
 #include "nsStringFwd.h"
 #include "nsStubMutationObserver.h"
 #include "nsSVGUtils.h"
 #include "nsCycleCollectionParticipant.h"
 
 class nsAtom;
 class nsIURI;
 class nsSVGClipPathFrame;
@@ -40,45 +41,38 @@ namespace mozilla {
 /*
  * This class contains URL and referrer information (referrer and referrer
  * policy).
  * We use it to pass to svg system instead of nsIURI. The object brings referrer
  * and referrer policy so we can send correct Referer headers.
  */
 class URLAndReferrerInfo {
  public:
-  URLAndReferrerInfo(nsIURI* aURI, nsIURI* aReferrer,
-                     mozilla::net::ReferrerPolicy aReferrerPolicy)
-      : mURI(aURI), mReferrer(aReferrer), mReferrerPolicy(aReferrerPolicy) {
+  URLAndReferrerInfo(nsIURI* aURI, nsIReferrerInfo* aReferrerInfo)
+      : mURI(aURI), mReferrerInfo(aReferrerInfo) {
     MOZ_ASSERT(aURI);
   }
 
   URLAndReferrerInfo(nsIURI* aURI, const URLExtraData& aExtraData)
-      : mURI(aURI),
-        mReferrer(aExtraData.GetReferrer()),
-        mReferrerPolicy(aExtraData.GetReferrerPolicy()) {
+      : mURI(aURI), mReferrerInfo(aExtraData.ReferrerInfo()) {
     MOZ_ASSERT(aURI);
   }
 
   NS_INLINE_DECL_REFCOUNTING(URLAndReferrerInfo)
 
   nsIURI* GetURI() const { return mURI; }
-  nsIURI* GetReferrer() const { return mReferrer; }
-  mozilla::net::ReferrerPolicy GetReferrerPolicy() const {
-    return mReferrerPolicy;
-  }
+  nsIReferrerInfo* GetReferrerInfo() const { return mReferrerInfo; }
 
   bool operator==(const URLAndReferrerInfo& aRHS) const;
 
  private:
   ~URLAndReferrerInfo() = default;
 
   nsCOMPtr<nsIURI> mURI;
-  nsCOMPtr<nsIURI> mReferrer;
-  mozilla::net::ReferrerPolicy mReferrerPolicy;
+  nsCOMPtr<nsIReferrerInfo> mReferrerInfo;
 };
 
 /**
  * This interface allows us to be notified when a piece of SVG content is
  * re-rendered.
  *
  * Concrete implementations of this base class need to implement
  * GetReferencedElementWithoutObserving to specify the SVG element that
--- a/layout/svg/nsSVGFilterInstance.cpp
+++ b/layout/svg/nsSVGFilterInstance.cpp
@@ -142,18 +142,17 @@ nsSVGFilterFrame* nsSVGFilterInstance::G
         "an StyleFilter of type URL should have a non-null URL");
     return nullptr;
   }
 
   // Look up the filter element by URL.
   IDTracker idTracker;
   bool watch = false;
   idTracker.ResetToURIFragmentID(
-      mTargetContent, url, mFilter.AsUrl().ExtraData().GetReferrer(),
-      mFilter.AsUrl().ExtraData().GetReferrerPolicy(), watch);
+      mTargetContent, url, mFilter.AsUrl().ExtraData().ReferrerInfo(), watch);
   Element* element = idTracker.get();
   if (!element) {
     // The URL points to no element.
     return nullptr;
   }
 
   // Get the frame of the filter element.
   nsIFrame* frame = element->GetPrimaryFrame();
--- a/layout/xul/nsImageBoxFrame.cpp
+++ b/layout/xul/nsImageBoxFrame.cpp
@@ -237,21 +237,23 @@ void nsImageBoxFrame::UpdateImage() {
       nsContentUtils::GetContentPolicyTypeForUIImageLoading(
           mContent, getter_AddRefs(triggeringPrincipal), contentPolicyType,
           &requestContextID);
 
       nsCOMPtr<nsIURI> uri;
       nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(uri), src, doc,
                                                 mContent->GetBaseURI());
       if (uri) {
+        nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo();
+        referrerInfo->InitWithNode(mContent);
+
         nsresult rv = nsContentUtils::LoadImage(
             uri, mContent, doc, triggeringPrincipal, requestContextID,
-            doc->GetDocumentURIAsReferrer(), doc->GetReferrerPolicy(),
-            mListener, mLoadFlags, EmptyString(), getter_AddRefs(mImageRequest),
-            contentPolicyType);
+            referrerInfo, mListener, mLoadFlags, EmptyString(),
+            getter_AddRefs(mImageRequest), contentPolicyType);
 
         if (NS_SUCCEEDED(rv) && mImageRequest) {
           nsLayoutUtils::RegisterImageRequestIfAnimated(
               presContext, mImageRequest, &mRequestRegistered);
         }
       }
     }
   } else {
--- a/layout/xul/tree/nsTreeBodyFrame.cpp
+++ b/layout/xul/tree/nsTreeBodyFrame.cpp
@@ -1913,21 +1913,23 @@ nsresult nsTreeBodyFrame::GetImage(int32
       styleRequest->SyncClone(imgNotificationObserver, doc,
                               getter_AddRefs(imageRequest));
     } else {
       nsCOMPtr<nsIURI> srcURI;
       nsContentUtils::NewURIWithDocumentCharset(
           getter_AddRefs(srcURI), imageSrc, doc, mContent->GetBaseURI());
       if (!srcURI) return NS_ERROR_FAILURE;
 
+      nsCOMPtr<nsIReferrerInfo> referrerInfo = new mozilla::dom::ReferrerInfo();
+      referrerInfo->InitWithDocument(doc);
+
       // XXXbz what's the origin principal for this stuff that comes from our
       // view?  I guess we should assume that it's the node's principal...
       nsresult rv = nsContentUtils::LoadImage(
-          srcURI, mContent, doc, mContent->NodePrincipal(), 0,
-          doc->GetDocumentURIAsReferrer(), doc->GetReferrerPolicy(),
+          srcURI, mContent, doc, mContent->NodePrincipal(), 0, referrerInfo,
           imgNotificationObserver, nsIRequest::LOAD_NORMAL, EmptyString(),
           getter_AddRefs(imageRequest));
       NS_ENSURE_SUCCESS(rv, rv);
     }
     listener->UnsuppressInvalidation();
 
     if (!imageRequest) return NS_ERROR_FAILURE;