gecko-dev/dom/base/nsIContentInlines.h

225 строки
6.7 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsIContentInlines_h
#define nsIContentInlines_h
#include "nsIContent.h"
#include "mozilla/dom/Document.h"
#include "nsBindingManager.h"
#include "nsContentUtils.h"
#include "nsAtom.h"
#include "nsIFrame.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/HTMLSlotElement.h"
#include "mozilla/dom/ShadowRoot.h"
inline bool nsINode::IsUAWidget() const {
auto* shadow = mozilla::dom::ShadowRoot::FromNode(this);
return shadow && shadow->IsUAWidget();
}
inline bool nsINode::IsInUAWidget() const {
if (!IsInShadowTree()) {
return false;
}
mozilla::dom::ShadowRoot* shadow = AsContent()->GetContainingShadow();
return shadow && shadow->IsUAWidget();
}
inline bool nsINode::IsRootOfChromeAccessOnlySubtree() const {
return IsRootOfNativeAnonymousSubtree() || IsUAWidget();
}
inline bool nsIContent::IsInHTMLDocument() const {
return OwnerDoc()->IsHTMLDocument();
}
inline bool nsIContent::IsInChromeDocument() const {
return nsContentUtils::IsChromeDoc(OwnerDoc());
}
inline void nsIContent::SetPrimaryFrame(nsIFrame* aFrame) {
MOZ_ASSERT(IsInUncomposedDoc() || IsInShadowTree(), "This will end badly!");
// FIXME bug 749326
NS_ASSERTION(!aFrame || !mPrimaryFrame || aFrame == mPrimaryFrame,
"Losing track of existing primary frame");
if (aFrame) {
MOZ_ASSERT(!aFrame->IsPlaceholderFrame());
if (MOZ_LIKELY(!IsHTMLElement(nsGkAtoms::area)) ||
aFrame->GetContent() == this) {
aFrame->SetIsPrimaryFrame(true);
}
} else if (nsIFrame* currentPrimaryFrame = GetPrimaryFrame()) {
if (MOZ_LIKELY(!IsHTMLElement(nsGkAtoms::area)) ||
currentPrimaryFrame->GetContent() == this) {
currentPrimaryFrame->SetIsPrimaryFrame(false);
}
}
mPrimaryFrame = aFrame;
}
inline mozilla::dom::ShadowRoot* nsIContent::GetShadowRoot() const {
if (!IsElement()) {
return nullptr;
}
return AsElement()->GetShadowRoot();
}
template <nsINode::FlattenedParentType aType>
static inline nsINode* GetFlattenedTreeParentNode(const nsINode* aNode) {
if (!aNode->IsContent()) {
return nullptr;
}
nsINode* parent = aNode->GetParentNode();
if (!parent || !parent->IsContent()) {
return parent;
}
const nsIContent* content = aNode->AsContent();
nsIContent* parentAsContent = parent->AsContent();
if (aType == nsINode::eForStyle &&
content->IsRootOfNativeAnonymousSubtree() &&
parentAsContent == content->OwnerDoc()->GetRootElement()) {
const bool docLevel =
content->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent);
return docLevel ? content->OwnerDocAsNode() : parent;
}
if (content->IsRootOfAnonymousSubtree()) {
return parent;
}
if (parentAsContent->GetShadowRoot()) {
// If it's not assigned to any slot it's not part of the flat tree, and thus
// we return null.
return content->GetAssignedSlot();
}
if (parentAsContent->IsInShadowTree()) {
if (auto* slot = mozilla::dom::HTMLSlotElement::FromNode(parentAsContent)) {
// If the assigned nodes list is empty, we're fallback content which is
// active, otherwise we are not part of the flat tree.
return slot->AssignedNodes().IsEmpty() ? parent : nullptr;
}
if (auto* shadowRoot =
mozilla::dom::ShadowRoot::FromNode(parentAsContent)) {
return shadowRoot->GetHost();
}
}
if (content->HasFlag(NODE_MAY_BE_IN_BINDING_MNGR) ||
parent->HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
if (nsIContent* xblInsertionPoint = content->GetXBLInsertionPoint()) {
return xblInsertionPoint->GetParent();
}
if (parent->OwnerDoc()->BindingManager()->GetBindingWithContent(
parentAsContent)) {
// This is an unassigned node child of the bound element, so it isn't part
// of the flat tree.
return nullptr;
}
}
MOZ_ASSERT(!parentAsContent->IsActiveChildrenElement(),
"<xbl:children> isn't in the flattened tree");
// Common case.
return parent;
}
inline nsINode* nsINode::GetFlattenedTreeParentNode() const {
return ::GetFlattenedTreeParentNode<nsINode::eNotForStyle>(this);
}
inline nsIContent* nsIContent::GetFlattenedTreeParent() const {
nsINode* parent = GetFlattenedTreeParentNode();
return (parent && parent->IsContent()) ? parent->AsContent() : nullptr;
}
inline bool nsIContent::IsEventAttributeName(nsAtom* aName) {
const char16_t* name = aName->GetUTF16String();
if (name[0] != 'o' || name[1] != 'n') {
return false;
}
return IsEventAttributeNameInternal(aName);
}
inline nsINode* nsINode::GetFlattenedTreeParentNodeForStyle() const {
return ::GetFlattenedTreeParentNode<nsINode::eForStyle>(this);
}
inline bool nsINode::NodeOrAncestorHasDirAuto() const {
return AncestorHasDirAuto() || (IsElement() && AsElement()->HasDirAuto());
}
inline bool nsINode::IsEditable() const {
if (HasFlag(NODE_IS_EDITABLE)) {
// The node is in an editable contentEditable subtree.
return true;
}
// All editable anonymous content should be made explicitly editable via the
// NODE_IS_EDITABLE flag.
if (IsInNativeAnonymousSubtree()) {
return false;
}
// Check if the node is in a document and the document is in designMode.
Document* doc = GetUncomposedDoc();
return doc && doc->HasFlag(NODE_IS_EDITABLE);
}
inline bool nsIContent::IsActiveChildrenElement() const {
if (!mNodeInfo->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
return false;
}
nsIContent* bindingParent = GetBindingParent();
if (!bindingParent) {
return false;
}
// We reuse the binding parent machinery for Shadow DOM too, so prevent that
// from getting us confused in this case.
return !bindingParent->GetShadowRoot();
}
inline bool nsIContent::IsInAnonymousSubtree() const {
NS_ASSERTION(
!IsInNativeAnonymousSubtree() || GetBindingParent() ||
(!IsInUncomposedDoc() && static_cast<nsIContent*>(SubtreeRoot())
->IsInNativeAnonymousSubtree()),
"Must have binding parent when in native anonymous subtree which is in "
"document.\n"
"Native anonymous subtree which is not in document must have native "
"anonymous root.");
if (IsInNativeAnonymousSubtree()) {
return true;
}
nsIContent* bindingParent = GetBindingParent();
if (!bindingParent) {
return false;
}
// We reuse the binding parent machinery for Shadow DOM too, so prevent that
// from getting us confused in this case.
return !bindingParent->GetShadowRoot();
}
#endif // nsIContentInlines_h