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