Bug 704320 - apply referrer policies to image loads (r=seth)
authorSid Stamm <sstamm@mozilla.com>
Tue, 18 Nov 2014 08:46:53 -0500
changeset 216286 3511a31f2cd316c86564127f6d544d3fc6a7d73a
parent 216285 dd257f17530cb90837c196cecb31abd33e70b3c5
child 216287 5f0f56a36128be35208c853416ebbed793f08d06
push id27845
push userkwierso@gmail.com
push dateWed, 19 Nov 2014 02:08:01 +0000
treeherdermozilla-central@64e7a6391916 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersseth
bugs704320
milestone36.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 704320 - apply referrer policies to image loads (r=seth)
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
dom/base/nsDocument.cpp
dom/base/nsDocument.h
dom/base/nsIDocument.h
dom/base/nsImageLoadingContent.cpp
dom/xbl/nsXBLResourceLoader.cpp
embedding/browser/nsContextMenuInfo.cpp
image/public/imgILoader.idl
image/src/imgLoader.cpp
image/src/imgLoader.h
image/src/imgRequest.cpp
image/src/imgRequest.h
image/test/unit/async_load_tests.js
image/test/unit/test_private_channel.js
layout/generic/nsImageFrame.cpp
layout/style/ImageLoader.cpp
layout/xul/nsImageBoxFrame.cpp
layout/xul/tree/nsTreeBodyFrame.cpp
parser/html/nsHtml5TreeOpExecutor.cpp
toolkit/system/gnome/nsAlertsIconListener.cpp
widget/cocoa/OSXNotificationCenter.mm
widget/cocoa/nsMenuItemIconX.mm
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -2980,16 +2980,17 @@ nsContentUtils::IsImageInCache(nsIURI* a
     nsresult rv = cache->FindEntryProperties(aURI, getter_AddRefs(props));
     return (NS_SUCCEEDED(rv) && props);
 }
 
 // static
 nsresult
 nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
                           nsIPrincipal* aLoadingPrincipal, nsIURI* aReferrer,
+                          net::ReferrerPolicy aReferrerPolicy,
                           imgINotificationObserver* aObserver, int32_t aLoadFlags,
                           const nsAString& initiatorType,
                           imgRequestProxy** aRequest,
                           uint32_t aContentPolicyType)
 {
   NS_PRECONDITION(aURI, "Must have a URI");
   NS_PRECONDITION(aLoadingDocument, "Must have a document");
   NS_PRECONDITION(aLoadingPrincipal, "Must have a principal");
@@ -3011,16 +3012,17 @@ nsContentUtils::LoadImage(nsIURI* aURI, 
   // Make the URI immutable so people won't change it under us
   NS_TryToSetImmutable(aURI);
 
   // XXXbz using "documentURI" for the initialDocumentURI is not quite
   // right, but the best we can do here...
   return imgLoader->LoadImage(aURI,                 /* uri to load */
                               documentURI,          /* initialDocumentURI */
                               aReferrer,            /* referrer */
+                              aReferrerPolicy,      /* referrer policy */
                               aLoadingPrincipal,    /* loading principal */
                               loadGroup,            /* loadgroup */
                               aObserver,            /* imgINotificationObserver */
                               aLoadingDocument,     /* uniquification key */
                               aLoadFlags,           /* load flags */
                               nullptr,              /* cache key */
                               aContentPolicyType,   /* content policy type */
                               initiatorType,        /* the load initiator */
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -25,16 +25,17 @@
 #include "mozilla/TimeStamp.h"
 #include "nsContentListDeclarations.h"
 #include "nsMathUtils.h"
 #include "nsTArrayForwardDeclare.h"
 #include "Units.h"
 #include "mozilla/dom/AutocompleteInfoBinding.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/FloatingPoint.h"
+#include "mozilla/net/ReferrerPolicy.h"
 #include "nsIContentPolicy.h"
 
 #if defined(XP_WIN)
 // Undefine LoadImage to prevent naming conflict with Windows.
 #undef LoadImage
 #endif
 
 class imgICache;
@@ -614,26 +615,29 @@ public:
    * Method to start an image load.  This does not do any security checks.
    * 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 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 aObserver the observer for the image load
    * @param aLoadFlags the load flags to use.  See nsIRequest
    * @param [aContentPolicyType=nsIContentPolicy::TYPE_IMAGE] (Optional)
    *        The CP content type to use
    * @return the imgIRequest for the image load
    */
   static nsresult LoadImage(nsIURI* aURI,
                             nsIDocument* aLoadingDocument,
                             nsIPrincipal* aLoadingPrincipal,
                             nsIURI* aReferrer,
+                            mozilla::net::ReferrerPolicy aReferrerPolicy,
                             imgINotificationObserver* aObserver,
                             int32_t aLoadFlags,
                             const nsAString& initiatorType,
                             imgRequestProxy** aRequest,
                             uint32_t aContentPolicyType = nsIContentPolicy::TYPE_IMAGE);
 
   /**
    * Obtain an image loader that respects the given document/channel's privacy status.
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -9496,17 +9496,18 @@ FireOrClearDelayedEvents(nsTArray<nsCOMP
                     aDocuments[i]->GetInnerWindow()->IsCurrentInnerWindow();
         shell->FireOrClearDelayedEvents(fire);
       }
     }
   }
 }
 
 void
-nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr)
+nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr,
+                              ReferrerPolicy aReferrerPolicy)
 {
   // Early exit if the img is already present in the img-cache
   // which indicates that the "real" load has already started and
   // that we shouldn't preload it.
   int16_t blockingStatus;
   if (nsContentUtils::IsImageInCache(uri, static_cast<nsIDocument *>(this)) ||
       !nsContentUtils::CanLoadImage(uri, static_cast<nsIDocument *>(this),
                                     this, NodePrincipal(), &blockingStatus)) {
@@ -9530,16 +9531,17 @@ nsDocument::MaybePreLoadImage(nsIURI* ur
 
   // Image not in cache - trigger preload
   nsRefPtr<imgRequestProxy> request;
   nsresult rv =
     nsContentUtils::LoadImage(uri,
                               this,
                               NodePrincipal(),
                               mDocumentURI, // uri of document used as referrer
+                              aReferrerPolicy,
                               nullptr,       // no observer
                               loadFlags,
                               NS_LITERAL_STRING("img"),
                               getter_AddRefs(request));
 
   // Pin image-reference to avoid evicting it from the img-cache before
   // the "real" load occurs. Unpinned in DispatchContentLoadedEvents and
   // unlink
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -1087,17 +1087,18 @@ public:
 
   nsresult CloneDocHelper(nsDocument* clone) const;
 
   void MaybeInitializeFinalizeFrameLoaders();
 
   void MaybeEndOutermostXBLUpdate();
 
   virtual void MaybePreLoadImage(nsIURI* uri,
-                                 const nsAString &aCrossOriginAttr) MOZ_OVERRIDE;
+                                 const nsAString &aCrossOriginAttr,
+                                 ReferrerPolicy aReferrerPolicy) MOZ_OVERRIDE;
 
   virtual void PreloadStyle(nsIURI* uri, const nsAString& charset,
                             const nsAString& aCrossOriginAttr,
                             ReferrerPolicy aReferrerPolicy) MOZ_OVERRIDE;
 
   virtual nsresult LoadChromeSheetSync(nsIURI* uri, bool isAgentSheet,
                                        mozilla::CSSStyleSheet** sheet) MOZ_OVERRIDE;
 
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -1892,17 +1892,18 @@ public:
 
   /**
    * Called by nsParser to preload images. Can be removed and code moved
    * to nsPreloadURIs::PreloadURIs() in file nsParser.cpp whenever the
    * parser-module is linked with gklayout-module.  aCrossOriginAttr should
    * be a void string if the attr is not present.
    */
   virtual void MaybePreLoadImage(nsIURI* uri,
-                                 const nsAString& aCrossOriginAttr) = 0;
+                                 const nsAString& aCrossOriginAttr,
+                                 ReferrerPolicy aReferrerPolicy) = 0;
 
   /**
    * Called by nsParser to preload style sheets.  Can also be merged into the
    * parser if and when the parser is merged with libgklayout.  aCrossOriginAttr
    * should be a void string if the attr is not present.
    */
   virtual void PreloadStyle(nsIURI* aURI, const nsAString& aCharset,
                             const nsAString& aCrossOriginAttr,
--- a/dom/base/nsImageLoadingContent.cpp
+++ b/dom/base/nsImageLoadingContent.cpp
@@ -882,16 +882,17 @@ nsImageLoadingContent::LoadImage(nsIURI*
   // Not blocked. Do the load.
   nsRefPtr<imgRequestProxy>& req = PrepareNextRequest(aImageLoadType);
   nsCOMPtr<nsIContent> content =
       do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
   nsresult rv;
   rv = nsContentUtils::LoadImage(aNewURI, aDocument,
                                  aDocument->NodePrincipal(),
                                  aDocument->GetDocumentURI(),
+                                 aDocument->GetReferrerPolicy(),
                                  this, loadFlags,
                                  content->LocalName(),
                                  getter_AddRefs(req),
                                  policyType);
 
   if (NS_SUCCEEDED(rv)) {
     TrackImage(req);
     ResetAnimationIfNeeded();
--- a/dom/xbl/nsXBLResourceLoader.cpp
+++ b/dom/xbl/nsXBLResourceLoader.cpp
@@ -115,17 +115,18 @@ nsXBLResourceLoader::LoadResources(bool*
         // We're not permitted to load this image, move on...
         continue;
       }
 
       // Now kick off the image load...
       // Passing nullptr for pretty much everything -- cause we don't care!
       // XXX: initialDocumentURI is nullptr! 
       nsRefPtr<imgRequestProxy> req;
-      nsContentUtils::LoadImage(url, doc, docPrincipal, docURL, nullptr,
+      nsContentUtils::LoadImage(url, doc, docPrincipal, docURL,
+                                doc->GetReferrerPolicy(), nullptr,
                                 nsIRequest::LOAD_BACKGROUND, EmptyString(),
                                 getter_AddRefs(req));
     }
     else if (curr->mType == nsGkAtoms::stylesheet) {
       // Kick off the load of the stylesheet.
 
       // Always load chrome synchronously
       // XXXbz should that still do a content policy check?
--- a/embedding/browser/nsContextMenuInfo.cpp
+++ b/embedding/browser/nsContextMenuInfo.cpp
@@ -289,17 +289,18 @@ nsContextMenuInfo::GetBackgroundImageReq
         if (!bgStringValue.EqualsLiteral("none")) {
           nsCOMPtr<nsIURI> bgUri;
           NS_NewURI(getter_AddRefs(bgUri), bgStringValue);
           NS_ENSURE_TRUE(bgUri, NS_ERROR_FAILURE);
 
           nsRefPtr<imgLoader> il = imgLoader::GetInstance();
           NS_ENSURE_TRUE(il, NS_ERROR_FAILURE);
 
-          return il->LoadImage(bgUri, nullptr, nullptr, principal, nullptr,
+          return il->LoadImage(bgUri, nullptr, nullptr,
+                               doc->GetReferrerPolicy(), principal, nullptr,
                                nullptr, nullptr, nsIRequest::LOAD_NORMAL,
                                nullptr, nsIContentPolicy::TYPE_IMAGE,
                                EmptyString(), aRequest);
         }
       }
 
       // bail if we encounter non-transparent background-color
       computedStyle->GetPropertyCSSValue(NS_LITERAL_STRING("background-color"),
--- a/image/public/imgILoader.idl
+++ b/image/public/imgILoader.idl
@@ -22,29 +22,32 @@ interface nsISimpleEnumerator;
 
 /**
  * imgILoader interface
  *
  * @author Stuart Parmenter <pavlov@netscape.com>
  * @version 0.3
  * @see imagelib2
  */
-[scriptable, builtinclass, uuid(42ef3b0a-cd82-454b-b4c4-f3470014a68b)]
+[scriptable, builtinclass, uuid(e61377d2-910e-4c65-a64b-428d150e1fd1)]
 interface imgILoader : nsISupports
 {
   // Extra flags to pass to loadImage if you want a load to use CORS
   // validation.
   const unsigned long LOAD_CORS_ANONYMOUS = 1 << 16;
   const unsigned long LOAD_CORS_USE_CREDENTIALS = 1 << 17;
 
   /**
    * Start the load and decode of an image.
    * @param aURI the URI to load
    * @param aInitialDocumentURI the URI that 'initiated' the load -- used for 3rd party cookie blocking
    * @param aReferrerURI the 'referring' URI
+   * @param aReferrerPolicy the policy to apply to sending referrers.
+   *           examples: "default", "never", "always", "origin"
+   *           (see W3C referrer-policy spec for valid policy strings)
    * @param aLoadingPrincipal the principal of the loading document
    * @param aLoadGroup Loadgroup to put the image load into
    * @param aObserver the observer (may be null)
    * @param aCX some random data
    * @param aLoadFlags Load flags for the request
    * @param aCacheKey cache key to use for a load if the original
    *                  image came from a request that had post data
    * @param aContentPolicyType [optional] the nsContentPolicyType to
@@ -55,16 +58,17 @@ interface imgILoader : nsISupports
    * ImageLib does NOT keep a strong ref to the observer; this prevents
    * reference cycles.  This means that callers of loadImage should
    * make sure to Cancel() the resulting request before the observer
    * goes away.
    */
   imgIRequest loadImageXPCOM(in nsIURI aURI,
                              in nsIURI aInitialDocumentURL,
                              in nsIURI aReferrerURI,
+                             in AString aReferrerPolicy,
                              in nsIPrincipal aLoadingPrincipal,
                              in nsILoadGroup aLoadGroup,
                              in imgINotificationObserver aObserver,
                              in nsISupports aCX,
                              in nsLoadFlags aLoadFlags,
                              in nsISupports cacheKey,
                              [optional]
                              in nsContentPolicyType aContentPolicyType);
--- a/image/src/imgLoader.cpp
+++ b/image/src/imgLoader.cpp
@@ -43,16 +43,17 @@
 // so we can associate the document URI with the load group.
 // until this point, we have an evil hack:
 #include "nsIHttpChannelInternal.h"
 #include "nsILoadContext.h"
 #include "nsILoadGroupChild.h"
 
 using namespace mozilla;
 using namespace mozilla::image;
+using namespace mozilla::net;
 
 MOZ_DEFINE_MALLOC_SIZE_OF(ImagesMallocSizeOf)
 
 class imgMemoryReporter MOZ_FINAL : public nsIMemoryReporter
 {
   ~imgMemoryReporter() {}
 
 public:
@@ -585,21 +586,28 @@ static bool ShouldRevalidateEntry(imgCac
     }
   }
 
   return bValidateEntry;
 }
 
 // Returns true if this request is compatible with the given CORS mode on the
 // given loading principal, and false if the request may not be reused due
-// to CORS.
+// to CORS.  Also checks the Referrer Policy, since requests with different
+// referrers/policies may generate different responses.
 static bool
-ValidateCORSAndPrincipal(imgRequest* request, bool forcePrincipalCheck,
-                         int32_t corsmode, nsIPrincipal* loadingPrincipal)
+ValidateSecurityInfo(imgRequest* request, bool forcePrincipalCheck,
+                     int32_t corsmode, nsIPrincipal* loadingPrincipal,
+                     ReferrerPolicy referrerPolicy)
 {
+  // If the entry's Referrer Policy doesn't match, we can't use this request.
+  if (referrerPolicy != request->GetReferrerPolicy()) {
+    return false;
+  }
+
   // If the entry's CORS mode doesn't match, or the CORS mode matches but the
   // document principal isn't the same, we can't use this request.
   if (request->GetCORSMode() != corsmode) {
     return false;
   } else if (request->GetCORSMode() != imgIRequest::CORS_NONE ||
              forcePrincipalCheck) {
     nsCOMPtr<nsIPrincipal> otherprincipal = request->GetLoadingPrincipal();
 
@@ -627,16 +635,17 @@ static nsresult NewImageChannel(nsIChann
                                 // create for this channel.  This is an out
                                 // param that should be set to true if this
                                 // channel ends up depending on
                                 // aLoadingPrincipal and false otherwise.
                                 bool *aForcePrincipalCheckForCacheEntry,
                                 nsIURI *aURI,
                                 nsIURI *aInitialDocumentURI,
                                 nsIURI *aReferringURI,
+                                ReferrerPolicy aReferrerPolicy,
                                 nsILoadGroup *aLoadGroup,
                                 const nsCString& aAcceptHeader,
                                 nsLoadFlags aLoadFlags,
                                 nsContentPolicyType aPolicyType,
                                 nsIPrincipal *aLoadingPrincipal,
                                 nsISupports *aRequestingContext)
 {
   nsresult rv;
@@ -723,17 +732,17 @@ static nsresult NewImageChannel(nsIChann
   if (newHttpChannel) {
     newHttpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
                                      aAcceptHeader,
                                      false);
 
     nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal = do_QueryInterface(newHttpChannel);
     NS_ENSURE_TRUE(httpChannelInternal, NS_ERROR_UNEXPECTED);
     httpChannelInternal->SetDocumentURI(aInitialDocumentURI);
-    newHttpChannel->SetReferrer(aReferringURI);
+    newHttpChannel->SetReferrerWithPolicy(aReferringURI, aReferrerPolicy);
   }
 
   // Image channels are loaded by default with reduced priority.
   nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(*aResult);
   if (p) {
     uint32_t priority = nsISupportsPriority::PRIORITY_LOW;
 
     if (aLoadFlags & nsIRequest::LOAD_BACKGROUND)
@@ -1452,16 +1461,17 @@ void imgLoader::CheckCacheLimits(imgCach
       RemoveFromCache(entry);
   }
 }
 
 bool imgLoader::ValidateRequestWithNewChannel(imgRequest *request,
                                                 nsIURI *aURI,
                                                 nsIURI *aInitialDocumentURI,
                                                 nsIURI *aReferrerURI,
+                                                ReferrerPolicy aReferrerPolicy,
                                                 nsILoadGroup *aLoadGroup,
                                                 imgINotificationObserver *aObserver,
                                                 nsISupports *aCX,
                                                 nsLoadFlags aLoadFlags,
                                                 nsContentPolicyType aLoadPolicyType,
                                                 imgRequestProxy **aProxyRequest,
                                                 nsIPrincipal* aLoadingPrincipal,
                                                 int32_t aCORSMode)
@@ -1502,16 +1512,17 @@ bool imgLoader::ValidateRequestWithNewCh
     // cache.
     nsCOMPtr<nsIChannel> newChannel;
     bool forcePrincipalCheck;
     rv = NewImageChannel(getter_AddRefs(newChannel),
                          &forcePrincipalCheck,
                          aURI,
                          aInitialDocumentURI,
                          aReferrerURI,
+                         aReferrerPolicy,
                          aLoadGroup,
                          mAcceptHeader,
                          aLoadFlags,
                          aLoadPolicyType,
                          aLoadingPrincipal,
                          aCX);
     if (NS_FAILED(rv)) {
       return false;
@@ -1579,16 +1590,17 @@ bool imgLoader::ValidateRequestWithNewCh
     return NS_SUCCEEDED(rv);
   }
 }
 
 bool imgLoader::ValidateEntry(imgCacheEntry *aEntry,
                                 nsIURI *aURI,
                                 nsIURI *aInitialDocumentURI,
                                 nsIURI *aReferrerURI,
+                                ReferrerPolicy aReferrerPolicy,
                                 nsILoadGroup *aLoadGroup,
                                 imgINotificationObserver *aObserver,
                                 nsISupports *aCX,
                                 nsLoadFlags aLoadFlags,
                                 nsContentPolicyType aLoadPolicyType,
                                 bool aCanMakeNewChannel,
                                 imgRequestProxy **aProxyRequest,
                                 nsIPrincipal* aLoadingPrincipal,
@@ -1624,18 +1636,19 @@ bool imgLoader::ValidateEntry(imgCacheEn
     }
   }
 
   nsRefPtr<imgRequest> request(aEntry->GetRequest());
 
   if (!request)
     return false;
 
-  if (!ValidateCORSAndPrincipal(request, aEntry->ForcePrincipalCheck(),
-                                aCORSMode, aLoadingPrincipal))
+  if (!ValidateSecurityInfo(request, aEntry->ForcePrincipalCheck(),
+                            aCORSMode, aLoadingPrincipal,
+                            aReferrerPolicy))
     return false;
 
   // data URIs are immutable and by their nature can't leak data, so we can
   // just return true in that case.  Doing so would mean that shift-reload
   // doesn't reload data URI documents/images though (which is handy for
   // debugging during gecko development) so we make an exception in that case.
   nsAutoCString scheme;
   aURI->GetScheme(scheme);
@@ -1694,17 +1707,18 @@ bool imgLoader::ValidateEntry(imgCacheEn
             address_of(request)));
     return false;
   }
 
   if (validateRequest && aCanMakeNewChannel) {
     LOG_SCOPE(GetImgLog(), "imgLoader::ValidateRequest |cache hit| must validate");
 
     return ValidateRequestWithNewChannel(request, aURI, aInitialDocumentURI,
-                                         aReferrerURI, aLoadGroup, aObserver,
+                                         aReferrerURI, aReferrerPolicy,
+                                         aLoadGroup, aObserver,
                                          aCX, aLoadFlags, aLoadPolicyType,
                                          aProxyRequest, aLoadingPrincipal,
                                          aCORSMode);
   }
 
   return !validateRequest;
 }
 
@@ -1865,58 +1879,62 @@ void imgLoader::RemoveFromUncachedImages
 
 #define LOAD_FLAGS_VALIDATE_MASK (nsIRequest::VALIDATE_ALWAYS |   \
                                   nsIRequest::VALIDATE_NEVER |    \
                                   nsIRequest::VALIDATE_ONCE_PER_SESSION)
 
 NS_IMETHODIMP imgLoader::LoadImageXPCOM(nsIURI *aURI,
                                    nsIURI *aInitialDocumentURI,
                                    nsIURI *aReferrerURI,
+                                   const nsAString& aReferrerPolicy,
                                    nsIPrincipal* aLoadingPrincipal,
                                    nsILoadGroup *aLoadGroup,
                                    imgINotificationObserver *aObserver,
                                    nsISupports *aCX,
                                    nsLoadFlags aLoadFlags,
                                    nsISupports *aCacheKey,
                                    nsContentPolicyType aContentPolicyType,
                                    imgIRequest **_retval)
 {
     // Optional parameter, so defaults to 0 (== TYPE_INVALID)
     if (!aContentPolicyType) {
       aContentPolicyType = nsIContentPolicy::TYPE_IMAGE;
     }
     imgRequestProxy *proxy;
-    nsresult result = LoadImage(aURI,
-                                aInitialDocumentURI,
-                                aReferrerURI,
-                                aLoadingPrincipal,
-                                aLoadGroup,
-                                aObserver,
-                                aCX,
-                                aLoadFlags,
-                                aCacheKey,
-                                aContentPolicyType,
-                                EmptyString(),
-                                &proxy);
+    ReferrerPolicy refpol = ReferrerPolicyFromString(aReferrerPolicy);
+    nsresult rv = LoadImage(aURI,
+                            aInitialDocumentURI,
+                            aReferrerURI,
+                            refpol,
+                            aLoadingPrincipal,
+                            aLoadGroup,
+                            aObserver,
+                            aCX,
+                            aLoadFlags,
+                            aCacheKey,
+                            aContentPolicyType,
+                            EmptyString(),
+                            &proxy);
     *_retval = proxy;
-    return result;
+    return rv;
 }
 
 // imgIRequest loadImage(in nsIURI aURI,
 //                       in nsIURI aInitialDocumentURL,
 //                       in nsIURI aReferrerURI,
 //                       in nsIPrincipal aLoadingPrincipal,
 //                       in nsILoadGroup aLoadGroup,
 //                       in imgINotificationObserver aObserver,
 //                       in nsISupports aCX,
 //                       in nsLoadFlags aLoadFlags,
 //                       in nsISupports cacheKey);
 nsresult imgLoader::LoadImage(nsIURI *aURI,
                               nsIURI *aInitialDocumentURI,
                               nsIURI *aReferrerURI,
+                              ReferrerPolicy aReferrerPolicy,
                               nsIPrincipal* aLoadingPrincipal,
                               nsILoadGroup *aLoadGroup,
                               imgINotificationObserver *aObserver,
                               nsISupports *aCX,
                               nsLoadFlags aLoadFlags,
                               nsISupports *aCacheKey,
                               nsContentPolicyType aContentPolicyType,
                               const nsAString& initiatorType,
@@ -1992,18 +2010,18 @@ nsresult imgLoader::LoadImage(nsIURI *aU
   // Look in the cache for our URI, and then validate it.
   // XXX For now ignore aCacheKey. We will need it in the future
   // for correctly dealing with image load requests that are a result
   // of post data.
   imgCacheTable &cache = GetCache(aURI);
 
   if (cache.Get(spec, getter_AddRefs(entry)) && entry) {
     if (ValidateEntry(entry, aURI, aInitialDocumentURI, aReferrerURI,
-                      aLoadGroup, aObserver, aCX, requestFlags,
-                      aContentPolicyType, true, _retval,
+                      aReferrerPolicy, aLoadGroup, aObserver, aCX,
+                      requestFlags, aContentPolicyType, true, _retval,
                       aLoadingPrincipal, corsmode)) {
       request = entry->GetRequest();
 
       // If this entry has no proxies, its request has no reference to the entry.
       if (entry->HasNoProxies()) {
         LOG_FUNC_WITH_PARAM(GetImgLog(), "imgLoader::LoadImage() adding proxyless entry", "uri", spec.get());
         NS_ABORT_IF_FALSE(!request->HasCacheEntry(), "Proxyless entry's request has cache entry!");
         request->SetCacheEntry(entry);
@@ -2033,16 +2051,17 @@ nsresult imgLoader::LoadImage(nsIURI *aU
     LOG_SCOPE(GetImgLog(), "imgLoader::LoadImage |cache miss|");
 
     bool forcePrincipalCheck;
     rv = NewImageChannel(getter_AddRefs(newChannel),
                          &forcePrincipalCheck,
                          aURI,
                          aInitialDocumentURI,
                          aReferrerURI,
+                         aReferrerPolicy,
                          aLoadGroup,
                          mAcceptHeader,
                          requestFlags,
                          aContentPolicyType,
                          aLoadingPrincipal,
                          aCX);
     if (NS_FAILED(rv))
       return NS_ERROR_FAILURE;
@@ -2052,17 +2071,17 @@ nsresult imgLoader::LoadImage(nsIURI *aU
     NewRequestAndEntry(forcePrincipalCheck, this, getter_AddRefs(request), getter_AddRefs(entry));
 
     PR_LOG(GetImgLog(), PR_LOG_DEBUG,
            ("[this=%p] imgLoader::LoadImage -- Created new imgRequest [request=%p]\n", this, request.get()));
 
     nsCOMPtr<nsILoadGroup> channelLoadGroup;
     newChannel->GetLoadGroup(getter_AddRefs(channelLoadGroup));
     request->Init(aURI, aURI, channelLoadGroup, newChannel, entry, aCX,
-                  aLoadingPrincipal, corsmode);
+                  aLoadingPrincipal, corsmode, aReferrerPolicy);
 
     // Add the initiator type for this image load
     nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(newChannel);
     if (timedChannel) {
       timedChannel->SetInitiatorType(initiatorType);
     }
 
     // Pass the inner window ID of the loading document, if possible.
@@ -2222,18 +2241,18 @@ nsresult imgLoader::LoadImageWithChannel
       // it says that the entry isn't valid any more, we'll only use the entry
       // we're getting if the channel is loading from the cache anyways.
       //
       // XXX -- should this be changed? it's pretty much verbatim from the old
       // code, but seems nonsensical.
       //
       // Since aCanMakeNewChannel == false, we don't need to pass content policy
       // type/principal/etc
-      if (ValidateEntry(entry, uri, nullptr, nullptr, nullptr,
-                        aObserver, aCX, requestFlags,
+      if (ValidateEntry(entry, uri, nullptr, nullptr, RP_Default,
+                        nullptr, aObserver, aCX, requestFlags,
                         nsIContentPolicy::TYPE_INVALID, false, nullptr,
                         nullptr, imgIRequest::CORS_NONE)) {
         request = entry->GetRequest();
       } else {
         nsCOMPtr<nsICachingChannel> cacheChan(do_QueryInterface(channel));
         bool bUseCacheCopy;
 
         if (cacheChan)
@@ -2286,17 +2305,17 @@ nsresult imgLoader::LoadImageWithChannel
     NewRequestAndEntry(true, this, getter_AddRefs(request), getter_AddRefs(entry));
 
     // We use originalURI here to fulfil the imgIRequest contract on GetURI.
     nsCOMPtr<nsIURI> originalURI;
     channel->GetOriginalURI(getter_AddRefs(originalURI));
 
     // No principal specified here, because we're not passed one.
     request->Init(originalURI, uri, channel, channel, entry,
-                  aCX, nullptr, imgIRequest::CORS_NONE);
+                  aCX, nullptr, imgIRequest::CORS_NONE, RP_Default);
 
     ProxyListener *pl = new ProxyListener(static_cast<nsIStreamListener *>(request.get()));
     NS_ADDREF(pl);
 
     *listener = static_cast<nsIStreamListener*>(pl);
     NS_ADDREF(*listener);
 
     NS_RELEASE(pl);
@@ -2607,30 +2626,31 @@ NS_IMETHODIMP imgCacheValidator::OnStart
 
 #if defined(PR_LOGGING)
   nsAutoCString spec;
   uri->GetSpec(spec);
   LOG_MSG_WITH_PARAM(GetImgLog(), "imgCacheValidator::OnStartRequest creating new request", "uri", spec.get());
 #endif
 
   int32_t corsmode = mRequest->GetCORSMode();
+  ReferrerPolicy refpol = mRequest->GetReferrerPolicy();
   nsCOMPtr<nsIPrincipal> loadingPrincipal = mRequest->GetLoadingPrincipal();
 
   // Doom the old request's cache entry
   mRequest->RemoveFromCache();
 
   mRequest->mValidator = nullptr;
   mRequest = nullptr;
 
   // We use originalURI here to fulfil the imgIRequest contract on GetURI.
   nsCOMPtr<nsIURI> originalURI;
   channel->GetOriginalURI(getter_AddRefs(originalURI));
   mNewRequest->Init(originalURI, uri, aRequest, channel, mNewEntry,
                     mContext, loadingPrincipal,
-                    corsmode);
+                    corsmode, refpol);
 
   mDestListener = new ProxyListener(mNewRequest);
 
   // Try to add the new request into the cache. Note that the entry must be in
   // the cache before the proxies' ownership changes, because adding a proxy
   // changes the caching behaviour for imgRequests.
   mImgLoader->PutIntoCache(originalURI, mNewEntry);
 
--- a/image/src/imgLoader.h
+++ b/image/src/imgLoader.h
@@ -17,16 +17,17 @@
 #include "nsRefPtrHashtable.h"
 #include "nsExpirationTracker.h"
 #include "nsAutoPtr.h"
 #include "imgRequest.h"
 #include "nsIProgressEventSink.h"
 #include "nsIChannel.h"
 #include "nsIThreadRetargetableStreamListener.h"
 #include "imgIRequest.h"
+#include "mozilla/net/ReferrerPolicy.h"
 
 class imgLoader;
 class imgRequestProxy;
 class imgINotificationObserver;
 class nsILoadGroup;
 class imgCacheExpirationTracker;
 class imgMemoryReporter;
 
@@ -212,16 +213,17 @@ class imgLoader MOZ_FINAL : public imgIL
                             public nsIObserver
 {
   virtual ~imgLoader();
 
 public:
   typedef mozilla::image::ImageURL ImageURL;
   typedef nsRefPtrHashtable<nsCStringHashKey, imgCacheEntry> imgCacheTable;
   typedef nsTHashtable<nsPtrHashKey<imgRequest>> imgSet;
+  typedef mozilla::net::ReferrerPolicy ReferrerPolicy;
   typedef mozilla::Mutex Mutex;
 
   NS_DECL_ISUPPORTS
   NS_DECL_IMGILOADER
   NS_DECL_NSICONTENTSNIFFER
   NS_DECL_IMGICACHE
   NS_DECL_NSIOBSERVER
 
@@ -246,16 +248,17 @@ public:
       return static_cast<imgLoader*>(loader);
   }
 
   static already_AddRefed<imgLoader> GetInstance();
 
   nsresult LoadImage(nsIURI *aURI,
                      nsIURI *aInitialDocumentURI,
                      nsIURI *aReferrerURI,
+                     ReferrerPolicy aReferrerPolicy,
                      nsIPrincipal* aLoadingPrincipal,
                      nsILoadGroup *aLoadGroup,
                      imgINotificationObserver *aObserver,
                      nsISupports *aCX,
                      nsLoadFlags aLoadFlags,
                      nsISupports *aCacheKey,
                      nsContentPolicyType aContentPolicyType,
                      const nsAString& initiatorType,
@@ -331,28 +334,30 @@ public:
   // observers is re-requested.
   bool SetHasNoProxies(imgRequest *aRequest, imgCacheEntry *aEntry);
   bool SetHasProxies(imgRequest *aRequest);
 
 private: // methods
 
   bool ValidateEntry(imgCacheEntry *aEntry, nsIURI *aKey,
                        nsIURI *aInitialDocumentURI, nsIURI *aReferrerURI,
+                       ReferrerPolicy aReferrerPolicy,
                        nsILoadGroup *aLoadGroup,
                        imgINotificationObserver *aObserver, nsISupports *aCX,
                        nsLoadFlags aLoadFlags,
                        nsContentPolicyType aContentPolicyType,
                        bool aCanMakeNewChannel,
                        imgRequestProxy **aProxyRequest,
                        nsIPrincipal* aLoadingPrincipal,
                        int32_t aCORSMode);
 
   bool ValidateRequestWithNewChannel(imgRequest *request, nsIURI *aURI,
                                        nsIURI *aInitialDocumentURI,
                                        nsIURI *aReferrerURI,
+                                       ReferrerPolicy aReferrerPolicy,
                                        nsILoadGroup *aLoadGroup,
                                        imgINotificationObserver *aObserver,
                                        nsISupports *aCX, nsLoadFlags aLoadFlags,
                                        nsContentPolicyType aContentPolicyType,
                                        imgRequestProxy **aProxyRequest,
                                        nsIPrincipal* aLoadingPrincipal,
                                        int32_t aCORSMode);
 
--- a/image/src/imgRequest.cpp
+++ b/image/src/imgRequest.cpp
@@ -61,16 +61,17 @@ NS_IMPL_ISUPPORTS(imgRequest,
                   nsIAsyncVerifyRedirectCallback)
 
 imgRequest::imgRequest(imgLoader* aLoader)
  : mLoader(aLoader)
  , mProgressTracker(new ProgressTracker(nullptr))
  , mValidator(nullptr)
  , mInnerWindowId(0)
  , mCORSMode(imgIRequest::CORS_NONE)
+ , mReferrerPolicy(mozilla::net::RP_Default)
  , mImageErrorCode(NS_OK)
  , mDecodeRequested(false)
  , mIsMultiPartChannel(false)
  , mGotData(false)
  , mIsInCache(false)
  , mResniffMimeType(false)
 { }
 
@@ -89,17 +90,18 @@ imgRequest::~imgRequest()
 
 nsresult imgRequest::Init(nsIURI *aURI,
                           nsIURI *aCurrentURI,
                           nsIRequest *aRequest,
                           nsIChannel *aChannel,
                           imgCacheEntry *aCacheEntry,
                           void *aLoadId,
                           nsIPrincipal* aLoadingPrincipal,
-                          int32_t aCORSMode)
+                          int32_t aCORSMode,
+                          ReferrerPolicy aReferrerPolicy)
 {
   MOZ_ASSERT(NS_IsMainThread(), "Cannot use nsIURI off main thread!");
 
   LOG_FUNC(GetImgLog(), "imgRequest::Init");
 
   NS_ABORT_IF_FALSE(!mImage, "Multiple calls to init");
   NS_ABORT_IF_FALSE(aURI, "No uri");
   NS_ABORT_IF_FALSE(aCurrentURI, "No current uri");
@@ -112,16 +114,17 @@ nsresult imgRequest::Init(nsIURI *aURI,
   mURI = new ImageURL(aURI);
   mCurrentURI = aCurrentURI;
   mRequest = aRequest;
   mChannel = aChannel;
   mTimedChannel = do_QueryInterface(mChannel);
 
   mLoadingPrincipal = aLoadingPrincipal;
   mCORSMode = aCORSMode;
+  mReferrerPolicy = aReferrerPolicy;
 
   mChannel->GetNotificationCallbacks(getter_AddRefs(mPrevChannelSink));
 
   NS_ASSERTION(mPrevChannelSink != this,
                "Initializing with a channel that already calls back to us!");
 
   mChannel->SetNotificationCallbacks(this);
 
--- a/image/src/imgRequest.h
+++ b/image/src/imgRequest.h
@@ -14,16 +14,17 @@
 #include "nsIPrincipal.h"
 
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsProxyRelease.h"
 #include "nsStringGlue.h"
 #include "nsError.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
+#include "mozilla/net/ReferrerPolicy.h"
 
 class imgCacheValidator;
 class imgLoader;
 class imgRequestProxy;
 class imgCacheEntry;
 class imgMemoryReporter;
 class imgRequestNotifyRunnable;
 class nsIApplicationCache;
@@ -47,29 +48,31 @@ class imgRequest MOZ_FINAL : public nsIS
                              public nsIAsyncVerifyRedirectCallback
 {
   virtual ~imgRequest();
 
 public:
   typedef mozilla::image::Image Image;
   typedef mozilla::image::ImageURL ImageURL;
   typedef mozilla::image::ProgressTracker ProgressTracker;
+  typedef mozilla::net::ReferrerPolicy ReferrerPolicy;
 
   explicit imgRequest(imgLoader* aLoader);
 
   NS_DECL_THREADSAFE_ISUPPORTS
 
   nsresult Init(nsIURI *aURI,
                 nsIURI *aCurrentURI,
                 nsIRequest *aRequest,
                 nsIChannel *aChannel,
                 imgCacheEntry *aCacheEntry,
                 void *aLoadId,
                 nsIPrincipal* aLoadingPrincipal,
-                int32_t aCORSMode);
+                int32_t aCORSMode,
+                ReferrerPolicy aReferrerPolicy);
 
   void ClearLoader();
 
   // Callers must call imgRequestProxy::Notify later.
   void AddProxy(imgRequestProxy *proxy);
 
   nsresult RemoveProxy(imgRequestProxy *proxy, nsresult aStatus);
 
@@ -111,16 +114,19 @@ public:
   // HTTP cache may contain a different data then app cache.
   bool CacheChanged(nsIRequest* aNewRequest);
 
   bool GetMultipart() const { return mIsMultiPartChannel; }
 
   // The CORS mode for which we loaded this image.
   int32_t GetCORSMode() const { return mCORSMode; }
 
+  // The Referrer Policy in effect when loading this image.
+  ReferrerPolicy GetReferrerPolicy() const { return mReferrerPolicy; }
+
   // The principal for the document that loaded this image. Used when trying to
   // validate a CORS image load.
   already_AddRefed<nsIPrincipal> GetLoadingPrincipal() const
   {
     nsCOMPtr<nsIPrincipal> principal = mLoadingPrincipal;
     return principal.forget();
   }
 
@@ -248,16 +254,19 @@ private:
 
   // The ID of the inner window origin, used for error reporting.
   uint64_t mInnerWindowId;
 
   // The CORS mode (defined in imgIRequest) this image was loaded with. By
   // default, imgIRequest::CORS_NONE.
   int32_t mCORSMode;
 
+  // The Referrer Policy (defined in ReferrerPolicy.h) used for this image.
+  ReferrerPolicy mReferrerPolicy;
+
   nsresult mImageErrorCode;
 
   // Sometimes consumers want to do things before the image is ready. Let them,
   // and apply the action when the image becomes available.
   bool mDecodeRequested : 1;
 
   bool mIsMultiPartChannel : 1;
   bool mGotData : 1;
--- a/image/test/unit/async_load_tests.js
+++ b/image/test/unit/async_load_tests.js
@@ -91,17 +91,17 @@ function secondLoadDone(oldlistener, aRe
 // therefore would be at most risk of being served synchronously.
 function checkSecondLoad()
 {
   do_test_pending();
 
   var listener = new ImageListener(checkClone, secondLoadDone);
   var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
                 .createScriptedObserver(listener);
-  requests.push(gCurrentLoader.loadImageXPCOM(uri, null, null, null, null, outer, null, 0, null));
+  requests.push(gCurrentLoader.loadImageXPCOM(uri, null, null, "default", null, null, outer, null, 0, null));
   listener.synchronous = false;
 }
 
 function firstLoadDone(oldlistener, aRequest)
 {
   checkSecondLoad(uri);
 
   do_test_finished();
@@ -189,17 +189,17 @@ function startImageCallback(otherCb)
 {
   return function(listener, request)
   {
     // Make sure we can load the same image immediately out of the cache.
     do_test_pending();
     var listener2 = new ImageListener(null, function(foo, bar) { do_test_finished(); });
     var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
                   .createScriptedObserver(listener2);
-    requests.push(gCurrentLoader.loadImageXPCOM(uri, null, null, null, null, outer, null, 0, null));
+    requests.push(gCurrentLoader.loadImageXPCOM(uri, null, null, "default", null, null, outer, null, 0, null));
     listener2.synchronous = false;
 
     // Now that we've started another load, chain to the callback.
     otherCb(listener, request);
   }
 }
 
 var gCurrentLoader;
@@ -216,16 +216,16 @@ function run_test()
   do_register_cleanup(cleanup);
 
   gCurrentLoader = Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader);
 
   do_test_pending();
   var listener = new ImageListener(startImageCallback(checkClone), firstLoadDone);
   var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
                 .createScriptedObserver(listener);
-  var req = gCurrentLoader.loadImageXPCOM(uri, null, null, null, null, outer, null, 0, null);
+  var req = gCurrentLoader.loadImageXPCOM(uri, null, null, "default", null, null, outer, null, 0, null);
   requests.push(req);
 
   // Ensure that we don't cause any mayhem when we lock an image.
   req.lockImage();
 
   listener.synchronous = false;
 }
--- a/image/test/unit/test_private_channel.js
+++ b/image/test/unit/test_private_channel.js
@@ -72,17 +72,17 @@ function setup_chan(path, isPrivate, cal
 function loadImage(isPrivate, callback) {
   var listener = new ImageListener(null, callback);
   var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
                 .createScriptedObserver(listener);
   var uri = gIoService.newURI(gImgPath, null, null);
   var loadGroup = Cc["@mozilla.org/network/load-group;1"].createInstance(Ci.nsILoadGroup);
   loadGroup.notificationCallbacks = new NotificationCallbacks(isPrivate);
   var loader = isPrivate ? gPrivateLoader : gPublicLoader;
-  requests.push(loader.loadImageXPCOM(uri, null, null, null, loadGroup, outer, null, 0, null));
+  requests.push(loader.loadImageXPCOM(uri, null, null, "default", null, loadGroup, outer, null, 0, null));
   listener.synchronous = false;
 }
 
 function run_loadImage_tests() {
   function observer() {
     Services.obs.removeObserver(observer, "cacheservice:empty-cache");
     gHits = 0;
     loadImage(false, function() {
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -1976,16 +1976,17 @@ nsImageFrame::LoadIcon(const nsAString& 
   nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL;
   nsContentPolicyType contentPolicyType = nsIContentPolicy::TYPE_IMAGE;
 
   return il->LoadImage(realURI,     /* icon URI */
                        nullptr,      /* initial document URI; this is only
                                        relevant for cookies, so does not
                                        apply to icons. */
                        nullptr,      /* referrer (not relevant for icons) */
+                       mozilla::net::RP_Default,
                        nullptr,      /* principal (not relevant for icons) */
                        loadGroup,
                        gIconLoad,
                        nullptr,      /* Not associated with any particular document */
                        loadFlags,
                        nullptr,
                        contentPolicyType,
                        EmptyString(),
--- a/layout/style/ImageLoader.cpp
+++ b/layout/style/ImageLoader.cpp
@@ -280,16 +280,17 @@ ImageLoader::LoadImage(nsIURI* aURI, nsI
 
   if (!nsContentUtils::CanLoadImage(aURI, mDocument, mDocument,
                                     aOriginPrincipal)) {
     return;
   }
 
   nsRefPtr<imgRequestProxy> request;
   nsContentUtils::LoadImage(aURI, mDocument, aOriginPrincipal, aReferrer,
+                            mDocument->GetReferrerPolicy(),
                             nullptr, nsIRequest::LOAD_NORMAL,
                             NS_LITERAL_STRING("css"),
                             getter_AddRefs(request));
 
   if (!request) {
     return;
   }
 
--- a/layout/xul/nsImageBoxFrame.cpp
+++ b/layout/xul/nsImageBoxFrame.cpp
@@ -233,17 +233,18 @@ nsImageBoxFrame::UpdateImage()
     nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(uri),
                                               src,
                                               doc,
                                               baseURI);
 
     if (uri && nsContentUtils::CanLoadImage(uri, mContent, doc,
                                             mContent->NodePrincipal())) {
       nsContentUtils::LoadImage(uri, doc, mContent->NodePrincipal(),
-                                doc->GetDocumentURI(), mListener, mLoadFlags,
+                                doc->GetDocumentURI(), doc->GetReferrerPolicy(),
+                                mListener, mLoadFlags,
                                 EmptyString(), getter_AddRefs(mImageRequest));
 
       if (mImageRequest) {
         nsLayoutUtils::RegisterImageRequestIfAnimated(presContext,
                                                       mImageRequest,
                                                       &mRequestRegistered);
       }
     }
--- a/layout/xul/tree/nsTreeBodyFrame.cpp
+++ b/layout/xul/tree/nsTreeBodyFrame.cpp
@@ -2188,16 +2188,17 @@ nsTreeBodyFrame::GetImage(int32_t aRowIn
       // 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...
       if (nsContentUtils::CanLoadImage(srcURI, mContent, doc,
                                        mContent->NodePrincipal())) {
         nsresult rv = nsContentUtils::LoadImage(srcURI,
                                                 doc,
                                                 mContent->NodePrincipal(),
                                                 doc->GetDocumentURI(),
+                                                doc->GetReferrerPolicy(),
                                                 imgNotificationObserver,
                                                 nsIRequest::LOAD_NORMAL,
                                                 EmptyString(),
                                                 getter_AddRefs(imageRequest));
         NS_ENSURE_SUCCESS(rv, rv);
                                   
       }
     }
--- a/parser/html/nsHtml5TreeOpExecutor.cpp
+++ b/parser/html/nsHtml5TreeOpExecutor.cpp
@@ -925,17 +925,17 @@ nsHtml5TreeOpExecutor::PreloadStyle(cons
 void
 nsHtml5TreeOpExecutor::PreloadImage(const nsAString& aURL,
                                     const nsAString& aCrossOrigin)
 {
   nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYet(aURL);
   if (!uri) {
     return;
   }
-  mDocument->MaybePreLoadImage(uri, aCrossOrigin);
+  mDocument->MaybePreLoadImage(uri, aCrossOrigin, mSpeculationReferrerPolicy);
 }
 
 void
 nsHtml5TreeOpExecutor::AddBase(const nsAString& aURL)
 {
   const nsCString& charset = mDocument->GetDocumentCharacterSet();
   nsresult rv = NS_NewURI(getter_AddRefs(mViewSourceBaseURI), aURL,
                                      charset.get(), GetViewSourceBaseURI());
--- a/toolkit/system/gnome/nsAlertsIconListener.cpp
+++ b/toolkit/system/gnome/nsAlertsIconListener.cpp
@@ -212,17 +212,18 @@ nsAlertsIconListener::StartRequest(const
   NS_NewURI(getter_AddRefs(imageUri), aImageUrl);
   if (!imageUri)
     return ShowAlert(nullptr);
 
   nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1"));
   if (!il)
     return ShowAlert(nullptr);
 
-  nsresult rv = il->LoadImageXPCOM(imageUri, nullptr, nullptr, nullptr, nullptr,
+  nsresult rv = il->LoadImageXPCOM(imageUri, nullptr, nullptr,
+                                   NS_LITERAL_STRING("default"), nullptr, nullptr,
                                    this, nullptr, nsIRequest::LOAD_NORMAL, nullptr,
                                    0 /* use default */, getter_AddRefs(mIconRequest));
   if (NS_FAILED(rv))
     return rv;
 
   mIconRequest->StartDecoding();
 
   return NS_OK;
--- a/widget/cocoa/OSXNotificationCenter.mm
+++ b/widget/cocoa/OSXNotificationCenter.mm
@@ -238,17 +238,19 @@ OSXNotificationCenter::ShowAlertNotifica
   } else {
     mPendingAlerts.AppendElement(osxni);
     osxni->mPendingNotifiction = notification;
     nsRefPtr<imgLoader> il = imgLoader::GetInstance();
     if (il) {
       nsCOMPtr<nsIURI> imageUri;
       NS_NewURI(getter_AddRefs(imageUri), aImageUrl);
       if (imageUri) {
-        nsresult rv = il->LoadImage(imageUri, nullptr, nullptr, aPrincipal, nullptr,
+        nsresult rv = il->LoadImage(imageUri, nullptr, nullptr,
+                                    mozilla::net::RP_Default,
+                                    aPrincipal, nullptr,
                                     this, nullptr, nsIRequest::LOAD_NORMAL, nullptr,
                                     nsIContentPolicy::TYPE_IMAGE, EmptyString(),
                                     getter_AddRefs(osxni->mIconRequest));
         if (NS_SUCCEEDED(rv)) {
           // Set a timer for six seconds. If we don't have an icon by the time this
           // goes off then we go ahead without an icon.
           nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
           osxni->mIconTimeoutTimer = timer;
--- a/widget/cocoa/nsMenuItemIconX.mm
+++ b/widget/cocoa/nsMenuItemIconX.mm
@@ -301,17 +301,19 @@ nsMenuItemIconX::LoadIcon(nsIURI* aIconU
     }
 
     if (!sPlaceholderIconImage) return NS_ERROR_FAILURE;
 
     if (mNativeMenuItem)
       [mNativeMenuItem setImage:sPlaceholderIconImage];
   }
 
-  nsresult rv = loader->LoadImage(aIconURI, nullptr, nullptr, nullptr, loadGroup, this,
+  nsresult rv = loader->LoadImage(aIconURI, nullptr, nullptr,
+                                  mozilla::net::RP_Default,
+                                  nullptr, loadGroup, this,
                                   nullptr, nsIRequest::LOAD_NORMAL, nullptr,
                                   nsIContentPolicy::TYPE_IMAGE, EmptyString(),
                                   getter_AddRefs(mIconRequest));
   if (NS_FAILED(rv)) return rv;
 
   // We need to request the icon be decoded (bug 573583, bug 705516).
   mIconRequest->StartDecoding();