Home | History | Annotate | Download | only in dom
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 1999 Antti Koivisto (koivisto (at) kde.org)
      4  *           (C) 2001 Peter Kelly (pmk (at) post.com)
      5  *           (C) 2001 Dirk Mueller (mueller (at) kde.org)
      6  *           (C) 2007 David Smith (catfish.man (at) gmail.com)
      7  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
      8  *           (C) 2007 Eric Seidel (eric (at) webkit.org)
      9  *
     10  * This library is free software; you can redistribute it and/or
     11  * modify it under the terms of the GNU Library General Public
     12  * License as published by the Free Software Foundation; either
     13  * version 2 of the License, or (at your option) any later version.
     14  *
     15  * This library is distributed in the hope that it will be useful,
     16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     18  * Library General Public License for more details.
     19  *
     20  * You should have received a copy of the GNU Library General Public License
     21  * along with this library; see the file COPYING.LIB.  If not, write to
     22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     23  * Boston, MA 02110-1301, USA.
     24  */
     25 
     26 #include "config.h"
     27 #include "Element.h"
     28 
     29 #include "AXObjectCache.h"
     30 #include "Attr.h"
     31 #include "CSSParser.h"
     32 #include "CSSSelectorList.h"
     33 #include "CSSStyleSelector.h"
     34 #include "ClassList.h"
     35 #include "ClientRect.h"
     36 #include "ClientRectList.h"
     37 #include "DOMTokenList.h"
     38 #include "DatasetDOMStringMap.h"
     39 #include "Document.h"
     40 #include "DocumentFragment.h"
     41 #include "ElementRareData.h"
     42 #include "ExceptionCode.h"
     43 #include "FocusController.h"
     44 #include "Frame.h"
     45 #include "FrameView.h"
     46 #include "HTMLElement.h"
     47 #include "HTMLNames.h"
     48 #include "HTMLParserIdioms.h"
     49 #include "InspectorInstrumentation.h"
     50 #include "NodeList.h"
     51 #include "NodeRenderStyle.h"
     52 #include "Page.h"
     53 #include "RenderLayer.h"
     54 #include "RenderView.h"
     55 #include "RenderWidget.h"
     56 #include "Settings.h"
     57 #include "ShadowRoot.h"
     58 #include "TextIterator.h"
     59 #include "WebKitAnimationList.h"
     60 #include "XMLNames.h"
     61 #include "htmlediting.h"
     62 #include <wtf/text/CString.h>
     63 
     64 #if ENABLE(SVG)
     65 #include "SVGElement.h"
     66 #include "SVGNames.h"
     67 #endif
     68 
     69 namespace WebCore {
     70 
     71 using namespace HTMLNames;
     72 using namespace XMLNames;
     73 
     74 class StyleSelectorParentPusher {
     75 public:
     76     StyleSelectorParentPusher(Element* parent)
     77         : m_parent(parent)
     78         , m_pushedStyleSelector(0)
     79     {
     80     }
     81     void push()
     82     {
     83         if (m_pushedStyleSelector)
     84             return;
     85         m_pushedStyleSelector = m_parent->document()->styleSelector();
     86         m_pushedStyleSelector->pushParent(m_parent);
     87     }
     88     ~StyleSelectorParentPusher()
     89     {
     90 
     91         if (!m_pushedStyleSelector)
     92             return;
     93 
     94         // This tells us that our pushed style selector is in a bad state,
     95         // so we should just bail out in that scenario.
     96         ASSERT(m_pushedStyleSelector == m_parent->document()->styleSelector());
     97         if (m_pushedStyleSelector != m_parent->document()->styleSelector())
     98             return;
     99 
    100         m_pushedStyleSelector->popParent(m_parent);
    101     }
    102 
    103 private:
    104     Element* m_parent;
    105     CSSStyleSelector* m_pushedStyleSelector;
    106 };
    107 
    108 PassRefPtr<Element> Element::create(const QualifiedName& tagName, Document* document)
    109 {
    110     return adoptRef(new Element(tagName, document, CreateElement));
    111 }
    112 
    113 Element::~Element()
    114 {
    115     removeShadowRoot();
    116     if (m_attributeMap)
    117         m_attributeMap->detachFromElement();
    118 }
    119 
    120 inline ElementRareData* Element::rareData() const
    121 {
    122     ASSERT(hasRareData());
    123     return static_cast<ElementRareData*>(NodeRareData::rareDataFromMap(this));
    124 }
    125 
    126 inline ElementRareData* Element::ensureRareData()
    127 {
    128     return static_cast<ElementRareData*>(Node::ensureRareData());
    129 }
    130 
    131 NodeRareData* Element::createRareData()
    132 {
    133     return new ElementRareData;
    134 }
    135 
    136 DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, blur);
    137 DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, error);
    138 DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, focus);
    139 DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, load);
    140 
    141 PassRefPtr<DocumentFragment> Element::deprecatedCreateContextualFragment(const String& markup, FragmentScriptingPermission scriptingPermission)
    142 {
    143     RefPtr<DocumentFragment> fragment = document()->createDocumentFragment();
    144 
    145     if (document()->isHTMLDocument())
    146         fragment->parseHTML(markup, this, scriptingPermission);
    147     else {
    148         if (!fragment->parseXML(markup, this, scriptingPermission))
    149             // FIXME: We should propagate a syntax error exception out here.
    150             return 0;
    151     }
    152 
    153     // Exceptions are ignored because none ought to happen here.
    154     ExceptionCode ignoredExceptionCode;
    155 
    156     // We need to pop <html> and <body> elements and remove <head> to
    157     // accommodate folks passing complete HTML documents to make the
    158     // child of an element.
    159 
    160     RefPtr<Node> nextNode;
    161     for (RefPtr<Node> node = fragment->firstChild(); node; node = nextNode) {
    162         nextNode = node->nextSibling();
    163         if (node->hasTagName(htmlTag) || node->hasTagName(bodyTag)) {
    164             HTMLElement* element = toHTMLElement(node.get());
    165             Node* firstChild = element->firstChild();
    166             if (firstChild)
    167                 nextNode = firstChild;
    168             RefPtr<Node> nextChild;
    169             for (RefPtr<Node> child = firstChild; child; child = nextChild) {
    170                 nextChild = child->nextSibling();
    171                 element->removeChild(child.get(), ignoredExceptionCode);
    172                 ASSERT(!ignoredExceptionCode);
    173                 fragment->insertBefore(child, element, ignoredExceptionCode);
    174                 ASSERT(!ignoredExceptionCode);
    175             }
    176             fragment->removeChild(element, ignoredExceptionCode);
    177             ASSERT(!ignoredExceptionCode);
    178         } else if (node->hasTagName(headTag)) {
    179             fragment->removeChild(node.get(), ignoredExceptionCode);
    180             ASSERT(!ignoredExceptionCode);
    181         }
    182     }
    183     return fragment.release();
    184 }
    185 
    186 PassRefPtr<Node> Element::cloneNode(bool deep)
    187 {
    188     return deep ? cloneElementWithChildren() : cloneElementWithoutChildren();
    189 }
    190 
    191 PassRefPtr<Element> Element::cloneElementWithChildren()
    192 {
    193     RefPtr<Element> clone = cloneElementWithoutChildren();
    194     cloneChildNodes(clone.get());
    195     return clone.release();
    196 }
    197 
    198 PassRefPtr<Element> Element::cloneElementWithoutChildren()
    199 {
    200     RefPtr<Element> clone = cloneElementWithoutAttributesAndChildren();
    201     // This will catch HTML elements in the wrong namespace that are not correctly copied.
    202     // This is a sanity check as HTML overloads some of the DOM methods.
    203     ASSERT(isHTMLElement() == clone->isHTMLElement());
    204 
    205     // Call attributes(true) to force attribute synchronization to occur for SVG and style attributes.
    206     if (NamedNodeMap* attributeMap = attributes(true))
    207         clone->attributes()->setAttributes(*attributeMap);
    208 
    209     clone->copyNonAttributeProperties(this);
    210 
    211     return clone.release();
    212 }
    213 
    214 PassRefPtr<Element> Element::cloneElementWithoutAttributesAndChildren() const
    215 {
    216     return document()->createElement(tagQName(), false);
    217 }
    218 
    219 void Element::removeAttribute(const QualifiedName& name, ExceptionCode& ec)
    220 {
    221     if (m_attributeMap) {
    222         ec = 0;
    223         m_attributeMap->removeNamedItem(name, ec);
    224         if (ec == NOT_FOUND_ERR)
    225             ec = 0;
    226     }
    227 }
    228 
    229 void Element::setAttribute(const QualifiedName& name, const AtomicString& value)
    230 {
    231     ExceptionCode ec;
    232     setAttribute(name, value, ec);
    233 }
    234 
    235 void Element::setCStringAttribute(const QualifiedName& name, const char* cStringValue)
    236 {
    237     ExceptionCode ec;
    238     setAttribute(name, AtomicString(cStringValue), ec);
    239 }
    240 
    241 void Element::setBooleanAttribute(const QualifiedName& name, bool b)
    242 {
    243     if (b)
    244         setAttribute(name, emptyAtom);
    245     else {
    246         ExceptionCode ex;
    247         removeAttribute(name, ex);
    248     }
    249 }
    250 
    251 Node::NodeType Element::nodeType() const
    252 {
    253     return ELEMENT_NODE;
    254 }
    255 
    256 bool Element::hasAttribute(const QualifiedName& name) const
    257 {
    258     return hasAttributeNS(name.namespaceURI(), name.localName());
    259 }
    260 
    261 const AtomicString& Element::getAttribute(const QualifiedName& name) const
    262 {
    263     if (UNLIKELY(name == styleAttr) && !isStyleAttributeValid())
    264         updateStyleAttribute();
    265 
    266 #if ENABLE(SVG)
    267     if (UNLIKELY(!areSVGAttributesValid()))
    268         updateAnimatedSVGAttribute(name);
    269 #endif
    270 
    271     return fastGetAttribute(name);
    272 }
    273 
    274 void Element::scrollIntoView(bool alignToTop)
    275 {
    276     document()->updateLayoutIgnorePendingStylesheets();
    277     IntRect bounds = getRect();
    278     if (renderer()) {
    279         // Align to the top / bottom and to the closest edge.
    280         if (alignToTop)
    281             renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
    282         else
    283             renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignBottomAlways);
    284     }
    285 }
    286 
    287 void Element::scrollIntoViewIfNeeded(bool centerIfNeeded)
    288 {
    289     document()->updateLayoutIgnorePendingStylesheets();
    290     IntRect bounds = getRect();
    291     if (renderer()) {
    292         if (centerIfNeeded)
    293             renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded);
    294         else
    295             renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
    296     }
    297 }
    298 
    299 void Element::scrollByUnits(int units, ScrollGranularity granularity)
    300 {
    301     document()->updateLayoutIgnorePendingStylesheets();
    302     if (RenderObject *rend = renderer()) {
    303         if (rend->hasOverflowClip()) {
    304             ScrollDirection direction = ScrollDown;
    305             if (units < 0) {
    306                 direction = ScrollUp;
    307                 units = -units;
    308             }
    309             toRenderBox(rend)->layer()->scroll(direction, granularity, units);
    310         }
    311     }
    312 }
    313 
    314 void Element::scrollByLines(int lines)
    315 {
    316     scrollByUnits(lines, ScrollByLine);
    317 }
    318 
    319 void Element::scrollByPages(int pages)
    320 {
    321     scrollByUnits(pages, ScrollByPage);
    322 }
    323 
    324 static float localZoomForRenderer(RenderObject* renderer)
    325 {
    326     // FIXME: This does the wrong thing if two opposing zooms are in effect and canceled each
    327     // other out, but the alternative is that we'd have to crawl up the whole render tree every
    328     // time (or store an additional bit in the RenderStyle to indicate that a zoom was specified).
    329     float zoomFactor = 1;
    330     if (renderer->style()->effectiveZoom() != 1) {
    331         // Need to find the nearest enclosing RenderObject that set up
    332         // a differing zoom, and then we divide our result by it to eliminate the zoom.
    333         RenderObject* prev = renderer;
    334         for (RenderObject* curr = prev->parent(); curr; curr = curr->parent()) {
    335             if (curr->style()->effectiveZoom() != prev->style()->effectiveZoom()) {
    336                 zoomFactor = prev->style()->zoom();
    337                 break;
    338             }
    339             prev = curr;
    340         }
    341         if (prev->isRenderView())
    342             zoomFactor = prev->style()->zoom();
    343     }
    344     return zoomFactor;
    345 }
    346 
    347 static int adjustForLocalZoom(int value, RenderObject* renderer)
    348 {
    349     float zoomFactor = localZoomForRenderer(renderer);
    350     if (zoomFactor == 1)
    351         return value;
    352     // Needed because computeLengthInt truncates (rather than rounds) when scaling up.
    353     if (zoomFactor > 1)
    354         value++;
    355     return static_cast<int>(value / zoomFactor);
    356 }
    357 
    358 int Element::offsetLeft()
    359 {
    360     document()->updateLayoutIgnorePendingStylesheets();
    361     if (RenderBoxModelObject* rend = renderBoxModelObject())
    362         return adjustForLocalZoom(rend->offsetLeft(), rend);
    363     return 0;
    364 }
    365 
    366 int Element::offsetTop()
    367 {
    368     document()->updateLayoutIgnorePendingStylesheets();
    369     if (RenderBoxModelObject* rend = renderBoxModelObject())
    370         return adjustForLocalZoom(rend->offsetTop(), rend);
    371     return 0;
    372 }
    373 
    374 int Element::offsetWidth()
    375 {
    376     document()->updateLayoutIgnorePendingStylesheets();
    377     if (RenderBoxModelObject* rend = renderBoxModelObject())
    378         return adjustForAbsoluteZoom(rend->offsetWidth(), rend);
    379     return 0;
    380 }
    381 
    382 int Element::offsetHeight()
    383 {
    384     document()->updateLayoutIgnorePendingStylesheets();
    385     if (RenderBoxModelObject* rend = renderBoxModelObject())
    386         return adjustForAbsoluteZoom(rend->offsetHeight(), rend);
    387     return 0;
    388 }
    389 
    390 Element* Element::offsetParent()
    391 {
    392     document()->updateLayoutIgnorePendingStylesheets();
    393     if (RenderObject* rend = renderer())
    394         if (RenderObject* offsetParent = rend->offsetParent())
    395             return static_cast<Element*>(offsetParent->node());
    396     return 0;
    397 }
    398 
    399 int Element::clientLeft()
    400 {
    401     document()->updateLayoutIgnorePendingStylesheets();
    402 
    403     if (RenderBox* rend = renderBox())
    404         return adjustForAbsoluteZoom(rend->clientLeft(), rend);
    405     return 0;
    406 }
    407 
    408 int Element::clientTop()
    409 {
    410     document()->updateLayoutIgnorePendingStylesheets();
    411 
    412     if (RenderBox* rend = renderBox())
    413         return adjustForAbsoluteZoom(rend->clientTop(), rend);
    414     return 0;
    415 }
    416 
    417 int Element::clientWidth()
    418 {
    419     document()->updateLayoutIgnorePendingStylesheets();
    420 
    421     // When in strict mode, clientWidth for the document element should return the width of the containing frame.
    422     // When in quirks mode, clientWidth for the body element should return the width of the containing frame.
    423     bool inQuirksMode = document()->inQuirksMode();
    424     if ((!inQuirksMode && document()->documentElement() == this) ||
    425         (inQuirksMode && isHTMLElement() && document()->body() == this)) {
    426         if (FrameView* view = document()->view()) {
    427             if (RenderView* renderView = document()->renderView())
    428                 return adjustForAbsoluteZoom(view->layoutWidth(), renderView);
    429         }
    430     }
    431 
    432     if (RenderBox* rend = renderBox())
    433         return adjustForAbsoluteZoom(rend->clientWidth(), rend);
    434     return 0;
    435 }
    436 
    437 int Element::clientHeight()
    438 {
    439     document()->updateLayoutIgnorePendingStylesheets();
    440 
    441     // When in strict mode, clientHeight for the document element should return the height of the containing frame.
    442     // When in quirks mode, clientHeight for the body element should return the height of the containing frame.
    443     bool inQuirksMode = document()->inQuirksMode();
    444 
    445     if ((!inQuirksMode && document()->documentElement() == this) ||
    446         (inQuirksMode && isHTMLElement() && document()->body() == this)) {
    447         if (FrameView* view = document()->view()) {
    448             if (RenderView* renderView = document()->renderView())
    449                 return adjustForAbsoluteZoom(view->layoutHeight(), renderView);
    450         }
    451     }
    452 
    453     if (RenderBox* rend = renderBox())
    454         return adjustForAbsoluteZoom(rend->clientHeight(), rend);
    455     return 0;
    456 }
    457 
    458 int Element::scrollLeft() const
    459 {
    460     document()->updateLayoutIgnorePendingStylesheets();
    461     if (RenderBox* rend = renderBox())
    462         return adjustForAbsoluteZoom(rend->scrollLeft(), rend);
    463     return 0;
    464 }
    465 
    466 int Element::scrollTop() const
    467 {
    468     document()->updateLayoutIgnorePendingStylesheets();
    469     if (RenderBox* rend = renderBox())
    470         return adjustForAbsoluteZoom(rend->scrollTop(), rend);
    471     return 0;
    472 }
    473 
    474 void Element::setScrollLeft(int newLeft)
    475 {
    476     document()->updateLayoutIgnorePendingStylesheets();
    477     if (RenderBox* rend = renderBox())
    478         rend->setScrollLeft(static_cast<int>(newLeft * rend->style()->effectiveZoom()));
    479 }
    480 
    481 void Element::setScrollTop(int newTop)
    482 {
    483     document()->updateLayoutIgnorePendingStylesheets();
    484     if (RenderBox* rend = renderBox())
    485         rend->setScrollTop(static_cast<int>(newTop * rend->style()->effectiveZoom()));
    486 }
    487 
    488 int Element::scrollWidth() const
    489 {
    490     document()->updateLayoutIgnorePendingStylesheets();
    491     if (RenderBox* rend = renderBox())
    492         return adjustForAbsoluteZoom(rend->scrollWidth(), rend);
    493     return 0;
    494 }
    495 
    496 int Element::scrollHeight() const
    497 {
    498     document()->updateLayoutIgnorePendingStylesheets();
    499     if (RenderBox* rend = renderBox())
    500         return adjustForAbsoluteZoom(rend->scrollHeight(), rend);
    501     return 0;
    502 }
    503 
    504 IntRect Element::boundsInWindowSpace() const
    505 {
    506     document()->updateLayoutIgnorePendingStylesheets();
    507 
    508     FrameView* view = document()->view();
    509     if (!view)
    510         return IntRect();
    511 
    512     Vector<FloatQuad> quads;
    513 #if ENABLE(SVG)
    514     if (isSVGElement() && renderer()) {
    515         // Get the bounding rectangle from the SVG model.
    516         const SVGElement* svgElement = static_cast<const SVGElement*>(this);
    517         FloatRect localRect;
    518         if (svgElement->boundingBox(localRect))
    519             quads.append(renderer()->localToAbsoluteQuad(localRect));
    520     } else
    521 #endif
    522     {
    523         // Get the bounding rectangle from the box model.
    524         if (renderBoxModelObject())
    525             renderBoxModelObject()->absoluteQuads(quads);
    526     }
    527 
    528     if (quads.isEmpty())
    529         return IntRect();
    530 
    531     IntRect result = quads[0].enclosingBoundingBox();
    532     for (size_t i = 1; i < quads.size(); ++i)
    533         result.unite(quads[i].enclosingBoundingBox());
    534 
    535     result = view->contentsToWindow(result);
    536     return result;
    537 }
    538 
    539 PassRefPtr<ClientRectList> Element::getClientRects() const
    540 {
    541     document()->updateLayoutIgnorePendingStylesheets();
    542 
    543     RenderBoxModelObject* renderBoxModelObject = this->renderBoxModelObject();
    544     if (!renderBoxModelObject)
    545         return ClientRectList::create();
    546 
    547     // FIXME: Handle SVG elements.
    548     // FIXME: Handle table/inline-table with a caption.
    549 
    550     Vector<FloatQuad> quads;
    551     renderBoxModelObject->absoluteQuads(quads);
    552 
    553     float pageScale = 1;
    554     if (Page* page = document()->page()) {
    555         if (Frame* frame = page->mainFrame())
    556             pageScale = frame->pageScaleFactor();
    557     }
    558 
    559     if (FrameView* view = document()->view()) {
    560         IntRect visibleContentRect = view->visibleContentRect();
    561         for (size_t i = 0; i < quads.size(); ++i) {
    562             quads[i].move(-visibleContentRect.x(), -visibleContentRect.y());
    563             adjustFloatQuadForAbsoluteZoom(quads[i], renderBoxModelObject);
    564             if (pageScale != 1)
    565                 adjustFloatQuadForPageScale(quads[i], pageScale);
    566         }
    567     }
    568 
    569     return ClientRectList::create(quads);
    570 }
    571 
    572 PassRefPtr<ClientRect> Element::getBoundingClientRect() const
    573 {
    574     document()->updateLayoutIgnorePendingStylesheets();
    575 
    576     Vector<FloatQuad> quads;
    577 #if ENABLE(SVG)
    578     if (isSVGElement() && renderer()) {
    579         // Get the bounding rectangle from the SVG model.
    580         const SVGElement* svgElement = static_cast<const SVGElement*>(this);
    581         FloatRect localRect;
    582         if (svgElement->boundingBox(localRect))
    583             quads.append(renderer()->localToAbsoluteQuad(localRect));
    584     } else
    585 #endif
    586     {
    587         // Get the bounding rectangle from the box model.
    588         if (renderBoxModelObject())
    589             renderBoxModelObject()->absoluteQuads(quads);
    590     }
    591 
    592     if (quads.isEmpty())
    593         return ClientRect::create();
    594 
    595     FloatRect result = quads[0].boundingBox();
    596     for (size_t i = 1; i < quads.size(); ++i)
    597         result.unite(quads[i].boundingBox());
    598 
    599     if (FrameView* view = document()->view()) {
    600         IntRect visibleContentRect = view->visibleContentRect();
    601         result.move(-visibleContentRect.x(), -visibleContentRect.y());
    602     }
    603 
    604     adjustFloatRectForAbsoluteZoom(result, renderer());
    605     if (Page* page = document()->page()) {
    606         if (Frame* frame = page->mainFrame())
    607             adjustFloatRectForPageScale(result, frame->pageScaleFactor());
    608     }
    609 
    610     return ClientRect::create(result);
    611 }
    612 
    613 IntRect Element::screenRect() const
    614 {
    615     if (!renderer())
    616         return IntRect();
    617     return renderer()->view()->frameView()->contentsToScreen(renderer()->absoluteBoundingBoxRect());
    618 }
    619 
    620 static inline bool shouldIgnoreAttributeCase(const Element* e)
    621 {
    622     return e && e->document()->isHTMLDocument() && e->isHTMLElement();
    623 }
    624 
    625 const AtomicString& Element::getAttribute(const String& name) const
    626 {
    627     bool ignoreCase = shouldIgnoreAttributeCase(this);
    628 
    629     // Update the 'style' attribute if it's invalid and being requested:
    630     if (!isStyleAttributeValid() && equalPossiblyIgnoringCase(name, styleAttr.localName(), ignoreCase))
    631         updateStyleAttribute();
    632 
    633 #if ENABLE(SVG)
    634     if (!areSVGAttributesValid()) {
    635         // We're not passing a namespace argument on purpose. SVGNames::*Attr are defined w/o namespaces as well.
    636         updateAnimatedSVGAttribute(QualifiedName(nullAtom, name, nullAtom));
    637     }
    638 #endif
    639 
    640     if (m_attributeMap) {
    641         if (Attribute* attribute = m_attributeMap->getAttributeItem(name, ignoreCase))
    642             return attribute->value();
    643     }
    644 
    645     return nullAtom;
    646 }
    647 
    648 const AtomicString& Element::getAttributeNS(const String& namespaceURI, const String& localName) const
    649 {
    650     return getAttribute(QualifiedName(nullAtom, localName, namespaceURI));
    651 }
    652 
    653 void Element::setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode& ec)
    654 {
    655     if (!Document::isValidName(name)) {
    656         ec = INVALID_CHARACTER_ERR;
    657         return;
    658     }
    659 
    660 #if ENABLE(INSPECTOR)
    661     if (!isSynchronizingStyleAttribute())
    662         InspectorInstrumentation::willModifyDOMAttr(document(), this);
    663 #endif
    664 
    665     const AtomicString& localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
    666     QualifiedName attributeName(nullAtom, localName, nullAtom);
    667 
    668     // Allocate attribute map if necessary.
    669     Attribute* old = attributes(false)->getAttributeItem(localName, false);
    670 
    671     document()->incDOMTreeVersion();
    672 
    673     if (isIdAttributeName(old ? old->name() : attributeName))
    674         updateId(old ? old->value() : nullAtom, value);
    675 
    676     if (old && value.isNull())
    677         m_attributeMap->removeAttribute(old->name());
    678     else if (!old && !value.isNull())
    679         m_attributeMap->addAttribute(createAttribute(attributeName, value));
    680     else if (old && !value.isNull()) {
    681         if (Attr* attrNode = old->attr())
    682             attrNode->setValue(value);
    683         else
    684             old->setValue(value);
    685         attributeChanged(old);
    686     }
    687 
    688 #if ENABLE(INSPECTOR)
    689     if (!isSynchronizingStyleAttribute())
    690         InspectorInstrumentation::didModifyDOMAttr(document(), this);
    691 #endif
    692 }
    693 
    694 void Element::setAttribute(const QualifiedName& name, const AtomicString& value, ExceptionCode&)
    695 {
    696 #if ENABLE(INSPECTOR)
    697     if (!isSynchronizingStyleAttribute())
    698         InspectorInstrumentation::willModifyDOMAttr(document(), this);
    699 #endif
    700 
    701     document()->incDOMTreeVersion();
    702 
    703     // Allocate attribute map if necessary.
    704     Attribute* old = attributes(false)->getAttributeItem(name);
    705 
    706     if (isIdAttributeName(name))
    707         updateId(old ? old->value() : nullAtom, value);
    708 
    709     if (old && value.isNull())
    710         m_attributeMap->removeAttribute(name);
    711     else if (!old && !value.isNull())
    712         m_attributeMap->addAttribute(createAttribute(name, value));
    713     else if (old) {
    714         if (Attr* attrNode = old->attr())
    715             attrNode->setValue(value);
    716         else
    717             old->setValue(value);
    718         attributeChanged(old);
    719     }
    720 
    721 #if ENABLE(INSPECTOR)
    722     if (!isSynchronizingStyleAttribute())
    723         InspectorInstrumentation::didModifyDOMAttr(document(), this);
    724 #endif
    725 }
    726 
    727 PassRefPtr<Attribute> Element::createAttribute(const QualifiedName& name, const AtomicString& value)
    728 {
    729     return Attribute::create(name, value);
    730 }
    731 
    732 void Element::attributeChanged(Attribute* attr, bool)
    733 {
    734     if (isIdAttributeName(attr->name()))
    735         idAttributeChanged(attr);
    736     recalcStyleIfNeededAfterAttributeChanged(attr);
    737     updateAfterAttributeChanged(attr);
    738 }
    739 
    740 void Element::updateAfterAttributeChanged(Attribute* attr)
    741 {
    742     if (!AXObjectCache::accessibilityEnabled())
    743         return;
    744 
    745     const QualifiedName& attrName = attr->name();
    746     if (attrName == aria_activedescendantAttr) {
    747         // any change to aria-activedescendant attribute triggers accessibility focus change, but document focus remains intact
    748         document()->axObjectCache()->handleActiveDescendantChanged(renderer());
    749     } else if (attrName == roleAttr) {
    750         // the role attribute can change at any time, and the AccessibilityObject must pick up these changes
    751         document()->axObjectCache()->handleAriaRoleChanged(renderer());
    752     } else if (attrName == aria_valuenowAttr) {
    753         // If the valuenow attribute changes, AX clients need to be notified.
    754         document()->axObjectCache()->postNotification(renderer(), AXObjectCache::AXValueChanged, true);
    755     } else if (attrName == aria_labelAttr || attrName == aria_labeledbyAttr || attrName == altAttr || attrName == titleAttr) {
    756         // If the content of an element changes due to an attribute change, notify accessibility.
    757         document()->axObjectCache()->contentChanged(renderer());
    758     } else if (attrName == aria_selectedAttr)
    759         document()->axObjectCache()->selectedChildrenChanged(renderer());
    760     else if (attrName == aria_expandedAttr)
    761         document()->axObjectCache()->handleAriaExpandedChange(renderer());
    762     else if (attrName == aria_hiddenAttr)
    763         document()->axObjectCache()->childrenChanged(renderer());
    764     else if (attrName == aria_invalidAttr)
    765         document()->axObjectCache()->postNotification(renderer(), AXObjectCache::AXInvalidStatusChanged, true);
    766 }
    767 
    768 void Element::recalcStyleIfNeededAfterAttributeChanged(Attribute* attr)
    769 {
    770     if (document()->attached() && document()->styleSelector()->hasSelectorForAttribute(attr->name().localName()))
    771         setNeedsStyleRecalc();
    772 }
    773 
    774 void Element::idAttributeChanged(Attribute* attr)
    775 {
    776     setHasID(!attr->isNull());
    777     if (attributeMap()) {
    778         if (attr->isNull())
    779             attributeMap()->setIdForStyleResolution(nullAtom);
    780         else if (document()->inQuirksMode())
    781             attributeMap()->setIdForStyleResolution(attr->value().lower());
    782         else
    783             attributeMap()->setIdForStyleResolution(attr->value());
    784     }
    785     setNeedsStyleRecalc();
    786 }
    787 
    788 // Returns true is the given attribute is an event handler.
    789 // We consider an event handler any attribute that begins with "on".
    790 // It is a simple solution that has the advantage of not requiring any
    791 // code or configuration change if a new event handler is defined.
    792 
    793 static bool isEventHandlerAttribute(const QualifiedName& name)
    794 {
    795     return name.namespaceURI().isNull() && name.localName().startsWith("on");
    796 }
    797 
    798 static bool isAttributeToRemove(const QualifiedName& name, const AtomicString& value)
    799 {
    800     return (name.localName().endsWith(hrefAttr.localName()) || name == srcAttr || name == actionAttr) && protocolIsJavaScript(stripLeadingAndTrailingHTMLSpaces(value));
    801 }
    802 
    803 void Element::setAttributeMap(PassRefPtr<NamedNodeMap> list, FragmentScriptingPermission scriptingPermission)
    804 {
    805     document()->incDOMTreeVersion();
    806 
    807     // If setting the whole map changes the id attribute, we need to call updateId.
    808 
    809     const QualifiedName& idName = document()->idAttributeName();
    810     Attribute* oldId = m_attributeMap ? m_attributeMap->getAttributeItem(idName) : 0;
    811     Attribute* newId = list ? list->getAttributeItem(idName) : 0;
    812 
    813     if (oldId || newId)
    814         updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom);
    815 
    816     if (m_attributeMap)
    817         m_attributeMap->m_element = 0;
    818 
    819     m_attributeMap = list;
    820 
    821     if (m_attributeMap) {
    822         m_attributeMap->m_element = this;
    823         // If the element is created as result of a paste or drag-n-drop operation
    824         // we want to remove all the script and event handlers.
    825         if (scriptingPermission == FragmentScriptingNotAllowed) {
    826             unsigned i = 0;
    827             while (i < m_attributeMap->length()) {
    828                 const QualifiedName& attributeName = m_attributeMap->m_attributes[i]->name();
    829                 if (isEventHandlerAttribute(attributeName)) {
    830                     m_attributeMap->m_attributes.remove(i);
    831                     continue;
    832                 }
    833 
    834                 if (isAttributeToRemove(attributeName, m_attributeMap->m_attributes[i]->value()))
    835                     m_attributeMap->m_attributes[i]->setValue(nullAtom);
    836                 i++;
    837             }
    838         }
    839         // Store the set of attributes that changed on the stack in case
    840         // attributeChanged mutates m_attributeMap.
    841         Vector<RefPtr<Attribute> > attributes;
    842         m_attributeMap->copyAttributesToVector(attributes);
    843         for (Vector<RefPtr<Attribute> >::iterator iter = attributes.begin(); iter != attributes.end(); ++iter)
    844             attributeChanged(iter->get());
    845         // FIXME: What about attributes that were in the old map that are not in the new map?
    846     }
    847 }
    848 
    849 bool Element::hasAttributes() const
    850 {
    851     if (!isStyleAttributeValid())
    852         updateStyleAttribute();
    853 
    854 #if ENABLE(SVG)
    855     if (!areSVGAttributesValid())
    856         updateAnimatedSVGAttribute(anyQName());
    857 #endif
    858 
    859     return m_attributeMap && m_attributeMap->length();
    860 }
    861 
    862 String Element::nodeName() const
    863 {
    864     return m_tagName.toString();
    865 }
    866 
    867 String Element::nodeNamePreservingCase() const
    868 {
    869     return m_tagName.toString();
    870 }
    871 
    872 void Element::setPrefix(const AtomicString& prefix, ExceptionCode& ec)
    873 {
    874     ec = 0;
    875     checkSetPrefix(prefix, ec);
    876     if (ec)
    877         return;
    878 
    879     m_tagName.setPrefix(prefix.isEmpty() ? AtomicString() : prefix);
    880 }
    881 
    882 KURL Element::baseURI() const
    883 {
    884     const AtomicString& baseAttribute = getAttribute(baseAttr);
    885     KURL base(KURL(), baseAttribute);
    886     if (!base.protocol().isEmpty())
    887         return base;
    888 
    889     ContainerNode* parent = parentNode();
    890     if (!parent)
    891         return base;
    892 
    893     const KURL& parentBase = parent->baseURI();
    894     if (parentBase.isNull())
    895         return base;
    896 
    897     return KURL(parentBase, baseAttribute);
    898 }
    899 
    900 void Element::createAttributeMap() const
    901 {
    902     m_attributeMap = NamedNodeMap::create(const_cast<Element*>(this));
    903 }
    904 
    905 bool Element::isURLAttribute(Attribute*) const
    906 {
    907     return false;
    908 }
    909 
    910 const QualifiedName& Element::imageSourceAttributeName() const
    911 {
    912     return srcAttr;
    913 }
    914 
    915 RenderObject* Element::createRenderer(RenderArena* arena, RenderStyle* style)
    916 {
    917     if (document()->documentElement() == this && style->display() == NONE) {
    918         // Ignore display: none on root elements.  Force a display of block in that case.
    919         RenderBlock* result = new (arena) RenderBlock(this);
    920         if (result)
    921             result->setAnimatableStyle(style);
    922         return result;
    923     }
    924     return RenderObject::createObject(this, style);
    925 }
    926 
    927 bool Element::wasChangedSinceLastFormControlChangeEvent() const
    928 {
    929     return false;
    930 }
    931 
    932 void Element::setChangedSinceLastFormControlChangeEvent(bool)
    933 {
    934 }
    935 
    936 void Element::insertedIntoDocument()
    937 {
    938     // need to do superclass processing first so inDocument() is true
    939     // by the time we reach updateId
    940     ContainerNode::insertedIntoDocument();
    941     if (Node* shadow = shadowRoot())
    942         shadow->insertedIntoDocument();
    943 
    944     if (hasID()) {
    945         if (m_attributeMap) {
    946             Attribute* idItem = m_attributeMap->getAttributeItem(document()->idAttributeName());
    947             if (idItem && !idItem->isNull())
    948                 updateId(nullAtom, idItem->value());
    949         }
    950     }
    951 }
    952 
    953 void Element::removedFromDocument()
    954 {
    955     if (hasID()) {
    956         if (m_attributeMap) {
    957             Attribute* idItem = m_attributeMap->getAttributeItem(document()->idAttributeName());
    958             if (idItem && !idItem->isNull())
    959                 updateId(idItem->value(), nullAtom);
    960         }
    961     }
    962 
    963     ContainerNode::removedFromDocument();
    964     if (Node* shadow = shadowRoot())
    965         shadow->removedFromDocument();
    966 }
    967 
    968 void Element::insertedIntoTree(bool deep)
    969 {
    970     ContainerNode::insertedIntoTree(deep);
    971     if (!deep)
    972         return;
    973     if (Node* shadow = shadowRoot())
    974         shadow->insertedIntoTree(true);
    975 }
    976 
    977 void Element::removedFromTree(bool deep)
    978 {
    979     ContainerNode::removedFromTree(deep);
    980     if (!deep)
    981         return;
    982     if (Node* shadow = shadowRoot())
    983         shadow->removedFromTree(true);
    984 }
    985 
    986 void Element::attach()
    987 {
    988     suspendPostAttachCallbacks();
    989     RenderWidget::suspendWidgetHierarchyUpdates();
    990 
    991     createRendererIfNeeded();
    992 
    993     StyleSelectorParentPusher parentPusher(this);
    994 
    995     if (Node* shadow = shadowRoot()) {
    996         parentPusher.push();
    997         shadow->attach();
    998     }
    999 
   1000     if (firstChild())
   1001         parentPusher.push();
   1002     ContainerNode::attach();
   1003 
   1004     if (hasRareData()) {
   1005         ElementRareData* data = rareData();
   1006         if (data->needsFocusAppearanceUpdateSoonAfterAttach()) {
   1007             if (isFocusable() && document()->focusedNode() == this)
   1008                 document()->updateFocusAppearanceSoon(false /* don't restore selection */);
   1009             data->setNeedsFocusAppearanceUpdateSoonAfterAttach(false);
   1010         }
   1011     }
   1012 
   1013     RenderWidget::resumeWidgetHierarchyUpdates();
   1014     resumePostAttachCallbacks();
   1015 }
   1016 
   1017 void Element::detach()
   1018 {
   1019     RenderWidget::suspendWidgetHierarchyUpdates();
   1020 
   1021     cancelFocusAppearanceUpdate();
   1022     if (hasRareData())
   1023         rareData()->resetComputedStyle();
   1024     ContainerNode::detach();
   1025     if (Node* shadow = shadowRoot())
   1026         shadow->detach();
   1027 
   1028     RenderWidget::resumeWidgetHierarchyUpdates();
   1029 }
   1030 
   1031 bool Element::pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle)
   1032 {
   1033     ASSERT(currentStyle == renderStyle());
   1034 
   1035     if (!renderer() || !currentStyle)
   1036         return false;
   1037 
   1038     const PseudoStyleCache* pseudoStyleCache = currentStyle->cachedPseudoStyles();
   1039     if (!pseudoStyleCache)
   1040         return false;
   1041 
   1042     size_t cacheSize = pseudoStyleCache->size();
   1043     for (size_t i = 0; i < cacheSize; ++i) {
   1044         RefPtr<RenderStyle> newPseudoStyle;
   1045         PseudoId pseudoId = pseudoStyleCache->at(i)->styleType();
   1046         if (pseudoId == VISITED_LINK) {
   1047             newPseudoStyle =  newStyle->getCachedPseudoStyle(VISITED_LINK); // This pseudo-style was aggressively computed already when we first called styleForElement on the new style.
   1048             if (!newPseudoStyle || *newPseudoStyle != *pseudoStyleCache->at(i))
   1049                 return true;
   1050         } else if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED)
   1051             newPseudoStyle = renderer()->uncachedFirstLineStyle(newStyle);
   1052         else
   1053             newPseudoStyle = renderer()->getUncachedPseudoStyle(pseudoId, newStyle, newStyle);
   1054         if (!newPseudoStyle)
   1055             return true;
   1056         if (*newPseudoStyle != *pseudoStyleCache->at(i)) {
   1057             if (pseudoId < FIRST_INTERNAL_PSEUDOID)
   1058                 newStyle->setHasPseudoStyle(pseudoId);
   1059             newStyle->addCachedPseudoStyle(newPseudoStyle);
   1060             if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED) {
   1061                 // FIXME: We should do an actual diff to determine whether a repaint vs. layout
   1062                 // is needed, but for now just assume a layout will be required.  The diff code
   1063                 // in RenderObject::setStyle would need to be factored out so that it could be reused.
   1064                 renderer()->setNeedsLayoutAndPrefWidthsRecalc();
   1065             }
   1066             return true;
   1067         }
   1068     }
   1069     return false;
   1070 }
   1071 
   1072 void Element::recalcStyle(StyleChange change)
   1073 {
   1074     // Ref currentStyle in case it would otherwise be deleted when setRenderStyle() is called.
   1075     RefPtr<RenderStyle> currentStyle(renderStyle());
   1076     bool hasParentStyle = parentNodeForRenderingAndStyle() ? parentNodeForRenderingAndStyle()->renderStyle() : false;
   1077     bool hasDirectAdjacentRules = currentStyle && currentStyle->childrenAffectedByDirectAdjacentRules();
   1078 
   1079     if ((change > NoChange || needsStyleRecalc())) {
   1080         if (hasRareData())
   1081             rareData()->resetComputedStyle();
   1082     }
   1083     if (hasParentStyle && (change >= Inherit || needsStyleRecalc())) {
   1084         RefPtr<RenderStyle> newStyle = document()->styleSelector()->styleForElement(this);
   1085         StyleChange ch = diff(currentStyle.get(), newStyle.get());
   1086         if (ch == Detach || !currentStyle) {
   1087             if (attached())
   1088                 detach();
   1089             attach(); // FIXME: The style gets computed twice by calling attach. We could do better if we passed the style along.
   1090             // attach recalulates the style for all children. No need to do it twice.
   1091             clearNeedsStyleRecalc();
   1092             clearChildNeedsStyleRecalc();
   1093             return;
   1094         }
   1095 
   1096         if (currentStyle) {
   1097             // Preserve "affected by" bits that were propagated to us from descendants in the case where we didn't do a full
   1098             // style change (e.g., only inline style changed).
   1099             if (currentStyle->affectedByHoverRules())
   1100                 newStyle->setAffectedByHoverRules(true);
   1101             if (currentStyle->affectedByActiveRules())
   1102                 newStyle->setAffectedByActiveRules(true);
   1103             if (currentStyle->affectedByDragRules())
   1104                 newStyle->setAffectedByDragRules(true);
   1105             if (currentStyle->childrenAffectedByForwardPositionalRules())
   1106                 newStyle->setChildrenAffectedByForwardPositionalRules();
   1107             if (currentStyle->childrenAffectedByBackwardPositionalRules())
   1108                 newStyle->setChildrenAffectedByBackwardPositionalRules();
   1109             if (currentStyle->childrenAffectedByFirstChildRules())
   1110                 newStyle->setChildrenAffectedByFirstChildRules();
   1111             if (currentStyle->childrenAffectedByLastChildRules())
   1112                 newStyle->setChildrenAffectedByLastChildRules();
   1113             if (currentStyle->childrenAffectedByDirectAdjacentRules())
   1114                 newStyle->setChildrenAffectedByDirectAdjacentRules();
   1115         }
   1116 
   1117         if (ch != NoChange || pseudoStyleCacheIsInvalid(currentStyle.get(), newStyle.get()) || (change == Force && renderer() && renderer()->requiresForcedStyleRecalcPropagation())) {
   1118             setRenderStyle(newStyle);
   1119         } else if (needsStyleRecalc() && styleChangeType() != SyntheticStyleChange) {
   1120             // Although no change occurred, we use the new style so that the cousin style sharing code won't get
   1121             // fooled into believing this style is the same.
   1122             if (renderer())
   1123                 renderer()->setStyleInternal(newStyle.get());
   1124             else
   1125                 setRenderStyle(newStyle);
   1126         } else if (styleChangeType() == SyntheticStyleChange)
   1127              setRenderStyle(newStyle);
   1128 
   1129         if (change != Force) {
   1130             // 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
   1131             // 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).
   1132             if (document()->usesRemUnits() && ch != NoChange && currentStyle && newStyle && currentStyle->fontSize() != newStyle->fontSize() && document()->documentElement() == this)
   1133                 change = Force;
   1134             else if (styleChangeType() >= FullStyleChange)
   1135                 change = Force;
   1136             else
   1137                 change = ch;
   1138         }
   1139     }
   1140     StyleSelectorParentPusher parentPusher(this);
   1141     // FIXME: This check is good enough for :hover + foo, but it is not good enough for :hover + foo + bar.
   1142     // For now we will just worry about the common case, since it's a lot trickier to get the second case right
   1143     // without doing way too much re-resolution.
   1144     bool forceCheckOfNextElementSibling = false;
   1145     for (Node *n = firstChild(); n; n = n->nextSibling()) {
   1146         bool childRulesChanged = n->needsStyleRecalc() && n->styleChangeType() == FullStyleChange;
   1147         if (forceCheckOfNextElementSibling && n->isElementNode())
   1148             n->setNeedsStyleRecalc();
   1149         if (change >= Inherit || n->isTextNode() || n->childNeedsStyleRecalc() || n->needsStyleRecalc()) {
   1150             parentPusher.push();
   1151             n->recalcStyle(change);
   1152         }
   1153         if (n->isElementNode())
   1154             forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentRules;
   1155     }
   1156     // FIXME: This does not care about sibling combinators. Will be necessary in XBL2 world.
   1157     if (Node* shadow = shadowRoot()) {
   1158         if (change >= Inherit || shadow->childNeedsStyleRecalc() || shadow->needsStyleRecalc()) {
   1159             parentPusher.push();
   1160             shadow->recalcStyle(change);
   1161         }
   1162     }
   1163 
   1164     clearNeedsStyleRecalc();
   1165     clearChildNeedsStyleRecalc();
   1166 }
   1167 
   1168 ContainerNode* Element::shadowRoot() const
   1169 {
   1170     return hasRareData() ? rareData()->m_shadowRoot : 0;
   1171 }
   1172 
   1173 ContainerNode* Element::ensureShadowRoot()
   1174 {
   1175     if (ContainerNode* existingRoot = shadowRoot())
   1176         return existingRoot;
   1177 
   1178     RefPtr<ShadowRoot> newRoot = ShadowRoot::create(document());
   1179     ensureRareData()->m_shadowRoot = newRoot.get();
   1180     newRoot->setShadowHost(this);
   1181     if (inDocument())
   1182         newRoot->insertedIntoDocument();
   1183     if (attached())
   1184         newRoot->lazyAttach();
   1185     return newRoot.get();
   1186 }
   1187 
   1188 void Element::removeShadowRoot()
   1189 {
   1190     if (!hasRareData())
   1191         return;
   1192 
   1193     ElementRareData* data = rareData();
   1194     if (RefPtr<Node> oldRoot = data->m_shadowRoot) {
   1195         data->m_shadowRoot = 0;
   1196         document()->removeFocusedNodeOfSubtree(oldRoot.get());
   1197         oldRoot->setShadowHost(0);
   1198         if (oldRoot->inDocument())
   1199             oldRoot->removedFromDocument();
   1200         else
   1201             oldRoot->removedFromTree(true);
   1202     }
   1203 }
   1204 
   1205 bool Element::childTypeAllowed(NodeType type) const
   1206 {
   1207     switch (type) {
   1208     case ELEMENT_NODE:
   1209     case TEXT_NODE:
   1210     case COMMENT_NODE:
   1211     case PROCESSING_INSTRUCTION_NODE:
   1212     case CDATA_SECTION_NODE:
   1213     case ENTITY_REFERENCE_NODE:
   1214         return true;
   1215     default:
   1216         break;
   1217     }
   1218     return false;
   1219 }
   1220 
   1221 static void checkForEmptyStyleChange(Element* element, RenderStyle* style)
   1222 {
   1223     if (!style)
   1224         return;
   1225 
   1226     if (style->affectedByEmpty() && (!style->emptyState() || element->hasChildNodes()))
   1227         element->setNeedsStyleRecalc();
   1228 }
   1229 
   1230 static void checkForSiblingStyleChanges(Element* e, RenderStyle* style, bool finishedParsingCallback,
   1231                                         Node* beforeChange, Node* afterChange, int childCountDelta)
   1232 {
   1233     if (!style || (e->needsStyleRecalc() && style->childrenAffectedByPositionalRules()))
   1234         return;
   1235 
   1236     // :first-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
   1237     // In the DOM case, we only need to do something if |afterChange| is not 0.
   1238     // |afterChange| is 0 in the parser case, so it works out that we'll skip this block.
   1239     if (style->childrenAffectedByFirstChildRules() && afterChange) {
   1240         // Find our new first child.
   1241         Node* newFirstChild = 0;
   1242         for (newFirstChild = e->firstChild(); newFirstChild && !newFirstChild->isElementNode(); newFirstChild = newFirstChild->nextSibling()) {};
   1243 
   1244         // Find the first element node following |afterChange|
   1245         Node* firstElementAfterInsertion = 0;
   1246         for (firstElementAfterInsertion = afterChange;
   1247              firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
   1248              firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
   1249 
   1250         // This is the insert/append case.
   1251         if (newFirstChild != firstElementAfterInsertion && firstElementAfterInsertion && firstElementAfterInsertion->attached() &&
   1252             firstElementAfterInsertion->renderStyle() && firstElementAfterInsertion->renderStyle()->firstChildState())
   1253             firstElementAfterInsertion->setNeedsStyleRecalc();
   1254 
   1255         // We also have to handle node removal.
   1256         if (childCountDelta < 0 && newFirstChild == firstElementAfterInsertion && newFirstChild && newFirstChild->renderStyle() && !newFirstChild->renderStyle()->firstChildState())
   1257             newFirstChild->setNeedsStyleRecalc();
   1258     }
   1259 
   1260     // :last-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
   1261     // In the DOM case, we only need to do something if |afterChange| is not 0.
   1262     if (style->childrenAffectedByLastChildRules() && beforeChange) {
   1263         // Find our new last child.
   1264         Node* newLastChild = 0;
   1265         for (newLastChild = e->lastChild(); newLastChild && !newLastChild->isElementNode(); newLastChild = newLastChild->previousSibling()) {};
   1266 
   1267         // Find the last element node going backwards from |beforeChange|
   1268         Node* lastElementBeforeInsertion = 0;
   1269         for (lastElementBeforeInsertion = beforeChange;
   1270              lastElementBeforeInsertion && !lastElementBeforeInsertion->isElementNode();
   1271              lastElementBeforeInsertion = lastElementBeforeInsertion->previousSibling()) {};
   1272 
   1273         if (newLastChild != lastElementBeforeInsertion && lastElementBeforeInsertion && lastElementBeforeInsertion->attached() &&
   1274             lastElementBeforeInsertion->renderStyle() && lastElementBeforeInsertion->renderStyle()->lastChildState())
   1275             lastElementBeforeInsertion->setNeedsStyleRecalc();
   1276 
   1277         // 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
   1278         // to match now.
   1279         if ((childCountDelta < 0 || finishedParsingCallback) && newLastChild == lastElementBeforeInsertion && newLastChild && newLastChild->renderStyle() && !newLastChild->renderStyle()->lastChildState())
   1280             newLastChild->setNeedsStyleRecalc();
   1281     }
   1282 
   1283     // The + selector.  We need to invalidate the first element following the insertion point.  It is the only possible element
   1284     // that could be affected by this DOM change.
   1285     if (style->childrenAffectedByDirectAdjacentRules() && afterChange) {
   1286         Node* firstElementAfterInsertion = 0;
   1287         for (firstElementAfterInsertion = afterChange;
   1288              firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
   1289              firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
   1290         if (firstElementAfterInsertion && firstElementAfterInsertion->attached())
   1291             firstElementAfterInsertion->setNeedsStyleRecalc();
   1292     }
   1293 
   1294     // Forward positional selectors include the ~ selector, nth-child, nth-of-type, first-of-type and only-of-type.
   1295     // Backward positional selectors include nth-last-child, nth-last-of-type, last-of-type and only-of-type.
   1296     // We have to invalidate everything following the insertion point in the forward case, and everything before the insertion point in the
   1297     // backward case.
   1298     // |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.
   1299     // 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
   1300     // here.  recalcStyle will then force a walk of the children when it sees that this has happened.
   1301     if ((style->childrenAffectedByForwardPositionalRules() && afterChange) ||
   1302         (style->childrenAffectedByBackwardPositionalRules() && beforeChange))
   1303         e->setNeedsStyleRecalc();
   1304 
   1305     // :empty selector.
   1306     checkForEmptyStyleChange(e, style);
   1307 }
   1308 
   1309 void Element::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
   1310 {
   1311     ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
   1312     if (changedByParser)
   1313         checkForEmptyStyleChange(this, renderStyle());
   1314     else
   1315         checkForSiblingStyleChanges(this, renderStyle(), false, beforeChange, afterChange, childCountDelta);
   1316 }
   1317 
   1318 void Element::beginParsingChildren()
   1319 {
   1320     clearIsParsingChildrenFinished();
   1321     CSSStyleSelector* styleSelector = document()->styleSelectorIfExists();
   1322     if (styleSelector && attached())
   1323         styleSelector->pushParent(this);
   1324 }
   1325 
   1326 void Element::finishParsingChildren()
   1327 {
   1328     ContainerNode::finishParsingChildren();
   1329     setIsParsingChildrenFinished();
   1330     checkForSiblingStyleChanges(this, renderStyle(), true, lastChild(), 0, 0);
   1331     if (CSSStyleSelector* styleSelector = document()->styleSelectorIfExists())
   1332         styleSelector->popParent(this);
   1333 }
   1334 
   1335 void Element::dispatchAttrRemovalEvent(Attribute*)
   1336 {
   1337     ASSERT(!eventDispatchForbidden());
   1338 
   1339 #if 0
   1340     if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER))
   1341         return;
   1342     ExceptionCode ec = 0;
   1343     dispatchScopedEvent(MutationEvent::create(DOMAttrModifiedEvent, true, attr, attr->value(),
   1344         attr->value(), document()->attrName(attr->id()), MutationEvent::REMOVAL), ec);
   1345 #endif
   1346 }
   1347 
   1348 void Element::dispatchAttrAdditionEvent(Attribute*)
   1349 {
   1350     ASSERT(!eventDispatchForbidden());
   1351 
   1352 #if 0
   1353     if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER))
   1354         return;
   1355     ExceptionCode ec = 0;
   1356     dispatchScopedEvent(MutationEvent::create(DOMAttrModifiedEvent, true, attr, attr->value(),
   1357         attr->value(), document()->attrName(attr->id()), MutationEvent::ADDITION), ec);
   1358 #endif
   1359 }
   1360 
   1361 String Element::openTagStartToString() const
   1362 {
   1363     String result = "<" + nodeName();
   1364 
   1365     NamedNodeMap* attrMap = attributes(true);
   1366 
   1367     if (attrMap) {
   1368         unsigned numAttrs = attrMap->length();
   1369         for (unsigned i = 0; i < numAttrs; i++) {
   1370             result += " ";
   1371 
   1372             Attribute *attribute = attrMap->attributeItem(i);
   1373             result += attribute->name().toString();
   1374             if (!attribute->value().isNull()) {
   1375                 result += "=\"";
   1376                 // FIXME: substitute entities for any instances of " or '
   1377                 result += attribute->value();
   1378                 result += "\"";
   1379             }
   1380         }
   1381     }
   1382 
   1383     return result;
   1384 }
   1385 
   1386 #ifndef NDEBUG
   1387 void Element::formatForDebugger(char* buffer, unsigned length) const
   1388 {
   1389     String result;
   1390     String s;
   1391 
   1392     s = nodeName();
   1393     if (s.length() > 0) {
   1394         result += s;
   1395     }
   1396 
   1397     s = getIdAttribute();
   1398     if (s.length() > 0) {
   1399         if (result.length() > 0)
   1400             result += "; ";
   1401         result += "id=";
   1402         result += s;
   1403     }
   1404 
   1405     s = getAttribute(classAttr);
   1406     if (s.length() > 0) {
   1407         if (result.length() > 0)
   1408             result += "; ";
   1409         result += "class=";
   1410         result += s;
   1411     }
   1412 
   1413     strncpy(buffer, result.utf8().data(), length - 1);
   1414 }
   1415 #endif
   1416 
   1417 PassRefPtr<Attr> Element::setAttributeNode(Attr* attr, ExceptionCode& ec)
   1418 {
   1419     if (!attr) {
   1420         ec = TYPE_MISMATCH_ERR;
   1421         return 0;
   1422     }
   1423     return static_pointer_cast<Attr>(attributes(false)->setNamedItem(attr, ec));
   1424 }
   1425 
   1426 PassRefPtr<Attr> Element::setAttributeNodeNS(Attr* attr, ExceptionCode& ec)
   1427 {
   1428     if (!attr) {
   1429         ec = TYPE_MISMATCH_ERR;
   1430         return 0;
   1431     }
   1432     return static_pointer_cast<Attr>(attributes(false)->setNamedItem(attr, ec));
   1433 }
   1434 
   1435 PassRefPtr<Attr> Element::removeAttributeNode(Attr* attr, ExceptionCode& ec)
   1436 {
   1437     if (!attr) {
   1438         ec = TYPE_MISMATCH_ERR;
   1439         return 0;
   1440     }
   1441     if (attr->ownerElement() != this) {
   1442         ec = NOT_FOUND_ERR;
   1443         return 0;
   1444     }
   1445 
   1446     ASSERT(document() == attr->document());
   1447 
   1448     NamedNodeMap* attrs = attributes(true);
   1449     if (!attrs)
   1450         return 0;
   1451 
   1452     return static_pointer_cast<Attr>(attrs->removeNamedItem(attr->qualifiedName(), ec));
   1453 }
   1454 
   1455 void Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode& ec, FragmentScriptingPermission scriptingPermission)
   1456 {
   1457     String prefix, localName;
   1458     if (!Document::parseQualifiedName(qualifiedName, prefix, localName, ec))
   1459         return;
   1460 
   1461     if (namespaceURI.isNull() && !prefix.isNull()) {
   1462         ec = NAMESPACE_ERR;
   1463         return;
   1464     }
   1465 
   1466     QualifiedName qName(prefix, localName, namespaceURI);
   1467 
   1468     if (scriptingPermission == FragmentScriptingNotAllowed && (isEventHandlerAttribute(qName) || isAttributeToRemove(qName, value)))
   1469         return;
   1470 
   1471     setAttribute(qName, value, ec);
   1472 }
   1473 
   1474 void Element::removeAttribute(const String& name, ExceptionCode& ec)
   1475 {
   1476     InspectorInstrumentation::willModifyDOMAttr(document(), this);
   1477 
   1478     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
   1479 
   1480     if (m_attributeMap) {
   1481         m_attributeMap->removeNamedItem(localName, ec);
   1482         if (ec == NOT_FOUND_ERR)
   1483             ec = 0;
   1484     }
   1485 
   1486     InspectorInstrumentation::didModifyDOMAttr(document(), this);
   1487 }
   1488 
   1489 void Element::removeAttributeNS(const String& namespaceURI, const String& localName, ExceptionCode& ec)
   1490 {
   1491     removeAttribute(QualifiedName(nullAtom, localName, namespaceURI), ec);
   1492 }
   1493 
   1494 PassRefPtr<Attr> Element::getAttributeNode(const String& name)
   1495 {
   1496     NamedNodeMap* attrs = attributes(true);
   1497     if (!attrs)
   1498         return 0;
   1499     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
   1500     return static_pointer_cast<Attr>(attrs->getNamedItem(localName));
   1501 }
   1502 
   1503 PassRefPtr<Attr> Element::getAttributeNodeNS(const String& namespaceURI, const String& localName)
   1504 {
   1505     NamedNodeMap* attrs = attributes(true);
   1506     if (!attrs)
   1507         return 0;
   1508     return static_pointer_cast<Attr>(attrs->getNamedItem(QualifiedName(nullAtom, localName, namespaceURI)));
   1509 }
   1510 
   1511 bool Element::hasAttribute(const String& name) const
   1512 {
   1513     NamedNodeMap* attrs = attributes(true);
   1514     if (!attrs)
   1515         return false;
   1516 
   1517     // This call to String::lower() seems to be required but
   1518     // there may be a way to remove it.
   1519     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
   1520     return attrs->getAttributeItem(localName, false);
   1521 }
   1522 
   1523 bool Element::hasAttributeNS(const String& namespaceURI, const String& localName) const
   1524 {
   1525     NamedNodeMap* attrs = attributes(true);
   1526     if (!attrs)
   1527         return false;
   1528     return attrs->getAttributeItem(QualifiedName(nullAtom, localName, namespaceURI));
   1529 }
   1530 
   1531 CSSStyleDeclaration *Element::style()
   1532 {
   1533     return 0;
   1534 }
   1535 
   1536 void Element::focus(bool restorePreviousSelection)
   1537 {
   1538     if (!inDocument())
   1539         return;
   1540 
   1541     Document* doc = document();
   1542     if (doc->focusedNode() == this)
   1543         return;
   1544 
   1545     // If the stylesheets have already been loaded we can reliably check isFocusable.
   1546     // If not, we continue and set the focused node on the focus controller below so
   1547     // that it can be updated soon after attach.
   1548     if (doc->haveStylesheetsLoaded()) {
   1549         doc->updateLayoutIgnorePendingStylesheets();
   1550         if (!isFocusable())
   1551             return;
   1552     }
   1553 
   1554     if (!supportsFocus())
   1555         return;
   1556 
   1557     RefPtr<Node> protect;
   1558     if (Page* page = doc->page()) {
   1559         // Focus and change event handlers can cause us to lose our last ref.
   1560         // If a focus event handler changes the focus to a different node it
   1561         // does not make sense to continue and update appearence.
   1562         protect = this;
   1563         if (!page->focusController()->setFocusedNode(this, doc->frame()))
   1564             return;
   1565     }
   1566 
   1567     // Setting the focused node above might have invalidated the layout due to scripts.
   1568     doc->updateLayoutIgnorePendingStylesheets();
   1569 
   1570     if (!isFocusable()) {
   1571         ensureRareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(true);
   1572         return;
   1573     }
   1574 
   1575     cancelFocusAppearanceUpdate();
   1576     updateFocusAppearance(restorePreviousSelection);
   1577 }
   1578 
   1579 void Element::updateFocusAppearance(bool /*restorePreviousSelection*/)
   1580 {
   1581     if (this == rootEditableElement()) {
   1582         Frame* frame = document()->frame();
   1583         if (!frame)
   1584             return;
   1585 
   1586         // When focusing an editable element in an iframe, don't reset the selection if it already contains a selection.
   1587         if (this == frame->selection()->rootEditableElement())
   1588             return;
   1589 
   1590         // FIXME: We should restore the previous selection if there is one.
   1591         VisibleSelection newSelection = VisibleSelection(firstPositionInOrBeforeNode(this), DOWNSTREAM);
   1592 
   1593         if (frame->selection()->shouldChangeSelection(newSelection)) {
   1594             frame->selection()->setSelection(newSelection);
   1595             frame->selection()->revealSelection();
   1596         }
   1597     } else if (renderer() && !renderer()->isWidget())
   1598         renderer()->enclosingLayer()->scrollRectToVisible(getRect());
   1599 }
   1600 
   1601 void Element::blur()
   1602 {
   1603     cancelFocusAppearanceUpdate();
   1604     Document* doc = document();
   1605     if (doc->focusedNode() == this) {
   1606         if (doc->frame())
   1607             doc->frame()->page()->focusController()->setFocusedNode(0, doc->frame());
   1608         else
   1609             doc->setFocusedNode(0);
   1610     }
   1611 }
   1612 
   1613 String Element::innerText() const
   1614 {
   1615     // We need to update layout, since plainText uses line boxes in the render tree.
   1616     document()->updateLayoutIgnorePendingStylesheets();
   1617 
   1618     if (!renderer())
   1619         return textContent(true);
   1620 
   1621     return plainText(rangeOfContents(const_cast<Element*>(this)).get());
   1622 }
   1623 
   1624 String Element::outerText() const
   1625 {
   1626     // Getting outerText is the same as getting innerText, only
   1627     // setting is different. You would think this should get the plain
   1628     // text for the outer range, but this is wrong, <br> for instance
   1629     // would return different values for inner and outer text by such
   1630     // a rule, but it doesn't in WinIE, and we want to match that.
   1631     return innerText();
   1632 }
   1633 
   1634 String Element::title() const
   1635 {
   1636     return String();
   1637 }
   1638 
   1639 IntSize Element::minimumSizeForResizing() const
   1640 {
   1641     return hasRareData() ? rareData()->m_minimumSizeForResizing : defaultMinimumSizeForResizing();
   1642 }
   1643 
   1644 void Element::setMinimumSizeForResizing(const IntSize& size)
   1645 {
   1646     if (size == defaultMinimumSizeForResizing() && !hasRareData())
   1647         return;
   1648     ensureRareData()->m_minimumSizeForResizing = size;
   1649 }
   1650 
   1651 RenderStyle* Element::computedStyle(PseudoId pseudoElementSpecifier)
   1652 {
   1653     // FIXME: Find and use the renderer from the pseudo element instead of the actual element so that the 'length'
   1654     // properties, which are only known by the renderer because it did the layout, will be correct and so that the
   1655     // values returned for the ":selection" pseudo-element will be correct.
   1656     if (RenderStyle* usedStyle = renderStyle())
   1657         return pseudoElementSpecifier ? usedStyle->getCachedPseudoStyle(pseudoElementSpecifier) : usedStyle;
   1658 
   1659     if (!attached())
   1660         // FIXME: Try to do better than this. Ensure that styleForElement() works for elements that are not in the
   1661         // document tree and figure out when to destroy the computed style for such elements.
   1662         return 0;
   1663 
   1664     ElementRareData* data = ensureRareData();
   1665     if (!data->m_computedStyle)
   1666         data->m_computedStyle = document()->styleForElementIgnoringPendingStylesheets(this);
   1667     return pseudoElementSpecifier ? data->m_computedStyle->getCachedPseudoStyle(pseudoElementSpecifier) : data->m_computedStyle.get();
   1668 }
   1669 
   1670 AtomicString Element::computeInheritedLanguage() const
   1671 {
   1672     const Node* n = this;
   1673     AtomicString value;
   1674     // The language property is inherited, so we iterate over the parents to find the first language.
   1675     while (n && value.isNull()) {
   1676         if (n->isElementNode()) {
   1677             // Spec: xml:lang takes precedence -- http://www.w3.org/TR/xhtml1/#C_7
   1678             value = static_cast<const Element*>(n)->fastGetAttribute(XMLNames::langAttr);
   1679             if (value.isNull())
   1680                 value = static_cast<const Element*>(n)->fastGetAttribute(HTMLNames::langAttr);
   1681         } else if (n->isDocumentNode()) {
   1682             // checking the MIME content-language
   1683             value = static_cast<const Document*>(n)->contentLanguage();
   1684         }
   1685 
   1686         n = n->parentNode();
   1687     }
   1688 
   1689     return value;
   1690 }
   1691 
   1692 void Element::cancelFocusAppearanceUpdate()
   1693 {
   1694     if (hasRareData())
   1695         rareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(false);
   1696     if (document()->focusedNode() == this)
   1697         document()->cancelFocusAppearanceUpdate();
   1698 }
   1699 
   1700 void Element::normalizeAttributes()
   1701 {
   1702     // Normalize attributes.
   1703     NamedNodeMap* attrs = attributes(true);
   1704     if (!attrs)
   1705         return;
   1706 
   1707     if (attrs->isEmpty())
   1708         return;
   1709 
   1710     Vector<RefPtr<Attribute> > attributeVector;
   1711     attrs->copyAttributesToVector(attributeVector);
   1712     size_t numAttrs = attributeVector.size();
   1713     for (size_t i = 0; i < numAttrs; ++i) {
   1714         if (Attr* attr = attributeVector[i]->attr())
   1715             attr->normalize();
   1716     }
   1717 }
   1718 
   1719 // ElementTraversal API
   1720 Element* Element::firstElementChild() const
   1721 {
   1722     return WebCore::firstElementChild(this);
   1723 }
   1724 
   1725 Element* Element::lastElementChild() const
   1726 {
   1727     Node* n = lastChild();
   1728     while (n && !n->isElementNode())
   1729         n = n->previousSibling();
   1730     return static_cast<Element*>(n);
   1731 }
   1732 
   1733 Element* Element::previousElementSibling() const
   1734 {
   1735     Node* n = previousSibling();
   1736     while (n && !n->isElementNode())
   1737         n = n->previousSibling();
   1738     return static_cast<Element*>(n);
   1739 }
   1740 
   1741 Element* Element::nextElementSibling() const
   1742 {
   1743     Node* n = nextSibling();
   1744     while (n && !n->isElementNode())
   1745         n = n->nextSibling();
   1746     return static_cast<Element*>(n);
   1747 }
   1748 
   1749 unsigned Element::childElementCount() const
   1750 {
   1751     unsigned count = 0;
   1752     Node* n = firstChild();
   1753     while (n) {
   1754         count += n->isElementNode();
   1755         n = n->nextSibling();
   1756     }
   1757     return count;
   1758 }
   1759 
   1760 bool Element::webkitMatchesSelector(const String& selector, ExceptionCode& ec)
   1761 {
   1762     if (selector.isEmpty()) {
   1763         ec = SYNTAX_ERR;
   1764         return false;
   1765     }
   1766 
   1767     bool strictParsing = !document()->inQuirksMode();
   1768     CSSParser p(strictParsing);
   1769 
   1770     CSSSelectorList selectorList;
   1771     p.parseSelector(selector, document(), selectorList);
   1772 
   1773     if (!selectorList.first()) {
   1774         ec = SYNTAX_ERR;
   1775         return false;
   1776     }
   1777 
   1778     // Throw a NAMESPACE_ERR if the selector includes any namespace prefixes.
   1779     if (selectorList.selectorsNeedNamespaceResolution()) {
   1780         ec = NAMESPACE_ERR;
   1781         return false;
   1782     }
   1783 
   1784     CSSStyleSelector::SelectorChecker selectorChecker(document(), strictParsing);
   1785     for (CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
   1786         if (selectorChecker.checkSelector(selector, this))
   1787             return true;
   1788     }
   1789 
   1790     return false;
   1791 }
   1792 
   1793 DOMTokenList* Element::classList()
   1794 {
   1795     ElementRareData* data = ensureRareData();
   1796     if (!data->m_classList)
   1797         data->m_classList = ClassList::create(this);
   1798     return data->m_classList.get();
   1799 }
   1800 
   1801 DOMTokenList* Element::optionalClassList() const
   1802 {
   1803     if (!hasRareData())
   1804         return 0;
   1805     return rareData()->m_classList.get();
   1806 }
   1807 
   1808 DOMStringMap* Element::dataset()
   1809 {
   1810     ElementRareData* data = ensureRareData();
   1811     if (!data->m_datasetDOMStringMap)
   1812         data->m_datasetDOMStringMap = DatasetDOMStringMap::create(this);
   1813     return data->m_datasetDOMStringMap.get();
   1814 }
   1815 
   1816 DOMStringMap* Element::optionalDataset() const
   1817 {
   1818     if (!hasRareData())
   1819         return 0;
   1820     return rareData()->m_datasetDOMStringMap.get();
   1821 }
   1822 
   1823 KURL Element::getURLAttribute(const QualifiedName& name) const
   1824 {
   1825 #if !ASSERT_DISABLED
   1826     if (m_attributeMap) {
   1827         if (Attribute* attribute = m_attributeMap->getAttributeItem(name))
   1828             ASSERT(isURLAttribute(attribute));
   1829     }
   1830 #endif
   1831     return document()->completeURL(stripLeadingAndTrailingHTMLSpaces(getAttribute(name)));
   1832 }
   1833 
   1834 KURL Element::getNonEmptyURLAttribute(const QualifiedName& name) const
   1835 {
   1836 #if !ASSERT_DISABLED
   1837     if (m_attributeMap) {
   1838         if (Attribute* attribute = m_attributeMap->getAttributeItem(name))
   1839             ASSERT(isURLAttribute(attribute));
   1840     }
   1841 #endif
   1842     String value = stripLeadingAndTrailingHTMLSpaces(getAttribute(name));
   1843     if (value.isEmpty())
   1844         return KURL();
   1845     return document()->completeURL(value);
   1846 }
   1847 
   1848 int Element::getIntegralAttribute(const QualifiedName& attributeName) const
   1849 {
   1850     return getAttribute(attributeName).string().toInt();
   1851 }
   1852 
   1853 void Element::setIntegralAttribute(const QualifiedName& attributeName, int value)
   1854 {
   1855     // FIXME: Need an AtomicString version of String::number.
   1856     ExceptionCode ec;
   1857     setAttribute(attributeName, String::number(value), ec);
   1858 }
   1859 
   1860 unsigned Element::getUnsignedIntegralAttribute(const QualifiedName& attributeName) const
   1861 {
   1862     return getAttribute(attributeName).string().toUInt();
   1863 }
   1864 
   1865 void Element::setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value)
   1866 {
   1867     // FIXME: Need an AtomicString version of String::number.
   1868     ExceptionCode ec;
   1869     setAttribute(attributeName, String::number(value), ec);
   1870 }
   1871 
   1872 #if ENABLE(SVG)
   1873 bool Element::childShouldCreateRenderer(Node* child) const
   1874 {
   1875     // Only create renderers for SVG elements whose parents are SVG elements, or for proper <svg xmlns="svgNS"> subdocuments.
   1876     if (child->isSVGElement())
   1877         return child->hasTagName(SVGNames::svgTag) || isSVGElement();
   1878 
   1879     return Node::childShouldCreateRenderer(child);
   1880 }
   1881 #endif
   1882 
   1883 #if ENABLE(FULLSCREEN_API)
   1884 void Element::webkitRequestFullScreen(unsigned short flags)
   1885 {
   1886     document()->webkitRequestFullScreenForElement(this, flags);
   1887 }
   1888 #endif
   1889 
   1890 SpellcheckAttributeState Element::spellcheckAttributeState() const
   1891 {
   1892     if (!hasAttribute(HTMLNames::spellcheckAttr))
   1893         return SpellcheckAttributeDefault;
   1894 
   1895     const AtomicString& value = getAttribute(HTMLNames::spellcheckAttr);
   1896     if (equalIgnoringCase(value, "true") || equalIgnoringCase(value, ""))
   1897         return SpellcheckAttributeTrue;
   1898     if (equalIgnoringCase(value, "false"))
   1899         return SpellcheckAttributeFalse;
   1900 
   1901     return SpellcheckAttributeDefault;
   1902 }
   1903 
   1904 bool Element::isSpellCheckingEnabled() const
   1905 {
   1906     const Element* element = this;
   1907     while (element) {
   1908         switch (element->spellcheckAttributeState()) {
   1909         case SpellcheckAttributeTrue:
   1910             return true;
   1911         case SpellcheckAttributeFalse:
   1912             return false;
   1913         case SpellcheckAttributeDefault:
   1914             break;
   1915         }
   1916 
   1917         ContainerNode* parent = const_cast<Element*>(element)->parentOrHostNode();
   1918         element = (parent && parent->isElementNode()) ? toElement(parent) : 0;
   1919     }
   1920 
   1921     return true;
   1922 }
   1923 
   1924 PassRefPtr<WebKitAnimationList> Element::webkitGetAnimations() const
   1925 {
   1926     if (!renderer())
   1927         return 0;
   1928 
   1929     AnimationController* animController = renderer()->animation();
   1930 
   1931     if (!animController)
   1932         return 0;
   1933 
   1934     return animController->animationsForRenderer(renderer());
   1935 }
   1936 
   1937 } // namespace WebCore
   1938