diff --git a/dom/base/nsStyleLinkElement.cpp b/dom/base/nsStyleLinkElement.cpp index 8f72be7ecfca..e73b58b5ee3a 100644 --- a/dom/base/nsStyleLinkElement.cpp +++ b/dom/base/nsStyleLinkElement.cpp @@ -17,6 +17,7 @@ #include "mozilla/css/Loader.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/FragmentOrElement.h" +#include "mozilla/dom/HTMLLinkElement.h" #include "mozilla/dom/ShadowRoot.h" #include "mozilla/dom/SRILogHelper.h" #include "mozilla/Preferences.h" @@ -435,13 +436,22 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument, NS_ConvertUTF16toUTF8(integrity).get())); } + // if referrer attributes are enabled in preferences, load the link's referrer + // attribute. If the link does not provide a referrer attribute, ignore this + // and use the document's referrer policy + + net::ReferrerPolicy referrerPolicy = GetLinkReferrerPolicy(); + if (referrerPolicy == net::RP_Unset) { + referrerPolicy = doc->GetReferrerPolicy(); + } + // XXXbz clone the URI here to work around content policies modifying URIs. nsCOMPtr clonedURI; uri->Clone(getter_AddRefs(clonedURI)); NS_ENSURE_TRUE(clonedURI, NS_ERROR_OUT_OF_MEMORY); rv = doc->CSSLoader()-> LoadStyleLink(thisContent, clonedURI, title, media, isAlternate, - GetCORSMode(), doc->GetReferrerPolicy(), integrity, + GetCORSMode(), referrerPolicy, integrity, aObserver, &isAlternate); if (NS_FAILED(rv)) { // Don't propagate LoadStyleLink() errors further than this, since some diff --git a/dom/base/nsStyleLinkElement.h b/dom/base/nsStyleLinkElement.h index a948f099e0b7..408e10a6d0a6 100644 --- a/dom/base/nsStyleLinkElement.h +++ b/dom/base/nsStyleLinkElement.h @@ -16,6 +16,7 @@ #include "mozilla/Attributes.h" #include "mozilla/CORSMode.h" #include "mozilla/CSSStyleSheet.h" +#include "mozilla/net/ReferrerPolicy.h" #include "nsCOMPtr.h" #include "nsIStyleSheetLinkingElement.h" #include "nsTArray.h" @@ -113,6 +114,11 @@ protected: return mozilla::CORS_NONE; } + virtual mozilla::net::ReferrerPolicy GetLinkReferrerPolicy() + { + return mozilla::net::RP_Unset; + } + // CC methods void Unlink(); void Traverse(nsCycleCollectionTraversalCallback &cb); diff --git a/dom/html/HTMLLinkElement.h b/dom/html/HTMLLinkElement.h index e4e8bc89f88f..421b149e961c 100644 --- a/dom/html/HTMLLinkElement.h +++ b/dom/html/HTMLLinkElement.h @@ -150,6 +150,18 @@ public: { SetHTMLAttr(nsGkAtoms::integrity, aIntegrity, aRv); } + void SetReferrerPolicy(const nsAString& aReferrer, ErrorResult& aError) + { + SetHTMLAttr(nsGkAtoms::referrerpolicy, aReferrer, aError); + } + void GetReferrerPolicy(nsAString& aReferrer) + { + GetEnumAttr(nsGkAtoms::referrerpolicy, EmptyCString().get(), aReferrer); + } + mozilla::net::ReferrerPolicy GetLinkReferrerPolicy() override + { + return GetReferrerPolicyAsEnum(); + } already_AddRefed GetImport(); already_AddRefed GetImportLoader() diff --git a/dom/webidl/HTMLLinkElement.webidl b/dom/webidl/HTMLLinkElement.webidl index af53c5824213..ec094e55ece4 100644 --- a/dom/webidl/HTMLLinkElement.webidl +++ b/dom/webidl/HTMLLinkElement.webidl @@ -29,6 +29,8 @@ interface HTMLLinkElement : HTMLElement { attribute DOMString hreflang; [SetterThrows, Pure] attribute DOMString type; + [SetterThrows, Pure, Pref="network.http.enablePerElementReferrer"] + attribute DOMString referrerPolicy; [PutForwards=value] readonly attribute DOMTokenList sizes; }; HTMLLinkElement implements LinkStyle; diff --git a/uriloader/prefetch/nsPrefetchService.cpp b/uriloader/prefetch/nsPrefetchService.cpp index caebdc8f25e9..cad6240ae6fe 100644 --- a/uriloader/prefetch/nsPrefetchService.cpp +++ b/uriloader/prefetch/nsPrefetchService.cpp @@ -109,9 +109,17 @@ nsPrefetchNode::OpenChannel() } nsCOMPtr loadGroup = source->OwnerDoc()->GetDocumentLoadGroup(); CORSMode corsMode = CORS_NONE; + net::ReferrerPolicy referrerPolicy = net::RP_Unset; if (source->IsHTMLElement(nsGkAtoms::link)) { - corsMode = static_cast(source.get())->GetCORSMode(); + dom::HTMLLinkElement* link = static_cast(source.get()); + corsMode = link->GetCORSMode(); + referrerPolicy = link->GetLinkReferrerPolicy(); } + + if (referrerPolicy == net::RP_Unset) { + referrerPolicy = source->OwnerDoc()->GetReferrerPolicy(); + } + uint32_t securityFlags; if (corsMode == CORS_NONE) { securityFlags = nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS; @@ -139,7 +147,7 @@ nsPrefetchNode::OpenChannel() nsCOMPtr httpChannel = do_QueryInterface(mChannel); if (httpChannel) { - httpChannel->SetReferrer(mReferrerURI); + httpChannel->SetReferrerWithPolicy(mReferrerURI, referrerPolicy); httpChannel->SetRequestHeader( NS_LITERAL_CSTRING("X-Moz"), NS_LITERAL_CSTRING("prefetch"),