Make CXFA_Node inherit from fxcrt::TreeNode<>

Remove explicit pointer manipulations from this class, relying
on TreeNode to keep the tree consistent.

Change-Id: I0836e23ad2dbcaa11d9ed125b8bcd93be92ba0a3
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/53511
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/xfa/fxfa/parser/cxfa_node.cpp b/xfa/fxfa/parser/cxfa_node.cpp
index 737e05d..8f45335 100644
--- a/xfa/fxfa/parser/cxfa_node.cpp
+++ b/xfa/fxfa/parser/cxfa_node.cpp
@@ -1014,7 +1014,7 @@
 }
 
 CXFA_Node* CXFA_Node::GetNextContainerSibling() const {
-  for (auto* pNode = next_sibling_; pNode; pNode = pNode->next_sibling_) {
+  for (auto* pNode = GetNextSibling(); pNode; pNode = pNode->GetNextSibling()) {
     if (pNode->GetObjectType() == XFA_ObjectType::ContainerNode)
       return pNode;
   }
@@ -1022,7 +1022,7 @@
 }
 
 CXFA_Node* CXFA_Node::GetPrevContainerSibling() const {
-  for (auto* pNode = prev_sibling_; pNode; pNode = pNode->prev_sibling_) {
+  for (auto* pNode = GetPrevSibling(); pNode; pNode = pNode->GetPrevSibling()) {
     if (pNode->GetObjectType() == XFA_ObjectType::ContainerNode)
       return pNode;
   }
@@ -1030,7 +1030,7 @@
 }
 
 CXFA_Node* CXFA_Node::GetFirstContainerChild() const {
-  for (auto* pNode = first_child_; pNode; pNode = pNode->next_sibling_) {
+  for (auto* pNode = GetFirstChild(); pNode; pNode = pNode->GetNextSibling()) {
     if (pNode->GetObjectType() == XFA_ObjectType::ContainerNode)
       return pNode;
   }
@@ -1038,7 +1038,7 @@
 }
 
 CXFA_Node* CXFA_Node::GetContainerParent() const {
-  for (auto* pNode = parent_; pNode; pNode = pNode->parent_) {
+  for (auto* pNode = GetParent(); pNode; pNode = pNode->GetParent()) {
     if (pNode->GetObjectType() == XFA_ObjectType::ContainerNode)
       return pNode;
   }
@@ -1109,8 +1109,8 @@
                                                XFA_Element eTypeFilter) {
   if (eTypeFilter != XFA_Element::Unknown) {
     std::vector<CXFA_Node*> nodes;
-    for (CXFA_Node* pChild = first_child_; pChild;
-         pChild = pChild->next_sibling_) {
+    for (CXFA_Node* pChild = GetFirstChild(); pChild;
+         pChild = pChild->GetNextSibling()) {
       if (pChild->GetElementType() == eTypeFilter)
         nodes.push_back(pChild);
     }
@@ -1119,8 +1119,8 @@
 
   if (dwTypeFilter == (XFA_NODEFILTER_Children | XFA_NODEFILTER_Properties)) {
     std::vector<CXFA_Node*> nodes;
-    for (CXFA_Node* pChild = first_child_; pChild;
-         pChild = pChild->next_sibling_)
+    for (CXFA_Node* pChild = GetFirstChild(); pChild;
+         pChild = pChild->GetNextSibling())
       nodes.push_back(pChild);
     return nodes;
   }
@@ -1132,8 +1132,8 @@
   bool bFilterProperties = !!(dwTypeFilter & XFA_NODEFILTER_Properties);
   bool bFilterOneOfProperties = !!(dwTypeFilter & XFA_NODEFILTER_OneOfProperty);
   std::vector<CXFA_Node*> nodes;
-  for (CXFA_Node* pChild = first_child_; pChild;
-       pChild = pChild->next_sibling_) {
+  for (CXFA_Node* pChild = GetFirstChild(); pChild;
+       pChild = pChild->GetNextSibling()) {
     if (HasProperty(pChild->GetElementType())) {
       if (bFilterProperties) {
         nodes.push_back(pChild);
@@ -1475,7 +1475,7 @@
 
 size_t CXFA_Node::CountChildren(XFA_Element eType, bool bOnlyChild) {
   size_t count = 0;
-  for (CXFA_Node* pNode = first_child_; pNode;
+  for (CXFA_Node* pNode = GetFirstChild(); pNode;
        pNode = pNode->GetNextSibling()) {
     if (pNode->GetElementType() != eType && eType != XFA_Element::Unknown)
       continue;
@@ -1490,7 +1490,7 @@
                                        XFA_Element eType,
                                        bool bOnlyChild) const {
   size_t count = 0;
-  for (CXFA_Node* pNode = first_child_; pNode;
+  for (CXFA_Node* pNode = GetFirstChild(); pNode;
        pNode = pNode->GetNextSibling()) {
     if (pNode->GetElementType() != eType && eType != XFA_Element::Unknown)
       continue;
@@ -1505,46 +1505,22 @@
 }
 
 void CXFA_Node::InsertChild(int32_t index, CXFA_Node* pNode) {
-  CHECK(pNode);
-  CHECK(!pNode->parent_);
-
-  pNode->parent_ = this;
+  CHECK(!pNode->GetParent());
   pNode->ClearFlag(XFA_NodeFlag_HasRemovedChildren);
 
-  if (!first_child_) {
-    ASSERT(!last_child_);
-
-    pNode->prev_sibling_ = nullptr;
-    pNode->next_sibling_ = nullptr;
-    first_child_ = pNode;
-    last_child_ = pNode;
+  CXFA_Node* pPrev = GetFirstChild();
+  if (!pPrev) {
+    AppendFirstChild(pNode);
     index = 0;
-  } else if (index == 0) {
-    pNode->prev_sibling_ = nullptr;
-    pNode->next_sibling_ = first_child_;
-    first_child_->prev_sibling_ = pNode;
-    first_child_ = pNode;
   } else if (index < 0) {
-    pNode->prev_sibling_ = last_child_;
-    pNode->next_sibling_ = nullptr;
-    last_child_->next_sibling_ = pNode;
-    last_child_ = pNode;
+    AppendLastChild(pNode);
+  } else if (index == 0) {
+    AppendFirstChild(pNode);
   } else {
-    CXFA_Node* pPrev = first_child_;
     int32_t count = 0;
-    while (++count < index && pPrev->next_sibling_)
-      pPrev = pPrev->next_sibling_;
-
-    pNode->prev_sibling_ = pPrev;
-    pNode->next_sibling_ = pPrev->next_sibling_;
-    if (pPrev->next_sibling_)
-      pPrev->next_sibling_->prev_sibling_ = pNode;
-    pPrev->next_sibling_ = pNode;
-
-    // Move the last child pointer if needed.
-    if (pPrev == last_child_)
-      last_child_ = pNode;
-
+    while (++count < index && pPrev->GetNextSibling())
+      pPrev = pPrev->GetNextSibling();
+    InsertAfter(pNode, pPrev);
     index = count;
   }
 
@@ -1560,18 +1536,18 @@
 }
 
 void CXFA_Node::InsertChild(CXFA_Node* pNode, CXFA_Node* pBeforeNode) {
-  CHECK(!pBeforeNode || pBeforeNode->parent_ == this);
+  CHECK(!pBeforeNode || pBeforeNode->GetParent() == this);
 
   int32_t index = -1;
-  if (!first_child_ || pBeforeNode == first_child_) {
+  if (!GetFirstChild() || pBeforeNode == GetFirstChild()) {
     index = 0;
   } else if (!pBeforeNode) {
     index = -1;
   } else {
     index = 0;
-    CXFA_Node* prev = first_child_;
+    CXFA_Node* prev = GetFirstChild();
     while (prev && prev != pBeforeNode) {
-      prev = prev->next_sibling_;
+      prev = prev->GetNextSibling();
       ++index;
     }
   }
@@ -1580,28 +1556,10 @@
 
 void CXFA_Node::RemoveChild(CXFA_Node* pNode, bool bNotify) {
   CHECK(pNode);
-  CHECK_EQ(pNode->parent_, this);
+  CHECK_EQ(pNode->GetParent(), this);
 
   pNode->SetFlag(XFA_NodeFlag_HasRemovedChildren);
-
-  if (first_child_ == pNode && last_child_ == pNode) {
-    first_child_ = nullptr;
-    last_child_ = nullptr;
-  } else if (first_child_ == pNode) {
-    first_child_ = pNode->next_sibling_;
-    first_child_->prev_sibling_ = nullptr;
-  } else if (last_child_ == pNode) {
-    last_child_ = pNode->prev_sibling_;
-    last_child_->next_sibling_ = nullptr;
-  } else {
-    CXFA_Node* pPrev = pNode->prev_sibling_;
-    pPrev->next_sibling_ = pNode->next_sibling_;
-    pPrev->next_sibling_->prev_sibling_ = pPrev;
-  }
-  pNode->next_sibling_ = nullptr;
-  pNode->prev_sibling_ = nullptr;
-  pNode->parent_ = nullptr;
-
+  TreeNode<CXFA_Node>::RemoveChild(pNode);
   OnRemoved(bNotify);
 
   if (!IsNeedSavingXMLNode() || !pNode->xml_node_)
@@ -1781,7 +1739,7 @@
   if (m_uNodeFlags & dwFlag)
     return true;
   if (dwFlag == XFA_NodeFlag_HasRemovedChildren)
-    return parent_ && parent_->HasFlag(dwFlag);
+    return GetParent() && GetParent()->HasFlag(dwFlag);
   return false;
 }
 
diff --git a/xfa/fxfa/parser/cxfa_node.h b/xfa/fxfa/parser/cxfa_node.h
index 2daae05..182bbae 100644
--- a/xfa/fxfa/parser/cxfa_node.h
+++ b/xfa/fxfa/parser/cxfa_node.h
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include "core/fxcrt/fx_string.h"
+#include "core/fxcrt/tree_node.h"
 #include "core/fxge/fx_dib.h"
 #include "third_party/base/optional.h"
 #include "third_party/base/span.h"
@@ -71,7 +72,7 @@
   XFA_NodeFlag_LayoutGeneratedNode = 1 << 6
 };
 
-class CXFA_Node : public CXFA_Object {
+class CXFA_Node : public CXFA_Object, public TreeNode<CXFA_Node> {
  public:
   struct PropertyData {
     XFA_Element property;
@@ -169,12 +170,6 @@
 
   CXFA_Node* Clone(bool bRecursive);
 
-  CXFA_Node* GetNextSibling() const { return next_sibling_; }
-  CXFA_Node* GetPrevSibling() const { return prev_sibling_; }
-  CXFA_Node* GetFirstChild() const { return first_child_; }
-  CXFA_Node* GetLastChild() const { return last_child_; }
-  CXFA_Node* GetParent() const { return parent_; }
-
   CXFA_Node* GetNextContainerSibling() const;
   CXFA_Node* GetPrevContainerSibling() const;
   CXFA_Node* GetFirstContainerChild() const;
@@ -487,17 +482,6 @@
   pdfium::span<const PropertyData> const m_Properties;
   pdfium::span<const AttributeData> const m_Attributes;
   const uint32_t m_ValidPackets;
-
-  // These members are responsible for building the CXFA_Node tree. Node
-  // pointers within the tree (or in objects owned by nodes in the tree)
-  // can't be UnownedPtr<> because the cleanup process will remove the nodes
-  // in an order that doesn't necessarily match up to the tree structure.
-  CXFA_Node* parent_ = nullptr;        // Raw, intra-tree node pointer.
-  CXFA_Node* next_sibling_ = nullptr;  // Raw, intra-tree node pointer.
-  CXFA_Node* prev_sibling_ = nullptr;  // Raw, intra-tree node pointer.
-  CXFA_Node* first_child_ = nullptr;   // Raw, intra-tree node pointer.
-  CXFA_Node* last_child_ = nullptr;    // Raw, intra-tree node pointer.
-
   UnownedPtr<CFX_XMLNode> xml_node_;
   const XFA_PacketType m_ePacket;
   uint8_t m_ExecuteRecursionDepth = 0;
@@ -509,7 +493,6 @@
   bool m_bPreNull = true;
   bool is_widget_ready_ = false;
   std::unique_ptr<CXFA_WidgetLayoutData> m_pLayoutData;
-
   CXFA_Ui* ui_ = nullptr;
   XFA_FFWidgetType ff_widget_type_ = XFA_FFWidgetType::kNone;
 };