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