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