/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2001 Peter Kelly (pmk@post.com)
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
 *           (C) 2007 David Smith (catfish.man@gmail.com)
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
 *           (C) 2007 Eric Seidel (eric@webkit.org)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "config.h"
#include "Element.h"

#include "AXObjectCache.h"
#include "Attr.h"
#include "CSSParser.h"
#include "CSSSelectorList.h"
#include "CSSStyleSelector.h"
#include "ClassList.h"
#include "ClientRect.h"
#include "ClientRectList.h"
#include "DOMTokenList.h"
#include "DatasetDOMStringMap.h"
#include "Document.h"
#include "DocumentFragment.h"
#include "ElementRareData.h"
#include "ExceptionCode.h"
#include "FocusController.h"
#include "Frame.h"
#include "FrameView.h"
#include "HTMLCollection.h"
#include "HTMLDocument.h"
#include "HTMLElement.h"
#include "HTMLFrameOwnerElement.h"
#include "HTMLNames.h"
#include "HTMLParserIdioms.h"
#include "InspectorInstrumentation.h"
#include "MutationObserverInterestGroup.h"
#include "MutationRecord.h"
#include "NamedNodeMap.h"
#include "NodeList.h"
#include "NodeRenderStyle.h"
#include "NodeRenderingContext.h"
#include "Page.h"
#include "RenderLayer.h"
#include "RenderRegion.h"
#include "RenderView.h"
#include "RenderWidget.h"
#include "RuntimeEnabledFeatures.h"
#include "Settings.h"
#include "ShadowRoot.h"
#include "Text.h"
#include "TextIterator.h"
#include "WebKitMutationObserver.h"
#include "WebKitAnimationList.h"
#include "XMLNSNames.h"
#include "XMLNames.h"
#include "htmlediting.h"
#include <wtf/text/CString.h>

#if ENABLE(SVG)
#include "SVGElement.h"
#include "SVGNames.h"
#endif

namespace WebCore {

using namespace HTMLNames;
using namespace XMLNames;
    
class StyleSelectorParentPusher {
public:
    StyleSelectorParentPusher(Element* parent)
        : m_parent(parent)
        , m_pushedStyleSelector(0)
    {
    }
    void push()
    {
        if (m_pushedStyleSelector)
            return;
        m_pushedStyleSelector = m_parent->document()->styleSelector();
        m_pushedStyleSelector->pushParentElement(m_parent);
    }
    ~StyleSelectorParentPusher() 
    {

        if (!m_pushedStyleSelector)
            return;

        // This tells us that our pushed style selector is in a bad state,
        // so we should just bail out in that scenario.
        ASSERT(m_pushedStyleSelector == m_parent->document()->styleSelector());
        if (m_pushedStyleSelector != m_parent->document()->styleSelector())
            return;

        m_pushedStyleSelector->popParentElement(m_parent); 
    }

private:
    Element* m_parent;
    CSSStyleSelector* m_pushedStyleSelector;
};

PassRefPtr<Element> Element::create(const QualifiedName& tagName, Document* document)
{
    return adoptRef(new Element(tagName, document, CreateElement));
}

Element::~Element()
{
    if (shadowTree())
        rareData()->m_shadowTree.clear();
    if (m_attributeData)
        m_attributeData->clearAttributes();
}

inline ElementRareData* Element::rareData() const
{
    ASSERT(hasRareData());
    return static_cast<ElementRareData*>(NodeRareData::rareDataFromMap(this));
}
    
inline ElementRareData* Element::ensureRareData()
{
    return static_cast<ElementRareData*>(Node::ensureRareData());
}
    
OwnPtr<NodeRareData> Element::createRareData()
{
    return adoptPtr(new ElementRareData);
}

DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, blur);
DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, error);
DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, focus);
DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, load);

PassRefPtr<Node> Element::cloneNode(bool deep)
{
    return deep ? cloneElementWithChildren() : cloneElementWithoutChildren();
}

PassRefPtr<Element> Element::cloneElementWithChildren()
{
    RefPtr<Element> clone = cloneElementWithoutChildren();
    cloneChildNodes(clone.get());
    return clone.release();
}

PassRefPtr<Element> Element::cloneElementWithoutChildren()
{
    RefPtr<Element> clone = cloneElementWithoutAttributesAndChildren();
    // This will catch HTML elements in the wrong namespace that are not correctly copied.
    // This is a sanity check as HTML overloads some of the DOM methods.
    ASSERT(isHTMLElement() == clone->isHTMLElement());

    clone->setAttributesFromElement(*this);
    clone->copyNonAttributeProperties(this);

    return clone.release();
}

PassRefPtr<Element> Element::cloneElementWithoutAttributesAndChildren()
{
    return document()->createElement(tagQName(), false);
}

void Element::copyNonAttributeProperties(const Element*)
{
}

void Element::removeAttribute(const QualifiedName& name)
{
    if (!attributeData())
        return;
    attributeData()->removeAttribute(name, this);
}

void Element::setBooleanAttribute(const QualifiedName& name, bool value)
{
    if (value)
        setAttribute(name, emptyAtom);
    else
        removeAttribute(name);
}

NamedNodeMap* Element::attributes() const
{
    ensureUpdatedAttributeData();
    ElementRareData* rareData = const_cast<Element*>(this)->ensureRareData();
    if (NamedNodeMap* attributeMap = rareData->m_attributeMap.get())
        return attributeMap;

    rareData->m_attributeMap = NamedNodeMap::create(const_cast<Element*>(this));
    return rareData->m_attributeMap.get();
}

Node::NodeType Element::nodeType() const
{
    return ELEMENT_NODE;
}

bool Element::hasAttribute(const QualifiedName& name) const
{
    return hasAttributeNS(name.namespaceURI(), name.localName());
}

const AtomicString& Element::getAttribute(const QualifiedName& name) const
{
    if (UNLIKELY(name == styleAttr) && !isStyleAttributeValid())
        updateStyleAttribute();

#if ENABLE(SVG)
    if (UNLIKELY(!areSVGAttributesValid()))
        updateAnimatedSVGAttribute(name);
#endif

    if (m_attributeData) {
        if (Attribute* attribute = getAttributeItem(name))
            return attribute->value();
    }
    return nullAtom;
}

void Element::scrollIntoView(bool alignToTop) 
{
    document()->updateLayoutIgnorePendingStylesheets();

    if (!renderer())
        return;

    LayoutRect bounds = getRect();
    // Align to the top / bottom and to the closest edge.
    if (alignToTop)
        renderer()->enclosingLayer()->scrollRectToVisible(bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
    else
        renderer()->enclosingLayer()->scrollRectToVisible(bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignBottomAlways);
}

void Element::scrollIntoViewIfNeeded(bool centerIfNeeded)
{
    document()->updateLayoutIgnorePendingStylesheets();

    if (!renderer())
        return;

    LayoutRect bounds = getRect();
    if (centerIfNeeded)
        renderer()->enclosingLayer()->scrollRectToVisible(bounds, ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded);
    else
        renderer()->enclosingLayer()->scrollRectToVisible(bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
}

void Element::scrollByUnits(int units, ScrollGranularity granularity)
{
    document()->updateLayoutIgnorePendingStylesheets();

    if (!renderer())
        return;

    if (!renderer()->hasOverflowClip())
        return;

    ScrollDirection direction = ScrollDown;
    if (units < 0) {
        direction = ScrollUp;
        units = -units;
    }
    toRenderBox(renderer())->layer()->scroll(direction, granularity, units);
}

void Element::scrollByLines(int lines)
{
    scrollByUnits(lines, ScrollByLine);
}

void Element::scrollByPages(int pages)
{
    scrollByUnits(pages, ScrollByPage);
}

static float localZoomForRenderer(RenderObject* renderer)
{
    // FIXME: This does the wrong thing if two opposing zooms are in effect and canceled each
    // other out, but the alternative is that we'd have to crawl up the whole render tree every
    // time (or store an additional bit in the RenderStyle to indicate that a zoom was specified).
    float zoomFactor = 1;
    if (renderer->style()->effectiveZoom() != 1) {
        // Need to find the nearest enclosing RenderObject that set up
        // a differing zoom, and then we divide our result by it to eliminate the zoom.
        RenderObject* prev = renderer;
        for (RenderObject* curr = prev->parent(); curr; curr = curr->parent()) {
            if (curr->style()->effectiveZoom() != prev->style()->effectiveZoom()) {
                zoomFactor = prev->style()->zoom();
                break;
            }
            prev = curr;
        }
        if (prev->isRenderView())
            zoomFactor = prev->style()->zoom();
    }
    return zoomFactor;
}

static LayoutUnit adjustForLocalZoom(LayoutUnit value, RenderObject* renderer)
{
    float zoomFactor = localZoomForRenderer(renderer);
    if (zoomFactor == 1)
        return value;
    // Needed because computeLengthInt truncates (rather than rounds) when scaling up.
    if (zoomFactor > 1)
        value++;
    return static_cast<LayoutUnit>(value / zoomFactor);
}

int Element::offsetLeft()
{
    document()->updateLayoutIgnorePendingStylesheets();
    if (RenderBoxModelObject* rend = renderBoxModelObject())
        return adjustForLocalZoom(rend->offsetLeft(), rend);
    return 0;
}

int Element::offsetTop()
{
    document()->updateLayoutIgnorePendingStylesheets();
    if (RenderBoxModelObject* rend = renderBoxModelObject())
        return adjustForLocalZoom(rend->offsetTop(), rend);
    return 0;
}

int Element::offsetWidth()
{
    document()->updateLayoutIgnorePendingStylesheets();
    if (RenderBoxModelObject* rend = renderBoxModelObject())
        return adjustForAbsoluteZoom(rend->offsetWidth(), rend);
    return 0;
}

int Element::offsetHeight()
{
    document()->updateLayoutIgnorePendingStylesheets();
    if (RenderBoxModelObject* rend = renderBoxModelObject())
        return adjustForAbsoluteZoom(rend->offsetHeight(), rend);
    return 0;
}

Element* Element::offsetParent()
{
    document()->updateLayoutIgnorePendingStylesheets();
    if (RenderObject* rend = renderer())
        if (RenderObject* offsetParent = rend->offsetParent())
            return static_cast<Element*>(offsetParent->node());
    return 0;
}

int Element::clientLeft()
{
    document()->updateLayoutIgnorePendingStylesheets();

    if (RenderBox* rend = renderBox())
        return adjustForAbsoluteZoom(rend->clientLeft(), rend);
    return 0;
}

int Element::clientTop()
{
    document()->updateLayoutIgnorePendingStylesheets();

    if (RenderBox* rend = renderBox())
        return adjustForAbsoluteZoom(rend->clientTop(), rend);
    return 0;
}

int Element::clientWidth()
{
    document()->updateLayoutIgnorePendingStylesheets();

    // When in strict mode, clientWidth for the document element should return the width of the containing frame.
    // When in quirks mode, clientWidth for the body element should return the width of the containing frame.
    bool inQuirksMode = document()->inQuirksMode();
    if ((!inQuirksMode && document()->documentElement() == this) ||
        (inQuirksMode && isHTMLElement() && document()->body() == this)) {
        if (FrameView* view = document()->view()) {
            if (RenderView* renderView = document()->renderView())
                return adjustForAbsoluteZoom(view->layoutWidth(), renderView);
        }
    }
    
    if (RenderBox* rend = renderBox())
        return adjustForAbsoluteZoom(rend->clientWidth(), rend);
    return 0;
}

int Element::clientHeight()
{
    document()->updateLayoutIgnorePendingStylesheets();

    // When in strict mode, clientHeight for the document element should return the height of the containing frame.
    // When in quirks mode, clientHeight for the body element should return the height of the containing frame.
    bool inQuirksMode = document()->inQuirksMode();     

    if ((!inQuirksMode && document()->documentElement() == this) ||
        (inQuirksMode && isHTMLElement() && document()->body() == this)) {
        if (FrameView* view = document()->view()) {
            if (RenderView* renderView = document()->renderView())
                return adjustForAbsoluteZoom(view->layoutHeight(), renderView);
        }
    }
    
    if (RenderBox* rend = renderBox())
        return adjustForAbsoluteZoom(rend->clientHeight(), rend);
    return 0;
}

int Element::scrollLeft()
{
    document()->updateLayoutIgnorePendingStylesheets();
    if (RenderBox* rend = renderBox())
        return adjustForAbsoluteZoom(rend->scrollLeft(), rend);
    return 0;
}

int Element::scrollTop()
{
    document()->updateLayoutIgnorePendingStylesheets();
    if (RenderBox* rend = renderBox())
        return adjustForAbsoluteZoom(rend->scrollTop(), rend);
    return 0;
}

void Element::setScrollLeft(int newLeft)
{
    document()->updateLayoutIgnorePendingStylesheets();
    if (RenderBox* rend = renderBox())
        rend->setScrollLeft(static_cast<int>(newLeft * rend->style()->effectiveZoom()));
}

void Element::setScrollTop(int newTop)
{
    document()->updateLayoutIgnorePendingStylesheets();
    if (RenderBox* rend = renderBox())
        rend->setScrollTop(static_cast<int>(newTop * rend->style()->effectiveZoom()));
}

int Element::scrollWidth()
{
    document()->updateLayoutIgnorePendingStylesheets();
    if (RenderBox* rend = renderBox())
        return adjustForAbsoluteZoom(rend->scrollWidth(), rend);
    return 0;
}

int Element::scrollHeight()
{
    document()->updateLayoutIgnorePendingStylesheets();
    if (RenderBox* rend = renderBox())
        return adjustForAbsoluteZoom(rend->scrollHeight(), rend);
    return 0;
}

IntRect Element::boundsInRootViewSpace()
{
    document()->updateLayoutIgnorePendingStylesheets();

    FrameView* view = document()->view();
    if (!view)
        return IntRect();

    Vector<FloatQuad> quads;
#if ENABLE(SVG)
    if (isSVGElement() && renderer()) {
        // Get the bounding rectangle from the SVG model.
        SVGElement* svgElement = static_cast<SVGElement*>(this);
        FloatRect localRect;
        if (svgElement->boundingBox(localRect))
            quads.append(renderer()->localToAbsoluteQuad(localRect));
    } else
#endif
    {
        // Get the bounding rectangle from the box model.
        if (renderBoxModelObject())
            renderBoxModelObject()->absoluteQuads(quads);
    }

    if (quads.isEmpty())
        return IntRect();

    IntRect result = quads[0].enclosingBoundingBox();
    for (size_t i = 1; i < quads.size(); ++i)
        result.unite(quads[i].enclosingBoundingBox());

    result = view->contentsToRootView(result);
    return result;
}

PassRefPtr<ClientRectList> Element::getClientRects()
{
    document()->updateLayoutIgnorePendingStylesheets();

    RenderBoxModelObject* renderBoxModelObject = this->renderBoxModelObject();
    if (!renderBoxModelObject)
        return ClientRectList::create();

    // FIXME: Handle SVG elements.
    // FIXME: Handle table/inline-table with a caption.

    Vector<FloatQuad> quads;
    renderBoxModelObject->absoluteQuads(quads);

    float pageScale = 1;
    if (Page* page = document()->page()) 
        pageScale = page->pageScaleFactor();

    if (FrameView* view = document()->view()) {
        LayoutRect visibleContentRect = view->visibleContentRect();
        for (size_t i = 0; i < quads.size(); ++i) {
            quads[i].move(-visibleContentRect.x(), -visibleContentRect.y());
            adjustFloatQuadForAbsoluteZoom(quads[i], renderBoxModelObject);
            if (pageScale != 1)
                adjustFloatQuadForPageScale(quads[i], pageScale);
        }
    }

    return ClientRectList::create(quads);
}

PassRefPtr<ClientRect> Element::getBoundingClientRect()
{
    document()->updateLayoutIgnorePendingStylesheets();

    Vector<FloatQuad> quads;
#if ENABLE(SVG)
    if (isSVGElement() && renderer() && !renderer()->isSVGRoot()) {
        // Get the bounding rectangle from the SVG model.
        SVGElement* svgElement = static_cast<SVGElement*>(this);
        FloatRect localRect;
        if (svgElement->boundingBox(localRect))
            quads.append(renderer()->localToAbsoluteQuad(localRect));
    } else
#endif
    {
        // Get the bounding rectangle from the box model.
        if (renderBoxModelObject())
            renderBoxModelObject()->absoluteQuads(quads);
    }

    if (quads.isEmpty())
        return ClientRect::create();

    FloatRect result = quads[0].boundingBox();
    for (size_t i = 1; i < quads.size(); ++i)
        result.unite(quads[i].boundingBox());

    if (FrameView* view = document()->view()) {
        LayoutRect visibleContentRect = view->visibleContentRect();
        result.move(-visibleContentRect.x(), -visibleContentRect.y());
    }

    adjustFloatRectForAbsoluteZoom(result, renderer());
    if (Page* page = document()->page())
        adjustFloatRectForPageScale(result, page->pageScaleFactor());

    return ClientRect::create(result);
}
    
IntRect Element::screenRect() const
{
    if (!renderer())
        return IntRect();
    // FIXME: this should probably respect transforms
    return renderer()->view()->frameView()->contentsToScreen(renderer()->absoluteBoundingBoxRectIgnoringTransforms());
}

static inline bool shouldIgnoreAttributeCase(const Element* e)
{
    return e && e->document()->isHTMLDocument() && e->isHTMLElement();
}

const AtomicString& Element::getAttribute(const String& name) const
{
    bool ignoreCase = shouldIgnoreAttributeCase(this);
    
    // Update the 'style' attribute if it's invalid and being requested:
    if (!isStyleAttributeValid() && equalPossiblyIgnoringCase(name, styleAttr.localName(), ignoreCase))
        updateStyleAttribute();

#if ENABLE(SVG)
    if (!areSVGAttributesValid()) {
        // We're not passing a namespace argument on purpose. SVGNames::*Attr are defined w/o namespaces as well.
        updateAnimatedSVGAttribute(QualifiedName(nullAtom, name, nullAtom));
    }
#endif

    if (m_attributeData) {
        if (Attribute* attribute = m_attributeData->getAttributeItem(name, ignoreCase))
            return attribute->value();
    }

    return nullAtom;
}

const AtomicString& Element::getAttributeNS(const String& namespaceURI, const String& localName) const
{
    return getAttribute(QualifiedName(nullAtom, localName, namespaceURI));
}

void Element::setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode& ec)
{
    if (!Document::isValidName(name)) {
        ec = INVALID_CHARACTER_ERR;
        return;
    }

    const AtomicString& localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;

    size_t index = ensureUpdatedAttributeData()->getAttributeItemIndex(localName, false);
    const QualifiedName& qName = index != notFound ? attributeItem(index)->name() : QualifiedName(nullAtom, localName, nullAtom);
    setAttributeInternal(index, qName, value, NotInUpdateStyleAttribute);
}

void Element::setAttribute(const QualifiedName& name, const AtomicString& value, EInUpdateStyleAttribute inUpdateStyleAttribute)
{
    setAttributeInternal(ensureUpdatedAttributeData()->getAttributeItemIndex(name), name, value, inUpdateStyleAttribute);
}

inline void Element::setAttributeInternal(size_t index, const QualifiedName& name, const AtomicString& value, EInUpdateStyleAttribute inUpdateStyleAttribute)
{
    Attribute* old = index != notFound ? m_attributeData->attributeItem(index) : 0;
    if (value.isNull()) {
        if (old)
            m_attributeData->removeAttribute(index, this, inUpdateStyleAttribute);
        return;
    }

    if (!old) {
        m_attributeData->addAttribute(Attribute::create(name, value), this, inUpdateStyleAttribute);
        return;
    }

    if (inUpdateStyleAttribute == NotInUpdateStyleAttribute)
        willModifyAttribute(name, old ? old->value() : nullAtom, value);

    if (Attr* attrNode = old->attr())
        attrNode->setValue(value);
    else
        old->setValue(value);

    if (inUpdateStyleAttribute == NotInUpdateStyleAttribute)
        didModifyAttribute(old);
}

void Element::attributeChanged(Attribute* attr)
{
    document()->incDOMTreeVersion();

    if (isIdAttributeName(attr->name()))
        idAttributeChanged(attr);
    else if (attr->name() == HTMLNames::nameAttr)
        setHasName(!attr->isNull());

    if (!needsStyleRecalc() && document()->attached()) {
        CSSStyleSelector* styleSelector = document()->styleSelectorIfExists();
        if (!styleSelector || styleSelector->hasSelectorForAttribute(attr->name().localName()))
            setNeedsStyleRecalc();
    }

    invalidateNodeListsCacheAfterAttributeChanged(attr->name());

    if (!AXObjectCache::accessibilityEnabled())
        return;

    const QualifiedName& attrName = attr->name();
    if (attrName == aria_activedescendantAttr) {
        // any change to aria-activedescendant attribute triggers accessibility focus change, but document focus remains intact
        document()->axObjectCache()->handleActiveDescendantChanged(renderer());
    } else if (attrName == roleAttr) {
        // the role attribute can change at any time, and the AccessibilityObject must pick up these changes
        document()->axObjectCache()->handleAriaRoleChanged(renderer());
    } else if (attrName == aria_valuenowAttr) {
        // If the valuenow attribute changes, AX clients need to be notified.
        document()->axObjectCache()->postNotification(renderer(), AXObjectCache::AXValueChanged, true);
    } else if (attrName == aria_labelAttr || attrName == aria_labeledbyAttr || attrName == altAttr || attrName == titleAttr) {
        // If the content of an element changes due to an attribute change, notify accessibility.
        document()->axObjectCache()->contentChanged(renderer());
    } else if (attrName == aria_checkedAttr)
        document()->axObjectCache()->checkedStateChanged(renderer());
    else if (attrName == aria_selectedAttr)
        document()->axObjectCache()->selectedChildrenChanged(renderer());
    else if (attrName == aria_expandedAttr)
        document()->axObjectCache()->handleAriaExpandedChange(renderer());
    else if (attrName == aria_hiddenAttr)
        document()->axObjectCache()->childrenChanged(renderer());
    else if (attrName == aria_invalidAttr)
        document()->axObjectCache()->postNotification(renderer(), AXObjectCache::AXInvalidStatusChanged, true);
}

void Element::idAttributeChanged(Attribute* attr)
{
    if (attributeData()) {
        if (attr->isNull())
            attributeData()->setIdForStyleResolution(nullAtom);
        else if (document()->inQuirksMode())
            attributeData()->setIdForStyleResolution(attr->value().lower());
        else
            attributeData()->setIdForStyleResolution(attr->value());
    }
    setNeedsStyleRecalc();
}
    
// Returns true is the given attribute is an event handler.
// We consider an event handler any attribute that begins with "on".
// It is a simple solution that has the advantage of not requiring any
// code or configuration change if a new event handler is defined.

static bool isEventHandlerAttribute(const QualifiedName& name)
{
    return name.namespaceURI().isNull() && name.localName().startsWith("on");
}

static bool isAttributeToRemove(const QualifiedName& name, const AtomicString& value)
{    
    return (name.localName().endsWith(hrefAttr.localName()) || name == srcAttr || name == actionAttr) && protocolIsJavaScript(stripLeadingAndTrailingHTMLSpaces(value));       
}

void Element::parserSetAttributes(PassOwnPtr<AttributeVector> attributeVector, FragmentScriptingPermission scriptingPermission)
{
    ASSERT(!inDocument());
    ASSERT(!parentNode());

    ASSERT(!m_attributeData);

    if (!attributeVector)
        return;

    createAttributeData();
    m_attributeData->m_attributes.swap(*attributeVector);

    // If the element is created as result of a paste or drag-n-drop operation
    // we want to remove all the script and event handlers.
    if (scriptingPermission == FragmentScriptingNotAllowed) {
        unsigned i = 0;
        while (i < m_attributeData->length()) {
            const QualifiedName& attributeName = m_attributeData->m_attributes[i]->name();
            if (isEventHandlerAttribute(attributeName)) {
                m_attributeData->m_attributes.remove(i);
                continue;
            }

            if (isAttributeToRemove(attributeName, m_attributeData->m_attributes[i]->value()))
                m_attributeData->m_attributes[i]->setValue(nullAtom);
            i++;
        }
    }

    // Store the set of attributes that changed on the stack in case
    // attributeChanged mutates m_attributeData.
    Vector<RefPtr<Attribute> > attributes;
    m_attributeData->copyAttributesToVector(attributes);
    for (Vector<RefPtr<Attribute> >::iterator iter = attributes.begin(); iter != attributes.end(); ++iter)
        attributeChanged(iter->get());
}

bool Element::hasAttributes() const
{
    updateInvalidAttributes();
    return m_attributeData && m_attributeData->length();
}

bool Element::hasEquivalentAttributes(const Element* other) const
{
    ElementAttributeData* attributeData = updatedAttributeData();
    ElementAttributeData* otherAttributeData = other->updatedAttributeData();
    if (attributeData)
        return attributeData->isEquivalent(otherAttributeData);
    if (otherAttributeData)
        return otherAttributeData->isEquivalent(attributeData);
    return true;
}

String Element::nodeName() const
{
    return m_tagName.toString();
}

String Element::nodeNamePreservingCase() const
{
    return m_tagName.toString();
}

void Element::setPrefix(const AtomicString& prefix, ExceptionCode& ec)
{
    ec = 0;
    checkSetPrefix(prefix, ec);
    if (ec)
        return;

    m_tagName.setPrefix(prefix.isEmpty() ? AtomicString() : prefix);
}

KURL Element::baseURI() const
{
    const AtomicString& baseAttribute = getAttribute(baseAttr);
    KURL base(KURL(), baseAttribute);
    if (!base.protocol().isEmpty())
        return base;

    ContainerNode* parent = parentNode();
    if (!parent)
        return base;

    const KURL& parentBase = parent->baseURI();
    if (parentBase.isNull())
        return base;

    return KURL(parentBase, baseAttribute);
}

void Element::createAttributeData() const
{
    m_attributeData = ElementAttributeData::create();
}

bool Element::isURLAttribute(Attribute*) const
{
    return false;
}

const QualifiedName& Element::imageSourceAttributeName() const
{
    return srcAttr;
}

RenderObject* Element::createRenderer(RenderArena* arena, RenderStyle* style)
{
    if (document()->documentElement() == this && style->display() == NONE) {
        // Ignore display: none on root elements.  Force a display of block in that case.
        RenderBlock* result = new (arena) RenderBlock(this);
        if (result)
            result->setAnimatableStyle(style);
        return result;
    }
    return RenderObject::createObject(this, style);
}

bool Element::wasChangedSinceLastFormControlChangeEvent() const
{
    return false;
}

void Element::setChangedSinceLastFormControlChangeEvent(bool)
{
}

void Element::willRemove()
{
#if ENABLE(FULLSCREEN_API)
    if (containsFullScreenElement())
        setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false);
#endif
    if (ShadowTree* tree = shadowTree())
        tree->willRemove();
    ContainerNode::willRemove();
}

void Element::insertedIntoDocument()
{
    // need to do superclass processing first so inDocument() is true
    // by the time we reach updateId
    ContainerNode::insertedIntoDocument();
    if (ShadowTree* tree = shadowTree())
        tree->insertedIntoDocument();

    if (m_attributeData) {
        if (hasID()) {
            Attribute* idItem = getAttributeItem(document()->idAttributeName());
            if (idItem && !idItem->isNull())
                updateId(nullAtom, idItem->value());
        }
        if (hasName()) {
            Attribute* nameItem = getAttributeItem(HTMLNames::nameAttr);
            if (nameItem && !nameItem->isNull())
                updateName(nullAtom, nameItem->value());
        }
    }
}

void Element::removedFromDocument()
{
    setSavedLayerScrollOffset(IntSize());

    if (m_attributeData) {
        if (hasID()) {
            Attribute* idItem = getAttributeItem(document()->idAttributeName());
            if (idItem && !idItem->isNull())
                updateId(idItem->value(), nullAtom);
        }
        if (hasName()) {
            Attribute* nameItem = getAttributeItem(HTMLNames::nameAttr);
            if (nameItem && !nameItem->isNull())
                updateName(nameItem->value(), nullAtom);
        }
    }

    ContainerNode::removedFromDocument();
    if (ShadowTree* tree = shadowTree())
        tree->removedFromDocument();
}

void Element::insertedIntoTree(bool deep)
{
    ContainerNode::insertedIntoTree(deep);
    if (!deep)
        return;
    if (ShadowTree* tree = shadowTree())
        tree->insertedIntoTree(true);

#if ENABLE(FULLSCREEN_API)
    if (containsFullScreenElement() && parentElement() && !parentElement()->containsFullScreenElement())
        setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(true);
#endif
}

void Element::removedFromTree(bool deep)
{
    ContainerNode::removedFromTree(deep);
    if (!deep)
        return;
    if (ShadowTree* tree = shadowTree())
        tree->removedFromTree(true);
}

void Element::attach()
{
    suspendPostAttachCallbacks();
    RenderWidget::suspendWidgetHierarchyUpdates();

    createRendererIfNeeded();
    StyleSelectorParentPusher parentPusher(this);

    // When a shadow root exists, it does the work of attaching the children.
    if (ShadowTree* tree = shadowTree()) {
        parentPusher.push();
        tree->attachHost(this);
    } else {
        if (firstChild())
            parentPusher.push();
        ContainerNode::attach();
    }

    if (hasRareData()) {   
        ElementRareData* data = rareData();
        if (data->needsFocusAppearanceUpdateSoonAfterAttach()) {
            if (isFocusable() && document()->focusedNode() == this)
                document()->updateFocusAppearanceSoon(false /* don't restore selection */);
            data->setNeedsFocusAppearanceUpdateSoonAfterAttach(false);
        }
    }

    RenderWidget::resumeWidgetHierarchyUpdates();
    resumePostAttachCallbacks();
}

void Element::detach()
{
    RenderWidget::suspendWidgetHierarchyUpdates();

    cancelFocusAppearanceUpdate();
    if (hasRareData())
        rareData()->resetComputedStyle();

    if (ShadowTree* tree = shadowTree())
        tree->detachHost(this);
    else
        ContainerNode::detach();

    RenderWidget::resumeWidgetHierarchyUpdates();
}

bool Element::pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle)
{
    ASSERT(currentStyle == renderStyle());

    if (!renderer() || !currentStyle)
        return false;

    const PseudoStyleCache* pseudoStyleCache = currentStyle->cachedPseudoStyles();
    if (!pseudoStyleCache)
        return false;

    size_t cacheSize = pseudoStyleCache->size();
    for (size_t i = 0; i < cacheSize; ++i) {
        RefPtr<RenderStyle> newPseudoStyle;
        PseudoId pseudoId = pseudoStyleCache->at(i)->styleType();
        if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED)
            newPseudoStyle = renderer()->uncachedFirstLineStyle(newStyle);
        else
            newPseudoStyle = renderer()->getUncachedPseudoStyle(pseudoId, newStyle, newStyle);
        if (!newPseudoStyle)
            return true;
        if (*newPseudoStyle != *pseudoStyleCache->at(i)) {
            if (pseudoId < FIRST_INTERNAL_PSEUDOID)
                newStyle->setHasPseudoStyle(pseudoId);
            newStyle->addCachedPseudoStyle(newPseudoStyle);
            if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED) {
                // FIXME: We should do an actual diff to determine whether a repaint vs. layout
                // is needed, but for now just assume a layout will be required.  The diff code
                // in RenderObject::setStyle would need to be factored out so that it could be reused.
                renderer()->setNeedsLayoutAndPrefWidthsRecalc();
            }
            return true;
        }
    }
    return false;
}

PassRefPtr<RenderStyle> Element::customStyleForRenderer()
{
    ASSERT_NOT_REACHED(); 
    return 0; 
}

PassRefPtr<RenderStyle> Element::styleForRenderer()
{
    if (hasCustomStyleForRenderer())
        return customStyleForRenderer();
    return document()->styleSelector()->styleForElement(static_cast<Element*>(this));
}

void Element::recalcStyle(StyleChange change)
{
    if (hasCustomWillOrDidRecalcStyle()) {
        if (!willRecalcStyle(change))
            return;
    }

    // Ref currentStyle in case it would otherwise be deleted when setRenderStyle() is called.
    RefPtr<RenderStyle> currentStyle(renderStyle());
    bool hasParentStyle = parentNodeForRenderingAndStyle() ? static_cast<bool>(parentNodeForRenderingAndStyle()->renderStyle()) : false;
    bool hasDirectAdjacentRules = currentStyle && currentStyle->childrenAffectedByDirectAdjacentRules();
    bool hasIndirectAdjacentRules = currentStyle && currentStyle->childrenAffectedByForwardPositionalRules();

    if ((change > NoChange || needsStyleRecalc())) {
        if (hasRareData()) {
            ElementRareData* data = rareData();
            data->resetComputedStyle();
            data->m_styleAffectedByEmpty = false;
        }
    }
    if (hasParentStyle && (change >= Inherit || needsStyleRecalc())) {
        RefPtr<RenderStyle> newStyle = styleForRenderer();
        StyleChange ch = Node::diff(currentStyle.get(), newStyle.get(), document());
        if (ch == Detach || !currentStyle) {
            // FIXME: The style gets computed twice by calling attach. We could do better if we passed the style along.
            reattach();
            // attach recalculates the style for all children. No need to do it twice.
            clearNeedsStyleRecalc();
            clearChildNeedsStyleRecalc();

            if (hasCustomWillOrDidRecalcStyle())
                didRecalcStyle(change);
            return;
        }

        if (currentStyle) {
            // Preserve "affected by" bits that were propagated to us from descendants in the case where we didn't do a full
            // style change (e.g., only inline style changed).
            if (currentStyle->affectedByHoverRules())
                newStyle->setAffectedByHoverRules(true);
            if (currentStyle->affectedByActiveRules())
                newStyle->setAffectedByActiveRules(true);
            if (currentStyle->affectedByDragRules())
                newStyle->setAffectedByDragRules(true);
            if (currentStyle->childrenAffectedByForwardPositionalRules())
                newStyle->setChildrenAffectedByForwardPositionalRules();
            if (currentStyle->childrenAffectedByBackwardPositionalRules())
                newStyle->setChildrenAffectedByBackwardPositionalRules();
            if (currentStyle->childrenAffectedByFirstChildRules())
                newStyle->setChildrenAffectedByFirstChildRules();
            if (currentStyle->childrenAffectedByLastChildRules())
                newStyle->setChildrenAffectedByLastChildRules();
            if (currentStyle->childrenAffectedByDirectAdjacentRules())
                newStyle->setChildrenAffectedByDirectAdjacentRules();
        }

        if (ch != NoChange || pseudoStyleCacheIsInvalid(currentStyle.get(), newStyle.get()) || (change == Force && renderer() && renderer()->requiresForcedStyleRecalcPropagation())) {
            setRenderStyle(newStyle);
        } else if (needsStyleRecalc() && styleChangeType() != SyntheticStyleChange) {
            // Although no change occurred, we use the new style so that the cousin style sharing code won't get
            // fooled into believing this style is the same.
            if (renderer())
                renderer()->setStyleInternal(newStyle.get());
            else
                setRenderStyle(newStyle);
        } else if (styleChangeType() == SyntheticStyleChange)
             setRenderStyle(newStyle);

        // If "rem" units are used anywhere in the document, and if the document element's font size changes, then go ahead and force font updating
        // all the way down the tree. This is simpler than having to maintain a cache of objects (and such font size changes should be rare anyway).
        if (document()->usesRemUnits() && document()->documentElement() == this && ch != NoChange && currentStyle && newStyle && currentStyle->fontSize() != newStyle->fontSize()) {
            // Cached RenderStyles may depend on the rem units.
            document()->styleSelector()->invalidateMatchedPropertiesCache();
            change = Force;
        }

        if (change != Force) {
            if (styleChangeType() == FullStyleChange)
                change = Force;
            else
                change = ch;
        }
    }
    StyleSelectorParentPusher parentPusher(this);
    // FIXME: This check is good enough for :hover + foo, but it is not good enough for :hover + foo + bar.
    // For now we will just worry about the common case, since it's a lot trickier to get the second case right
    // without doing way too much re-resolution.
    bool forceCheckOfNextElementSibling = false;
    bool forceCheckOfAnyElementSibling = false;
    for (Node *n = firstChild(); n; n = n->nextSibling()) {
        if (n->isTextNode()) {
            toText(n)->recalcTextStyle(change);
            continue;
        } 
        if (!n->isElementNode()) 
            continue;
        Element* element = static_cast<Element*>(n);
        bool childRulesChanged = element->needsStyleRecalc() && element->styleChangeType() == FullStyleChange;
        if ((forceCheckOfNextElementSibling || forceCheckOfAnyElementSibling))
            element->setNeedsStyleRecalc();
        if (change >= Inherit || element->childNeedsStyleRecalc() || element->needsStyleRecalc()) {
            parentPusher.push();
            element->recalcStyle(change);
        }
        forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentRules;
        forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (childRulesChanged && hasIndirectAdjacentRules);
    }
    // FIXME: This does not care about sibling combinators. Will be necessary in XBL2 world.
    if (hasShadowRoot()) {
        ShadowTree* tree = shadowTree();
        if (change >= Inherit || tree->childNeedsStyleRecalc() || tree->needsStyleRecalc()) {
            parentPusher.push();
            tree->recalcShadowTreeStyle(change);
        }
    }

    clearNeedsStyleRecalc();
    clearChildNeedsStyleRecalc();
    
    if (hasCustomWillOrDidRecalcStyle())
        didRecalcStyle(change);
}

bool Element::hasShadowRoot() const
{
    if (ShadowTree* tree = shadowTree())
        return tree->hasShadowRoot();
    return false;
}

ShadowTree* Element::shadowTree() const
{
    if (!hasRareData())
        return 0;

    return rareData()->m_shadowTree.get();
}

ShadowTree* Element::ensureShadowTree()
{
    if (ShadowTree* tree = ensureRareData()->m_shadowTree.get())
        return tree;

    rareData()->m_shadowTree = adoptPtr(new ShadowTree());
    return rareData()->m_shadowTree.get();
}

ShadowRoot* Element::ensureShadowRoot()
{
    if (hasShadowRoot())
        return shadowTree()->oldestShadowRoot();

    return ShadowRoot::create(this, ShadowRoot::CreatingUserAgentShadowRoot).get();
}

const AtomicString& Element::shadowPseudoId() const
{
    return hasRareData() ? rareData()->m_shadowPseudoId : nullAtom;
}

void Element::setShadowPseudoId(const AtomicString& id, ExceptionCode& ec)
{
    if (!hasRareData() && id == nullAtom)
        return;

    if (!CSSSelector::isUnknownPseudoType(id)) {
        ec = SYNTAX_ERR;
        return;
    }

    ensureRareData()->m_shadowPseudoId = id;
}

bool Element::childTypeAllowed(NodeType type) const
{
    switch (type) {
    case ELEMENT_NODE:
    case TEXT_NODE:
    case COMMENT_NODE:
    case PROCESSING_INSTRUCTION_NODE:
    case CDATA_SECTION_NODE:
    case ENTITY_REFERENCE_NODE:
        return true;
    default:
        break;
    }
    return false;
}

static void checkForEmptyStyleChange(Element* element, RenderStyle* style)
{
    if (!style && !element->styleAffectedByEmpty())
        return;

    if (!style || (style->affectedByEmpty() && (!style->emptyState() || element->hasChildNodes())))
        element->setNeedsStyleRecalc();
}

static void checkForSiblingStyleChanges(Element* e, RenderStyle* style, bool finishedParsingCallback,
                                        Node* beforeChange, Node* afterChange, int childCountDelta)
{
    // :empty selector.
    checkForEmptyStyleChange(e, style);
    
    if (!style || (e->needsStyleRecalc() && style->childrenAffectedByPositionalRules()))
        return;

    // :first-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
    // In the DOM case, we only need to do something if |afterChange| is not 0.
    // |afterChange| is 0 in the parser case, so it works out that we'll skip this block.
    if (style->childrenAffectedByFirstChildRules() && afterChange) {
        // Find our new first child.
        Node* newFirstChild = 0;
        for (newFirstChild = e->firstChild(); newFirstChild && !newFirstChild->isElementNode(); newFirstChild = newFirstChild->nextSibling()) {};
        
        // Find the first element node following |afterChange|
        Node* firstElementAfterInsertion = 0;
        for (firstElementAfterInsertion = afterChange;
             firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
             firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
        
        // This is the insert/append case.
        if (newFirstChild != firstElementAfterInsertion && firstElementAfterInsertion && firstElementAfterInsertion->attached() &&
            firstElementAfterInsertion->renderStyle() && firstElementAfterInsertion->renderStyle()->firstChildState())
            firstElementAfterInsertion->setNeedsStyleRecalc();
            
        // We also have to handle node removal.
        if (childCountDelta < 0 && newFirstChild == firstElementAfterInsertion && newFirstChild && newFirstChild->renderStyle() && !newFirstChild->renderStyle()->firstChildState())
            newFirstChild->setNeedsStyleRecalc();
    }

    // :last-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
    // In the DOM case, we only need to do something if |afterChange| is not 0.
    if (style->childrenAffectedByLastChildRules() && beforeChange) {
        // Find our new last child.
        Node* newLastChild = 0;
        for (newLastChild = e->lastChild(); newLastChild && !newLastChild->isElementNode(); newLastChild = newLastChild->previousSibling()) {};
        
        // Find the last element node going backwards from |beforeChange|
        Node* lastElementBeforeInsertion = 0;
        for (lastElementBeforeInsertion = beforeChange;
             lastElementBeforeInsertion && !lastElementBeforeInsertion->isElementNode();
             lastElementBeforeInsertion = lastElementBeforeInsertion->previousSibling()) {};
        
        if (newLastChild != lastElementBeforeInsertion && lastElementBeforeInsertion && lastElementBeforeInsertion->attached() &&
            lastElementBeforeInsertion->renderStyle() && lastElementBeforeInsertion->renderStyle()->lastChildState())
            lastElementBeforeInsertion->setNeedsStyleRecalc();
            
        // We also have to handle node removal.  The parser callback case is similar to node removal as well in that we need to change the last child
        // to match now.
        if ((childCountDelta < 0 || finishedParsingCallback) && newLastChild == lastElementBeforeInsertion && newLastChild && newLastChild->renderStyle() && !newLastChild->renderStyle()->lastChildState())
            newLastChild->setNeedsStyleRecalc();
    }

    // The + selector.  We need to invalidate the first element following the insertion point.  It is the only possible element
    // that could be affected by this DOM change.
    if (style->childrenAffectedByDirectAdjacentRules() && afterChange) {
        Node* firstElementAfterInsertion = 0;
        for (firstElementAfterInsertion = afterChange;
             firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
             firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
        if (firstElementAfterInsertion && firstElementAfterInsertion->attached())
            firstElementAfterInsertion->setNeedsStyleRecalc();
    }

    // Forward positional selectors include the ~ selector, nth-child, nth-of-type, first-of-type and only-of-type.
    // Backward positional selectors include nth-last-child, nth-last-of-type, last-of-type and only-of-type.
    // We have to invalidate everything following the insertion point in the forward case, and everything before the insertion point in the
    // backward case.
    // |afterChange| is 0 in the parser callback case, so we won't do any work for the forward case if we don't have to.
    // For performance reasons we just mark the parent node as changed, since we don't want to make childrenChanged O(n^2) by crawling all our kids
    // here.  recalcStyle will then force a walk of the children when it sees that this has happened.
    if ((style->childrenAffectedByForwardPositionalRules() && afterChange) ||
        (style->childrenAffectedByBackwardPositionalRules() && beforeChange))
        e->setNeedsStyleRecalc();
}

void Element::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
{
    ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
    if (changedByParser)
        checkForEmptyStyleChange(this, renderStyle());
    else
        checkForSiblingStyleChanges(this, renderStyle(), false, beforeChange, afterChange, childCountDelta);

    if (hasRareData()) {
        if (hasShadowRoot())
            shadowTree()->hostChildrenChanged();
    }
}

void Element::beginParsingChildren()
{
    clearIsParsingChildrenFinished();
    CSSStyleSelector* styleSelector = document()->styleSelectorIfExists();
    if (styleSelector && attached())
        styleSelector->pushParentElement(this);
}

void Element::finishParsingChildren()
{
    ContainerNode::finishParsingChildren();
    setIsParsingChildrenFinished();
    checkForSiblingStyleChanges(this, renderStyle(), true, lastChild(), 0, 0);
    if (CSSStyleSelector* styleSelector = document()->styleSelectorIfExists())
        styleSelector->popParentElement(this);
}

#ifndef NDEBUG
void Element::formatForDebugger(char* buffer, unsigned length) const
{
    String result;
    String s;
    
    s = nodeName();
    if (s.length() > 0) {
        result += s;
    }
          
    s = getIdAttribute();
    if (s.length() > 0) {
        if (result.length() > 0)
            result += "; ";
        result += "id=";
        result += s;
    }
          
    s = getAttribute(classAttr);
    if (s.length() > 0) {
        if (result.length() > 0)
            result += "; ";
        result += "class=";
        result += s;
    }
          
    strncpy(buffer, result.utf8().data(), length - 1);
}
#endif

PassRefPtr<Attr> Element::setAttributeNode(Attr* attr, ExceptionCode& ec)
{
    if (!attr) {
        ec = TYPE_MISMATCH_ERR;
        return 0;
    }

    ElementAttributeData* attributeData = ensureUpdatedAttributeData();
    Attribute* attribute = attr->attr();
    size_t index = attributeData->getAttributeItemIndex(attribute->name());
    Attribute* oldAttribute = index != notFound ? attributeData->attributeItem(index) : 0;
    if (oldAttribute == attribute)
        return attr; // we know about it already

    // INUSE_ATTRIBUTE_ERR: Raised if node is an Attr that is already an attribute of another Element object.
    // The DOM user must explicitly clone Attr nodes to re-use them in other elements.
    if (attr->ownerElement()) {
        ec = INUSE_ATTRIBUTE_ERR;
        return 0;
    }

    RefPtr<Attr> oldAttr;
    if (oldAttribute) {
        oldAttr = oldAttribute->createAttrIfNeeded(this);
        attributeData->replaceAttribute(index, attribute, this);
    } else
        attributeData->addAttribute(attribute, this);

    return oldAttr.release();
}

PassRefPtr<Attr> Element::setAttributeNodeNS(Attr* attr, ExceptionCode& ec)
{
    return setAttributeNode(attr, ec);
}

PassRefPtr<Attr> Element::removeAttributeNode(Attr* attr, ExceptionCode& ec)
{
    if (!attr) {
        ec = TYPE_MISMATCH_ERR;
        return 0;
    }
    if (attr->ownerElement() != this) {
        ec = NOT_FOUND_ERR;
        return 0;
    }

    ASSERT(document() == attr->document());

    ElementAttributeData* attributeData = updatedAttributeData();
    if (!attributeData)
        return 0;

    size_t index = attributeData->getAttributeItemIndex(attr->qualifiedName());
    if (index == notFound) {
        ec = NOT_FOUND_ERR;
        return 0;
    }

    return attributeData->takeAttribute(index, this);
}

void Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode& ec, FragmentScriptingPermission scriptingPermission)
{
    String prefix, localName;
    if (!Document::parseQualifiedName(qualifiedName, prefix, localName, ec))
        return;

    QualifiedName qName(prefix, localName, namespaceURI);

    if (!Document::hasValidNamespaceForAttributes(qName)) {
        ec = NAMESPACE_ERR;
        return;
    }

    if (scriptingPermission == FragmentScriptingNotAllowed && (isEventHandlerAttribute(qName) || isAttributeToRemove(qName, value)))
        return;

    setAttribute(qName, value);
}

void Element::removeAttribute(const String& name)
{
    ElementAttributeData* attributeData = this->attributeData();
    if (!attributeData)
        return;

    String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
    size_t index = attributeData->getAttributeItemIndex(localName, false);
    if (index == notFound)
        return;

    attributeData->removeAttribute(index, this);
}

void Element::removeAttributeNS(const String& namespaceURI, const String& localName)
{
    removeAttribute(QualifiedName(nullAtom, localName, namespaceURI));
}

PassRefPtr<Attr> Element::getAttributeNode(const String& name)
{
    ElementAttributeData* attributeData = updatedAttributeData();
    if (!attributeData)
        return 0;
    return attributeData->getAttributeNode(name, shouldIgnoreAttributeCase(this), this);
}

PassRefPtr<Attr> Element::getAttributeNodeNS(const String& namespaceURI, const String& localName)
{
    ElementAttributeData* attributeData = updatedAttributeData();
    if (!attributeData)
        return 0;
    return attributeData->getAttributeNode(QualifiedName(nullAtom, localName, namespaceURI), this);
}

bool Element::hasAttribute(const String& name) const
{
    ElementAttributeData* attributeData = updatedAttributeData();
    if (!attributeData)
        return false;

    // This call to String::lower() seems to be required but
    // there may be a way to remove it.
    String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
    return attributeData->getAttributeItem(localName, false);
}

bool Element::hasAttributeNS(const String& namespaceURI, const String& localName) const
{
    ElementAttributeData* attributeData = updatedAttributeData();
    if (!attributeData)
        return false;
    return attributeData->getAttributeItem(QualifiedName(nullAtom, localName, namespaceURI));
}

CSSStyleDeclaration *Element::style()
{
    return 0;
}

void Element::focus(bool restorePreviousSelection)
{
    if (!inDocument())
        return;

    Document* doc = document();
    if (doc->focusedNode() == this)
        return;

    // If the stylesheets have already been loaded we can reliably check isFocusable.
    // If not, we continue and set the focused node on the focus controller below so
    // that it can be updated soon after attach. 
    if (doc->haveStylesheetsLoaded()) {
        doc->updateLayoutIgnorePendingStylesheets();
        if (!isFocusable())
            return;
    }

    if (!supportsFocus())
        return;

    RefPtr<Node> protect;
    if (Page* page = doc->page()) {
        // Focus and change event handlers can cause us to lose our last ref.
        // If a focus event handler changes the focus to a different node it
        // does not make sense to continue and update appearence.
        protect = this;
        if (!page->focusController()->setFocusedNode(this, doc->frame()))
            return;
    }

    // Setting the focused node above might have invalidated the layout due to scripts.
    doc->updateLayoutIgnorePendingStylesheets();

    if (!isFocusable()) {
        ensureRareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(true);
        return;
    }
        
    cancelFocusAppearanceUpdate();
    updateFocusAppearance(restorePreviousSelection);
}

void Element::updateFocusAppearance(bool /*restorePreviousSelection*/)
{
    if (this == rootEditableElement()) { 
        Frame* frame = document()->frame();
        if (!frame)
            return;
        
        // When focusing an editable element in an iframe, don't reset the selection if it already contains a selection.
        if (this == frame->selection()->rootEditableElement())
            return;

        // FIXME: We should restore the previous selection if there is one.
        VisibleSelection newSelection = VisibleSelection(firstPositionInOrBeforeNode(this), DOWNSTREAM);
        
        if (frame->selection()->shouldChangeSelection(newSelection)) {
            frame->selection()->setSelection(newSelection);
            frame->selection()->revealSelection();
        }
    } else if (renderer() && !renderer()->isWidget())
        renderer()->enclosingLayer()->scrollRectToVisible(getRect());
}

void Element::blur()
{
    cancelFocusAppearanceUpdate();
    Document* doc = document();
    if (treeScope()->focusedNode() == this) {
        if (doc->frame())
            doc->frame()->page()->focusController()->setFocusedNode(0, doc->frame());
        else
            doc->setFocusedNode(0);
    }
}

String Element::innerText()
{
    // We need to update layout, since plainText uses line boxes in the render tree.
    document()->updateLayoutIgnorePendingStylesheets();

    if (!renderer())
        return textContent(true);

    return plainText(rangeOfContents(const_cast<Element*>(this)).get());
}

String Element::outerText()
{
    // Getting outerText is the same as getting innerText, only
    // setting is different. You would think this should get the plain
    // text for the outer range, but this is wrong, <br> for instance
    // would return different values for inner and outer text by such
    // a rule, but it doesn't in WinIE, and we want to match that.
    return innerText();
}

String Element::title() const
{
    return String();
}

LayoutSize Element::minimumSizeForResizing() const
{
    return hasRareData() ? rareData()->m_minimumSizeForResizing : defaultMinimumSizeForResizing();
}

void Element::setMinimumSizeForResizing(const LayoutSize& size)
{
    if (size == defaultMinimumSizeForResizing() && !hasRareData())
        return;
    ensureRareData()->m_minimumSizeForResizing = size;
}

RenderStyle* Element::computedStyle(PseudoId pseudoElementSpecifier)
{
    // FIXME: Find and use the renderer from the pseudo element instead of the actual element so that the 'length'
    // properties, which are only known by the renderer because it did the layout, will be correct and so that the
    // values returned for the ":selection" pseudo-element will be correct.
    if (RenderStyle* usedStyle = renderStyle()) {
        if (pseudoElementSpecifier) {
            RenderStyle* cachedPseudoStyle = usedStyle->getCachedPseudoStyle(pseudoElementSpecifier);
            return cachedPseudoStyle ? cachedPseudoStyle : usedStyle;
         } else
            return usedStyle;
    }

    if (!attached())
        // FIXME: Try to do better than this. Ensure that styleForElement() works for elements that are not in the
        // document tree and figure out when to destroy the computed style for such elements.
        return 0;

    ElementRareData* data = ensureRareData();
    if (!data->m_computedStyle)
        data->m_computedStyle = document()->styleForElementIgnoringPendingStylesheets(this);
    return pseudoElementSpecifier ? data->m_computedStyle->getCachedPseudoStyle(pseudoElementSpecifier) : data->m_computedStyle.get();
}

void Element::setStyleAffectedByEmpty()
{
    ElementRareData* data = ensureRareData();
    data->m_styleAffectedByEmpty = true;
}

bool Element::styleAffectedByEmpty() const
{
    return hasRareData() && rareData()->m_styleAffectedByEmpty;
}

AtomicString Element::computeInheritedLanguage() const
{
    const Node* n = this;
    AtomicString value;
    // The language property is inherited, so we iterate over the parents to find the first language.
    while (n && value.isNull()) {
        if (n->isElementNode()) {
            // Spec: xml:lang takes precedence -- http://www.w3.org/TR/xhtml1/#C_7
            value = static_cast<const Element*>(n)->fastGetAttribute(XMLNames::langAttr);
            if (value.isNull())
                value = static_cast<const Element*>(n)->fastGetAttribute(HTMLNames::langAttr);
        } else if (n->isDocumentNode()) {
            // checking the MIME content-language
            value = static_cast<const Document*>(n)->contentLanguage();
        }

        n = n->parentNode();
    }

    return value;
}

void Element::cancelFocusAppearanceUpdate()
{
    if (hasRareData())
        rareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(false);
    if (document()->focusedNode() == this)
        document()->cancelFocusAppearanceUpdate();
}

void Element::normalizeAttributes()
{
    ElementAttributeData* attributeData = updatedAttributeData();
    if (!attributeData || attributeData->isEmpty())
        return;

    Vector<RefPtr<Attribute> > attributeVector;
    attributeData->copyAttributesToVector(attributeVector);
    size_t numAttrs = attributeVector.size();
    for (size_t i = 0; i < numAttrs; ++i) {
        if (Attr* attr = attributeVector[i]->attr())
            attr->normalize();
    }
}

// ElementTraversal API
Element* Element::firstElementChild() const
{
    return WebCore::firstElementChild(this);
}

Element* Element::lastElementChild() const
{
    Node* n = lastChild();
    while (n && !n->isElementNode())
        n = n->previousSibling();
    return static_cast<Element*>(n);
}

unsigned Element::childElementCount() const
{
    unsigned count = 0;
    Node* n = firstChild();
    while (n) {
        count += n->isElementNode();
        n = n->nextSibling();
    }
    return count;
}

bool Element::webkitMatchesSelector(const String& selector, ExceptionCode& ec)
{
    if (selector.isEmpty()) {
        ec = SYNTAX_ERR;
        return false;
    }

    bool strictParsing = !document()->inQuirksMode();
    CSSParser p(strictToCSSParserMode(strictParsing));

    CSSSelectorList selectorList;
    p.parseSelector(selector, document(), selectorList);

    if (!selectorList.first()) {
        ec = SYNTAX_ERR;
        return false;
    }

    // Throw a NAMESPACE_ERR if the selector includes any namespace prefixes.
    if (selectorList.selectorsNeedNamespaceResolution()) {
        ec = NAMESPACE_ERR;
        return false;
    }

    SelectorChecker selectorChecker(document(), strictParsing);
    for (CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
        if (selectorChecker.checkSelector(selector, this))
            return true;
    }

    return false;
}

DOMTokenList* Element::classList()
{
    ElementRareData* data = ensureRareData();
    if (!data->m_classList)
        data->m_classList = ClassList::create(this);
    return data->m_classList.get();
}

DOMTokenList* Element::optionalClassList() const
{
    if (!hasRareData())
        return 0;
    return rareData()->m_classList.get();
}

DOMStringMap* Element::dataset()
{
    ElementRareData* data = ensureRareData();
    if (!data->m_datasetDOMStringMap)
        data->m_datasetDOMStringMap = DatasetDOMStringMap::create(this);
    return data->m_datasetDOMStringMap.get();
}

KURL Element::getURLAttribute(const QualifiedName& name) const
{
#if !ASSERT_DISABLED
    if (m_attributeData) {
        if (Attribute* attribute = getAttributeItem(name))
            ASSERT(isURLAttribute(attribute));
    }
#endif
    return document()->completeURL(stripLeadingAndTrailingHTMLSpaces(getAttribute(name)));
}

KURL Element::getNonEmptyURLAttribute(const QualifiedName& name) const
{
#if !ASSERT_DISABLED
    if (m_attributeData) {
        if (Attribute* attribute = getAttributeItem(name))
            ASSERT(isURLAttribute(attribute));
    }
#endif
    String value = stripLeadingAndTrailingHTMLSpaces(getAttribute(name));
    if (value.isEmpty())
        return KURL();
    return document()->completeURL(value);
}

int Element::getIntegralAttribute(const QualifiedName& attributeName) const
{
    return getAttribute(attributeName).string().toInt();
}

void Element::setIntegralAttribute(const QualifiedName& attributeName, int value)
{
    // FIXME: Need an AtomicString version of String::number.
    setAttribute(attributeName, String::number(value));
}

unsigned Element::getUnsignedIntegralAttribute(const QualifiedName& attributeName) const
{
    return getAttribute(attributeName).string().toUInt();
}

void Element::setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value)
{
    // FIXME: Need an AtomicString version of String::number.
    setAttribute(attributeName, String::number(value));
}

#if ENABLE(SVG)
bool Element::childShouldCreateRenderer(const NodeRenderingContext& childContext) const
{
    // Only create renderers for SVG elements whose parents are SVG elements, or for proper <svg xmlns="svgNS"> subdocuments.
    if (childContext.node()->isSVGElement())
        return childContext.node()->hasTagName(SVGNames::svgTag) || isSVGElement();

    return Node::childShouldCreateRenderer(childContext);
}
#endif
    
#if ENABLE(FULLSCREEN_API)
void Element::webkitRequestFullscreen()
{
    document()->requestFullScreenForElement(this, ALLOW_KEYBOARD_INPUT, Document::EnforceIFrameAllowFulScreenRequirement);
}

void Element::webkitRequestFullScreen(unsigned short flags)
{
    document()->requestFullScreenForElement(this, (flags | LEGACY_MOZILLA_REQUEST), Document::EnforceIFrameAllowFulScreenRequirement);
}

bool Element::containsFullScreenElement() const
{
    return hasRareData() ? rareData()->m_containsFullScreenElement : false;
}

void Element::setContainsFullScreenElement(bool flag)
{
    ensureRareData()->m_containsFullScreenElement = flag;
    setNeedsStyleRecalc(SyntheticStyleChange);
}

static Element* parentCrossingFrameBoundaries(Element* element)
{
    ASSERT(element);
    return element->parentElement() ? element->parentElement() : element->document()->ownerElement();
}

void Element::setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(bool flag)
{
    Element* element = this;
    while ((element = parentCrossingFrameBoundaries(element)))
        element->setContainsFullScreenElement(flag);
}
#endif    

SpellcheckAttributeState Element::spellcheckAttributeState() const
{
    const AtomicString& value = getAttribute(HTMLNames::spellcheckAttr);
    if (value == nullAtom)
        return SpellcheckAttributeDefault;
    if (equalIgnoringCase(value, "true") || equalIgnoringCase(value, ""))
        return SpellcheckAttributeTrue;
    if (equalIgnoringCase(value, "false"))
        return SpellcheckAttributeFalse;

    return SpellcheckAttributeDefault;
}

bool Element::isSpellCheckingEnabled() const
{
    const Element* element = this;
    while (element) {
        switch (element->spellcheckAttributeState()) {
        case SpellcheckAttributeTrue:
            return true;
        case SpellcheckAttributeFalse:
            return false;
        case SpellcheckAttributeDefault:
            break;
        }

        ContainerNode* parent = const_cast<Element*>(element)->parentOrHostNode();
        if (parent && parent->isElementNode())
            element = toElement(parent);
        else if (parent && parent->isShadowRoot())
            element = toElement(parent->parentOrHostNode());
        else
            element = 0;
    }

    return true;
}

PassRefPtr<WebKitAnimationList> Element::webkitGetAnimations() const
{
    if (!renderer())
        return 0;

    AnimationController* animController = renderer()->animation();

    if (!animController)
        return 0;
    
    return animController->animationsForRenderer(renderer());
}

const AtomicString& Element::webkitRegionOverflow() const
{
    document()->updateLayoutIgnorePendingStylesheets();

    if (document()->cssRegionsEnabled() && renderer() && renderer()->isRenderRegion()) {
        RenderRegion* region = toRenderRegion(renderer());
        switch (region->regionState()) {
        case RenderRegion::RegionFit: {
            DEFINE_STATIC_LOCAL(AtomicString, fitState, ("fit"));
            return fitState;
        }
        case RenderRegion::RegionEmpty: {
            DEFINE_STATIC_LOCAL(AtomicString, emptyState, ("empty"));
            return emptyState;
        }
        case RenderRegion::RegionOverflow: {
            DEFINE_STATIC_LOCAL(AtomicString, overflowState, ("overflow"));
            return overflowState;
        }
        default:
            break;
        }
    }
    DEFINE_STATIC_LOCAL(AtomicString, undefinedState, ("undefined"));
    return undefinedState;
}

#ifndef NDEBUG
bool Element::fastAttributeLookupAllowed(const QualifiedName& name) const
{
    if (name == HTMLNames::styleAttr)
        return false;

#if ENABLE(SVG)
    if (isSVGElement())
        return !SVGElement::isAnimatableAttribute(name);
#endif

    return true;
}
#endif

#ifdef DUMP_NODE_STATISTICS
bool Element::hasNamedNodeMap() const
{
    return hasRareData() && rareData()->m_attributeMap;
}
#endif

void Element::willModifyAttribute(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue)
{
    if (isIdAttributeName(name))
        updateId(oldValue, newValue);
    else if (name == HTMLNames::nameAttr)
        updateName(oldValue, newValue);

#if ENABLE(MUTATION_OBSERVERS)
    if (OwnPtr<MutationObserverInterestGroup> recipients = MutationObserverInterestGroup::createForAttributesMutation(this, name))
        recipients->enqueueMutationRecord(MutationRecord::createAttributes(this, name, oldValue));
#endif

#if ENABLE(INSPECTOR)
    InspectorInstrumentation::willModifyDOMAttr(document(), this, oldValue, newValue);
#endif
}

void Element::didAddAttribute(Attribute* attr)
{
    attributeChanged(attr);
    InspectorInstrumentation::didModifyDOMAttr(document(), this, attr->name().localName(), attr->value());
    dispatchSubtreeModifiedEvent();
}

void Element::didModifyAttribute(Attribute* attr)
{
    attributeChanged(attr);
    InspectorInstrumentation::didModifyDOMAttr(document(), this, attr->name().localName(), attr->value());
    // Do not dispatch a DOMSubtreeModified event here; see bug 81141.
}

void Element::didRemoveAttribute(Attribute* attr)
{
    if (attr->isNull())
        return;

    AtomicString savedValue = attr->value();
    attr->setValue(nullAtom);
    attributeChanged(attr);
    attr->setValue(savedValue);

    InspectorInstrumentation::didRemoveDOMAttr(document(), this, attr->name().localName());
    dispatchSubtreeModifiedEvent();
}


void Element::updateNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName)
{
    if (!document()->isHTMLDocument())
        return;

    if (!oldName.isEmpty())
        static_cast<HTMLDocument*>(document())->removeNamedItem(oldName);

    if (!newName.isEmpty())
        static_cast<HTMLDocument*>(document())->addNamedItem(newName);
}

void Element::updateExtraNamedItemRegistration(const AtomicString& oldId, const AtomicString& newId)
{
    if (!document()->isHTMLDocument())
        return;

    if (!oldId.isEmpty())
        static_cast<HTMLDocument*>(document())->removeExtraNamedItem(oldId);

    if (!newId.isEmpty())
        static_cast<HTMLDocument*>(document())->addExtraNamedItem(newId);
}

HTMLCollection* Element::ensureCachedHTMLCollection(CollectionType type)
{
    return ensureRareData()->ensureCachedHTMLCollection(this, type);
}

IntSize Element::savedLayerScrollOffset() const
{
    return hasRareData() ? rareData()->m_savedLayerScrollOffset : IntSize();
}

void Element::setSavedLayerScrollOffset(const IntSize& size)
{
    if (size.isZero() && !hasRareData())
        return;
    ensureRareData()->m_savedLayerScrollOffset = size;
}

} // namespace WebCore
