Introduce CodecModuleIface for progressive decoder modules.

Another step before trying to fix the memory issue. Forces common
APIs on the bunch of decoders, though some methods are unused.
Requires adding some arguments/return values to get to a common
API which are not used in all cases (yet?). Required converting
some args to spans. Required proxying a GetJumpMark() call through
the public module API to the private context.

Bug: pdfium:1082

Change-Id: I0c0b7415141ff2a6f4f44777ca3d05521f08130d
Reviewed-on: https://pdfium-review.googlesource.com/41950
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index 8a72c71..d3ea24d 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -739,6 +739,7 @@
     "core/fxcodec/codec/ccodec_scanlinedecoder.h",
     "core/fxcodec/codec/cjpx_decoder.h",
     "core/fxcodec/codec/codec_int.h",
+    "core/fxcodec/codec/codec_module_iface.h",
     "core/fxcodec/codec/fx_codec.cpp",
     "core/fxcodec/fx_codec.h",
     "core/fxcodec/fx_codec_def.h",
diff --git a/core/fxcodec/bmp/cfx_bmpcontext.h b/core/fxcodec/bmp/cfx_bmpcontext.h
index 89e6463..ddb179b 100644
--- a/core/fxcodec/bmp/cfx_bmpcontext.h
+++ b/core/fxcodec/bmp/cfx_bmpcontext.h
@@ -10,7 +10,7 @@
 #include "core/fxcodec/bmp/cfx_bmpdecompressor.h"
 #include "core/fxcodec/bmp/fx_bmp.h"
 
-class CFX_BmpContext final : public CCodec_BmpModule::Context {
+class CFX_BmpContext final : public CodecModuleIface::Context {
  public:
   CFX_BmpContext(CCodec_BmpModule* pModule,
                  CCodec_BmpModule::Delegate* pDelegate);
diff --git a/core/fxcodec/codec/ccodec_bmpmodule.cpp b/core/fxcodec/codec/ccodec_bmpmodule.cpp
index ff4164c..9884662 100644
--- a/core/fxcodec/codec/ccodec_bmpmodule.cpp
+++ b/core/fxcodec/codec/ccodec_bmpmodule.cpp
@@ -17,7 +17,7 @@
 
 CCodec_BmpModule::~CCodec_BmpModule() {}
 
-std::unique_ptr<CCodec_BmpModule::Context> CCodec_BmpModule::Start(
+std::unique_ptr<CodecModuleIface::Context> CCodec_BmpModule::Start(
     Delegate* pDelegate) {
   auto p = pdfium::MakeUnique<CFX_BmpContext>(this, pDelegate);
   p->m_Bmp.context_ptr_ = p.get();
@@ -67,6 +67,9 @@
   return static_cast<CFX_BmpContext*>(pContext)->m_Bmp.GetAvailInput();
 }
 
-void CCodec_BmpModule::Input(Context* pContext, pdfium::span<uint8_t> src_buf) {
+bool CCodec_BmpModule::Input(Context* pContext,
+                             pdfium::span<uint8_t> src_buf,
+                             CFX_DIBAttribute*) {
   static_cast<CFX_BmpContext*>(pContext)->m_Bmp.SetInputBuffer(src_buf);
+  return true;
 }
diff --git a/core/fxcodec/codec/ccodec_bmpmodule.h b/core/fxcodec/codec/ccodec_bmpmodule.h
index 6dc0ebd..d5b6a75 100644
--- a/core/fxcodec/codec/ccodec_bmpmodule.h
+++ b/core/fxcodec/codec/ccodec_bmpmodule.h
@@ -10,19 +10,15 @@
 #include <memory>
 #include <vector>
 
+#include "core/fxcodec/codec/codec_module_iface.h"
 #include "core/fxcrt/fx_system.h"
 #include "core/fxcrt/unowned_ptr.h"
 #include "third_party/base/span.h"
 
 class CFX_DIBAttribute;
 
-class CCodec_BmpModule {
+class CCodec_BmpModule final : public CodecModuleIface {
  public:
-  class Context {
-   public:
-    virtual ~Context() {}
-  };
-
   class Delegate {
    public:
     virtual bool BmpInputImagePositionBuf(uint32_t rcd_pos) = 0;
@@ -31,11 +27,15 @@
   };
 
   CCodec_BmpModule();
-  ~CCodec_BmpModule();
+  ~CCodec_BmpModule() override;
+
+  // CodecModuleIface:
+  FX_FILESIZE GetAvailInput(Context* pContext) const override;
+  bool Input(Context* pContext,
+             pdfium::span<uint8_t> src_buf,
+             CFX_DIBAttribute* pAttribute) override;
 
   std::unique_ptr<Context> Start(Delegate* pDelegate);
-  FX_FILESIZE GetAvailInput(Context* pContext) const;
-  void Input(Context* pContext, pdfium::span<uint8_t> src_buf);
   int32_t ReadHeader(Context* pContext,
                      int32_t* width,
                      int32_t* height,
diff --git a/core/fxcodec/codec/ccodec_gifmodule.cpp b/core/fxcodec/codec/ccodec_gifmodule.cpp
index a93cb27..289993c 100644
--- a/core/fxcodec/codec/ccodec_gifmodule.cpp
+++ b/core/fxcodec/codec/ccodec_gifmodule.cpp
@@ -17,7 +17,7 @@
 
 CCodec_GifModule::~CCodec_GifModule() {}
 
-std::unique_ptr<CCodec_GifModule::Context> CCodec_GifModule::Start(
+std::unique_ptr<CodecModuleIface::Context> CCodec_GifModule::Start(
     Delegate* pDelegate) {
   return pdfium::MakeUnique<CFX_GifContext>(this, pDelegate);
 }
@@ -66,10 +66,13 @@
   return CFX_GifDecodeStatus::Success;
 }
 
-uint32_t CCodec_GifModule::GetAvailInput(Context* pContext) const {
+FX_FILESIZE CCodec_GifModule::GetAvailInput(Context* pContext) const {
   return static_cast<CFX_GifContext*>(pContext)->GetAvailInput();
 }
 
-void CCodec_GifModule::Input(Context* pContext, pdfium::span<uint8_t> src_buf) {
+bool CCodec_GifModule::Input(Context* pContext,
+                             pdfium::span<uint8_t> src_buf,
+                             CFX_DIBAttribute*) {
   static_cast<CFX_GifContext*>(pContext)->SetInputBuffer(src_buf);
+  return true;
 }
diff --git a/core/fxcodec/codec/ccodec_gifmodule.h b/core/fxcodec/codec/ccodec_gifmodule.h
index 9529583..665208b 100644
--- a/core/fxcodec/codec/ccodec_gifmodule.h
+++ b/core/fxcodec/codec/ccodec_gifmodule.h
@@ -10,6 +10,7 @@
 #include <memory>
 #include <utility>
 
+#include "core/fxcodec/codec/codec_module_iface.h"
 #include "core/fxcodec/gif/cfx_gif.h"
 #include "core/fxcrt/fx_coordinates.h"
 #include "core/fxcrt/fx_system.h"
@@ -17,13 +18,8 @@
 
 class CFX_DIBAttribute;
 
-class CCodec_GifModule {
+class CCodec_GifModule final : public CodecModuleIface {
  public:
-  class Context {
-   public:
-    virtual ~Context() {}
-  };
-
   class Delegate {
    public:
     virtual void GifRecordCurrentPosition(uint32_t& cur_pos) = 0;
@@ -40,11 +36,15 @@
   };
 
   CCodec_GifModule();
-  ~CCodec_GifModule();
+  ~CCodec_GifModule() override;
+
+  // CodecModuleIface:
+  FX_FILESIZE GetAvailInput(Context* context) const override;
+  bool Input(Context* context,
+             pdfium::span<uint8_t> src_buf,
+             CFX_DIBAttribute* pAttribute) override;
 
   std::unique_ptr<Context> Start(Delegate* pDelegate);
-  uint32_t GetAvailInput(Context* context) const;
-  void Input(Context* context, pdfium::span<uint8_t> src_buf);
   CFX_GifDecodeStatus ReadHeader(Context* context,
                                  int* width,
                                  int* height,
diff --git a/core/fxcodec/codec/ccodec_jpegmodule.cpp b/core/fxcodec/codec/ccodec_jpegmodule.cpp
index aaf16ae..7c15aa3 100644
--- a/core/fxcodec/codec/ccodec_jpegmodule.cpp
+++ b/core/fxcodec/codec/ccodec_jpegmodule.cpp
@@ -31,12 +31,12 @@
 #endif
 }  // extern "C"
 
-class CJpegContext final : public CCodec_JpegModule::Context {
+class CJpegContext final : public CodecModuleIface::Context {
  public:
   CJpegContext();
   ~CJpegContext() override;
 
-  jmp_buf* GetJumpMark() override { return &m_JumpMark; }
+  jmp_buf* GetJumpMark() { return &m_JumpMark; }
 
   jmp_buf m_JumpMark;
   jpeg_decompress_struct m_Info;
@@ -398,7 +398,7 @@
   jpeg_destroy_decompress(&m_Info);
 }
 
-std::unique_ptr<CCodec_JpegModule::Context> CCodec_JpegModule::Start() {
+std::unique_ptr<CodecModuleIface::Context> CCodec_JpegModule::Start() {
   // Use ordinary pointer until past the possibility of a longjump.
   auto* pContext = new CJpegContext();
   if (setjmp(pContext->m_JumpMark) == -1) {
@@ -412,22 +412,22 @@
   return pdfium::WrapUnique(pContext);
 }
 
-void CCodec_JpegModule::Input(Context* pContext,
-                              const unsigned char* src_buf,
-                              uint32_t src_size) {
+bool CCodec_JpegModule::Input(Context* pContext,
+                              pdfium::span<uint8_t> src_buf,
+                              CFX_DIBAttribute*) {
   auto* ctx = static_cast<CJpegContext*>(pContext);
   if (ctx->m_SkipSize) {
-    if (ctx->m_SkipSize > src_size) {
+    if (ctx->m_SkipSize > src_buf.size()) {
       ctx->m_SrcMgr.bytes_in_buffer = 0;
-      ctx->m_SkipSize -= src_size;
-      return;
+      ctx->m_SkipSize -= src_buf.size();
+      return true;
     }
-    src_size -= ctx->m_SkipSize;
-    src_buf += ctx->m_SkipSize;
+    src_buf = src_buf.subspan(ctx->m_SkipSize);
     ctx->m_SkipSize = 0;
   }
-  ctx->m_SrcMgr.next_input_byte = src_buf;
-  ctx->m_SrcMgr.bytes_in_buffer = src_size;
+  ctx->m_SrcMgr.next_input_byte = src_buf.data();
+  ctx->m_SrcMgr.bytes_in_buffer = src_buf.size();
+  return true;
 }
 
 #ifdef PDF_ENABLE_XFA
@@ -464,9 +464,13 @@
   return nlines == 1;
 }
 
-uint32_t CCodec_JpegModule::GetAvailInput(Context* pContext) const {
+FX_FILESIZE CCodec_JpegModule::GetAvailInput(Context* pContext) const {
   auto* ctx = static_cast<CJpegContext*>(pContext);
-  return (uint32_t)ctx->m_SrcMgr.bytes_in_buffer;
+  return static_cast<FX_FILESIZE>(ctx->m_SrcMgr.bytes_in_buffer);
+}
+
+jmp_buf* CCodec_JpegModule::GetJumpMark(Context* pContext) {
+  return static_cast<CJpegContext*>(pContext)->GetJumpMark();
 }
 
 #if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
diff --git a/core/fxcodec/codec/ccodec_jpegmodule.h b/core/fxcodec/codec/ccodec_jpegmodule.h
index 2c72db3..45b1d1b 100644
--- a/core/fxcodec/codec/ccodec_jpegmodule.h
+++ b/core/fxcodec/codec/ccodec_jpegmodule.h
@@ -10,25 +10,17 @@
 #include <csetjmp>
 #include <memory>
 
+#include "core/fxcodec/codec/codec_module_iface.h"
 #include "core/fxcrt/fx_system.h"
 #include "core/fxcrt/retain_ptr.h"
 #include "third_party/base/span.h"
 
 class CCodec_ScanlineDecoder;
+class CFX_DIBAttribute;
 class CFX_DIBBase;
 
-#ifdef PDF_ENABLE_XFA
-class CFX_DIBAttribute;
-#endif  // PDF_ENABLE_XFA
-
-class CCodec_JpegModule {
+class CCodec_JpegModule final : public CodecModuleIface {
  public:
-  class Context {
-   public:
-    virtual ~Context() {}
-    virtual jmp_buf* GetJumpMark() = 0;
-  };
-
   std::unique_ptr<CCodec_ScanlineDecoder> CreateDecoder(
       pdfium::span<const uint8_t> src_buf,
       int width,
@@ -36,6 +28,13 @@
       int nComps,
       bool ColorTransform);
 
+  // CodecModuleIface:
+  FX_FILESIZE GetAvailInput(Context* pContext) const override;
+  bool Input(Context* pContext,
+             pdfium::span<uint8_t> src_buf,
+             CFX_DIBAttribute* pAttribute) override;
+
+  jmp_buf* GetJumpMark(Context* pContext);
   bool LoadInfo(pdfium::span<const uint8_t> src_span,
                 int* width,
                 int* height,
@@ -44,7 +43,6 @@
                 bool* color_transform);
 
   std::unique_ptr<Context> Start();
-  void Input(Context* pContext, const uint8_t* src_buf, uint32_t src_size);
 
 #ifdef PDF_ENABLE_XFA
   int ReadHeader(Context* pContext,
@@ -56,7 +54,6 @@
 
   bool StartScanline(Context* pContext, int down_scale);
   bool ReadScanline(Context* pContext, uint8_t* dest_buf);
-  uint32_t GetAvailInput(Context* pContext) const;
 
 #if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
   static bool JpegEncode(const RetainPtr<CFX_DIBBase>& pSource,
diff --git a/core/fxcodec/codec/ccodec_pngmodule.cpp b/core/fxcodec/codec/ccodec_pngmodule.cpp
index b98e68d..593c215 100644
--- a/core/fxcodec/codec/ccodec_pngmodule.cpp
+++ b/core/fxcodec/codec/ccodec_pngmodule.cpp
@@ -23,9 +23,7 @@
 
 #define PNG_ERROR_SIZE 256
 
-namespace {
-
-class CPngContext final : public CCodec_PngModule::Context {
+class CPngContext final : public CodecModuleIface::Context {
  public:
   explicit CPngContext(CCodec_PngModule::Delegate* pDelegate);
   ~CPngContext() override;
@@ -184,9 +182,7 @@
                           m_pInfo ? &m_pInfo : nullptr, nullptr);
 }
 
-}  // namespace
-
-std::unique_ptr<CCodec_PngModule::Context> CCodec_PngModule::Start(
+std::unique_ptr<CodecModuleIface::Context> CCodec_PngModule::Start(
     Delegate* pDelegate) {
   auto p = pdfium::MakeUnique<CPngContext>(pDelegate);
   p->m_pPng =
@@ -208,9 +204,13 @@
   return p;
 }
 
+FX_FILESIZE CCodec_PngModule::GetAvailInput(Context* pContext) const {
+  NOTREACHED();
+  return 0;
+}
+
 bool CCodec_PngModule::Input(Context* pContext,
-                             const uint8_t* src_buf,
-                             uint32_t src_size,
+                             pdfium::span<uint8_t> src_buf,
                              CFX_DIBAttribute* pAttribute) {
   auto* ctx = static_cast<CPngContext*>(pContext);
   if (setjmp(png_jmpbuf(ctx->m_pPng))) {
@@ -220,7 +220,6 @@
     }
     return false;
   }
-  png_process_data(ctx->m_pPng, ctx->m_pInfo, const_cast<uint8_t*>(src_buf),
-                   src_size);
+  png_process_data(ctx->m_pPng, ctx->m_pInfo, src_buf.data(), src_buf.size());
   return true;
 }
diff --git a/core/fxcodec/codec/ccodec_pngmodule.h b/core/fxcodec/codec/ccodec_pngmodule.h
index 847f67e..e97a221 100644
--- a/core/fxcodec/codec/ccodec_pngmodule.h
+++ b/core/fxcodec/codec/ccodec_pngmodule.h
@@ -9,17 +9,13 @@
 
 #include <memory>
 
+#include "core/fxcodec/codec/codec_module_iface.h"
 #include "core/fxcrt/fx_system.h"
 
 class CFX_DIBAttribute;
 
-class CCodec_PngModule {
+class CCodec_PngModule final : public CodecModuleIface {
  public:
-  class Context {
-   public:
-    virtual ~Context() {}
-  };
-
   class Delegate {
    public:
     virtual bool PngReadHeader(int width,
@@ -36,11 +32,13 @@
     virtual void PngFillScanlineBufCompleted(int pass, int line) = 0;
   };
 
-  std::unique_ptr<Context> Start(Delegate* pDelegate);
+  // CodecModuleIface:
+  FX_FILESIZE GetAvailInput(Context* pContext) const override;
   bool Input(Context* pContext,
-             const uint8_t* src_buf,
-             uint32_t src_size,
-             CFX_DIBAttribute* pAttribute);
+             pdfium::span<uint8_t> src_buf,
+             CFX_DIBAttribute* pAttribute) override;
+
+  std::unique_ptr<Context> Start(Delegate* pDelegate);
 };
 
 #endif  // CORE_FXCODEC_CODEC_CCODEC_PNGMODULE_H_
diff --git a/core/fxcodec/codec/ccodec_progressivedecoder.cpp b/core/fxcodec/codec/ccodec_progressivedecoder.cpp
index f7c9f65..c2d121d 100644
--- a/core/fxcodec/codec/ccodec_progressivedecoder.cpp
+++ b/core/fxcodec/codec/ccodec_progressivedecoder.cpp
@@ -716,9 +716,9 @@
     return false;
   }
 
-  std::unique_ptr<CCodec_BmpModule::Context> pBmpContext =
+  std::unique_ptr<CodecModuleIface::Context> pBmpContext =
       pBmpModule->Start(this);
-  pBmpModule->Input(pBmpContext.get(), {m_pSrcBuf.get(), m_SrcSize});
+  pBmpModule->Input(pBmpContext.get(), {m_pSrcBuf.get(), m_SrcSize}, nullptr);
 
   std::vector<uint32_t> palette;
   int32_t readResult = pBmpModule->ReadHeader(
@@ -788,7 +788,7 @@
 
 bool CCodec_ProgressiveDecoder::BmpReadMoreData(
     CCodec_BmpModule* pBmpModule,
-    CCodec_BmpModule::Context* pBmpContext,
+    CodecModuleIface::Context* pBmpContext,
     FXCODEC_STATUS& err_status) {
   uint32_t dwSize = (uint32_t)m_pFile->GetSize();
   if (dwSize <= m_offSet)
@@ -825,7 +825,7 @@
     return false;
   }
   m_offSet += dwSize;
-  pBmpModule->Input(pBmpContext, {m_pSrcBuf.get(), dwSize + dwAvail});
+  pBmpModule->Input(pBmpContext, {m_pSrcBuf.get(), dwSize + dwAvail}, nullptr);
   return true;
 }
 
@@ -919,9 +919,9 @@
   }
 
   m_offSet += dwAmountToFetchFromFile;
-  pGifModule->Input(
-      m_pGifContext.get(),
-      {m_pSrcBuf.get(), dwAmountToFetchFromFile + dwUnusedBuffer});
+  pGifModule->Input(m_pGifContext.get(),
+                    {m_pSrcBuf.get(), dwAmountToFetchFromFile + dwUnusedBuffer},
+                    nullptr);
   m_InvalidateGifBuffer = false;
   return true;
 }
@@ -934,7 +934,7 @@
     return false;
   }
   m_pGifContext = pGifModule->Start(this);
-  pGifModule->Input(m_pGifContext.get(), {m_pSrcBuf.get(), m_SrcSize});
+  pGifModule->Input(m_pGifContext.get(), {m_pSrcBuf.get(), m_SrcSize}, nullptr);
   m_SrcComponents = 1;
   CFX_GifDecodeStatus readResult = pGifModule->ReadHeader(
       m_pGifContext.get(), &m_SrcWidth, &m_SrcHeight, &m_GifPltNumber,
@@ -1138,7 +1138,8 @@
     return false;
   }
   m_offSet += dwSize;
-  pJpegModule->Input(m_pJpegContext.get(), m_pSrcBuf.get(), dwSize + dwAvail);
+  pJpegModule->Input(m_pJpegContext.get(), {m_pSrcBuf.get(), dwSize + dwAvail},
+                     nullptr);
   return true;
 }
 
@@ -1150,10 +1151,11 @@
     m_status = FXCODEC_STATUS_ERR_MEMORY;
     return false;
   }
-  pJpegModule->Input(m_pJpegContext.get(), m_pSrcBuf.get(), m_SrcSize);
+  pJpegModule->Input(m_pJpegContext.get(), {m_pSrcBuf.get(), m_SrcSize},
+                     nullptr);
   // Setting jump marker before calling ReadHeader, since a longjmp to
   // the marker indicates a fatal error.
-  if (setjmp(*m_pJpegContext->GetJumpMark()) == -1) {
+  if (setjmp(*pJpegModule->GetJumpMark(m_pJpegContext.get())) == -1) {
     m_pJpegContext.reset();
     m_status = FXCODEC_STATUS_ERR_FORMAT;
     return false;
@@ -1184,17 +1186,17 @@
 
 FXCODEC_STATUS CCodec_ProgressiveDecoder::JpegStartDecode(
     const RetainPtr<CFX_DIBitmap>& pDIBitmap) {
+  CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule();
   int down_scale = 1;
   GetDownScale(down_scale);
   // Setting jump marker before calling StartScanLine, since a longjmp to
   // the marker indicates a fatal error.
-  if (setjmp(*m_pJpegContext->GetJumpMark()) == -1) {
+  if (setjmp(*pJpegModule->GetJumpMark(m_pJpegContext.get())) == -1) {
     m_pJpegContext.reset();
     m_status = FXCODEC_STATUS_ERROR;
     return FXCODEC_STATUS_ERROR;
   }
 
-  CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule();
   bool startStatus =
       pJpegModule->StartScanline(m_pJpegContext.get(), down_scale);
   while (!startStatus) {
@@ -1235,7 +1237,7 @@
   CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule();
   // Setting jump marker before calling ReadScanLine, since a longjmp to
   // the marker indicates a fatal error.
-  if (setjmp(*m_pJpegContext->GetJumpMark()) == -1) {
+  if (setjmp(*pJpegModule->GetJumpMark(m_pJpegContext.get())) == -1) {
     m_pJpegContext.reset();
     m_status = FXCODEC_STATUS_ERROR;
     return FXCODEC_STATUS_ERROR;
@@ -1360,8 +1362,8 @@
     m_status = FXCODEC_STATUS_ERR_MEMORY;
     return false;
   }
-  bool bResult = pPngModule->Input(m_pPngContext.get(), m_pSrcBuf.get(),
-                                   m_SrcSize, pAttribute);
+  bool bResult = pPngModule->Input(m_pPngContext.get(),
+                                   {m_pSrcBuf.get(), m_SrcSize}, pAttribute);
   while (bResult) {
     uint32_t remain_size = static_cast<uint32_t>(m_pFile->GetSize()) - m_offSet;
     uint32_t input_size =
@@ -1382,8 +1384,8 @@
       return false;
     }
     m_offSet += input_size;
-    bResult = pPngModule->Input(m_pPngContext.get(), m_pSrcBuf.get(),
-                                input_size, pAttribute);
+    bResult = pPngModule->Input(m_pPngContext.get(),
+                                {m_pSrcBuf.get(), input_size}, pAttribute);
   }
   m_pPngContext.reset();
   if (m_SrcPassNumber == 0) {
@@ -1472,8 +1474,8 @@
       return m_status;
     }
     m_offSet += input_size;
-    bResult = pPngModule->Input(m_pPngContext.get(), m_pSrcBuf.get(),
-                                input_size, nullptr);
+    bResult = pPngModule->Input(m_pPngContext.get(),
+                                {m_pSrcBuf.get(), input_size}, nullptr);
     if (!bResult) {
       m_pDeviceBitmap = nullptr;
       m_pFile = nullptr;
diff --git a/core/fxcodec/codec/ccodec_progressivedecoder.h b/core/fxcodec/codec/ccodec_progressivedecoder.h
index 87bf184..9a4572e 100644
--- a/core/fxcodec/codec/ccodec_progressivedecoder.h
+++ b/core/fxcodec/codec/ccodec_progressivedecoder.h
@@ -182,7 +182,7 @@
  private:
 #ifdef PDF_ENABLE_XFA_BMP
   bool BmpReadMoreData(CCodec_BmpModule* pBmpModule,
-                       CCodec_BmpModule::Context* pBmpContext,
+                       CodecModuleIface::Context* pBmpContext,
                        FXCODEC_STATUS& err_status);
   bool BmpDetectImageTypeInBuffer(CFX_DIBAttribute* pAttribute);
   FXCODEC_STATUS BmpStartDecode(const RetainPtr<CFX_DIBitmap>& pDIBitmap);
@@ -251,18 +251,18 @@
   std::unique_ptr<uint8_t, FxFreeDeleter> m_pSrcBuf;
   std::unique_ptr<uint8_t, FxFreeDeleter> m_pDecodeBuf;
   std::unique_ptr<FX_ARGB, FxFreeDeleter> m_pSrcPalette;
-  std::unique_ptr<CCodec_JpegModule::Context> m_pJpegContext;
+  std::unique_ptr<CodecModuleIface::Context> m_pJpegContext;
 #ifdef PDF_ENABLE_XFA_BMP
-  std::unique_ptr<CCodec_BmpModule::Context> m_pBmpContext;
+  std::unique_ptr<CodecModuleIface::Context> m_pBmpContext;
 #endif  // PDF_ENABLE_XFA_BMP
 #ifdef PDF_ENABLE_XFA_GIF
-  std::unique_ptr<CCodec_GifModule::Context> m_pGifContext;
+  std::unique_ptr<CodecModuleIface::Context> m_pGifContext;
 #endif  // PDF_ENABLE_XFA_GIF
 #ifdef PDF_ENABLE_XFA_PNG
-  std::unique_ptr<CCodec_PngModule::Context> m_pPngContext;
+  std::unique_ptr<CodecModuleIface::Context> m_pPngContext;
 #endif  // PDF_ENABLE_XFA_PNG
 #ifdef PDF_ENABLE_XFA_TIFF
-  std::unique_ptr<CCodec_TiffModule::Context> m_pTiffContext;
+  std::unique_ptr<CodecModuleIface::Context> m_pTiffContext;
 #endif  // PDF_ENABLE_XFA_TIFF
   uint32_t m_offSet = 0;
   uint32_t m_SrcSize = 0;
diff --git a/core/fxcodec/codec/ccodec_tiffmodule.cpp b/core/fxcodec/codec/ccodec_tiffmodule.cpp
index 78f631c..d2c6c26 100644
--- a/core/fxcodec/codec/ccodec_tiffmodule.cpp
+++ b/core/fxcodec/codec/ccodec_tiffmodule.cpp
@@ -32,7 +32,7 @@
 
 }  // namespace
 
-class CTiffContext final : public CCodec_TiffModule::Context {
+class CTiffContext final : public CodecModuleIface::Context {
  public:
   CTiffContext() = default;
   ~CTiffContext() override = default;
@@ -487,7 +487,7 @@
   return false;
 }
 
-std::unique_ptr<CCodec_TiffModule::Context> CCodec_TiffModule::CreateDecoder(
+std::unique_ptr<CodecModuleIface::Context> CCodec_TiffModule::CreateDecoder(
     const RetainPtr<IFX_SeekableReadStream>& file_ptr) {
   auto pDecoder = pdfium::MakeUnique<CTiffContext>();
   if (!pDecoder->InitDecoder(file_ptr))
@@ -496,6 +496,18 @@
   return pDecoder;
 }
 
+FX_FILESIZE CCodec_TiffModule::GetAvailInput(Context* pContext) const {
+  NOTREACHED();
+  return 0;
+}
+
+bool CCodec_TiffModule::Input(Context* pContext,
+                              pdfium::span<uint8_t> src_buf,
+                              CFX_DIBAttribute*) {
+  NOTREACHED();
+  return false;
+}
+
 bool CCodec_TiffModule::LoadFrameInfo(Context* pContext,
                                       int32_t frame,
                                       int32_t* width,
diff --git a/core/fxcodec/codec/ccodec_tiffmodule.h b/core/fxcodec/codec/ccodec_tiffmodule.h
index 8d3bed7..15d2a9f 100644
--- a/core/fxcodec/codec/ccodec_tiffmodule.h
+++ b/core/fxcodec/codec/ccodec_tiffmodule.h
@@ -9,6 +9,7 @@
 
 #include <memory>
 
+#include "core/fxcodec/codec/codec_module_iface.h"
 #include "core/fxcrt/fx_system.h"
 #include "core/fxcrt/retain_ptr.h"
 #include "core/fxge/dib/cfx_dibitmap.h"
@@ -16,15 +17,17 @@
 class CFX_DIBAttribute;
 class IFX_SeekableReadStream;
 
-class CCodec_TiffModule {
+class CCodec_TiffModule final : public CodecModuleIface {
  public:
-  class Context {
-   public:
-    virtual ~Context() {}
-  };
-
   std::unique_ptr<Context> CreateDecoder(
       const RetainPtr<IFX_SeekableReadStream>& file_ptr);
+
+  // CodecModuleIface:
+  FX_FILESIZE GetAvailInput(Context* pContext) const override;
+  bool Input(Context* pContext,
+             pdfium::span<uint8_t> src_buf,
+             CFX_DIBAttribute* pAttribute) override;
+
   bool LoadFrameInfo(Context* ctx,
                      int32_t frame,
                      int32_t* width,
diff --git a/core/fxcodec/codec/codec_module_iface.h b/core/fxcodec/codec/codec_module_iface.h
new file mode 100644
index 0000000..0846972
--- /dev/null
+++ b/core/fxcodec/codec/codec_module_iface.h
@@ -0,0 +1,35 @@
+// Copyright 2018 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_CODEC_CODEC_MODULE_IFACE_H_
+#define CORE_FXCODEC_CODEC_CODEC_MODULE_IFACE_H_
+
+#include "core/fxcrt/fx_system.h"
+#include "third_party/base/span.h"
+
+class CFX_DIBAttribute;
+
+class CodecModuleIface {
+ public:
+  class Context {
+   public:
+    virtual ~Context() {}
+  };
+
+  virtual ~CodecModuleIface() {}
+
+  // Returns the number of unprocessed bytes remaining in the input buffer.
+  virtual FX_FILESIZE GetAvailInput(Context* pContext) const = 0;
+
+  // Provides a new input buffer to the codec. Returns true on success,
+  // setting details about the image extracted from the buffer into |pAttribute|
+  // (if provided and the codec is capable providing that information).
+  virtual bool Input(Context* pContext,
+                     pdfium::span<uint8_t> src_buf,
+                     CFX_DIBAttribute* pAttribute) = 0;
+};
+
+#endif  // CORE_FXCODEC_CODEC_CODEC_MODULE_IFACE_H_
diff --git a/core/fxcodec/gif/cfx_gifcontext.h b/core/fxcodec/gif/cfx_gifcontext.h
index 5eae516..c2828db 100644
--- a/core/fxcodec/gif/cfx_gifcontext.h
+++ b/core/fxcodec/gif/cfx_gifcontext.h
@@ -18,7 +18,7 @@
 #include "core/fxcrt/unowned_ptr.h"
 #include "third_party/base/span.h"
 
-class CFX_GifContext : public CCodec_GifModule::Context {
+class CFX_GifContext : public CodecModuleIface::Context {
  public:
   CFX_GifContext(CCodec_GifModule* gif_module,
                  CCodec_GifModule::Delegate* delegate);