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 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 "CString.h"
     35 #include "ClientRect.h"
     36 #include "ClientRectList.h"
     37 #include "Document.h"
     38 #include "ElementRareData.h"
     39 #include "ExceptionCode.h"
     40 #include "FocusController.h"
     41 #include "Frame.h"
     42 #include "FrameView.h"
     43 #include "HTMLElement.h"
     44 #include "HTMLNames.h"
     45 #include "InspectorController.h"
     46 #include "NamedNodeMap.h"
     47 #include "NodeList.h"
     48 #include "NodeRenderStyle.h"
     49 #include "Page.h"
     50 #include "RenderView.h"
     51 #include "RenderWidget.h"
     52 #include "TextIterator.h"
     53 #include "XMLNames.h"
     54 
     55 #if ENABLE(SVG)
     56 #include "SVGNames.h"
     57 #endif
     58 
     59 namespace WebCore {
     60 
     61 using namespace HTMLNames;
     62 using namespace XMLNames;
     63 
     64 Element::Element(const QualifiedName& tagName, Document* document, ConstructionType type)
     65     : ContainerNode(document, type)
     66     , m_tagName(tagName)
     67 {
     68 }
     69 
     70 PassRefPtr<Element> Element::create(const QualifiedName& tagName, Document* document)
     71 {
     72     return adoptRef(new Element(tagName, document, CreateElement));
     73 }
     74 
     75 Element::~Element()
     76 {
     77     if (namedAttrMap)
     78         namedAttrMap->detachFromElement();
     79 }
     80 
     81 inline ElementRareData* Element::rareData() const
     82 {
     83     ASSERT(hasRareData());
     84     return static_cast<ElementRareData*>(NodeRareData::rareDataFromMap(this));
     85 }
     86 
     87 inline ElementRareData* Element::ensureRareData()
     88 {
     89     return static_cast<ElementRareData*>(Node::ensureRareData());
     90 }
     91 
     92 NodeRareData* Element::createRareData()
     93 {
     94     return new ElementRareData;
     95 }
     96 
     97 PassRefPtr<Node> Element::cloneNode(bool deep)
     98 {
     99     return deep ? cloneElementWithChildren() : cloneElementWithoutChildren();
    100 }
    101 
    102 PassRefPtr<Element> Element::cloneElementWithChildren()
    103 {
    104     RefPtr<Element> clone = cloneElementWithoutChildren();
    105     cloneChildNodes(clone.get());
    106     return clone.release();
    107 }
    108 
    109 PassRefPtr<Element> Element::cloneElementWithoutChildren()
    110 {
    111     RefPtr<Element> clone = document()->createElement(tagQName(), false);
    112     // This will catch HTML elements in the wrong namespace that are not correctly copied.
    113     // This is a sanity check as HTML overloads some of the DOM methods.
    114     ASSERT(isHTMLElement() == clone->isHTMLElement());
    115 
    116     clone->copyNonAttributeProperties(this);
    117 
    118     // Clone attributes.
    119     if (namedAttrMap)
    120         clone->attributes()->setAttributes(*attributes(true)); // Call attributes(true) to force attribute synchronization to occur (for svg and style) before cloning happens.
    121 
    122     return clone.release();
    123 }
    124 
    125 void Element::removeAttribute(const QualifiedName& name, ExceptionCode& ec)
    126 {
    127     if (namedAttrMap) {
    128         ec = 0;
    129         namedAttrMap->removeNamedItem(name, ec);
    130         if (ec == NOT_FOUND_ERR)
    131             ec = 0;
    132     }
    133 }
    134 
    135 void Element::setAttribute(const QualifiedName& name, const AtomicString& value)
    136 {
    137     ExceptionCode ec;
    138     setAttribute(name, value, ec);
    139 }
    140 
    141 void Element::setCStringAttribute(const QualifiedName& name, const char* cStringValue)
    142 {
    143     ExceptionCode ec;
    144     setAttribute(name, AtomicString(cStringValue), ec);
    145 }
    146 
    147 void Element::setBooleanAttribute(const QualifiedName& name, bool b)
    148 {
    149     if (b)
    150         setAttribute(name, name.localName());
    151     else {
    152         ExceptionCode ex;
    153         removeAttribute(name, ex);
    154     }
    155 }
    156 
    157 // Virtual function, defined in base class.
    158 NamedNodeMap* Element::attributes() const
    159 {
    160     return attributes(false);
    161 }
    162 
    163 Node::NodeType Element::nodeType() const
    164 {
    165     return ELEMENT_NODE;
    166 }
    167 
    168 const AtomicString& Element::getIDAttribute() const
    169 {
    170     return namedAttrMap ? namedAttrMap->id() : nullAtom;
    171 }
    172 
    173 bool Element::hasAttribute(const QualifiedName& name) const
    174 {
    175     return hasAttributeNS(name.namespaceURI(), name.localName());
    176 }
    177 
    178 const AtomicString& Element::getAttribute(const QualifiedName& name) const
    179 {
    180     if (name == styleAttr && !m_isStyleAttributeValid)
    181         updateStyleAttribute();
    182 
    183 #if ENABLE(SVG)
    184     if (!m_areSVGAttributesValid)
    185         updateAnimatedSVGAttribute(name);
    186 #endif
    187 
    188     if (namedAttrMap)
    189         if (Attribute* a = namedAttrMap->getAttributeItem(name))
    190             return a->value();
    191 
    192     return nullAtom;
    193 }
    194 
    195 void Element::scrollIntoView(bool alignToTop)
    196 {
    197     document()->updateLayoutIgnorePendingStylesheets();
    198     IntRect bounds = getRect();
    199     if (renderer()) {
    200         // Align to the top / bottom and to the closest edge.
    201         if (alignToTop)
    202             renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
    203         else
    204             renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignBottomAlways);
    205     }
    206 }
    207 
    208 void Element::scrollIntoViewIfNeeded(bool centerIfNeeded)
    209 {
    210     document()->updateLayoutIgnorePendingStylesheets();
    211     IntRect bounds = getRect();
    212     if (renderer()) {
    213         if (centerIfNeeded)
    214             renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded);
    215         else
    216             renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
    217     }
    218 }
    219 
    220 void Element::scrollByUnits(int units, ScrollGranularity granularity)
    221 {
    222     document()->updateLayoutIgnorePendingStylesheets();
    223     if (RenderObject *rend = renderer()) {
    224         if (rend->hasOverflowClip()) {
    225             ScrollDirection direction = ScrollDown;
    226             if (units < 0) {
    227                 direction = ScrollUp;
    228                 units = -units;
    229             }
    230             toRenderBox(rend)->layer()->scroll(direction, granularity, units);
    231         }
    232     }
    233 }
    234 
    235 void Element::scrollByLines(int lines)
    236 {
    237     scrollByUnits(lines, ScrollByLine);
    238 }
    239 
    240 void Element::scrollByPages(int pages)
    241 {
    242     scrollByUnits(pages, ScrollByPage);
    243 }
    244 
    245 static float localZoomForRenderer(RenderObject* renderer)
    246 {
    247     // FIXME: This does the wrong thing if two opposing zooms are in effect and canceled each
    248     // other out, but the alternative is that we'd have to crawl up the whole render tree every
    249     // time (or store an additional bit in the RenderStyle to indicate that a zoom was specified).
    250     float zoomFactor = 1.0f;
    251     if (renderer->style()->effectiveZoom() != 1.0f) {
    252         // Need to find the nearest enclosing RenderObject that set up
    253         // a differing zoom, and then we divide our result by it to eliminate the zoom.
    254         RenderObject* prev = renderer;
    255         for (RenderObject* curr = prev->parent(); curr; curr = curr->parent()) {
    256             if (curr->style()->effectiveZoom() != prev->style()->effectiveZoom()) {
    257                 zoomFactor = prev->style()->zoom();
    258                 break;
    259             }
    260             prev = curr;
    261         }
    262         if (prev->isRenderView())
    263             zoomFactor = prev->style()->zoom();
    264     }
    265     return zoomFactor;
    266 }
    267 
    268 static int adjustForLocalZoom(int value, RenderObject* renderer)
    269 {
    270     float zoomFactor = localZoomForRenderer(renderer);
    271     if (zoomFactor == 1)
    272         return value;
    273     // Needed because computeLengthInt truncates (rather than rounds) when scaling up.
    274     if (zoomFactor > 1)
    275         value++;
    276     return static_cast<int>(value / zoomFactor);
    277 }
    278 
    279 int Element::offsetLeft()
    280 {
    281     document()->updateLayoutIgnorePendingStylesheets();
    282     if (RenderBoxModelObject* rend = renderBoxModelObject())
    283         return adjustForLocalZoom(rend->offsetLeft(), rend);
    284     return 0;
    285 }
    286 
    287 int Element::offsetTop()
    288 {
    289     document()->updateLayoutIgnorePendingStylesheets();
    290     if (RenderBoxModelObject* rend = renderBoxModelObject())
    291         return adjustForLocalZoom(rend->offsetTop(), rend);
    292     return 0;
    293 }
    294 
    295 int Element::offsetWidth()
    296 {
    297     document()->updateLayoutIgnorePendingStylesheets();
    298     if (RenderBoxModelObject* rend = renderBoxModelObject())
    299         return adjustForAbsoluteZoom(rend->offsetWidth(), rend);
    300     return 0;
    301 }
    302 
    303 int Element::offsetHeight()
    304 {
    305     document()->updateLayoutIgnorePendingStylesheets();
    306     if (RenderBoxModelObject* rend = renderBoxModelObject())
    307         return adjustForAbsoluteZoom(rend->offsetHeight(), rend);
    308     return 0;
    309 }
    310 
    311 Element* Element::offsetParent()
    312 {
    313     document()->updateLayoutIgnorePendingStylesheets();
    314     if (RenderObject* rend = renderer())
    315         if (RenderObject* offsetParent = rend->offsetParent())
    316             return static_cast<Element*>(offsetParent->node());
    317     return 0;
    318 }
    319 
    320 int Element::clientLeft()
    321 {
    322     document()->updateLayoutIgnorePendingStylesheets();
    323 
    324     if (RenderBox* rend = renderBox())
    325         return adjustForAbsoluteZoom(rend->clientLeft(), rend);
    326     return 0;
    327 }
    328 
    329 int Element::clientTop()
    330 {
    331     document()->updateLayoutIgnorePendingStylesheets();
    332 
    333     if (RenderBox* rend = renderBox())
    334         return adjustForAbsoluteZoom(rend->clientTop(), rend);
    335     return 0;
    336 }
    337 
    338 int Element::clientWidth()
    339 {
    340     document()->updateLayoutIgnorePendingStylesheets();
    341 
    342     // When in strict mode, clientWidth for the document element should return the width of the containing frame.
    343     // When in quirks mode, clientWidth for the body element should return the width of the containing frame.
    344     bool inCompatMode = document()->inCompatMode();
    345     if ((!inCompatMode && document()->documentElement() == this) ||
    346         (inCompatMode && isHTMLElement() && document()->body() == this)) {
    347         if (FrameView* view = document()->view()) {
    348             if (RenderView* renderView = document()->renderView())
    349                 return adjustForAbsoluteZoom(view->layoutWidth(), renderView);
    350         }
    351     }
    352 
    353     if (RenderBox* rend = renderBox())
    354         return adjustForAbsoluteZoom(rend->clientWidth(), rend);
    355     return 0;
    356 }
    357 
    358 int Element::clientHeight()
    359 {
    360     document()->updateLayoutIgnorePendingStylesheets();
    361 
    362     // When in strict mode, clientHeight for the document element should return the height of the containing frame.
    363     // When in quirks mode, clientHeight for the body element should return the height of the containing frame.
    364     bool inCompatMode = document()->inCompatMode();
    365 
    366     if ((!inCompatMode && document()->documentElement() == this) ||
    367         (inCompatMode && isHTMLElement() && document()->body() == this)) {
    368         if (FrameView* view = document()->view()) {
    369             if (RenderView* renderView = document()->renderView())
    370                 return adjustForAbsoluteZoom(view->layoutHeight(), renderView);
    371         }
    372     }
    373 
    374     if (RenderBox* rend = renderBox())
    375         return adjustForAbsoluteZoom(rend->clientHeight(), rend);
    376     return 0;
    377 }
    378 
    379 int Element::scrollLeft() const
    380 {
    381     document()->updateLayoutIgnorePendingStylesheets();
    382     if (RenderBox* rend = renderBox())
    383         return adjustForAbsoluteZoom(rend->scrollLeft(), rend);
    384     return 0;
    385 }
    386 
    387 int Element::scrollTop() const
    388 {
    389     document()->updateLayoutIgnorePendingStylesheets();
    390     if (RenderBox* rend = renderBox())
    391         return adjustForAbsoluteZoom(rend->scrollTop(), rend);
    392     return 0;
    393 }
    394 
    395 void Element::setScrollLeft(int newLeft)
    396 {
    397     document()->updateLayoutIgnorePendingStylesheets();
    398     if (RenderBox* rend = renderBox())
    399         rend->setScrollLeft(static_cast<int>(newLeft * rend->style()->effectiveZoom()));
    400 }
    401 
    402 void Element::setScrollTop(int newTop)
    403 {
    404     document()->updateLayoutIgnorePendingStylesheets();
    405     if (RenderBox* rend = renderBox())
    406         rend->setScrollTop(static_cast<int>(newTop * rend->style()->effectiveZoom()));
    407 }
    408 
    409 int Element::scrollWidth() const
    410 {
    411     document()->updateLayoutIgnorePendingStylesheets();
    412     if (RenderBox* rend = renderBox())
    413         return adjustForAbsoluteZoom(rend->scrollWidth(), rend);
    414     return 0;
    415 }
    416 
    417 int Element::scrollHeight() const
    418 {
    419     document()->updateLayoutIgnorePendingStylesheets();
    420     if (RenderBox* rend = renderBox())
    421         return adjustForAbsoluteZoom(rend->scrollHeight(), rend);
    422     return 0;
    423 }
    424 
    425 PassRefPtr<ClientRectList> Element::getClientRects() const
    426 {
    427     document()->updateLayoutIgnorePendingStylesheets();
    428 
    429     RenderBoxModelObject* renderBoxModelObject = this->renderBoxModelObject();
    430     if (!renderBoxModelObject)
    431         return ClientRectList::create();
    432 
    433     // FIXME: Handle SVG elements.
    434     // FIXME: Handle table/inline-table with a caption.
    435 
    436     Vector<FloatQuad> quads;
    437     renderBoxModelObject->absoluteQuads(quads);
    438 
    439     if (FrameView* view = document()->view()) {
    440         IntRect visibleContentRect = view->visibleContentRect();
    441         for (size_t i = 0; i < quads.size(); ++i) {
    442             quads[i].move(-visibleContentRect.x(), -visibleContentRect.y());
    443             adjustFloatQuadForAbsoluteZoom(quads[i], renderBoxModelObject);
    444         }
    445     }
    446 
    447     return ClientRectList::create(quads);
    448 }
    449 
    450 PassRefPtr<ClientRect> Element::getBoundingClientRect() const
    451 {
    452     document()->updateLayoutIgnorePendingStylesheets();
    453     RenderBoxModelObject* renderBoxModelObject = this->renderBoxModelObject();
    454     if (!renderBoxModelObject)
    455         return ClientRect::create();
    456 
    457     Vector<FloatQuad> quads;
    458     renderBoxModelObject->absoluteQuads(quads);
    459 
    460     if (quads.isEmpty())
    461         return ClientRect::create();
    462 
    463     IntRect result = quads[0].enclosingBoundingBox();
    464     for (size_t i = 1; i < quads.size(); ++i)
    465         result.unite(quads[i].enclosingBoundingBox());
    466 
    467     if (FrameView* view = document()->view()) {
    468         IntRect visibleContentRect = view->visibleContentRect();
    469         result.move(-visibleContentRect.x(), -visibleContentRect.y());
    470     }
    471 
    472     adjustIntRectForAbsoluteZoom(result, renderBoxModelObject);
    473 
    474     return ClientRect::create(result);
    475 }
    476 
    477 static inline bool shouldIgnoreAttributeCase(const Element* e)
    478 {
    479     return e && e->document()->isHTMLDocument() && e->isHTMLElement();
    480 }
    481 
    482 const AtomicString& Element::getAttribute(const String& name) const
    483 {
    484     bool ignoreCase = shouldIgnoreAttributeCase(this);
    485 
    486     // Update the 'style' attribute if it's invalid and being requested:
    487     if (!m_isStyleAttributeValid && equalPossiblyIgnoringCase(name, styleAttr.localName(), ignoreCase))
    488         updateStyleAttribute();
    489 
    490 #if ENABLE(SVG)
    491     if (!m_areSVGAttributesValid) {
    492         // We're not passing a namespace argument on purpose. SVGNames::*Attr are defined w/o namespaces as well.
    493         updateAnimatedSVGAttribute(QualifiedName(nullAtom, name, nullAtom));
    494     }
    495 #endif
    496 
    497     if (namedAttrMap)
    498         if (Attribute* attribute = namedAttrMap->getAttributeItem(name, ignoreCase))
    499             return attribute->value();
    500 
    501     return nullAtom;
    502 }
    503 
    504 const AtomicString& Element::getAttributeNS(const String& namespaceURI, const String& localName) const
    505 {
    506     return getAttribute(QualifiedName(nullAtom, localName, namespaceURI));
    507 }
    508 
    509 void Element::setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode& ec)
    510 {
    511     if (!Document::isValidName(name)) {
    512         ec = INVALID_CHARACTER_ERR;
    513         return;
    514     }
    515 
    516     const AtomicString& localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
    517 
    518     // allocate attributemap if necessary
    519     Attribute* old = attributes(false)->getAttributeItem(localName, false);
    520 
    521     document()->incDOMTreeVersion();
    522 
    523     if (localName == idAttributeName().localName())
    524         updateId(old ? old->value() : nullAtom, value);
    525 
    526     if (old && value.isNull())
    527         namedAttrMap->removeAttribute(old->name());
    528     else if (!old && !value.isNull())
    529         namedAttrMap->addAttribute(createAttribute(QualifiedName(nullAtom, localName, nullAtom), value));
    530     else if (old && !value.isNull()) {
    531         old->setValue(value);
    532         attributeChanged(old);
    533     }
    534 
    535 #if ENABLE(INSPECTOR)
    536     if (Page* page = document()->page()) {
    537         if (InspectorController* inspectorController = page->inspectorController()) {
    538             if (!m_synchronizingStyleAttribute)
    539                 inspectorController->didModifyDOMAttr(this);
    540         }
    541     }
    542 #endif
    543 }
    544 
    545 void Element::setAttribute(const QualifiedName& name, const AtomicString& value, ExceptionCode&)
    546 {
    547     document()->incDOMTreeVersion();
    548 
    549     // allocate attributemap if necessary
    550     Attribute* old = attributes(false)->getAttributeItem(name);
    551 
    552     if (name == idAttributeName())
    553         updateId(old ? old->value() : nullAtom, value);
    554 
    555     if (old && value.isNull())
    556         namedAttrMap->removeAttribute(name);
    557     else if (!old && !value.isNull())
    558         namedAttrMap->addAttribute(createAttribute(name, value));
    559     else if (old) {
    560         old->setValue(value);
    561         attributeChanged(old);
    562     }
    563 
    564 #if ENABLE(INSPECTOR)
    565     if (Page* page = document()->page()) {
    566         if (InspectorController* inspectorController = page->inspectorController()) {
    567             if (!m_synchronizingStyleAttribute)
    568                 inspectorController->didModifyDOMAttr(this);
    569         }
    570     }
    571 #endif
    572 }
    573 
    574 PassRefPtr<Attribute> Element::createAttribute(const QualifiedName& name, const AtomicString& value)
    575 {
    576     return Attribute::create(name, value);
    577 }
    578 
    579 void Element::attributeChanged(Attribute* attr, bool)
    580 {
    581     recalcStyleIfNeededAfterAttributeChanged(attr);
    582     updateAfterAttributeChanged(attr);
    583 }
    584 
    585 void Element::updateAfterAttributeChanged(Attribute* attr)
    586 {
    587     if (!AXObjectCache::accessibilityEnabled())
    588         return;
    589 
    590     const QualifiedName& attrName = attr->name();
    591     if (attrName == aria_activedescendantAttr) {
    592         // any change to aria-activedescendant attribute triggers accessibility focus change, but document focus remains intact
    593         document()->axObjectCache()->handleActiveDescendantChanged(renderer());
    594     } else if (attrName == roleAttr) {
    595         // the role attribute can change at any time, and the AccessibilityObject must pick up these changes
    596         document()->axObjectCache()->handleAriaRoleChanged(renderer());
    597     } else if (attrName == aria_valuenowAttr) {
    598         // If the valuenow attribute changes, AX clients need to be notified.
    599         document()->axObjectCache()->postNotification(renderer(), AXObjectCache::AXValueChanged, true);
    600     } else if (attrName == aria_labelAttr || attrName == aria_labeledbyAttr || attrName == altAttr || attrName == titleAttr) {
    601         // If the content of an element changes due to an attribute change, notify accessibility.
    602         document()->axObjectCache()->contentChanged(renderer());
    603     }
    604 }
    605 
    606 void Element::recalcStyleIfNeededAfterAttributeChanged(Attribute* attr)
    607 {
    608     if (document()->attached() && document()->styleSelector()->hasSelectorForAttribute(attr->name().localName()))
    609         setNeedsStyleRecalc();
    610 }
    611 
    612 // Returns true is the given attribute is an event handler.
    613 // We consider an event handler any attribute that begins with "on".
    614 // It is a simple solution that has the advantage of not requiring any
    615 // code or configuration change if a new event handler is defined.
    616 
    617 static bool isEventHandlerAttribute(const QualifiedName& name)
    618 {
    619     return name.namespaceURI().isNull() && name.localName().startsWith("on");
    620 }
    621 
    622 static bool isAttributeToRemove(const QualifiedName& name, const AtomicString& value)
    623 {
    624     return (name.localName().endsWith(hrefAttr.localName()) || name == srcAttr || name == actionAttr) && protocolIsJavaScript(deprecatedParseURL(value));
    625 }
    626 
    627 void Element::setAttributeMap(PassRefPtr<NamedNodeMap> list, FragmentScriptingPermission scriptingPermission)
    628 {
    629     document()->incDOMTreeVersion();
    630 
    631     // If setting the whole map changes the id attribute, we need to call updateId.
    632 
    633     const QualifiedName& idName = idAttributeName();
    634     Attribute* oldId = namedAttrMap ? namedAttrMap->getAttributeItem(idName) : 0;
    635     Attribute* newId = list ? list->getAttributeItem(idName) : 0;
    636 
    637     if (oldId || newId)
    638         updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom);
    639 
    640     if (namedAttrMap)
    641         namedAttrMap->m_element = 0;
    642 
    643     namedAttrMap = list;
    644 
    645     if (namedAttrMap) {
    646         namedAttrMap->m_element = this;
    647         // If the element is created as result of a paste or drag-n-drop operation
    648         // we want to remove all the script and event handlers.
    649         if (scriptingPermission == FragmentScriptingNotAllowed) {
    650             unsigned i = 0;
    651             while (i < namedAttrMap->length()) {
    652                 const QualifiedName& attributeName = namedAttrMap->m_attributes[i]->name();
    653                 if (isEventHandlerAttribute(attributeName)) {
    654                     namedAttrMap->m_attributes.remove(i);
    655                     continue;
    656                 }
    657 
    658                 if (isAttributeToRemove(attributeName, namedAttrMap->m_attributes[i]->value()))
    659                     namedAttrMap->m_attributes[i]->setValue(nullAtom);
    660                 i++;
    661             }
    662         }
    663         unsigned len = namedAttrMap->length();
    664         for (unsigned i = 0; i < len; i++)
    665             attributeChanged(namedAttrMap->m_attributes[i].get());
    666         // FIXME: What about attributes that were in the old map that are not in the new map?
    667     }
    668 }
    669 
    670 bool Element::hasAttributes() const
    671 {
    672     if (!m_isStyleAttributeValid)
    673         updateStyleAttribute();
    674 
    675 #if ENABLE(SVG)
    676     if (!m_areSVGAttributesValid)
    677         updateAnimatedSVGAttribute(anyQName());
    678 #endif
    679 
    680     return namedAttrMap && namedAttrMap->length() > 0;
    681 }
    682 
    683 String Element::nodeName() const
    684 {
    685     return m_tagName.toString();
    686 }
    687 
    688 String Element::nodeNamePreservingCase() const
    689 {
    690     return m_tagName.toString();
    691 }
    692 
    693 void Element::setPrefix(const AtomicString& prefix, ExceptionCode& ec)
    694 {
    695     ec = 0;
    696     checkSetPrefix(prefix, ec);
    697     if (ec)
    698         return;
    699 
    700     m_tagName.setPrefix(prefix.isEmpty() ? AtomicString() : prefix);
    701 }
    702 
    703 KURL Element::baseURI() const
    704 {
    705     const AtomicString& baseAttribute = getAttribute(baseAttr);
    706     KURL base(KURL(), baseAttribute);
    707     if (!base.protocol().isEmpty())
    708         return base;
    709 
    710     Node* parent = parentNode();
    711     if (!parent)
    712         return base;
    713 
    714     const KURL& parentBase = parent->baseURI();
    715     if (parentBase.isNull())
    716         return base;
    717 
    718     return KURL(parentBase, baseAttribute);
    719 }
    720 
    721 void Element::createAttributeMap() const
    722 {
    723     namedAttrMap = NamedNodeMap::create(const_cast<Element*>(this));
    724 }
    725 
    726 bool Element::isURLAttribute(Attribute*) const
    727 {
    728     return false;
    729 }
    730 
    731 const QualifiedName& Element::imageSourceAttributeName() const
    732 {
    733     return srcAttr;
    734 }
    735 
    736 RenderObject* Element::createRenderer(RenderArena* arena, RenderStyle* style)
    737 {
    738     if (document()->documentElement() == this && style->display() == NONE) {
    739         // Ignore display: none on root elements.  Force a display of block in that case.
    740         RenderBlock* result = new (arena) RenderBlock(this);
    741         if (result)
    742             result->setAnimatableStyle(style);
    743         return result;
    744     }
    745     return RenderObject::createObject(this, style);
    746 }
    747 
    748 
    749 void Element::insertedIntoDocument()
    750 {
    751     // need to do superclass processing first so inDocument() is true
    752     // by the time we reach updateId
    753     ContainerNode::insertedIntoDocument();
    754 
    755     if (hasID()) {
    756         if (NamedNodeMap* attrs = namedAttrMap.get()) {
    757             Attribute* idItem = attrs->getAttributeItem(idAttributeName());
    758             if (idItem && !idItem->isNull())
    759                 updateId(nullAtom, idItem->value());
    760         }
    761     }
    762 }
    763 
    764 void Element::removedFromDocument()
    765 {
    766     if (hasID()) {
    767         if (NamedNodeMap* attrs = namedAttrMap.get()) {
    768             Attribute* idItem = attrs->getAttributeItem(idAttributeName());
    769             if (idItem && !idItem->isNull())
    770                 updateId(idItem->value(), nullAtom);
    771         }
    772     }
    773 
    774     ContainerNode::removedFromDocument();
    775 }
    776 
    777 void Element::attach()
    778 {
    779     suspendPostAttachCallbacks();
    780     RenderWidget::suspendWidgetHierarchyUpdates();
    781 
    782     createRendererIfNeeded();
    783     ContainerNode::attach();
    784     if (hasRareData()) {
    785         ElementRareData* data = rareData();
    786         if (data->needsFocusAppearanceUpdateSoonAfterAttach()) {
    787             if (isFocusable() && document()->focusedNode() == this)
    788                 document()->updateFocusAppearanceSoon(false /* don't restore selection */);
    789             data->setNeedsFocusAppearanceUpdateSoonAfterAttach(false);
    790         }
    791     }
    792 
    793     RenderWidget::resumeWidgetHierarchyUpdates();
    794     resumePostAttachCallbacks();
    795 }
    796 
    797 void Element::detach()
    798 {
    799     RenderWidget::suspendWidgetHierarchyUpdates();
    800 
    801     cancelFocusAppearanceUpdate();
    802     if (hasRareData())
    803         rareData()->resetComputedStyle();
    804     ContainerNode::detach();
    805 
    806     RenderWidget::resumeWidgetHierarchyUpdates();
    807 }
    808 
    809 bool Element::pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle)
    810 {
    811     ASSERT(currentStyle == renderStyle());
    812 
    813     if (!renderer() || !currentStyle)
    814         return false;
    815 
    816     RenderStyle::PseudoStyleCache pseudoStyleCache;
    817     currentStyle->getPseudoStyleCache(pseudoStyleCache);
    818     size_t cacheSize = pseudoStyleCache.size();
    819     for (size_t i = 0; i < cacheSize; ++i) {
    820         RefPtr<RenderStyle> newPseudoStyle;
    821         PseudoId pseudoId = pseudoStyleCache[i]->styleType();
    822         if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED)
    823             newPseudoStyle = renderer()->uncachedFirstLineStyle(newStyle);
    824         else
    825             newPseudoStyle = renderer()->getUncachedPseudoStyle(pseudoId, newStyle, newStyle);
    826 
    827         if (*newPseudoStyle != *pseudoStyleCache[i]) {
    828             if (pseudoId < FIRST_INTERNAL_PSEUDOID)
    829                 newStyle->setHasPseudoStyle(pseudoId);
    830             newStyle->addCachedPseudoStyle(newPseudoStyle);
    831             return true;
    832         }
    833     }
    834     return false;
    835 }
    836 
    837 void Element::recalcStyle(StyleChange change)
    838 {
    839     // Ref currentStyle in case it would otherwise be deleted when setRenderStyle() is called.
    840     RefPtr<RenderStyle> currentStyle(renderStyle());
    841     bool hasParentStyle = parentNode() ? parentNode()->renderStyle() : false;
    842     bool hasPositionalRules = needsStyleRecalc() && currentStyle && currentStyle->childrenAffectedByPositionalRules();
    843     bool hasDirectAdjacentRules = currentStyle && currentStyle->childrenAffectedByDirectAdjacentRules();
    844 
    845 #if ENABLE(SVG)
    846     if (!hasParentStyle && isShadowNode() && isSVGElement())
    847         hasParentStyle = true;
    848 #endif
    849 
    850     if ((change > NoChange || needsStyleRecalc())) {
    851         if (hasRareData())
    852             rareData()->resetComputedStyle();
    853     }
    854     if (hasParentStyle && (change >= Inherit || needsStyleRecalc())) {
    855         RefPtr<RenderStyle> newStyle = document()->styleSelector()->styleForElement(this);
    856         StyleChange ch = diff(currentStyle.get(), newStyle.get());
    857         if (ch == Detach || !currentStyle) {
    858             if (attached())
    859                 detach();
    860             attach(); // FIXME: The style gets computed twice by calling attach. We could do better if we passed the style along.
    861             // attach recalulates the style for all children. No need to do it twice.
    862             setNeedsStyleRecalc(NoStyleChange);
    863             setChildNeedsStyleRecalc(false);
    864             return;
    865         }
    866 
    867         if (currentStyle) {
    868             // Preserve "affected by" bits that were propagated to us from descendants in the case where we didn't do a full
    869             // style change (e.g., only inline style changed).
    870             if (currentStyle->affectedByHoverRules())
    871                 newStyle->setAffectedByHoverRules(true);
    872             if (currentStyle->affectedByActiveRules())
    873                 newStyle->setAffectedByActiveRules(true);
    874             if (currentStyle->affectedByDragRules())
    875                 newStyle->setAffectedByDragRules(true);
    876             if (currentStyle->childrenAffectedByForwardPositionalRules())
    877                 newStyle->setChildrenAffectedByForwardPositionalRules();
    878             if (currentStyle->childrenAffectedByBackwardPositionalRules())
    879                 newStyle->setChildrenAffectedByBackwardPositionalRules();
    880             if (currentStyle->childrenAffectedByFirstChildRules())
    881                 newStyle->setChildrenAffectedByFirstChildRules();
    882             if (currentStyle->childrenAffectedByLastChildRules())
    883                 newStyle->setChildrenAffectedByLastChildRules();
    884             if (currentStyle->childrenAffectedByDirectAdjacentRules())
    885                 newStyle->setChildrenAffectedByDirectAdjacentRules();
    886         }
    887 
    888         if (ch != NoChange || pseudoStyleCacheIsInvalid(currentStyle.get(), newStyle.get())) {
    889             setRenderStyle(newStyle);
    890         } else if (needsStyleRecalc() && (styleChangeType() != SyntheticStyleChange) && (document()->usesSiblingRules() || document()->usesDescendantRules())) {
    891             // Although no change occurred, we use the new style so that the cousin style sharing code won't get
    892             // fooled into believing this style is the same.  This is only necessary if the document actually uses
    893             // sibling/descendant rules, since otherwise it isn't possible for ancestor styles to affect sharing of
    894             // descendants.
    895             if (renderer())
    896                 renderer()->setStyleInternal(newStyle.get());
    897             else
    898                 setRenderStyle(newStyle);
    899         } else if (styleChangeType() == SyntheticStyleChange)
    900              setRenderStyle(newStyle);
    901 
    902         if (change != Force) {
    903             // 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
    904             // 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).
    905             if (document()->usesRemUnits() && ch != NoChange && currentStyle && newStyle && currentStyle->fontSize() != newStyle->fontSize() && document()->documentElement() == this)
    906                 change = Force;
    907             else if ((document()->usesDescendantRules() || hasPositionalRules) && styleChangeType() >= FullStyleChange)
    908                 change = Force;
    909             else
    910                 change = ch;
    911         }
    912     }
    913 
    914     // FIXME: This check is good enough for :hover + foo, but it is not good enough for :hover + foo + bar.
    915     // For now we will just worry about the common case, since it's a lot trickier to get the second case right
    916     // without doing way too much re-resolution.
    917     bool forceCheckOfNextElementSibling = false;
    918     for (Node *n = firstChild(); n; n = n->nextSibling()) {
    919         bool childRulesChanged = n->needsStyleRecalc() && n->styleChangeType() == FullStyleChange;
    920         if (forceCheckOfNextElementSibling && n->isElementNode())
    921             n->setNeedsStyleRecalc();
    922         if (change >= Inherit || n->isTextNode() || n->childNeedsStyleRecalc() || n->needsStyleRecalc())
    923             n->recalcStyle(change);
    924         if (n->isElementNode())
    925             forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentRules;
    926     }
    927 
    928     setNeedsStyleRecalc(NoStyleChange);
    929     setChildNeedsStyleRecalc(false);
    930 }
    931 
    932 bool Element::childTypeAllowed(NodeType type)
    933 {
    934     switch (type) {
    935         case ELEMENT_NODE:
    936         case TEXT_NODE:
    937         case COMMENT_NODE:
    938         case PROCESSING_INSTRUCTION_NODE:
    939         case CDATA_SECTION_NODE:
    940         case ENTITY_REFERENCE_NODE:
    941             return true;
    942             break;
    943         default:
    944             return false;
    945     }
    946 }
    947 
    948 static void checkForSiblingStyleChanges(Element* e, RenderStyle* style, bool finishedParsingCallback,
    949                                         Node* beforeChange, Node* afterChange, int childCountDelta)
    950 {
    951     if (!style || (e->needsStyleRecalc() && style->childrenAffectedByPositionalRules()))
    952         return;
    953 
    954     // :first-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
    955     // In the DOM case, we only need to do something if |afterChange| is not 0.
    956     // |afterChange| is 0 in the parser case, so it works out that we'll skip this block.
    957     if (style->childrenAffectedByFirstChildRules() && afterChange) {
    958         // Find our new first child.
    959         Node* newFirstChild = 0;
    960         for (newFirstChild = e->firstChild(); newFirstChild && !newFirstChild->isElementNode(); newFirstChild = newFirstChild->nextSibling()) {};
    961 
    962         // Find the first element node following |afterChange|
    963         Node* firstElementAfterInsertion = 0;
    964         for (firstElementAfterInsertion = afterChange;
    965              firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
    966              firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
    967 
    968         // This is the insert/append case.
    969         if (newFirstChild != firstElementAfterInsertion && firstElementAfterInsertion && firstElementAfterInsertion->attached() &&
    970             firstElementAfterInsertion->renderStyle() && firstElementAfterInsertion->renderStyle()->firstChildState())
    971             firstElementAfterInsertion->setNeedsStyleRecalc();
    972 
    973         // We also have to handle node removal.
    974         if (childCountDelta < 0 && newFirstChild == firstElementAfterInsertion && newFirstChild && newFirstChild->renderStyle() && !newFirstChild->renderStyle()->firstChildState())
    975             newFirstChild->setNeedsStyleRecalc();
    976     }
    977 
    978     // :last-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
    979     // In the DOM case, we only need to do something if |afterChange| is not 0.
    980     if (style->childrenAffectedByLastChildRules() && beforeChange) {
    981         // Find our new last child.
    982         Node* newLastChild = 0;
    983         for (newLastChild = e->lastChild(); newLastChild && !newLastChild->isElementNode(); newLastChild = newLastChild->previousSibling()) {};
    984 
    985         // Find the last element node going backwards from |beforeChange|
    986         Node* lastElementBeforeInsertion = 0;
    987         for (lastElementBeforeInsertion = beforeChange;
    988              lastElementBeforeInsertion && !lastElementBeforeInsertion->isElementNode();
    989              lastElementBeforeInsertion = lastElementBeforeInsertion->previousSibling()) {};
    990 
    991         if (newLastChild != lastElementBeforeInsertion && lastElementBeforeInsertion && lastElementBeforeInsertion->attached() &&
    992             lastElementBeforeInsertion->renderStyle() && lastElementBeforeInsertion->renderStyle()->lastChildState())
    993             lastElementBeforeInsertion->setNeedsStyleRecalc();
    994 
    995         // 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
    996         // to match now.
    997         if ((childCountDelta < 0 || finishedParsingCallback) && newLastChild == lastElementBeforeInsertion && newLastChild && newLastChild->renderStyle() && !newLastChild->renderStyle()->lastChildState())
    998             newLastChild->setNeedsStyleRecalc();
    999     }
   1000 
   1001     // The + selector.  We need to invalidate the first element following the insertion point.  It is the only possible element
   1002     // that could be affected by this DOM change.
   1003     if (style->childrenAffectedByDirectAdjacentRules() && afterChange) {
   1004         Node* firstElementAfterInsertion = 0;
   1005         for (firstElementAfterInsertion = afterChange;
   1006              firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
   1007              firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
   1008         if (firstElementAfterInsertion && firstElementAfterInsertion->attached())
   1009             firstElementAfterInsertion->setNeedsStyleRecalc();
   1010     }
   1011 
   1012     // Forward positional selectors include the ~ selector, nth-child, nth-of-type, first-of-type and only-of-type.
   1013     // Backward positional selectors include nth-last-child, nth-last-of-type, last-of-type and only-of-type.
   1014     // We have to invalidate everything following the insertion point in the forward case, and everything before the insertion point in the
   1015     // backward case.
   1016     // |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.
   1017     // 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
   1018     // here.  recalcStyle will then force a walk of the children when it sees that this has happened.
   1019     if ((style->childrenAffectedByForwardPositionalRules() && afterChange) ||
   1020         (style->childrenAffectedByBackwardPositionalRules() && beforeChange))
   1021         e->setNeedsStyleRecalc();
   1022 
   1023     // :empty selector.
   1024     if (style->affectedByEmpty() && (!style->emptyState() || e->hasChildNodes()))
   1025         e->setNeedsStyleRecalc();
   1026 }
   1027 
   1028 void Element::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
   1029 {
   1030     ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
   1031     if (!changedByParser)
   1032         checkForSiblingStyleChanges(this, renderStyle(), false, beforeChange, afterChange, childCountDelta);
   1033 }
   1034 
   1035 void Element::finishParsingChildren()
   1036 {
   1037     ContainerNode::finishParsingChildren();
   1038     m_parsingChildrenFinished = true;
   1039     checkForSiblingStyleChanges(this, renderStyle(), true, lastChild(), 0, 0);
   1040 }
   1041 
   1042 void Element::dispatchAttrRemovalEvent(Attribute*)
   1043 {
   1044     ASSERT(!eventDispatchForbidden());
   1045 
   1046 #if 0
   1047     if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER))
   1048         return;
   1049     ExceptionCode ec = 0;
   1050     dispatchEvent(new MutationEvent(DOMAttrModifiedEvent, true, false, attr, attr->value(),
   1051         attr->value(), document()->attrName(attr->id()), MutationEvent::REMOVAL), ec);
   1052 #endif
   1053 }
   1054 
   1055 void Element::dispatchAttrAdditionEvent(Attribute*)
   1056 {
   1057     ASSERT(!eventDispatchForbidden());
   1058 
   1059 #if 0
   1060     if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER))
   1061         return;
   1062     ExceptionCode ec = 0;
   1063     dispatchEvent(new MutationEvent(DOMAttrModifiedEvent, true, false, attr, attr->value(),
   1064         attr->value(), document()->attrName(attr->id()), MutationEvent::ADDITION), ec);
   1065 #endif
   1066 }
   1067 
   1068 String Element::openTagStartToString() const
   1069 {
   1070     String result = "<" + nodeName();
   1071 
   1072     NamedNodeMap* attrMap = attributes(true);
   1073 
   1074     if (attrMap) {
   1075         unsigned numAttrs = attrMap->length();
   1076         for (unsigned i = 0; i < numAttrs; i++) {
   1077             result += " ";
   1078 
   1079             Attribute *attribute = attrMap->attributeItem(i);
   1080             result += attribute->name().toString();
   1081             if (!attribute->value().isNull()) {
   1082                 result += "=\"";
   1083                 // FIXME: substitute entities for any instances of " or '
   1084                 result += attribute->value();
   1085                 result += "\"";
   1086             }
   1087         }
   1088     }
   1089 
   1090     return result;
   1091 }
   1092 
   1093 #ifndef NDEBUG
   1094 void Element::formatForDebugger(char* buffer, unsigned length) const
   1095 {
   1096     String result;
   1097     String s;
   1098 
   1099     s = nodeName();
   1100     if (s.length() > 0) {
   1101         result += s;
   1102     }
   1103 
   1104     s = getAttribute(idAttributeName());
   1105     if (s.length() > 0) {
   1106         if (result.length() > 0)
   1107             result += "; ";
   1108         result += "id=";
   1109         result += s;
   1110     }
   1111 
   1112     s = getAttribute(classAttr);
   1113     if (s.length() > 0) {
   1114         if (result.length() > 0)
   1115             result += "; ";
   1116         result += "class=";
   1117         result += s;
   1118     }
   1119 
   1120     strncpy(buffer, result.utf8().data(), length - 1);
   1121 }
   1122 #endif
   1123 
   1124 PassRefPtr<Attr> Element::setAttributeNode(Attr* attr, ExceptionCode& ec)
   1125 {
   1126     if (!attr) {
   1127         ec = TYPE_MISMATCH_ERR;
   1128         return 0;
   1129     }
   1130     return static_pointer_cast<Attr>(attributes(false)->setNamedItem(attr, ec));
   1131 }
   1132 
   1133 PassRefPtr<Attr> Element::setAttributeNodeNS(Attr* attr, ExceptionCode& ec)
   1134 {
   1135     if (!attr) {
   1136         ec = TYPE_MISMATCH_ERR;
   1137         return 0;
   1138     }
   1139     return static_pointer_cast<Attr>(attributes(false)->setNamedItem(attr, ec));
   1140 }
   1141 
   1142 PassRefPtr<Attr> Element::removeAttributeNode(Attr* attr, ExceptionCode& ec)
   1143 {
   1144     if (!attr) {
   1145         ec = TYPE_MISMATCH_ERR;
   1146         return 0;
   1147     }
   1148     if (attr->ownerElement() != this) {
   1149         ec = NOT_FOUND_ERR;
   1150         return 0;
   1151     }
   1152     if (document() != attr->document()) {
   1153         ec = WRONG_DOCUMENT_ERR;
   1154         return 0;
   1155     }
   1156 
   1157     NamedNodeMap* attrs = attributes(true);
   1158     if (!attrs)
   1159         return 0;
   1160 
   1161     return static_pointer_cast<Attr>(attrs->removeNamedItem(attr->qualifiedName(), ec));
   1162 }
   1163 
   1164 void Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode& ec, FragmentScriptingPermission scriptingPermission)
   1165 {
   1166     String prefix, localName;
   1167     if (!Document::parseQualifiedName(qualifiedName, prefix, localName, ec))
   1168         return;
   1169 
   1170     QualifiedName qName(prefix, localName, namespaceURI);
   1171 
   1172     if (scriptingPermission == FragmentScriptingNotAllowed && (isEventHandlerAttribute(qName) || isAttributeToRemove(qName, value)))
   1173         return;
   1174 
   1175     setAttribute(qName, value, ec);
   1176 }
   1177 
   1178 void Element::removeAttribute(const String& name, ExceptionCode& ec)
   1179 {
   1180     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
   1181 
   1182     if (namedAttrMap) {
   1183         namedAttrMap->removeNamedItem(localName, ec);
   1184         if (ec == NOT_FOUND_ERR)
   1185             ec = 0;
   1186     }
   1187 
   1188 #if ENABLE(INSPECTOR)
   1189     if (Page* page = document()->page()) {
   1190         if (InspectorController* inspectorController = page->inspectorController())
   1191             inspectorController->didModifyDOMAttr(this);
   1192     }
   1193 #endif
   1194 
   1195 }
   1196 
   1197 void Element::removeAttributeNS(const String& namespaceURI, const String& localName, ExceptionCode& ec)
   1198 {
   1199     removeAttribute(QualifiedName(nullAtom, localName, namespaceURI), ec);
   1200 }
   1201 
   1202 PassRefPtr<Attr> Element::getAttributeNode(const String& name)
   1203 {
   1204     NamedNodeMap* attrs = attributes(true);
   1205     if (!attrs)
   1206         return 0;
   1207     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
   1208     return static_pointer_cast<Attr>(attrs->getNamedItem(localName));
   1209 }
   1210 
   1211 PassRefPtr<Attr> Element::getAttributeNodeNS(const String& namespaceURI, const String& localName)
   1212 {
   1213     NamedNodeMap* attrs = attributes(true);
   1214     if (!attrs)
   1215         return 0;
   1216     return static_pointer_cast<Attr>(attrs->getNamedItem(QualifiedName(nullAtom, localName, namespaceURI)));
   1217 }
   1218 
   1219 bool Element::hasAttribute(const String& name) const
   1220 {
   1221     NamedNodeMap* attrs = attributes(true);
   1222     if (!attrs)
   1223         return false;
   1224 
   1225     // This call to String::lower() seems to be required but
   1226     // there may be a way to remove it.
   1227     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
   1228     return attrs->getAttributeItem(localName, false);
   1229 }
   1230 
   1231 bool Element::hasAttributeNS(const String& namespaceURI, const String& localName) const
   1232 {
   1233     NamedNodeMap* attrs = attributes(true);
   1234     if (!attrs)
   1235         return false;
   1236     return attrs->getAttributeItem(QualifiedName(nullAtom, localName, namespaceURI));
   1237 }
   1238 
   1239 CSSStyleDeclaration *Element::style()
   1240 {
   1241     return 0;
   1242 }
   1243 
   1244 void Element::focus(bool restorePreviousSelection)
   1245 {
   1246     Document* doc = document();
   1247     if (doc->focusedNode() == this)
   1248         return;
   1249 
   1250     if (!supportsFocus())
   1251         return;
   1252 
   1253     // If the stylesheets have already been loaded we can reliably check isFocusable.
   1254     // If not, we continue and set the focused node on the focus controller below so
   1255     // that it can be updated soon after attach.
   1256     if (doc->haveStylesheetsLoaded()) {
   1257         doc->updateLayoutIgnorePendingStylesheets();
   1258         if (!isFocusable())
   1259             return;
   1260     }
   1261 
   1262     if (Page* page = doc->page())
   1263         page->focusController()->setFocusedNode(this, doc->frame());
   1264 
   1265     // Setting the focused node above might have invalidated the layout due to scripts.
   1266     doc->updateLayoutIgnorePendingStylesheets();
   1267 
   1268     if (!isFocusable()) {
   1269         ensureRareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(true);
   1270         return;
   1271     }
   1272 
   1273     cancelFocusAppearanceUpdate();
   1274     updateFocusAppearance(restorePreviousSelection);
   1275 }
   1276 
   1277 void Element::updateFocusAppearance(bool /*restorePreviousSelection*/)
   1278 {
   1279     if (this == rootEditableElement()) {
   1280         Frame* frame = document()->frame();
   1281         if (!frame)
   1282             return;
   1283 
   1284         // FIXME: We should restore the previous selection if there is one.
   1285         VisibleSelection newSelection = hasTagName(htmlTag) || hasTagName(bodyTag) ? VisibleSelection(Position(this, 0), DOWNSTREAM) : VisibleSelection::selectionFromContentsOfNode(this);
   1286 
   1287         if (frame->shouldChangeSelection(newSelection)) {
   1288             frame->selection()->setSelection(newSelection);
   1289             frame->revealSelection();
   1290         }
   1291     }
   1292     // FIXME: I'm not sure all devices will want this off, but this is
   1293     // currently turned off for Android.
   1294 #if !ENABLE(DIRECTIONAL_PAD_NAVIGATION)
   1295     else if (renderer() && !renderer()->isWidget())
   1296         renderer()->enclosingLayer()->scrollRectToVisible(getRect());
   1297 #endif
   1298 }
   1299 
   1300 void Element::blur()
   1301 {
   1302     cancelFocusAppearanceUpdate();
   1303     Document* doc = document();
   1304     if (doc->focusedNode() == this) {
   1305         if (doc->frame())
   1306             doc->frame()->page()->focusController()->setFocusedNode(0, doc->frame());
   1307         else
   1308             doc->setFocusedNode(0);
   1309     }
   1310 }
   1311 
   1312 String Element::innerText() const
   1313 {
   1314     // We need to update layout, since plainText uses line boxes in the render tree.
   1315     document()->updateLayoutIgnorePendingStylesheets();
   1316 
   1317     if (!renderer())
   1318         return textContent(true);
   1319 
   1320     return plainText(rangeOfContents(const_cast<Element*>(this)).get());
   1321 }
   1322 
   1323 String Element::outerText() const
   1324 {
   1325     // Getting outerText is the same as getting innerText, only
   1326     // setting is different. You would think this should get the plain
   1327     // text for the outer range, but this is wrong, <br> for instance
   1328     // would return different values for inner and outer text by such
   1329     // a rule, but it doesn't in WinIE, and we want to match that.
   1330     return innerText();
   1331 }
   1332 
   1333 String Element::title() const
   1334 {
   1335     return String();
   1336 }
   1337 
   1338 IntSize Element::minimumSizeForResizing() const
   1339 {
   1340     return hasRareData() ? rareData()->m_minimumSizeForResizing : defaultMinimumSizeForResizing();
   1341 }
   1342 
   1343 void Element::setMinimumSizeForResizing(const IntSize& size)
   1344 {
   1345     if (size == defaultMinimumSizeForResizing() && !hasRareData())
   1346         return;
   1347     ensureRareData()->m_minimumSizeForResizing = size;
   1348 }
   1349 
   1350 RenderStyle* Element::computedStyle()
   1351 {
   1352     if (RenderStyle* usedStyle = renderStyle())
   1353         return usedStyle;
   1354 
   1355     if (!attached())
   1356         // FIXME: Try to do better than this. Ensure that styleForElement() works for elements that are not in the
   1357         // document tree and figure out when to destroy the computed style for such elements.
   1358         return 0;
   1359 
   1360     ElementRareData* data = ensureRareData();
   1361     if (!data->m_computedStyle)
   1362         data->m_computedStyle = document()->styleSelector()->styleForElement(this, parent() ? parent()->computedStyle() : 0);
   1363     return data->m_computedStyle.get();
   1364 }
   1365 
   1366 void Element::cancelFocusAppearanceUpdate()
   1367 {
   1368     if (hasRareData())
   1369         rareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(false);
   1370     if (document()->focusedNode() == this)
   1371         document()->cancelFocusAppearanceUpdate();
   1372 }
   1373 
   1374 void Element::normalizeAttributes()
   1375 {
   1376     // Normalize attributes.
   1377     NamedNodeMap* attrs = attributes(true);
   1378     if (!attrs)
   1379         return;
   1380     unsigned numAttrs = attrs->length();
   1381     for (unsigned i = 0; i < numAttrs; i++) {
   1382         if (Attr* attr = attrs->attributeItem(i)->attr())
   1383             attr->normalize();
   1384     }
   1385 }
   1386 
   1387 // ElementTraversal API
   1388 Element* Element::firstElementChild() const
   1389 {
   1390     Node* n = firstChild();
   1391     while (n && !n->isElementNode())
   1392         n = n->nextSibling();
   1393     return static_cast<Element*>(n);
   1394 }
   1395 
   1396 Element* Element::lastElementChild() const
   1397 {
   1398     Node* n = lastChild();
   1399     while (n && !n->isElementNode())
   1400         n = n->previousSibling();
   1401     return static_cast<Element*>(n);
   1402 }
   1403 
   1404 Element* Element::previousElementSibling() const
   1405 {
   1406     Node* n = previousSibling();
   1407     while (n && !n->isElementNode())
   1408         n = n->previousSibling();
   1409     return static_cast<Element*>(n);
   1410 }
   1411 
   1412 Element* Element::nextElementSibling() const
   1413 {
   1414     Node* n = nextSibling();
   1415     while (n && !n->isElementNode())
   1416         n = n->nextSibling();
   1417     return static_cast<Element*>(n);
   1418 }
   1419 
   1420 unsigned Element::childElementCount() const
   1421 {
   1422     unsigned count = 0;
   1423     Node* n = firstChild();
   1424     while (n) {
   1425         count += n->isElementNode();
   1426         n = n->nextSibling();
   1427     }
   1428     return count;
   1429 }
   1430 
   1431 bool Element::webkitMatchesSelector(const String& selector, ExceptionCode& ec)
   1432 {
   1433     if (selector.isEmpty()) {
   1434         ec = SYNTAX_ERR;
   1435         return false;
   1436     }
   1437 
   1438     bool strictParsing = !document()->inCompatMode();
   1439     CSSParser p(strictParsing);
   1440 
   1441     CSSSelectorList selectorList;
   1442     p.parseSelector(selector, document(), selectorList);
   1443 
   1444     if (!selectorList.first()) {
   1445         ec = SYNTAX_ERR;
   1446         return false;
   1447     }
   1448 
   1449     // Throw a NAMESPACE_ERR if the selector includes any namespace prefixes.
   1450     if (selectorList.selectorsNeedNamespaceResolution()) {
   1451         ec = NAMESPACE_ERR;
   1452         return false;
   1453     }
   1454 
   1455     CSSStyleSelector::SelectorChecker selectorChecker(document(), strictParsing);
   1456     for (CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
   1457         if (selectorChecker.checkSelector(selector, this))
   1458             return true;
   1459     }
   1460 
   1461     return false;
   1462 }
   1463 
   1464 KURL Element::getURLAttribute(const QualifiedName& name) const
   1465 {
   1466 #if !ASSERT_DISABLED
   1467     if (namedAttrMap) {
   1468         if (Attribute* attribute = namedAttrMap->getAttributeItem(name))
   1469             ASSERT(isURLAttribute(attribute));
   1470     }
   1471 #endif
   1472     return document()->completeURL(deprecatedParseURL(getAttribute(name)));
   1473 }
   1474 
   1475 const QualifiedName& Element::rareIDAttributeName() const
   1476 {
   1477     return rareData()->m_idAttributeName;
   1478 }
   1479 
   1480 } // namespace WebCore
   1481