WebCore: Patch for https://bugs.webkit.org/show_bug.cgi?id=41146
[WebKit-https.git] / WebCore / dom / Element.h
index 57f98cc..7dd7d80 100644 (file)
@@ -3,7 +3,7 @@
  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
  *           (C) 2001 Peter Kelly (pmk@post.com)
  *           (C) 2001 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
 #ifndef Element_h
 #define Element_h
 
-#include "ContainerNode.h"
-#include "QualifiedName.h"
+#include "Document.h"
+#include "FragmentScriptingPermission.h"
+#include "NamedNodeMap.h"
 #include "ScrollTypes.h"
 
 namespace WebCore {
 
-class Attr;
 class Attribute;
-class CSSStyleDeclaration;
+class ClientRect;
+class ClientRectList;
+class DOMStringMap;
 class ElementRareData;
 class IntSize;
 
 class Element : public ContainerNode {
 public:
-    Element(const QualifiedName&, Document*);
-    ~Element();
+    static PassRefPtr<Element> create(const QualifiedName&, Document*);
+    virtual ~Element();
+
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(change);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(click);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(contextmenu);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(dblclick);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragenter);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragover);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragleave);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(drop);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragstart);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(drag);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragend);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(input);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(invalid);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(keydown);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(keypress);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(keyup);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(mousedown);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(mousemove);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseout);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseover);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseup);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(mousewheel);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(scroll);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(select);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(submit);
+
+    // These four attribute event handler attributes are overridden by HTMLBodyElement
+    // and HTMLFrameSetElement to forward to the DOMWindow.
+    DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(blur);
+    DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(error);
+    DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(focus);
+    DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(load);
+
+    // WebKit extensions
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(cut);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecopy);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(copy);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(paste);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(reset);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(search);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(selectstart);
+#if ENABLE(TOUCH_EVENTS)
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel);
+#endif
+
+    virtual PassRefPtr<DocumentFragment> createContextualFragment(const String&, FragmentScriptingPermission = FragmentScriptingAllowed);
 
-    const AtomicString& getIDAttribute() const;
     bool hasAttribute(const QualifiedName&) const;
     const AtomicString& getAttribute(const QualifiedName&) const;
     void setAttribute(const QualifiedName&, const AtomicString& value, ExceptionCode&);
     void removeAttribute(const QualifiedName&, ExceptionCode&);
 
+    // Typed getters and setters for language bindings.
+    int getIntegralAttribute(const QualifiedName& attributeName) const;
+    void setIntegralAttribute(const QualifiedName& attributeName, int value);
+    unsigned getUnsignedIntegralAttribute(const QualifiedName& attributeName) const;
+    void setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value);
+
+    // Call this to get the value of an attribute that is known not to be the style
+    // attribute or one of the SVG animatable attributes.
+    bool fastHasAttribute(const QualifiedName&) const;
+    const AtomicString& fastGetAttribute(const QualifiedName&) const;
+
     bool hasAttributes() const;
 
     bool hasAttribute(const String& name) const;
@@ -57,12 +122,20 @@ public:
     const AtomicString& getAttributeNS(const String& namespaceURI, const String& localName) const;
 
     void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode&);
-    void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode&);
+    void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode&, FragmentScriptingPermission = FragmentScriptingAllowed);
 
-    void scrollIntoView (bool alignToTop = true);
+    bool isIdAttributeName(const QualifiedName&) const;
+    const AtomicString& getIdAttribute() const;
+    void setIdAttribute(const AtomicString&);
+
+    // Call this to get the value of the id attribute for style resolution purposes.
+    // The value will already be lowercased if the document is in compatibility mode,
+    // so this function is not suitable for non-style uses.
+    const AtomicString& idForStyleResolution() const;
+
+    void scrollIntoView(bool alignToTop = true);
     void scrollIntoViewIfNeeded(bool centerIfNeeded = true);
 
-    void scrollByUnits(int units, ScrollGranularity);
     void scrollByLines(int lines);
     void scrollByPages(int pages);
 
@@ -75,12 +148,15 @@ public:
     int clientTop();
     int clientWidth();
     int clientHeight();
-    int scrollLeft();
-    int scrollTop();
-    void setScrollLeft(int);
-    void setScrollTop(int);
-    int scrollWidth();
-    int scrollHeight();
+    virtual int scrollLeft() const;
+    virtual int scrollTop() const;
+    virtual void setScrollLeft(int);
+    virtual void setScrollTop(int);
+    virtual int scrollWidth() const;
+    virtual int scrollHeight() const;
+
+    PassRefPtr<ClientRectList> getClientRects() const;
+    PassRefPtr<ClientRect> getBoundingClientRect() const;
 
     void removeAttribute(const String& name, ExceptionCode&);
     void removeAttributeNS(const String& namespaceURI, const String& localName, ExceptionCode&);
@@ -103,58 +179,51 @@ public:
 
     const AtomicString& localName() const { return m_tagName.localName(); }
     const AtomicString& prefix() const { return m_tagName.prefix(); }
-    virtual void setPrefix(const AtomicString&, ExceptionCode&);
     const AtomicString& namespaceURI() const { return m_tagName.namespaceURI(); }
 
     virtual KURL baseURI() const;
 
-    // DOM methods overridden from parent classes
-    virtual NodeType nodeType() const;
-    virtual PassRefPtr<Node> cloneNode(bool deep);
     virtual String nodeName() const;
-    virtual void insertedIntoDocument();
-    virtual void removedFromDocument();
-    virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
-
-    void normalizeAttributes();
 
-    virtual bool isInputTypeHidden() const { return false; }
-    virtual bool isPasswordField() const { return false; }
+    PassRefPtr<Element> cloneElementWithChildren();
+    PassRefPtr<Element> cloneElementWithoutChildren();
 
+    void normalizeAttributes();
     String nodeNamePreservingCase() const;
 
     // convenience methods which ignore exceptions
     void setAttribute(const QualifiedName&, const AtomicString& value);
     void setBooleanAttribute(const QualifiedName& name, bool);
+    // Please don't use setCStringAttribute in performance-sensitive code;
+    // use a static AtomicString value instead to avoid the conversion overhead.
+    void setCStringAttribute(const QualifiedName&, const char* cStringValue);
 
-    virtual NamedAttrMap* attributes() const;
-    NamedAttrMap* attributes(bool readonly) const;
+    virtual NamedNodeMap* attributes() const;
+    NamedNodeMap* attributes(bool readonly) const;
 
     // This method is called whenever an attribute is added, changed or removed.
     virtual void attributeChanged(Attribute*, bool preserveDecls = false);
 
     // not part of the DOM
-    void setAttributeMap(PassRefPtr<NamedAttrMap>);
+    void setAttributeMap(PassRefPtr<NamedNodeMap>, FragmentScriptingPermission = FragmentScriptingAllowed);
+    NamedNodeMap* attributeMap() const { return namedAttrMap.get(); }
 
-    virtual void copyNonAttributeProperties(const Element* source) {}
+    virtual void copyNonAttributeProperties(const Element* /*source*/) { }
 
     virtual void attach();
     virtual void detach();
     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
     virtual void recalcStyle(StyleChange = NoChange);
 
-    virtual RenderStyle* computedStyle();
+    RenderStyle* computedStyle(PseudoId = NOPSEUDO);
 
-    virtual bool childTypeAllowed(NodeType);
-
-    virtual PassRefPtr<Attribute> createAttribute(const QualifiedName&, const AtomicString& value);
-    
     void dispatchAttrRemovalEvent(Attribute*);
     void dispatchAttrAdditionEvent(Attribute*);
 
-    virtual void accessKeyAction(bool sendToAnyEvent) { }
+    virtual void accessKeyAction(bool /*sendToAnyEvent*/) { }
 
     virtual bool isURLAttribute(Attribute*) const;
+    KURL getURLAttribute(const QualifiedName&) const;
     virtual const QualifiedName& imageSourceAttributeName() const;
     virtual String target() const { return String(); }
 
@@ -162,10 +231,6 @@ public:
     virtual void updateFocusAppearance(bool restorePreviousSelection);
     void blur();
 
-#ifndef NDEBUG
-    virtual void formatForDebugger(char* buffer, unsigned length) const;
-#endif
-
     String innerText() const;
     String outerText() const;
  
@@ -178,13 +243,16 @@ public:
     IntSize minimumSizeForResizing() const;
     void setMinimumSizeForResizing(const IntSize&);
 
-    // Use Document::registerForDocumentActivationCallbacks() to subscribe these
+    // Use Document::registerForDocumentActivationCallbacks() to subscribe to these
     virtual void documentWillBecomeInactive() { }
     virtual void documentDidBecomeActive() { }
-    
-    bool isFinishedParsingChildren() const { return m_parsingChildrenFinished; }
+
+    // Use Document::registerForMediaVolumeCallbacks() to subscribe to this
+    virtual void mediaVolumeDidChange() { }
+
+    bool isFinishedParsingChildren() const { return isParsingChildrenFinished(); }
     virtual void finishParsingChildren();
-    virtual void beginParsingChildren() { m_parsingChildrenFinished = false; }
+    virtual void beginParsingChildren() { clearIsParsingChildrenFinished(); }
 
     // ElementTraversal API
     Element* firstElementChild() const;
@@ -193,44 +261,95 @@ public:
     Element* nextElementSibling() const;
     unsigned childElementCount() const;
 
+    bool webkitMatchesSelector(const String& selectors, ExceptionCode&);
+
+    DOMStringMap* dataset();
+
+    virtual bool isFormControlElement() const { return false; }
+    virtual bool isEnabledFormControl() const { return true; }
+    virtual bool isReadOnlyFormControl() const { return false; }
+    virtual bool isSpinButtonElement() const { return false; }
+    virtual bool isTextFormControl() const { return false; }
+    virtual bool isOptionalFormControl() const { return false; }
+    virtual bool isRequiredFormControl() const { return false; }
+    virtual bool isDefaultButtonForForm() const { return false; }
+    virtual bool willValidate() const { return false; }
+    virtual bool isValidFormControlElement() { return false; }
+
+    virtual bool formControlValueMatchesRenderer() const { return false; }
+    virtual void setFormControlValueMatchesRenderer(bool) { }
+
+    virtual const AtomicString& formControlName() const { return nullAtom; }
+    virtual const AtomicString& formControlType() const { return nullAtom; }
+
+    virtual bool shouldSaveAndRestoreFormControlState() const { return true; }
+    virtual bool saveFormControlState(String&) const { return false; }
+    virtual void restoreFormControlState(const String&) { }
+
+    virtual void dispatchFormControlChangeEvent() { }
+
+#if ENABLE(SVG)
+    virtual bool childShouldCreateRenderer(Node*) const; 
+#endif
+
+protected:
+    Element(const QualifiedName& tagName, Document* document, ConstructionType type)
+        : ContainerNode(document, type)
+        , m_tagName(tagName)
+    {
+    }
+
+    virtual void insertedIntoDocument();
+    virtual void removedFromDocument();
+    virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
+
+    // The implementation of Element::attributeChanged() calls the following two functions.
+    // They are separated to allow a different flow of control in StyledElement::attributeChanged().
+    void recalcStyleIfNeededAfterAttributeChanged(Attribute*);
+    void updateAfterAttributeChanged(Attribute*);
+
 private:
-    virtual void createAttributeMap() const;
+    void scrollByUnits(int units, ScrollGranularity);
 
-    virtual void updateStyleAttribute() const {}
+    virtual void setPrefix(const AtomicString&, ExceptionCode&);
+    virtual NodeType nodeType() const;
+    virtual bool childTypeAllowed(NodeType);
+
+    virtual PassRefPtr<Attribute> createAttribute(const QualifiedName&, const AtomicString& value);
+    
+#ifndef NDEBUG
+    virtual void formatForDebugger(char* buffer, unsigned length) const;
+#endif
+
+    bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle);
+
+    void createAttributeMap() const;
+
+    virtual void updateStyleAttribute() const { }
 
 #if ENABLE(SVG)
-    virtual void updateAnimatedSVGAttribute(const String&) const {}
+    virtual void updateAnimatedSVGAttribute(const QualifiedName&) const { }
 #endif
 
-    void updateFocusAppearanceSoonAfterAttach();
     void cancelFocusAppearanceUpdate();
 
     virtual const AtomicString& virtualPrefix() const { return prefix(); }
     virtual const AtomicString& virtualLocalName() const { return localName(); }
     virtual const AtomicString& virtualNamespaceURI() const { return namespaceURI(); }
+    virtual RenderStyle* virtualComputedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return computedStyle(pseudoElementSpecifier); }
     
+    // cloneNode is private so that non-virtual cloneElementWithChildren and cloneElementWithoutChildren
+    // are used instead.
+    virtual PassRefPtr<Node> cloneNode(bool deep);
+
     QualifiedName m_tagName;
     virtual NodeRareData* createRareData();
 
-protected:
     ElementRareData* rareData() const;
     ElementRareData* ensureRareData();
     
-    mutable RefPtr<NamedAttrMap> namedAttrMap;
-
-    // These two bits are really used by the StyledElement subclass, but they are pulled up here in order to be shared with other
-    // Element bits.
-    mutable bool m_isStyleAttributeValid : 1;
-    mutable bool m_synchronizingStyleAttribute : 1;
-
-#if ENABLE(SVG)
-    // These bit is are used by SVGElement subclasses, and it lives here for the same reason as above.
-    mutable bool m_areSVGAttributesValid : 1;
-    mutable bool m_synchronizingSVGAttributes : 1;
-#endif
-
-private:
-    bool m_parsingChildrenFinished : 1;
+protected:
+    mutable RefPtr<NamedNodeMap> namedAttrMap;
 };
     
 inline bool Node::hasTagName(const QualifiedName& name) const
@@ -243,11 +362,86 @@ inline bool Node::hasAttributes() const
     return isElementNode() && static_cast<const Element*>(this)->hasAttributes();
 }
 
-inline NamedAttrMap* Node::attributes() const
+inline NamedNodeMap* Node::attributes() const
 {
     return isElementNode() ? static_cast<const Element*>(this)->attributes() : 0;
 }
 
-} //namespace
+inline Element* Node::parentElement() const
+{
+    Node* parent = parentNode();
+    return parent && parent->isElementNode() ? static_cast<Element*>(parent) : 0;
+}
+
+inline NamedNodeMap* Element::attributes(bool readonly) const
+{
+    if (!isStyleAttributeValid())
+        updateStyleAttribute();
+
+#if ENABLE(SVG)
+    if (!areSVGAttributesValid())
+        updateAnimatedSVGAttribute(anyQName());
+#endif
+
+    if (!readonly && !namedAttrMap)
+        createAttributeMap();
+    return namedAttrMap.get();
+}
+
+inline void Element::updateId(const AtomicString& oldId, const AtomicString& newId)
+{
+    if (!inDocument())
+        return;
+
+    if (oldId == newId)
+        return;
+
+    Document* doc = document();
+    if (!oldId.isEmpty())
+        doc->removeElementById(oldId, this);
+    if (!newId.isEmpty())
+        doc->addElementById(newId, this);
+}
+
+inline bool Element::fastHasAttribute(const QualifiedName& name) const
+{
+    return namedAttrMap && namedAttrMap->getAttributeItem(name);
+}
+
+inline const AtomicString& Element::fastGetAttribute(const QualifiedName& name) const
+{
+    if (namedAttrMap) {
+        if (Attribute* attribute = namedAttrMap->getAttributeItem(name))
+            return attribute->value();
+    }
+    return nullAtom;
+}
+
+inline const AtomicString& Element::idForStyleResolution() const
+{
+    ASSERT(hasID());
+    return namedAttrMap->idForStyleResolution();
+}
+
+inline bool Element::isIdAttributeName(const QualifiedName& attributeName) const
+{
+    // FIXME: This check is probably not correct for the case where the document has an id attribute
+    // with a non-null namespace, because it will return false, a false negative, if the prefixes
+    // don't match but the local name and namespace both do. However, since this has been like this
+    // for a while and the code paths may be hot, we'll have to measure performance if we fix it.
+    return attributeName == document()->idAttributeName();
+}
+
+inline const AtomicString& Element::getIdAttribute() const
+{
+    return fastGetAttribute(document()->idAttributeName());
+}
+
+inline void Element::setIdAttribute(const AtomicString& value)
+{
+    setAttribute(document()->idAttributeName(), value);
+}
+
+} // namespace
 
 #endif