SVGStyleElement.cpp (7618B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/dom/SVGStyleElement.h" 8 9 #include "mozilla/RefPtr.h" 10 #include "mozilla/dom/Document.h" 11 #include "mozilla/dom/Element.h" 12 #include "mozilla/dom/FetchPriority.h" 13 #include "mozilla/dom/ReferrerInfo.h" 14 #include "mozilla/dom/SVGStyleElementBinding.h" 15 #include "nsCOMPtr.h" 16 #include "nsContentUtils.h" 17 18 NS_IMPL_NS_NEW_SVG_ELEMENT(Style) 19 20 namespace mozilla::dom { 21 22 JSObject* SVGStyleElement::WrapNode(JSContext* aCx, 23 JS::Handle<JSObject*> aGivenProto) { 24 return SVGStyleElement_Binding::Wrap(aCx, this, aGivenProto); 25 } 26 27 //---------------------------------------------------------------------- 28 // nsISupports methods 29 30 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(SVGStyleElement, 31 SVGStyleElementBase, 32 nsIMutationObserver) 33 34 NS_IMPL_CYCLE_COLLECTION_CLASS(SVGStyleElement) 35 36 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SVGStyleElement, 37 SVGStyleElementBase) 38 tmp->LinkStyle::Traverse(cb); 39 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 40 41 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SVGStyleElement, 42 SVGStyleElementBase) 43 tmp->LinkStyle::Unlink(); 44 NS_IMPL_CYCLE_COLLECTION_UNLINK_END 45 46 //---------------------------------------------------------------------- 47 // Implementation 48 49 SVGStyleElement::SVGStyleElement( 50 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo) 51 : SVGStyleElementBase(std::move(aNodeInfo)) { 52 AddMutationObserver(this); 53 SetEnabledCallbacks(kCharacterDataChanged | kContentAppended | 54 kContentInserted | kContentWillBeRemoved); 55 } 56 57 //---------------------------------------------------------------------- 58 // nsINode methods 59 60 NS_IMPL_ELEMENT_CLONE(SVGStyleElement) 61 62 //---------------------------------------------------------------------- 63 // nsIContent methods 64 65 nsresult SVGStyleElement::BindToTree(BindContext& aContext, nsINode& aParent) { 66 nsresult rv = SVGStyleElementBase::BindToTree(aContext, aParent); 67 NS_ENSURE_SUCCESS(rv, rv); 68 LinkStyle::BindToTree(); 69 return rv; 70 } 71 72 void SVGStyleElement::UnbindFromTree(UnbindContext& aContext) { 73 nsCOMPtr<Document> oldDoc = GetUncomposedDoc(); 74 ShadowRoot* oldShadow = GetContainingShadow(); 75 SVGStyleElementBase::UnbindFromTree(aContext); 76 (void)UpdateStyleSheetInternal(oldDoc, oldShadow); 77 } 78 79 void SVGStyleElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName, 80 const nsAttrValue* aValue, 81 const nsAttrValue* aOldValue, 82 nsIPrincipal* aMaybeScriptedPrincipal, 83 bool aNotify) { 84 if (aNameSpaceID == kNameSpaceID_None) { 85 if (aName == nsGkAtoms::title || aName == nsGkAtoms::media || 86 aName == nsGkAtoms::type) { 87 (void)UpdateStyleSheetInternal(nullptr, nullptr, ForceUpdate::Yes); 88 } 89 } 90 91 return SVGStyleElementBase::AfterSetAttr( 92 aNameSpaceID, aName, aValue, aOldValue, aMaybeScriptedPrincipal, aNotify); 93 } 94 95 bool SVGStyleElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, 96 const nsAString& aValue, 97 nsIPrincipal* aMaybeScriptedPrincipal, 98 nsAttrValue& aResult) { 99 if (aNamespaceID == kNameSpaceID_None && 100 aAttribute == nsGkAtoms::crossorigin) { 101 ParseCORSValue(aValue, aResult); 102 return true; 103 } 104 105 return SVGStyleElementBase::ParseAttribute(aNamespaceID, aAttribute, aValue, 106 aMaybeScriptedPrincipal, aResult); 107 } 108 109 //---------------------------------------------------------------------- 110 // nsIMutationObserver methods 111 112 void SVGStyleElement::CharacterDataChanged(nsIContent* aContent, 113 const CharacterDataChangeInfo&) { 114 ContentChanged(aContent); 115 } 116 117 void SVGStyleElement::ContentAppended(nsIContent* aFirstNewContent, 118 const ContentAppendInfo&) { 119 ContentChanged(aFirstNewContent->GetParent()); 120 } 121 122 void SVGStyleElement::ContentInserted(nsIContent* aChild, 123 const ContentInsertInfo&) { 124 ContentChanged(aChild); 125 } 126 127 void SVGStyleElement::ContentWillBeRemoved(nsIContent* aChild, 128 const ContentRemoveInfo& aInfo) { 129 if (!nsContentUtils::IsInSameAnonymousTree(this, aChild)) { 130 return; 131 } 132 if (aInfo.mBatchRemovalState && !aInfo.mBatchRemovalState->mIsFirst) { 133 return; 134 } 135 // Make sure to run this once the removal has taken place. 136 nsContentUtils::AddScriptRunner(NS_NewRunnableFunction( 137 "SVGStyleElement::ContentWillBeRemoved", 138 [self = RefPtr{this}] { self->UpdateStyleSheetInternal(); })); 139 } 140 141 void SVGStyleElement::ContentChanged(nsIContent* aContent) { 142 if (nsContentUtils::IsInSameAnonymousTree(this, aContent)) { 143 (void)UpdateStyleSheetInternal(nullptr, nullptr); 144 } 145 } 146 147 //---------------------------------------------------------------------- 148 149 void SVGStyleElement::GetMedia(nsAString& aMedia) { 150 GetAttr(nsGkAtoms::media, aMedia); 151 } 152 153 void SVGStyleElement::SetMedia(const nsAString& aMedia, ErrorResult& rv) { 154 SetAttr(nsGkAtoms::media, aMedia, rv); 155 } 156 157 void SVGStyleElement::GetType(nsAString& aType) { 158 GetAttr(nsGkAtoms::type, aType); 159 } 160 161 void SVGStyleElement::SetType(const nsAString& aType, ErrorResult& rv) { 162 SetAttr(nsGkAtoms::type, aType, rv); 163 } 164 165 void SVGStyleElement::GetTitle(nsAString& aTitle) { 166 GetAttr(nsGkAtoms::title, aTitle); 167 } 168 169 void SVGStyleElement::SetTitle(const nsAString& aTitle, ErrorResult& rv) { 170 SetAttr(nsGkAtoms::title, aTitle, rv); 171 } 172 173 bool SVGStyleElement::Disabled() const { 174 StyleSheet* ss = GetSheet(); 175 return ss && ss->Disabled(); 176 } 177 178 void SVGStyleElement::SetDisabled(bool aDisabled) { 179 if (StyleSheet* ss = GetSheet()) { 180 ss->SetDisabled(aDisabled); 181 } 182 } 183 184 //---------------------------------------------------------------------- 185 // nsStyleLinkElement methods 186 187 Maybe<LinkStyle::SheetInfo> SVGStyleElement::GetStyleSheetInfo() { 188 if (!IsCSSMimeTypeAttributeForStyleElement(*this)) { 189 return Nothing(); 190 } 191 192 nsAutoString title; 193 nsAutoString media; 194 GetTitleAndMediaForElement(*this, title, media); 195 196 return Some(SheetInfo{ 197 *OwnerDoc(), 198 this, 199 nullptr, 200 // FIXME(bug 1459822): Why doesn't this need a principal, but 201 // HTMLStyleElement does? 202 nullptr, 203 // FIXME(bug 1459822): Why does this need a crossorigin attribute, but 204 // HTMLStyleElement doesn't? 205 MakeAndAddRef<ReferrerInfo>(*this), 206 AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin)), 207 title, 208 media, 209 /* integrity = */ u""_ns, 210 /* nsStyleUtil::CSPAllowsInlineStyle takes care of nonce checking for 211 inline styles. Bug 1607011 */ 212 /* nonce = */ u""_ns, 213 HasAlternateRel::No, 214 IsInline::Yes, 215 IsExplicitlyEnabled::No, 216 FetchPriority::Auto, 217 }); 218 } 219 220 nsresult SVGStyleElement::CopyInnerTo(SVGStyleElement* aDest) { 221 nsresult rv = Element::CopyInnerTo(aDest); 222 NS_ENSURE_SUCCESS(rv, rv); 223 MaybeStartCopyStyleSheetTo(aDest, aDest->OwnerDoc()); 224 return NS_OK; 225 } 226 227 } // namespace mozilla::dom