Separate GifModule from ModuleMgr.

Then make GifModule methods static, and separate out the non-static part
into GifProgressiveDecoder.

Change-Id: Ifac98c3b72fed01e407466ca023e09aaa4c16c95
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/69934
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxcodec/BUILD.gn b/core/fxcodec/BUILD.gn
index b168112..bc478ae 100644
--- a/core/fxcodec/BUILD.gn
+++ b/core/fxcodec/BUILD.gn
@@ -107,6 +107,8 @@
         "gif/cfx_gifcontext.h",
         "gif/cfx_lzwdecompressor.cpp",
         "gif/cfx_lzwdecompressor.h",
+        "gif/gif_progressive_decoder.cpp",
+        "gif/gif_progressive_decoder.h",
         "gif/gifmodule.cpp",
         "gif/gifmodule.h",
       ]
diff --git a/core/fxcodec/fx_codec.cpp b/core/fxcodec/fx_codec.cpp
index 9aba833..b3cd13d 100644
--- a/core/fxcodec/fx_codec.cpp
+++ b/core/fxcodec/fx_codec.cpp
@@ -12,6 +12,7 @@
 #include <utility>
 
 #include "core/fxcrt/fx_extension.h"
+#include "core/fxcrt/fx_memory.h"
 #include "core/fxcrt/fx_safe_types.h"
 #include "third_party/base/logging.h"
 #include "third_party/base/ptr_util.h"
@@ -47,10 +48,6 @@
 #ifdef PDF_ENABLE_XFA_BMP
   SetBmpModule(pdfium::MakeUnique<BmpModule>());
 #endif
-
-#ifdef PDF_ENABLE_XFA_GIF
-  SetGifModule(pdfium::MakeUnique<GifModule>());
-#endif
 }
 
 ModuleMgr::~ModuleMgr() = default;
diff --git a/core/fxcodec/fx_codec.h b/core/fxcodec/fx_codec.h
index 21a79ed..f730def 100644
--- a/core/fxcodec/fx_codec.h
+++ b/core/fxcodec/fx_codec.h
@@ -19,10 +19,6 @@
 #ifdef PDF_ENABLE_XFA_BMP
 #include "core/fxcodec/bmp/bmpmodule.h"
 #endif  // PDF_ENABLE_XFA_BMP
-
-#ifdef PDF_ENABLE_XFA_GIF
-#include "core/fxcodec/gif/gifmodule.h"
-#endif  // PDF_ENABLE_XFA_GIF
 #endif
 
 namespace fxcodec {
@@ -58,13 +54,6 @@
     m_pBmpModule = std::move(module);
   }
 #endif  // PDF_ENABLE_XFA_BMP
-
-#ifdef PDF_ENABLE_XFA_GIF
-  GifModule* GetGifModule() const { return m_pGifModule.get(); }
-  void SetGifModule(std::unique_ptr<GifModule> module) {
-    m_pGifModule = std::move(module);
-  }
-#endif  // PDF_ENABLE_XFA_GIF
 #endif  // PDF_ENABLE_XFA
 
  private:
@@ -75,10 +64,6 @@
 #ifdef PDF_ENABLE_XFA_BMP
   std::unique_ptr<BmpModule> m_pBmpModule;
 #endif  // PDF_ENABLE_XFA_BMP
-
-#ifdef PDF_ENABLE_XFA_GIF
-  std::unique_ptr<GifModule> m_pGifModule;
-#endif  // PDF_ENABLE_XFA_GIF
 #endif  // PDF_ENABLE_XFA
 };
 
diff --git a/core/fxcodec/gif/gif_progressive_decoder.cpp b/core/fxcodec/gif/gif_progressive_decoder.cpp
new file mode 100644
index 0000000..775ef78
--- /dev/null
+++ b/core/fxcodec/gif/gif_progressive_decoder.cpp
@@ -0,0 +1,34 @@
+// Copyright 2020 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxcodec/gif/gif_progressive_decoder.h"
+
+#include "core/fxcodec/cfx_codec_memory.h"
+#include "core/fxcodec/gif/gifmodule.h"
+
+namespace fxcodec {
+
+// static
+GifProgressiveDecoder* GifProgressiveDecoder::GetInstance() {
+  static pdfium::base::NoDestructor<GifProgressiveDecoder> s;
+  return s.get();
+}
+
+GifProgressiveDecoder::GifProgressiveDecoder() = default;
+
+GifProgressiveDecoder::~GifProgressiveDecoder() = default;
+
+FX_FILESIZE GifProgressiveDecoder::GetAvailInput(Context* context) const {
+  return GifModule::GetAvailInput(context);
+}
+
+bool GifProgressiveDecoder::Input(Context* context,
+                                  RetainPtr<CFX_CodecMemory> codec_memory,
+                                  CFX_DIBAttribute* pAttribute) {
+  return GifModule::Input(context, codec_memory, pAttribute);
+}
+
+}  // namespace fxcodec
diff --git a/core/fxcodec/gif/gif_progressive_decoder.h b/core/fxcodec/gif/gif_progressive_decoder.h
new file mode 100644
index 0000000..dec148c
--- /dev/null
+++ b/core/fxcodec/gif/gif_progressive_decoder.h
@@ -0,0 +1,40 @@
+// Copyright 2020 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_GIF_GIF_PROGRESSIVE_DECODER_H_
+#define CORE_FXCODEC_GIF_GIF_PROGRESSIVE_DECODER_H_
+
+#include "core/fxcodec/progressive_decoder_iface.h"
+#include "third_party/base/no_destructor.h"
+
+#ifndef PDF_ENABLE_XFA_GIF
+#error "GIF must be enabled"
+#endif
+
+namespace fxcodec {
+
+class GifProgressiveDecoder final : public ProgressiveDecoderIface {
+ public:
+  static GifProgressiveDecoder* GetInstance();
+
+  // ProgressiveDecoderIface:
+  FX_FILESIZE GetAvailInput(Context* context) const override;
+  bool Input(Context* context,
+             RetainPtr<CFX_CodecMemory> codec_memory,
+             CFX_DIBAttribute* pAttribute) override;
+
+ private:
+  friend pdfium::base::NoDestructor<GifProgressiveDecoder>;
+
+  GifProgressiveDecoder();
+  ~GifProgressiveDecoder() override;
+};
+
+}  // namespace fxcodec
+
+using GifProgressiveDecoder = fxcodec::GifProgressiveDecoder;
+
+#endif  // CORE_FXCODEC_GIF_GIF_PROGRESSIVE_DECODER_H_
diff --git a/core/fxcodec/gif/gifmodule.cpp b/core/fxcodec/gif/gifmodule.cpp
index 81fe3a591..dc25022 100644
--- a/core/fxcodec/gif/gifmodule.cpp
+++ b/core/fxcodec/gif/gifmodule.cpp
@@ -8,28 +8,26 @@
 
 #include "core/fxcodec/cfx_codec_memory.h"
 #include "core/fxcodec/fx_codec.h"
-#include "core/fxcodec/gif/cfx_gif.h"
 #include "core/fxcodec/gif/cfx_gifcontext.h"
 #include "core/fxge/fx_dib.h"
 #include "third_party/base/ptr_util.h"
 
 namespace fxcodec {
 
-GifModule::GifModule() = default;
-
-GifModule::~GifModule() = default;
-
-std::unique_ptr<ProgressiveDecoderIface::Context> GifModule::Start(
+// static
+std::unique_ptr<ProgressiveDecoderIface::Context> GifModule::StartDecode(
     Delegate* pDelegate) {
   return pdfium::MakeUnique<CFX_GifContext>(pDelegate);
 }
 
-CFX_GifDecodeStatus GifModule::ReadHeader(Context* pContext,
-                                          int* width,
-                                          int* height,
-                                          int* pal_num,
-                                          CFX_GifPalette** pal_pp,
-                                          int* bg_index) {
+// static
+CFX_GifDecodeStatus GifModule::ReadHeader(
+    ProgressiveDecoderIface::Context* pContext,
+    int* width,
+    int* height,
+    int* pal_num,
+    CFX_GifPalette** pal_pp,
+    int* bg_index) {
   auto* context = static_cast<CFX_GifContext*>(pContext);
   CFX_GifDecodeStatus ret = context->ReadHeader();
   if (ret != CFX_GifDecodeStatus::Success)
@@ -44,8 +42,9 @@
   return CFX_GifDecodeStatus::Success;
 }
 
+// static
 std::pair<CFX_GifDecodeStatus, size_t> GifModule::LoadFrameInfo(
-    Context* pContext) {
+    ProgressiveDecoderIface::Context* pContext) {
   auto* context = static_cast<CFX_GifContext*>(pContext);
   CFX_GifDecodeStatus ret = context->GetFrame();
   if (ret != CFX_GifDecodeStatus::Success)
@@ -53,15 +52,21 @@
   return {CFX_GifDecodeStatus::Success, context->GetFrameNum()};
 }
 
-CFX_GifDecodeStatus GifModule::LoadFrame(Context* pContext, size_t frame_num) {
+// static
+CFX_GifDecodeStatus GifModule::LoadFrame(
+    ProgressiveDecoderIface::Context* pContext,
+    size_t frame_num) {
   return static_cast<CFX_GifContext*>(pContext)->LoadFrame(frame_num);
 }
 
-FX_FILESIZE GifModule::GetAvailInput(Context* pContext) const {
+// static
+FX_FILESIZE GifModule::GetAvailInput(
+    ProgressiveDecoderIface::Context* pContext) {
   return static_cast<CFX_GifContext*>(pContext)->GetAvailInput();
 }
 
-bool GifModule::Input(Context* pContext,
+// static
+bool GifModule::Input(ProgressiveDecoderIface::Context* pContext,
                       RetainPtr<CFX_CodecMemory> codec_memory,
                       CFX_DIBAttribute*) {
   auto* ctx = static_cast<CFX_GifContext*>(pContext);
diff --git a/core/fxcodec/gif/gifmodule.h b/core/fxcodec/gif/gifmodule.h
index c8bbaee..fd8c446 100644
--- a/core/fxcodec/gif/gifmodule.h
+++ b/core/fxcodec/gif/gifmodule.h
@@ -14,11 +14,15 @@
 #include "core/fxcodec/progressive_decoder_iface.h"
 #include "core/fxcrt/fx_coordinates.h"
 
+#ifndef PDF_ENABLE_XFA_GIF
+#error "GIF must be enabled"
+#endif
+
 namespace fxcodec {
 
 class CFX_DIBAttribute;
 
-class GifModule final : public ProgressiveDecoderIface {
+class GifModule {
  public:
   class Delegate {
    public:
@@ -35,24 +39,28 @@
     virtual void GifReadScanline(int32_t row_num, uint8_t* row_buf) = 0;
   };
 
-  GifModule();
-  ~GifModule() override;
+  static std::unique_ptr<ProgressiveDecoderIface::Context> StartDecode(
+      Delegate* pDelegate);
+  static CFX_GifDecodeStatus ReadHeader(
+      ProgressiveDecoderIface::Context* context,
+      int* width,
+      int* height,
+      int* pal_num,
+      CFX_GifPalette** pal_pp,
+      int* bg_index);
+  static std::pair<CFX_GifDecodeStatus, size_t> LoadFrameInfo(
+      ProgressiveDecoderIface::Context* context);
+  static CFX_GifDecodeStatus LoadFrame(
+      ProgressiveDecoderIface::Context* context,
+      size_t frame_num);
+  static FX_FILESIZE GetAvailInput(ProgressiveDecoderIface::Context* context);
+  static bool Input(ProgressiveDecoderIface::Context* context,
+                    RetainPtr<CFX_CodecMemory> codec_memory,
+                    CFX_DIBAttribute* pAttribute);
 
-  // ProgressiveDecoderIface:
-  FX_FILESIZE GetAvailInput(Context* context) const override;
-  bool Input(Context* context,
-             RetainPtr<CFX_CodecMemory> codec_memory,
-             CFX_DIBAttribute* pAttribute) override;
-
-  std::unique_ptr<Context> Start(Delegate* pDelegate);
-  CFX_GifDecodeStatus ReadHeader(Context* context,
-                                 int* width,
-                                 int* height,
-                                 int* pal_num,
-                                 CFX_GifPalette** pal_pp,
-                                 int* bg_index);
-  std::pair<CFX_GifDecodeStatus, size_t> LoadFrameInfo(Context* context);
-  CFX_GifDecodeStatus LoadFrame(Context* context, size_t frame_num);
+  GifModule() = delete;
+  GifModule(const GifModule&) = delete;
+  GifModule& operator=(const GifModule&) = delete;
 };
 
 }  // namespace fxcodec
diff --git a/core/fxcodec/progressivedecoder.cpp b/core/fxcodec/progressivedecoder.cpp
index feb5fde..876a93d 100644
--- a/core/fxcodec/progressivedecoder.cpp
+++ b/core/fxcodec/progressivedecoder.cpp
@@ -23,6 +23,10 @@
 #include "third_party/base/logging.h"
 #include "third_party/base/ptr_util.h"
 
+#ifdef PDF_ENABLE_XFA_GIF
+#include "core/fxcodec/gif/gif_progressive_decoder.h"
+#endif  // PDF_ENABLE_XFA_GIF
+
 #ifdef PDF_ENABLE_XFA_TIFF
 #include "core/fxcodec/tiff/tiff_decoder.h"
 #endif  // PDF_ENABLE_XFA_TIFF
@@ -405,8 +409,7 @@
 
 #ifdef PDF_ENABLE_XFA_GIF
 void ProgressiveDecoder::GifRecordCurrentPosition(uint32_t& cur_pos) {
-  uint32_t remain_size =
-      m_pCodecMgr->GetGifModule()->GetAvailInput(m_pGifContext.get());
+  uint32_t remain_size = GifModule::GetAvailInput(m_pGifContext.get());
   cur_pos = m_offSet - remain_size;
 }
 
@@ -423,9 +426,9 @@
   m_InvalidateGifBuffer = true;
 
   FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR;
-  if (!GifReadMoreData(m_pCodecMgr->GetGifModule(), &error_status)) {
+  if (!GifReadMoreData(&error_status))
     return false;
-  }
+
   CFX_GifPalette* pPalette = nullptr;
   if (pal_num != 0 && pal_ptr) {
     pPalette = pal_ptr;
@@ -811,10 +814,9 @@
 #endif  // PDF_ENABLE_XFA_BMP
 
 #ifdef PDF_ENABLE_XFA_GIF
-bool ProgressiveDecoder::GifReadMoreData(GifModule* pGifModule,
-                                         FXCODEC_STATUS* err_status) {
-  if (!ReadMoreData(pGifModule, m_pGifContext.get(), m_InvalidateGifBuffer,
-                    err_status)) {
+bool ProgressiveDecoder::GifReadMoreData(FXCODEC_STATUS* err_status) {
+  if (!ReadMoreData(GifProgressiveDecoder::GetInstance(), m_pGifContext.get(),
+                    m_InvalidateGifBuffer, err_status)) {
     return false;
   }
   m_InvalidateGifBuffer = false;
@@ -822,23 +824,22 @@
 }
 
 bool ProgressiveDecoder::GifDetectImageTypeInBuffer() {
-  GifModule* pGifModule = m_pCodecMgr->GetGifModule();
-  m_pGifContext = pGifModule->Start(this);
-  pGifModule->Input(m_pGifContext.get(), m_pCodecMemory, nullptr);
+  m_pGifContext = GifModule::StartDecode(this);
+  GifModule::Input(m_pGifContext.get(), m_pCodecMemory, nullptr);
   m_SrcComponents = 1;
   CFX_GifDecodeStatus readResult =
-      pGifModule->ReadHeader(m_pGifContext.get(), &m_SrcWidth, &m_SrcHeight,
-                             &m_GifPltNumber, &m_pGifPalette, &m_GifBgIndex);
+      GifModule::ReadHeader(m_pGifContext.get(), &m_SrcWidth, &m_SrcHeight,
+                            &m_GifPltNumber, &m_pGifPalette, &m_GifBgIndex);
   while (readResult == CFX_GifDecodeStatus::Unfinished) {
     FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT;
-    if (!GifReadMoreData(pGifModule, &error_status)) {
+    if (!GifReadMoreData(&error_status)) {
       m_pGifContext = nullptr;
       m_status = error_status;
       return false;
     }
     readResult =
-        pGifModule->ReadHeader(m_pGifContext.get(), &m_SrcWidth, &m_SrcHeight,
-                               &m_GifPltNumber, &m_pGifPalette, &m_GifBgIndex);
+        GifModule::ReadHeader(m_pGifContext.get(), &m_SrcWidth, &m_SrcHeight,
+                              &m_GifPltNumber, &m_pGifPalette, &m_GifBgIndex);
   }
   if (readResult == CFX_GifDecodeStatus::Success) {
     m_SrcBPC = 8;
@@ -864,18 +865,17 @@
 }
 
 FXCODEC_STATUS ProgressiveDecoder::GifContinueDecode() {
-  GifModule* pGifModule = m_pCodecMgr->GetGifModule();
   CFX_GifDecodeStatus readRes =
-      pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur);
+      GifModule::LoadFrame(m_pGifContext.get(), m_FrameCur);
   while (readRes == CFX_GifDecodeStatus::Unfinished) {
     FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH;
-    if (!GifReadMoreData(pGifModule, &error_status)) {
+    if (!GifReadMoreData(&error_status)) {
       m_pDeviceBitmap = nullptr;
       m_pFile = nullptr;
       m_status = error_status;
       return m_status;
     }
-    readRes = pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur);
+    readRes = GifModule::LoadFrame(m_pGifContext.get(), m_FrameCur);
   }
 
   if (readRes == CFX_GifDecodeStatus::Success) {
@@ -2113,18 +2113,17 @@
       return {m_status, 1};
 #ifdef PDF_ENABLE_XFA_GIF
     case FXCODEC_IMAGE_GIF: {
-      GifModule* pGifModule = m_pCodecMgr->GetGifModule();
       while (true) {
         CFX_GifDecodeStatus readResult;
         std::tie(readResult, m_FrameNumber) =
-            pGifModule->LoadFrameInfo(m_pGifContext.get());
+            GifModule::LoadFrameInfo(m_pGifContext.get());
         while (readResult == CFX_GifDecodeStatus::Unfinished) {
           FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_READ;
-          if (!GifReadMoreData(pGifModule, &error_status))
+          if (!GifReadMoreData(&error_status))
             return {error_status, 0};
 
           std::tie(readResult, m_FrameNumber) =
-              pGifModule->LoadFrameInfo(m_pGifContext.get());
+              GifModule::LoadFrameInfo(m_pGifContext.get());
         }
         if (readResult == CFX_GifDecodeStatus::Success) {
           m_status = FXCODEC_STATUS_DECODE_READY;
diff --git a/core/fxcodec/progressivedecoder.h b/core/fxcodec/progressivedecoder.h
index e45cc9f..a8bbad1 100644
--- a/core/fxcodec/progressivedecoder.h
+++ b/core/fxcodec/progressivedecoder.h
@@ -185,7 +185,7 @@
 #endif  // PDF_ENABLE_XFA_BMP
 
 #ifdef PDF_ENABLE_XFA_GIF
-  bool GifReadMoreData(GifModule* pGifModule, FXCODEC_STATUS* err_status);
+  bool GifReadMoreData(FXCODEC_STATUS* err_status);
   bool GifDetectImageTypeInBuffer();
   FXCODEC_STATUS GifStartDecode(const RetainPtr<CFX_DIBitmap>& pDIBitmap);
   FXCODEC_STATUS GifContinueDecode();
diff --git a/core/fxcodec/progressivedecoder_unittest.cpp b/core/fxcodec/progressivedecoder_unittest.cpp
index 5c4e26f..11ef14c 100644
--- a/core/fxcodec/progressivedecoder_unittest.cpp
+++ b/core/fxcodec/progressivedecoder_unittest.cpp
@@ -371,7 +371,6 @@
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
   ModuleMgr::Create();
-  ModuleMgr::GetInstance()->SetGifModule(pdfium::MakeUnique<GifModule>());
   {
     std::unique_ptr<ProgressiveDecoder> decoder =
         ModuleMgr::GetInstance()->CreateProgressiveDecoder();