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 "CSSPropertyNames.h" 29 #include "HTMLNames.h" 30 #include "core/css/CSSPrimitiveValue.h" 31 #include "core/dom/Attribute.h" 32 #include "core/dom/Document.h" 33 #include "core/dom/SpaceSplitString.h" 34 #include "core/html/CollectionType.h" 35 #include "core/page/FocusDirection.h" 36 #include "core/platform/ScrollTypes.h" 37 #include "core/rendering/RegionOversetState.h" 38 39 namespace WebCore { 40 41 class ActiveAnimations; 42 class Attr; 43 class Attribute; 44 class ClientRect; 45 class ClientRectList; 46 class DOMStringMap; 47 class DOMTokenList; 48 class Element; 49 class ElementRareData; 50 class ElementShadow; 51 class ExceptionState; 52 class Image; 53 class InputMethodContext; 54 class IntSize; 55 class Locale; 56 class MutableStylePropertySet; 57 class PropertySetCSSStyleDeclaration; 58 class PseudoElement; 59 class RenderRegion; 60 class ShadowRoot; 61 class ShareableElementData; 62 class StylePropertySet; 63 class UniqueElementData; 64 65 struct PresentationAttributeCacheKey; 66 67 class ElementData : public RefCounted<ElementData> { 68 WTF_MAKE_FAST_ALLOCATED; 69 public: 70 // Override RefCounted's deref() to ensure operator delete is called on 71 // the appropriate subclass type. 72 void deref(); 73 74 void clearClass() const { m_classNames.clear(); } 75 void setClass(const AtomicString& className, bool shouldFoldCase) const { m_classNames.set(className, shouldFoldCase); } 76 const SpaceSplitString& classNames() const { return m_classNames; } 77 78 const AtomicString& idForStyleResolution() const { return m_idForStyleResolution; } 79 void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyleResolution = newId; } 80 81 const StylePropertySet* inlineStyle() const { return m_inlineStyle.get(); } 82 83 const StylePropertySet* presentationAttributeStyle() const; 84 85 size_t length() const; 86 bool isEmpty() const { return !length(); } 87 88 const Attribute* attributeItem(unsigned index) const; 89 const Attribute* getAttributeItem(const QualifiedName&) const; 90 size_t getAttributeItemIndex(const QualifiedName&) const; 91 size_t getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const; 92 size_t getAttrIndex(Attr*) const; 93 94 bool hasID() const { return !m_idForStyleResolution.isNull(); } 95 bool hasClass() const { return !m_classNames.isNull(); } 96 97 bool isEquivalent(const ElementData* other) const; 98 99 bool isUnique() const { return m_isUnique; } 100 101 protected: 102 ElementData(); 103 ElementData(unsigned arraySize); 104 ElementData(const ElementData&, bool isUnique); 105 106 unsigned m_isUnique : 1; 107 unsigned m_arraySize : 28; 108 mutable unsigned m_presentationAttributeStyleIsDirty : 1; 109 mutable unsigned m_styleAttributeIsDirty : 1; 110 mutable unsigned m_animatedSVGAttributesAreDirty : 1; 111 112 mutable RefPtr<StylePropertySet> m_inlineStyle; 113 mutable SpaceSplitString m_classNames; 114 mutable AtomicString m_idForStyleResolution; 115 116 private: 117 friend class Element; 118 friend class ShareableElementData; 119 friend class UniqueElementData; 120 friend class SVGElement; 121 122 const Attribute* attributeBase() const; 123 const Attribute* getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase) const; 124 size_t getAttributeItemIndexSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase) const; 125 126 PassRefPtr<UniqueElementData> makeUniqueCopy() const; 127 }; 128 129 #if COMPILER(MSVC) 130 #pragma warning(push) 131 #pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" warning 132 #endif 133 134 class ShareableElementData : public ElementData { 135 public: 136 static PassRefPtr<ShareableElementData> createWithAttributes(const Vector<Attribute>&); 137 138 explicit ShareableElementData(const Vector<Attribute>&); 139 explicit ShareableElementData(const UniqueElementData&); 140 ~ShareableElementData(); 141 142 Attribute m_attributeArray[0]; 143 }; 144 145 #if COMPILER(MSVC) 146 #pragma warning(pop) 147 #endif 148 149 class UniqueElementData : public ElementData { 150 public: 151 static PassRefPtr<UniqueElementData> create(); 152 PassRefPtr<ShareableElementData> makeShareableCopy() const; 153 154 // These functions do no error/duplicate checking. 155 void addAttribute(const QualifiedName&, const AtomicString&); 156 void removeAttribute(size_t index); 157 158 Attribute* attributeItem(unsigned index); 159 Attribute* getAttributeItem(const QualifiedName&); 160 161 UniqueElementData(); 162 explicit UniqueElementData(const ShareableElementData&); 163 explicit UniqueElementData(const UniqueElementData&); 164 165 mutable RefPtr<StylePropertySet> m_presentationAttributeStyle; 166 Vector<Attribute, 4> m_attributeVector; 167 }; 168 169 enum AffectedSelectorType { 170 AffectedSelectorChecked = 1, 171 AffectedSelectorEnabled = 1 << 1, 172 AffectedSelectorDisabled = 1 << 2, 173 AffectedSelectorIndeterminate = 1 << 3, 174 AffectedSelectorLink = 1 << 4, 175 AffectedSelectorTarget = 1 << 5, 176 AffectedSelectorVisited = 1 << 6 177 }; 178 typedef int AffectedSelectorMask; 179 180 enum SpellcheckAttributeState { 181 SpellcheckAttributeTrue, 182 SpellcheckAttributeFalse, 183 SpellcheckAttributeDefault 184 }; 185 186 class Element : public ContainerNode { 187 public: 188 static PassRefPtr<Element> create(const QualifiedName&, Document*); 189 virtual ~Element(); 190 191 DEFINE_ATTRIBUTE_EVENT_LISTENER(abort); 192 DEFINE_ATTRIBUTE_EVENT_LISTENER(change); 193 DEFINE_ATTRIBUTE_EVENT_LISTENER(click); 194 DEFINE_ATTRIBUTE_EVENT_LISTENER(contextmenu); 195 DEFINE_ATTRIBUTE_EVENT_LISTENER(dblclick); 196 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragenter); 197 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragover); 198 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragleave); 199 DEFINE_ATTRIBUTE_EVENT_LISTENER(drop); 200 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragstart); 201 DEFINE_ATTRIBUTE_EVENT_LISTENER(drag); 202 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragend); 203 DEFINE_ATTRIBUTE_EVENT_LISTENER(input); 204 DEFINE_ATTRIBUTE_EVENT_LISTENER(invalid); 205 DEFINE_ATTRIBUTE_EVENT_LISTENER(keydown); 206 DEFINE_ATTRIBUTE_EVENT_LISTENER(keypress); 207 DEFINE_ATTRIBUTE_EVENT_LISTENER(keyup); 208 DEFINE_ATTRIBUTE_EVENT_LISTENER(mousedown); 209 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseenter); 210 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseleave); 211 DEFINE_ATTRIBUTE_EVENT_LISTENER(mousemove); 212 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseout); 213 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseover); 214 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseup); 215 DEFINE_ATTRIBUTE_EVENT_LISTENER(mousewheel); 216 DEFINE_ATTRIBUTE_EVENT_LISTENER(scroll); 217 DEFINE_ATTRIBUTE_EVENT_LISTENER(select); 218 DEFINE_ATTRIBUTE_EVENT_LISTENER(submit); 219 220 // These four attribute event handler attributes are overridden by HTMLBodyElement 221 // and HTMLFrameSetElement to forward to the DOMWindow. 222 DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(blur); 223 DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(error); 224 DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(focus); 225 DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(load); 226 227 // WebKit extensions 228 DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut); 229 DEFINE_ATTRIBUTE_EVENT_LISTENER(cut); 230 DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecopy); 231 DEFINE_ATTRIBUTE_EVENT_LISTENER(copy); 232 DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste); 233 DEFINE_ATTRIBUTE_EVENT_LISTENER(paste); 234 DEFINE_ATTRIBUTE_EVENT_LISTENER(reset); 235 DEFINE_ATTRIBUTE_EVENT_LISTENER(search); 236 DEFINE_ATTRIBUTE_EVENT_LISTENER(selectstart); 237 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart); 238 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove); 239 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend); 240 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel); 241 DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenchange); 242 DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenerror); 243 244 bool hasAttribute(const QualifiedName&) const; 245 const AtomicString& getAttribute(const QualifiedName&) const; 246 void setAttribute(const QualifiedName&, const AtomicString& value); 247 void setSynchronizedLazyAttribute(const QualifiedName&, const AtomicString& value); 248 void removeAttribute(const QualifiedName&); 249 250 // Typed getters and setters for language bindings. 251 int getIntegralAttribute(const QualifiedName& attributeName) const; 252 void setIntegralAttribute(const QualifiedName& attributeName, int value); 253 unsigned getUnsignedIntegralAttribute(const QualifiedName& attributeName) const; 254 void setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value); 255 256 // Call this to get the value of an attribute that is known not to be the style 257 // attribute or one of the SVG animatable attributes. 258 bool fastHasAttribute(const QualifiedName&) const; 259 const AtomicString& fastGetAttribute(const QualifiedName&) const; 260 #ifndef NDEBUG 261 bool fastAttributeLookupAllowed(const QualifiedName&) const; 262 #endif 263 264 #ifdef DUMP_NODE_STATISTICS 265 bool hasNamedNodeMap() const; 266 #endif 267 bool hasAttributes() const; 268 // This variant will not update the potentially invalid attributes. To be used when not interested 269 // in style attribute or one of the SVG animation attributes. 270 bool hasAttributesWithoutUpdate() const; 271 272 bool hasAttribute(const AtomicString& name) const; 273 bool hasAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const; 274 275 const AtomicString& getAttribute(const AtomicString& name) const; 276 const AtomicString& getAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const; 277 278 void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionState&); 279 static bool parseAttributeName(QualifiedName&, const AtomicString& namespaceURI, const AtomicString& qualifiedName, ExceptionState&); 280 void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionState&); 281 282 bool isIdAttributeName(const QualifiedName&) const; 283 const AtomicString& getIdAttribute() const; 284 void setIdAttribute(const AtomicString&); 285 286 const AtomicString& getNameAttribute() const; 287 const AtomicString& getClassAttribute() const; 288 289 // Call this to get the value of the id attribute for style resolution purposes. 290 // The value will already be lowercased if the document is in compatibility mode, 291 // so this function is not suitable for non-style uses. 292 const AtomicString& idForStyleResolution() const; 293 294 // Internal methods that assume the existence of attribute storage, one should use hasAttributes() 295 // before calling them. 296 size_t attributeCount() const; 297 const Attribute* attributeItem(unsigned index) const; 298 const Attribute* getAttributeItem(const QualifiedName&) const; 299 size_t getAttributeItemIndex(const QualifiedName& name) const { return elementData()->getAttributeItemIndex(name); } 300 size_t getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const { return elementData()->getAttributeItemIndex(name, shouldIgnoreAttributeCase); } 301 302 void scrollIntoView(bool alignToTop = true); 303 void scrollIntoViewIfNeeded(bool centerIfNeeded = true); 304 305 void scrollByLines(int lines); 306 void scrollByPages(int pages); 307 308 int offsetLeft(); 309 int offsetTop(); 310 int offsetWidth(); 311 int offsetHeight(); 312 313 // FIXME: Replace uses of offsetParent in the platform with calls 314 // to the render layer and merge bindingsOffsetParent and offsetParent. 315 Element* bindingsOffsetParent(); 316 317 Element* offsetParent(); 318 int clientLeft(); 319 int clientTop(); 320 int clientWidth(); 321 int clientHeight(); 322 virtual int scrollLeft(); 323 virtual int scrollTop(); 324 virtual void setScrollLeft(int); 325 virtual void setScrollTop(int); 326 virtual int scrollWidth(); 327 virtual int scrollHeight(); 328 329 IntRect boundsInRootViewSpace(); 330 331 PassRefPtr<ClientRectList> getClientRects(); 332 PassRefPtr<ClientRect> getBoundingClientRect(); 333 334 // Returns the absolute bounding box translated into screen coordinates: 335 IntRect screenRect() const; 336 337 virtual void didMoveToNewDocument(Document*) OVERRIDE; 338 339 void removeAttribute(const AtomicString& name); 340 void removeAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName); 341 342 PassRefPtr<Attr> detachAttribute(size_t index); 343 344 PassRefPtr<Attr> getAttributeNode(const AtomicString& name); 345 PassRefPtr<Attr> getAttributeNodeNS(const AtomicString& namespaceURI, const AtomicString& localName); 346 PassRefPtr<Attr> setAttributeNode(Attr*, ExceptionState&); 347 PassRefPtr<Attr> setAttributeNodeNS(Attr*, ExceptionState&); 348 PassRefPtr<Attr> removeAttributeNode(Attr*, ExceptionState&); 349 350 PassRefPtr<Attr> attrIfExists(const QualifiedName&); 351 PassRefPtr<Attr> ensureAttr(const QualifiedName&); 352 353 const Vector<RefPtr<Attr> >& attrNodeList(); 354 355 CSSStyleDeclaration* style(); 356 357 const QualifiedName& tagQName() const { return m_tagName; } 358 String tagName() const { return nodeName(); } 359 bool hasTagName(const QualifiedName& tagName) const { return m_tagName.matches(tagName); } 360 361 // A fast function for checking the local name against another atomic string. 362 bool hasLocalName(const AtomicString& other) const { return m_tagName.localName() == other; } 363 bool hasLocalName(const QualifiedName& other) const { return m_tagName.localName() == other.localName(); } 364 365 virtual const AtomicString& localName() const OVERRIDE { return m_tagName.localName(); } 366 virtual const AtomicString& prefix() const OVERRIDE { return m_tagName.prefix(); } 367 virtual const AtomicString& namespaceURI() const OVERRIDE { return m_tagName.namespaceURI(); } 368 369 virtual KURL baseURI() const OVERRIDE FINAL; 370 371 virtual String nodeName() const; 372 373 PassRefPtr<Element> cloneElementWithChildren(); 374 PassRefPtr<Element> cloneElementWithoutChildren(); 375 376 void scheduleLayerUpdate(); 377 378 void normalizeAttributes(); 379 String nodeNamePreservingCase() const; 380 381 void setBooleanAttribute(const QualifiedName& name, bool); 382 383 virtual const StylePropertySet* additionalPresentationAttributeStyle() { return 0; } 384 void invalidateStyleAttribute(); 385 386 const StylePropertySet* inlineStyle() const { return elementData() ? elementData()->m_inlineStyle.get() : 0; } 387 388 bool setInlineStyleProperty(CSSPropertyID, CSSValueID identifier, bool important = false); 389 bool setInlineStyleProperty(CSSPropertyID, CSSPropertyID identifier, bool important = false); 390 bool setInlineStyleProperty(CSSPropertyID, double value, CSSPrimitiveValue::UnitTypes, bool important = false); 391 bool setInlineStyleProperty(CSSPropertyID, const String& value, bool important = false); 392 bool removeInlineStyleProperty(CSSPropertyID); 393 void removeAllInlineStyleProperties(); 394 395 void synchronizeStyleAttributeInternal() const; 396 397 const StylePropertySet* presentationAttributeStyle(); 398 virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) { } 399 400 // For exposing to DOM only. 401 NamedNodeMap* attributes() const; 402 403 enum AttributeModificationReason { 404 ModifiedDirectly, 405 ModifiedByCloning 406 }; 407 408 // This method is called whenever an attribute is added, changed or removed. 409 virtual void attributeChanged(const QualifiedName&, const AtomicString&, AttributeModificationReason = ModifiedDirectly); 410 virtual void parseAttribute(const QualifiedName&, const AtomicString&) { } 411 412 // Only called by the parser immediately after element construction. 413 void parserSetAttributes(const Vector<Attribute>&); 414 415 // Remove attributes that might introduce scripting from the vector leaving the element unchanged. 416 void stripScriptingAttributes(Vector<Attribute>&) const; 417 418 const ElementData* elementData() const { return m_elementData.get(); } 419 UniqueElementData* ensureUniqueElementData(); 420 421 void synchronizeAllAttributes() const; 422 423 // Clones attributes only. 424 void cloneAttributesFromElement(const Element&); 425 426 // Clones all attribute-derived data, including subclass specifics (through copyNonAttributeProperties.) 427 void cloneDataFromElement(const Element&); 428 429 bool hasEquivalentAttributes(const Element* other) const; 430 431 virtual void copyNonAttributePropertiesFromElement(const Element&) { } 432 433 virtual void attach(const AttachContext& = AttachContext()) OVERRIDE; 434 virtual void detach(const AttachContext& = AttachContext()) OVERRIDE; 435 virtual RenderObject* createRenderer(RenderStyle*); 436 virtual bool rendererIsNeeded(const NodeRenderingContext&); 437 bool recalcStyle(StyleChange = NoChange); 438 void didAffectSelector(AffectedSelectorMask); 439 440 ElementShadow* shadow() const; 441 ElementShadow* ensureShadow(); 442 PassRefPtr<ShadowRoot> createShadowRoot(ExceptionState&); 443 ShadowRoot* shadowRoot() const; 444 445 bool hasAuthorShadowRoot() const { return shadowRoot(); } 446 447 ShadowRoot* userAgentShadowRoot() const; 448 ShadowRoot* ensureUserAgentShadowRoot(); 449 Element* uaShadowElementById(const AtomicString& id) const; 450 virtual bool supportsShadowElementForUserAgentShadow() const; 451 virtual const AtomicString& shadowPseudoId() const { return !part().isEmpty() ? part() : pseudo(); } 452 453 RenderStyle* computedStyle(PseudoId = NOPSEUDO); 454 455 // Methods for indicating the style is affected by dynamic updates (e.g., children changing, our position changing in our sibling list, etc.) 456 bool styleAffectedByEmpty() const { return hasRareData() && rareDataStyleAffectedByEmpty(); } 457 bool childrenAffectedByHover() const { return hasRareData() && rareDataChildrenAffectedByHover(); } 458 bool childrenAffectedByActive() const { return hasRareData() && rareDataChildrenAffectedByActive(); } 459 bool childrenAffectedByDrag() const { return hasRareData() && rareDataChildrenAffectedByDrag(); } 460 bool childrenAffectedByPositionalRules() const { return hasRareData() && (rareDataChildrenAffectedByForwardPositionalRules() || rareDataChildrenAffectedByBackwardPositionalRules()); } 461 bool childrenAffectedByFirstChildRules() const { return hasRareData() && rareDataChildrenAffectedByFirstChildRules(); } 462 bool childrenAffectedByLastChildRules() const { return hasRareData() && rareDataChildrenAffectedByLastChildRules(); } 463 bool childrenAffectedByDirectAdjacentRules() const { return hasRareData() && rareDataChildrenAffectedByDirectAdjacentRules(); } 464 bool childrenAffectedByForwardPositionalRules() const { return hasRareData() && rareDataChildrenAffectedByForwardPositionalRules(); } 465 bool childrenAffectedByBackwardPositionalRules() const { return hasRareData() && rareDataChildrenAffectedByBackwardPositionalRules(); } 466 unsigned childIndex() const { return hasRareData() ? rareDataChildIndex() : 0; } 467 468 bool hasFlagsSetDuringStylingOfChildren() const; 469 470 void setStyleAffectedByEmpty(); 471 void setChildrenAffectedByHover(bool); 472 void setChildrenAffectedByActive(bool); 473 void setChildrenAffectedByDrag(bool); 474 void setChildrenAffectedByFirstChildRules(); 475 void setChildrenAffectedByLastChildRules(); 476 void setChildrenAffectedByDirectAdjacentRules(); 477 void setChildrenAffectedByForwardPositionalRules(); 478 void setChildrenAffectedByBackwardPositionalRules(); 479 void setChildIndex(unsigned); 480 481 void setIsInCanvasSubtree(bool); 482 bool isInCanvasSubtree() const; 483 484 bool isUpgradedCustomElement() { return customElementState() == Upgraded; } 485 bool isUnresolvedCustomElement() { return isCustomElement() && !isUpgradedCustomElement(); } 486 487 void setIsInsideRegion(bool); 488 bool isInsideRegion() const; 489 490 void setRegionOversetState(RegionOversetState); 491 RegionOversetState regionOversetState() const; 492 493 AtomicString computeInheritedLanguage() const; 494 Locale& locale() const; 495 496 virtual void accessKeyAction(bool /*sendToAnyEvent*/) { } 497 498 virtual bool isURLAttribute(const Attribute&) const { return false; } 499 virtual bool isHTMLContentAttribute(const Attribute&) const { return false; } 500 501 KURL getURLAttribute(const QualifiedName&) const; 502 KURL getNonEmptyURLAttribute(const QualifiedName&) const; 503 504 virtual const AtomicString& imageSourceURL() const; 505 virtual String target() const { return String(); } 506 virtual Image* imageContents() { return 0; } 507 508 virtual void focus(bool restorePreviousSelection = true, FocusDirection = FocusDirectionNone); 509 virtual void updateFocusAppearance(bool restorePreviousSelection); 510 virtual void blur(); 511 // Whether this element can receive focus at all. Most elements are not 512 // focusable but some elements, such as form controls and links, are. Unlike 513 // rendererIsFocusable(), this method may be called when layout is not up to 514 // date, so it must not use the renderer to determine focusability. 515 virtual bool supportsFocus() const; 516 // Whether the node can actually be focused. 517 bool isFocusable() const; 518 virtual bool isKeyboardFocusable() const; 519 virtual bool isMouseFocusable() const; 520 virtual void dispatchFocusEvent(Element* oldFocusedElement, FocusDirection); 521 virtual void dispatchBlurEvent(Element* newFocusedElement); 522 void dispatchFocusInEvent(const AtomicString& eventType, Element* oldFocusedElement); 523 void dispatchFocusOutEvent(const AtomicString& eventType, Element* newFocusedElement); 524 525 String innerText(); 526 String outerText(); 527 528 String textFromChildren(); 529 530 virtual String title() const { return String(); } 531 532 const AtomicString& pseudo() const; 533 virtual const AtomicString& part() const; 534 void setPart(const AtomicString&); 535 536 LayoutSize minimumSizeForResizing() const; 537 void setMinimumSizeForResizing(const LayoutSize&); 538 539 virtual void didBecomeFullscreenElement() { } 540 virtual void willStopBeingFullscreenElement() { } 541 542 bool isFinishedParsingChildren() const { return isParsingChildrenFinished(); } 543 virtual void finishParsingChildren(); 544 virtual void beginParsingChildren() OVERRIDE FINAL; 545 546 PseudoElement* pseudoElement(PseudoId) const; 547 RenderObject* pseudoElementRenderer(PseudoId) const; 548 549 virtual bool matchesReadOnlyPseudoClass() const { return false; } 550 virtual bool matchesReadWritePseudoClass() const { return false; } 551 bool webkitMatchesSelector(const String& selectors, ExceptionState&); 552 virtual bool shouldAppearIndeterminate() const { return false; } 553 554 DOMTokenList* classList(); 555 556 DOMStringMap* dataset(); 557 558 static bool isMathMLElement() { return false; } 559 virtual bool isMediaElement() const { return false; } 560 561 #if ENABLE(INPUT_SPEECH) 562 virtual bool isInputFieldSpeechButtonElement() const { return false; } 563 #endif 564 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI) 565 virtual bool isDateTimeEditElement() const { return false; } 566 virtual bool isDateTimeFieldElement() const { return false; } 567 virtual bool isPickerIndicatorElement() const { return false; } 568 #endif 569 570 virtual bool isFormControlElement() const { return false; } 571 virtual bool isSpinButtonElement() const { return false; } 572 virtual bool isTextFormControl() const { return false; } 573 virtual bool isOptionalFormControl() const { return false; } 574 virtual bool isRequiredFormControl() const { return false; } 575 virtual bool isDefaultButtonForForm() const { return false; } 576 virtual bool willValidate() const { return false; } 577 virtual bool isValidFormControlElement() { return false; } 578 virtual bool isInRange() const { return false; } 579 virtual bool isOutOfRange() const { return false; } 580 virtual bool isFrameElementBase() const { return false; } 581 virtual bool isPasswordGeneratorButtonElement() const { return false; } 582 virtual bool isClearButtonElement() const { return false; } 583 584 virtual bool canContainRangeEndPoint() const { return true; } 585 586 virtual const AtomicString& formControlType() const { return nullAtom; } 587 588 // FIXME: Only HTMLInputElement uses these, they don't need to be virtual. 589 virtual bool wasChangedSinceLastFormControlChangeEvent() const { return false; } 590 virtual void setChangedSinceLastFormControlChangeEvent(bool) { } 591 virtual void dispatchFormControlChangeEvent() { } 592 593 // Used for disabled form elements; if true, prevents mouse events from being dispatched 594 // to event listeners, and prevents DOMActivate events from being sent at all. 595 virtual bool isDisabledFormControl() const { return false; } 596 597 bool isInert() const; 598 virtual bool shouldBeReparentedUnderRenderView(const RenderStyle*) const { return isInTopLayer(); } 599 600 virtual bool childShouldCreateRenderer(const NodeRenderingContext&) const; 601 bool hasPendingResources() const; 602 void setHasPendingResources(); 603 void clearHasPendingResources(); 604 virtual void buildPendingResource() { }; 605 606 enum { 607 ALLOW_KEYBOARD_INPUT = 1 << 0, 608 LEGACY_MOZILLA_REQUEST = 1 << 1, 609 }; 610 611 void webkitRequestFullScreen(unsigned short flags); 612 bool containsFullScreenElement() const; 613 void setContainsFullScreenElement(bool); 614 void setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(bool); 615 616 // W3C API 617 void webkitRequestFullscreen(); 618 619 bool isInTopLayer() const; 620 void setIsInTopLayer(bool); 621 622 void webkitRequestPointerLock(); 623 624 bool isSpellCheckingEnabled() const; 625 626 PassRefPtr<RenderStyle> styleForRenderer(); 627 PassRefPtr<RenderStyle> originalStyleForRenderer(); 628 629 RenderRegion* renderRegion() const; 630 virtual bool shouldMoveToFlowThread(RenderStyle*) const; 631 const AtomicString& webkitRegionOverset() const; 632 Vector<RefPtr<Range> > webkitGetRegionFlowRanges() const; 633 634 bool hasID() const; 635 bool hasClass() const; 636 const SpaceSplitString& classNames() const; 637 638 IntSize savedLayerScrollOffset() const; 639 void setSavedLayerScrollOffset(const IntSize&); 640 641 ActiveAnimations* activeAnimations() const; 642 ActiveAnimations* ensureActiveAnimations(); 643 bool hasActiveAnimations() const; 644 645 InputMethodContext* inputMethodContext(); 646 647 protected: 648 Element(const QualifiedName& tagName, Document* document, ConstructionType type) 649 : ContainerNode(document, type) 650 , m_tagName(tagName) 651 { 652 ScriptWrappable::init(this); 653 } 654 655 virtual bool isPresentationAttribute(const QualifiedName&) const { return false; } 656 657 void addPropertyToPresentationAttributeStyle(MutableStylePropertySet*, CSSPropertyID, CSSValueID identifier); 658 void addPropertyToPresentationAttributeStyle(MutableStylePropertySet*, CSSPropertyID, double value, CSSPrimitiveValue::UnitTypes); 659 void addPropertyToPresentationAttributeStyle(MutableStylePropertySet*, CSSPropertyID, const String& value); 660 661 virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const; 662 663 virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; 664 virtual void removedFrom(ContainerNode*) OVERRIDE; 665 virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0) OVERRIDE; 666 virtual void removeAllEventListeners() OVERRIDE FINAL; 667 668 virtual void willRecalcStyle(StyleChange); 669 virtual void didRecalcStyle(StyleChange); 670 virtual PassRefPtr<RenderStyle> customStyleForRenderer(); 671 672 virtual bool shouldRegisterAsNamedItem() const { return false; } 673 virtual bool shouldRegisterAsExtraNamedItem() const { return false; } 674 675 void clearTabIndexExplicitlyIfNeeded(); 676 void setTabIndexExplicitly(short); 677 virtual short tabIndex() const OVERRIDE; 678 // Subclasses may override this method to affect focusability. Unlike 679 // supportsFocus, this method must be called on an up-to-date layout, so it 680 // may use the renderer to reason about focusability. This method cannot be 681 // moved to RenderObject because some focusable nodes don't have renderers, 682 // e.g., HTMLOptionElement. 683 virtual bool rendererIsFocusable() const; 684 PassRefPtr<HTMLCollection> ensureCachedHTMLCollection(CollectionType); 685 HTMLCollection* cachedHTMLCollection(CollectionType); 686 687 // classAttributeChanged() exists to share code between 688 // parseAttribute (called via setAttribute()) and 689 // svgAttributeChanged (called when element.className.baseValue is set) 690 void classAttributeChanged(const AtomicString& newClassString); 691 692 private: 693 void styleAttributeChanged(const AtomicString& newStyleString, AttributeModificationReason); 694 695 void inlineStyleChanged(); 696 PropertySetCSSStyleDeclaration* inlineStyleCSSOMWrapper(); 697 void setInlineStyleFromString(const AtomicString&); 698 MutableStylePropertySet* ensureMutableInlineStyle(); 699 700 void makePresentationAttributeCacheKey(PresentationAttributeCacheKey&) const; 701 void rebuildPresentationAttributeStyle(); 702 703 void updatePseudoElement(PseudoId, StyleChange); 704 void createPseudoElementIfNeeded(PseudoId); 705 706 // FIXME: Everyone should allow author shadows. 707 virtual bool areAuthorShadowsAllowed() const { return true; } 708 virtual void didAddUserAgentShadowRoot(ShadowRoot*) { } 709 virtual bool alwaysCreateUserAgentShadowRoot() const { return false; } 710 711 // FIXME: Remove the need for Attr to call willModifyAttribute/didModifyAttribute. 712 friend class Attr; 713 714 enum SynchronizationOfLazyAttribute { NotInSynchronizationOfLazyAttribute = 0, InSynchronizationOfLazyAttribute }; 715 716 void didAddAttribute(const QualifiedName&, const AtomicString&); 717 void willModifyAttribute(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue); 718 void didModifyAttribute(const QualifiedName&, const AtomicString&); 719 void didRemoveAttribute(const QualifiedName&); 720 721 void synchronizeAttribute(const QualifiedName&) const; 722 void synchronizeAttribute(const AtomicString& localName) const; 723 724 void updateId(const AtomicString& oldId, const AtomicString& newId); 725 void updateId(TreeScope*, const AtomicString& oldId, const AtomicString& newId); 726 void updateName(const AtomicString& oldName, const AtomicString& newName); 727 void updateLabel(TreeScope*, const AtomicString& oldForAttributeValue, const AtomicString& newForAttributeValue); 728 729 void scrollByUnits(int units, ScrollGranularity); 730 731 virtual void setPrefix(const AtomicString&, ExceptionState&) OVERRIDE FINAL; 732 virtual NodeType nodeType() const OVERRIDE FINAL; 733 virtual bool childTypeAllowed(NodeType) const OVERRIDE FINAL; 734 735 void setAttributeInternal(size_t index, const QualifiedName&, const AtomicString& value, SynchronizationOfLazyAttribute); 736 void addAttributeInternal(const QualifiedName&, const AtomicString& value, SynchronizationOfLazyAttribute); 737 void removeAttributeInternal(size_t index, SynchronizationOfLazyAttribute); 738 void attributeChangedFromParserOrByCloning(const QualifiedName&, const AtomicString&, AttributeModificationReason); 739 740 #ifndef NDEBUG 741 virtual void formatForDebugger(char* buffer, unsigned length) const; 742 #endif 743 744 bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle); 745 746 void cancelFocusAppearanceUpdate(); 747 748 virtual RenderStyle* virtualComputedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return computedStyle(pseudoElementSpecifier); } 749 750 // cloneNode is private so that non-virtual cloneElementWithChildren and cloneElementWithoutChildren 751 // are used instead. 752 virtual PassRefPtr<Node> cloneNode(bool deep) OVERRIDE; 753 virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren(); 754 755 QualifiedName m_tagName; 756 bool rareDataStyleAffectedByEmpty() const; 757 bool rareDataChildrenAffectedByHover() const; 758 bool rareDataChildrenAffectedByActive() const; 759 bool rareDataChildrenAffectedByDrag() const; 760 bool rareDataChildrenAffectedByFirstChildRules() const; 761 bool rareDataChildrenAffectedByLastChildRules() const; 762 bool rareDataChildrenAffectedByDirectAdjacentRules() const; 763 bool rareDataChildrenAffectedByForwardPositionalRules() const; 764 bool rareDataChildrenAffectedByBackwardPositionalRules() const; 765 unsigned rareDataChildIndex() const; 766 767 SpellcheckAttributeState spellcheckAttributeState() const; 768 769 void updateNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName); 770 void updateExtraNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName); 771 772 void unregisterNamedFlowContentNode(); 773 774 void createUniqueElementData(); 775 776 bool shouldInvalidateDistributionWhenAttributeChanged(ElementShadow*, const QualifiedName&, const AtomicString&); 777 778 ElementRareData* elementRareData() const; 779 ElementRareData* ensureElementRareData(); 780 781 void detachAllAttrNodesFromElement(); 782 void detachAttrNodeFromElementWithValue(Attr*, const AtomicString& value); 783 void detachAttrNodeAtIndex(Attr*, size_t index); 784 785 bool isJavaScriptURLAttribute(const Attribute&) const; 786 787 RefPtr<ElementData> m_elementData; 788 }; 789 790 inline Element* toElement(Node* node) 791 { 792 ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isElementNode()); 793 return static_cast<Element*>(node); 794 } 795 796 inline const Element* toElement(const Node* node) 797 { 798 ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isElementNode()); 799 return static_cast<const Element*>(node); 800 } 801 802 // This will catch anyone doing an unnecessary cast. 803 void toElement(const Element*); 804 805 inline bool isDisabledFormControl(const Node* node) 806 { 807 return node->isElementNode() && toElement(node)->isDisabledFormControl(); 808 } 809 810 inline bool Node::hasTagName(const QualifiedName& name) const 811 { 812 return isElementNode() && toElement(this)->hasTagName(name); 813 } 814 815 inline bool Node::hasLocalName(const AtomicString& name) const 816 { 817 return isElementNode() && toElement(this)->hasLocalName(name); 818 } 819 820 inline bool Node::hasAttributes() const 821 { 822 return isElementNode() && toElement(this)->hasAttributes(); 823 } 824 825 inline NamedNodeMap* Node::attributes() const 826 { 827 return isElementNode() ? toElement(this)->attributes() : 0; 828 } 829 830 inline Element* Node::parentElement() const 831 { 832 ContainerNode* parent = parentNode(); 833 return parent && parent->isElementNode() ? toElement(parent) : 0; 834 } 835 836 inline Element* Node::previousElementSibling() const 837 { 838 Node* n = previousSibling(); 839 while (n && !n->isElementNode()) 840 n = n->previousSibling(); 841 return toElement(n); 842 } 843 844 inline Element* Node::nextElementSibling() const 845 { 846 Node* n = nextSibling(); 847 while (n && !n->isElementNode()) 848 n = n->nextSibling(); 849 return toElement(n); 850 } 851 852 inline bool Element::fastHasAttribute(const QualifiedName& name) const 853 { 854 ASSERT(fastAttributeLookupAllowed(name)); 855 return elementData() && getAttributeItem(name); 856 } 857 858 inline const AtomicString& Element::fastGetAttribute(const QualifiedName& name) const 859 { 860 ASSERT(fastAttributeLookupAllowed(name)); 861 if (elementData()) { 862 if (const Attribute* attribute = getAttributeItem(name)) 863 return attribute->value(); 864 } 865 return nullAtom; 866 } 867 868 inline bool Element::hasAttributesWithoutUpdate() const 869 { 870 return elementData() && !elementData()->isEmpty(); 871 } 872 873 inline const AtomicString& Element::idForStyleResolution() const 874 { 875 ASSERT(hasID()); 876 return elementData()->idForStyleResolution(); 877 } 878 879 inline bool Element::isIdAttributeName(const QualifiedName& attributeName) const 880 { 881 // FIXME: This check is probably not correct for the case where the document has an id attribute 882 // with a non-null namespace, because it will return false, a false negative, if the prefixes 883 // don't match but the local name and namespace both do. However, since this has been like this 884 // for a while and the code paths may be hot, we'll have to measure performance if we fix it. 885 return attributeName == document()->idAttributeName(); 886 } 887 888 inline const AtomicString& Element::getIdAttribute() const 889 { 890 return hasID() ? fastGetAttribute(document()->idAttributeName()) : nullAtom; 891 } 892 893 inline const AtomicString& Element::getNameAttribute() const 894 { 895 return hasName() ? fastGetAttribute(HTMLNames::nameAttr) : nullAtom; 896 } 897 898 inline const AtomicString& Element::getClassAttribute() const 899 { 900 if (!hasClass()) 901 return nullAtom; 902 if (isSVGElement()) 903 return getAttribute(HTMLNames::classAttr); 904 return fastGetAttribute(HTMLNames::classAttr); 905 } 906 907 inline void Element::setIdAttribute(const AtomicString& value) 908 { 909 setAttribute(document()->idAttributeName(), value); 910 } 911 912 inline const SpaceSplitString& Element::classNames() const 913 { 914 ASSERT(hasClass()); 915 ASSERT(elementData()); 916 return elementData()->classNames(); 917 } 918 919 inline size_t Element::attributeCount() const 920 { 921 ASSERT(elementData()); 922 return elementData()->length(); 923 } 924 925 inline const Attribute* Element::attributeItem(unsigned index) const 926 { 927 ASSERT(elementData()); 928 return elementData()->attributeItem(index); 929 } 930 931 inline const Attribute* Element::getAttributeItem(const QualifiedName& name) const 932 { 933 ASSERT(elementData()); 934 return elementData()->getAttributeItem(name); 935 } 936 937 inline bool Element::hasID() const 938 { 939 return elementData() && elementData()->hasID(); 940 } 941 942 inline bool Element::hasClass() const 943 { 944 return elementData() && elementData()->hasClass(); 945 } 946 947 inline UniqueElementData* Element::ensureUniqueElementData() 948 { 949 if (!elementData() || !elementData()->isUnique()) 950 createUniqueElementData(); 951 return static_cast<UniqueElementData*>(m_elementData.get()); 952 } 953 954 // Put here to make them inline. 955 inline bool Node::hasID() const 956 { 957 return isElementNode() && toElement(this)->hasID(); 958 } 959 960 inline bool Node::hasClass() const 961 { 962 return isElementNode() && toElement(this)->hasClass(); 963 } 964 965 inline Node::InsertionNotificationRequest Node::insertedInto(ContainerNode* insertionPoint) 966 { 967 ASSERT(insertionPoint->inDocument() || isContainerNode()); 968 if (insertionPoint->inDocument()) 969 setFlag(InDocumentFlag); 970 if (parentOrShadowHostNode()->isInShadowTree()) 971 setFlag(IsInShadowTreeFlag); 972 if (childNeedsDistributionRecalc() && !insertionPoint->childNeedsDistributionRecalc()) 973 insertionPoint->markAncestorsWithChildNeedsDistributionRecalc(); 974 return InsertionDone; 975 } 976 977 inline void Node::removedFrom(ContainerNode* insertionPoint) 978 { 979 ASSERT(insertionPoint->inDocument() || isContainerNode()); 980 if (insertionPoint->inDocument()) 981 clearFlag(InDocumentFlag); 982 if (isInShadowTree() && !treeScope()->rootNode()->isShadowRoot()) 983 clearFlag(IsInShadowTreeFlag); 984 } 985 986 inline void Element::invalidateStyleAttribute() 987 { 988 ASSERT(elementData()); 989 elementData()->m_styleAttributeIsDirty = true; 990 } 991 992 inline const StylePropertySet* Element::presentationAttributeStyle() 993 { 994 if (!elementData()) 995 return 0; 996 if (elementData()->m_presentationAttributeStyleIsDirty) 997 rebuildPresentationAttributeStyle(); 998 return elementData()->presentationAttributeStyle(); 999 } 1000 1001 inline bool isShadowHost(const Node* node) 1002 { 1003 return node && node->isElementNode() && toElement(node)->shadow(); 1004 } 1005 1006 inline bool isShadowHost(const Element* element) 1007 { 1008 return element && element->shadow(); 1009 } 1010 1011 inline size_t ElementData::length() const 1012 { 1013 if (isUnique()) 1014 return static_cast<const UniqueElementData*>(this)->m_attributeVector.size(); 1015 return m_arraySize; 1016 } 1017 1018 inline const StylePropertySet* ElementData::presentationAttributeStyle() const 1019 { 1020 if (!m_isUnique) 1021 return 0; 1022 return static_cast<const UniqueElementData*>(this)->m_presentationAttributeStyle.get(); 1023 } 1024 1025 inline const Attribute* ElementData::getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase) const 1026 { 1027 size_t index = getAttributeItemIndex(name, shouldIgnoreAttributeCase); 1028 if (index != notFound) 1029 return attributeItem(index); 1030 return 0; 1031 } 1032 1033 inline const Attribute* ElementData::attributeBase() const 1034 { 1035 if (m_isUnique) 1036 return static_cast<const UniqueElementData*>(this)->m_attributeVector.begin(); 1037 return static_cast<const ShareableElementData*>(this)->m_attributeArray; 1038 } 1039 1040 inline size_t ElementData::getAttributeItemIndex(const QualifiedName& name) const 1041 { 1042 const Attribute* begin = attributeBase(); 1043 for (unsigned i = 0; i < length(); ++i) { 1044 const Attribute& attribute = begin[i]; 1045 if (attribute.name().matches(name)) 1046 return i; 1047 } 1048 return notFound; 1049 } 1050 1051 // We use a boolean parameter instead of calling shouldIgnoreAttributeCase so that the caller 1052 // can tune the behavior (hasAttribute is case sensitive whereas getAttribute is not). 1053 inline size_t ElementData::getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const 1054 { 1055 unsigned len = length(); 1056 bool doSlowCheck = shouldIgnoreAttributeCase; 1057 1058 // Optimize for the case where the attribute exists and its name exactly matches. 1059 const Attribute* begin = attributeBase(); 1060 for (unsigned i = 0; i < len; ++i) { 1061 const Attribute& attribute = begin[i]; 1062 if (!attribute.name().hasPrefix()) { 1063 if (name == attribute.localName()) 1064 return i; 1065 } else 1066 doSlowCheck = true; 1067 } 1068 1069 if (doSlowCheck) 1070 return getAttributeItemIndexSlowCase(name, shouldIgnoreAttributeCase); 1071 return notFound; 1072 } 1073 1074 inline const Attribute* ElementData::getAttributeItem(const QualifiedName& name) const 1075 { 1076 const Attribute* begin = attributeBase(); 1077 for (unsigned i = 0; i < length(); ++i) { 1078 const Attribute& attribute = begin[i]; 1079 if (attribute.name().matches(name)) 1080 return &attribute; 1081 } 1082 return 0; 1083 } 1084 1085 inline const Attribute* ElementData::attributeItem(unsigned index) const 1086 { 1087 RELEASE_ASSERT(index < length()); 1088 return attributeBase() + index; 1089 } 1090 1091 } // namespace 1092 1093 #endif 1094