--- a/dom/base/nsContentSink.cpp
+++ b/dom/base/nsContentSink.cpp
@@ -805,17 +805,17 @@ nsContentSink::ProcessStyleLink(nsIConte
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;
- rv = mCSSLoader->LoadStyleLink(aElement, url, aTitle, aMedia, aAlternate,
+ rv = mCSSLoader->LoadStyleLink(aElement, url, nullptr, aTitle, aMedia, aAlternate,
CORS_NONE, referrerPolicy,
integrity, mRunsToCompletion ? nullptr : this,
&isAlternate);
NS_ENSURE_SUCCESS(rv, rv);
if (!isAlternate && !mRunsToCompletion) {
++mPendingSheetCount;
mScriptLoader->AddParserBlockingScriptExecutionBlocker();
--- a/dom/base/nsStyleLinkElement.cpp
+++ b/dom/base/nsStyleLinkElement.cpp
@@ -466,17 +466,18 @@ nsStyleLinkElement::DoUpdateStyleSheet(n
nsCOMPtr<nsIDocument> doc = thisContent->IsInShadowTree() ?
thisContent->OwnerDoc() : thisContent->GetUncomposedDoc();
if (!doc || !doc->CSSLoader()->GetEnabled()) {
return NS_OK;
}
bool isInline;
- nsCOMPtr<nsIURI> uri = GetStyleSheetURL(&isInline);
+ nsCOMPtr<nsIPrincipal> triggeringPrincipal;
+ nsCOMPtr<nsIURI> uri = GetStyleSheetURL(&isInline, getter_AddRefs(triggeringPrincipal));
if (!aForceUpdate && mStyleSheet && !isInline && uri) {
nsIURI* oldURI = mStyleSheet->GetSheetURI();
if (oldURI) {
bool equal;
nsresult rv = oldURI->Equals(uri, &equal);
if (NS_SUCCEEDED(rv) && equal) {
return NS_OK; // We already loaded this stylesheet
@@ -558,18 +559,18 @@ nsStyleLinkElement::DoUpdateStyleSheet(n
NS_ConvertUTF16toUTF8(integrity).get()));
}
// XXXbz clone the URI here to work around content policies modifying URIs.
nsCOMPtr<nsIURI> 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(), referrerPolicy, integrity,
+ LoadStyleLink(thisContent, clonedURI, triggeringPrincipal, title, media,
+ isAlternate, GetCORSMode(), referrerPolicy, integrity,
aObserver, &isAlternate);
if (NS_FAILED(rv)) {
// Don't propagate LoadStyleLink() errors further than this, since some
// consumers (e.g. nsXMLContentSink) will completely abort on innocuous
// things like a stylesheet load being blocked by the security system.
doneLoading = true;
isAlternate = false;
rv = NS_OK;
--- a/dom/base/nsStyleLinkElement.h
+++ b/dom/base/nsStyleLinkElement.h
@@ -88,17 +88,17 @@ protected:
* changed but the URI may not have changed.
*/
nsresult UpdateStyleSheetInternal(nsIDocument *aOldDocument,
mozilla::dom::ShadowRoot *aOldShadowRoot,
bool aForceUpdate = false);
void UpdateStyleSheetScopedness(bool aIsNowScoped);
- virtual already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline) = 0;
+ virtual already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal) = 0;
virtual void GetStyleSheetInfo(nsAString& aTitle,
nsAString& aType,
nsAString& aMedia,
bool* aIsScoped,
bool* aIsAlternate) = 0;
virtual mozilla::CORSMode GetCORSMode() const
{
@@ -132,15 +132,16 @@ private:
mozilla::dom::ShadowRoot* aOldShadowRoot,
nsICSSLoaderObserver* aObserver,
bool* aWillNotify,
bool* aIsAlternate,
bool aForceUpdate);
RefPtr<mozilla::StyleSheet> mStyleSheet;
protected:
+ nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
bool mDontLoadStyle;
bool mUpdatesEnabled;
uint32_t mLineNumber;
};
#endif /* nsStyleLinkElement_h___ */
--- a/dom/html/HTMLLinkElement.cpp
+++ b/dom/html/HTMLLinkElement.cpp
@@ -304,16 +304,22 @@ HTMLLinkElement::AfterSetAttr(int32_t aN
if (aName == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID) {
bool hasHref = aValue;
Link::ResetLinkState(!!aNotify, hasHref);
if (IsInUncomposedDoc()) {
CreateAndDispatchEvent(OwnerDoc(), NS_LITERAL_STRING("DOMLinkChanged"));
}
}
+ if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::href) {
+ mTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal(
+ this, aValue ? aValue->GetStringValue() : EmptyString(),
+ aSubjectPrincipal);
+ }
+
if (aValue) {
if (aNameSpaceID == kNameSpaceID_None &&
(aName == nsGkAtoms::href ||
aName == nsGkAtoms::rel ||
aName == nsGkAtoms::title ||
aName == nsGkAtoms::media ||
aName == nsGkAtoms::type ||
aName == nsGkAtoms::as ||
@@ -421,24 +427,30 @@ HTMLLinkElement::RelList()
already_AddRefed<nsIURI>
HTMLLinkElement::GetHrefURI() const
{
return GetHrefURIForAnchors();
}
already_AddRefed<nsIURI>
-HTMLLinkElement::GetStyleSheetURL(bool* aIsInline)
+HTMLLinkElement::GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal)
{
*aIsInline = false;
+ *aTriggeringPrincipal = nullptr;
+
nsAutoString href;
GetAttr(kNameSpaceID_None, nsGkAtoms::href, href);
if (href.IsEmpty()) {
return nullptr;
}
+
+ nsCOMPtr<nsIPrincipal> prin = mTriggeringPrincipal;
+ prin.forget(aTriggeringPrincipal);
+
nsCOMPtr<nsIURI> uri = Link::GetURI();
return uri.forget();
}
void
HTMLLinkElement::GetStyleSheetInfo(nsAString& aTitle,
nsAString& aType,
nsAString& aMedia,
--- a/dom/html/HTMLLinkElement.h
+++ b/dom/html/HTMLLinkElement.h
@@ -81,20 +81,23 @@ public:
virtual void OnDNSPrefetchDeferred() override;
virtual void OnDNSPrefetchRequested() override;
virtual bool HasDeferredDNSPrefetchRequest() override;
// WebIDL
bool Disabled();
void SetDisabled(bool aDisabled);
- // XPCOM GetHref is fine.
- void SetHref(const nsAString& aHref, ErrorResult& aRv)
+ void GetHref(nsString& aHref, nsIPrincipal&)
{
- SetHTMLAttr(nsGkAtoms::href, aHref, aRv);
+ GetHref(aHref);
+ }
+ void SetHref(const nsAString& aHref, nsIPrincipal& aPrincipal, ErrorResult& aRv)
+ {
+ SetHTMLAttr(nsGkAtoms::href, aHref, aPrincipal, aRv);
}
void GetCrossOrigin(nsAString& aResult)
{
// Null for both missing and invalid defaults is ok, since we
// always parse to an enum value, so we don't need an invalid
// default, and we _want_ the missing default to be null.
GetEnumAttr(nsGkAtoms::crossorigin, nullptr, aResult);
}
@@ -175,17 +178,17 @@ public:
ClearHasPendingLinkUpdate();
nsGenericHTMLElement::NodeInfoChanged(aOldDoc);
}
protected:
virtual ~HTMLLinkElement();
// nsStyleLinkElement
- virtual already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline) override;
+ virtual already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal) override;
virtual void GetStyleSheetInfo(nsAString& aTitle,
nsAString& aType,
nsAString& aMedia,
bool* aIsScoped,
bool* aIsAlternate) override;
protected:
RefPtr<nsDOMTokenList> mRelList;
};
--- a/dom/html/HTMLStyleElement.cpp
+++ b/dom/html/HTMLStyleElement.cpp
@@ -181,19 +181,20 @@ HTMLStyleElement::SetInnerHTML(const nsA
aError = nsContentUtils::SetNodeTextContent(this, aInnerHTML, true);
SetEnableUpdates(true);
UpdateStyleSheetInternal(nullptr, nullptr);
}
already_AddRefed<nsIURI>
-HTMLStyleElement::GetStyleSheetURL(bool* aIsInline)
+HTMLStyleElement::GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal)
{
*aIsInline = true;
+ *aTriggeringPrincipal = nullptr;
return nullptr;
}
void
HTMLStyleElement::GetStyleSheetInfo(nsAString& aTitle,
nsAString& aType,
nsAString& aMedia,
bool* aIsScoped,
--- a/dom/html/HTMLStyleElement.h
+++ b/dom/html/HTMLStyleElement.h
@@ -83,17 +83,17 @@ public:
SetHTMLBoolAttr(nsGkAtoms::scoped, aScoped, aError);
}
virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
protected:
virtual ~HTMLStyleElement();
- already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline) override;
+ already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal) override;
void GetStyleSheetInfo(nsAString& aTitle,
nsAString& aType,
nsAString& aMedia,
bool* aIsScoped,
bool* aIsAlternate) override;
/**
* Common method to call from the various mutation observer methods.
* aContent is a content node that's either the one that changed or its
--- a/dom/svg/SVGStyleElement.cpp
+++ b/dom/svg/SVGStyleElement.cpp
@@ -252,19 +252,20 @@ SVGStyleElement::SetTitle(const nsAStrin
{
rv = SetAttr(kNameSpaceID_None, nsGkAtoms::title, aTitle, true);
}
//----------------------------------------------------------------------
// nsStyleLinkElement methods
already_AddRefed<nsIURI>
-SVGStyleElement::GetStyleSheetURL(bool* aIsInline)
+SVGStyleElement::GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal)
{
*aIsInline = true;
+ *aTriggeringPrincipal = nullptr;
return nullptr;
}
void
SVGStyleElement::GetStyleSheetInfo(nsAString& aTitle,
nsAString& aType,
nsAString& aMedia,
bool* aIsScoped,
--- a/dom/svg/SVGStyleElement.h
+++ b/dom/svg/SVGStyleElement.h
@@ -82,17 +82,17 @@ protected:
// NS_IMPL_ELEMENT_CLONE_WITH_INIT usable with this class. This should be
// completely optimized away.
inline nsresult Init()
{
return NS_OK;
}
// nsStyleLinkElement overrides
- already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline) override;
+ already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal) override;
void GetStyleSheetInfo(nsAString& aTitle,
nsAString& aType,
nsAString& aMedia,
bool* aIsScoped,
bool* aIsAlternate) override;
virtual CORSMode GetCORSMode() const override;
--- a/dom/webidl/HTMLLinkElement.webidl
+++ b/dom/webidl/HTMLLinkElement.webidl
@@ -11,17 +11,17 @@
* and create derivative works of this document.
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-link-element
[HTMLConstructor]
interface HTMLLinkElement : HTMLElement {
[Pure]
attribute boolean disabled;
- [CEReactions, SetterThrows, Pure]
+ [CEReactions, NeedsSubjectPrincipal, SetterThrows, Pure]
attribute DOMString href;
[CEReactions, SetterThrows, Pure]
attribute DOMString? crossOrigin;
[CEReactions, SetterThrows, Pure]
attribute DOMString rel;
[PutForwards=value]
readonly attribute DOMTokenList relList;
[CEReactions, SetterThrows, Pure]
--- a/dom/xml/XMLStylesheetProcessingInstruction.cpp
+++ b/dom/xml/XMLStylesheetProcessingInstruction.cpp
@@ -95,19 +95,20 @@ XMLStylesheetProcessingInstruction::GetC
/* virtual */ void
XMLStylesheetProcessingInstruction::OverrideBaseURI(nsIURI* aNewBaseURI)
{
mOverriddenBaseURI = aNewBaseURI;
}
already_AddRefed<nsIURI>
-XMLStylesheetProcessingInstruction::GetStyleSheetURL(bool* aIsInline)
+XMLStylesheetProcessingInstruction::GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal)
{
*aIsInline = false;
+ *aTriggeringPrincipal = nullptr;
nsAutoString href;
if (!GetAttrValue(nsGkAtoms::href, href)) {
return nullptr;
}
nsIURI *baseURL;
nsIDocument *document = OwnerDoc();
--- a/dom/xml/XMLStylesheetProcessingInstruction.h
+++ b/dom/xml/XMLStylesheetProcessingInstruction.h
@@ -72,17 +72,17 @@ public:
}
using ProcessingInstruction::SetData; // Prevent hiding overloaded virtual function.
protected:
virtual ~XMLStylesheetProcessingInstruction();
nsCOMPtr<nsIURI> mOverriddenBaseURI;
- already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline) override;
+ already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal) override;
void GetStyleSheetInfo(nsAString& aTitle,
nsAString& aType,
nsAString& aMedia,
bool* aIsScoped,
bool* aIsAlternate) override;
virtual nsGenericDOMDataNode* CloneDataNode(mozilla::dom::NodeInfo *aNodeInfo,
bool aCloneText) const override;
};
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -1917,16 +1917,17 @@ Loader::LoadInlineStyle(nsIContent* aEle
data->mMustNotify = true;
}
return rv;
}
nsresult
Loader::LoadStyleLink(nsIContent* aElement,
nsIURI* aURL,
+ nsIPrincipal* aTriggeringPrincipal,
const nsAString& aTitle,
const nsAString& aMedia,
bool aHasAlternateRel,
CORSMode aCORSMode,
ReferrerPolicy aReferrerPolicy,
const nsAString& aIntegrity,
nsICSSLoaderObserver* aObserver,
bool* aIsAlternate)
@@ -1942,18 +1943,20 @@ Loader::LoadStyleLink(nsIContent* aEleme
if (!mEnabled) {
LOG_WARN((" Not enabled"));
return NS_ERROR_NOT_AVAILABLE;
}
NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_INITIALIZED);
- nsIPrincipal* principal =
- aElement ? aElement->NodePrincipal() : mDocument->NodePrincipal();
+ nsIPrincipal* principal = aTriggeringPrincipal;
+ if (!principal) {
+ principal = aElement ? aElement->NodePrincipal() : mDocument->NodePrincipal();
+ }
nsISupports* context = aElement;
if (!context) {
context = mDocument;
}
nsresult rv = CheckContentPolicy(principal, aURL, context, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
--- a/layout/style/Loader.h
+++ b/layout/style/Loader.h
@@ -251,29 +251,31 @@ public:
* Load a linked (document) stylesheet. If a successful result is returned,
* aObserver is guaranteed to be notified asynchronously once the sheet is
* loaded and marked complete. If an error is returned, aObserver will not
* be notified. In addition to loading the sheet, this method will insert it
* into the stylesheet list of this CSSLoader's document.
*
* @param aElement the element linking to the the stylesheet. May be null.
* @param aURL the URL of the sheet.
+ * @param aTriggeringPrincipal the triggering principal for the load.
* @param aTitle the title of the sheet.
* @param aMedia the media string for the sheet.
* @param aHasAlternateRel whether the rel for this link included
* "alternate".
* @param aCORSMode the CORS mode for this load.
* @param aObserver the observer to notify when the load completes.
* May be null.
* @param [out] aIsAlternate whether the stylesheet actually ended up beinga
* an alternate sheet. Note that this need not match
* aHasAlternateRel.
*/
nsresult LoadStyleLink(nsIContent* aElement,
nsIURI* aURL,
+ nsIPrincipal* aTriggeringPrincipal,
const nsAString& aTitle,
const nsAString& aMedia,
bool aHasAlternateRel,
CORSMode aCORSMode,
ReferrerPolicy aReferrerPolicy,
const nsAString& aIntegrity,
nsICSSLoaderObserver* aObserver,
bool* aIsAlternate);
--- a/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_triggeringPrincipal.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_triggeringPrincipal.js
@@ -448,16 +448,21 @@ add_task(async function test_contentscri
src: "imgset.png",
srcAttr: "srcset",
},
{
element: ["input", {type: "image"}],
src: "input.png",
},
{
+ element: ["link", {rel: "stylesheet"}],
+ src: "link.css",
+ srcAttr: "href",
+ },
+ {
element: ["picture", {}, ["source", {}], ["img", {}]],
src: "picture.png",
srcAttr: "srcset",
},
{
element: ["script", {}],
src: "script.js",
liveSrc: false,