diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 770eb43119..459ed7523a 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -9951,6 +9951,9 @@ nsDocShell::InternalLoad(nsIURI* aURI, int16_t shouldLoad = nsIContentPolicy::ACCEPT; rv = NS_CheckContentLoadPolicy(contentType, aURI, + // This is a top-level load, so the loading + // principal is null. + nullptr, aTriggeringPrincipal, requestingContext, EmptyCString(), // mime guess diff --git a/dom/base/AnonymousContent.cpp b/dom/base/AnonymousContent.cpp index ffb7597979..6b9f47be18 100644 --- a/dom/base/AnonymousContent.cpp +++ b/dom/base/AnonymousContent.cpp @@ -74,6 +74,7 @@ void AnonymousContent::SetAttributeForElement(const nsAString& aElementId, const nsAString& aName, const nsAString& aValue, + nsIPrincipal* aSubjectPrincipal, ErrorResult& aRv) { Element* element = GetElementById(aElementId); @@ -82,7 +83,7 @@ AnonymousContent::SetAttributeForElement(const nsAString& aElementId, return; } - element->SetAttribute(aName, aValue, aRv); + element->SetAttribute(aName, aValue, aSubjectPrincipal, aRv); } void diff --git a/dom/base/AnonymousContent.h b/dom/base/AnonymousContent.h index c1c2b189b6..161c117579 100644 --- a/dom/base/AnonymousContent.h +++ b/dom/base/AnonymousContent.h @@ -42,6 +42,7 @@ public: void SetAttributeForElement(const nsAString& aElementId, const nsAString& aName, const nsAString& aValue, + nsIPrincipal* aSubjectPrincipal, ErrorResult& aRv); void GetAttributeForElement(const nsAString& aElementId, diff --git a/dom/base/Attr.cpp b/dom/base/Attr.cpp index 91e9c1db23..2abe675a52 100644 --- a/dom/base/Attr.cpp +++ b/dom/base/Attr.cpp @@ -174,7 +174,7 @@ Attr::GetValue(nsAString& aValue) } void -Attr::SetValue(const nsAString& aValue, ErrorResult& aRv) +Attr::SetValue(const nsAString& aValue, nsIPrincipal* aTriggeringPrincipal, ErrorResult& aRv) { Element* element = GetElement(); if (!element) { @@ -187,6 +187,7 @@ Attr::SetValue(const nsAString& aValue, ErrorResult& aRv) nameAtom, mNodeInfo->GetPrefixAtom(), aValue, + aTriggeringPrincipal, true); } @@ -194,7 +195,7 @@ NS_IMETHODIMP Attr::SetValue(const nsAString& aValue) { ErrorResult rv; - SetValue(aValue, rv); + SetValue(aValue, nullptr, rv); return rv.StealNSResult(); } diff --git a/dom/base/Attr.h b/dom/base/Attr.h index 154a83102e..5c6fe895a5 100644 --- a/dom/base/Attr.h +++ b/dom/base/Attr.h @@ -84,9 +84,13 @@ public: virtual JSObject* WrapNode(JSContext* aCx, JS::Handle aGivenProto) override; // XPCOM GetName() is OK - // XPCOM GetValue() is OK - void SetValue(const nsAString& aValue, ErrorResult& aRv); + void GetValue(nsString& val, nsIPrincipal&) + { + GetValue(val); + } + + void SetValue(const nsAString& aValue, nsIPrincipal* aTriggeringPrincipal, ErrorResult& aRv); bool Specified() const; diff --git a/dom/base/DocumentFragment.h b/dom/base/DocumentFragment.h index 3ffc8ac0b8..817d37c9dd 100644 --- a/dom/base/DocumentFragment.h +++ b/dom/base/DocumentFragment.h @@ -69,13 +69,10 @@ public: virtual JSObject* WrapNode(JSContext *aCx, JS::Handle aGivenProto) override; // nsIContent - nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAString& aValue, bool aNotify) - { - return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify); - } + using nsIContent::SetAttr; virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix, const nsAString& aValue, + nsIPrincipal* aSubjectPrincipal, bool aNotify) override { return NS_OK; diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp index 7522128d46..7e555df9f6 100644 --- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -1254,6 +1254,7 @@ Element::ToggleAttribute(const nsAString& aName, void Element::SetAttribute(const nsAString& aName, const nsAString& aValue, + nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError) { aError = nsContentUtils::CheckQName(aName, false); @@ -1269,12 +1270,12 @@ Element::SetAttribute(const nsAString& aName, aError.Throw(NS_ERROR_OUT_OF_MEMORY); return; } - aError = SetAttr(kNameSpaceID_None, nameAtom, aValue, true); + aError = SetAttr(kNameSpaceID_None, nameAtom, aValue, aTriggeringPrincipal, true); return; } aError = SetAttr(name->NamespaceID(), name->LocalName(), name->GetPrefix(), - aValue, true); + aValue, aTriggeringPrincipal, true); return; } @@ -1357,6 +1358,7 @@ void Element::SetAttributeNS(const nsAString& aNamespaceURI, const nsAString& aQualifiedName, const nsAString& aValue, + nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError) { RefPtr ni; @@ -1370,7 +1372,7 @@ Element::SetAttributeNS(const nsAString& aNamespaceURI, } aError = SetAttr(ni->NamespaceID(), ni->NameAtom(), ni->GetPrefixAtom(), - aValue, true); + aValue, aTriggeringPrincipal, true); } void @@ -2419,6 +2421,7 @@ Element::SetSingleClassFromParser(nsIAtom* aSingleClassName) nullptr, // prefix nullptr, // old value value, + nullptr, // subject principal static_cast(nsIDOMMutationEvent::ADDITION), false, // hasListeners false, // notify @@ -2430,6 +2433,7 @@ Element::SetSingleClassFromParser(nsIAtom* aSingleClassName) nsresult Element::SetAttr(int32_t aNamespaceID, nsIAtom* aName, nsIAtom* aPrefix, const nsAString& aValue, + nsIPrincipal* aSubjectPrincipal, bool aNotify) { // Keep this in sync with SetParsedAttr below and SetSingleClassFromParser @@ -2489,7 +2493,8 @@ Element::SetAttr(int32_t aNamespaceID, nsIAtom* aName, return SetAttrAndNotify(aNamespaceID, aName, aPrefix, oldValueSet ? &oldValue : nullptr, - attrValue, modType, hasListeners, aNotify, + attrValue, aSubjectPrincipal, modType, + hasListeners, aNotify, kCallAfterSetAttr, document, updateBatch); } @@ -2534,7 +2539,7 @@ Element::SetParsedAttr(int32_t aNamespaceID, nsIAtom* aName, mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify); return SetAttrAndNotify(aNamespaceID, aName, aPrefix, oldValueSet ? &oldValue : nullptr, - aParsedValue, modType, hasListeners, aNotify, + aParsedValue, nullptr, modType, hasListeners, aNotify, kCallAfterSetAttr, document, updateBatch); } @@ -2544,6 +2549,7 @@ Element::SetAttrAndNotify(int32_t aNamespaceID, nsIAtom* aPrefix, const nsAttrValue* aOldValue, nsAttrValue& aParsedValue, + nsIPrincipal* aSubjectPrincipal, uint8_t aModType, bool aFireMutation, bool aNotify, @@ -2650,7 +2656,7 @@ Element::SetAttrAndNotify(int32_t aNamespaceID, if (aCallAfterSetAttr) { rv = AfterSetAttr(aNamespaceID, aName, &valueForAfterSetAttr, oldValue, - aNotify); + aSubjectPrincipal, aNotify); NS_ENSURE_SUCCESS(rv, rv); if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::dir) { @@ -2946,7 +2952,7 @@ Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName, } } - rv = AfterSetAttr(aNameSpaceID, aName, nullptr, &oldValue, aNotify); + rv = AfterSetAttr(aNameSpaceID, aName, nullptr, &oldValue, nullptr, aNotify); NS_ENSURE_SUCCESS(rv, rv); UpdateState(aNotify); @@ -4047,9 +4053,16 @@ Element::GetReferrerPolicyAsEnum() if (Preferences::GetBool("network.http.enablePerElementReferrer", true) && IsHTMLElement()) { const nsAttrValue* referrerValue = GetParsedAttr(nsGkAtoms::referrerpolicy); - if (referrerValue && referrerValue->Type() == nsAttrValue::eEnum) { - return net::ReferrerPolicy(referrerValue->GetEnumValue()); - } + return ReferrerPolicyFromAttr(referrerValue); + } + return net::RP_Unset; +} + +net::ReferrerPolicy +Element::ReferrerPolicyFromAttr(const nsAttrValue* aValue) +{ + if (aValue && aValue->Type() == nsAttrValue::eEnum) { + return net::ReferrerPolicy(aValue->GetEnumValue()); } return net::RP_Unset; } diff --git a/dom/base/Element.h b/dom/base/Element.h index 4d4c9284d3..ff7aef6177 100644 --- a/dom/base/Element.h +++ b/dom/base/Element.h @@ -542,12 +542,7 @@ public: already_AddRefed GetExistingAttrNameFromQName(const nsAString& aStr) const; - MOZ_ALWAYS_INLINE // Avoid a crashy hook from Avast 10 Beta (Bug 1058131) - nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAString& aValue, bool aNotify) - { - return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify); - } + using nsIContent::SetAttr; /** * Helper for SetAttr/SetParsedAttr. This method will return true if aNotify @@ -610,7 +605,8 @@ public: nsresult SetSingleClassFromParser(nsIAtom* aSingleClassName); virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix, - const nsAString& aValue, bool aNotify) override; + const nsAString& aValue, nsIPrincipal* aSubjectPrincipal, + bool aNotify) override; // aParsedValue receives the old value of the attribute. That's useful if // either the input or output value of aParsedValue is StoresOwnData. nsresult SetParsedAttr(int32_t aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix, @@ -783,11 +779,18 @@ public: bool ToggleAttribute(const nsAString& aName, const Optional& aForce, ErrorResult& aError); void SetAttribute(const nsAString& aName, const nsAString& aValue, - ErrorResult& aError); + nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError); void SetAttributeNS(const nsAString& aNamespaceURI, const nsAString& aLocalName, const nsAString& aValue, + nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError); + void SetAttribute(const nsAString& aName, const nsAString& aValue, + ErrorResult& aError) + { + SetAttribute(aName, aValue, nullptr, aError); + } + void RemoveAttribute(const nsAString& aName, ErrorResult& aError); void RemoveAttributeNS(const nsAString& aNamespaceURI, @@ -1232,6 +1235,11 @@ public: aError = SetAttr(kNameSpaceID_None, aAttr, aValue, true); } + void SetAttr(nsIAtom* aAttr, const nsAString& aValue, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aError) + { + aError = nsIContent::SetAttr(kNameSpaceID_None, aAttr, aValue, &aTriggeringPrincipal, true); + } + /** * Set a content attribute via a reflecting nullable string IDL * attribute (e.g. a CORS attribute). If DOMStringIsNull(aValue), @@ -1257,6 +1265,7 @@ public: float FontSizeInflation(); net::ReferrerPolicy GetReferrerPolicyAsEnum(); + net::ReferrerPolicy ReferrerPolicyFromAttr(const nsAttrValue* aValue); /* * Helpers for .dataset. This is implemented on Element, though only some @@ -1309,6 +1318,14 @@ protected: * @param aParsedValue parsed new value of attribute. Replaced by the * old value of the attribute. This old value is only * useful if either it or the new value is StoresOwnData. + * @param aMaybeScriptedPrincipal + * the principal of the scripted caller responsible for + * setting the attribute, or null if no scripted caller + * can be determined. A null value here does not + * guarantee that there is no scripted caller, but a + * non-null value does guarantee that a scripted caller + * with the given principal is directly responsible for + * the attribute change. * @param aModType nsIDOMMutationEvent::MODIFICATION or ADDITION. Only * needed if aFireMutation or aNotify is true. * @param aFireMutation should mutation-events be fired? @@ -1321,6 +1338,7 @@ protected: nsIAtom* aPrefix, const nsAttrValue* aOldValue, nsAttrValue& aParsedValue, + nsIPrincipal* aMaybeScriptedPrincipal, uint8_t aModType, bool aFireMutation, bool aNotify, @@ -1412,13 +1430,21 @@ protected: * the attr was not previously set. This argument may not have the * correct value for SVG elements, or other cases in which the * attribute value doesn't store its own data + * @param aMaybeScriptedPrincipal the principal of the scripted caller + * responsible for setting the attribute, or null if no scripted caller + * can be determined, or the attribute is being unset. A null value + * here does not guarantee that there is no scripted caller, but a + * non-null value does guarantee that a scripted caller with the given + * principal is directly responsible for the attribute change. * @param aNotify Whether we plan to notify document observers. */ // Note that this is inlined so that when subclasses call it it gets // inlined. Those calls don't go through a vtable. virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, const nsAttrValue* aValue, - const nsAttrValue* aOldValue, bool aNotify) + const nsAttrValue* aOldValue, + nsIPrincipal* aMaybeScriptedPrincipal, + bool aNotify) { return NS_OK; } @@ -1801,7 +1827,7 @@ NS_IMETHOD SetAttribute(const nsAString& name, \ const nsAString& value) override \ { \ mozilla::ErrorResult rv; \ - Element::SetAttribute(name, value, rv); \ + Element::SetAttribute(name, value, nullptr, rv); \ return rv.StealNSResult(); \ } \ NS_IMETHOD SetAttributeNS(const nsAString& namespaceURI, \ @@ -1809,22 +1835,22 @@ NS_IMETHOD SetAttributeNS(const nsAString& namespaceURI, \ const nsAString& value) final override \ { \ mozilla::ErrorResult rv; \ - Element::SetAttributeNS(namespaceURI, qualifiedName, value, rv); \ - return rv.StealNSResult(); \ + Element::SetAttributeNS(namespaceURI, qualifiedName, value, nullptr, rv); \ + return rv.StealNSResult(); \ } \ using Element::RemoveAttribute; \ NS_IMETHOD RemoveAttribute(const nsAString& name) final override \ { \ mozilla::ErrorResult rv; \ RemoveAttribute(name, rv); \ - return rv.StealNSResult(); \ + return rv.StealNSResult(); \ } \ NS_IMETHOD RemoveAttributeNS(const nsAString& namespaceURI, \ const nsAString& localName) final override \ { \ mozilla::ErrorResult rv; \ Element::RemoveAttributeNS(namespaceURI, localName, rv); \ - return rv.StealNSResult(); \ + return rv.StealNSResult(); \ } \ using Element::HasAttribute; \ NS_IMETHOD HasAttribute(const nsAString& name, \ @@ -1860,7 +1886,7 @@ NS_IMETHOD SetAttributeNode(nsIDOMAttr* newAttr, \ mozilla::ErrorResult rv; \ mozilla::dom::Attr* attr = static_cast(newAttr); \ *_retval = Element::SetAttributeNode(*attr, rv).take(); \ - return rv.StealNSResult(); \ + return rv.StealNSResult(); \ } \ NS_IMETHOD RemoveAttributeNode(nsIDOMAttr* oldAttr, \ nsIDOMAttr** _retval) final override \ @@ -1871,7 +1897,7 @@ NS_IMETHOD RemoveAttributeNode(nsIDOMAttr* oldAttr, \ mozilla::ErrorResult rv; \ mozilla::dom::Attr* attr = static_cast(oldAttr); \ *_retval = Element::RemoveAttributeNode(*attr, rv).take(); \ - return rv.StealNSResult(); \ + return rv.StealNSResult(); \ } \ NS_IMETHOD GetAttributeNodeNS(const nsAString& namespaceURI, \ const nsAString& localName, \ @@ -1887,7 +1913,7 @@ NS_IMETHOD SetAttributeNodeNS(nsIDOMAttr* newAttr, \ mozilla::ErrorResult rv; \ mozilla::dom::Attr* attr = static_cast(newAttr); \ *_retval = Element::SetAttributeNodeNS(*attr, rv).take(); \ - return rv.StealNSResult(); \ + return rv.StealNSResult(); \ } \ NS_IMETHOD GetElementsByTagName(const nsAString& name, \ nsIDOMHTMLCollection** _retval) final \ @@ -2055,7 +2081,7 @@ NS_IMETHOD ReleaseCapture(void) final override \ NS_IMETHOD MozRequestFullScreen(void) final override \ { \ mozilla::ErrorResult rv; \ - Element::RequestFullscreen(rv); \ + Element::RequestFullscreen(rv); \ return rv.StealNSResult(); \ } \ NS_IMETHOD MozRequestPointerLock(void) final override \ diff --git a/dom/base/ResponsiveImageSelector.cpp b/dom/base/ResponsiveImageSelector.cpp index 0a64fc7430..8a224bf459 100644 --- a/dom/base/ResponsiveImageSelector.cpp +++ b/dom/base/ResponsiveImageSelector.cpp @@ -115,7 +115,8 @@ ResponsiveImageSelector::~ResponsiveImageSelector() // http://www.whatwg.org/specs/web-apps/current-work/#processing-the-image-candidates bool -ResponsiveImageSelector::SetCandidatesFromSourceSet(const nsAString & aSrcSet) +ResponsiveImageSelector::SetCandidatesFromSourceSet(const nsAString & aSrcSet, + nsIPrincipal* aTriggeringPrincipal) { ClearSelectedCandidate(); @@ -167,6 +168,8 @@ ResponsiveImageSelector::SetCandidatesFromSourceSet(const nsAString & aSrcSet) ResponsiveImageCandidate candidate; if (candidate.ConsumeDescriptors(iter, end)) { candidate.SetURLSpec(urlStr); + candidate.SetTriggeringPrincipal(nsContentUtils::GetAttrTriggeringPrincipal( + Content(), urlStr, aTriggeringPrincipal)); AppendCandidateIfUnique(candidate); } } @@ -207,7 +210,8 @@ ResponsiveImageSelector::Document() } void -ResponsiveImageSelector::SetDefaultSource(const nsAString& aURLString) +ResponsiveImageSelector::SetDefaultSource(const nsAString& aURLString, + nsIPrincipal* aPrincipal) { ClearSelectedCandidate(); @@ -219,6 +223,7 @@ ResponsiveImageSelector::SetDefaultSource(const nsAString& aURLString) } mDefaultSourceURL = aURLString; + mDefaultSourceTriggeringPrincipal = aPrincipal; // Add new default to end of list MaybeAppendDefaultCandidate(); @@ -291,8 +296,9 @@ ResponsiveImageSelector::MaybeAppendDefaultCandidate() ResponsiveImageCandidate defaultCandidate; defaultCandidate.SetParameterDefault(); defaultCandidate.SetURLSpec(mDefaultSourceURL); + defaultCandidate.SetTriggeringPrincipal(mDefaultSourceTriggeringPrincipal); // We don't use MaybeAppend since we want to keep this even if it can never - // match, as it may if the source set changes. + // match, because as it may match if the source set changes dynamically. mCandidates.AppendElement(defaultCandidate); } @@ -329,6 +335,17 @@ ResponsiveImageSelector::GetSelectedImageDensity() return mCandidates[bestIndex].Density(this); } +nsIPrincipal* +ResponsiveImageSelector::GetSelectedImageTriggeringPrincipal() +{ + int bestIndex = GetSelectedCandidateIndex(); + if (bestIndex < 0) { + return nullptr; + } + + return mCandidates[bestIndex].TriggeringPrincipal(); +} + bool ResponsiveImageSelector::SelectImage(bool aReselect) { @@ -457,8 +474,10 @@ ResponsiveImageCandidate::ResponsiveImageCandidate() } ResponsiveImageCandidate::ResponsiveImageCandidate(const nsAString& aURLString, - double aDensity) + double aDensity, + nsIPrincipal* aTriggeringPrincipal) : mURLString(aURLString) + , mTriggeringPrincipal(aTriggeringPrincipal) { mType = eCandidateType_Density; mValue.mDensity = aDensity; @@ -471,6 +490,12 @@ ResponsiveImageCandidate::SetURLSpec(const nsAString& aURLString) mURLString = aURLString; } +void +ResponsiveImageCandidate::SetTriggeringPrincipal(nsIPrincipal* aPrincipal) +{ + mTriggeringPrincipal = aPrincipal; +} + void ResponsiveImageCandidate::SetParameterAsComputedWidth(int32_t aWidth) { @@ -717,6 +742,12 @@ ResponsiveImageCandidate::URLString() const return mURLString; } +nsIPrincipal* +ResponsiveImageCandidate::TriggeringPrincipal() const +{ + return mTriggeringPrincipal; +} + double ResponsiveImageCandidate::Density(ResponsiveImageSelector *aSelector) const { diff --git a/dom/base/ResponsiveImageSelector.h b/dom/base/ResponsiveImageSelector.h index b4314b8bf7..2f1245f594 100644 --- a/dom/base/ResponsiveImageSelector.h +++ b/dom/base/ResponsiveImageSelector.h @@ -44,14 +44,16 @@ public: // Given a srcset string, parse and replace current candidates (does not // replace default source) - bool SetCandidatesFromSourceSet(const nsAString & aSrcSet); + bool SetCandidatesFromSourceSet(const nsAString & aSrcSet, + nsIPrincipal* aTriggeringPrincipal = nullptr); // Fill the source sizes from a valid sizes descriptor. Returns false if // descriptor is invalid. bool SetSizesFromDescriptor(const nsAString & aSizesDescriptor); // Set the default source, treated as the least-precedence 1.0 density source. - void SetDefaultSource(const nsAString& aURLString); + void SetDefaultSource(const nsAString& aURLString, + nsIPrincipal* aPrincipal = nullptr); uint32_t NumCandidates(bool aIncludeDefault = true); @@ -69,6 +71,7 @@ public: // Returns false if there is no selected image bool GetSelectedImageURLSpec(nsAString& aResult); double GetSelectedImageDensity(); + nsIPrincipal* GetSelectedImageTriggeringPrincipal(); // Runs image selection now if necessary. If an image has already // been choosen, takes no action unless aReselect is true. @@ -107,6 +110,7 @@ private: nsCOMPtr mOwnerNode; // The cached URL for default candidate. nsString mDefaultSourceURL; + nsCOMPtr mDefaultSourceTriggeringPrincipal; // If this array contains an eCandidateType_Default, it should be the last // element, such that the Setters can preserve/replace it respectively. nsTArray mCandidates; @@ -122,9 +126,11 @@ private: class ResponsiveImageCandidate { public: ResponsiveImageCandidate(); - ResponsiveImageCandidate(const nsAString& aURLString, double aDensity); + ResponsiveImageCandidate(const nsAString& aURLString, double aDensity, + nsIPrincipal* aTriggeringPrincipal = nullptr); void SetURLSpec(const nsAString& aURLString); + void SetTriggeringPrincipal(nsIPrincipal* aPrincipal); // Set this as a default-candidate. This behaves the same as density 1.0, but // has a differing type such that it can be replaced by subsequent // SetDefaultSource calls. @@ -147,6 +153,7 @@ public: bool HasSameParameter(const ResponsiveImageCandidate & aOther) const; const nsAString& URLString() const; + nsIPrincipal* TriggeringPrincipal() const; // Compute and return the density relative to a selector. double Density(ResponsiveImageSelector *aSelector) const; @@ -171,6 +178,7 @@ public: private: nsString mURLString; + nsCOMPtr mTriggeringPrincipal; eCandidateType mType; union { double mDensity; diff --git a/dom/base/WebSocket.cpp b/dom/base/WebSocket.cpp index 075697dd71..f91de98773 100644 --- a/dom/base/WebSocket.cpp +++ b/dom/base/WebSocket.cpp @@ -1556,7 +1556,8 @@ WebSocketImpl::Init(JSContext* aCx, int16_t shouldLoad = nsIContentPolicy::ACCEPT; aRv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_WEBSOCKET, uri, - aPrincipal, + aPrincipal, // loading principal + aPrincipal, // triggering principal originDoc, EmptyCString(), nullptr, diff --git a/dom/base/nsContentPolicyUtils.h b/dom/base/nsContentPolicyUtils.h index 3984ede544..9b4de24276 100644 --- a/dom/base/nsContentPolicyUtils.h +++ b/dom/base/nsContentPolicyUtils.h @@ -152,7 +152,7 @@ NS_CP_ContentTypeName(uint32_t contentType) return NS_ERROR_FAILURE; \ \ return policy-> action (contentType, contentLocation, requestOrigin, \ - context, mimeType, extra, originPrincipal, \ + context, mimeType, extra, triggeringPrincipal, \ decision); \ PR_END_MACRO @@ -160,7 +160,7 @@ NS_CP_ContentTypeName(uint32_t contentType) #define CHECK_CONTENT_POLICY_WITH_SERVICE(action, _policy) \ PR_BEGIN_MACRO \ return _policy-> action (contentType, contentLocation, requestOrigin, \ - context, mimeType, extra, originPrincipal, \ + context, mimeType, extra, triggeringPrincipal, \ decision); \ PR_END_MACRO @@ -173,14 +173,18 @@ NS_CP_ContentTypeName(uint32_t contentType) #define CHECK_PRINCIPAL_AND_DATA(action) \ nsCOMPtr requestOrigin; \ PR_BEGIN_MACRO \ - if (originPrincipal) { \ + if (loadingPrincipal) { \ nsCOMPtr secMan = aSecMan; \ if (!secMan) { \ secMan = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID); \ } \ if (secMan) { \ bool isSystem; \ - nsresult rv = secMan->IsSystemPrincipal(originPrincipal, \ + /* We exempt most loads into any document with the system principal \ + * from content policy checks, mostly as an optimization. Which means \ + * that we need to apply this check to the loading principal, not the \ + * principal that triggered the load. */ \ + nsresult rv = secMan->IsSystemPrincipal(loadingPrincipal, \ &isSystem); \ NS_ENSURE_SUCCESS(rv, rv); \ if (isSystem && contentType != nsIContentPolicy::TYPE_DOCUMENT) { \ @@ -203,31 +207,33 @@ NS_CP_ContentTypeName(uint32_t contentType) dataPolicy-> action (externalType, contentLocation, \ requestOrigin, context, \ mimeType, extra, \ - originPrincipal, decision); \ + triggeringPrincipal, decision);\ } \ } \ } \ return NS_OK; \ } \ } \ - nsresult rv = originPrincipal->GetURI(getter_AddRefs(requestOrigin)); \ + nsresult rv = loadingPrincipal->GetURI(getter_AddRefs(requestOrigin)); \ NS_ENSURE_SUCCESS(rv, rv); \ } \ PR_END_MACRO /** * Alias for calling ShouldLoad on the content policy service. Parameters are - * the same as nsIContentPolicy::shouldLoad, except for the originPrincipal - * parameter, which should be non-null if possible, and the last two - * parameters, which can be used to pass in pointer to some useful services if - * the caller already has them. The origin URI to pass to shouldLoad will be - * the URI of originPrincipal, unless originPrincipal is null (in which case a - * null origin URI will be passed). + * the same as nsIContentPolicy::shouldLoad, except for the loadingPrincipal + * and triggeringPrincipal parameters (which should be non-null if possible, + * and have the same semantics as in LoadInfo), and the last two parameters, + * which can be used to pass in pointer to some useful services if the caller + * already has them. The origin URI to pass to shouldLoad will be the URI of + * loadingPrincipal, unless loadingPrincipal is null (in which case a null + * origin URI will be passed). */ inline nsresult NS_CheckContentLoadPolicy(uint32_t contentType, nsIURI *contentLocation, - nsIPrincipal *originPrincipal, + nsIPrincipal *loadingPrincipal, + nsIPrincipal *triggeringPrincipal, nsISupports *context, const nsACString &mimeType, nsISupports *extra, @@ -244,17 +250,19 @@ NS_CheckContentLoadPolicy(uint32_t contentType, /** * Alias for calling ShouldProcess on the content policy service. Parameters - * are the same as nsIContentPolicy::shouldLoad, except for the originPrincipal - * parameter, which should be non-null if possible, and the last two - * parameters, which can be used to pass in pointer to some useful services if - * the caller already has them. The origin URI to pass to shouldLoad will be - * the URI of originPrincipal, unless originPrincipal is null (in which case a - * null origin URI will be passed). + * are the same as nsIContentPolicy::shouldLoad, except for the and + * triggeringPrincipal parameters (which should be non-null if possible, and + * have the same semantics as in nsLoadInfo), and the last parameter, which + * can be used to pass in a pointer to a useful service if the caller already + * has it. The origin URI to pass to shouldLoad will be the URI of + * loadingPrincipal, unless loadingPrincipal is null (in which case a null + * origin URI will be passed). */ inline nsresult NS_CheckContentProcessPolicy(uint32_t contentType, nsIURI *contentLocation, - nsIPrincipal *originPrincipal, + nsIPrincipal *loadingPrincipal, + nsIPrincipal *triggeringPrincipal, nsISupports *context, const nsACString &mimeType, nsISupports *extra, diff --git a/dom/base/nsContentSink.cpp b/dom/base/nsContentSink.cpp index 066ec84466..2040b1a70f 100644 --- a/dom/base/nsContentSink.cpp +++ b/dom/base/nsContentSink.cpp @@ -820,7 +820,8 @@ nsContentSink::ProcessStyleLink(nsIContent* aElement, // We don't support CORS for processing instructions bool isAlternate; bool isExplicitlyEnabled; - rv = mCSSLoader->LoadStyleLink(aElement, url, aTitle, aMedia, aAlternate, + rv = mCSSLoader->LoadStyleLink(aElement, url, nullptr /* triggeringPrincipal */, + aTitle, aMedia, aAlternate, CORS_NONE, referrerPolicy, integrity, mRunsToCompletion ? nullptr : this, &isAlternate, &isExplicitlyEnabled); diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index 155d55ac29..e4b49f0d13 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -199,6 +199,7 @@ #include "nsThreadUtils.h" #include "nsUnicharUtilCIID.h" #include "nsUnicodeProperties.h" +#include "nsURLHelper.h" #include "nsViewManager.h" #include "nsViewportInfo.h" #include "nsWidgetsCID.h" @@ -2118,6 +2119,54 @@ nsContentUtils::CanCallerAccess(nsPIDOMWindowInner* aWindow) return CanCallerAccess(SubjectPrincipal(), scriptObject->GetPrincipal()); } +// static +nsIPrincipal* +nsContentUtils::GetAttrTriggeringPrincipal(nsIContent* aContent, const nsAString& aAttrValue, + nsIPrincipal* aSubjectPrincipal) +{ + nsIPrincipal* contentPrin = aContent ? aContent->NodePrincipal() : nullptr; + + // If the subject principal is the same as the content principal, or no + // explicit subject principal was provided, we don't need to do any further + // checks. Just return the content principal. + if (contentPrin == aSubjectPrincipal || !aSubjectPrincipal) { + return contentPrin; + } + + // If the attribute value is empty, it's not an absolute URL, so don't bother + // with more expensive checks. + if (!aAttrValue.IsEmpty() && + IsAbsoluteURL(NS_ConvertUTF16toUTF8(aAttrValue))) { + return aSubjectPrincipal; + } + + return contentPrin; +} + +// static +bool +nsContentUtils::IsAbsoluteURL(const nsACString& aURL) +{ + nsAutoCString scheme; + if (NS_FAILED(net_ExtractURLScheme(aURL, scheme))) { + // If we can't extract a scheme, it's not an absolute URL. + return false; + } + + // If it parses as an absolute StandardURL, it's definitely an absolute URL, + // so no need to check with the IO service. + if (net_IsAbsoluteURL(aURL)) { + return true; + } + + uint32_t flags; + if (NS_SUCCEEDED(sIOService->GetProtocolFlags(scheme.get(), &flags))) { + return flags & nsIProtocolHandler::URI_NORELATIVE; + } + + return false; +} + //static bool nsContentUtils::InProlog(nsINode *aNode) @@ -3289,6 +3338,7 @@ nsContentUtils::CanLoadImage(nsIURI* aURI, nsISupports* aContext, rv = NS_CheckContentLoadPolicy(aContentType, aURI, aLoadingPrincipal, + aLoadingPrincipal, // triggering principal aContext, EmptyCString(), //mime guess nullptr, //extra @@ -8930,6 +8980,25 @@ nsContentUtils::StreamsEnabled(JSContext* aCx, JSObject* aObj) return workerPrivate->StreamsEnabled(); } +// static +bool +nsContentUtils::CSPEnabled(JSContext* aCx, JSObject* aObj) +{ + if (NS_IsMainThread()) { + return Preferences::GetBool("security.csp.enabled", true); + } + + using namespace workers; + + // Otherwise, check the pref via the WorkerPrivate + WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx); + if (!workerPrivate) { + return false; + } + + return workerPrivate->CSPEnabled(); +} + // static bool nsContentUtils::IsNonSubresourceRequest(nsIChannel* aChannel) diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index 37866aaf64..00871628cf 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -526,6 +526,40 @@ public: // aWindow can be either outer or inner window. static bool CanCallerAccess(nsPIDOMWindowInner* aWindow); + /** + * Returns the triggering principal which should be used for the given URL + * attribute value with the given subject principal. + * + * If the attribute value is not an absolute URL, the subject principal will + * be ignored, and the node principal of aContent will be used instead. + * If aContent is non-null, this function will always return a principal. + * Otherewise, it may return null if aSubjectPrincipal is null or is rejected + * based on the attribute value. + * + * @param aContent The content on which the attribute is being set. + * @param aAttrValue The URL value of the attribute. For parsed attribute + * values, such as `srcset`, this function should be called separately + * for each URL value it contains. + * @param aSubjectPrincipal The subject principal of the scripted caller + * responsible for setting the attribute, or null if no scripted caller + * can be determined. + */ + static nsIPrincipal* GetAttrTriggeringPrincipal(nsIContent* aContent, + const nsAString& aAttrValue, + nsIPrincipal* aSubjectPrincipal); + + /** + * Returns true if the given string is guaranteed to be treated as an absolute + * URL, rather than a relative URL. In practice, this means any complete URL + * as supported by nsStandardURL, or any string beginning with a valid scheme + * which is known to the IO service, and has the URI_NORELATIVE flag. + * + * If the URL may be treated as absolute in some cases, but relative in others + * (for instance, "http:foo", which can be either an absolute or relative URL, + * depending on the context), this function returns false. + */ + static bool IsAbsoluteURL(const nsACString& aURL); + /** * GetDocumentFromCaller gets its document by looking at the last called * function and finding the document that the function itself relates to. @@ -2764,6 +2798,8 @@ public: static bool PushEnabled(JSContext* aCx, JSObject* aObj); + static bool CSPEnabled(JSContext* aCx, JSObject* aObj); + static bool StreamsEnabled(JSContext* aCx, JSObject* aObj); static bool IsNonSubresourceRequest(nsIChannel* aChannel); diff --git a/dom/base/nsFrameLoader.cpp b/dom/base/nsFrameLoader.cpp index ee030abf24..fb655244af 100644 --- a/dom/base/nsFrameLoader.cpp +++ b/dom/base/nsFrameLoader.cpp @@ -57,6 +57,7 @@ #include "nsView.h" #include "GroupedSHistory.h" #include "PartialSHistory.h" +#include "nsQueryObject.h" #include "nsIURI.h" #include "nsIURL.h" @@ -86,6 +87,7 @@ #include "mozilla/dom/Element.h" #include "mozilla/jsipc/CrossProcessObjectWrappers.h" #include "mozilla/layout/RenderFrameParent.h" +#include "nsGenericHTMLFrameElement.h" #include "GeckoProfiler.h" #include "jsapi.h" @@ -231,6 +233,7 @@ nsFrameLoader::LoadFrame() NS_ENSURE_TRUE(mOwnerContent, NS_ERROR_NOT_INITIALIZED); nsAutoString src; + nsCOMPtr principal; bool isSrcdoc = mOwnerContent->IsHTMLElement(nsGkAtoms::iframe) && mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::srcdoc); @@ -238,7 +241,7 @@ nsFrameLoader::LoadFrame() src.AssignLiteral("about:srcdoc"); } else { - GetURL(src); + GetURL(src, getter_AddRefs(principal)); src.Trim(" \t\n\r"); @@ -279,7 +282,7 @@ nsFrameLoader::LoadFrame() } if (NS_SUCCEEDED(rv)) { - rv = LoadURI(uri); + rv = LoadURI(uri, principal); } if (NS_FAILED(rv)) { @@ -305,7 +308,7 @@ nsFrameLoader::FireErrorEvent() } NS_IMETHODIMP -nsFrameLoader::LoadURI(nsIURI* aURI) +nsFrameLoader::LoadURI(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal) { if (!aURI) return NS_ERROR_INVALID_POINTER; @@ -313,13 +316,15 @@ nsFrameLoader::LoadURI(nsIURI* aURI) nsCOMPtr doc = mOwnerContent->OwnerDoc(); - nsresult rv = CheckURILoad(aURI); + nsresult rv = CheckURILoad(aURI, aTriggeringPrincipal); NS_ENSURE_SUCCESS(rv, rv); mURIToLoad = aURI; + mTriggeringPrincipal = aTriggeringPrincipal ? aTriggeringPrincipal : nullptr; rv = doc->InitializeFrameLoader(this); if (NS_FAILED(rv)) { mURIToLoad = nullptr; + mTriggeringPrincipal = nullptr; } return rv; } @@ -513,7 +518,7 @@ nsFrameLoader::ReallyStartLoadingInternal() "MaybeCreateDocShell succeeded with a null mDocShell"); // Just to be safe, recheck uri. - rv = CheckURILoad(mURIToLoad); + rv = CheckURILoad(mURIToLoad, mTriggeringPrincipal); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr loadInfo; @@ -527,7 +532,11 @@ nsFrameLoader::ReallyStartLoadingInternal() // We'll use our principal, not that of the document loaded inside us. This // is very important; needed to prevent XSS attacks on documents loaded in // subframes! - loadInfo->SetTriggeringPrincipal(mOwnerContent->NodePrincipal()); + if (mTriggeringPrincipal) { + loadInfo->SetTriggeringPrincipal(mTriggeringPrincipal); + } else { + loadInfo->SetTriggeringPrincipal(mOwnerContent->NodePrincipal()); + } nsCOMPtr referrer; @@ -601,7 +610,7 @@ nsFrameLoader::ReallyStartLoadingInternal() } nsresult -nsFrameLoader::CheckURILoad(nsIURI* aURI) +nsFrameLoader::CheckURILoad(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal) { // Check for security. The fun part is trying to figure out what principals // to use. The way I figure it, if we're doing a LoadFrame() accidentally @@ -620,7 +629,9 @@ nsFrameLoader::CheckURILoad(nsIURI* aURI) nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager(); // Get our principal - nsIPrincipal* principal = mOwnerContent->NodePrincipal(); + nsIPrincipal* principal = (aTriggeringPrincipal ? + aTriggeringPrincipal : + mOwnerContent->NodePrincipal()); // Check if we are allowed to load absURL nsresult rv = @@ -2191,7 +2202,7 @@ nsFrameLoader::MaybeCreateDocShell() } void -nsFrameLoader::GetURL(nsString& aURI) +nsFrameLoader::GetURL(nsString& aURI, nsIPrincipal** aTriggeringPrincipal) { aURI.Truncate(); @@ -2199,6 +2210,10 @@ nsFrameLoader::GetURL(nsString& aURI) mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::data, aURI); } else { mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::src, aURI); + if (RefPtr frame = do_QueryObject(mOwnerContent)) { + nsCOMPtr prin = frame->GetSrcTriggeringPrincipal(); + prin.forget(aTriggeringPrincipal); + } } } diff --git a/dom/base/nsFrameLoader.h b/dom/base/nsFrameLoader.h index 900997572e..e8091ea915 100644 --- a/dom/base/nsFrameLoader.h +++ b/dom/base/nsFrameLoader.h @@ -215,7 +215,7 @@ public: */ void ApplySandboxFlags(uint32_t sandboxFlags); - void GetURL(nsString& aURL); + void GetURL(nsString& aURL, nsIPrincipal** aTriggeringPrincipal); // Properly retrieves documentSize of any subdocument type. nsresult GetWindowDimensions(nsIntRect& aRect); @@ -264,7 +264,17 @@ private: // Updates the subdocument position and size. This gets called only // when we have our own in-process DocShell. void UpdateBaseWindowPositionAndSize(nsSubDocumentFrame *aIFrame); - nsresult CheckURILoad(nsIURI* aURI); + + /** + * Checks whether a load of the given URI should be allowed, and returns an + * error result if it should not. + * + * @param aURI The URI to check. + * @param aTriggeringPrincipal The triggering principal for the load. May be + * null, in which case the node principal of the owner content is used. + */ + nsresult CheckURILoad(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal); + void FireErrorEvent(); nsresult ReallyStartLoadingInternal(); @@ -302,6 +312,7 @@ private: nsCOMPtr mDocShell; nsCOMPtr mURIToLoad; + nsCOMPtr mTriggeringPrincipal; mozilla::dom::Element* mOwnerContent; // WEAK // After the frameloader has been removed from the DOM but before all of the diff --git a/dom/base/nsGenericDOMDataNode.cpp b/dom/base/nsGenericDOMDataNode.cpp index ebb135d88b..85f8833d00 100644 --- a/dom/base/nsGenericDOMDataNode.cpp +++ b/dom/base/nsGenericDOMDataNode.cpp @@ -625,6 +625,7 @@ nsGenericDOMDataNode::GetChildren(uint32_t aFilter) nsresult nsGenericDOMDataNode::SetAttr(int32_t aNameSpaceID, nsIAtom* aAttr, nsIAtom* aPrefix, const nsAString& aValue, + nsIPrincipal* aContentPrincipal, bool aNotify) { return NS_OK; diff --git a/dom/base/nsGenericDOMDataNode.h b/dom/base/nsGenericDOMDataNode.h index c3e8ae4740..683528efea 100644 --- a/dom/base/nsGenericDOMDataNode.h +++ b/dom/base/nsGenericDOMDataNode.h @@ -117,13 +117,10 @@ public: virtual already_AddRefed GetChildren(uint32_t aFilter) override; - nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAString& aValue, bool aNotify) - { - return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify); - } + using nsIContent::SetAttr; virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, nsIAtom* aPrefix, const nsAString& aValue, + nsIPrincipal* aSubjectPrincipal, bool aNotify) override; virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, bool aNotify) override; diff --git a/dom/base/nsIContent.h b/dom/base/nsIContent.h index 4e2f1e09fb..35451444ac 100644 --- a/dom/base/nsIContent.h +++ b/dom/base/nsIContent.h @@ -363,6 +363,16 @@ public: { return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify); } + nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix, + const nsAString& aValue, bool aNotify) + { + return SetAttr(aNameSpaceID, aName, aPrefix, aValue, nullptr, aNotify); + } + nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAString& aValue, + nsIPrincipal* aTriggeringPrincipal, bool aNotify) + { + return SetAttr(aNameSpaceID, aName, nullptr, aValue, aTriggeringPrincipal, aNotify); + } /** * Set attribute values. All attribute values are assumed to have a @@ -375,11 +385,18 @@ public: * @param aName the name of the attribute * @param aPrefix the prefix of the attribute * @param aValue the value to set + * @param aMaybeScriptedPrincipal the principal of the scripted caller responsible + * for setting the attribute, or null if no scripted caller can be + * determined. A null value here does not guarantee that there is no + * scripted caller, but a non-null value does guarantee that a scripted + * caller with the given principal is directly responsible for the + * attribute change. * @param aNotify specifies how whether or not the document should be * notified of the attribute change. */ virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix, const nsAString& aValue, + nsIPrincipal* aMaybeScriptedPrincipal, bool aNotify) = 0; /** diff --git a/dom/base/nsIContentPolicy.idl b/dom/base/nsIContentPolicy.idl index 870ed6f739..31044e46f0 100644 --- a/dom/base/nsIContentPolicy.idl +++ b/dom/base/nsIContentPolicy.idl @@ -34,8 +34,11 @@ interface nsIContentPolicy : nsIContentPolicyBase * not be null * * @param aRequestOrigin OPTIONAL. the location of the resource that - * initiated this load request; can be null if - * inapplicable + * that is loading the request. This will generally + * be the URI of the loading principal for the + * resulting request (as determined by its + * LoadInfo), but may vary depending on the + * caller. Can be null if inapplicable. * * @param aContext OPTIONAL. the nsIDOMNode or nsIDOMWindow that * initiated the request, or something that can QI @@ -55,8 +58,12 @@ interface nsIContentPolicy : nsIContentPolicyBase * @param aRequestPrincipal an OPTIONAL argument, defines the principal that * caused the load. This is optional only for * non-gecko code: all gecko code should set this - * argument. For navigation events, this is - * the principal of the page that caused this load. + * argument. This should generally be the same as + * the triggering principal for the resulting + * request (as determined by its LoadInfo), but may + * vary depending on the caller. Sometimes it will + * be the loading principal or final channel + * principal instead. * * @return ACCEPT or REJECT_* * diff --git a/dom/base/nsIFrameLoader.idl b/dom/base/nsIFrameLoader.idl index d09dd93421..dbb976aa3e 100644 --- a/dom/base/nsIFrameLoader.idl +++ b/dom/base/nsIFrameLoader.idl @@ -8,6 +8,7 @@ interface nsFrameLoader; interface nsIDocShell; interface nsIURI; +interface nsIPrincipal; interface nsIFrame; interface nsSubDocumentFrame; interface nsIMessageSender; @@ -51,7 +52,7 @@ interface nsIFrameLoader : nsISupports * Loads the specified URI in this frame. Behaves identically to loadFrame, * except that this method allows specifying the URI to load. */ - void loadURI(in nsIURI aURI); + void loadURI(in nsIURI aURI, [optional] in nsIPrincipal aTriggeringPrincipal); /** * Puts the frameloader in prerendering mode. diff --git a/dom/base/nsImageLoadingContent.cpp b/dom/base/nsImageLoadingContent.cpp index 26fa18df99..082522ccbf 100644 --- a/dom/base/nsImageLoadingContent.cpp +++ b/dom/base/nsImageLoadingContent.cpp @@ -734,7 +734,8 @@ nsresult nsImageLoadingContent::LoadImage(const nsAString& aNewURI, bool aForce, bool aNotify, - ImageLoadType aImageLoadType) + ImageLoadType aImageLoadType, + nsIPrincipal* aTriggeringPrincipal) { // First, get a document (needed for security checks and the like) nsIDocument* doc = GetOurOwnerDoc(); @@ -768,7 +769,8 @@ nsImageLoadingContent::LoadImage(const nsAString& aNewURI, NS_TryToSetImmutable(imageURI); - return LoadImage(imageURI, aForce, aNotify, aImageLoadType, false, doc); + return LoadImage(imageURI, aForce, aNotify, aImageLoadType, false, doc, + nsIRequest::LOAD_NORMAL, aTriggeringPrincipal); } nsresult @@ -778,7 +780,8 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI, ImageLoadType aImageLoadType, bool aLoadStart, nsIDocument* aDocument, - nsLoadFlags aLoadFlags) + nsLoadFlags aLoadFlags, + nsIPrincipal* aTriggeringPrincipal) { MOZ_ASSERT(!mIsStartingImageLoad, "some evil code is reentering LoadImage."); if (mIsStartingImageLoad) { @@ -886,7 +889,7 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI, nsresult rv = nsContentUtils::LoadImage(aNewURI, thisNode, aDocument, - aDocument->NodePrincipal(), + aTriggeringPrincipal ? aTriggeringPrincipal : aDocument->NodePrincipal(), aDocument->GetDocumentURI(), referrerPolicy, this, loadFlags, diff --git a/dom/base/nsImageLoadingContent.h b/dom/base/nsImageLoadingContent.h index b97bede0d0..85240db788 100644 --- a/dom/base/nsImageLoadingContent.h +++ b/dom/base/nsImageLoadingContent.h @@ -102,9 +102,12 @@ protected: * @param aNotify If true, nsIDocumentObserver state change notifications * will be sent as needed. * @param aImageLoadType The ImageLoadType for this request + * @param aTriggeringPrincipal Optional parameter specifying the triggering + * principal to use for the image load */ nsresult LoadImage(const nsAString& aNewURI, bool aForce, - bool aNotify, ImageLoadType aImageLoadType); + bool aNotify, ImageLoadType aImageLoadType, + nsIPrincipal* aTriggeringPrincipal = nullptr); /** * ImageState is called by subclasses that are computing their content state. @@ -134,11 +137,23 @@ protected: * This is purely a performance optimization. * @param aLoadFlags Optional parameter specifying load flags to use for * the image load + * @param aTriggeringPrincipal Optional parameter specifying the triggering + * principal to use for the image load */ nsresult LoadImage(nsIURI* aNewURI, bool aForce, bool aNotify, ImageLoadType aImageLoadType, bool aLoadStart = true, nsIDocument* aDocument = nullptr, - nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL); + nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL, + nsIPrincipal* aTriggeringPrincipal = nullptr); + // Simplified version to pass triggering principal with defaults otherwise. + nsresult LoadImage(nsIURI* aNewURI, bool aForce, bool aNotify, + ImageLoadType aImageLoadType, + nsIPrincipal* aTriggeringPrincipal) + { + return LoadImage(aNewURI, aForce, aNotify, aImageLoadType, + true, nullptr, nsIRequest::LOAD_NORMAL, + aTriggeringPrincipal); + } /** * helpers to get the document for this content (from the nodeinfo diff --git a/dom/base/nsObjectLoadingContent.cpp b/dom/base/nsObjectLoadingContent.cpp index 0f0c9106eb..e6ff926906 100644 --- a/dom/base/nsObjectLoadingContent.cpp +++ b/dom/base/nsObjectLoadingContent.cpp @@ -1633,7 +1633,8 @@ nsObjectLoadingContent::CheckLoadPolicy(int16_t *aContentPolicy) *aContentPolicy = nsIContentPolicy::ACCEPT; nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType, mURI, - doc->NodePrincipal(), + doc->NodePrincipal(), // loading principal + doc->NodePrincipal(), // triggering principal thisContent, mContentType, nullptr, //extra @@ -1684,7 +1685,8 @@ nsObjectLoadingContent::CheckProcessPolicy(int16_t *aContentPolicy) nsresult rv = NS_CheckContentProcessPolicy(objectType, mURI ? mURI : mBaseURI, - doc->NodePrincipal(), + doc->NodePrincipal(), // loading principal + doc->NodePrincipal(), // triggering principal static_cast(this), mContentType, nullptr, //extra diff --git a/dom/base/nsStyleLinkElement.cpp b/dom/base/nsStyleLinkElement.cpp index 971af21b4c..2da27ca2f6 100644 --- a/dom/base/nsStyleLinkElement.cpp +++ b/dom/base/nsStyleLinkElement.cpp @@ -224,8 +224,7 @@ nsStyleLinkElement::UpdateStyleSheet(nsICSSLoaderObserver* aObserver, { if (aForceReload) { // We remove this stylesheet from the cache to load a new version. - nsCOMPtr thisContent; - CallQueryInterface(this, getter_AddRefs(thisContent)); + nsCOMPtr thisContent = do_QueryInterface(this); nsCOMPtr doc = thisContent->IsInShadowTree() ? thisContent->OwnerDoc() : thisContent->GetUncomposedDoc(); if (doc && doc->CSSLoader()->GetEnabled() && @@ -306,11 +305,10 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument, { *aWillNotify = false; - nsCOMPtr thisContent; - CallQueryInterface(this, getter_AddRefs(thisContent)); + nsCOMPtr thisContent = do_QueryInterface(this); // All instances of nsStyleLinkElement should implement nsIContent. - NS_ENSURE_TRUE(thisContent, NS_ERROR_FAILURE); + MOZ_ASSERT(thisContent); if (thisContent->IsInAnonymousSubtree() && thisContent->IsAnonymousContentInSVGUseSubtree()) { @@ -362,7 +360,8 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument, } bool isInline; - nsCOMPtr uri = GetStyleSheetURL(&isInline); + nsCOMPtr triggeringPrincipal; + nsCOMPtr uri = GetStyleSheetURL(&isInline, getter_AddRefs(triggeringPrincipal)); if (!aForceUpdate && mStyleSheet && !isInline && uri) { nsIURI* oldURI = mStyleSheet->GetSheetURI(); @@ -455,8 +454,8 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument, 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, &isExplicitlyEnabled); if (NS_FAILED(rv)) { // Don't propagate LoadStyleLink() errors further than this, since some @@ -486,8 +485,7 @@ nsStyleLinkElement::UpdateStyleSheetScopedness(bool aIsNowScoped) CSSStyleSheet* sheet = mStyleSheet->AsConcrete(); - nsCOMPtr thisContent; - CallQueryInterface(this, getter_AddRefs(thisContent)); + nsCOMPtr thisContent = do_QueryInterface(this); Element* oldScopeElement = sheet->GetScopeElement(); Element* newScopeElement = aIsNowScoped ? diff --git a/dom/base/nsStyleLinkElement.h b/dom/base/nsStyleLinkElement.h index a76cd8a6b2..b7d57ca3d1 100644 --- a/dom/base/nsStyleLinkElement.h +++ b/dom/base/nsStyleLinkElement.h @@ -95,7 +95,7 @@ protected: void UpdateStyleSheetScopedness(bool aIsNowScoped); - virtual already_AddRefed GetStyleSheetURL(bool* aIsInline) = 0; + virtual already_AddRefed GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal) = 0; virtual void GetStyleSheetInfo(nsAString& aTitle, nsAString& aType, nsAString& aMedia, @@ -140,6 +140,7 @@ private: RefPtr mStyleSheet; protected: + nsCOMPtr mTriggeringPrincipal; bool mDontLoadStyle; bool mUpdatesEnabled; uint32_t mLineNumber; diff --git a/dom/base/nsStyledElement.cpp b/dom/base/nsStyledElement.cpp index 4fd423acc7..01c8856444 100644 --- a/dom/base/nsStyledElement.cpp +++ b/dom/base/nsStyledElement.cpp @@ -110,7 +110,8 @@ nsStyledElement::SetInlineStyleDeclaration(css::Declaration* aDeclaration, nsIDocument* document = GetComposedDoc(); mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify); return SetAttrAndNotify(kNameSpaceID_None, nsGkAtoms::style, nullptr, - oldValueSet ? &oldValue : nullptr, attrValue, modType, + oldValueSet ? &oldValue : nullptr, attrValue, + nullptr, modType, hasListeners, aNotify, kDontCallAfterSetAttr, document, updateBatch); } diff --git a/dom/html/HTMLAnchorElement.cpp b/dom/html/HTMLAnchorElement.cpp index 2fb5ea4677..01e1ab1759 100644 --- a/dom/html/HTMLAnchorElement.cpp +++ b/dom/html/HTMLAnchorElement.cpp @@ -386,7 +386,9 @@ HTMLAnchorElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, nsresult HTMLAnchorElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, const nsAttrValue* aValue, - const nsAttrValue* aOldValue, bool aNotify) + const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, + bool aNotify) { if (aNamespaceID == kNameSpaceID_None) { if (aName == nsGkAtoms::href) { @@ -398,7 +400,8 @@ HTMLAnchorElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, } return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, - aValue, aOldValue, aNotify); + aValue, aOldValue, + aSubjectPrincipal, aNotify); } EventStates diff --git a/dom/html/HTMLAnchorElement.h b/dom/html/HTMLAnchorElement.h index c80c823c72..99c37b9676 100644 --- a/dom/html/HTMLAnchorElement.h +++ b/dom/html/HTMLAnchorElement.h @@ -71,6 +71,7 @@ public: virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, const nsAttrValue* aValue, const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, bool aNotify) override; virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override; diff --git a/dom/html/HTMLAreaElement.cpp b/dom/html/HTMLAreaElement.cpp index 89c25f2902..834c13b9ab 100644 --- a/dom/html/HTMLAreaElement.cpp +++ b/dom/html/HTMLAreaElement.cpp @@ -142,7 +142,9 @@ HTMLAreaElement::UnbindFromTree(bool aDeep, bool aNullParent) nsresult HTMLAreaElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, const nsAttrValue* aValue, - const nsAttrValue* aOldValue, bool aNotify) + const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, + bool aNotify) { if (aNamespaceID == kNameSpaceID_None) { // This must happen after the attribute is set. We will need the updated @@ -155,7 +157,7 @@ HTMLAreaElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, } return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue, - aOldValue, aNotify); + aOldValue, aSubjectPrincipal, aNotify); } #define IMPL_URI_PART(_part) \ diff --git a/dom/html/HTMLAreaElement.h b/dom/html/HTMLAreaElement.h index 919ba9d60c..083675824a 100644 --- a/dom/html/HTMLAreaElement.h +++ b/dom/html/HTMLAreaElement.h @@ -178,6 +178,7 @@ protected: virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, const nsAttrValue* aValue, const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, bool aNotify) override; RefPtr mRelList; diff --git a/dom/html/HTMLButtonElement.cpp b/dom/html/HTMLButtonElement.cpp index 3e48c09d16..853a9db0f4 100644 --- a/dom/html/HTMLButtonElement.cpp +++ b/dom/html/HTMLButtonElement.cpp @@ -438,7 +438,9 @@ HTMLButtonElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsresult HTMLButtonElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, - const nsAttrValue* aOldValue, bool aNotify) + const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, + bool aNotify) { if (aNameSpaceID == kNameSpaceID_None) { if (aName == nsGkAtoms::type) { @@ -454,7 +456,7 @@ HTMLButtonElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName, aValue, aOldValue, - aNotify); + aSubjectPrincipal, aNotify); } NS_IMETHODIMP diff --git a/dom/html/HTMLButtonElement.h b/dom/html/HTMLButtonElement.h index 139596ae30..3765ce8d12 100644 --- a/dom/html/HTMLButtonElement.h +++ b/dom/html/HTMLButtonElement.h @@ -88,6 +88,7 @@ public: virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, const nsAttrValue* aValue, const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, bool aNotify) override; virtual bool ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute, diff --git a/dom/html/HTMLCanvasElement.cpp b/dom/html/HTMLCanvasElement.cpp index 1d6c008240..b7071079ac 100644 --- a/dom/html/HTMLCanvasElement.cpp +++ b/dom/html/HTMLCanvasElement.cpp @@ -443,12 +443,14 @@ NS_IMPL_BOOL_ATTR(HTMLCanvasElement, MozOpaque, moz_opaque) nsresult HTMLCanvasElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, const nsAttrValue* aValue, - const nsAttrValue* aOldValue, bool aNotify) + const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, + bool aNotify) { AfterMaybeChangeAttr(aNamespaceID, aName, aNotify); return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue, - aOldValue, aNotify); + aOldValue, aSubjectPrincipal, aNotify); } nsresult diff --git a/dom/html/HTMLCanvasElement.h b/dom/html/HTMLCanvasElement.h index b84f2eac92..e647cd43a2 100644 --- a/dom/html/HTMLCanvasElement.h +++ b/dom/html/HTMLCanvasElement.h @@ -361,6 +361,7 @@ protected: virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, const nsAttrValue* aValue, const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, bool aNotify) override; virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsIAtom* aName, const nsAttrValueOrString& aValue, diff --git a/dom/html/HTMLFieldSetElement.cpp b/dom/html/HTMLFieldSetElement.cpp index 9052d399eb..8cf87f31bc 100644 --- a/dom/html/HTMLFieldSetElement.cpp +++ b/dom/html/HTMLFieldSetElement.cpp @@ -83,7 +83,9 @@ HTMLFieldSetElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) nsresult HTMLFieldSetElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, - const nsAttrValue* aOldValue, bool aNotify) + const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, + bool aNotify) { if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::disabled && nsINode::GetFirstChild()) { @@ -100,7 +102,8 @@ HTMLFieldSetElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName, - aValue, aOldValue, aNotify); + aValue, aOldValue, + aSubjectPrincipal, aNotify); } // nsIDOMHTMLFieldSetElement diff --git a/dom/html/HTMLFieldSetElement.h b/dom/html/HTMLFieldSetElement.h index e56a279c34..80990dc63b 100644 --- a/dom/html/HTMLFieldSetElement.h +++ b/dom/html/HTMLFieldSetElement.h @@ -44,6 +44,7 @@ public: virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, bool aNotify) override; virtual nsresult InsertChildAt(nsIContent* aChild, uint32_t aIndex, diff --git a/dom/html/HTMLFormElement.cpp b/dom/html/HTMLFormElement.cpp index d2b39461f1..c84c1e752e 100644 --- a/dom/html/HTMLFormElement.cpp +++ b/dom/html/HTMLFormElement.cpp @@ -218,7 +218,9 @@ HTMLFormElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, nsresult HTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, - const nsAttrValue* aOldValue, bool aNotify) + const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, + bool aNotify) { if (aName == nsGkAtoms::novalidate && aNameSpaceID == kNameSpaceID_None) { // Update all form elements states because they might be [no longer] @@ -235,7 +237,7 @@ HTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, - aOldValue, aNotify); + aOldValue, aSubjectPrincipal, aNotify); } NS_IMPL_STRING_ATTR(HTMLFormElement, AcceptCharset, acceptcharset) diff --git a/dom/html/HTMLFormElement.h b/dom/html/HTMLFormElement.h index 102e24fdf9..b0d355d5a7 100644 --- a/dom/html/HTMLFormElement.h +++ b/dom/html/HTMLFormElement.h @@ -110,6 +110,7 @@ public: virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, bool aNotify) override; /** diff --git a/dom/html/HTMLFrameElement.h b/dom/html/HTMLFrameElement.h index 31b07c03ed..e868e2f3f6 100644 --- a/dom/html/HTMLFrameElement.h +++ b/dom/html/HTMLFrameElement.h @@ -82,10 +82,13 @@ public: SetHTMLAttr(nsGkAtoms::scrolling, aScrolling, aError); } - // The XPCOM GetSrc is OK for us - void SetSrc(const nsAString& aSrc, ErrorResult& aError) + void GetSrc(nsString& aSrc, nsIPrincipal&) { - SetAttrHelper(nsGkAtoms::src, aSrc); + GetURIAttr(nsGkAtoms::src, nullptr, aSrc); + } + void SetSrc(const nsAString& aSrc, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aError) + { + SetHTMLAttr(nsGkAtoms::src, aSrc, aTriggeringPrincipal, aError); } using nsGenericHTMLFrameElement::GetContentDocument; diff --git a/dom/html/HTMLIFrameElement.cpp b/dom/html/HTMLIFrameElement.cpp index 8cf19dc9f4..7468b64023 100644 --- a/dom/html/HTMLIFrameElement.cpp +++ b/dom/html/HTMLIFrameElement.cpp @@ -183,7 +183,9 @@ HTMLIFrameElement::GetAttributeMappingFunction() const nsresult HTMLIFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, - const nsAttrValue* aOldValue, bool aNotify) + const nsAttrValue* aOldValue, + nsIPrincipal* aMaybeScriptedPrincipal, + bool aNotify) { AfterMaybeChangeAttr(aNameSpaceID, aName, aNotify); @@ -197,8 +199,10 @@ HTMLIFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } } } - return nsGenericHTMLFrameElement::AfterSetAttr(aNameSpaceID, aName, aValue, - aOldValue, aNotify); + return nsGenericHTMLFrameElement::AfterSetAttr(aNameSpaceID, aName, + aValue, aOldValue, + aMaybeScriptedPrincipal, + aNotify); } nsresult diff --git a/dom/html/HTMLIFrameElement.h b/dom/html/HTMLIFrameElement.h index e1240de814..5c49a448d5 100644 --- a/dom/html/HTMLIFrameElement.h +++ b/dom/html/HTMLIFrameElement.h @@ -48,10 +48,13 @@ public: uint32_t GetSandboxFlags(); // Web IDL binding methods - // The XPCOM GetSrc is fine for our purposes - void SetSrc(const nsAString& aSrc, ErrorResult& aError) + void GetSrc(nsString& aSrc, nsIPrincipal&) const { - SetHTMLAttr(nsGkAtoms::src, aSrc, aError); + GetURIAttr(nsGkAtoms::src, nullptr, aSrc); + } + void SetSrc(const nsAString& aSrc, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aError) + { + SetHTMLAttr(nsGkAtoms::src, aSrc, aTriggeringPrincipal, aError); } void GetSrcdoc(DOMString& aSrcdoc) { @@ -184,6 +187,7 @@ protected: virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, const nsAttrValue* aOldValue, + nsIPrincipal* aMaybeScriptedPrincipal, bool aNotify) override; virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsIAtom* aName, const nsAttrValueOrString& aValue, diff --git a/dom/html/HTMLImageElement.cpp b/dom/html/HTMLImageElement.cpp index b697dcabea..4dd46f5a0e 100644 --- a/dom/html/HTMLImageElement.cpp +++ b/dom/html/HTMLImageElement.cpp @@ -109,7 +109,6 @@ private: HTMLImageElement::HTMLImageElement(already_AddRefed& aNodeInfo) : nsGenericHTMLElement(aNodeInfo) , mForm(nullptr) - , mForceReload(false) , mInDocResponsiveContent(false) , mCurrentDensity(1.0) { @@ -370,10 +369,6 @@ HTMLImageElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValueOrString* aValue, bool aNotify) { - if (aValue) { - BeforeMaybeChangeAttr(aNameSpaceID, aName, *aValue, aNotify); - } - if (aNameSpaceID == kNameSpaceID_None && mForm && (aName == nsGkAtoms::name || aName == nsGkAtoms::id)) { // remove the image from the hashtable as needed @@ -393,10 +388,15 @@ HTMLImageElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsresult HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, - const nsAttrValue* aOldValue, bool aNotify) + const nsAttrValue* aOldValue, + nsIPrincipal* aMaybeScriptedPrincipal, + bool aNotify) { + nsAttrValueOrString attrVal(aValue); + if (aValue) { - AfterMaybeChangeAttr(aNameSpaceID, aName, aNotify); + AfterMaybeChangeAttr(aNameSpaceID, aName, attrVal, aOldValue, true, + aMaybeScriptedPrincipal, aNotify); } if (aNameSpaceID == kNameSpaceID_None && mForm && @@ -413,8 +413,6 @@ HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, // parser or some such place; we'll get bound after all the attributes have // been set, so we'll do the image load from BindToTree. - nsAttrValueOrString attrVal(aValue); - if (aName == nsGkAtoms::src && aNameSpaceID == kNameSpaceID_None && !aValue) { @@ -432,6 +430,7 @@ HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } } else if (aName == nsGkAtoms::srcset && aNameSpaceID == kNameSpaceID_None) { + mSrcsetTriggeringPrincipal = aMaybeScriptedPrincipal; PictureSourceSrcsetChanged(this, attrVal.String(), aNotify); } else if (aName == nsGkAtoms::sizes && aNameSpaceID == kNameSpaceID_None) { @@ -439,7 +438,9 @@ HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, - aValue, aOldValue, aNotify); + aValue, aOldValue, + aMaybeScriptedPrincipal, + aNotify); } nsresult @@ -447,18 +448,21 @@ HTMLImageElement::OnAttrSetButNotChanged(int32_t aNamespaceID, nsIAtom* aName, const nsAttrValueOrString& aValue, bool aNotify) { - BeforeMaybeChangeAttr(aNamespaceID, aName, aValue, aNotify); - AfterMaybeChangeAttr(aNamespaceID, aName, aNotify); + AfterMaybeChangeAttr(aNamespaceID, aName, aValue, nullptr, false, nullptr, aNotify); return nsGenericHTMLElement::OnAttrSetButNotChanged(aNamespaceID, aName, aValue, aNotify); } void -HTMLImageElement::BeforeMaybeChangeAttr(int32_t aNamespaceID, nsIAtom* aName, - const nsAttrValueOrString& aValue, - bool aNotify) +HTMLImageElement::AfterMaybeChangeAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString& aValue, + const nsAttrValue* aOldValue, + bool aValueMaybeChanged, + nsIPrincipal* aMaybeScriptedPrincipal, + bool aNotify) { + bool forceReload = false; // We need to force our image to reload. This must be done here, not in // AfterSetAttr or BeforeSetAttr, because we want to do it even if the attr is // being set to its existing value, which is normally optimized away as a @@ -469,16 +473,16 @@ HTMLImageElement::BeforeMaybeChangeAttr(int32_t aNamespaceID, nsIAtom* aName, // spec. // // Both cases handle unsetting src in AfterSetAttr - // - // Much of this should probably happen in AfterMaybeChangeAttr. - // See Bug 1370705 if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::src) { + mSrcTriggeringPrincipal = + nsContentUtils::GetAttrTriggeringPrincipal(this, aValue.String(), aMaybeScriptedPrincipal); + if (InResponsiveMode()) { if (mResponsiveSelector && mResponsiveSelector->Content() == this) { - mResponsiveSelector->SetDefaultSource(aValue.String()); + mResponsiveSelector->SetDefaultSource(aValue.String(), mSrcTriggeringPrincipal); } QueueImageLoadTask(true); } else if (aNotify && OwnerDoc()->IsCurrentActiveDocument()) { @@ -492,52 +496,46 @@ HTMLImageElement::BeforeMaybeChangeAttr(int32_t aNamespaceID, nsIAtom* aName, mNewRequestsWillNeedAnimationReset = true; // Force image loading here, so that we'll try to load the image from - // network if it's set to be not cacheable... If we change things so that - // the state gets in Element's attr-setting happen around this - // LoadImage call, we could start passing false instead of aNotify - // here. - LoadImage(aValue.String(), true, aNotify, eImageLoadType_Normal); + // network if it's set to be not cacheable. + // Potentially, false could be passed here rather than aNotify since + // UpdateState will be called by SetAttrAndNotify, but there are two + // obstacles to this: 1) LoadImage will end up calling + // UpdateState(aNotify), and we do not want it to call UpdateState(false) + // when aNotify is true, and 2) When this function is called by + // OnAttrSetButNotChanged, SetAttrAndNotify will not subsequently call + // UpdateState. + LoadImage(aValue.String(), true, aNotify, eImageLoadType_Normal, mSrcTriggeringPrincipal); mNewRequestsWillNeedAnimationReset = false; } } else if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::crossorigin && aNotify) { - nsAttrValue attrValue; - ParseCORSValue(aValue.String(), attrValue); - if (GetCORSMode() != AttrValueToCORSMode(&attrValue)) { + if (aValueMaybeChanged && GetCORSMode() != AttrValueToCORSMode(aOldValue)) { // Force a new load of the image with the new cross origin policy. - mForceReload = true; + forceReload = true; } } else if (aName == nsGkAtoms::referrerpolicy && aNamespaceID == kNameSpaceID_None && aNotify) { - ReferrerPolicy referrerPolicy = AttributeReferrerPolicyFromString(aValue.String()); + ReferrerPolicy referrerPolicy = GetImageReferrerPolicy(); if (!InResponsiveMode() && referrerPolicy != RP_Unset && - referrerPolicy != GetImageReferrerPolicy()) { + aValueMaybeChanged && + referrerPolicy != ReferrerPolicyFromAttr(aOldValue)) { // XXX: Bug 1076583 - We still use the older synchronous algorithm // Because referrerPolicy is not treated as relevant mutations, setting // the attribute will neither trigger a reload nor update the referrer // policy of the loading channel (whether it has previously completed or // not). Force a new load of the image with the new referrerpolicy. - mForceReload = true; + forceReload = true; } } - return; -} - -void -HTMLImageElement::AfterMaybeChangeAttr(int32_t aNamespaceID, nsIAtom* aName, - bool aNotify) -{ // Because we load image synchronously in non-responsive-mode, we need to do // reload after the attribute has been set if the reload is triggerred by // cross origin changing. - if (mForceReload) { - mForceReload = false; - + if (forceReload) { if (InResponsiveMode()) { // per spec, full selection runs when this changes, even though // it doesn't directly affect the source selection @@ -549,8 +547,6 @@ HTMLImageElement::AfterMaybeChangeAttr(int32_t aNamespaceID, nsIAtom* aName, ForceReload(aNotify); } } - - return; } nsresult @@ -1005,13 +1001,14 @@ HTMLImageElement::LoadSelectedImage(bool aForce, bool aNotify, bool aAlwaysLoad) double currentDensity = 1.0; // default to 1.0 for the src attribute case if (mResponsiveSelector) { nsCOMPtr url = mResponsiveSelector->GetSelectedImageURL(); + nsCOMPtr triggeringPrincipal = mResponsiveSelector->GetSelectedImageTriggeringPrincipal(); selectedSource = url; currentDensity = mResponsiveSelector->GetSelectedImageDensity(); if (!aAlwaysLoad && SelectedSourceMatchesLast(selectedSource, currentDensity)) { return NS_OK; } if (url) { - rv = LoadImage(url, aForce, aNotify, eImageLoadType_Imageset); + rv = LoadImage(url, aForce, aNotify, eImageLoadType_Imageset, triggeringPrincipal); } } else { nsAutoString src; @@ -1032,7 +1029,8 @@ HTMLImageElement::LoadSelectedImage(bool aForce, bool aNotify, bool aAlwaysLoad) // valid responsive sources from either, per spec. rv = LoadImage(src, aForce, aNotify, HaveSrcsetOrInPicture() ? eImageLoadType_Imageset - : eImageLoadType_Normal); + : eImageLoadType_Normal, + mSrcTriggeringPrincipal); } } mLastSelectedSource = selectedSource; @@ -1059,7 +1057,13 @@ HTMLImageElement::PictureSourceSrcsetChanged(nsIContent *aSourceNode, if (aSourceNode == currentSrc) { // We're currently using this node as our responsive selector // source. - mResponsiveSelector->SetCandidatesFromSourceSet(aNewValue); + nsCOMPtr principal; + if (aSourceNode == this) { + principal = mSrcsetTriggeringPrincipal; + } else if (auto* source = HTMLSourceElement::FromContent(aSourceNode)) { + principal = source->GetSrcsetTriggeringPrincipal(); + } + mResponsiveSelector->SetCandidatesFromSourceSet(aNewValue, principal); } if (!mInDocResponsiveContent && IsInComposedDoc()) { @@ -1244,15 +1248,20 @@ HTMLImageElement::SourceElementMatches(nsIContent* aSourceNode) bool HTMLImageElement::TryCreateResponsiveSelector(nsIContent *aSourceNode) { + nsCOMPtr principal; + // Skip if this is not a with matching media query bool isSourceTag = aSourceNode->IsHTMLElement(nsGkAtoms::source); if (isSourceTag) { if (!SourceElementMatches(aSourceNode)) { return false; } + auto* source = HTMLSourceElement::FromContent(aSourceNode); + principal = source->GetSrcsetTriggeringPrincipal(); } else if (aSourceNode->IsHTMLElement(nsGkAtoms::img)) { // Otherwise this is the tag itself MOZ_ASSERT(aSourceNode == this); + principal = mSrcsetTriggeringPrincipal; } // Skip if has no srcset or an empty srcset @@ -1268,8 +1277,8 @@ HTMLImageElement::TryCreateResponsiveSelector(nsIContent *aSourceNode) // Try to parse RefPtr sel = new ResponsiveImageSelector(aSourceNode); - if (!sel->SetCandidatesFromSourceSet(srcset)) { - // No possible candidates, don't need to bother parsing sizes + if (!sel->SetCandidatesFromSourceSet(srcset, principal)) { + // No possible candidates; no need to bother parsing sizes return false; } @@ -1282,7 +1291,7 @@ HTMLImageElement::TryCreateResponsiveSelector(nsIContent *aSourceNode) MOZ_ASSERT(aSourceNode == this); nsAutoString src; if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, src) && !src.IsEmpty()) { - sel->SetDefaultSource(src); + sel->SetDefaultSource(src, mSrcTriggeringPrincipal); } } diff --git a/dom/html/HTMLImageElement.h b/dom/html/HTMLImageElement.h index 3d3c7c834e..2c184d26d9 100644 --- a/dom/html/HTMLImageElement.h +++ b/dom/html/HTMLImageElement.h @@ -137,13 +137,21 @@ public: { SetHTMLAttr(nsGkAtoms::alt, aAlt, aError); } - void SetSrc(const nsAString& aSrc, ErrorResult& aError) + void GetSrc(nsAString& aSrc, nsIPrincipal&) { - SetHTMLAttr(nsGkAtoms::src, aSrc, aError); + GetURIAttr(nsGkAtoms::src, nullptr, aSrc); } - void SetSrcset(const nsAString& aSrcset, ErrorResult& aError) + void SetSrc(const nsAString& aSrc, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aError) { - SetHTMLAttr(nsGkAtoms::srcset, aSrcset, aError); + SetHTMLAttr(nsGkAtoms::src, aSrc, aTriggeringPrincipal, aError); + } + void GetSrcset(nsAString& aSrcset, nsIPrincipal&) + { + GetHTMLAttr(nsGkAtoms::srcset, aSrcset); + } + void SetSrcset(const nsAString& aSrcset, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aError) + { + SetHTMLAttr(nsGkAtoms::srcset, aSrcset, aTriggeringPrincipal, aError); } void GetCrossOrigin(nsAString& aResult) { @@ -337,6 +345,7 @@ protected: virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, const nsAttrValue* aOldValue, + nsIPrincipal* aMaybeScriptedPrincipal, bool aNotify) override; virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsIAtom* aName, @@ -364,30 +373,25 @@ private: * @param aName the localname of the attribute being set * @param aValue the value it's being set to represented as either a string or * a parsed nsAttrValue. - * @param aNotify Whether we plan to notify document observers. - */ - void BeforeMaybeChangeAttr(int32_t aNamespaceID, nsIAtom* aName, - const nsAttrValueOrString& aValue, - bool aNotify); - /** - * This function is called by AfterSetAttr and OnAttrSetButNotChanged. - * It will not be called if the value is being unset. - * - * @param aNamespaceID the namespace of the attr being set - * @param aName the localname of the attribute being set + * @param aOldValue the value previously set. Will be null if no value was + * previously set. This value should only be used when + * aValueMaybeChanged is true; when aValueMaybeChanged is false, + * aOldValue should be considered unreliable. + * @param aValueMaybeChanged will be false when this function is called from + * OnAttrSetButNotChanged to indicate that the value was not changed. * @param aNotify Whether we plan to notify document observers. */ void AfterMaybeChangeAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString& aValue, + const nsAttrValue* aOldValue, + bool aValueMaybeChanged, + nsIPrincipal* aMaybeScriptedPrincipal, bool aNotify); - /** - * Used by BeforeMaybeChangeAttr and AfterMaybeChangeAttr to keep track of - * whether a reload needs to be forced after an attribute change that is - * currently in progress. - */ - bool mForceReload; bool mInDocResponsiveContent; RefPtr mPendingImageLoadTask; + nsCOMPtr mSrcTriggeringPrincipal; + nsCOMPtr mSrcsetTriggeringPrincipal; // Last URL that was attempted to load by this element. nsCOMPtr mLastSelectedSource; diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp index 7d9a4db1cd..374fb14ef1 100644 --- a/dom/html/HTMLInputElement.cpp +++ b/dom/html/HTMLInputElement.cpp @@ -1255,14 +1255,6 @@ HTMLInputElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, mType == NS_FORM_INPUT_RADIO && (mForm || mDoneCreating)) { WillRemoveFromRadioGroup(); - } else if (aNotify && aName == nsGkAtoms::src && - mType == NS_FORM_INPUT_IMAGE) { - if (aValue) { - LoadImage(aValue->String(), true, aNotify, eImageLoadType_Normal); - } else { - // Null value means the attr got unset; drop the image - CancelImageRequests(aNotify); - } } else if (aNotify && aName == nsGkAtoms::disabled) { mDisabledChanged = true; } else if (mType == NS_FORM_INPUT_RADIO && aName == nsGkAtoms::required) { @@ -1285,7 +1277,9 @@ HTMLInputElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsresult HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, - const nsAttrValue* aOldValue, bool aNotify) + const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, + bool aNotify) { if (aNameSpaceID == kNameSpaceID_None) { // @@ -1301,6 +1295,21 @@ HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, UpdateValueMissingValidityStateForRadio(false); } + if (aName == nsGkAtoms::src) { + mSrcTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal( + this, aValue ? aValue->GetStringValue() : EmptyString(), + aSubjectPrincipal); + if (aNotify && mType == NS_FORM_INPUT_IMAGE) { + if (aValue) { + LoadImage(aValue->GetStringValue(), true, aNotify, eImageLoadType_Normal, + mSrcTriggeringPrincipal); + } else { + // Null value means the attr got unset; drop the image + CancelImageRequests(aNotify); + } + } + } + // If @value is changed and BF_VALUE_CHANGED is false, @value is the value // of the element so, if the value of the element is different than @value, // we have to re-set it. This is only the case when GetValueMode() returns @@ -1436,6 +1445,7 @@ HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName, aValue, aOldValue, + aSubjectPrincipal, aNotify); } @@ -4958,7 +4968,7 @@ HTMLInputElement::MaybeLoadImage() nsAutoString uri; if (mType == NS_FORM_INPUT_IMAGE && GetAttr(kNameSpaceID_None, nsGkAtoms::src, uri) && - (NS_FAILED(LoadImage(uri, false, true, eImageLoadType_Normal)) || + (NS_FAILED(LoadImage(uri, false, true, eImageLoadType_Normal, mSrcTriggeringPrincipal)) || !LoadingEnabled())) { CancelImageRequests(true); } @@ -5162,7 +5172,7 @@ HTMLInputElement::HandleTypeChange(uint8_t aNewType, bool aNotify) // whether we have an image to load; nsAutoString src; if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) { - LoadImage(src, false, aNotify, eImageLoadType_Normal); + LoadImage(src, false, aNotify, eImageLoadType_Normal, mSrcTriggeringPrincipal); } } diff --git a/dom/html/HTMLInputElement.h b/dom/html/HTMLInputElement.h index 44e1f9c1ca..e46be30ea7 100644 --- a/dom/html/HTMLInputElement.h +++ b/dom/html/HTMLInputElement.h @@ -638,10 +638,13 @@ public: SetUnsignedIntAttr(nsGkAtoms::size, aValue, DEFAULT_COLS, aRv); } - // XPCOM GetSrc() is OK - void SetSrc(const nsAString& aValue, ErrorResult& aRv) + void GetSrc(nsAString& aValue, nsIPrincipal&) { - SetHTMLAttr(nsGkAtoms::src, aValue, aRv); + GetURIAttr(nsGkAtoms::src, nullptr, aValue); + } + void SetSrc(const nsAString& aValue, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aRv) + { + SetHTMLAttr(nsGkAtoms::src, aValue, aTriggeringPrincipal, aRv); } // XPCOM GetStep() is OK @@ -966,6 +969,7 @@ protected: virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, bool aNotify) override; virtual void ResultForDialogSubmit(nsAString& aResult) override; @@ -1558,6 +1562,11 @@ protected: */ nsTextEditorState::SelectionProperties mSelectionProperties; + /** + * The triggering principal for the src attribute. + */ + nsCOMPtr mSrcTriggeringPrincipal; + // Step scale factor values, for input types that have one. static const Decimal kStepScaleFactorDate; static const Decimal kStepScaleFactorNumberRange; diff --git a/dom/html/HTMLLinkElement.cpp b/dom/html/HTMLLinkElement.cpp index 8fe317cec0..e4426f0c21 100644 --- a/dom/html/HTMLLinkElement.cpp +++ b/dom/html/HTMLLinkElement.cpp @@ -357,7 +357,9 @@ HTMLLinkElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsresult HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, - const nsAttrValue* aOldValue, bool aNotify) + const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, + bool aNotify) { // It's safe to call ResetLinkState here because our new attr value has // already been set or unset. ResetLinkState needs the updated attribute @@ -372,6 +374,12 @@ HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } } + 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 || @@ -451,7 +459,8 @@ HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, - aOldValue, aNotify); + aOldValue, aSubjectPrincipal, + aNotify); } nsresult @@ -517,14 +526,20 @@ HTMLLinkElement::GetHrefURI() const } already_AddRefed -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 prin = mTriggeringPrincipal; + prin.forget(aTriggeringPrincipal); + nsCOMPtr uri = Link::GetURI(); return uri.forget(); } diff --git a/dom/html/HTMLLinkElement.h b/dom/html/HTMLLinkElement.h index c7742478e3..2c4af10c7f 100644 --- a/dom/html/HTMLLinkElement.h +++ b/dom/html/HTMLLinkElement.h @@ -66,6 +66,7 @@ public: virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, bool aNotify) override; virtual bool IsLink(nsIURI** aURI) const override; virtual already_AddRefed GetHrefURI() const override; @@ -87,10 +88,14 @@ public: // WebIDL bool Disabled() const; void SetDisabled(bool aDisabled, ErrorResult& aRv); - // XPCOM GetHref is fine. - void SetHref(const nsAString& aHref, ErrorResult& aRv) + + void GetHref(nsString& aValue, nsIPrincipal&) { - SetHTMLAttr(nsGkAtoms::href, aHref, aRv); + GetHref(aValue); + } + void SetHref(const nsAString& aHref, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aRv) + { + SetHTMLAttr(nsGkAtoms::href, aHref, aTriggeringPrincipal, aRv); } void GetCrossOrigin(nsAString& aResult) { @@ -188,7 +193,7 @@ protected: virtual ~HTMLLinkElement(); // nsStyleLinkElement - virtual already_AddRefed GetStyleSheetURL(bool* aIsInline) override; + virtual already_AddRefed GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal) override; virtual void GetStyleSheetInfo(nsAString& aTitle, nsAString& aType, nsAString& aMedia, diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index 7cce0a3441..2f2d7a1a7a 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -3713,11 +3713,16 @@ int32_t HTMLMediaElement::TabIndexDefault() nsresult HTMLMediaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, - const nsAttrValue* aOldValue, bool aNotify) + const nsAttrValue* aOldValue, + nsIPrincipal* aMaybeScriptedPrincipal, + bool aNotify) { if (aNameSpaceID == kNameSpaceID_None) { if (aName == nsGkAtoms::src) { mSrcMediaSource = nullptr; + mSrcAttrTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal( + this, aValue ? aValue->GetStringValue() : EmptyString(), + aMaybeScriptedPrincipal); if (aValue) { nsString srcStr = aValue->GetStringValue(); nsCOMPtr uri; @@ -3755,7 +3760,9 @@ HTMLMediaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, - aValue, aOldValue, aNotify); + aValue, aOldValue, + aMaybeScriptedPrincipal, + aNotify); } nsresult diff --git a/dom/html/HTMLMediaElement.h b/dom/html/HTMLMediaElement.h index bda9924a6f..5943c08419 100644 --- a/dom/html/HTMLMediaElement.h +++ b/dom/html/HTMLMediaElement.h @@ -410,10 +410,13 @@ public: MediaError* GetError() const; - // XPCOM GetSrc() is OK - void SetSrc(const nsAString& aSrc, ErrorResult& aRv) + void GetSrc(nsString& aSrc, nsIPrincipal&) { - SetHTMLAttr(nsGkAtoms::src, aSrc, aRv); + GetSrc(aSrc); // XPCOM + } + void SetSrc(const nsAString& aSrc, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aRv) + { + SetHTMLAttr(nsGkAtoms::src, aSrc, aTriggeringPrincipal, aRv); } // XPCOM GetCurrentSrc() is OK @@ -1301,6 +1304,7 @@ protected: virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, const nsAttrValue* aOldValue, + nsIPrincipal* aMaybeScriptedPrincipal, bool aNotify) override; virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsIAtom* aName, const nsAttrValueOrString& aValue, @@ -1325,6 +1329,9 @@ protected: // set in the src attribute. RefPtr mSrcAttrStream; + // Holds the triggering principal for the src attribute. + nsCOMPtr mSrcAttrTriggeringPrincipal; + // Holds a reference to the DOM wrapper for the MediaStream that we're // actually playing. // At most one of mDecoder and mSrcStream can be non-null. diff --git a/dom/html/HTMLMenuItemElement.cpp b/dom/html/HTMLMenuItemElement.cpp index 42cee132e6..fbd9377298 100644 --- a/dom/html/HTMLMenuItemElement.cpp +++ b/dom/html/HTMLMenuItemElement.cpp @@ -389,7 +389,9 @@ HTMLMenuItemElement::GetText(nsAString& aText) nsresult HTMLMenuItemElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, - const nsAttrValue* aOldValue, bool aNotify) + const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, + bool aNotify) { if (aNameSpaceID == kNameSpaceID_None) { if ((aName == nsGkAtoms::radiogroup || aName == nsGkAtoms::type) && @@ -412,8 +414,10 @@ HTMLMenuItemElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } } - return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, - aOldValue, aNotify); + return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, + aValue, aOldValue, + aSubjectPrincipal, + aNotify); } void diff --git a/dom/html/HTMLMenuItemElement.h b/dom/html/HTMLMenuItemElement.h index 1c738187ce..e3a877a313 100644 --- a/dom/html/HTMLMenuItemElement.h +++ b/dom/html/HTMLMenuItemElement.h @@ -126,6 +126,7 @@ protected: virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, const nsAttrValue* aValue, const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, bool aNotify) override; void WalkRadioGroup(Visitor* aVisitor); diff --git a/dom/html/HTMLMetaElement.cpp b/dom/html/HTMLMetaElement.cpp index f0a66b52c1..2a07dad968 100644 --- a/dom/html/HTMLMetaElement.cpp +++ b/dom/html/HTMLMetaElement.cpp @@ -61,7 +61,9 @@ HTMLMetaElement::SetMetaReferrer(nsIDocument* aDocument) nsresult HTMLMetaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, - const nsAttrValue* aOldValue, bool aNotify) + const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, + bool aNotify) { if (aNameSpaceID == kNameSpaceID_None) { nsIDocument *document = GetUncomposedDoc(); @@ -82,8 +84,10 @@ HTMLMetaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } } - return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, - aOldValue, aNotify); + return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, + aValue, aOldValue, + aSubjectPrincipal, + aNotify); } nsresult diff --git a/dom/html/HTMLMetaElement.h b/dom/html/HTMLMetaElement.h index 649ea11cf1..9fabe36d40 100644 --- a/dom/html/HTMLMetaElement.h +++ b/dom/html/HTMLMetaElement.h @@ -34,6 +34,7 @@ public: virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, bool aNotify) override; void CreateAndDispatchEvent(nsIDocument* aDoc, const nsAString& aEventName); diff --git a/dom/html/HTMLObjectElement.cpp b/dom/html/HTMLObjectElement.cpp index a77cd6fe57..7dc60949d2 100644 --- a/dom/html/HTMLObjectElement.cpp +++ b/dom/html/HTMLObjectElement.cpp @@ -299,13 +299,16 @@ HTMLObjectElement::UnbindFromTree(bool aDeep, nsresult HTMLObjectElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, const nsAttrValue* aValue, - const nsAttrValue* aOldValue, bool aNotify) + const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, + bool aNotify) { nsresult rv = AfterMaybeChangeAttr(aNamespaceID, aName, aNotify); NS_ENSURE_SUCCESS(rv, rv); return nsGenericHTMLFormElement::AfterSetAttr(aNamespaceID, aName, aValue, - aOldValue, aNotify); + aOldValue, aSubjectPrincipal, + aNotify); } nsresult diff --git a/dom/html/HTMLObjectElement.h b/dom/html/HTMLObjectElement.h index 6f0990918f..6c982b2b19 100644 --- a/dom/html/HTMLObjectElement.h +++ b/dom/html/HTMLObjectElement.h @@ -245,6 +245,7 @@ public: virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, const nsAttrValue* aValue, const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, bool aNotify) override; virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsIAtom* aName, const nsAttrValueOrString& aValue, diff --git a/dom/html/HTMLOptGroupElement.cpp b/dom/html/HTMLOptGroupElement.cpp index a65a79ecf5..49645ad933 100644 --- a/dom/html/HTMLOptGroupElement.cpp +++ b/dom/html/HTMLOptGroupElement.cpp @@ -106,7 +106,9 @@ HTMLOptGroupElement::RemoveChildAt(uint32_t aIndex, bool aNotify) nsresult HTMLOptGroupElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, - const nsAttrValue* aOldValue, bool aNotify) + const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, + bool aNotify) { if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::disabled) { // All our children