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, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013 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 "CollectionType.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 "StyleResolveTree.h"
36
37namespace WebCore {
38
39class ClientRect;
40class ClientRectList;
41class DatasetDOMStringMap;
42class DOMTokenList;
43class ElementRareData;
44class HTMLDocument;
45class IntSize;
46class Locale;
47class PlatformKeyboardEvent;
48class PlatformMouseEvent;
49class PlatformWheelEvent;
50class PseudoElement;
51class RenderNamedFlowFragment;
52class ShadowRoot;
53
54enum AffectedSelectorType {
55    AffectedSelectorChecked = 1,
56    AffectedSelectorEnabled = 1 << 1,
57    AffectedSelectorDisabled = 1 << 2,
58    AffectedSelectorIndeterminate = 1 << 3,
59    AffectedSelectorLink = 1 << 4,
60    AffectedSelectorTarget = 1 << 5,
61    AffectedSelectorVisited = 1 << 6
62};
63typedef int AffectedSelectorMask;
64
65enum SpellcheckAttributeState {
66    SpellcheckAttributeTrue,
67    SpellcheckAttributeFalse,
68    SpellcheckAttributeDefault
69};
70
71class Element : public ContainerNode {
72public:
73    static PassRefPtr<Element> create(const QualifiedName&, Document&);
74    virtual ~Element();
75
76    DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
77    DEFINE_ATTRIBUTE_EVENT_LISTENER(change);
78    DEFINE_ATTRIBUTE_EVENT_LISTENER(click);
79    DEFINE_ATTRIBUTE_EVENT_LISTENER(contextmenu);
80    DEFINE_ATTRIBUTE_EVENT_LISTENER(dblclick);
81    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragenter);
82    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragover);
83    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragleave);
84    DEFINE_ATTRIBUTE_EVENT_LISTENER(drop);
85    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragstart);
86    DEFINE_ATTRIBUTE_EVENT_LISTENER(drag);
87    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragend);
88    DEFINE_ATTRIBUTE_EVENT_LISTENER(input);
89    DEFINE_ATTRIBUTE_EVENT_LISTENER(invalid);
90    DEFINE_ATTRIBUTE_EVENT_LISTENER(keydown);
91    DEFINE_ATTRIBUTE_EVENT_LISTENER(keypress);
92    DEFINE_ATTRIBUTE_EVENT_LISTENER(keyup);
93    DEFINE_ATTRIBUTE_EVENT_LISTENER(mousedown);
94    DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseenter);
95    DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseleave);
96    DEFINE_ATTRIBUTE_EVENT_LISTENER(mousemove);
97    DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseout);
98    DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseover);
99    DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseup);
100    DEFINE_ATTRIBUTE_EVENT_LISTENER(mousewheel);
101    DEFINE_ATTRIBUTE_EVENT_LISTENER(scroll);
102    DEFINE_ATTRIBUTE_EVENT_LISTENER(select);
103    DEFINE_ATTRIBUTE_EVENT_LISTENER(submit);
104#if ENABLE(WILL_REVEAL_EDGE_EVENTS)
105    DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitwillrevealbottom);
106    DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitwillrevealleft);
107    DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitwillrevealright);
108    DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitwillrevealtop);
109#endif
110    DEFINE_ATTRIBUTE_EVENT_LISTENER(wheel);
111
112    // These four attribute event handler attributes are overridden by HTMLBodyElement
113    // and HTMLFrameSetElement to forward to the DOMWindow.
114    DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(blur);
115    DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(error);
116    DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(focus);
117    DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(load);
118
119    // WebKit extensions
120    DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut);
121    DEFINE_ATTRIBUTE_EVENT_LISTENER(cut);
122    DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecopy);
123    DEFINE_ATTRIBUTE_EVENT_LISTENER(copy);
124    DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste);
125    DEFINE_ATTRIBUTE_EVENT_LISTENER(paste);
126    DEFINE_ATTRIBUTE_EVENT_LISTENER(reset);
127    DEFINE_ATTRIBUTE_EVENT_LISTENER(search);
128    DEFINE_ATTRIBUTE_EVENT_LISTENER(selectstart);
129#if ENABLE(TOUCH_EVENTS)
130    DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart);
131    DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove);
132    DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend);
133    DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel);
134#endif
135#if ENABLE(IOS_GESTURE_EVENTS)
136    DEFINE_ATTRIBUTE_EVENT_LISTENER(gesturestart);
137    DEFINE_ATTRIBUTE_EVENT_LISTENER(gesturechange);
138    DEFINE_ATTRIBUTE_EVENT_LISTENER(gestureend);
139#endif
140#if ENABLE(FULLSCREEN_API)
141    DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenchange);
142    DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenerror);
143#endif
144
145    bool hasAttribute(const QualifiedName&) const;
146    const AtomicString& getAttribute(const QualifiedName&) const;
147    void setAttribute(const QualifiedName&, const AtomicString& value);
148    void setAttributeWithoutSynchronization(const QualifiedName&, const AtomicString& value);
149    void setSynchronizedLazyAttribute(const QualifiedName&, const AtomicString& value);
150    bool removeAttribute(const QualifiedName&);
151
152    // Typed getters and setters for language bindings.
153    int getIntegralAttribute(const QualifiedName& attributeName) const;
154    void setIntegralAttribute(const QualifiedName& attributeName, int value);
155    unsigned getUnsignedIntegralAttribute(const QualifiedName& attributeName) const;
156    void setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value);
157
158    // Call this to get the value of an attribute that is known not to be the style
159    // attribute or one of the SVG animatable attributes.
160    bool fastHasAttribute(const QualifiedName&) const;
161    const AtomicString& fastGetAttribute(const QualifiedName&) const;
162#ifndef NDEBUG
163    bool fastAttributeLookupAllowed(const QualifiedName&) const;
164#endif
165
166#ifdef DUMP_NODE_STATISTICS
167    bool hasNamedNodeMap() const;
168#endif
169    bool hasAttributes() const;
170    // This variant will not update the potentially invalid attributes. To be used when not interested
171    // in style attribute or one of the SVG animation attributes.
172    bool hasAttributesWithoutUpdate() const;
173
174    bool hasAttribute(const AtomicString& name) const;
175    bool hasAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const;
176
177    const AtomicString& getAttribute(const AtomicString& name) const;
178    const AtomicString& getAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const;
179
180    void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode&);
181    static bool parseAttributeName(QualifiedName&, const AtomicString& namespaceURI, const AtomicString& qualifiedName, ExceptionCode&);
182    void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode&);
183
184    const AtomicString& getIdAttribute() const;
185    void setIdAttribute(const AtomicString&);
186
187    const AtomicString& getNameAttribute() const;
188
189    // Call this to get the value of the id attribute for style resolution purposes.
190    // The value will already be lowercased if the document is in compatibility mode,
191    // so this function is not suitable for non-style uses.
192    const AtomicString& idForStyleResolution() const;
193
194    // Internal methods that assume the existence of attribute storage, one should use hasAttributes()
195    // before calling them.
196    AttributeIteratorAccessor attributesIterator() const { return elementData()->attributesIterator(); }
197    unsigned attributeCount() const;
198    const Attribute& attributeAt(unsigned index) const;
199    const Attribute* findAttributeByName(const QualifiedName&) const;
200    unsigned findAttributeIndexByName(const QualifiedName& name) const { return elementData()->findAttributeIndexByName(name); }
201    unsigned findAttributeIndexByName(const AtomicString& name, bool shouldIgnoreAttributeCase) const { return elementData()->findAttributeIndexByName(name, shouldIgnoreAttributeCase); }
202
203    void scrollIntoView(bool alignToTop = true);
204    void scrollIntoViewIfNeeded(bool centerIfNeeded = true);
205
206    void scrollByLines(int lines);
207    void scrollByPages(int pages);
208
209    double offsetLeft();
210    double offsetTop();
211    double offsetWidth();
212    double offsetHeight();
213
214    // FIXME: Replace uses of offsetParent in the platform with calls
215    // to the render layer and merge bindingsOffsetParent and offsetParent.
216    Element* bindingsOffsetParent();
217
218    Element* offsetParent();
219    double clientLeft();
220    double clientTop();
221    double clientWidth();
222    double clientHeight();
223    virtual int scrollLeft();
224    virtual int scrollTop();
225    virtual void setScrollLeft(int);
226    virtual void setScrollTop(int);
227    virtual int scrollWidth();
228    virtual int scrollHeight();
229
230    IntRect boundsInRootViewSpace();
231
232    PassRefPtr<ClientRectList> getClientRects();
233    PassRefPtr<ClientRect> getBoundingClientRect();
234
235    // Returns the absolute bounding box translated into client coordinates.
236    IntRect clientRect() const;
237    // Returns the absolute bounding box translated into screen coordinates.
238    IntRect screenRect() const;
239
240    bool removeAttribute(const AtomicString& name);
241    bool removeAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName);
242
243    PassRefPtr<Attr> detachAttribute(unsigned index);
244
245    PassRefPtr<Attr> getAttributeNode(const AtomicString& name);
246    PassRefPtr<Attr> getAttributeNodeNS(const AtomicString& namespaceURI, const AtomicString& localName);
247    PassRefPtr<Attr> setAttributeNode(Attr*, ExceptionCode&);
248    PassRefPtr<Attr> setAttributeNodeNS(Attr*, ExceptionCode&);
249    PassRefPtr<Attr> removeAttributeNode(Attr*, ExceptionCode&);
250
251    PassRefPtr<Attr> attrIfExists(const QualifiedName&);
252    PassRefPtr<Attr> ensureAttr(const QualifiedName&);
253
254    const Vector<RefPtr<Attr>>& attrNodeList();
255
256    virtual CSSStyleDeclaration* style();
257
258    const QualifiedName& tagQName() const { return m_tagName; }
259#if ENABLE(CSS_SELECTOR_JIT)
260    static ptrdiff_t tagQNameMemoryOffset() { return OBJECT_OFFSETOF(Element, m_tagName); }
261#endif // ENABLE(CSS_SELECTOR_JIT)
262    String tagName() const { return nodeName(); }
263    bool hasTagName(const QualifiedName& tagName) const { return m_tagName.matches(tagName); }
264    bool hasTagName(const HTMLQualifiedName& tagName) const { return ContainerNode::hasTagName(tagName); }
265    bool hasTagName(const MathMLQualifiedName& tagName) const { return ContainerNode::hasTagName(tagName); }
266    bool hasTagName(const SVGQualifiedName& tagName) const { return ContainerNode::hasTagName(tagName); }
267
268    // A fast function for checking the local name against another atomic string.
269    bool hasLocalName(const AtomicString& other) const { return m_tagName.localName() == other; }
270
271    virtual const AtomicString& localName() const override final { return m_tagName.localName(); }
272    virtual const AtomicString& prefix() const override final { return m_tagName.prefix(); }
273    virtual const AtomicString& namespaceURI() const override final { return m_tagName.namespaceURI(); }
274
275    virtual URL baseURI() const override final;
276
277    virtual String nodeName() const override;
278
279    PassRefPtr<Element> cloneElementWithChildren();
280    PassRefPtr<Element> cloneElementWithoutChildren();
281
282    void normalizeAttributes();
283    String nodeNamePreservingCase() const;
284
285    void setBooleanAttribute(const QualifiedName& name, bool);
286
287    // For exposing to DOM only.
288    NamedNodeMap* attributes() const;
289
290    enum AttributeModificationReason {
291        ModifiedDirectly,
292        ModifiedByCloning
293    };
294
295    // This method is called whenever an attribute is added, changed or removed.
296    virtual void attributeChanged(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue, AttributeModificationReason = ModifiedDirectly);
297    virtual void parseAttribute(const QualifiedName&, const AtomicString&) { }
298
299    // Only called by the parser immediately after element construction.
300    void parserSetAttributes(const Vector<Attribute>&);
301
302    // Remove attributes that might introduce scripting from the vector leaving the element unchanged.
303    void stripScriptingAttributes(Vector<Attribute>&) const;
304
305    const ElementData* elementData() const { return m_elementData.get(); }
306    static ptrdiff_t elementDataMemoryOffset() { return OBJECT_OFFSETOF(Element, m_elementData); }
307    UniqueElementData& ensureUniqueElementData();
308
309    void synchronizeAllAttributes() const;
310
311    // Clones attributes only.
312    void cloneAttributesFromElement(const Element&);
313
314    // Clones all attribute-derived data, including subclass specifics (through copyNonAttributeProperties.)
315    void cloneDataFromElement(const Element&);
316
317    bool hasEquivalentAttributes(const Element* other) const;
318
319    virtual void copyNonAttributePropertiesFromElement(const Element&) { }
320
321    void lazyReattach();
322
323    virtual RenderPtr<RenderElement> createElementRenderer(PassRef<RenderStyle>);
324    virtual bool rendererIsNeeded(const RenderStyle&);
325    void didAffectSelector(AffectedSelectorMask);
326
327    ShadowRoot* shadowRoot() const;
328    PassRefPtr<ShadowRoot> createShadowRoot(ExceptionCode&);
329
330    ShadowRoot* userAgentShadowRoot() const;
331    ShadowRoot& ensureUserAgentShadowRoot();
332
333    virtual const AtomicString& shadowPseudoId() const;
334
335    bool inActiveChain() const { return isUserActionElement() && isUserActionElementInActiveChain(); }
336    bool active() const { return isUserActionElement() && isUserActionElementActive(); }
337    bool hovered() const { return isUserActionElement() && isUserActionElementHovered(); }
338    bool focused() const { return isUserActionElement() && isUserActionElementFocused(); }
339
340    virtual void setActive(bool flag = true, bool pause = false);
341    virtual void setHovered(bool flag = true);
342    virtual void setFocus(bool flag);
343
344    virtual bool supportsFocus() const;
345    virtual bool isFocusable() const;
346    virtual bool isKeyboardFocusable(KeyboardEvent*) const;
347    virtual bool isMouseFocusable() const;
348
349    virtual bool shouldUseInputMethod();
350
351    virtual short tabIndex() const;
352    void setTabIndex(int);
353    virtual Element* focusDelegate();
354
355    virtual RenderStyle* computedStyle(PseudoId = NOPSEUDO) override;
356
357    // Methods for indicating the style is affected by dynamic updates (e.g., children changing, our position changing in our sibling list, etc.)
358    bool styleAffectedByEmpty() const { return hasRareData() && rareDataStyleAffectedByEmpty(); }
359    bool childrenAffectedByHover() const { return getFlag(ChildrenAffectedByHoverRulesFlag); }
360    bool childrenAffectedByActive() const { return hasRareData() && rareDataChildrenAffectedByActive(); }
361    bool childrenAffectedByDrag() const { return hasRareData() && rareDataChildrenAffectedByDrag(); }
362    bool childrenAffectedByPositionalRules() const { return hasRareData() && (rareDataChildrenAffectedByForwardPositionalRules() || rareDataChildrenAffectedByBackwardPositionalRules()); }
363    bool childrenAffectedByFirstChildRules() const { return getFlag(ChildrenAffectedByFirstChildRulesFlag); }
364    bool childrenAffectedByLastChildRules() const { return getFlag(ChildrenAffectedByLastChildRulesFlag); }
365    bool childrenAffectedByDirectAdjacentRules() const { return getFlag(ChildrenAffectedByDirectAdjacentRulesFlag); }
366    bool childrenAffectedByForwardPositionalRules() const { return hasRareData() && rareDataChildrenAffectedByForwardPositionalRules(); }
367    bool childrenAffectedByBackwardPositionalRules() const { return hasRareData() && rareDataChildrenAffectedByBackwardPositionalRules(); }
368    unsigned childIndex() const { return hasRareData() ? rareDataChildIndex() : 0; }
369
370    bool hasFlagsSetDuringStylingOfChildren() const;
371
372    void setStyleAffectedByEmpty();
373    void setChildrenAffectedByHover() { setFlag(ChildrenAffectedByHoverRulesFlag); }
374    void setChildrenAffectedByActive();
375    void setChildrenAffectedByDrag();
376    void setChildrenAffectedByFirstChildRules() { setFlag(ChildrenAffectedByFirstChildRulesFlag); }
377    void setChildrenAffectedByLastChildRules() { setFlag(ChildrenAffectedByLastChildRulesFlag); }
378    void setChildrenAffectedByDirectAdjacentRules() { setFlag(ChildrenAffectedByDirectAdjacentRulesFlag); }
379    static void setChildrenAffectedByForwardPositionalRules(Element*);
380    void setChildrenAffectedByForwardPositionalRules() { setChildrenAffectedByForwardPositionalRules(this); }
381    void setChildrenAffectedByBackwardPositionalRules();
382    void setChildIndex(unsigned);
383
384    void setIsInCanvasSubtree(bool);
385    bool isInCanvasSubtree() const;
386
387    void setRegionOversetState(RegionOversetState);
388    RegionOversetState regionOversetState() const;
389
390    AtomicString computeInheritedLanguage() const;
391    Locale& locale() const;
392
393    virtual void accessKeyAction(bool /*sendToAnyEvent*/) { }
394
395    virtual bool isURLAttribute(const Attribute&) const { return false; }
396    virtual bool isHTMLContentAttribute(const Attribute&) const { return false; }
397
398    URL getURLAttribute(const QualifiedName&) const;
399    URL getNonEmptyURLAttribute(const QualifiedName&) const;
400
401    virtual const AtomicString& imageSourceURL() const;
402    virtual String target() const { return String(); }
403
404    void updateFocusAppearanceAfterAttachIfNeeded();
405    virtual void focus(bool restorePreviousSelection = true, FocusDirection = FocusDirectionNone);
406    virtual void updateFocusAppearance(bool restorePreviousSelection);
407    virtual void blur();
408
409    String innerText();
410    String outerText();
411
412    virtual String title() const;
413
414    const AtomicString& pseudo() const;
415    void setPseudo(const AtomicString&);
416
417    LayoutSize minimumSizeForResizing() const;
418    void setMinimumSizeForResizing(const LayoutSize&);
419
420    // Use Document::registerForDocumentActivationCallbacks() to subscribe to these
421    virtual void documentWillSuspendForPageCache() { }
422    virtual void documentDidResumeFromPageCache() { }
423
424    // Use Document::registerForMediaVolumeCallbacks() to subscribe to this
425    virtual void mediaVolumeDidChange() { }
426
427    // Use Document::registerForPrivateBrowsingStateChangedCallbacks() to subscribe to this.
428    virtual void privateBrowsingStateDidChange() { }
429
430    virtual void didBecomeFullscreenElement() { }
431    virtual void willStopBeingFullscreenElement() { }
432
433    // Use Document::registerForVisibilityStateChangedCallbacks() to subscribe to this.
434    virtual void visibilityStateChanged() { }
435
436#if ENABLE(VIDEO_TRACK)
437    virtual void captionPreferencesChanged() { }
438#endif
439
440    bool isFinishedParsingChildren() const { return isParsingChildrenFinished(); }
441    virtual void finishParsingChildren() override;
442    virtual void beginParsingChildren() override final;
443
444    PseudoElement* beforePseudoElement() const;
445    PseudoElement* afterPseudoElement() const;
446    bool childNeedsShadowWalker() const;
447    void didShadowTreeAwareChildrenChange();
448
449    // ElementTraversal API
450    Element* firstElementChild() const;
451    Element* lastElementChild() const;
452    Element* previousElementSibling() const;
453    Element* nextElementSibling() const;
454    unsigned childElementCount() const;
455
456    virtual bool matchesReadOnlyPseudoClass() const;
457    virtual bool matchesReadWritePseudoClass() const;
458    bool matches(const String& selectors, ExceptionCode&);
459    virtual bool shouldAppearIndeterminate() const;
460
461    DOMTokenList* classList();
462
463    DatasetDOMStringMap* dataset();
464
465#if ENABLE(VIDEO)
466    virtual bool isMediaElement() const { return false; }
467#endif
468
469#if ENABLE(INPUT_SPEECH)
470    virtual bool isInputFieldSpeechButtonElement() const { return false; }
471#endif
472
473    virtual bool isFormControlElement() const { return false; }
474    virtual bool isSpinButtonElement() const { return false; }
475    virtual bool isTextFormControl() const { return false; }
476    virtual bool isOptionalFormControl() const { return false; }
477    virtual bool isRequiredFormControl() const { return false; }
478    virtual bool isDefaultButtonForForm() const { return false; }
479    virtual bool willValidate() const { return false; }
480    virtual bool isValidFormControlElement() const { return false; }
481    virtual bool isInRange() const { return false; }
482    virtual bool isOutOfRange() const { return false; }
483    virtual bool isFrameElementBase() const { return false; }
484    virtual bool isSearchFieldCancelButtonElement() const { return false; }
485
486    virtual bool canContainRangeEndPoint() const override;
487
488    // Used for disabled form elements; if true, prevents mouse events from being dispatched
489    // to event listeners, and prevents DOMActivate events from being sent at all.
490    virtual bool isDisabledFormControl() const { return false; }
491
492    virtual bool childShouldCreateRenderer(const Node&) const override;
493
494    bool hasPendingResources() const;
495    void setHasPendingResources();
496    void clearHasPendingResources();
497    virtual void buildPendingResource() { };
498
499#if ENABLE(FULLSCREEN_API)
500    enum {
501        ALLOW_KEYBOARD_INPUT = 1 << 0,
502        LEGACY_MOZILLA_REQUEST = 1 << 1,
503    };
504
505    void webkitRequestFullScreen(unsigned short flags);
506    bool containsFullScreenElement() const;
507    void setContainsFullScreenElement(bool);
508    void setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(bool);
509
510    // W3C API
511    void webkitRequestFullscreen();
512#endif
513
514#if ENABLE(POINTER_LOCK)
515    void requestPointerLock();
516#endif
517
518#if ENABLE(INDIE_UI)
519    void setUIActions(const AtomicString&);
520    const AtomicString& UIActions() const;
521#endif
522
523    virtual bool isSpellCheckingEnabled() const;
524
525    RenderNamedFlowFragment* renderNamedFlowFragment() const;
526
527#if ENABLE(CSS_REGIONS)
528    virtual bool shouldMoveToFlowThread(const RenderStyle&) const;
529
530    const AtomicString& webkitRegionOverset() const;
531    Vector<RefPtr<Range>> webkitGetRegionFlowRanges() const;
532#endif
533
534    bool hasID() const;
535    bool hasClass() const;
536    bool hasName() const;
537    const SpaceSplitString& classNames() const;
538
539    IntSize savedLayerScrollOffset() const;
540    void setSavedLayerScrollOffset(const IntSize&);
541
542    bool dispatchMouseEvent(const PlatformMouseEvent&, const AtomicString& eventType, int clickCount = 0, Element* relatedTarget = nullptr);
543    bool dispatchWheelEvent(const PlatformWheelEvent&);
544    bool dispatchKeyEvent(const PlatformKeyboardEvent&);
545    void dispatchSimulatedClick(Event* underlyingEvent, SimulatedClickMouseEventOptions = SendNoEvents, SimulatedClickVisualOptions = ShowPressedLook);
546    void dispatchFocusInEvent(const AtomicString& eventType, PassRefPtr<Element> oldFocusedElement);
547    void dispatchFocusOutEvent(const AtomicString& eventType, PassRefPtr<Element> newFocusedElement);
548    virtual void dispatchFocusEvent(PassRefPtr<Element> oldFocusedElement, FocusDirection);
549    virtual void dispatchBlurEvent(PassRefPtr<Element> newFocusedElement);
550
551    virtual bool willRecalcStyle(Style::Change);
552    virtual void didRecalcStyle(Style::Change);
553    virtual void willAttachRenderers();
554    virtual void didAttachRenderers();
555    virtual void willDetachRenderers();
556    virtual void didDetachRenderers();
557    virtual PassRefPtr<RenderStyle> customStyleForRenderer(RenderStyle& parentStyle);
558
559    void setBeforePseudoElement(PassRefPtr<PseudoElement>);
560    void setAfterPseudoElement(PassRefPtr<PseudoElement>);
561    void clearBeforePseudoElement();
562    void clearAfterPseudoElement();
563    void resetComputedStyle();
564    void clearStyleDerivedDataBeforeDetachingRenderer();
565    void clearHoverAndActiveStatusBeforeDetachingRenderer();
566
567    URL absoluteLinkURL() const;
568
569protected:
570    Element(const QualifiedName& tagName, Document& document, ConstructionType type)
571        : ContainerNode(document, type)
572        , m_tagName(tagName)
573    {
574    }
575
576    virtual InsertionNotificationRequest insertedInto(ContainerNode&) override;
577    virtual void removedFrom(ContainerNode&) override;
578    virtual void childrenChanged(const ChildChange&) override;
579    virtual void removeAllEventListeners() override final;
580
581    void clearTabIndexExplicitlyIfNeeded();
582    void setTabIndexExplicitly(short);
583
584    PassRefPtr<HTMLCollection> ensureCachedHTMLCollection(CollectionType);
585    HTMLCollection* cachedHTMLCollection(CollectionType);
586
587    // classAttributeChanged() exists to share code between
588    // parseAttribute (called via setAttribute()) and
589    // svgAttributeChanged (called when element.className.baseValue is set)
590    void classAttributeChanged(const AtomicString& newClassString);
591
592private:
593    bool isTextNode() const;
594
595    bool isUserActionElementInActiveChain() const;
596    bool isUserActionElementActive() const;
597    bool isUserActionElementFocused() const;
598    bool isUserActionElementHovered() const;
599
600    void resetNeedsNodeRenderingTraversalSlowPath();
601
602    virtual void didAddUserAgentShadowRoot(ShadowRoot*) { }
603    virtual bool alwaysCreateUserAgentShadowRoot() const { return false; }
604
605    // FIXME: Remove the need for Attr to call willModifyAttribute/didModifyAttribute.
606    friend class Attr;
607
608    enum SynchronizationOfLazyAttribute { NotInSynchronizationOfLazyAttribute = 0, InSynchronizationOfLazyAttribute };
609
610    void didAddAttribute(const QualifiedName&, const AtomicString&);
611    void willModifyAttribute(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue);
612    void didModifyAttribute(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue);
613    void didRemoveAttribute(const QualifiedName&, const AtomicString& oldValue);
614
615    void synchronizeAttribute(const QualifiedName&) const;
616    void synchronizeAttribute(const AtomicString& localName) const;
617
618    void updateName(const AtomicString& oldName, const AtomicString& newName);
619    void updateNameForTreeScope(TreeScope&, const AtomicString& oldName, const AtomicString& newName);
620    void updateNameForDocument(HTMLDocument&, const AtomicString& oldName, const AtomicString& newName);
621    void updateId(const AtomicString& oldId, const AtomicString& newId);
622    void updateIdForTreeScope(TreeScope&, const AtomicString& oldId, const AtomicString& newId);
623    enum HTMLDocumentNamedItemMapsUpdatingCondition { AlwaysUpdateHTMLDocumentNamedItemMaps, UpdateHTMLDocumentNamedItemMapsOnlyIfDiffersFromNameAttribute };
624    void updateIdForDocument(HTMLDocument&, const AtomicString& oldId, const AtomicString& newId, HTMLDocumentNamedItemMapsUpdatingCondition);
625    void updateLabel(TreeScope&, const AtomicString& oldForAttributeValue, const AtomicString& newForAttributeValue);
626
627    void scrollByUnits(int units, ScrollGranularity);
628
629    virtual void setPrefix(const AtomicString&, ExceptionCode&) override final;
630    virtual NodeType nodeType() const override final;
631    virtual bool childTypeAllowed(NodeType) const override final;
632
633    void setAttributeInternal(unsigned index, const QualifiedName&, const AtomicString& value, SynchronizationOfLazyAttribute);
634    void addAttributeInternal(const QualifiedName&, const AtomicString& value, SynchronizationOfLazyAttribute);
635    void removeAttributeInternal(unsigned index, SynchronizationOfLazyAttribute);
636
637#ifndef NDEBUG
638    virtual void formatForDebugger(char* buffer, unsigned length) const override;
639#endif
640
641    void cancelFocusAppearanceUpdate();
642
643    // cloneNode is private so that non-virtual cloneElementWithChildren and cloneElementWithoutChildren
644    // are used instead.
645    virtual PassRefPtr<Node> cloneNode(bool deep) override;
646    virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren();
647
648    void addShadowRoot(PassRefPtr<ShadowRoot>);
649    void removeShadowRoot();
650
651    bool rareDataStyleAffectedByEmpty() const;
652    bool rareDataChildrenAffectedByHover() const;
653    bool rareDataChildrenAffectedByActive() const;
654    bool rareDataChildrenAffectedByDrag() const;
655    bool rareDataChildrenAffectedByLastChildRules() const;
656    bool rareDataChildrenAffectedByForwardPositionalRules() const;
657    bool rareDataChildrenAffectedByBackwardPositionalRules() const;
658    unsigned rareDataChildIndex() const;
659
660    SpellcheckAttributeState spellcheckAttributeState() const;
661
662    void unregisterNamedFlowContentElement();
663
664    void createUniqueElementData();
665
666    ElementRareData* elementRareData() const;
667    ElementRareData& ensureElementRareData();
668
669    void detachAllAttrNodesFromElement();
670    void detachAttrNodeFromElementWithValue(Attr*, const AtomicString& value);
671
672    bool isJavaScriptURLAttribute(const Attribute&) const;
673
674    // Anyone thinking of using this should call document instead of ownerDocument.
675    void ownerDocument() const = delete;
676
677    QualifiedName m_tagName;
678    RefPtr<ElementData> m_elementData;
679};
680
681inline bool isElement(const Node& node) { return node.isElementNode(); }
682
683NODE_TYPE_CASTS(Element)
684
685template <typename Type> bool isElementOfType(const Element&);
686template <typename Type> inline bool isElementOfType(const Node& node) { return node.isElementNode() && isElementOfType<const Type>(toElement(node)); }
687template <> inline bool isElementOfType<const Element>(const Element&) { return true; }
688
689inline bool Node::hasAttributes() const
690{
691    return isElementNode() && toElement(this)->hasAttributes();
692}
693
694inline NamedNodeMap* Node::attributes() const
695{
696    return isElementNode() ? toElement(this)->attributes() : nullptr;
697}
698
699inline Element* Node::parentElement() const
700{
701    ContainerNode* parent = parentNode();
702    return parent && parent->isElementNode() ? toElement(parent) : nullptr;
703}
704
705inline bool Element::fastHasAttribute(const QualifiedName& name) const
706{
707    ASSERT(fastAttributeLookupAllowed(name));
708    return elementData() && findAttributeByName(name);
709}
710
711inline const AtomicString& Element::fastGetAttribute(const QualifiedName& name) const
712{
713    ASSERT(fastAttributeLookupAllowed(name));
714    if (elementData()) {
715        if (const Attribute* attribute = findAttributeByName(name))
716            return attribute->value();
717    }
718    return nullAtom;
719}
720
721inline bool Element::hasAttributesWithoutUpdate() const
722{
723    return elementData() && !elementData()->isEmpty();
724}
725
726inline const AtomicString& Element::idForStyleResolution() const
727{
728    ASSERT(hasID());
729    return elementData()->idForStyleResolution();
730}
731
732inline const AtomicString& Element::getIdAttribute() const
733{
734    if (hasID())
735        return elementData()->findAttributeByName(HTMLNames::idAttr)->value();
736    return nullAtom;
737}
738
739inline const AtomicString& Element::getNameAttribute() const
740{
741    if (hasName())
742        return elementData()->findAttributeByName(HTMLNames::nameAttr)->value();
743    return nullAtom;
744}
745
746inline void Element::setIdAttribute(const AtomicString& value)
747{
748    setAttribute(HTMLNames::idAttr, value);
749}
750
751inline const SpaceSplitString& Element::classNames() const
752{
753    ASSERT(hasClass());
754    ASSERT(elementData());
755    return elementData()->classNames();
756}
757
758inline unsigned Element::attributeCount() const
759{
760    ASSERT(elementData());
761    return elementData()->length();
762}
763
764inline const Attribute& Element::attributeAt(unsigned index) const
765{
766    ASSERT(elementData());
767    return elementData()->attributeAt(index);
768}
769
770inline const Attribute* Element::findAttributeByName(const QualifiedName& name) const
771{
772    ASSERT(elementData());
773    return elementData()->findAttributeByName(name);
774}
775
776inline bool Element::hasID() const
777{
778    return elementData() && elementData()->hasID();
779}
780
781inline bool Element::hasClass() const
782{
783    return elementData() && elementData()->hasClass();
784}
785
786inline bool Element::hasName() const
787{
788    return elementData() && elementData()->hasName();
789}
790
791inline UniqueElementData& Element::ensureUniqueElementData()
792{
793    if (!elementData() || !elementData()->isUnique())
794        createUniqueElementData();
795    return static_cast<UniqueElementData&>(*m_elementData);
796}
797
798} // namespace WebCore
799
800#endif
801