Make CPDF_Object and its subclasses retainable.

Allows us to solve subsequent lifetime issues by replacing cached raw
pointers to changeable objects with retain pointers, and eventually
remove code tasked with tracking orphan resources.

Change-Id: Ib248b93fa6e24e9368100fc138cf7a0ec3bef5d3
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/53750
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/edit/cpdf_creator.cpp b/core/fpdfapi/edit/cpdf_creator.cpp
index c815f8f..8233281 100644
--- a/core/fpdfapi/edit/cpdf_creator.cpp
+++ b/core/fpdfapi/edit/cpdf_creator.cpp
@@ -443,11 +443,11 @@
   }
 
   if (m_pParser) {
-    std::unique_ptr<CPDF_Dictionary> p = m_pParser->GetCombinedTrailer();
-    CPDF_DictionaryLocker locker(p.get());
+    RetainPtr<CPDF_Dictionary> p = m_pParser->GetCombinedTrailer();
+    CPDF_DictionaryLocker locker(p.Get());
     for (const auto& it : locker) {
       const ByteString& key = it.first;
-      CPDF_Object* pValue = it.second.get();
+      CPDF_Object* pValue = it.second.Get();
       if (key == "Encrypt" || key == "Size" || key == "Filter" ||
           key == "Index" || key == "Length" || key == "Prev" || key == "W" ||
           key == "XRefStm" || key == "ID" || key == "DecodeParms" ||
@@ -591,7 +591,7 @@
 void CPDF_Creator::InitID() {
   ASSERT(!m_pIDArray);
 
-  m_pIDArray = pdfium::MakeUnique<CPDF_Array>();
+  m_pIDArray = pdfium::MakeRetain<CPDF_Array>();
   const CPDF_Array* pOldIDArray = m_pParser ? m_pParser->GetIDArray() : nullptr;
   const CPDF_Object* pID1 = pOldIDArray ? pOldIDArray->GetObjectAt(0) : nullptr;
   if (pID1) {
@@ -619,9 +619,9 @@
     ASSERT(m_pParser);
     if (m_pEncryptDict->GetStringFor("Filter") == "Standard") {
       m_pNewEncryptDict = ToDictionary(m_pEncryptDict->Clone());
-      m_pEncryptDict = m_pNewEncryptDict.get();
+      m_pEncryptDict = m_pNewEncryptDict.Get();
       m_pSecurityHandler = pdfium::MakeRetain<CPDF_SecurityHandler>();
-      m_pSecurityHandler->OnCreate(m_pNewEncryptDict.get(), m_pIDArray.get(),
+      m_pSecurityHandler->OnCreate(m_pNewEncryptDict.Get(), m_pIDArray.Get(),
                                    m_pParser->GetPassword());
       m_bSecurityChanged = true;
     }
@@ -666,7 +666,7 @@
   m_pSecurityHandler.Reset();
   m_bSecurityChanged = true;
   m_pEncryptDict = nullptr;
-  m_pNewEncryptDict.reset();
+  m_pNewEncryptDict.Reset();
 }
 
 CPDF_CryptoHandler* CPDF_Creator::GetCryptoHandler() {
diff --git a/core/fpdfapi/edit/cpdf_creator.h b/core/fpdfapi/edit/cpdf_creator.h
index 64b2e4d..9399dba 100644
--- a/core/fpdfapi/edit/cpdf_creator.h
+++ b/core/fpdfapi/edit/cpdf_creator.h
@@ -75,7 +75,7 @@
   UnownedPtr<CPDF_Document> const m_pDocument;
   UnownedPtr<const CPDF_Parser> const m_pParser;
   UnownedPtr<const CPDF_Dictionary> m_pEncryptDict;
-  std::unique_ptr<CPDF_Dictionary> m_pNewEncryptDict;
+  RetainPtr<CPDF_Dictionary> m_pNewEncryptDict;
   RetainPtr<CPDF_SecurityHandler> m_pSecurityHandler;
   UnownedPtr<const CPDF_Object> m_pMetadata;
   uint32_t m_dwLastObjNum;
@@ -86,7 +86,7 @@
   FX_FILESIZE m_XrefStart = 0;
   std::map<uint32_t, FX_FILESIZE> m_ObjectOffsets;
   std::vector<uint32_t> m_NewObjNumArray;  // Sorted, ascending.
-  std::unique_ptr<CPDF_Array> m_pIDArray;
+  RetainPtr<CPDF_Array> m_pIDArray;
   int32_t m_FileVersion = 0;
   bool m_bSecurityChanged = false;
   bool m_IsIncremental = false;
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
index d2c8bf2..a678f39 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
@@ -460,7 +460,7 @@
   if (it != m_pObjHolder->m_GraphicsMap.end()) {
     name = it->second;
   } else {
-    auto gsDict = pdfium::MakeUnique<CPDF_Dictionary>();
+    auto gsDict = pdfium::MakeRetain<CPDF_Dictionary>();
     if (graphD.fillAlpha != 1.0f)
       gsDict->SetNewFor<CPDF_Number>("ca", graphD.fillAlpha);
 
@@ -499,7 +499,7 @@
     return it->second;
 
   // Otherwise, create them.
-  auto gsDict = pdfium::MakeUnique<CPDF_Dictionary>();
+  auto gsDict = pdfium::MakeRetain<CPDF_Dictionary>();
   gsDict->SetNewFor<CPDF_Number>("ca", defaultGraphics.fillAlpha);
   gsDict->SetNewFor<CPDF_Number>("CA", defaultGraphics.strokeAlpha);
   gsDict->SetNewFor<CPDF_Name>("BM", "Normal");
@@ -543,7 +543,7 @@
     CPDF_Object* pIndirectFont = pFont->GetFontDict();
     if (pIndirectFont->IsInline()) {
       // In this case we assume it must be a standard font
-      auto pFontDict = pdfium::MakeUnique<CPDF_Dictionary>();
+      auto pFontDict = pdfium::MakeRetain<CPDF_Dictionary>();
       pFontDict->SetNewFor<CPDF_Name>("Type", "Font");
       pFontDict->SetNewFor<CPDF_Name>("Subtype", data.type);
       pFontDict->SetNewFor<CPDF_Name>("BaseFont", data.baseFont);
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp
index ff61c01..20e4374 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp
@@ -55,9 +55,9 @@
   pPathObj->set_filltype(FXFILL_ALTERNATE);
   pPathObj->path().AppendRect(10, 5, 13, 30);
 
-  CPDF_Dictionary dummy_page_dict;
+  auto dummy_page_dict = pdfium::MakeRetain<CPDF_Dictionary>();
   auto pTestPage =
-      pdfium::MakeRetain<CPDF_Page>(nullptr, &dummy_page_dict, false);
+      pdfium::MakeRetain<CPDF_Page>(nullptr, dummy_page_dict.Get(), false);
   CPDF_PageContentGenerator generator(pTestPage.Get());
   std::ostringstream buf;
   TestProcessPath(&generator, &buf, pPathObj.get());
@@ -92,9 +92,9 @@
     pPathObj->Transform(CFX_Matrix(1, 0, 0, 1, 0.000000000000000000001,
                                    200000000000000.000002));
 
-    CPDF_Dictionary dummy_page_dict;
+    auto dummy_page_dict = pdfium::MakeRetain<CPDF_Dictionary>();
     auto pTestPage =
-        pdfium::MakeRetain<CPDF_Page>(nullptr, &dummy_page_dict, false);
+        pdfium::MakeRetain<CPDF_Page>(nullptr, dummy_page_dict.Get(), false);
     CPDF_PageContentGenerator generator(pTestPage.Get());
     std::ostringstream buf;
     TestProcessPath(&generator, &buf, pPathObj.get());
@@ -126,9 +126,9 @@
     pPathObj->path().AppendPoint(
         CFX_PointF(53.4f, 5000000000000000000.00000000000000004),
         FXPT_TYPE::BezierTo, true);
-    CPDF_Dictionary dummy_page_dict;
+    auto dummy_page_dict = pdfium::MakeRetain<CPDF_Dictionary>();
     auto pTestPage =
-        pdfium::MakeRetain<CPDF_Page>(nullptr, &dummy_page_dict, false);
+        pdfium::MakeRetain<CPDF_Page>(nullptr, dummy_page_dict.Get(), false);
     CPDF_PageContentGenerator generator(pTestPage.Get());
     std::ostringstream buf;
 
@@ -165,9 +165,9 @@
   pPathObj->path().AppendPoint(CFX_PointF(12, 13.64f), FXPT_TYPE::BezierTo,
                                true);
 
-  CPDF_Dictionary dummy_page_dict;
+  auto dummy_page_dict = pdfium::MakeRetain<CPDF_Dictionary>();
   auto pTestPage =
-      pdfium::MakeRetain<CPDF_Page>(nullptr, &dummy_page_dict, false);
+      pdfium::MakeRetain<CPDF_Page>(nullptr, dummy_page_dict.Get(), false);
   CPDF_PageContentGenerator generator(pTestPage.Get());
   std::ostringstream buf;
   TestProcessPath(&generator, &buf, pPathObj.get());
@@ -361,12 +361,12 @@
 TEST_F(CPDF_PageContentGeneratorTest, ProcessEmptyForm) {
   auto pDoc = pdfium::MakeUnique<CPDF_Document>();
   pDoc->CreateNewDoc();
-  auto pDict = pdfium::MakeUnique<CPDF_Dictionary>();
-  auto pStream = pdfium::MakeUnique<CPDF_Stream>(nullptr, 0, std::move(pDict));
+  auto pDict = pdfium::MakeRetain<CPDF_Dictionary>();
+  auto pStream = pdfium::MakeRetain<CPDF_Stream>(nullptr, 0, std::move(pDict));
 
   // Create an empty form.
   auto pTestForm =
-      pdfium::MakeUnique<CPDF_Form>(pDoc.get(), nullptr, pStream.get());
+      pdfium::MakeUnique<CPDF_Form>(pDoc.get(), nullptr, pStream.Get());
   pTestForm->ParseContent(nullptr, nullptr, nullptr, nullptr);
   ASSERT_EQ(CPDF_PageObjectHolder::ParseState::kParsed,
             pTestForm->GetParseState());
@@ -381,19 +381,19 @@
 TEST_F(CPDF_PageContentGeneratorTest, ProcessFormWithPath) {
   auto pDoc = pdfium::MakeUnique<CPDF_Document>();
   pDoc->CreateNewDoc();
-  auto pDict = pdfium::MakeUnique<CPDF_Dictionary>();
+  auto pDict = pdfium::MakeRetain<CPDF_Dictionary>();
   const char content[] =
       "q 1 0 0 1 0 0 cm 3.102 4.6700001 m 5.4500012 .28999999 "
       "l 4.2399998 3.1499999 4.65 2.98 3.456 0.24 c 3.102 4.6700001 l h f Q\n";
   size_t buf_len = FX_ArraySize(content);
   std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_Alloc(uint8_t, buf_len));
   memcpy(buf.get(), content, buf_len);
-  auto pStream = pdfium::MakeUnique<CPDF_Stream>(std::move(buf), buf_len,
+  auto pStream = pdfium::MakeRetain<CPDF_Stream>(std::move(buf), buf_len,
                                                  std::move(pDict));
 
   // Create a form with a non-empty stream.
   auto pTestForm =
-      pdfium::MakeUnique<CPDF_Form>(pDoc.get(), nullptr, pStream.get());
+      pdfium::MakeUnique<CPDF_Form>(pDoc.get(), nullptr, pStream.Get());
   pTestForm->ParseContent(nullptr, nullptr, nullptr, nullptr);
   ASSERT_EQ(CPDF_PageObjectHolder::ParseState::kParsed,
             pTestForm->GetParseState());
diff --git a/core/fpdfapi/font/cfx_stockfontarray.cpp b/core/fpdfapi/font/cfx_stockfontarray.cpp
index 60a4c4d..7dd9646 100644
--- a/core/fpdfapi/font/cfx_stockfontarray.cpp
+++ b/core/fpdfapi/font/cfx_stockfontarray.cpp
@@ -18,7 +18,7 @@
 CFX_StockFontArray::~CFX_StockFontArray() {
   for (size_t i = 0; i < FX_ArraySize(m_StockFonts); ++i) {
     if (m_StockFonts[i]) {
-      std::unique_ptr<CPDF_Dictionary> destroy(m_StockFonts[i]->GetFontDict());
+      RetainPtr<CPDF_Dictionary> destroy(m_StockFonts[i]->GetFontDict());
       m_StockFonts[i]->ClearFontDict();
     }
   }
diff --git a/core/fpdfapi/font/cpdf_cidfont_unittest.cpp b/core/fpdfapi/font/cpdf_cidfont_unittest.cpp
index 2e40357..4166a93 100644
--- a/core/fpdfapi/font/cpdf_cidfont_unittest.cpp
+++ b/core/fpdfapi/font/cpdf_cidfont_unittest.cpp
@@ -22,20 +22,20 @@
 
 TEST_F(CPDF_CIDFontTest, BUG_920636) {
   CPDF_Document doc;
-  CPDF_Dictionary font_dict;
-  font_dict.SetNewFor<CPDF_Name>("Encoding", "Identity−H");
+  auto font_dict = pdfium::MakeRetain<CPDF_Dictionary>();
+  font_dict->SetNewFor<CPDF_Name>("Encoding", "Identity−H");
 
   {
-    auto descendant_fonts = pdfium::MakeUnique<CPDF_Array>();
+    auto descendant_fonts = pdfium::MakeRetain<CPDF_Array>();
     {
-      auto descendant_font = pdfium::MakeUnique<CPDF_Dictionary>();
+      auto descendant_font = pdfium::MakeRetain<CPDF_Dictionary>();
       descendant_font->SetNewFor<CPDF_Name>("BaseFont", "CourierStd");
       descendant_fonts->Add(std::move(descendant_font));
     }
-    font_dict.SetFor("DescendantFonts", std::move(descendant_fonts));
+    font_dict->SetFor("DescendantFonts", std::move(descendant_fonts));
   }
 
-  CPDF_CIDFont font(&doc, &font_dict);
+  CPDF_CIDFont font(&doc, font_dict.Get());
   ASSERT_TRUE(font.Load());
 
   // It would be nice if we can test more values here. However, the glyph
diff --git a/core/fpdfapi/font/cpdf_font.cpp b/core/fpdfapi/font/cpdf_font.cpp
index fb1fd89..81e195b 100644
--- a/core/fpdfapi/font/cpdf_font.cpp
+++ b/core/fpdfapi/font/cpdf_font.cpp
@@ -297,12 +297,13 @@
   if (pFont)
     return pFont;
 
-  CPDF_Dictionary* pDict = pDoc->New<CPDF_Dictionary>().release();
+  auto pDict = pDoc->New<CPDF_Dictionary>();
   pDict->SetNewFor<CPDF_Name>("Type", "Font");
   pDict->SetNewFor<CPDF_Name>("Subtype", "Type1");
   pDict->SetNewFor<CPDF_Name>("BaseFont", fontname);
   pDict->SetNewFor<CPDF_Name>("Encoding", "WinAnsiEncoding");
-  return pFontGlobals->Set(pDoc, font_id, CPDF_Font::Create(nullptr, pDict));
+  return pFontGlobals->Set(pDoc, font_id,
+                           CPDF_Font::Create(nullptr, pDict.Get()));
 }
 
 // static
diff --git a/core/fpdfapi/font/cpdf_font.h b/core/fpdfapi/font/cpdf_font.h
index ff5ec30..74271bd 100644
--- a/core/fpdfapi/font/cpdf_font.h
+++ b/core/fpdfapi/font/cpdf_font.h
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "build/build_config.h"
+#include "core/fpdfapi/parser/cpdf_dictionary.h"
 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
 #include "core/fxcrt/fx_string.h"
 #include "core/fxcrt/fx_system.h"
@@ -19,7 +20,6 @@
 
 class CFX_SubstFont;
 class CPDF_CIDFont;
-class CPDF_Dictionary;
 class CPDF_Document;
 class CPDF_Object;
 class CPDF_TrueTypeFont;
@@ -106,7 +106,7 @@
   CFX_Font m_Font;
   std::vector<std::unique_ptr<CFX_Font>> m_FontFallbacks;
   RetainPtr<CPDF_StreamAcc> m_pFontFile;
-  UnownedPtr<CPDF_Dictionary> m_pFontDict;
+  RetainPtr<CPDF_Dictionary> m_pFontDict;
   ByteString m_BaseFont;
   mutable std::unique_ptr<CPDF_ToUnicodeMap> m_pToUnicodeMap;
   mutable bool m_bToUnicodeLoaded = false;
diff --git a/core/fpdfapi/font/cpdf_fontencoding.cpp b/core/fpdfapi/font/cpdf_fontencoding.cpp
index adc1225..bab36cb 100644
--- a/core/fpdfapi/font/cpdf_fontencoding.cpp
+++ b/core/fpdfapi/font/cpdf_fontencoding.cpp
@@ -1680,7 +1680,7 @@
   return memcmp(m_Unicodes, pAnother->m_Unicodes, sizeof(m_Unicodes)) == 0;
 }
 
-std::unique_ptr<CPDF_Object> CPDF_FontEncoding::Realize(
+RetainPtr<CPDF_Object> CPDF_FontEncoding::Realize(
     WeakPtr<ByteStringPool> pPool) const {
   int predefined = 0;
   for (int cs = PDFFONT_ENCODING_WINANSI; cs < PDFFONT_ENCODING_ZAPFDINGBATS;
@@ -1709,11 +1709,11 @@
     else
       return nullptr;
 
-    return pdfium::MakeUnique<CPDF_Name>(pPool, pName);
+    return pdfium::MakeRetain<CPDF_Name>(pPool, pName);
   }
   const uint16_t* pStandard =
       PDF_UnicodesForPredefinedCharSet(PDFFONT_ENCODING_WINANSI);
-  auto pDiff = pdfium::MakeUnique<CPDF_Array>();
+  auto pDiff = pdfium::MakeRetain<CPDF_Array>();
   for (size_t i = 0; i < FX_ArraySize(m_Unicodes); i++) {
     if (pStandard[i] == m_Unicodes[i])
       continue;
@@ -1722,7 +1722,7 @@
     pDiff->AddNew<CPDF_Name>(PDF_AdobeNameFromUnicode(m_Unicodes[i]));
   }
 
-  auto pDict = pdfium::MakeUnique<CPDF_Dictionary>(pPool);
+  auto pDict = pdfium::MakeRetain<CPDF_Dictionary>(pPool);
   pDict->SetNewFor<CPDF_Name>("BaseEncoding", "WinAnsiEncoding");
   pDict->SetFor("Differences", std::move(pDiff));
   return std::move(pDict);
diff --git a/core/fpdfapi/font/cpdf_fontencoding.h b/core/fpdfapi/font/cpdf_fontencoding.h
index 1bbd415..ca98851 100644
--- a/core/fpdfapi/font/cpdf_fontencoding.h
+++ b/core/fpdfapi/font/cpdf_fontencoding.h
@@ -52,7 +52,7 @@
     m_Unicodes[charcode] = unicode;
   }
 
-  std::unique_ptr<CPDF_Object> Realize(WeakPtr<ByteStringPool> pPool) const;
+  RetainPtr<CPDF_Object> Realize(WeakPtr<ByteStringPool> pPool) const;
 
  private:
   wchar_t m_Unicodes[kEncodingTableSize];
diff --git a/core/fpdfapi/page/cpdf_allstates.cpp b/core/fpdfapi/page/cpdf_allstates.cpp
index 81df192..f0c7359 100644
--- a/core/fpdfapi/page/cpdf_allstates.cpp
+++ b/core/fpdfapi/page/cpdf_allstates.cpp
@@ -42,7 +42,7 @@
   CPDF_DictionaryLocker locker(pGS);
   for (const auto& it : locker) {
     const ByteString& key_str = it.first;
-    CPDF_Object* pElement = it.second.get();
+    CPDF_Object* pElement = it.second.Get();
     CPDF_Object* pObject = pElement ? pElement->GetDirect() : nullptr;
     if (!pObject)
       continue;
diff --git a/core/fpdfapi/page/cpdf_colorspace.cpp b/core/fpdfapi/page/cpdf_colorspace.cpp
index bcfd42d..dd33f93 100644
--- a/core/fpdfapi/page/cpdf_colorspace.cpp
+++ b/core/fpdfapi/page/cpdf_colorspace.cpp
@@ -464,7 +464,7 @@
     CPDF_DictionaryLocker locker(pDict);
     for (const auto& it : locker) {
       std::unique_ptr<CPDF_ColorSpace> pRet;
-      CPDF_Object* pValue = it.second.get();
+      CPDF_Object* pValue = it.second.Get();
       if (ToName(pValue))
         pRet.reset(ColorspaceFromName(pValue->GetString()));
       if (pRet)
diff --git a/core/fpdfapi/page/cpdf_contentmarkitem.cpp b/core/fpdfapi/page/cpdf_contentmarkitem.cpp
index d831fc2..89191f7 100644
--- a/core/fpdfapi/page/cpdf_contentmarkitem.cpp
+++ b/core/fpdfapi/page/cpdf_contentmarkitem.cpp
@@ -20,7 +20,7 @@
     case kPropertiesDict:
       return m_pPropertiesHolder->GetDictFor(m_PropertyName);
     case kDirectDict:
-      return m_pDirectDict.get();
+      return m_pDirectDict.Get();
     case kNone:
     default:
       return nullptr;
@@ -37,8 +37,7 @@
   return pDict && pDict->KeyExist("MCID");
 }
 
-void CPDF_ContentMarkItem::SetDirectDict(
-    std::unique_ptr<CPDF_Dictionary> pDict) {
+void CPDF_ContentMarkItem::SetDirectDict(RetainPtr<CPDF_Dictionary> pDict) {
   m_ParamType = kDirectDict;
   m_pDirectDict = std::move(pDict);
 }
diff --git a/core/fpdfapi/page/cpdf_contentmarkitem.h b/core/fpdfapi/page/cpdf_contentmarkitem.h
index c7012a4..9a8ea46 100644
--- a/core/fpdfapi/page/cpdf_contentmarkitem.h
+++ b/core/fpdfapi/page/cpdf_contentmarkitem.h
@@ -30,7 +30,7 @@
   const ByteString& GetPropertyName() const { return m_PropertyName; }
   bool HasMCID() const;
 
-  void SetDirectDict(std::unique_ptr<CPDF_Dictionary> pDict);
+  void SetDirectDict(RetainPtr<CPDF_Dictionary> pDict);
   void SetPropertiesHolder(CPDF_Dictionary* pHolder,
                            const ByteString& property_name);
 
@@ -39,7 +39,7 @@
   ByteString m_MarkName;
   ByteString m_PropertyName;
   UnownedPtr<CPDF_Dictionary> m_pPropertiesHolder;
-  std::unique_ptr<CPDF_Dictionary> m_pDirectDict;
+  RetainPtr<CPDF_Dictionary> m_pDirectDict;
 };
 
 #endif  // CORE_FPDFAPI_PAGE_CPDF_CONTENTMARKITEM_H_
diff --git a/core/fpdfapi/page/cpdf_image.cpp b/core/fpdfapi/page/cpdf_image.cpp
index 17142ef..63ec6ce 100644
--- a/core/fpdfapi/page/cpdf_image.cpp
+++ b/core/fpdfapi/page/cpdf_image.cpp
@@ -46,11 +46,9 @@
   ASSERT(m_pDocument);
 }
 
-CPDF_Image::CPDF_Image(CPDF_Document* pDoc,
-                       std::unique_ptr<CPDF_Stream> pStream)
+CPDF_Image::CPDF_Image(CPDF_Document* pDoc, RetainPtr<CPDF_Stream> pStream)
     : m_bIsInline(true), m_pDocument(pDoc), m_pStream(std::move(pStream)) {
   ASSERT(m_pDocument);
-  ASSERT(m_pStream.IsOwned());
   FinishInitialization(m_pStream->GetDict());
 }
 
@@ -58,7 +56,6 @@
     : m_pDocument(pDoc),
       m_pStream(ToStream(pDoc->GetIndirectObject(dwStreamObjNum))) {
   ASSERT(m_pDocument);
-  ASSERT(!m_pStream.IsOwned());
   FinishInitialization(m_pStream->GetDict());
 }
 
@@ -77,15 +74,14 @@
   if (!m_pStream->IsInline())
     return;
 
-  ASSERT(m_pStream.IsOwned());
-  m_pDocument->AddIndirectObject(m_pStream.Release());
+  m_pDocument->AddIndirectObject(m_pStream);
 }
 
 CPDF_Dictionary* CPDF_Image::GetDict() const {
   return m_pStream ? m_pStream->GetDict() : nullptr;
 }
 
-std::unique_ptr<CPDF_Dictionary> CPDF_Image::InitJPEG(
+RetainPtr<CPDF_Dictionary> CPDF_Image::InitJPEG(
     pdfium::span<uint8_t> src_span) {
   int32_t width;
   int32_t height;
@@ -129,7 +125,7 @@
   m_Width = width;
   m_Height = height;
   if (!m_pStream)
-    m_pStream = pdfium::MakeUnique<CPDF_Stream>();
+    m_pStream = pdfium::MakeRetain<CPDF_Stream>();
   return pDict;
 }
 
@@ -143,7 +139,7 @@
   if (!pFile->ReadBlockAtOffset(data.data(), 0, dwEstimateSize))
     return;
 
-  std::unique_ptr<CPDF_Dictionary> pDict = InitJPEG(data);
+  RetainPtr<CPDF_Dictionary> pDict = InitJPEG(data);
   if (!pDict && size > dwEstimateSize) {
     data.resize(size);
     pFile->ReadBlockAtOffset(data.data(), 0, size);
@@ -165,7 +161,7 @@
   if (!pFile->ReadBlockAtOffset(data.data(), 0, size))
     return;
 
-  std::unique_ptr<CPDF_Dictionary> pDict = InitJPEG(data);
+  RetainPtr<CPDF_Dictionary> pDict = InitJPEG(data);
   if (!pDict)
     return;
 
@@ -329,7 +325,7 @@
     }
   }
   if (!m_pStream)
-    m_pStream = pdfium::MakeUnique<CPDF_Stream>();
+    m_pStream = pdfium::MakeRetain<CPDF_Stream>();
 
   m_pStream->InitStream(dest_span, std::move(pDict));
   m_bIsMask = pBitmap->IsAlphaMask();
diff --git a/core/fpdfapi/page/cpdf_image.h b/core/fpdfapi/page/cpdf_image.h
index b2d3946..44f3f84 100644
--- a/core/fpdfapi/page/cpdf_image.h
+++ b/core/fpdfapi/page/cpdf_image.h
@@ -10,7 +10,6 @@
 #include <memory>
 
 #include "core/fxcrt/fx_system.h"
-#include "core/fxcrt/maybe_owned.h"
 #include "core/fxcrt/retain_ptr.h"
 #include "core/fxcrt/unowned_ptr.h"
 #include "third_party/base/span.h"
@@ -73,12 +72,12 @@
 
  private:
   explicit CPDF_Image(CPDF_Document* pDoc);
-  CPDF_Image(CPDF_Document* pDoc, std::unique_ptr<CPDF_Stream> pStream);
+  CPDF_Image(CPDF_Document* pDoc, RetainPtr<CPDF_Stream> pStream);
   CPDF_Image(CPDF_Document* pDoc, uint32_t dwStreamObjNum);
   ~CPDF_Image() override;
 
   void FinishInitialization(CPDF_Dictionary* pStreamDict);
-  std::unique_ptr<CPDF_Dictionary> InitJPEG(pdfium::span<uint8_t> src_span);
+  RetainPtr<CPDF_Dictionary> InitJPEG(pdfium::span<uint8_t> src_span);
 
   int32_t m_Height = 0;
   int32_t m_Width = 0;
@@ -86,7 +85,7 @@
   bool m_bIsMask = false;
   bool m_bInterpolate = false;
   UnownedPtr<CPDF_Document> const m_pDocument;
-  MaybeOwned<CPDF_Stream> m_pStream;
+  RetainPtr<CPDF_Stream> m_pStream;
   UnownedPtr<const CPDF_Dictionary> m_pOC;
 };
 
diff --git a/core/fpdfapi/page/cpdf_streamcontentparser.cpp b/core/fpdfapi/page/cpdf_streamcontentparser.cpp
index adc7c49..3da7f5f 100644
--- a/core/fpdfapi/page/cpdf_streamcontentparser.cpp
+++ b/core/fpdfapi/page/cpdf_streamcontentparser.cpp
@@ -179,7 +179,7 @@
     CPDF_DictionaryLocker locker(pDict);
     for (const auto& it : locker) {
       ByteString key = it.first;
-      CPDF_Object* value = it.second.get();
+      CPDF_Object* value = it.second.Get();
       ByteStringView fullname = FindFullName(
           kInlineKeyAbbr, FX_ArraySize(kInlineKeyAbbr), key.AsStringView());
       if (!fullname.IsEmpty()) {
@@ -305,7 +305,7 @@
       m_ParamStartPos = 0;
     }
     if (m_ParamBuf[m_ParamStartPos].m_Type == ContentParam::OBJECT)
-      m_ParamBuf[m_ParamStartPos].m_pObject.reset();
+      m_ParamBuf[m_ParamStartPos].m_pObject.Reset();
 
     return m_ParamStartPos;
   }
@@ -330,8 +330,7 @@
   param.m_Number = FX_Number(str);
 }
 
-void CPDF_StreamContentParser::AddObjectParam(
-    std::unique_ptr<CPDF_Object> pObj) {
+void CPDF_StreamContentParser::AddObjectParam(RetainPtr<CPDF_Object> pObj) {
   ContentParam& param = m_ParamBuf[GetNextParamPos()];
   param.m_Type = ContentParam::OBJECT;
   param.m_pObject = std::move(pObj);
@@ -341,7 +340,7 @@
   uint32_t index = m_ParamStartPos;
   for (uint32_t i = 0; i < m_ParamCount; i++) {
     if (m_ParamBuf[index].m_Type == ContentParam::OBJECT)
-      m_ParamBuf[index].m_pObject.reset();
+      m_ParamBuf[index].m_pObject.Reset();
     index++;
     if (index == kParamBufSize)
       index = 0;
@@ -363,17 +362,17 @@
     param.m_Type = ContentParam::OBJECT;
     param.m_pObject =
         param.m_Number.IsInteger()
-            ? pdfium::MakeUnique<CPDF_Number>(param.m_Number.GetSigned())
-            : pdfium::MakeUnique<CPDF_Number>(param.m_Number.GetFloat());
-    return param.m_pObject.get();
+            ? pdfium::MakeRetain<CPDF_Number>(param.m_Number.GetSigned())
+            : pdfium::MakeRetain<CPDF_Number>(param.m_Number.GetFloat());
+    return param.m_pObject.Get();
   }
   if (param.m_Type == ContentParam::NAME) {
     param.m_Type = ContentParam::OBJECT;
     param.m_pObject = m_pDocument->New<CPDF_Name>(param.m_Name);
-    return param.m_pObject.get();
+    return param.m_pObject.Get();
   }
   if (param.m_Type == ContentParam::OBJECT)
-    return param.m_pObject.get();
+    return param.m_pObject.Get();
 
   NOTREACHED();
   return nullptr;
@@ -634,7 +633,7 @@
         pDict->SetFor(key, std::move(pObj));
     }
   }
-  ReplaceAbbr(pDict.get());
+  ReplaceAbbr(pDict.Get());
   CPDF_Object* pCSObj = nullptr;
   if (pDict->KeyExist("ColorSpace")) {
     pCSObj = pDict->GetDirectObjectFor("ColorSpace");
@@ -648,7 +647,7 @@
     }
   }
   pDict->SetNewFor<CPDF_Name>("Subtype", "Image");
-  std::unique_ptr<CPDF_Stream> pStream =
+  RetainPtr<CPDF_Stream> pStream =
       m_pSyntax->ReadInlineStream(m_pDocument.Get(), std::move(pDict), pCSObj);
   while (1) {
     CPDF_StreamParser::SyntaxType type = m_pSyntax->ParseNextElement();
@@ -762,8 +761,7 @@
 
   if (type == "Image") {
     CPDF_ImageObject* pObj = pXObject->IsInline()
-                                 ? AddImage(std::unique_ptr<CPDF_Stream>(
-                                       ToStream(pXObject->Clone())))
+                                 ? AddImage(ToStream(pXObject->Clone()))
                                  : AddImage(pXObject->GetObjNum());
 
     m_LastImageName = std::move(name);
@@ -799,7 +797,7 @@
 }
 
 CPDF_ImageObject* CPDF_StreamContentParser::AddImage(
-    std::unique_ptr<CPDF_Stream> pStream) {
+    RetainPtr<CPDF_Stream> pStream) {
   if (!pStream)
     return nullptr;
 
diff --git a/core/fpdfapi/page/cpdf_streamcontentparser.h b/core/fpdfapi/page/cpdf_streamcontentparser.h
index 63e344c..25ac268 100644
--- a/core/fpdfapi/page/cpdf_streamcontentparser.h
+++ b/core/fpdfapi/page/cpdf_streamcontentparser.h
@@ -72,7 +72,7 @@
     Type m_Type;
     FX_Number m_Number;
     ByteString m_Name;
-    std::unique_ptr<CPDF_Object> m_pObject;
+    RetainPtr<CPDF_Object> m_pObject;
   };
 
   static const int kParamBufSize = 16;
@@ -82,7 +82,7 @@
 
   void AddNameParam(ByteStringView str);
   void AddNumberParam(ByteStringView str);
-  void AddObjectParam(std::unique_ptr<CPDF_Object> pObj);
+  void AddObjectParam(RetainPtr<CPDF_Object> pObj);
   int GetNextParamPos();
   void ClearAllParams();
   CPDF_Object* GetObject(uint32_t index);
@@ -107,7 +107,7 @@
   void AddPathPoint(float x, float y, FXPT_TYPE type, bool close);
   void AddPathRect(float x, float y, float w, float h);
   void AddPathObject(int FillType, bool bStroke);
-  CPDF_ImageObject* AddImage(std::unique_ptr<CPDF_Stream> pStream);
+  CPDF_ImageObject* AddImage(RetainPtr<CPDF_Stream> pStream);
   CPDF_ImageObject* AddImage(uint32_t streamObjNum);
   CPDF_ImageObject* AddImage(const RetainPtr<CPDF_Image>& pImage);
 
diff --git a/core/fpdfapi/page/cpdf_streamparser.cpp b/core/fpdfapi/page/cpdf_streamparser.cpp
index 1cff97f..f6bc1ac 100644
--- a/core/fpdfapi/page/cpdf_streamparser.cpp
+++ b/core/fpdfapi/page/cpdf_streamparser.cpp
@@ -124,9 +124,9 @@
 
 CPDF_StreamParser::~CPDF_StreamParser() {}
 
-std::unique_ptr<CPDF_Stream> CPDF_StreamParser::ReadInlineStream(
+RetainPtr<CPDF_Stream> CPDF_StreamParser::ReadInlineStream(
     CPDF_Document* pDoc,
-    std::unique_ptr<CPDF_Dictionary> pDict,
+    RetainPtr<CPDF_Dictionary> pDict,
     const CPDF_Object* pCSObj) {
   if (m_Pos < m_pBuf.size() && PDFCharIsWhitespace(m_pBuf[m_Pos]))
     m_Pos++;
@@ -210,12 +210,12 @@
     m_Pos += dwStreamSize;
   }
   pDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(dwStreamSize));
-  return pdfium::MakeUnique<CPDF_Stream>(std::move(pData), dwStreamSize,
+  return pdfium::MakeRetain<CPDF_Stream>(std::move(pData), dwStreamSize,
                                          std::move(pDict));
 }
 
 CPDF_StreamParser::SyntaxType CPDF_StreamParser::ParseNextElement() {
-  m_pLastObj.reset();
+  m_pLastObj.Reset();
   m_WordSize = 0;
   if (!PositionIsInBounds())
     return EndOfData;
@@ -276,23 +276,23 @@
 
   if (m_WordSize == 4) {
     if (WordBufferMatches(kTrue)) {
-      m_pLastObj = pdfium::MakeUnique<CPDF_Boolean>(true);
+      m_pLastObj = pdfium::MakeRetain<CPDF_Boolean>(true);
       return Others;
     }
     if (WordBufferMatches(kNull)) {
-      m_pLastObj = pdfium::MakeUnique<CPDF_Null>();
+      m_pLastObj = pdfium::MakeRetain<CPDF_Null>();
       return Others;
     }
   } else if (m_WordSize == 5) {
     if (WordBufferMatches(kFalse)) {
-      m_pLastObj = pdfium::MakeUnique<CPDF_Boolean>(false);
+      m_pLastObj = pdfium::MakeRetain<CPDF_Boolean>(false);
       return Others;
     }
   }
   return Keyword;
 }
 
-std::unique_ptr<CPDF_Object> CPDF_StreamParser::ReadNextObject(
+RetainPtr<CPDF_Object> CPDF_StreamParser::ReadNextObject(
     bool bAllowNestedArray,
     bool bInArray,
     uint32_t dwRecursionLevel) {
@@ -304,7 +304,7 @@
 
   if (bIsNumber) {
     m_WordBuffer[m_WordSize] = 0;
-    return pdfium::MakeUnique<CPDF_Number>(
+    return pdfium::MakeRetain<CPDF_Number>(
         ByteStringView(m_WordBuffer, m_WordSize));
   }
 
@@ -312,19 +312,19 @@
   if (first_char == '/') {
     ByteString name =
         PDF_NameDecode(ByteStringView(m_WordBuffer + 1, m_WordSize - 1));
-    return pdfium::MakeUnique<CPDF_Name>(m_pPool, name);
+    return pdfium::MakeRetain<CPDF_Name>(m_pPool, name);
   }
 
   if (first_char == '(') {
     ByteString str = ReadString();
-    return pdfium::MakeUnique<CPDF_String>(m_pPool, str, false);
+    return pdfium::MakeRetain<CPDF_String>(m_pPool, str, false);
   }
 
   if (first_char == '<') {
     if (m_WordSize == 1)
-      return pdfium::MakeUnique<CPDF_String>(m_pPool, ReadHexString(), true);
+      return pdfium::MakeRetain<CPDF_String>(m_pPool, ReadHexString(), true);
 
-    auto pDict = pdfium::MakeUnique<CPDF_Dictionary>(m_pPool);
+    auto pDict = pdfium::MakeRetain<CPDF_Dictionary>(m_pPool);
     while (1) {
       GetNextWord(bIsNumber);
       if (m_WordSize == 2 && m_WordBuffer[0] == '>')
@@ -335,7 +335,7 @@
 
       ByteString key =
           PDF_NameDecode(ByteStringView(m_WordBuffer + 1, m_WordSize - 1));
-      std::unique_ptr<CPDF_Object> pObj =
+      RetainPtr<CPDF_Object> pObj =
           ReadNextObject(true, bInArray, dwRecursionLevel + 1);
       if (!pObj)
         return nullptr;
@@ -350,9 +350,9 @@
     if ((!bAllowNestedArray && bInArray))
       return nullptr;
 
-    auto pArray = pdfium::MakeUnique<CPDF_Array>();
+    auto pArray = pdfium::MakeRetain<CPDF_Array>();
     while (1) {
-      std::unique_ptr<CPDF_Object> pObj =
+      RetainPtr<CPDF_Object> pObj =
           ReadNextObject(bAllowNestedArray, true, dwRecursionLevel + 1);
       if (pObj) {
         pArray->Add(std::move(pObj));
@@ -365,11 +365,11 @@
   }
 
   if (WordBufferMatches(kFalse))
-    return pdfium::MakeUnique<CPDF_Boolean>(false);
+    return pdfium::MakeRetain<CPDF_Boolean>(false);
   if (WordBufferMatches(kTrue))
-    return pdfium::MakeUnique<CPDF_Boolean>(true);
+    return pdfium::MakeRetain<CPDF_Boolean>(true);
   if (WordBufferMatches(kNull))
-    return pdfium::MakeUnique<CPDF_Null>();
+    return pdfium::MakeRetain<CPDF_Null>();
   return nullptr;
 }
 
diff --git a/core/fpdfapi/page/cpdf_streamparser.h b/core/fpdfapi/page/cpdf_streamparser.h
index a359544..6051b8c 100644
--- a/core/fpdfapi/page/cpdf_streamparser.h
+++ b/core/fpdfapi/page/cpdf_streamparser.h
@@ -34,14 +34,13 @@
   }
   uint32_t GetPos() const { return m_Pos; }
   void SetPos(uint32_t pos) { m_Pos = pos; }
-  std::unique_ptr<CPDF_Object> GetObject() { return std::move(m_pLastObj); }
-  std::unique_ptr<CPDF_Object> ReadNextObject(bool bAllowNestedArray,
-                                              bool bInArray,
-                                              uint32_t dwRecursionLevel);
-  std::unique_ptr<CPDF_Stream> ReadInlineStream(
-      CPDF_Document* pDoc,
-      std::unique_ptr<CPDF_Dictionary> pDict,
-      const CPDF_Object* pCSObj);
+  const RetainPtr<CPDF_Object>& GetObject() const { return m_pLastObj; }
+  RetainPtr<CPDF_Object> ReadNextObject(bool bAllowNestedArray,
+                                        bool bInArray,
+                                        uint32_t dwRecursionLevel);
+  RetainPtr<CPDF_Stream> ReadInlineStream(CPDF_Document* pDoc,
+                                          RetainPtr<CPDF_Dictionary> pDict,
+                                          const CPDF_Object* pCSObj);
 
  private:
   friend class cpdf_streamparser_ReadHexString_Test;
@@ -56,7 +55,7 @@
   uint32_t m_Pos = 0;       // Current byte position within |m_pBuf|.
   uint32_t m_WordSize = 0;  // Current byte position within |m_WordBuffer|.
   WeakPtr<ByteStringPool> m_pPool;
-  std::unique_ptr<CPDF_Object> m_pLastObj;
+  RetainPtr<CPDF_Object> m_pLastObj;
   pdfium::span<const uint8_t> m_pBuf;
   uint8_t m_WordBuffer[kMaxWordLength + 1];  // Include space for NUL.
 };
diff --git a/core/fpdfapi/parser/cfdf_document.cpp b/core/fpdfapi/parser/cfdf_document.cpp
index 739fefa..b39db02 100644
--- a/core/fpdfapi/parser/cfdf_document.cpp
+++ b/core/fpdfapi/parser/cfdf_document.cpp
@@ -54,7 +54,7 @@
       if (word != "obj")
         break;
 
-      std::unique_ptr<CPDF_Object> pObj = parser.GetObjectBody(this);
+      RetainPtr<CPDF_Object> pObj = parser.GetObjectBody(this);
       if (!pObj)
         break;
 
@@ -66,7 +66,7 @@
       if (word != "trailer")
         break;
 
-      std::unique_ptr<CPDF_Dictionary> pMainDict =
+      RetainPtr<CPDF_Dictionary> pMainDict =
           ToDictionary(parser.GetObjectBody(this));
       if (pMainDict)
         m_pRootDict = pMainDict->GetDictFor("Root");
@@ -84,7 +84,7 @@
   buf << "%FDF-1.2\r\n";
   for (const auto& pair : *this)
     buf << pair.first << " 0 obj\r\n"
-        << pair.second.get() << "\r\nendobj\r\n\r\n";
+        << pair.second.Get() << "\r\nendobj\r\n\r\n";
 
   buf << "trailer\r\n<</Root " << m_pRootDict->GetObjNum()
       << " 0 R>>\r\n%%EOF\r\n";
diff --git a/core/fpdfapi/parser/cpdf_array.cpp b/core/fpdfapi/parser/cpdf_array.cpp
index d3f7213..076e666 100644
--- a/core/fpdfapi/parser/cpdf_array.cpp
+++ b/core/fpdfapi/parser/cpdf_array.cpp
@@ -28,7 +28,7 @@
   m_ObjNum = kInvalidObjNum;
   for (auto& it : m_Objects) {
     if (it && it->GetObjNum() == kInvalidObjNum)
-      it.release();
+      it.Leak();
   }
 }
 
@@ -48,23 +48,23 @@
   return this;
 }
 
-std::unique_ptr<CPDF_Object> CPDF_Array::Clone() const {
+RetainPtr<CPDF_Object> CPDF_Array::Clone() const {
   return CloneObjectNonCyclic(false);
 }
 
-std::unique_ptr<CPDF_Object> CPDF_Array::CloneNonCyclic(
+RetainPtr<CPDF_Object> CPDF_Array::CloneNonCyclic(
     bool bDirect,
     std::set<const CPDF_Object*>* pVisited) const {
   pVisited->insert(this);
-  auto pCopy = pdfium::MakeUnique<CPDF_Array>();
+  auto pCopy = pdfium::MakeRetain<CPDF_Array>();
   for (const auto& pValue : m_Objects) {
-    if (!pdfium::ContainsKey(*pVisited, pValue.get())) {
+    if (!pdfium::ContainsKey(*pVisited, pValue.Get())) {
       std::set<const CPDF_Object*> visited(*pVisited);
       if (auto obj = pValue->CloneNonCyclic(bDirect, &visited))
         pCopy->m_Objects.push_back(std::move(obj));
     }
   }
-  return std::move(pCopy);
+  return pCopy;
 }
 
 CFX_FloatRect CPDF_Array::GetRect() const {
@@ -90,13 +90,13 @@
 CPDF_Object* CPDF_Array::GetObjectAt(size_t i) {
   if (i >= m_Objects.size())
     return nullptr;
-  return m_Objects[i].get();
+  return m_Objects[i].Get();
 }
 
 const CPDF_Object* CPDF_Array::GetObjectAt(size_t i) const {
   if (i >= m_Objects.size())
     return nullptr;
-  return m_Objects[i].get();
+  return m_Objects[i].Get();
 }
 
 CPDF_Object* CPDF_Array::GetDirectObjectAt(size_t i) {
@@ -197,7 +197,7 @@
   m_Objects[i] = pNew->MakeReference(pHolder);
 }
 
-CPDF_Object* CPDF_Array::SetAt(size_t i, std::unique_ptr<CPDF_Object> pObj) {
+CPDF_Object* CPDF_Array::SetAt(size_t i, RetainPtr<CPDF_Object> pObj) {
   CHECK(!IsLocked());
   ASSERT(IsArray());
   ASSERT(!pObj || pObj->IsInline());
@@ -205,17 +205,16 @@
     NOTREACHED();
     return nullptr;
   }
-  CPDF_Object* pRet = pObj.get();
+  CPDF_Object* pRet = pObj.Get();
   m_Objects[i] = std::move(pObj);
   return pRet;
 }
 
-CPDF_Object* CPDF_Array::InsertAt(size_t index,
-                                  std::unique_ptr<CPDF_Object> pObj) {
+CPDF_Object* CPDF_Array::InsertAt(size_t index, RetainPtr<CPDF_Object> pObj) {
   CHECK(!IsLocked());
   ASSERT(IsArray());
   CHECK(!pObj || pObj->IsInline());
-  CPDF_Object* pRet = pObj.get();
+  CPDF_Object* pRet = pObj.Get();
   if (index >= m_Objects.size()) {
     // Allocate space first.
     m_Objects.resize(index + 1);
@@ -227,11 +226,11 @@
   return pRet;
 }
 
-CPDF_Object* CPDF_Array::Add(std::unique_ptr<CPDF_Object> pObj) {
+CPDF_Object* CPDF_Array::Add(RetainPtr<CPDF_Object> pObj) {
   CHECK(!IsLocked());
   ASSERT(IsArray());
   CHECK(!pObj || pObj->IsInline());
-  CPDF_Object* pRet = pObj.get();
+  CPDF_Object* pRet = pObj.Get();
   m_Objects.push_back(std::move(pObj));
   return pRet;
 }
diff --git a/core/fpdfapi/parser/cpdf_array.h b/core/fpdfapi/parser/cpdf_array.h
index f7b4a1f..55d4cd6 100644
--- a/core/fpdfapi/parser/cpdf_array.h
+++ b/core/fpdfapi/parser/cpdf_array.h
@@ -20,16 +20,14 @@
 
 class CPDF_Array final : public CPDF_Object {
  public:
-  using const_iterator =
-      std::vector<std::unique_ptr<CPDF_Object>>::const_iterator;
+  using const_iterator = std::vector<RetainPtr<CPDF_Object>>::const_iterator;
 
-  CPDF_Array();
-  explicit CPDF_Array(const WeakPtr<ByteStringPool>& pPool);
-  ~CPDF_Array() override;
+  template <typename T, typename... Args>
+  friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
 
   // CPDF_Object:
   Type GetType() const override;
-  std::unique_ptr<CPDF_Object> Clone() const override;
+  RetainPtr<CPDF_Object> Clone() const override;
   bool IsArray() const override;
   CPDF_Array* AsArray() override;
   const CPDF_Array* AsArray() const override;
@@ -57,9 +55,9 @@
   CFX_FloatRect GetRect() const;
 
   // Takes ownership of |pObj|, returns unowned pointer to it.
-  CPDF_Object* Add(std::unique_ptr<CPDF_Object> pObj);
-  CPDF_Object* SetAt(size_t index, std::unique_ptr<CPDF_Object> pObj);
-  CPDF_Object* InsertAt(size_t index, std::unique_ptr<CPDF_Object> pObj);
+  CPDF_Object* Add(RetainPtr<CPDF_Object> pObj);
+  CPDF_Object* SetAt(size_t index, RetainPtr<CPDF_Object> pObj);
+  CPDF_Object* InsertAt(size_t index, RetainPtr<CPDF_Object> pObj);
 
   // Creates object owned by the array, returns unowned pointer to it.
   // We have special cases for objects that can intern strings from
@@ -68,41 +66,41 @@
   typename std::enable_if<!CanInternStrings<T>::value, T*>::type AddNew(
       Args&&... args) {
     return static_cast<T*>(
-        Add(pdfium::MakeUnique<T>(std::forward<Args>(args)...)));
+        Add(pdfium::MakeRetain<T>(std::forward<Args>(args)...)));
   }
   template <typename T, typename... Args>
   typename std::enable_if<CanInternStrings<T>::value, T*>::type AddNew(
       Args&&... args) {
     return static_cast<T*>(
-        Add(pdfium::MakeUnique<T>(m_pPool, std::forward<Args>(args)...)));
+        Add(pdfium::MakeRetain<T>(m_pPool, std::forward<Args>(args)...)));
   }
   template <typename T, typename... Args>
   typename std::enable_if<!CanInternStrings<T>::value, T*>::type SetNewAt(
       size_t index,
       Args&&... args) {
     return static_cast<T*>(
-        SetAt(index, pdfium::MakeUnique<T>(std::forward<Args>(args)...)));
+        SetAt(index, pdfium::MakeRetain<T>(std::forward<Args>(args)...)));
   }
   template <typename T, typename... Args>
   typename std::enable_if<CanInternStrings<T>::value, T*>::type SetNewAt(
       size_t index,
       Args&&... args) {
     return static_cast<T*>(SetAt(
-        index, pdfium::MakeUnique<T>(m_pPool, std::forward<Args>(args)...)));
+        index, pdfium::MakeRetain<T>(m_pPool, std::forward<Args>(args)...)));
   }
   template <typename T, typename... Args>
   typename std::enable_if<!CanInternStrings<T>::value, T*>::type InsertNewAt(
       size_t index,
       Args&&... args) {
     return static_cast<T*>(
-        InsertAt(index, pdfium::MakeUnique<T>(std::forward<Args>(args)...)));
+        InsertAt(index, pdfium::MakeRetain<T>(std::forward<Args>(args)...)));
   }
   template <typename T, typename... Args>
   typename std::enable_if<CanInternStrings<T>::value, T*>::type InsertNewAt(
       size_t index,
       Args&&... args) {
     return static_cast<T*>(InsertAt(
-        index, pdfium::MakeUnique<T>(m_pPool, std::forward<Args>(args)...)));
+        index, pdfium::MakeRetain<T>(m_pPool, std::forward<Args>(args)...)));
   }
 
   void Clear();
@@ -113,11 +111,15 @@
  private:
   friend class CPDF_ArrayLocker;
 
-  std::unique_ptr<CPDF_Object> CloneNonCyclic(
+  CPDF_Array();
+  explicit CPDF_Array(const WeakPtr<ByteStringPool>& pPool);
+  ~CPDF_Array() override;
+
+  RetainPtr<CPDF_Object> CloneNonCyclic(
       bool bDirect,
       std::set<const CPDF_Object*>* pVisited) const override;
 
-  std::vector<std::unique_ptr<CPDF_Object>> m_Objects;
+  std::vector<RetainPtr<CPDF_Object>> m_Objects;
   WeakPtr<ByteStringPool> m_pPool;
   mutable uint32_t m_LockCount = 0;
 };
@@ -150,12 +152,8 @@
   return obj ? obj->AsArray() : nullptr;
 }
 
-inline std::unique_ptr<CPDF_Array> ToArray(std::unique_ptr<CPDF_Object> obj) {
-  CPDF_Array* pArray = ToArray(obj.get());
-  if (!pArray)
-    return nullptr;
-  obj.release();
-  return std::unique_ptr<CPDF_Array>(pArray);
+inline RetainPtr<CPDF_Array> ToArray(RetainPtr<CPDF_Object> obj) {
+  return RetainPtr<CPDF_Array>(ToArray(obj.Get()));
 }
 
 #endif  // CORE_FPDFAPI_PARSER_CPDF_ARRAY_H_
diff --git a/core/fpdfapi/parser/cpdf_array_unittest.cpp b/core/fpdfapi/parser/cpdf_array_unittest.cpp
index fbc5c39..a941160 100644
--- a/core/fpdfapi/parser/cpdf_array_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_array_unittest.cpp
@@ -15,7 +15,7 @@
 TEST(cpdf_array, RemoveAt) {
   {
     const int elems[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-    auto arr = pdfium::MakeUnique<CPDF_Array>();
+    auto arr = pdfium::MakeRetain<CPDF_Array>();
     for (size_t i = 0; i < FX_ArraySize(elems); ++i)
       arr->AddNew<CPDF_Number>(elems[i]);
     for (size_t i = 0; i < 3; ++i)
@@ -34,7 +34,7 @@
   {
     // When the range is out of bound, RemoveAt() has no effect.
     const int elems[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-    auto arr = pdfium::MakeUnique<CPDF_Array>();
+    auto arr = pdfium::MakeRetain<CPDF_Array>();
     for (size_t i = 0; i < FX_ArraySize(elems); ++i)
       arr->AddNew<CPDF_Number>(elems[i]);
     arr->RemoveAt(11);
@@ -44,7 +44,7 @@
 
 TEST(cpdf_array, Clear) {
   const int elems[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-  auto arr = pdfium::MakeUnique<CPDF_Array>();
+  auto arr = pdfium::MakeRetain<CPDF_Array>();
   EXPECT_EQ(0U, arr->size());
   for (size_t i = 0; i < FX_ArraySize(elems); ++i)
     arr->AddNew<CPDF_Number>(elems[i]);
@@ -56,7 +56,7 @@
 TEST(cpdf_array, InsertAt) {
   {
     const int elems[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-    auto arr = pdfium::MakeUnique<CPDF_Array>();
+    auto arr = pdfium::MakeRetain<CPDF_Array>();
     for (size_t i = 0; i < FX_ArraySize(elems); ++i)
       arr->InsertNewAt<CPDF_Number>(i, elems[i]);
     ASSERT_EQ(FX_ArraySize(elems), arr->size());
@@ -75,7 +75,7 @@
     // an element is inserted at that position while other unfilled
     // positions have nullptr.
     const int elems[] = {1, 2};
-    auto arr = pdfium::MakeUnique<CPDF_Array>();
+    auto arr = pdfium::MakeRetain<CPDF_Array>();
     for (size_t i = 0; i < FX_ArraySize(elems); ++i)
       arr->InsertNewAt<CPDF_Number>(i, elems[i]);
     arr->InsertNewAt<CPDF_Number>(10, 10);
@@ -92,10 +92,10 @@
   {
     // Basic case.
     const int elems[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-    auto arr = pdfium::MakeUnique<CPDF_Array>();
+    auto arr = pdfium::MakeRetain<CPDF_Array>();
     for (size_t i = 0; i < FX_ArraySize(elems); ++i)
       arr->InsertNewAt<CPDF_Number>(i, elems[i]);
-    std::unique_ptr<CPDF_Array> arr2 = ToArray(arr->Clone());
+    RetainPtr<CPDF_Array> arr2 = ToArray(arr->Clone());
     ASSERT_EQ(arr->size(), arr2->size());
     for (size_t i = 0; i < FX_ArraySize(elems); ++i) {
       // Clone() always create new objects.
@@ -109,13 +109,13 @@
     static const size_t kNumOfRowElems = 5;
     const int elems[kNumOfRows][kNumOfRowElems] = {
         {1, 2, 3, 4, 5}, {10, 9, 8, 7, 6}, {11, 12, 13, 14, 15}};
-    auto arr = pdfium::MakeUnique<CPDF_Array>();
+    auto arr = pdfium::MakeRetain<CPDF_Array>();
     // Indirect references to indirect objects.
     auto obj_holder = pdfium::MakeUnique<CPDF_IndirectObjectHolder>();
     for (size_t i = 0; i < kNumOfRows; ++i) {
-      auto arr_elem = pdfium::MakeUnique<CPDF_Array>();
+      auto arr_elem = pdfium::MakeRetain<CPDF_Array>();
       for (size_t j = 0; j < kNumOfRowElems; ++j) {
-        auto obj = pdfium::MakeUnique<CPDF_Number>(elems[i][j]);
+        auto obj = pdfium::MakeRetain<CPDF_Number>(elems[i][j]);
         // Starts object number from 1.
         int obj_num = i * kNumOfRowElems + j + 1;
         obj_holder->ReplaceIndirectObjectIfHigherGeneration(obj_num,
@@ -127,10 +127,10 @@
     ASSERT_EQ(kNumOfRows, arr->size());
     // Not dereferencing reference objects means just creating new references
     // instead of new copies of direct objects.
-    std::unique_ptr<CPDF_Array> arr1 = ToArray(arr->Clone());
+    RetainPtr<CPDF_Array> arr1 = ToArray(arr->Clone());
     ASSERT_EQ(arr->size(), arr1->size());
     // Dereferencing reference objects creates new copies of direct objects.
-    std::unique_ptr<CPDF_Array> arr2 = ToArray(arr->CloneDirectObject());
+    RetainPtr<CPDF_Array> arr2 = ToArray(arr->CloneDirectObject());
     ASSERT_EQ(arr->size(), arr2->size());
     for (size_t i = 0; i < kNumOfRows; ++i) {
       CPDF_Array* arr_elem = arr->GetObjectAt(i)->AsArray();
@@ -155,7 +155,7 @@
         EXPECT_EQ(elem_obj->GetInteger(), elem_obj2->GetInteger());
       }
     }
-    arr.reset();
+    arr.Reset();
     ASSERT_EQ(kNumOfRows, arr1->size());
     for (size_t i = 0; i < kNumOfRows; ++i) {
       for (size_t j = 0; j < kNumOfRowElems; ++j) {
@@ -174,12 +174,12 @@
 TEST(cpdf_array, Iterator) {
   const int elems[] = {-23, -11,     3,         455,   2345877,
                        0,   7895330, -12564334, 10000, -100000};
-  auto arr = pdfium::MakeUnique<CPDF_Array>();
+  auto arr = pdfium::MakeRetain<CPDF_Array>();
   for (size_t i = 0; i < FX_ArraySize(elems); ++i)
     arr->InsertNewAt<CPDF_Number>(i, elems[i]);
   size_t index = 0;
 
-  CPDF_ArrayLocker locker(arr.get());
+  CPDF_ArrayLocker locker(arr.Get());
   for (const auto& it : locker)
     EXPECT_EQ(elems[index++], it->AsNumber()->GetInteger());
   EXPECT_EQ(FX_ArraySize(elems), index);
diff --git a/core/fpdfapi/parser/cpdf_boolean.cpp b/core/fpdfapi/parser/cpdf_boolean.cpp
index fdf5b57..09a5fd3 100644
--- a/core/fpdfapi/parser/cpdf_boolean.cpp
+++ b/core/fpdfapi/parser/cpdf_boolean.cpp
@@ -19,8 +19,8 @@
   return kBoolean;
 }
 
-std::unique_ptr<CPDF_Object> CPDF_Boolean::Clone() const {
-  return pdfium::MakeUnique<CPDF_Boolean>(m_bValue);
+RetainPtr<CPDF_Object> CPDF_Boolean::Clone() const {
+  return pdfium::MakeRetain<CPDF_Boolean>(m_bValue);
 }
 
 ByteString CPDF_Boolean::GetString() const {
diff --git a/core/fpdfapi/parser/cpdf_boolean.h b/core/fpdfapi/parser/cpdf_boolean.h
index 5aa63af..1f093da 100644
--- a/core/fpdfapi/parser/cpdf_boolean.h
+++ b/core/fpdfapi/parser/cpdf_boolean.h
@@ -15,13 +15,12 @@
 
 class CPDF_Boolean final : public CPDF_Object {
  public:
-  CPDF_Boolean();
-  explicit CPDF_Boolean(bool value);
-  ~CPDF_Boolean() override;
+  template <typename T, typename... Args>
+  friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
 
   // CPDF_Object:
   Type GetType() const override;
-  std::unique_ptr<CPDF_Object> Clone() const override;
+  RetainPtr<CPDF_Object> Clone() const override;
   ByteString GetString() const override;
   int GetInteger() const override;
   void SetString(const ByteString& str) override;
@@ -32,6 +31,10 @@
                const CPDF_Encryptor* encryptor) const override;
 
  private:
+  CPDF_Boolean();
+  explicit CPDF_Boolean(bool value);
+  ~CPDF_Boolean() override;
+
   bool m_bValue;
 };
 
diff --git a/core/fpdfapi/parser/cpdf_cross_ref_avail.cpp b/core/fpdfapi/parser/cpdf_cross_ref_avail.cpp
index 6dc8d00..db4a754 100644
--- a/core/fpdfapi/parser/cpdf_cross_ref_avail.cpp
+++ b/core/fpdfapi/parser/cpdf_cross_ref_avail.cpp
@@ -136,7 +136,7 @@
 bool CPDF_CrossRefAvail::CheckCrossRefV4Trailer() {
   parser_->SetPos(current_offset_);
 
-  std::unique_ptr<CPDF_Dictionary> trailer =
+  RetainPtr<CPDF_Dictionary> trailer =
       ToDictionary(parser_->GetObjectBody(nullptr));
   if (CheckReadProblems())
     return false;
@@ -152,13 +152,13 @@
   }
 
   const int32_t xrefpos =
-      GetDirectInteger(trailer.get(), kPrevCrossRefFieldKey);
+      GetDirectInteger(trailer.Get(), kPrevCrossRefFieldKey);
   if (xrefpos &&
       pdfium::base::IsValueInRangeForNumericType<FX_FILESIZE>(xrefpos))
     AddCrossRefForCheck(static_cast<FX_FILESIZE>(xrefpos));
 
   const int32_t stream_xref_offset =
-      GetDirectInteger(trailer.get(), kPrevCrossRefStreamOffsetFieldKey);
+      GetDirectInteger(trailer.Get(), kPrevCrossRefStreamOffsetFieldKey);
   if (stream_xref_offset &&
       pdfium::base::IsValueInRangeForNumericType<FX_FILESIZE>(
           stream_xref_offset))
diff --git a/core/fpdfapi/parser/cpdf_cross_ref_table.cpp b/core/fpdfapi/parser/cpdf_cross_ref_table.cpp
index 31e9fd3..bd25b6c 100644
--- a/core/fpdfapi/parser/cpdf_cross_ref_table.cpp
+++ b/core/fpdfapi/parser/cpdf_cross_ref_table.cpp
@@ -27,7 +27,7 @@
 
 CPDF_CrossRefTable::CPDF_CrossRefTable() = default;
 
-CPDF_CrossRefTable::CPDF_CrossRefTable(std::unique_ptr<CPDF_Dictionary> trailer)
+CPDF_CrossRefTable::CPDF_CrossRefTable(RetainPtr<CPDF_Dictionary> trailer)
     : trailer_(std::move(trailer)) {}
 
 CPDF_CrossRefTable::~CPDF_CrossRefTable() = default;
@@ -88,7 +88,7 @@
   info.pos = 0;
 }
 
-void CPDF_CrossRefTable::SetTrailer(std::unique_ptr<CPDF_Dictionary> trailer) {
+void CPDF_CrossRefTable::SetTrailer(RetainPtr<CPDF_Dictionary> trailer) {
   trailer_ = std::move(trailer);
 }
 
@@ -141,8 +141,7 @@
   objects_info_ = std::move(new_objects_info);
 }
 
-void CPDF_CrossRefTable::UpdateTrailer(
-    std::unique_ptr<CPDF_Dictionary> new_trailer) {
+void CPDF_CrossRefTable::UpdateTrailer(RetainPtr<CPDF_Dictionary> new_trailer) {
   if (!new_trailer)
     return;
 
diff --git a/core/fpdfapi/parser/cpdf_cross_ref_table.h b/core/fpdfapi/parser/cpdf_cross_ref_table.h
index 9631216..c2b4f1e 100644
--- a/core/fpdfapi/parser/cpdf_cross_ref_table.h
+++ b/core/fpdfapi/parser/cpdf_cross_ref_table.h
@@ -9,6 +9,7 @@
 #include <memory>
 
 #include "core/fxcrt/fx_system.h"
+#include "core/fxcrt/retain_ptr.h"
 
 class CPDF_Dictionary;
 
@@ -42,15 +43,15 @@
       std::unique_ptr<CPDF_CrossRefTable> top);
 
   CPDF_CrossRefTable();
-  explicit CPDF_CrossRefTable(std::unique_ptr<CPDF_Dictionary> trailer);
+  explicit CPDF_CrossRefTable(RetainPtr<CPDF_Dictionary> trailer);
   ~CPDF_CrossRefTable();
 
   void AddCompressed(uint32_t obj_num, uint32_t archive_obj_num);
   void AddNormal(uint32_t obj_num, uint16_t gen_num, FX_FILESIZE pos);
   void SetFree(uint32_t obj_num);
 
-  const CPDF_Dictionary* trailer() const { return trailer_.get(); }
-  void SetTrailer(std::unique_ptr<CPDF_Dictionary> trailer);
+  const CPDF_Dictionary* trailer() const { return trailer_.Get(); }
+  void SetTrailer(RetainPtr<CPDF_Dictionary> trailer);
 
   const ObjectInfo* GetObjectInfo(uint32_t obj_num) const;
 
@@ -64,9 +65,9 @@
 
  private:
   void UpdateInfo(std::map<uint32_t, ObjectInfo>&& new_objects_info);
-  void UpdateTrailer(std::unique_ptr<CPDF_Dictionary> new_trailer);
+  void UpdateTrailer(RetainPtr<CPDF_Dictionary> new_trailer);
 
-  std::unique_ptr<CPDF_Dictionary> trailer_;
+  RetainPtr<CPDF_Dictionary> trailer_;
   std::map<uint32_t, ObjectInfo> objects_info_;
 };
 
diff --git a/core/fpdfapi/parser/cpdf_crypto_handler.cpp b/core/fpdfapi/parser/cpdf_crypto_handler.cpp
index 335a57b..72ca15e 100644
--- a/core/fpdfapi/parser/cpdf_crypto_handler.cpp
+++ b/core/fpdfapi/parser/cpdf_crypto_handler.cpp
@@ -279,10 +279,9 @@
   return m_Cipher == FXCIPHER_AES;
 }
 
-std::unique_ptr<CPDF_Object> CPDF_CryptoHandler::DecryptObjectTree(
-    std::unique_ptr<CPDF_Object> object) {
+bool CPDF_CryptoHandler::DecryptObjectTree(RetainPtr<CPDF_Object> object) {
   if (!object)
-    return nullptr;
+    return false;
 
   struct MayBeSignature {
     const CPDF_Dictionary* parent;
@@ -293,7 +292,7 @@
   const uint32_t obj_num = object->GetObjNum();
   const uint32_t gen_num = object->GetGenNum();
 
-  CPDF_Object* object_to_decrypt = object.get();
+  CPDF_Object* object_to_decrypt = object.Get();
   while (object_to_decrypt) {
     CPDF_NonConstObjectWalker walker(object_to_decrypt);
     object_to_decrypt = nullptr;
@@ -361,7 +360,7 @@
       }
     }
   }
-  return object;
+  return true;
 }
 
 bool CPDF_CryptoHandler::DecryptStream(void* context,
diff --git a/core/fpdfapi/parser/cpdf_crypto_handler.h b/core/fpdfapi/parser/cpdf_crypto_handler.h
index 0704f61..c760f61 100644
--- a/core/fpdfapi/parser/cpdf_crypto_handler.h
+++ b/core/fpdfapi/parser/cpdf_crypto_handler.h
@@ -27,9 +27,7 @@
 
   static bool IsSignatureDictionary(const CPDF_Dictionary* dictionary);
 
-  std::unique_ptr<CPDF_Object> DecryptObjectTree(
-      std::unique_ptr<CPDF_Object> object);
-
+  bool DecryptObjectTree(RetainPtr<CPDF_Object> object);
   size_t EncryptGetSize(pdfium::span<const uint8_t> source) const;
   bool EncryptContent(uint32_t objnum,
                       uint32_t version,
diff --git a/core/fpdfapi/parser/cpdf_data_avail.cpp b/core/fpdfapi/parser/cpdf_data_avail.cpp
index d80feef..3ead07e 100644
--- a/core/fpdfapi/parser/cpdf_data_avail.cpp
+++ b/core/fpdfapi/parser/cpdf_data_avail.cpp
@@ -35,16 +35,16 @@
 namespace {
 
 // static
-const CPDF_Object* GetResourceObject(const CPDF_Dictionary* pDict) {
+CPDF_Object* GetResourceObject(CPDF_Dictionary* pDict) {
   constexpr size_t kMaxHierarchyDepth = 64;
   size_t depth = 0;
 
-  const CPDF_Dictionary* dictionary_to_check = pDict;
+  CPDF_Dictionary* dictionary_to_check = pDict;
   while (dictionary_to_check) {
-    const CPDF_Object* result = dictionary_to_check->GetObjectFor("Resources");
+    CPDF_Object* result = dictionary_to_check->GetObjectFor("Resources");
     if (result)
       return result;
-    const CPDF_Object* parent = dictionary_to_check->GetObjectFor("Parent");
+    CPDF_Object* parent = dictionary_to_check->GetObjectFor("Parent");
     dictionary_to_check = parent ? parent->GetDict() : nullptr;
 
     if (++depth > kMaxHierarchyDepth) {
@@ -211,8 +211,8 @@
   return true;
 }
 
-std::unique_ptr<CPDF_Object> CPDF_DataAvail::GetObject(uint32_t objnum,
-                                                       bool* pExistInFile) {
+RetainPtr<CPDF_Object> CPDF_DataAvail::GetObject(uint32_t objnum,
+                                                 bool* pExistInFile) {
   CPDF_Parser* pParser = nullptr;
 
   if (pExistInFile)
@@ -220,7 +220,7 @@
 
   pParser = m_pDocument ? m_pDocument->GetParser() : &m_parser;
 
-  std::unique_ptr<CPDF_Object> pRet;
+  RetainPtr<CPDF_Object> pRet;
   if (pParser) {
     const CPDF_ReadValidator::Session read_session(GetValidator());
     pRet = pParser->ParseIndirectObject(objnum);
@@ -300,17 +300,17 @@
   std::vector<uint32_t> UnavailObjList;
   for (uint32_t dwPageObjNum : m_PageObjList) {
     bool bExists = false;
-    std::unique_ptr<CPDF_Object> pObj = GetObject(dwPageObjNum, &bExists);
+    RetainPtr<CPDF_Object> pObj = GetObject(dwPageObjNum, &bExists);
     if (!pObj) {
       if (bExists)
         UnavailObjList.push_back(dwPageObjNum);
       continue;
     }
-    CPDF_Array* pArray = ToArray(pObj.get());
+    CPDF_Array* pArray = ToArray(pObj.Get());
     if (pArray) {
       CPDF_ArrayLocker locker(pArray);
       for (const auto& pArrayObj : locker) {
-        if (CPDF_Reference* pRef = ToReference(pArrayObj.get()))
+        if (CPDF_Reference* pRef = ToReference(pArrayObj.Get()))
           UnavailObjList.push_back(pRef->GetRefObjNum());
       }
     }
@@ -330,8 +330,8 @@
   }
   size_t iPages = m_PagesArray.size();
   for (size_t i = 0; i < iPages; ++i) {
-    std::unique_ptr<CPDF_Object> pPages = std::move(m_PagesArray[i]);
-    if (pPages && !GetPageKids(pPages.get())) {
+    RetainPtr<CPDF_Object> pPages = std::move(m_PagesArray[i]);
+    if (pPages && !GetPageKids(pPages.Get())) {
       m_PagesArray.clear();
       m_docStatus = PDF_DATAAVAIL_ERROR;
       return false;
@@ -371,7 +371,7 @@
 
 bool CPDF_DataAvail::CheckPages() {
   bool bExists = false;
-  std::unique_ptr<CPDF_Object> pPages = GetObject(m_PagesObjNum, &bExists);
+  RetainPtr<CPDF_Object> pPages = GetObject(m_PagesObjNum, &bExists);
   if (!bExists) {
     m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
     return true;
@@ -385,7 +385,7 @@
     return false;
   }
 
-  if (!GetPageKids(pPages.get())) {
+  if (!GetPageKids(pPages.Get())) {
     m_docStatus = PDF_DATAAVAIL_ERROR;
     return false;
   }
@@ -451,13 +451,13 @@
   return true;
 }
 
-std::unique_ptr<CPDF_Object> CPDF_DataAvail::ParseIndirectObjectAt(
+RetainPtr<CPDF_Object> CPDF_DataAvail::ParseIndirectObjectAt(
     FX_FILESIZE pos,
     uint32_t objnum,
     CPDF_IndirectObjectHolder* pObjList) const {
   const FX_FILESIZE SavedPos = GetSyntaxParser()->GetPos();
   GetSyntaxParser()->SetPos(pos);
-  std::unique_ptr<CPDF_Object> result = GetSyntaxParser()->GetIndirectObject(
+  RetainPtr<CPDF_Object> result = GetSyntaxParser()->GetIndirectObject(
       pObjList, CPDF_SyntaxParser::ParseType::kLoose);
   GetSyntaxParser()->SetPos(SavedPos);
   return (result && (!objnum || result->GetObjNum() == objnum))
@@ -528,7 +528,7 @@
 bool CPDF_DataAvail::CheckArrayPageNode(uint32_t dwPageNo,
                                         PageNode* pPageNode) {
   bool bExists = false;
-  std::unique_ptr<CPDF_Object> pPages = GetObject(dwPageNo, &bExists);
+  RetainPtr<CPDF_Object> pPages = GetObject(dwPageNo, &bExists);
   if (!bExists) {
     m_docStatus = PDF_DATAAVAIL_ERROR;
     return false;
@@ -559,7 +559,7 @@
 bool CPDF_DataAvail::CheckUnknownPageNode(uint32_t dwPageNo,
                                           PageNode* pPageNode) {
   bool bExists = false;
-  std::unique_ptr<CPDF_Object> pPage = GetObject(dwPageNo, &bExists);
+  RetainPtr<CPDF_Object> pPage = GetObject(dwPageNo, &bExists);
   if (!bExists) {
     m_docStatus = PDF_DATAAVAIL_ERROR;
     return false;
@@ -694,7 +694,7 @@
 
 bool CPDF_DataAvail::CheckPageCount() {
   bool bExists = false;
-  std::unique_ptr<CPDF_Object> pPages = GetObject(m_PagesObjNum, &bExists);
+  RetainPtr<CPDF_Object> pPages = GetObject(m_PagesObjNum, &bExists);
   if (!bExists) {
     m_docStatus = PDF_DATAAVAIL_ERROR;
     return false;
@@ -884,10 +884,10 @@
 }
 
 CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::CheckResources(
-    const CPDF_Dictionary* page) {
+    CPDF_Dictionary* page) {
   ASSERT(page);
   const CPDF_ReadValidator::Session read_session(GetValidator());
-  const CPDF_Object* resources = GetResourceObject(page);
+  CPDF_Object* resources = GetResourceObject(page);
   if (GetValidator()->has_read_problems())
     return DocAvailStatus::DataNotAvailable;
 
@@ -968,11 +968,11 @@
   }
 
   if (!m_pFormAvail) {
-    const CPDF_Dictionary* pRoot = m_pDocument->GetRoot();
+    CPDF_Dictionary* pRoot = m_pDocument->GetRoot();
     if (!pRoot)
       return FormAvailable;
 
-    const CPDF_Object* pAcroForm = pRoot->GetObjectFor("AcroForm");
+    CPDF_Object* pAcroForm = pRoot->GetObjectFor("AcroForm");
     if (!pAcroForm)
       return FormNotExist;
 
diff --git a/core/fpdfapi/parser/cpdf_data_avail.h b/core/fpdfapi/parser/cpdf_data_avail.h
index 4dff3ce..baf2a90 100644
--- a/core/fpdfapi/parser/cpdf_data_avail.h
+++ b/core/fpdfapi/parser/cpdf_data_avail.h
@@ -133,17 +133,16 @@
   bool CheckInfo();
   bool CheckPages();
   bool CheckPage();
-  DocAvailStatus CheckResources(const CPDF_Dictionary* page);
+  DocAvailStatus CheckResources(CPDF_Dictionary* page);
   DocFormStatus CheckAcroForm();
   bool CheckPageStatus();
 
   DocAvailStatus CheckHeaderAndLinearized();
-  std::unique_ptr<CPDF_Object> ParseIndirectObjectAt(
+  RetainPtr<CPDF_Object> ParseIndirectObjectAt(
       FX_FILESIZE pos,
       uint32_t objnum,
       CPDF_IndirectObjectHolder* pObjList) const;
-  std::unique_ptr<CPDF_Object> GetObject(uint32_t objnum,
-                                         bool* pExistInFile);
+  RetainPtr<CPDF_Object> GetObject(uint32_t objnum, bool* pExistInFile);
   bool GetPageKids(CPDF_Object* pPages);
   bool PreparePageItem();
   bool LoadPages();
@@ -168,7 +167,7 @@
 
   RetainPtr<CPDF_ReadValidator> m_pFileRead;
   CPDF_Parser m_parser;
-  std::unique_ptr<CPDF_Dictionary> m_pRoot;
+  RetainPtr<CPDF_Dictionary> m_pRoot;
   std::unique_ptr<CPDF_LinearizedHeader> m_pLinearized;
   bool m_bDocAvail = false;
   std::unique_ptr<CPDF_CrossRefAvail> m_pCrossRefAvail;
@@ -183,7 +182,7 @@
   bool m_bPagesTreeLoad = false;
   bool m_bPagesLoad = false;
   std::unique_ptr<CPDF_PageObjectAvail> m_pFormAvail;
-  std::vector<std::unique_ptr<CPDF_Object>> m_PagesArray;
+  std::vector<RetainPtr<CPDF_Object>> m_PagesArray;
   bool m_bTotalLoadPageTree = false;
   bool m_bCurPageDictLoadOK = false;
   PageNode m_PageNode;
diff --git a/core/fpdfapi/parser/cpdf_dictionary.cpp b/core/fpdfapi/parser/cpdf_dictionary.cpp
index c514e79..b79def9 100644
--- a/core/fpdfapi/parser/cpdf_dictionary.cpp
+++ b/core/fpdfapi/parser/cpdf_dictionary.cpp
@@ -35,7 +35,7 @@
   m_ObjNum = kInvalidObjNum;
   for (auto& it : m_Map) {
     if (it.second && it.second->GetObjNum() == kInvalidObjNum)
-      it.second.release();
+      it.second.Leak();
   }
 }
 
@@ -63,18 +63,18 @@
   return this;
 }
 
-std::unique_ptr<CPDF_Object> CPDF_Dictionary::Clone() const {
+RetainPtr<CPDF_Object> CPDF_Dictionary::Clone() const {
   return CloneObjectNonCyclic(false);
 }
 
-std::unique_ptr<CPDF_Object> CPDF_Dictionary::CloneNonCyclic(
+RetainPtr<CPDF_Object> CPDF_Dictionary::CloneNonCyclic(
     bool bDirect,
     std::set<const CPDF_Object*>* pVisited) const {
   pVisited->insert(this);
-  auto pCopy = pdfium::MakeUnique<CPDF_Dictionary>(m_pPool);
+  auto pCopy = pdfium::MakeRetain<CPDF_Dictionary>(m_pPool);
   CPDF_DictionaryLocker locker(this);
   for (const auto& it : locker) {
-    if (!pdfium::ContainsKey(*pVisited, it.second.get())) {
+    if (!pdfium::ContainsKey(*pVisited, it.second.Get())) {
       std::set<const CPDF_Object*> visited(*pVisited);
       if (auto obj = it.second->CloneNonCyclic(bDirect, &visited))
         pCopy->m_Map.insert(std::make_pair(it.first, std::move(obj)));
@@ -85,7 +85,7 @@
 
 const CPDF_Object* CPDF_Dictionary::GetObjectFor(const ByteString& key) const {
   auto it = m_Map.find(key);
-  return it != m_Map.end() ? it->second.get() : nullptr;
+  return it != m_Map.end() ? it->second.Get() : nullptr;
 }
 
 CPDF_Object* CPDF_Dictionary::GetObjectFor(const ByteString& key) {
@@ -205,14 +205,14 @@
 }
 
 CPDF_Object* CPDF_Dictionary::SetFor(const ByteString& key,
-                                     std::unique_ptr<CPDF_Object> pObj) {
+                                     RetainPtr<CPDF_Object> pObj) {
   CHECK(!IsLocked());
   if (!pObj) {
     m_Map.erase(key);
     return nullptr;
   }
   ASSERT(pObj->IsInline());
-  CPDF_Object* pRet = pObj.get();
+  CPDF_Object* pRet = pObj.Get();
   m_Map[MaybeIntern(key)] = std::move(pObj);
   return pRet;
 }
@@ -229,9 +229,9 @@
   it->second = pObj->MakeReference(pHolder);
 }
 
-std::unique_ptr<CPDF_Object> CPDF_Dictionary::RemoveFor(const ByteString& key) {
+RetainPtr<CPDF_Object> CPDF_Dictionary::RemoveFor(const ByteString& key) {
   CHECK(!IsLocked());
-  std::unique_ptr<CPDF_Object> result;
+  RetainPtr<CPDF_Object> result;
   auto it = m_Map.find(key);
   if (it != m_Map.end()) {
     result = std::move(it->second);
@@ -289,7 +289,7 @@
   CPDF_DictionaryLocker locker(this);
   for (const auto& it : locker) {
     const ByteString& key = it.first;
-    CPDF_Object* pValue = it.second.get();
+    CPDF_Object* pValue = it.second.Get();
     if (!archive->WriteString("/") ||
         !archive->WriteString(PDF_NameEncode(key).AsStringView())) {
       return false;
diff --git a/core/fpdfapi/parser/cpdf_dictionary.h b/core/fpdfapi/parser/cpdf_dictionary.h
index e6abd26..af14f5c 100644
--- a/core/fpdfapi/parser/cpdf_dictionary.h
+++ b/core/fpdfapi/parser/cpdf_dictionary.h
@@ -26,15 +26,14 @@
 class CPDF_Dictionary final : public CPDF_Object {
  public:
   using const_iterator =
-      std::map<ByteString, std::unique_ptr<CPDF_Object>>::const_iterator;
+      std::map<ByteString, RetainPtr<CPDF_Object>>::const_iterator;
 
-  CPDF_Dictionary();
-  explicit CPDF_Dictionary(const WeakPtr<ByteStringPool>& pPool);
-  ~CPDF_Dictionary() override;
+  template <typename T, typename... Args>
+  friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
 
   // CPDF_Object:
   Type GetType() const override;
-  std::unique_ptr<CPDF_Object> Clone() const override;
+  RetainPtr<CPDF_Object> Clone() const override;
   CPDF_Dictionary* GetDict() override;
   const CPDF_Dictionary* GetDict() const override;
   bool IsDictionary() const override;
@@ -73,7 +72,7 @@
 
   // Set* functions invalidate iterators for the element with the key |key|.
   // Takes ownership of |pObj|, returns an unowned pointer to it.
-  CPDF_Object* SetFor(const ByteString& key, std::unique_ptr<CPDF_Object> pObj);
+  CPDF_Object* SetFor(const ByteString& key, RetainPtr<CPDF_Object> pObj);
 
   // Creates a new object owned by the dictionary and returns an unowned
   // pointer to it.
@@ -83,7 +82,7 @@
       Args&&... args) {
     CHECK(!IsLocked());
     return static_cast<T*>(
-        SetFor(key, pdfium::MakeUnique<T>(std::forward<Args>(args)...)));
+        SetFor(key, pdfium::MakeRetain<T>(std::forward<Args>(args)...)));
   }
   template <typename T, typename... Args>
   typename std::enable_if<CanInternStrings<T>::value, T*>::type SetNewFor(
@@ -91,7 +90,7 @@
       Args&&... args) {
     CHECK(!IsLocked());
     return static_cast<T*>(SetFor(
-        key, pdfium::MakeUnique<T>(m_pPool, std::forward<Args>(args)...)));
+        key, pdfium::MakeRetain<T>(m_pPool, std::forward<Args>(args)...)));
   }
 
   // Convenience functions to convert native objects to array form.
@@ -102,7 +101,7 @@
                                   CPDF_IndirectObjectHolder* pHolder);
 
   // Invalidates iterators for the element with the key |key|.
-  std::unique_ptr<CPDF_Object> RemoveFor(const ByteString& key);
+  RetainPtr<CPDF_Object> RemoveFor(const ByteString& key);
 
   // Invalidates iterators for the element with the key |oldkey|.
   void ReplaceKey(const ByteString& oldkey, const ByteString& newkey);
@@ -112,14 +111,18 @@
  private:
   friend class CPDF_DictionaryLocker;
 
+  CPDF_Dictionary();
+  explicit CPDF_Dictionary(const WeakPtr<ByteStringPool>& pPool);
+  ~CPDF_Dictionary() override;
+
   ByteString MaybeIntern(const ByteString& str);
-  std::unique_ptr<CPDF_Object> CloneNonCyclic(
+  RetainPtr<CPDF_Object> CloneNonCyclic(
       bool bDirect,
       std::set<const CPDF_Object*>* visited) const override;
 
   mutable uint32_t m_LockCount = 0;
   WeakPtr<ByteStringPool> m_pPool;
-  std::map<ByteString, std::unique_ptr<CPDF_Object>> m_Map;
+  std::map<ByteString, RetainPtr<CPDF_Object>> m_Map;
 };
 
 class CPDF_DictionaryLocker {
@@ -150,13 +153,8 @@
   return obj ? obj->AsDictionary() : nullptr;
 }
 
-inline std::unique_ptr<CPDF_Dictionary> ToDictionary(
-    std::unique_ptr<CPDF_Object> obj) {
-  CPDF_Dictionary* pDict = ToDictionary(obj.get());
-  if (!pDict)
-    return nullptr;
-  obj.release();
-  return std::unique_ptr<CPDF_Dictionary>(pDict);
+inline RetainPtr<CPDF_Dictionary> ToDictionary(RetainPtr<CPDF_Object> obj) {
+  return RetainPtr<CPDF_Dictionary>(ToDictionary(obj.Get()));
 }
 
 #endif  // CORE_FPDFAPI_PARSER_CPDF_DICTIONARY_H_
diff --git a/core/fpdfapi/parser/cpdf_document.cpp b/core/fpdfapi/parser/cpdf_document.cpp
index 2d0e4f7..459cad1 100644
--- a/core/fpdfapi/parser/cpdf_document.cpp
+++ b/core/fpdfapi/parser/cpdf_document.cpp
@@ -148,7 +148,7 @@
                     bool bold,
                     bool italic,
                     ByteString basefont,
-                    std::unique_ptr<CPDF_Array> pWidths) {
+                    RetainPtr<CPDF_Array> pWidths) {
   if (bold && italic)
     basefont += ",BoldItalic";
   else if (bold)
@@ -162,15 +162,14 @@
   pBaseDict->SetFor("Widths", std::move(pWidths));
 }
 
-std::unique_ptr<CPDF_Dictionary> CalculateFontDesc(
-    CPDF_Document* pDoc,
-    ByteString basefont,
-    int flags,
-    int italicangle,
-    int ascend,
-    int descend,
-    std::unique_ptr<CPDF_Array> bbox,
-    int32_t stemV) {
+RetainPtr<CPDF_Dictionary> CalculateFontDesc(CPDF_Document* pDoc,
+                                             ByteString basefont,
+                                             int flags,
+                                             int italicangle,
+                                             int ascend,
+                                             int descend,
+                                             RetainPtr<CPDF_Array> bbox,
+                                             int32_t stemV) {
   auto pFontDesc = pDoc->New<CPDF_Dictionary>();
   pFontDesc->SetNewFor<CPDF_Name>("Type", "FontDescriptor");
   pFontDesc->SetNewFor<CPDF_Name>("FontName", basefont);
@@ -192,8 +191,7 @@
 
 CPDF_Document::~CPDF_Document() = default;
 
-std::unique_ptr<CPDF_Object> CPDF_Document::ParseIndirectObject(
-    uint32_t objnum) {
+RetainPtr<CPDF_Object> CPDF_Document::ParseIndirectObject(uint32_t objnum) {
   return m_pParser ? m_pParser->ParseIndirectObject(objnum) : nullptr;
 }
 
@@ -605,8 +603,9 @@
   if (!m_pParser || !m_pParser->GetInfoObjNum())
     return nullptr;
 
-  CPDF_Reference ref(this, m_pParser->GetInfoObjNum());
-  m_pInfoDict = ToDictionary(ref.GetDirect());
+  auto ref =
+      pdfium::MakeRetain<CPDF_Reference>(this, m_pParser->GetInfoObjNum());
+  m_pInfoDict = ToDictionary(ref->GetDirect());
   return m_pInfoDict.Get();
 }
 
@@ -741,7 +740,7 @@
   auto pEncoding = pdfium::MakeUnique<CFX_UnicodeEncoding>(pFont);
   CPDF_Dictionary* pFontDict = pBaseDict;
   if (!bCJK) {
-    auto pWidths = pdfium::MakeUnique<CPDF_Array>();
+    auto pWidths = pdfium::MakeRetain<CPDF_Array>();
     for (int charcode = 32; charcode < 128; charcode++) {
       int glyph_index = pEncoding->GlyphFromCharCode(charcode);
       int char_width = pFont->GetGlyphWidth(glyph_index);
@@ -779,7 +778,7 @@
       pFont->GetSubstFont() ? pFont->GetSubstFont()->m_ItalicAngle : 0;
   FX_RECT bbox;
   pFont->GetBBox(&bbox);
-  auto pBBox = pdfium::MakeUnique<CPDF_Array>();
+  auto pBBox = pdfium::MakeRetain<CPDF_Array>();
   pBBox->AddNew<CPDF_Number>(bbox.left);
   pBBox->AddNew<CPDF_Number>(bbox.bottom);
   pBBox->AddNew<CPDF_Number>(bbox.right);
@@ -859,7 +858,7 @@
     }
     int char_widths[224];
     GetCharWidth(hDC, 32, 255, char_widths);
-    auto pWidths = pdfium::MakeUnique<CPDF_Array>();
+    auto pWidths = pdfium::MakeRetain<CPDF_Array>();
     for (size_t i = 0; i < 224; i++)
       pWidths->AddNew<CPDF_Number>(char_widths[i]);
     ProcessNonbCJK(pBaseDict, pLogFont->lfWeight > FW_MEDIUM,
@@ -871,10 +870,10 @@
                       InsertWidthArray(hDC, start, end, widthArr);
                     });
   }
-  auto pBBox = pdfium::MakeUnique<CPDF_Array>();
+  auto pBBox = pdfium::MakeRetain<CPDF_Array>();
   for (int i = 0; i < 4; i++)
     pBBox->AddNew<CPDF_Number>(bbox[i]);
-  std::unique_ptr<CPDF_Dictionary> pFontDesc =
+  RetainPtr<CPDF_Dictionary> pFontDesc =
       CalculateFontDesc(this, basefont, flags, italicangle, ascend, descend,
                         std::move(pBBox), pLogFont->lfWeight / 5);
   pFontDesc->SetNewFor<CPDF_Number>("CapHeight", capheight);
diff --git a/core/fpdfapi/parser/cpdf_document.h b/core/fpdfapi/parser/cpdf_document.h
index 3ef4ff6..2153813 100644
--- a/core/fpdfapi/parser/cpdf_document.h
+++ b/core/fpdfapi/parser/cpdf_document.h
@@ -149,7 +149,7 @@
                     uint32_t objnum,
                     int* index,
                     int level) const;
-  std::unique_ptr<CPDF_Object> ParseIndirectObject(uint32_t objnum) override;
+  RetainPtr<CPDF_Object> ParseIndirectObject(uint32_t objnum) override;
   size_t CalculateEncodingDict(int charset, CPDF_Dictionary* pBaseDict);
   const CPDF_Dictionary* GetPagesDict() const;
   CPDF_Dictionary* GetPagesDict();
diff --git a/core/fpdfapi/parser/cpdf_document_unittest.cpp b/core/fpdfapi/parser/cpdf_document_unittest.cpp
index 8d86b79..d20a654 100644
--- a/core/fpdfapi/parser/cpdf_document_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_document_unittest.cpp
@@ -24,7 +24,7 @@
 
 const int kNumTestPages = 7;
 
-CPDF_Dictionary* CreatePageTreeNode(std::unique_ptr<CPDF_Array> kids,
+CPDF_Dictionary* CreatePageTreeNode(RetainPtr<CPDF_Array> kids,
                                     CPDF_Document* pDoc,
                                     int count) {
   CPDF_Array* pUnowned = pDoc->AddIndirectObject(std::move(kids))->AsArray();
@@ -39,8 +39,8 @@
   return pageNode;
 }
 
-std::unique_ptr<CPDF_Dictionary> CreateNumberedPage(size_t number) {
-  auto page = pdfium::MakeUnique<CPDF_Dictionary>();
+RetainPtr<CPDF_Dictionary> CreateNumberedPage(size_t number) {
+  auto page = pdfium::MakeRetain<CPDF_Dictionary>();
   page->SetNewFor<CPDF_String>("Type", "Page", false);
   page->SetNewFor<CPDF_Number>("PageNumbering", static_cast<int>(number));
   return page;
@@ -50,7 +50,7 @@
  public:
   CPDF_TestDocumentForPages() : CPDF_Document() {
     // Set up test
-    auto zeroToTwo = pdfium::MakeUnique<CPDF_Array>();
+    auto zeroToTwo = pdfium::MakeRetain<CPDF_Array>();
     zeroToTwo->AddNew<CPDF_Reference>(
         this, AddIndirectObject(CreateNumberedPage(0))->GetObjNum());
     zeroToTwo->AddNew<CPDF_Reference>(
@@ -60,26 +60,26 @@
     CPDF_Dictionary* branch1 =
         CreatePageTreeNode(std::move(zeroToTwo), this, 3);
 
-    auto zeroToThree = pdfium::MakeUnique<CPDF_Array>();
+    auto zeroToThree = pdfium::MakeRetain<CPDF_Array>();
     zeroToThree->AddNew<CPDF_Reference>(this, branch1->GetObjNum());
     zeroToThree->AddNew<CPDF_Reference>(
         this, AddIndirectObject(CreateNumberedPage(3))->GetObjNum());
     CPDF_Dictionary* branch2 =
         CreatePageTreeNode(std::move(zeroToThree), this, 4);
 
-    auto fourFive = pdfium::MakeUnique<CPDF_Array>();
+    auto fourFive = pdfium::MakeRetain<CPDF_Array>();
     fourFive->AddNew<CPDF_Reference>(
         this, AddIndirectObject(CreateNumberedPage(4))->GetObjNum());
     fourFive->AddNew<CPDF_Reference>(
         this, AddIndirectObject(CreateNumberedPage(5))->GetObjNum());
     CPDF_Dictionary* branch3 = CreatePageTreeNode(std::move(fourFive), this, 2);
 
-    auto justSix = pdfium::MakeUnique<CPDF_Array>();
+    auto justSix = pdfium::MakeRetain<CPDF_Array>();
     justSix->AddNew<CPDF_Reference>(
         this, AddIndirectObject(CreateNumberedPage(6))->GetObjNum());
     CPDF_Dictionary* branch4 = CreatePageTreeNode(std::move(justSix), this, 1);
 
-    auto allPages = pdfium::MakeUnique<CPDF_Array>();
+    auto allPages = pdfium::MakeRetain<CPDF_Array>();
     allPages->AddNew<CPDF_Reference>(this, branch2->GetObjNum());
     allPages->AddNew<CPDF_Reference>(this, branch3->GetObjNum());
     allPages->AddNew<CPDF_Reference>(this, branch4->GetObjNum());
@@ -102,7 +102,7 @@
  public:
   CPDF_TestDocumentWithPageWithoutPageNum() : CPDF_Document() {
     // Set up test
-    auto allPages = pdfium::MakeUnique<CPDF_Array>();
+    auto allPages = pdfium::MakeRetain<CPDF_Array>();
     allPages->AddNew<CPDF_Reference>(
         this, AddIndirectObject(CreateNumberedPage(0))->GetObjNum());
     allPages->AddNew<CPDF_Reference>(
@@ -219,11 +219,11 @@
   // ObjNum can be added in CPDF_DataAvail::IsPageAvail, and PagesDict
   // can be not exists in this case.
   // (case, when hint table is used to page check in CPDF_DataAvail).
-  auto dict = pdfium::MakeUnique<CPDF_Dictionary>();
+  auto dict = pdfium::MakeRetain<CPDF_Dictionary>();
   dict->SetNewFor<CPDF_Boolean>("Linearized", true);
   const int page_count = 100;
   dict->SetNewFor<CPDF_Number>("N", page_count);
-  auto linearized = pdfium::MakeUnique<TestLinearized>(dict.get());
+  auto linearized = pdfium::MakeUnique<TestLinearized>(dict.Get());
   auto parser = pdfium::MakeUnique<CPDF_Parser>();
   parser->SetLinearizedHeader(std::move(linearized));
   CPDF_TestDocumentAllowSetParser document;
diff --git a/core/fpdfapi/parser/cpdf_flateencoder.cpp b/core/fpdfapi/parser/cpdf_flateencoder.cpp
index cf56540..71428b1 100644
--- a/core/fpdfapi/parser/cpdf_flateencoder.cpp
+++ b/core/fpdfapi/parser/cpdf_flateencoder.cpp
@@ -69,13 +69,13 @@
 
 CPDF_Dictionary* CPDF_FlateEncoder::GetClonedDict() {
   ASSERT(!m_pDict);
-  return m_pClonedDict.get();
+  return m_pClonedDict.Get();
 }
 
 const CPDF_Dictionary* CPDF_FlateEncoder::GetDict() const {
   if (m_pClonedDict) {
     ASSERT(!m_pDict);
-    return m_pClonedDict.get();
+    return m_pClonedDict.Get();
   }
 
   return m_pDict.Get();
diff --git a/core/fpdfapi/parser/cpdf_flateencoder.h b/core/fpdfapi/parser/cpdf_flateencoder.h
index 069df6f..fdcad2f 100644
--- a/core/fpdfapi/parser/cpdf_flateencoder.h
+++ b/core/fpdfapi/parser/cpdf_flateencoder.h
@@ -41,7 +41,7 @@
 
   // Only one of these two pointers is valid at any time.
   UnownedPtr<const CPDF_Dictionary> m_pDict;
-  std::unique_ptr<CPDF_Dictionary> m_pClonedDict;
+  RetainPtr<CPDF_Dictionary> m_pClonedDict;
 };
 
 #endif  // CORE_FPDFAPI_PARSER_CPDF_FLATEENCODER_H_
diff --git a/core/fpdfapi/parser/cpdf_hint_tables.cpp b/core/fpdfapi/parser/cpdf_hint_tables.cpp
index 9f53e3a..dbe7f3e 100644
--- a/core/fpdfapi/parser/cpdf_hint_tables.cpp
+++ b/core/fpdfapi/parser/cpdf_hint_tables.cpp
@@ -61,7 +61,7 @@
   }
 
   parser->SetPos(szHintStart);
-  std::unique_ptr<CPDF_Stream> hints_stream = ToStream(
+  RetainPtr<CPDF_Stream> hints_stream = ToStream(
       parser->GetIndirectObject(nullptr, CPDF_SyntaxParser::ParseType::kLoose));
 
   if (!hints_stream)
@@ -69,7 +69,7 @@
 
   auto pHintTables = pdfium::MakeUnique<CPDF_HintTables>(
       parser->GetValidator().Get(), pLinearized);
-  if (!pHintTables->LoadHintStream(hints_stream.get()))
+  if (!pHintTables->LoadHintStream(hints_stream.Get()))
     return nullptr;
 
   return pHintTables;
diff --git a/core/fpdfapi/parser/cpdf_hint_tables_unittest.cpp b/core/fpdfapi/parser/cpdf_hint_tables_unittest.cpp
index c3b05ac..85db7d3 100644
--- a/core/fpdfapi/parser/cpdf_hint_tables_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_hint_tables_unittest.cpp
@@ -50,10 +50,10 @@
       const std::string& inline_data) {
     CPDF_SyntaxParser parser(pdfium::MakeRetain<CFX_ReadOnlyMemoryStream>(
         pdfium::as_bytes(pdfium::make_span(inline_data))));
-    std::unique_ptr<CPDF_Dictionary> dict =
+    RetainPtr<CPDF_Dictionary> dict =
         ToDictionary(parser.GetObjectBody(nullptr));
     ASSERT(dict);
-    return pdfium::MakeUnique<TestLinearizedHeader>(dict.get(), 0);
+    return pdfium::MakeUnique<TestLinearizedHeader>(dict.Get(), 0);
   }
 };
 
@@ -170,12 +170,12 @@
   RetainPtr<CPDF_ReadValidator> validator =
       MakeValidatorFromFile("hint_table_102p.bin");
   CPDF_SyntaxParser parser(validator, 0);
-  std::unique_ptr<CPDF_Stream> stream = ToStream(parser.GetObjectBody(nullptr));
+  RetainPtr<CPDF_Stream> stream = ToStream(parser.GetObjectBody(nullptr));
   ASSERT_TRUE(stream);
   auto hint_tables = pdfium::MakeUnique<CPDF_HintTables>(
       validator.Get(), linearized_header.get());
   // Check that hint table will load.
-  ASSERT_TRUE(hint_tables->LoadHintStream(stream.get()));
+  ASSERT_TRUE(hint_tables->LoadHintStream(stream.Get()));
   // Check that hint table have correct first page offset.
   // 127546 is predefined real value from original file.
   EXPECT_EQ(127546, hint_tables->GetFirstPageObjOffset());
diff --git a/core/fpdfapi/parser/cpdf_indirect_object_holder.cpp b/core/fpdfapi/parser/cpdf_indirect_object_holder.cpp
index 32ba87f..345a8ae 100644
--- a/core/fpdfapi/parser/cpdf_indirect_object_holder.cpp
+++ b/core/fpdfapi/parser/cpdf_indirect_object_holder.cpp
@@ -33,7 +33,7 @@
 CPDF_Object* CPDF_IndirectObjectHolder::GetIndirectObject(
     uint32_t objnum) const {
   auto it = m_IndirectObjs.find(objnum);
-  return (it != m_IndirectObjs.end()) ? FilterInvalidObjNum(it->second.get())
+  return (it != m_IndirectObjs.end()) ? FilterInvalidObjNum(it->second.Get())
                                       : nullptr;
 }
 
@@ -45,9 +45,9 @@
   // Add item anyway to prevent recursively parsing of same object.
   auto insert_result = m_IndirectObjs.insert(std::make_pair(objnum, nullptr));
   if (!insert_result.second)
-    return FilterInvalidObjNum(insert_result.first->second.get());
+    return FilterInvalidObjNum(insert_result.first->second.Get());
 
-  std::unique_ptr<CPDF_Object> pNewObj = ParseIndirectObject(objnum);
+  RetainPtr<CPDF_Object> pNewObj = ParseIndirectObject(objnum);
   if (!pNewObj) {
     m_IndirectObjs.erase(insert_result.first);
     return nullptr;
@@ -56,16 +56,16 @@
   pNewObj->SetObjNum(objnum);
   m_LastObjNum = std::max(m_LastObjNum, objnum);
   insert_result.first->second = std::move(pNewObj);
-  return insert_result.first->second.get();
+  return insert_result.first->second.Get();
 }
 
-std::unique_ptr<CPDF_Object> CPDF_IndirectObjectHolder::ParseIndirectObject(
+RetainPtr<CPDF_Object> CPDF_IndirectObjectHolder::ParseIndirectObject(
     uint32_t objnum) {
   return nullptr;
 }
 
 CPDF_Object* CPDF_IndirectObjectHolder::AddIndirectObject(
-    std::unique_ptr<CPDF_Object> pObj) {
+    RetainPtr<CPDF_Object> pObj) {
   CHECK(!pObj->GetObjNum());
   pObj->SetObjNum(++m_LastObjNum);
 
@@ -74,18 +74,18 @@
     m_OrphanObjs.push_back(std::move(obj_holder));
 
   obj_holder = std::move(pObj);
-  return obj_holder.get();
+  return obj_holder.Get();
 }
 
 bool CPDF_IndirectObjectHolder::ReplaceIndirectObjectIfHigherGeneration(
     uint32_t objnum,
-    std::unique_ptr<CPDF_Object> pObj) {
+    RetainPtr<CPDF_Object> pObj) {
   ASSERT(objnum);
   if (!pObj || objnum == CPDF_Object::kInvalidObjNum)
     return false;
 
   auto& obj_holder = m_IndirectObjs[objnum];
-  const CPDF_Object* old_object = FilterInvalidObjNum(obj_holder.get());
+  const CPDF_Object* old_object = FilterInvalidObjNum(obj_holder.Get());
   if (old_object && pObj->GetGenNum() <= old_object->GetGenNum())
     return false;
 
@@ -98,14 +98,13 @@
 
 void CPDF_IndirectObjectHolder::DeleteIndirectObject(uint32_t objnum) {
   auto it = m_IndirectObjs.find(objnum);
-  if (it == m_IndirectObjs.end() || !FilterInvalidObjNum(it->second.get()))
+  if (it == m_IndirectObjs.end() || !FilterInvalidObjNum(it->second.Get()))
     return;
 
   m_IndirectObjs.erase(it);
 }
 
-void CPDF_IndirectObjectHolder::AddOrphan(
-    std::unique_ptr<CPDF_Object> pObject) {
+void CPDF_IndirectObjectHolder::AddOrphan(RetainPtr<CPDF_Object> pObject) {
   if (pObject)
     m_OrphanObjs.push_back(std::move(pObject));
 }
diff --git a/core/fpdfapi/parser/cpdf_indirect_object_holder.h b/core/fpdfapi/parser/cpdf_indirect_object_holder.h
index e812044..36735bd 100644
--- a/core/fpdfapi/parser/cpdf_indirect_object_holder.h
+++ b/core/fpdfapi/parser/cpdf_indirect_object_holder.h
@@ -22,7 +22,7 @@
 class CPDF_IndirectObjectHolder {
  public:
   using const_iterator =
-      std::map<uint32_t, std::unique_ptr<CPDF_Object>>::const_iterator;
+      std::map<uint32_t, RetainPtr<CPDF_Object>>::const_iterator;
 
   CPDF_IndirectObjectHolder();
   virtual ~CPDF_IndirectObjectHolder();
@@ -38,36 +38,35 @@
   typename std::enable_if<!CanInternStrings<T>::value, T*>::type NewIndirect(
       Args&&... args) {
     return static_cast<T*>(
-        AddIndirectObject(pdfium::MakeUnique<T>(std::forward<Args>(args)...)));
+        AddIndirectObject(pdfium::MakeRetain<T>(std::forward<Args>(args)...)));
   }
   template <typename T, typename... Args>
   typename std::enable_if<CanInternStrings<T>::value, T*>::type NewIndirect(
       Args&&... args) {
     return static_cast<T*>(AddIndirectObject(
-        pdfium::MakeUnique<T>(m_pByteStringPool, std::forward<Args>(args)...)));
+        pdfium::MakeRetain<T>(m_pByteStringPool, std::forward<Args>(args)...)));
   }
 
   // Creates and adds a new object not owned by the indirect object holder,
   // but which can intern strings from it.
   template <typename T, typename... Args>
-  typename std::enable_if<CanInternStrings<T>::value, std::unique_ptr<T>>::type
-  New(Args&&... args) {
-    return pdfium::MakeUnique<T>(m_pByteStringPool,
+  typename std::enable_if<CanInternStrings<T>::value, RetainPtr<T>>::type New(
+      Args&&... args) {
+    return pdfium::MakeRetain<T>(m_pByteStringPool,
                                  std::forward<Args>(args)...);
   }
 
   // Takes ownership of |pObj|, returns unowned pointer to it.
-  CPDF_Object* AddIndirectObject(std::unique_ptr<CPDF_Object> pObj);
+  CPDF_Object* AddIndirectObject(RetainPtr<CPDF_Object> pObj);
 
   // Always takes ownership of |pObj|, return true if higher generation number.
-  bool ReplaceIndirectObjectIfHigherGeneration(
-      uint32_t objnum,
-      std::unique_ptr<CPDF_Object> pObj);
+  bool ReplaceIndirectObjectIfHigherGeneration(uint32_t objnum,
+                                               RetainPtr<CPDF_Object> pObj);
 
   // Takes ownership of |pObj|, persist it for life of the indirect object
   // holder (typically so that unowned pointers to it remain valid). No-op
   // if |pObj| is NULL.
-  void AddOrphan(std::unique_ptr<CPDF_Object> pObj);
+  void AddOrphan(RetainPtr<CPDF_Object> pObj);
 
   uint32_t GetLastObjNum() const { return m_LastObjNum; }
   void SetLastObjNum(uint32_t objnum) { m_LastObjNum = objnum; }
@@ -80,12 +79,12 @@
   const_iterator end() const { return m_IndirectObjs.end(); }
 
  protected:
-  virtual std::unique_ptr<CPDF_Object> ParseIndirectObject(uint32_t objnum);
+  virtual RetainPtr<CPDF_Object> ParseIndirectObject(uint32_t objnum);
 
  private:
   uint32_t m_LastObjNum;
-  std::map<uint32_t, std::unique_ptr<CPDF_Object>> m_IndirectObjs;
-  std::vector<std::unique_ptr<CPDF_Object>> m_OrphanObjs;
+  std::map<uint32_t, RetainPtr<CPDF_Object>> m_IndirectObjs;
+  std::vector<RetainPtr<CPDF_Object>> m_OrphanObjs;
   WeakPtr<ByteStringPool> m_pByteStringPool;
 };
 
diff --git a/core/fpdfapi/parser/cpdf_indirect_object_holder_unittest.cpp b/core/fpdfapi/parser/cpdf_indirect_object_holder_unittest.cpp
index 6f913ca..5494855 100644
--- a/core/fpdfapi/parser/cpdf_indirect_object_holder_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_indirect_object_holder_unittest.cpp
@@ -19,8 +19,7 @@
   MockIndirectObjectHolder() {}
   ~MockIndirectObjectHolder() override {}
 
-  MOCK_METHOD1(ParseIndirectObject,
-               std::unique_ptr<CPDF_Object>(uint32_t objnum));
+  MOCK_METHOD1(ParseIndirectObject, RetainPtr<CPDF_Object>(uint32_t objnum));
 };
 
 }  // namespace
@@ -31,11 +30,11 @@
   // parse request.
   EXPECT_CALL(mock_holder, ParseIndirectObject(::testing::_))
       .WillOnce(::testing::WithArg<0>(::testing::Invoke(
-          [&mock_holder](uint32_t objnum) -> std::unique_ptr<CPDF_Object> {
+          [&mock_holder](uint32_t objnum) -> RetainPtr<CPDF_Object> {
             const CPDF_Object* same_parse =
                 mock_holder.GetOrParseIndirectObject(objnum);
             CHECK(!same_parse);
-            return pdfium::MakeUnique<CPDF_Null>();
+            return pdfium::MakeRetain<CPDF_Null>();
           })));
 
   EXPECT_TRUE(mock_holder.GetOrParseIndirectObject(1000));
@@ -50,9 +49,9 @@
   ::testing::Mock::VerifyAndClearExpectations(&mock_holder);
 
   EXPECT_CALL(mock_holder, ParseIndirectObject(::testing::_))
-      .WillOnce(::testing::WithArg<0>(::testing::Invoke(
-          [](uint32_t objnum) -> std::unique_ptr<CPDF_Object> {
-            return pdfium::MakeUnique<CPDF_Null>();
+      .WillOnce(::testing::WithArg<0>(
+          ::testing::Invoke([](uint32_t objnum) -> RetainPtr<CPDF_Object> {
+            return pdfium::MakeRetain<CPDF_Null>();
           })));
   EXPECT_TRUE(mock_holder.GetOrParseIndirectObject(kObjNum));
   ::testing::Mock::VerifyAndClearExpectations(&mock_holder);
@@ -77,5 +76,5 @@
 
   EXPECT_CALL(mock_holder, ParseIndirectObject(::testing::_)).Times(0);
   EXPECT_FALSE(mock_holder.ReplaceIndirectObjectIfHigherGeneration(
-      CPDF_Object::kInvalidObjNum, pdfium::MakeUnique<CPDF_Null>()));
+      CPDF_Object::kInvalidObjNum, pdfium::MakeRetain<CPDF_Null>()));
 }
diff --git a/core/fpdfapi/parser/cpdf_linearized_header.cpp b/core/fpdfapi/parser/cpdf_linearized_header.cpp
index 467d7c6..eaa8e23 100644
--- a/core/fpdfapi/parser/cpdf_linearized_header.cpp
+++ b/core/fpdfapi/parser/cpdf_linearized_header.cpp
@@ -60,12 +60,12 @@
       parser->GetIndirectObject(nullptr, CPDF_SyntaxParser::ParseType::kLoose));
 
   if (!pDict || !pDict->KeyExist("Linearized") ||
-      !IsValidNumericDictionaryValue<FX_FILESIZE>(pDict.get(), "L", 1) ||
-      !IsValidNumericDictionaryValue<uint32_t>(pDict.get(), "P", 0, false) ||
-      !IsValidNumericDictionaryValue<FX_FILESIZE>(pDict.get(), "T", 1) ||
-      !IsValidNumericDictionaryValue<uint32_t>(pDict.get(), "N", 1) ||
-      !IsValidNumericDictionaryValue<FX_FILESIZE>(pDict.get(), "E", 1) ||
-      !IsValidNumericDictionaryValue<uint32_t>(pDict.get(), "O", 1)) {
+      !IsValidNumericDictionaryValue<FX_FILESIZE>(pDict.Get(), "L", 1) ||
+      !IsValidNumericDictionaryValue<uint32_t>(pDict.Get(), "P", 0, false) ||
+      !IsValidNumericDictionaryValue<FX_FILESIZE>(pDict.Get(), "T", 1) ||
+      !IsValidNumericDictionaryValue<uint32_t>(pDict.Get(), "N", 1) ||
+      !IsValidNumericDictionaryValue<FX_FILESIZE>(pDict.Get(), "E", 1) ||
+      !IsValidNumericDictionaryValue<uint32_t>(pDict.Get(), "O", 1)) {
     return nullptr;
   }
   // Move parser to the start of the xref table for the documents first page.
@@ -74,7 +74,7 @@
     return nullptr;
 
   auto result = pdfium::WrapUnique(
-      new CPDF_LinearizedHeader(pDict.get(), parser->GetPos()));
+      new CPDF_LinearizedHeader(pDict.Get(), parser->GetPos()));
 
   if (!IsLinearizedHeaderValid(result.get(), parser->GetDocumentSize()))
     return nullptr;
diff --git a/core/fpdfapi/parser/cpdf_name.cpp b/core/fpdfapi/parser/cpdf_name.cpp
index 46c1a1a..bc54623 100644
--- a/core/fpdfapi/parser/cpdf_name.cpp
+++ b/core/fpdfapi/parser/cpdf_name.cpp
@@ -23,8 +23,8 @@
   return kName;
 }
 
-std::unique_ptr<CPDF_Object> CPDF_Name::Clone() const {
-  return pdfium::MakeUnique<CPDF_Name>(nullptr, m_Name);
+RetainPtr<CPDF_Object> CPDF_Name::Clone() const {
+  return pdfium::MakeRetain<CPDF_Name>(nullptr, m_Name);
 }
 
 ByteString CPDF_Name::GetString() const {
diff --git a/core/fpdfapi/parser/cpdf_name.h b/core/fpdfapi/parser/cpdf_name.h
index ee5a6ce..cfd90bb 100644
--- a/core/fpdfapi/parser/cpdf_name.h
+++ b/core/fpdfapi/parser/cpdf_name.h
@@ -15,12 +15,12 @@
 
 class CPDF_Name final : public CPDF_Object {
  public:
-  CPDF_Name(WeakPtr<ByteStringPool> pPool, const ByteString& str);
-  ~CPDF_Name() override;
+  template <typename T, typename... Args>
+  friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
 
   // CPDF_Object:
   Type GetType() const override;
-  std::unique_ptr<CPDF_Object> Clone() const override;
+  RetainPtr<CPDF_Object> Clone() const override;
   ByteString GetString() const override;
   WideString GetUnicodeText() const override;
   void SetString(const ByteString& str) override;
@@ -31,6 +31,9 @@
                const CPDF_Encryptor* encryptor) const override;
 
  private:
+  CPDF_Name(WeakPtr<ByteStringPool> pPool, const ByteString& str);
+  ~CPDF_Name() override;
+
   ByteString m_Name;
 };
 
diff --git a/core/fpdfapi/parser/cpdf_null.cpp b/core/fpdfapi/parser/cpdf_null.cpp
index 2a0a890..71299c1 100644
--- a/core/fpdfapi/parser/cpdf_null.cpp
+++ b/core/fpdfapi/parser/cpdf_null.cpp
@@ -15,8 +15,8 @@
   return kNullobj;
 }
 
-std::unique_ptr<CPDF_Object> CPDF_Null::Clone() const {
-  return pdfium::MakeUnique<CPDF_Null>();
+RetainPtr<CPDF_Object> CPDF_Null::Clone() const {
+  return pdfium::MakeRetain<CPDF_Null>();
 }
 
 bool CPDF_Null::WriteTo(IFX_ArchiveStream* archive,
diff --git a/core/fpdfapi/parser/cpdf_null.h b/core/fpdfapi/parser/cpdf_null.h
index c72d3b0..767583b 100644
--- a/core/fpdfapi/parser/cpdf_null.h
+++ b/core/fpdfapi/parser/cpdf_null.h
@@ -13,14 +13,18 @@
 
 class CPDF_Null final : public CPDF_Object {
  public:
-  CPDF_Null();
+  template <typename T, typename... Args>
+  friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
 
   // CPDF_Object.
   Type GetType() const override;
-  std::unique_ptr<CPDF_Object> Clone() const override;
+  RetainPtr<CPDF_Object> Clone() const override;
   bool WriteTo(IFX_ArchiveStream* archive,
                const CPDF_Encryptor* encryptor) const override;
   bool IsNull() const override;
+
+ private:
+  CPDF_Null();
 };
 
 #endif  // CORE_FPDFAPI_PARSER_CPDF_NULL_H_
diff --git a/core/fpdfapi/parser/cpdf_number.cpp b/core/fpdfapi/parser/cpdf_number.cpp
index 2233a1a..24abf20 100644
--- a/core/fpdfapi/parser/cpdf_number.cpp
+++ b/core/fpdfapi/parser/cpdf_number.cpp
@@ -23,10 +23,10 @@
   return kNumber;
 }
 
-std::unique_ptr<CPDF_Object> CPDF_Number::Clone() const {
+RetainPtr<CPDF_Object> CPDF_Number::Clone() const {
   return m_Number.IsInteger()
-             ? pdfium::MakeUnique<CPDF_Number>(m_Number.GetSigned())
-             : pdfium::MakeUnique<CPDF_Number>(m_Number.GetFloat());
+             ? pdfium::MakeRetain<CPDF_Number>(m_Number.GetSigned())
+             : pdfium::MakeRetain<CPDF_Number>(m_Number.GetFloat());
 }
 
 float CPDF_Number::GetNumber() const {
diff --git a/core/fpdfapi/parser/cpdf_number.h b/core/fpdfapi/parser/cpdf_number.h
index 5a2adcd..dc75340 100644
--- a/core/fpdfapi/parser/cpdf_number.h
+++ b/core/fpdfapi/parser/cpdf_number.h
@@ -16,15 +16,12 @@
 
 class CPDF_Number final : public CPDF_Object {
  public:
-  CPDF_Number();
-  explicit CPDF_Number(int value);
-  explicit CPDF_Number(float value);
-  explicit CPDF_Number(ByteStringView str);
-  ~CPDF_Number() override;
+  template <typename T, typename... Args>
+  friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
 
   // CPDF_Object:
   Type GetType() const override;
-  std::unique_ptr<CPDF_Object> Clone() const override;
+  RetainPtr<CPDF_Object> Clone() const override;
   ByteString GetString() const override;
   float GetNumber() const override;
   int GetInteger() const override;
@@ -38,6 +35,12 @@
   bool IsInteger() const { return m_Number.IsInteger(); }
 
  private:
+  CPDF_Number();
+  explicit CPDF_Number(int value);
+  explicit CPDF_Number(float value);
+  explicit CPDF_Number(ByteStringView str);
+  ~CPDF_Number() override;
+
   FX_Number m_Number;
 };
 
diff --git a/core/fpdfapi/parser/cpdf_object.cpp b/core/fpdfapi/parser/cpdf_object.cpp
index 3fdb235..b61ee7e 100644
--- a/core/fpdfapi/parser/cpdf_object.cpp
+++ b/core/fpdfapi/parser/cpdf_object.cpp
@@ -27,17 +27,16 @@
   return this;
 }
 
-std::unique_ptr<CPDF_Object> CPDF_Object::CloneObjectNonCyclic(
-    bool bDirect) const {
+RetainPtr<CPDF_Object> CPDF_Object::CloneObjectNonCyclic(bool bDirect) const {
   std::set<const CPDF_Object*> visited_objs;
   return CloneNonCyclic(bDirect, &visited_objs);
 }
 
-std::unique_ptr<CPDF_Object> CPDF_Object::CloneDirectObject() const {
+RetainPtr<CPDF_Object> CPDF_Object::CloneDirectObject() const {
   return CloneObjectNonCyclic(true);
 }
 
-std::unique_ptr<CPDF_Object> CPDF_Object::CloneNonCyclic(
+RetainPtr<CPDF_Object> CPDF_Object::CloneNonCyclic(
     bool bDirect,
     std::set<const CPDF_Object*>* pVisited) const {
   return Clone();
@@ -171,11 +170,11 @@
   return nullptr;
 }
 
-std::unique_ptr<CPDF_Object> CPDF_Object::MakeReference(
+RetainPtr<CPDF_Object> CPDF_Object::MakeReference(
     CPDF_IndirectObjectHolder* holder) const {
   if (IsInline()) {
     NOTREACHED();
     return nullptr;
   }
-  return pdfium::MakeUnique<CPDF_Reference>(holder, GetObjNum());
+  return pdfium::MakeRetain<CPDF_Reference>(holder, GetObjNum());
 }
diff --git a/core/fpdfapi/parser/cpdf_object.h b/core/fpdfapi/parser/cpdf_object.h
index 9404ad2..77810ca 100644
--- a/core/fpdfapi/parser/cpdf_object.h
+++ b/core/fpdfapi/parser/cpdf_object.h
@@ -27,7 +27,7 @@
 class CPDF_String;
 class IFX_ArchiveStream;
 
-class CPDF_Object {
+class CPDF_Object : public Retainable {
  public:
   static const uint32_t kInvalidObjNum = static_cast<uint32_t>(-1);
   enum Type {
@@ -42,8 +42,6 @@
     kReference
   };
 
-  virtual ~CPDF_Object();
-
   virtual Type GetType() const = 0;
   uint32_t GetObjNum() const { return m_ObjNum; }
   void SetObjNum(uint32_t objnum) { m_ObjNum = objnum; }
@@ -52,11 +50,11 @@
   bool IsInline() const { return m_ObjNum == 0; }
 
   // Create a deep copy of the object.
-  virtual std::unique_ptr<CPDF_Object> Clone() const = 0;
+  virtual RetainPtr<CPDF_Object> Clone() const = 0;
 
   // Create a deep copy of the object except any reference object be
   // copied to the object it points to directly.
-  virtual std::unique_ptr<CPDF_Object> CloneDirectObject() const;
+  virtual RetainPtr<CPDF_Object> CloneDirectObject() const;
 
   virtual CPDF_Object* GetDirect();
   virtual const CPDF_Object* GetDirect() const;
@@ -105,20 +103,21 @@
   // Also check cyclic reference against |pVisited|, no copy if it is found.
   // Complex objects should implement their own CloneNonCyclic()
   // function to properly check for possible loop.
-  virtual std::unique_ptr<CPDF_Object> CloneNonCyclic(
+  virtual RetainPtr<CPDF_Object> CloneNonCyclic(
       bool bDirect,
       std::set<const CPDF_Object*>* pVisited) const;
 
   // Return a reference to itself.
   // The object must be direct (!IsInlined).
-  virtual std::unique_ptr<CPDF_Object> MakeReference(
+  virtual RetainPtr<CPDF_Object> MakeReference(
       CPDF_IndirectObjectHolder* holder) const;
 
  protected:
   CPDF_Object() = default;
   CPDF_Object(const CPDF_Object& src) = delete;
+  ~CPDF_Object() override;
 
-  std::unique_ptr<CPDF_Object> CloneObjectNonCyclic(bool bDirect) const;
+  RetainPtr<CPDF_Object> CloneObjectNonCyclic(bool bDirect) const;
 
   uint32_t m_ObjNum = 0;
   uint32_t m_GenNum = 0;
diff --git a/core/fpdfapi/parser/cpdf_object_avail.cpp b/core/fpdfapi/parser/cpdf_object_avail.cpp
index 5beb7a0..9d92c11 100644
--- a/core/fpdfapi/parser/cpdf_object_avail.cpp
+++ b/core/fpdfapi/parser/cpdf_object_avail.cpp
@@ -16,7 +16,7 @@
 CPDF_ObjectAvail::CPDF_ObjectAvail(
     const RetainPtr<CPDF_ReadValidator>& validator,
     CPDF_IndirectObjectHolder* holder,
-    const CPDF_Object* root)
+    CPDF_Object* root)
     : validator_(validator), holder_(holder), root_(root) {
   ASSERT(validator_);
   ASSERT(holder);
@@ -31,7 +31,7 @@
     uint32_t obj_num)
     : validator_(validator),
       holder_(holder),
-      root_(pdfium::MakeUnique<CPDF_Reference>(holder, obj_num)) {
+      root_(pdfium::MakeRetain<CPDF_Reference>(holder, obj_num)) {
   ASSERT(validator_);
   ASSERT(holder);
 }
@@ -61,12 +61,12 @@
     }
 
     const CPDF_ReadValidator::Session parse_session(validator_);
-    const CPDF_Object* direct = holder_->GetOrParseIndirectObject(ref_obj_num);
+    CPDF_Object* direct = holder_->GetOrParseIndirectObject(ref_obj_num);
     if (validator_->has_read_problems())
       return false;
 
     parsed_objnums_.insert(ref_obj_num);
-    root_ = direct;
+    root_.Reset(direct);
   }
   std::stack<uint32_t> non_parsed_objects_in_root;
   if (AppendObjectSubRefs(root_.Get(), &non_parsed_objects_in_root)) {
diff --git a/core/fpdfapi/parser/cpdf_object_avail.h b/core/fpdfapi/parser/cpdf_object_avail.h
index 017ea9a..901fb17 100644
--- a/core/fpdfapi/parser/cpdf_object_avail.h
+++ b/core/fpdfapi/parser/cpdf_object_avail.h
@@ -9,7 +9,6 @@
 #include <stack>
 
 #include "core/fpdfapi/parser/cpdf_data_avail.h"
-#include "core/fxcrt/maybe_owned.h"
 #include "core/fxcrt/retain_ptr.h"
 #include "core/fxcrt/unowned_ptr.h"
 
@@ -23,7 +22,7 @@
  public:
   CPDF_ObjectAvail(const RetainPtr<CPDF_ReadValidator>& validator,
                    CPDF_IndirectObjectHolder* holder,
-                   const CPDF_Object* root);
+                   CPDF_Object* root);
   CPDF_ObjectAvail(const RetainPtr<CPDF_ReadValidator>& validator,
                    CPDF_IndirectObjectHolder* holder,
                    uint32_t obj_num);
@@ -44,7 +43,7 @@
 
   RetainPtr<CPDF_ReadValidator> validator_;
   UnownedPtr<CPDF_IndirectObjectHolder> holder_;
-  MaybeOwned<const CPDF_Object> root_;
+  RetainPtr<CPDF_Object> root_;
   std::set<uint32_t> parsed_objnums_;
   std::stack<uint32_t> non_parsed_objects_;
 };
diff --git a/core/fpdfapi/parser/cpdf_object_avail_unittest.cpp b/core/fpdfapi/parser/cpdf_object_avail_unittest.cpp
index f7e0cad..f27ae63 100644
--- a/core/fpdfapi/parser/cpdf_object_avail_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_object_avail_unittest.cpp
@@ -55,13 +55,13 @@
       validator_->SimulateReadError();
       return nullptr;
     }
-    return obj_data.object.get();
+    return obj_data.object.Get();
   }
 
   RetainPtr<CPDF_ReadValidator> GetValidator() { return validator_; }
 
   void AddObject(uint32_t objnum,
-                 std::unique_ptr<CPDF_Object> object,
+                 RetainPtr<CPDF_Object> object,
                  ObjectState state) {
     ObjectData object_data;
     object_data.object = std::move(object);
@@ -81,12 +81,12 @@
     auto it = objects_data_.find(objnum);
     if (it == objects_data_.end())
       return nullptr;
-    return it->second.object.get();
+    return it->second.object.Get();
   }
 
  private:
   struct ObjectData {
-    std::unique_ptr<CPDF_Object> object;
+    RetainPtr<CPDF_Object> object;
     ObjectState state = ObjectState::Unavailable;
   };
   std::map<uint32_t, ObjectData> objects_data_;
@@ -130,7 +130,7 @@
 
 TEST(CPDF_ObjectAvailTest, OneObject) {
   TestHolder holder;
-  holder.AddObject(1, pdfium::MakeUnique<CPDF_String>(nullptr, "string", false),
+  holder.AddObject(1, pdfium::MakeRetain<CPDF_String>(nullptr, "string", false),
                    TestHolder::ObjectState::Unavailable);
   CPDF_ObjectAvail avail(holder.GetValidator(), &holder, 1);
   EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable,
@@ -141,9 +141,9 @@
 
 TEST(CPDF_ObjectAvailTest, OneReferencedObject) {
   TestHolder holder;
-  holder.AddObject(1, pdfium::MakeUnique<CPDF_Reference>(&holder, 2),
+  holder.AddObject(1, pdfium::MakeRetain<CPDF_Reference>(&holder, 2),
                    TestHolder::ObjectState::Unavailable);
-  holder.AddObject(2, pdfium::MakeUnique<CPDF_String>(nullptr, "string", false),
+  holder.AddObject(2, pdfium::MakeRetain<CPDF_String>(nullptr, "string", false),
                    TestHolder::ObjectState::Unavailable);
   CPDF_ObjectAvail avail(holder.GetValidator(), &holder, 1);
   EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable,
@@ -159,11 +159,11 @@
 
 TEST(CPDF_ObjectAvailTest, CycledReferences) {
   TestHolder holder;
-  holder.AddObject(1, pdfium::MakeUnique<CPDF_Reference>(&holder, 2),
+  holder.AddObject(1, pdfium::MakeRetain<CPDF_Reference>(&holder, 2),
                    TestHolder::ObjectState::Unavailable);
-  holder.AddObject(2, pdfium::MakeUnique<CPDF_Reference>(&holder, 3),
+  holder.AddObject(2, pdfium::MakeRetain<CPDF_Reference>(&holder, 3),
                    TestHolder::ObjectState::Unavailable);
-  holder.AddObject(3, pdfium::MakeUnique<CPDF_Reference>(&holder, 1),
+  holder.AddObject(3, pdfium::MakeRetain<CPDF_Reference>(&holder, 1),
                    TestHolder::ObjectState::Unavailable);
 
   CPDF_ObjectAvail avail(holder.GetValidator(), &holder, 1);
@@ -184,9 +184,9 @@
 
 TEST(CPDF_ObjectAvailTest, DoNotCheckParent) {
   TestHolder holder;
-  holder.AddObject(1, pdfium::MakeUnique<CPDF_Dictionary>(),
+  holder.AddObject(1, pdfium::MakeRetain<CPDF_Dictionary>(),
                    TestHolder::ObjectState::Unavailable);
-  holder.AddObject(2, pdfium::MakeUnique<CPDF_Dictionary>(),
+  holder.AddObject(2, pdfium::MakeRetain<CPDF_Dictionary>(),
                    TestHolder::ObjectState::Unavailable);
 
   holder.GetTestObject(2)->GetDict()->SetNewFor<CPDF_Reference>("Parent",
@@ -205,14 +205,14 @@
   TestHolder holder;
   const uint32_t kDepth = 100;
   for (uint32_t i = 1; i < kDepth; ++i) {
-    holder.AddObject(i, pdfium::MakeUnique<CPDF_Dictionary>(),
+    holder.AddObject(i, pdfium::MakeRetain<CPDF_Dictionary>(),
                      TestHolder::ObjectState::Unavailable);
     // Add ref to next dictionary.
     holder.GetTestObject(i)->GetDict()->SetNewFor<CPDF_Reference>(
         "Child", &holder, i + 1);
   }
   // Add final object
-  holder.AddObject(kDepth, pdfium::MakeUnique<CPDF_Dictionary>(),
+  holder.AddObject(kDepth, pdfium::MakeRetain<CPDF_Dictionary>(),
                    TestHolder::ObjectState::Unavailable);
 
   CPDF_ObjectAvail avail(holder.GetValidator(), &holder, 1);
@@ -226,7 +226,7 @@
 
 TEST(CPDF_ObjectAvailTest, NotExcludeRoot) {
   TestHolder holder;
-  holder.AddObject(1, pdfium::MakeUnique<CPDF_Dictionary>(),
+  holder.AddObject(1, pdfium::MakeRetain<CPDF_Dictionary>(),
                    TestHolder::ObjectState::Available);
   CPDF_ObjectAvailFailOnExclude avail(holder.GetValidator(), &holder, 1);
   EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail());
@@ -234,9 +234,9 @@
 
 TEST(CPDF_ObjectAvailTest, NotExcludeReferedRoot) {
   TestHolder holder;
-  holder.AddObject(1, pdfium::MakeUnique<CPDF_Reference>(&holder, 2),
+  holder.AddObject(1, pdfium::MakeRetain<CPDF_Reference>(&holder, 2),
                    TestHolder::ObjectState::Available);
-  holder.AddObject(2, pdfium::MakeUnique<CPDF_Dictionary>(),
+  holder.AddObject(2, pdfium::MakeRetain<CPDF_Dictionary>(),
                    TestHolder::ObjectState::Available);
   CPDF_ObjectAvailFailOnExclude avail(holder.GetValidator(), &holder, 1);
   EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail());
@@ -244,18 +244,18 @@
 
 TEST(CPDF_ObjectAvailTest, Exclude) {
   TestHolder holder;
-  holder.AddObject(1, pdfium::MakeUnique<CPDF_Dictionary>(),
+  holder.AddObject(1, pdfium::MakeRetain<CPDF_Dictionary>(),
                    TestHolder::ObjectState::Available);
   holder.GetTestObject(1)->GetDict()->SetNewFor<CPDF_Reference>("ArrayRef",
                                                                 &holder, 2);
-  holder.AddObject(2, pdfium::MakeUnique<CPDF_Array>(),
+  holder.AddObject(2, pdfium::MakeRetain<CPDF_Array>(),
                    TestHolder::ObjectState::Available);
   holder.GetTestObject(2)->AsArray()->AddNew<CPDF_Reference>(&holder, 2);
 
   // Add string, which is refered by array item. It is should not be checked.
   holder.AddObject(
       3,
-      pdfium::MakeUnique<CPDF_String>(nullptr, "Not available string", false),
+      pdfium::MakeRetain<CPDF_String>(nullptr, "Not available string", false),
       TestHolder::ObjectState::Unavailable);
   CPDF_ObjectAvailExcludeArray avail(holder.GetValidator(), &holder, 1);
   EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail());
@@ -263,18 +263,18 @@
 
 TEST(CPDF_ObjectAvailTest, ReadErrorOnExclude) {
   TestHolder holder;
-  holder.AddObject(1, pdfium::MakeUnique<CPDF_Dictionary>(),
+  holder.AddObject(1, pdfium::MakeRetain<CPDF_Dictionary>(),
                    TestHolder::ObjectState::Available);
   holder.GetTestObject(1)->GetDict()->SetNewFor<CPDF_Reference>("DictRef",
                                                                 &holder, 2);
-  holder.AddObject(2, pdfium::MakeUnique<CPDF_Dictionary>(),
+  holder.AddObject(2, pdfium::MakeRetain<CPDF_Dictionary>(),
                    TestHolder::ObjectState::Available);
 
   holder.GetTestObject(2)->GetDict()->SetNewFor<CPDF_Reference>("Type", &holder,
                                                                 3);
   // The value of "Type" key is not available at start
   holder.AddObject(
-      3, pdfium::MakeUnique<CPDF_String>(nullptr, "Exclude me", false),
+      3, pdfium::MakeRetain<CPDF_String>(nullptr, "Exclude me", false),
       TestHolder::ObjectState::Unavailable);
 
   holder.GetTestObject(2)->GetDict()->SetNewFor<CPDF_Reference>("OtherData",
@@ -283,7 +283,7 @@
   // checked, because the dictionary with it, should be skipped.
   holder.AddObject(
       4,
-      pdfium::MakeUnique<CPDF_String>(nullptr, "Not available string", false),
+      pdfium::MakeRetain<CPDF_String>(nullptr, "Not available string", false),
       TestHolder::ObjectState::Unavailable);
 
   CPDF_ObjectAvailExcludeTypeKey avail(holder.GetValidator(), &holder, 1);
@@ -301,7 +301,7 @@
 
 TEST(CPDF_ObjectAvailTest, IgnoreNotExistsObject) {
   TestHolder holder;
-  holder.AddObject(1, pdfium::MakeUnique<CPDF_Dictionary>(),
+  holder.AddObject(1, pdfium::MakeRetain<CPDF_Dictionary>(),
                    TestHolder::ObjectState::Available);
   holder.GetTestObject(1)->GetDict()->SetNewFor<CPDF_Reference>(
       "NotExistsObjRef", &holder, 2);
@@ -313,7 +313,7 @@
 
 TEST(CPDF_ObjectAvailTest, CheckTwice) {
   TestHolder holder;
-  holder.AddObject(1, pdfium::MakeUnique<CPDF_String>(nullptr, "string", false),
+  holder.AddObject(1, pdfium::MakeRetain<CPDF_String>(nullptr, "string", false),
                    TestHolder::ObjectState::Unavailable);
 
   CPDF_ObjectAvail avail(holder.GetValidator(), &holder, 1);
@@ -325,7 +325,7 @@
 
 TEST(CPDF_ObjectAvailTest, SelfReferedInlinedObject) {
   TestHolder holder;
-  holder.AddObject(1, pdfium::MakeUnique<CPDF_Dictionary>(),
+  holder.AddObject(1, pdfium::MakeRetain<CPDF_Dictionary>(),
                    TestHolder::ObjectState::Available);
 
   holder.GetTestObject(1)->GetDict()->SetNewFor<CPDF_Reference>("Data", &holder,
@@ -335,7 +335,7 @@
 
   root->SetNewFor<CPDF_Reference>("Self", &holder, 1);
 
-  holder.AddObject(2, pdfium::MakeUnique<CPDF_String>(nullptr, "Data", false),
+  holder.AddObject(2, pdfium::MakeRetain<CPDF_String>(nullptr, "Data", false),
                    TestHolder::ObjectState::Unavailable);
 
   CPDF_ObjectAvail avail(holder.GetValidator(), &holder, root);
diff --git a/core/fpdfapi/parser/cpdf_object_stream.cpp b/core/fpdfapi/parser/cpdf_object_stream.cpp
index 3f974ee..1fc0e83 100644
--- a/core/fpdfapi/parser/cpdf_object_stream.cpp
+++ b/core/fpdfapi/parser/cpdf_object_stream.cpp
@@ -76,15 +76,14 @@
   return pdfium::ContainsKey(objects_offsets_, obj_number);
 }
 
-std::unique_ptr<CPDF_Object> CPDF_ObjectStream::ParseObject(
+RetainPtr<CPDF_Object> CPDF_ObjectStream::ParseObject(
     CPDF_IndirectObjectHolder* pObjList,
     uint32_t obj_number) const {
   const auto it = objects_offsets_.find(obj_number);
   if (it == objects_offsets_.end())
     return nullptr;
 
-  std::unique_ptr<CPDF_Object> result =
-      ParseObjectAtOffset(pObjList, it->second);
+  RetainPtr<CPDF_Object> result = ParseObjectAtOffset(pObjList, it->second);
   if (!result)
     return nullptr;
 
@@ -116,7 +115,7 @@
   }
 }
 
-std::unique_ptr<CPDF_Object> CPDF_ObjectStream::ParseObjectAtOffset(
+RetainPtr<CPDF_Object> CPDF_ObjectStream::ParseObjectAtOffset(
     CPDF_IndirectObjectHolder* pObjList,
     uint32_t object_offset) const {
   FX_SAFE_FILESIZE offset_in_stream = first_object_offset_;
diff --git a/core/fpdfapi/parser/cpdf_object_stream.h b/core/fpdfapi/parser/cpdf_object_stream.h
index b872462..2fa1634 100644
--- a/core/fpdfapi/parser/cpdf_object_stream.h
+++ b/core/fpdfapi/parser/cpdf_object_stream.h
@@ -29,8 +29,8 @@
   uint32_t extends_obj_num() const { return extends_obj_num_; }
 
   bool HasObject(uint32_t obj_number) const;
-  std::unique_ptr<CPDF_Object> ParseObject(CPDF_IndirectObjectHolder* pObjList,
-                                           uint32_t obj_number) const;
+  RetainPtr<CPDF_Object> ParseObject(CPDF_IndirectObjectHolder* pObjList,
+                                     uint32_t obj_number) const;
   const std::map<uint32_t, uint32_t>& objects_offsets() const {
     return objects_offsets_;
   }
@@ -39,7 +39,7 @@
   explicit CPDF_ObjectStream(const CPDF_Stream* stream);
 
   void Init(const CPDF_Stream* stream);
-  std::unique_ptr<CPDF_Object> ParseObjectAtOffset(
+  RetainPtr<CPDF_Object> ParseObjectAtOffset(
       CPDF_IndirectObjectHolder* pObjList,
       uint32_t object_offset) const;
 
diff --git a/core/fpdfapi/parser/cpdf_object_unittest.cpp b/core/fpdfapi/parser/cpdf_object_unittest.cpp
index 0b69096..cb18a1c 100644
--- a/core/fpdfapi/parser/cpdf_object_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_object_unittest.cpp
@@ -49,22 +49,23 @@
   void SetUp() override {
     // Initialize different kinds of objects.
     // Boolean objects.
-    CPDF_Boolean* boolean_false_obj = new CPDF_Boolean(false);
-    CPDF_Boolean* boolean_true_obj = new CPDF_Boolean(true);
+    auto boolean_false_obj = pdfium::MakeRetain<CPDF_Boolean>(false);
+    auto boolean_true_obj = pdfium::MakeRetain<CPDF_Boolean>(true);
     // Number objects.
-    CPDF_Number* number_int_obj = new CPDF_Number(1245);
-    CPDF_Number* number_float_obj = new CPDF_Number(9.00345f);
+    auto number_int_obj = pdfium::MakeRetain<CPDF_Number>(1245);
+    auto number_float_obj = pdfium::MakeRetain<CPDF_Number>(9.00345f);
     // String objects.
-    CPDF_String* str_reg_obj = new CPDF_String(nullptr, L"A simple test");
-    CPDF_String* str_spec_obj = new CPDF_String(nullptr, L"\t\n");
+    auto str_reg_obj =
+        pdfium::MakeRetain<CPDF_String>(nullptr, L"A simple test");
+    auto str_spec_obj = pdfium::MakeRetain<CPDF_String>(nullptr, L"\t\n");
     // Name object.
-    CPDF_Name* name_obj = new CPDF_Name(nullptr, "space");
+    auto name_obj = pdfium::MakeRetain<CPDF_Name>(nullptr, "space");
     // Array object.
-    m_ArrayObj = new CPDF_Array;
+    m_ArrayObj = pdfium::MakeRetain<CPDF_Array>();
     m_ArrayObj->InsertNewAt<CPDF_Number>(0, 8902);
     m_ArrayObj->InsertNewAt<CPDF_Name>(1, "address");
     // Dictionary object.
-    m_DictObj = new CPDF_Dictionary();
+    m_DictObj = pdfium::MakeRetain<CPDF_Dictionary>();
     m_DictObj->SetNewFor<CPDF_Boolean>("bool", false);
     m_DictObj->SetNewFor<CPDF_Number>("num", 0.23f);
     // Stream object.
@@ -72,19 +73,20 @@
     size_t buf_len = FX_ArraySize(content);
     std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_Alloc(uint8_t, buf_len));
     memcpy(buf.get(), content, buf_len);
-    auto pNewDict = pdfium::MakeUnique<CPDF_Dictionary>();
-    m_StreamDictObj = pNewDict.get();
+    auto pNewDict = pdfium::MakeRetain<CPDF_Dictionary>();
+    m_StreamDictObj = pNewDict;
     m_StreamDictObj->SetNewFor<CPDF_String>("key1", L" test dict");
     m_StreamDictObj->SetNewFor<CPDF_Number>("key2", -1);
-    CPDF_Stream* stream_obj =
-        new CPDF_Stream(std::move(buf), buf_len, std::move(pNewDict));
+    auto stream_obj = pdfium::MakeRetain<CPDF_Stream>(std::move(buf), buf_len,
+                                                      std::move(pNewDict));
     // Null Object.
-    CPDF_Null* null_obj = new CPDF_Null;
+    auto null_obj = pdfium::MakeRetain<CPDF_Null>();
     // All direct objects.
-    CPDF_Object* objs[] = {boolean_false_obj, boolean_true_obj, number_int_obj,
-                           number_float_obj,  str_reg_obj,      str_spec_obj,
-                           name_obj,          m_ArrayObj.Get(), m_DictObj.Get(),
-                           stream_obj,        null_obj};
+    CPDF_Object* objs[] = {
+        boolean_false_obj.Get(), boolean_true_obj.Get(), number_int_obj.Get(),
+        number_float_obj.Get(),  str_reg_obj.Get(),      str_spec_obj.Get(),
+        name_obj.Get(),          m_ArrayObj.Get(),       m_DictObj.Get(),
+        stream_obj.Get(),        null_obj.Get()};
     m_DirectObjTypes = {
         CPDF_Object::kBoolean, CPDF_Object::kBoolean, CPDF_Object::kNumber,
         CPDF_Object::kNumber,  CPDF_Object::kString,  CPDF_Object::kString,
@@ -103,8 +105,8 @@
                       m_ObjHolder->AddIndirectObject(m_DictObj->Clone()),
                       m_ObjHolder->AddIndirectObject(stream_obj->Clone())};
     for (CPDF_Object* pObj : m_IndirectObjs) {
-      m_RefObjs.emplace_back(
-          new CPDF_Reference(m_ObjHolder.get(), pObj->GetObjNum()));
+      m_RefObjs.emplace_back(pdfium::MakeRetain<CPDF_Reference>(
+          m_ObjHolder.get(), pObj->GetObjNum()));
     }
   }
 
@@ -140,7 +142,7 @@
           return false;
         CPDF_DictionaryLocker locker1(dict1);
         for (const auto& item : locker1) {
-          if (!Equal(item.second.get(), dict2->GetObjectFor(item.first)))
+          if (!Equal(item.second.Get(), dict2->GetObjectFor(item.first)))
             return false;
         }
         return true;
@@ -179,12 +181,12 @@
   // m_ObjHolder needs to be declared first and destructed last since it also
   // refers to some objects in m_DirectObjs.
   std::unique_ptr<CPDF_IndirectObjectHolder> m_ObjHolder;
-  std::vector<std::unique_ptr<CPDF_Object>> m_DirectObjs;
+  std::vector<RetainPtr<CPDF_Object>> m_DirectObjs;
   std::vector<int> m_DirectObjTypes;
-  std::vector<std::unique_ptr<CPDF_Object>> m_RefObjs;
-  UnownedPtr<CPDF_Dictionary> m_DictObj;
-  UnownedPtr<CPDF_Dictionary> m_StreamDictObj;
-  UnownedPtr<CPDF_Array> m_ArrayObj;
+  std::vector<RetainPtr<CPDF_Object>> m_RefObjs;
+  RetainPtr<CPDF_Dictionary> m_DictObj;
+  RetainPtr<CPDF_Dictionary> m_StreamDictObj;
+  RetainPtr<CPDF_Array> m_ArrayObj;
   std::vector<CPDF_Object*> m_IndirectObjs;
 };
 
@@ -282,14 +284,14 @@
 TEST_F(PDFObjectsTest, Clone) {
   // Check for direct objects.
   for (size_t i = 0; i < m_DirectObjs.size(); ++i) {
-    std::unique_ptr<CPDF_Object> obj = m_DirectObjs[i]->Clone();
-    EXPECT_TRUE(Equal(m_DirectObjs[i].get(), obj.get()));
+    RetainPtr<CPDF_Object> obj = m_DirectObjs[i]->Clone();
+    EXPECT_TRUE(Equal(m_DirectObjs[i].Get(), obj.Get()));
   }
 
   // Check indirect references.
   for (const auto& it : m_RefObjs) {
-    std::unique_ptr<CPDF_Object> obj = it->Clone();
-    EXPECT_TRUE(Equal(it.get(), obj.get()));
+    RetainPtr<CPDF_Object> obj = it->Clone();
+    EXPECT_TRUE(Equal(it.Get(), obj.Get()));
   }
 }
 
@@ -306,7 +308,7 @@
 TEST_F(PDFObjectsTest, GetDirect) {
   // Check for direct objects.
   for (size_t i = 0; i < m_DirectObjs.size(); ++i)
-    EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->GetDirect());
+    EXPECT_EQ(m_DirectObjs[i].Get(), m_DirectObjs[i]->GetDirect());
 
   // Check indirect references.
   for (size_t i = 0; i < m_RefObjs.size(); ++i)
@@ -330,7 +332,7 @@
   for (size_t i = 0; i < m_DirectObjs.size(); ++i) {
     if (m_DirectObjTypes[i] == CPDF_Object::kArray) {
       EXPECT_TRUE(m_DirectObjs[i]->IsArray());
-      EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsArray());
+      EXPECT_EQ(m_DirectObjs[i].Get(), m_DirectObjs[i]->AsArray());
     } else {
       EXPECT_FALSE(m_DirectObjs[i]->IsArray());
       EXPECT_EQ(nullptr, m_DirectObjs[i]->AsArray());
@@ -338,7 +340,7 @@
 
     if (m_DirectObjTypes[i] == CPDF_Object::kBoolean) {
       EXPECT_TRUE(m_DirectObjs[i]->IsBoolean());
-      EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsBoolean());
+      EXPECT_EQ(m_DirectObjs[i].Get(), m_DirectObjs[i]->AsBoolean());
     } else {
       EXPECT_FALSE(m_DirectObjs[i]->IsBoolean());
       EXPECT_EQ(nullptr, m_DirectObjs[i]->AsBoolean());
@@ -346,7 +348,7 @@
 
     if (m_DirectObjTypes[i] == CPDF_Object::kName) {
       EXPECT_TRUE(m_DirectObjs[i]->IsName());
-      EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsName());
+      EXPECT_EQ(m_DirectObjs[i].Get(), m_DirectObjs[i]->AsName());
     } else {
       EXPECT_FALSE(m_DirectObjs[i]->IsName());
       EXPECT_EQ(nullptr, m_DirectObjs[i]->AsName());
@@ -354,7 +356,7 @@
 
     if (m_DirectObjTypes[i] == CPDF_Object::kNumber) {
       EXPECT_TRUE(m_DirectObjs[i]->IsNumber());
-      EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsNumber());
+      EXPECT_EQ(m_DirectObjs[i].Get(), m_DirectObjs[i]->AsNumber());
     } else {
       EXPECT_FALSE(m_DirectObjs[i]->IsNumber());
       EXPECT_EQ(nullptr, m_DirectObjs[i]->AsNumber());
@@ -362,7 +364,7 @@
 
     if (m_DirectObjTypes[i] == CPDF_Object::kString) {
       EXPECT_TRUE(m_DirectObjs[i]->IsString());
-      EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsString());
+      EXPECT_EQ(m_DirectObjs[i].Get(), m_DirectObjs[i]->AsString());
     } else {
       EXPECT_FALSE(m_DirectObjs[i]->IsString());
       EXPECT_EQ(nullptr, m_DirectObjs[i]->AsString());
@@ -370,7 +372,7 @@
 
     if (m_DirectObjTypes[i] == CPDF_Object::kDictionary) {
       EXPECT_TRUE(m_DirectObjs[i]->IsDictionary());
-      EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsDictionary());
+      EXPECT_EQ(m_DirectObjs[i].Get(), m_DirectObjs[i]->AsDictionary());
     } else {
       EXPECT_FALSE(m_DirectObjs[i]->IsDictionary());
       EXPECT_EQ(nullptr, m_DirectObjs[i]->AsDictionary());
@@ -378,7 +380,7 @@
 
     if (m_DirectObjTypes[i] == CPDF_Object::kStream) {
       EXPECT_TRUE(m_DirectObjs[i]->IsStream());
-      EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsStream());
+      EXPECT_EQ(m_DirectObjs[i].Get(), m_DirectObjs[i]->AsStream());
     } else {
       EXPECT_FALSE(m_DirectObjs[i]->IsStream());
       EXPECT_EQ(nullptr, m_DirectObjs[i]->AsStream());
@@ -390,12 +392,12 @@
   // Check indirect references.
   for (size_t i = 0; i < m_RefObjs.size(); ++i) {
     EXPECT_TRUE(m_RefObjs[i]->IsReference());
-    EXPECT_EQ(m_RefObjs[i].get(), m_RefObjs[i]->AsReference());
+    EXPECT_EQ(m_RefObjs[i].Get(), m_RefObjs[i]->AsReference());
   }
 }
 
 TEST_F(PDFObjectsTest, MakeReferenceGeneric) {
-  auto original_obj = pdfium::MakeUnique<CPDF_Null>();
+  auto original_obj = pdfium::MakeRetain<CPDF_Null>();
   original_obj->SetObjNum(42);
   ASSERT_FALSE(original_obj->IsInline());
 
@@ -403,7 +405,7 @@
 
   ASSERT_TRUE(ref_obj->IsReference());
   EXPECT_EQ(original_obj->GetObjNum(),
-            ToReference(ref_obj.get())->GetRefObjNum());
+            ToReference(ref_obj.Get())->GetRefObjNum());
 }
 
 TEST(PDFArrayTest, GetMatrix) {
@@ -412,7 +414,7 @@
                       {2.3f, 4.05f, 3, -2, -3, 0.0f},
                       {0.05f, 0.1f, 0.56f, 0.67f, 1.34f, 99.9f}};
   for (size_t i = 0; i < FX_ArraySize(elems); ++i) {
-    auto arr = pdfium::MakeUnique<CPDF_Array>();
+    auto arr = pdfium::MakeRetain<CPDF_Array>();
     CFX_Matrix matrix(elems[i][0], elems[i][1], elems[i][2], elems[i][3],
                       elems[i][4], elems[i][5]);
     for (size_t j = 0; j < 6; ++j)
@@ -433,7 +435,7 @@
                       {2.3f, 4.05f, -3, 0.0f},
                       {0.05f, 0.1f, 1.34f, 99.9f}};
   for (size_t i = 0; i < FX_ArraySize(elems); ++i) {
-    auto arr = pdfium::MakeUnique<CPDF_Array>();
+    auto arr = pdfium::MakeRetain<CPDF_Array>();
     CFX_FloatRect rect(elems[i]);
     for (size_t j = 0; j < 4; ++j)
       arr->AddNew<CPDF_Number>(elems[i][j]);
@@ -449,11 +451,11 @@
   {
     // Boolean array.
     const bool vals[] = {true, false, false, true, true};
-    auto arr = pdfium::MakeUnique<CPDF_Array>();
+    auto arr = pdfium::MakeRetain<CPDF_Array>();
     for (size_t i = 0; i < FX_ArraySize(vals); ++i)
       arr->InsertNewAt<CPDF_Boolean>(i, vals[i]);
     for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
-      TestArrayAccessors(arr.get(), i,                // Array and index.
+      TestArrayAccessors(arr.Get(), i,                // Array and index.
                          vals[i] ? "true" : "false",  // String value.
                          nullptr,                     // Const string value.
                          vals[i] ? 1 : 0,             // Integer value.
@@ -466,12 +468,12 @@
   {
     // Integer array.
     const int vals[] = {10, 0, -345, 2089345456, -1000000000, 567, 93658767};
-    auto arr = pdfium::MakeUnique<CPDF_Array>();
+    auto arr = pdfium::MakeRetain<CPDF_Array>();
     for (size_t i = 0; i < FX_ArraySize(vals); ++i)
       arr->InsertNewAt<CPDF_Number>(i, vals[i]);
     for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
       char buf[33];
-      TestArrayAccessors(arr.get(), i,                  // Array and index.
+      TestArrayAccessors(arr.Get(), i,                  // Array and index.
                          FXSYS_itoa(vals[i], buf, 10),  // String value.
                          nullptr,                       // Const string value.
                          vals[i],                       // Integer value.
@@ -487,11 +489,11 @@
                           897.34f, -2.5f, -1.0f, -345.0f, -0.0f};
     const char* const expected_str[] = {
         "0", "0", "10", "10", "0.0345", "897.34", "-2.5", "-1", "-345", "0"};
-    auto arr = pdfium::MakeUnique<CPDF_Array>();
+    auto arr = pdfium::MakeRetain<CPDF_Array>();
     for (size_t i = 0; i < FX_ArraySize(vals); ++i)
       arr->InsertNewAt<CPDF_Number>(i, vals[i]);
     for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
-      TestArrayAccessors(arr.get(), i,     // Array and index.
+      TestArrayAccessors(arr.Get(), i,     // Array and index.
                          expected_str[i],  // String value.
                          nullptr,          // Const string value.
                          vals[i],          // Integer value.
@@ -505,14 +507,14 @@
     // String and name array
     const char* const vals[] = {"this", "adsde$%^", "\r\t",           "\"012",
                                 ".",    "EYREW",    "It is a joke :)"};
-    auto string_array = pdfium::MakeUnique<CPDF_Array>();
-    auto name_array = pdfium::MakeUnique<CPDF_Array>();
+    auto string_array = pdfium::MakeRetain<CPDF_Array>();
+    auto name_array = pdfium::MakeRetain<CPDF_Array>();
     for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
       string_array->InsertNewAt<CPDF_String>(i, vals[i], false);
       name_array->InsertNewAt<CPDF_Name>(i, vals[i]);
     }
     for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
-      TestArrayAccessors(string_array.get(), i,  // Array and index.
+      TestArrayAccessors(string_array.Get(), i,  // Array and index.
                          vals[i],                // String value.
                          vals[i],                // Const string value.
                          0,                      // Integer value.
@@ -520,7 +522,7 @@
                          nullptr,                // Array value.
                          nullptr,                // Dictionary value.
                          nullptr);               // Stream value.
-      TestArrayAccessors(name_array.get(), i,    // Array and index.
+      TestArrayAccessors(name_array.Get(), i,    // Array and index.
                          vals[i],                // String value.
                          vals[i],                // Const string value.
                          0,                      // Integer value.
@@ -532,11 +534,11 @@
   }
   {
     // Null element array.
-    auto arr = pdfium::MakeUnique<CPDF_Array>();
+    auto arr = pdfium::MakeRetain<CPDF_Array>();
     for (size_t i = 0; i < 3; ++i)
       arr->InsertNewAt<CPDF_Null>(i);
     for (size_t i = 0; i < 3; ++i) {
-      TestArrayAccessors(arr.get(), i,  // Array and index.
+      TestArrayAccessors(arr.Get(), i,  // Array and index.
                          "",            // String value.
                          nullptr,       // Const string value.
                          0,             // Integer value.
@@ -549,7 +551,7 @@
   {
     // Array of array.
     CPDF_Array* vals[3];
-    auto arr = pdfium::MakeUnique<CPDF_Array>();
+    auto arr = pdfium::MakeRetain<CPDF_Array>();
     for (size_t i = 0; i < 3; ++i) {
       vals[i] = arr->AddNew<CPDF_Array>();
       for (size_t j = 0; j < 3; ++j) {
@@ -558,7 +560,7 @@
       }
     }
     for (size_t i = 0; i < 3; ++i) {
-      TestArrayAccessors(arr.get(), i,  // Array and index.
+      TestArrayAccessors(arr.Get(), i,  // Array and index.
                          "",            // String value.
                          nullptr,       // Const string value.
                          0,             // Integer value.
@@ -571,7 +573,7 @@
   {
     // Dictionary array.
     CPDF_Dictionary* vals[3];
-    auto arr = pdfium::MakeUnique<CPDF_Array>();
+    auto arr = pdfium::MakeRetain<CPDF_Array>();
     for (size_t i = 0; i < 3; ++i) {
       vals[i] = arr->AddNew<CPDF_Dictionary>();
       for (size_t j = 0; j < 3; ++j) {
@@ -583,7 +585,7 @@
       }
     }
     for (size_t i = 0; i < 3; ++i) {
-      TestArrayAccessors(arr.get(), i,  // Array and index.
+      TestArrayAccessors(arr.Get(), i,  // Array and index.
                          "",            // String value.
                          nullptr,       // Const string value.
                          0,             // Integer value.
@@ -595,11 +597,11 @@
   }
   {
     // Stream array.
-    CPDF_Dictionary* vals[3];
+    RetainPtr<CPDF_Dictionary> vals[3];
     CPDF_Stream* stream_vals[3];
-    auto arr = pdfium::MakeUnique<CPDF_Array>();
+    auto arr = pdfium::MakeRetain<CPDF_Array>();
     for (size_t i = 0; i < 3; ++i) {
-      vals[i] = new CPDF_Dictionary();
+      vals[i] = pdfium::MakeRetain<CPDF_Dictionary>();
       for (size_t j = 0; j < 3; ++j) {
         std::string key("key");
         char buf[33];
@@ -612,23 +614,23 @@
       std::unique_ptr<uint8_t, FxFreeDeleter> data(
           FX_Alloc(uint8_t, data_size));
       memcpy(data.get(), content, data_size);
-      stream_vals[i] = arr->AddNew<CPDF_Stream>(std::move(data), data_size,
-                                                pdfium::WrapUnique(vals[i]));
+      stream_vals[i] =
+          arr->AddNew<CPDF_Stream>(std::move(data), data_size, vals[i]);
     }
     for (size_t i = 0; i < 3; ++i) {
-      TestArrayAccessors(arr.get(), i,     // Array and index.
+      TestArrayAccessors(arr.Get(), i,     // Array and index.
                          "",               // String value.
                          nullptr,          // Const string value.
                          0,                // Integer value.
                          0,                // Float value.
                          nullptr,          // Array value.
-                         vals[i],          // Dictionary value.
+                         vals[i].Get(),    // Dictionary value.
                          stream_vals[i]);  // Stream value.
     }
   }
   {
     // Mixed array.
-    auto arr = pdfium::MakeUnique<CPDF_Array>();
+    auto arr = pdfium::MakeRetain<CPDF_Array>();
     arr->InsertNewAt<CPDF_Boolean>(0, true);
     arr->InsertNewAt<CPDF_Boolean>(1, false);
     arr->InsertNewAt<CPDF_Number>(2, 0);
@@ -649,7 +651,7 @@
     dict_val->SetNewFor<CPDF_String>("key1", "Linda", false);
     dict_val->SetNewFor<CPDF_String>("key2", "Zoe", false);
 
-    CPDF_Dictionary* stream_dict = new CPDF_Dictionary();
+    auto stream_dict = pdfium::MakeRetain<CPDF_Dictionary>();
     stream_dict->SetNewFor<CPDF_String>("key1", "John", false);
     stream_dict->SetNewFor<CPDF_String>("key2", "King", false);
     uint8_t data[] = "A stream for test";
@@ -659,7 +661,7 @@
     std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_Alloc(uint8_t, buf_size));
     memcpy(buf.get(), data, buf_size);
     CPDF_Stream* stream_val = arr->InsertNewAt<CPDF_Stream>(
-        13, std::move(buf), buf_size, pdfium::WrapUnique(stream_dict));
+        13, std::move(buf), buf_size, stream_dict);
     const char* const expected_str[] = {
         "true",          "false", "0",    "-1234", "2345", "0.05", "",
         "It is a test!", "NAME",  "test", "",      "",     "",     ""};
@@ -693,7 +695,7 @@
 TEST(PDFArrayTest, AddNumber) {
   float vals[] = {1.0f,         -1.0f, 0,    0.456734f,
                   12345.54321f, 0.5f,  1000, 0.000045f};
-  auto arr = pdfium::MakeUnique<CPDF_Array>();
+  auto arr = pdfium::MakeRetain<CPDF_Array>();
   for (size_t i = 0; i < FX_ArraySize(vals); ++i)
     arr->AddNew<CPDF_Number>(vals[i]);
   for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
@@ -704,7 +706,7 @@
 
 TEST(PDFArrayTest, AddInteger) {
   int vals[] = {0, 1, 934435456, 876, 10000, -1, -24354656, -100};
-  auto arr = pdfium::MakeUnique<CPDF_Array>();
+  auto arr = pdfium::MakeRetain<CPDF_Array>();
   for (size_t i = 0; i < FX_ArraySize(vals); ++i)
     arr->AddNew<CPDF_Number>(vals[i]);
   for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
@@ -717,8 +719,8 @@
   static constexpr const char* vals[] = {
       "",        "a", "ehjhRIOYTTFdfcdnv",  "122323",
       "$#%^&**", " ", "This is a test.\r\n"};
-  auto string_array = pdfium::MakeUnique<CPDF_Array>();
-  auto name_array = pdfium::MakeUnique<CPDF_Array>();
+  auto string_array = pdfium::MakeRetain<CPDF_Array>();
+  auto name_array = pdfium::MakeRetain<CPDF_Array>();
   for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
     string_array->AddNew<CPDF_String>(vals[i], false);
     name_array->AddNew<CPDF_Name>(vals[i]);
@@ -733,22 +735,22 @@
 
 TEST(PDFArrayTest, AddReferenceAndGetObjectAt) {
   auto holder = pdfium::MakeUnique<CPDF_IndirectObjectHolder>();
-  CPDF_Boolean* boolean_obj = new CPDF_Boolean(true);
-  CPDF_Number* int_obj = new CPDF_Number(-1234);
-  CPDF_Number* float_obj = new CPDF_Number(2345.089f);
-  CPDF_String* str_obj =
-      new CPDF_String(nullptr, "Adsfdsf 343434 %&&*\n", false);
-  CPDF_Name* name_obj = new CPDF_Name(nullptr, "Title:");
-  CPDF_Null* null_obj = new CPDF_Null();
-  CPDF_Object* indirect_objs[] = {boolean_obj, int_obj,  float_obj,
-                                  str_obj,     name_obj, null_obj};
+  auto boolean_obj = pdfium::MakeRetain<CPDF_Boolean>(true);
+  auto int_obj = pdfium::MakeRetain<CPDF_Number>(-1234);
+  auto float_obj = pdfium::MakeRetain<CPDF_Number>(2345.089f);
+  auto str_obj =
+      pdfium::MakeRetain<CPDF_String>(nullptr, "Adsfdsf 343434 %&&*\n", false);
+  auto name_obj = pdfium::MakeRetain<CPDF_Name>(nullptr, "Title:");
+  auto null_obj = pdfium::MakeRetain<CPDF_Null>();
+  RetainPtr<CPDF_Object> indirect_objs[] = {boolean_obj, int_obj,  float_obj,
+                                            str_obj,     name_obj, null_obj};
   unsigned int obj_nums[] = {2, 4, 7, 2345, 799887, 1};
-  auto arr = pdfium::MakeUnique<CPDF_Array>();
-  auto arr1 = pdfium::MakeUnique<CPDF_Array>();
+  auto arr = pdfium::MakeRetain<CPDF_Array>();
+  auto arr1 = pdfium::MakeRetain<CPDF_Array>();
   // Create two arrays of references by different AddReference() APIs.
   for (size_t i = 0; i < FX_ArraySize(indirect_objs); ++i) {
-    holder->ReplaceIndirectObjectIfHigherGeneration(
-        obj_nums[i], pdfium::WrapUnique<CPDF_Object>(indirect_objs[i]));
+    holder->ReplaceIndirectObjectIfHigherGeneration(obj_nums[i],
+                                                    indirect_objs[i]);
     arr->AddNew<CPDF_Reference>(holder.get(), obj_nums[i]);
     arr1->AddNew<CPDF_Reference>(holder.get(), indirect_objs[i]->GetObjNum());
   }
@@ -769,19 +771,18 @@
 
 TEST(PDFArrayTest, CloneDirectObject) {
   CPDF_IndirectObjectHolder objects_holder;
-  auto array = pdfium::MakeUnique<CPDF_Array>();
+  auto array = pdfium::MakeRetain<CPDF_Array>();
   array->AddNew<CPDF_Reference>(&objects_holder, 1234);
   ASSERT_EQ(1U, array->size());
   CPDF_Object* obj = array->GetObjectAt(0);
   ASSERT_TRUE(obj);
   EXPECT_TRUE(obj->IsReference());
 
-  std::unique_ptr<CPDF_Object> cloned_array_object = array->CloneDirectObject();
+  RetainPtr<CPDF_Object> cloned_array_object = array->CloneDirectObject();
   ASSERT_TRUE(cloned_array_object);
   ASSERT_TRUE(cloned_array_object->IsArray());
 
-  std::unique_ptr<CPDF_Array> cloned_array =
-      ToArray(std::move(cloned_array_object));
+  RetainPtr<CPDF_Array> cloned_array = ToArray(std::move(cloned_array_object));
   ASSERT_EQ(0U, cloned_array->size());
   CPDF_Object* cloned_obj = cloned_array->GetObjectAt(0);
   EXPECT_FALSE(cloned_obj);
@@ -789,7 +790,7 @@
 
 TEST(PDFArrayTest, ConvertIndirect) {
   CPDF_IndirectObjectHolder objects_holder;
-  auto array = pdfium::MakeUnique<CPDF_Array>();
+  auto array = pdfium::MakeRetain<CPDF_Array>();
   CPDF_Object* pObj = array->AddNew<CPDF_Number>(42);
   array->ConvertToIndirectObjectAt(0, &objects_holder);
   CPDF_Object* pRef = array->GetObjectAt(0);
@@ -803,8 +804,8 @@
 
 TEST(PDFStreamTest, SetData) {
   std::vector<uint8_t> data(100);
-  auto stream = pdfium::MakeUnique<CPDF_Stream>();
-  stream->InitStream(data, pdfium::MakeUnique<CPDF_Dictionary>());
+  auto stream = pdfium::MakeRetain<CPDF_Stream>();
+  stream->InitStream(data, pdfium::MakeRetain<CPDF_Dictionary>());
   EXPECT_EQ(static_cast<int>(data.size()),
             stream->GetDict()->GetIntegerFor(pdfium::stream::kLength));
 
@@ -829,8 +830,8 @@
 
 TEST(PDFStreamTest, SetDataAndRemoveFilter) {
   std::vector<uint8_t> data(100);
-  auto stream = pdfium::MakeUnique<CPDF_Stream>();
-  stream->InitStream(data, pdfium::MakeUnique<CPDF_Dictionary>());
+  auto stream = pdfium::MakeRetain<CPDF_Stream>();
+  stream->InitStream(data, pdfium::MakeRetain<CPDF_Dictionary>());
   EXPECT_EQ(static_cast<int>(data.size()),
             stream->GetDict()->GetIntegerFor(pdfium::stream::kLength));
 
@@ -856,8 +857,8 @@
   {
     std::unique_ptr<uint8_t, FxFreeDeleter> data;
     data.reset(FX_Alloc(uint8_t, kBufSize));
-    auto stream = pdfium::MakeUnique<CPDF_Stream>(
-        std::move(data), kBufSize, pdfium::MakeUnique<CPDF_Dictionary>());
+    auto stream = pdfium::MakeRetain<CPDF_Stream>(
+        std::move(data), kBufSize, pdfium::MakeRetain<CPDF_Dictionary>());
     EXPECT_EQ(static_cast<int>(kBufSize),
               stream->GetDict()->GetIntegerFor(pdfium::stream::kLength));
   }
@@ -865,9 +866,9 @@
   {
     std::unique_ptr<uint8_t, FxFreeDeleter> data;
     data.reset(FX_Alloc(uint8_t, kBufSize));
-    auto dict = pdfium::MakeUnique<CPDF_Dictionary>();
+    auto dict = pdfium::MakeRetain<CPDF_Dictionary>();
     dict->SetNewFor<CPDF_Number>(pdfium::stream::kLength, 30000);
-    auto stream = pdfium::MakeUnique<CPDF_Stream>(std::move(data), kBufSize,
+    auto stream = pdfium::MakeRetain<CPDF_Stream>(std::move(data), kBufSize,
                                                   std::move(dict));
     EXPECT_EQ(static_cast<int>(kBufSize),
               stream->GetDict()->GetIntegerFor(pdfium::stream::kLength));
@@ -876,18 +877,18 @@
 
 TEST(PDFDictionaryTest, CloneDirectObject) {
   CPDF_IndirectObjectHolder objects_holder;
-  auto dict = pdfium::MakeUnique<CPDF_Dictionary>();
+  auto dict = pdfium::MakeRetain<CPDF_Dictionary>();
   dict->SetNewFor<CPDF_Reference>("foo", &objects_holder, 1234);
   ASSERT_EQ(1U, dict->size());
   CPDF_Object* obj = dict->GetObjectFor("foo");
   ASSERT_TRUE(obj);
   EXPECT_TRUE(obj->IsReference());
 
-  std::unique_ptr<CPDF_Object> cloned_dict_object = dict->CloneDirectObject();
+  RetainPtr<CPDF_Object> cloned_dict_object = dict->CloneDirectObject();
   ASSERT_TRUE(cloned_dict_object);
   ASSERT_TRUE(cloned_dict_object->IsDictionary());
 
-  std::unique_ptr<CPDF_Dictionary> cloned_dict =
+  RetainPtr<CPDF_Dictionary> cloned_dict =
       ToDictionary(std::move(cloned_dict_object));
   ASSERT_EQ(0U, cloned_dict->size());
   CPDF_Object* cloned_obj = cloned_dict->GetObjectFor("foo");
@@ -896,14 +897,12 @@
 
 TEST(PDFObjectTest, CloneCheckLoop) {
   {
-    // Create a dictionary/array pair with a reference loop. It takes
-    // some work to do this nowadays, in particular we need the
-    // anti-pattern pdfium::WrapUnique(arr.get()).
-    auto arr_obj = pdfium::MakeUnique<CPDF_Array>();
+    // Create a dictionary/array pair with a reference loop.
+    auto arr_obj = pdfium::MakeRetain<CPDF_Array>();
     CPDF_Dictionary* dict_obj = arr_obj->InsertNewAt<CPDF_Dictionary>(0);
-    dict_obj->SetFor("arr", pdfium::WrapUnique(arr_obj.get()));
+    dict_obj->SetFor("arr", arr_obj);
     // Clone this object to see whether stack overflow will be triggered.
-    std::unique_ptr<CPDF_Array> cloned_array = ToArray(arr_obj->Clone());
+    RetainPtr<CPDF_Array> cloned_array = ToArray(arr_obj->Clone());
     // Cloned object should be the same as the original.
     ASSERT_TRUE(cloned_array);
     EXPECT_EQ(1u, cloned_array->size());
@@ -912,16 +911,15 @@
     ASSERT_TRUE(cloned_dict->IsDictionary());
     // Recursively referenced object is not cloned.
     EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("arr"));
+    dict_obj->RemoveFor("arr");  // Break deliberate cycle for cleanup.
   }
   {
-    // Create a dictionary/stream pair with a reference loop. It takes
-    // some work to do this nowadays, in particular we need the
-    // anti-pattern pdfium::WrapUnique(dict.get()).
-    auto dict_obj = pdfium::MakeUnique<CPDF_Dictionary>();
-    CPDF_Stream* stream_obj = dict_obj->SetNewFor<CPDF_Stream>(
-        "stream", nullptr, 0, pdfium::WrapUnique(dict_obj.get()));
+    // Create a dictionary/stream pair with a reference loop.
+    auto dict_obj = pdfium::MakeRetain<CPDF_Dictionary>();
+    CPDF_Stream* stream_obj =
+        dict_obj->SetNewFor<CPDF_Stream>("stream", nullptr, 0, dict_obj);
     // Clone this object to see whether stack overflow will be triggered.
-    std::unique_ptr<CPDF_Stream> cloned_stream = ToStream(stream_obj->Clone());
+    RetainPtr<CPDF_Stream> cloned_stream = ToStream(stream_obj->Clone());
     // Cloned object should be the same as the original.
     ASSERT_TRUE(cloned_stream);
     CPDF_Object* cloned_dict = cloned_stream->GetDict();
@@ -929,12 +927,13 @@
     ASSERT_TRUE(cloned_dict->IsDictionary());
     // Recursively referenced object is not cloned.
     EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("stream"));
+    dict_obj->RemoveFor("stream");  // Break deliberate cycle for cleanup.
   }
   {
     CPDF_IndirectObjectHolder objects_holder;
     // Create an object with a reference loop.
     CPDF_Dictionary* dict_obj = objects_holder.NewIndirect<CPDF_Dictionary>();
-    std::unique_ptr<CPDF_Array> arr_obj = pdfium::MakeUnique<CPDF_Array>();
+    RetainPtr<CPDF_Array> arr_obj = pdfium::MakeRetain<CPDF_Array>();
     arr_obj->InsertNewAt<CPDF_Reference>(0, &objects_holder,
                                          dict_obj->GetObjNum());
     CPDF_Object* elem0 = arr_obj->GetObjectAt(0);
@@ -946,7 +945,7 @@
     EXPECT_EQ(dict_obj, elem0->AsReference()->GetDirect());
 
     // Clone this object to see whether stack overflow will be triggered.
-    std::unique_ptr<CPDF_Dictionary> cloned_dict =
+    RetainPtr<CPDF_Dictionary> cloned_dict =
         ToDictionary(dict_obj->CloneDirectObject());
     // Cloned object should be the same as the original.
     ASSERT_TRUE(cloned_dict);
@@ -956,12 +955,13 @@
     EXPECT_EQ(0U, cloned_arr->AsArray()->size());
     // Recursively referenced object is not cloned.
     EXPECT_EQ(nullptr, cloned_arr->AsArray()->GetObjectAt(0));
+    dict_obj->RemoveFor("arr");  // Break deliberate cycle for cleanup.
   }
 }
 
 TEST(PDFDictionaryTest, ConvertIndirect) {
   CPDF_IndirectObjectHolder objects_holder;
-  auto dict = pdfium::MakeUnique<CPDF_Dictionary>();
+  auto dict = pdfium::MakeRetain<CPDF_Dictionary>();
   CPDF_Object* pObj = dict->SetNewFor<CPDF_Number>("clams", 42);
   dict->ConvertToIndirectObjectFor("clams", &objects_holder);
   CPDF_Object* pRef = dict->GetObjectFor("clams");
@@ -974,10 +974,10 @@
 }
 
 TEST(PDFDictionaryTest, ExtractObjectOnRemove) {
-  auto dict = pdfium::MakeUnique<CPDF_Dictionary>();
+  auto dict = pdfium::MakeRetain<CPDF_Dictionary>();
   CPDF_Object* pObj = dict->SetNewFor<CPDF_Number>("child", 42);
   auto extracted_object = dict->RemoveFor("child");
-  EXPECT_EQ(pObj, extracted_object.get());
+  EXPECT_EQ(pObj, extracted_object.Get());
 
   extracted_object = dict->RemoveFor("non_exists_object");
   EXPECT_FALSE(extracted_object);
@@ -985,7 +985,7 @@
 
 TEST(PDFRefernceTest, MakeReferenceToReference) {
   auto obj_holder = pdfium::MakeUnique<CPDF_IndirectObjectHolder>();
-  auto original_ref = pdfium::MakeUnique<CPDF_Reference>(obj_holder.get(), 42);
+  auto original_ref = pdfium::MakeRetain<CPDF_Reference>(obj_holder.get(), 42);
   original_ref->SetObjNum(1952);
   ASSERT_FALSE(original_ref->IsInline());
 
@@ -995,5 +995,5 @@
   // We do not allow reference to reference.
   // New reference should have same RefObjNum.
   EXPECT_EQ(original_ref->GetRefObjNum(),
-            ToReference(ref_obj.get())->GetRefObjNum());
+            ToReference(ref_obj.Get())->GetRefObjNum());
 }
diff --git a/core/fpdfapi/parser/cpdf_object_walker.cpp b/core/fpdfapi/parser/cpdf_object_walker.cpp
index f3e1062..dbc7752 100644
--- a/core/fpdfapi/parser/cpdf_object_walker.cpp
+++ b/core/fpdfapi/parser/cpdf_object_walker.cpp
@@ -47,7 +47,7 @@
   const CPDF_Object* IncrementImpl() override {
     ASSERT(IsStarted());
     ASSERT(!IsFinished());
-    const CPDF_Object* result = dict_iterator_->second.get();
+    const CPDF_Object* result = dict_iterator_->second.Get();
     dict_key_ = dict_iterator_->first;
     ++dict_iterator_;
     return result;
@@ -80,7 +80,7 @@
   const CPDF_Object* IncrementImpl() override {
     ASSERT(IsStarted());
     ASSERT(!IsFinished());
-    const CPDF_Object* result = arr_iterator_->get();
+    const CPDF_Object* result = arr_iterator_->Get();
     ++arr_iterator_;
     return result;
   }
diff --git a/core/fpdfapi/parser/cpdf_object_walker_unittest.cpp b/core/fpdfapi/parser/cpdf_object_walker_unittest.cpp
index c5ffe84..7de4e9a 100644
--- a/core/fpdfapi/parser/cpdf_object_walker_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_object_walker_unittest.cpp
@@ -55,45 +55,45 @@
 }  // namespace
 
 TEST(CPDF_ObjectWalkerTest, Simple) {
-  EXPECT_EQ(Walk(pdfium::MakeUnique<CPDF_Null>().get()), "Null");
-  EXPECT_EQ(Walk(pdfium::MakeUnique<CPDF_Dictionary>().get()), "Dict");
-  EXPECT_EQ(Walk(pdfium::MakeUnique<CPDF_Array>().get()), "Arr");
-  EXPECT_EQ(Walk(pdfium::MakeUnique<CPDF_String>().get()), "Str");
-  EXPECT_EQ(Walk(pdfium::MakeUnique<CPDF_Boolean>().get()), "Bool");
-  EXPECT_EQ(Walk(pdfium::MakeUnique<CPDF_Stream>().get()), "Stream");
-  EXPECT_EQ(Walk(pdfium::MakeUnique<CPDF_Reference>(nullptr, 0).get()), "Ref");
+  EXPECT_EQ(Walk(pdfium::MakeRetain<CPDF_Null>().Get()), "Null");
+  EXPECT_EQ(Walk(pdfium::MakeRetain<CPDF_Dictionary>().Get()), "Dict");
+  EXPECT_EQ(Walk(pdfium::MakeRetain<CPDF_Array>().Get()), "Arr");
+  EXPECT_EQ(Walk(pdfium::MakeRetain<CPDF_String>().Get()), "Str");
+  EXPECT_EQ(Walk(pdfium::MakeRetain<CPDF_Boolean>().Get()), "Bool");
+  EXPECT_EQ(Walk(pdfium::MakeRetain<CPDF_Stream>().Get()), "Stream");
+  EXPECT_EQ(Walk(pdfium::MakeRetain<CPDF_Reference>(nullptr, 0).Get()), "Ref");
 }
 
 TEST(CPDF_ObjectWalkerTest, CombinedObject) {
-  auto dict = pdfium::MakeUnique<CPDF_Dictionary>();
-  dict->SetFor("1", pdfium::MakeUnique<CPDF_String>());
-  dict->SetFor("2", pdfium::MakeUnique<CPDF_Boolean>());
-  auto array = pdfium::MakeUnique<CPDF_Array>();
-  array->Add(pdfium::MakeUnique<CPDF_Reference>(nullptr, 0));
-  array->Add(pdfium::MakeUnique<CPDF_Null>());
-  array->Add(pdfium::MakeUnique<CPDF_Stream>(
-      nullptr, 0, pdfium::MakeUnique<CPDF_Dictionary>()));
+  auto dict = pdfium::MakeRetain<CPDF_Dictionary>();
+  dict->SetFor("1", pdfium::MakeRetain<CPDF_String>());
+  dict->SetFor("2", pdfium::MakeRetain<CPDF_Boolean>());
+  auto array = pdfium::MakeRetain<CPDF_Array>();
+  array->Add(pdfium::MakeRetain<CPDF_Reference>(nullptr, 0));
+  array->Add(pdfium::MakeRetain<CPDF_Null>());
+  array->Add(pdfium::MakeRetain<CPDF_Stream>(
+      nullptr, 0, pdfium::MakeRetain<CPDF_Dictionary>()));
   dict->SetFor("3", std::move(array));
   // The last number for stream length.
-  EXPECT_EQ(Walk(dict.get()), "Dict Str Bool Arr Ref Null Stream Dict Num");
+  EXPECT_EQ(Walk(dict.Get()), "Dict Str Bool Arr Ref Null Stream Dict Num");
 }
 
 TEST(CPDF_ObjectWalkerTest, GetParent) {
-  auto level_4 = pdfium::MakeUnique<CPDF_Number>(0);
-  auto level_3 = pdfium::MakeUnique<CPDF_Dictionary>();
+  auto level_4 = pdfium::MakeRetain<CPDF_Number>(0);
+  auto level_3 = pdfium::MakeRetain<CPDF_Dictionary>();
   level_3->SetFor("Length", std::move(level_4));
   auto level_2 =
-      pdfium::MakeUnique<CPDF_Stream>(nullptr, 0, std::move(level_3));
-  auto level_1 = pdfium::MakeUnique<CPDF_Array>();
+      pdfium::MakeRetain<CPDF_Stream>(nullptr, 0, std::move(level_3));
+  auto level_1 = pdfium::MakeRetain<CPDF_Array>();
   level_1->Add(std::move(level_2));
-  auto level_0 = pdfium::MakeUnique<CPDF_Dictionary>();
+  auto level_0 = pdfium::MakeRetain<CPDF_Dictionary>();
   level_0->SetFor("Array", std::move(level_1));
 
   // We have <</Array [ stream( << /Length 0 >>) ]>>
   // In this case each step will increase depth.
   // And on each step the prev object should be parent for current.
   const CPDF_Object* cur_parent = nullptr;
-  CPDF_ObjectWalker walker(level_0.get());
+  CPDF_ObjectWalker walker(level_0.Get());
   while (const CPDF_Object* obj = walker.GetNext()) {
     EXPECT_EQ(cur_parent, walker.GetParent());
     cur_parent = obj;
@@ -101,7 +101,7 @@
 }
 
 TEST(CPDF_ObjectWalkerTest, SkipWalkIntoCurrentObject) {
-  auto root_array = pdfium::MakeUnique<CPDF_Array>();
+  auto root_array = pdfium::MakeRetain<CPDF_Array>();
   // Add 2 null objects into |root_array|. [ null1, null2 ]
   root_array->AddNew<CPDF_Null>();
   root_array->AddNew<CPDF_Null>();
@@ -110,9 +110,9 @@
   root_array->Add(root_array->Clone());
 
   int non_array_objects = 0;
-  CPDF_ObjectWalker walker(root_array.get());
+  CPDF_ObjectWalker walker(root_array.Get());
   while (const CPDF_Object* obj = walker.GetNext()) {
-    if (obj != root_array.get() && obj->IsArray()) {
+    if (obj != root_array.Get() && obj->IsArray()) {
       // skip other array except root.
       walker.SkipWalkIntoCurrentObject();
     }
@@ -124,16 +124,16 @@
 }
 
 TEST(CPDF_ObjectWalkerTest, DictionaryKey) {
-  auto dict = pdfium::MakeUnique<CPDF_Dictionary>();
-  dict->SetFor("1", pdfium::MakeUnique<CPDF_Null>());
-  dict->SetFor("2", pdfium::MakeUnique<CPDF_Null>());
-  dict->SetFor("3", pdfium::MakeUnique<CPDF_Null>());
-  dict->SetFor("4", pdfium::MakeUnique<CPDF_Null>());
-  dict->SetFor("5", pdfium::MakeUnique<CPDF_Null>());
+  auto dict = pdfium::MakeRetain<CPDF_Dictionary>();
+  dict->SetFor("1", pdfium::MakeRetain<CPDF_Null>());
+  dict->SetFor("2", pdfium::MakeRetain<CPDF_Null>());
+  dict->SetFor("3", pdfium::MakeRetain<CPDF_Null>());
+  dict->SetFor("4", pdfium::MakeRetain<CPDF_Null>());
+  dict->SetFor("5", pdfium::MakeRetain<CPDF_Null>());
 
-  CPDF_ObjectWalker walker(dict.get());
+  CPDF_ObjectWalker walker(dict.Get());
   while (const CPDF_Object* obj = walker.GetNext()) {
-    if (obj == dict.get()) {
+    if (dict == obj) {
       // Ignore root dictinary object
       continue;
     }
diff --git a/core/fpdfapi/parser/cpdf_page_object_avail_unittest.cpp b/core/fpdfapi/parser/cpdf_page_object_avail_unittest.cpp
index 18a973b..6a76118 100644
--- a/core/fpdfapi/parser/cpdf_page_object_avail_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_page_object_avail_unittest.cpp
@@ -55,13 +55,13 @@
       validator_->SimulateReadError();
       return nullptr;
     }
-    return obj_data.object.get();
+    return obj_data.object.Get();
   }
 
   RetainPtr<CPDF_ReadValidator> GetValidator() { return validator_; }
 
   void AddObject(uint32_t objnum,
-                 std::unique_ptr<CPDF_Object> object,
+                 RetainPtr<CPDF_Object> object,
                  ObjectState state) {
     ObjectData object_data;
     object_data.object = std::move(object);
@@ -81,12 +81,12 @@
     auto it = objects_data_.find(objnum);
     if (it == objects_data_.end())
       return nullptr;
-    return it->second.object.get();
+    return it->second.object.Get();
   }
 
  private:
   struct ObjectData {
-    std::unique_ptr<CPDF_Object> object;
+    RetainPtr<CPDF_Object> object;
     ObjectState state = ObjectState::Unavailable;
   };
   std::map<uint32_t, ObjectData> objects_data_;
@@ -97,23 +97,23 @@
 
 TEST(CPDF_PageObjectAvailTest, ExcludePages) {
   TestHolder holder;
-  holder.AddObject(1, pdfium::MakeUnique<CPDF_Dictionary>(),
+  holder.AddObject(1, pdfium::MakeRetain<CPDF_Dictionary>(),
                    TestHolder::ObjectState::Available);
   holder.GetTestObject(1)->GetDict()->SetNewFor<CPDF_Reference>("Kids", &holder,
                                                                 2);
-  holder.AddObject(2, pdfium::MakeUnique<CPDF_Array>(),
+  holder.AddObject(2, pdfium::MakeRetain<CPDF_Array>(),
                    TestHolder::ObjectState::Available);
   holder.GetTestObject(2)->AsArray()->AddNew<CPDF_Reference>(&holder, 3);
 
-  holder.AddObject(3, pdfium::MakeUnique<CPDF_Dictionary>(),
+  holder.AddObject(3, pdfium::MakeRetain<CPDF_Dictionary>(),
                    TestHolder::ObjectState::Available);
   holder.GetTestObject(3)->GetDict()->SetFor(
-      "Type", pdfium::MakeUnique<CPDF_String>(nullptr, "Page", false));
+      "Type", pdfium::MakeRetain<CPDF_String>(nullptr, "Page", false));
   holder.GetTestObject(3)->GetDict()->SetNewFor<CPDF_Reference>("OtherPageData",
                                                                 &holder, 4);
   // Add unavailable object related to other page.
   holder.AddObject(
-      4, pdfium::MakeUnique<CPDF_String>(nullptr, "Other page data", false),
+      4, pdfium::MakeRetain<CPDF_String>(nullptr, "Other page data", false),
       TestHolder::ObjectState::Unavailable);
 
   CPDF_PageObjectAvail avail(holder.GetValidator(), &holder, 1);
diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp
index 2a7852c..2a3fac5 100644
--- a/core/fpdfapi/parser/cpdf_parser.cpp
+++ b/core/fpdfapi/parser/cpdf_parser.cpp
@@ -292,7 +292,7 @@
   if (!LoadCrossRefV4(xrefpos, true))
     return false;
 
-  std::unique_ptr<CPDF_Dictionary> trailer = LoadTrailerV4();
+  RetainPtr<CPDF_Dictionary> trailer = LoadTrailerV4();
   if (!trailer)
     return false;
 
@@ -323,11 +323,11 @@
     CrossRefList.insert(CrossRefList.begin(), xrefpos);
     LoadCrossRefV4(xrefpos, true);
 
-    std::unique_ptr<CPDF_Dictionary> pDict(LoadTrailerV4());
+    RetainPtr<CPDF_Dictionary> pDict(LoadTrailerV4());
     if (!pDict)
       return false;
 
-    xrefpos = GetDirectInteger(pDict.get(), "Prev");
+    xrefpos = GetDirectInteger(pDict.Get(), "Prev");
 
     // SLOW ...
     XRefStreamList.insert(XRefStreamList.begin(),
@@ -355,7 +355,7 @@
   if (!LoadCrossRefV4(xrefpos, false))
     return false;
 
-  std::unique_ptr<CPDF_Dictionary> trailer = LoadTrailerV4();
+  RetainPtr<CPDF_Dictionary> trailer = LoadTrailerV4();
   if (!trailer)
     return false;
 
@@ -387,11 +387,11 @@
     CrossRefList.insert(CrossRefList.begin(), xrefpos);
     LoadCrossRefV4(xrefpos, true);
 
-    std::unique_ptr<CPDF_Dictionary> pDict(LoadTrailerV4());
+    RetainPtr<CPDF_Dictionary> pDict(LoadTrailerV4());
     if (!pDict)
       return false;
 
-    xrefpos = GetDirectInteger(pDict.get(), "Prev");
+    xrefpos = GetDirectInteger(pDict.Get(), "Prev");
 
     // SLOW ...
     XRefStreamList.insert(XRefStreamList.begin(),
@@ -608,7 +608,7 @@
     } else if (word == "<") {
       m_pSyntax->ReadHexString();
     } else if (word == "trailer") {
-      std::unique_ptr<CPDF_Object> pTrailer = m_pSyntax->GetObjectBody(nullptr);
+      RetainPtr<CPDF_Object> pTrailer = m_pSyntax->GetObjectBody(nullptr);
       if (pTrailer) {
         cross_ref_table = CPDF_CrossRefTable::MergeUp(
             std::move(cross_ref_table),
@@ -622,7 +622,7 @@
       const uint32_t gen_num = numbers[1].first;
 
       m_pSyntax->SetPos(obj_pos);
-      const std::unique_ptr<CPDF_Stream> pStream =
+      const RetainPtr<CPDF_Stream> pStream =
           ToStream(m_pSyntax->GetIndirectObject(
               nullptr, CPDF_SyntaxParser::ParseType::kStrict));
 
@@ -636,7 +636,7 @@
       if (obj_num < kMaxObjectNumber) {
         cross_ref_table->AddNormal(obj_num, gen_num, obj_pos);
         if (const auto object_stream =
-                CPDF_ObjectStream::Create(pStream.get())) {
+                CPDF_ObjectStream::Create(pStream.Get())) {
           for (const auto& it : object_stream->objects_offsets()) {
             if (it.first < kMaxObjectNumber)
               cross_ref_table->AddCompressed(it.first, obj_num);
@@ -656,7 +656,7 @@
 }
 
 bool CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, bool bMainXRef) {
-  std::unique_ptr<CPDF_Object> pObject(ParseIndirectObjectAt(*pos, 0));
+  RetainPtr<CPDF_Object> pObject(ParseIndirectObjectAt(*pos, 0));
   if (!pObject || !pObject->GetObjNum())
     return false;
 
@@ -670,7 +670,7 @@
   if (size < 0)
     return false;
 
-  std::unique_ptr<CPDF_Dictionary> pNewTrailer = ToDictionary(pDict->Clone());
+  RetainPtr<CPDF_Dictionary> pNewTrailer = ToDictionary(pDict->Clone());
   if (bMainXRef) {
     m_CrossRefTable =
         pdfium::MakeUnique<CPDF_CrossRefTable>(std::move(pNewTrailer));
@@ -827,10 +827,10 @@
   return m_CrossRefTable->trailer();
 }
 
-std::unique_ptr<CPDF_Dictionary> CPDF_Parser::GetCombinedTrailer() const {
+RetainPtr<CPDF_Dictionary> CPDF_Parser::GetCombinedTrailer() const {
   return m_CrossRefTable->trailer()
              ? ToDictionary(m_CrossRefTable->trailer()->Clone())
-             : std::unique_ptr<CPDF_Dictionary>();
+             : RetainPtr<CPDF_Dictionary>();
 }
 
 uint32_t CPDF_Parser::GetInfoObjNum() const {
@@ -849,8 +849,7 @@
   return pRef ? pRef->GetRefObjNum() : CPDF_Object::kInvalidObjNum;
 }
 
-std::unique_ptr<CPDF_Object> CPDF_Parser::ParseIndirectObject(
-    uint32_t objnum) {
+RetainPtr<CPDF_Object> CPDF_Parser::ParseIndirectObject(uint32_t objnum) {
   if (!IsValidObjectNumber(objnum))
     return nullptr;
 
@@ -896,39 +895,37 @@
   if (object_pos <= 0)
     return nullptr;
 
-  std::unique_ptr<CPDF_Object> object =
+  RetainPtr<CPDF_Object> object =
       ParseIndirectObjectAt(object_pos, object_number);
   if (!object)
     return nullptr;
 
   std::unique_ptr<CPDF_ObjectStream> objs_stream =
-      CPDF_ObjectStream::Create(ToStream(object.get()));
+      CPDF_ObjectStream::Create(ToStream(object.Get()));
   const CPDF_ObjectStream* result = objs_stream.get();
   m_ObjectStreamMap[object_number] = std::move(objs_stream);
 
   return result;
 }
 
-std::unique_ptr<CPDF_Object> CPDF_Parser::ParseIndirectObjectAt(
-    FX_FILESIZE pos,
-    uint32_t objnum) {
+RetainPtr<CPDF_Object> CPDF_Parser::ParseIndirectObjectAt(FX_FILESIZE pos,
+                                                          uint32_t objnum) {
   const FX_FILESIZE saved_pos = m_pSyntax->GetPos();
   m_pSyntax->SetPos(pos);
+
   auto result = m_pSyntax->GetIndirectObject(
       m_pObjectsHolder.Get(), CPDF_SyntaxParser::ParseType::kLoose);
-
   m_pSyntax->SetPos(saved_pos);
-
   if (result && objnum && result->GetObjNum() != objnum)
     return nullptr;
 
   const bool should_decrypt = m_pSecurityHandler &&
                               m_pSecurityHandler->GetCryptoHandler() &&
                               objnum != m_MetadataObjnum;
-  if (should_decrypt)
-    result = m_pSecurityHandler->GetCryptoHandler()->DecryptObjectTree(
-        std::move(result));
-
+  if (should_decrypt &&
+      !m_pSecurityHandler->GetCryptoHandler()->DecryptObjectTree(result)) {
+    return nullptr;
+  }
   return result;
 }
 
@@ -941,7 +938,7 @@
   m_pLinearized = std::move(pLinearized);
 }
 
-std::unique_ptr<CPDF_Dictionary> CPDF_Parser::LoadTrailerV4() {
+RetainPtr<CPDF_Dictionary> CPDF_Parser::LoadTrailerV4() {
   if (m_pSyntax->GetKeyword() != "trailer")
     return nullptr;
 
@@ -985,7 +982,7 @@
     m_LastXRefOffset = 0;
   }
   if (bLoadV4) {
-    std::unique_ptr<CPDF_Dictionary> trailer = LoadTrailerV4();
+    RetainPtr<CPDF_Dictionary> trailer = LoadTrailerV4();
     if (!trailer)
       return SUCCESS;
 
diff --git a/core/fpdfapi/parser/cpdf_parser.h b/core/fpdfapi/parser/cpdf_parser.h
index b7b63e4..bc26488 100644
--- a/core/fpdfapi/parser/cpdf_parser.h
+++ b/core/fpdfapi/parser/cpdf_parser.h
@@ -71,7 +71,7 @@
 
   // Returns a new trailer which combines the last read trailer with the /Root
   // and /Info from previous ones.
-  std::unique_ptr<CPDF_Dictionary> GetCombinedTrailer() const;
+  RetainPtr<CPDF_Dictionary> GetCombinedTrailer() const;
 
   FX_FILESIZE GetLastXRefOffset() const { return m_LastXRefOffset; }
 
@@ -83,7 +83,7 @@
 
   const CPDF_Dictionary* GetEncryptDict() const;
 
-  std::unique_ptr<CPDF_Object> ParseIndirectObject(uint32_t objnum);
+  RetainPtr<CPDF_Object> ParseIndirectObject(uint32_t objnum);
 
   uint32_t GetLastObjNum() const;
   bool IsValidObjectNumber(uint32_t objnum) const;
@@ -98,9 +98,8 @@
   int GetFileVersion() const { return m_FileVersion; }
   bool IsXRefStream() const { return m_bXRefStream; }
 
-  std::unique_ptr<CPDF_Object> ParseIndirectObjectAt(
-      FX_FILESIZE pos,
-      uint32_t objnum);
+  RetainPtr<CPDF_Object> ParseIndirectObjectAt(FX_FILESIZE pos,
+                                               uint32_t objnum);
 
   uint32_t GetFirstPageNo() const;
   const CPDF_LinearizedHeader* GetLinearizedHeader() const {
@@ -143,7 +142,7 @@
   bool LoadAllCrossRefV4(FX_FILESIZE pos);
   bool LoadAllCrossRefV5(FX_FILESIZE pos);
   bool LoadCrossRefV5(FX_FILESIZE* pos, bool bMainXRef);
-  std::unique_ptr<CPDF_Dictionary> LoadTrailerV4();
+  RetainPtr<CPDF_Dictionary> LoadTrailerV4();
   Error SetEncryptHandler();
   void ReleaseEncryptHandler();
   bool LoadLinearizedAllCrossRefV4(FX_FILESIZE pos);
diff --git a/core/fpdfapi/parser/cpdf_parser_unittest.cpp b/core/fpdfapi/parser/cpdf_parser_unittest.cpp
index f5f170e..06328f0 100644
--- a/core/fpdfapi/parser/cpdf_parser_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_parser_unittest.cpp
@@ -272,7 +272,7 @@
   ASSERT_TRUE(parser.InitTestFromFile(test_file.c_str())) << test_file;
 
   EXPECT_EQ(100940, parser.ParseStartXRef());
-  std::unique_ptr<CPDF_Object> cross_ref_v5_obj =
+  RetainPtr<CPDF_Object> cross_ref_v5_obj =
       parser.ParseIndirectObjectAt(100940, 0);
   ASSERT_TRUE(cross_ref_v5_obj);
   EXPECT_EQ(75u, cross_ref_v5_obj->GetObjNum());
@@ -294,7 +294,7 @@
   parser.InitTestFromBufferWithOffset(data, kTestHeaderOffset);
 
   EXPECT_EQ(100940, parser.ParseStartXRef());
-  std::unique_ptr<CPDF_Object> cross_ref_v5_obj =
+  RetainPtr<CPDF_Object> cross_ref_v5_obj =
       parser.ParseIndirectObjectAt(100940, 0);
   ASSERT_TRUE(cross_ref_v5_obj);
   EXPECT_EQ(75u, cross_ref_v5_obj->GetObjNum());
diff --git a/core/fpdfapi/parser/cpdf_reference.cpp b/core/fpdfapi/parser/cpdf_reference.cpp
index 6885d2c..8341ca1 100644
--- a/core/fpdfapi/parser/cpdf_reference.cpp
+++ b/core/fpdfapi/parser/cpdf_reference.cpp
@@ -57,11 +57,11 @@
   return this;
 }
 
-std::unique_ptr<CPDF_Object> CPDF_Reference::Clone() const {
+RetainPtr<CPDF_Object> CPDF_Reference::Clone() const {
   return CloneObjectNonCyclic(false);
 }
 
-std::unique_ptr<CPDF_Object> CPDF_Reference::CloneNonCyclic(
+RetainPtr<CPDF_Object> CPDF_Reference::CloneNonCyclic(
     bool bDirect,
     std::set<const CPDF_Object*>* pVisited) const {
   pVisited->insert(this);
@@ -71,7 +71,7 @@
                ? pDirect->CloneNonCyclic(true, pVisited)
                : nullptr;
   }
-  return pdfium::MakeUnique<CPDF_Reference>(m_pObjList.Get(), m_RefObjNum);
+  return pdfium::MakeRetain<CPDF_Reference>(m_pObjList.Get(), m_RefObjNum);
 }
 
 CPDF_Object* CPDF_Reference::SafeGetDirect() {
@@ -105,10 +105,10 @@
          archive->WriteString(" 0 R ");
 }
 
-std::unique_ptr<CPDF_Object> CPDF_Reference::MakeReference(
+RetainPtr<CPDF_Object> CPDF_Reference::MakeReference(
     CPDF_IndirectObjectHolder* holder) const {
   ASSERT(holder == m_pObjList.Get());
   // Do not allow reference to reference, just create other reference for same
   // object.
-  return pdfium::MakeUnique<CPDF_Reference>(holder, GetRefObjNum());
+  return pdfium::MakeRetain<CPDF_Reference>(holder, GetRefObjNum());
 }
diff --git a/core/fpdfapi/parser/cpdf_reference.h b/core/fpdfapi/parser/cpdf_reference.h
index f7b03ac..1ec7282 100644
--- a/core/fpdfapi/parser/cpdf_reference.h
+++ b/core/fpdfapi/parser/cpdf_reference.h
@@ -17,12 +17,12 @@
 
 class CPDF_Reference final : public CPDF_Object {
  public:
-  CPDF_Reference(CPDF_IndirectObjectHolder* pDoc, uint32_t objnum);
-  ~CPDF_Reference() override;
+  template <typename T, typename... Args>
+  friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
 
   // CPDF_Object:
   Type GetType() const override;
-  std::unique_ptr<CPDF_Object> Clone() const override;
+  RetainPtr<CPDF_Object> Clone() const override;
   CPDF_Object* GetDirect() override;
   const CPDF_Object* GetDirect() const override;
   ByteString GetString() const override;
@@ -35,7 +35,7 @@
   const CPDF_Reference* AsReference() const override;
   bool WriteTo(IFX_ArchiveStream* archive,
                const CPDF_Encryptor* encryptor) const override;
-  std::unique_ptr<CPDF_Object> MakeReference(
+  RetainPtr<CPDF_Object> MakeReference(
       CPDF_IndirectObjectHolder* holder) const override;
 
   CPDF_IndirectObjectHolder* GetObjList() const { return m_pObjList.Get(); }
@@ -43,7 +43,10 @@
   void SetRef(CPDF_IndirectObjectHolder* pDoc, uint32_t objnum);
 
  private:
-  std::unique_ptr<CPDF_Object> CloneNonCyclic(
+  CPDF_Reference(CPDF_IndirectObjectHolder* pDoc, uint32_t objnum);
+  ~CPDF_Reference() override;
+
+  RetainPtr<CPDF_Object> CloneNonCyclic(
       bool bDirect,
       std::set<const CPDF_Object*>* pVisited) const override;
   CPDF_Object* SafeGetDirect();
diff --git a/core/fpdfapi/parser/cpdf_stream.cpp b/core/fpdfapi/parser/cpdf_stream.cpp
index 06b7657..4b5ef5c 100644
--- a/core/fpdfapi/parser/cpdf_stream.cpp
+++ b/core/fpdfapi/parser/cpdf_stream.cpp
@@ -34,7 +34,7 @@
 
 CPDF_Stream::CPDF_Stream(std::unique_ptr<uint8_t, FxFreeDeleter> pData,
                          uint32_t size,
-                         std::unique_ptr<CPDF_Dictionary> pDict)
+                         RetainPtr<CPDF_Dictionary> pDict)
     : m_pDict(std::move(pDict)) {
   TakeData(std::move(pData), size);
 }
@@ -42,7 +42,7 @@
 CPDF_Stream::~CPDF_Stream() {
   m_ObjNum = kInvalidObjNum;
   if (m_pDict && m_pDict->GetObjNum() == kInvalidObjNum)
-    m_pDict.release();  // lowercase release, release ownership.
+    m_pDict.Leak();  // lowercase release, release ownership.
 }
 
 CPDF_Object::Type CPDF_Stream::GetType() const {
@@ -50,11 +50,11 @@
 }
 
 CPDF_Dictionary* CPDF_Stream::GetDict() {
-  return m_pDict.get();
+  return m_pDict.Get();
 }
 
 const CPDF_Dictionary* CPDF_Stream::GetDict() const {
-  return m_pDict.get();
+  return m_pDict.Get();
 }
 
 bool CPDF_Stream::IsStream() const {
@@ -70,14 +70,14 @@
 }
 
 void CPDF_Stream::InitStream(pdfium::span<const uint8_t> pData,
-                             std::unique_ptr<CPDF_Dictionary> pDict) {
+                             RetainPtr<CPDF_Dictionary> pDict) {
   m_pDict = std::move(pDict);
   SetData(pData);
 }
 
 void CPDF_Stream::InitStreamFromFile(
     const RetainPtr<IFX_SeekableReadStream>& pFile,
-    std::unique_ptr<CPDF_Dictionary> pDict) {
+    RetainPtr<CPDF_Dictionary> pDict) {
   m_bMemoryBased = false;
   m_pDataBuf.reset();
   m_pFile = pFile;
@@ -86,11 +86,11 @@
   m_pDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(m_dwSize));
 }
 
-std::unique_ptr<CPDF_Object> CPDF_Stream::Clone() const {
+RetainPtr<CPDF_Object> CPDF_Stream::Clone() const {
   return CloneObjectNonCyclic(false);
 }
 
-std::unique_ptr<CPDF_Object> CPDF_Stream::CloneNonCyclic(
+RetainPtr<CPDF_Object> CPDF_Stream::CloneNonCyclic(
     bool bDirect,
     std::set<const CPDF_Object*>* pVisited) const {
   pVisited->insert(this);
@@ -99,13 +99,13 @@
 
   uint32_t streamSize = pAcc->GetSize();
   const CPDF_Dictionary* pDict = GetDict();
-  std::unique_ptr<CPDF_Dictionary> pNewDict;
+  RetainPtr<CPDF_Dictionary> pNewDict;
   if (pDict && !pdfium::ContainsKey(*pVisited, pDict)) {
     pNewDict =
         ToDictionary(static_cast<const CPDF_Object*>(pDict)->CloneNonCyclic(
             bDirect, pVisited));
   }
-  return pdfium::MakeUnique<CPDF_Stream>(pAcc->DetachData(), streamSize,
+  return pdfium::MakeRetain<CPDF_Stream>(pAcc->DetachData(), streamSize,
                                          std::move(pNewDict));
 }
 
@@ -143,7 +143,7 @@
   m_pDataBuf = std::move(pData);
   m_dwSize = size;
   if (!m_pDict)
-    m_pDict = pdfium::MakeUnique<CPDF_Dictionary>();
+    m_pDict = pdfium::MakeRetain<CPDF_Dictionary>();
   m_pDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(size));
 }
 
diff --git a/core/fpdfapi/parser/cpdf_stream.h b/core/fpdfapi/parser/cpdf_stream.h
index e446c85..d76b683 100644
--- a/core/fpdfapi/parser/cpdf_stream.h
+++ b/core/fpdfapi/parser/cpdf_stream.h
@@ -16,16 +16,12 @@
 
 class CPDF_Stream final : public CPDF_Object {
  public:
-  CPDF_Stream();
-  CPDF_Stream(std::unique_ptr<uint8_t, FxFreeDeleter> pData,
-              uint32_t size,
-              std::unique_ptr<CPDF_Dictionary> pDict);
-
-  ~CPDF_Stream() override;
+  template <typename T, typename... Args>
+  friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
 
   // CPDF_Object:
   Type GetType() const override;
-  std::unique_ptr<CPDF_Object> Clone() const override;
+  RetainPtr<CPDF_Object> Clone() const override;
   CPDF_Dictionary* GetDict() override;
   const CPDF_Dictionary* GetDict() const override;
   WideString GetUnicodeText() const override;
@@ -53,9 +49,9 @@
   void SetDataFromStringstreamAndRemoveFilter(std::ostringstream* stream);
 
   void InitStream(pdfium::span<const uint8_t> pData,
-                  std::unique_ptr<CPDF_Dictionary> pDict);
+                  RetainPtr<CPDF_Dictionary> pDict);
   void InitStreamFromFile(const RetainPtr<IFX_SeekableReadStream>& pFile,
-                          std::unique_ptr<CPDF_Dictionary> pDict);
+                          RetainPtr<CPDF_Dictionary> pDict);
 
   bool ReadRawData(FX_FILESIZE start_pos,
                    uint8_t* pBuf,
@@ -65,13 +61,19 @@
   bool HasFilter() const;
 
  private:
-  std::unique_ptr<CPDF_Object> CloneNonCyclic(
+  CPDF_Stream();
+  CPDF_Stream(std::unique_ptr<uint8_t, FxFreeDeleter> pData,
+              uint32_t size,
+              RetainPtr<CPDF_Dictionary> pDict);
+  ~CPDF_Stream() override;
+
+  RetainPtr<CPDF_Object> CloneNonCyclic(
       bool bDirect,
       std::set<const CPDF_Object*>* pVisited) const override;
 
   bool m_bMemoryBased = true;
   uint32_t m_dwSize = 0;
-  std::unique_ptr<CPDF_Dictionary> m_pDict;
+  RetainPtr<CPDF_Dictionary> m_pDict;
   std::unique_ptr<uint8_t, FxFreeDeleter> m_pDataBuf;
   RetainPtr<IFX_SeekableReadStream> m_pFile;
 };
@@ -84,12 +86,8 @@
   return obj ? obj->AsStream() : nullptr;
 }
 
-inline std::unique_ptr<CPDF_Stream> ToStream(std::unique_ptr<CPDF_Object> obj) {
-  CPDF_Stream* pStream = ToStream(obj.get());
-  if (!pStream)
-    return nullptr;
-  obj.release();
-  return std::unique_ptr<CPDF_Stream>(pStream);
+inline RetainPtr<CPDF_Stream> ToStream(RetainPtr<CPDF_Object> obj) {
+  return RetainPtr<CPDF_Stream>(ToStream(obj.Get()));
 }
 
 #endif  // CORE_FPDFAPI_PARSER_CPDF_STREAM_H_
diff --git a/core/fpdfapi/parser/cpdf_stream_acc_unittest.cpp b/core/fpdfapi/parser/cpdf_stream_acc_unittest.cpp
index d8b1f98..72ba93d 100644
--- a/core/fpdfapi/parser/cpdf_stream_acc_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_stream_acc_unittest.cpp
@@ -11,10 +11,11 @@
 #include "testing/invalid_seekable_read_stream.h"
 
 TEST(CPDF_StreamAccTest, ReadRawDataFailed) {
-  CPDF_Stream stream;
-  stream.InitStreamFromFile(pdfium::MakeRetain<InvalidSeekableReadStream>(1024),
-                            pdfium::MakeUnique<CPDF_Dictionary>());
-  auto stream_acc = pdfium::MakeRetain<CPDF_StreamAcc>(&stream);
+  auto stream = pdfium::MakeRetain<CPDF_Stream>();
+  stream->InitStreamFromFile(
+      pdfium::MakeRetain<InvalidSeekableReadStream>(1024),
+      pdfium::MakeRetain<CPDF_Dictionary>());
+  auto stream_acc = pdfium::MakeRetain<CPDF_StreamAcc>(stream.Get());
   stream_acc->LoadAllDataRaw();
   EXPECT_EQ(0u, stream_acc->GetSize());
   EXPECT_FALSE(stream_acc->GetData());
diff --git a/core/fpdfapi/parser/cpdf_string.cpp b/core/fpdfapi/parser/cpdf_string.cpp
index 2a7653e..721672d 100644
--- a/core/fpdfapi/parser/cpdf_string.cpp
+++ b/core/fpdfapi/parser/cpdf_string.cpp
@@ -36,8 +36,8 @@
   return kString;
 }
 
-std::unique_ptr<CPDF_Object> CPDF_String::Clone() const {
-  auto pRet = pdfium::MakeUnique<CPDF_String>();
+RetainPtr<CPDF_Object> CPDF_String::Clone() const {
+  auto pRet = pdfium::MakeRetain<CPDF_String>();
   pRet->m_String = m_String;
   pRet->m_bHex = m_bHex;
   return std::move(pRet);
diff --git a/core/fpdfapi/parser/cpdf_string.h b/core/fpdfapi/parser/cpdf_string.h
index d3fc2c5..9dc50f7 100644
--- a/core/fpdfapi/parser/cpdf_string.h
+++ b/core/fpdfapi/parser/cpdf_string.h
@@ -17,14 +17,12 @@
 
 class CPDF_String final : public CPDF_Object {
  public:
-  CPDF_String();
-  CPDF_String(WeakPtr<ByteStringPool> pPool, const ByteString& str, bool bHex);
-  CPDF_String(WeakPtr<ByteStringPool> pPool, const WideString& str);
-  ~CPDF_String() override;
+  template <typename T, typename... Args>
+  friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
 
   // CPDF_Object:
   Type GetType() const override;
-  std::unique_ptr<CPDF_Object> Clone() const override;
+  RetainPtr<CPDF_Object> Clone() const override;
   ByteString GetString() const override;
   WideString GetUnicodeText() const override;
   void SetString(const ByteString& str) override;
@@ -37,6 +35,11 @@
   bool IsHex() const { return m_bHex; }
 
  private:
+  CPDF_String();
+  CPDF_String(WeakPtr<ByteStringPool> pPool, const ByteString& str, bool bHex);
+  CPDF_String(WeakPtr<ByteStringPool> pPool, const WideString& str);
+  ~CPDF_String() override;
+
   ByteString m_String;
   bool m_bHex;
 };
diff --git a/core/fpdfapi/parser/cpdf_syntax_parser.cpp b/core/fpdfapi/parser/cpdf_syntax_parser.cpp
index ae844bd..bdc1a55 100644
--- a/core/fpdfapi/parser/cpdf_syntax_parser.cpp
+++ b/core/fpdfapi/parser/cpdf_syntax_parser.cpp
@@ -410,7 +410,7 @@
   m_Pos = std::min(pos, m_FileLen);
 }
 
-std::unique_ptr<CPDF_Object> CPDF_SyntaxParser::GetObjectBody(
+RetainPtr<CPDF_Object> CPDF_SyntaxParser::GetObjectBody(
     CPDF_IndirectObjectHolder* pObjList) {
   const CPDF_ReadValidator::Session read_session(GetValidator());
   auto result = GetObjectBodyInternal(pObjList, ParseType::kLoose);
@@ -419,7 +419,7 @@
   return result;
 }
 
-std::unique_ptr<CPDF_Object> CPDF_SyntaxParser::GetObjectBodyInternal(
+RetainPtr<CPDF_Object> CPDF_SyntaxParser::GetObjectBodyInternal(
     CPDF_IndirectObjectHolder* pObjList,
     ParseType parse_type) {
   AutoRestorer<int> depth_restorer(&s_CurrentRecursionDepth);
@@ -436,37 +436,37 @@
     AutoRestorer<FX_FILESIZE> pos_restorer(&m_Pos);
     ByteString nextword = GetNextWord(&bIsNumber);
     if (!bIsNumber)
-      return pdfium::MakeUnique<CPDF_Number>(word.AsStringView());
+      return pdfium::MakeRetain<CPDF_Number>(word.AsStringView());
 
     ByteString nextword2 = GetNextWord(nullptr);
     if (nextword2 != "R")
-      return pdfium::MakeUnique<CPDF_Number>(word.AsStringView());
+      return pdfium::MakeRetain<CPDF_Number>(word.AsStringView());
 
     pos_restorer.AbandonRestoration();
     uint32_t refnum = FXSYS_atoui(word.c_str());
     if (refnum == CPDF_Object::kInvalidObjNum)
       return nullptr;
 
-    return pdfium::MakeUnique<CPDF_Reference>(pObjList, refnum);
+    return pdfium::MakeRetain<CPDF_Reference>(pObjList, refnum);
   }
 
   if (word == "true" || word == "false")
-    return pdfium::MakeUnique<CPDF_Boolean>(word == "true");
+    return pdfium::MakeRetain<CPDF_Boolean>(word == "true");
 
   if (word == "null")
-    return pdfium::MakeUnique<CPDF_Null>();
+    return pdfium::MakeRetain<CPDF_Null>();
 
   if (word == "(") {
     ByteString str = ReadString();
-    return pdfium::MakeUnique<CPDF_String>(m_pPool, str, false);
+    return pdfium::MakeRetain<CPDF_String>(m_pPool, str, false);
   }
   if (word == "<") {
     ByteString str = ReadHexString();
-    return pdfium::MakeUnique<CPDF_String>(m_pPool, str, true);
+    return pdfium::MakeRetain<CPDF_String>(m_pPool, str, true);
   }
   if (word == "[") {
-    auto pArray = pdfium::MakeUnique<CPDF_Array>();
-    while (std::unique_ptr<CPDF_Object> pObj =
+    auto pArray = pdfium::MakeRetain<CPDF_Array>();
+    while (RetainPtr<CPDF_Object> pObj =
                GetObjectBodyInternal(pObjList, ParseType::kLoose)) {
       pArray->Add(std::move(pObj));
     }
@@ -475,13 +475,13 @@
                : nullptr;
   }
   if (word[0] == '/') {
-    return pdfium::MakeUnique<CPDF_Name>(
+    return pdfium::MakeRetain<CPDF_Name>(
         m_pPool,
         PDF_NameDecode(ByteStringView(m_WordBuffer + 1, m_WordSize - 1)));
   }
   if (word == "<<") {
-    std::unique_ptr<CPDF_Dictionary> pDict =
-        pdfium::MakeUnique<CPDF_Dictionary>(m_pPool);
+    RetainPtr<CPDF_Dictionary> pDict =
+        pdfium::MakeRetain<CPDF_Dictionary>(m_pPool);
     while (1) {
       ByteString inner_word = GetNextWord(nullptr);
       if (inner_word.IsEmpty())
@@ -502,7 +502,7 @@
       if (key.IsEmpty() && parse_type == ParseType::kLoose)
         continue;
 
-      std::unique_ptr<CPDF_Object> pObj =
+      RetainPtr<CPDF_Object> pObj =
           GetObjectBodyInternal(pObjList, ParseType::kLoose);
       if (!pObj) {
         if (parse_type == ParseType::kLoose)
@@ -530,7 +530,7 @@
   return nullptr;
 }
 
-std::unique_ptr<CPDF_Object> CPDF_SyntaxParser::GetIndirectObject(
+RetainPtr<CPDF_Object> CPDF_SyntaxParser::GetIndirectObject(
     CPDF_IndirectObjectHolder* pObjList,
     ParseType parse_type) {
   const CPDF_ReadValidator::Session read_session(GetValidator());
@@ -555,8 +555,7 @@
     return nullptr;
   }
 
-  std::unique_ptr<CPDF_Object> pObj =
-      GetObjectBodyInternal(pObjList, parse_type);
+  RetainPtr<CPDF_Object> pObj = GetObjectBodyInternal(pObjList, parse_type);
   if (pObj) {
     pObj->SetObjNum(parser_objnum);
     pObj->SetGenNum(parser_gennum);
@@ -631,8 +630,8 @@
   return endStreamWordOffset;
 }
 
-std::unique_ptr<CPDF_Stream> CPDF_SyntaxParser::ReadStream(
-    std::unique_ptr<CPDF_Dictionary> pDict) {
+RetainPtr<CPDF_Stream> CPDF_SyntaxParser::ReadStream(
+    RetainPtr<CPDF_Dictionary> pDict) {
   const CPDF_Number* pLenObj = ToNumber(pDict->GetDirectObjectFor("Length"));
   FX_FILESIZE len = pLenObj ? pLenObj->GetInteger() : -1;
 
@@ -709,7 +708,7 @@
     }
   }
 
-  auto pStream = pdfium::MakeUnique<CPDF_Stream>();
+  auto pStream = pdfium::MakeRetain<CPDF_Stream>();
   if (data) {
     pStream->InitStreamFromFile(data, std::move(pDict));
   } else {
diff --git a/core/fpdfapi/parser/cpdf_syntax_parser.h b/core/fpdfapi/parser/cpdf_syntax_parser.h
index 53d0c12..14b5057 100644
--- a/core/fpdfapi/parser/cpdf_syntax_parser.h
+++ b/core/fpdfapi/parser/cpdf_syntax_parser.h
@@ -43,12 +43,10 @@
   FX_FILESIZE GetPos() const { return m_Pos; }
   void SetPos(FX_FILESIZE pos);
 
-  std::unique_ptr<CPDF_Object> GetObjectBody(
-      CPDF_IndirectObjectHolder* pObjList);
+  RetainPtr<CPDF_Object> GetObjectBody(CPDF_IndirectObjectHolder* pObjList);
 
-  std::unique_ptr<CPDF_Object> GetIndirectObject(
-      CPDF_IndirectObjectHolder* pObjList,
-      ParseType parse_type);
+  RetainPtr<CPDF_Object> GetIndirectObject(CPDF_IndirectObjectHolder* pObjList,
+                                           ParseType parse_type);
 
   ByteString GetKeyword();
   void ToNextLine();
@@ -95,12 +93,11 @@
   unsigned int ReadEOLMarkers(FX_FILESIZE pos);
   FX_FILESIZE FindWordPos(ByteStringView word);
   FX_FILESIZE FindStreamEndPos();
-  std::unique_ptr<CPDF_Stream> ReadStream(
-      std::unique_ptr<CPDF_Dictionary> pDict);
+  RetainPtr<CPDF_Stream> ReadStream(RetainPtr<CPDF_Dictionary> pDict);
 
   bool IsPositionRead(FX_FILESIZE pos) const;
 
-  std::unique_ptr<CPDF_Object> GetObjectBodyInternal(
+  RetainPtr<CPDF_Object> GetObjectBodyInternal(
       CPDF_IndirectObjectHolder* pObjList,
       ParseType parse_type);
 
diff --git a/core/fpdfapi/parser/cpdf_syntax_parser_unittest.cpp b/core/fpdfapi/parser/cpdf_syntax_parser_unittest.cpp
index 5b06d33..53f0a17 100644
--- a/core/fpdfapi/parser/cpdf_syntax_parser_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_syntax_parser_unittest.cpp
@@ -150,7 +150,7 @@
   static const uint8_t data[] = "4294967295 0 R";
   CPDF_SyntaxParser parser(pdfium::MakeRetain<CFX_ReadOnlyMemoryStream>(
       pdfium::make_span(data, 14)));
-  std::unique_ptr<CPDF_Object> ref = parser.GetObjectBody(nullptr);
+  RetainPtr<CPDF_Object> ref = parser.GetObjectBody(nullptr);
   EXPECT_FALSE(ref);
 }
 
diff --git a/core/fpdfapi/parser/fpdf_parser_decode_unittest.cpp b/core/fpdfapi/parser/fpdf_parser_decode_unittest.cpp
index d240599..171482e 100644
--- a/core/fpdfapi/parser/fpdf_parser_decode_unittest.cpp
+++ b/core/fpdfapi/parser/fpdf_parser_decode_unittest.cpp
@@ -13,101 +13,101 @@
 TEST(fpdf_parser_decode, ValidateDecoderPipeline) {
   {
     // Empty decoder list is always valid.
-    CPDF_Array decoders;
-    EXPECT_TRUE(ValidateDecoderPipeline(&decoders));
+    auto decoders = pdfium::MakeRetain<CPDF_Array>();
+    EXPECT_TRUE(ValidateDecoderPipeline(decoders.Get()));
   }
   {
     // 1 decoder is almost always valid.
-    CPDF_Array decoders;
-    decoders.AddNew<CPDF_Name>("FlateEncode");
-    EXPECT_TRUE(ValidateDecoderPipeline(&decoders));
+    auto decoders = pdfium::MakeRetain<CPDF_Array>();
+    decoders->AddNew<CPDF_Name>("FlateEncode");
+    EXPECT_TRUE(ValidateDecoderPipeline(decoders.Get()));
   }
   {
     // 1 decoder is almost always valid, even with an unknown decoder.
-    CPDF_Array decoders;
-    decoders.AddNew<CPDF_Name>("FooBar");
-    EXPECT_TRUE(ValidateDecoderPipeline(&decoders));
+    auto decoders = pdfium::MakeRetain<CPDF_Array>();
+    decoders->AddNew<CPDF_Name>("FooBar");
+    EXPECT_TRUE(ValidateDecoderPipeline(decoders.Get()));
   }
   {
     // Valid 2 decoder pipeline.
-    CPDF_Array decoders;
-    decoders.AddNew<CPDF_Name>("AHx");
-    decoders.AddNew<CPDF_Name>("LZWDecode");
-    EXPECT_TRUE(ValidateDecoderPipeline(&decoders));
+    auto decoders = pdfium::MakeRetain<CPDF_Array>();
+    decoders->AddNew<CPDF_Name>("AHx");
+    decoders->AddNew<CPDF_Name>("LZWDecode");
+    EXPECT_TRUE(ValidateDecoderPipeline(decoders.Get()));
   }
   {
     // Valid 2 decoder pipeline.
-    CPDF_Array decoders;
-    decoders.AddNew<CPDF_Name>("ASCII85Decode");
-    decoders.AddNew<CPDF_Name>("ASCII85Decode");
-    EXPECT_TRUE(ValidateDecoderPipeline(&decoders));
+    auto decoders = pdfium::MakeRetain<CPDF_Array>();
+    decoders->AddNew<CPDF_Name>("ASCII85Decode");
+    decoders->AddNew<CPDF_Name>("ASCII85Decode");
+    EXPECT_TRUE(ValidateDecoderPipeline(decoders.Get()));
   }
   {
     // Valid 5 decoder pipeline.
-    CPDF_Array decoders;
-    decoders.AddNew<CPDF_Name>("ASCII85Decode");
-    decoders.AddNew<CPDF_Name>("A85");
-    decoders.AddNew<CPDF_Name>("RunLengthDecode");
-    decoders.AddNew<CPDF_Name>("FlateDecode");
-    decoders.AddNew<CPDF_Name>("RL");
-    EXPECT_TRUE(ValidateDecoderPipeline(&decoders));
+    auto decoders = pdfium::MakeRetain<CPDF_Array>();
+    decoders->AddNew<CPDF_Name>("ASCII85Decode");
+    decoders->AddNew<CPDF_Name>("A85");
+    decoders->AddNew<CPDF_Name>("RunLengthDecode");
+    decoders->AddNew<CPDF_Name>("FlateDecode");
+    decoders->AddNew<CPDF_Name>("RL");
+    EXPECT_TRUE(ValidateDecoderPipeline(decoders.Get()));
   }
   {
     // Valid 5 decoder pipeline, with an image decoder at the end.
-    CPDF_Array decoders;
-    decoders.AddNew<CPDF_Name>("RunLengthDecode");
-    decoders.AddNew<CPDF_Name>("ASCII85Decode");
-    decoders.AddNew<CPDF_Name>("FlateDecode");
-    decoders.AddNew<CPDF_Name>("LZW");
-    decoders.AddNew<CPDF_Name>("DCTDecode");
-    EXPECT_TRUE(ValidateDecoderPipeline(&decoders));
+    auto decoders = pdfium::MakeRetain<CPDF_Array>();
+    decoders->AddNew<CPDF_Name>("RunLengthDecode");
+    decoders->AddNew<CPDF_Name>("ASCII85Decode");
+    decoders->AddNew<CPDF_Name>("FlateDecode");
+    decoders->AddNew<CPDF_Name>("LZW");
+    decoders->AddNew<CPDF_Name>("DCTDecode");
+    EXPECT_TRUE(ValidateDecoderPipeline(decoders.Get()));
   }
   {
     // Invalid 1 decoder pipeline due to wrong type.
-    CPDF_Array decoders;
-    decoders.AddNew<CPDF_String>("FlateEncode", false);
-    EXPECT_FALSE(ValidateDecoderPipeline(&decoders));
+    auto decoders = pdfium::MakeRetain<CPDF_Array>();
+    decoders->AddNew<CPDF_String>("FlateEncode", false);
+    EXPECT_FALSE(ValidateDecoderPipeline(decoders.Get()));
   }
   {
     // Invalid 2 decoder pipeline, with 2 image decoders.
-    CPDF_Array decoders;
-    decoders.AddNew<CPDF_Name>("DCTDecode");
-    decoders.AddNew<CPDF_Name>("CCITTFaxDecode");
-    EXPECT_FALSE(ValidateDecoderPipeline(&decoders));
+    auto decoders = pdfium::MakeRetain<CPDF_Array>();
+    decoders->AddNew<CPDF_Name>("DCTDecode");
+    decoders->AddNew<CPDF_Name>("CCITTFaxDecode");
+    EXPECT_FALSE(ValidateDecoderPipeline(decoders.Get()));
   }
   {
     // Invalid 2 decoder pipeline, with 1 image decoder at the start.
-    CPDF_Array decoders;
-    decoders.AddNew<CPDF_Name>("DCTDecode");
-    decoders.AddNew<CPDF_Name>("FlateDecode");
-    EXPECT_FALSE(ValidateDecoderPipeline(&decoders));
+    auto decoders = pdfium::MakeRetain<CPDF_Array>();
+    decoders->AddNew<CPDF_Name>("DCTDecode");
+    decoders->AddNew<CPDF_Name>("FlateDecode");
+    EXPECT_FALSE(ValidateDecoderPipeline(decoders.Get()));
   }
   {
     // Invalid 2 decoder pipeline due to wrong type.
-    CPDF_Array decoders;
-    decoders.AddNew<CPDF_String>("AHx", false);
-    decoders.AddNew<CPDF_Name>("LZWDecode");
-    EXPECT_FALSE(ValidateDecoderPipeline(&decoders));
+    auto decoders = pdfium::MakeRetain<CPDF_Array>();
+    decoders->AddNew<CPDF_String>("AHx", false);
+    decoders->AddNew<CPDF_Name>("LZWDecode");
+    EXPECT_FALSE(ValidateDecoderPipeline(decoders.Get()));
   }
   {
     // Invalid 5 decoder pipeline.
-    CPDF_Array decoders;
-    decoders.AddNew<CPDF_Name>("FlateDecode");
-    decoders.AddNew<CPDF_Name>("FlateDecode");
-    decoders.AddNew<CPDF_Name>("DCTDecode");
-    decoders.AddNew<CPDF_Name>("FlateDecode");
-    decoders.AddNew<CPDF_Name>("FlateDecode");
-    EXPECT_FALSE(ValidateDecoderPipeline(&decoders));
+    auto decoders = pdfium::MakeRetain<CPDF_Array>();
+    decoders->AddNew<CPDF_Name>("FlateDecode");
+    decoders->AddNew<CPDF_Name>("FlateDecode");
+    decoders->AddNew<CPDF_Name>("DCTDecode");
+    decoders->AddNew<CPDF_Name>("FlateDecode");
+    decoders->AddNew<CPDF_Name>("FlateDecode");
+    EXPECT_FALSE(ValidateDecoderPipeline(decoders.Get()));
   }
   {
     // Invalid 5 decoder pipeline due to wrong type.
-    CPDF_Array decoders;
-    decoders.AddNew<CPDF_Name>("ASCII85Decode");
-    decoders.AddNew<CPDF_Name>("A85");
-    decoders.AddNew<CPDF_Name>("RunLengthDecode");
-    decoders.AddNew<CPDF_Name>("FlateDecode");
-    decoders.AddNew<CPDF_String>("RL", false);
-    EXPECT_FALSE(ValidateDecoderPipeline(&decoders));
+    auto decoders = pdfium::MakeRetain<CPDF_Array>();
+    decoders->AddNew<CPDF_Name>("ASCII85Decode");
+    decoders->AddNew<CPDF_Name>("A85");
+    decoders->AddNew<CPDF_Name>("RunLengthDecode");
+    decoders->AddNew<CPDF_Name>("FlateDecode");
+    decoders->AddNew<CPDF_String>("RL", false);
+    EXPECT_FALSE(ValidateDecoderPipeline(decoders.Get()));
   }
 }
 
diff --git a/core/fpdfapi/parser/fpdf_parser_utility.cpp b/core/fpdfapi/parser/fpdf_parser_utility.cpp
index f607353..ec42087 100644
--- a/core/fpdfapi/parser/fpdf_parser_utility.cpp
+++ b/core/fpdfapi/parser/fpdf_parser_utility.cpp
@@ -196,7 +196,7 @@
       buf << "<<";
       for (const auto& it : locker) {
         const ByteString& key = it.first;
-        CPDF_Object* pValue = it.second.get();
+        CPDF_Object* pValue = it.second.Get();
         buf << "/" << PDF_NameEncode(key);
         if (pValue && !pValue->IsInline()) {
           buf << " " << pValue->GetObjNum() << " 0 R ";
diff --git a/core/fpdfapi/render/cpdf_docrenderdata_unittest.cpp b/core/fpdfapi/render/cpdf_docrenderdata_unittest.cpp
index dce0a83..69162f0 100644
--- a/core/fpdfapi/render/cpdf_docrenderdata_unittest.cpp
+++ b/core/fpdfapi/render/cpdf_docrenderdata_unittest.cpp
@@ -69,8 +69,8 @@
     26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
     26, 26, 26, 26, 26, 26, 26, 26, 26};
 
-std::unique_ptr<CPDF_Stream> CreateType0FunctionStream() {
-  auto func_dict = pdfium::MakeUnique<CPDF_Dictionary>();
+RetainPtr<CPDF_Stream> CreateType0FunctionStream() {
+  auto func_dict = pdfium::MakeRetain<CPDF_Dictionary>();
   func_dict->SetNewFor<CPDF_Number>("FunctionType", 0);
 
   CPDF_Array* domain_array = func_dict->SetNewFor<CPDF_Array>("Domain");
@@ -90,12 +90,12 @@
   size_t len = FX_ArraySize(content);
   std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_Alloc(uint8_t, len));
   memcpy(buf.get(), content, len);
-  return pdfium::MakeUnique<CPDF_Stream>(std::move(buf), len,
+  return pdfium::MakeRetain<CPDF_Stream>(std::move(buf), len,
                                          std::move(func_dict));
 }
 
-std::unique_ptr<CPDF_Dictionary> CreateType2FunctionDict() {
-  auto func_dict = pdfium::MakeUnique<CPDF_Dictionary>();
+RetainPtr<CPDF_Dictionary> CreateType2FunctionDict() {
+  auto func_dict = pdfium::MakeRetain<CPDF_Dictionary>();
   func_dict->SetNewFor<CPDF_Number>("FunctionType", 2);
   func_dict->SetNewFor<CPDF_Number>("N", 1);
 
@@ -116,8 +116,8 @@
   return func_dict;
 }
 
-std::unique_ptr<CPDF_Stream> CreateType4FunctionStream() {
-  auto func_dict = pdfium::MakeUnique<CPDF_Dictionary>();
+RetainPtr<CPDF_Stream> CreateType4FunctionStream() {
+  auto func_dict = pdfium::MakeRetain<CPDF_Dictionary>();
   func_dict->SetNewFor<CPDF_Number>("FunctionType", 4);
 
   CPDF_Array* domain_array = func_dict->SetNewFor<CPDF_Array>("Domain");
@@ -132,12 +132,12 @@
   size_t len = FX_ArraySize(content);
   std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_Alloc(uint8_t, len));
   memcpy(buf.get(), content, len);
-  return pdfium::MakeUnique<CPDF_Stream>(std::move(buf), len,
+  return pdfium::MakeRetain<CPDF_Stream>(std::move(buf), len,
                                          std::move(func_dict));
 }
 
-std::unique_ptr<CPDF_Stream> CreateBadType4FunctionStream() {
-  auto func_dict = pdfium::MakeUnique<CPDF_Dictionary>();
+RetainPtr<CPDF_Stream> CreateBadType4FunctionStream() {
+  auto func_dict = pdfium::MakeRetain<CPDF_Dictionary>();
   func_dict->SetNewFor<CPDF_Number>("FunctionType", 4);
 
   CPDF_Array* domain_array = func_dict->SetNewFor<CPDF_Array>("Domain");
@@ -152,7 +152,7 @@
   size_t len = FX_ArraySize(content);
   std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_Alloc(uint8_t, len));
   memcpy(buf.get(), content, len);
-  return pdfium::MakeUnique<CPDF_Stream>(std::move(buf), len,
+  return pdfium::MakeRetain<CPDF_Stream>(std::move(buf), len,
                                          std::move(func_dict));
 }
 
@@ -167,10 +167,10 @@
 };
 
 TEST(CPDF_DocRenderDataTest, TransferFunctionOne) {
-  std::unique_ptr<CPDF_Dictionary> func_dict = CreateType2FunctionDict();
+  RetainPtr<CPDF_Dictionary> func_dict = CreateType2FunctionDict();
 
   TestDocRenderData render_data;
-  auto func = render_data.CreateTransferFuncForTesting(func_dict.get());
+  auto func = render_data.CreateTransferFuncForTesting(func_dict.Get());
   ASSERT_TRUE(func);
   EXPECT_FALSE(func->GetIdentity());
 
@@ -200,13 +200,13 @@
 }
 
 TEST(CPDF_DocRenderDataTest, TransferFunctionArray) {
-  auto func_array = pdfium::MakeUnique<CPDF_Array>();
+  auto func_array = pdfium::MakeRetain<CPDF_Array>();
   func_array->Add(CreateType0FunctionStream());
   func_array->Add(CreateType2FunctionDict());
   func_array->Add(CreateType4FunctionStream());
 
   TestDocRenderData render_data;
-  auto func = render_data.CreateTransferFuncForTesting(func_array.get());
+  auto func = render_data.CreateTransferFuncForTesting(func_array.Get());
   ASSERT_TRUE(func);
   EXPECT_FALSE(func->GetIdentity());
 
@@ -240,26 +240,26 @@
     auto func_stream = CreateBadType4FunctionStream();
 
     TestDocRenderData render_data;
-    auto func = render_data.CreateTransferFuncForTesting(func_stream.get());
+    auto func = render_data.CreateTransferFuncForTesting(func_stream.Get());
     EXPECT_FALSE(func);
   }
 
   {
-    auto func_array = pdfium::MakeUnique<CPDF_Array>();
+    auto func_array = pdfium::MakeRetain<CPDF_Array>();
 
     TestDocRenderData render_data;
-    auto func = render_data.CreateTransferFuncForTesting(func_array.get());
+    auto func = render_data.CreateTransferFuncForTesting(func_array.Get());
     EXPECT_FALSE(func);
   }
 
   {
-    auto func_array = pdfium::MakeUnique<CPDF_Array>();
+    auto func_array = pdfium::MakeRetain<CPDF_Array>();
     func_array->Add(CreateType0FunctionStream());
     func_array->Add(CreateType2FunctionDict());
     func_array->Add(CreateBadType4FunctionStream());
 
     TestDocRenderData render_data;
-    auto func = render_data.CreateTransferFuncForTesting(func_array.get());
+    auto func = render_data.CreateTransferFuncForTesting(func_array.Get());
     EXPECT_FALSE(func);
   }
 }
diff --git a/core/fpdfdoc/cpdf_annot.cpp b/core/fpdfdoc/cpdf_annot.cpp
index 04029ac..adc6f53 100644
--- a/core/fpdfdoc/cpdf_annot.cpp
+++ b/core/fpdfdoc/cpdf_annot.cpp
@@ -92,7 +92,7 @@
 
 }  // namespace
 
-CPDF_Annot::CPDF_Annot(std::unique_ptr<CPDF_Dictionary> pDict,
+CPDF_Annot::CPDF_Annot(RetainPtr<CPDF_Dictionary> pDict,
                        CPDF_Document* pDocument)
     : m_pAnnotDict(std::move(pDict)), m_pDocument(pDocument) {
   Init();
diff --git a/core/fpdfdoc/cpdf_annot.h b/core/fpdfdoc/cpdf_annot.h
index 45d0e50..64ab69d 100644
--- a/core/fpdfdoc/cpdf_annot.h
+++ b/core/fpdfdoc/cpdf_annot.h
@@ -70,7 +70,7 @@
   static size_t QuadPointCount(const CPDF_Array* pArray);
 
   // The second constructor does not take ownership of the dictionary.
-  CPDF_Annot(std::unique_ptr<CPDF_Dictionary> pDict, CPDF_Document* pDocument);
+  CPDF_Annot(RetainPtr<CPDF_Dictionary> pDict, CPDF_Document* pDocument);
   CPDF_Annot(CPDF_Dictionary* pDict, CPDF_Document* pDocument);
   ~CPDF_Annot();
 
@@ -110,7 +110,7 @@
 
   CFX_FloatRect RectForDrawing() const;
 
-  MaybeOwned<CPDF_Dictionary> const m_pAnnotDict;
+  RetainPtr<CPDF_Dictionary> const m_pAnnotDict;
   UnownedPtr<CPDF_Document> const m_pDocument;
   CPDF_Annot::Subtype m_nSubtype;
   std::map<CPDF_Stream*, std::unique_ptr<CPDF_Form>> m_APMap;
diff --git a/core/fpdfdoc/cpdf_annot_unittest.cpp b/core/fpdfdoc/cpdf_annot_unittest.cpp
index 40817f4..a7625e9 100644
--- a/core/fpdfdoc/cpdf_annot_unittest.cpp
+++ b/core/fpdfdoc/cpdf_annot_unittest.cpp
@@ -14,9 +14,9 @@
 
 namespace {
 
-std::unique_ptr<CPDF_Array> CreateQuadPointArrayFromVector(
+RetainPtr<CPDF_Array> CreateQuadPointArrayFromVector(
     const std::vector<int>& points) {
-  auto array = pdfium::MakeUnique<CPDF_Array>();
+  auto array = pdfium::MakeRetain<CPDF_Array>();
   for (float point : points)
     array->AddNew<CPDF_Number>(point);
   return array;
@@ -25,15 +25,15 @@
 }  // namespace
 
 TEST(CPDFAnnotTest, RectFromQuadPointsArray) {
-  std::unique_ptr<CPDF_Array> array = CreateQuadPointArrayFromVector(
+  RetainPtr<CPDF_Array> array = CreateQuadPointArrayFromVector(
       {0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1});
-  CFX_FloatRect rect = CPDF_Annot::RectFromQuadPointsArray(array.get(), 0);
+  CFX_FloatRect rect = CPDF_Annot::RectFromQuadPointsArray(array.Get(), 0);
   EXPECT_EQ(4.0f, rect.left);
   EXPECT_EQ(5.0f, rect.bottom);
   EXPECT_EQ(2.0f, rect.right);
   EXPECT_EQ(3.0f, rect.top);
 
-  rect = CPDF_Annot::RectFromQuadPointsArray(array.get(), 1);
+  rect = CPDF_Annot::RectFromQuadPointsArray(array.Get(), 1);
   EXPECT_EQ(4.0f, rect.left);
   EXPECT_EQ(3.0f, rect.bottom);
   EXPECT_EQ(6.0f, rect.right);
@@ -41,32 +41,32 @@
 }
 
 TEST(CPDFAnnotTest, BoundingRectFromQuadPoints) {
-  CPDF_Dictionary dict;
-  CFX_FloatRect rect = CPDF_Annot::BoundingRectFromQuadPoints(&dict);
+  auto dict = pdfium::MakeRetain<CPDF_Dictionary>();
+  CFX_FloatRect rect = CPDF_Annot::BoundingRectFromQuadPoints(dict.Get());
   EXPECT_EQ(0.0f, rect.left);
   EXPECT_EQ(0.0f, rect.bottom);
   EXPECT_EQ(0.0f, rect.right);
   EXPECT_EQ(0.0f, rect.top);
 
-  dict.SetFor("QuadPoints", CreateQuadPointArrayFromVector({0, 1, 2}));
-  rect = CPDF_Annot::BoundingRectFromQuadPoints(&dict);
+  dict->SetFor("QuadPoints", CreateQuadPointArrayFromVector({0, 1, 2}));
+  rect = CPDF_Annot::BoundingRectFromQuadPoints(dict.Get());
   EXPECT_EQ(0.0f, rect.left);
   EXPECT_EQ(0.0f, rect.bottom);
   EXPECT_EQ(0.0f, rect.right);
   EXPECT_EQ(0.0f, rect.top);
 
-  dict.SetFor("QuadPoints",
-              CreateQuadPointArrayFromVector({0, 1, 2, 3, 4, 5, 6, 7}));
-  rect = CPDF_Annot::BoundingRectFromQuadPoints(&dict);
+  dict->SetFor("QuadPoints",
+               CreateQuadPointArrayFromVector({0, 1, 2, 3, 4, 5, 6, 7}));
+  rect = CPDF_Annot::BoundingRectFromQuadPoints(dict.Get());
   EXPECT_EQ(4.0f, rect.left);
   EXPECT_EQ(5.0f, rect.bottom);
   EXPECT_EQ(2.0f, rect.right);
   EXPECT_EQ(3.0f, rect.top);
 
-  dict.SetFor("QuadPoints", CreateQuadPointArrayFromVector(
-                                {0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5,
-                                 4, 3, 2, 1, 9, 2, 5, 7, 3, 6, 4, 1}));
-  rect = CPDF_Annot::BoundingRectFromQuadPoints(&dict);
+  dict->SetFor("QuadPoints", CreateQuadPointArrayFromVector(
+                                 {0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5,
+                                  4, 3, 2, 1, 9, 2, 5, 7, 3, 6, 4, 1}));
+  rect = CPDF_Annot::BoundingRectFromQuadPoints(dict.Get());
   EXPECT_EQ(2.0f, rect.left);
   EXPECT_EQ(3.0f, rect.bottom);
   EXPECT_EQ(6.0f, rect.right);
@@ -74,45 +74,45 @@
 }
 
 TEST(CPDFAnnotTest, RectFromQuadPoints) {
-  CPDF_Dictionary dict;
-  CFX_FloatRect rect = CPDF_Annot::RectFromQuadPoints(&dict, 0);
+  auto dict = pdfium::MakeRetain<CPDF_Dictionary>();
+  CFX_FloatRect rect = CPDF_Annot::RectFromQuadPoints(dict.Get(), 0);
   EXPECT_EQ(0.0f, rect.left);
   EXPECT_EQ(0.0f, rect.bottom);
   EXPECT_EQ(0.0f, rect.right);
   EXPECT_EQ(0.0f, rect.top);
-  rect = CPDF_Annot::RectFromQuadPoints(&dict, 5);
+  rect = CPDF_Annot::RectFromQuadPoints(dict.Get(), 5);
   EXPECT_EQ(0.0f, rect.left);
   EXPECT_EQ(0.0f, rect.bottom);
   EXPECT_EQ(0.0f, rect.right);
   EXPECT_EQ(0.0f, rect.top);
 
-  dict.SetFor("QuadPoints",
-              CreateQuadPointArrayFromVector({0, 1, 2, 3, 4, 5, 6, 7}));
-  rect = CPDF_Annot::RectFromQuadPoints(&dict, 0);
+  dict->SetFor("QuadPoints",
+               CreateQuadPointArrayFromVector({0, 1, 2, 3, 4, 5, 6, 7}));
+  rect = CPDF_Annot::RectFromQuadPoints(dict.Get(), 0);
   EXPECT_EQ(4.0f, rect.left);
   EXPECT_EQ(5.0f, rect.bottom);
   EXPECT_EQ(2.0f, rect.right);
   EXPECT_EQ(3.0f, rect.top);
-  rect = CPDF_Annot::RectFromQuadPoints(&dict, 5);
+  rect = CPDF_Annot::RectFromQuadPoints(dict.Get(), 5);
   EXPECT_EQ(0.0f, rect.left);
   EXPECT_EQ(0.0f, rect.bottom);
   EXPECT_EQ(0.0f, rect.right);
   EXPECT_EQ(0.0f, rect.top);
 
-  dict.SetFor("QuadPoints", CreateQuadPointArrayFromVector(
-                                {0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5,
-                                 4, 3, 2, 1, 9, 2, 5, 7, 3, 6, 4, 1}));
-  rect = CPDF_Annot::RectFromQuadPoints(&dict, 0);
+  dict->SetFor("QuadPoints", CreateQuadPointArrayFromVector(
+                                 {0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5,
+                                  4, 3, 2, 1, 9, 2, 5, 7, 3, 6, 4, 1}));
+  rect = CPDF_Annot::RectFromQuadPoints(dict.Get(), 0);
   EXPECT_EQ(4.0f, rect.left);
   EXPECT_EQ(5.0f, rect.bottom);
   EXPECT_EQ(2.0f, rect.right);
   EXPECT_EQ(3.0f, rect.top);
-  rect = CPDF_Annot::RectFromQuadPoints(&dict, 1);
+  rect = CPDF_Annot::RectFromQuadPoints(dict.Get(), 1);
   EXPECT_EQ(4.0f, rect.left);
   EXPECT_EQ(3.0f, rect.bottom);
   EXPECT_EQ(6.0f, rect.right);
   EXPECT_EQ(5.0f, rect.top);
-  rect = CPDF_Annot::RectFromQuadPoints(&dict, 2);
+  rect = CPDF_Annot::RectFromQuadPoints(dict.Get(), 2);
   EXPECT_EQ(3.0f, rect.left);
   EXPECT_EQ(6.0f, rect.bottom);
   EXPECT_EQ(5.0f, rect.right);
@@ -120,18 +120,18 @@
 }
 
 TEST(CPDFAnnotTest, QuadPointCount) {
-  std::unique_ptr<CPDF_Array> array = CreateQuadPointArrayFromVector({});
-  EXPECT_EQ(0u, CPDF_Annot::QuadPointCount(array.get()));
+  RetainPtr<CPDF_Array> array = CreateQuadPointArrayFromVector({});
+  EXPECT_EQ(0u, CPDF_Annot::QuadPointCount(array.Get()));
 
   for (int i = 0; i < 7; ++i) {
     array->AddNew<CPDF_Number>(0);
-    EXPECT_EQ(0u, CPDF_Annot::QuadPointCount(array.get()));
+    EXPECT_EQ(0u, CPDF_Annot::QuadPointCount(array.Get()));
   }
   for (int i = 0; i < 8; ++i) {
     array->AddNew<CPDF_Number>(0);
-    EXPECT_EQ(1u, CPDF_Annot::QuadPointCount(array.get()));
+    EXPECT_EQ(1u, CPDF_Annot::QuadPointCount(array.Get()));
   }
   for (int i = 0; i < 50; ++i)
     array->AddNew<CPDF_Number>(0);
-  EXPECT_EQ(8u, CPDF_Annot::QuadPointCount(array.get()));
+  EXPECT_EQ(8u, CPDF_Annot::QuadPointCount(array.Get()));
 }
diff --git a/core/fpdfdoc/cpdf_dest_unittest.cpp b/core/fpdfdoc/cpdf_dest_unittest.cpp
index a47c1ee..9c258e5 100644
--- a/core/fpdfdoc/cpdf_dest_unittest.cpp
+++ b/core/fpdfdoc/cpdf_dest_unittest.cpp
@@ -19,7 +19,7 @@
   float zoom;
 
   // |array| must outlive |dest|.
-  auto array = pdfium::MakeUnique<CPDF_Array>();
+  auto array = pdfium::MakeRetain<CPDF_Array>();
   array->AddNew<CPDF_Number>(0);  // Page Index.
   array->AddNew<CPDF_Name>("XYZ");
   array->AddNew<CPDF_Number>(4);  // X
@@ -29,13 +29,13 @@
   }
   {
     // Not enough entries.
-    auto dest = pdfium::MakeUnique<CPDF_Dest>(array.get());
+    auto dest = pdfium::MakeUnique<CPDF_Dest>(array.Get());
     EXPECT_FALSE(dest->GetXYZ(&hasX, &hasY, &hasZoom, &x, &y, &zoom));
   }
   array->AddNew<CPDF_Number>(5);  // Y
   array->AddNew<CPDF_Number>(6);  // Zoom.
   {
-    auto dest = pdfium::MakeUnique<CPDF_Dest>(array.get());
+    auto dest = pdfium::MakeUnique<CPDF_Dest>(array.Get());
     EXPECT_TRUE(dest->GetXYZ(&hasX, &hasY, &hasZoom, &x, &y, &zoom));
     EXPECT_TRUE(hasX);
     EXPECT_TRUE(hasY);
@@ -47,7 +47,7 @@
   // Set zoom to 0.
   array->SetNewAt<CPDF_Number>(4, 0);
   {
-    auto dest = pdfium::MakeUnique<CPDF_Dest>(array.get());
+    auto dest = pdfium::MakeUnique<CPDF_Dest>(array.Get());
     EXPECT_TRUE(dest->GetXYZ(&hasX, &hasY, &hasZoom, &x, &y, &zoom));
     EXPECT_FALSE(hasZoom);
   }
@@ -56,7 +56,7 @@
   array->SetNewAt<CPDF_Null>(3);
   array->SetNewAt<CPDF_Null>(4);
   {
-    auto dest = pdfium::MakeUnique<CPDF_Dest>(array.get());
+    auto dest = pdfium::MakeUnique<CPDF_Dest>(array.Get());
     EXPECT_TRUE(dest->GetXYZ(&hasX, &hasY, &hasZoom, &x, &y, &zoom));
     EXPECT_FALSE(hasX);
     EXPECT_FALSE(hasY);
diff --git a/core/fpdfdoc/cpdf_filespec_unittest.cpp b/core/fpdfdoc/cpdf_filespec_unittest.cpp
index e3149e9..bee6574 100644
--- a/core/fpdfdoc/cpdf_filespec_unittest.cpp
+++ b/core/fpdfdoc/cpdf_filespec_unittest.cpp
@@ -72,8 +72,8 @@
       L"/docs/test.pdf"
 #endif
     };
-    auto str_obj = pdfium::MakeUnique<CPDF_String>(nullptr, test_data.input);
-    CPDF_FileSpec file_spec(str_obj.get());
+    auto str_obj = pdfium::MakeRetain<CPDF_String>(nullptr, test_data.input);
+    CPDF_FileSpec file_spec(str_obj.Get());
     EXPECT_STREQ(test_data.expected, file_spec.GetFileName().c_str());
   }
   {
@@ -103,8 +103,8 @@
     const char* const keywords[] = {"Unix", "Mac", "DOS", "F", "UF"};
     static_assert(FX_ArraySize(test_data) == FX_ArraySize(keywords),
                   "size mismatch");
-    auto dict_obj = pdfium::MakeUnique<CPDF_Dictionary>();
-    CPDF_FileSpec file_spec(dict_obj.get());
+    auto dict_obj = pdfium::MakeRetain<CPDF_Dictionary>();
+    CPDF_FileSpec file_spec(dict_obj.Get());
     EXPECT_TRUE(file_spec.GetFileName().IsEmpty());
     for (size_t i = 0; i < FX_ArraySize(keywords); ++i) {
       dict_obj->SetNewFor<CPDF_String>(keywords[i], test_data[i].input);
@@ -118,8 +118,8 @@
   }
   {
     // Invalid object.
-    auto name_obj = pdfium::MakeUnique<CPDF_Name>(nullptr, "test.pdf");
-    CPDF_FileSpec file_spec(name_obj.get());
+    auto name_obj = pdfium::MakeRetain<CPDF_Name>(nullptr, "test.pdf");
+    CPDF_FileSpec file_spec(name_obj.Get());
     EXPECT_TRUE(file_spec.GetFileName().IsEmpty());
   }
 }
@@ -138,8 +138,8 @@
 #endif
   };
   // String object.
-  auto str_obj = pdfium::MakeUnique<CPDF_String>(nullptr, L"babababa");
-  CPDF_FileSpec file_spec1(str_obj.get());
+  auto str_obj = pdfium::MakeRetain<CPDF_String>(nullptr, L"babababa");
+  CPDF_FileSpec file_spec1(str_obj.Get());
   file_spec1.SetFileName(test_data.input);
   // Check internal object value.
   EXPECT_STREQ(test_data.expected, str_obj->GetUnicodeText().c_str());
@@ -147,8 +147,8 @@
   EXPECT_STREQ(test_data.input, file_spec1.GetFileName().c_str());
 
   // Dictionary object.
-  auto dict_obj = pdfium::MakeUnique<CPDF_Dictionary>();
-  CPDF_FileSpec file_spec2(dict_obj.get());
+  auto dict_obj = pdfium::MakeRetain<CPDF_Dictionary>();
+  CPDF_FileSpec file_spec2(dict_obj.Get());
   file_spec2.SetFileName(test_data.input);
   // Check internal object value.
   EXPECT_STREQ(test_data.expected, dict_obj->GetUnicodeTextFor("F").c_str());
@@ -160,28 +160,28 @@
 TEST(cpdf_filespec, GetFileStream) {
   {
     // Invalid object.
-    auto name_obj = pdfium::MakeUnique<CPDF_Name>(nullptr, "test.pdf");
-    CPDF_FileSpec file_spec(name_obj.get());
+    auto name_obj = pdfium::MakeRetain<CPDF_Name>(nullptr, "test.pdf");
+    CPDF_FileSpec file_spec(name_obj.Get());
     EXPECT_FALSE(file_spec.GetFileStream());
   }
   {
     // Dictionary object missing its embedded files dictionary.
-    auto dict_obj = pdfium::MakeUnique<CPDF_Dictionary>();
-    CPDF_FileSpec file_spec(dict_obj.get());
+    auto dict_obj = pdfium::MakeRetain<CPDF_Dictionary>();
+    CPDF_FileSpec file_spec(dict_obj.Get());
     EXPECT_FALSE(file_spec.GetFileStream());
   }
   {
     // Dictionary object with an empty embedded files dictionary.
-    auto dict_obj = pdfium::MakeUnique<CPDF_Dictionary>();
+    auto dict_obj = pdfium::MakeRetain<CPDF_Dictionary>();
     dict_obj->SetNewFor<CPDF_Dictionary>("EF");
-    CPDF_FileSpec file_spec(dict_obj.get());
+    CPDF_FileSpec file_spec(dict_obj.Get());
     EXPECT_FALSE(file_spec.GetFileStream());
   }
   {
     // Dictionary object with a non-empty embedded files dictionary.
-    auto dict_obj = pdfium::MakeUnique<CPDF_Dictionary>();
+    auto dict_obj = pdfium::MakeRetain<CPDF_Dictionary>();
     dict_obj->SetNewFor<CPDF_Dictionary>("EF");
-    CPDF_FileSpec file_spec(dict_obj.get());
+    CPDF_FileSpec file_spec(dict_obj.Get());
 
     const wchar_t file_name[] = L"test.pdf";
     const char* const keys[] = {"Unix", "Mac", "DOS", "F", "UF"};
@@ -196,7 +196,7 @@
       dict_obj->SetNewFor<CPDF_String>(keys[i], file_name);
 
       // Set the file stream.
-      auto pDict = pdfium::MakeUnique<CPDF_Dictionary>();
+      auto pDict = pdfium::MakeRetain<CPDF_Dictionary>();
       size_t buf_len = strlen(streams[i]) + 1;
       std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_Alloc(uint8_t, buf_len));
       memcpy(buf.get(), streams[i], buf_len);
@@ -219,22 +219,22 @@
 TEST(cpdf_filespec, GetParamsDict) {
   {
     // Invalid object.
-    auto name_obj = pdfium::MakeUnique<CPDF_Name>(nullptr, "test.pdf");
-    CPDF_FileSpec file_spec(name_obj.get());
+    auto name_obj = pdfium::MakeRetain<CPDF_Name>(nullptr, "test.pdf");
+    CPDF_FileSpec file_spec(name_obj.Get());
     EXPECT_FALSE(file_spec.GetParamsDict());
   }
   {
     // Dictionary object.
-    auto dict_obj = pdfium::MakeUnique<CPDF_Dictionary>();
+    auto dict_obj = pdfium::MakeRetain<CPDF_Dictionary>();
     dict_obj->SetNewFor<CPDF_Dictionary>("EF");
     dict_obj->SetNewFor<CPDF_String>("UF", L"test.pdf");
-    CPDF_FileSpec file_spec(dict_obj.get());
+    CPDF_FileSpec file_spec(dict_obj.Get());
     EXPECT_FALSE(file_spec.GetParamsDict());
 
     // Add a file stream to the embedded files dictionary.
     CPDF_Dictionary* file_dict =
         file_spec.GetObj()->AsDictionary()->GetDictFor("EF");
-    auto pDict = pdfium::MakeUnique<CPDF_Dictionary>();
+    auto pDict = pdfium::MakeRetain<CPDF_Dictionary>();
     std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_Alloc(uint8_t, 6));
     memcpy(buf.get(), "hello", 6);
     file_dict->SetNewFor<CPDF_Stream>("UF", std::move(buf), 6,
diff --git a/core/fpdfdoc/cpdf_formfield.cpp b/core/fpdfdoc/cpdf_formfield.cpp
index cb1344d..e3f2bd8 100644
--- a/core/fpdfdoc/cpdf_formfield.cpp
+++ b/core/fpdfdoc/cpdf_formfield.cpp
@@ -236,7 +236,7 @@
         return false;
       }
       if (pDV) {
-        std::unique_ptr<CPDF_Object> pClone = pDV->Clone();
+        RetainPtr<CPDF_Object> pClone = pDV->Clone();
         if (!pClone)
           return false;
 
@@ -329,7 +329,7 @@
   return pObj ? pObj->GetString() : ByteString();
 }
 
-void CPDF_FormField::SetOpt(std::unique_ptr<CPDF_Object> pOpt) {
+void CPDF_FormField::SetOpt(RetainPtr<CPDF_Object> pOpt) {
   m_pDict->SetFor("Opt", std::move(pOpt));
 }
 
@@ -637,7 +637,7 @@
   if (!pValue->IsArray())
     return;
 
-  auto pArray = pdfium::MakeUnique<CPDF_Array>();
+  auto pArray = pdfium::MakeRetain<CPDF_Array>();
   for (int i = 0; i < CountOptions(); i++) {
     if (i != index && IsItemSelected(i))
       pArray->AddNew<CPDF_String>(GetOptionValue(i));
diff --git a/core/fpdfdoc/cpdf_formfield.h b/core/fpdfdoc/cpdf_formfield.h
index 4937a37..8ce888f 100644
--- a/core/fpdfdoc/cpdf_formfield.h
+++ b/core/fpdfdoc/cpdf_formfield.h
@@ -168,7 +168,7 @@
 
   WideString GetCheckValue(bool bDefault) const;
 
-  void SetOpt(std::unique_ptr<CPDF_Object> pOpt);
+  void SetOpt(RetainPtr<CPDF_Object> pOpt);
 
  private:
   WideString GetValue(bool bDefault) const;
diff --git a/core/fpdfdoc/cpdf_interactiveform.cpp b/core/fpdfdoc/cpdf_interactiveform.cpp
index 6d8c3c8..b5616ec 100644
--- a/core/fpdfdoc/cpdf_interactiveform.cpp
+++ b/core/fpdfdoc/cpdf_interactiveform.cpp
@@ -933,7 +933,7 @@
     pField = newField.get();
     CPDF_Object* pTObj = pDict->GetObjectFor(pdfium::form_fields::kT);
     if (ToReference(pTObj)) {
-      std::unique_ptr<CPDF_Object> pClone = pTObj->CloneDirectObject();
+      RetainPtr<CPDF_Object> pClone = pTObj->CloneDirectObject();
       if (pClone)
         pDict->SetFor(pdfium::form_fields::kT, std::move(pClone));
       else
@@ -1035,7 +1035,7 @@
     } else {
       auto pNewDict = pDoc->New<CPDF_Dictionary>();
       pNewDict->SetNewFor<CPDF_Name>("Type", "Filespec");
-      CPDF_FileSpec filespec(pNewDict.get());
+      CPDF_FileSpec filespec(pNewDict.Get());
       filespec.SetFileName(pdf_path);
       pMainDict->SetFor("F", std::move(pNewDict));
     }
diff --git a/core/fpdfdoc/cpdf_metadata_unittest.cpp b/core/fpdfdoc/cpdf_metadata_unittest.cpp
index 9433162..41f4b5d 100644
--- a/core/fpdfdoc/cpdf_metadata_unittest.cpp
+++ b/core/fpdfdoc/cpdf_metadata_unittest.cpp
@@ -15,9 +15,9 @@
       "<adhocwf:version>1.1</adhocwf:version>\n"
       "</node>";
 
-  CPDF_Stream stream;
-  stream.SetData(ByteStringView(data).raw_span());
-  CPDF_Metadata metadata(&stream);
+  auto stream = pdfium::MakeRetain<CPDF_Stream>();
+  stream->SetData(ByteStringView(data).raw_span());
+  CPDF_Metadata metadata(stream.Get());
 
   auto results = metadata.CheckForSharedForm();
   ASSERT_EQ(1U, results.size());
@@ -32,9 +32,9 @@
       "<adhocwf:version>1.1</adhocwf:version>\n"
       "</node>";
 
-  CPDF_Stream stream;
-  stream.SetData(ByteStringView(data).raw_span());
-  CPDF_Metadata metadata(&stream);
+  auto stream = pdfium::MakeRetain<CPDF_Stream>();
+  stream->SetData(ByteStringView(data).raw_span());
+  CPDF_Metadata metadata(stream.Get());
 
   auto results = metadata.CheckForSharedForm();
   ASSERT_EQ(1U, results.size());
@@ -49,9 +49,9 @@
       "<adhocwf:version>1.1</adhocwf:version>\n"
       "</node>";
 
-  CPDF_Stream stream;
-  stream.SetData(ByteStringView(data).raw_span());
-  CPDF_Metadata metadata(&stream);
+  auto stream = pdfium::MakeRetain<CPDF_Stream>();
+  stream->SetData(ByteStringView(data).raw_span());
+  CPDF_Metadata metadata(stream.Get());
 
   auto results = metadata.CheckForSharedForm();
   ASSERT_EQ(1U, results.size());
@@ -66,9 +66,9 @@
       "<adhocwf:version>1.1</adhocwf:version>\n"
       "</node>";
 
-  CPDF_Stream stream;
-  stream.SetData(ByteStringView(data).raw_span());
-  CPDF_Metadata metadata(&stream);
+  auto stream = pdfium::MakeRetain<CPDF_Stream>();
+  stream->SetData(ByteStringView(data).raw_span());
+  CPDF_Metadata metadata(stream.Get());
 
   auto results = metadata.CheckForSharedForm();
   EXPECT_EQ(0U, results.size());
@@ -84,9 +84,9 @@
       "</node>"
       "</parent></grandparent>";
 
-  CPDF_Stream stream;
-  stream.SetData(ByteStringView(data).raw_span());
-  CPDF_Metadata metadata(&stream);
+  auto stream = pdfium::MakeRetain<CPDF_Stream>();
+  stream->SetData(ByteStringView(data).raw_span());
+  CPDF_Metadata metadata(stream.Get());
 
   auto results = metadata.CheckForSharedForm();
   ASSERT_EQ(1U, results.size());
@@ -98,9 +98,9 @@
       "<?xml charset=\"utf-8\"?>\n"
       "<node></node>";
 
-  CPDF_Stream stream;
-  stream.SetData(ByteStringView(data).raw_span());
-  CPDF_Metadata metadata(&stream);
+  auto stream = pdfium::MakeRetain<CPDF_Stream>();
+  stream->SetData(ByteStringView(data).raw_span());
+  CPDF_Metadata metadata(stream.Get());
 
   auto results = metadata.CheckForSharedForm();
   EXPECT_EQ(0U, results.size());
@@ -114,9 +114,9 @@
       "<adhocwf:version>1.1</adhocwf:version>\n"
       "</node>";
 
-  CPDF_Stream stream;
-  stream.SetData(ByteStringView(data).raw_span());
-  CPDF_Metadata metadata(&stream);
+  auto stream = pdfium::MakeRetain<CPDF_Stream>();
+  stream->SetData(ByteStringView(data).raw_span());
+  CPDF_Metadata metadata(stream.Get());
 
   auto results = metadata.CheckForSharedForm();
   EXPECT_EQ(0U, results.size());
@@ -144,9 +144,9 @@
       "</node3>"
       "</grandparent>";
 
-  CPDF_Stream stream;
-  stream.SetData(ByteStringView(data).raw_span());
-  CPDF_Metadata metadata(&stream);
+  auto stream = pdfium::MakeRetain<CPDF_Stream>();
+  stream->SetData(ByteStringView(data).raw_span());
+  CPDF_Metadata metadata(stream.Get());
 
   auto results = metadata.CheckForSharedForm();
   ASSERT_EQ(3U, results.size());
diff --git a/core/fpdfdoc/cpdf_nametree.cpp b/core/fpdfdoc/cpdf_nametree.cpp
index 3e13c85..de04ed7 100644
--- a/core/fpdfdoc/cpdf_nametree.cpp
+++ b/core/fpdfdoc/cpdf_nametree.cpp
@@ -328,7 +328,7 @@
   return nIndex;
 }
 
-bool CPDF_NameTree::AddValueAndName(std::unique_ptr<CPDF_Object> pObj,
+bool CPDF_NameTree::AddValueAndName(RetainPtr<CPDF_Object> pObj,
                                     const WideString& name) {
   if (!m_pRoot)
     return false;
diff --git a/core/fpdfdoc/cpdf_nametree.h b/core/fpdfdoc/cpdf_nametree.h
index 495798c..ea8c817 100644
--- a/core/fpdfdoc/cpdf_nametree.h
+++ b/core/fpdfdoc/cpdf_nametree.h
@@ -23,8 +23,7 @@
   CPDF_NameTree(CPDF_Document* pDoc, const ByteString& category);
   ~CPDF_NameTree();
 
-  bool AddValueAndName(std::unique_ptr<CPDF_Object> pObj,
-                       const WideString& name);
+  bool AddValueAndName(RetainPtr<CPDF_Object> pObj, const WideString& name);
   bool DeleteValueAndName(int nIndex);
 
   CPDF_Object* LookupValueAndName(int nIndex, WideString* csName) const;
diff --git a/core/fpdfdoc/cpdf_nametree_unittest.cpp b/core/fpdfdoc/cpdf_nametree_unittest.cpp
index 39e9dea..1a8086d 100644
--- a/core/fpdfdoc/cpdf_nametree_unittest.cpp
+++ b/core/fpdfdoc/cpdf_nametree_unittest.cpp
@@ -77,7 +77,7 @@
 
 TEST(cpdf_nametree, GetUnicodeNameWithBOM) {
   // Set up the root dictionary with a Names array.
-  auto pRootDict = pdfium::MakeUnique<CPDF_Dictionary>();
+  auto pRootDict = pdfium::MakeRetain<CPDF_Dictionary>();
   CPDF_Array* pNames = pRootDict->SetNewFor<CPDF_Array>("Names");
 
   // Add the key "1" (with BOM) and value 100 into the array.
@@ -89,7 +89,7 @@
   pNames->AddNew<CPDF_Number>(100);
 
   // Check that the key is as expected.
-  CPDF_NameTree nameTree(pRootDict.get());
+  CPDF_NameTree nameTree(pRootDict.Get());
   WideString storedName;
   nameTree.LookupValueAndName(0, &storedName);
   EXPECT_STREQ(L"1", storedName.c_str());
@@ -103,29 +103,29 @@
 
 TEST(cpdf_nametree, AddIntoNames) {
   // Set up a name tree with a single Names array.
-  auto pRootDict = pdfium::MakeUnique<CPDF_Dictionary>();
+  auto pRootDict = pdfium::MakeRetain<CPDF_Dictionary>();
   CPDF_Array* pNames = pRootDict->SetNewFor<CPDF_Array>("Names");
   AddNameKeyValue(pNames, "2.txt", 222);
   AddNameKeyValue(pNames, "7.txt", 777);
 
-  CPDF_NameTree nameTree(pRootDict.get());
+  CPDF_NameTree nameTree(pRootDict.Get());
   pNames = nameTree.GetRoot()->GetArrayFor("Names");
 
   // Insert a name that already exists in the names array.
   EXPECT_FALSE(
-      nameTree.AddValueAndName(pdfium::MakeUnique<CPDF_Number>(111), L"2.txt"));
+      nameTree.AddValueAndName(pdfium::MakeRetain<CPDF_Number>(111), L"2.txt"));
 
   // Insert in the beginning of the names array.
   EXPECT_TRUE(
-      nameTree.AddValueAndName(pdfium::MakeUnique<CPDF_Number>(111), L"1.txt"));
+      nameTree.AddValueAndName(pdfium::MakeRetain<CPDF_Number>(111), L"1.txt"));
 
   // Insert in the middle of the names array.
   EXPECT_TRUE(
-      nameTree.AddValueAndName(pdfium::MakeUnique<CPDF_Number>(555), L"5.txt"));
+      nameTree.AddValueAndName(pdfium::MakeRetain<CPDF_Number>(555), L"5.txt"));
 
   // Insert at the end of the names array.
   EXPECT_TRUE(
-      nameTree.AddValueAndName(pdfium::MakeUnique<CPDF_Number>(999), L"9.txt"));
+      nameTree.AddValueAndName(pdfium::MakeRetain<CPDF_Number>(999), L"9.txt"));
 
   // Check that the names array has the expected key-value pairs.
   CheckNameKeyValue(pNames, 0, "1.txt", 111);
@@ -137,35 +137,35 @@
 
 TEST(cpdf_nametree, AddIntoKids) {
   // Set up a name tree with five nodes of three levels.
-  auto pRootDict = pdfium::MakeUnique<CPDF_Dictionary>();
-  FillNameTreeDict(pRootDict.get());
-  CPDF_NameTree nameTree(pRootDict.get());
+  auto pRootDict = pdfium::MakeRetain<CPDF_Dictionary>();
+  FillNameTreeDict(pRootDict.Get());
+  CPDF_NameTree nameTree(pRootDict.Get());
 
   // Check that adding an existing name would fail.
   EXPECT_FALSE(
-      nameTree.AddValueAndName(pdfium::MakeUnique<CPDF_Number>(444), L"9.txt"));
+      nameTree.AddValueAndName(pdfium::MakeRetain<CPDF_Number>(444), L"9.txt"));
 
   // Add a name within the limits of a leaf node.
   EXPECT_TRUE(
-      nameTree.AddValueAndName(pdfium::MakeUnique<CPDF_Number>(444), L"4.txt"));
+      nameTree.AddValueAndName(pdfium::MakeRetain<CPDF_Number>(444), L"4.txt"));
   ASSERT_TRUE(nameTree.LookupValue(L"4.txt"));
   EXPECT_EQ(444, nameTree.LookupValue(L"4.txt")->GetInteger());
 
   // Add a name that requires changing the limits of two bottom levels.
   EXPECT_TRUE(
-      nameTree.AddValueAndName(pdfium::MakeUnique<CPDF_Number>(666), L"6.txt"));
+      nameTree.AddValueAndName(pdfium::MakeRetain<CPDF_Number>(666), L"6.txt"));
   ASSERT_TRUE(nameTree.LookupValue(L"6.txt"));
   EXPECT_EQ(666, nameTree.LookupValue(L"6.txt")->GetInteger());
 
   // Add a name that requires changing the limits of two top levels.
   EXPECT_TRUE(
-      nameTree.AddValueAndName(pdfium::MakeUnique<CPDF_Number>(99), L"99.txt"));
+      nameTree.AddValueAndName(pdfium::MakeRetain<CPDF_Number>(99), L"99.txt"));
   ASSERT_TRUE(nameTree.LookupValue(L"99.txt"));
   EXPECT_EQ(99, nameTree.LookupValue(L"99.txt")->GetInteger());
 
   // Add a name that requires changing the lower limit of all levels.
   EXPECT_TRUE(
-      nameTree.AddValueAndName(pdfium::MakeUnique<CPDF_Number>(-5), L"0.txt"));
+      nameTree.AddValueAndName(pdfium::MakeRetain<CPDF_Number>(-5), L"0.txt"));
   ASSERT_TRUE(nameTree.LookupValue(L"0.txt"));
   EXPECT_EQ(-5, nameTree.LookupValue(L"0.txt")->GetInteger());
 
@@ -211,9 +211,9 @@
 
 TEST(cpdf_nametree, DeleteFromKids) {
   // Set up a name tree with five nodes of three levels.
-  auto pRootDict = pdfium::MakeUnique<CPDF_Dictionary>();
-  FillNameTreeDict(pRootDict.get());
-  CPDF_NameTree nameTree(pRootDict.get());
+  auto pRootDict = pdfium::MakeRetain<CPDF_Dictionary>();
+  FillNameTreeDict(pRootDict.Get());
+  CPDF_NameTree nameTree(pRootDict.Get());
 
   // Retrieve the kid dictionaries.
   CPDF_Dictionary* pKid1 =
diff --git a/core/fpdfdoc/cpvt_generateap.cpp b/core/fpdfdoc/cpvt_generateap.cpp
index d9c2785..fdf2b26 100644
--- a/core/fpdfdoc/cpvt_generateap.cpp
+++ b/core/fpdfdoc/cpvt_generateap.cpp
@@ -398,7 +398,7 @@
   return ByteString(sAppStream);
 }
 
-std::unique_ptr<CPDF_Dictionary> GenerateResourceFontDict(
+RetainPtr<CPDF_Dictionary> GenerateResourceFontDict(
     CPDF_Document* pDoc,
     const ByteString& sFontDictName) {
   CPDF_Dictionary* pFontDict = pDoc->NewIndirect<CPDF_Dictionary>();
@@ -468,12 +468,12 @@
   return ByteString(sAppStream);
 }
 
-std::unique_ptr<CPDF_Dictionary> GenerateExtGStateDict(
+RetainPtr<CPDF_Dictionary> GenerateExtGStateDict(
     const CPDF_Dictionary& pAnnotDict,
     const ByteString& sExtGSDictName,
     const ByteString& sBlendMode) {
   auto pGSDict =
-      pdfium::MakeUnique<CPDF_Dictionary>(pAnnotDict.GetByteStringPool());
+      pdfium::MakeRetain<CPDF_Dictionary>(pAnnotDict.GetByteStringPool());
   pGSDict->SetNewFor<CPDF_Name>("Type", "ExtGState");
 
   float fOpacity =
@@ -484,15 +484,15 @@
   pGSDict->SetNewFor<CPDF_Name>("BM", sBlendMode);
 
   auto pExtGStateDict =
-      pdfium::MakeUnique<CPDF_Dictionary>(pAnnotDict.GetByteStringPool());
+      pdfium::MakeRetain<CPDF_Dictionary>(pAnnotDict.GetByteStringPool());
   pExtGStateDict->SetFor(sExtGSDictName, std::move(pGSDict));
   return pExtGStateDict;
 }
 
-std::unique_ptr<CPDF_Dictionary> GenerateResourceDict(
+RetainPtr<CPDF_Dictionary> GenerateResourceDict(
     CPDF_Document* pDoc,
-    std::unique_ptr<CPDF_Dictionary> pExtGStateDict,
-    std::unique_ptr<CPDF_Dictionary> pResourceFontDict) {
+    RetainPtr<CPDF_Dictionary> pExtGStateDict,
+    RetainPtr<CPDF_Dictionary> pResourceFontDict) {
   auto pResourceDict = pDoc->New<CPDF_Dictionary>();
   if (pExtGStateDict)
     pResourceDict->SetFor("ExtGState", std::move(pExtGStateDict));
@@ -504,7 +504,7 @@
 void GenerateAndSetAPDict(CPDF_Document* pDoc,
                           CPDF_Dictionary* pAnnotDict,
                           std::ostringstream* psAppStream,
-                          std::unique_ptr<CPDF_Dictionary> pResourceDict,
+                          RetainPtr<CPDF_Dictionary> pResourceDict,
                           bool bIsTextMarkupAnnotation) {
   CPDF_Stream* pNormalStream = pDoc->NewIndirect<CPDF_Stream>();
   pNormalStream->SetDataFromStringstream(psAppStream);
@@ -760,7 +760,7 @@
 
   ByteString sFontName = "FONT";
   auto pResourceFontDict = GenerateResourceFontDict(pDoc, sFontName);
-  CPDF_Font* pDefFont = pDoc->LoadFont(pResourceFontDict.get());
+  CPDF_Font* pDefFont = pDoc->LoadFont(pResourceFontDict.Get());
   if (!pDefFont)
     return false;
 
diff --git a/core/fxcodec/jbig2/JBig2_BitStream_unittest.cpp b/core/fxcodec/jbig2/JBig2_BitStream_unittest.cpp
index c9359f5..2dc6ca3 100644
--- a/core/fxcodec/jbig2/JBig2_BitStream_unittest.cpp
+++ b/core/fxcodec/jbig2/JBig2_BitStream_unittest.cpp
@@ -17,8 +17,8 @@
   std::unique_ptr<uint8_t, FxFreeDeleter> data(FX_Alloc(uint8_t, 1));
   data.get()[0] = 0xb1;  // 10110001
 
-  auto in_stream = pdfium::MakeUnique<CPDF_Stream>(std::move(data), 1, nullptr);
-  auto acc = pdfium::MakeRetain<CPDF_StreamAcc>(in_stream.get());
+  auto in_stream = pdfium::MakeRetain<CPDF_Stream>(std::move(data), 1, nullptr);
+  auto acc = pdfium::MakeRetain<CPDF_StreamAcc>(in_stream.Get());
   acc->LoadAllDataFiltered();
 
   CJBig2_BitStream stream(acc);
@@ -42,8 +42,8 @@
   std::unique_ptr<uint8_t, FxFreeDeleter> data(FX_Alloc(uint8_t, 1));
   data.get()[0] = 0xb1;
 
-  auto in_stream = pdfium::MakeUnique<CPDF_Stream>(std::move(data), 1, nullptr);
-  auto acc = pdfium::MakeRetain<CPDF_StreamAcc>(in_stream.get());
+  auto in_stream = pdfium::MakeRetain<CPDF_Stream>(std::move(data), 1, nullptr);
+  auto acc = pdfium::MakeRetain<CPDF_StreamAcc>(in_stream.Get());
   acc->LoadAllDataFiltered();
 
   CJBig2_BitStream stream(acc);
@@ -54,8 +54,8 @@
 }
 
 TEST(JBig2_BitStream, ReadNBitsNullStream) {
-  auto in_stream = pdfium::MakeUnique<CPDF_Stream>(nullptr, 0, nullptr);
-  auto acc = pdfium::MakeRetain<CPDF_StreamAcc>(in_stream.get());
+  auto in_stream = pdfium::MakeRetain<CPDF_Stream>(nullptr, 0, nullptr);
+  auto acc = pdfium::MakeRetain<CPDF_StreamAcc>(in_stream.Get());
   acc->LoadAllDataFiltered();
 
   CJBig2_BitStream stream(acc);
@@ -70,8 +70,8 @@
 TEST(JBig2_BitStream, ReadNBitsEmptyStream) {
   std::unique_ptr<uint8_t, FxFreeDeleter> data(FX_Alloc(uint8_t, 1));
 
-  auto in_stream = pdfium::MakeUnique<CPDF_Stream>(std::move(data), 0, nullptr);
-  auto acc = pdfium::MakeRetain<CPDF_StreamAcc>(in_stream.get());
+  auto in_stream = pdfium::MakeRetain<CPDF_Stream>(std::move(data), 0, nullptr);
+  auto acc = pdfium::MakeRetain<CPDF_StreamAcc>(in_stream.Get());
   acc->LoadAllDataFiltered();
 
   CJBig2_BitStream stream(acc);
@@ -87,8 +87,8 @@
   std::unique_ptr<uint8_t, FxFreeDeleter> data(FX_Alloc(uint8_t, 1));
   data.get()[0] = 0xb1;  // 10110001
 
-  auto in_stream = pdfium::MakeUnique<CPDF_Stream>(std::move(data), 1, nullptr);
-  auto acc = pdfium::MakeRetain<CPDF_StreamAcc>(in_stream.get());
+  auto in_stream = pdfium::MakeRetain<CPDF_Stream>(std::move(data), 1, nullptr);
+  auto acc = pdfium::MakeRetain<CPDF_StreamAcc>(in_stream.Get());
   acc->LoadAllDataFiltered();
 
   CJBig2_BitStream stream(acc);
@@ -108,8 +108,8 @@
   data.get()[3] = 0x00;
   data.get()[4] = 0x40;
 
-  auto in_stream = pdfium::MakeUnique<CPDF_Stream>(std::move(data), 5, nullptr);
-  auto acc = pdfium::MakeRetain<CPDF_StreamAcc>(in_stream.get());
+  auto in_stream = pdfium::MakeRetain<CPDF_Stream>(std::move(data), 5, nullptr);
+  auto acc = pdfium::MakeRetain<CPDF_StreamAcc>(in_stream.Get());
   acc->LoadAllDataFiltered();
 
   CJBig2_BitStream stream(acc);
diff --git a/core/fxcrt/cfx_seekablemultistream_unittest.cpp b/core/fxcrt/cfx_seekablemultistream_unittest.cpp
index 977563f..ad6fa2f 100644
--- a/core/fxcrt/cfx_seekablemultistream_unittest.cpp
+++ b/core/fxcrt/cfx_seekablemultistream_unittest.cpp
@@ -24,8 +24,8 @@
 
 TEST(CXFAFileReadTest, EmptyStreams) {
   std::vector<const CPDF_Stream*> streams;
-  auto stream1 = pdfium::MakeUnique<CPDF_Stream>();
-  streams.push_back(stream1.get());
+  auto stream1 = pdfium::MakeRetain<CPDF_Stream>();
+  streams.push_back(stream1.Get());
   auto fileread = pdfium::MakeRetain<CFX_SeekableMultiStream>(streams);
 
   uint8_t output_buffer[16];
@@ -36,21 +36,21 @@
 
 TEST(CXFAFileReadTest, NormalStreams) {
   std::vector<const CPDF_Stream*> streams;
-  auto stream1 = pdfium::MakeUnique<CPDF_Stream>();
-  auto stream2 = pdfium::MakeUnique<CPDF_Stream>();
-  auto stream3 = pdfium::MakeUnique<CPDF_Stream>();
+  auto stream1 = pdfium::MakeRetain<CPDF_Stream>();
+  auto stream2 = pdfium::MakeRetain<CPDF_Stream>();
+  auto stream3 = pdfium::MakeRetain<CPDF_Stream>();
 
   // 16 chars total.
   stream1->InitStream(ByteStringView("one t").raw_span(),
-                      pdfium::MakeUnique<CPDF_Dictionary>());
+                      pdfium::MakeRetain<CPDF_Dictionary>());
   stream2->InitStream(ByteStringView("wo ").raw_span(),
-                      pdfium::MakeUnique<CPDF_Dictionary>());
+                      pdfium::MakeRetain<CPDF_Dictionary>());
   stream3->InitStream(ByteStringView("three!!!").raw_span(),
-                      pdfium::MakeUnique<CPDF_Dictionary>());
+                      pdfium::MakeRetain<CPDF_Dictionary>());
 
-  streams.push_back(stream1.get());
-  streams.push_back(stream2.get());
-  streams.push_back(stream3.get());
+  streams.push_back(stream1.Get());
+  streams.push_back(stream2.Get());
+  streams.push_back(stream3.Get());
   auto fileread = pdfium::MakeRetain<CFX_SeekableMultiStream>(streams);
 
   uint8_t output_buffer[16];
diff --git a/core/fxge/dib/cstretchengine_unittest.cpp b/core/fxge/dib/cstretchengine_unittest.cpp
index 0400627..83f9b68 100644
--- a/core/fxge/dib/cstretchengine_unittest.cpp
+++ b/core/fxge/dib/cstretchengine_unittest.cpp
@@ -17,14 +17,13 @@
 
 TEST(CStretchEngine, OverflowInCtor) {
   FX_RECT clip_rect;
-  std::unique_ptr<CPDF_Dictionary> dict_obj =
-      pdfium::MakeUnique<CPDF_Dictionary>();
+  RetainPtr<CPDF_Dictionary> dict_obj = pdfium::MakeRetain<CPDF_Dictionary>();
   dict_obj->SetNewFor<CPDF_Number>("Width", 71000);
   dict_obj->SetNewFor<CPDF_Number>("Height", 12500);
-  std::unique_ptr<CPDF_Stream> stream =
-      pdfium::MakeUnique<CPDF_Stream>(nullptr, 0, std::move(dict_obj));
+  RetainPtr<CPDF_Stream> stream =
+      pdfium::MakeRetain<CPDF_Stream>(nullptr, 0, std::move(dict_obj));
   auto dib_source = pdfium::MakeRetain<CPDF_DIBBase>();
-  dib_source->Load(nullptr, stream.get());
+  dib_source->Load(nullptr, stream.Get());
   CStretchEngine engine(nullptr, FXDIB_8bppRgb, 500, 500, clip_rect, dib_source,
                         FXDIB_ResampleOptions());
   EXPECT_FALSE(engine.m_ResampleOptions.bInterpolateDownsample);
diff --git a/fpdfsdk/formfiller/cba_fontmap.cpp b/fpdfsdk/formfiller/cba_fontmap.cpp
index d286df6..66678a4 100644
--- a/fpdfsdk/formfiller/cba_fontmap.cpp
+++ b/fpdfsdk/formfiller/cba_fontmap.cpp
@@ -299,7 +299,7 @@
   CPDF_Dictionary* pStreamDict = pStream->GetDict();
   if (!pStreamDict) {
     auto pOwnedDict = m_pDocument->New<CPDF_Dictionary>();
-    pStreamDict = pOwnedDict.get();
+    pStreamDict = pOwnedDict.Get();
     pStream->InitStream({}, std::move(pOwnedDict));
   }
 
@@ -314,7 +314,7 @@
   }
   if (!pStreamResFontList->KeyExist(sAlias)) {
     CPDF_Dictionary* pFontDict = pFont->GetFontDict();
-    std::unique_ptr<CPDF_Object> pObject =
+    RetainPtr<CPDF_Object> pObject =
         pFontDict->IsInline() ? pFontDict->Clone()
                               : pFontDict->MakeReference(m_pDocument.Get());
     pStreamResFontList->SetFor(sAlias, std::move(pObject));
diff --git a/fpdfsdk/fpdf_annot.cpp b/fpdfsdk/fpdf_annot.cpp
index a829028..32e49df 100644
--- a/fpdfsdk/fpdf_annot.cpp
+++ b/fpdfsdk/fpdf_annot.cpp
@@ -239,7 +239,7 @@
   pDict->SetNewFor<CPDF_Name>(pdfium::annotation::kSubtype,
                               CPDF_Annot::AnnotSubtypeToString(
                                   static_cast<CPDF_Annot::Subtype>(subtype)));
-  auto pNewAnnot = pdfium::MakeUnique<CPDF_AnnotContext>(pDict.get(), pPage);
+  auto pNewAnnot = pdfium::MakeUnique<CPDF_AnnotContext>(pDict.Get(), pPage);
 
   CPDF_Array* pAnnotList = pPage->GetDict()->GetArrayFor("Annots");
   if (!pAnnotList)
@@ -294,11 +294,10 @@
     return -1;
 
   CPDF_ArrayLocker locker(pAnnots);
-  auto it =
-      std::find_if(locker.begin(), locker.end(),
-                   [pAnnotDict](const std::unique_ptr<CPDF_Object>& candidate) {
-                     return candidate->GetDirect() == pAnnotDict;
-                   });
+  auto it = std::find_if(locker.begin(), locker.end(),
+                         [pAnnotDict](const RetainPtr<CPDF_Object>& candidate) {
+                           return candidate->GetDirect() == pAnnotDict;
+                         });
 
   if (it == locker.end())
     return -1;
@@ -774,7 +773,7 @@
       pApDict = pAnnotDict->SetNewFor<CPDF_Dictionary>(pdfium::annotation::kAP);
 
     ByteString newValue = PDF_EncodeText(WideStringFromFPDFWideString(value));
-    auto pNewApStream = pdfium::MakeUnique<CPDF_Stream>();
+    auto pNewApStream = pdfium::MakeRetain<CPDF_Stream>();
     pNewApStream->SetData(newValue.AsRawSpan());
     pApDict->SetFor(modeKey, std::move(pNewApStream));
   } else {
diff --git a/fpdfsdk/fpdf_attachment.cpp b/fpdfsdk/fpdf_attachment.cpp
index 655d8cf..0ba0b1a 100644
--- a/fpdfsdk/fpdf_attachment.cpp
+++ b/fpdfsdk/fpdf_attachment.cpp
@@ -201,7 +201,8 @@
     CPDF_String* stringValue = pParamsDict->GetObjectFor(bsKey)->AsString();
     if (stringValue->IsHex()) {
       ByteString encoded = PDF_EncodeString(stringValue->GetString(), true);
-      value = CPDF_String(nullptr, encoded, false).GetUnicodeText();
+      value = pdfium::MakeRetain<CPDF_String>(nullptr, encoded, false)
+                  ->GetUnicodeText();
     }
   }
 
@@ -223,7 +224,7 @@
     return false;
 
   // Create a dictionary for the new embedded file stream.
-  auto pFileStreamDict = pdfium::MakeUnique<CPDF_Dictionary>();
+  auto pFileStreamDict = pdfium::MakeRetain<CPDF_Dictionary>();
   CPDF_Dictionary* pParamsDict =
       pFileStreamDict->SetNewFor<CPDF_Dictionary>("Params");
 
diff --git a/fpdfsdk/fpdf_catalog_unittest.cpp b/fpdfsdk/fpdf_catalog_unittest.cpp
index 7927c04..5c129ca 100644
--- a/fpdfsdk/fpdf_catalog_unittest.cpp
+++ b/fpdfsdk/fpdf_catalog_unittest.cpp
@@ -32,7 +32,7 @@
     CPDF_ModuleMgr::Get()->Init();
     auto pTestDoc = pdfium::MakeUnique<CPDF_TestDocument>();
     m_pDoc.reset(FPDFDocumentFromCPDFDocument(pTestDoc.release()));
-    m_pRootObj = pdfium::MakeUnique<CPDF_Dictionary>();
+    m_pRootObj = pdfium::MakeRetain<CPDF_Dictionary>();
   }
 
   void TearDown() override {
@@ -42,7 +42,7 @@
 
  protected:
   ScopedFPDFDocument m_pDoc;
-  std::unique_ptr<CPDF_Dictionary> m_pRootObj;
+  RetainPtr<CPDF_Dictionary> m_pRootObj;
 };
 
 TEST_F(PDFCatalogTest, IsTagged) {
@@ -57,7 +57,7 @@
   EXPECT_FALSE(FPDFCatalog_IsTagged(m_pDoc.get()));
 
   // Empty root
-  pTestDoc->SetRoot(m_pRootObj.get());
+  pTestDoc->SetRoot(m_pRootObj.Get());
   EXPECT_FALSE(FPDFCatalog_IsTagged(m_pDoc.get()));
 
   // Root with other key
diff --git a/fpdfsdk/fpdf_doc_unittest.cpp b/fpdfsdk/fpdf_doc_unittest.cpp
index aeca3de..8faa2d1 100644
--- a/fpdfsdk/fpdf_doc_unittest.cpp
+++ b/fpdfsdk/fpdf_doc_unittest.cpp
@@ -212,7 +212,7 @@
 }
 
 TEST_F(PDFDocTest, GetLocationInPage) {
-  auto array = pdfium::MakeUnique<CPDF_Array>();
+  auto array = pdfium::MakeRetain<CPDF_Array>();
   array->AddNew<CPDF_Number>(0);  // Page Index.
   array->AddNew<CPDF_Name>("XYZ");
   array->AddNew<CPDF_Number>(4);  // X
@@ -226,7 +226,7 @@
   FS_FLOAT y;
   FS_FLOAT zoom;
 
-  EXPECT_TRUE(FPDFDest_GetLocationInPage(FPDFDestFromCPDFArray(array.get()),
+  EXPECT_TRUE(FPDFDest_GetLocationInPage(FPDFDestFromCPDFArray(array.Get()),
                                          &hasX, &hasY, &hasZoom, &x, &y,
                                          &zoom));
   EXPECT_TRUE(hasX);
@@ -239,15 +239,15 @@
   array->SetNewAt<CPDF_Null>(2);
   array->SetNewAt<CPDF_Null>(3);
   array->SetNewAt<CPDF_Null>(4);
-  EXPECT_TRUE(FPDFDest_GetLocationInPage(FPDFDestFromCPDFArray(array.get()),
+  EXPECT_TRUE(FPDFDest_GetLocationInPage(FPDFDestFromCPDFArray(array.Get()),
                                          &hasX, &hasY, &hasZoom, &x, &y,
                                          &zoom));
   EXPECT_FALSE(hasX);
   EXPECT_FALSE(hasY);
   EXPECT_FALSE(hasZoom);
 
-  array = pdfium::MakeUnique<CPDF_Array>();
-  EXPECT_FALSE(FPDFDest_GetLocationInPage(FPDFDestFromCPDFArray(array.get()),
+  array = pdfium::MakeRetain<CPDF_Array>();
+  EXPECT_FALSE(FPDFDest_GetLocationInPage(FPDFDestFromCPDFArray(array.Get()),
                                           &hasX, &hasY, &hasZoom, &x, &y,
                                           &zoom));
 }
diff --git a/fpdfsdk/fpdf_editpage.cpp b/fpdfsdk/fpdf_editpage.cpp
index 09b287d..d55a451 100644
--- a/fpdfsdk/fpdf_editpage.cpp
+++ b/fpdfsdk/fpdf_editpage.cpp
@@ -118,7 +118,7 @@
   // If the Params dict does not exist, create a new one.
   if (!pParams) {
     auto new_dict = pDoc->New<CPDF_Dictionary>();
-    pParams = new_dict.get();
+    pParams = new_dict.Get();
     pMarkItem->SetDirectDict(std::move(new_dict));
   }
 
diff --git a/fpdfsdk/fpdf_edittext.cpp b/fpdfsdk/fpdf_edittext.cpp
index c744814..388f6bb 100644
--- a/fpdfsdk/fpdf_edittext.cpp
+++ b/fpdfsdk/fpdf_edittext.cpp
@@ -368,7 +368,7 @@
     int w = it->second;
     if (std::next(it) == widths.end()) {
       // Only one char left, use format c [w]
-      auto oneW = pdfium::MakeUnique<CPDF_Array>();
+      auto oneW = pdfium::MakeRetain<CPDF_Array>();
       oneW->AddNew<CPDF_Number>(w);
       widthsArray->AddNew<CPDF_Number>(ch);
       widthsArray->Add(std::move(oneW));
@@ -398,7 +398,7 @@
     // Otherwise we can have a group of the form c [w1 w2 ...]: c has width
     // w1, c+1 has width w2, etc.
     widthsArray->AddNew<CPDF_Number>(ch);
-    auto curWidthArray = pdfium::MakeUnique<CPDF_Array>();
+    auto curWidthArray = pdfium::MakeRetain<CPDF_Array>();
     curWidthArray->AddNew<CPDF_Number>(w);
     curWidthArray->AddNew<CPDF_Number>(next_w);
     while (true) {
@@ -413,7 +413,7 @@
   pCIDFont->SetFor("W", widthsArray->MakeReference(pDoc));
   // TODO(npm): Support vertical writing
 
-  auto pDescendant = pdfium::MakeUnique<CPDF_Array>();
+  auto pDescendant = pdfium::MakeRetain<CPDF_Array>();
   pDescendant->Add(pCIDFont->MakeReference(pDoc));
   pFontDict->SetFor("DescendantFonts", std::move(pDescendant));
   CPDF_Stream* toUnicodeStream = LoadUnicode(pDoc, to_unicode);
diff --git a/fpdfsdk/fpdf_flatten.cpp b/fpdfsdk/fpdf_flatten.cpp
index 50b94c2..5128e22 100644
--- a/fpdfsdk/fpdf_flatten.cpp
+++ b/fpdfsdk/fpdf_flatten.cpp
@@ -349,7 +349,7 @@
       } else {
         if (pAPDict->size() > 0) {
           CPDF_DictionaryLocker locker(pAPDict);
-          CPDF_Object* pFirstObj = locker.begin()->second.get();
+          CPDF_Object* pFirstObj = locker.begin()->second.Get();
           if (pFirstObj) {
             if (pFirstObj->IsReference())
               pFirstObj = pFirstObj->GetDirect();
@@ -376,8 +376,8 @@
 
     CPDF_Object* pObj = pAPStream;
     if (pObj->IsInline()) {
-      std::unique_ptr<CPDF_Object> pNew = pObj->Clone();
-      pObj = pNew.get();
+      RetainPtr<CPDF_Object> pNew = pObj->Clone();
+      pObj = pNew.Get();
       pDocument->AddIndirectObject(std::move(pNew));
     }
 
diff --git a/fpdfsdk/fpdf_ppo.cpp b/fpdfsdk/fpdf_ppo.cpp
index b9200b9..8285e30 100644
--- a/fpdfsdk/fpdf_ppo.cpp
+++ b/fpdfsdk/fpdf_ppo.cpp
@@ -365,7 +365,7 @@
           const ByteString& key = it.first;
           if (key == "Parent" || key == "Prev" || key == "First")
             continue;
-          CPDF_Object* pNextObj = it.second.get();
+          CPDF_Object* pNextObj = it.second.Get();
           if (!pNextObj)
             return false;
           if (!UpdateReference(pNextObj))
@@ -411,7 +411,7 @@
   if (!pDirect)
     return 0;
 
-  std::unique_ptr<CPDF_Object> pClone = pDirect->Clone();
+  RetainPtr<CPDF_Object> pClone = pDirect->Clone();
   if (CPDF_Dictionary* pDictClone = pClone->AsDictionary()) {
     if (pDictClone->KeyExist("Type")) {
       ByteString strType = pDictClone->GetStringFor("Type");
@@ -471,7 +471,7 @@
         continue;
       }
 
-      CPDF_Object* pObj = it.second.get();
+      CPDF_Object* pObj = it.second.Get();
       pDestPageDict->SetFor(cbSrcKeyStr, pObj->Clone());
     }
 
diff --git a/fpdfsdk/fpdf_transformpage.cpp b/fpdfsdk/fpdf_transformpage.cpp
index f6cabcd..ced87f2 100644
--- a/fpdfsdk/fpdf_transformpage.cpp
+++ b/fpdfsdk/fpdf_transformpage.cpp
@@ -226,7 +226,7 @@
 
   CPDF_DictionaryLocker locker(pPatternDict);
   for (const auto& it : locker) {
-    CPDF_Object* pObj = it.second.get();
+    CPDF_Object* pObj = it.second.Get();
     if (pObj->IsReference())
       pObj = pObj->GetDirect();
 
diff --git a/fpdfsdk/fpdf_view.cpp b/fpdfsdk/fpdf_view.cpp
index 8c49acf..f9bc6c0 100644
--- a/fpdfsdk/fpdf_view.cpp
+++ b/fpdfsdk/fpdf_view.cpp
@@ -1154,7 +1154,7 @@
     CPDF_DictionaryLocker locker(pDest);
     for (const auto& it : locker) {
       bsName = it.first.AsStringView();
-      pDestObj = it.second.get();
+      pDestObj = it.second.Get();
       if (!pDestObj)
         continue;
       if (i == index)
diff --git a/fpdfsdk/pwl/cpwl_appstream.cpp b/fpdfsdk/pwl/cpwl_appstream.cpp
index fc1e6f1..ce6d3fb 100644
--- a/fpdfsdk/pwl/cpwl_appstream.cpp
+++ b/fpdfsdk/pwl/cpwl_appstream.cpp
@@ -1932,7 +1932,7 @@
   if (!pStreamDict) {
     auto pNewDict =
         widget_->GetPDFAnnot()->GetDocument()->New<CPDF_Dictionary>();
-    pStreamDict = pNewDict.get();
+    pStreamDict = pNewDict.Get();
     pStreamDict->SetNewFor<CPDF_Name>("Type", "XObject");
     pStreamDict->SetNewFor<CPDF_Name>("Subtype", "Form");
     pStreamDict->SetNewFor<CPDF_Number>("FormType", 1);
diff --git a/fxjs/cjs_document.cpp b/fxjs/cjs_document.cpp
index 606ac4c..c93ee78 100644
--- a/fxjs/cjs_document.cpp
+++ b/fxjs/cjs_document.cpp
@@ -750,10 +750,10 @@
 
   // PutObjectProperty() calls below may re-enter JS and change info dict.
   auto pCopy = pDictionary->Clone();
-  CPDF_DictionaryLocker locker(ToDictionary(pCopy.get()));
+  CPDF_DictionaryLocker locker(ToDictionary(pCopy.Get()));
   for (const auto& it : locker) {
     const ByteString& bsKey = it.first;
-    CPDF_Object* pValueObj = it.second.get();
+    CPDF_Object* pValueObj = it.second.Get();
     if (pValueObj->IsString() || pValueObj->IsName()) {
       pRuntime->PutObjectProperty(
           pObj, bsKey.AsStringView(),
diff --git a/testing/fuzzers/pdf_codec_jbig2_fuzzer.cc b/testing/fuzzers/pdf_codec_jbig2_fuzzer.cc
index c218a27..82afa20 100644
--- a/testing/fuzzers/pdf_codec_jbig2_fuzzer.cc
+++ b/testing/fuzzers/pdf_codec_jbig2_fuzzer.cc
@@ -37,7 +37,7 @@
   if (!bitmap->Create(width, height, FXDIB_1bppRgb))
     return 0;
 
-  auto stream = pdfium::MakeUnique<CPDF_Stream>();
+  auto stream = pdfium::MakeRetain<CPDF_Stream>();
   stream->AsStream()->SetData({data, size});
 
   auto src_stream = pdfium::MakeRetain<CPDF_StreamAcc>(stream->AsStream());
diff --git a/testing/fuzzers/pdf_hint_table_fuzzer.cc b/testing/fuzzers/pdf_hint_table_fuzzer.cc
index 19b18ac..1540074 100644
--- a/testing/fuzzers/pdf_hint_table_fuzzer.cc
+++ b/testing/fuzzers/pdf_hint_table_fuzzer.cc
@@ -62,7 +62,7 @@
 
   const int32_t* data32 = reinterpret_cast<const int32_t*>(data);
 
-  auto linearized_dict = pdfium::MakeUnique<CPDF_Dictionary>();
+  auto linearized_dict = pdfium::MakeRetain<CPDF_Dictionary>();
   // Set initial value.
   linearized_dict->SetNewFor<CPDF_Boolean>("Linearized", true);
   // Set first page end offset
@@ -74,7 +74,7 @@
   // Set first page no
   linearized_dict->SetNewFor<CPDF_Number>("P", GetData(&data32, &data, &size));
 
-  auto hint_info = pdfium::MakeUnique<CPDF_Array>();
+  auto hint_info = pdfium::MakeRetain<CPDF_Array>();
   // Add primary hint stream offset
   hint_info->AddNew<CPDF_Number>(GetData(&data32, &data, &size));
   // Add primary hint stream size
@@ -85,7 +85,7 @@
   const int shared_hint_table_offset = GetData(&data32, &data, &size);
 
   {
-    FakeLinearized linearized(linearized_dict.get());
+    FakeLinearized linearized(linearized_dict.Get());
     HintTableForFuzzing hint_table(&linearized, shared_hint_table_offset);
     hint_table.Fuzz(data, size);
   }
diff --git a/testing/fuzzers/pdf_streamparser_fuzzer.cc b/testing/fuzzers/pdf_streamparser_fuzzer.cc
index 4d9a368..2bbda5e 100644
--- a/testing/fuzzers/pdf_streamparser_fuzzer.cc
+++ b/testing/fuzzers/pdf_streamparser_fuzzer.cc
@@ -11,8 +11,7 @@
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
   CPDF_StreamParser parser(pdfium::make_span(data, size));
-  while (std::unique_ptr<CPDF_Object> pObj =
-             parser.ReadNextObject(true, false, 0))
+  while (RetainPtr<CPDF_Object> pObj = parser.ReadNextObject(true, false, 0))
     continue;
 
   return 0;
diff --git a/xfa/fgas/font/cfgas_pdffontmgr.cpp b/xfa/fgas/font/cfgas_pdffontmgr.cpp
index bf4e83a..9c504d2 100644
--- a/xfa/fgas/font/cfgas_pdffontmgr.cpp
+++ b/xfa/fgas/font/cfgas_pdffontmgr.cpp
@@ -53,7 +53,7 @@
   CPDF_DictionaryLocker locker(pFontSetDict);
   for (const auto& it : locker) {
     const ByteString& key = it.first;
-    CPDF_Object* pObj = it.second.get();
+    CPDF_Object* pObj = it.second.Get();
     if (!PsNameMatchDRFontName(name.AsStringView(), bBold, bItalic, key,
                                bStrictMatch)) {
       continue;