1 /*
2  * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann
3  * <zimmermann@kde.org>
4  * Copyright (C) 2004, 2005, 2006, 2008 Rob Buis <buis@kde.org>
5  * Copyright (C) 2008 Apple Inc. All rights reserved.
6  * Copyright (C) 2008 Alp Toker <alp@atoker.com>
7  * Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24 
25 #include "third_party/blink/renderer/core/svg/svg_element.h"
26 
27 #include "base/auto_reset.h"
28 #include "base/stl_util.h"
29 #include "third_party/blink/renderer/bindings/core/v8/js_event_handler_for_content_attribute.h"
30 #include "third_party/blink/renderer/core/animation/document_animations.h"
31 #include "third_party/blink/renderer/core/animation/effect_stack.h"
32 #include "third_party/blink/renderer/core/animation/element_animations.h"
33 #include "third_party/blink/renderer/core/animation/invalidatable_interpolation.h"
34 #include "third_party/blink/renderer/core/animation/keyframe_effect.h"
35 #include "third_party/blink/renderer/core/animation/svg_interpolation_environment.h"
36 #include "third_party/blink/renderer/core/animation/svg_interpolation_types_map.h"
37 #include "third_party/blink/renderer/core/css/css_property_id_templates.h"
38 #include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
39 #include "third_party/blink/renderer/core/dom/document.h"
40 #include "third_party/blink/renderer/core/dom/element_traversal.h"
41 #include "third_party/blink/renderer/core/dom/events/add_event_listener_options_resolved.h"
42 #include "third_party/blink/renderer/core/dom/events/event.h"
43 #include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
44 #include "third_party/blink/renderer/core/dom/node_computed_style.h"
45 #include "third_party/blink/renderer/core/dom/shadow_root.h"
46 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
47 #include "third_party/blink/renderer/core/frame/settings.h"
48 #include "third_party/blink/renderer/core/html/html_element.h"
49 #include "third_party/blink/renderer/core/html_names.h"
50 #include "third_party/blink/renderer/core/inspector/console_message.h"
51 #include "third_party/blink/renderer/core/layout/layout_object.h"
52 #include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.h"
53 #include "third_party/blink/renderer/core/layout/svg/transform_helper.h"
54 #include "third_party/blink/renderer/core/svg/animation/element_smil_animations.h"
55 #include "third_party/blink/renderer/core/svg/properties/svg_animated_property.h"
56 #include "third_party/blink/renderer/core/svg/properties/svg_property.h"
57 #include "third_party/blink/renderer/core/svg/svg_animated_string.h"
58 #include "third_party/blink/renderer/core/svg/svg_document_extensions.h"
59 #include "third_party/blink/renderer/core/svg/svg_element_rare_data.h"
60 #include "third_party/blink/renderer/core/svg/svg_graphics_element.h"
61 #include "third_party/blink/renderer/core/svg/svg_svg_element.h"
62 #include "third_party/blink/renderer/core/svg/svg_title_element.h"
63 #include "third_party/blink/renderer/core/svg/svg_use_element.h"
64 #include "third_party/blink/renderer/core/svg_names.h"
65 #include "third_party/blink/renderer/core/xml_names.h"
66 #include "third_party/blink/renderer/platform/heap/heap.h"
67 #include "third_party/blink/renderer/platform/wtf/threading.h"
68 
69 namespace blink {
70 
SVGElement(const QualifiedName & tag_name,Document & document,ConstructionType construction_type)71 SVGElement::SVGElement(const QualifiedName& tag_name,
72                        Document& document,
73                        ConstructionType construction_type)
74     : Element(tag_name, &document, construction_type),
75       svg_rare_data_(nullptr),
76       class_name_(
77           MakeGarbageCollected<SVGAnimatedString>(this,
78                                                   html_names::kClassAttr)) {
79   AddToPropertyMap(class_name_);
80   SetHasCustomStyleCallbacks();
81 }
82 
~SVGElement()83 SVGElement::~SVGElement() {
84   DCHECK(isConnected() || !HasRelativeLengths());
85 }
86 
DetachLayoutTree(bool performing_reattach)87 void SVGElement::DetachLayoutTree(bool performing_reattach) {
88   Element::DetachLayoutTree(performing_reattach);
89   // To avoid a noncollectable Blink GC reference cycle, we must clear the
90   // ComputedStyle here. See http://crbug.com/878032#c11
91   if (HasSVGRareData())
92     SvgRareData()->ClearOverriddenComputedStyle();
93 }
94 
WillRecalcStyle(const StyleRecalcChange change)95 void SVGElement::WillRecalcStyle(const StyleRecalcChange change) {
96   if (!HasSVGRareData())
97     return;
98   // If the style changes because of a regular property change (not induced by
99   // SMIL animations themselves) reset the "computed style without SMIL style
100   // properties", so the base value change gets reflected.
101   if (change.ShouldRecalcStyleFor(*this))
102     SvgRareData()->SetNeedsOverrideComputedStyleUpdate();
103 }
104 
EnsureSVGRareData()105 SVGElementRareData* SVGElement::EnsureSVGRareData() {
106   if (!svg_rare_data_)
107     svg_rare_data_ = MakeGarbageCollected<SVGElementRareData>();
108   return svg_rare_data_.Get();
109 }
110 
IsOutermostSVGSVGElement() const111 bool SVGElement::IsOutermostSVGSVGElement() const {
112   if (!IsA<SVGSVGElement>(*this))
113     return false;
114 
115   // Element may not be in the document, pretend we're outermost for viewport(),
116   // getCTM(), etc.
117   if (!parentNode())
118     return true;
119 
120   // We act like an outermost SVG element, if we're a direct child of a
121   // <foreignObject> element.
122   if (IsA<SVGForeignObjectElement>(*parentNode()))
123     return true;
124 
125   // If we're living in a shadow tree, we're a <svg> element that got created as
126   // replacement for a <symbol> element or a cloned <svg> element in the
127   // referenced tree. In that case we're always an inner <svg> element.
128   if (InUseShadowTree() && ParentOrShadowHostElement() &&
129       ParentOrShadowHostElement()->IsSVGElement())
130     return false;
131 
132   // This is true whenever this is the outermost SVG, even if there are HTML
133   // elements outside it
134   return !parentNode()->IsSVGElement();
135 }
136 
ReportAttributeParsingError(SVGParsingError error,const QualifiedName & name,const AtomicString & value)137 void SVGElement::ReportAttributeParsingError(SVGParsingError error,
138                                              const QualifiedName& name,
139                                              const AtomicString& value) {
140   if (error == SVGParseStatus::kNoError)
141     return;
142   // Don't report any errors on attribute removal.
143   if (value.IsNull())
144     return;
145   GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
146       mojom::ConsoleMessageSource::kRendering,
147       mojom::ConsoleMessageLevel::kError,
148       "Error: " + error.Format(tagName(), name, value)));
149 }
150 
title() const151 String SVGElement::title() const {
152   // According to spec, we should not return titles when hovering over root
153   // <svg> elements imported as a standalone document(those <title> elements
154   // are the title of the document, not a tooltip) so we instantly return.
155   if (IsA<SVGSVGElement>(*this) && this == GetDocument().documentElement())
156     return String();
157 
158   if (InUseShadowTree()) {
159     String use_title(OwnerShadowHost()->title());
160     if (!use_title.IsEmpty())
161       return use_title;
162   }
163 
164   // If we aren't an instance in a <use> or the <use> title was not found, then
165   // find the first <title> child of this element.
166   // If a title child was found, return the text contents.
167   if (Element* title_element = Traversal<SVGTitleElement>::FirstChild(*this))
168     return title_element->innerText();
169 
170   // Otherwise return a null/empty string.
171   return String();
172 }
173 
InstanceUpdatesBlocked() const174 bool SVGElement::InstanceUpdatesBlocked() const {
175   return HasSVGRareData() && SvgRareData()->InstanceUpdatesBlocked();
176 }
177 
SetInstanceUpdatesBlocked(bool value)178 void SVGElement::SetInstanceUpdatesBlocked(bool value) {
179   if (HasSVGRareData())
180     SvgRareData()->SetInstanceUpdatesBlocked(value);
181 }
182 
SetWebAnimationsPending()183 void SVGElement::SetWebAnimationsPending() {
184   GetDocument().AccessSVGExtensions().AddWebAnimationsPendingSVGElement(*this);
185   EnsureSVGRareData()->SetWebAnimatedAttributesDirty(true);
186 }
187 
IsSVGAttributeHandle(const PropertyHandle & property_handle)188 static bool IsSVGAttributeHandle(const PropertyHandle& property_handle) {
189   return property_handle.IsSVGAttribute();
190 }
191 
ApplyActiveWebAnimations()192 void SVGElement::ApplyActiveWebAnimations() {
193   ActiveInterpolationsMap active_interpolations_map =
194       EffectStack::ActiveInterpolations(
195           &GetElementAnimations()->GetEffectStack(), nullptr, nullptr,
196           KeyframeEffect::kDefaultPriority, IsSVGAttributeHandle);
197   for (auto& entry : active_interpolations_map) {
198     const QualifiedName& attribute = entry.key.SvgAttribute();
199     SVGInterpolationTypesMap map;
200     SVGInterpolationEnvironment environment(
201         map, *this, PropertyFromAttribute(attribute)->BaseValueBase());
202     InvalidatableInterpolation::ApplyStack(*entry.value, environment);
203   }
204   if (!HasSVGRareData())
205     return;
206   SvgRareData()->SetWebAnimatedAttributesDirty(false);
207 }
208 
209 template <typename T>
ForSelfAndInstances(SVGElement * element,T callback)210 static void ForSelfAndInstances(SVGElement* element, T callback) {
211   SVGElement::InstanceUpdateBlocker blocker(element);
212   callback(element);
213   for (SVGElement* instance : element->InstancesForElement())
214     callback(instance);
215 }
216 
SetWebAnimatedAttribute(const QualifiedName & attribute,SVGPropertyBase * value)217 void SVGElement::SetWebAnimatedAttribute(const QualifiedName& attribute,
218                                          SVGPropertyBase* value) {
219   SetAnimatedAttribute(attribute, value);
220   EnsureSVGRareData()->WebAnimatedAttributes().insert(attribute);
221 }
222 
ClearWebAnimatedAttributes()223 void SVGElement::ClearWebAnimatedAttributes() {
224   if (!HasSVGRareData())
225     return;
226   HashSet<QualifiedName>& animated_attributes =
227       SvgRareData()->WebAnimatedAttributes();
228   for (const QualifiedName& attribute : animated_attributes)
229     ClearAnimatedAttribute(attribute);
230   animated_attributes.clear();
231 }
232 
GetSMILAnimations() const233 ElementSMILAnimations* SVGElement::GetSMILAnimations() const {
234   if (!HasSVGRareData())
235     return nullptr;
236   return SvgRareData()->GetSMILAnimations();
237 }
238 
EnsureSMILAnimations()239 ElementSMILAnimations& SVGElement::EnsureSMILAnimations() {
240   return EnsureSVGRareData()->EnsureSMILAnimations();
241 }
242 
SetAnimatedAttribute(const QualifiedName & attribute,SVGPropertyBase * value)243 void SVGElement::SetAnimatedAttribute(const QualifiedName& attribute,
244                                       SVGPropertyBase* value) {
245   // When animating the 'class' attribute we need to have our own
246   // unique element data since we'll be altering the active class
247   // names for the element.
248   if (attribute == html_names::kClassAttr)
249     EnsureUniqueElementData();
250 
251   ForSelfAndInstances(this, [&attribute, &value](SVGElement* element) {
252     if (SVGAnimatedPropertyBase* animated_property =
253             element->PropertyFromAttribute(attribute)) {
254       animated_property->SetAnimatedValue(value);
255       element->SvgAttributeChanged(attribute);
256     }
257   });
258 }
259 
ClearAnimatedAttribute(const QualifiedName & attribute)260 void SVGElement::ClearAnimatedAttribute(const QualifiedName& attribute) {
261   ForSelfAndInstances(this, [&attribute](SVGElement* element) {
262     if (SVGAnimatedPropertyBase* animated_property =
263             element->PropertyFromAttribute(attribute)) {
264       animated_property->AnimationEnded();
265       element->SvgAttributeChanged(attribute);
266     }
267   });
268 }
269 
SetAnimatedMotionTransform(const AffineTransform & motion_transform)270 void SVGElement::SetAnimatedMotionTransform(
271     const AffineTransform& motion_transform) {
272   ForSelfAndInstances(this, [&motion_transform](SVGElement* element) {
273     AffineTransform* transform = element->AnimateMotionTransform();
274     DCHECK(transform);
275     *transform = motion_transform;
276     if (LayoutObject* layout_object = element->GetLayoutObject()) {
277       layout_object->SetNeedsTransformUpdate();
278       // The transform paint property relies on the SVG transform value.
279       layout_object->SetNeedsPaintPropertyUpdate();
280       MarkForLayoutAndParentResourceInvalidation(*layout_object);
281     }
282   });
283 }
284 
ClearAnimatedMotionTransform()285 void SVGElement::ClearAnimatedMotionTransform() {
286   SetAnimatedMotionTransform(AffineTransform());
287 }
288 
HasNonCSSPropertyAnimations() const289 bool SVGElement::HasNonCSSPropertyAnimations() const {
290   if (HasSVGRareData() && !SvgRareData()->WebAnimatedAttributes().IsEmpty())
291     return true;
292   if (GetSMILAnimations() && GetSMILAnimations()->HasAnimations())
293     return true;
294   return false;
295 }
296 
LocalCoordinateSpaceTransform(CTMScope) const297 AffineTransform SVGElement::LocalCoordinateSpaceTransform(CTMScope) const {
298   // To be overriden by SVGGraphicsElement (or as special case SVGTextElement
299   // and SVGPatternElement)
300   return AffineTransform();
301 }
302 
HasTransform(ApplyMotionTransform apply_motion_transform) const303 bool SVGElement::HasTransform(
304     ApplyMotionTransform apply_motion_transform) const {
305   return (GetLayoutObject() && GetLayoutObject()->StyleRef().HasTransform()) ||
306          (apply_motion_transform == kIncludeMotionTransform &&
307           HasSVGRareData());
308 }
309 
CalculateTransform(ApplyMotionTransform apply_motion_transform) const310 AffineTransform SVGElement::CalculateTransform(
311     ApplyMotionTransform apply_motion_transform) const {
312   const LayoutObject* layout_object = GetLayoutObject();
313 
314   AffineTransform matrix;
315   if (layout_object && layout_object->StyleRef().HasTransform()) {
316     matrix = TransformHelper::ComputeTransform(
317         *layout_object, ComputedStyle::kIncludeTransformOrigin);
318   }
319 
320   // Apply any "motion transform" contribution if requested (and existing.)
321   if (apply_motion_transform == kIncludeMotionTransform && HasSVGRareData())
322     matrix.PreMultiply(*SvgRareData()->AnimateMotionTransform());
323 
324   return matrix;
325 }
326 
InsertedInto(ContainerNode & root_parent)327 Node::InsertionNotificationRequest SVGElement::InsertedInto(
328     ContainerNode& root_parent) {
329   Element::InsertedInto(root_parent);
330   HideNonce();
331   UpdateRelativeLengthsInformation();
332   return kInsertionDone;
333 }
334 
RemovedFrom(ContainerNode & root_parent)335 void SVGElement::RemovedFrom(ContainerNode& root_parent) {
336   bool was_in_document = root_parent.isConnected();
337   auto* root_parent_svg_element = DynamicTo<SVGElement>(
338       root_parent.IsShadowRoot() ? root_parent.ParentOrShadowHostElement()
339                                  : &root_parent);
340 
341   if (was_in_document && HasRelativeLengths()) {
342     // The root of the subtree being removed should take itself out from its
343     // parent's relative length set. For the other nodes in the subtree we don't
344     // need to do anything: they will get their own removedFrom() notification
345     // and just clear their sets.
346     if (root_parent_svg_element && !ParentOrShadowHostElement()) {
347       DCHECK(root_parent_svg_element->elements_with_relative_lengths_.Contains(
348           this));
349       root_parent_svg_element->UpdateRelativeLengthsInformation(false, this);
350     }
351 
352     elements_with_relative_lengths_.clear();
353   }
354 
355   DCHECK(
356       !root_parent_svg_element ||
357       !root_parent_svg_element->elements_with_relative_lengths_.Contains(this));
358 
359   Element::RemovedFrom(root_parent);
360 
361   if (was_in_document) {
362     if (HasSVGRareData() && SvgRareData()->CorrespondingElement())
363       SvgRareData()->CorrespondingElement()->RemoveInstanceMapping(this);
364     RebuildAllIncomingReferences();
365     RemoveAllIncomingReferences();
366   }
367 
368   InvalidateInstances();
369 }
370 
ChildrenChanged(const ChildrenChange & change)371 void SVGElement::ChildrenChanged(const ChildrenChange& change) {
372   Element::ChildrenChanged(change);
373 
374   // Invalidate all instances associated with us.
375   InvalidateInstances();
376 }
377 
CssPropertyIdForSVGAttributeName(const ExecutionContext * execution_context,const QualifiedName & attr_name)378 CSSPropertyID SVGElement::CssPropertyIdForSVGAttributeName(
379     const ExecutionContext* execution_context,
380     const QualifiedName& attr_name) {
381   if (!attr_name.NamespaceURI().IsNull())
382     return CSSPropertyID::kInvalid;
383 
384   static HashMap<StringImpl*, CSSPropertyID>* property_name_to_id_map = nullptr;
385   if (!property_name_to_id_map) {
386     property_name_to_id_map = new HashMap<StringImpl*, CSSPropertyID>;
387     // This is a list of all base CSS and SVG CSS properties which are exposed
388     // as SVG XML attributes
389     const QualifiedName* const attr_names[] = {
390         &svg_names::kAlignmentBaselineAttr,
391         &svg_names::kBaselineShiftAttr,
392         &svg_names::kBufferedRenderingAttr,
393         &svg_names::kClipAttr,
394         &svg_names::kClipPathAttr,
395         &svg_names::kClipRuleAttr,
396         &svg_names::kColorAttr,
397         &svg_names::kColorInterpolationAttr,
398         &svg_names::kColorInterpolationFiltersAttr,
399         &svg_names::kColorRenderingAttr,
400         &svg_names::kCursorAttr,
401         &svg_names::kDirectionAttr,
402         &svg_names::kDisplayAttr,
403         &svg_names::kDominantBaselineAttr,
404         &svg_names::kFillAttr,
405         &svg_names::kFillOpacityAttr,
406         &svg_names::kFillRuleAttr,
407         &svg_names::kFilterAttr,
408         &svg_names::kFloodColorAttr,
409         &svg_names::kFloodOpacityAttr,
410         &svg_names::kFontFamilyAttr,
411         &svg_names::kFontSizeAttr,
412         &svg_names::kFontStretchAttr,
413         &svg_names::kFontStyleAttr,
414         &svg_names::kFontVariantAttr,
415         &svg_names::kFontWeightAttr,
416         &svg_names::kImageRenderingAttr,
417         &svg_names::kLetterSpacingAttr,
418         &svg_names::kLightingColorAttr,
419         &svg_names::kMarkerEndAttr,
420         &svg_names::kMarkerMidAttr,
421         &svg_names::kMarkerStartAttr,
422         &svg_names::kMaskAttr,
423         &svg_names::kMaskTypeAttr,
424         &svg_names::kOpacityAttr,
425         &svg_names::kOverflowAttr,
426         &svg_names::kPaintOrderAttr,
427         &svg_names::kPointerEventsAttr,
428         &svg_names::kShapeRenderingAttr,
429         &svg_names::kStopColorAttr,
430         &svg_names::kStopOpacityAttr,
431         &svg_names::kStrokeAttr,
432         &svg_names::kStrokeDasharrayAttr,
433         &svg_names::kStrokeDashoffsetAttr,
434         &svg_names::kStrokeLinecapAttr,
435         &svg_names::kStrokeLinejoinAttr,
436         &svg_names::kStrokeMiterlimitAttr,
437         &svg_names::kStrokeOpacityAttr,
438         &svg_names::kStrokeWidthAttr,
439         &svg_names::kTextAnchorAttr,
440         &svg_names::kTextDecorationAttr,
441         &svg_names::kTextRenderingAttr,
442         &svg_names::kTransformOriginAttr,
443         &svg_names::kUnicodeBidiAttr,
444         &svg_names::kVectorEffectAttr,
445         &svg_names::kVisibilityAttr,
446         &svg_names::kWordSpacingAttr,
447         &svg_names::kWritingModeAttr,
448     };
449     for (size_t i = 0; i < base::size(attr_names); i++) {
450       CSSPropertyID property_id =
451           cssPropertyID(execution_context, attr_names[i]->LocalName());
452       DCHECK_GT(property_id, CSSPropertyID::kInvalid);
453       property_name_to_id_map->Set(attr_names[i]->LocalName().Impl(),
454                                    property_id);
455     }
456   }
457 
458   return property_name_to_id_map->at(attr_name.LocalName().Impl());
459 }
460 
UpdateRelativeLengthsInformation(bool client_has_relative_lengths,SVGElement * client_element)461 void SVGElement::UpdateRelativeLengthsInformation(
462     bool client_has_relative_lengths,
463     SVGElement* client_element) {
464   DCHECK(client_element);
465 
466   // Through an unfortunate chain of events, we can end up calling this while a
467   // subtree is being removed, and before the subtree has been properly
468   // "disconnected". Hence check the entire ancestor chain to avoid propagating
469   // relative length clients up into ancestors that have already been
470   // disconnected.
471   // If we're not yet in a document, this function will be called again from
472   // insertedInto(). Do nothing now.
473   for (Node* current_node = this; current_node;
474        current_node = current_node->ParentOrShadowHostNode()) {
475     if (!current_node->isConnected())
476       return;
477   }
478 
479   // An element wants to notify us that its own relative lengths state changed.
480   // Register it in the relative length map, and register us in the parent
481   // relative length map.  Register the parent in the grandparents map, etc.
482   // Repeat procedure until the root of the SVG tree.
483   for (Element* current_node = this; current_node;
484        current_node = current_node->ParentOrShadowHostElement()) {
485     auto* current_element = DynamicTo<SVGElement>(current_node);
486     if (!current_element)
487       break;
488 
489 #if DCHECK_IS_ON()
490     DCHECK(!current_element->in_relative_length_clients_invalidation_);
491 #endif
492 
493     bool had_relative_lengths = current_element->HasRelativeLengths();
494     if (client_has_relative_lengths)
495       current_element->elements_with_relative_lengths_.insert(client_element);
496     else
497       current_element->elements_with_relative_lengths_.erase(client_element);
498 
499     // If the relative length state hasn't changed, we can stop propagating the
500     // notification.
501     if (had_relative_lengths == current_element->HasRelativeLengths())
502       return;
503 
504     client_element = current_element;
505     client_has_relative_lengths = client_element->HasRelativeLengths();
506   }
507 
508   // Register root SVG elements for top level viewport change notifications.
509   if (auto* svg = DynamicTo<SVGSVGElement>(*client_element)) {
510     SVGDocumentExtensions& svg_extensions = GetDocument().AccessSVGExtensions();
511     if (client_element->HasRelativeLengths())
512       svg_extensions.AddSVGRootWithRelativeLengthDescendents(svg);
513     else
514       svg_extensions.RemoveSVGRootWithRelativeLengthDescendents(svg);
515   }
516 }
517 
InvalidateRelativeLengthClients(SubtreeLayoutScope * layout_scope)518 void SVGElement::InvalidateRelativeLengthClients(
519     SubtreeLayoutScope* layout_scope) {
520   if (!isConnected())
521     return;
522 
523 #if DCHECK_IS_ON()
524   DCHECK(!in_relative_length_clients_invalidation_);
525   base::AutoReset<bool> in_relative_length_clients_invalidation_change(
526       &in_relative_length_clients_invalidation_, true);
527 #endif
528 
529   if (LayoutObject* layout_object = GetLayoutObject()) {
530     if (HasRelativeLengths() && layout_object->IsSVGResourceContainer()) {
531       To<LayoutSVGResourceContainer>(layout_object)
532           ->InvalidateCacheAndMarkForLayout(
533               layout_invalidation_reason::kSizeChanged, layout_scope);
534     } else if (SelfHasRelativeLengths()) {
535       layout_object->SetNeedsLayoutAndFullPaintInvalidation(
536           layout_invalidation_reason::kUnknown, kMarkContainerChain,
537           layout_scope);
538     }
539   }
540 
541   for (SVGElement* element : elements_with_relative_lengths_) {
542     if (element != this)
543       element->InvalidateRelativeLengthClients(layout_scope);
544   }
545 }
546 
ownerSVGElement() const547 SVGSVGElement* SVGElement::ownerSVGElement() const {
548   ContainerNode* n = ParentOrShadowHostNode();
549   while (n) {
550     if (auto* svg_svg_element = DynamicTo<SVGSVGElement>(n))
551       return svg_svg_element;
552 
553     n = n->ParentOrShadowHostNode();
554   }
555 
556   return nullptr;
557 }
558 
viewportElement() const559 SVGElement* SVGElement::viewportElement() const {
560   // This function needs shadow tree support - as LayoutSVGContainer uses this
561   // function to determine the "overflow" property. <use> on <symbol> wouldn't
562   // work otherwhise.
563   ContainerNode* n = ParentOrShadowHostNode();
564   while (n) {
565     if (IsA<SVGSVGElement>(*n) || IsA<SVGImageElement>(*n) ||
566         IsA<SVGSymbolElement>(*n))
567       return To<SVGElement>(n);
568 
569     n = n->ParentOrShadowHostNode();
570   }
571 
572   return nullptr;
573 }
574 
MapInstanceToElement(SVGElement * instance)575 void SVGElement::MapInstanceToElement(SVGElement* instance) {
576   DCHECK(instance);
577   DCHECK(instance->InUseShadowTree());
578 
579   HeapHashSet<WeakMember<SVGElement>>& instances =
580       EnsureSVGRareData()->ElementInstances();
581   DCHECK(!instances.Contains(instance));
582 
583   instances.insert(instance);
584 }
585 
RemoveInstanceMapping(SVGElement * instance)586 void SVGElement::RemoveInstanceMapping(SVGElement* instance) {
587   DCHECK(instance);
588   // Called during instance->RemovedFrom() after removal from shadow tree
589   DCHECK(!instance->isConnected());
590 
591   HeapHashSet<WeakMember<SVGElement>>& instances =
592       SvgRareData()->ElementInstances();
593 
594   instances.erase(instance);
595 }
596 
EmptyInstances()597 static HeapHashSet<WeakMember<SVGElement>>& EmptyInstances() {
598   DEFINE_STATIC_LOCAL(
599       Persistent<HeapHashSet<WeakMember<SVGElement>>>, empty_instances,
600       (MakeGarbageCollected<HeapHashSet<WeakMember<SVGElement>>>()));
601   return *empty_instances;
602 }
603 
InstancesForElement() const604 const HeapHashSet<WeakMember<SVGElement>>& SVGElement::InstancesForElement()
605     const {
606   if (!HasSVGRareData())
607     return EmptyInstances();
608   return SvgRareData()->ElementInstances();
609 }
610 
CorrespondingElement() const611 SVGElement* SVGElement::CorrespondingElement() const {
612   DCHECK(!HasSVGRareData() || !SvgRareData()->CorrespondingElement() ||
613          ContainingShadowRoot());
614   return HasSVGRareData() ? SvgRareData()->CorrespondingElement() : nullptr;
615 }
616 
GeneratingUseElement() const617 SVGUseElement* SVGElement::GeneratingUseElement() const {
618   if (ShadowRoot* root = ContainingShadowRoot()) {
619     return DynamicTo<SVGUseElement>(root->host());
620   }
621   return nullptr;
622 }
623 
SetCorrespondingElement(SVGElement * corresponding_element)624 void SVGElement::SetCorrespondingElement(SVGElement* corresponding_element) {
625   EnsureSVGRareData()->SetCorrespondingElement(corresponding_element);
626 }
627 
InUseShadowTree() const628 bool SVGElement::InUseShadowTree() const {
629   return GeneratingUseElement();
630 }
631 
ParseAttribute(const AttributeModificationParams & params)632 void SVGElement::ParseAttribute(const AttributeModificationParams& params) {
633   // Note about the 'class' attribute:
634   // The "special storage" (SVGAnimatedString) for the 'class' attribute (and
635   // the 'className' property) is updated by the follow block (|class_name_|
636   // registered in |attribute_to_property_map_|.). SvgAttributeChanged then
637   // triggers the resulting style updates (instead of
638   // Element::ParseAttribute). We don't tell Element about the change to avoid
639   // parsing the class list twice.
640   if (SVGAnimatedPropertyBase* property = PropertyFromAttribute(params.name)) {
641     SVGParsingError parse_error = property->AttributeChanged(params.new_value);
642     ReportAttributeParsingError(parse_error, params.name, params.new_value);
643     return;
644   }
645 
646   // SVGElement and HTMLElement are handling "nonce" the same way.
647   if (params.name == html_names::kNonceAttr) {
648     if (params.new_value != g_empty_atom)
649       setNonce(params.new_value);
650   }
651 
652   const AtomicString& event_name =
653       HTMLElement::EventNameForAttributeName(params.name);
654   if (!event_name.IsNull()) {
655     SetAttributeEventListener(
656         event_name, JSEventHandlerForContentAttribute::Create(
657                         GetExecutionContext(), params.name, params.new_value));
658     return;
659   }
660 
661   Element::ParseAttribute(params);
662 }
663 
664 // If the attribute is not present in the map, the map will return the "empty
665 // value" - which is kAnimatedUnknown.
666 struct AnimatedPropertyTypeHashTraits : HashTraits<AnimatedPropertyType> {
667   static const bool kEmptyValueIsZero = true;
EmptyValueblink::AnimatedPropertyTypeHashTraits668   static AnimatedPropertyType EmptyValue() { return kAnimatedUnknown; }
669 };
670 
671 using AttributeToPropertyTypeMap = HashMap<QualifiedName,
672                                            AnimatedPropertyType,
673                                            DefaultHash<QualifiedName>::Hash,
674                                            HashTraits<QualifiedName>,
675                                            AnimatedPropertyTypeHashTraits>;
AnimatedPropertyTypeForCSSAttribute(const QualifiedName & attribute_name)676 AnimatedPropertyType SVGElement::AnimatedPropertyTypeForCSSAttribute(
677     const QualifiedName& attribute_name) {
678   DEFINE_STATIC_LOCAL(AttributeToPropertyTypeMap, css_property_map, ());
679 
680   if (css_property_map.IsEmpty()) {
681     // Fill the map for the first use.
682     struct AttrToTypeEntry {
683       const QualifiedName& attr;
684       const AnimatedPropertyType prop_type;
685     };
686     const AttrToTypeEntry attr_to_types[] = {
687         {svg_names::kAlignmentBaselineAttr, kAnimatedString},
688         {svg_names::kBaselineShiftAttr, kAnimatedString},
689         {svg_names::kBufferedRenderingAttr, kAnimatedString},
690         {svg_names::kClipPathAttr, kAnimatedString},
691         {svg_names::kClipRuleAttr, kAnimatedString},
692         {svg_names::kColorAttr, kAnimatedColor},
693         {svg_names::kColorInterpolationAttr, kAnimatedString},
694         {svg_names::kColorInterpolationFiltersAttr, kAnimatedString},
695         {svg_names::kColorRenderingAttr, kAnimatedString},
696         {svg_names::kCursorAttr, kAnimatedString},
697         {svg_names::kDisplayAttr, kAnimatedString},
698         {svg_names::kDominantBaselineAttr, kAnimatedString},
699         {svg_names::kFillAttr, kAnimatedColor},
700         {svg_names::kFillOpacityAttr, kAnimatedNumber},
701         {svg_names::kFillRuleAttr, kAnimatedString},
702         {svg_names::kFilterAttr, kAnimatedString},
703         {svg_names::kFloodColorAttr, kAnimatedColor},
704         {svg_names::kFloodOpacityAttr, kAnimatedNumber},
705         {svg_names::kFontFamilyAttr, kAnimatedString},
706         {svg_names::kFontSizeAttr, kAnimatedLength},
707         {svg_names::kFontStretchAttr, kAnimatedString},
708         {svg_names::kFontStyleAttr, kAnimatedString},
709         {svg_names::kFontVariantAttr, kAnimatedString},
710         {svg_names::kFontWeightAttr, kAnimatedString},
711         {svg_names::kImageRenderingAttr, kAnimatedString},
712         {svg_names::kLetterSpacingAttr, kAnimatedLength},
713         {svg_names::kLightingColorAttr, kAnimatedColor},
714         {svg_names::kMarkerEndAttr, kAnimatedString},
715         {svg_names::kMarkerMidAttr, kAnimatedString},
716         {svg_names::kMarkerStartAttr, kAnimatedString},
717         {svg_names::kMaskAttr, kAnimatedString},
718         {svg_names::kMaskTypeAttr, kAnimatedString},
719         {svg_names::kOpacityAttr, kAnimatedNumber},
720         {svg_names::kOverflowAttr, kAnimatedString},
721         {svg_names::kPaintOrderAttr, kAnimatedString},
722         {svg_names::kPointerEventsAttr, kAnimatedString},
723         {svg_names::kShapeRenderingAttr, kAnimatedString},
724         {svg_names::kStopColorAttr, kAnimatedColor},
725         {svg_names::kStopOpacityAttr, kAnimatedNumber},
726         {svg_names::kStrokeAttr, kAnimatedColor},
727         {svg_names::kStrokeDasharrayAttr, kAnimatedLengthList},
728         {svg_names::kStrokeDashoffsetAttr, kAnimatedLength},
729         {svg_names::kStrokeLinecapAttr, kAnimatedString},
730         {svg_names::kStrokeLinejoinAttr, kAnimatedString},
731         {svg_names::kStrokeMiterlimitAttr, kAnimatedNumber},
732         {svg_names::kStrokeOpacityAttr, kAnimatedNumber},
733         {svg_names::kStrokeWidthAttr, kAnimatedLength},
734         {svg_names::kTextAnchorAttr, kAnimatedString},
735         {svg_names::kTextDecorationAttr, kAnimatedString},
736         {svg_names::kTextRenderingAttr, kAnimatedString},
737         {svg_names::kVectorEffectAttr, kAnimatedString},
738         {svg_names::kVisibilityAttr, kAnimatedString},
739         {svg_names::kWordSpacingAttr, kAnimatedLength},
740     };
741     for (size_t i = 0; i < base::size(attr_to_types); i++)
742       css_property_map.Set(attr_to_types[i].attr, attr_to_types[i].prop_type);
743   }
744   return css_property_map.at(attribute_name);
745 }
746 
AddToPropertyMap(SVGAnimatedPropertyBase * property)747 void SVGElement::AddToPropertyMap(SVGAnimatedPropertyBase* property) {
748   attribute_to_property_map_.Set(property->AttributeName(), property);
749 }
750 
PropertyFromAttribute(const QualifiedName & attribute_name) const751 SVGAnimatedPropertyBase* SVGElement::PropertyFromAttribute(
752     const QualifiedName& attribute_name) const {
753   AttributeToPropertyMap::const_iterator it =
754       attribute_to_property_map_.Find<SVGAttributeHashTranslator>(
755           attribute_name);
756   if (it == attribute_to_property_map_.end())
757     return nullptr;
758 
759   return it->value.Get();
760 }
761 
IsAnimatableCSSProperty(const QualifiedName & attr_name)762 bool SVGElement::IsAnimatableCSSProperty(const QualifiedName& attr_name) {
763   return AnimatedPropertyTypeForCSSAttribute(attr_name) != kAnimatedUnknown;
764 }
765 
IsPresentationAttribute(const QualifiedName & name) const766 bool SVGElement::IsPresentationAttribute(const QualifiedName& name) const {
767   if (const SVGAnimatedPropertyBase* property = PropertyFromAttribute(name))
768     return property->HasPresentationAttributeMapping();
769   return CssPropertyIdForSVGAttributeName(GetExecutionContext(), name) >
770          CSSPropertyID::kInvalid;
771 }
772 
CollectStyleForPresentationAttribute(const QualifiedName & name,const AtomicString & value,MutableCSSPropertyValueSet * style)773 void SVGElement::CollectStyleForPresentationAttribute(
774     const QualifiedName& name,
775     const AtomicString& value,
776     MutableCSSPropertyValueSet* style) {
777   CSSPropertyID property_id =
778       CssPropertyIdForSVGAttributeName(GetExecutionContext(), name);
779   if (property_id > CSSPropertyID::kInvalid)
780     AddPropertyToPresentationAttributeStyle(style, property_id, value);
781 }
782 
HaveLoadedRequiredResources()783 bool SVGElement::HaveLoadedRequiredResources() {
784   for (SVGElement* child = Traversal<SVGElement>::FirstChild(*this); child;
785        child = Traversal<SVGElement>::NextSibling(*child)) {
786     if (!child->HaveLoadedRequiredResources())
787       return false;
788   }
789   return true;
790 }
791 
CollectInstancesForSVGElement(SVGElement * element,HeapHashSet<WeakMember<SVGElement>> & instances)792 static inline void CollectInstancesForSVGElement(
793     SVGElement* element,
794     HeapHashSet<WeakMember<SVGElement>>& instances) {
795   DCHECK(element);
796   if (element->ContainingShadowRoot())
797     return;
798 
799   DCHECK(!element->InstanceUpdatesBlocked());
800 
801   instances = element->InstancesForElement();
802 }
803 
AddedEventListener(const AtomicString & event_type,RegisteredEventListener & registered_listener)804 void SVGElement::AddedEventListener(
805     const AtomicString& event_type,
806     RegisteredEventListener& registered_listener) {
807   // Add event listener to regular DOM element
808   Node::AddedEventListener(event_type, registered_listener);
809 
810   // Add event listener to all shadow tree DOM element instances
811   HeapHashSet<WeakMember<SVGElement>> instances;
812   CollectInstancesForSVGElement(this, instances);
813   AddEventListenerOptionsResolved* options = registered_listener.Options();
814   EventListener* listener = registered_listener.Callback();
815   for (SVGElement* element : instances) {
816     bool result =
817         element->Node::AddEventListenerInternal(event_type, listener, options);
818     DCHECK(result);
819   }
820 }
821 
RemovedEventListener(const AtomicString & event_type,const RegisteredEventListener & registered_listener)822 void SVGElement::RemovedEventListener(
823     const AtomicString& event_type,
824     const RegisteredEventListener& registered_listener) {
825   Node::RemovedEventListener(event_type, registered_listener);
826 
827   // Remove event listener from all shadow tree DOM element instances
828   HeapHashSet<WeakMember<SVGElement>> instances;
829   CollectInstancesForSVGElement(this, instances);
830   EventListenerOptions* options = registered_listener.Options();
831   const EventListener* listener = registered_listener.Callback();
832   for (SVGElement* shadow_tree_element : instances) {
833     DCHECK(shadow_tree_element);
834 
835     shadow_tree_element->Node::RemoveEventListenerInternal(event_type, listener,
836                                                            options);
837   }
838 }
839 
HasLoadListener(Element * element)840 static bool HasLoadListener(Element* element) {
841   if (element->HasEventListeners(event_type_names::kLoad))
842     return true;
843 
844   for (element = element->ParentOrShadowHostElement(); element;
845        element = element->ParentOrShadowHostElement()) {
846     EventListenerVector* entry =
847         element->GetEventListeners(event_type_names::kLoad);
848     if (!entry)
849       continue;
850     for (wtf_size_t i = 0; i < entry->size(); ++i) {
851       if (entry->at(i).Capture())
852         return true;
853     }
854   }
855 
856   return false;
857 }
858 
SendSVGLoadEventIfPossible()859 bool SVGElement::SendSVGLoadEventIfPossible() {
860   if (!HaveLoadedRequiredResources())
861     return false;
862   if ((IsStructurallyExternal() || IsA<SVGSVGElement>(*this)) &&
863       HasLoadListener(this))
864     DispatchEvent(*Event::Create(event_type_names::kLoad));
865   return true;
866 }
867 
SendSVGLoadEventToSelfAndAncestorChainIfPossible()868 void SVGElement::SendSVGLoadEventToSelfAndAncestorChainIfPossible() {
869   // Let Document::implicitClose() dispatch the 'load' to the outermost SVG
870   // root.
871   if (IsOutermostSVGSVGElement())
872     return;
873 
874   // Save the next parent to dispatch to in case dispatching the event mutates
875   // the tree.
876   Element* parent = ParentOrShadowHostElement();
877   if (!SendSVGLoadEventIfPossible())
878     return;
879 
880   // If document/window 'load' has been sent already, then only deliver to
881   // the element in question.
882   if (GetDocument().LoadEventFinished())
883     return;
884 
885   auto* svg_element = DynamicTo<SVGElement>(parent);
886   if (!svg_element)
887     return;
888 
889   svg_element->SendSVGLoadEventToSelfAndAncestorChainIfPossible();
890 }
891 
AttributeChanged(const AttributeModificationParams & params)892 void SVGElement::AttributeChanged(const AttributeModificationParams& params) {
893   Element::AttributeChanged(params);
894 
895   if (params.name == html_names::kIdAttr) {
896     RebuildAllIncomingReferences();
897     InvalidateInstances();
898     return;
899   }
900 
901   // Changes to the style attribute are processed lazily (see
902   // Element::getAttribute() and related methods), so we don't want changes to
903   // the style attribute to result in extra work here.
904   if (params.name == html_names::kStyleAttr)
905     return;
906 
907   SvgAttributeChanged(params.name);
908   UpdateWebAnimatedAttributeOnBaseValChange(params.name);
909 }
910 
SvgAttributeChanged(const QualifiedName & attr_name)911 void SVGElement::SvgAttributeChanged(const QualifiedName& attr_name) {
912   CSSPropertyID prop_id = SVGElement::CssPropertyIdForSVGAttributeName(
913       GetExecutionContext(), attr_name);
914   if (prop_id > CSSPropertyID::kInvalid) {
915     InvalidateInstances();
916     return;
917   }
918 
919   if (attr_name == html_names::kClassAttr) {
920     ClassAttributeChanged(AtomicString(class_name_->CurrentValue()->Value()));
921     InvalidateInstances();
922     return;
923   }
924 }
925 
BaseValueChanged(const SVGAnimatedPropertyBase & animated_property)926 void SVGElement::BaseValueChanged(
927     const SVGAnimatedPropertyBase& animated_property) {
928   const QualifiedName& attribute = animated_property.AttributeName();
929   EnsureUniqueElementData().SetSvgAttributesAreDirty(true);
930   SvgAttributeChanged(attribute);
931   if (class_name_ == &animated_property) {
932     UpdateClassList(g_null_atom,
933                     AtomicString(class_name_->BaseValue()->Value()));
934   }
935   UpdateWebAnimatedAttributeOnBaseValChange(attribute);
936 }
937 
UpdateWebAnimatedAttributeOnBaseValChange(const QualifiedName & attribute)938 void SVGElement::UpdateWebAnimatedAttributeOnBaseValChange(
939     const QualifiedName& attribute) {
940   if (!HasSVGRareData())
941     return;
942   const auto& animated_attributes = SvgRareData()->WebAnimatedAttributes();
943   if (animated_attributes.IsEmpty() || !animated_attributes.Contains(attribute))
944     return;
945   // TODO(alancutter): Only mark attributes as dirty if their animation depends
946   // on the underlying value.
947   SvgRareData()->SetWebAnimatedAttributesDirty(true);
948   EnsureAttributeAnimValUpdated();
949 }
950 
EnsureAttributeAnimValUpdated()951 void SVGElement::EnsureAttributeAnimValUpdated() {
952   if (!RuntimeEnabledFeatures::WebAnimationsSVGEnabled())
953     return;
954 
955   if ((HasSVGRareData() && SvgRareData()->WebAnimatedAttributesDirty()) ||
956       (GetElementAnimations() &&
957        GetDocument().GetDocumentAnimations().NeedsAnimationTimingUpdate())) {
958     GetDocument().GetDocumentAnimations().UpdateAnimationTimingIfNeeded();
959     ApplyActiveWebAnimations();
960   }
961 }
962 
SynchronizeSVGAttribute(const QualifiedName & name) const963 void SVGElement::SynchronizeSVGAttribute(const QualifiedName& name) const {
964   DCHECK(GetElementData());
965   DCHECK(GetElementData()->svg_attributes_are_dirty());
966   if (name == AnyQName()) {
967     for (SVGAnimatedPropertyBase* property :
968          attribute_to_property_map_.Values()) {
969       if (property->NeedsSynchronizeAttribute())
970         property->SynchronizeAttribute();
971     }
972     GetElementData()->SetSvgAttributesAreDirty(false);
973   } else {
974     SVGAnimatedPropertyBase* property = PropertyFromAttribute(name);
975     if (property && property->NeedsSynchronizeAttribute())
976       property->SynchronizeAttribute();
977   }
978 }
979 
CollectStyleForAnimatedPresentationAttributes(MutableCSSPropertyValueSet * style)980 void SVGElement::CollectStyleForAnimatedPresentationAttributes(
981     MutableCSSPropertyValueSet* style) {
982   // TODO(fs): This re-applies all animating attributes that are also
983   // presentation attributes. The precise predicate that we want is animated
984   // attributes that are presentation attributes and do not have a content
985   // attribute.
986   // That last bit ("do not have a content attribute") would mean a linear
987   // search of the attribute collection per property.
988   // Maybe reversing the order of operations would be preferable here (i.e
989   // collect style for animating attributes first, stashing which in a map, and
990   // then selectively collecting the rest of the presentation attributes).
991   // Maintaining the presentation attribute style "manually" also seems like a
992   // reasonable scheme since that means we can avoid reparsing the presentation
993   // attributes that didn't change.
994   for (SVGAnimatedPropertyBase* property :
995        attribute_to_property_map_.Values()) {
996     if (!property->HasPresentationAttributeMapping() ||
997         !property->IsAnimating())
998       continue;
999     CollectStyleForPresentationAttribute(property->AttributeName(),
1000                                          g_empty_atom, style);
1001   }
1002 }
1003 
CustomStyleForLayoutObject()1004 scoped_refptr<ComputedStyle> SVGElement::CustomStyleForLayoutObject() {
1005   SVGElement* corresponding_element = CorrespondingElement();
1006   if (!corresponding_element)
1007     return GetDocument().GetStyleResolver().StyleForElement(this);
1008 
1009   const ComputedStyle* style = nullptr;
1010   if (Element* parent = ParentOrShadowHostElement())
1011     style = parent->GetComputedStyle();
1012 
1013   return GetDocument().GetStyleResolver().StyleForElement(corresponding_element,
1014                                                           style, style);
1015 }
1016 
LayoutObjectIsNeeded(const ComputedStyle & style) const1017 bool SVGElement::LayoutObjectIsNeeded(const ComputedStyle& style) const {
1018   return IsValid() && HasSVGParent() && Element::LayoutObjectIsNeeded(style);
1019 }
1020 
HasSVGParent() const1021 bool SVGElement::HasSVGParent() const {
1022   Element* parent = FlatTreeTraversal::ParentElement(*this);
1023   return parent && parent->IsSVGElement();
1024 }
1025 
AnimatedSMILStyleProperties() const1026 MutableCSSPropertyValueSet* SVGElement::AnimatedSMILStyleProperties() const {
1027   if (HasSVGRareData())
1028     return SvgRareData()->AnimatedSMILStyleProperties();
1029   return nullptr;
1030 }
1031 
EnsureAnimatedSMILStyleProperties()1032 MutableCSSPropertyValueSet* SVGElement::EnsureAnimatedSMILStyleProperties() {
1033   return EnsureSVGRareData()->EnsureAnimatedSMILStyleProperties();
1034 }
1035 
BaseComputedStyleForSMIL()1036 const ComputedStyle* SVGElement::BaseComputedStyleForSMIL() {
1037   if (!HasSVGRareData())
1038     return EnsureComputedStyle();
1039   const ComputedStyle* parent_style = nullptr;
1040   if (ContainerNode* parent = LayoutTreeBuilderTraversal::Parent(*this))
1041     parent_style = parent->EnsureComputedStyle();
1042   return SvgRareData()->OverrideComputedStyle(this, parent_style);
1043 }
1044 
HasFocusEventListeners() const1045 bool SVGElement::HasFocusEventListeners() const {
1046   return HasEventListeners(event_type_names::kFocusin) ||
1047          HasEventListeners(event_type_names::kFocusout) ||
1048          HasEventListeners(event_type_names::kFocus) ||
1049          HasEventListeners(event_type_names::kBlur);
1050 }
1051 
MarkForLayoutAndParentResourceInvalidation(LayoutObject & layout_object)1052 void SVGElement::MarkForLayoutAndParentResourceInvalidation(
1053     LayoutObject& layout_object) {
1054   LayoutSVGResourceContainer::MarkForLayoutAndParentResourceInvalidation(
1055       layout_object, true);
1056 }
1057 
InvalidateInstances()1058 void SVGElement::InvalidateInstances() {
1059   if (InstanceUpdatesBlocked())
1060     return;
1061 
1062   const HeapHashSet<WeakMember<SVGElement>>& set = InstancesForElement();
1063   if (set.IsEmpty())
1064     return;
1065 
1066   // Mark all use elements referencing 'element' for rebuilding
1067   for (SVGElement* instance : set) {
1068     instance->SetCorrespondingElement(nullptr);
1069 
1070     if (SVGUseElement* element = instance->GeneratingUseElement()) {
1071       DCHECK(element->isConnected());
1072       element->InvalidateShadowTree();
1073     }
1074   }
1075 
1076   SvgRareData()->ElementInstances().clear();
1077 }
1078 
SetNeedsStyleRecalcForInstances(StyleChangeType change_type,const StyleChangeReasonForTracing & reason)1079 void SVGElement::SetNeedsStyleRecalcForInstances(
1080     StyleChangeType change_type,
1081     const StyleChangeReasonForTracing& reason) {
1082   const HeapHashSet<WeakMember<SVGElement>>& set = InstancesForElement();
1083   if (set.IsEmpty())
1084     return;
1085 
1086   for (SVGElement* instance : set)
1087     instance->SetNeedsStyleRecalc(change_type, reason);
1088 }
1089 
InstanceUpdateBlocker(SVGElement * target_element)1090 SVGElement::InstanceUpdateBlocker::InstanceUpdateBlocker(
1091     SVGElement* target_element)
1092     : target_element_(target_element) {
1093   if (target_element_)
1094     target_element_->SetInstanceUpdatesBlocked(true);
1095 }
1096 
~InstanceUpdateBlocker()1097 SVGElement::InstanceUpdateBlocker::~InstanceUpdateBlocker() {
1098   if (target_element_)
1099     target_element_->SetInstanceUpdatesBlocked(false);
1100 }
1101 
1102 #if DCHECK_IS_ON()
IsAnimatableAttribute(const QualifiedName & name) const1103 bool SVGElement::IsAnimatableAttribute(const QualifiedName& name) const {
1104   // This static is atomically initialized to dodge a warning about
1105   // a race when dumping debug data for a layer.
1106   DEFINE_THREAD_SAFE_STATIC_LOCAL(HashSet<QualifiedName>, animatable_attributes,
1107                                   ({
1108                                       svg_names::kAmplitudeAttr,
1109                                       svg_names::kAzimuthAttr,
1110                                       svg_names::kBaseFrequencyAttr,
1111                                       svg_names::kBiasAttr,
1112                                       svg_names::kClipPathUnitsAttr,
1113                                       svg_names::kCxAttr,
1114                                       svg_names::kCyAttr,
1115                                       svg_names::kDiffuseConstantAttr,
1116                                       svg_names::kDivisorAttr,
1117                                       svg_names::kDxAttr,
1118                                       svg_names::kDyAttr,
1119                                       svg_names::kEdgeModeAttr,
1120                                       svg_names::kElevationAttr,
1121                                       svg_names::kExponentAttr,
1122                                       svg_names::kFilterUnitsAttr,
1123                                       svg_names::kFxAttr,
1124                                       svg_names::kFyAttr,
1125                                       svg_names::kGradientTransformAttr,
1126                                       svg_names::kGradientUnitsAttr,
1127                                       svg_names::kHeightAttr,
1128                                       svg_names::kHrefAttr,
1129                                       svg_names::kIn2Attr,
1130                                       svg_names::kInAttr,
1131                                       svg_names::kInterceptAttr,
1132                                       svg_names::kK1Attr,
1133                                       svg_names::kK2Attr,
1134                                       svg_names::kK3Attr,
1135                                       svg_names::kK4Attr,
1136                                       svg_names::kKernelMatrixAttr,
1137                                       svg_names::kKernelUnitLengthAttr,
1138                                       svg_names::kLengthAdjustAttr,
1139                                       svg_names::kLimitingConeAngleAttr,
1140                                       svg_names::kMarkerHeightAttr,
1141                                       svg_names::kMarkerUnitsAttr,
1142                                       svg_names::kMarkerWidthAttr,
1143                                       svg_names::kMaskContentUnitsAttr,
1144                                       svg_names::kMaskUnitsAttr,
1145                                       svg_names::kMethodAttr,
1146                                       svg_names::kModeAttr,
1147                                       svg_names::kNumOctavesAttr,
1148                                       svg_names::kOffsetAttr,
1149                                       svg_names::kOperatorAttr,
1150                                       svg_names::kOrderAttr,
1151                                       svg_names::kOrientAttr,
1152                                       svg_names::kPathLengthAttr,
1153                                       svg_names::kPatternContentUnitsAttr,
1154                                       svg_names::kPatternTransformAttr,
1155                                       svg_names::kPatternUnitsAttr,
1156                                       svg_names::kPointsAtXAttr,
1157                                       svg_names::kPointsAtYAttr,
1158                                       svg_names::kPointsAtZAttr,
1159                                       svg_names::kPreserveAlphaAttr,
1160                                       svg_names::kPreserveAspectRatioAttr,
1161                                       svg_names::kPrimitiveUnitsAttr,
1162                                       svg_names::kRadiusAttr,
1163                                       svg_names::kRAttr,
1164                                       svg_names::kRefXAttr,
1165                                       svg_names::kRefYAttr,
1166                                       svg_names::kResultAttr,
1167                                       svg_names::kRotateAttr,
1168                                       svg_names::kRxAttr,
1169                                       svg_names::kRyAttr,
1170                                       svg_names::kScaleAttr,
1171                                       svg_names::kSeedAttr,
1172                                       svg_names::kSlopeAttr,
1173                                       svg_names::kSpacingAttr,
1174                                       svg_names::kSpecularConstantAttr,
1175                                       svg_names::kSpecularExponentAttr,
1176                                       svg_names::kSpreadMethodAttr,
1177                                       svg_names::kStartOffsetAttr,
1178                                       svg_names::kStdDeviationAttr,
1179                                       svg_names::kStitchTilesAttr,
1180                                       svg_names::kSurfaceScaleAttr,
1181                                       svg_names::kTableValuesAttr,
1182                                       svg_names::kTargetAttr,
1183                                       svg_names::kTargetXAttr,
1184                                       svg_names::kTargetYAttr,
1185                                       svg_names::kTransformAttr,
1186                                       svg_names::kTypeAttr,
1187                                       svg_names::kValuesAttr,
1188                                       svg_names::kViewBoxAttr,
1189                                       svg_names::kWidthAttr,
1190                                       svg_names::kX1Attr,
1191                                       svg_names::kX2Attr,
1192                                       svg_names::kXAttr,
1193                                       svg_names::kXChannelSelectorAttr,
1194                                       svg_names::kY1Attr,
1195                                       svg_names::kY2Attr,
1196                                       svg_names::kYAttr,
1197                                       svg_names::kYChannelSelectorAttr,
1198                                       svg_names::kZAttr,
1199                                   }));
1200 
1201   if (name == html_names::kClassAttr)
1202     return true;
1203 
1204   return animatable_attributes.Contains(name);
1205 }
1206 #endif  // DCHECK_IS_ON()
1207 
SetOfIncomingReferences() const1208 SVGElementSet* SVGElement::SetOfIncomingReferences() const {
1209   if (!HasSVGRareData())
1210     return nullptr;
1211   return &SvgRareData()->IncomingReferences();
1212 }
1213 
AddReferenceTo(SVGElement * target_element)1214 void SVGElement::AddReferenceTo(SVGElement* target_element) {
1215   DCHECK(target_element);
1216 
1217   EnsureSVGRareData()->OutgoingReferences().insert(target_element);
1218   target_element->EnsureSVGRareData()->IncomingReferences().insert(this);
1219 }
1220 
GetDependencyTraversalVisitedSet()1221 SVGElementSet& SVGElement::GetDependencyTraversalVisitedSet() {
1222   // This strong reference is safe, as it is guaranteed that this set will be
1223   // emptied at the end of recursion in NotifyIncomingReferences.
1224   DEFINE_STATIC_LOCAL(Persistent<SVGElementSet>, invalidating_dependencies,
1225                       (MakeGarbageCollected<SVGElementSet>()));
1226   return *invalidating_dependencies;
1227 }
1228 
RebuildAllIncomingReferences()1229 void SVGElement::RebuildAllIncomingReferences() {
1230   if (!HasSVGRareData())
1231     return;
1232 
1233   const SVGElementSet& incoming_references =
1234       SvgRareData()->IncomingReferences();
1235 
1236   // Iterate on a snapshot as |incomingReferences| may be altered inside loop.
1237   HeapVector<Member<SVGElement>> incoming_references_snapshot;
1238   CopyToVector(incoming_references, incoming_references_snapshot);
1239 
1240   // Force rebuilding the |sourceElement| so it knows about this change.
1241   for (SVGElement* source_element : incoming_references_snapshot) {
1242     // Before rebuilding |sourceElement| ensure it was not removed from under
1243     // us.
1244     if (incoming_references.Contains(source_element))
1245       source_element->SvgAttributeChanged(svg_names::kHrefAttr);
1246   }
1247 }
1248 
RemoveAllIncomingReferences()1249 void SVGElement::RemoveAllIncomingReferences() {
1250   if (!HasSVGRareData())
1251     return;
1252 
1253   SVGElementSet& incoming_references = SvgRareData()->IncomingReferences();
1254   for (SVGElement* source_element : incoming_references) {
1255     DCHECK(source_element->HasSVGRareData());
1256     source_element->EnsureSVGRareData()->OutgoingReferences().erase(this);
1257   }
1258   incoming_references.clear();
1259 }
1260 
RemoveAllOutgoingReferences()1261 void SVGElement::RemoveAllOutgoingReferences() {
1262   if (!HasSVGRareData())
1263     return;
1264 
1265   SVGElementSet& outgoing_references = SvgRareData()->OutgoingReferences();
1266   for (SVGElement* target_element : outgoing_references) {
1267     DCHECK(target_element->HasSVGRareData());
1268     target_element->EnsureSVGRareData()->IncomingReferences().erase(this);
1269   }
1270   outgoing_references.clear();
1271 }
1272 
GetSVGResourceClient()1273 SVGElementResourceClient* SVGElement::GetSVGResourceClient() {
1274   if (!HasSVGRareData())
1275     return nullptr;
1276   return SvgRareData()->GetSVGResourceClient();
1277 }
1278 
EnsureSVGResourceClient()1279 SVGElementResourceClient& SVGElement::EnsureSVGResourceClient() {
1280   return EnsureSVGRareData()->EnsureSVGResourceClient(this);
1281 }
1282 
Trace(Visitor * visitor) const1283 void SVGElement::Trace(Visitor* visitor) const {
1284   visitor->Trace(elements_with_relative_lengths_);
1285   visitor->Trace(attribute_to_property_map_);
1286   visitor->Trace(svg_rare_data_);
1287   visitor->Trace(class_name_);
1288   Element::Trace(visitor);
1289 }
1290 
AccessKeyAction(bool send_mouse_events)1291 void SVGElement::AccessKeyAction(bool send_mouse_events) {
1292   DispatchSimulatedClick(
1293       nullptr, send_mouse_events ? kSendMouseUpDownEvents : kSendNoEvents);
1294 }
1295 
1296 }  // namespace blink
1297