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