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