1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef nsIContent_h___
7 #define nsIContent_h___
8
9 #include "mozilla/Attributes.h"
10 #include "mozilla/dom/BorrowedAttrInfo.h"
11 #include "nsCaseTreatment.h" // for enum, cannot be forward-declared
12 #include "nsINode.h"
13
14 // Forward declarations
15 class nsAString;
16 class nsIAtom;
17 class nsIURI;
18 class nsRuleWalker;
19 class nsAttrValue;
20 class nsAttrName;
21 class nsTextFragment;
22 class nsIFrame;
23 class nsXBLBinding;
24
25 namespace mozilla {
26 class EventChainPreVisitor;
27 namespace dom {
28 class ShadowRoot;
29 struct CustomElementData;
30 } // namespace dom
31 namespace widget {
32 struct IMEState;
33 } // namespace widget
34 } // namespace mozilla
35
36 enum nsLinkState {
37 eLinkState_Unvisited = 1,
38 eLinkState_Visited = 2,
39 eLinkState_NotLink = 3
40 };
41
42 // IID for the nsIContent interface
43 #define NS_ICONTENT_IID \
44 { 0x8e1bab9d, 0x8815, 0x4d2c, \
45 { 0xa2, 0x4d, 0x7a, 0xba, 0x52, 0x39, 0xdc, 0x22 } }
46
47 /**
48 * A node of content in a document's content model. This interface
49 * is supported by all content objects.
50 */
51 class nsIContent : public nsINode {
52 public:
53 typedef mozilla::widget::IMEState IMEState;
54
55 #ifdef MOZILLA_INTERNAL_API
56 // If you're using the external API, the only thing you can know about
57 // nsIContent is that it exists with an IID
58
nsIContent(already_AddRefed<mozilla::dom::NodeInfo> & aNodeInfo)59 explicit nsIContent(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
60 : nsINode(aNodeInfo)
61 {
62 MOZ_ASSERT(mNodeInfo);
63 SetNodeIsContent();
64 }
65 #endif // MOZILLA_INTERNAL_API
66
67 NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICONTENT_IID)
68
69 /**
70 * Bind this content node to a tree. If this method throws, the caller must
71 * call UnbindFromTree() on the node. In the typical case of a node being
72 * appended to a parent, this will be called after the node has been added to
73 * the parent's child list and before nsIDocumentObserver notifications for
74 * the addition are dispatched.
75 * @param aDocument The new document for the content node. May not be null
76 * if aParent is null. Must match the current document of
77 * aParent, if aParent is not null (note that
78 * aParent->GetUncomposedDoc() can be null, in which case
79 * this must also be null).
80 * @param aParent The new parent for the content node. May be null if the
81 * node is being bound as a direct child of the document.
82 * @param aBindingParent The new binding parent for the content node.
83 * This is must either be non-null if a particular
84 * binding parent is desired or match aParent's binding
85 * parent.
86 * @param aCompileEventHandlers whether to initialize the event handlers in
87 * the document (used by nsXULElement)
88 * @note either aDocument or aParent must be non-null. If both are null,
89 * this method _will_ crash.
90 * @note This method must not be called by consumers of nsIContent on a node
91 * that is already bound to a tree. Call UnbindFromTree first.
92 * @note This method will handle rebinding descendants appropriately (eg
93 * changing their binding parent as needed).
94 * @note This method does not add the content node to aParent's child list
95 * @throws NS_ERROR_OUT_OF_MEMORY if that happens
96 */
97 virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
98 nsIContent* aBindingParent,
99 bool aCompileEventHandlers) = 0;
100
101 /**
102 * Unbind this content node from a tree. This will set its current document
103 * and binding parent to null. In the typical case of a node being removed
104 * from a parent, this will be called after it has been removed from the
105 * parent's child list and after the nsIDocumentObserver notifications for
106 * the removal have been dispatched.
107 * @param aDeep Whether to recursively unbind the entire subtree rooted at
108 * this node. The only time false should be passed is when the
109 * parent node of the content is being destroyed.
110 * @param aNullParent Whether to null out the parent pointer as well. This
111 * is usually desirable. This argument should only be false while
112 * recursively calling UnbindFromTree when a subtree is detached.
113 * @note This method is safe to call on nodes that are not bound to a tree.
114 */
115 virtual void UnbindFromTree(bool aDeep = true,
116 bool aNullParent = true) = 0;
117
118 enum {
119 /**
120 * All XBL flattened tree children of the node, as well as :before and
121 * :after anonymous content and native anonymous children.
122 *
123 * @note the result children order is
124 * 1. :before generated node
125 * 2. XBL flattened tree children of this node
126 * 3. native anonymous nodes
127 * 4. :after generated node
128 */
129 eAllChildren = 0,
130
131 /**
132 * All XBL explicit children of the node (see
133 * http://www.w3.org/TR/xbl/#explicit3 ), as well as :before and :after
134 * anonymous content and native anonymous children.
135 *
136 * @note the result children order is
137 * 1. :before generated node
138 * 2. XBL explicit children of the node
139 * 3. native anonymous nodes
140 * 4. :after generated node
141 */
142 eAllButXBL = 1,
143
144 /**
145 * Skip native anonymous content created for placeholder of HTML input,
146 * used in conjunction with eAllChildren or eAllButXBL.
147 */
148 eSkipPlaceholderContent = 2
149 };
150
151 /**
152 * Return either the XBL explicit children of the node or the XBL flattened
153 * tree children of the node, depending on the filter, as well as
154 * native anonymous children.
155 *
156 * @note calling this method with eAllButXBL will return children that are
157 * also in the eAllButXBL and eAllChildren child lists of other descendants
158 * of this node in the tree, but those other nodes cannot be reached from the
159 * eAllButXBL child list.
160 */
161 virtual already_AddRefed<nsINodeList> GetChildren(uint32_t aFilter) = 0;
162
163 /**
164 * Get whether this content is C++-generated anonymous content
165 * @see nsIAnonymousContentCreator
166 * @return whether this content is anonymous
167 */
IsRootOfNativeAnonymousSubtree()168 bool IsRootOfNativeAnonymousSubtree() const
169 {
170 NS_ASSERTION(!HasFlag(NODE_IS_NATIVE_ANONYMOUS_ROOT) ||
171 (HasFlag(NODE_IS_ANONYMOUS_ROOT) &&
172 HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE)),
173 "Some flags seem to be missing!");
174 return HasFlag(NODE_IS_NATIVE_ANONYMOUS_ROOT);
175 }
176
IsRootOfChromeAccessOnlySubtree()177 bool IsRootOfChromeAccessOnlySubtree() const
178 {
179 return HasFlag(NODE_IS_NATIVE_ANONYMOUS_ROOT |
180 NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS);
181 }
182
183 /**
184 * Makes this content anonymous
185 * @see nsIAnonymousContentCreator
186 */
SetIsNativeAnonymousRoot()187 void SetIsNativeAnonymousRoot()
188 {
189 SetFlags(NODE_IS_ANONYMOUS_ROOT | NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE |
190 NODE_IS_NATIVE_ANONYMOUS_ROOT);
191 }
192
193 /**
194 * Returns |this| if it is not chrome-only/native anonymous, otherwise
195 * first non chrome-only/native anonymous ancestor.
196 */
197 virtual nsIContent* FindFirstNonChromeOnlyAccessContent() const;
198
199 /**
200 * Returns true if and only if this node has a parent, but is not in
201 * its parent's child list.
202 */
IsRootOfAnonymousSubtree()203 bool IsRootOfAnonymousSubtree() const
204 {
205 NS_ASSERTION(!IsRootOfNativeAnonymousSubtree() ||
206 (GetParent() && GetBindingParent() == GetParent()),
207 "root of native anonymous subtree must have parent equal "
208 "to binding parent");
209 NS_ASSERTION(!GetParent() ||
210 ((GetBindingParent() == GetParent()) ==
211 HasFlag(NODE_IS_ANONYMOUS_ROOT)) ||
212 // Unfortunately default content for XBL insertion points is
213 // anonymous content that is bound with the parent of the
214 // insertion point as the parent but the bound element for the
215 // binding as the binding parent. So we have to complicate
216 // the assert a bit here.
217 (GetBindingParent() &&
218 (GetBindingParent() == GetParent()->GetBindingParent()) ==
219 HasFlag(NODE_IS_ANONYMOUS_ROOT)),
220 "For nodes with parent, flag and GetBindingParent() check "
221 "should match");
222 return HasFlag(NODE_IS_ANONYMOUS_ROOT);
223 }
224
225 /**
226 * Returns true if there is NOT a path through child lists
227 * from the top of this node's parent chain back to this node or
228 * if the node is in native anonymous subtree without a parent.
229 */
IsInAnonymousSubtree()230 bool IsInAnonymousSubtree() const
231 {
232 NS_ASSERTION(!IsInNativeAnonymousSubtree() || GetBindingParent() ||
233 (!IsInUncomposedDoc() &&
234 static_cast<nsIContent*>(SubtreeRoot())->IsInNativeAnonymousSubtree()),
235 "Must have binding parent when in native anonymous subtree which is in document.\n"
236 "Native anonymous subtree which is not in document must have native anonymous root.");
237 return IsInNativeAnonymousSubtree() || (!IsInShadowTree() && GetBindingParent() != nullptr);
238 }
239
240 /**
241 * Return true iff this node is in an HTML document (in the HTML5 sense of
242 * the term, i.e. not in an XHTML/XML document).
243 */
244 inline bool IsInHTMLDocument() const;
245
246
247 /**
248 * Returns true if in a chrome document
249 */
250 virtual bool IsInChromeDocument() const;
251
252 /**
253 * Get the namespace that this element's tag is defined in
254 * @return the namespace
255 */
GetNameSpaceID()256 inline int32_t GetNameSpaceID() const
257 {
258 return mNodeInfo->NamespaceID();
259 }
260
IsHTMLElement()261 inline bool IsHTMLElement() const
262 {
263 return IsInNamespace(kNameSpaceID_XHTML);
264 }
265
IsHTMLElement(nsIAtom * aTag)266 inline bool IsHTMLElement(nsIAtom* aTag) const
267 {
268 return mNodeInfo->Equals(aTag, kNameSpaceID_XHTML);
269 }
270
271 template<typename First, typename... Args>
IsAnyOfHTMLElements(First aFirst,Args...aArgs)272 inline bool IsAnyOfHTMLElements(First aFirst, Args... aArgs) const
273 {
274 return IsHTMLElement() && IsNodeInternal(aFirst, aArgs...);
275 }
276
IsSVGElement()277 inline bool IsSVGElement() const
278 {
279 return IsInNamespace(kNameSpaceID_SVG);
280 }
281
IsSVGElement(nsIAtom * aTag)282 inline bool IsSVGElement(nsIAtom* aTag) const
283 {
284 return mNodeInfo->Equals(aTag, kNameSpaceID_SVG);
285 }
286
287 template<typename First, typename... Args>
IsAnyOfSVGElements(First aFirst,Args...aArgs)288 inline bool IsAnyOfSVGElements(First aFirst, Args... aArgs) const
289 {
290 return IsSVGElement() && IsNodeInternal(aFirst, aArgs...);
291 }
292
IsXULElement()293 inline bool IsXULElement() const
294 {
295 return IsInNamespace(kNameSpaceID_XUL);
296 }
297
IsXULElement(nsIAtom * aTag)298 inline bool IsXULElement(nsIAtom* aTag) const
299 {
300 return mNodeInfo->Equals(aTag, kNameSpaceID_XUL);
301 }
302
303 template<typename First, typename... Args>
IsAnyOfXULElements(First aFirst,Args...aArgs)304 inline bool IsAnyOfXULElements(First aFirst, Args... aArgs) const
305 {
306 return IsXULElement() && IsNodeInternal(aFirst, aArgs...);
307 }
308
IsMathMLElement()309 inline bool IsMathMLElement() const
310 {
311 return IsInNamespace(kNameSpaceID_MathML);
312 }
313
IsMathMLElement(nsIAtom * aTag)314 inline bool IsMathMLElement(nsIAtom* aTag) const
315 {
316 return mNodeInfo->Equals(aTag, kNameSpaceID_MathML);
317 }
318
319 template<typename First, typename... Args>
IsAnyOfMathMLElements(First aFirst,Args...aArgs)320 inline bool IsAnyOfMathMLElements(First aFirst, Args... aArgs) const
321 {
322 return IsMathMLElement() && IsNodeInternal(aFirst, aArgs...);
323 }
IsActiveChildrenElement()324 inline bool IsActiveChildrenElement() const
325 {
326 return mNodeInfo->Equals(nsGkAtoms::children, kNameSpaceID_XBL) &&
327 GetBindingParent();
328 }
329
IsGeneratedContentContainerForBefore()330 bool IsGeneratedContentContainerForBefore() const
331 {
332 return IsRootOfNativeAnonymousSubtree() &&
333 mNodeInfo->NameAtom() == nsGkAtoms::mozgeneratedcontentbefore;
334 }
335
IsGeneratedContentContainerForAfter()336 bool IsGeneratedContentContainerForAfter() const
337 {
338 return IsRootOfNativeAnonymousSubtree() &&
339 mNodeInfo->NameAtom() == nsGkAtoms::mozgeneratedcontentafter;
340 }
341
342 /**
343 * Set attribute values. All attribute values are assumed to have a
344 * canonical string representation that can be used for these
345 * methods. The SetAttr method is assumed to perform a translation
346 * of the canonical form into the underlying content specific
347 * form.
348 *
349 * @param aNameSpaceID the namespace of the attribute
350 * @param aName the name of the attribute
351 * @param aValue the value to set
352 * @param aNotify specifies how whether or not the document should be
353 * notified of the attribute change.
354 */
SetAttr(int32_t aNameSpaceID,nsIAtom * aName,const nsAString & aValue,bool aNotify)355 nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
356 const nsAString& aValue, bool aNotify)
357 {
358 return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
359 }
360
361 /**
362 * Set attribute values. All attribute values are assumed to have a
363 * canonical String representation that can be used for these
364 * methods. The SetAttr method is assumed to perform a translation
365 * of the canonical form into the underlying content specific
366 * form.
367 *
368 * @param aNameSpaceID the namespace of the attribute
369 * @param aName the name of the attribute
370 * @param aPrefix the prefix of the attribute
371 * @param aValue the value to set
372 * @param aNotify specifies how whether or not the document should be
373 * notified of the attribute change.
374 */
375 virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
376 nsIAtom* aPrefix, const nsAString& aValue,
377 bool aNotify) = 0;
378
379 /**
380 * Get the current value of the attribute. This returns a form that is
381 * suitable for passing back into SetAttr.
382 *
383 * @param aNameSpaceID the namespace of the attr
384 * @param aName the name of the attr
385 * @param aResult the value (may legitimately be the empty string) [OUT]
386 * @returns true if the attribute was set (even when set to empty string)
387 * false when not set.
388 */
389 bool GetAttr(int32_t aNameSpaceID, nsIAtom* aName,
390 nsAString& aResult) const;
391
392 /**
393 * Determine if an attribute has been set (empty string or otherwise).
394 *
395 * @param aNameSpaceId the namespace id of the attribute
396 * @param aAttr the attribute name
397 * @return whether an attribute exists
398 */
399 bool HasAttr(int32_t aNameSpaceID, nsIAtom* aName) const;
400
401 /**
402 * Test whether this content node's given attribute has the given value. If
403 * the attribute is not set at all, this will return false.
404 *
405 * @param aNameSpaceID The namespace ID of the attribute. Must not
406 * be kNameSpaceID_Unknown.
407 * @param aName The name atom of the attribute. Must not be null.
408 * @param aValue The value to compare to.
409 * @param aCaseSensitive Whether to do a case-sensitive compare on the value.
410 */
411 bool AttrValueIs(int32_t aNameSpaceID,
412 nsIAtom* aName,
413 const nsAString& aValue,
414 nsCaseTreatment aCaseSensitive) const;
415
416 /**
417 * Test whether this content node's given attribute has the given value. If
418 * the attribute is not set at all, this will return false.
419 *
420 * @param aNameSpaceID The namespace ID of the attribute. Must not
421 * be kNameSpaceID_Unknown.
422 * @param aName The name atom of the attribute. Must not be null.
423 * @param aValue The value to compare to. Must not be null.
424 * @param aCaseSensitive Whether to do a case-sensitive compare on the value.
425 */
426 bool AttrValueIs(int32_t aNameSpaceID,
427 nsIAtom* aName,
428 nsIAtom* aValue,
429 nsCaseTreatment aCaseSensitive) const;
430
431 enum {
432 ATTR_MISSING = -1,
433 ATTR_VALUE_NO_MATCH = -2
434 };
435 /**
436 * Check whether this content node's given attribute has one of a given
437 * list of values. If there is a match, we return the index in the list
438 * of the first matching value. If there was no attribute at all, then
439 * we return ATTR_MISSING. If there was an attribute but it didn't
440 * match, we return ATTR_VALUE_NO_MATCH. A non-negative result always
441 * indicates a match.
442 *
443 * @param aNameSpaceID The namespace ID of the attribute. Must not
444 * be kNameSpaceID_Unknown.
445 * @param aName The name atom of the attribute. Must not be null.
446 * @param aValues a nullptr-terminated array of pointers to atom values to test
447 * against.
448 * @param aCaseSensitive Whether to do a case-sensitive compare on the values.
449 * @return ATTR_MISSING, ATTR_VALUE_NO_MATCH or the non-negative index
450 * indicating the first value of aValues that matched
451 */
452 typedef nsIAtom* const* const AttrValuesArray;
FindAttrValueIn(int32_t aNameSpaceID,nsIAtom * aName,AttrValuesArray * aValues,nsCaseTreatment aCaseSensitive)453 virtual int32_t FindAttrValueIn(int32_t aNameSpaceID,
454 nsIAtom* aName,
455 AttrValuesArray* aValues,
456 nsCaseTreatment aCaseSensitive) const
457 {
458 return ATTR_MISSING;
459 }
460
461 /**
462 * Remove an attribute so that it is no longer explicitly specified.
463 *
464 * @param aNameSpaceID the namespace id of the attribute
465 * @param aAttr the name of the attribute to unset
466 * @param aNotify specifies whether or not the document should be
467 * notified of the attribute change
468 */
469 virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttr,
470 bool aNotify) = 0;
471
472
473 /**
474 * Get the namespace / name / prefix of a given attribute.
475 *
476 * @param aIndex the index of the attribute name
477 * @returns The name at the given index, or null if the index is
478 * out-of-bounds.
479 * @note The document returned by NodeInfo()->GetDocument() (if one is
480 * present) is *not* necessarily the owner document of the element.
481 * @note The pointer returned by this function is only valid until the
482 * next call of either GetAttrNameAt or SetAttr on the element.
483 */
484 virtual const nsAttrName* GetAttrNameAt(uint32_t aIndex) const = 0;
485
486 /**
487 * Gets the attribute info (name and value) for this content at a given index.
488 */
489 virtual mozilla::dom::BorrowedAttrInfo GetAttrInfoAt(uint32_t aIndex) const = 0;
490
491 /**
492 * Get the number of all specified attributes.
493 *
494 * @return the number of attributes
495 */
496 virtual uint32_t GetAttrCount() const = 0;
497
498 /**
499 * Get direct access (but read only) to the text in the text content.
500 * NOTE: For elements this is *not* the concatenation of all text children,
501 * it is simply null;
502 */
503 virtual const nsTextFragment *GetText() = 0;
504
505 /**
506 * Get the length of the text content.
507 * NOTE: This should not be called on elements.
508 */
509 virtual uint32_t TextLength() const = 0;
510
511 /**
512 * Determines if an event attribute name (such as onclick) is valid for
513 * a given element type.
514 * @note calls nsContentUtils::IsEventAttributeName with right flag
515 * @note overridden by subclasses as needed
516 * @param aName the event name to look up
517 */
IsEventAttributeName(nsIAtom * aName)518 virtual bool IsEventAttributeName(nsIAtom* aName)
519 {
520 return false;
521 }
522
523 /**
524 * Set the text to the given value. If aNotify is true then
525 * the document is notified of the content change.
526 * NOTE: For elements this always ASSERTS and returns NS_ERROR_FAILURE
527 */
528 virtual nsresult SetText(const char16_t* aBuffer, uint32_t aLength,
529 bool aNotify) = 0;
530
531 /**
532 * Append the given value to the current text. If aNotify is true then
533 * the document is notified of the content change.
534 * NOTE: For elements this always ASSERTS and returns NS_ERROR_FAILURE
535 */
536 virtual nsresult AppendText(const char16_t* aBuffer, uint32_t aLength,
537 bool aNotify) = 0;
538
539 /**
540 * Set the text to the given value. If aNotify is true then
541 * the document is notified of the content change.
542 * NOTE: For elements this always asserts and returns NS_ERROR_FAILURE
543 */
SetText(const nsAString & aStr,bool aNotify)544 nsresult SetText(const nsAString& aStr, bool aNotify)
545 {
546 return SetText(aStr.BeginReading(), aStr.Length(), aNotify);
547 }
548
549 /**
550 * Query method to see if the frame is nothing but whitespace
551 * NOTE: Always returns false for elements
552 */
553 virtual bool TextIsOnlyWhitespace() = 0;
554
555 /**
556 * Method to see if the text node contains data that is useful
557 * for a translation: i.e., it consists of more than just whitespace,
558 * digits and punctuation.
559 * NOTE: Always returns false for elements.
560 */
561 virtual bool HasTextForTranslation() = 0;
562
563 /**
564 * Append the text content to aResult.
565 * NOTE: This asserts and returns for elements
566 */
567 virtual void AppendTextTo(nsAString& aResult) = 0;
568
569 /**
570 * Append the text content to aResult.
571 * NOTE: This asserts and returns for elements
572 */
573 MOZ_MUST_USE
574 virtual bool AppendTextTo(nsAString& aResult, const mozilla::fallible_t&) = 0;
575
576 /**
577 * Check if this content is focusable and in the current tab order.
578 * Note: most callers should use nsIFrame::IsFocusable() instead as it
579 * checks visibility and other layout factors as well.
580 * Tabbable is indicated by a nonnegative tabindex & is a subset of focusable.
581 * For example, only the selected radio button in a group is in the
582 * tab order, unless the radio group has no selection in which case
583 * all of the visible, non-disabled radio buttons in the group are
584 * in the tab order. On the other hand, all of the visible, non-disabled
585 * radio buttons are always focusable via clicking or script.
586 * Also, depending on either the accessibility.tabfocus pref or
587 * a system setting (nowadays: Full keyboard access, mac only)
588 * some widgets may be focusable but removed from the tab order.
589 * @param [inout, optional] aTabIndex the computed tab index
590 * In: default tabindex for element (-1 nonfocusable, == 0 focusable)
591 * Out: computed tabindex
592 * @param [optional] aTabIndex the computed tab index
593 * < 0 if not tabbable
594 * == 0 if in normal tab order
595 * > 0 can be tabbed to in the order specified by this value
596 * @return whether the content is focusable via mouse, kbd or script.
597 */
598 bool IsFocusable(int32_t* aTabIndex = nullptr, bool aWithMouse = false);
599 virtual bool IsFocusableInternal(int32_t* aTabIndex, bool aWithMouse);
600
601 /**
602 * The method focuses (or activates) element that accesskey is bound to. It is
603 * called when accesskey is activated.
604 *
605 * @param aKeyCausesActivation - if true then element should be activated
606 * @param aIsTrustedEvent - if true then event that is cause of accesskey
607 * execution is trusted.
608 * @return true if the focus was changed.
609 */
PerformAccesskey(bool aKeyCausesActivation,bool aIsTrustedEvent)610 virtual bool PerformAccesskey(bool aKeyCausesActivation,
611 bool aIsTrustedEvent)
612 {
613 return false;
614 }
615
616 /*
617 * Get desired IME state for the content.
618 *
619 * @return The desired IME status for the content.
620 * This is a combination of an IME enabled value and
621 * an IME open value of widget::IMEState.
622 * If you return DISABLED, you should not set the OPEN and CLOSE
623 * value.
624 * PASSWORD should be returned only from password editor, this value
625 * has a special meaning. It is used as alternative of DISABLED.
626 * PLUGIN should be returned only when plug-in has focus. When a
627 * plug-in is focused content, we should send native events directly.
628 * Because we don't process some native events, but they may be needed
629 * by the plug-in.
630 */
631 virtual IMEState GetDesiredIMEState();
632
633 /**
634 * Gets content node with the binding (or native code, possibly on the
635 * frame) responsible for our construction (and existence). Used by
636 * anonymous content (both XBL-generated and native-anonymous).
637 *
638 * null for all explicit content (i.e., content reachable from the top
639 * of its GetParent() chain via child lists).
640 *
641 * @return the binding parent
642 */
643 virtual nsIContent *GetBindingParent() const = 0;
644
645 /**
646 * Gets the current XBL binding that is bound to this element.
647 *
648 * @return the current binding.
649 */
650 virtual nsXBLBinding *GetXBLBinding() const = 0;
651
652 /**
653 * Sets or unsets an XBL binding for this element. Setting a
654 * binding on an element that already has a binding will remove the
655 * old binding.
656 *
657 * @param aBinding The binding to bind to this content. If nullptr is
658 * provided as the argument, then existing binding will be
659 * removed.
660 *
661 * @param aOldBindingManager The old binding manager that contains
662 * this content if this content was adopted
663 * to another document.
664 */
665 virtual void SetXBLBinding(nsXBLBinding* aBinding,
666 nsBindingManager* aOldBindingManager = nullptr) = 0;
667
668 /**
669 * Sets the ShadowRoot binding for this element. The contents of the
670 * binding is rendered in place of this node's children.
671 *
672 * @param aShadowRoot The ShadowRoot to be bound to this element.
673 */
674 virtual void SetShadowRoot(mozilla::dom::ShadowRoot* aShadowRoot) = 0;
675
676 /**
677 * Gets the ShadowRoot binding for this element.
678 *
679 * @return The ShadowRoot currently bound to this element.
680 */
681 inline mozilla::dom::ShadowRoot *GetShadowRoot() const;
682
683 /**
684 * Gets the root of the node tree for this content if it is in a shadow tree.
685 * This method is called |GetContainingShadow| instead of |GetRootShadowRoot|
686 * to avoid confusion with |GetShadowRoot|.
687 *
688 * @return The ShadowRoot that is the root of the node tree.
689 */
690 virtual mozilla::dom::ShadowRoot *GetContainingShadow() const = 0;
691
692 /**
693 * Gets an array of destination insertion points where this content
694 * is distributed by web component distribution algorithms.
695 * The array is created if it does not already exist.
696 */
697 virtual nsTArray<nsIContent*> &DestInsertionPoints() = 0;
698
699 /**
700 * Same as DestInsertionPoints except that this method will return
701 * null if the array of destination insertion points does not already
702 * exist.
703 */
704 virtual nsTArray<nsIContent*> *GetExistingDestInsertionPoints() const = 0;
705
706 /**
707 * Gets the insertion parent element of the XBL binding.
708 * The insertion parent is our one true parent in the transformed DOM.
709 *
710 * @return the insertion parent element.
711 */
712 virtual nsIContent *GetXBLInsertionParent() const = 0;
713
714 /**
715 * Sets the insertion parent element of the XBL binding.
716 *
717 * @param aContent The insertion parent element.
718 */
719 virtual void SetXBLInsertionParent(nsIContent* aContent) = 0;
720
721 /**
722 * Same as GetFlattenedTreeParentNode, but returns null if the parent is
723 * non-nsIContent.
724 */
725 inline nsIContent *GetFlattenedTreeParent() const;
726
727 /**
728 * Helper method, which we leave public so that it's accessible from nsINode.
729 */
730 nsINode *GetFlattenedTreeParentNodeInternal() const;
731
732 /**
733 * Gets the custom element data used by web components custom element.
734 * Custom element data is created at the first attempt to enqueue a callback.
735 *
736 * @return The custom element data or null if none.
737 */
738 virtual mozilla::dom::CustomElementData *GetCustomElementData() const = 0;
739
740 /**
741 * Sets the custom element data, ownership of the
742 * callback data is taken by this content.
743 *
744 * @param aCallbackData The custom element data.
745 */
746 virtual void SetCustomElementData(mozilla::dom::CustomElementData* aData) = 0;
747
748 /**
749 * API to check if this is a link that's traversed in response to user input
750 * (e.g. a click event). Specializations for HTML/SVG/generic XML allow for
751 * different types of link in different types of content.
752 *
753 * @param aURI Required out param. If this content is a link, a new nsIURI
754 * set to this link's URI will be passed out.
755 *
756 * @note The out param, aURI, is guaranteed to be set to a non-null pointer
757 * when the return value is true.
758 *
759 * XXXjwatt: IMO IsInteractiveLink would be a better name.
760 */
761 virtual bool IsLink(nsIURI** aURI) const = 0;
762
763 /**
764 * Get a pointer to the full href URI (fully resolved and canonicalized,
765 * since it's an nsIURI object) for link elements.
766 *
767 * @return A pointer to the URI or null if the element is not a link or it
768 * has no HREF attribute.
769 */
GetHrefURI()770 virtual already_AddRefed<nsIURI> GetHrefURI() const
771 {
772 return nullptr;
773 }
774
775 /**
776 * This method is called when the parser finishes creating the element. This
777 * particularly means that it has done everything you would expect it to have
778 * done after it encounters the > at the end of the tag (for HTML or XML).
779 * This includes setting the attributes, setting the document / form, and
780 * placing the element into the tree at its proper place.
781 *
782 * For container elements, this is called *before* any of the children are
783 * created or added into the tree.
784 *
785 * NOTE: this is currently only called for input and button, in the HTML
786 * content sink. If you want to call it on your element, modify the content
787 * sink of your choice to do so. This is an efficiency measure.
788 *
789 * If you also need to determine whether the parser is the one creating your
790 * element (through createElement() or cloneNode() generally) then add a
791 * uint32_t aFromParser to the NS_NewXXX() constructor for your element and
792 * have the parser pass the appropriate flags. See HTMLInputElement.cpp and
793 * nsHTMLContentSink::MakeContentObject().
794 *
795 * DO NOT USE THIS METHOD to get around the fact that it's hard to deal with
796 * attributes dynamically. If you make attributes affect your element from
797 * this method, it will only happen on initialization and JavaScript will not
798 * be able to create elements (which requires them to first create the
799 * element and then call setAttribute() directly, at which point
800 * DoneCreatingElement() has already been called and is out of the picture).
801 */
DoneCreatingElement()802 virtual void DoneCreatingElement()
803 {
804 }
805
806 /**
807 * This method is called when the parser begins creating the element's
808 * children, if any are present.
809 *
810 * This is only called for XTF elements currently.
811 */
BeginAddingChildren()812 virtual void BeginAddingChildren()
813 {
814 }
815
816 /**
817 * This method is called when the parser finishes creating the element's children,
818 * if any are present.
819 *
820 * NOTE: this is currently only called for textarea, select, applet, and
821 * object elements in the HTML content sink. If you want
822 * to call it on your element, modify the content sink of your
823 * choice to do so. This is an efficiency measure.
824 *
825 * If you also need to determine whether the parser is the one creating your
826 * element (through createElement() or cloneNode() generally) then add a
827 * boolean aFromParser to the NS_NewXXX() constructor for your element and
828 * have the parser pass true. See HTMLInputElement.cpp and
829 * nsHTMLContentSink::MakeContentObject().
830 *
831 * @param aHaveNotified Whether there has been a
832 * ContentInserted/ContentAppended notification for this content node
833 * yet.
834 */
DoneAddingChildren(bool aHaveNotified)835 virtual void DoneAddingChildren(bool aHaveNotified)
836 {
837 }
838
839 /**
840 * For HTML textarea, select, applet, and object elements, returns
841 * true if all children have been added OR if the element was not
842 * created by the parser. Returns true for all other elements.
843 * @returns false if the element was created by the parser and
844 * it is an HTML textarea, select, applet, or object
845 * element and not all children have been added.
846 * @returns true otherwise.
847 */
IsDoneAddingChildren()848 virtual bool IsDoneAddingChildren()
849 {
850 return true;
851 }
852
853 /**
854 * Get the ID of this content node (the atom corresponding to the
855 * value of the id attribute). This may be null if there is no ID.
856 */
GetID()857 nsIAtom* GetID() const {
858 if (HasID()) {
859 return DoGetID();
860 }
861 return nullptr;
862 }
863
864 /**
865 * Get the class list of this content node (this corresponds to the
866 * value of the class attribute). This may be null if there are no
867 * classes, but that's not guaranteed.
868 */
GetClasses()869 const nsAttrValue* GetClasses() const {
870 if (HasFlag(NODE_MAY_HAVE_CLASS)) {
871 return DoGetClasses();
872 }
873 return nullptr;
874 }
875
876 /**
877 * Walk aRuleWalker over the content style rules (presentational
878 * hint rules) for this content node.
879 */
880 NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) = 0;
881
882 /**
883 * Should be called when the node can become editable or when it can stop
884 * being editable (for example when its contentEditable attribute changes,
885 * when it is moved into an editable parent, ...). If aNotify is true and
886 * the node is an element, this will notify the state change.
887 */
888 virtual void UpdateEditableState(bool aNotify);
889
890 /**
891 * Destroy this node and its children. Ideally this shouldn't be needed
892 * but for now we need to do it to break cycles.
893 */
DestroyContent()894 virtual void DestroyContent()
895 {
896 }
897
898 /**
899 * Saves the form state of this node and its children.
900 */
901 virtual void SaveSubtreeState() = 0;
902
903 /**
904 * Getter and setter for our primary frame pointer. This is the frame that
905 * is most closely associated with the content. A frame is more closely
906 * associated with the content than another frame if the one frame contains
907 * directly or indirectly the other frame (e.g., when a frame is scrolled
908 * there is a scroll frame that contains the frame being scrolled). This
909 * frame is always the first continuation.
910 *
911 * In the case of absolutely positioned elements and floated elements, this
912 * frame is the out of flow frame, not the placeholder.
913 */
GetPrimaryFrame()914 nsIFrame* GetPrimaryFrame() const
915 {
916 return (IsInUncomposedDoc() || IsInShadowTree()) ? mPrimaryFrame : nullptr;
917 }
SetPrimaryFrame(nsIFrame * aFrame)918 void SetPrimaryFrame(nsIFrame* aFrame) {
919 MOZ_ASSERT(IsInUncomposedDoc() || IsInShadowTree(), "This will end badly!");
920 NS_PRECONDITION(!aFrame || !mPrimaryFrame || aFrame == mPrimaryFrame,
921 "Losing track of existing primary frame");
922 mPrimaryFrame = aFrame;
923 }
924
925 nsresult LookupNamespaceURIInternal(const nsAString& aNamespacePrefix,
926 nsAString& aNamespaceURI) const;
927
928 /**
929 * If this content has independent selection, e.g., if this is input field
930 * or textarea, this return TRUE. Otherwise, false.
931 */
932 bool HasIndependentSelection();
933
934 /**
935 * If the content is a part of HTML editor, this returns editing
936 * host content. When the content is in designMode, this returns its body
937 * element. Also, when the content isn't editable, this returns null.
938 */
939 mozilla::dom::Element* GetEditingHost();
940
941
942 /**
943 * Set NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO all the way up the flattened
944 * parent chain to the document. If an ancestor is found with the bit already
945 * set, this method asserts that all of its ancestors also have the bit set.
946 */
947 void MarkAncestorsAsHavingDirtyDescendantsForServo();
948
949 /**
950 * Determining language. Look at the nearest ancestor element that has a lang
951 * attribute in the XML namespace or is an HTML/SVG element and has a lang in
952 * no namespace attribute. Returns false if no language was specified.
953 */
GetLang(nsAString & aResult)954 bool GetLang(nsAString& aResult) const {
955 for (const nsIContent* content = this; content; content = content->GetParent()) {
956 if (content->GetAttrCount() > 0) {
957 // xml:lang has precedence over lang on HTML elements (see
958 // XHTML1 section C.7).
959 bool hasAttr = content->GetAttr(kNameSpaceID_XML, nsGkAtoms::lang,
960 aResult);
961 if (!hasAttr && (content->IsHTMLElement() || content->IsSVGElement() ||
962 content->IsXULElement())) {
963 hasAttr = content->GetAttr(kNameSpaceID_None, nsGkAtoms::lang,
964 aResult);
965 }
966 NS_ASSERTION(hasAttr || aResult.IsEmpty(),
967 "GetAttr that returns false should not make string non-empty");
968 if (hasAttr) {
969 return true;
970 }
971 }
972 }
973 return false;
974 }
975
976 // Overloaded from nsINode
977 virtual already_AddRefed<nsIURI> GetBaseURI(bool aTryUseXHRDocBaseURI = false) const override;
978
979 virtual nsresult PreHandleEvent(
980 mozilla::EventChainPreVisitor& aVisitor) override;
981
982 virtual bool IsPurple() = 0;
983 virtual void RemovePurple() = 0;
984
OwnedOnlyByTheDOMTree()985 virtual bool OwnedOnlyByTheDOMTree() { return false; }
986 protected:
987 /**
988 * Hook for implementing GetID. This is guaranteed to only be
989 * called if HasID() is true.
990 */
991 nsIAtom* DoGetID() const;
992
993 private:
994 /**
995 * Hook for implementing GetClasses. This is guaranteed to only be
996 * called if the NODE_MAY_HAVE_CLASS flag is set.
997 */
998 const nsAttrValue* DoGetClasses() const;
999
1000 public:
1001 #ifdef DEBUG
1002 /**
1003 * List the content (and anything it contains) out to the given
1004 * file stream. Use aIndent as the base indent during formatting.
1005 */
1006 virtual void List(FILE* out = stdout, int32_t aIndent = 0) const = 0;
1007
1008 /**
1009 * Dump the content (and anything it contains) out to the given
1010 * file stream. Use aIndent as the base indent during formatting.
1011 */
1012 virtual void DumpContent(FILE* out = stdout, int32_t aIndent = 0,
1013 bool aDumpAll = true) const = 0;
1014 #endif
1015
1016 /**
1017 * Append to aOutDescription a short (preferably one line) string
1018 * describing the content.
1019 * Currently implemented for elements only.
1020 */
Describe(nsAString & aOutDescription)1021 virtual void Describe(nsAString& aOutDescription) const {
1022 aOutDescription = NS_LITERAL_STRING("(not an element)");
1023 }
1024
1025 enum ETabFocusType {
1026 eTabFocus_textControlsMask = (1<<0), // textboxes and lists always tabbable
1027 eTabFocus_formElementsMask = (1<<1), // non-text form elements
1028 eTabFocus_linksMask = (1<<2), // links
1029 eTabFocus_any = 1 + (1<<1) + (1<<2) // everything that can be focused
1030 };
1031
1032 // Tab focus model bit field:
1033 static int32_t sTabFocusModel;
1034
1035 // accessibility.tabfocus_applies_to_xul pref - if it is set to true,
1036 // the tabfocus bit field applies to xul elements.
1037 static bool sTabFocusModelAppliesToXUL;
1038 };
1039
NS_DEFINE_STATIC_IID_ACCESSOR(nsIContent,NS_ICONTENT_IID)1040 NS_DEFINE_STATIC_IID_ACCESSOR(nsIContent, NS_ICONTENT_IID)
1041
1042 inline nsIContent* nsINode::AsContent()
1043 {
1044 MOZ_ASSERT(IsContent());
1045 return static_cast<nsIContent*>(this);
1046 }
1047
1048 #define NS_IMPL_FROMCONTENT_HELPER(_class, _check) \
1049 static _class* FromContent(nsIContent* aContent) \
1050 { \
1051 return aContent->_check ? static_cast<_class*>(aContent) : nullptr; \
1052 } \
1053 static _class* FromContentOrNull(nsIContent* aContent) \
1054 { \
1055 return aContent ? FromContent(aContent) : nullptr; \
1056 }
1057
1058 #define NS_IMPL_FROMCONTENT(_class, _nsid) \
1059 NS_IMPL_FROMCONTENT_HELPER(_class, IsInNamespace(_nsid))
1060
1061 #define NS_IMPL_FROMCONTENT_WITH_TAG(_class, _nsid, _tag) \
1062 NS_IMPL_FROMCONTENT_HELPER(_class, NodeInfo()->Equals(nsGkAtoms::_tag, _nsid))
1063
1064 #define NS_IMPL_FROMCONTENT_HTML_WITH_TAG(_class, _tag) \
1065 NS_IMPL_FROMCONTENT_WITH_TAG(_class, kNameSpaceID_XHTML, _tag)
1066
1067 #endif /* nsIContent_h___ */
1068