Start CSS parser unit tests

Start adding unit tests for the css parser. Fixup memory
leaks that are exposed by the tests.

Change-Id: Id863d9cd5f13ab82626bc7b945de925253c88d43
Reviewed-on: https://pdfium-review.googlesource.com/2180
Reviewed-by: Nicolás Peña <npm@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: dsinclair <dsinclair@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index fccc6d7..6281eee 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1757,6 +1757,7 @@
   if (pdf_enable_xfa) {
     sources += [
       "xfa/fde/cfde_txtedtbuf_unittest.cpp",
+      "xfa/fde/css/cfde_cssstylesheet_unittest.cpp",
       "xfa/fde/css/fde_cssdatatable_unittest.cpp",
       "xfa/fde/xml/fde_xml_imp_unittest.cpp",
       "xfa/fxbarcode/pdf417/BC_PDF417HighLevelEncoder_unittest.cpp",
diff --git a/xfa/fde/css/cfde_cssstylesheet_unittest.cpp b/xfa/fde/css/cfde_cssstylesheet_unittest.cpp
new file mode 100644
index 0000000..1edc4b5
--- /dev/null
+++ b/xfa/fde/css/cfde_cssstylesheet_unittest.cpp
@@ -0,0 +1,112 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "xfa/fde/css/fde_cssstylesheet.h"
+
+#include <memory>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/base/ptr_util.h"
+
+class CFDE_CSSStyleSheetTest : public testing::Test {
+ public:
+  void SetUp() override {
+    sheet_ = pdfium::MakeUnique<CFDE_CSSStyleSheet>();
+    decl_ = nullptr;
+  }
+
+  void TearDown() override { decl_ = nullptr; }
+
+  void LoadAndVerifyDecl(const FX_WCHAR* buf, size_t decl_count) {
+    ASSERT(sheet_);
+
+    EXPECT_TRUE(sheet_->LoadFromBuffer(buf, FXSYS_wcslen(buf)));
+    EXPECT_EQ(1, sheet_->CountRules());
+
+    CFDE_CSSRule* rule = sheet_->GetRule(0);
+    EXPECT_EQ(FDE_CSSRuleType::Style, rule->GetType());
+
+    CFDE_CSSStyleRule* style = static_cast<CFDE_CSSStyleRule*>(rule);
+    decl_ = style->GetDeclaration();
+    EXPECT_EQ(decl_count, decl_->PropertyCountForTesting());
+  }
+
+  void VerifyFloat(FDE_CSSProperty prop, float val, FDE_CSSPrimitiveType type) {
+    ASSERT(decl_);
+
+    bool important;
+    CFDE_CSSValue* v = decl_->GetProperty(prop, important);
+    CFDE_CSSPrimitiveValue* pval = static_cast<CFDE_CSSPrimitiveValue*>(v);
+    EXPECT_EQ(type, pval->GetPrimitiveType());
+    EXPECT_EQ(val, pval->GetFloat());
+  }
+
+  void VerifyEnum(FDE_CSSProperty prop, FDE_CSSPropertyValue val) {
+    ASSERT(decl_);
+
+    bool important;
+    CFDE_CSSValue* v = decl_->GetProperty(prop, important);
+    CFDE_CSSPrimitiveValue* pval = static_cast<CFDE_CSSPrimitiveValue*>(v);
+    EXPECT_EQ(FDE_CSSPrimitiveType::Enum, pval->GetPrimitiveType());
+    EXPECT_EQ(val, pval->GetEnum());
+  }
+
+  std::unique_ptr<CFDE_CSSStyleSheet> sheet_;
+  CFDE_CSSDeclaration* decl_;
+};
+
+TEST_F(CFDE_CSSStyleSheetTest, ParseBorder) {
+  LoadAndVerifyDecl(L"a { border: 5px; }", 4);
+  VerifyFloat(FDE_CSSProperty::BorderLeftWidth, 5.0,
+              FDE_CSSPrimitiveType::Pixels);
+  VerifyFloat(FDE_CSSProperty::BorderRightWidth, 5.0,
+              FDE_CSSPrimitiveType::Pixels);
+  VerifyFloat(FDE_CSSProperty::BorderTopWidth, 5.0,
+              FDE_CSSPrimitiveType::Pixels);
+  VerifyFloat(FDE_CSSProperty::BorderBottomWidth, 5.0,
+              FDE_CSSPrimitiveType::Pixels);
+}
+
+TEST_F(CFDE_CSSStyleSheetTest, ParseBorderFull) {
+  LoadAndVerifyDecl(L"a { border: 5px solid red; }", 4);
+  VerifyFloat(FDE_CSSProperty::BorderLeftWidth, 5.0,
+              FDE_CSSPrimitiveType::Pixels);
+  VerifyFloat(FDE_CSSProperty::BorderRightWidth, 5.0,
+              FDE_CSSPrimitiveType::Pixels);
+  VerifyFloat(FDE_CSSProperty::BorderTopWidth, 5.0,
+              FDE_CSSPrimitiveType::Pixels);
+  VerifyFloat(FDE_CSSProperty::BorderBottomWidth, 5.0,
+              FDE_CSSPrimitiveType::Pixels);
+}
+
+TEST_F(CFDE_CSSStyleSheetTest, ParseBorderLeft) {
+  LoadAndVerifyDecl(L"a { border-left: 2.5pc; }", 1);
+  VerifyFloat(FDE_CSSProperty::BorderLeftWidth, 2.5,
+              FDE_CSSPrimitiveType::Picas);
+}
+
+TEST_F(CFDE_CSSStyleSheetTest, ParseBorderLeftThick) {
+  LoadAndVerifyDecl(L"a { border-left: thick; }", 1);
+  VerifyEnum(FDE_CSSProperty::BorderLeftWidth, FDE_CSSPropertyValue::Thick);
+}
+
+TEST_F(CFDE_CSSStyleSheetTest, ParseBorderRight) {
+  LoadAndVerifyDecl(L"a { border-right: 2.5pc; }", 1);
+  VerifyFloat(FDE_CSSProperty::BorderRightWidth, 2.5,
+              FDE_CSSPrimitiveType::Picas);
+}
+
+TEST_F(CFDE_CSSStyleSheetTest, ParseBorderTop) {
+  LoadAndVerifyDecl(L"a { border-top: 2.5pc; }", 1);
+  VerifyFloat(FDE_CSSProperty::BorderTopWidth, 2.5,
+              FDE_CSSPrimitiveType::Picas);
+}
+
+TEST_F(CFDE_CSSStyleSheetTest, ParseBorderBottom) {
+  LoadAndVerifyDecl(L"a { border-bottom: 2.5pc; }", 1);
+  VerifyFloat(FDE_CSSProperty::BorderBottomWidth, 2.5,
+              FDE_CSSPrimitiveType::Picas);
+}
diff --git a/xfa/fde/css/cfde_cssvalue.cpp b/xfa/fde/css/cfde_cssvalue.cpp
index 84e9935..0dc577b 100644
--- a/xfa/fde/css/cfde_cssvalue.cpp
+++ b/xfa/fde/css/cfde_cssvalue.cpp
@@ -7,5 +7,3 @@
 #include "xfa/fde/css/cfde_cssvalue.h"
 
 CFDE_CSSValue::CFDE_CSSValue(FDE_CSSVALUETYPE type) : m_value(type) {}
-
-CFDE_CSSValue::~CFDE_CSSValue() {}
diff --git a/xfa/fde/css/cfde_cssvalue.h b/xfa/fde/css/cfde_cssvalue.h
index 17cc565..a5ac24c 100644
--- a/xfa/fde/css/cfde_cssvalue.h
+++ b/xfa/fde/css/cfde_cssvalue.h
@@ -9,10 +9,8 @@
 
 #include "xfa/fde/css/fde_css.h"
 
-class CFDE_CSSValue {
+class CFDE_CSSValue : public CFX_Retainable {
  public:
-  virtual ~CFDE_CSSValue();
-
   FDE_CSSVALUETYPE GetType() const { return m_value; }
 
  protected:
diff --git a/xfa/fde/css/fde_cssdatatable.cpp b/xfa/fde/css/fde_cssdatatable.cpp
index 569a6f2..82a29e2 100644
--- a/xfa/fde/css/fde_cssdatatable.cpp
+++ b/xfa/fde/css/fde_cssdatatable.cpp
@@ -6,6 +6,8 @@
 
 #include "xfa/fde/css/fde_cssdatatable.h"
 
+#include <utility>
+
 #include "core/fxcrt/fx_ext.h"
 #include "xfa/fde/css/fde_cssstyleselector.h"
 #include "xfa/fgas/crt/fgas_codepage.h"
@@ -535,20 +537,19 @@
 }
 
 CFDE_CSSValueList::CFDE_CSSValueList(
-    const CFX_ArrayTemplate<CFDE_CSSValue*>& list)
-    : CFDE_CSSValue(FDE_CSSVALUETYPE_List) {
-  m_iCount = list.GetSize();
-  m_ppList = FX_Alloc(CFDE_CSSValue*, m_iCount);
-  FXSYS_memcpy(m_ppList, list.GetData(), m_iCount * sizeof(CFDE_CSSValue*));
-}
+    std::vector<CFX_RetainPtr<CFDE_CSSValue>>& list)
+    : CFDE_CSSValue(FDE_CSSVALUETYPE_List), m_ppList(std::move(list)) {}
+
+CFDE_CSSValueList::~CFDE_CSSValueList() {}
 
 int32_t CFDE_CSSValueList::CountValues() const {
-  return m_iCount;
+  return m_ppList.size();
 }
 
 CFDE_CSSValue* CFDE_CSSValueList::GetValue(int32_t index) const {
-  return m_ppList[index];
+  return m_ppList[index].Get();
 }
+
 bool CFDE_CSSValueListParser::NextValue(FDE_CSSPrimitiveType& eType,
                                         const FX_WCHAR*& pStart,
                                         int32_t& iLength) {
@@ -651,9 +652,6 @@
   return m_pCur - pStart;
 }
 
-CFDE_CSSPrimitiveValue::CFDE_CSSPrimitiveValue(
-    const CFDE_CSSPrimitiveValue& src) = default;
-
 CFDE_CSSPrimitiveValue::CFDE_CSSPrimitiveValue(FX_ARGB color)
     : CFDE_CSSValue(FDE_CSSVALUETYPE_Primitive),
       m_eType(FDE_CSSPrimitiveType::RGB),
@@ -678,10 +676,13 @@
   ASSERT(m_pString);
 }
 
-CFDE_CSSPrimitiveValue::CFDE_CSSPrimitiveValue(CFDE_CSSFunction* pFunction)
+CFDE_CSSPrimitiveValue::CFDE_CSSPrimitiveValue(
+    std::unique_ptr<CFDE_CSSFunction> pFunction)
     : CFDE_CSSValue(FDE_CSSVALUETYPE_Primitive),
       m_eType(FDE_CSSPrimitiveType::Function),
-      m_pFunction(pFunction) {}
+      m_pFunction(std::move(pFunction)) {}
+
+CFDE_CSSPrimitiveValue::~CFDE_CSSPrimitiveValue() {}
 
 FDE_CSSPrimitiveType CFDE_CSSPrimitiveValue::GetPrimitiveType() const {
   return m_eType;
@@ -724,3 +725,11 @@
   ASSERT(m_eType == FDE_CSSPrimitiveType::Function);
   return m_pFunction->GetArgs(index);
 }
+
+CFDE_CSSFunction::CFDE_CSSFunction(const FX_WCHAR* pszFuncName,
+                                   CFX_RetainPtr<CFDE_CSSValueList> pArgList)
+    : m_pArgList(pArgList), m_pszFuncName(pszFuncName) {
+  ASSERT(pArgList);
+}
+
+CFDE_CSSFunction::~CFDE_CSSFunction() {}
diff --git a/xfa/fde/css/fde_cssdatatable.h b/xfa/fde/css/fde_cssdatatable.h
index 0904b44..0b14ffc 100644
--- a/xfa/fde/css/fde_cssdatatable.h
+++ b/xfa/fde/css/fde_cssdatatable.h
@@ -7,6 +7,9 @@
 #ifndef XFA_FDE_CSS_FDE_CSSDATATABLE_H_
 #define XFA_FDE_CSS_FDE_CSSDATATABLE_H_
 
+#include <memory>
+#include <vector>
+
 #include "core/fxcrt/fx_system.h"
 #include "xfa/fde/css/cfde_cssvalue.h"
 #include "xfa/fde/css/fde_css.h"
@@ -17,10 +20,11 @@
  public:
   explicit CFDE_CSSPrimitiveValue(FX_ARGB color);
   explicit CFDE_CSSPrimitiveValue(FDE_CSSPropertyValue eValue);
-  explicit CFDE_CSSPrimitiveValue(CFDE_CSSFunction* pFunction);
+  explicit CFDE_CSSPrimitiveValue(std::unique_ptr<CFDE_CSSFunction> pFunction);
   CFDE_CSSPrimitiveValue(FDE_CSSPrimitiveType eType, FX_FLOAT fValue);
   CFDE_CSSPrimitiveValue(FDE_CSSPrimitiveType eType, const FX_WCHAR* pValue);
   CFDE_CSSPrimitiveValue(const CFDE_CSSPrimitiveValue& src);
+  ~CFDE_CSSPrimitiveValue() override;
 
   FDE_CSSPrimitiveType GetPrimitiveType() const;
   FX_ARGB GetRGBColor() const;
@@ -37,20 +41,20 @@
     FX_FLOAT m_fNumber;
     const FX_WCHAR* m_pString;
     FDE_CSSPropertyValue m_eEnum;
-    CFDE_CSSFunction* m_pFunction;
   };
+  std::unique_ptr<CFDE_CSSFunction> m_pFunction;
 };
 
 class CFDE_CSSValueList : public CFDE_CSSValue {
  public:
-  explicit CFDE_CSSValueList(const CFX_ArrayTemplate<CFDE_CSSValue*>& list);
+  explicit CFDE_CSSValueList(std::vector<CFX_RetainPtr<CFDE_CSSValue>>& list);
+  ~CFDE_CSSValueList() override;
 
   int32_t CountValues() const;
   CFDE_CSSValue* GetValue(int32_t index) const;
 
  protected:
-  CFDE_CSSValue** m_ppList;
-  int32_t m_iCount;
+  std::vector<CFX_RetainPtr<CFDE_CSSValue>> m_ppList;
 };
 
 class CFDE_CSSValueListParser {
@@ -75,10 +79,10 @@
 
 class CFDE_CSSFunction {
  public:
-  CFDE_CSSFunction(const FX_WCHAR* pszFuncName, CFDE_CSSValueList* pArgList)
-      : m_pArgList(pArgList), m_pszFuncName(pszFuncName) {
-    ASSERT(pArgList);
-  }
+  CFDE_CSSFunction(const FX_WCHAR* pszFuncName,
+                   CFX_RetainPtr<CFDE_CSSValueList> pArgList);
+  ~CFDE_CSSFunction();
+
   int32_t CountArgs() const { return m_pArgList->CountValues(); }
   CFDE_CSSValue* GetArgs(int32_t index) const {
     return m_pArgList->GetValue(index);
@@ -86,7 +90,7 @@
   const FX_WCHAR* GetFuncName() const { return m_pszFuncName; }
 
  protected:
-  CFDE_CSSValueList* m_pArgList;
+  CFX_RetainPtr<CFDE_CSSValueList> m_pArgList;
   const FX_WCHAR* m_pszFuncName;
 };
 
diff --git a/xfa/fde/css/fde_cssdeclaration.cpp b/xfa/fde/css/fde_cssdeclaration.cpp
index b995649..14ed101 100644
--- a/xfa/fde/css/fde_cssdeclaration.cpp
+++ b/xfa/fde/css/fde_cssdeclaration.cpp
@@ -7,45 +7,23 @@
 #include "xfa/fde/css/fde_cssdeclaration.h"
 
 #include "core/fxcrt/fx_ext.h"
+#include "third_party/base/ptr_util.h"
+
+CFDE_CSSDeclaration::CFDE_CSSDeclaration() {}
+
+CFDE_CSSDeclaration::~CFDE_CSSDeclaration() {}
 
 CFDE_CSSValue* CFDE_CSSDeclaration::GetProperty(FDE_CSSProperty eProperty,
                                                 bool& bImportant) const {
-  for (const FDE_CSSPropertyHolder* pHolder = m_pFirstProperty; pHolder;
-       pHolder = pHolder->pNext) {
-    if (pHolder->eProperty == eProperty) {
-      bImportant = pHolder->bImportant;
-      return pHolder->pValue;
+  for (const auto& p : properties_) {
+    if (p->eProperty == eProperty) {
+      bImportant = p->bImportant;
+      return p->pValue.Get();
     }
   }
   return nullptr;
 }
-FX_POSITION CFDE_CSSDeclaration::GetStartPosition() const {
-  return (FX_POSITION)m_pFirstProperty;
-}
-void CFDE_CSSDeclaration::GetNextProperty(FX_POSITION& pos,
-                                          FDE_CSSProperty& eProperty,
-                                          CFDE_CSSValue*& pValue,
-                                          bool& bImportant) const {
-  const FDE_CSSPropertyHolder* pHolder = (const FDE_CSSPropertyHolder*)pos;
-  bImportant = pHolder->bImportant;
-  eProperty = pHolder->eProperty;
-  pValue = pHolder->pValue;
-  pos = (FX_POSITION)pHolder->pNext;
-}
-FX_POSITION CFDE_CSSDeclaration::GetStartCustom() const {
-  return (FX_POSITION)m_pFirstCustom;
-}
-void CFDE_CSSDeclaration::GetNextCustom(FX_POSITION& pos,
-                                        CFX_WideString& wsName,
-                                        CFX_WideString& wsValue) const {
-  const FDE_CSSCustomProperty* pProperty = (const FDE_CSSCustomProperty*)pos;
-  if (!pProperty)
-    return;
 
-  wsName = pProperty->pwsName;
-  wsValue = pProperty->pwsValue;
-  pos = (FX_POSITION)pProperty->pNext;
-}
 const FX_WCHAR* CFDE_CSSDeclaration::CopyToLocal(
     const FDE_CSSPropertyArgs* pArgs,
     const FX_WCHAR* pszValue,
@@ -67,43 +45,40 @@
 
   return psz;
 }
-CFDE_CSSPrimitiveValue* CFDE_CSSDeclaration::NewNumberValue(
+
+CFX_RetainPtr<CFDE_CSSPrimitiveValue> CFDE_CSSDeclaration::NewNumberValue(
     FDE_CSSPrimitiveType eUnit,
     FX_FLOAT fValue) const {
-  static CFDE_CSSPrimitiveValue s_ZeroValue(FDE_CSSPrimitiveType::Number, 0.0f);
-  if (eUnit == FDE_CSSPrimitiveType::Number && FXSYS_fabs(fValue) < 0.001f) {
-    return &s_ZeroValue;
-  }
-  return new CFDE_CSSPrimitiveValue(eUnit, fValue);
+  if (eUnit == FDE_CSSPrimitiveType::Number && FXSYS_fabs(fValue) < 0.001f)
+    fValue = 0.0f;
+  return pdfium::MakeRetain<CFDE_CSSPrimitiveValue>(eUnit, fValue);
 }
-CFDE_CSSPrimitiveValue* CFDE_CSSDeclaration::NewEnumValue(
+
+CFX_RetainPtr<CFDE_CSSPrimitiveValue> CFDE_CSSDeclaration::NewEnumValue(
     FDE_CSSPropertyValue eValue) const {
-  return new CFDE_CSSPrimitiveValue(eValue);
+  return pdfium::MakeRetain<CFDE_CSSPrimitiveValue>(eValue);
 }
+
 void CFDE_CSSDeclaration::AddPropertyHolder(FDE_CSSProperty eProperty,
-                                            CFDE_CSSValue* pValue,
+                                            CFX_RetainPtr<CFDE_CSSValue> pValue,
                                             bool bImportant) {
-  FDE_CSSPropertyHolder* pHolder = new FDE_CSSPropertyHolder;
+  auto pHolder = pdfium::MakeUnique<FDE_CSSPropertyHolder>();
   pHolder->bImportant = bImportant;
   pHolder->eProperty = eProperty;
   pHolder->pValue = pValue;
-  pHolder->pNext = nullptr;
-  if (m_pLastProperty)
-    m_pLastProperty->pNext = pHolder;
-  else
-    m_pFirstProperty = pHolder;
-  m_pLastProperty = pHolder;
+  properties_.push_back(std::move(pHolder));
 }
-bool CFDE_CSSDeclaration::AddProperty(const FDE_CSSPropertyArgs* pArgs,
+
+void CFDE_CSSDeclaration::AddProperty(const FDE_CSSPropertyArgs* pArgs,
                                       const FX_WCHAR* pszValue,
                                       int32_t iValueLen) {
   ASSERT(iValueLen > 0);
   bool bImportant = false;
   if (iValueLen >= 10 && pszValue[iValueLen - 10] == '!' &&
       FXSYS_wcsnicmp(L"important", pszValue + iValueLen - 9, 9) == 0) {
-    if ((iValueLen -= 10) == 0) {
-      return false;
-    }
+    if ((iValueLen -= 10) == 0)
+      return;
+
     bImportant = true;
   }
   const uint32_t dwType = pArgs->pProperty->dwType;
@@ -121,7 +96,7 @@
         if (dwMatch == 0) {
           continue;
         }
-        CFDE_CSSValue* pCSSValue = nullptr;
+        CFX_RetainPtr<CFDE_CSSValue> pCSSValue;
         switch (dwMatch) {
           case FDE_CSSVALUETYPE_MaybeFunction:
             pCSSValue = ParseFunction(pArgs, pszValue, iValueLen);
@@ -146,18 +121,19 @@
         }
         if (pCSSValue) {
           AddPropertyHolder(pArgs->pProperty->eName, pCSSValue, bImportant);
-          return true;
+          return;
         }
-        if (FDE_IsOnlyValue(dwType, g_ValueGuessOrder[i])) {
-          return false;
-        }
+        if (FDE_IsOnlyValue(dwType, g_ValueGuessOrder[i]))
+          return;
       }
-    } break;
+      break;
+    }
     case FDE_CSSVALUETYPE_Shorthand: {
-      CFDE_CSSValue* pWidth;
+      CFX_RetainPtr<CFDE_CSSValue> pWidth;
       switch (pArgs->pProperty->eName) {
         case FDE_CSSProperty::Font:
-          return ParseFontProperty(pArgs, pszValue, iValueLen, bImportant);
+          ParseFontProperty(pArgs, pszValue, iValueLen, bImportant);
+          return;
         case FDE_CSSProperty::Border:
           if (ParseBorderProperty(pszValue, iValueLen, pWidth)) {
             AddPropertyHolder(FDE_CSSProperty::BorderLeftWidth, pWidth,
@@ -168,35 +144,35 @@
                               bImportant);
             AddPropertyHolder(FDE_CSSProperty::BorderBottomWidth, pWidth,
                               bImportant);
-            return true;
+            return;
           }
           break;
         case FDE_CSSProperty::BorderLeft:
           if (ParseBorderProperty(pszValue, iValueLen, pWidth)) {
             AddPropertyHolder(FDE_CSSProperty::BorderLeftWidth, pWidth,
                               bImportant);
-            return true;
+            return;
           }
           break;
         case FDE_CSSProperty::BorderTop:
           if (ParseBorderProperty(pszValue, iValueLen, pWidth)) {
             AddPropertyHolder(FDE_CSSProperty::BorderTopWidth, pWidth,
                               bImportant);
-            return true;
+            return;
           }
           break;
         case FDE_CSSProperty::BorderRight:
           if (ParseBorderProperty(pszValue, iValueLen, pWidth)) {
             AddPropertyHolder(FDE_CSSProperty::BorderRightWidth, pWidth,
                               bImportant);
-            return true;
+            return;
           }
           break;
         case FDE_CSSProperty::BorderBottom:
           if (ParseBorderProperty(pszValue, iValueLen, pWidth)) {
             AddPropertyHolder(FDE_CSSProperty::BorderBottomWidth, pWidth,
                               bImportant);
-            return true;
+            return;
           }
           break;
         default:
@@ -204,60 +180,59 @@
       }
     } break;
     case FDE_CSSVALUETYPE_List:
-      return ParseValueListProperty(pArgs, pszValue, iValueLen, bImportant);
+      ParseValueListProperty(pArgs, pszValue, iValueLen, bImportant);
+      return;
     default:
       ASSERT(false);
       break;
   }
-  return false;
 }
-bool CFDE_CSSDeclaration::AddProperty(const FDE_CSSPropertyArgs* pArgs,
+
+void CFDE_CSSDeclaration::AddProperty(const FDE_CSSPropertyArgs* pArgs,
                                       const FX_WCHAR* pszName,
                                       int32_t iNameLen,
                                       const FX_WCHAR* pszValue,
                                       int32_t iValueLen) {
-  FDE_CSSCustomProperty* pProperty = new FDE_CSSCustomProperty;
+  auto pProperty = pdfium::MakeUnique<FDE_CSSCustomProperty>();
   pProperty->pwsName = CopyToLocal(pArgs, pszName, iNameLen);
   pProperty->pwsValue = CopyToLocal(pArgs, pszValue, iValueLen);
-  pProperty->pNext = nullptr;
-  if (m_pLastCustom)
-    m_pLastCustom->pNext = pProperty;
-  else
-    m_pFirstCustom = pProperty;
-  m_pLastCustom = pProperty;
-  return true;
+  custom_properties_.push_back(std::move(pProperty));
 }
-CFDE_CSSValue* CFDE_CSSDeclaration::ParseNumber(
+
+CFX_RetainPtr<CFDE_CSSValue> CFDE_CSSDeclaration::ParseNumber(
     const FDE_CSSPropertyArgs* pArgs,
     const FX_WCHAR* pszValue,
     int32_t iValueLen) {
   FX_FLOAT fValue;
   FDE_CSSPrimitiveType eUnit;
-  if (!FDE_ParseCSSNumber(pszValue, iValueLen, fValue, eUnit)) {
+  if (!FDE_ParseCSSNumber(pszValue, iValueLen, fValue, eUnit))
     return nullptr;
-  }
   return NewNumberValue(eUnit, fValue);
 }
-CFDE_CSSValue* CFDE_CSSDeclaration::ParseEnum(const FDE_CSSPropertyArgs* pArgs,
-                                              const FX_WCHAR* pszValue,
-                                              int32_t iValueLen) {
+
+CFX_RetainPtr<CFDE_CSSValue> CFDE_CSSDeclaration::ParseEnum(
+    const FDE_CSSPropertyArgs* pArgs,
+    const FX_WCHAR* pszValue,
+    int32_t iValueLen) {
   const FDE_CSSPropertyValueTable* pValue =
       FDE_GetCSSPropertyValueByName(CFX_WideStringC(pszValue, iValueLen));
   return pValue ? NewEnumValue(pValue->eName) : nullptr;
 }
-CFDE_CSSValue* CFDE_CSSDeclaration::ParseColor(const FDE_CSSPropertyArgs* pArgs,
-                                               const FX_WCHAR* pszValue,
-                                               int32_t iValueLen) {
+
+CFX_RetainPtr<CFDE_CSSValue> CFDE_CSSDeclaration::ParseColor(
+    const FDE_CSSPropertyArgs* pArgs,
+    const FX_WCHAR* pszValue,
+    int32_t iValueLen) {
   FX_ARGB dwColor;
-  if (!FDE_ParseCSSColor(pszValue, iValueLen, dwColor)) {
+  if (!FDE_ParseCSSColor(pszValue, iValueLen, dwColor))
     return nullptr;
-  }
-  return new CFDE_CSSPrimitiveValue(dwColor);
+  return pdfium::MakeRetain<CFDE_CSSPrimitiveValue>(dwColor);
 }
 
-CFDE_CSSValue* CFDE_CSSDeclaration::ParseURI(const FDE_CSSPropertyArgs* pArgs,
-                                             const FX_WCHAR* pszValue,
-                                             int32_t iValueLen) {
+CFX_RetainPtr<CFDE_CSSValue> CFDE_CSSDeclaration::ParseURI(
+    const FDE_CSSPropertyArgs* pArgs,
+    const FX_WCHAR* pszValue,
+    int32_t iValueLen) {
   int32_t iOffset;
   if (!FDE_ParseCSSURI(pszValue, &iOffset, &iValueLen))
     return nullptr;
@@ -266,12 +241,12 @@
     return nullptr;
 
   pszValue = CopyToLocal(pArgs, pszValue + iOffset, iValueLen);
-  return pszValue
-             ? new CFDE_CSSPrimitiveValue(FDE_CSSPrimitiveType::URI, pszValue)
-             : nullptr;
+  return pszValue ? pdfium::MakeRetain<CFDE_CSSPrimitiveValue>(
+                        FDE_CSSPrimitiveType::URI, pszValue)
+                  : nullptr;
 }
 
-CFDE_CSSValue* CFDE_CSSDeclaration::ParseString(
+CFX_RetainPtr<CFDE_CSSValue> CFDE_CSSDeclaration::ParseString(
     const FDE_CSSPropertyArgs* pArgs,
     const FX_WCHAR* pszValue,
     int32_t iValueLen) {
@@ -283,32 +258,31 @@
     return nullptr;
 
   pszValue = CopyToLocal(pArgs, pszValue + iOffset, iValueLen);
-  return pszValue ? new CFDE_CSSPrimitiveValue(FDE_CSSPrimitiveType::String,
-                                               pszValue)
+  return pszValue ? pdfium::MakeRetain<CFDE_CSSPrimitiveValue>(
+                        FDE_CSSPrimitiveType::String, pszValue)
                   : nullptr;
 }
-CFDE_CSSValue* CFDE_CSSDeclaration::ParseFunction(
+
+CFX_RetainPtr<CFDE_CSSValue> CFDE_CSSDeclaration::ParseFunction(
     const FDE_CSSPropertyArgs* pArgs,
     const FX_WCHAR* pszValue,
     int32_t iValueLen) {
-  if (pszValue[iValueLen - 1] != ')') {
+  if (pszValue[iValueLen - 1] != ')')
     return nullptr;
-  }
+
   int32_t iStartBracket = 0;
   while (pszValue[iStartBracket] != '(') {
-    if (iStartBracket < iValueLen) {
-      iStartBracket++;
-    } else {
+    if (iStartBracket >= iValueLen)
       return nullptr;
-    }
+    iStartBracket++;
   }
-  if (iStartBracket == 0) {
+  if (iStartBracket == 0)
     return nullptr;
-  }
+
   const FX_WCHAR* pszFuncName = CopyToLocal(pArgs, pszValue, iStartBracket);
   pszValue += (iStartBracket + 1);
   iValueLen -= (iStartBracket + 2);
-  CFX_ArrayTemplate<CFDE_CSSValue*> argumentArr;
+  std::vector<CFX_RetainPtr<CFDE_CSSValue>> argumentArr;
   CFDE_CSSValueListParser parser(pszValue, iValueLen, ',');
   FDE_CSSPrimitiveType ePrimitiveType;
   while (parser.NextValue(ePrimitiveType, pszValue, iValueLen)) {
@@ -317,17 +291,16 @@
         const FDE_CSSPropertyValueTable* pPropertyValue =
             FDE_GetCSSPropertyValueByName(CFX_WideStringC(pszValue, iValueLen));
         if (pPropertyValue) {
-          argumentArr.Add(NewEnumValue(pPropertyValue->eName));
+          argumentArr.push_back(NewEnumValue(pPropertyValue->eName));
           continue;
         }
 
-        CFDE_CSSValue* pFunctionValue =
-            ParseFunction(pArgs, pszValue, iValueLen);
+        auto pFunctionValue = ParseFunction(pArgs, pszValue, iValueLen);
         if (pFunctionValue) {
-          argumentArr.Add(pFunctionValue);
+          argumentArr.push_back(pFunctionValue);
           continue;
         }
-        argumentArr.Add(new CFDE_CSSPrimitiveValue(
+        argumentArr.push_back(pdfium::MakeRetain<CFDE_CSSPrimitiveValue>(
             FDE_CSSPrimitiveType::String,
             CopyToLocal(pArgs, pszValue, iValueLen)));
         break;
@@ -335,23 +308,24 @@
       case FDE_CSSPrimitiveType::Number: {
         FX_FLOAT fValue;
         if (FDE_ParseCSSNumber(pszValue, iValueLen, fValue, ePrimitiveType))
-          argumentArr.Add(NewNumberValue(ePrimitiveType, fValue));
+          argumentArr.push_back(NewNumberValue(ePrimitiveType, fValue));
         break;
       }
       default:
-        argumentArr.Add(new CFDE_CSSPrimitiveValue(
+        argumentArr.push_back(pdfium::MakeRetain<CFDE_CSSPrimitiveValue>(
             FDE_CSSPrimitiveType::String,
             CopyToLocal(pArgs, pszValue, iValueLen)));
         break;
     }
   }
-  CFDE_CSSValueList* pArgumentList = new CFDE_CSSValueList(argumentArr);
-  CFDE_CSSFunction* pFunction =
-      new CFDE_CSSFunction(pszFuncName, pArgumentList);
-  return new CFDE_CSSPrimitiveValue(pFunction);
+
+  auto pArgumentList = pdfium::MakeRetain<CFDE_CSSValueList>(argumentArr);
+  auto pFunction =
+      pdfium::MakeUnique<CFDE_CSSFunction>(pszFuncName, pArgumentList);
+  return pdfium::MakeRetain<CFDE_CSSPrimitiveValue>(std::move(pFunction));
 }
 
-bool CFDE_CSSDeclaration::ParseValueListProperty(
+void CFDE_CSSDeclaration::ParseValueListProperty(
     const FDE_CSSPropertyArgs* pArgs,
     const FX_WCHAR* pszValue,
     int32_t iValueLen,
@@ -359,23 +333,24 @@
   FX_WCHAR separator =
       (pArgs->pProperty->eName == FDE_CSSProperty::FontFamily) ? ',' : ' ';
   CFDE_CSSValueListParser parser(pszValue, iValueLen, separator);
+
   const uint32_t dwType = pArgs->pProperty->dwType;
   FDE_CSSPrimitiveType eType;
-  CFX_ArrayTemplate<CFDE_CSSValue*> list;
+  std::vector<CFX_RetainPtr<CFDE_CSSValue>> list;
   while (parser.NextValue(eType, pszValue, iValueLen)) {
     switch (eType) {
       case FDE_CSSPrimitiveType::Number:
         if (dwType & FDE_CSSVALUETYPE_MaybeNumber) {
           FX_FLOAT fValue;
           if (FDE_ParseCSSNumber(pszValue, iValueLen, fValue, eType))
-            list.Add(NewNumberValue(eType, fValue));
+            list.push_back(NewNumberValue(eType, fValue));
         }
         break;
       case FDE_CSSPrimitiveType::String:
         if (dwType & FDE_CSSVALUETYPE_MaybeColor) {
           FX_ARGB dwColor;
           if (FDE_ParseCSSColor(pszValue, iValueLen, dwColor)) {
-            list.Add(new CFDE_CSSPrimitiveValue(dwColor));
+            list.push_back(pdfium::MakeRetain<CFDE_CSSPrimitiveValue>(dwColor));
             continue;
           }
         }
@@ -384,21 +359,21 @@
               FDE_GetCSSPropertyValueByName(
                   CFX_WideStringC(pszValue, iValueLen));
           if (pValue) {
-            list.Add(NewEnumValue(pValue->eName));
+            list.push_back(NewEnumValue(pValue->eName));
             continue;
           }
         }
         if (dwType & FDE_CSSVALUETYPE_MaybeString) {
           pszValue = CopyToLocal(pArgs, pszValue, iValueLen);
-          list.Add(new CFDE_CSSPrimitiveValue(FDE_CSSPrimitiveType::String,
-                                              pszValue));
+          list.push_back(pdfium::MakeRetain<CFDE_CSSPrimitiveValue>(
+              FDE_CSSPrimitiveType::String, pszValue));
         }
         break;
       case FDE_CSSPrimitiveType::RGB:
         if (dwType & FDE_CSSVALUETYPE_MaybeColor) {
           FX_ARGB dwColor;
           if (FDE_ParseCSSColor(pszValue, iValueLen, dwColor)) {
-            list.Add(new CFDE_CSSPrimitiveValue(dwColor));
+            list.push_back(pdfium::MakeRetain<CFDE_CSSPrimitiveValue>(dwColor));
           }
         }
         break;
@@ -406,75 +381,79 @@
         break;
     }
   }
-  if (list.GetSize() == 0) {
-    return false;
-  }
+  if (list.empty())
+    return;
+
   switch (pArgs->pProperty->eName) {
     case FDE_CSSProperty::BorderWidth:
-      return Add4ValuesProperty(
-          list, bImportant, FDE_CSSProperty::BorderLeftWidth,
-          FDE_CSSProperty::BorderTopWidth, FDE_CSSProperty::BorderRightWidth,
-          FDE_CSSProperty::BorderBottomWidth);
+      Add4ValuesProperty(list, bImportant, FDE_CSSProperty::BorderLeftWidth,
+                         FDE_CSSProperty::BorderTopWidth,
+                         FDE_CSSProperty::BorderRightWidth,
+                         FDE_CSSProperty::BorderBottomWidth);
+      return;
     case FDE_CSSProperty::Margin:
-      return Add4ValuesProperty(list, bImportant, FDE_CSSProperty::MarginLeft,
-                                FDE_CSSProperty::MarginTop,
-                                FDE_CSSProperty::MarginRight,
-                                FDE_CSSProperty::MarginBottom);
+      Add4ValuesProperty(list, bImportant, FDE_CSSProperty::MarginLeft,
+                         FDE_CSSProperty::MarginTop,
+                         FDE_CSSProperty::MarginRight,
+                         FDE_CSSProperty::MarginBottom);
+      return;
     case FDE_CSSProperty::Padding:
-      return Add4ValuesProperty(list, bImportant, FDE_CSSProperty::PaddingLeft,
-                                FDE_CSSProperty::PaddingTop,
-                                FDE_CSSProperty::PaddingRight,
-                                FDE_CSSProperty::PaddingBottom);
+      Add4ValuesProperty(list, bImportant, FDE_CSSProperty::PaddingLeft,
+                         FDE_CSSProperty::PaddingTop,
+                         FDE_CSSProperty::PaddingRight,
+                         FDE_CSSProperty::PaddingBottom);
+      return;
     default: {
-      CFDE_CSSValueList* pList = new CFDE_CSSValueList(list);
+      auto pList = pdfium::MakeRetain<CFDE_CSSValueList>(list);
       AddPropertyHolder(pArgs->pProperty->eName, pList, bImportant);
-      return true;
-    } break;
+      return;
+    }
   }
-  return false;
 }
 
-bool CFDE_CSSDeclaration::Add4ValuesProperty(
-    const CFX_ArrayTemplate<CFDE_CSSValue*>& list,
+void CFDE_CSSDeclaration::Add4ValuesProperty(
+    const std::vector<CFX_RetainPtr<CFDE_CSSValue>>& list,
     bool bImportant,
     FDE_CSSProperty eLeft,
     FDE_CSSProperty eTop,
     FDE_CSSProperty eRight,
     FDE_CSSProperty eBottom) {
-  switch (list.GetSize()) {
+  switch (list.size()) {
     case 1:
       AddPropertyHolder(eLeft, list[0], bImportant);
       AddPropertyHolder(eTop, list[0], bImportant);
       AddPropertyHolder(eRight, list[0], bImportant);
       AddPropertyHolder(eBottom, list[0], bImportant);
-      return true;
+      return;
     case 2:
       AddPropertyHolder(eLeft, list[1], bImportant);
       AddPropertyHolder(eTop, list[0], bImportant);
       AddPropertyHolder(eRight, list[1], bImportant);
       AddPropertyHolder(eBottom, list[0], bImportant);
-      return true;
+      return;
     case 3:
       AddPropertyHolder(eLeft, list[1], bImportant);
       AddPropertyHolder(eTop, list[0], bImportant);
       AddPropertyHolder(eRight, list[1], bImportant);
       AddPropertyHolder(eBottom, list[2], bImportant);
-      return true;
+      return;
     case 4:
       AddPropertyHolder(eLeft, list[3], bImportant);
       AddPropertyHolder(eTop, list[0], bImportant);
       AddPropertyHolder(eRight, list[1], bImportant);
       AddPropertyHolder(eBottom, list[2], bImportant);
-      return true;
+      return;
     default:
       break;
   }
-  return false;
 }
-bool CFDE_CSSDeclaration::ParseBorderProperty(const FX_WCHAR* pszValue,
-                                              int32_t iValueLen,
-                                              CFDE_CSSValue*& pWidth) const {
-  pWidth = nullptr;
+
+bool CFDE_CSSDeclaration::ParseBorderProperty(
+    const FX_WCHAR* pszValue,
+    int32_t iValueLen,
+    CFX_RetainPtr<CFDE_CSSValue>& pWidth) const {
+  pWidth.Reset(nullptr);
+
   CFDE_CSSValueListParser parser(pszValue, iValueLen, ' ');
   FDE_CSSPrimitiveType eType;
   while (parser.NextValue(eType, pszValue, iValueLen)) {
@@ -521,17 +500,17 @@
   return true;
 }
 
-bool CFDE_CSSDeclaration::ParseFontProperty(const FDE_CSSPropertyArgs* pArgs,
+void CFDE_CSSDeclaration::ParseFontProperty(const FDE_CSSPropertyArgs* pArgs,
                                             const FX_WCHAR* pszValue,
                                             int32_t iValueLen,
                                             bool bImportant) {
   CFDE_CSSValueListParser parser(pszValue, iValueLen, '/');
-  CFDE_CSSPrimitiveValue* pStyle = nullptr;
-  CFDE_CSSPrimitiveValue* pVariant = nullptr;
-  CFDE_CSSPrimitiveValue* pWeight = nullptr;
-  CFDE_CSSPrimitiveValue* pFontSize = nullptr;
-  CFDE_CSSPrimitiveValue* pLineHeight = nullptr;
-  CFX_ArrayTemplate<CFDE_CSSValue*> familyList;
+  CFX_RetainPtr<CFDE_CSSPrimitiveValue> pStyle;
+  CFX_RetainPtr<CFDE_CSSPrimitiveValue> pVariant;
+  CFX_RetainPtr<CFDE_CSSPrimitiveValue> pWeight;
+  CFX_RetainPtr<CFDE_CSSPrimitiveValue> pFontSize;
+  CFX_RetainPtr<CFDE_CSSPrimitiveValue> pLineHeight;
+  std::vector<CFX_RetainPtr<CFDE_CSSValue>> familyList;
   FDE_CSSPrimitiveType eType;
   while (parser.NextValue(eType, pszValue, iValueLen)) {
     switch (eType) {
@@ -584,16 +563,16 @@
           }
         }
         if (pFontSize) {
-          familyList.Add(new CFDE_CSSPrimitiveValue(
+          familyList.push_back(pdfium::MakeRetain<CFDE_CSSPrimitiveValue>(
               eType, CopyToLocal(pArgs, pszValue, iValueLen)));
         }
         parser.m_Separator = ',';
-      } break;
+        break;
+      }
       case FDE_CSSPrimitiveType::Number: {
         FX_FLOAT fValue;
-        if (!FDE_ParseCSSNumber(pszValue, iValueLen, fValue, eType)) {
+        if (!FDE_ParseCSSNumber(pszValue, iValueLen, fValue, eType))
           break;
-        }
         if (eType == FDE_CSSPrimitiveType::Number) {
           switch ((int32_t)fValue) {
             case 100:
@@ -605,9 +584,8 @@
             case 700:
             case 800:
             case 900:
-              if (!pWeight) {
+              if (!pWeight)
                 pWeight = NewNumberValue(FDE_CSSPrimitiveType::Number, fValue);
-              }
               continue;
           }
         }
@@ -615,11 +593,13 @@
           pFontSize = NewNumberValue(eType, fValue);
         else if (!pLineHeight)
           pLineHeight = NewNumberValue(eType, fValue);
-      } break;
+        break;
+      }
       default:
         break;
     }
   }
+
   if (!pStyle)
     pStyle = NewEnumValue(FDE_CSSPropertyValue::Normal);
   if (!pVariant)
@@ -636,9 +616,16 @@
   AddPropertyHolder(FDE_CSSProperty::FontWeight, pWeight, bImportant);
   AddPropertyHolder(FDE_CSSProperty::FontSize, pFontSize, bImportant);
   AddPropertyHolder(FDE_CSSProperty::LineHeight, pLineHeight, bImportant);
-  if (familyList.GetSize() > 0) {
-    CFDE_CSSValueList* pList = new CFDE_CSSValueList(familyList);
+  if (!familyList.empty()) {
+    auto pList = pdfium::MakeRetain<CFDE_CSSValueList>(familyList);
     AddPropertyHolder(FDE_CSSProperty::FontFamily, pList, bImportant);
   }
-  return true;
 }
+
+size_t CFDE_CSSDeclaration::PropertyCountForTesting() const {
+  return properties_.size();
+}
+
+FDE_CSSPropertyHolder::FDE_CSSPropertyHolder() {}
+
+FDE_CSSPropertyHolder::~FDE_CSSPropertyHolder() {}
diff --git a/xfa/fde/css/fde_cssdeclaration.h b/xfa/fde/css/fde_cssdeclaration.h
index 2dbd7a0..bb8795c 100644
--- a/xfa/fde/css/fde_cssdeclaration.h
+++ b/xfa/fde/css/fde_cssdeclaration.h
@@ -7,23 +7,27 @@
 #ifndef XFA_FDE_CSS_FDE_CSSDECLARATION_H_
 #define XFA_FDE_CSS_FDE_CSSDECLARATION_H_
 
+#include <memory>
 #include <unordered_map>
+#include <utility>
+#include <vector>
 
 #include "xfa/fde/css/fde_cssdatatable.h"
 
 class FDE_CSSPropertyHolder {
  public:
+  FDE_CSSPropertyHolder();
+  ~FDE_CSSPropertyHolder();
+
   FDE_CSSProperty eProperty;
   bool bImportant;
-  CFDE_CSSValue* pValue;
-  FDE_CSSPropertyHolder* pNext;
+  CFX_RetainPtr<CFDE_CSSValue> pValue;
 };
 
 class FDE_CSSCustomProperty {
  public:
   const FX_WCHAR* pwsName;
   const FX_WCHAR* pwsValue;
-  FDE_CSSCustomProperty* pNext;
 };
 
 struct FDE_CSSPropertyArgs {
@@ -33,81 +37,87 @@
 
 class CFDE_CSSDeclaration {
  public:
-  CFDE_CSSDeclaration()
-      : m_pFirstProperty(nullptr),
-        m_pLastProperty(nullptr),
-        m_pFirstCustom(nullptr),
-        m_pLastCustom(nullptr) {}
+  using const_prop_iterator =
+      std::vector<std::unique_ptr<FDE_CSSPropertyHolder>>::const_iterator;
+  using const_custom_iterator =
+      std::vector<std::unique_ptr<FDE_CSSCustomProperty>>::const_iterator;
+
+  CFDE_CSSDeclaration();
+  ~CFDE_CSSDeclaration();
 
   CFDE_CSSValue* GetProperty(FDE_CSSProperty eProperty, bool& bImportant) const;
-  FX_POSITION GetStartPosition() const;
-  void GetNextProperty(FX_POSITION& pos,
-                       FDE_CSSProperty& eProperty,
-                       CFDE_CSSValue*& pValue,
-                       bool& bImportant) const;
-  FX_POSITION GetStartCustom() const;
-  void GetNextCustom(FX_POSITION& pos,
-                     CFX_WideString& wsName,
-                     CFX_WideString& wsValue) const;
-  bool AddProperty(const FDE_CSSPropertyArgs* pArgs,
+
+  const_prop_iterator begin() const { return properties_.begin(); }
+  const_prop_iterator end() const { return properties_.end(); }
+
+  const_custom_iterator custom_begin() const {
+    return custom_properties_.begin();
+  }
+  const_custom_iterator custom_end() const { return custom_properties_.end(); }
+
+  bool empty() const { return properties_.empty(); }
+
+  void AddProperty(const FDE_CSSPropertyArgs* pArgs,
                    const FX_WCHAR* pszValue,
                    int32_t iValueLen);
-  bool AddProperty(const FDE_CSSPropertyArgs* pArgs,
+  void AddProperty(const FDE_CSSPropertyArgs* pArgs,
                    const FX_WCHAR* pszName,
                    int32_t iNameLen,
                    const FX_WCHAR* pszValue,
                    int32_t iValueLen);
 
+  size_t PropertyCountForTesting() const;
+
  protected:
-  bool ParseFontProperty(const FDE_CSSPropertyArgs* pArgs,
+  void ParseFontProperty(const FDE_CSSPropertyArgs* pArgs,
                          const FX_WCHAR* pszValue,
                          int32_t iValueLen,
                          bool bImportant);
   bool ParseBorderProperty(const FX_WCHAR* pszValue,
                            int32_t iValueLen,
-                           CFDE_CSSValue*& pWidth) const;
-  bool ParseValueListProperty(const FDE_CSSPropertyArgs* pArgs,
+                           CFX_RetainPtr<CFDE_CSSValue>& pWidth) const;
+  void ParseValueListProperty(const FDE_CSSPropertyArgs* pArgs,
                               const FX_WCHAR* pszValue,
                               int32_t iValueLen,
                               bool bImportant);
-  bool Add4ValuesProperty(const CFX_ArrayTemplate<CFDE_CSSValue*>& list,
+  void Add4ValuesProperty(const std::vector<CFX_RetainPtr<CFDE_CSSValue>>& list,
                           bool bImportant,
                           FDE_CSSProperty eLeft,
                           FDE_CSSProperty eTop,
                           FDE_CSSProperty eRight,
                           FDE_CSSProperty eBottom);
-  CFDE_CSSValue* ParseNumber(const FDE_CSSPropertyArgs* pArgs,
-                             const FX_WCHAR* pszValue,
-                             int32_t iValueLen);
-  CFDE_CSSValue* ParseEnum(const FDE_CSSPropertyArgs* pArgs,
-                           const FX_WCHAR* pszValue,
-                           int32_t iValueLen);
-  CFDE_CSSValue* ParseColor(const FDE_CSSPropertyArgs* pArgs,
-                            const FX_WCHAR* pszValue,
-                            int32_t iValueLen);
-  CFDE_CSSValue* ParseURI(const FDE_CSSPropertyArgs* pArgs,
-                          const FX_WCHAR* pszValue,
-                          int32_t iValueLen);
-  CFDE_CSSValue* ParseString(const FDE_CSSPropertyArgs* pArgs,
-                             const FX_WCHAR* pszValue,
-                             int32_t iValueLen);
-  CFDE_CSSValue* ParseFunction(const FDE_CSSPropertyArgs* pArgs,
-                               const FX_WCHAR* pszValue,
-                               int32_t iValueLen);
+  CFX_RetainPtr<CFDE_CSSValue> ParseNumber(const FDE_CSSPropertyArgs* pArgs,
+                                           const FX_WCHAR* pszValue,
+                                           int32_t iValueLen);
+  CFX_RetainPtr<CFDE_CSSValue> ParseEnum(const FDE_CSSPropertyArgs* pArgs,
+                                         const FX_WCHAR* pszValue,
+                                         int32_t iValueLen);
+  CFX_RetainPtr<CFDE_CSSValue> ParseColor(const FDE_CSSPropertyArgs* pArgs,
+                                          const FX_WCHAR* pszValue,
+                                          int32_t iValueLen);
+  CFX_RetainPtr<CFDE_CSSValue> ParseURI(const FDE_CSSPropertyArgs* pArgs,
+                                        const FX_WCHAR* pszValue,
+                                        int32_t iValueLen);
+  CFX_RetainPtr<CFDE_CSSValue> ParseString(const FDE_CSSPropertyArgs* pArgs,
+                                           const FX_WCHAR* pszValue,
+                                           int32_t iValueLen);
+  CFX_RetainPtr<CFDE_CSSValue> ParseFunction(const FDE_CSSPropertyArgs* pArgs,
+                                             const FX_WCHAR* pszValue,
+                                             int32_t iValueLen);
   const FX_WCHAR* CopyToLocal(const FDE_CSSPropertyArgs* pArgs,
                               const FX_WCHAR* pszValue,
                               int32_t iValueLen);
   void AddPropertyHolder(FDE_CSSProperty eProperty,
-                         CFDE_CSSValue* pValue,
+                         CFX_RetainPtr<CFDE_CSSValue> pValue,
                          bool bImportant);
-  CFDE_CSSPrimitiveValue* NewNumberValue(FDE_CSSPrimitiveType eUnit,
-                                         FX_FLOAT fValue) const;
-  CFDE_CSSPrimitiveValue* NewEnumValue(FDE_CSSPropertyValue eValue) const;
+  CFX_RetainPtr<CFDE_CSSPrimitiveValue> NewNumberValue(
+      FDE_CSSPrimitiveType eUnit,
+      FX_FLOAT fValue) const;
+  CFX_RetainPtr<CFDE_CSSPrimitiveValue> NewEnumValue(
+      FDE_CSSPropertyValue eValue) const;
 
-  FDE_CSSPropertyHolder* m_pFirstProperty;
-  FDE_CSSPropertyHolder* m_pLastProperty;
-  FDE_CSSCustomProperty* m_pFirstCustom;
-  FDE_CSSCustomProperty* m_pLastCustom;
+  std::vector<std::unique_ptr<FDE_CSSPropertyHolder>> properties_;
+  std::vector<std::unique_ptr<FDE_CSSCustomProperty>> custom_properties_;
 };
 
 #endif  // XFA_FDE_CSS_FDE_CSSDECLARATION_H_
diff --git a/xfa/fde/css/fde_cssstyleselector.cpp b/xfa/fde/css/fde_cssstyleselector.cpp
index 5e981d9..e6ee18f 100644
--- a/xfa/fde/css/fde_cssstyleselector.cpp
+++ b/xfa/fde/css/fde_cssstyleselector.cpp
@@ -280,14 +280,15 @@
     int32_t iDeclCount,
     CFDE_CSSComputedStyle* pDestStyle) {
   CFDE_CSSComputedStyle* pComputedStyle = pDestStyle;
-  CFDE_CSSValue* pVal;
-  bool bImportant;
+
   int32_t i;
   if (bPriority) {
     CFDE_CSSValue* pLastest = nullptr;
     CFDE_CSSValue* pImportant = nullptr;
     for (i = 0; i < iDeclCount; ++i) {
-      pVal = ppDeclArray[i]->GetProperty(FDE_CSSProperty::FontSize, bImportant);
+      bool bImportant;
+      CFDE_CSSValue* pVal =
+          ppDeclArray[i]->GetProperty(FDE_CSSProperty::FontSize, bImportant);
       if (!pVal)
         continue;
 
@@ -304,39 +305,33 @@
   } else {
     CFX_ArrayTemplate<CFDE_CSSDeclaration*> importants;
     const CFDE_CSSDeclaration* pDecl = nullptr;
-    FDE_CSSProperty eProp;
-    FX_POSITION pos;
+
     for (i = 0; i < iDeclCount; ++i) {
       pDecl = ppDeclArray[i];
-      pos = pDecl->GetStartPosition();
-      while (pos) {
-        pDecl->GetNextProperty(pos, eProp, pVal, bImportant);
-        if (eProp == FDE_CSSProperty::FontSize) {
+      for (auto it = pDecl->begin(); it != pDecl->end(); it++) {
+        if ((*it)->eProperty == FDE_CSSProperty::FontSize)
           continue;
-        } else if (!bImportant) {
-          ApplyProperty(eProp, pVal, pComputedStyle);
+        if (!(*it)->bImportant) {
+          ApplyProperty((*it)->eProperty, (*it)->pValue.Get(), pComputedStyle);
         } else if (importants.GetSize() == 0 ||
                    importants[importants.GetUpperBound()] != pDecl) {
           importants.Add(const_cast<CFDE_CSSDeclaration*>(pDecl));
         }
       }
     }
+
     iDeclCount = importants.GetSize();
     for (i = 0; i < iDeclCount; ++i) {
       pDecl = importants[i];
-      pos = pDecl->GetStartPosition();
-      while (pos) {
-        pDecl->GetNextProperty(pos, eProp, pVal, bImportant);
-        if (bImportant && eProp != FDE_CSSProperty::FontSize) {
-          ApplyProperty(eProp, pVal, pComputedStyle);
-        }
+
+      for (auto it = pDecl->begin(); it != pDecl->end(); it++) {
+        if ((*it)->bImportant && (*it)->eProperty != FDE_CSSProperty::FontSize)
+          ApplyProperty((*it)->eProperty, (*it)->pValue.Get(), pComputedStyle);
       }
     }
-    CFX_WideString wsName, wsValue;
-    pos = pDecl->GetStartCustom();
-    while (pos) {
-      pDecl->GetNextCustom(pos, wsName, wsValue);
-      pComputedStyle->AddCustomStyle(wsName, wsValue);
+
+    for (auto it = pDecl->custom_begin(); it != pDecl->custom_end(); it++) {
+      pComputedStyle->AddCustomStyle((*it)->pwsName, (*it)->pwsValue);
     }
   }
 }
diff --git a/xfa/fde/css/fde_cssstylesheet.cpp b/xfa/fde/css/fde_cssstylesheet.cpp
index a5ac0c0..a3667b2 100644
--- a/xfa/fde/css/fde_cssstylesheet.cpp
+++ b/xfa/fde/css/fde_cssstylesheet.cpp
@@ -9,15 +9,50 @@
 #include <memory>
 
 #include "third_party/base/ptr_util.h"
+#include "third_party/base/stl_util.h"
 #include "xfa/fde/css/fde_cssdatatable.h"
 #include "xfa/fde/css/fde_csssyntax.h"
 #include "xfa/fgas/crt/fgas_codepage.h"
 
+namespace {
+
+bool IsCSSChar(FX_WCHAR wch) {
+  return (wch >= 'a' && wch <= 'z') || (wch >= 'A' && wch <= 'Z');
+}
+
+int32_t GetCSSPseudoLen(const FX_WCHAR* psz, const FX_WCHAR* pEnd) {
+  ASSERT(*psz == ':');
+  const FX_WCHAR* pStart = psz;
+  while (psz < pEnd) {
+    FX_WCHAR wch = *psz;
+    if (IsCSSChar(wch) || wch == ':')
+      ++psz;
+    else
+      break;
+  }
+  return psz - pStart;
+}
+
+int32_t GetCSSNameLen(const FX_WCHAR* psz, const FX_WCHAR* pEnd) {
+  const FX_WCHAR* pStart = psz;
+  while (psz < pEnd) {
+    FX_WCHAR wch = *psz;
+    if (IsCSSChar(wch) || (wch >= '0' && wch <= '9') || wch == '_' ||
+        wch == '-') {
+      ++psz;
+    } else {
+      break;
+    }
+  }
+  return psz - pStart;
+}
+
+}  // namespace
+
 CFDE_CSSStyleSheet::CFDE_CSSStyleSheet()
     : m_wCodePage(FX_CODEPAGE_UTF8),
       m_wRefCount(1),
-      m_dwMediaList(FDE_CSSMEDIATYPE_ALL),
-      m_RuleArray(100) {
+      m_dwMediaList(FDE_CSSMEDIATYPE_ALL) {
   ASSERT(m_dwMediaList > 0);
 }
 
@@ -26,25 +61,8 @@
 }
 
 void CFDE_CSSStyleSheet::Reset() {
-  for (int32_t i = m_RuleArray.GetSize() - 1; i >= 0; --i) {
-    CFDE_CSSRule* pRule = m_RuleArray.GetAt(i);
-    switch (pRule->GetType()) {
-      case FDE_CSSRuleType::Style:
-        static_cast<CFDE_CSSStyleRule*>(pRule)->~CFDE_CSSStyleRule();
-        break;
-      case FDE_CSSRuleType::Media:
-        static_cast<CFDE_CSSMediaRule*>(pRule)->~CFDE_CSSMediaRule();
-        break;
-      case FDE_CSSRuleType::FontFace:
-        static_cast<CFDE_CSSFontFaceRule*>(pRule)->~CFDE_CSSFontFaceRule();
-        break;
-      default:
-        ASSERT(false);
-        break;
-    }
-  }
-  m_RuleArray.RemoveAll(false);
-  m_Selectors.RemoveAll();
+  m_RuleArray.clear();
+  m_Selectors.clear();
   m_StringCache.clear();
 }
 
@@ -73,11 +91,11 @@
 }
 
 int32_t CFDE_CSSStyleSheet::CountRules() const {
-  return m_RuleArray.GetSize();
+  return pdfium::CollectionSize<int32_t>(m_RuleArray);
 }
 
 CFDE_CSSRule* CFDE_CSSStyleSheet::GetRule(int32_t index) {
-  return m_RuleArray.GetAt(index);
+  return m_RuleArray[index].get();
 }
 
 bool CFDE_CSSStyleSheet::LoadFromBuffer(const FX_WCHAR* pBuffer,
@@ -97,13 +115,13 @@
   do {
     switch (eStatus = pSyntax->DoSyntaxParse()) {
       case FDE_CSSSyntaxStatus::StyleRule:
-        eStatus = LoadStyleRule(pSyntax, m_RuleArray);
+        eStatus = LoadStyleRule(pSyntax, &m_RuleArray);
         break;
       case FDE_CSSSyntaxStatus::MediaRule:
         eStatus = LoadMediaRule(pSyntax);
         break;
       case FDE_CSSSyntaxStatus::FontFaceRule:
-        eStatus = LoadFontFaceRule(pSyntax, m_RuleArray);
+        eStatus = LoadFontFaceRule(pSyntax, &m_RuleArray);
         break;
       case FDE_CSSSyntaxStatus::ImportRule:
         eStatus = LoadImportRule(pSyntax);
@@ -115,7 +133,7 @@
         break;
     }
   } while (eStatus >= FDE_CSSSyntaxStatus::None);
-  m_Selectors.RemoveAll();
+  m_Selectors.clear();
   m_StringCache.clear();
   return eStatus != FDE_CSSSyntaxStatus::Error;
 }
@@ -137,7 +155,7 @@
       case FDE_CSSSyntaxStatus::StyleRule:
         if (pMediaRule) {
           FDE_CSSSyntaxStatus eStatus =
-              LoadStyleRule(pSyntax, pMediaRule->GetArray());
+              LoadStyleRule(pSyntax, &pMediaRule->GetArray());
           if (eStatus < FDE_CSSSyntaxStatus::None) {
             return eStatus;
           }
@@ -147,8 +165,10 @@
         break;
       case FDE_CSSSyntaxStatus::DeclOpen:
         if ((dwMediaList & m_dwMediaList) > 0 && !pMediaRule) {
-          pMediaRule = new CFDE_CSSMediaRule(dwMediaList);
-          m_RuleArray.Add(pMediaRule);
+          m_RuleArray.push_back(
+              pdfium::MakeUnique<CFDE_CSSMediaRule>(dwMediaList));
+          pMediaRule =
+              static_cast<CFDE_CSSMediaRule*>(m_RuleArray.back().get());
         }
         break;
       case FDE_CSSSyntaxStatus::DeclClose:
@@ -164,8 +184,9 @@
 
 FDE_CSSSyntaxStatus CFDE_CSSStyleSheet::LoadStyleRule(
     CFDE_CSSSyntaxParser* pSyntax,
-    CFX_MassArrayTemplate<CFDE_CSSRule*>& ruleArray) {
-  m_Selectors.RemoveAt(0, m_Selectors.GetSize());
+    std::vector<std::unique_ptr<CFDE_CSSRule>>* ruleArray) {
+  m_Selectors.clear();
+
   CFDE_CSSStyleRule* pStyleRule = nullptr;
   const FX_WCHAR* pszValue = nullptr;
   int32_t iValueLen = 0;
@@ -177,10 +198,9 @@
     switch (pSyntax->DoSyntaxParse()) {
       case FDE_CSSSyntaxStatus::Selector: {
         pszValue = pSyntax->GetCurrentString(iValueLen);
-        CFDE_CSSSelector* pSelector =
-            CFDE_CSSSelector::FromString(pszValue, iValueLen);
+        auto pSelector = CFDE_CSSSelector::FromString(pszValue, iValueLen);
         if (pSelector)
-          m_Selectors.Add(pSelector);
+          m_Selectors.push_back(std::move(pSelector));
       } break;
       case FDE_CSSSyntaxStatus::PropertyName:
         pszValue = pSyntax->GetCurrentString(iValueLen);
@@ -206,19 +226,20 @@
         }
         break;
       case FDE_CSSSyntaxStatus::DeclOpen:
-        if (!pStyleRule && m_Selectors.GetSize() > 0) {
-          pStyleRule = new CFDE_CSSStyleRule;
+        if (!pStyleRule && !m_Selectors.empty()) {
+          auto rule = pdfium::MakeUnique<CFDE_CSSStyleRule>();
+          pStyleRule = rule.get();
           pStyleRule->SetSelector(m_Selectors);
-          ruleArray.Add(pStyleRule);
+          ruleArray->push_back(std::move(rule));
         } else {
           SkipRuleSet(pSyntax);
           return FDE_CSSSyntaxStatus::None;
         }
         break;
       case FDE_CSSSyntaxStatus::DeclClose:
-        if (pStyleRule && !pStyleRule->GetDeclImp().GetStartPosition()) {
-          pStyleRule->~CFDE_CSSStyleRule();
-          ruleArray.RemoveLast(1);
+        if (pStyleRule && pStyleRule->GetDeclImp().empty()) {
+          ruleArray->pop_back();
+          pStyleRule = nullptr;
         }
         return FDE_CSSSyntaxStatus::None;
       case FDE_CSSSyntaxStatus::EOS:
@@ -232,7 +253,7 @@
 
 FDE_CSSSyntaxStatus CFDE_CSSStyleSheet::LoadFontFaceRule(
     CFDE_CSSSyntaxParser* pSyntax,
-    CFX_MassArrayTemplate<CFDE_CSSRule*>& ruleArray) {
+    std::vector<std::unique_ptr<CFDE_CSSRule>>* ruleArray) {
   CFDE_CSSFontFaceRule* pFontFaceRule = nullptr;
   const FX_WCHAR* pszValue = nullptr;
   int32_t iValueLen = 0;
@@ -257,8 +278,9 @@
         break;
       case FDE_CSSSyntaxStatus::DeclOpen:
         if (!pFontFaceRule) {
-          pFontFaceRule = new CFDE_CSSFontFaceRule;
-          ruleArray.Add(pFontFaceRule);
+          auto rule = pdfium::MakeUnique<CFDE_CSSFontFaceRule>();
+          pFontFaceRule = rule.get();
+          ruleArray->push_back(std::move(rule));
         }
         break;
       case FDE_CSSSyntaxStatus::DeclClose:
@@ -316,9 +338,10 @@
 
 CFDE_CSSStyleRule::CFDE_CSSStyleRule()
     : CFDE_CSSRule(FDE_CSSRuleType::Style),
-      m_ppSelector(nullptr),
       m_iSelectors(0) {}
 
+CFDE_CSSStyleRule::~CFDE_CSSStyleRule() {}
+
 int32_t CFDE_CSSStyleRule::CountSelectorLists() const {
   return m_iSelectors;
 }
@@ -332,77 +355,28 @@
 }
 
 void CFDE_CSSStyleRule::SetSelector(
-    const CFX_ArrayTemplate<CFDE_CSSSelector*>& list) {
-  ASSERT(!m_ppSelector);
-  m_iSelectors = list.GetSize();
-  m_ppSelector = static_cast<CFDE_CSSSelector**>(
-      FX_Alloc(CFDE_CSSSelector*, m_iSelectors));
-  for (int32_t i = 0; i < m_iSelectors; ++i) {
-    m_ppSelector[i] = list.GetAt(i);
-  }
+    const std::vector<std::unique_ptr<CFDE_CSSSelector>>& list) {
+  ASSERT(m_ppSelector.empty());
+
+  for (const auto& item : list)
+    m_ppSelector.push_back(item.get());
 }
 
 CFDE_CSSMediaRule::CFDE_CSSMediaRule(uint32_t dwMediaList)
-    : CFDE_CSSRule(FDE_CSSRuleType::Media),
-      m_dwMediaList(dwMediaList),
-      m_RuleArray(100) {}
+    : CFDE_CSSRule(FDE_CSSRuleType::Media), m_dwMediaList(dwMediaList) {}
 
-CFDE_CSSMediaRule::~CFDE_CSSMediaRule() {
-  for (int32_t i = m_RuleArray.GetSize() - 1; i >= 0; --i) {
-    CFDE_CSSRule* pRule = m_RuleArray.GetAt(i);
-    switch (pRule->GetType()) {
-      case FDE_CSSRuleType::Style:
-        static_cast<CFDE_CSSStyleRule*>(pRule)->~CFDE_CSSStyleRule();
-        break;
-      default:
-        ASSERT(false);
-        break;
-    }
-  }
-}
+CFDE_CSSMediaRule::~CFDE_CSSMediaRule() {}
 
 uint32_t CFDE_CSSMediaRule::GetMediaList() const {
   return m_dwMediaList;
 }
 
 int32_t CFDE_CSSMediaRule::CountRules() const {
-  return m_RuleArray.GetSize();
+  return pdfium::CollectionSize<int32_t>(m_RuleArray);
 }
 
 CFDE_CSSRule* CFDE_CSSMediaRule::GetRule(int32_t index) {
-  return m_RuleArray.GetAt(index);
-}
-
-bool FDE_IsCSSChar(FX_WCHAR wch) {
-  return (wch >= 'a' && wch <= 'z') || (wch >= 'A' && wch <= 'Z');
-}
-
-int32_t FDE_GetCSSPseudoLen(const FX_WCHAR* psz, const FX_WCHAR* pEnd) {
-  ASSERT(*psz == ':');
-  const FX_WCHAR* pStart = psz;
-  while (psz < pEnd) {
-    FX_WCHAR wch = *psz;
-    if (FDE_IsCSSChar(wch) || wch == ':') {
-      ++psz;
-    } else {
-      break;
-    }
-  }
-  return psz - pStart;
-}
-
-int32_t FDE_GetCSSNameLen(const FX_WCHAR* psz, const FX_WCHAR* pEnd) {
-  const FX_WCHAR* pStart = psz;
-  while (psz < pEnd) {
-    FX_WCHAR wch = *psz;
-    if (FDE_IsCSSChar(wch) || (wch >= '0' && wch <= '9') || wch == '_' ||
-        wch == '-') {
-      ++psz;
-    } else {
-      break;
-    }
-  }
-  return psz - pStart;
+  return m_RuleArray[index].get();
 }
 
 CFDE_CSSSelector::CFDE_CSSSelector(FDE_CSSSelectorType eType,
@@ -410,8 +384,9 @@
                                    int32_t iLen,
                                    bool bIgnoreCase)
     : m_eType(eType),
-      m_dwHash(FX_HashCode_GetW(CFX_WideStringC(psz, iLen), bIgnoreCase)),
-      m_pNext(nullptr) {}
+      m_dwHash(FX_HashCode_GetW(CFX_WideStringC(psz, iLen), bIgnoreCase)) {}
+
+CFDE_CSSSelector::~CFDE_CSSSelector() {}
 
 FDE_CSSSelectorType CFDE_CSSSelector::GetType() const {
   return m_eType;
@@ -422,10 +397,14 @@
 }
 
 CFDE_CSSSelector* CFDE_CSSSelector::GetNextSelector() const {
-  return m_pNext;
+  return m_pNext.get();
 }
 
-CFDE_CSSSelector* CFDE_CSSSelector::FromString(
+std::unique_ptr<CFDE_CSSSelector> CFDE_CSSSelector::ReleaseNextSelector() {
+  return std::move(m_pNext);
+}
+
+std::unique_ptr<CFDE_CSSSelector> CFDE_CSSSelector::FromString(
     const FX_WCHAR* psz,
     int32_t iLen) {
   ASSERT(psz && iLen > 0);
@@ -440,72 +419,68 @@
         return nullptr;
     }
   }
-  CFDE_CSSSelector* pFirst = nullptr;
+
+  std::unique_ptr<CFDE_CSSSelector> pFirst = nullptr;
   CFDE_CSSSelector* pLast = nullptr;
-  CFDE_CSSSelector* pPseudoFirst = nullptr;
+  std::unique_ptr<CFDE_CSSSelector> pPseudoFirst = nullptr;
   CFDE_CSSSelector* pPseudoLast = nullptr;
+
   for (psz = pStart; psz < pEnd;) {
     FX_WCHAR wch = *psz;
     if (wch == '.' || wch == '#') {
       if (psz == pStart || psz[-1] == ' ') {
-        CFDE_CSSSelector* p =
-            new CFDE_CSSSelector(FDE_CSSSelectorType::Element, L"*", 1, true);
-        if (!p)
-          return nullptr;
+        auto p = pdfium::MakeUnique<CFDE_CSSSelector>(
+            FDE_CSSSelectorType::Element, L"*", 1, true);
 
         if (pFirst) {
           pFirst->SetType(FDE_CSSSelectorType::Descendant);
-          p->SetNext(pFirst);
+          p->SetNext(std::move(pFirst));
         }
-        pFirst = pLast = p;
+        pFirst = std::move(p);
+        pLast = pFirst.get();
       }
       ASSERT(pLast);
-      int32_t iNameLen = FDE_GetCSSNameLen(++psz, pEnd);
-      if (iNameLen == 0) {
+
+      int32_t iNameLen = GetCSSNameLen(++psz, pEnd);
+      if (iNameLen == 0)
         return nullptr;
-      }
+
       FDE_CSSSelectorType eType =
           wch == '.' ? FDE_CSSSelectorType::Class : FDE_CSSSelectorType::ID;
-      CFDE_CSSSelector* p = new CFDE_CSSSelector(eType, psz, iNameLen, false);
-      if (!p)
-        return nullptr;
+      auto p =
+          pdfium::MakeUnique<CFDE_CSSSelector>(eType, psz, iNameLen, false);
 
-      p->SetNext(pLast->GetNextSelector());
-      pLast->SetNext(p);
-      pLast = p;
+      p->SetNext(pLast->ReleaseNextSelector());
+      pLast->SetNext(std::move(p));
+      pLast = pLast->GetNextSelector();
       psz += iNameLen;
-    } else if (FDE_IsCSSChar(wch) || wch == '*') {
-      int32_t iNameLen = wch == '*' ? 1 : FDE_GetCSSNameLen(psz, pEnd);
-      if (iNameLen == 0) {
-        return nullptr;
-      }
-      CFDE_CSSSelector* p = new CFDE_CSSSelector(FDE_CSSSelectorType::Element,
-                                                 psz, iNameLen, true);
-      if (!p)
+    } else if (IsCSSChar(wch) || wch == '*') {
+      int32_t iNameLen = wch == '*' ? 1 : GetCSSNameLen(psz, pEnd);
+      if (iNameLen == 0)
         return nullptr;
 
+      auto p = pdfium::MakeUnique<CFDE_CSSSelector>(
+          FDE_CSSSelectorType::Element, psz, iNameLen, true);
       if (pFirst) {
         pFirst->SetType(FDE_CSSSelectorType::Descendant);
-        p->SetNext(pFirst);
+        p->SetNext(std::move(pFirst));
       }
-      pFirst = p;
-      pLast = p;
+      pFirst = std::move(p);
+      pLast = pFirst.get();
       psz += iNameLen;
     } else if (wch == ':') {
-      int32_t iNameLen = FDE_GetCSSPseudoLen(psz, pEnd);
-      if (iNameLen == 0) {
-        return nullptr;
-      }
-      CFDE_CSSSelector* p = new CFDE_CSSSelector(FDE_CSSSelectorType::Pseudo,
-                                                 psz, iNameLen, true);
-      if (!p)
+      int32_t iNameLen = GetCSSPseudoLen(psz, pEnd);
+      if (iNameLen == 0)
         return nullptr;
 
+      auto p = pdfium::MakeUnique<CFDE_CSSSelector>(FDE_CSSSelectorType::Pseudo,
+                                                    psz, iNameLen, true);
+      CFDE_CSSSelector* ptr = p.get();
       if (pPseudoFirst)
-        pPseudoLast->SetNext(p);
+        pPseudoLast->SetNext(std::move(p));
       else
-        pPseudoFirst = p;
-      pPseudoLast = p;
+        pPseudoFirst = std::move(p);
+      pPseudoLast = ptr;
       psz += iNameLen;
     } else if (wch == ' ') {
       psz++;
@@ -516,7 +491,7 @@
   if (!pPseudoFirst)
     return pFirst;
 
-  pPseudoLast->SetNext(pFirst);
+  pPseudoLast->SetNext(std::move(pFirst));
   return pPseudoFirst;
 }
 
diff --git a/xfa/fde/css/fde_cssstylesheet.h b/xfa/fde/css/fde_cssstylesheet.h
index 8cedb76..7acccd5 100644
--- a/xfa/fde/css/fde_cssstylesheet.h
+++ b/xfa/fde/css/fde_cssstylesheet.h
@@ -9,6 +9,8 @@
 
 #include <memory>
 #include <unordered_map>
+#include <utility>
+#include <vector>
 
 #include "core/fxcrt/fx_ext.h"
 #include "xfa/fde/css/cfde_cssrule.h"
@@ -18,40 +20,46 @@
 
 class CFDE_CSSSelector {
  public:
+  static std::unique_ptr<CFDE_CSSSelector> FromString(const FX_WCHAR* psz,
+                                                      int32_t iLen);
+
   CFDE_CSSSelector(FDE_CSSSelectorType eType,
                    const FX_WCHAR* psz,
                    int32_t iLen,
                    bool bIgnoreCase);
+  ~CFDE_CSSSelector();
 
-  virtual FDE_CSSSelectorType GetType() const;
-  virtual uint32_t GetNameHash() const;
-  virtual CFDE_CSSSelector* GetNextSelector() const;
+  FDE_CSSSelectorType GetType() const;
+  uint32_t GetNameHash() const;
+  CFDE_CSSSelector* GetNextSelector() const;
+  std::unique_ptr<CFDE_CSSSelector> ReleaseNextSelector();
 
-  static CFDE_CSSSelector* FromString(const FX_WCHAR* psz, int32_t iLen);
-
-  void SetNext(CFDE_CSSSelector* pNext) { m_pNext = pNext; }
+  void SetNext(std::unique_ptr<CFDE_CSSSelector> pNext) {
+    m_pNext = std::move(pNext);
+  }
 
  protected:
   void SetType(FDE_CSSSelectorType eType) { m_eType = eType; }
 
   FDE_CSSSelectorType m_eType;
   uint32_t m_dwHash;
-  CFDE_CSSSelector* m_pNext;
+  std::unique_ptr<CFDE_CSSSelector> m_pNext;
 };
 
 class CFDE_CSSStyleRule : public CFDE_CSSRule {
  public:
   CFDE_CSSStyleRule();
+  ~CFDE_CSSStyleRule() override;
 
   int32_t CountSelectorLists() const;
   CFDE_CSSSelector* GetSelectorList(int32_t index) const;
   CFDE_CSSDeclaration* GetDeclaration();
   CFDE_CSSDeclaration& GetDeclImp() { return m_Declaration; }
-  void SetSelector(const CFX_ArrayTemplate<CFDE_CSSSelector*>& list);
+  void SetSelector(const std::vector<std::unique_ptr<CFDE_CSSSelector>>& list);
 
  private:
   CFDE_CSSDeclaration m_Declaration;
-  CFDE_CSSSelector** m_ppSelector;
+  std::vector<CFDE_CSSSelector*> m_ppSelector;  // Owned by the stylessheet.
   int32_t m_iSelectors;
 };
 
@@ -64,11 +72,11 @@
   int32_t CountRules() const;
   CFDE_CSSRule* GetRule(int32_t index);
 
-  CFX_MassArrayTemplate<CFDE_CSSRule*>& GetArray() { return m_RuleArray; }
+  std::vector<std::unique_ptr<CFDE_CSSRule>>& GetArray() { return m_RuleArray; }
 
  protected:
   uint32_t m_dwMediaList;
-  CFX_MassArrayTemplate<CFDE_CSSRule*> m_RuleArray;
+  std::vector<std::unique_ptr<CFDE_CSSRule>> m_RuleArray;
 };
 
 class CFDE_CSSFontFaceRule : public CFDE_CSSRule {
@@ -104,21 +112,21 @@
   bool LoadFromSyntax(CFDE_CSSSyntaxParser* pSyntax);
   FDE_CSSSyntaxStatus LoadStyleRule(
       CFDE_CSSSyntaxParser* pSyntax,
-      CFX_MassArrayTemplate<CFDE_CSSRule*>& ruleArray);
+      std::vector<std::unique_ptr<CFDE_CSSRule>>* ruleArray);
   FDE_CSSSyntaxStatus LoadImportRule(CFDE_CSSSyntaxParser* pSyntax);
   FDE_CSSSyntaxStatus LoadPageRule(CFDE_CSSSyntaxParser* pSyntax);
   FDE_CSSSyntaxStatus LoadMediaRule(CFDE_CSSSyntaxParser* pSyntax);
   FDE_CSSSyntaxStatus LoadFontFaceRule(
       CFDE_CSSSyntaxParser* pSyntax,
-      CFX_MassArrayTemplate<CFDE_CSSRule*>& ruleArray);
+      std::vector<std::unique_ptr<CFDE_CSSRule>>* ruleArray);
   FDE_CSSSyntaxStatus SkipRuleSet(CFDE_CSSSyntaxParser* pSyntax);
 
   uint16_t m_wCodePage;
   uint16_t m_wRefCount;
   uint32_t m_dwMediaList;
-  CFX_MassArrayTemplate<CFDE_CSSRule*> m_RuleArray;
+  std::vector<std::unique_ptr<CFDE_CSSRule>> m_RuleArray;
   CFX_WideString m_szUrl;
-  CFX_ArrayTemplate<CFDE_CSSSelector*> m_Selectors;
+  std::vector<std::unique_ptr<CFDE_CSSSelector>> m_Selectors;
   std::unordered_map<uint32_t, FX_WCHAR*> m_StringCache;
 };