f47755ec39bbafc4694ce6d487074153c81c254d
[WebKit-https.git] / Source / WebCore / dom / Element.h
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 "Attribute.h"
29 #include "CollectionType.h"
30 #include "Document.h"
31 #include "HTMLNames.h"
32 #include "ScrollTypes.h"
33 #include "SpaceSplitString.h"
34
35 namespace WebCore {
36
37 class Attr;
38 class ClientRect;
39 class ClientRectList;
40 class DOMStringMap;
41 class DOMTokenList;
42 class Element;
43 class ElementRareData;
44 class ElementShadow;
45 class ShareableElementData;
46 class IntSize;
47 class Locale;
48 class UniqueElementData;
49 class PseudoElement;
50 class RenderRegion;
51 class ShadowRoot;
52 class StylePropertySet;
53
54 class ElementData : public RefCounted<ElementData> {
55     WTF_MAKE_FAST_ALLOCATED;
56 public:
57     // Override RefCounted's deref() to ensure operator delete is called on
58     // the appropriate subclass type.
59     void deref();
60
61     static const unsigned attributeNotFound = static_cast<unsigned>(-1);
62
63     void clearClass() const { m_classNames.clear(); }
64     void setClass(const AtomicString& className, bool shouldFoldCase) const { m_classNames.set(className, shouldFoldCase); }
65     const SpaceSplitString& classNames() const { return m_classNames; }
66
67     const AtomicString& idForStyleResolution() const { return m_idForStyleResolution; }
68     void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyleResolution = newId; }
69
70     const StylePropertySet* inlineStyle() const { return m_inlineStyle.get(); }
71
72     const StylePropertySet* presentationAttributeStyle() const;
73
74     unsigned length() const;
75     bool isEmpty() const { return !length(); }
76
77     const Attribute* attributeItem(unsigned index) const;
78     const Attribute* getAttributeItem(const QualifiedName&) const;
79     unsigned getAttributeItemIndex(const QualifiedName&) const;
80     unsigned getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
81
82     bool hasID() const { return !m_idForStyleResolution.isNull(); }
83     bool hasClass() const { return !m_classNames.isNull(); }
84
85     bool isEquivalent(const ElementData* other) const;
86
87     bool isUnique() const { return m_isUnique; }
88
89 protected:
90     ElementData();
91     ElementData(unsigned arraySize);
92     ElementData(const ElementData&, bool isUnique);
93
94     unsigned m_isUnique : 1;
95     unsigned m_arraySize : 28;
96     mutable unsigned m_presentationAttributeStyleIsDirty : 1;
97     mutable unsigned m_styleAttributeIsDirty : 1;
98 #if ENABLE(SVG)
99     mutable unsigned m_animatedSVGAttributesAreDirty : 1;
100 #endif
101
102     mutable RefPtr<StylePropertySet> m_inlineStyle;
103     mutable SpaceSplitString m_classNames;
104     mutable AtomicString m_idForStyleResolution;
105
106 private:
107     friend class Element;
108     friend class StyledElement;
109     friend class ShareableElementData;
110     friend class UniqueElementData;
111 #if ENABLE(SVG)
112     friend class SVGElement;
113 #endif
114
115     const Attribute* attributeBase() const;
116     const Attribute* getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
117     unsigned getAttributeItemIndexSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
118
119     PassRefPtr<UniqueElementData> makeUniqueCopy() const;
120 };
121
122 #if COMPILER(MSVC)
123 #pragma warning(push)
124 #pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" warning
125 #endif
126
127 class ShareableElementData : public ElementData {
128 public:
129     static PassRefPtr<ShareableElementData> createWithAttributes(const Vector<Attribute>&);
130
131     explicit ShareableElementData(const Vector<Attribute>&);
132     explicit ShareableElementData(const UniqueElementData&);
133     ~ShareableElementData();
134
135     Attribute m_attributeArray[0];
136 };
137
138 #if COMPILER(MSVC)
139 #pragma warning(pop)
140 #endif
141
142 class UniqueElementData : public ElementData {
143 public:
144     static PassRefPtr<UniqueElementData> create();
145     PassRefPtr<ShareableElementData> makeShareableCopy() const;
146
147     // These functions do no error/duplicate checking.
148     void addAttribute(const QualifiedName&, const AtomicString&);
149     void removeAttribute(unsigned index);
150
151     Attribute* attributeItem(unsigned index);
152     Attribute* getAttributeItem(const QualifiedName&);
153
154     UniqueElementData();
155     explicit UniqueElementData(const ShareableElementData&);
156     explicit UniqueElementData(const UniqueElementData&);
157
158     mutable RefPtr<StylePropertySet> m_presentationAttributeStyle;
159     Vector<Attribute, 4> m_attributeVector;
160 };
161
162 enum AffectedSelectorType {
163     AffectedSelectorChecked = 1,
164     AffectedSelectorEnabled = 1 << 1,
165     AffectedSelectorDisabled = 1 << 2,
166     AffectedSelectorIndeterminate = 1 << 3,
167     AffectedSelectorLink = 1 << 4,
168     AffectedSelectorTarget = 1 << 5,
169     AffectedSelectorVisited = 1 << 6
170 };
171 typedef int AffectedSelectorMask;
172
173 enum SpellcheckAttributeState {
174     SpellcheckAttributeTrue,
175     SpellcheckAttributeFalse,
176     SpellcheckAttributeDefault
177 };
178
179 class Element : public ContainerNode {
180 public:
181     static PassRefPtr<Element> create(const QualifiedName&, Document*);
182     virtual ~Element();
183
184     DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
185     DEFINE_ATTRIBUTE_EVENT_LISTENER(change);
186     DEFINE_ATTRIBUTE_EVENT_LISTENER(click);
187     DEFINE_ATTRIBUTE_EVENT_LISTENER(contextmenu);
188     DEFINE_ATTRIBUTE_EVENT_LISTENER(dblclick);
189     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragenter);
190     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragover);
191     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragleave);
192     DEFINE_ATTRIBUTE_EVENT_LISTENER(drop);
193     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragstart);
194     DEFINE_ATTRIBUTE_EVENT_LISTENER(drag);
195     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragend);
196     DEFINE_ATTRIBUTE_EVENT_LISTENER(input);
197     DEFINE_ATTRIBUTE_EVENT_LISTENER(invalid);
198     DEFINE_ATTRIBUTE_EVENT_LISTENER(keydown);
199     DEFINE_ATTRIBUTE_EVENT_LISTENER(keypress);
200     DEFINE_ATTRIBUTE_EVENT_LISTENER(keyup);
201     DEFINE_ATTRIBUTE_EVENT_LISTENER(mousedown);
202     DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseenter);
203     DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseleave);
204     DEFINE_ATTRIBUTE_EVENT_LISTENER(mousemove);
205     DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseout);
206     DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseover);
207     DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseup);
208     DEFINE_ATTRIBUTE_EVENT_LISTENER(mousewheel);
209     DEFINE_ATTRIBUTE_EVENT_LISTENER(scroll);
210     DEFINE_ATTRIBUTE_EVENT_LISTENER(select);
211     DEFINE_ATTRIBUTE_EVENT_LISTENER(submit);
212
213     // These four attribute event handler attributes are overridden by HTMLBodyElement
214     // and HTMLFrameSetElement to forward to the DOMWindow.
215     DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(blur);
216     DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(error);
217     DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(focus);
218     DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(load);
219
220     // WebKit extensions
221     DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut);
222     DEFINE_ATTRIBUTE_EVENT_LISTENER(cut);
223     DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecopy);
224     DEFINE_ATTRIBUTE_EVENT_LISTENER(copy);
225     DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste);
226     DEFINE_ATTRIBUTE_EVENT_LISTENER(paste);
227     DEFINE_ATTRIBUTE_EVENT_LISTENER(reset);
228     DEFINE_ATTRIBUTE_EVENT_LISTENER(search);
229     DEFINE_ATTRIBUTE_EVENT_LISTENER(selectstart);
230 #if ENABLE(TOUCH_EVENTS)
231     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart);
232     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove);
233     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend);
234     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel);
235 #endif
236 #if ENABLE(FULLSCREEN_API)
237     DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenchange);
238     DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenerror);
239 #endif
240
241     bool hasAttribute(const QualifiedName&) const;
242     const AtomicString& getAttribute(const QualifiedName&) const;
243     void setAttribute(const QualifiedName&, const AtomicString& value);
244     void setSynchronizedLazyAttribute(const QualifiedName&, const AtomicString& value);
245     void removeAttribute(const QualifiedName&);
246
247     // Typed getters and setters for language bindings.
248     int getIntegralAttribute(const QualifiedName& attributeName) const;
249     void setIntegralAttribute(const QualifiedName& attributeName, int value);
250     unsigned getUnsignedIntegralAttribute(const QualifiedName& attributeName) const;
251     void setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value);
252
253     // Call this to get the value of an attribute that is known not to be the style
254     // attribute or one of the SVG animatable attributes.
255     bool fastHasAttribute(const QualifiedName&) const;
256     const AtomicString& fastGetAttribute(const QualifiedName&) const;
257 #ifndef NDEBUG
258     bool fastAttributeLookupAllowed(const QualifiedName&) const;
259 #endif
260
261 #ifdef DUMP_NODE_STATISTICS
262     bool hasNamedNodeMap() const;
263 #endif
264     bool hasAttributes() const;
265     // This variant will not update the potentially invalid attributes. To be used when not interested
266     // in style attribute or one of the SVG animation attributes.
267     bool hasAttributesWithoutUpdate() const;
268
269     bool hasAttribute(const AtomicString& name) const;
270     bool hasAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const;
271
272     const AtomicString& getAttribute(const AtomicString& name) const;
273     const AtomicString& getAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const;
274
275     void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode&);
276     static bool parseAttributeName(QualifiedName&, const AtomicString& namespaceURI, const AtomicString& qualifiedName, ExceptionCode&);
277     void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode&);
278
279     bool isIdAttributeName(const QualifiedName&) const;
280     const AtomicString& getIdAttribute() const;
281     void setIdAttribute(const AtomicString&);
282
283     const AtomicString& getNameAttribute() const;
284
285     // Call this to get the value of the id attribute for style resolution purposes.
286     // The value will already be lowercased if the document is in compatibility mode,
287     // so this function is not suitable for non-style uses.
288     const AtomicString& idForStyleResolution() const;
289
290     // Internal methods that assume the existence of attribute storage, one should use hasAttributes()
291     // before calling them.
292     unsigned attributeCount() const;
293     const Attribute* attributeItem(unsigned index) const;
294     const Attribute* getAttributeItem(const QualifiedName&) const;
295     unsigned getAttributeItemIndex(const QualifiedName& name) const { return elementData()->getAttributeItemIndex(name); }
296     unsigned getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const { return elementData()->getAttributeItemIndex(name, shouldIgnoreAttributeCase); }
297
298     void scrollIntoView(bool alignToTop = true);
299     void scrollIntoViewIfNeeded(bool centerIfNeeded = true);
300
301     void scrollByLines(int lines);
302     void scrollByPages(int pages);
303
304     int offsetLeft();
305     int offsetTop();
306     int offsetWidth();
307     int offsetHeight();
308
309     // FIXME: Replace uses of offsetParent in the platform with calls
310     // to the render layer and merge bindingsOffsetParent and offsetParent.
311     Element* bindingsOffsetParent();
312
313     Element* offsetParent();
314     int clientLeft();
315     int clientTop();
316     int clientWidth();
317     int clientHeight();
318     virtual int scrollLeft();
319     virtual int scrollTop();
320     virtual void setScrollLeft(int);
321     virtual void setScrollTop(int);
322     virtual int scrollWidth();
323     virtual int scrollHeight();
324
325     IntRect boundsInRootViewSpace();
326
327     PassRefPtr<ClientRectList> getClientRects();
328     PassRefPtr<ClientRect> getBoundingClientRect();
329     
330     // Returns the absolute bounding box translated into screen coordinates:
331     IntRect screenRect() const;
332
333     void removeAttribute(const AtomicString& name);
334     void removeAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName);
335
336     PassRefPtr<Attr> detachAttribute(unsigned index);
337
338     PassRefPtr<Attr> getAttributeNode(const AtomicString& name);
339     PassRefPtr<Attr> getAttributeNodeNS(const AtomicString& namespaceURI, const AtomicString& localName);
340     PassRefPtr<Attr> setAttributeNode(Attr*, ExceptionCode&);
341     PassRefPtr<Attr> setAttributeNodeNS(Attr*, ExceptionCode&);
342     PassRefPtr<Attr> removeAttributeNode(Attr*, ExceptionCode&);
343
344     PassRefPtr<Attr> attrIfExists(const QualifiedName&);
345     PassRefPtr<Attr> ensureAttr(const QualifiedName&);
346
347     const Vector<RefPtr<Attr> >& attrNodeList();
348
349     virtual CSSStyleDeclaration* style();
350
351     const QualifiedName& tagQName() const { return m_tagName; }
352     String tagName() const { return nodeName(); }
353     bool hasTagName(const QualifiedName& tagName) const { return m_tagName.matches(tagName); }
354     
355     // A fast function for checking the local name against another atomic string.
356     bool hasLocalName(const AtomicString& other) const { return m_tagName.localName() == other; }
357     bool hasLocalName(const QualifiedName& other) const { return m_tagName.localName() == other.localName(); }
358
359     const AtomicString& localName() const { return m_tagName.localName(); }
360     const AtomicString& prefix() const { return m_tagName.prefix(); }
361     const AtomicString& namespaceURI() const { return m_tagName.namespaceURI(); }
362
363     virtual KURL baseURI() const;
364
365     virtual String nodeName() const;
366
367     PassRefPtr<Element> cloneElementWithChildren();
368     PassRefPtr<Element> cloneElementWithoutChildren();
369
370     void normalizeAttributes();
371     String nodeNamePreservingCase() const;
372
373     void setBooleanAttribute(const QualifiedName& name, bool);
374
375     // For exposing to DOM only.
376     NamedNodeMap* attributes() const;
377
378     enum AttributeModificationReason {
379         ModifiedDirectly,
380         ModifiedByCloning
381     };
382
383     // This method is called whenever an attribute is added, changed or removed.
384     virtual void attributeChanged(const QualifiedName&, const AtomicString&, AttributeModificationReason = ModifiedDirectly);
385     virtual void parseAttribute(const QualifiedName&, const AtomicString&) { }
386
387     // Only called by the parser immediately after element construction.
388     void parserSetAttributes(const Vector<Attribute>&);
389
390     // Remove attributes that might introduce scripting from the vector leaving the element unchanged.
391     void stripScriptingAttributes(Vector<Attribute>&) const;
392
393     const ElementData* elementData() const { return m_elementData.get(); }
394     UniqueElementData* ensureUniqueElementData();
395
396     void synchronizeAllAttributes() const;
397
398     // Clones attributes only.
399     void cloneAttributesFromElement(const Element&);
400
401     // Clones all attribute-derived data, including subclass specifics (through copyNonAttributeProperties.)
402     void cloneDataFromElement(const Element&);
403
404     bool hasEquivalentAttributes(const Element* other) const;
405
406     virtual void copyNonAttributePropertiesFromElement(const Element&) { }
407
408     virtual void attach();
409     virtual void detach();
410     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
411     virtual bool rendererIsNeeded(const NodeRenderingContext&);
412     void recalcStyle(StyleChange = NoChange);
413     void didAffectSelector(AffectedSelectorMask);
414
415     ElementShadow* shadow() const;
416     ElementShadow* ensureShadow();
417     PassRefPtr<ShadowRoot> createShadowRoot(ExceptionCode&);
418     ShadowRoot* authorShadowRoot() const;
419
420     bool hasAuthorShadowRoot() const { return authorShadowRoot(); }
421     virtual void willAddAuthorShadowRoot() { }
422
423     ShadowRoot* userAgentShadowRoot() const;
424     ShadowRoot* ensureUserAgentShadowRoot();
425
426     virtual const AtomicString& shadowPseudoId() const;
427
428     RenderStyle* computedStyle(PseudoId = NOPSEUDO);
429
430     // Methods for indicating the style is affected by dynamic updates (e.g., children changing, our position changing in our sibling list, etc.)
431     bool styleAffectedByEmpty() const { return hasRareData() && rareDataStyleAffectedByEmpty(); }
432     bool childrenAffectedByHover() const { return hasRareData() && rareDataChildrenAffectedByHover(); }
433     bool childrenAffectedByActive() const { return hasRareData() && rareDataChildrenAffectedByActive(); }
434     bool childrenAffectedByDrag() const { return hasRareData() && rareDataChildrenAffectedByDrag(); }
435     bool childrenAffectedByPositionalRules() const { return hasRareData() && (rareDataChildrenAffectedByForwardPositionalRules() || rareDataChildrenAffectedByBackwardPositionalRules()); }
436     bool childrenAffectedByFirstChildRules() const { return hasRareData() && rareDataChildrenAffectedByFirstChildRules(); }
437     bool childrenAffectedByLastChildRules() const { return hasRareData() && rareDataChildrenAffectedByLastChildRules(); }
438     bool childrenAffectedByDirectAdjacentRules() const { return hasRareData() && rareDataChildrenAffectedByDirectAdjacentRules(); }
439     bool childrenAffectedByForwardPositionalRules() const { return hasRareData() && rareDataChildrenAffectedByForwardPositionalRules(); }
440     bool childrenAffectedByBackwardPositionalRules() const { return hasRareData() && rareDataChildrenAffectedByBackwardPositionalRules(); }
441     unsigned childIndex() const { return hasRareData() ? rareDataChildIndex() : 0; }
442
443     bool hasFlagsSetDuringStylingOfChildren() const;
444
445     void setStyleAffectedByEmpty();
446     void setChildrenAffectedByHover(bool);
447     void setChildrenAffectedByActive(bool);
448     void setChildrenAffectedByDrag(bool);
449     void setChildrenAffectedByFirstChildRules();
450     void setChildrenAffectedByLastChildRules();
451     void setChildrenAffectedByDirectAdjacentRules();
452     void setChildrenAffectedByForwardPositionalRules();
453     void setChildrenAffectedByBackwardPositionalRules();
454     void setChildIndex(unsigned);
455
456     void setIsInCanvasSubtree(bool);
457     bool isInCanvasSubtree() const;
458
459     AtomicString computeInheritedLanguage() const;
460     Locale& locale() const;
461
462     virtual void accessKeyAction(bool /*sendToAnyEvent*/) { }
463
464     virtual bool isURLAttribute(const Attribute&) const { return false; }
465     virtual bool isHTMLContentAttribute(const Attribute&) const { return false; }
466
467     KURL getURLAttribute(const QualifiedName&) const;
468     KURL getNonEmptyURLAttribute(const QualifiedName&) const;
469
470     virtual const AtomicString& imageSourceURL() const;
471     virtual String target() const { return String(); }
472
473     virtual void focus(bool restorePreviousSelection = true, FocusDirection = FocusDirectionNone);
474     virtual void updateFocusAppearance(bool restorePreviousSelection);
475     virtual void blur();
476
477     String innerText();
478     String outerText();
479  
480     virtual String title() const;
481
482     const AtomicString& pseudo() const;
483     void setPseudo(const AtomicString&);
484
485     LayoutSize minimumSizeForResizing() const;
486     void setMinimumSizeForResizing(const LayoutSize&);
487
488     // Use Document::registerForDocumentActivationCallbacks() to subscribe to these
489     virtual void documentWillSuspendForPageCache() { }
490     virtual void documentDidResumeFromPageCache() { }
491
492     // Use Document::registerForMediaVolumeCallbacks() to subscribe to this
493     virtual void mediaVolumeDidChange() { }
494
495     // Use Document::registerForPrivateBrowsingStateChangedCallbacks() to subscribe to this.
496     virtual void privateBrowsingStateDidChange() { }
497
498     virtual void didBecomeFullscreenElement() { }
499     virtual void willStopBeingFullscreenElement() { }
500
501 #if ENABLE(VIDEO_TRACK)
502     virtual void captionPreferencesChanged() { }
503 #endif
504
505     bool isFinishedParsingChildren() const { return isParsingChildrenFinished(); }
506     virtual void finishParsingChildren();
507     virtual void beginParsingChildren();
508
509     bool hasPseudoElements() const;
510     PseudoElement* pseudoElement(PseudoId) const;
511     RenderObject* pseudoElementRenderer(PseudoId) const;
512     bool childNeedsShadowWalker() const;
513     void didShadowTreeAwareChildrenChange();
514
515     // ElementTraversal API
516     Element* firstElementChild() const;
517     Element* lastElementChild() const;
518     Element* previousElementSibling() const;
519     Element* nextElementSibling() const;
520     unsigned childElementCount() const;
521
522     virtual bool matchesReadOnlyPseudoClass() const;
523     virtual bool matchesReadWritePseudoClass() const;
524     bool webkitMatchesSelector(const String& selectors, ExceptionCode&);
525     virtual bool shouldAppearIndeterminate() const;
526
527     DOMTokenList* classList();
528
529     DOMStringMap* dataset();
530
531 #if ENABLE(MATHML)
532     virtual bool isMathMLElement() const { return false; }
533 #else
534     static bool isMathMLElement() { return false; }
535 #endif
536
537 #if ENABLE(VIDEO)
538     virtual bool isMediaElement() const { return false; }
539 #endif
540
541 #if ENABLE(INPUT_SPEECH)
542     virtual bool isInputFieldSpeechButtonElement() const { return false; }
543 #endif
544 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
545     virtual bool isDateTimeFieldElement() const;
546 #endif
547
548     virtual bool isFormControlElement() const { return false; }
549     virtual bool isSpinButtonElement() const { return false; }
550     virtual bool isTextFormControl() const { return false; }
551     virtual bool isOptionalFormControl() const { return false; }
552     virtual bool isRequiredFormControl() const { return false; }
553     virtual bool isDefaultButtonForForm() const { return false; }
554     virtual bool willValidate() const { return false; }
555     virtual bool isValidFormControlElement() { return false; }
556     virtual bool isInRange() const { return false; }
557     virtual bool isOutOfRange() const { return false; }
558     virtual bool isFrameElementBase() const { return false; }
559
560     virtual bool canContainRangeEndPoint() const { return true; }
561
562     virtual const AtomicString& formControlType() const { return nullAtom; }
563
564     virtual bool wasChangedSinceLastFormControlChangeEvent() const;
565     virtual void setChangedSinceLastFormControlChangeEvent(bool);
566     virtual void dispatchFormControlChangeEvent() { }
567
568     // Used for disabled form elements; if true, prevents mouse events from being dispatched
569     // to event listeners, and prevents DOMActivate events from being sent at all.
570     virtual bool isDisabledFormControl() const;
571
572 #if ENABLE(DIALOG_ELEMENT)
573     bool isInert() const;
574 #endif
575
576 #if ENABLE(SVG)
577     virtual bool childShouldCreateRenderer(const NodeRenderingContext&) const;
578     bool hasPendingResources() const;
579     void setHasPendingResources();
580     void clearHasPendingResources();
581     virtual void buildPendingResource() { };
582 #endif
583
584 #if ENABLE(FULLSCREEN_API)
585     enum {
586         ALLOW_KEYBOARD_INPUT = 1 << 0,
587         LEGACY_MOZILLA_REQUEST = 1 << 1,
588     };
589     
590     void webkitRequestFullScreen(unsigned short flags);
591     virtual bool containsFullScreenElement() const;
592     virtual void setContainsFullScreenElement(bool);
593     virtual void setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(bool);
594
595     // W3C API
596     void webkitRequestFullscreen();
597 #endif
598
599 #if ENABLE(DIALOG_ELEMENT)
600     bool isInTopLayer() const;
601     void setIsInTopLayer(bool);
602 #endif
603
604 #if ENABLE(POINTER_LOCK)
605     void webkitRequestPointerLock();
606 #endif
607
608     virtual bool isSpellCheckingEnabled() const;
609
610     PassRefPtr<RenderStyle> styleForRenderer();
611
612     RenderRegion* renderRegion() const;
613     virtual bool moveToFlowThreadIsNeeded(RefPtr<RenderStyle>& cachedStyle);
614 #if ENABLE(CSS_REGIONS)
615     const AtomicString& webkitRegionOverset() const;
616     Vector<RefPtr<Range> > webkitGetRegionFlowRanges() const;
617 #endif
618
619     bool hasID() const;
620     bool hasClass() const;
621     const SpaceSplitString& classNames() const;
622
623     IntSize savedLayerScrollOffset() const;
624     void setSavedLayerScrollOffset(const IntSize&);
625
626 protected:
627     Element(const QualifiedName& tagName, Document* document, ConstructionType type)
628         : ContainerNode(document, type)
629         , m_tagName(tagName)
630     {
631     }
632
633     virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
634     virtual void removedFrom(ContainerNode*) OVERRIDE;
635     virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
636     virtual void removeAllEventListeners() OVERRIDE;
637
638     virtual bool willRecalcStyle(StyleChange);
639     virtual void didRecalcStyle(StyleChange);
640     virtual PassRefPtr<RenderStyle> customStyleForRenderer();
641
642     void clearTabIndexExplicitlyIfNeeded();    
643     void setTabIndexExplicitly(short);
644     virtual bool supportsFocus() const OVERRIDE;
645     virtual short tabIndex() const OVERRIDE;
646
647     PassRefPtr<HTMLCollection> ensureCachedHTMLCollection(CollectionType);
648     HTMLCollection* cachedHTMLCollection(CollectionType);
649
650     // classAttributeChanged() exists to share code between
651     // parseAttribute (called via setAttribute()) and
652     // svgAttributeChanged (called when element.className.baseValue is set)
653     void classAttributeChanged(const AtomicString& newClassString);
654
655 private:
656     void updatePseudoElement(PseudoId, StyleChange = NoChange);
657     PassRefPtr<PseudoElement> createPseudoElementIfNeeded(PseudoId);
658     void setPseudoElement(PseudoId, PassRefPtr<PseudoElement>);
659
660     virtual bool areAuthorShadowsAllowed() const { return true; }
661     virtual void didAddUserAgentShadowRoot(ShadowRoot*) { }
662     virtual bool alwaysCreateUserAgentShadowRoot() const { return false; }
663
664     // FIXME: Remove the need for Attr to call willModifyAttribute/didModifyAttribute.
665     friend class Attr;
666
667     enum SynchronizationOfLazyAttribute { NotInSynchronizationOfLazyAttribute = 0, InSynchronizationOfLazyAttribute };
668
669     void didAddAttribute(const QualifiedName&, const AtomicString&);
670     void willModifyAttribute(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue);
671     void didModifyAttribute(const QualifiedName&, const AtomicString&);
672     void didRemoveAttribute(const QualifiedName&);
673
674     void synchronizeAttribute(const QualifiedName&) const;
675     void synchronizeAttribute(const AtomicString& localName) const;
676
677     void updateId(const AtomicString& oldId, const AtomicString& newId);
678     void updateId(TreeScope*, const AtomicString& oldId, const AtomicString& newId);
679     void updateName(const AtomicString& oldName, const AtomicString& newName);
680     void updateName(TreeScope*, const AtomicString& oldName, const AtomicString& newName);
681     void updateLabel(TreeScope*, const AtomicString& oldForAttributeValue, const AtomicString& newForAttributeValue);
682
683     void scrollByUnits(int units, ScrollGranularity);
684
685     virtual void setPrefix(const AtomicString&, ExceptionCode&);
686     virtual NodeType nodeType() const;
687     virtual bool childTypeAllowed(NodeType) const;
688
689     void setAttributeInternal(unsigned index, const QualifiedName&, const AtomicString& value, SynchronizationOfLazyAttribute);
690     void addAttributeInternal(const QualifiedName&, const AtomicString& value, SynchronizationOfLazyAttribute);
691     void removeAttributeInternal(unsigned index, SynchronizationOfLazyAttribute);
692     void attributeChangedFromParserOrByCloning(const QualifiedName&, const AtomicString&, AttributeModificationReason);
693
694 #ifndef NDEBUG
695     virtual void formatForDebugger(char* buffer, unsigned length) const;
696 #endif
697
698     bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle);
699
700     void cancelFocusAppearanceUpdate();
701
702     virtual const AtomicString& virtualPrefix() const { return prefix(); }
703     virtual const AtomicString& virtualLocalName() const { return localName(); }
704     virtual const AtomicString& virtualNamespaceURI() const { return namespaceURI(); }
705     virtual RenderStyle* virtualComputedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return computedStyle(pseudoElementSpecifier); }
706     
707     // cloneNode is private so that non-virtual cloneElementWithChildren and cloneElementWithoutChildren
708     // are used instead.
709     virtual PassRefPtr<Node> cloneNode(bool deep) OVERRIDE;
710     virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren();
711
712     QualifiedName m_tagName;
713     bool rareDataStyleAffectedByEmpty() const;
714     bool rareDataChildrenAffectedByHover() const;
715     bool rareDataChildrenAffectedByActive() const;
716     bool rareDataChildrenAffectedByDrag() const;
717     bool rareDataChildrenAffectedByFirstChildRules() const;
718     bool rareDataChildrenAffectedByLastChildRules() const;
719     bool rareDataChildrenAffectedByDirectAdjacentRules() const;
720     bool rareDataChildrenAffectedByForwardPositionalRules() const;
721     bool rareDataChildrenAffectedByBackwardPositionalRules() const;
722     unsigned rareDataChildIndex() const;
723
724     SpellcheckAttributeState spellcheckAttributeState() const;
725
726     void unregisterNamedFlowContentNode();
727
728     void createUniqueElementData();
729
730     ElementRareData* elementRareData() const;
731     ElementRareData* ensureElementRareData();
732
733     void detachAllAttrNodesFromElement();
734     void detachAttrNodeFromElementWithValue(Attr*, const AtomicString& value);
735
736     void createRendererIfNeeded();
737
738     bool isJavaScriptURLAttribute(const Attribute&) const;
739
740     RefPtr<ElementData> m_elementData;
741 };
742     
743 inline Element* toElement(Node* node)
744 {
745     ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isElementNode());
746     return static_cast<Element*>(node);
747 }
748
749 inline const Element* toElement(const Node* node)
750 {
751     ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isElementNode());
752     return static_cast<const Element*>(node);
753 }
754
755 // This will catch anyone doing an unnecessary cast.
756 void toElement(const Element*);
757
758 inline bool isDisabledFormControl(const Node* node)
759 {
760     return node->isElementNode() && toElement(node)->isDisabledFormControl();
761 }
762
763 inline bool Node::hasTagName(const QualifiedName& name) const
764 {
765     return isElementNode() && toElement(this)->hasTagName(name);
766 }
767     
768 inline bool Node::hasLocalName(const AtomicString& name) const
769 {
770     return isElementNode() && toElement(this)->hasLocalName(name);
771 }
772
773 inline bool Node::hasAttributes() const
774 {
775     return isElementNode() && toElement(this)->hasAttributes();
776 }
777
778 inline NamedNodeMap* Node::attributes() const
779 {
780     return isElementNode() ? toElement(this)->attributes() : 0;
781 }
782
783 inline Element* Node::parentElement() const
784 {
785     ContainerNode* parent = parentNode();
786     return parent && parent->isElementNode() ? toElement(parent) : 0;
787 }
788
789 inline Element* Element::previousElementSibling() const
790 {
791     Node* n = previousSibling();
792     while (n && !n->isElementNode())
793         n = n->previousSibling();
794     return static_cast<Element*>(n);
795 }
796
797 inline Element* Element::nextElementSibling() const
798 {
799     Node* n = nextSibling();
800     while (n && !n->isElementNode())
801         n = n->nextSibling();
802     return static_cast<Element*>(n);
803 }
804
805 inline bool Element::fastHasAttribute(const QualifiedName& name) const
806 {
807     ASSERT(fastAttributeLookupAllowed(name));
808     return elementData() && getAttributeItem(name);
809 }
810
811 inline const AtomicString& Element::fastGetAttribute(const QualifiedName& name) const
812 {
813     ASSERT(fastAttributeLookupAllowed(name));
814     if (elementData()) {
815         if (const Attribute* attribute = getAttributeItem(name))
816             return attribute->value();
817     }
818     return nullAtom;
819 }
820
821 inline bool Element::hasAttributesWithoutUpdate() const
822 {
823     return elementData() && !elementData()->isEmpty();
824 }
825
826 inline const AtomicString& Element::idForStyleResolution() const
827 {
828     ASSERT(hasID());
829     return elementData()->idForStyleResolution();
830 }
831
832 inline bool Element::isIdAttributeName(const QualifiedName& attributeName) const
833 {
834     // FIXME: This check is probably not correct for the case where the document has an id attribute
835     // with a non-null namespace, because it will return false, a false negative, if the prefixes
836     // don't match but the local name and namespace both do. However, since this has been like this
837     // for a while and the code paths may be hot, we'll have to measure performance if we fix it.
838     return attributeName == document()->idAttributeName();
839 }
840
841 inline const AtomicString& Element::getIdAttribute() const
842 {
843     return hasID() ? fastGetAttribute(document()->idAttributeName()) : nullAtom;
844 }
845
846 inline const AtomicString& Element::getNameAttribute() const
847 {
848     return hasName() ? fastGetAttribute(HTMLNames::nameAttr) : nullAtom;
849 }
850
851 inline void Element::setIdAttribute(const AtomicString& value)
852 {
853     setAttribute(document()->idAttributeName(), value);
854 }
855
856 inline const SpaceSplitString& Element::classNames() const
857 {
858     ASSERT(hasClass());
859     ASSERT(elementData());
860     return elementData()->classNames();
861 }
862
863 inline unsigned Element::attributeCount() const
864 {
865     ASSERT(elementData());
866     return elementData()->length();
867 }
868
869 inline const Attribute* Element::attributeItem(unsigned index) const
870 {
871     ASSERT(elementData());
872     return elementData()->attributeItem(index);
873 }
874
875 inline const Attribute* Element::getAttributeItem(const QualifiedName& name) const
876 {
877     ASSERT(elementData());
878     return elementData()->getAttributeItem(name);
879 }
880
881 inline bool Element::hasID() const
882 {
883     return elementData() && elementData()->hasID();
884 }
885
886 inline bool Element::hasClass() const
887 {
888     return elementData() && elementData()->hasClass();
889 }
890
891 inline UniqueElementData* Element::ensureUniqueElementData()
892 {
893     if (!elementData() || !elementData()->isUnique())
894         createUniqueElementData();
895     return static_cast<UniqueElementData*>(m_elementData.get());
896 }
897
898 // Put here to make them inline.
899 inline bool Node::hasID() const
900 {
901     return isElementNode() && toElement(this)->hasID();
902 }
903
904 inline bool Node::hasClass() const
905 {
906     return isElementNode() && toElement(this)->hasClass();
907 }
908
909 inline Node::InsertionNotificationRequest Node::insertedInto(ContainerNode* insertionPoint)
910 {
911     ASSERT(insertionPoint->inDocument() || isContainerNode());
912     if (insertionPoint->inDocument())
913         setFlag(InDocumentFlag);
914     if (parentOrShadowHostNode()->isInShadowTree())
915         setFlag(IsInShadowTreeFlag);
916     return InsertionDone;
917 }
918
919 inline void Node::removedFrom(ContainerNode* insertionPoint)
920 {
921     ASSERT(insertionPoint->inDocument() || isContainerNode());
922     if (insertionPoint->inDocument())
923         clearFlag(InDocumentFlag);
924     if (isInShadowTree() && !treeScope()->rootNode()->isShadowRoot())
925         clearFlag(IsInShadowTreeFlag);
926 }
927
928 inline bool isShadowHost(const Node* node)
929 {
930     return node && node->isElementNode() && toElement(node)->shadow();
931 }
932
933 inline unsigned ElementData::length() const
934 {
935     if (isUnique())
936         return static_cast<const UniqueElementData*>(this)->m_attributeVector.size();
937     return m_arraySize;
938 }
939
940 inline const Attribute* ElementData::attributeBase() const
941 {
942     if (m_isUnique)
943         return static_cast<const UniqueElementData*>(this)->m_attributeVector.data();
944     return static_cast<const ShareableElementData*>(this)->m_attributeArray;
945 }
946
947 inline const StylePropertySet* ElementData::presentationAttributeStyle() const
948 {
949     if (!m_isUnique)
950         return 0;
951     return static_cast<const UniqueElementData*>(this)->m_presentationAttributeStyle.get();
952 }
953
954 inline const Attribute* ElementData::getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase) const
955 {
956     unsigned index = getAttributeItemIndex(name, shouldIgnoreAttributeCase);
957     if (index != attributeNotFound)
958         return attributeItem(index);
959     return 0;
960 }
961
962 inline unsigned ElementData::getAttributeItemIndex(const QualifiedName& name) const
963 {
964     const Attribute* attributes = attributeBase();
965     for (unsigned i = 0, count = length(); i < count; ++i) {
966         if (attributes[i].name().matches(name))
967             return i;
968     }
969     return attributeNotFound;
970 }
971
972 // We use a boolean parameter instead of calling shouldIgnoreAttributeCase so that the caller
973 // can tune the behavior (hasAttribute is case sensitive whereas getAttribute is not).
974 inline unsigned ElementData::getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const
975 {
976     const Attribute* attributes = attributeBase();
977     bool doSlowCheck = shouldIgnoreAttributeCase;
978     const AtomicString& caseAdjustedName = shouldIgnoreAttributeCase ? name.lower() : name;
979
980     // Optimize for the case where the attribute exists and its name exactly matches.
981     for (unsigned i = 0, count = length(); i < count; ++i) {
982         if (!attributes[i].name().hasPrefix()) {
983             if (caseAdjustedName == attributes[i].localName())
984                 return i;
985         } else
986             doSlowCheck = true;
987     }
988
989     if (doSlowCheck)
990         return getAttributeItemIndexSlowCase(name, shouldIgnoreAttributeCase);
991     return attributeNotFound;
992 }
993
994 inline const Attribute* ElementData::getAttributeItem(const QualifiedName& name) const
995 {
996     const Attribute* attributes = attributeBase();
997     for (unsigned i = 0, count = length(); i < count; ++i) {
998         if (attributes[i].name().matches(name))
999             return &attributes[i];
1000     }
1001     return 0;
1002 }
1003
1004 inline const Attribute* ElementData::attributeItem(unsigned index) const
1005 {
1006     RELEASE_ASSERT(index < length());
1007     return attributeBase() + index;
1008 }
1009
1010 } // namespace
1011
1012 #endif