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