1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
6 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
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 Node_h
26 #define Node_h
27
28 #include "bindings/v8/ExceptionStatePlaceholder.h"
29 #include "bindings/v8/ScriptWrappable.h"
30 #include "core/dom/MutationObserver.h"
31 #include "core/dom/SimulatedClickOptions.h"
32 #include "core/dom/TreeScope.h"
33 #include "core/dom/TreeShared.h"
34 #include "core/editing/EditingBoundary.h"
35 #include "core/events/EventTarget.h"
36 #include "core/inspector/InspectorCounters.h"
37 #include "core/rendering/style/RenderStyleConstants.h"
38 #include "platform/geometry/LayoutRect.h"
39 #include "platform/weborigin/KURLHash.h"
40 #include "wtf/Forward.h"
41 #include "wtf/ListHashSet.h"
42 #include "wtf/text/AtomicString.h"
43
44 // This needs to be here because Document.h also depends on it.
45 #define DUMP_NODE_STATISTICS 0
46
47 namespace WebCore {
48
49 class Attribute;
50 class ClassNodeList;
51 class ContainerNode;
52 class DOMSettableTokenList;
53 class Document;
54 class Element;
55 class Event;
56 class EventContext;
57 class EventDispatchMediator;
58 class EventListener;
59 class ExceptionState;
60 class FloatPoint;
61 class Frame;
62 class HTMLInputElement;
63 class IntRect;
64 class KeyboardEvent;
65 class NSResolver;
66 class NameNodeList;
67 class NamedNodeMap;
68 class NodeList;
69 class NodeListsNodeData;
70 class NodeRareData;
71 class NodeRenderingContext;
72 class PlatformGestureEvent;
73 class PlatformKeyboardEvent;
74 class PlatformMouseEvent;
75 class PlatformWheelEvent;
76 class QualifiedName;
77 class RadioNodeList;
78 class RegisteredEventListener;
79 class RenderBox;
80 class RenderBoxModelObject;
81 class RenderObject;
82 class RenderStyle;
83 class ShadowRoot;
84 class TagNodeList;
85 class Text;
86 class TouchEvent;
87
88 const int nodeStyleChangeShift = 14;
89
90 enum StyleChangeType {
91 NoStyleChange = 0,
92 LocalStyleChange = 1 << nodeStyleChangeShift,
93 SubtreeStyleChange = 2 << nodeStyleChangeShift,
94 NeedsReattachStyleChange = 3 << nodeStyleChangeShift,
95 };
96
97 // If the style change is from the renderer then we'll call setStyle on the
98 // renderer even if the style computed from CSS is identical.
99 enum StyleChangeSource {
100 StyleChangeFromCSS,
101 StyleChangeFromRenderer
102 };
103
104 class NodeRareDataBase {
105 public:
renderer()106 RenderObject* renderer() const { return m_renderer; }
setRenderer(RenderObject * renderer)107 void setRenderer(RenderObject* renderer) { m_renderer = renderer; }
108
109 protected:
NodeRareDataBase(RenderObject * renderer)110 NodeRareDataBase(RenderObject* renderer)
111 : m_renderer(renderer)
112 { }
113
114 private:
115 RenderObject* m_renderer;
116 };
117
118 class Node : public EventTarget, public ScriptWrappable, public TreeShared<Node> {
119 friend class Document;
120 friend class TreeScope;
121 friend class TreeScopeAdopter;
122
123 DEFINE_EVENT_TARGET_REFCOUNTING(TreeShared<Node>);
124 public:
125 enum NodeType {
126 ELEMENT_NODE = 1,
127 ATTRIBUTE_NODE = 2,
128 TEXT_NODE = 3,
129 CDATA_SECTION_NODE = 4,
130 ENTITY_NODE = 6,
131 PROCESSING_INSTRUCTION_NODE = 7,
132 COMMENT_NODE = 8,
133 DOCUMENT_NODE = 9,
134 DOCUMENT_TYPE_NODE = 10,
135 DOCUMENT_FRAGMENT_NODE = 11,
136 NOTATION_NODE = 12,
137 XPATH_NAMESPACE_NODE = 13,
138 };
139
140 // EntityReference nodes are deprecated and impossible to create in WebKit.
141 // We want Node.ENTITY_REFERNCE_NODE to exist in JS and this enum, makes the bindings
142 // generation not complain about ENTITY_REFERENCE_NODE being missing from the implementation
143 // while not requiring all switch(NodeType) blocks to include this deprecated constant.
144 enum DeprecatedNodeType {
145 ENTITY_REFERENCE_NODE = 5
146 };
147
148 enum DocumentPosition {
149 DOCUMENT_POSITION_EQUIVALENT = 0x00,
150 DOCUMENT_POSITION_DISCONNECTED = 0x01,
151 DOCUMENT_POSITION_PRECEDING = 0x02,
152 DOCUMENT_POSITION_FOLLOWING = 0x04,
153 DOCUMENT_POSITION_CONTAINS = 0x08,
154 DOCUMENT_POSITION_CONTAINED_BY = 0x10,
155 DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20,
156 };
157
158 // All Nodes are placed in their own heap partition for security.
159 // See http://crbug.com/246860 for detail.
160 void* operator new(size_t);
161 void operator delete(void*);
162
163 static bool isSupported(const String& feature, const String& version);
164 static void dumpStatistics();
165
166 virtual ~Node();
167
168 // DOM methods & attributes for Node
169
170 bool hasTagName(const QualifiedName&) const;
171 virtual String nodeName() const = 0;
172 virtual String nodeValue() const;
173 virtual void setNodeValue(const String&);
174 virtual NodeType nodeType() const = 0;
175 ContainerNode* parentNode() const;
176 Element* parentElement() const;
previousSibling()177 Node* previousSibling() const { return m_previous; }
nextSibling()178 Node* nextSibling() const { return m_next; }
179 PassRefPtr<NodeList> childNodes();
180 Node* firstChild() const;
181 Node* lastChild() const;
182
183 // ChildNode interface API
184 Element* previousElementSibling() const;
185 Element* nextElementSibling() const;
186 void remove(ExceptionState&);
187
188 Node* pseudoAwareNextSibling() const;
189 Node* pseudoAwarePreviousSibling() const;
190 Node* pseudoAwareFirstChild() const;
191 Node* pseudoAwareLastChild() const;
192
193 virtual KURL baseURI() const;
194
195 // These should all actually return a node, but this is only important for language bindings,
196 // which will already know and hold a ref on the right node to return.
197 void insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionState& = ASSERT_NO_EXCEPTION);
198 void replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionState& = ASSERT_NO_EXCEPTION);
199 void removeChild(Node* child, ExceptionState&);
200 void appendChild(PassRefPtr<Node> newChild, ExceptionState& = ASSERT_NO_EXCEPTION);
201
hasChildNodes()202 bool hasChildNodes() const { return firstChild(); }
203 virtual PassRefPtr<Node> cloneNode(bool deep = false) = 0;
204 virtual const AtomicString& localName() const;
205 virtual const AtomicString& namespaceURI() const;
206 virtual const AtomicString& prefix() const;
207 virtual void setPrefix(const AtomicString&, ExceptionState&);
208 void normalize();
209
isSameNode(Node * other)210 bool isSameNode(Node* other) const { return this == other; }
211 bool isEqualNode(Node*) const;
212 bool isDefaultNamespace(const AtomicString& namespaceURI) const;
213 const AtomicString& lookupPrefix(const AtomicString& namespaceURI) const;
214 const AtomicString& lookupNamespaceURI(const String& prefix) const;
215 const AtomicString& lookupNamespacePrefix(const AtomicString& namespaceURI, const Element* originalElement) const;
216
217 String textContent(bool convertBRsToNewlines = false) const;
218 void setTextContent(const String&);
219
220 Node& lastDescendant() const;
221
222 // Other methods (not part of DOM)
223
isElementNode()224 bool isElementNode() const { return getFlag(IsElementFlag); }
isContainerNode()225 bool isContainerNode() const { return getFlag(IsContainerFlag); }
isTextNode()226 bool isTextNode() const { return getFlag(IsTextFlag); }
isHTMLElement()227 bool isHTMLElement() const { return getFlag(IsHTMLFlag); }
isSVGElement()228 bool isSVGElement() const { return getFlag(IsSVGFlag); }
229
isPseudoElement()230 bool isPseudoElement() const { return pseudoId() != NOPSEUDO; }
isBeforePseudoElement()231 bool isBeforePseudoElement() const { return pseudoId() == BEFORE; }
isAfterPseudoElement()232 bool isAfterPseudoElement() const { return pseudoId() == AFTER; }
pseudoId()233 PseudoId pseudoId() const { return (isElementNode() && hasCustomStyleCallbacks()) ? customPseudoId() : NOPSEUDO; }
234
isCustomElement()235 bool isCustomElement() const { return getFlag(CustomElement); }
236 enum CustomElementState {
237 NotCustomElement = 0,
238 WaitingForUpgrade = 1 << 0,
239 Upgraded = 1 << 1
240 };
customElementState()241 CustomElementState customElementState() const
242 {
243 return isCustomElement()
244 ? (getFlag(CustomElementUpgraded) ? Upgraded : WaitingForUpgrade)
245 : NotCustomElement;
246 }
247 void setCustomElementState(CustomElementState newState);
248
isMediaControlElement()249 virtual bool isMediaControlElement() const { return false; }
isMediaControls()250 virtual bool isMediaControls() const { return false; }
isVTTElement()251 virtual bool isVTTElement() const { return false; }
isAttributeNode()252 virtual bool isAttributeNode() const { return false; }
isCharacterDataNode()253 virtual bool isCharacterDataNode() const { return false; }
isFrameOwnerElement()254 virtual bool isFrameOwnerElement() const { return false; }
isPluginElement()255 virtual bool isPluginElement() const { return false; }
256
257 // StyledElements allow inline style (style="border: 1px"), presentational attributes (ex. color),
258 // class names (ex. class="foo bar") and other non-basic styling features. They and also control
259 // if this element can participate in style sharing.
260 //
261 // FIXME: The only things that ever go through StyleResolver that aren't StyledElements are
262 // PseudoElements and VTTElements. It's possible we can just eliminate all the checks
263 // since those elements will never have class names, inline style, or other things that
264 // this apparently guards against.
isStyledElement()265 bool isStyledElement() const { return isHTMLElement() || isSVGElement(); }
266
267 bool isDocumentNode() const;
isTreeScope()268 bool isTreeScope() const { return treeScope().rootNode() == this; }
isDocumentFragment()269 bool isDocumentFragment() const { return getFlag(IsDocumentFragmentFlag); }
isShadowRoot()270 bool isShadowRoot() const { return isDocumentFragment() && isTreeScope(); }
isInsertionPoint()271 bool isInsertionPoint() const { return getFlag(IsInsertionPointFlag); }
272
inNamedFlow()273 bool inNamedFlow() const { return getFlag(InNamedFlowFlag); }
hasCustomStyleCallbacks()274 bool hasCustomStyleCallbacks() const { return getFlag(HasCustomStyleCallbacksFlag); }
275
276 bool isRegisteredWithNamedFlow() const;
277
hasSyntheticAttrChildNodes()278 bool hasSyntheticAttrChildNodes() const { return getFlag(HasSyntheticAttrChildNodesFlag); }
setHasSyntheticAttrChildNodes(bool flag)279 void setHasSyntheticAttrChildNodes(bool flag) { setFlag(flag, HasSyntheticAttrChildNodesFlag); }
280
281 // If this node is in a shadow tree, returns its shadow host. Otherwise, returns 0.
282 Element* shadowHost() const;
283 // If this node is in a shadow tree, returns its shadow host. Otherwise, returns this.
284 // Deprecated. Should use shadowHost() and check the return value.
285 Node* deprecatedShadowAncestorNode() const;
286 ShadowRoot* containingShadowRoot() const;
287 ShadowRoot* youngestShadowRoot() const;
288
289 // Returns 0, a child of ShadowRoot, or a legacy shadow root.
290 Node* nonBoundaryShadowTreeRootNode();
291
292 // Node's parent, shadow tree host.
293 ContainerNode* parentOrShadowHostNode() const;
294 Element* parentOrShadowHostElement() const;
295 void setParentOrShadowHostNode(ContainerNode*);
296 Node* highestAncestor() const;
297
298 // Knows about all kinds of hosts.
299 ContainerNode* parentOrShadowHostOrTemplateHostNode() const;
300
301 // Returns the parent node, but 0 if the parent node is a ShadowRoot.
302 ContainerNode* nonShadowBoundaryParentNode() const;
303
selfOrAncestorHasDirAutoAttribute()304 bool selfOrAncestorHasDirAutoAttribute() const { return getFlag(SelfOrAncestorHasDirAutoFlag); }
setSelfOrAncestorHasDirAutoAttribute(bool flag)305 void setSelfOrAncestorHasDirAutoAttribute(bool flag) { setFlag(flag, SelfOrAncestorHasDirAutoFlag); }
306
307 // Returns the enclosing event parent node (or self) that, when clicked, would trigger a navigation.
308 Node* enclosingLinkEventParentOrSelf();
309
310 bool isBlockFlowElement() const;
311
312 // These low-level calls give the caller responsibility for maintaining the integrity of the tree.
setPreviousSibling(Node * previous)313 void setPreviousSibling(Node* previous) { m_previous = previous; }
setNextSibling(Node * next)314 void setNextSibling(Node* next) { m_next = next; }
315
canContainRangeEndPoint()316 virtual bool canContainRangeEndPoint() const { return false; }
317
318 // FIXME: These two functions belong in editing -- "atomic node" is an editing concept.
319 Node* previousNodeConsideringAtomicNodes() const;
320 Node* nextNodeConsideringAtomicNodes() const;
321
322 // Returns the next leaf node or 0 if there are no more.
323 // Delivers leaf nodes as if the whole DOM tree were a linear chain of its leaf nodes.
324 // Uses an editing-specific concept of what a leaf node is, and should probably be moved
325 // out of the Node class into an editing-specific source file.
326 Node* nextLeafNode() const;
327
328 // Returns the previous leaf node or 0 if there are no more.
329 // Delivers leaf nodes as if the whole DOM tree were a linear chain of its leaf nodes.
330 // Uses an editing-specific concept of what a leaf node is, and should probably be moved
331 // out of the Node class into an editing-specific source file.
332 Node* previousLeafNode() const;
333
334 // enclosingBlockFlowElement() is deprecated. Use enclosingBlock instead.
335 Element* enclosingBlockFlowElement() const;
336
337 bool isRootEditableElement() const;
338 Element* rootEditableElement() const;
339 Element* rootEditableElement(EditableType) const;
340
341 bool inSameContainingBlockFlowElement(Node*);
342
343 // Called by the parser when this element's close tag is reached,
344 // signaling that all child tags have been parsed and added.
345 // This is needed for <applet> and <object> elements, which can't lay themselves out
346 // until they know all of their nested <param>s. [Radar 3603191, 4040848].
347 // Also used for script elements and some SVG elements for similar purposes,
348 // but making parsing a special case in this respect should be avoided if possible.
finishParsingChildren()349 virtual void finishParsingChildren() { }
beginParsingChildren()350 virtual void beginParsingChildren() { }
351
352 // For <link> and <style> elements.
sheetLoaded()353 virtual bool sheetLoaded() { return true; }
notifyLoadedSheetAndAllCriticalSubresources(bool)354 virtual void notifyLoadedSheetAndAllCriticalSubresources(bool /* error loading subresource */) { }
startLoadingDynamicSheet()355 virtual void startLoadingDynamicSheet() { ASSERT_NOT_REACHED(); }
356
hasName()357 bool hasName() const { return !isTextNode() && getFlag(HasNameOrIsEditingTextFlag); }
358 bool hasID() const;
359 bool hasClass() const;
360
isUserActionElement()361 bool isUserActionElement() const { return getFlag(IsUserActionElement); }
setUserActionElement(bool flag)362 void setUserActionElement(bool flag) { setFlag(flag, IsUserActionElement); }
363
active()364 bool active() const { return isUserActionElement() && isUserActionElementActive(); }
inActiveChain()365 bool inActiveChain() const { return isUserActionElement() && isUserActionElementInActiveChain(); }
hovered()366 bool hovered() const { return isUserActionElement() && isUserActionElementHovered(); }
focused()367 bool focused() const { return isUserActionElement() && isUserActionElementFocused(); }
368
needsAttach()369 bool needsAttach() const { return styleChangeType() == NeedsReattachStyleChange; }
needsStyleRecalc()370 bool needsStyleRecalc() const { return styleChangeType() != NoStyleChange; }
styleChangeType()371 StyleChangeType styleChangeType() const { return static_cast<StyleChangeType>(m_nodeFlags & StyleChangeMask); }
childNeedsStyleRecalc()372 bool childNeedsStyleRecalc() const { return getFlag(ChildNeedsStyleRecalcFlag); }
isLink()373 bool isLink() const { return getFlag(IsLinkFlag); }
isEditingText()374 bool isEditingText() const { return isTextNode() && getFlag(HasNameOrIsEditingTextFlag); }
375
setHasName(bool f)376 void setHasName(bool f) { ASSERT(!isTextNode()); setFlag(f, HasNameOrIsEditingTextFlag); }
setChildNeedsStyleRecalc()377 void setChildNeedsStyleRecalc() { setFlag(ChildNeedsStyleRecalcFlag); }
clearChildNeedsStyleRecalc()378 void clearChildNeedsStyleRecalc() { clearFlag(ChildNeedsStyleRecalcFlag); }
379
380 void setNeedsStyleRecalc(StyleChangeType = SubtreeStyleChange, StyleChangeSource = StyleChangeFromCSS);
381 void clearNeedsStyleRecalc();
382
childNeedsDistributionRecalc()383 bool childNeedsDistributionRecalc() const { return getFlag(ChildNeedsDistributionRecalc); }
setChildNeedsDistributionRecalc()384 void setChildNeedsDistributionRecalc() { setFlag(ChildNeedsDistributionRecalc); }
clearChildNeedsDistributionRecalc()385 void clearChildNeedsDistributionRecalc() { clearFlag(ChildNeedsDistributionRecalc); }
386 void markAncestorsWithChildNeedsDistributionRecalc();
387
388 void recalcDistribution();
389
shouldNotifyRendererWithIdenticalStyles()390 bool shouldNotifyRendererWithIdenticalStyles() const { return getFlag(NotifyRendererWithIdenticalStyles); }
391
392 void setIsLink(bool f);
393
setInNamedFlow()394 void setInNamedFlow() { setFlag(InNamedFlowFlag); }
clearInNamedFlow()395 void clearInNamedFlow() { clearFlag(InNamedFlowFlag); }
396
hasScopedHTMLStyleChild()397 bool hasScopedHTMLStyleChild() const { return getFlag(HasScopedHTMLStyleChildFlag); }
setHasScopedHTMLStyleChild(bool flag)398 void setHasScopedHTMLStyleChild(bool flag) { setFlag(flag, HasScopedHTMLStyleChildFlag); }
399
hasEventTargetData()400 bool hasEventTargetData() const { return getFlag(HasEventTargetDataFlag); }
setHasEventTargetData(bool flag)401 void setHasEventTargetData(bool flag) { setFlag(flag, HasEventTargetDataFlag); }
402
isV8CollectableDuringMinorGC()403 bool isV8CollectableDuringMinorGC() const { return getFlag(V8CollectableDuringMinorGCFlag); }
setV8CollectableDuringMinorGC(bool flag)404 void setV8CollectableDuringMinorGC(bool flag) { setFlag(flag, V8CollectableDuringMinorGCFlag); }
405
406 virtual void setFocus(bool flag);
407 virtual void setActive(bool flag = true);
408 virtual void setHovered(bool flag = true);
409
410 virtual short tabIndex() const;
411
412 virtual Node* focusDelegate();
413 // This is called only when the node is focused.
414 virtual bool shouldHaveFocusAppearance() const;
415
416 // Whether the node is inert. This can't be in Element because text nodes
417 // must be recognized as inert to prevent text selection.
418 bool isInert() const;
419
420 enum UserSelectAllTreatment {
421 UserSelectAllDoesNotAffectEditability,
422 UserSelectAllIsAlwaysNonEditable
423 };
424 bool isContentEditable(UserSelectAllTreatment = UserSelectAllDoesNotAffectEditability);
425 bool isContentRichlyEditable();
426
427 bool rendererIsEditable(EditableType editableType = ContentIsEditable, UserSelectAllTreatment treatment = UserSelectAllIsAlwaysNonEditable) const
428 {
429 switch (editableType) {
430 case ContentIsEditable:
431 return rendererIsEditable(Editable, treatment);
432 case HasEditableAXRole:
433 return isEditableToAccessibility(Editable);
434 }
435 ASSERT_NOT_REACHED();
436 return false;
437 }
438
439 bool rendererIsRichlyEditable(EditableType editableType = ContentIsEditable) const
440 {
441 switch (editableType) {
442 case ContentIsEditable:
443 return rendererIsEditable(RichlyEditable, UserSelectAllIsAlwaysNonEditable);
444 case HasEditableAXRole:
445 return isEditableToAccessibility(RichlyEditable);
446 }
447 ASSERT_NOT_REACHED();
448 return false;
449 }
450
451 virtual bool shouldUseInputMethod();
452 virtual LayoutRect boundingBox() const;
pixelSnappedBoundingBox()453 IntRect pixelSnappedBoundingBox() const { return pixelSnappedIntRect(boundingBox()); }
454
455 // Returns true if the node has a non-empty bounding box in layout.
456 // This does not 100% guarantee the user can see it, but is pretty close.
457 // Note: This method only works properly after layout has occurred.
458 bool hasNonEmptyBoundingBox() const;
459
460 unsigned nodeIndex() const;
461
462 // Returns the DOM ownerDocument attribute. This method never returns NULL, except in the case
463 // of a Document node.
464 Document* ownerDocument() const;
465
466 // Returns the document associated with this node. A Document node returns itself.
document()467 Document& document() const
468 {
469 ASSERT(this);
470 ASSERT(documentInternal());
471 return *documentInternal();
472 }
473
treeScope()474 TreeScope& treeScope() const
475 {
476 ASSERT(m_treeScope);
477 return *m_treeScope;
478 }
479
480 bool inActiveDocument() const;
481
482 // Returns true if this node is associated with a document and is in its associated document's
483 // node tree, false otherwise.
inDocument()484 bool inDocument() const
485 {
486 ASSERT(documentInternal() || !getFlag(InDocumentFlag));
487 return getFlag(InDocumentFlag);
488 }
isInShadowTree()489 bool isInShadowTree() const { return getFlag(IsInShadowTreeFlag); }
isInTreeScope()490 bool isInTreeScope() const { return getFlag(static_cast<NodeFlags>(InDocumentFlag | IsInShadowTreeFlag)); }
491
isDocumentTypeNode()492 bool isDocumentTypeNode() const { return nodeType() == DOCUMENT_TYPE_NODE; }
childTypeAllowed(NodeType)493 virtual bool childTypeAllowed(NodeType) const { return false; }
494 unsigned childNodeCount() const;
495 Node* childNode(unsigned index) const;
496
497 void checkSetPrefix(const AtomicString& prefix, ExceptionState&);
498 bool isDescendantOf(const Node*) const;
499 bool contains(const Node*) const;
500 bool containsIncludingShadowDOM(const Node*) const;
501 bool containsIncludingHostElements(const Node&) const;
502 Node* commonAncestor(const Node&, Node* (*parent)(const Node&));
503
504 // FIXME: Remove this when crbug.com/265716 cleans up contains semantics.
bindingsContains(const Node * node)505 bool bindingsContains(const Node* node) const { return containsIncludingShadowDOM(node); }
506
507 // Used to determine whether range offsets use characters or node indices.
508 virtual bool offsetInCharacters() const;
509 // Number of DOM 16-bit units contained in node. Note that rendered text length can be different - e.g. because of
510 // css-transform:capitalize breaking up precomposed characters and ligatures.
511 virtual int maxCharacterOffset() const;
512
513 // Whether or not a selection can be started in this object
514 virtual bool canStartSelection() const;
515
516 // Getting points into and out of screen space
517 FloatPoint convertToPage(const FloatPoint&) const;
518 FloatPoint convertFromPage(const FloatPoint&) const;
519
520 // -----------------------------------------------------------------------------
521 // Integration with rendering tree
522
523 // As renderer() includes a branch you should avoid calling it repeatedly in hot code paths.
524 // Note that if a Node has a renderer, it's parentNode is guaranteed to have one as well.
renderer()525 RenderObject* renderer() const { return hasRareData() ? m_data.m_rareData->renderer() : m_data.m_renderer; };
setRenderer(RenderObject * renderer)526 void setRenderer(RenderObject* renderer)
527 {
528 if (hasRareData())
529 m_data.m_rareData->setRenderer(renderer);
530 else
531 m_data.m_renderer = renderer;
532 }
hasRenderer()533 bool hasRenderer() const { return renderer(); }
534
535 // Use these two methods with caution.
536 RenderBox* renderBox() const;
537 RenderBoxModelObject* renderBoxModelObject() const;
538
539 struct AttachContext {
540 RenderStyle* resolvedStyle;
541 bool performingReattach;
542
AttachContextAttachContext543 AttachContext() : resolvedStyle(0), performingReattach(false) { }
544 };
545
546 // Attaches this node to the rendering tree. This calculates the style to be applied to the node and creates an
547 // appropriate RenderObject which will be inserted into the tree (except when the style has display: none). This
548 // makes the node visible in the FrameView.
549 virtual void attach(const AttachContext& = AttachContext());
550
551 // Detaches the node from the rendering tree, making it invisible in the rendered view. This method will remove
552 // the node's rendering object from the rendering tree and delete it.
553 virtual void detach(const AttachContext& = AttachContext());
554
555 #ifndef NDEBUG
556 bool inDetach() const;
557 #endif
558
559 void reattach(const AttachContext& = AttachContext());
560 void lazyReattachIfAttached();
561
562 // Wrapper for nodes that don't have a renderer, but still cache the style (like HTMLOptionElement).
563 RenderStyle* renderStyle() const;
564 RenderStyle* parentRenderStyle() const;
565
566 RenderStyle* computedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return virtualComputedStyle(pseudoElementSpecifier); }
567
568 // -----------------------------------------------------------------------------
569 // Notification of document structure changes (see ContainerNode.h for more notification methods)
570 //
571 // At first, WebKit notifies the node that it has been inserted into the document. This is called during document parsing, and also
572 // when a node is added through the DOM methods insertBefore(), appendChild() or replaceChild(). The call happens _after_ the node has been added to the tree.
573 // This is similar to the DOMNodeInsertedIntoDocument DOM event, but does not require the overhead of event
574 // dispatching.
575 //
576 // WebKit notifies this callback regardless if the subtree of the node is a document tree or a floating subtree.
577 // Implementation can determine the type of subtree by seeing insertionPoint->inDocument().
578 // For a performance reason, notifications are delivered only to ContainerNode subclasses if the insertionPoint is out of document.
579 //
580 // There are another callback named didNotifySubtreeInsertionsToDocument(), which is called after all the descendant is notified,
581 // if this node was inserted into the document tree. Only a few subclasses actually need this. To utilize this, the node should
582 // return InsertionShouldCallDidNotifySubtreeInsertions from insrtedInto().
583 //
584 enum InsertionNotificationRequest {
585 InsertionDone,
586 InsertionShouldCallDidNotifySubtreeInsertions
587 };
588
589 virtual InsertionNotificationRequest insertedInto(ContainerNode* insertionPoint);
didNotifySubtreeInsertionsToDocument()590 virtual void didNotifySubtreeInsertionsToDocument() { }
591
592 // Notifies the node that it is no longer part of the tree.
593 //
594 // This is a dual of insertedInto(), and is similar to the DOMNodeRemovedFromDocument DOM event, but does not require the overhead of event
595 // dispatching, and is called _after_ the node is removed from the tree.
596 //
597 virtual void removedFrom(ContainerNode* insertionPoint);
598
599 String debugName() const;
600
601 #ifndef NDEBUG
602 virtual void formatForDebugger(char* buffer, unsigned length) const;
603
604 void showNode(const char* prefix = "") const;
605 void showTreeForThis() const;
606 void showNodePathForThis() const;
607 void showTreeAndMark(const Node* markedNode1, const char* markedLabel1, const Node* markedNode2 = 0, const char* markedLabel2 = 0) const;
608 void showTreeForThisAcrossFrame() const;
609 #endif
610
611 void invalidateNodeListCachesInAncestors(const QualifiedName* attrName = 0, Element* attributeOwnerElement = 0);
612 NodeListsNodeData* nodeLists();
613 void clearNodeLists();
614
615 PassRefPtr<NodeList> getElementsByTagName(const AtomicString&);
616 PassRefPtr<NodeList> getElementsByTagNameNS(const AtomicString& namespaceURI, const AtomicString& localName);
617 PassRefPtr<NodeList> getElementsByName(const String& elementName);
618 PassRefPtr<NodeList> getElementsByClassName(const String& classNames);
619 PassRefPtr<RadioNodeList> radioNodeList(const AtomicString&);
620
621 virtual bool willRespondToMouseMoveEvents();
622 virtual bool willRespondToMouseClickEvents();
623 virtual bool willRespondToTouchEvents();
624
625 PassRefPtr<Element> querySelector(const AtomicString& selectors, ExceptionState&);
626 PassRefPtr<NodeList> querySelectorAll(const AtomicString& selectors, ExceptionState&);
627
628 unsigned short compareDocumentPosition(const Node*) const;
629
630 enum ShadowTreesTreatment {
631 TreatShadowTreesAsDisconnected,
632 TreatShadowTreesAsComposed
633 };
634
635 unsigned short compareDocumentPositionInternal(const Node*, ShadowTreesTreatment) const;
636
637 virtual Node* toNode();
638
639 virtual const AtomicString& interfaceName() const OVERRIDE;
640 virtual ExecutionContext* executionContext() const OVERRIDE;
641
642 virtual bool addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture);
643 virtual bool removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture);
644
645 // Handlers to do/undo actions on the target node before an event is dispatched to it and after the event
646 // has been dispatched. The data pointer is handed back by the preDispatch and passed to postDispatch.
preDispatchEventHandler(Event *)647 virtual void* preDispatchEventHandler(Event*) { return 0; }
postDispatchEventHandler(Event *,void *)648 virtual void postDispatchEventHandler(Event*, void* /*dataFromPreDispatch*/) { }
649
650 using EventTarget::dispatchEvent;
651 virtual bool dispatchEvent(PassRefPtr<Event>) OVERRIDE;
652
653 void dispatchScopedEvent(PassRefPtr<Event>);
654 void dispatchScopedEventDispatchMediator(PassRefPtr<EventDispatchMediator>);
655
656 virtual void handleLocalEvents(Event*);
657
658 void dispatchSubtreeModifiedEvent();
659 bool dispatchDOMActivateEvent(int detail, PassRefPtr<Event> underlyingEvent);
660
661 bool dispatchKeyEvent(const PlatformKeyboardEvent&);
662 bool dispatchWheelEvent(const PlatformWheelEvent&);
663 bool dispatchMouseEvent(const PlatformMouseEvent&, const AtomicString& eventType, int clickCount = 0, Node* relatedTarget = 0);
664 bool dispatchGestureEvent(const PlatformGestureEvent&);
665 bool dispatchTouchEvent(PassRefPtr<TouchEvent>);
666
667 void dispatchSimulatedClick(Event* underlyingEvent, SimulatedClickMouseEventOptions = SendNoEvents);
668
669 virtual bool dispatchBeforeLoadEvent(const String& sourceURL);
670 virtual void dispatchChangeEvent();
671 virtual void dispatchInputEvent();
672
673 // Perform the default action for an event.
674 virtual void defaultEventHandler(Event*);
675 virtual void willCallDefaultEventHandler(const Event&);
676
677 virtual EventTargetData* eventTargetData() OVERRIDE;
678 virtual EventTargetData& ensureEventTargetData() OVERRIDE;
679
680 void getRegisteredMutationObserversOfType(HashMap<MutationObserver*, MutationRecordDeliveryOptions>&, MutationObserver::MutationType, const QualifiedName* attributeName);
681 void registerMutationObserver(MutationObserver*, MutationObserverOptions, const HashSet<AtomicString>& attributeFilter);
682 void unregisterMutationObserver(MutationObserverRegistration*);
683 void registerTransientMutationObserver(MutationObserverRegistration*);
684 void unregisterTransientMutationObserver(MutationObserverRegistration*);
685 void notifyMutationObserversNodeWillDetach();
686
687 virtual void registerScopedHTMLStyleChild();
688 virtual void unregisterScopedHTMLStyleChild();
689 size_t numberOfScopedHTMLStyleChildren() const;
690
691 unsigned connectedSubframeCount() const;
692 void incrementConnectedSubframeCount(unsigned amount = 1);
693 void decrementConnectedSubframeCount(unsigned amount = 1);
694 void updateAncestorConnectedSubframeCountForRemoval() const;
695 void updateAncestorConnectedSubframeCountForInsertion() const;
696
697 PassRefPtr<NodeList> getDestinationInsertionPoints();
698
setAlreadySpellChecked(bool flag)699 void setAlreadySpellChecked(bool flag) { setFlag(flag, AlreadySpellCheckedFlag); }
isAlreadySpellChecked()700 bool isAlreadySpellChecked() { return getFlag(AlreadySpellCheckedFlag); }
701
702 private:
703 enum NodeFlags {
704 IsTextFlag = 1,
705 IsContainerFlag = 1 << 1,
706 IsElementFlag = 1 << 2,
707 IsHTMLFlag = 1 << 3,
708 IsSVGFlag = 1 << 4,
709
710 ChildNeedsDistributionRecalc = 1 << 5,
711 ChildNeedsStyleRecalcFlag = 1 << 6,
712 InDocumentFlag = 1 << 7,
713 IsLinkFlag = 1 << 8,
714 IsUserActionElement = 1 << 9,
715 HasRareDataFlag = 1 << 10,
716 IsDocumentFragmentFlag = 1 << 11,
717
718 // These bits are used by derived classes, pulled up here so they can
719 // be stored in the same memory word as the Node bits above.
720 IsParsingChildrenFinishedFlag = 1 << 12, // Element
721 HasSVGRareDataFlag = 1 << 13, // SVGElement
722
723 StyleChangeMask = 1 << nodeStyleChangeShift | 1 << (nodeStyleChangeShift + 1),
724
725 SelfOrAncestorHasDirAutoFlag = 1 << 16,
726
727 HasNameOrIsEditingTextFlag = 1 << 17,
728
729 InNamedFlowFlag = 1 << 18,
730 HasSyntheticAttrChildNodesFlag = 1 << 19,
731 HasCustomStyleCallbacksFlag = 1 << 20,
732 HasScopedHTMLStyleChildFlag = 1 << 21,
733 HasEventTargetDataFlag = 1 << 22,
734 V8CollectableDuringMinorGCFlag = 1 << 23,
735 IsInsertionPointFlag = 1 << 24,
736 IsInShadowTreeFlag = 1 << 25,
737
738 NotifyRendererWithIdenticalStyles = 1 << 26,
739
740 CustomElement = 1 << 27,
741 CustomElementUpgraded = 1 << 28,
742
743 AlreadySpellCheckedFlag = 1 << 29,
744
745 DefaultNodeFlags = IsParsingChildrenFinishedFlag | ChildNeedsStyleRecalcFlag | NeedsReattachStyleChange
746 };
747
748 // 3 bits remaining.
749
getFlag(NodeFlags mask)750 bool getFlag(NodeFlags mask) const { return m_nodeFlags & mask; }
setFlag(bool f,NodeFlags mask)751 void setFlag(bool f, NodeFlags mask) const { m_nodeFlags = (m_nodeFlags & ~mask) | (-(int32_t)f & mask); }
setFlag(NodeFlags mask)752 void setFlag(NodeFlags mask) const { m_nodeFlags |= mask; }
clearFlag(NodeFlags mask)753 void clearFlag(NodeFlags mask) const { m_nodeFlags &= ~mask; }
754
755 protected:
756 enum ConstructionType {
757 CreateOther = DefaultNodeFlags,
758 CreateText = DefaultNodeFlags | IsTextFlag,
759 CreateContainer = DefaultNodeFlags | IsContainerFlag,
760 CreateElement = CreateContainer | IsElementFlag,
761 CreateShadowRoot = CreateContainer | IsDocumentFragmentFlag | IsInShadowTreeFlag,
762 CreateDocumentFragment = CreateContainer | IsDocumentFragmentFlag,
763 CreateHTMLElement = CreateElement | IsHTMLFlag,
764 CreateSVGElement = CreateElement | IsSVGFlag,
765 CreateDocument = CreateContainer | InDocumentFlag,
766 CreateInsertionPoint = CreateHTMLElement | IsInsertionPointFlag,
767 CreateEditingText = CreateText | HasNameOrIsEditingTextFlag,
768 };
769
Node(TreeScope * treeScope,ConstructionType type)770 Node(TreeScope* treeScope, ConstructionType type)
771 : m_nodeFlags(type)
772 , m_parentOrShadowHostNode(0)
773 , m_treeScope(treeScope)
774 , m_previous(0)
775 , m_next(0)
776 {
777 ASSERT(m_treeScope || type == CreateDocument || type == CreateShadowRoot);
778 ScriptWrappable::init(this);
779 if (m_treeScope)
780 m_treeScope->guardRef();
781
782 #if !defined(NDEBUG) || (defined(DUMP_NODE_STATISTICS) && DUMP_NODE_STATISTICS)
783 trackForDebugging();
784 #endif
785 InspectorCounters::incrementCounter(InspectorCounters::NodeCounter);
786 }
787
788 virtual void didMoveToNewDocument(Document& oldDocument);
789
addSubresourceAttributeURLs(ListHashSet<KURL> &)790 virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const { }
791
792 static void reattachWhitespaceSiblings(Text* start);
793
794 void willBeDeletedFromDocument();
795
hasRareData()796 bool hasRareData() const { return getFlag(HasRareDataFlag); }
797
798 NodeRareData* rareData() const;
799 NodeRareData& ensureRareData();
800 void clearRareData();
801
802 void clearEventTargetData();
803
setHasCustomStyleCallbacks()804 void setHasCustomStyleCallbacks() { setFlag(true, HasCustomStyleCallbacksFlag); }
805
documentInternal()806 Document* documentInternal() const { return treeScope().documentScope(); }
setTreeScope(TreeScope * scope)807 void setTreeScope(TreeScope* scope) { m_treeScope = scope; }
808
809 // isTreeScopeInitialized() can be false
810 // - in the destruction of Document or ShadowRoot where m_treeScope is set to null or
811 // - in the Node constructor called by these two classes where m_treeScope is set by TreeScope ctor.
isTreeScopeInitialized()812 bool isTreeScopeInitialized() const { return m_treeScope; }
813
814 void markAncestorsWithChildNeedsStyleRecalc();
815
816 private:
817 friend class TreeShared<Node>;
818
customPseudoId()819 virtual PseudoId customPseudoId() const
820 {
821 ASSERT(hasCustomStyleCallbacks());
822 return NOPSEUDO;
823 }
824
825 void removedLastRef();
hasTreeSharedParent()826 bool hasTreeSharedParent() const { return !!parentOrShadowHostNode(); }
827
828 enum EditableLevel { Editable, RichlyEditable };
829 bool rendererIsEditable(EditableLevel, UserSelectAllTreatment = UserSelectAllIsAlwaysNonEditable) const;
830 bool isEditableToAccessibility(EditableLevel) const;
831
832 bool isUserActionElementActive() const;
833 bool isUserActionElementInActiveChain() const;
834 bool isUserActionElementHovered() const;
835 bool isUserActionElementFocused() const;
836
837 void traceStyleChange(StyleChangeType);
838 void traceStyleChangeIfNeeded(StyleChangeType);
839 void setStyleChange(StyleChangeType);
840
nonRendererStyle()841 virtual RenderStyle* nonRendererStyle() const { return 0; }
842
843 virtual RenderStyle* virtualComputedStyle(PseudoId = NOPSEUDO);
844
845 Element* ancestorElement() const;
846
847 void trackForDebugging();
848
849 Vector<OwnPtr<MutationObserverRegistration> >* mutationObserverRegistry();
850 HashSet<MutationObserverRegistration*>* transientMutationObserverRegistry();
851
852 mutable uint32_t m_nodeFlags;
853 ContainerNode* m_parentOrShadowHostNode;
854 TreeScope* m_treeScope;
855 Node* m_previous;
856 Node* m_next;
857 // When a node has rare data we move the renderer into the rare data.
858 union DataUnion {
DataUnion()859 DataUnion() : m_renderer(0) { }
860 RenderObject* m_renderer;
861 NodeRareDataBase* m_rareData;
862 } m_data;
863
864 protected:
isParsingChildrenFinished()865 bool isParsingChildrenFinished() const { return getFlag(IsParsingChildrenFinishedFlag); }
setIsParsingChildrenFinished()866 void setIsParsingChildrenFinished() { setFlag(IsParsingChildrenFinishedFlag); }
clearIsParsingChildrenFinished()867 void clearIsParsingChildrenFinished() { clearFlag(IsParsingChildrenFinishedFlag); }
868
hasSVGRareData()869 bool hasSVGRareData() const { return getFlag(HasSVGRareDataFlag); }
setHasSVGRareData()870 void setHasSVGRareData() { setFlag(HasSVGRareDataFlag); }
clearHasSVGRareData()871 void clearHasSVGRareData() { clearFlag(HasSVGRareDataFlag); }
872 };
873
874 // Used in Node::addSubresourceAttributeURLs() and in addSubresourceStyleURLs()
addSubresourceURL(ListHashSet<KURL> & urls,const KURL & url)875 inline void addSubresourceURL(ListHashSet<KURL>& urls, const KURL& url)
876 {
877 if (!url.isNull())
878 urls.add(url);
879 }
880
setParentOrShadowHostNode(ContainerNode * parent)881 inline void Node::setParentOrShadowHostNode(ContainerNode* parent)
882 {
883 ASSERT(isMainThread());
884 m_parentOrShadowHostNode = parent;
885 }
886
parentOrShadowHostNode()887 inline ContainerNode* Node::parentOrShadowHostNode() const
888 {
889 ASSERT(isMainThread());
890 return m_parentOrShadowHostNode;
891 }
892
parentNode()893 inline ContainerNode* Node::parentNode() const
894 {
895 return isShadowRoot() ? 0 : parentOrShadowHostNode();
896 }
897
lazyReattachIfAttached()898 inline void Node::lazyReattachIfAttached()
899 {
900 if (styleChangeType() == NeedsReattachStyleChange)
901 return;
902 if (!inActiveDocument())
903 return;
904
905 AttachContext context;
906 context.performingReattach = true;
907
908 detach(context);
909 markAncestorsWithChildNeedsStyleRecalc();
910 }
911
shouldRecalcStyle(StyleRecalcChange change,const Node * node)912 inline bool shouldRecalcStyle(StyleRecalcChange change, const Node* node)
913 {
914 return change >= Inherit || node->childNeedsStyleRecalc() || node->needsStyleRecalc();
915 }
916
isTreeScopeRoot(const Node * node)917 inline bool isTreeScopeRoot(const Node* node)
918 {
919 return !node || node->isDocumentNode() || node->isShadowRoot();
920 }
921
isTreeScopeRoot(const Node & node)922 inline bool isTreeScopeRoot(const Node& node)
923 {
924 return node.isDocumentNode() || node.isShadowRoot();
925 }
926
927 // Allow equality comparisons of Nodes by reference or pointer, interchangeably.
928 inline bool operator==(const Node& a, const Node& b) { return &a == &b; }
929 inline bool operator==(const Node& a, const Node* b) { return &a == b; }
930 inline bool operator==(const Node* a, const Node& b) { return a == &b; }
931 inline bool operator!=(const Node& a, const Node& b) { return !(a == b); }
932 inline bool operator!=(const Node& a, const Node* b) { return !(a == b); }
933 inline bool operator!=(const Node* a, const Node& b) { return !(a == b); }
934 inline bool operator==(const PassRefPtr<Node>& a, const Node& b) { return a.get() == &b; }
935 inline bool operator==(const Node& a, const PassRefPtr<Node>& b) { return &a == b.get(); }
936 inline bool operator!=(const PassRefPtr<Node>& a, const Node& b) { return !(a == b); }
937 inline bool operator!=(const Node& a, const PassRefPtr<Node>& b) { return !(a == b); }
938
939
940 #define DEFINE_NODE_TYPE_CASTS(thisType, predicate) \
941 template<typename T> inline thisType* to##thisType(const RefPtr<T>& node) { return to##thisType(node.get()); } \
942 DEFINE_TYPE_CASTS(thisType, Node, node, node->predicate, node.predicate)
943
944 // This requires isClassName(const Node&).
945 #define DEFINE_NODE_TYPE_CASTS_WITH_FUNCTION(thisType) \
946 template<typename T> inline thisType* to##thisType(const RefPtr<T>& node) { return to##thisType(node.get()); } \
947 DEFINE_TYPE_CASTS(thisType, Node, node, is##thisType(*node), is##thisType(node))
948
949 } // namespace WebCore
950
951 #ifndef NDEBUG
952 // Outside the WebCore namespace for ease of invocation from gdb.
953 void showTree(const WebCore::Node*);
954 void showNodePath(const WebCore::Node*);
955 #endif
956
957 #endif
958