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