94432b45adfc34e4a96bd69163477719005ebdfa
[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 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 "Document.h"
29 #include "FragmentScriptingPermission.h"
30 #include "NamedNodeMap.h"
31 #include "ScrollTypes.h"
32
33 namespace WebCore {
34
35 class Attribute;
36 class ClientRect;
37 class ClientRectList;
38 class DOMStringMap;
39 class DOMTokenList;
40 class ElementRareData;
41 class IntSize;
42 class ShadowRoot;
43 class WebKitAnimationList;
44
45 enum SpellcheckAttributeState {
46     SpellcheckAttributeTrue,
47     SpellcheckAttributeFalse,
48     SpellcheckAttributeDefault
49 };
50
51 class Element : public ContainerNode {
52 public:
53     static PassRefPtr<Element> create(const QualifiedName&, Document*);
54     virtual ~Element();
55
56     DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
57     DEFINE_ATTRIBUTE_EVENT_LISTENER(change);
58     DEFINE_ATTRIBUTE_EVENT_LISTENER(click);
59     DEFINE_ATTRIBUTE_EVENT_LISTENER(contextmenu);
60     DEFINE_ATTRIBUTE_EVENT_LISTENER(dblclick);
61     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragenter);
62     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragover);
63     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragleave);
64     DEFINE_ATTRIBUTE_EVENT_LISTENER(drop);
65     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragstart);
66     DEFINE_ATTRIBUTE_EVENT_LISTENER(drag);
67     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragend);
68     DEFINE_ATTRIBUTE_EVENT_LISTENER(input);
69     DEFINE_ATTRIBUTE_EVENT_LISTENER(invalid);
70     DEFINE_ATTRIBUTE_EVENT_LISTENER(keydown);
71     DEFINE_ATTRIBUTE_EVENT_LISTENER(keypress);
72     DEFINE_ATTRIBUTE_EVENT_LISTENER(keyup);
73     DEFINE_ATTRIBUTE_EVENT_LISTENER(mousedown);
74     DEFINE_ATTRIBUTE_EVENT_LISTENER(mousemove);
75     DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseout);
76     DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseover);
77     DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseup);
78     DEFINE_ATTRIBUTE_EVENT_LISTENER(mousewheel);
79     DEFINE_ATTRIBUTE_EVENT_LISTENER(scroll);
80     DEFINE_ATTRIBUTE_EVENT_LISTENER(select);
81     DEFINE_ATTRIBUTE_EVENT_LISTENER(submit);
82
83     // These four attribute event handler attributes are overridden by HTMLBodyElement
84     // and HTMLFrameSetElement to forward to the DOMWindow.
85     DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(blur);
86     DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(error);
87     DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(focus);
88     DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(load);
89
90     // WebKit extensions
91     DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut);
92     DEFINE_ATTRIBUTE_EVENT_LISTENER(cut);
93     DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecopy);
94     DEFINE_ATTRIBUTE_EVENT_LISTENER(copy);
95     DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste);
96     DEFINE_ATTRIBUTE_EVENT_LISTENER(paste);
97     DEFINE_ATTRIBUTE_EVENT_LISTENER(reset);
98     DEFINE_ATTRIBUTE_EVENT_LISTENER(search);
99     DEFINE_ATTRIBUTE_EVENT_LISTENER(selectstart);
100 #if ENABLE(TOUCH_EVENTS)
101     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart);
102     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove);
103     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend);
104     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel);
105 #endif
106 #if ENABLE(FULLSCREEN_API)
107     DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenchange);
108 #endif
109
110     virtual PassRefPtr<DocumentFragment> deprecatedCreateContextualFragment(const String&, FragmentScriptingPermission = FragmentScriptingAllowed);
111
112     bool hasAttribute(const QualifiedName&) const;
113     const AtomicString& getAttribute(const QualifiedName&) const;
114     void setAttribute(const QualifiedName&, const AtomicString& value, ExceptionCode&);
115     void removeAttribute(const QualifiedName&, ExceptionCode&);
116
117     // Typed getters and setters for language bindings.
118     int getIntegralAttribute(const QualifiedName& attributeName) const;
119     void setIntegralAttribute(const QualifiedName& attributeName, int value);
120     unsigned getUnsignedIntegralAttribute(const QualifiedName& attributeName) const;
121     void setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value);
122
123     // Call this to get the value of an attribute that is known not to be the style
124     // attribute or one of the SVG animatable attributes.
125     bool fastHasAttribute(const QualifiedName&) const;
126     const AtomicString& fastGetAttribute(const QualifiedName&) const;
127
128     bool hasAttributes() const;
129
130     bool hasAttribute(const String& name) const;
131     bool hasAttributeNS(const String& namespaceURI, const String& localName) const;
132
133     const AtomicString& getAttribute(const String& name) const;
134     const AtomicString& getAttributeNS(const String& namespaceURI, const String& localName) const;
135
136     void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode&);
137     void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode&, FragmentScriptingPermission = FragmentScriptingAllowed);
138
139     bool isIdAttributeName(const QualifiedName&) const;
140     const AtomicString& getIdAttribute() const;
141     void setIdAttribute(const AtomicString&);
142
143     // Call this to get the value of the id attribute for style resolution purposes.
144     // The value will already be lowercased if the document is in compatibility mode,
145     // so this function is not suitable for non-style uses.
146     const AtomicString& idForStyleResolution() const;
147
148     void scrollIntoView(bool alignToTop = true);
149     void scrollIntoViewIfNeeded(bool centerIfNeeded = true);
150
151     void scrollByLines(int lines);
152     void scrollByPages(int pages);
153
154     int offsetLeft();
155     int offsetTop();
156     int offsetWidth();
157     int offsetHeight();
158     Element* offsetParent();
159     int clientLeft();
160     int clientTop();
161     int clientWidth();
162     int clientHeight();
163     virtual int scrollLeft() const;
164     virtual int scrollTop() const;
165     virtual void setScrollLeft(int);
166     virtual void setScrollTop(int);
167     virtual int scrollWidth() const;
168     virtual int scrollHeight() const;
169
170     IntRect boundsInWindowSpace() const;
171
172     PassRefPtr<ClientRectList> getClientRects() const;
173     PassRefPtr<ClientRect> getBoundingClientRect() const;
174     
175     // Returns the absolute bounding box translated into screen coordinates:
176     IntRect screenRect() const;
177
178     void removeAttribute(const String& name, ExceptionCode&);
179     void removeAttributeNS(const String& namespaceURI, const String& localName, ExceptionCode&);
180
181     PassRefPtr<Attr> getAttributeNode(const String& name);
182     PassRefPtr<Attr> getAttributeNodeNS(const String& namespaceURI, const String& localName);
183     PassRefPtr<Attr> setAttributeNode(Attr*, ExceptionCode&);
184     PassRefPtr<Attr> setAttributeNodeNS(Attr*, ExceptionCode&);
185     PassRefPtr<Attr> removeAttributeNode(Attr*, ExceptionCode&);
186     
187     virtual CSSStyleDeclaration* style();
188
189     const QualifiedName& tagQName() const { return m_tagName; }
190     String tagName() const { return nodeName(); }
191     bool hasTagName(const QualifiedName& tagName) const { return m_tagName.matches(tagName); }
192     
193     // A fast function for checking the local name against another atomic string.
194     bool hasLocalName(const AtomicString& other) const { return m_tagName.localName() == other; }
195     bool hasLocalName(const QualifiedName& other) const { return m_tagName.localName() == other.localName(); }
196
197     const AtomicString& localName() const { return m_tagName.localName(); }
198     const AtomicString& prefix() const { return m_tagName.prefix(); }
199     const AtomicString& namespaceURI() const { return m_tagName.namespaceURI(); }
200
201     virtual KURL baseURI() const;
202
203     virtual String nodeName() const;
204
205     PassRefPtr<Element> cloneElementWithChildren();
206     PassRefPtr<Element> cloneElementWithoutChildren();
207
208     void normalizeAttributes();
209     String nodeNamePreservingCase() const;
210
211     // convenience methods which ignore exceptions
212     void setAttribute(const QualifiedName&, const AtomicString& value);
213     void setBooleanAttribute(const QualifiedName& name, bool);
214     // Please don't use setCStringAttribute in performance-sensitive code;
215     // use a static AtomicString value instead to avoid the conversion overhead.
216     void setCStringAttribute(const QualifiedName&, const char* cStringValue);
217
218     NamedNodeMap* attributes(bool readonly = false) const;
219
220     // This method is called whenever an attribute is added, changed or removed.
221     virtual void attributeChanged(Attribute*, bool preserveDecls = false);
222
223     void setAttributeMap(PassRefPtr<NamedNodeMap>, FragmentScriptingPermission = FragmentScriptingAllowed);
224     NamedNodeMap* attributeMap() const { return m_attributeMap.get(); }
225
226     virtual void copyNonAttributeProperties(const Element* source);
227
228     virtual void attach();
229     virtual void detach();
230     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
231     virtual void recalcStyle(StyleChange = NoChange);
232
233     ShadowRoot* shadowRoot() const;
234     void setShadowRoot(PassRefPtr<ShadowRoot>, ExceptionCode&);
235     ShadowRoot* ensureShadowRoot();
236     void removeShadowRoot();
237
238     virtual const AtomicString& shadowPseudoId() const;
239     void setShadowPseudoId(const AtomicString&, ExceptionCode&);
240
241     RenderStyle* computedStyle(PseudoId = NOPSEUDO);
242
243     AtomicString computeInheritedLanguage() const;
244
245     void dispatchAttrRemovalEvent(Attribute*);
246     void dispatchAttrAdditionEvent(Attribute*);
247
248     virtual void accessKeyAction(bool /*sendToAnyEvent*/) { }
249
250     virtual bool isURLAttribute(Attribute*) const;
251
252     KURL getURLAttribute(const QualifiedName&) const;
253     KURL getNonEmptyURLAttribute(const QualifiedName&) const;
254
255     virtual const QualifiedName& imageSourceAttributeName() const;
256     virtual String target() const { return String(); }
257
258     virtual void focus(bool restorePreviousSelection = true);
259     virtual void updateFocusAppearance(bool restorePreviousSelection);
260     void blur();
261
262     String innerText() const;
263     String outerText() const;
264  
265     virtual String title() const;
266
267     String openTagStartToString() const;
268
269     void updateId(const AtomicString& oldId, const AtomicString& newId);
270
271     IntSize minimumSizeForResizing() const;
272     void setMinimumSizeForResizing(const IntSize&);
273
274     // Use Document::registerForDocumentActivationCallbacks() to subscribe to these
275     virtual void documentWillBecomeInactive() { }
276     virtual void documentDidBecomeActive() { }
277
278     // Use Document::registerForMediaVolumeCallbacks() to subscribe to this
279     virtual void mediaVolumeDidChange() { }
280
281     // Use Document::registerForPrivateBrowsingStateChangedCallbacks() to subscribe to this.
282     virtual void privateBrowsingStateDidChange() { }
283
284     virtual void didBecomeFullscreenElement() { }
285     virtual void willStopBeingFullscreenElement() { }
286
287     bool isFinishedParsingChildren() const { return isParsingChildrenFinished(); }
288     virtual void finishParsingChildren();
289     virtual void beginParsingChildren();
290
291     // ElementTraversal API
292     Element* firstElementChild() const;
293     Element* lastElementChild() const;
294     Element* previousElementSibling() const;
295     Element* nextElementSibling() const;
296     unsigned childElementCount() const;
297
298     bool webkitMatchesSelector(const String& selectors, ExceptionCode&);
299
300     DOMTokenList* classList();
301     DOMTokenList* optionalClassList() const;
302
303     DOMStringMap* dataset();
304
305 #if ENABLE(MATHML)
306     virtual bool isMathMLElement() const { return false; }
307 #else
308     static bool isMathMLElement() { return false; }
309 #endif
310
311 #if ENABLE(VIDEO)
312     virtual bool isMediaElement() const { return false; }
313 #endif
314
315 #if ENABLE(INPUT_SPEECH)
316     virtual bool isInputFieldSpeechButtonElement() const { return false; }
317 #endif
318
319     virtual bool isFormControlElement() const { return false; }
320     virtual bool isEnabledFormControl() const { return true; }
321     virtual bool isReadOnlyFormControl() const { return false; }
322     virtual bool isSpinButtonElement() const { return false; }
323     virtual bool isTextFormControl() const { return false; }
324     virtual bool isOptionalFormControl() const { return false; }
325     virtual bool isRequiredFormControl() const { return false; }
326     virtual bool isDefaultButtonForForm() const { return false; }
327     virtual bool willValidate() const { return false; }
328     virtual bool isValidFormControlElement() { return false; }
329     virtual bool hasUnacceptableValue() const { return false; }
330     virtual bool isInRange() const { return false; }
331     virtual bool isOutOfRange() const { return false; }
332     virtual bool isFrameElementBase() const { return false; }
333
334     virtual bool canContainRangeEndPoint() const { return true; }
335
336     virtual bool formControlValueMatchesRenderer() const { return false; }
337     virtual void setFormControlValueMatchesRenderer(bool) { }
338
339     virtual const AtomicString& formControlName() const { return nullAtom; }
340     virtual const AtomicString& formControlType() const { return nullAtom; }
341
342     virtual bool shouldSaveAndRestoreFormControlState() const { return true; }
343     virtual bool saveFormControlState(String&) const { return false; }
344     virtual void restoreFormControlState(const String&) { }
345
346     virtual bool wasChangedSinceLastFormControlChangeEvent() const;
347     virtual void setChangedSinceLastFormControlChangeEvent(bool);
348     virtual void dispatchFormControlChangeEvent() { }
349
350 #if ENABLE(SVG)
351     virtual bool childShouldCreateRenderer(Node*) const; 
352 #endif
353     
354 #if ENABLE(FULLSCREEN_API)
355     enum {
356         ALLOW_KEYBOARD_INPUT = 1
357     };
358     
359     void webkitRequestFullScreen(unsigned short flags);
360     virtual bool containsFullScreenElement() const;
361     virtual void setContainsFullScreenElement(bool);
362     virtual void setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(bool);
363 #endif
364
365     virtual bool isSpellCheckingEnabled() const;
366
367     PassRefPtr<WebKitAnimationList> webkitGetAnimations() const;
368
369 protected:
370     Element(const QualifiedName& tagName, Document* document, ConstructionType type)
371         : ContainerNode(document, type)
372         , m_tagName(tagName)
373     {
374     }
375
376     virtual void willRemove();
377     virtual void insertedIntoDocument();
378     virtual void removedFromDocument();
379     virtual void insertedIntoTree(bool);
380     virtual void removedFromTree(bool);
381     virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
382
383     // The implementation of Element::attributeChanged() calls the following two functions.
384     // They are separated to allow a different flow of control in StyledElement::attributeChanged().
385     void recalcStyleIfNeededAfterAttributeChanged(Attribute*);
386     void updateAfterAttributeChanged(Attribute*);
387     
388     void idAttributeChanged(Attribute*);
389
390 private:
391     void scrollByUnits(int units, ScrollGranularity);
392
393     virtual void setPrefix(const AtomicString&, ExceptionCode&);
394     virtual NodeType nodeType() const;
395     virtual bool childTypeAllowed(NodeType) const;
396
397     virtual PassRefPtr<Attribute> createAttribute(const QualifiedName&, const AtomicString& value);
398     
399 #ifndef NDEBUG
400     virtual void formatForDebugger(char* buffer, unsigned length) const;
401 #endif
402
403     bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle);
404
405     void createAttributeMap() const;
406
407     virtual void updateStyleAttribute() const { }
408
409 #if ENABLE(SVG)
410     virtual void updateAnimatedSVGAttribute(const QualifiedName&) const { }
411 #endif
412
413     void cancelFocusAppearanceUpdate();
414
415     virtual const AtomicString& virtualPrefix() const { return prefix(); }
416     virtual const AtomicString& virtualLocalName() const { return localName(); }
417     virtual const AtomicString& virtualNamespaceURI() const { return namespaceURI(); }
418     virtual RenderStyle* virtualComputedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return computedStyle(pseudoElementSpecifier); }
419     
420     // cloneNode is private so that non-virtual cloneElementWithChildren and cloneElementWithoutChildren
421     // are used instead.
422     virtual PassRefPtr<Node> cloneNode(bool deep);
423     virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren() const;
424
425     QualifiedName m_tagName;
426     virtual NodeRareData* createRareData();
427
428     ElementRareData* rareData() const;
429     ElementRareData* ensureRareData();
430
431     SpellcheckAttributeState spellcheckAttributeState() const;
432
433 private:
434     mutable RefPtr<NamedNodeMap> m_attributeMap;
435 };
436     
437 inline Element* toElement(Node* node)
438 {
439     ASSERT(!node || node->isElementNode());
440     return static_cast<Element*>(node);
441 }
442
443 inline const Element* toElement(const Node* node)
444 {
445     ASSERT(!node || node->isElementNode());
446     return static_cast<const Element*>(node);
447 }
448
449 // This will catch anyone doing an unnecessary cast.
450 void toElement(const Element*);
451
452 inline bool Node::hasTagName(const QualifiedName& name) const
453 {
454     return isElementNode() && toElement(this)->hasTagName(name);
455 }
456     
457 inline bool Node::hasLocalName(const AtomicString& name) const
458 {
459     return isElementNode() && toElement(this)->hasLocalName(name);
460 }
461
462 inline bool Node::hasAttributes() const
463 {
464     return isElementNode() && toElement(this)->hasAttributes();
465 }
466
467 inline NamedNodeMap* Node::attributes() const
468 {
469     return isElementNode() ? toElement(this)->attributes() : 0;
470 }
471
472 inline Element* Node::parentElement() const
473 {
474     ContainerNode* parent = parentNode();
475     return parent && parent->isElementNode() ? toElement(parent) : 0;
476 }
477
478 inline NamedNodeMap* Element::attributes(bool readonly) const
479 {
480     if (!isStyleAttributeValid())
481         updateStyleAttribute();
482
483 #if ENABLE(SVG)
484     if (!areSVGAttributesValid())
485         updateAnimatedSVGAttribute(anyQName());
486 #endif
487
488     if (!readonly && !m_attributeMap)
489         createAttributeMap();
490     return m_attributeMap.get();
491 }
492
493 inline void Element::updateId(const AtomicString& oldId, const AtomicString& newId)
494 {
495     if (!inDocument())
496         return;
497
498     if (oldId == newId)
499         return;
500
501     TreeScope* scope = treeScope();
502     if (!oldId.isEmpty())
503         scope->removeElementById(oldId, this);
504     if (!newId.isEmpty())
505         scope->addElementById(newId, this);
506 }
507
508 inline bool Element::fastHasAttribute(const QualifiedName& name) const
509 {
510     return m_attributeMap && m_attributeMap->getAttributeItem(name);
511 }
512
513 inline const AtomicString& Element::fastGetAttribute(const QualifiedName& name) const
514 {
515     if (m_attributeMap) {
516         if (Attribute* attribute = m_attributeMap->getAttributeItem(name))
517             return attribute->value();
518     }
519     return nullAtom;
520 }
521
522 inline const AtomicString& Element::idForStyleResolution() const
523 {
524     ASSERT(hasID());
525     return m_attributeMap->idForStyleResolution();
526 }
527
528 inline bool Element::isIdAttributeName(const QualifiedName& attributeName) const
529 {
530     // FIXME: This check is probably not correct for the case where the document has an id attribute
531     // with a non-null namespace, because it will return false, a false negative, if the prefixes
532     // don't match but the local name and namespace both do. However, since this has been like this
533     // for a while and the code paths may be hot, we'll have to measure performance if we fix it.
534     return attributeName == document()->idAttributeName();
535 }
536
537 inline const AtomicString& Element::getIdAttribute() const
538 {
539     return fastGetAttribute(document()->idAttributeName());
540 }
541
542 inline void Element::setIdAttribute(const AtomicString& value)
543 {
544     setAttribute(document()->idAttributeName(), value);
545 }
546
547 inline Element* firstElementChild(const ContainerNode* container)
548 {
549     ASSERT_ARG(container, container);
550     Node* child = container->firstChild();
551     while (child && !child->isElementNode())
552         child = child->nextSibling();
553     return static_cast<Element*>(child);
554 }
555
556 } // namespace
557
558 #endif