diff --git a/dom/base/nsContentSink.cpp b/dom/base/nsContentSink.cpp index 26e1ea5f89..abbba90457 100644 --- a/dom/base/nsContentSink.cpp +++ b/dom/base/nsContentSink.cpp @@ -472,6 +472,7 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData) nsAutoString media; nsAutoString anchor; nsAutoString crossOrigin; + nsAutoString referrerPolicy; nsAutoString destination; crossOrigin.SetIsVoid(true); @@ -660,6 +661,15 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData) destination = value; destination.StripWhitespace(); } + } else if (attr.LowerCaseEqualsLiteral("referrerpolicy")) { + // https://html.spec.whatwg.org/multipage/urls-and-fetching.html#referrer-policy-attribute + // Specs says referrer policy attribute is an enumerated attribute, + // case insensitive and includes the empty string + // We will parse the value with AttributeReferrerPolicyFromString + // later, which will handle parsing it as an enumerated attribute. + if (referrerPolicy.IsEmpty()) { + referrerPolicy = value; + } } } } @@ -673,7 +683,7 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData) rv = ProcessLink(anchor, href, rel, // prefer RFC 5987 variant over non-I18zed version titleStar.IsEmpty() ? title : titleStar, - type, media, crossOrigin, destination); + type, media, crossOrigin, referrerPolicy, destination); } href.Truncate(); @@ -682,6 +692,7 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData) type.Truncate(); media.Truncate(); anchor.Truncate(); + referrerPolicy.Truncate(); crossOrigin.SetIsVoid(true); destination.Truncate(); @@ -696,7 +707,7 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData) rv = ProcessLink(anchor, href, rel, // prefer RFC 5987 variant over non-I18zed version titleStar.IsEmpty() ? title : titleStar, - type, media, crossOrigin, destination); + type, media, crossOrigin, referrerPolicy, destination); } return rv; @@ -708,6 +719,7 @@ nsContentSink::ProcessLink(const nsSubstring& aAnchor, const nsSubstring& aHref, const nsSubstring& aRel, const nsSubstring& aTitle, const nsSubstring& aType, const nsSubstring& aMedia, const nsSubstring& aCrossOrigin, + const nsAString& aReferrerPolicy, const nsSubstring& aDestination) { uint32_t linkTypes = @@ -749,7 +761,7 @@ nsContentSink::ProcessLink(const nsSubstring& aAnchor, const nsSubstring& aHref, bool isAlternate = linkTypes & nsStyleLinkElement::eALTERNATE; return ProcessStyleLink(nullptr, aHref, isAlternate, aTitle, aType, - aMedia); + aMedia, aReferrerPolicy); } nsresult @@ -758,7 +770,8 @@ nsContentSink::ProcessStyleLink(nsIContent* aElement, bool aAlternate, const nsSubstring& aTitle, const nsSubstring& aType, - const nsSubstring& aMedia) + const nsSubstring& aMedia, + const nsSubstring& aReferrerPolicy) { if (aAlternate && aTitle.IsEmpty()) { // alternates must have title return without error, for now @@ -797,13 +810,18 @@ nsContentSink::ProcessStyleLink(nsIContent* aElement, ("nsContentSink::ProcessStyleLink, integrity=%s", NS_ConvertUTF16toUTF8(integrity).get())); } + mozilla::net::ReferrerPolicy referrerPolicy = + mozilla::net::AttributeReferrerPolicyFromString(aReferrerPolicy); + if (referrerPolicy == net::RP_Unset) { + referrerPolicy = mDocument->GetReferrerPolicy(); + } // If this is a fragment parser, we don't want to observe. // We don't support CORS for processing instructions bool isAlternate; bool isExplicitlyEnabled; rv = mCSSLoader->LoadStyleLink(aElement, url, aTitle, aMedia, aAlternate, - CORS_NONE, mDocument->GetReferrerPolicy(), + CORS_NONE, referrerPolicy, integrity, mRunsToCompletion ? nullptr : this, &isAlternate, &isExplicitlyEnabled); NS_ENSURE_SUCCESS(rv, rv); diff --git a/dom/base/nsContentSink.h b/dom/base/nsContentSink.h index bed7392ca3..d6605af8d9 100644 --- a/dom/base/nsContentSink.h +++ b/dom/base/nsContentSink.h @@ -154,6 +154,7 @@ protected: const nsSubstring& aHref, const nsSubstring& aRel, const nsSubstring& aTitle, const nsSubstring& aType, const nsSubstring& aMedia, const nsSubstring& aCrossOrigin, + const nsSubstring& aReferrerPolicy, const nsSubstring& aDestination); virtual nsresult ProcessStyleLink(nsIContent* aElement, @@ -161,7 +162,8 @@ protected: bool aAlternate, const nsSubstring& aTitle, const nsSubstring& aType, - const nsSubstring& aMedia); + const nsSubstring& aMedia, + const nsSubstring& aReferrerPolicy); void PrefetchOrPreloadHref(const nsAString &aHref, nsINode *aSource, diff --git a/dom/base/nsStyleLinkElement.cpp b/dom/base/nsStyleLinkElement.cpp index 7a0a563350..971af21b4c 100644 --- a/dom/base/nsStyleLinkElement.cpp +++ b/dom/base/nsStyleLinkElement.cpp @@ -411,6 +411,16 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument, bool doneLoading = false; nsresult rv = NS_OK; + + // Load the link's referrerpolicy attribute. If the link does not provide a + // referrerpolicy attribute, ignore this and use the document's referrer + // policy + + net::ReferrerPolicy referrerPolicy = GetLinkReferrerPolicy(); + if (referrerPolicy == net::RP_Unset) { + referrerPolicy = doc->GetReferrerPolicy(); + } + if (isInline) { nsAutoString text; if (!nsContentUtils::GetNodeTextContent(thisContent, false, text, fallible)) { @@ -429,7 +439,7 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument, // Parse the style sheet. rv = doc->CSSLoader()-> - LoadInlineStyle(thisContent, text, mLineNumber, title, media, + LoadInlineStyle(thisContent, text, mLineNumber, title, media, referrerPolicy, scopeElement, aObserver, &doneLoading, &isAlternate, &isExplicitlyEnabled); } else { nsAutoString integrity; @@ -440,15 +450,6 @@ 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)); diff --git a/dom/xml/nsXMLContentSink.cpp b/dom/xml/nsXMLContentSink.cpp index 7db1ea4a6a..2125416d73 100644 --- a/dom/xml/nsXMLContentSink.cpp +++ b/dom/xml/nsXMLContentSink.cpp @@ -655,7 +655,8 @@ nsXMLContentSink::ProcessStyleLink(nsIContent* aElement, bool aAlternate, const nsSubstring& aTitle, const nsSubstring& aType, - const nsSubstring& aMedia) + const nsSubstring& aMedia, + const nsSubstring& aReferrerPolicy) { nsresult rv = NS_OK; mPrettyPrintXML = false; @@ -714,7 +715,7 @@ nsXMLContentSink::ProcessStyleLink(nsIContent* aElement, // Let nsContentSink deal with css. rv = nsContentSink::ProcessStyleLink(aElement, aHref, aAlternate, - aTitle, aType, aMedia); + aTitle, aType, aMedia, aReferrerPolicy); // nsContentSink::ProcessStyleLink handles the bookkeeping here wrt // pending sheets. @@ -1261,7 +1262,9 @@ nsXMLContentSink::HandleProcessingInstruction(const char16_t *aTarget, return DidProcessATokenImpl(); } - rv = ProcessStyleLink(node, href, isAlternate, title, type, media); + // processing instructions don't have a referrerpolicy + // pseudo-attribute, so we pass in an empty string + rv = ProcessStyleLink(node, href, isAlternate, title, type, media, EmptyString()); return NS_SUCCEEDED(rv) ? DidProcessATokenImpl() : rv; } diff --git a/dom/xml/nsXMLContentSink.h b/dom/xml/nsXMLContentSink.h index ea190954a2..d7399349e8 100644 --- a/dom/xml/nsXMLContentSink.h +++ b/dom/xml/nsXMLContentSink.h @@ -150,7 +150,8 @@ protected: bool aAlternate, const nsSubstring& aTitle, const nsSubstring& aType, - const nsSubstring& aMedia) override; + const nsSubstring& aMedia, + const nsSubstring& aReferrerPolicy) override; nsresult LoadXSLStyleSheet(nsIURI* aUrl); diff --git a/dom/xml/nsXMLFragmentContentSink.cpp b/dom/xml/nsXMLFragmentContentSink.cpp index a4bb406351..664fbbeb6a 100644 --- a/dom/xml/nsXMLFragmentContentSink.cpp +++ b/dom/xml/nsXMLFragmentContentSink.cpp @@ -97,7 +97,9 @@ protected: bool aAlternate, const nsSubstring& aTitle, const nsSubstring& aType, - const nsSubstring& aMedia) override; + const nsSubstring& aMedia, + const nsSubstring& aReferrerPolicy) override; + nsresult LoadXSLStyleSheet(nsIURI* aUrl); void StartLayout(); @@ -332,7 +334,8 @@ nsXMLFragmentContentSink::ProcessStyleLink(nsIContent* aElement, bool aAlternate, const nsSubstring& aTitle, const nsSubstring& aType, - const nsSubstring& aMedia) + const nsSubstring& aMedia, + const nsSubstring& aReferrerPolicy) { // don't process until moved to document return NS_OK; diff --git a/layout/style/Loader.cpp b/layout/style/Loader.cpp index 4e1a1d6fe1..3b445eb567 100644 --- a/layout/style/Loader.cpp +++ b/layout/style/Loader.cpp @@ -1941,6 +1941,7 @@ Loader::LoadInlineStyle(nsIContent* aElement, uint32_t aLineNumber, const nsAString& aTitle, const nsAString& aMedia, + ReferrerPolicy aReferrerPolicy, Element* aScopeElement, nsICSSLoaderObserver* aObserver, bool* aCompleted, @@ -1964,11 +1965,12 @@ Loader::LoadInlineStyle(nsIContent* aElement, // Since we're not planning to load a URI, no need to hand a principal to the // load data or to CreateSheet(). Also, OK to use CORS_NONE for the CORS - // mode and mDocument's ReferrerPolicy. + // mode. + StyleSheetState state; RefPtr sheet; nsresult rv = CreateSheet(nullptr, aElement, nullptr, eAuthorSheetFeatures, - CORS_NONE, mDocument->GetReferrerPolicy(), + CORS_NONE, aReferrerPolicy, EmptyString(), // no inline integrity checks false, false, aTitle, state, aIsAlternate, &sheet); diff --git a/layout/style/Loader.h b/layout/style/Loader.h index c9af2f39e8..2319164a2f 100644 --- a/layout/style/Loader.h +++ b/layout/style/Loader.h @@ -224,6 +224,7 @@ public: * @param aLineNumber the line number at which the stylesheet data started. * @param aTitle the title of the sheet. * @param aMedia the media string for the sheet. + * @param aReferrerPolicy the referrer policy for loading the sheet. * @param aObserver the observer to notify when the load completes. * May be null. * @param [out] aCompleted whether parsing of the sheet completed. @@ -237,6 +238,7 @@ public: uint32_t aLineNumber, const nsAString& aTitle, const nsAString& aMedia, + ReferrerPolicy aReferrerPolicy, mozilla::dom::Element* aScopeElement, nsICSSLoaderObserver* aObserver, bool* aCompleted,