Use unique_ptrs for codec contexts in ccodec_progressivedecoder.

Change-Id: I4deaf8ca946c2dcb6842c5702b02eed1c22b1201
Reviewed-on: https://pdfium-review.googlesource.com/6191
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index 9ecd20d..d54df57 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -86,6 +86,7 @@
   if (is_win) {
     cflags += [
       "/wd4267",
+      "/wd4324",
       "/wd4577",
     ]
   }
diff --git a/core/fxcodec/codec/ccodec_bmpmodule.cpp b/core/fxcodec/codec/ccodec_bmpmodule.cpp
index ae0a30c..15394f1 100644
--- a/core/fxcodec/codec/ccodec_bmpmodule.cpp
+++ b/core/fxcodec/codec/ccodec_bmpmodule.cpp
@@ -11,13 +11,14 @@
 #include "core/fxcodec/lbmp/fx_bmp.h"
 #include "core/fxcrt/cfx_unowned_ptr.h"
 #include "core/fxge/fx_dib.h"
+#include "third_party/base/ptr_util.h"
 
-class CCodec_BmpModule::Context {
+class CBmpContext : public CCodec_BmpModule::Context {
  public:
-  Context(bmp_decompress_struct_p pBmp,
-          CCodec_BmpModule* pModule,
-          CCodec_BmpModule::Delegate* pDelegate);
-  ~Context();
+  CBmpContext(bmp_decompress_struct_p pBmp,
+              CCodec_BmpModule* pModule,
+              CCodec_BmpModule::Delegate* pDelegate);
+  ~CBmpContext() override;
 
   bmp_decompress_struct_p m_pBmp;
   CFX_UnownedPtr<CCodec_BmpModule> const m_pModule;
@@ -35,26 +36,26 @@
 static void bmp_read_scanline(bmp_decompress_struct_p pBmp,
                               int32_t row_num,
                               uint8_t* row_buf) {
-  auto* p = reinterpret_cast<CCodec_BmpModule::Context*>(pBmp->context_ptr);
+  auto* p = reinterpret_cast<CBmpContext*>(pBmp->context_ptr);
   p->m_pDelegate->BmpReadScanline(row_num, row_buf);
 }
 
 static bool bmp_get_data_position(bmp_decompress_struct_p pBmp,
                                   uint32_t rcd_pos) {
-  auto* p = reinterpret_cast<CCodec_BmpModule::Context*>(pBmp->context_ptr);
+  auto* p = reinterpret_cast<CBmpContext*>(pBmp->context_ptr);
   return p->m_pDelegate->BmpInputImagePositionBuf(rcd_pos);
 }
 
 }  // extern "C"
 
-CCodec_BmpModule::Context::Context(bmp_decompress_struct_p pBmp,
-                                   CCodec_BmpModule* pModule,
-                                   CCodec_BmpModule::Delegate* pDelegate)
+CBmpContext::CBmpContext(bmp_decompress_struct_p pBmp,
+                         CCodec_BmpModule* pModule,
+                         CCodec_BmpModule::Delegate* pDelegate)
     : m_pBmp(pBmp), m_pModule(pModule), m_pDelegate(pDelegate) {
   memset(m_szLastError, 0, sizeof(m_szLastError));
 }
 
-CCodec_BmpModule::Context::~Context() {
+CBmpContext::~CBmpContext() {
   bmp_destroy_decompress(&m_pBmp);
 }
 
@@ -62,13 +63,14 @@
 
 CCodec_BmpModule::~CCodec_BmpModule() {}
 
-CCodec_BmpModule::Context* CCodec_BmpModule::Start(Delegate* pDelegate) {
+std::unique_ptr<CCodec_BmpModule::Context> CCodec_BmpModule::Start(
+    Delegate* pDelegate) {
   bmp_decompress_struct_p pBmp = bmp_create_decompress();
   if (!pBmp)
     return nullptr;
 
-  auto* p = new Context(pBmp, this, pDelegate);
-  p->m_pBmp->context_ptr = p;
+  auto p = pdfium::MakeUnique<CBmpContext>(pBmp, this, pDelegate);
+  p->m_pBmp->context_ptr = p.get();
   p->m_pBmp->err_ptr = p->m_szLastError;
   p->m_pBmp->bmp_error_fn = bmp_error_data;
   p->m_pBmp->bmp_get_row_fn = bmp_read_scanline;
@@ -76,11 +78,7 @@
   return p;
 }
 
-void CCodec_BmpModule::Finish(Context* ctx) {
-  delete ctx;
-}
-
-int32_t CCodec_BmpModule::ReadHeader(Context* ctx,
+int32_t CCodec_BmpModule::ReadHeader(Context* pContext,
                                      int32_t* width,
                                      int32_t* height,
                                      bool* tb_flag,
@@ -88,6 +86,7 @@
                                      int32_t* pal_num,
                                      uint32_t** pal_pp,
                                      CFX_DIBAttribute* pAttribute) {
+  auto* ctx = static_cast<CBmpContext*>(pContext);
   if (setjmp(ctx->m_pBmp->jmpbuf)) {
     return 0;
   }
@@ -110,19 +109,22 @@
   return 1;
 }
 
-int32_t CCodec_BmpModule::LoadImage(Context* ctx) {
+int32_t CCodec_BmpModule::LoadImage(Context* pContext) {
+  auto* ctx = static_cast<CBmpContext*>(pContext);
   if (setjmp(ctx->m_pBmp->jmpbuf))
     return 0;
   return bmp_decode_image(ctx->m_pBmp);
 }
 
-uint32_t CCodec_BmpModule::GetAvailInput(Context* ctx,
+uint32_t CCodec_BmpModule::GetAvailInput(Context* pContext,
                                          uint8_t** avail_buf_ptr) {
+  auto* ctx = static_cast<CBmpContext*>(pContext);
   return bmp_get_avail_input(ctx->m_pBmp, avail_buf_ptr);
 }
 
-void CCodec_BmpModule::Input(Context* ctx,
+void CCodec_BmpModule::Input(Context* pContext,
                              const uint8_t* src_buf,
                              uint32_t src_size) {
+  auto* ctx = static_cast<CBmpContext*>(pContext);
   bmp_input_buffer(ctx->m_pBmp, (uint8_t*)src_buf, src_size);
 }
diff --git a/core/fxcodec/codec/ccodec_bmpmodule.h b/core/fxcodec/codec/ccodec_bmpmodule.h
index 7893fba..10bc6b7 100644
--- a/core/fxcodec/codec/ccodec_bmpmodule.h
+++ b/core/fxcodec/codec/ccodec_bmpmodule.h
@@ -7,6 +7,8 @@
 #ifndef CORE_FXCODEC_CODEC_CCODEC_BMPMODULE_H_
 #define CORE_FXCODEC_CODEC_CCODEC_BMPMODULE_H_
 
+#include <memory>
+
 #include "core/fxcrt/cfx_unowned_ptr.h"
 #include "core/fxcrt/fx_system.h"
 
@@ -14,7 +16,11 @@
 
 class CCodec_BmpModule {
  public:
-  class Context;
+  class Context {
+   public:
+    virtual ~Context() {}
+  };
+
   class Delegate {
    public:
     virtual bool BmpInputImagePositionBuf(uint32_t rcd_pos) = 0;
@@ -24,8 +30,7 @@
   CCodec_BmpModule();
   ~CCodec_BmpModule();
 
-  Context* Start(Delegate* pDelegate);
-  void Finish(Context* pContext);
+  std::unique_ptr<Context> Start(Delegate* pDelegate);
   uint32_t GetAvailInput(Context* pContext, uint8_t** avail_buf_ptr);
   void Input(Context* pContext, const uint8_t* src_buf, uint32_t src_size);
   int32_t ReadHeader(Context* pContext,
diff --git a/core/fxcodec/codec/ccodec_jpegmodule.h b/core/fxcodec/codec/ccodec_jpegmodule.h
index 276e46a..a583717 100644
--- a/core/fxcodec/codec/ccodec_jpegmodule.h
+++ b/core/fxcodec/codec/ccodec_jpegmodule.h
@@ -21,7 +21,10 @@
 
 class CCodec_JpegModule {
  public:
-  class Context;
+  class Context {
+   public:
+    virtual ~Context() {}
+  };
 
   std::unique_ptr<CCodec_ScanlineDecoder> CreateDecoder(const uint8_t* src_buf,
                                                         uint32_t src_size,
@@ -36,8 +39,8 @@
                 int* num_components,
                 int* bits_per_components,
                 bool* color_transform);
-  Context* Start();
-  void Finish(Context* pContext);
+
+  std::unique_ptr<Context> Start();
   void Input(Context* pContext, const uint8_t* src_buf, uint32_t src_size);
 
 #ifndef PDF_ENABLE_XFA
diff --git a/core/fxcodec/codec/ccodec_pngmodule.cpp b/core/fxcodec/codec/ccodec_pngmodule.cpp
index 39d4610b..8a3de3a 100644
--- a/core/fxcodec/codec/ccodec_pngmodule.cpp
+++ b/core/fxcodec/codec/ccodec_pngmodule.cpp
@@ -21,15 +21,15 @@
 
 #define PNG_ERROR_SIZE 256
 
-class CCodec_PngModule::Context {
+class CPngContext : public CCodec_PngModule::Context {
  public:
-  Context(CCodec_PngModule* pModule, Delegate* pDelegate);
-  ~Context();
+  CPngContext(CCodec_PngModule* pModule, CCodec_PngModule::Delegate* pDelegate);
+  ~CPngContext() override;
 
   png_structp m_pPng;
   png_infop m_pInfo;
   CFX_UnownedPtr<CCodec_PngModule> m_pModule;
-  CFX_UnownedPtr<Delegate> m_pDelegate;
+  CFX_UnownedPtr<CCodec_PngModule::Delegate> m_pDelegate;
   void* (*m_AllocFunc)(unsigned int);
   void (*m_FreeFunc)(void*);
   char m_szLastError[PNG_ERROR_SIZE];
@@ -104,8 +104,8 @@
 }
 
 static void _png_get_header_func(png_structp png_ptr, png_infop info_ptr) {
-  auto* pContext = reinterpret_cast<CCodec_PngModule::Context*>(
-      png_get_progressive_ptr(png_ptr));
+  auto* pContext =
+      reinterpret_cast<CPngContext*>(png_get_progressive_ptr(png_ptr));
   if (!pContext)
     return;
 
@@ -176,8 +176,8 @@
                               png_bytep new_row,
                               png_uint_32 row_num,
                               int pass) {
-  auto* pContext = reinterpret_cast<CCodec_PngModule::Context*>(
-      png_get_progressive_ptr(png_ptr));
+  auto* pContext =
+      reinterpret_cast<CPngContext*>(png_get_progressive_ptr(png_ptr));
   if (!pContext)
     return;
 
@@ -193,8 +193,8 @@
 
 }  // extern "C"
 
-CCodec_PngModule::Context::Context(CCodec_PngModule* pModule,
-                                   Delegate* pDelegate)
+CPngContext::CPngContext(CCodec_PngModule* pModule,
+                         CCodec_PngModule::Delegate* pDelegate)
     : m_pPng(nullptr),
       m_pInfo(nullptr),
       m_pModule(pModule),
@@ -204,13 +204,14 @@
   memset(m_szLastError, 0, sizeof(m_szLastError));
 }
 
-CCodec_PngModule::Context::~Context() {
+CPngContext::~CPngContext() {
   png_destroy_read_struct(m_pPng ? &m_pPng : nullptr,
                           m_pInfo ? &m_pInfo : nullptr, nullptr);
 }
 
-CCodec_PngModule::Context* CCodec_PngModule::Start(Delegate* pDelegate) {
-  auto p = pdfium::MakeUnique<Context>(this, pDelegate);
+std::unique_ptr<CCodec_PngModule::Context> CCodec_PngModule::Start(
+    Delegate* pDelegate) {
+  auto p = pdfium::MakeUnique<CPngContext>(this, pDelegate);
   p->m_pPng =
       png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
   if (!p->m_pPng)
@@ -227,17 +228,14 @@
                               _png_get_row_func, _png_get_end_func);
   png_set_error_fn(p->m_pPng, p->m_szLastError, _png_error_data,
                    _png_warning_data);
-  return p.release();
+  return p;
 }
 
-void CCodec_PngModule::Finish(Context* ctx) {
-  delete ctx;
-}
-
-bool CCodec_PngModule::Input(Context* ctx,
+bool CCodec_PngModule::Input(Context* pContext,
                              const uint8_t* src_buf,
                              uint32_t src_size,
                              CFX_DIBAttribute* pAttribute) {
+  auto* ctx = static_cast<CPngContext*>(pContext);
   if (setjmp(png_jmpbuf(ctx->m_pPng))) {
     if (pAttribute &&
         strcmp(ctx->m_szLastError, "Read Header Callback Error") == 0) {
diff --git a/core/fxcodec/codec/ccodec_pngmodule.h b/core/fxcodec/codec/ccodec_pngmodule.h
index b92e09c..121e646 100644
--- a/core/fxcodec/codec/ccodec_pngmodule.h
+++ b/core/fxcodec/codec/ccodec_pngmodule.h
@@ -7,14 +7,19 @@
 #ifndef CORE_FXCODEC_CODEC_CCODEC_PNGMODULE_H_
 #define CORE_FXCODEC_CODEC_CCODEC_PNGMODULE_H_
 
-#include "core/fxcrt/cfx_unowned_ptr.h"
+#include <memory>
+
 #include "core/fxcrt/fx_system.h"
 
 class CFX_DIBAttribute;
 
 class CCodec_PngModule {
  public:
-  class Context;
+  class Context {
+   public:
+    virtual ~Context() {}
+  };
+
   class Delegate {
    public:
     virtual bool PngReadHeader(int width,
@@ -27,8 +32,7 @@
     virtual void PngFillScanlineBufCompleted(int pass, int line) = 0;
   };
 
-  Context* Start(Delegate* pDelegate);
-  void Finish(Context* pContext);
+  std::unique_ptr<Context> Start(Delegate* pDelegate);
   bool Input(Context* pContext,
              const uint8_t* src_buf,
              uint32_t src_size,
diff --git a/core/fxcodec/codec/ccodec_progressivedecoder.h b/core/fxcodec/codec/ccodec_progressivedecoder.h
index 19101c1..50c5405 100644
--- a/core/fxcodec/codec/ccodec_progressivedecoder.h
+++ b/core/fxcodec/codec/ccodec_progressivedecoder.h
@@ -125,51 +125,6 @@
     std::vector<uint8_t> m_pWeightTables;
   };
 
-  CFX_RetainPtr<IFX_SeekableReadStream> m_pFile;
-  CFX_UnownedPtr<CCodec_ModuleMgr> m_pCodecMgr;
-
-  // TODO(tsepez): All these contexts probably should be unique_ptrs.
-  CFX_UnownedPtr<CCodec_JpegModule::Context> m_pJpegContext;
-  CFX_UnownedPtr<CCodec_PngModule::Context> m_pPngContext;
-  std::unique_ptr<CCodec_GifModule::Context> m_pGifContext;
-  CFX_UnownedPtr<CCodec_BmpModule::Context> m_pBmpContext;
-  CFX_UnownedPtr<CCodec_TiffContext> m_pTiffContext;
-  FXCODEC_IMAGE_TYPE m_imagType;
-  uint32_t m_offSet;
-  uint8_t* m_pSrcBuf;
-  uint32_t m_SrcSize;
-  uint8_t* m_pDecodeBuf;
-  int m_ScanlineSize;
-  CFX_RetainPtr<CFX_DIBitmap> m_pDeviceBitmap;
-  bool m_bInterpol;
-  CFXCODEC_WeightTable m_WeightHorz;
-  CFXCODEC_VertTable m_WeightVert;
-  CFXCODEC_HorzTable m_WeightHorzOO;
-  int m_SrcWidth;
-  int m_SrcHeight;
-  int m_SrcComponents;
-  int m_SrcBPC;
-  FX_RECT m_clipBox;
-  int m_startX;
-  int m_startY;
-  int m_sizeX;
-  int m_sizeY;
-  int m_TransMethod;
-  FX_ARGB* m_pSrcPalette;
-  int m_SrcPaletteNumber;
-  int m_SrcRow;
-  FXCodec_Format m_SrcFormat;
-  int m_SrcPassNumber;
-  int m_FrameNumber;
-  int m_FrameCur;
-  int m_GifBgIndex;
-  uint8_t* m_pGifPalette;
-  int32_t m_GifPltNumber;
-  int m_GifTransIndex;
-  FX_RECT m_GifFrameRect;
-  bool m_BmpIsTopBottom;
-  FXCODEC_STATUS m_status;
-
   // CCodec_PngModule::Delegate
   bool PngReadHeader(int width,
                      int height,
@@ -197,7 +152,7 @@
   bool BmpInputImagePositionBuf(uint32_t rcd_pos) override;
   void BmpReadScanline(int32_t row_num, uint8_t* row_buf) override;
 
- protected:
+ private:
   bool BmpReadMoreData(CCodec_BmpModule* pBmpModule,
                        FXCODEC_STATUS& err_status);
   bool GifReadMoreData(CCodec_GifModule* pGifModule,
@@ -231,6 +186,49 @@
   void ResampleVertBT(const CFX_RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
                       double scale_y,
                       int des_row);
+
+  CFX_RetainPtr<IFX_SeekableReadStream> m_pFile;
+  CFX_RetainPtr<CFX_DIBitmap> m_pDeviceBitmap;
+  CFX_UnownedPtr<CCodec_ModuleMgr> m_pCodecMgr;
+  std::unique_ptr<CCodec_JpegModule::Context> m_pJpegContext;
+  std::unique_ptr<CCodec_PngModule::Context> m_pPngContext;
+  std::unique_ptr<CCodec_GifModule::Context> m_pGifContext;
+  std::unique_ptr<CCodec_BmpModule::Context> m_pBmpContext;
+  std::unique_ptr<CCodec_TiffModule::Context> m_pTiffContext;
+  FXCODEC_IMAGE_TYPE m_imagType;
+  uint32_t m_offSet;
+  uint8_t* m_pSrcBuf;
+  uint32_t m_SrcSize;
+  uint8_t* m_pDecodeBuf;
+  int m_ScanlineSize;
+  bool m_bInterpol;
+  CFXCODEC_WeightTable m_WeightHorz;
+  CFXCODEC_VertTable m_WeightVert;
+  CFXCODEC_HorzTable m_WeightHorzOO;
+  int m_SrcWidth;
+  int m_SrcHeight;
+  int m_SrcComponents;
+  int m_SrcBPC;
+  FX_RECT m_clipBox;
+  int m_startX;
+  int m_startY;
+  int m_sizeX;
+  int m_sizeY;
+  int m_TransMethod;
+  FX_ARGB* m_pSrcPalette;
+  int m_SrcPaletteNumber;
+  int m_SrcRow;
+  FXCodec_Format m_SrcFormat;
+  int m_SrcPassNumber;
+  int m_FrameNumber;
+  int m_FrameCur;
+  int m_GifBgIndex;
+  uint8_t* m_pGifPalette;
+  int32_t m_GifPltNumber;
+  int m_GifTransIndex;
+  FX_RECT m_GifFrameRect;
+  bool m_BmpIsTopBottom;
+  FXCODEC_STATUS m_status;
 };
 
 #endif  // CORE_FXCODEC_CODEC_CCODEC_PROGRESSIVEDECODER_H_
diff --git a/core/fxcodec/codec/ccodec_tiffmodule.cpp b/core/fxcodec/codec/ccodec_tiffmodule.cpp
index 6ead576..1f10106 100644
--- a/core/fxcodec/codec/ccodec_tiffmodule.cpp
+++ b/core/fxcodec/codec/ccodec_tiffmodule.cpp
@@ -21,10 +21,10 @@
 #include "third_party/libtiff/tiffiop.h"
 }
 
-class CCodec_TiffContext {
+class CTiffContext : public CCodec_TiffModule::Context {
  public:
-  CCodec_TiffContext();
-  ~CCodec_TiffContext();
+  CTiffContext();
+  ~CTiffContext() override;
 
   bool InitDecoder(const CFX_RetainPtr<IFX_SeekableReadStream>& file_ptr);
   bool LoadFrameInfo(int32_t frame,
@@ -101,8 +101,7 @@
 namespace {
 
 tsize_t tiff_read(thandle_t context, tdata_t buf, tsize_t length) {
-  CCodec_TiffContext* pTiffContext =
-      reinterpret_cast<CCodec_TiffContext*>(context);
+  CTiffContext* pTiffContext = reinterpret_cast<CTiffContext*>(context);
   FX_SAFE_UINT32 increment = pTiffContext->offset();
   increment += length;
   if (!increment.IsValid())
@@ -125,8 +124,7 @@
 }
 
 toff_t tiff_seek(thandle_t context, toff_t offset, int whence) {
-  CCodec_TiffContext* pTiffContext =
-      reinterpret_cast<CCodec_TiffContext*>(context);
+  CTiffContext* pTiffContext = reinterpret_cast<CTiffContext*>(context);
   FX_SAFE_FILESIZE safe_offset = offset;
   if (!safe_offset.IsValid())
     return static_cast<toff_t>(-1);
@@ -163,8 +161,7 @@
 }
 
 toff_t tiff_get_size(thandle_t context) {
-  CCodec_TiffContext* pTiffContext =
-      reinterpret_cast<CCodec_TiffContext*>(context);
+  CTiffContext* pTiffContext = reinterpret_cast<CTiffContext*>(context);
   return static_cast<toff_t>(pTiffContext->io_in()->GetSize());
 }
 
@@ -221,27 +218,27 @@
 
 }  // namespace
 
-CCodec_TiffContext::CCodec_TiffContext()
+CTiffContext::CTiffContext()
     : m_io_in(nullptr), m_offset(0), m_tif_ctx(nullptr) {}
 
-CCodec_TiffContext::~CCodec_TiffContext() {
+CTiffContext::~CTiffContext() {
   if (m_tif_ctx)
     TIFFClose(m_tif_ctx);
 }
 
-bool CCodec_TiffContext::InitDecoder(
+bool CTiffContext::InitDecoder(
     const CFX_RetainPtr<IFX_SeekableReadStream>& file_ptr) {
   m_io_in = file_ptr;
   m_tif_ctx = tiff_open(this, "r");
   return !!m_tif_ctx;
 }
 
-bool CCodec_TiffContext::LoadFrameInfo(int32_t frame,
-                                       int32_t* width,
-                                       int32_t* height,
-                                       int32_t* comps,
-                                       int32_t* bpc,
-                                       CFX_DIBAttribute* pAttribute) {
+bool CTiffContext::LoadFrameInfo(int32_t frame,
+                                 int32_t* width,
+                                 int32_t* height,
+                                 int32_t* comps,
+                                 int32_t* bpc,
+                                 CFX_DIBAttribute* pAttribute) {
   if (!TIFFSetDirectory(m_tif_ctx, (uint16)frame))
     return false;
 
@@ -293,7 +290,7 @@
   return true;
 }
 
-bool CCodec_TiffContext::IsSupport(
+bool CTiffContext::IsSupport(
     const CFX_RetainPtr<CFX_DIBitmap>& pDIBitmap) const {
   if (TIFFIsTiled(m_tif_ctx))
     return false;
@@ -324,9 +321,8 @@
   return planarconfig != PLANARCONFIG_SEPARATE;
 }
 
-void CCodec_TiffContext::SetPalette(
-    const CFX_RetainPtr<CFX_DIBitmap>& pDIBitmap,
-    uint16_t bps) {
+void CTiffContext::SetPalette(const CFX_RetainPtr<CFX_DIBitmap>& pDIBitmap,
+                              uint16_t bps) {
   uint16_t* red_orig = nullptr;
   uint16_t* green_orig = nullptr;
   uint16_t* blue_orig = nullptr;
@@ -349,12 +345,11 @@
   }
 }
 
-bool CCodec_TiffContext::Decode1bppRGB(
-    const CFX_RetainPtr<CFX_DIBitmap>& pDIBitmap,
-    int32_t height,
-    int32_t width,
-    uint16_t bps,
-    uint16_t spp) {
+bool CTiffContext::Decode1bppRGB(const CFX_RetainPtr<CFX_DIBitmap>& pDIBitmap,
+                                 int32_t height,
+                                 int32_t width,
+                                 uint16_t bps,
+                                 uint16_t spp) {
   if (pDIBitmap->GetBPP() != 1 || spp != 1 || bps != 1 ||
       !IsSupport(pDIBitmap)) {
     return false;
@@ -378,12 +373,11 @@
   return true;
 }
 
-bool CCodec_TiffContext::Decode8bppRGB(
-    const CFX_RetainPtr<CFX_DIBitmap>& pDIBitmap,
-    int32_t height,
-    int32_t width,
-    uint16_t bps,
-    uint16_t spp) {
+bool CTiffContext::Decode8bppRGB(const CFX_RetainPtr<CFX_DIBitmap>& pDIBitmap,
+                                 int32_t height,
+                                 int32_t width,
+                                 uint16_t bps,
+                                 uint16_t spp) {
   if (pDIBitmap->GetBPP() != 8 || spp != 1 || (bps != 4 && bps != 8) ||
       !IsSupport(pDIBitmap)) {
     return false;
@@ -415,12 +409,11 @@
   return true;
 }
 
-bool CCodec_TiffContext::Decode24bppRGB(
-    const CFX_RetainPtr<CFX_DIBitmap>& pDIBitmap,
-    int32_t height,
-    int32_t width,
-    uint16_t bps,
-    uint16_t spp) {
+bool CTiffContext::Decode24bppRGB(const CFX_RetainPtr<CFX_DIBitmap>& pDIBitmap,
+                                  int32_t height,
+                                  int32_t width,
+                                  uint16_t bps,
+                                  uint16_t spp) {
   if (pDIBitmap->GetBPP() != 24 || !IsSupport(pDIBitmap))
     return false;
 
@@ -444,7 +437,7 @@
   return true;
 }
 
-bool CCodec_TiffContext::Decode(const CFX_RetainPtr<CFX_DIBitmap>& pDIBitmap) {
+bool CTiffContext::Decode(const CFX_RetainPtr<CFX_DIBitmap>& pDIBitmap) {
   uint32_t img_wid = pDIBitmap->GetWidth();
   uint32_t img_hei = pDIBitmap->GetHeight();
   uint32_t width = 0;
@@ -485,30 +478,28 @@
   return false;
 }
 
-CCodec_TiffContext* CCodec_TiffModule::CreateDecoder(
+std::unique_ptr<CCodec_TiffModule::Context> CCodec_TiffModule::CreateDecoder(
     const CFX_RetainPtr<IFX_SeekableReadStream>& file_ptr) {
-  auto pDecoder = pdfium::MakeUnique<CCodec_TiffContext>();
+  auto pDecoder = pdfium::MakeUnique<CTiffContext>();
   if (!pDecoder->InitDecoder(file_ptr))
     return nullptr;
 
-  return pDecoder.release();
+  return pDecoder;
 }
 
-bool CCodec_TiffModule::LoadFrameInfo(CCodec_TiffContext* ctx,
+bool CCodec_TiffModule::LoadFrameInfo(Context* pContext,
                                       int32_t frame,
                                       int32_t* width,
                                       int32_t* height,
                                       int32_t* comps,
                                       int32_t* bpc,
                                       CFX_DIBAttribute* pAttribute) {
+  auto* ctx = static_cast<CTiffContext*>(pContext);
   return ctx->LoadFrameInfo(frame, width, height, comps, bpc, pAttribute);
 }
 
-bool CCodec_TiffModule::Decode(CCodec_TiffContext* ctx,
+bool CCodec_TiffModule::Decode(Context* pContext,
                                const CFX_RetainPtr<CFX_DIBitmap>& pDIBitmap) {
+  auto* ctx = static_cast<CTiffContext*>(pContext);
   return ctx->Decode(pDIBitmap);
 }
-
-void CCodec_TiffModule::DestroyDecoder(CCodec_TiffContext* ctx) {
-  delete ctx;
-}
diff --git a/core/fxcodec/codec/ccodec_tiffmodule.h b/core/fxcodec/codec/ccodec_tiffmodule.h
index be791e5..73d9c37 100644
--- a/core/fxcodec/codec/ccodec_tiffmodule.h
+++ b/core/fxcodec/codec/ccodec_tiffmodule.h
@@ -7,27 +7,31 @@
 #ifndef CORE_FXCODEC_CODEC_CCODEC_TIFFMODULE_H_
 #define CORE_FXCODEC_CODEC_CCODEC_TIFFMODULE_H_
 
+#include <memory>
+
 #include "core/fxcrt/cfx_retain_ptr.h"
 #include "core/fxcrt/fx_system.h"
 #include "core/fxge/dib/cfx_dibitmap.h"
 
-class CCodec_TiffContext;
 class CFX_DIBAttribute;
 
 class CCodec_TiffModule {
  public:
-  CCodec_TiffContext* CreateDecoder(
+  class Context {
+   public:
+    virtual ~Context() {}
+  };
+
+  std::unique_ptr<Context> CreateDecoder(
       const CFX_RetainPtr<IFX_SeekableReadStream>& file_ptr);
-  bool LoadFrameInfo(CCodec_TiffContext* ctx,
+  bool LoadFrameInfo(Context* ctx,
                      int32_t frame,
                      int32_t* width,
                      int32_t* height,
                      int32_t* comps,
                      int32_t* bpc,
                      CFX_DIBAttribute* pAttribute);
-  bool Decode(CCodec_TiffContext* ctx,
-              const CFX_RetainPtr<CFX_DIBitmap>& pDIBitmap);
-  void DestroyDecoder(CCodec_TiffContext* ctx);
+  bool Decode(Context* ctx, const CFX_RetainPtr<CFX_DIBitmap>& pDIBitmap);
 };
 
 #endif  // CORE_FXCODEC_CODEC_CCODEC_TIFFMODULE_H_
diff --git a/core/fxcodec/codec/fx_codec_jpeg.cpp b/core/fxcodec/codec/fx_codec_jpeg.cpp
index 741d43d..521053a 100644
--- a/core/fxcodec/codec/fx_codec_jpeg.cpp
+++ b/core/fxcodec/codec/fx_codec_jpeg.cpp
@@ -28,10 +28,10 @@
 #endif
 }  // extern "C"
 
-class CCodec_JpegModule::Context {
+class CJpegContext : public CCodec_JpegModule::Context {
  public:
-  Context();
-  ~Context();
+  CJpegContext();
+  ~CJpegContext() override;
 
   jmp_buf m_JumpMark;
   jpeg_decompress_struct m_Info;
@@ -363,15 +363,13 @@
 extern "C" {
 
 static void _error_fatal1(j_common_ptr cinfo) {
-  auto* pContext =
-      reinterpret_cast<CCodec_JpegModule::Context*>(cinfo->client_data);
+  auto* pContext = reinterpret_cast<CJpegContext*>(cinfo->client_data);
   longjmp(pContext->m_JumpMark, -1);
 }
 
 static void _src_skip_data1(struct jpeg_decompress_struct* cinfo, long num) {
   if (cinfo->src->bytes_in_buffer < (size_t)num) {
-    auto* pContext =
-        reinterpret_cast<CCodec_JpegModule::Context*>(cinfo->client_data);
+    auto* pContext = reinterpret_cast<CJpegContext*>(cinfo->client_data);
     pContext->m_SkipSize = (unsigned int)(num - cinfo->src->bytes_in_buffer);
     cinfo->src->bytes_in_buffer = 0;
   } else {
@@ -390,7 +388,7 @@
 
 }  // extern "C"
 
-CCodec_JpegModule::Context::Context()
+CJpegContext::CJpegContext()
     : m_SkipSize(0), m_AllocFunc(jpeg_alloc_func), m_FreeFunc(jpeg_free_func) {
   memset(&m_Info, 0, sizeof(m_Info));
   m_Info.client_data = this;
@@ -411,28 +409,26 @@
   m_SrcMgr.resync_to_restart = _src_resync;
 }
 
-CCodec_JpegModule::Context::~Context() {
+CJpegContext::~CJpegContext() {
   jpeg_destroy_decompress(&m_Info);
 }
 
-CCodec_JpegModule::Context* CCodec_JpegModule::Start() {
-  auto* pContext = new CCodec_JpegModule::Context();
+std::unique_ptr<CCodec_JpegModule::Context> CCodec_JpegModule::Start() {
+  // Use ordinary pointer until past the fear of a longjump.
+  auto* pContext = new CJpegContext();
   if (setjmp(pContext->m_JumpMark) == -1)
     return nullptr;
 
   jpeg_create_decompress(&pContext->m_Info);
   pContext->m_Info.src = &pContext->m_SrcMgr;
   pContext->m_SkipSize = 0;
-  return pContext;
+  return pdfium::WrapUnique(pContext);
 }
 
-void CCodec_JpegModule::Finish(Context* ctx) {
-  delete ctx;
-}
-
-void CCodec_JpegModule::Input(Context* ctx,
+void CCodec_JpegModule::Input(Context* pContext,
                               const unsigned char* src_buf,
                               uint32_t src_size) {
+  auto* ctx = static_cast<CJpegContext*>(pContext);
   if (ctx->m_SkipSize) {
     if (ctx->m_SkipSize > src_size) {
       ctx->m_SrcMgr.bytes_in_buffer = 0;
@@ -448,17 +444,18 @@
 }
 
 #ifdef PDF_ENABLE_XFA
-int CCodec_JpegModule::ReadHeader(Context* ctx,
+int CCodec_JpegModule::ReadHeader(Context* pContext,
                                   int* width,
                                   int* height,
                                   int* nComps,
                                   CFX_DIBAttribute* pAttribute) {
 #else   // PDF_ENABLE_XFA
-int CCodec_JpegModule::ReadHeader(Context* ctx,
+int CCodec_JpegModule::ReadHeader(Context* pContext,
                                   int* width,
                                   int* height,
                                   int* nComps) {
 #endif  // PDF_ENABLE_XFA
+  auto* ctx = static_cast<CJpegContext*>(pContext);
   if (setjmp(ctx->m_JumpMark) == -1)
     return 1;
 
@@ -477,7 +474,8 @@
   return 0;
 }
 
-bool CCodec_JpegModule::StartScanline(Context* ctx, int down_scale) {
+bool CCodec_JpegModule::StartScanline(Context* pContext, int down_scale) {
+  auto* ctx = static_cast<CJpegContext*>(pContext);
   if (setjmp(ctx->m_JumpMark) == -1)
     return false;
 
@@ -485,7 +483,9 @@
   return !!jpeg_start_decompress(&ctx->m_Info);
 }
 
-bool CCodec_JpegModule::ReadScanline(Context* ctx, unsigned char* dest_buf) {
+bool CCodec_JpegModule::ReadScanline(Context* pContext,
+                                     unsigned char* dest_buf) {
+  auto* ctx = static_cast<CJpegContext*>(pContext);
   if (setjmp(ctx->m_JumpMark) == -1)
     return false;
 
@@ -493,8 +493,9 @@
   return nlines == 1;
 }
 
-uint32_t CCodec_JpegModule::GetAvailInput(Context* ctx,
+uint32_t CCodec_JpegModule::GetAvailInput(Context* pContext,
                                           uint8_t** avail_buf_ptr) {
+  auto* ctx = static_cast<CJpegContext*>(pContext);
   if (avail_buf_ptr) {
     *avail_buf_ptr = nullptr;
     if (ctx->m_SrcMgr.bytes_in_buffer > 0) {
diff --git a/core/fxcodec/codec/fx_codec_progress.cpp b/core/fxcodec/codec/fx_codec_progress.cpp
index a11ba44..5ec7d66 100644
--- a/core/fxcodec/codec/fx_codec_progress.cpp
+++ b/core/fxcodec/codec/fx_codec_progress.cpp
@@ -294,15 +294,6 @@
 }
 
 CCodec_ProgressiveDecoder::~CCodec_ProgressiveDecoder() {
-  m_pFile = nullptr;
-  if (m_pJpegContext)
-    m_pCodecMgr->GetJpegModule()->Finish(m_pJpegContext.Release());
-  if (m_pBmpContext)
-    m_pCodecMgr->GetBmpModule()->Finish(m_pBmpContext.Release());
-  if (m_pPngContext)
-    m_pCodecMgr->GetPngModule()->Finish(m_pPngContext.Release());
-  if (m_pTiffContext)
-    m_pCodecMgr->GetTiffModule()->DestroyDecoder(m_pTiffContext.Release());
   FX_Free(m_pSrcBuf);
   FX_Free(m_pDecodeBuf);
   FX_Free(m_pSrcPalette);
@@ -315,7 +306,7 @@
     return false;
   }
   dwSize = dwSize - m_offSet;
-  uint32_t dwAvail = pJpegModule->GetAvailInput(m_pJpegContext.Get(), nullptr);
+  uint32_t dwAvail = pJpegModule->GetAvailInput(m_pJpegContext.get(), nullptr);
   if (dwAvail == m_SrcSize) {
     if (dwSize > FXCODEC_BLOCK_SIZE) {
       dwSize = FXCODEC_BLOCK_SIZE;
@@ -341,7 +332,7 @@
     return false;
   }
   m_offSet += dwSize;
-  pJpegModule->Input(m_pJpegContext.Get(), m_pSrcBuf, dwSize + dwAvail);
+  pJpegModule->Input(m_pJpegContext.get(), m_pSrcBuf, dwSize + dwAvail);
   return true;
 }
 
@@ -851,7 +842,7 @@
     return false;
 
   dwSize = dwSize - m_offSet;
-  uint32_t dwAvail = pBmpModule->GetAvailInput(m_pBmpContext.Get(), nullptr);
+  uint32_t dwAvail = pBmpModule->GetAvailInput(m_pBmpContext.get(), nullptr);
   if (dwAvail == m_SrcSize) {
     if (dwSize > FXCODEC_BLOCK_SIZE) {
       dwSize = FXCODEC_BLOCK_SIZE;
@@ -877,7 +868,7 @@
     return false;
   }
   m_offSet += dwSize;
-  pBmpModule->Input(m_pBmpContext.Get(), m_pSrcBuf, dwSize + dwAvail);
+  pBmpModule->Input(m_pBmpContext.get(), m_pSrcBuf, dwSize + dwAvail);
   return true;
 }
 
@@ -1031,10 +1022,10 @@
         return false;
       }
       m_offSet += size;
-      pBmpModule->Input(m_pBmpContext.Get(), m_pSrcBuf, size);
+      pBmpModule->Input(m_pBmpContext.get(), m_pSrcBuf, size);
       uint32_t* pPalette = nullptr;
       int32_t readResult = pBmpModule->ReadHeader(
-          m_pBmpContext.Get(), &m_SrcWidth, &m_SrcHeight, &m_BmpIsTopBottom,
+          m_pBmpContext.get(), &m_SrcWidth, &m_SrcHeight, &m_BmpIsTopBottom,
           &m_SrcComponents, &m_SrcPaletteNumber, &pPalette, pAttribute);
       while (readResult == 2) {
         FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT;
@@ -1043,7 +1034,7 @@
           return false;
         }
         readResult = pBmpModule->ReadHeader(
-            m_pBmpContext.Get(), &m_SrcWidth, &m_SrcHeight, &m_BmpIsTopBottom,
+            m_pBmpContext.get(), &m_SrcWidth, &m_SrcHeight, &m_BmpIsTopBottom,
             &m_SrcComponents, &m_SrcPaletteNumber, &pPalette, pAttribute);
       }
       if (readResult == 1) {
@@ -1059,8 +1050,7 @@
         }
         return true;
       }
-      if (m_pBmpContext)
-        pBmpModule->Finish(m_pBmpContext.Release());
+      m_pBmpContext.reset();
       m_status = FXCODEC_STATUS_ERR_FORMAT;
       return false;
     }
@@ -1077,9 +1067,9 @@
         return false;
       }
       m_offSet += size;
-      pJpegModule->Input(m_pJpegContext.Get(), m_pSrcBuf, size);
+      pJpegModule->Input(m_pJpegContext.get(), m_pSrcBuf, size);
       int32_t readResult =
-          pJpegModule->ReadHeader(m_pJpegContext.Get(), &m_SrcWidth,
+          pJpegModule->ReadHeader(m_pJpegContext.get(), &m_SrcWidth,
                                   &m_SrcHeight, &m_SrcComponents, pAttribute);
       while (readResult == 2) {
         FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT;
@@ -1088,7 +1078,7 @@
           return false;
         }
         readResult =
-            pJpegModule->ReadHeader(m_pJpegContext.Get(), &m_SrcWidth,
+            pJpegModule->ReadHeader(m_pJpegContext.get(), &m_SrcWidth,
                                     &m_SrcHeight, &m_SrcComponents, pAttribute);
       }
       if (!readResult) {
@@ -1096,8 +1086,7 @@
         m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
         return true;
       }
-      if (m_pJpegContext)
-        pJpegModule->Finish(m_pJpegContext.Release());
+      m_pJpegContext.reset();
       m_status = FXCODEC_STATUS_ERR_FORMAT;
       return false;
     }
@@ -1119,14 +1108,13 @@
       }
       m_offSet += size;
       bResult =
-          pPngModule->Input(m_pPngContext.Get(), m_pSrcBuf, size, pAttribute);
+          pPngModule->Input(m_pPngContext.get(), m_pSrcBuf, size, pAttribute);
       while (bResult) {
         uint32_t remain_size = (uint32_t)m_pFile->GetSize() - m_offSet;
         uint32_t input_size =
             remain_size > FXCODEC_BLOCK_SIZE ? FXCODEC_BLOCK_SIZE : remain_size;
         if (input_size == 0) {
-          if (m_pPngContext)
-            pPngModule->Finish(m_pPngContext.Release());
+          m_pPngContext.reset();
           m_status = FXCODEC_STATUS_ERR_FORMAT;
           return false;
         }
@@ -1142,12 +1130,11 @@
           return false;
         }
         m_offSet += input_size;
-        bResult = pPngModule->Input(m_pPngContext.Get(), m_pSrcBuf, input_size,
+        bResult = pPngModule->Input(m_pPngContext.get(), m_pSrcBuf, input_size,
                                     pAttribute);
       }
       ASSERT(!bResult);
-      if (m_pPngContext)
-        pPngModule->Finish(m_pPngContext.Release());
+      m_pPngContext.reset();
       if (m_SrcPassNumber == 0) {
         m_status = FXCODEC_STATUS_ERR_FORMAT;
         return false;
@@ -1204,12 +1191,12 @@
       }
       int32_t dummy_bpc;
       bool ret = pTiffModule->LoadFrameInfo(
-          m_pTiffContext.Get(), 0, &m_SrcWidth, &m_SrcHeight, &m_SrcComponents,
+          m_pTiffContext.get(), 0, &m_SrcWidth, &m_SrcHeight, &m_SrcComponents,
           &dummy_bpc, pAttribute);
       m_SrcComponents = 4;
       m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
       if (!ret) {
-        pTiffModule->DestroyDecoder(m_pTiffContext.Release());
+        m_pTiffContext.reset();
         m_status = FXCODEC_STATUS_ERR_FORMAT;
         return false;
       }
@@ -1863,7 +1850,7 @@
       GetDownScale(down_scale);
       CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule();
       bool bStart =
-          pJpegModule->StartScanline(m_pJpegContext.Get(), down_scale);
+          pJpegModule->StartScanline(m_pJpegContext.get(), down_scale);
       while (!bStart) {
         FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR;
         if (!JpegReadMoreData(pJpegModule, error_status)) {
@@ -1872,7 +1859,7 @@
           m_status = error_status;
           return m_status;
         }
-        bStart = pJpegModule->StartScanline(m_pJpegContext.Get(), down_scale);
+        bStart = pJpegModule->StartScanline(m_pJpegContext.get(), down_scale);
       }
       int scanline_size = (m_SrcWidth + down_scale - 1) / down_scale;
       scanline_size = (scanline_size * m_SrcComponents + 3) / 4 * 4;
@@ -1905,8 +1892,6 @@
         m_status = FXCODEC_STATUS_ERR_MEMORY;
         return m_status;
       }
-      if (m_pPngContext)
-        pPngModule->Finish(m_pPngContext.Release());
       m_pPngContext = pPngModule->Start(this);
       if (!m_pPngContext) {
         m_pDeviceBitmap = nullptr;
@@ -2015,7 +2000,7 @@
       CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule();
       while (true) {
         bool readRes =
-            pJpegModule->ReadScanline(m_pJpegContext.Get(), m_pDecodeBuf);
+            pJpegModule->ReadScanline(m_pJpegContext.get(), m_pDecodeBuf);
         while (!readRes) {
           FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH;
           if (!JpegReadMoreData(pJpegModule, error_status)) {
@@ -2025,7 +2010,7 @@
             return m_status;
           }
           readRes =
-              pJpegModule->ReadScanline(m_pJpegContext.Get(), m_pDecodeBuf);
+              pJpegModule->ReadScanline(m_pJpegContext.get(), m_pDecodeBuf);
         }
         if (m_SrcFormat == FXCodec_Rgb) {
           int src_Bpp = (m_SrcFormat & 0xff) >> 3;
@@ -2052,8 +2037,7 @@
         uint32_t input_size =
             remain_size > FXCODEC_BLOCK_SIZE ? FXCODEC_BLOCK_SIZE : remain_size;
         if (input_size == 0) {
-          if (m_pPngContext)
-            pPngModule->Finish(m_pPngContext.Release());
+          m_pPngContext.reset();
           m_pDeviceBitmap = nullptr;
           m_pFile = nullptr;
           m_status = FXCODEC_STATUS_DECODE_FINISH;
@@ -2073,7 +2057,7 @@
           return m_status;
         }
         m_offSet += input_size;
-        bResult = pPngModule->Input(m_pPngContext.Get(), m_pSrcBuf, input_size,
+        bResult = pPngModule->Input(m_pPngContext.get(), m_pSrcBuf, input_size,
                                     nullptr);
         if (!bResult) {
           m_pDeviceBitmap = nullptr;
@@ -2122,7 +2106,7 @@
         return m_status;
       }
       while (true) {
-        int32_t readRes = pBmpModule->LoadImage(m_pBmpContext.Get());
+        int32_t readRes = pBmpModule->LoadImage(m_pBmpContext.get());
         while (readRes == 2) {
           FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH;
           if (!BmpReadMoreData(pBmpModule, error_status)) {
@@ -2131,7 +2115,7 @@
             m_status = error_status;
             return m_status;
           }
-          readRes = pBmpModule->LoadImage(m_pBmpContext.Get());
+          readRes = pBmpModule->LoadImage(m_pBmpContext.get());
         }
         if (readRes == 1) {
           m_pDeviceBitmap = nullptr;
@@ -2158,7 +2142,7 @@
           m_SrcHeight == m_sizeY && m_startX == 0 && m_startY == 0 &&
           m_clipBox.left == 0 && m_clipBox.top == 0 &&
           m_clipBox.right == m_SrcWidth && m_clipBox.bottom == m_SrcHeight) {
-        ret = pTiffModule->Decode(m_pTiffContext.Get(), m_pDeviceBitmap);
+        ret = pTiffModule->Decode(m_pTiffContext.get(), m_pDeviceBitmap);
         m_pDeviceBitmap = nullptr;
         m_pFile = nullptr;
         if (!ret) {
@@ -2177,7 +2161,7 @@
         m_status = FXCODEC_STATUS_ERR_MEMORY;
         return m_status;
       }
-      ret = pTiffModule->Decode(m_pTiffContext.Get(), pDIBitmap);
+      ret = pTiffModule->Decode(m_pTiffContext.get(), pDIBitmap);
       if (!ret) {
         m_pDeviceBitmap = nullptr;
         m_pFile = nullptr;