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 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013 Apple Inc. All rights reserved. 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Library General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Library General Public License for more details. 17 * 18 * You should have received a copy of the GNU Library General Public License 19 * along with this library; see the file COPYING.LIB. If not, write to 20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 * Boston, MA 02110-1301, USA. 22 * 23 */ 24 25 #ifndef Element_h 26 #define Element_h 27 28 #include "core/CSSPropertyNames.h" 29 #include "core/HTMLNames.h" 30 #include "core/css/CSSPrimitiveValue.h" 31 #include "core/dom/Attribute.h" 32 #include "core/dom/ContainerNode.h" 33 #include "core/dom/ElementData.h" 34 #include "core/dom/SpaceSplitString.h" 35 #include "core/html/CollectionType.h" 36 #include "core/page/FocusType.h" 37 #include "platform/heap/Handle.h" 38 #include "platform/scroll/ScrollTypes.h" 39 40 namespace WebCore { 41 42 class ActiveAnimations; 43 class Attr; 44 class Attribute; 45 class CSSStyleDeclaration; 46 class ClientRect; 47 class ClientRectList; 48 class CustomElementDefinition; 49 class DOMStringMap; 50 class DOMTokenList; 51 class Document; 52 class ElementRareData; 53 class ElementShadow; 54 class ExceptionState; 55 class Image; 56 class InputMethodContext; 57 class IntSize; 58 class Locale; 59 class MutableStylePropertySet; 60 class PropertySetCSSStyleDeclaration; 61 class PseudoElement; 62 class ShadowRoot; 63 class StylePropertySet; 64 65 enum AffectedSelectorType { 66 AffectedSelectorChecked = 1, 67 AffectedSelectorEnabled = 1 << 1, 68 AffectedSelectorDisabled = 1 << 2, 69 AffectedSelectorIndeterminate = 1 << 3, 70 AffectedSelectorLink = 1 << 4, 71 AffectedSelectorTarget = 1 << 5, 72 AffectedSelectorVisited = 1 << 6 73 }; 74 typedef int AffectedSelectorMask; 75 76 enum SpellcheckAttributeState { 77 SpellcheckAttributeTrue, 78 SpellcheckAttributeFalse, 79 SpellcheckAttributeDefault 80 }; 81 82 enum ElementFlags { 83 TabIndexWasSetExplicitly = 1 << 0, 84 StyleAffectedByEmpty = 1 << 1, 85 IsInCanvasSubtree = 1 << 2, 86 ContainsFullScreenElement = 1 << 3, 87 IsInTopLayer = 1 << 4, 88 HasPendingResources = 1 << 5, 89 90 NumberOfElementFlags = 6, // Required size of bitfield used to store the flags. 91 }; 92 93 class Element : public ContainerNode { 94 public: 95 static PassRefPtrWillBeRawPtr<Element> create(const QualifiedName&, Document*); 96 virtual ~Element(); 97 98 DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecopy); 99 DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut); 100 DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste); 101 DEFINE_ATTRIBUTE_EVENT_LISTENER(copy); 102 DEFINE_ATTRIBUTE_EVENT_LISTENER(cut); 103 DEFINE_ATTRIBUTE_EVENT_LISTENER(paste); 104 DEFINE_ATTRIBUTE_EVENT_LISTENER(search); 105 DEFINE_ATTRIBUTE_EVENT_LISTENER(selectstart); 106 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel); 107 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend); 108 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove); 109 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart); 110 DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenchange); 111 DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenerror); 112 DEFINE_ATTRIBUTE_EVENT_LISTENER(wheel); 113 114 bool hasAttribute(const QualifiedName&) const; 115 const AtomicString& getAttribute(const QualifiedName&) const; 116 117 // Passing nullAtom as the second parameter removes the attribute when calling either of these set methods. 118 void setAttribute(const QualifiedName&, const AtomicString& value); 119 void setSynchronizedLazyAttribute(const QualifiedName&, const AtomicString& value); 120 121 void removeAttribute(const QualifiedName&); 122 123 // Typed getters and setters for language bindings. 124 int getIntegralAttribute(const QualifiedName& attributeName) const; 125 void setIntegralAttribute(const QualifiedName& attributeName, int value); 126 unsigned getUnsignedIntegralAttribute(const QualifiedName& attributeName) const; 127 void setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value); 128 double getFloatingPointAttribute(const QualifiedName& attributeName, double fallbackValue = std::numeric_limits<double>::quiet_NaN()) const; 129 void setFloatingPointAttribute(const QualifiedName& attributeName, double value); 130 131 // Call this to get the value of an attribute that is known not to be the style 132 // attribute or one of the SVG animatable attributes. 133 bool fastHasAttribute(const QualifiedName&) const; 134 const AtomicString& fastGetAttribute(const QualifiedName&) const; 135 #ifndef NDEBUG 136 bool fastAttributeLookupAllowed(const QualifiedName&) const; 137 #endif 138 139 #ifdef DUMP_NODE_STATISTICS 140 bool hasNamedNodeMap() const; 141 #endif 142 bool hasAttributes() const; 143 // This variant will not update the potentially invalid attributes. To be used when not interested 144 // in style attribute or one of the SVG animation attributes. 145 bool hasAttributesWithoutUpdate() const; 146 147 bool hasAttribute(const AtomicString& name) const; 148 bool hasAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const; 149 150 const AtomicString& getAttribute(const AtomicString& name) const; 151 const AtomicString& getAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const; 152 153 void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionState&); 154 static bool parseAttributeName(QualifiedName&, const AtomicString& namespaceURI, const AtomicString& qualifiedName, ExceptionState&); 155 void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionState&); 156 157 bool isIdAttributeName(const QualifiedName&) const; 158 const AtomicString& getIdAttribute() const; 159 void setIdAttribute(const AtomicString&); 160 161 const AtomicString& getNameAttribute() const; 162 const AtomicString& getClassAttribute() const; 163 164 bool shouldIgnoreAttributeCase() const; 165 166 // Call this to get the value of the id attribute for style resolution purposes. 167 // The value will already be lowercased if the document is in compatibility mode, 168 // so this function is not suitable for non-style uses. 169 const AtomicString& idForStyleResolution() const; 170 171 // Internal methods that assume the existence of attribute storage, one should use hasAttributes() 172 // before calling them. This is not a trivial getter and its return value should be cached for 173 // performance. 174 AttributeCollection attributes() const { return elementData()->attributes(); } 175 size_t attributeCount() const; 176 const Attribute& attributeAt(unsigned index) const; 177 const Attribute* findAttributeByName(const QualifiedName&) const; 178 size_t findAttributeIndexByName(const QualifiedName& name) const { return elementData()->findAttributeIndexByName(name); } 179 size_t findAttributeIndexByName(const AtomicString& name, bool shouldIgnoreAttributeCase) const { return elementData()->findAttributeIndexByName(name, shouldIgnoreAttributeCase); } 180 181 void scrollIntoView(bool alignToTop = true); 182 void scrollIntoViewIfNeeded(bool centerIfNeeded = true); 183 184 void scrollByLines(int lines); 185 void scrollByPages(int pages); 186 187 int offsetLeft(); 188 int offsetTop(); 189 int offsetWidth(); 190 int offsetHeight(); 191 192 // FIXME: Replace uses of offsetParent in the platform with calls 193 // to the render layer and merge offsetParentForBindings and offsetParent. 194 Element* offsetParentForBindings(); 195 196 Element* offsetParent(); 197 int clientLeft(); 198 int clientTop(); 199 int clientWidth(); 200 int clientHeight(); 201 virtual int scrollLeft(); 202 virtual int scrollTop(); 203 virtual void setScrollLeft(int); 204 virtual void setScrollLeft(const Dictionary& scrollOptionsHorizontal, ExceptionState&); 205 virtual void setScrollTop(int); 206 virtual void setScrollTop(const Dictionary& scrollOptionsVertical, ExceptionState&); 207 virtual int scrollWidth(); 208 virtual int scrollHeight(); 209 210 IntRect boundsInRootViewSpace(); 211 212 PassRefPtrWillBeRawPtr<ClientRectList> getClientRects(); 213 PassRefPtrWillBeRawPtr<ClientRect> getBoundingClientRect(); 214 215 // Returns the absolute bounding box translated into screen coordinates: 216 IntRect screenRect() const; 217 218 virtual void didMoveToNewDocument(Document&) OVERRIDE; 219 220 void removeAttribute(const AtomicString& name); 221 void removeAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName); 222 223 PassRefPtrWillBeRawPtr<Attr> detachAttribute(size_t index); 224 225 PassRefPtrWillBeRawPtr<Attr> getAttributeNode(const AtomicString& name); 226 PassRefPtrWillBeRawPtr<Attr> getAttributeNodeNS(const AtomicString& namespaceURI, const AtomicString& localName); 227 PassRefPtrWillBeRawPtr<Attr> setAttributeNode(Attr*, ExceptionState&); 228 PassRefPtrWillBeRawPtr<Attr> setAttributeNodeNS(Attr*, ExceptionState&); 229 PassRefPtrWillBeRawPtr<Attr> removeAttributeNode(Attr*, ExceptionState&); 230 231 PassRefPtrWillBeRawPtr<Attr> attrIfExists(const QualifiedName&); 232 PassRefPtrWillBeRawPtr<Attr> ensureAttr(const QualifiedName&); 233 234 WillBeHeapVector<RefPtrWillBeMember<Attr> >* attrNodeList(); 235 236 CSSStyleDeclaration* style(); 237 238 const QualifiedName& tagQName() const { return m_tagName; } 239 String tagName() const { return nodeName(); } 240 bool hasTagName(const QualifiedName& tagName) const { return m_tagName.matches(tagName); } 241 242 // Should be called only by Document::createElementNS to fix up m_tagName immediately after construction. 243 void setTagNameForCreateElementNS(const QualifiedName&); 244 245 // A fast function for checking the local name against another atomic string. 246 bool hasLocalName(const AtomicString& other) const { return m_tagName.localName() == other; } 247 bool hasLocalName(const QualifiedName& other) const { return m_tagName.localName() == other.localName(); } 248 249 virtual const AtomicString& localName() const OVERRIDE FINAL { return m_tagName.localName(); } 250 const AtomicString& prefix() const { return m_tagName.prefix(); } 251 virtual const AtomicString& namespaceURI() const OVERRIDE FINAL { return m_tagName.namespaceURI(); } 252 253 const AtomicString& locateNamespacePrefix(const AtomicString& namespaceURI) const; 254 255 virtual KURL baseURI() const OVERRIDE FINAL; 256 257 virtual String nodeName() const OVERRIDE; 258 259 PassRefPtrWillBeRawPtr<Element> cloneElementWithChildren(); 260 PassRefPtrWillBeRawPtr<Element> cloneElementWithoutChildren(); 261 262 void scheduleSVGFilterLayerUpdateHack(); 263 264 void normalizeAttributes(); 265 266 void setBooleanAttribute(const QualifiedName& name, bool); 267 268 virtual const StylePropertySet* additionalPresentationAttributeStyle() { return 0; } 269 void invalidateStyleAttribute(); 270 271 const StylePropertySet* inlineStyle() const { return elementData() ? elementData()->m_inlineStyle.get() : 0; } 272 273 bool setInlineStyleProperty(CSSPropertyID, CSSValueID identifier, bool important = false); 274 bool setInlineStyleProperty(CSSPropertyID, double value, CSSPrimitiveValue::UnitType, bool important = false); 275 bool setInlineStyleProperty(CSSPropertyID, const String& value, bool important = false); 276 bool removeInlineStyleProperty(CSSPropertyID); 277 void removeAllInlineStyleProperties(); 278 279 void synchronizeStyleAttributeInternal() const; 280 281 const StylePropertySet* presentationAttributeStyle(); 282 virtual bool isPresentationAttribute(const QualifiedName&) const { return false; } 283 virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) { } 284 285 // For exposing to DOM only. 286 NamedNodeMap* attributesForBindings() const; 287 288 enum AttributeModificationReason { 289 ModifiedDirectly, 290 ModifiedByCloning 291 }; 292 293 // This method is called whenever an attribute is added, changed or removed. 294 virtual void attributeChanged(const QualifiedName&, const AtomicString&, AttributeModificationReason = ModifiedDirectly); 295 virtual void parseAttribute(const QualifiedName&, const AtomicString&); 296 297 virtual bool hasLegalLinkAttribute(const QualifiedName&) const; 298 virtual const QualifiedName& subResourceAttributeName() const; 299 300 // Only called by the parser immediately after element construction. 301 void parserSetAttributes(const Vector<Attribute>&); 302 303 // Remove attributes that might introduce scripting from the vector leaving the element unchanged. 304 void stripScriptingAttributes(Vector<Attribute>&) const; 305 306 const ElementData* elementData() const { return m_elementData.get(); } 307 UniqueElementData& ensureUniqueElementData(); 308 309 void synchronizeAllAttributes() const; 310 311 // Clones attributes only. 312 void cloneAttributesFromElement(const Element&); 313 314 // Clones all attribute-derived data, including subclass specifics (through copyNonAttributeProperties.) 315 void cloneDataFromElement(const Element&); 316 317 bool hasEquivalentAttributes(const Element* other) const; 318 319 virtual void copyNonAttributePropertiesFromElement(const Element&) { } 320 321 virtual void attach(const AttachContext& = AttachContext()) OVERRIDE; 322 virtual void detach(const AttachContext& = AttachContext()) OVERRIDE; 323 virtual RenderObject* createRenderer(RenderStyle*); 324 virtual bool rendererIsNeeded(const RenderStyle&); 325 void recalcStyle(StyleRecalcChange, Text* nextTextSibling = 0); 326 void didAffectSelector(AffectedSelectorMask); 327 void setAnimationStyleChange(bool); 328 void setNeedsAnimationStyleRecalc(); 329 330 void setNeedsCompositingUpdate(); 331 332 bool supportsStyleSharing() const; 333 334 ElementShadow* shadow() const; 335 ElementShadow& ensureShadow(); 336 PassRefPtrWillBeRawPtr<ShadowRoot> createShadowRoot(ExceptionState&); 337 ShadowRoot* shadowRoot() const; 338 ShadowRoot* youngestShadowRoot() const; 339 340 bool hasAuthorShadowRoot() const { return shadowRoot(); } 341 ShadowRoot* userAgentShadowRoot() const; 342 ShadowRoot& ensureUserAgentShadowRoot(); 343 virtual void willAddFirstAuthorShadowRoot() { } 344 345 bool isInDescendantTreeOf(const Element* shadowHost) const; 346 347 RenderStyle* computedStyle(PseudoId = NOPSEUDO); 348 349 // Methods for indicating the style is affected by dynamic updates (e.g., children changing, our position changing in our sibling list, etc.) 350 bool styleAffectedByEmpty() const { return hasElementFlag(StyleAffectedByEmpty); } 351 void setStyleAffectedByEmpty() { setElementFlag(StyleAffectedByEmpty); } 352 353 void setIsInCanvasSubtree(bool value) { setElementFlag(IsInCanvasSubtree, value); } 354 bool isInCanvasSubtree() const { return hasElementFlag(IsInCanvasSubtree); } 355 356 bool isUpgradedCustomElement() { return customElementState() == Upgraded; } 357 bool isUnresolvedCustomElement() { return customElementState() == WaitingForUpgrade; } 358 359 AtomicString computeInheritedLanguage() const; 360 Locale& locale() const; 361 362 virtual void accessKeyAction(bool /*sendToAnyEvent*/) { } 363 364 virtual bool isURLAttribute(const Attribute&) const { return false; } 365 virtual bool isHTMLContentAttribute(const Attribute&) const { return false; } 366 367 KURL getURLAttribute(const QualifiedName&) const; 368 KURL getNonEmptyURLAttribute(const QualifiedName&) const; 369 370 virtual const AtomicString imageSourceURL() const; 371 virtual Image* imageContents() { return 0; } 372 373 virtual void focus(bool restorePreviousSelection = true, FocusType = FocusTypeNone); 374 virtual void updateFocusAppearance(bool restorePreviousSelection); 375 virtual void blur(); 376 // Whether this element can receive focus at all. Most elements are not 377 // focusable but some elements, such as form controls and links, are. Unlike 378 // rendererIsFocusable(), this method may be called when layout is not up to 379 // date, so it must not use the renderer to determine focusability. 380 virtual bool supportsFocus() const; 381 // Whether the node can actually be focused. 382 bool isFocusable() const; 383 virtual bool isKeyboardFocusable() const; 384 virtual bool isMouseFocusable() const; 385 virtual void dispatchFocusEvent(Element* oldFocusedElement, FocusType); 386 virtual void dispatchBlurEvent(Element* newFocusedElement); 387 void dispatchFocusInEvent(const AtomicString& eventType, Element* oldFocusedElement); 388 void dispatchFocusOutEvent(const AtomicString& eventType, Element* newFocusedElement); 389 390 String innerText(); 391 String outerText(); 392 String innerHTML() const; 393 String outerHTML() const; 394 void setInnerHTML(const String&, ExceptionState&); 395 void setOuterHTML(const String&, ExceptionState&); 396 397 Element* insertAdjacentElement(const String& where, Element* newChild, ExceptionState&); 398 void insertAdjacentText(const String& where, const String& text, ExceptionState&); 399 void insertAdjacentHTML(const String& where, const String& html, ExceptionState&); 400 401 String textFromChildren(); 402 403 virtual String title() const { return String(); } 404 405 virtual const AtomicString& shadowPseudoId() const; 406 void setShadowPseudoId(const AtomicString&); 407 408 LayoutSize minimumSizeForResizing() const; 409 void setMinimumSizeForResizing(const LayoutSize&); 410 411 virtual void didBecomeFullscreenElement() { } 412 virtual void willStopBeingFullscreenElement() { } 413 414 // Called by the parser when this element's close tag is reached, 415 // signaling that all child tags have been parsed and added. 416 // This is needed for <applet> and <object> elements, which can't lay themselves out 417 // until they know all of their nested <param>s. [Radar 3603191, 4040848]. 418 // Also used for script elements and some SVG elements for similar purposes, 419 // but making parsing a special case in this respect should be avoided if possible. 420 virtual void finishParsingChildren(); 421 422 void beginParsingChildren() { setIsFinishedParsingChildren(false); } 423 424 PseudoElement* pseudoElement(PseudoId) const; 425 RenderObject* pseudoElementRenderer(PseudoId) const; 426 427 virtual bool matchesReadOnlyPseudoClass() const { return false; } 428 virtual bool matchesReadWritePseudoClass() const { return false; } 429 bool matches(const String& selectors, ExceptionState&); 430 virtual bool shouldAppearIndeterminate() const { return false; } 431 432 DOMTokenList& classList(); 433 434 DOMStringMap& dataset(); 435 436 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI) 437 virtual bool isDateTimeEditElement() const { return false; } 438 virtual bool isDateTimeFieldElement() const { return false; } 439 virtual bool isPickerIndicatorElement() const { return false; } 440 #endif 441 442 virtual bool isFormControlElement() const { return false; } 443 virtual bool isSpinButtonElement() const { return false; } 444 virtual bool isTextFormControl() const { return false; } 445 virtual bool isOptionalFormControl() const { return false; } 446 virtual bool isRequiredFormControl() const { return false; } 447 virtual bool isDefaultButtonForForm() const { return false; } 448 virtual bool willValidate() const { return false; } 449 virtual bool isValidFormControlElement() { return false; } 450 virtual bool isInRange() const { return false; } 451 virtual bool isOutOfRange() const { return false; } 452 virtual bool isClearButtonElement() const { return false; } 453 454 virtual bool canContainRangeEndPoint() const OVERRIDE { return true; } 455 456 // Used for disabled form elements; if true, prevents mouse events from being dispatched 457 // to event listeners, and prevents DOMActivate events from being sent at all. 458 virtual bool isDisabledFormControl() const { return false; } 459 460 bool hasPendingResources() const { return hasElementFlag(HasPendingResources); } 461 void setHasPendingResources() { setElementFlag(HasPendingResources); } 462 void clearHasPendingResources() { clearElementFlag(HasPendingResources); } 463 virtual void buildPendingResource() { }; 464 465 void setCustomElementDefinition(PassRefPtr<CustomElementDefinition>); 466 CustomElementDefinition* customElementDefinition() const; 467 468 enum { 469 ALLOW_KEYBOARD_INPUT = 1 << 0, 470 LEGACY_MOZILLA_REQUEST = 1 << 1, 471 }; 472 473 void webkitRequestFullScreen(unsigned short flags); 474 bool containsFullScreenElement() const { return hasElementFlag(ContainsFullScreenElement); } 475 void setContainsFullScreenElement(bool); 476 void setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(bool); 477 478 // W3C API 479 void webkitRequestFullscreen(); 480 481 bool isInTopLayer() const { return hasElementFlag(IsInTopLayer); } 482 void setIsInTopLayer(bool); 483 484 void webkitRequestPointerLock(); 485 void requestPointerLock(); 486 487 bool isSpellCheckingEnabled() const; 488 489 // FIXME: public for RenderTreeBuilder, we shouldn't expose this though. 490 PassRefPtr<RenderStyle> styleForRenderer(); 491 492 bool hasID() const; 493 bool hasClass() const; 494 const SpaceSplitString& classNames() const; 495 496 IntSize savedLayerScrollOffset() const; 497 void setSavedLayerScrollOffset(const IntSize&); 498 499 ActiveAnimations* activeAnimations() const; 500 ActiveAnimations& ensureActiveAnimations(); 501 bool hasActiveAnimations() const; 502 503 InputMethodContext& inputMethodContext(); 504 bool hasInputMethodContext() const; 505 506 void setPrefix(const AtomicString&, ExceptionState&); 507 508 void synchronizeAttribute(const AtomicString& localName) const; 509 510 MutableStylePropertySet& ensureMutableInlineStyle(); 511 void clearMutableInlineStyleIfEmpty(); 512 513 void setTabIndex(int); 514 virtual short tabIndex() const OVERRIDE; 515 516 virtual void trace(Visitor*) OVERRIDE; 517 518 protected: 519 Element(const QualifiedName& tagName, Document*, ConstructionType); 520 521 void addPropertyToPresentationAttributeStyle(MutableStylePropertySet*, CSSPropertyID, CSSValueID identifier); 522 void addPropertyToPresentationAttributeStyle(MutableStylePropertySet*, CSSPropertyID, double value, CSSPrimitiveValue::UnitType); 523 void addPropertyToPresentationAttributeStyle(MutableStylePropertySet*, CSSPropertyID, const String& value); 524 525 virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; 526 virtual void removedFrom(ContainerNode*) OVERRIDE; 527 virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0) OVERRIDE; 528 529 virtual void willRecalcStyle(StyleRecalcChange); 530 virtual void didRecalcStyle(StyleRecalcChange); 531 virtual PassRefPtr<RenderStyle> customStyleForRenderer(); 532 533 virtual bool shouldRegisterAsNamedItem() const { return false; } 534 virtual bool shouldRegisterAsExtraNamedItem() const { return false; } 535 536 virtual bool supportsSpatialNavigationFocus() const; 537 538 void clearTabIndexExplicitlyIfNeeded(); 539 void setTabIndexExplicitly(short); 540 // Subclasses may override this method to affect focusability. Unlike 541 // supportsFocus, this method must be called on an up-to-date layout, so it 542 // may use the renderer to reason about focusability. This method cannot be 543 // moved to RenderObject because some focusable nodes don't have renderers, 544 // e.g., HTMLOptionElement. 545 virtual bool rendererIsFocusable() const; 546 PassRefPtrWillBeRawPtr<HTMLCollection> ensureCachedHTMLCollection(CollectionType); 547 HTMLCollection* cachedHTMLCollection(CollectionType); 548 549 // classAttributeChanged() exists to share code between 550 // parseAttribute (called via setAttribute()) and 551 // svgAttributeChanged (called when element.className.baseValue is set) 552 void classAttributeChanged(const AtomicString& newClassString); 553 554 PassRefPtr<RenderStyle> originalStyleForRenderer(); 555 556 Node* insertAdjacent(const String& where, Node* newChild, ExceptionState&); 557 558 private: 559 bool hasElementFlag(ElementFlags mask) const { return hasRareData() && hasElementFlagInternal(mask); } 560 void setElementFlag(ElementFlags, bool value = true); 561 void clearElementFlag(ElementFlags); 562 bool hasElementFlagInternal(ElementFlags) const; 563 564 void styleAttributeChanged(const AtomicString& newStyleString, AttributeModificationReason); 565 566 void updatePresentationAttributeStyle(); 567 568 void inlineStyleChanged(); 569 PropertySetCSSStyleDeclaration* inlineStyleCSSOMWrapper(); 570 void setInlineStyleFromString(const AtomicString&); 571 572 StyleRecalcChange recalcOwnStyle(StyleRecalcChange); 573 void recalcChildStyle(StyleRecalcChange); 574 575 inline void checkForEmptyStyleChange(); 576 577 void updatePseudoElement(PseudoId, StyleRecalcChange); 578 579 inline void createPseudoElementIfNeeded(PseudoId); 580 581 // FIXME: Everyone should allow author shadows. 582 virtual bool areAuthorShadowsAllowed() const { return true; } 583 virtual void didAddUserAgentShadowRoot(ShadowRoot&) { } 584 virtual bool alwaysCreateUserAgentShadowRoot() const { return false; } 585 586 // FIXME: Remove the need for Attr to call willModifyAttribute/didModifyAttribute. 587 friend class Attr; 588 589 enum SynchronizationOfLazyAttribute { NotInSynchronizationOfLazyAttribute = 0, InSynchronizationOfLazyAttribute }; 590 591 void didAddAttribute(const QualifiedName&, const AtomicString&); 592 void willModifyAttribute(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue); 593 void didModifyAttribute(const QualifiedName&, const AtomicString&); 594 void didRemoveAttribute(const QualifiedName&); 595 596 void synchronizeAttribute(const QualifiedName&) const; 597 598 void updateId(const AtomicString& oldId, const AtomicString& newId); 599 void updateId(TreeScope&, const AtomicString& oldId, const AtomicString& newId); 600 void updateName(const AtomicString& oldName, const AtomicString& newName); 601 void updateLabel(TreeScope&, const AtomicString& oldForAttributeValue, const AtomicString& newForAttributeValue); 602 603 void scrollByUnits(int units, ScrollGranularity); 604 605 virtual NodeType nodeType() const OVERRIDE FINAL; 606 virtual bool childTypeAllowed(NodeType) const OVERRIDE FINAL; 607 608 void setAttributeInternal(size_t index, const QualifiedName&, const AtomicString& value, SynchronizationOfLazyAttribute); 609 void appendAttributeInternal(const QualifiedName&, const AtomicString& value, SynchronizationOfLazyAttribute); 610 void removeAttributeInternal(size_t index, SynchronizationOfLazyAttribute); 611 void attributeChangedFromParserOrByCloning(const QualifiedName&, const AtomicString&, AttributeModificationReason); 612 613 #ifndef NDEBUG 614 virtual void formatForDebugger(char* buffer, unsigned length) const OVERRIDE; 615 #endif 616 617 bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle); 618 619 void cancelFocusAppearanceUpdate(); 620 621 virtual RenderStyle* virtualComputedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) OVERRIDE { return computedStyle(pseudoElementSpecifier); } 622 623 inline void updateCallbackSelectors(RenderStyle* oldStyle, RenderStyle* newStyle); 624 inline void removeCallbackSelectors(); 625 inline void addCallbackSelectors(); 626 627 // cloneNode is private so that non-virtual cloneElementWithChildren and cloneElementWithoutChildren 628 // are used instead. 629 virtual PassRefPtrWillBeRawPtr<Node> cloneNode(bool deep) OVERRIDE; 630 virtual PassRefPtrWillBeRawPtr<Element> cloneElementWithoutAttributesAndChildren(); 631 632 QualifiedName m_tagName; 633 634 SpellcheckAttributeState spellcheckAttributeState() const; 635 636 void updateNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName); 637 void updateExtraNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName); 638 639 void createUniqueElementData(); 640 641 bool shouldInvalidateDistributionWhenAttributeChanged(ElementShadow*, const QualifiedName&, const AtomicString&); 642 643 ElementRareData* elementRareData() const; 644 ElementRareData& ensureElementRareData(); 645 646 WillBeHeapVector<RefPtrWillBeMember<Attr> >& ensureAttrNodeList(); 647 void removeAttrNodeList(); 648 void detachAllAttrNodesFromElement(); 649 void detachAttrNodeFromElementWithValue(Attr*, const AtomicString& value); 650 void detachAttrNodeAtIndex(Attr*, size_t index); 651 652 bool isJavaScriptURLAttribute(const Attribute&) const; 653 654 RefPtr<ElementData> m_elementData; 655 }; 656 657 DEFINE_NODE_TYPE_CASTS(Element, isElementNode()); 658 template <typename T> bool isElementOfType(const Element&); 659 template <typename T> inline bool isElementOfType(const Node& node) { return node.isElementNode() && isElementOfType<const T>(toElement(node)); } 660 template <> inline bool isElementOfType<const Element>(const Element&) { return true; } 661 662 // Type casting. 663 template<typename T> inline T& toElement(Node& node) 664 { 665 ASSERT_WITH_SECURITY_IMPLICATION(isElementOfType<const T>(node)); 666 return static_cast<T&>(node); 667 } 668 template<typename T> inline T* toElement(Node* node) 669 { 670 ASSERT_WITH_SECURITY_IMPLICATION(!node || isElementOfType<const T>(*node)); 671 return static_cast<T*>(node); 672 } 673 template<typename T> inline const T& toElement(const Node& node) 674 { 675 ASSERT_WITH_SECURITY_IMPLICATION(isElementOfType<const T>(node)); 676 return static_cast<const T&>(node); 677 } 678 template<typename T> inline const T* toElement(const Node* node) 679 { 680 ASSERT_WITH_SECURITY_IMPLICATION(!node || isElementOfType<const T>(*node)); 681 return static_cast<const T*>(node); 682 } 683 template<typename T, typename U> inline T* toElement(const RefPtr<U>& node) { return toElement<T>(node.get()); } 684 685 inline bool isDisabledFormControl(const Node* node) 686 { 687 return node->isElementNode() && toElement(node)->isDisabledFormControl(); 688 } 689 690 inline bool Node::hasTagName(const QualifiedName& name) const 691 { 692 return isElementNode() && toElement(this)->hasTagName(name); 693 } 694 695 inline Element* Node::parentElement() const 696 { 697 ContainerNode* parent = parentNode(); 698 return parent && parent->isElementNode() ? toElement(parent) : 0; 699 } 700 701 inline bool Element::fastHasAttribute(const QualifiedName& name) const 702 { 703 ASSERT(fastAttributeLookupAllowed(name)); 704 return elementData() && findAttributeByName(name); 705 } 706 707 inline const AtomicString& Element::fastGetAttribute(const QualifiedName& name) const 708 { 709 ASSERT(fastAttributeLookupAllowed(name)); 710 if (elementData()) { 711 if (const Attribute* attribute = findAttributeByName(name)) 712 return attribute->value(); 713 } 714 return nullAtom; 715 } 716 717 inline bool Element::hasAttributesWithoutUpdate() const 718 { 719 return elementData() && elementData()->hasAttributes(); 720 } 721 722 inline const AtomicString& Element::idForStyleResolution() const 723 { 724 ASSERT(hasID()); 725 return elementData()->idForStyleResolution(); 726 } 727 728 inline bool Element::isIdAttributeName(const QualifiedName& attributeName) const 729 { 730 // FIXME: This check is probably not correct for the case where the document has an id attribute 731 // with a non-null namespace, because it will return false, a false negative, if the prefixes 732 // don't match but the local name and namespace both do. However, since this has been like this 733 // for a while and the code paths may be hot, we'll have to measure performance if we fix it. 734 return attributeName == HTMLNames::idAttr; 735 } 736 737 inline const AtomicString& Element::getIdAttribute() const 738 { 739 return hasID() ? fastGetAttribute(HTMLNames::idAttr) : nullAtom; 740 } 741 742 inline const AtomicString& Element::getNameAttribute() const 743 { 744 return hasName() ? fastGetAttribute(HTMLNames::nameAttr) : nullAtom; 745 } 746 747 inline const AtomicString& Element::getClassAttribute() const 748 { 749 if (!hasClass()) 750 return nullAtom; 751 if (isSVGElement()) 752 return getAttribute(HTMLNames::classAttr); 753 return fastGetAttribute(HTMLNames::classAttr); 754 } 755 756 inline void Element::setIdAttribute(const AtomicString& value) 757 { 758 setAttribute(HTMLNames::idAttr, value); 759 } 760 761 inline const SpaceSplitString& Element::classNames() const 762 { 763 ASSERT(hasClass()); 764 ASSERT(elementData()); 765 return elementData()->classNames(); 766 } 767 768 inline size_t Element::attributeCount() const 769 { 770 ASSERT(elementData()); 771 return elementData()->attributeCount(); 772 } 773 774 inline const Attribute& Element::attributeAt(unsigned index) const 775 { 776 ASSERT(elementData()); 777 return elementData()->attributeAt(index); 778 } 779 780 inline const Attribute* Element::findAttributeByName(const QualifiedName& name) const 781 { 782 ASSERT(elementData()); 783 return elementData()->findAttributeByName(name); 784 } 785 786 inline bool Element::hasID() const 787 { 788 return elementData() && elementData()->hasID(); 789 } 790 791 inline bool Element::hasClass() const 792 { 793 return elementData() && elementData()->hasClass(); 794 } 795 796 inline UniqueElementData& Element::ensureUniqueElementData() 797 { 798 if (!elementData() || !elementData()->isUnique()) 799 createUniqueElementData(); 800 return static_cast<UniqueElementData&>(*m_elementData); 801 } 802 803 // Put here to make them inline. 804 inline bool Node::hasID() const 805 { 806 return isElementNode() && toElement(this)->hasID(); 807 } 808 809 inline bool Node::hasClass() const 810 { 811 return isElementNode() && toElement(this)->hasClass(); 812 } 813 814 inline Node::InsertionNotificationRequest Node::insertedInto(ContainerNode* insertionPoint) 815 { 816 ASSERT(!childNeedsStyleInvalidation()); 817 ASSERT(!needsStyleInvalidation()); 818 ASSERT(insertionPoint->inDocument() || isContainerNode()); 819 if (insertionPoint->inDocument()) 820 setFlag(InDocumentFlag); 821 if (parentOrShadowHostNode()->isInShadowTree()) 822 setFlag(IsInShadowTreeFlag); 823 if (childNeedsDistributionRecalc() && !insertionPoint->childNeedsDistributionRecalc()) 824 insertionPoint->markAncestorsWithChildNeedsDistributionRecalc(); 825 return InsertionDone; 826 } 827 828 inline void Node::removedFrom(ContainerNode* insertionPoint) 829 { 830 ASSERT(insertionPoint->inDocument() || isContainerNode()); 831 if (insertionPoint->inDocument()) 832 clearFlag(InDocumentFlag); 833 if (isInShadowTree() && !treeScope().rootNode().isShadowRoot()) 834 clearFlag(IsInShadowTreeFlag); 835 } 836 837 inline void Element::invalidateStyleAttribute() 838 { 839 ASSERT(elementData()); 840 elementData()->m_styleAttributeIsDirty = true; 841 } 842 843 inline const StylePropertySet* Element::presentationAttributeStyle() 844 { 845 if (!elementData()) 846 return 0; 847 if (elementData()->m_presentationAttributeStyleIsDirty) 848 updatePresentationAttributeStyle(); 849 // Need to call elementData() again since updatePresentationAttributeStyle() 850 // might swap it with a UniqueElementData. 851 return elementData()->presentationAttributeStyle(); 852 } 853 854 inline void Element::setTagNameForCreateElementNS(const QualifiedName& tagName) 855 { 856 // We expect this method to be called only to reset the prefix. 857 ASSERT(tagName.localName() == m_tagName.localName()); 858 ASSERT(tagName.namespaceURI() == m_tagName.namespaceURI()); 859 m_tagName = tagName; 860 } 861 862 inline bool isShadowHost(const Node* node) 863 { 864 return node && node->isElementNode() && toElement(node)->shadow(); 865 } 866 867 inline bool isShadowHost(const Element* element) 868 { 869 return element && element->shadow(); 870 } 871 872 // These macros do the same as their NODE equivalents but additionally provide a template specialization 873 // for isElementOfType<>() so that the Traversal<> API works for these Element types. 874 #define DEFINE_ELEMENT_TYPE_CASTS(thisType, predicate) \ 875 template <> inline bool isElementOfType<const thisType>(const Element& element) { return element.predicate; } \ 876 DEFINE_NODE_TYPE_CASTS(thisType, predicate) 877 878 #define DEFINE_ELEMENT_TYPE_CASTS_WITH_FUNCTION(thisType) \ 879 template <> inline bool isElementOfType<const thisType>(const Element& element) { return is##thisType(element); } \ 880 DEFINE_NODE_TYPE_CASTS_WITH_FUNCTION(thisType) 881 882 #define DECLARE_ELEMENT_FACTORY_WITH_TAGNAME(T) \ 883 static PassRefPtrWillBeRawPtr<T> create(const QualifiedName&, Document&) 884 #define DEFINE_ELEMENT_FACTORY_WITH_TAGNAME(T) \ 885 PassRefPtrWillBeRawPtr<T> T::create(const QualifiedName& tagName, Document& document) \ 886 { \ 887 return adoptRefWillBeNoop(new T(tagName, document)); \ 888 } 889 890 } // namespace 891 892 #endif 893