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/. */
7 #ifndef nsIContentInlines_h
8 #define nsIContentInlines_h
10 #include "nsIContent.h"
11 #include "mozilla/dom/Document.h"
12 #include "nsContentUtils.h"
15 #include "mozilla/dom/Element.h"
16 #include "mozilla/dom/HTMLSlotElement.h"
17 #include "mozilla/dom/ShadowRoot.h"
19 inline bool nsINode::IsUAWidget() const {
20 auto* shadow
= mozilla::dom::ShadowRoot::FromNode(this);
21 return shadow
&& shadow
->IsUAWidget();
24 inline bool nsINode::IsInUAWidget() const {
25 if (!IsInShadowTree()) {
28 mozilla::dom::ShadowRoot
* shadow
= AsContent()->GetContainingShadow();
29 return shadow
&& shadow
->IsUAWidget();
32 inline bool nsINode::IsRootOfChromeAccessOnlySubtree() const {
33 return IsRootOfNativeAnonymousSubtree() || IsUAWidget();
36 inline bool nsIContent::IsInHTMLDocument() const {
37 return OwnerDoc()->IsHTMLDocument();
40 inline bool nsIContent::IsInChromeDocument() const {
41 return nsContentUtils::IsChromeDoc(OwnerDoc());
44 inline void nsIContent::SetPrimaryFrame(nsIFrame
* aFrame
) {
45 MOZ_ASSERT(IsInUncomposedDoc() || IsInShadowTree(), "This will end badly!");
48 NS_ASSERTION(!aFrame
|| !mPrimaryFrame
|| aFrame
== mPrimaryFrame
,
49 "Losing track of existing primary frame");
52 MOZ_ASSERT(!aFrame
->IsPlaceholderFrame());
53 if (MOZ_LIKELY(!IsHTMLElement(nsGkAtoms::area
)) ||
54 aFrame
->GetContent() == this) {
55 aFrame
->SetIsPrimaryFrame(true);
57 } else if (nsIFrame
* currentPrimaryFrame
= GetPrimaryFrame()) {
58 if (MOZ_LIKELY(!IsHTMLElement(nsGkAtoms::area
)) ||
59 currentPrimaryFrame
->GetContent() == this) {
60 currentPrimaryFrame
->SetIsPrimaryFrame(false);
64 mPrimaryFrame
= aFrame
;
67 inline mozilla::dom::ShadowRoot
* nsIContent::GetShadowRoot() const {
72 return AsElement()->GetShadowRoot();
75 template <nsINode::FlattenedParentType aType
>
76 static inline nsINode
* GetFlattenedTreeParentNode(const nsINode
* aNode
) {
77 if (!aNode
->IsContent()) {
81 nsINode
* parent
= aNode
->GetParentNode();
82 if (!parent
|| !parent
->IsContent()) {
86 const nsIContent
* content
= aNode
->AsContent();
87 nsIContent
* parentAsContent
= parent
->AsContent();
89 if (aType
== nsINode::eForStyle
&&
90 content
->IsRootOfNativeAnonymousSubtree() &&
91 parentAsContent
== content
->OwnerDoc()->GetRootElement()) {
93 content
->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent
);
94 return docLevel
? content
->OwnerDocAsNode() : parent
;
97 if (content
->IsRootOfNativeAnonymousSubtree()) {
101 if (parentAsContent
->GetShadowRoot()) {
102 // If it's not assigned to any slot it's not part of the flat tree, and thus
104 return content
->GetAssignedSlot();
107 if (parentAsContent
->IsInShadowTree()) {
108 if (auto* slot
= mozilla::dom::HTMLSlotElement::FromNode(parentAsContent
)) {
109 // If the assigned nodes list is empty, we're fallback content which is
110 // active, otherwise we are not part of the flat tree.
111 return slot
->AssignedNodes().IsEmpty() ? parent
: nullptr;
114 if (auto* shadowRoot
=
115 mozilla::dom::ShadowRoot::FromNode(parentAsContent
)) {
116 return shadowRoot
->GetHost();
124 inline nsINode
* nsINode::GetFlattenedTreeParentNode() const {
125 return ::GetFlattenedTreeParentNode
<nsINode::eNotForStyle
>(this);
128 inline nsIContent
* nsIContent::GetFlattenedTreeParent() const {
129 nsINode
* parent
= GetFlattenedTreeParentNode();
130 return (parent
&& parent
->IsContent()) ? parent
->AsContent() : nullptr;
133 inline bool nsIContent::IsEventAttributeName(nsAtom
* aName
) {
134 const char16_t
* name
= aName
->GetUTF16String();
135 if (name
[0] != 'o' || name
[1] != 'n') {
139 return IsEventAttributeNameInternal(aName
);
142 inline nsINode
* nsINode::GetFlattenedTreeParentNodeForStyle() const {
143 return ::GetFlattenedTreeParentNode
<nsINode::eForStyle
>(this);
146 inline bool nsINode::NodeOrAncestorHasDirAuto() const {
147 return AncestorHasDirAuto() || (IsElement() && AsElement()->HasDirAuto());
150 inline bool nsINode::IsEditable() const {
151 if (HasFlag(NODE_IS_EDITABLE
)) {
152 // The node is in an editable contentEditable subtree.
156 // All editable anonymous content should be made explicitly editable via the
157 // NODE_IS_EDITABLE flag.
158 if (IsInNativeAnonymousSubtree()) {
162 // Check if the node is in a document and the document is in designMode.
164 // NOTE(emilio): If you change this to be the composed doc you also need to
165 // change NotifyEditableStateChange() in Document.cpp.
166 Document
* doc
= GetUncomposedDoc();
167 return doc
&& doc
->HasFlag(NODE_IS_EDITABLE
);
170 inline void nsIContent::HandleInsertionToOrRemovalFromSlot() {
171 using mozilla::dom::HTMLSlotElement
;
173 MOZ_ASSERT(GetParentElement());
174 if (!IsInShadowTree() || IsRootOfNativeAnonymousSubtree()) {
177 HTMLSlotElement
* slot
= HTMLSlotElement::FromNode(mParent
);
181 // If parent's root is a shadow root, and parent is a slot whose
182 // assigned nodes is the empty list, then run signal a slot change for
184 if (slot
->AssignedNodes().IsEmpty()) {
185 slot
->EnqueueSlotChangeEvent();
189 inline void nsIContent::HandleShadowDOMRelatedInsertionSteps(bool aHadParent
) {
190 using mozilla::dom::Element
;
191 using mozilla::dom::ShadowRoot
;
194 if (Element
* parentElement
= Element::FromNode(mParent
)) {
195 if (ShadowRoot
* shadow
= parentElement
->GetShadowRoot()) {
196 shadow
->MaybeSlotHostChild(*this);
198 HandleInsertionToOrRemovalFromSlot();
203 inline void nsIContent::HandleShadowDOMRelatedRemovalSteps(bool aNullParent
) {
204 using mozilla::dom::Element
;
205 using mozilla::dom::ShadowRoot
;
208 // FIXME(emilio, bug 1577141): FromNodeOrNull rather than just FromNode
209 // because XBL likes to call UnbindFromTree at very odd times (with already
210 // disconnected anonymous content subtrees).
211 if (Element
* parentElement
= Element::FromNodeOrNull(mParent
)) {
212 if (ShadowRoot
* shadow
= parentElement
->GetShadowRoot()) {
213 shadow
->MaybeUnslotHostChild(*this);
215 HandleInsertionToOrRemovalFromSlot();
220 #endif // nsIContentInlines_h