diff --git a/dom/svg/SVGFEImageElement.cpp b/dom/svg/SVGFEImageElement.cpp index 1b1ceedf6856..72c436f0ad46 100644 --- a/dom/svg/SVGFEImageElement.cpp +++ b/dom/svg/SVGFEImageElement.cpp @@ -101,6 +101,19 @@ void SVGFEImageElement::AsyncEventRunning(AsyncEventDispatcher* aEvent) { //---------------------------------------------------------------------- // nsIContent methods: +bool SVGFEImageElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, + const nsAString& aValue, + nsIPrincipal* aMaybeScriptedPrincipal, + nsAttrValue& aResult) { + if (aNamespaceID == kNameSpaceID_None && + aAttribute == nsGkAtoms::crossorigin) { + ParseCORSValue(aValue, aResult); + return true; + } + return SVGFEImageElementBase::ParseAttribute( + aNamespaceID, aAttribute, aValue, aMaybeScriptedPrincipal, aResult); +} + nsresult SVGFEImageElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName, const nsAttrValue* aValue, const nsAttrValue* aOldValue, @@ -115,6 +128,12 @@ nsresult SVGFEImageElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName, } else { CancelImageRequests(aNotify); } + } else if (aNamespaceID == kNameSpaceID_None && + aName == nsGkAtoms::crossorigin) { + if (aNotify && GetCORSMode() != AttrValueToCORSMode(aOldValue) && + ShouldLoadImage()) { + ForceReload(aNotify, IgnoreErrors()); + } } return SVGFEImageElementBase::AfterSetAttr( @@ -177,6 +196,13 @@ already_AddRefed SVGFEImageElement::Href() { : mStringAttributes[XLINK_HREF].ToDOMAnimatedString(this); } +//---------------------------------------------------------------------- +// nsImageLoadingContent methods: + +CORSMode SVGFEImageElement::GetCORSMode() { + return AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin)); +} + //---------------------------------------------------------------------- // nsIDOMSVGFEImageElement methods diff --git a/dom/svg/SVGFEImageElement.h b/dom/svg/SVGFEImageElement.h index d652fb0135b4..eead75682e79 100644 --- a/dom/svg/SVGFEImageElement.h +++ b/dom/svg/SVGFEImageElement.h @@ -52,12 +52,20 @@ class SVGFEImageElement final : public SVGFEImageElementBase, SVGAnimatedString& GetResultImageName() override { return mStringAttributes[RESULT]; } + + // nsImageLoadingContent + CORSMode GetCORSMode() override; + bool OutputIsTainted(const nsTArray& aInputsAreTainted, nsIPrincipal* aReferencePrincipal) override; // nsIContent nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override; + bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, + const nsAString& aValue, + nsIPrincipal* aMaybeScriptedPrincipal, + nsAttrValue& aResult) override; nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName, const nsAttrValue* aValue, const nsAttrValue* aOldValue, nsIPrincipal* aSubjectPrincipal, bool aNotify) override; @@ -76,6 +84,15 @@ class SVGFEImageElement final : public SVGFEImageElementBase, // WebIDL already_AddRefed Href(); already_AddRefed PreserveAspectRatio(); + void GetCrossOrigin(nsAString& aCrossOrigin) { + // 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, aCrossOrigin); + } + void SetCrossOrigin(const nsAString& aCrossOrigin, ErrorResult& aError) { + SetOrRemoveNullableStringAttr(nsGkAtoms::crossorigin, aCrossOrigin, aError); + } private: nsresult LoadSVGImage(bool aForce, bool aNotify); diff --git a/dom/svg/SVGImageElement.cpp b/dom/svg/SVGImageElement.cpp index 6ad6edebb6d8..b3cf89b50cc8 100644 --- a/dom/svg/SVGImageElement.cpp +++ b/dom/svg/SVGImageElement.cpp @@ -174,6 +174,13 @@ void SVGImageElement::AsyncEventRunning(AsyncEventDispatcher* aEvent) { nsImageLoadingContent::AsyncEventRunning(aEvent); } +//---------------------------------------------------------------------- +// nsImageLoadingContent methods: + +CORSMode SVGImageElement::GetCORSMode() { + return AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin)); +} + //---------------------------------------------------------------------- // nsIContent methods: @@ -182,6 +189,10 @@ bool SVGImageElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, nsIPrincipal* aMaybeScriptedPrincipal, nsAttrValue& aResult) { if (aNamespaceID == kNameSpaceID_None) { + if (aAttribute == nsGkAtoms::crossorigin) { + ParseCORSValue(aValue, aResult); + return true; + } if (aAttribute == nsGkAtoms::decoding) { return aResult.ParseEnumValue(aValue, kDecodingTable, false, kDecodingTableDefault); @@ -206,13 +217,20 @@ nsresult SVGImageElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName, } else { CancelImageRequests(aNotify); } - } else if (aName == nsGkAtoms::decoding && - aNamespaceID == kNameSpaceID_None) { - // Request sync or async image decoding. - SetSyncDecodingHint( - aValue && static_cast(aValue->GetEnumValue()) == - ImageDecodingType::Sync); + } else if (aNamespaceID == kNameSpaceID_None) { + if (aName == nsGkAtoms::decoding) { + // Request sync or async image decoding. + SetSyncDecodingHint( + aValue && static_cast(aValue->GetEnumValue()) == + ImageDecodingType::Sync); + } else if (aName == nsGkAtoms::crossorigin) { + if (aNotify && GetCORSMode() != AttrValueToCORSMode(aOldValue) && + ShouldLoadImage()) { + ForceReload(aNotify, IgnoreErrors()); + } + } } + return SVGImageElementBase::AfterSetAttr( aNamespaceID, aName, aValue, aOldValue, aSubjectPrincipal, aNotify); } diff --git a/dom/svg/SVGImageElement.h b/dom/svg/SVGImageElement.h index b64729298278..cf95422b8b17 100644 --- a/dom/svg/SVGImageElement.h +++ b/dom/svg/SVGImageElement.h @@ -46,6 +46,9 @@ class SVGImageElement final : public SVGImageElementBase, // EventTarget void AsyncEventRunning(AsyncEventDispatcher* aEvent) override; + // nsImageLoadingContent interface + CORSMode GetCORSMode() override; + // nsIContent interface bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, const nsAString& aValue, @@ -92,6 +95,15 @@ class SVGImageElement final : public SVGImageElementBase, already_AddRefed Height(); already_AddRefed PreserveAspectRatio(); already_AddRefed Href(); + void GetCrossOrigin(nsAString& aCrossOrigin) { + // 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, aCrossOrigin); + } + void SetCrossOrigin(const nsAString& aCrossOrigin, ErrorResult& aError) { + SetOrRemoveNullableStringAttr(nsGkAtoms::crossorigin, aCrossOrigin, aError); + } void SetDecoding(const nsAString& aDecoding, ErrorResult& aError) { SetAttr(nsGkAtoms::decoding, aDecoding, aError); diff --git a/dom/webidl/SVGFEImageElement.webidl b/dom/webidl/SVGFEImageElement.webidl index 17d9701df451..e6f451919531 100644 --- a/dom/webidl/SVGFEImageElement.webidl +++ b/dom/webidl/SVGFEImageElement.webidl @@ -14,6 +14,8 @@ interface SVGFEImageElement : SVGElement { [Constant] readonly attribute SVGAnimatedPreserveAspectRatio preserveAspectRatio; + [SetterThrows] + attribute DOMString? crossOrigin; }; SVGFEImageElement includes SVGFilterPrimitiveStandardAttributes; diff --git a/dom/webidl/SVGImageElement.webidl b/dom/webidl/SVGImageElement.webidl index 77f8a9a577a4..f2dd6596952d 100644 --- a/dom/webidl/SVGImageElement.webidl +++ b/dom/webidl/SVGImageElement.webidl @@ -22,6 +22,8 @@ interface SVGImageElement : SVGGraphicsElement { readonly attribute SVGAnimatedLength height; [Constant] readonly attribute SVGAnimatedPreserveAspectRatio preserveAspectRatio; + [SetterThrows] + attribute DOMString? crossOrigin; [CEReactions, SetterThrows] attribute DOMString decoding; [NewObject] diff --git a/testing/web-platform/meta/fetch/metadata/generated/svg-image.https.sub.html.ini b/testing/web-platform/meta/fetch/metadata/generated/svg-image.https.sub.html.ini index 9400388616ea..6ecba3360f30 100644 --- a/testing/web-platform/meta/fetch/metadata/generated/svg-image.https.sub.html.ini +++ b/testing/web-platform/meta/fetch/metadata/generated/svg-image.https.sub.html.ini @@ -1,14 +1,6 @@ [svg-image.https.sub.html] expected: if (os == "android") and fission: [OK, TIMEOUT] - [sec-fetch-mode attributes: crossorigin] - expected: FAIL - - [sec-fetch-mode attributes: crossorigin=anonymous] - expected: FAIL - - [sec-fetch-mode attributes: crossorigin=use-credentials] - expected: FAIL [sec-fetch-dest no attributes] expected: FAIL diff --git a/testing/web-platform/meta/svg/idlharness.window.js.ini b/testing/web-platform/meta/svg/idlharness.window.js.ini index 6f603c7bdb81..eeb1d643dc7c 100644 --- a/testing/web-platform/meta/svg/idlharness.window.js.ini +++ b/testing/web-platform/meta/svg/idlharness.window.js.ini @@ -230,12 +230,6 @@ [SVGElement interface: objects.textPath must inherit property "correspondingUseElement" with the proper type] expected: FAIL - [SVGImageElement interface: attribute crossOrigin] - expected: FAIL - - [SVGImageElement interface: objects.image must inherit property "crossOrigin" with the proper type] - expected: FAIL - [SVGElement interface: objects.image must inherit property "correspondingElement" with the proper type] expected: FAIL diff --git a/testing/web-platform/tests/svg/embedded/image-crossorigin.sub.html b/testing/web-platform/tests/svg/embedded/image-crossorigin.sub.html new file mode 100644 index 000000000000..531512ec1680 --- /dev/null +++ b/testing/web-platform/tests/svg/embedded/image-crossorigin.sub.html @@ -0,0 +1,69 @@ + + +Test Crossorigin + + + + + +