1/*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Peter Kelly (pmk@post.com)
5 * (C) 2001 Dirk Mueller (mueller@kde.org)
6 * Copyright (C) 2003-2016 Apple Inc. All rights reserved.
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 *
23 */
24
25#ifndef Element_h
26#define Element_h
27
28#include "AXTextStateChangeIntent.h"
29#include "Document.h"
30#include "ElementData.h"
31#include "HTMLNames.h"
32#include "RegionOversetState.h"
33#include "ScrollTypes.h"
34#include "SimulatedClickOptions.h"
35#include "StyleChange.h"
36
37namespace WebCore {
38
39class ClientRect;
40class ClientRectList;
41class DatasetDOMStringMap;
42class Dictionary;
43class DOMTokenList;
44class ElementRareData;
45class HTMLDocument;
46class IntSize;
47class Locale;
48class PlatformKeyboardEvent;
49class PlatformMouseEvent;
50class PlatformWheelEvent;
51class PseudoElement;
52class RenderNamedFlowFragment;
53class RenderTreePosition;
54class ShadowRoot;
55
56enum SpellcheckAttributeState {
57 SpellcheckAttributeTrue,
58 SpellcheckAttributeFalse,
59 SpellcheckAttributeDefault
60};
61
62class Element : public ContainerNode {
63public:
64 static Ref<Element> create(const QualifiedName&, Document&);
65 virtual ~Element();
66
67 WEBCORE_EXPORT bool hasAttribute(const QualifiedName&) const;
68 WEBCORE_EXPORT const AtomicString& getAttribute(const QualifiedName&) const;
69 WEBCORE_EXPORT void setAttribute(const QualifiedName&, const AtomicString& value);
70 void setAttributeWithoutSynchronization(const QualifiedName&, const AtomicString& value);
71 void setSynchronizedLazyAttribute(const QualifiedName&, const AtomicString& value);
72 bool removeAttribute(const QualifiedName&);
73 Vector<String> getAttributeNames() const;
74
75 // Typed getters and setters for language bindings.
76 int getIntegralAttribute(const QualifiedName& attributeName) const;
77 void setIntegralAttribute(const QualifiedName& attributeName, int value);
78 unsigned getUnsignedIntegralAttribute(const QualifiedName& attributeName) const;
79 void setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value);
80
81 // Call this to get the value of an attribute that is known not to be the style
82 // attribute or one of the SVG animatable attributes.
83 bool fastHasAttribute(const QualifiedName&) const;
84 const AtomicString& fastGetAttribute(const QualifiedName&) const;
85#ifndef NDEBUG
86 WEBCORE_EXPORT bool fastAttributeLookupAllowed(const QualifiedName&) const;
87#endif
88
89#ifdef DUMP_NODE_STATISTICS
90 bool hasNamedNodeMap() const;
91#endif
92 bool hasAttributes() const;
93 // This variant will not update the potentially invalid attributes. To be used when not interested
94 // in style attribute or one of the SVG animation attributes.
95 bool hasAttributesWithoutUpdate() const;
96
97 WEBCORE_EXPORT bool hasAttribute(const AtomicString& name) const;
98 bool hasAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const;
99
100 WEBCORE_EXPORT const AtomicString& getAttribute(const AtomicString& name) const;
101 const AtomicString& getAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const;
102
103 WEBCORE_EXPORT void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode&);
104 static bool parseAttributeName(QualifiedName&, const AtomicString& namespaceURI, const AtomicString& qualifiedName, ExceptionCode&);
105 void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode&);
106
107 const AtomicString& getIdAttribute() const;
108 void setIdAttribute(const AtomicString&);
109
110 const AtomicString& getNameAttribute() const;
111
112 // Call this to get the value of the id attribute for style resolution purposes.
113 // The value will already be lowercased if the document is in compatibility mode,
114 // so this function is not suitable for non-style uses.
115 const AtomicString& idForStyleResolution() const;
116
117 // Internal methods that assume the existence of attribute storage, one should use hasAttributes()
118 // before calling them.
119 AttributeIteratorAccessor attributesIterator() const { return elementData()->attributesIterator(); }
120 unsigned attributeCount() const;
121 const Attribute& attributeAt(unsigned index) const;
122 const Attribute* findAttributeByName(const QualifiedName&) const;
123 unsigned findAttributeIndexByName(const QualifiedName& name) const { return elementData()->findAttributeIndexByName(name); }
124 unsigned findAttributeIndexByName(const AtomicString& name, bool shouldIgnoreAttributeCase) const { return elementData()->findAttributeIndexByName(name, shouldIgnoreAttributeCase); }
125
126 void scrollIntoView(bool alignToTop = true);
127 void scrollIntoViewIfNeeded(bool centerIfNeeded = true);
128 WEBCORE_EXPORT void scrollIntoViewIfNotVisible(bool centerIfNotVisible = true);
129
130 void scrollByLines(int lines);
131 void scrollByPages(int pages);
132
133 double offsetLeft();
134 double offsetTop();
135 double offsetWidth();
136 double offsetHeight();
137
138 bool mayCauseRepaintInsideViewport(const IntRect* visibleRect = nullptr) const;
139
140 // FIXME: Replace uses of offsetParent in the platform with calls
141 // to the render layer and merge bindingsOffsetParent and offsetParent.
142 Element* bindingsOffsetParent();
143
144 const Element* rootElement() const;
145
146 Element* offsetParent();
147 double clientLeft();
148 double clientTop();
149 double clientWidth();
150 double clientHeight();
151 virtual int scrollLeft();
152 virtual int scrollTop();
153 virtual void setScrollLeft(int);
154 virtual void setScrollTop(int);
155 virtual int scrollWidth();
156 virtual int scrollHeight();
157
158 WEBCORE_EXPORT IntRect boundsInRootViewSpace();
159
160 Ref<ClientRectList> getClientRects();
161 Ref<ClientRect> getBoundingClientRect();
162
163 // Returns the absolute bounding box translated into client coordinates.
164 WEBCORE_EXPORT IntRect clientRect() const;
165 // Returns the absolute bounding box translated into screen coordinates.
166 WEBCORE_EXPORT IntRect screenRect() const;
167
168 bool removeAttribute(const AtomicString& name);
169 bool removeAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName);
170
171 RefPtr<Attr> detachAttribute(unsigned index);
172
173 RefPtr<Attr> getAttributeNode(const AtomicString& name);
174 RefPtr<Attr> getAttributeNodeNS(const AtomicString& namespaceURI, const AtomicString& localName);
175 RefPtr<Attr> setAttributeNode(Attr*, ExceptionCode&);
176 RefPtr<Attr> setAttributeNodeNS(Attr*, ExceptionCode&);
177 RefPtr<Attr> removeAttributeNode(Attr*, ExceptionCode&);
178
179 RefPtr<Attr> attrIfExists(const QualifiedName&);
180 RefPtr<Attr> attrIfExists(const AtomicString& localName, bool shouldIgnoreAttributeCase);
181 RefPtr<Attr> ensureAttr(const QualifiedName&);
182
183 const Vector<RefPtr<Attr>>& attrNodeList();
184
185 virtual CSSStyleDeclaration* cssomStyle();
186
187 const QualifiedName& tagQName() const { return m_tagName; }
188#if ENABLE(CSS_SELECTOR_JIT)
189 static ptrdiff_t tagQNameMemoryOffset() { return OBJECT_OFFSETOF(Element, m_tagName); }
190#endif // ENABLE(CSS_SELECTOR_JIT)
191 String tagName() const { return nodeName(); }
192 bool hasTagName(const QualifiedName& tagName) const { return m_tagName.matches(tagName); }
193 bool hasTagName(const HTMLQualifiedName& tagName) const { return ContainerNode::hasTagName(tagName); }
194 bool hasTagName(const MathMLQualifiedName& tagName) const { return ContainerNode::hasTagName(tagName); }
195 bool hasTagName(const SVGQualifiedName& tagName) const { return ContainerNode::hasTagName(tagName); }
196
197 // A fast function for checking the local name against another atomic string.
198 bool hasLocalName(const AtomicString& other) const { return m_tagName.localName() == other; }
199
200 virtual const AtomicString& localName() const override final { return m_tagName.localName(); }
201 virtual const AtomicString& prefix() const override final { return m_tagName.prefix(); }
202 virtual const AtomicString& namespaceURI() const override final { return m_tagName.namespaceURI(); }
203
204 virtual String nodeName() const override;
205
206 Ref<Element> cloneElementWithChildren(Document&);
207 Ref<Element> cloneElementWithoutChildren(Document&);
208
209 void normalizeAttributes();
210 String nodeNamePreservingCase() const;
211
212 void setBooleanAttribute(const QualifiedName& name, bool);
213
214 // For exposing to DOM only.
215 NamedNodeMap& attributes() const;
216
217 enum AttributeModificationReason {
218 ModifiedDirectly,
219 ModifiedByCloning
220 };
221
222 // This method is called whenever an attribute is added, changed or removed.
223 virtual void attributeChanged(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue, AttributeModificationReason = ModifiedDirectly);
224 virtual void parseAttribute(const QualifiedName&, const AtomicString&) { }
225
226 // Only called by the parser immediately after element construction.
227 void parserSetAttributes(const Vector<Attribute>&);
228
229 // Remove attributes that might introduce scripting from the vector leaving the element unchanged.
230 void stripScriptingAttributes(Vector<Attribute>&) const;
231
232 const ElementData* elementData() const { return m_elementData.get(); }
233 static ptrdiff_t elementDataMemoryOffset() { return OBJECT_OFFSETOF(Element, m_elementData); }
234 UniqueElementData& ensureUniqueElementData();
235
236 void synchronizeAllAttributes() const;
237
238 // Clones attributes only.
239 void cloneAttributesFromElement(const Element&);
240
241 // Clones all attribute-derived data, including subclass specifics (through copyNonAttributeProperties.)
242 void cloneDataFromElement(const Element&);
243
244 bool hasEquivalentAttributes(const Element* other) const;
245
246 virtual void copyNonAttributePropertiesFromElement(const Element&) { }
247
248 virtual RenderPtr<RenderElement> createElementRenderer(Ref<RenderStyle>&&, const RenderTreePosition&);
249 virtual bool rendererIsNeeded(const RenderStyle&);
250
251 WEBCORE_EXPORT ShadowRoot* shadowRoot() const;
252 WEBCORE_EXPORT RefPtr<ShadowRoot> createShadowRoot(ExceptionCode&);
253
254 ShadowRoot* shadowRootForBindings(JSC::ExecState&) const;
255 RefPtr<ShadowRoot> attachShadow(const Dictionary&, ExceptionCode&);
256
257 ShadowRoot* userAgentShadowRoot() const;
258 WEBCORE_EXPORT ShadowRoot& ensureUserAgentShadowRoot();
259
260 // FIXME: this should not be virtual, do not override this.
261 virtual const AtomicString& shadowPseudoId() const;
262
263 bool inActiveChain() const { return isUserActionElement() && isUserActionElementInActiveChain(); }
264 bool active() const { return isUserActionElement() && isUserActionElementActive(); }
265 bool hovered() const { return isUserActionElement() && isUserActionElementHovered(); }
266 bool focused() const { return isUserActionElement() && isUserActionElementFocused(); }
267
268 virtual void setActive(bool flag = true, bool pause = false);
269 virtual void setHovered(bool flag = true);
270 virtual void setFocus(bool flag);
271
272 virtual bool supportsFocus() const;
273 virtual bool isFocusable() const;
274 virtual bool isKeyboardFocusable(KeyboardEvent*) const;
275 virtual bool isMouseFocusable() const;
276
277 virtual bool shouldUseInputMethod();
278
279 virtual short tabIndex() const;
280 void setTabIndex(int);
281 virtual Element* focusDelegate();
282
283 virtual RenderStyle* computedStyle(PseudoId = NOPSEUDO) override;
284
285 bool needsStyleInvalidation() const;
286
287 // Methods for indicating the style is affected by dynamic updates (e.g., children changing, our position changing in our sibling list, etc.)
288 bool styleAffectedByEmpty() const { return hasRareData() && rareDataStyleAffectedByEmpty(); }
289 bool childrenAffectedByHover() const { return getFlag(ChildrenAffectedByHoverRulesFlag); }
290 bool childrenAffectedByActive() const { return hasRareData() && rareDataChildrenAffectedByActive(); }
291 bool childrenAffectedByDrag() const { return hasRareData() && rareDataChildrenAffectedByDrag(); }
292 bool childrenAffectedByFirstChildRules() const { return getFlag(ChildrenAffectedByFirstChildRulesFlag); }
293 bool childrenAffectedByLastChildRules() const { return getFlag(ChildrenAffectedByLastChildRulesFlag); }
294 bool childrenAffectedByBackwardPositionalRules() const { return hasRareData() && rareDataChildrenAffectedByBackwardPositionalRules(); }
295 bool childrenAffectedByPropertyBasedBackwardPositionalRules() const { return hasRareData() && rareDataChildrenAffectedByPropertyBasedBackwardPositionalRules(); }
296 bool affectsNextSiblingElementStyle() const { return getFlag(AffectsNextSiblingElementStyle); }
297 unsigned childIndex() const { return hasRareData() ? rareDataChildIndex() : 0; }
298
299 bool hasFlagsSetDuringStylingOfChildren() const;
300
301 void setStyleAffectedByEmpty();
302 void setChildrenAffectedByHover() { setFlag(ChildrenAffectedByHoverRulesFlag); }
303 void setChildrenAffectedByActive();
304 void setChildrenAffectedByDrag();
305 void setChildrenAffectedByFirstChildRules() { setFlag(ChildrenAffectedByFirstChildRulesFlag); }
306 void setChildrenAffectedByLastChildRules() { setFlag(ChildrenAffectedByLastChildRulesFlag); }
307 void setChildrenAffectedByBackwardPositionalRules();
308 void setChildrenAffectedByPropertyBasedBackwardPositionalRules();
309 void setAffectsNextSiblingElementStyle() { setFlag(AffectsNextSiblingElementStyle); }
310 void setStyleIsAffectedByPreviousSibling() { setFlag(StyleIsAffectedByPreviousSibling); }
311 void setChildIndex(unsigned);
312
313 void setRegionOversetState(RegionOversetState);
314 RegionOversetState regionOversetState() const;
315
316 AtomicString computeInheritedLanguage() const;
317 Locale& locale() const;
318
319 virtual void accessKeyAction(bool /*sendToAnyEvent*/) { }
320
321 virtual bool isURLAttribute(const Attribute&) const { return false; }
322 virtual bool attributeContainsURL(const Attribute& attribute) const { return isURLAttribute(attribute); }
323 virtual String completeURLsInAttributeValue(const URL& base, const Attribute&) const;
324 virtual bool isHTMLContentAttribute(const Attribute&) const { return false; }
325
326 WEBCORE_EXPORT URL getURLAttribute(const QualifiedName&) const;
327 URL getNonEmptyURLAttribute(const QualifiedName&) const;
328
329 virtual const AtomicString& imageSourceURL() const;
330 virtual String target() const { return String(); }
331
332 static AXTextStateChangeIntent defaultFocusTextStateChangeIntent() { return AXTextStateChangeIntent(AXTextStateChangeTypeSelectionMove, AXTextSelection { AXTextSelectionDirectionDiscontiguous, AXTextSelectionGranularityUnknown, true }); }
333 void updateFocusAppearanceAfterAttachIfNeeded();
334 virtual void focus(bool restorePreviousSelection = true, FocusDirection = FocusDirectionNone);
335 virtual void updateFocusAppearance(SelectionRestorationMode, SelectionRevealMode = SelectionRevealMode::Reveal);
336 virtual void blur();
337
338 String innerHTML() const;
339 String outerHTML() const;
340 void setInnerHTML(const String&, ExceptionCode&);
341 void setOuterHTML(const String&, ExceptionCode&);
342 WEBCORE_EXPORT String innerText();
343 String outerText();
344
345 virtual String title() const;
346
347 const AtomicString& pseudo() const;
348 WEBCORE_EXPORT void setPseudo(const AtomicString&);
349
350 LayoutSize minimumSizeForResizing() const;
351 void setMinimumSizeForResizing(const LayoutSize&);
352
353 // Use Document::registerForDocumentActivationCallbacks() to subscribe to these
354 virtual void prepareForDocumentSuspension() { }
355 virtual void resumeFromDocumentSuspension() { }
356
357 // Use Document::registerForMediaVolumeCallbacks() to subscribe to this
358 virtual void mediaVolumeDidChange() { }
359
360 // Use Document::registerForPrivateBrowsingStateChangedCallbacks() to subscribe to this.
361 virtual void privateBrowsingStateDidChange() { }
362
363 virtual void didBecomeFullscreenElement() { }
364 virtual void willStopBeingFullscreenElement() { }
365
366 // Use Document::registerForVisibilityStateChangedCallbacks() to subscribe to this.
367 virtual void visibilityStateChanged() { }
368
369#if ENABLE(VIDEO_TRACK)
370 virtual void captionPreferencesChanged() { }
371#endif
372
373 bool isFinishedParsingChildren() const { return isParsingChildrenFinished(); }
374 virtual void finishParsingChildren() override;
375 virtual void beginParsingChildren() override final;
376
377 WEBCORE_EXPORT PseudoElement* beforePseudoElement() const;
378 WEBCORE_EXPORT PseudoElement* afterPseudoElement() const;
379 bool childNeedsShadowWalker() const;
380 void didShadowTreeAwareChildrenChange();
381
382 virtual bool matchesReadWritePseudoClass() const;
383 bool matches(const String& selectors, ExceptionCode&);
384 Element* closest(const String& selectors, ExceptionCode&);
385 virtual bool shouldAppearIndeterminate() const;
386
387 DOMTokenList& classList();
388
389 DatasetDOMStringMap& dataset();
390
391#if ENABLE(VIDEO)
392 virtual bool isMediaElement() const { return false; }
393#endif
394
395 virtual bool matchesValidPseudoClass() const { return false; }
396 virtual bool matchesInvalidPseudoClass() const { return false; }
397 virtual bool isFormControlElement() const { return false; }
398 virtual bool isSpinButtonElement() const { return false; }
399 virtual bool isTextFormControl() const { return false; }
400 virtual bool isOptionalFormControl() const { return false; }
401 virtual bool isRequiredFormControl() const { return false; }
402 virtual bool isDefaultButtonForForm() const { return false; }
403 virtual bool isInRange() const { return false; }
404 virtual bool isOutOfRange() const { return false; }
405 virtual bool isFrameElementBase() const { return false; }
406
407 virtual bool canContainRangeEndPoint() const override;
408
409 // Used for disabled form elements; if true, prevents mouse events from being dispatched
410 // to event listeners, and prevents DOMActivate events from being sent at all.
411 virtual bool isDisabledFormControl() const { return false; }
412
413 virtual bool childShouldCreateRenderer(const Node&) const;
414
415 bool hasPendingResources() const;
416 void setHasPendingResources();
417 void clearHasPendingResources();
418 virtual void buildPendingResource() { };
419
420#if ENABLE(FULLSCREEN_API)
421 enum {
422 ALLOW_KEYBOARD_INPUT = 1 << 0,
423 LEGACY_MOZILLA_REQUEST = 1 << 1,
424 };
425
426 void webkitRequestFullScreen(unsigned short flags);
427 WEBCORE_EXPORT bool containsFullScreenElement() const;
428 void setContainsFullScreenElement(bool);
429 void setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(bool);
430
431 // W3C API
432 void webkitRequestFullscreen();
433#endif
434
435#if ENABLE(POINTER_LOCK)
436 void requestPointerLock();
437#endif
438
439#if ENABLE(INDIE_UI)
440 void setUIActions(const AtomicString&);
441 const AtomicString& UIActions() const;
442#endif
443
444 virtual bool isSpellCheckingEnabled() const;
445
446 RenderNamedFlowFragment* renderNamedFlowFragment() const;
447
448#if ENABLE(CSS_REGIONS)
449 virtual bool shouldMoveToFlowThread(const RenderStyle&) const;
450
451 const AtomicString& webkitRegionOverset() const;
452 Vector<RefPtr<Range>> webkitGetRegionFlowRanges() const;
453#endif
454
455 bool hasID() const;
456 bool hasClass() const;
457 bool hasName() const;
458 const SpaceSplitString& classNames() const;
459
460 IntPoint savedLayerScrollPosition() const;
461 void setSavedLayerScrollPosition(const IntPoint&);
462
463 bool dispatchMouseEvent(const PlatformMouseEvent&, const AtomicString& eventType, int clickCount = 0, Element* relatedTarget = nullptr);
464 bool dispatchWheelEvent(const PlatformWheelEvent&);
465 bool dispatchKeyEvent(const PlatformKeyboardEvent&);
466 void dispatchSimulatedClick(Event* underlyingEvent, SimulatedClickMouseEventOptions = SendNoEvents, SimulatedClickVisualOptions = ShowPressedLook);
467 void dispatchSimulatedClickForBindings(Event* underlyingEvent);
468 void dispatchFocusInEvent(const AtomicString& eventType, RefPtr<Element>&& oldFocusedElement);
469 void dispatchFocusOutEvent(const AtomicString& eventType, RefPtr<Element>&& newFocusedElement);
470 virtual void dispatchFocusEvent(RefPtr<Element>&& oldFocusedElement, FocusDirection);
471 virtual void dispatchBlurEvent(RefPtr<Element>&& newFocusedElement);
472
473 WEBCORE_EXPORT bool dispatchMouseForceWillBegin();
474
475 virtual bool willRecalcStyle(Style::Change);
476 virtual void didRecalcStyle(Style::Change);
477 virtual void willResetComputedStyle();
478 virtual void willAttachRenderers();
479 virtual void didAttachRenderers();
480 virtual void willDetachRenderers();
481 virtual void didDetachRenderers();
482 virtual RefPtr<RenderStyle> customStyleForRenderer(RenderStyle& parentStyle);
483
484 LayoutRect absoluteEventHandlerBounds(bool& includesFixedPositionElements) override;
485
486 void setBeforePseudoElement(Ref<PseudoElement>&&);
487 void setAfterPseudoElement(Ref<PseudoElement>&&);
488 void clearBeforePseudoElement();
489 void clearAfterPseudoElement();
490 void resetComputedStyle();
491 void clearStyleDerivedDataBeforeDetachingRenderer();
492 void clearHoverAndActiveStatusBeforeDetachingRenderer();
493
494 WEBCORE_EXPORT URL absoluteLinkURL() const;
495
496#if ENABLE(TOUCH_EVENTS)
497 virtual bool allowsDoubleTapGesture() const override;
498#endif
499
500 StyleResolver& styleResolver();
501 Ref<RenderStyle> resolveStyle(RenderStyle* parentStyle);
502
503 virtual void isVisibleInViewportChanged() { }
504
505protected:
506 Element(const QualifiedName&, Document&, ConstructionType);
507
508 virtual InsertionNotificationRequest insertedInto(ContainerNode&) override;
509 virtual void removedFrom(ContainerNode&) override;
510 virtual void childrenChanged(const ChildChange&) override;
511 virtual void removeAllEventListeners() override final;
512 virtual void parserDidSetAttributes();
513
514 void clearTabIndexExplicitlyIfNeeded();
515 void setTabIndexExplicitly(short);
516
517 // classAttributeChanged() exists to share code between
518 // parseAttribute (called via setAttribute()) and
519 // svgAttributeChanged (called when element.className.baseValue is set)
520 void classAttributeChanged(const AtomicString& newClassString);
521
522 void addShadowRoot(Ref<ShadowRoot>&&);
523
524 static void mergeWithNextTextNode(Text& node, ExceptionCode&);
525
526private:
527 bool isTextNode() const;
528
529 bool isUserActionElementInActiveChain() const;
530 bool isUserActionElementActive() const;
531 bool isUserActionElementFocused() const;
532 bool isUserActionElementHovered() const;
533
534 virtual void didAddUserAgentShadowRoot(ShadowRoot*) { }
535 virtual bool alwaysCreateUserAgentShadowRoot() const { return false; }
536
537 // FIXME: Remove the need for Attr to call willModifyAttribute/didModifyAttribute.
538 friend class Attr;
539
540 enum SynchronizationOfLazyAttribute { NotInSynchronizationOfLazyAttribute = 0, InSynchronizationOfLazyAttribute };
541
542 void didAddAttribute(const QualifiedName&, const AtomicString&);
543 void willModifyAttribute(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue);
544 void didModifyAttribute(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue);
545 void didRemoveAttribute(const QualifiedName&, const AtomicString& oldValue);
546
547 void synchronizeAttribute(const QualifiedName&) const;
548 void synchronizeAttribute(const AtomicString& localName) const;
549
550 void updateName(const AtomicString& oldName, const AtomicString& newName);
551 void updateNameForTreeScope(TreeScope&, const AtomicString& oldName, const AtomicString& newName);
552 void updateNameForDocument(HTMLDocument&, const AtomicString& oldName, const AtomicString& newName);
553
554 enum class NotifyObservers { No, Yes };
555 void updateId(const AtomicString& oldId, const AtomicString& newId, NotifyObservers = NotifyObservers::Yes);
556 void updateIdForTreeScope(TreeScope&, const AtomicString& oldId, const AtomicString& newId, NotifyObservers = NotifyObservers::Yes);
557
558 enum HTMLDocumentNamedItemMapsUpdatingCondition { AlwaysUpdateHTMLDocumentNamedItemMaps, UpdateHTMLDocumentNamedItemMapsOnlyIfDiffersFromNameAttribute };
559 void updateIdForDocument(HTMLDocument&, const AtomicString& oldId, const AtomicString& newId, HTMLDocumentNamedItemMapsUpdatingCondition);
560 void updateLabel(TreeScope&, const AtomicString& oldForAttributeValue, const AtomicString& newForAttributeValue);
561
562 void scrollByUnits(int units, ScrollGranularity);
563
564 virtual void setPrefix(const AtomicString&, ExceptionCode&) override final;
565 virtual NodeType nodeType() const override final;
566 virtual bool childTypeAllowed(NodeType) const override final;
567
568 void setAttributeInternal(unsigned index, const QualifiedName&, const AtomicString& value, SynchronizationOfLazyAttribute);
569 void addAttributeInternal(const QualifiedName&, const AtomicString& value, SynchronizationOfLazyAttribute);
570 void removeAttributeInternal(unsigned index, SynchronizationOfLazyAttribute);
571
572 LayoutRect absoluteEventBounds(bool& boundsIncludeAllDescendantElements, bool& includesFixedPositionElements);
573 LayoutRect absoluteEventBoundsOfElementAndDescendants(bool& includesFixedPositionElements);
574
575#if ENABLE(TREE_DEBUGGING)
576 virtual void formatForDebugger(char* buffer, unsigned length) const override;
577#endif
578
579 void cancelFocusAppearanceUpdate();
580
581 // cloneNode is private so that non-virtual cloneElementWithChildren and cloneElementWithoutChildren
582 // are used instead.
583 virtual Ref<Node> cloneNodeInternal(Document&, CloningOperation) override;
584 virtual Ref<Element> cloneElementWithoutAttributesAndChildren(Document&);
585
586 void removeShadowRoot();
587
588 RenderStyle* existingComputedStyle();
589 RenderStyle& resolveComputedStyle();
590
591 bool rareDataStyleAffectedByEmpty() const;
592 bool rareDataChildrenAffectedByHover() const;
593 bool rareDataChildrenAffectedByActive() const;
594 bool rareDataChildrenAffectedByDrag() const;
595 bool rareDataChildrenAffectedByLastChildRules() const;
596 bool rareDataChildrenAffectedByBackwardPositionalRules() const;
597 bool rareDataChildrenAffectedByPropertyBasedBackwardPositionalRules() const;
598 unsigned rareDataChildIndex() const;
599
600 SpellcheckAttributeState spellcheckAttributeState() const;
601
602 void unregisterNamedFlowContentElement();
603
604 void createUniqueElementData();
605
606 ElementRareData* elementRareData() const;
607 ElementRareData& ensureElementRareData();
608
609 void detachAllAttrNodesFromElement();
610 void detachAttrNodeFromElementWithValue(Attr*, const AtomicString& value);
611
612 bool isJavaScriptURLAttribute(const Attribute&) const;
613
614 // Anyone thinking of using this should call document instead of ownerDocument.
615 void ownerDocument() const = delete;
616
617 QualifiedName m_tagName;
618 RefPtr<ElementData> m_elementData;
619};
620
621inline bool Node::hasAttributes() const
622{
623 return is<Element>(*this) && downcast<Element>(*this).hasAttributes();
624}
625
626inline NamedNodeMap* Node::attributes() const
627{
628 return is<Element>(*this) ? &downcast<Element>(*this).attributes() : nullptr;
629}
630
631inline Element* Node::parentElement() const
632{
633 ContainerNode* parent = parentNode();
634 return is<Element>(parent) ? downcast<Element>(parent) : nullptr;
635}
636
637inline const Element* Element::rootElement() const
638{
639 if (inDocument())
640 return document().documentElement();
641
642 const Element* highest = this;
643 while (highest->parentElement())
644 highest = highest->parentElement();
645 return highest;
646}
647
648inline bool Element::fastHasAttribute(const QualifiedName& name) const
649{
650 ASSERT(fastAttributeLookupAllowed(name));
651 return elementData() && findAttributeByName(name);
652}
653
654inline const AtomicString& Element::fastGetAttribute(const QualifiedName& name) const
655{
656 ASSERT(fastAttributeLookupAllowed(name));
657 if (elementData()) {
658 if (const Attribute* attribute = findAttributeByName(name))
659 return attribute->value();
660 }
661 return nullAtom;
662}
663
664inline bool Element::hasAttributesWithoutUpdate() const
665{
666 return elementData() && !elementData()->isEmpty();
667}
668
669inline const AtomicString& Element::idForStyleResolution() const
670{
671 ASSERT(hasID());
672 return elementData()->idForStyleResolution();
673}
674
675inline const AtomicString& Element::getIdAttribute() const
676{
677 if (hasID())
678 return elementData()->findAttributeByName(HTMLNames::idAttr)->value();
679 return nullAtom;
680}
681
682inline const AtomicString& Element::getNameAttribute() const
683{
684 if (hasName())
685 return elementData()->findAttributeByName(HTMLNames::nameAttr)->value();
686 return nullAtom;
687}
688
689inline void Element::setIdAttribute(const AtomicString& value)
690{
691 setAttribute(HTMLNames::idAttr, value);
692}
693
694inline const SpaceSplitString& Element::classNames() const
695{
696 ASSERT(hasClass());
697 ASSERT(elementData());
698 return elementData()->classNames();
699}
700
701inline unsigned Element::attributeCount() const
702{
703 ASSERT(elementData());
704 return elementData()->length();
705}
706
707inline const Attribute& Element::attributeAt(unsigned index) const
708{
709 ASSERT(elementData());
710 return elementData()->attributeAt(index);
711}
712
713inline const Attribute* Element::findAttributeByName(const QualifiedName& name) const
714{
715 ASSERT(elementData());
716 return elementData()->findAttributeByName(name);
717}
718
719inline bool Element::hasID() const
720{
721 return elementData() && elementData()->hasID();
722}
723
724inline bool Element::hasClass() const
725{
726 return elementData() && elementData()->hasClass();
727}
728
729inline bool Element::hasName() const
730{
731 return elementData() && elementData()->hasName();
732}
733
734inline UniqueElementData& Element::ensureUniqueElementData()
735{
736 if (!elementData() || !elementData()->isUnique())
737 createUniqueElementData();
738 return static_cast<UniqueElementData&>(*m_elementData);
739}
740
741inline bool shouldIgnoreAttributeCase(const Element& element)
742{
743 return element.isHTMLElement() && element.document().isHTMLDocument();
744}
745
746} // namespace WebCore
747
748SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::Element)
749 static bool isType(const WebCore::Node& node) { return node.isElementNode(); }
750SPECIALIZE_TYPE_TRAITS_END()
751
752#endif
753