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