Make CCodec_ModuleMgr a per-process singleton.

Avoids some layering violatons at the cost of having global
singletons.

Change-Id: Idb23f77b657573f30406b32379268c7e81d56f35
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/55410
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/cpdf_modulemgr.cpp b/core/fpdfapi/cpdf_modulemgr.cpp
index 494b2fc..7b9f8f6 100644
--- a/core/fpdfapi/cpdf_modulemgr.cpp
+++ b/core/fpdfapi/cpdf_modulemgr.cpp
@@ -15,22 +15,6 @@
 #include "core/fxcodec/fx_codec.h"
 #include "third_party/base/ptr_util.h"
 
-#ifdef PDF_ENABLE_XFA_BMP
-#include "core/fxcodec/codec/ccodec_bmpmodule.h"
-#endif
-
-#ifdef PDF_ENABLE_XFA_GIF
-#include "core/fxcodec/codec/ccodec_gifmodule.h"
-#endif
-
-#ifdef PDF_ENABLE_XFA_PNG
-#include "core/fxcodec/codec/ccodec_pngmodule.h"
-#endif
-
-#ifdef PDF_ENABLE_XFA_TIFF
-#include "core/fxcodec/codec/ccodec_tiffmodule.h"
-#endif
-
 namespace {
 
 CPDF_ModuleMgr* g_pDefaultMgr = nullptr;
@@ -41,15 +25,15 @@
 void CPDF_ModuleMgr::Create() {
   ASSERT(!g_pDefaultMgr);
   g_pDefaultMgr = new CPDF_ModuleMgr;
-  g_pDefaultMgr->InitCodecModule();
+  CCodec_ModuleMgr::Create();
   g_pDefaultMgr->InitPageModule();
   g_pDefaultMgr->LoadEmbeddedMaps();
-  g_pDefaultMgr->LoadCodecModules();
 }
 
 // static
 void CPDF_ModuleMgr::Destroy() {
   ASSERT(g_pDefaultMgr);
+  CCodec_ModuleMgr::Destroy();
   delete g_pDefaultMgr;
   g_pDefaultMgr = nullptr;
 }
@@ -64,40 +48,10 @@
 
 CPDF_ModuleMgr::~CPDF_ModuleMgr() = default;
 
-CCodec_JpegModule* CPDF_ModuleMgr::GetJpegModule() {
-  return m_pCodecModule->GetJpegModule();
-}
-
-CCodec_Jbig2Module* CPDF_ModuleMgr::GetJbig2Module() {
-  return m_pCodecModule->GetJbig2Module();
-}
-
 void CPDF_ModuleMgr::InitPageModule() {
   m_pPageModule = pdfium::MakeUnique<CPDF_PageModule>();
 }
 
-void CPDF_ModuleMgr::InitCodecModule() {
-  m_pCodecModule = pdfium::MakeUnique<CCodec_ModuleMgr>();
-}
-
-void CPDF_ModuleMgr::LoadCodecModules() {
-#ifdef PDF_ENABLE_XFA_BMP
-  m_pCodecModule->SetBmpModule(pdfium::MakeUnique<CCodec_BmpModule>());
-#endif
-
-#ifdef PDF_ENABLE_XFA_GIF
-  m_pCodecModule->SetGifModule(pdfium::MakeUnique<CCodec_GifModule>());
-#endif
-
-#ifdef PDF_ENABLE_XFA_PNG
-  m_pCodecModule->SetPngModule(pdfium::MakeUnique<CCodec_PngModule>());
-#endif
-
-#ifdef PDF_ENABLE_XFA_TIFF
-  m_pCodecModule->SetTiffModule(pdfium::MakeUnique<CCodec_TiffModule>());
-#endif
-}
-
 void CPDF_ModuleMgr::LoadEmbeddedMaps() {
   LoadEmbeddedGB1CMaps();
   LoadEmbeddedCNS1CMaps();
diff --git a/core/fpdfapi/cpdf_modulemgr.h b/core/fpdfapi/cpdf_modulemgr.h
index e4793a9..f768d19 100644
--- a/core/fpdfapi/cpdf_modulemgr.h
+++ b/core/fpdfapi/cpdf_modulemgr.h
@@ -10,10 +10,6 @@
 #include <memory>
 #include <utility>
 
-class CCodec_FlateModule;
-class CCodec_Jbig2Module;
-class CCodec_JpegModule;
-class CCodec_ModuleMgr;
 class CPDF_PageModule;
 
 namespace fpdfapi {
@@ -45,27 +41,19 @@
     return m_pUnsupportInfoAdapter.get();
   }
 
-  CCodec_ModuleMgr* GetCodecModule() const { return m_pCodecModule.get(); }
   CPDF_PageModule* GetPageModule() const { return m_pPageModule.get(); }
 
-  CCodec_JpegModule* GetJpegModule();
-  CCodec_Jbig2Module* GetJbig2Module();
-  CCodec_FlateModule* GetFlateModule();
-
  private:
   CPDF_ModuleMgr();
   ~CPDF_ModuleMgr();
 
   void InitPageModule();
-  void InitCodecModule();
-  void LoadCodecModules();
   void LoadEmbeddedMaps();
   void LoadEmbeddedGB1CMaps();
   void LoadEmbeddedCNS1CMaps();
   void LoadEmbeddedJapan1CMaps();
   void LoadEmbeddedKorea1CMaps();
 
-  std::unique_ptr<CCodec_ModuleMgr> m_pCodecModule;
   std::unique_ptr<CPDF_PageModule> m_pPageModule;
   std::unique_ptr<fpdfapi::UnsupportedInfoAdapter> m_pUnsupportInfoAdapter;
 };
diff --git a/core/fpdfapi/page/cpdf_docpagedata.cpp b/core/fpdfapi/page/cpdf_docpagedata.cpp
index b311192..452f1a0 100644
--- a/core/fpdfapi/page/cpdf_docpagedata.cpp
+++ b/core/fpdfapi/page/cpdf_docpagedata.cpp
@@ -12,7 +12,6 @@
 #include <utility>
 
 #include "core/fdrm/fx_crypt.h"
-#include "core/fpdfapi/cpdf_modulemgr.h"
 #include "core/fpdfapi/font/cpdf_type1font.h"
 #include "core/fpdfapi/page/cpdf_iccprofile.h"
 #include "core/fpdfapi/page/cpdf_image.h"
diff --git a/core/fpdfapi/page/cpdf_image.cpp b/core/fpdfapi/page/cpdf_image.cpp
index 1d01edb..322666f 100644
--- a/core/fpdfapi/page/cpdf_image.cpp
+++ b/core/fpdfapi/page/cpdf_image.cpp
@@ -12,7 +12,6 @@
 #include <vector>
 
 #include "constants/stream_dict_common.h"
-#include "core/fpdfapi/cpdf_modulemgr.h"
 #include "core/fpdfapi/page/cpdf_page.h"
 #include "core/fpdfapi/parser/cpdf_array.h"
 #include "core/fpdfapi/parser/cpdf_boolean.h"
@@ -26,6 +25,7 @@
 #include "core/fpdfapi/render/cpdf_dibbase.h"
 #include "core/fpdfapi/render/cpdf_pagerendercache.h"
 #include "core/fxcodec/codec/ccodec_jpegmodule.h"
+#include "core/fxcodec/fx_codec.h"
 #include "core/fxcrt/fx_stream.h"
 #include "core/fxge/dib/cfx_dibitmap.h"
 #include "core/fxge/fx_dib.h"
@@ -88,7 +88,7 @@
   int32_t num_comps;
   int32_t bits;
   bool color_trans;
-  if (!CPDF_ModuleMgr::Get()->GetJpegModule()->LoadInfo(
+  if (!CCodec_ModuleMgr::GetInstance()->GetJpegModule()->LoadInfo(
           src_span, &width, &height, &num_comps, &bits, &color_trans)) {
     return nullptr;
   }
diff --git a/core/fpdfapi/page/cpdf_streamparser.cpp b/core/fpdfapi/page/cpdf_streamparser.cpp
index f7f18c1..3b34131 100644
--- a/core/fpdfapi/page/cpdf_streamparser.cpp
+++ b/core/fpdfapi/page/cpdf_streamparser.cpp
@@ -14,7 +14,6 @@
 #include <utility>
 
 #include "constants/stream_dict_common.h"
-#include "core/fpdfapi/cpdf_modulemgr.h"
 #include "core/fpdfapi/page/cpdf_docpagedata.h"
 #include "core/fpdfapi/parser/cpdf_array.h"
 #include "core/fpdfapi/parser/cpdf_boolean.h"
@@ -93,7 +92,7 @@
   }
   if (decoder == "DCTDecode") {
     std::unique_ptr<CCodec_ScanlineDecoder> pDecoder =
-        CPDF_ModuleMgr::Get()->GetJpegModule()->CreateDecoder(
+        CCodec_ModuleMgr::GetInstance()->GetJpegModule()->CreateDecoder(
             src_span, width, height, 0,
             !pParam || pParam->GetIntegerFor("ColorTransform", 1));
     return DecodeAllScanlines(std::move(pDecoder));
diff --git a/core/fpdfapi/render/cpdf_dibbase.cpp b/core/fpdfapi/render/cpdf_dibbase.cpp
index e82ce3c..4a39067 100644
--- a/core/fpdfapi/render/cpdf_dibbase.cpp
+++ b/core/fpdfapi/render/cpdf_dibbase.cpp
@@ -283,7 +283,8 @@
     return LoadState::kFail;
 
   FXCODEC_STATUS iDecodeStatus;
-  CCodec_Jbig2Module* pJbig2Module = CPDF_ModuleMgr::Get()->GetJbig2Module();
+  CCodec_Jbig2Module* pJbig2Module =
+      CCodec_ModuleMgr::GetInstance()->GetJbig2Module();
   if (!m_pJbig2Context) {
     m_pJbig2Context = pdfium::MakeUnique<CCodec_Jbig2Context>();
     if (m_pStreamAcc->GetImageParam()) {
@@ -512,7 +513,8 @@
 
 bool CPDF_DIBBase::CreateDCTDecoder(pdfium::span<const uint8_t> src_span,
                                     const CPDF_Dictionary* pParams) {
-  CCodec_JpegModule* pJpegModule = CPDF_ModuleMgr::Get()->GetJpegModule();
+  CCodec_JpegModule* pJpegModule =
+      CCodec_ModuleMgr::GetInstance()->GetJpegModule();
   m_pDecoder = pJpegModule->CreateDecoder(
       src_span, m_Width, m_Height, m_nComponents,
       !pParams || pParams->GetIntegerFor("ColorTransform", 1));
diff --git a/core/fxcodec/codec/ccodec_progressivedecoder_unittest.cpp b/core/fxcodec/codec/ccodec_progressivedecoder_unittest.cpp
index 8bc1143..9384c16 100644
--- a/core/fxcodec/codec/ccodec_progressivedecoder_unittest.cpp
+++ b/core/fxcodec/codec/ccodec_progressivedecoder_unittest.cpp
@@ -368,32 +368,36 @@
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
-  auto mgr = pdfium::MakeUnique<CCodec_ModuleMgr>();
-  mgr->SetGifModule(pdfium::MakeUnique<CCodec_GifModule>());
+  CCodec_ModuleMgr::Create();
+  CCodec_ModuleMgr::GetInstance()->SetGifModule(
+      pdfium::MakeUnique<CCodec_GifModule>());
+  {
+    std::unique_ptr<CCodec_ProgressiveDecoder> decoder =
+        CCodec_ModuleMgr::GetInstance()->CreateProgressiveDecoder();
 
-  std::unique_ptr<CCodec_ProgressiveDecoder> decoder =
-      mgr->CreateProgressiveDecoder();
-  auto source = pdfium::MakeRetain<CFX_ReadOnlyMemoryStream>(kInput);
-  CFX_DIBAttribute attr;
-  FXCODEC_STATUS status =
-      decoder->LoadImageInfo(source, FXCODEC_IMAGE_GIF, &attr, true);
-  ASSERT_EQ(FXCODEC_STATUS_FRAME_READY, status);
+    auto source = pdfium::MakeRetain<CFX_ReadOnlyMemoryStream>(kInput);
+    CFX_DIBAttribute attr;
+    FXCODEC_STATUS status =
+        decoder->LoadImageInfo(source, FXCODEC_IMAGE_GIF, &attr, true);
+    ASSERT_EQ(FXCODEC_STATUS_FRAME_READY, status);
 
-  ASSERT_EQ(98, decoder->GetWidth());
-  ASSERT_EQ(6945, decoder->GetHeight());
+    ASSERT_EQ(98, decoder->GetWidth());
+    ASSERT_EQ(6945, decoder->GetHeight());
 
-  auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
-  bitmap->Create(decoder->GetWidth(), decoder->GetHeight(), FXDIB_Argb);
+    auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
+    bitmap->Create(decoder->GetWidth(), decoder->GetHeight(), FXDIB_Argb);
 
-  size_t frames;
-  std::tie(status, frames) = decoder->GetFrames();
-  ASSERT_EQ(FXCODEC_STATUS_DECODE_READY, status);
-  ASSERT_EQ(1u, frames);
+    size_t frames;
+    std::tie(status, frames) = decoder->GetFrames();
+    ASSERT_EQ(FXCODEC_STATUS_DECODE_READY, status);
+    ASSERT_EQ(1u, frames);
 
-  status = decoder->StartDecode(bitmap, 0, 0, bitmap->GetWidth(),
-                                bitmap->GetHeight());
-  while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE)
-    status = decoder->ContinueDecode();
-  EXPECT_EQ(FXCODEC_STATUS_DECODE_FINISH, status);
+    status = decoder->StartDecode(bitmap, 0, 0, bitmap->GetWidth(),
+                                  bitmap->GetHeight());
+    while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE)
+      status = decoder->ContinueDecode();
+    EXPECT_EQ(FXCODEC_STATUS_DECODE_FINISH, status);
+  }
+  CCodec_ModuleMgr::Destroy();
 }
 #endif  // PDF_ENABLE_XFA_GIF
diff --git a/core/fxcodec/codec/fx_codec.cpp b/core/fxcodec/codec/fx_codec.cpp
index 0ffaabc..abb8017 100644
--- a/core/fxcodec/codec/fx_codec.cpp
+++ b/core/fxcodec/codec/fx_codec.cpp
@@ -19,9 +19,50 @@
 #include "third_party/base/logging.h"
 #include "third_party/base/ptr_util.h"
 
+namespace {
+
+CCodec_ModuleMgr* g_CCodecModuleMgr = nullptr;
+
+}  // namespace
+
+// static
+void CCodec_ModuleMgr::Create() {
+  ASSERT(!g_CCodecModuleMgr);
+  g_CCodecModuleMgr = new CCodec_ModuleMgr();
+}
+
+// static
+void CCodec_ModuleMgr::Destroy() {
+  ASSERT(g_CCodecModuleMgr);
+  delete g_CCodecModuleMgr;
+  g_CCodecModuleMgr = nullptr;
+}
+
+// static
+CCodec_ModuleMgr* CCodec_ModuleMgr::GetInstance() {
+  ASSERT(g_CCodecModuleMgr);
+  return g_CCodecModuleMgr;
+}
+
 CCodec_ModuleMgr::CCodec_ModuleMgr()
     : m_pJpegModule(pdfium::MakeUnique<CCodec_JpegModule>()),
-      m_pJbig2Module(pdfium::MakeUnique<CCodec_Jbig2Module>()) {}
+      m_pJbig2Module(pdfium::MakeUnique<CCodec_Jbig2Module>()) {
+#ifdef PDF_ENABLE_XFA_BMP
+  SetBmpModule(pdfium::MakeUnique<CCodec_BmpModule>());
+#endif
+
+#ifdef PDF_ENABLE_XFA_GIF
+  SetGifModule(pdfium::MakeUnique<CCodec_GifModule>());
+#endif
+
+#ifdef PDF_ENABLE_XFA_PNG
+  SetPngModule(pdfium::MakeUnique<CCodec_PngModule>());
+#endif
+
+#ifdef PDF_ENABLE_XFA_TIFF
+  SetTiffModule(pdfium::MakeUnique<CCodec_TiffModule>());
+#endif
+}
 
 CCodec_ModuleMgr::~CCodec_ModuleMgr() = default;
 
diff --git a/core/fxcodec/fx_codec.h b/core/fxcodec/fx_codec.h
index 034d6ce..8d3bfdd 100644
--- a/core/fxcodec/fx_codec.h
+++ b/core/fxcodec/fx_codec.h
@@ -54,8 +54,10 @@
 
 class CCodec_ModuleMgr {
  public:
-  CCodec_ModuleMgr();
-  ~CCodec_ModuleMgr();
+  // Per-process singleton managed by callers.
+  static void Create();
+  static void Destroy();
+  static CCodec_ModuleMgr* GetInstance();
 
   CCodec_JpegModule* GetJpegModule() const { return m_pJpegModule.get(); }
   CCodec_Jbig2Module* GetJbig2Module() const { return m_pJbig2Module.get(); }
@@ -92,7 +94,10 @@
 #endif  // PDF_ENABLE_XFA_TIFF
 #endif  // PDF_ENABLE_XFA
 
- protected:
+ private:
+  CCodec_ModuleMgr();
+  ~CCodec_ModuleMgr();
+
   std::unique_ptr<CCodec_JpegModule> m_pJpegModule;
   std::unique_ptr<CCodec_Jbig2Module> m_pJbig2Module;
 
diff --git a/testing/fuzzers/xfa_codec_fuzzer.h b/testing/fuzzers/xfa_codec_fuzzer.h
index 31ab512..2729963 100644
--- a/testing/fuzzers/xfa_codec_fuzzer.h
+++ b/testing/fuzzers/xfa_codec_fuzzer.h
@@ -37,7 +37,16 @@
 class XFACodecFuzzer {
  public:
   static int Fuzz(const uint8_t* data, size_t size, FXCODEC_IMAGE_TYPE type) {
-    auto mgr = pdfium::MakeUnique<CCodec_ModuleMgr>();
+    CCodec_ModuleMgr::Create();
+    int sts = FuzzInternal(CCodec_ModuleMgr::GetInstance(), data, size, type);
+    CCodec_ModuleMgr::Destroy();
+    return sts;
+  }
+
+  static int FuzzInternal(CCodec_ModuleMgr* mgr,
+                          const uint8_t* data,
+                          size_t size,
+                          FXCODEC_IMAGE_TYPE type) {
 #ifdef PDF_ENABLE_XFA_BMP
     mgr->SetBmpModule(pdfium::MakeUnique<CCodec_BmpModule>());
 #endif  // PDF_ENABLE_XFA_BMP
diff --git a/xfa/fxfa/cxfa_ffwidget.cpp b/xfa/fxfa/cxfa_ffwidget.cpp
index 8855738..15bbb14 100644
--- a/xfa/fxfa/cxfa_ffwidget.cpp
+++ b/xfa/fxfa/cxfa_ffwidget.cpp
@@ -155,7 +155,7 @@
     FXCODEC_IMAGE_TYPE type,
     int32_t& iImageXDpi,
     int32_t& iImageYDpi) {
-  CCodec_ModuleMgr* pCodecMgr = CPDF_ModuleMgr::Get()->GetCodecModule();
+  auto* pCodecMgr = CCodec_ModuleMgr::GetInstance();
   std::unique_ptr<CCodec_ProgressiveDecoder> pProgressiveDecoder =
       pCodecMgr->CreateProgressiveDecoder();