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