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         if (Attr* attrNode = old->attr())
    532             attrNode->setValue(value);
    533         else
    534             old->setValue(value);
    535         attributeChanged(old);
    536     }
    537 
    538 #if ENABLE(INSPECTOR)
    539     if (Page* page = document()->page()) {
    540         if (InspectorController* inspectorController = page->inspectorController()) {
    541             if (!m_synchronizingStyleAttribute)
    542                 inspectorController->didModifyDOMAttr(this);
    543         }
    544     }
    545 #endif
    546 }
    547 
    548 void Element::setAttribute(const QualifiedName& name, const AtomicString& value, ExceptionCode&)
    549 {
    550     document()->incDOMTreeVersion();
    551 
    552     // allocate attributemap if necessary
    553     Attribute* old = attributes(false)->getAttributeItem(name);
    554 
    555     if (name == idAttributeName())
    556         updateId(old ? old->value() : nullAtom, value);
    557 
    558     if (old && value.isNull())
    559         namedAttrMap->removeAttribute(name);
    560     else if (!old && !value.isNull())
    561         namedAttrMap->addAttribute(createAttribute(name, value));
    562     else if (old) {
    563         if (Attr* attrNode = old->attr())
    564             attrNode->setValue(value);
    565         else
    566             old->setValue(value);
    567         attributeChanged(old);
    568     }
    569 
    570 #if ENABLE(INSPECTOR)
    571     if (Page* page = document()->page()) {
    572         if (InspectorController* inspectorController = page->inspectorController()) {
    573             if (!m_synchronizingStyleAttribute)
    574                 inspectorController->didModifyDOMAttr(this);
    575         }
    576     }
    577 #endif
    578 }
    579 
    580 PassRefPtr<Attribute> Element::createAttribute(const QualifiedName& name, const AtomicString& value)
    581 {
    582     return Attribute::create(name, value);
    583 }
    584 
    585 void Element::attributeChanged(Attribute* attr, bool)
    586 {
    587     recalcStyleIfNeededAfterAttributeChanged(attr);
    588     updateAfterAttributeChanged(attr);
    589 }
    590 
    591 void Element::updateAfterAttributeChanged(Attribute* attr)
    592 {
    593     if (!AXObjectCache::accessibilityEnabled())
    594         return;
    595 
    596     const QualifiedName& attrName = attr->name();
    597     if (attrName == aria_activedescendantAttr) {
    598         // any change to aria-activedescendant attribute triggers accessibility focus change, but document focus remains intact
    599         document()->axObjectCache()->handleActiveDescendantChanged(renderer());
    600     } else if (attrName == roleAttr) {
    601         // the role attribute can change at any time, and the AccessibilityObject must pick up these changes
    602         document()->axObjectCache()->handleAriaRoleChanged(renderer());
    603     } else if (attrName == aria_valuenowAttr) {
    604         // If the valuenow attribute changes, AX clients need to be notified.
    605         document()->axObjectCache()->postNotification(renderer(), AXObjectCache::AXValueChanged, true);
    606     } else if (attrName == aria_labelAttr || attrName == aria_labeledbyAttr || attrName == altAttr || attrName == titleAttr) {
    607         // If the content of an element changes due to an attribute change, notify accessibility.
    608         document()->axObjectCache()->contentChanged(renderer());
    609     }
    610 }
    611 
    612 void Element::recalcStyleIfNeededAfterAttributeChanged(Attribute* attr)
    613 {
    614     if (document()->attached() && document()->styleSelector()->hasSelectorForAttribute(attr->name().localName()))
    615         setNeedsStyleRecalc();
    616 }
    617 
    618 // Returns true is the given attribute is an event handler.
    619 // We consider an event handler any attribute that begins with "on".
    620 // It is a simple solution that has the advantage of not requiring any
    621 // code or configuration change if a new event handler is defined.
    622 
    623 static bool isEventHandlerAttribute(const QualifiedName& name)
    624 {
    625     return name.namespaceURI().isNull() && name.localName().startsWith("on");
    626 }
    627 
    628 static bool isAttributeToRemove(const QualifiedName& name, const AtomicString& value)
    629 {
    630     return (name.localName().endsWith(hrefAttr.localName()) || name == srcAttr || name == actionAttr) && protocolIsJavaScript(deprecatedParseURL(value));
    631 }
    632 
    633 void Element::setAttributeMap(PassRefPtr<NamedNodeMap> list, FragmentScriptingPermission scriptingPermission)
    634 {
    635     document()->incDOMTreeVersion();
    636 
    637     // If setting the whole map changes the id attribute, we need to call updateId.
    638 
    639     const QualifiedName& idName = idAttributeName();
    640     Attribute* oldId = namedAttrMap ? namedAttrMap->getAttributeItem(idName) : 0;
    641     Attribute* newId = list ? list->getAttributeItem(idName) : 0;
    642 
    643     if (oldId || newId)
    644         updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom);
    645 
    646     if (namedAttrMap)
    647         namedAttrMap->m_element = 0;
    648 
    649     namedAttrMap = list;
    650 
    651     if (namedAttrMap) {
    652         namedAttrMap->m_element = this;
    653         // If the element is created as result of a paste or drag-n-drop operation
    654         // we want to remove all the script and event handlers.
    655         if (scriptingPermission == FragmentScriptingNotAllowed) {
    656             unsigned i = 0;
    657             while (i < namedAttrMap->length()) {
    658                 const QualifiedName& attributeName = namedAttrMap->m_attributes[i]->name();
    659                 if (isEventHandlerAttribute(attributeName)) {
    660                     namedAttrMap->m_attributes.remove(i);
    661                     continue;
    662                 }
    663 
    664                 if (isAttributeToRemove(attributeName, namedAttrMap->m_attributes[i]->value()))
    665                     namedAttrMap->m_attributes[i]->setValue(nullAtom);
    666                 i++;
    667             }
    668         }
    669         unsigned len = namedAttrMap->length();
    670         for (unsigned i = 0; i < len; i++)
    671             attributeChanged(namedAttrMap->m_attributes[i].get());
    672         // FIXME: What about attributes that were in the old map that are not in the new map?
    673     }
    674 }
    675 
    676 bool Element::hasAttributes() const
    677 {
    678     if (!m_isStyleAttributeValid)
    679         updateStyleAttribute();
    680 
    681 #if ENABLE(SVG)
    682     if (!m_areSVGAttributesValid)
    683         updateAnimatedSVGAttribute(anyQName());
    684 #endif
    685 
    686     return namedAttrMap && namedAttrMap->length() > 0;
    687 }
    688 
    689 String Element::nodeName() const
    690 {
    691     return m_tagName.toString();
    692 }
    693 
    694 String Element::nodeNamePreservingCase() const
    695 {
    696     return m_tagName.toString();
    697 }
    698 
    699 void Element::setPrefix(const AtomicString& prefix, ExceptionCode& ec)
    700 {
    701     ec = 0;
    702     checkSetPrefix(prefix, ec);
    703     if (ec)
    704         return;
    705 
    706     m_tagName.setPrefix(prefix.isEmpty() ? AtomicString() : prefix);
    707 }
    708 
    709 KURL Element::baseURI() const
    710 {
    711     const AtomicString& baseAttribute = getAttribute(baseAttr);
    712     KURL base(KURL(), baseAttribute);
    713     if (!base.protocol().isEmpty())
    714         return base;
    715 
    716     Node* parent = parentNode();
    717     if (!parent)
    718         return base;
    719 
    720     const KURL& parentBase = parent->baseURI();
    721     if (parentBase.isNull())
    722         return base;
    723 
    724     return KURL(parentBase, baseAttribute);
    725 }
    726 
    727 void Element::createAttributeMap() const
    728 {
    729     namedAttrMap = NamedNodeMap::create(const_cast<Element*>(this));
    730 }
    731 
    732 bool Element::isURLAttribute(Attribute*) const
    733 {
    734     return false;
    735 }
    736 
    737 const QualifiedName& Element::imageSourceAttributeName() const
    738 {
    739     return srcAttr;
    740 }
    741 
    742 RenderObject* Element::createRenderer(RenderArena* arena, RenderStyle* style)
    743 {
    744     if (document()->documentElement() == this && style->display() == NONE) {
    745         // Ignore display: none on root elements.  Force a display of block in that case.
    746         RenderBlock* result = new (arena) RenderBlock(this);
    747         if (result)
    748             result->setAnimatableStyle(style);
    749         return result;
    750     }
    751     return RenderObject::createObject(this, style);
    752 }
    753 
    754 
    755 void Element::insertedIntoDocument()
    756 {
    757     // need to do superclass processing first so inDocument() is true
    758     // by the time we reach updateId
    759     ContainerNode::insertedIntoDocument();
    760 
    761     if (hasID()) {
    762         if (NamedNodeMap* attrs = namedAttrMap.get()) {
    763             Attribute* idItem = attrs->getAttributeItem(idAttributeName());
    764             if (idItem && !idItem->isNull())
    765                 updateId(nullAtom, idItem->value());
    766         }
    767     }
    768 }
    769 
    770 void Element::removedFromDocument()
    771 {
    772     if (hasID()) {
    773         if (NamedNodeMap* attrs = namedAttrMap.get()) {
    774             Attribute* idItem = attrs->getAttributeItem(idAttributeName());
    775             if (idItem && !idItem->isNull())
    776                 updateId(idItem->value(), nullAtom);
    777         }
    778     }
    779 
    780     ContainerNode::removedFromDocument();
    781 }
    782 
    783 void Element::attach()
    784 {
    785     suspendPostAttachCallbacks();
    786     RenderWidget::suspendWidgetHierarchyUpdates();
    787 
    788     createRendererIfNeeded();
    789     ContainerNode::attach();
    790     if (hasRareData()) {
    791         ElementRareData* data = rareData();
    792         if (data->needsFocusAppearanceUpdateSoonAfterAttach()) {
    793             if (isFocusable() && document()->focusedNode() == this)
    794                 document()->updateFocusAppearanceSoon(false /* don't restore selection */);
    795             data->setNeedsFocusAppearanceUpdateSoonAfterAttach(false);
    796         }
    797     }
    798 
    799     RenderWidget::resumeWidgetHierarchyUpdates();
    800     resumePostAttachCallbacks();
    801 }
    802 
    803 void Element::detach()
    804 {
    805     RenderWidget::suspendWidgetHierarchyUpdates();
    806 
    807     cancelFocusAppearanceUpdate();
    808     if (hasRareData())
    809         rareData()->resetComputedStyle();
    810     ContainerNode::detach();
    811 
    812     RenderWidget::resumeWidgetHierarchyUpdates();
    813 }
    814 
    815 bool Element::pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle)
    816 {
    817     ASSERT(currentStyle == renderStyle());
    818 
    819     if (!renderer() || !currentStyle)
    820         return false;
    821 
    822     RenderStyle::PseudoStyleCache pseudoStyleCache;
    823     currentStyle->getPseudoStyleCache(pseudoStyleCache);
    824     size_t cacheSize = pseudoStyleCache.size();
    825     for (size_t i = 0; i < cacheSize; ++i) {
    826         RefPtr<RenderStyle> newPseudoStyle;
    827         PseudoId pseudoId = pseudoStyleCache[i]->styleType();
    828         if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED)
    829             newPseudoStyle = renderer()->uncachedFirstLineStyle(newStyle);
    830         else
    831             newPseudoStyle = renderer()->getUncachedPseudoStyle(pseudoId, newStyle, newStyle);
    832 
    833         if (*newPseudoStyle != *pseudoStyleCache[i]) {
    834             if (pseudoId < FIRST_INTERNAL_PSEUDOID)
    835                 newStyle->setHasPseudoStyle(pseudoId);
    836             newStyle->addCachedPseudoStyle(newPseudoStyle);
    837             return true;
    838         }
    839     }
    840     return false;
    841 }
    842 
    843 void Element::recalcStyle(StyleChange change)
    844 {
    845     // Ref currentStyle in case it would otherwise be deleted when setRenderStyle() is called.
    846     RefPtr<RenderStyle> currentStyle(renderStyle());
    847     bool hasParentStyle = parentNode() ? parentNode()->renderStyle() : false;
    848     bool hasPositionalRules = needsStyleRecalc() && currentStyle && currentStyle->childrenAffectedByPositionalRules();
    849     bool hasDirectAdjacentRules = currentStyle && currentStyle->childrenAffectedByDirectAdjacentRules();
    850 
    851 #if ENABLE(SVG)
    852     if (!hasParentStyle && isShadowNode() && isSVGElement())
    853         hasParentStyle = true;
    854 #endif
    855 
    856     if ((change > NoChange || needsStyleRecalc())) {
    857         if (hasRareData())
    858             rareData()->resetComputedStyle();
    859     }
    860     if (hasParentStyle && (change >= Inherit || needsStyleRecalc())) {
    861         RefPtr<RenderStyle> newStyle = document()->styleSelector()->styleForElement(this);
    862         StyleChange ch = diff(currentStyle.get(), newStyle.get());
    863         if (ch == Detach || !currentStyle) {
    864             if (attached())
    865                 detach();
    866             attach(); // FIXME: The style gets computed twice by calling attach. We could do better if we passed the style along.
    867             // attach recalulates the style for all children. No need to do it twice.
    868             setNeedsStyleRecalc(NoStyleChange);
    869             setChildNeedsStyleRecalc(false);
    870             return;
    871         }
    872 
    873         if (currentStyle) {
    874             // Preserve "affected by" bits that were propagated to us from descendants in the case where we didn't do a full
    875             // style change (e.g., only inline style changed).
    876             if (currentStyle->affectedByHoverRules())
    877                 newStyle->setAffectedByHoverRules(true);
    878             if (currentStyle->affectedByActiveRules())
    879                 newStyle->setAffectedByActiveRules(true);
    880             if (currentStyle->affectedByDragRules())
    881                 newStyle->setAffectedByDragRules(true);
    882             if (currentStyle->childrenAffectedByForwardPositionalRules())
    883                 newStyle->setChildrenAffectedByForwardPositionalRules();
    884             if (currentStyle->childrenAffectedByBackwardPositionalRules())
    885                 newStyle->setChildrenAffectedByBackwardPositionalRules();
    886             if (currentStyle->childrenAffectedByFirstChildRules())
    887                 newStyle->setChildrenAffectedByFirstChildRules();
    888             if (currentStyle->childrenAffectedByLastChildRules())
    889                 newStyle->setChildrenAffectedByLastChildRules();
    890             if (currentStyle->childrenAffectedByDirectAdjacentRules())
    891                 newStyle->setChildrenAffectedByDirectAdjacentRules();
    892         }
    893 
    894         if (ch != NoChange || pseudoStyleCacheIsInvalid(currentStyle.get(), newStyle.get())) {
    895             setRenderStyle(newStyle);
    896         } else if (needsStyleRecalc() && (styleChangeType() != SyntheticStyleChange) && (document()->usesSiblingRules() || document()->usesDescendantRules())) {
    897             // Although no change occurred, we use the new style so that the cousin style sharing code won't get
    898             // fooled into believing this style is the same.  This is only necessary if the document actually uses
    899             // sibling/descendant rules, since otherwise it isn't possible for ancestor styles to affect sharing of
    900             // descendants.
    901             if (renderer())
    902                 renderer()->setStyleInternal(newStyle.get());
    903             else
    904                 setRenderStyle(newStyle);
    905         } else if (styleChangeType() == SyntheticStyleChange)
    906              setRenderStyle(newStyle);
    907 
    908         if (change != Force) {
    909             // 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
    910             // 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).
    911             if (document()->usesRemUnits() && ch != NoChange && currentStyle && newStyle && currentStyle->fontSize() != newStyle->fontSize() && document()->documentElement() == this)
    912                 change = Force;
    913             else if ((document()->usesDescendantRules() || hasPositionalRules) && styleChangeType() >= FullStyleChange)
    914                 change = Force;
    915             else
    916                 change = ch;
    917         }
    918     }
    919 
    920     // FIXME: This check is good enough for :hover + foo, but it is not good enough for :hover + foo + bar.
    921     // For now we will just worry about the common case, since it's a lot trickier to get the second case right
    922     // without doing way too much re-resolution.
    923     bool forceCheckOfNextElementSibling = false;
    924     for (Node *n = firstChild(); n; n = n->nextSibling()) {
    925         bool childRulesChanged = n->needsStyleRecalc() && n->styleChangeType() == FullStyleChange;
    926         if (forceCheckOfNextElementSibling && n->isElementNode())
    927             n->setNeedsStyleRecalc();
    928         if (change >= Inherit || n->isTextNode() || n->childNeedsStyleRecalc() || n->needsStyleRecalc())
    929             n->recalcStyle(change);
    930         if (n->isElementNode())
    931             forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentRules;
    932     }
    933 
    934     setNeedsStyleRecalc(NoStyleChange);
    935     setChildNeedsStyleRecalc(false);
    936 }
    937 
    938 bool Element::childTypeAllowed(NodeType type)
    939 {
    940     switch (type) {
    941         case ELEMENT_NODE:
    942         case TEXT_NODE:
    943         case COMMENT_NODE:
    944         case PROCESSING_INSTRUCTION_NODE:
    945         case CDATA_SECTION_NODE:
    946         case ENTITY_REFERENCE_NODE:
    947             return true;
    948             break;
    949         default:
    950             return false;
    951     }
    952 }
    953 
    954 static void checkForSiblingStyleChanges(Element* e, RenderStyle* style, bool finishedParsingCallback,
    955                                         Node* beforeChange, Node* afterChange, int childCountDelta)
    956 {
    957     if (!style || (e->needsStyleRecalc() && style->childrenAffectedByPositionalRules()))
    958         return;
    959 
    960     // :first-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
    961     // In the DOM case, we only need to do something if |afterChange| is not 0.
    962     // |afterChange| is 0 in the parser case, so it works out that we'll skip this block.
    963     if (style->childrenAffectedByFirstChildRules() && afterChange) {
    964         // Find our new first child.
    965         Node* newFirstChild = 0;
    966         for (newFirstChild = e->firstChild(); newFirstChild && !newFirstChild->isElementNode(); newFirstChild = newFirstChild->nextSibling()) {};
    967 
    968         // Find the first element node following |afterChange|
    969         Node* firstElementAfterInsertion = 0;
    970         for (firstElementAfterInsertion = afterChange;
    971              firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
    972              firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
    973 
    974         // This is the insert/append case.
    975         if (newFirstChild != firstElementAfterInsertion && firstElementAfterInsertion && firstElementAfterInsertion->attached() &&
    976             firstElementAfterInsertion->renderStyle() && firstElementAfterInsertion->renderStyle()->firstChildState())
    977             firstElementAfterInsertion->setNeedsStyleRecalc();
    978 
    979         // We also have to handle node removal.
    980         if (childCountDelta < 0 && newFirstChild == firstElementAfterInsertion && newFirstChild && newFirstChild->renderStyle() && !newFirstChild->renderStyle()->firstChildState())
    981             newFirstChild->setNeedsStyleRecalc();
    982     }
    983 
    984     // :last-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
    985     // In the DOM case, we only need to do something if |afterChange| is not 0.
    986     if (style->childrenAffectedByLastChildRules() && beforeChange) {
    987         // Find our new last child.
    988         Node* newLastChild = 0;
    989         for (newLastChild = e->lastChild(); newLastChild && !newLastChild->isElementNode(); newLastChild = newLastChild->previousSibling()) {};
    990 
    991         // Find the last element node going backwards from |beforeChange|
    992         Node* lastElementBeforeInsertion = 0;
    993         for (lastElementBeforeInsertion = beforeChange;
    994              lastElementBeforeInsertion && !lastElementBeforeInsertion->isElementNode();
    995              lastElementBeforeInsertion = lastElementBeforeInsertion->previousSibling()) {};
    996 
    997         if (newLastChild != lastElementBeforeInsertion && lastElementBeforeInsertion && lastElementBeforeInsertion->attached() &&
    998             lastElementBeforeInsertion->renderStyle() && lastElementBeforeInsertion->renderStyle()->lastChildState())
    999             lastElementBeforeInsertion->setNeedsStyleRecalc();
   1000 
   1001         // 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
   1002         // to match now.
   1003         if ((childCountDelta < 0 || finishedParsingCallback) && newLastChild == lastElementBeforeInsertion && newLastChild && newLastChild->renderStyle() && !newLastChild->renderStyle()->lastChildState())
   1004             newLastChild->setNeedsStyleRecalc();
   1005     }
   1006 
   1007     // The + selector.  We need to invalidate the first element following the insertion point.  It is the only possible element
   1008     // that could be affected by this DOM change.
   1009     if (style->childrenAffectedByDirectAdjacentRules() && afterChange) {
   1010         Node* firstElementAfterInsertion = 0;
   1011         for (firstElementAfterInsertion = afterChange;
   1012              firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
   1013              firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
   1014         if (firstElementAfterInsertion && firstElementAfterInsertion->attached())
   1015             firstElementAfterInsertion->setNeedsStyleRecalc();
   1016     }
   1017 
   1018     // Forward positional selectors include the ~ selector, nth-child, nth-of-type, first-of-type and only-of-type.
   1019     // Backward positional selectors include nth-last-child, nth-last-of-type, last-of-type and only-of-type.
   1020     // We have to invalidate everything following the insertion point in the forward case, and everything before the insertion point in the
   1021     // backward case.
   1022     // |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.
   1023     // 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
   1024     // here.  recalcStyle will then force a walk of the children when it sees that this has happened.
   1025     if ((style->childrenAffectedByForwardPositionalRules() && afterChange) ||
   1026         (style->childrenAffectedByBackwardPositionalRules() && beforeChange))
   1027         e->setNeedsStyleRecalc();
   1028 
   1029     // :empty selector.
   1030     if (style->affectedByEmpty() && (!style->emptyState() || e->hasChildNodes()))
   1031         e->setNeedsStyleRecalc();
   1032 }
   1033 
   1034 void Element::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
   1035 {
   1036     ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
   1037     if (!changedByParser)
   1038         checkForSiblingStyleChanges(this, renderStyle(), false, beforeChange, afterChange, childCountDelta);
   1039 }
   1040 
   1041 void Element::finishParsingChildren()
   1042 {
   1043     ContainerNode::finishParsingChildren();
   1044     m_parsingChildrenFinished = true;
   1045     checkForSiblingStyleChanges(this, renderStyle(), true, lastChild(), 0, 0);
   1046 }
   1047 
   1048 void Element::dispatchAttrRemovalEvent(Attribute*)
   1049 {
   1050     ASSERT(!eventDispatchForbidden());
   1051 
   1052 #if 0
   1053     if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER))
   1054         return;
   1055     ExceptionCode ec = 0;
   1056     dispatchEvent(new MutationEvent(DOMAttrModifiedEvent, true, false, attr, attr->value(),
   1057         attr->value(), document()->attrName(attr->id()), MutationEvent::REMOVAL), ec);
   1058 #endif
   1059 }
   1060 
   1061 void Element::dispatchAttrAdditionEvent(Attribute*)
   1062 {
   1063     ASSERT(!eventDispatchForbidden());
   1064 
   1065 #if 0
   1066     if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER))
   1067         return;
   1068     ExceptionCode ec = 0;
   1069     dispatchEvent(new MutationEvent(DOMAttrModifiedEvent, true, false, attr, attr->value(),
   1070         attr->value(), document()->attrName(attr->id()), MutationEvent::ADDITION), ec);
   1071 #endif
   1072 }
   1073 
   1074 String Element::openTagStartToString() const
   1075 {
   1076     String result = "<" + nodeName();
   1077 
   1078     NamedNodeMap* attrMap = attributes(true);
   1079 
   1080     if (attrMap) {
   1081         unsigned numAttrs = attrMap->length();
   1082         for (unsigned i = 0; i < numAttrs; i++) {
   1083             result += " ";
   1084 
   1085             Attribute *attribute = attrMap->attributeItem(i);
   1086             result += attribute->name().toString();
   1087             if (!attribute->value().isNull()) {
   1088                 result += "=\"";
   1089                 // FIXME: substitute entities for any instances of " or '
   1090                 result += attribute->value();
   1091                 result += "\"";
   1092             }
   1093         }
   1094     }
   1095 
   1096     return result;
   1097 }
   1098 
   1099 #ifndef NDEBUG
   1100 void Element::formatForDebugger(char* buffer, unsigned length) const
   1101 {
   1102     String result;
   1103     String s;
   1104 
   1105     s = nodeName();
   1106     if (s.length() > 0) {
   1107         result += s;
   1108     }
   1109 
   1110     s = getAttribute(idAttributeName());
   1111     if (s.length() > 0) {
   1112         if (result.length() > 0)
   1113             result += "; ";
   1114         result += "id=";
   1115         result += s;
   1116     }
   1117 
   1118     s = getAttribute(classAttr);
   1119     if (s.length() > 0) {
   1120         if (result.length() > 0)
   1121             result += "; ";
   1122         result += "class=";
   1123         result += s;
   1124     }
   1125 
   1126     strncpy(buffer, result.utf8().data(), length - 1);
   1127 }
   1128 #endif
   1129 
   1130 PassRefPtr<Attr> Element::setAttributeNode(Attr* attr, ExceptionCode& ec)
   1131 {
   1132     if (!attr) {
   1133         ec = TYPE_MISMATCH_ERR;
   1134         return 0;
   1135     }
   1136     return static_pointer_cast<Attr>(attributes(false)->setNamedItem(attr, ec));
   1137 }
   1138 
   1139 PassRefPtr<Attr> Element::setAttributeNodeNS(Attr* attr, ExceptionCode& ec)
   1140 {
   1141     if (!attr) {
   1142         ec = TYPE_MISMATCH_ERR;
   1143         return 0;
   1144     }
   1145     return static_pointer_cast<Attr>(attributes(false)->setNamedItem(attr, ec));
   1146 }
   1147 
   1148 PassRefPtr<Attr> Element::removeAttributeNode(Attr* attr, ExceptionCode& ec)
   1149 {
   1150     if (!attr) {
   1151         ec = TYPE_MISMATCH_ERR;
   1152         return 0;
   1153     }
   1154     if (attr->ownerElement() != this) {
   1155         ec = NOT_FOUND_ERR;
   1156         return 0;
   1157     }
   1158     if (document() != attr->document()) {
   1159         ec = WRONG_DOCUMENT_ERR;
   1160         return 0;
   1161     }
   1162 
   1163     NamedNodeMap* attrs = attributes(true);
   1164     if (!attrs)
   1165         return 0;
   1166 
   1167     return static_pointer_cast<Attr>(attrs->removeNamedItem(attr->qualifiedName(), ec));
   1168 }
   1169 
   1170 void Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode& ec, FragmentScriptingPermission scriptingPermission)
   1171 {
   1172     String prefix, localName;
   1173     if (!Document::parseQualifiedName(qualifiedName, prefix, localName, ec))
   1174         return;
   1175 
   1176     QualifiedName qName(prefix, localName, namespaceURI);
   1177 
   1178     if (scriptingPermission == FragmentScriptingNotAllowed && (isEventHandlerAttribute(qName) || isAttributeToRemove(qName, value)))
   1179         return;
   1180 
   1181     setAttribute(qName, value, ec);
   1182 }
   1183 
   1184 void Element::removeAttribute(const String& name, ExceptionCode& ec)
   1185 {
   1186     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
   1187 
   1188     if (namedAttrMap) {
   1189         namedAttrMap->removeNamedItem(localName, ec);
   1190         if (ec == NOT_FOUND_ERR)
   1191             ec = 0;
   1192     }
   1193 
   1194 #if ENABLE(INSPECTOR)
   1195     if (Page* page = document()->page()) {
   1196         if (InspectorController* inspectorController = page->inspectorController())
   1197             inspectorController->didModifyDOMAttr(this);
   1198     }
   1199 #endif
   1200 
   1201 }
   1202 
   1203 void Element::removeAttributeNS(const String& namespaceURI, const String& localName, ExceptionCode& ec)
   1204 {
   1205     removeAttribute(QualifiedName(nullAtom, localName, namespaceURI), ec);
   1206 }
   1207 
   1208 PassRefPtr<Attr> Element::getAttributeNode(const String& name)
   1209 {
   1210     NamedNodeMap* attrs = attributes(true);
   1211     if (!attrs)
   1212         return 0;
   1213     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
   1214     return static_pointer_cast<Attr>(attrs->getNamedItem(localName));
   1215 }
   1216 
   1217 PassRefPtr<Attr> Element::getAttributeNodeNS(const String& namespaceURI, const String& localName)
   1218 {
   1219     NamedNodeMap* attrs = attributes(true);
   1220     if (!attrs)
   1221         return 0;
   1222     return static_pointer_cast<Attr>(attrs->getNamedItem(QualifiedName(nullAtom, localName, namespaceURI)));
   1223 }
   1224 
   1225 bool Element::hasAttribute(const String& name) const
   1226 {
   1227     NamedNodeMap* attrs = attributes(true);
   1228     if (!attrs)
   1229         return false;
   1230 
   1231     // This call to String::lower() seems to be required but
   1232     // there may be a way to remove it.
   1233     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
   1234     return attrs->getAttributeItem(localName, false);
   1235 }
   1236 
   1237 bool Element::hasAttributeNS(const String& namespaceURI, const String& localName) const
   1238 {
   1239     NamedNodeMap* attrs = attributes(true);
   1240     if (!attrs)
   1241         return false;
   1242     return attrs->getAttributeItem(QualifiedName(nullAtom, localName, namespaceURI));
   1243 }
   1244 
   1245 CSSStyleDeclaration *Element::style()
   1246 {
   1247     return 0;
   1248 }
   1249 
   1250 void Element::focus(bool restorePreviousSelection)
   1251 {
   1252     Document* doc = document();
   1253     if (doc->focusedNode() == this)
   1254         return;
   1255 
   1256     if (!supportsFocus())
   1257         return;
   1258 
   1259     // If the stylesheets have already been loaded we can reliably check isFocusable.
   1260     // If not, we continue and set the focused node on the focus controller below so
   1261     // that it can be updated soon after attach.
   1262     if (doc->haveStylesheetsLoaded()) {
   1263         doc->updateLayoutIgnorePendingStylesheets();
   1264         if (!isFocusable())
   1265             return;
   1266     }
   1267 
   1268     RefPtr<Node> protect;
   1269     if (Page* page = doc->page()) {
   1270         // Focus and change event handlers can cause us to lose our last ref.
   1271         protect = this;
   1272         page->focusController()->setFocusedNode(this, doc->frame());
   1273     }
   1274 
   1275     // Setting the focused node above might have invalidated the layout due to scripts.
   1276     doc->updateLayoutIgnorePendingStylesheets();
   1277 
   1278     if (!isFocusable()) {
   1279         ensureRareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(true);
   1280         return;
   1281     }
   1282 
   1283     cancelFocusAppearanceUpdate();
   1284     updateFocusAppearance(restorePreviousSelection);
   1285 }
   1286 
   1287 void Element::updateFocusAppearance(bool /*restorePreviousSelection*/)
   1288 {
   1289     if (this == rootEditableElement()) {
   1290         Frame* frame = document()->frame();
   1291         if (!frame)
   1292             return;
   1293 
   1294         // FIXME: We should restore the previous selection if there is one.
   1295         VisibleSelection newSelection = hasTagName(htmlTag) || hasTagName(bodyTag) ? VisibleSelection(Position(this, 0), DOWNSTREAM) : VisibleSelection::selectionFromContentsOfNode(this);
   1296 
   1297         if (frame->shouldChangeSelection(newSelection)) {
   1298             frame->selection()->setSelection(newSelection);
   1299             frame->revealSelection();
   1300         }
   1301     }
   1302     // FIXME: I'm not sure all devices will want this off, but this is
   1303     // currently turned off for Android.
   1304 #if !ENABLE(DIRECTIONAL_PAD_NAVIGATION)
   1305     else if (renderer() && !renderer()->isWidget())
   1306         renderer()->enclosingLayer()->scrollRectToVisible(getRect());
   1307 #endif
   1308 }
   1309 
   1310 void Element::blur()
   1311 {
   1312     cancelFocusAppearanceUpdate();
   1313     Document* doc = document();
   1314     if (doc->focusedNode() == this) {
   1315         if (doc->frame())
   1316             doc->frame()->page()->focusController()->setFocusedNode(0, doc->frame());
   1317         else
   1318             doc->setFocusedNode(0);
   1319     }
   1320 }
   1321 
   1322 String Element::innerText() const
   1323 {
   1324     // We need to update layout, since plainText uses line boxes in the render tree.
   1325     document()->updateLayoutIgnorePendingStylesheets();
   1326 
   1327     if (!renderer())
   1328         return textContent(true);
   1329 
   1330     return plainText(rangeOfContents(const_cast<Element*>(this)).get());
   1331 }
   1332 
   1333 String Element::outerText() const
   1334 {
   1335     // Getting outerText is the same as getting innerText, only
   1336     // setting is different. You would think this should get the plain
   1337     // text for the outer range, but this is wrong, <br> for instance
   1338     // would return different values for inner and outer text by such
   1339     // a rule, but it doesn't in WinIE, and we want to match that.
   1340     return innerText();
   1341 }
   1342 
   1343 String Element::title() const
   1344 {
   1345     return String();
   1346 }
   1347 
   1348 IntSize Element::minimumSizeForResizing() const
   1349 {
   1350     return hasRareData() ? rareData()->m_minimumSizeForResizing : defaultMinimumSizeForResizing();
   1351 }
   1352 
   1353 void Element::setMinimumSizeForResizing(const IntSize& size)
   1354 {
   1355     if (size == defaultMinimumSizeForResizing() && !hasRareData())
   1356         return;
   1357     ensureRareData()->m_minimumSizeForResizing = size;
   1358 }
   1359 
   1360 RenderStyle* Element::computedStyle()
   1361 {
   1362     if (RenderStyle* usedStyle = renderStyle())
   1363         return usedStyle;
   1364 
   1365     if (!attached())
   1366         // FIXME: Try to do better than this. Ensure that styleForElement() works for elements that are not in the
   1367         // document tree and figure out when to destroy the computed style for such elements.
   1368         return 0;
   1369 
   1370     ElementRareData* data = ensureRareData();
   1371     if (!data->m_computedStyle)
   1372         data->m_computedStyle = document()->styleSelector()->styleForElement(this, parent() ? parent()->computedStyle() : 0);
   1373     return data->m_computedStyle.get();
   1374 }
   1375 
   1376 void Element::cancelFocusAppearanceUpdate()
   1377 {
   1378     if (hasRareData())
   1379         rareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(false);
   1380     if (document()->focusedNode() == this)
   1381         document()->cancelFocusAppearanceUpdate();
   1382 }
   1383 
   1384 void Element::normalizeAttributes()
   1385 {
   1386     // Normalize attributes.
   1387     NamedNodeMap* attrs = attributes(true);
   1388     if (!attrs)
   1389         return;
   1390     unsigned numAttrs = attrs->length();
   1391     for (unsigned i = 0; i < numAttrs; i++) {
   1392         if (Attr* attr = attrs->attributeItem(i)->attr())
   1393             attr->normalize();
   1394     }
   1395 }
   1396 
   1397 // ElementTraversal API
   1398 Element* Element::firstElementChild() const
   1399 {
   1400     Node* n = firstChild();
   1401     while (n && !n->isElementNode())
   1402         n = n->nextSibling();
   1403     return static_cast<Element*>(n);
   1404 }
   1405 
   1406 Element* Element::lastElementChild() const
   1407 {
   1408     Node* n = lastChild();
   1409     while (n && !n->isElementNode())
   1410         n = n->previousSibling();
   1411     return static_cast<Element*>(n);
   1412 }
   1413 
   1414 Element* Element::previousElementSibling() const
   1415 {
   1416     Node* n = previousSibling();
   1417     while (n && !n->isElementNode())
   1418         n = n->previousSibling();
   1419     return static_cast<Element*>(n);
   1420 }
   1421 
   1422 Element* Element::nextElementSibling() const
   1423 {
   1424     Node* n = nextSibling();
   1425     while (n && !n->isElementNode())
   1426         n = n->nextSibling();
   1427     return static_cast<Element*>(n);
   1428 }
   1429 
   1430 unsigned Element::childElementCount() const
   1431 {
   1432     unsigned count = 0;
   1433     Node* n = firstChild();
   1434     while (n) {
   1435         count += n->isElementNode();
   1436         n = n->nextSibling();
   1437     }
   1438     return count;
   1439 }
   1440 
   1441 bool Element::webkitMatchesSelector(const String& selector, ExceptionCode& ec)
   1442 {
   1443     if (selector.isEmpty()) {
   1444         ec = SYNTAX_ERR;
   1445         return false;
   1446     }
   1447 
   1448     bool strictParsing = !document()->inCompatMode();
   1449     CSSParser p(strictParsing);
   1450 
   1451     CSSSelectorList selectorList;
   1452     p.parseSelector(selector, document(), selectorList);
   1453 
   1454     if (!selectorList.first()) {
   1455         ec = SYNTAX_ERR;
   1456         return false;
   1457     }
   1458 
   1459     // Throw a NAMESPACE_ERR if the selector includes any namespace prefixes.
   1460     if (selectorList.selectorsNeedNamespaceResolution()) {
   1461         ec = NAMESPACE_ERR;
   1462         return false;
   1463     }
   1464 
   1465     CSSStyleSelector::SelectorChecker selectorChecker(document(), strictParsing);
   1466     for (CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
   1467         if (selectorChecker.checkSelector(selector, this))
   1468             return true;
   1469     }
   1470 
   1471     return false;
   1472 }
   1473 
   1474 KURL Element::getURLAttribute(const QualifiedName& name) const
   1475 {
   1476 #if !ASSERT_DISABLED
   1477     if (namedAttrMap) {
   1478         if (Attribute* attribute = namedAttrMap->getAttributeItem(name))
   1479             ASSERT(isURLAttribute(attribute));
   1480     }
   1481 #endif
   1482     return document()->completeURL(deprecatedParseURL(getAttribute(name)));
   1483 }
   1484 
   1485 const QualifiedName& Element::rareIDAttributeName() const
   1486 {
   1487     return rareData()->m_idAttributeName;
   1488 }
   1489 
   1490 } // namespace WebCore
   1491