Remove some CPDFXFA_Context usage from top-level fpdfsdk layer.

The CPDF_Document::Extension is intended to keep non-xfa code
blissfully ignorant of the XFA feature bolted onto the side of it.
The cost is a few static_casts<> until the Extension gains a
few more virtual methods to cover these cases.

Use IPDF_Page abstraction in a few places where knowledge of
the underlying CPDFXFA_Page isn't required.

CJS_App becomes unaware of XFA while we're at it, with some
small changes for corner cases in the XFA case when no FFI,
etc.

Change-Id: Ie5d484d1c391d9f82947528b4856d7882f8cfad2
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/59250
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_document.h b/core/fpdfapi/parser/cpdf_document.h
index 7bd94f5..543611d 100644
--- a/core/fpdfapi/parser/cpdf_document.h
+++ b/core/fpdfapi/parser/cpdf_document.h
@@ -45,6 +45,7 @@
     virtual int GetPageCount() const = 0;
     virtual void DeletePage(int page_index) = 0;
     virtual uint32_t GetUserPermissions() const = 0;
+    virtual bool ContainsExtensionForm() const = 0;
   };
 
   class LinkListIface {
diff --git a/fpdfsdk/cpdfsdk_formfillenvironment.cpp b/fpdfsdk/cpdfsdk_formfillenvironment.cpp
index 7bf6162..634fd70 100644
--- a/fpdfsdk/cpdfsdk_formfillenvironment.cpp
+++ b/fpdfsdk/cpdfsdk_formfillenvironment.cpp
@@ -24,10 +24,6 @@
 #include "third_party/base/ptr_util.h"
 #include "third_party/base/stl_util.h"
 
-#ifdef PDF_ENABLE_XFA
-#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
-#endif
-
 FPDF_WIDESTRING AsFPDFWideString(ByteString* bsUTF16LE) {
   // Force a private version of the string, since we're about to hand it off
   // to the embedder. Should the embedder modify it by accident, it won't
@@ -106,6 +102,63 @@
 }
 
 #ifdef PDF_ENABLE_V8
+CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetCurrentView() {
+  IPDF_Page* pPage = IPDFPageFromFPDFPage(GetCurrentPage());
+  return pPage ? GetPageView(pPage, true) : nullptr;
+}
+
+FPDF_PAGE CPDFSDK_FormFillEnvironment::GetCurrentPage() const {
+  if (m_pInfo && m_pInfo->FFI_GetCurrentPage) {
+    return m_pInfo->FFI_GetCurrentPage(
+        m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc.Get()));
+  }
+  return nullptr;
+}
+
+WideString CPDFSDK_FormFillEnvironment::GetLanguage() {
+#ifdef PDF_ENABLE_XFA
+  if (!m_pInfo || !m_pInfo->FFI_GetLanguage)
+    return WideString();
+
+  int nRequiredLen = m_pInfo->FFI_GetLanguage(m_pInfo, nullptr, 0);
+  if (nRequiredLen <= 0)
+    return WideString();
+
+  std::vector<uint8_t> pBuff(nRequiredLen);
+  int nActualLen =
+      m_pInfo->FFI_GetLanguage(m_pInfo, pBuff.data(), nRequiredLen);
+  if (nActualLen <= 0 || nActualLen > nRequiredLen)
+    return WideString();
+
+  return WideString::FromUTF16LE(reinterpret_cast<uint16_t*>(pBuff.data()),
+                                 nActualLen / sizeof(uint16_t));
+#else   // PDF_ENABLE_XFA
+  return WideString();
+#endif  // PDF_ENABLE_XFA
+}
+
+WideString CPDFSDK_FormFillEnvironment::GetPlatform() {
+#ifdef PDF_ENABLE_XFA
+  if (!m_pInfo || !m_pInfo->FFI_GetPlatform)
+    return WideString();
+
+  int nRequiredLen = m_pInfo->FFI_GetPlatform(m_pInfo, nullptr, 0);
+  if (nRequiredLen <= 0)
+    return WideString();
+
+  std::vector<uint8_t> pBuff(nRequiredLen);
+  int nActualLen =
+      m_pInfo->FFI_GetPlatform(m_pInfo, pBuff.data(), nRequiredLen);
+  if (nActualLen <= 0 || nActualLen > nRequiredLen)
+    return WideString();
+
+  return WideString::FromUTF16LE(reinterpret_cast<uint16_t*>(pBuff.data()),
+                                 nActualLen / sizeof(uint16_t));
+#else   // PDF_ENABLE_XFA
+  return WideString();
+#endif  // PDF_ENABLE_XFA
+}
+
 int CPDFSDK_FormFillEnvironment::JS_appAlert(const WideString& Msg,
                                              const WideString& Title,
                                              int Type,
@@ -311,16 +364,6 @@
     m_pInfo->FFI_OnChange(m_pInfo);
 }
 
-#ifdef PDF_ENABLE_V8
-FPDF_PAGE CPDFSDK_FormFillEnvironment::GetCurrentPage() const {
-  if (m_pInfo && m_pInfo->FFI_GetCurrentPage) {
-    return m_pInfo->FFI_GetCurrentPage(
-        m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc.Get()));
-  }
-  return nullptr;
-}
-#endif
-
 void CPDFSDK_FormFillEnvironment::ExecuteNamedAction(const char* namedAction) {
   if (m_pInfo && m_pInfo->FFI_ExecuteNamedAction)
     m_pInfo->FFI_ExecuteNamedAction(m_pInfo, namedAction);
@@ -350,7 +393,11 @@
 }
 
 #ifdef PDF_ENABLE_XFA
-void CPDFSDK_FormFillEnvironment::DisplayCaret(CPDFXFA_Page* page,
+int CPDFSDK_FormFillEnvironment::GetPageViewCount() const {
+  return pdfium::CollectionSize<int>(m_PageMap);
+}
+
+void CPDFSDK_FormFillEnvironment::DisplayCaret(IPDF_Page* page,
                                                FPDF_BOOL bVisible,
                                                double left,
                                                double top,
@@ -376,24 +423,6 @@
       m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc.Get()), iCurPage);
 }
 
-WideString CPDFSDK_FormFillEnvironment::GetPlatform() {
-  if (!m_pInfo || !m_pInfo->FFI_GetPlatform)
-    return WideString();
-
-  int nRequiredLen = m_pInfo->FFI_GetPlatform(m_pInfo, nullptr, 0);
-  if (nRequiredLen <= 0)
-    return WideString();
-
-  std::vector<uint8_t> pBuff(nRequiredLen);
-  int nActualLen =
-      m_pInfo->FFI_GetPlatform(m_pInfo, pBuff.data(), nRequiredLen);
-  if (nActualLen <= 0 || nActualLen > nRequiredLen)
-    return WideString();
-
-  return WideString::FromUTF16LE(reinterpret_cast<uint16_t*>(pBuff.data()),
-                                 nActualLen / sizeof(uint16_t));
-}
-
 void CPDFSDK_FormFillEnvironment::GotoURL(const WideString& wsURL) {
   if (!m_pInfo || !m_pInfo->FFI_GotoURL)
     return;
@@ -403,7 +432,7 @@
                        AsFPDFWideString(&bsTo));
 }
 
-FS_RECTF CPDFSDK_FormFillEnvironment::GetPageViewRect(CPDFXFA_Page* page) {
+FS_RECTF CPDFSDK_FormFillEnvironment::GetPageViewRect(IPDF_Page* page) {
   FS_RECTF rect = {0.0f, 0.0f, 0.0f, 0.0f};
   if (!m_pInfo || !m_pInfo->FFI_GetPageViewRect)
     return rect;
@@ -422,7 +451,7 @@
   return rect;
 }
 
-bool CPDFSDK_FormFillEnvironment::PopupMenu(CPDFXFA_Page* page,
+bool CPDFSDK_FormFillEnvironment::PopupMenu(IPDF_Page* page,
                                             FPDF_WIDGET hWidget,
                                             int menuFlag,
                                             const CFX_PointF& pt) {
@@ -514,24 +543,6 @@
                                     AsFPDFWideString(&bsEncode));
 }
 
-WideString CPDFSDK_FormFillEnvironment::GetLanguage() {
-  if (!m_pInfo || !m_pInfo->FFI_GetLanguage)
-    return WideString();
-
-  int nRequiredLen = m_pInfo->FFI_GetLanguage(m_pInfo, nullptr, 0);
-  if (nRequiredLen <= 0)
-    return WideString();
-
-  std::vector<uint8_t> pBuff(nRequiredLen);
-  int nActualLen =
-      m_pInfo->FFI_GetLanguage(m_pInfo, pBuff.data(), nRequiredLen);
-  if (nActualLen <= 0 || nActualLen > nRequiredLen)
-    return WideString();
-
-  return WideString::FromUTF16LE(reinterpret_cast<uint16_t*>(pBuff.data()),
-                                 nActualLen / sizeof(uint16_t));
-}
-
 void CPDFSDK_FormFillEnvironment::PageEvent(int iPageCount,
                                             uint32_t dwEventType) const {
   if (m_pInfo && m_pInfo->FFI_PageEvent)
@@ -565,13 +576,6 @@
   return pPageView;
 }
 
-#ifdef PDF_ENABLE_V8
-CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetCurrentView() {
-  IPDF_Page* pPage = IPDFPageFromFPDFPage(GetCurrentPage());
-  return pPage ? GetPageView(pPage, true) : nullptr;
-}
-#endif
-
 CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetPageView(int nIndex) {
   IPDF_Page* pTempPage = GetPage(nIndex);
   if (!pTempPage)
@@ -729,22 +733,6 @@
   return !m_pFocusAnnot;
 }
 
-#ifdef PDF_ENABLE_XFA
-CPDFXFA_Context* CPDFSDK_FormFillEnvironment::GetXFAContext() const {
-  if (!m_pCPDFDoc)
-    return nullptr;
-  return static_cast<CPDFXFA_Context*>(m_pCPDFDoc->GetExtension());
-}
-
-int CPDFSDK_FormFillEnvironment::GetPageViewCount() const {
-  return pdfium::CollectionSize<int>(m_PageMap);
-}
-
-bool CPDFSDK_FormFillEnvironment::ContainsXFAForm() const {
-  return GetXFAContext()->ContainsXFAForm();
-}
-#endif  // PDF_ENABLE_XFA
-
 int CPDFSDK_FormFillEnvironment::GetPageCount() const {
   CPDF_Document::Extension* pExtension = m_pCPDFDoc->GetExtension();
   return pExtension ? pExtension->GetPageCount() : m_pCPDFDoc->GetPageCount();
diff --git a/fpdfsdk/cpdfsdk_formfillenvironment.h b/fpdfsdk/cpdfsdk_formfillenvironment.h
index e815cf5..abafcef 100644
--- a/fpdfsdk/cpdfsdk_formfillenvironment.h
+++ b/fpdfsdk/cpdfsdk_formfillenvironment.h
@@ -27,10 +27,6 @@
 class CPDFSDK_PageView;
 class IJS_Runtime;
 
-#if defined(PDF_ENABLE_XFA)
-class CPDFXFA_Context;
-#endif  // defined(PDF_ENABLE_XFA)
-
 // NOTE: |bsUTF16LE| must outlive the use of the result. Care must be taken
 // since modifying the result would impact |bsUTF16LE|.
 FPDF_WIDESTRING AsFPDFWideString(ByteString* bsUTF16LE);
@@ -67,9 +63,7 @@
 
   CPDFSDK_PageView* GetPageView(IPDF_Page* pUnderlyingPage, bool renew);
   CPDFSDK_PageView* GetPageView(int nIndex);
-#ifdef PDF_ENABLE_V8
-  CPDFSDK_PageView* GetCurrentView();
-#endif
+
   void RemovePageView(IPDF_Page* pUnderlyingPage);
   void UpdateAllViews(CPDFSDK_PageView* pSender, CPDFSDK_Annot* pAnnot);
 
@@ -98,10 +92,6 @@
   bool ProcOpenAction();
   void Invalidate(IPDF_Page* page, const FX_RECT& rect);
 
-#ifdef PDF_ENABLE_V8
-  FPDF_PAGE GetCurrentPage() const;
-#endif
-
   void OnChange();
   void ExecuteNamedAction(const char* namedAction);
   void OnSetFieldInputFocus(FPDF_WIDESTRING focusText,
@@ -114,58 +104,18 @@
                     int sizeOfArray);
 
   CPDF_Document* GetPDFDocument() const { return m_pCPDFDoc.Get(); }
+  CPDF_Document::Extension* GetDocExtension() const {
+    return m_pCPDFDoc->GetExtension();
+  }
+
+  bool IsJSPlatformPresent() const { return m_pInfo && m_pInfo->m_pJsPlatform; }
 
 #ifdef PDF_ENABLE_V8
-#ifdef PDF_ENABLE_XFA
-  CPDFXFA_Context* GetXFAContext() const;
-  int GetPageViewCount() const;
-  bool ContainsXFAForm() const;
+  CPDFSDK_PageView* GetCurrentView();
+  FPDF_PAGE GetCurrentPage() const;
 
-  void DisplayCaret(CPDFXFA_Page* page,
-                    FPDF_BOOL bVisible,
-                    double left,
-                    double top,
-                    double right,
-                    double bottom);
-  int GetCurrentPageIndex() const;
-  void SetCurrentPage(int iCurPage);
-
-  // TODO(dsinclair): This should probably change to PDFium?
-  WideString FFI_GetAppName() const { return WideString(L"Acrobat"); }
-
-  WideString GetPlatform();
-  void GotoURL(const WideString& wsURL);
-  FS_RECTF GetPageViewRect(CPDFXFA_Page* page);
-  bool PopupMenu(CPDFXFA_Page* page,
-                 FPDF_WIDGET hWidget,
-                 int menuFlag,
-                 const CFX_PointF& pt);
-
-  void EmailTo(FPDF_FILEHANDLER* fileHandler,
-               FPDF_WIDESTRING pTo,
-               FPDF_WIDESTRING pSubject,
-               FPDF_WIDESTRING pCC,
-               FPDF_WIDESTRING pBcc,
-               FPDF_WIDESTRING pMsg);
-  void UploadTo(FPDF_FILEHANDLER* fileHandler,
-                int fileFlag,
-                FPDF_WIDESTRING uploadTo);
-  FPDF_FILEHANDLER* OpenFile(int fileType,
-                             FPDF_WIDESTRING wsURL,
-                             const char* mode);
-  RetainPtr<IFX_SeekableReadStream> DownloadFromURL(const WideString& url);
-  WideString PostRequestURL(const WideString& wsURL,
-                            const WideString& wsData,
-                            const WideString& wsContentType,
-                            const WideString& wsEncode,
-                            const WideString& wsHeader);
-  FPDF_BOOL PutRequestURL(const WideString& wsURL,
-                          const WideString& wsData,
-                          const WideString& wsEncode);
   WideString GetLanguage();
-
-  void PageEvent(int iPageCount, uint32_t dwEventType) const;
-#endif  // PDF_ENABLE_XFA
+  WideString GetPlatform();
 
   int JS_appAlert(const WideString& Msg,
                   const WideString& Title,
@@ -198,9 +148,52 @@
                    FPDF_BOOL bAnnotations);
   void JS_docgotoPage(int nPageNum);
   WideString JS_docGetFilePath();
-#endif  // PDF_ENABLE_V8
 
-  bool IsJSPlatformPresent() const { return m_pInfo && m_pInfo->m_pJsPlatform; }
+#ifdef PDF_ENABLE_XFA
+  int GetPageViewCount() const;
+  void DisplayCaret(IPDF_Page* page,
+                    FPDF_BOOL bVisible,
+                    double left,
+                    double top,
+                    double right,
+                    double bottom);
+  int GetCurrentPageIndex() const;
+  void SetCurrentPage(int iCurPage);
+
+  // TODO(dsinclair): This should probably change to PDFium?
+  WideString FFI_GetAppName() const { return WideString(L"Acrobat"); }
+
+  void GotoURL(const WideString& wsURL);
+  FS_RECTF GetPageViewRect(IPDF_Page* page);
+  bool PopupMenu(IPDF_Page* page,
+                 FPDF_WIDGET hWidget,
+                 int menuFlag,
+                 const CFX_PointF& pt);
+  void EmailTo(FPDF_FILEHANDLER* fileHandler,
+               FPDF_WIDESTRING pTo,
+               FPDF_WIDESTRING pSubject,
+               FPDF_WIDESTRING pCC,
+               FPDF_WIDESTRING pBcc,
+               FPDF_WIDESTRING pMsg);
+  void UploadTo(FPDF_FILEHANDLER* fileHandler,
+                int fileFlag,
+                FPDF_WIDESTRING uploadTo);
+  FPDF_FILEHANDLER* OpenFile(int fileType,
+                             FPDF_WIDESTRING wsURL,
+                             const char* mode);
+  RetainPtr<IFX_SeekableReadStream> DownloadFromURL(const WideString& url);
+  WideString PostRequestURL(const WideString& wsURL,
+                            const WideString& wsData,
+                            const WideString& wsContentType,
+                            const WideString& wsEncode,
+                            const WideString& wsHeader);
+  FPDF_BOOL PutRequestURL(const WideString& wsURL,
+                          const WideString& wsData,
+                          const WideString& wsEncode);
+
+  void PageEvent(int iPageCount, uint32_t dwEventType) const;
+#endif  // PDF_ENABLE_XFA
+#endif  // PDF_ENABLE_V8
 
   WideString GetFilePath() const;
   ByteString GetAppName() const { return ByteString(); }
diff --git a/fpdfsdk/cpdfsdk_helpers.h b/fpdfsdk/cpdfsdk_helpers.h
index fc93d7c..0f7947a 100644
--- a/fpdfsdk/cpdfsdk_helpers.h
+++ b/fpdfsdk/cpdfsdk_helpers.h
@@ -45,7 +45,6 @@
 struct CPDF_JavaScript;
 
 #ifdef PDF_ENABLE_XFA
-class CPDFXFA_Context;
 class CPDFXFA_Page;
 class CXFA_FFWidget;
 #endif  // PDF_ENABLE_XFA
diff --git a/fpdfsdk/cpdfsdk_pageview.cpp b/fpdfsdk/cpdfsdk_pageview.cpp
index 2a5f179..45ef17a 100644
--- a/fpdfsdk/cpdfsdk_pageview.cpp
+++ b/fpdfsdk/cpdfsdk_pageview.cpp
@@ -146,8 +146,8 @@
   if (!pPage)
     return false;
 
-  auto* pContext = static_cast<CPDFXFA_Context*>(pPage->GetDocumentExtension());
-  if (!pContext->ContainsXFAForm())
+  CPDF_Document::Extension* pContext = pPage->GetDocumentExtension();
+  if (!pContext->ContainsExtensionForm())
     return false;
 
   ObservedPtr<CPDFSDK_Annot> pObserved(pAnnot);
@@ -475,7 +475,9 @@
 
 #ifdef PDF_ENABLE_XFA
   RetainPtr<CPDFXFA_Page> protector(ToXFAPage(m_page));
-  if (m_pFormFillEnv->GetXFAContext()->GetFormType() == FormType::kXFAFull) {
+  auto* pContext =
+      static_cast<CPDFXFA_Context*>(m_pFormFillEnv->GetDocExtension());
+  if (pContext->GetFormType() == FormType::kXFAFull) {
     CXFA_FFPageView* pageView = protector->GetXFAPageView();
     std::unique_ptr<IXFA_WidgetIterator> pWidgetHandler(
         pageView->CreateWidgetIterator(
diff --git a/fpdfsdk/cpdfsdk_widget.cpp b/fpdfsdk/cpdfsdk_widget.cpp
index 05c00f7..db60d89 100644
--- a/fpdfsdk/cpdfsdk_widget.cpp
+++ b/fpdfsdk/cpdfsdk_widget.cpp
@@ -51,7 +51,8 @@
 
 #ifdef PDF_ENABLE_XFA
 CXFA_FFWidget* CPDFSDK_Widget::GetMixXFAWidget() const {
-  CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
+  auto* pContext = static_cast<CPDFXFA_Context*>(
+      m_pPageView->GetFormFillEnv()->GetDocExtension());
   if (pContext->GetFormType() != FormType::kXFAForeground)
     return nullptr;
 
@@ -75,7 +76,8 @@
 }
 
 CXFA_FFWidget* CPDFSDK_Widget::GetGroupMixXFAWidget() const {
-  CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
+  auto* pContext = static_cast<CPDFXFA_Context*>(
+      m_pPageView->GetFormFillEnv()->GetDocExtension());
   if (pContext->GetFormType() != FormType::kXFAForeground)
     return nullptr;
 
@@ -88,7 +90,8 @@
 }
 
 CXFA_FFWidgetHandler* CPDFSDK_Widget::GetXFAWidgetHandler() const {
-  CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
+  auto* pContext = static_cast<CPDFXFA_Context*>(
+      m_pPageView->GetFormFillEnv()->GetDocExtension());
   if (pContext->GetFormType() != FormType::kXFAForeground)
     return nullptr;
 
@@ -210,7 +213,8 @@
 bool CPDFSDK_Widget::OnXFAAAction(PDFSDK_XFAAActionType eXFAAAT,
                                   CPDFSDK_FieldAction* data,
                                   CPDFSDK_PageView* pPageView) {
-  CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
+  auto* pContext = static_cast<CPDFXFA_Context*>(
+      m_pPageView->GetFormFillEnv()->GetDocExtension());
 
   ObservedPtr<CXFA_FFWidget> pWidget(GetMixXFAWidget());
   if (!pWidget)
@@ -306,7 +310,8 @@
   }
 
   if (bSynchronizeElse) {
-    CPDFXFA_Context* context = m_pPageView->GetFormFillEnv()->GetXFAContext();
+    auto* context = static_cast<CPDFXFA_Context*>(
+        m_pPageView->GetFormFillEnv()->GetDocExtension());
     context->GetXFADocView()->ProcessValueChanged(node);
   }
 }
@@ -358,9 +363,9 @@
 
 bool CPDFSDK_Widget::IsAppearanceValid() {
 #ifdef PDF_ENABLE_XFA
-  CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
-  FormType formType = pContext->GetFormType();
-  if (formType == FormType::kXFAFull)
+  auto* pContext = static_cast<CPDFXFA_Context*>(
+      m_pPageView->GetFormFillEnv()->GetDocExtension());
+  if (pContext->GetFormType() == FormType::kXFAFull)
     return true;
 #endif  // PDF_ENABLE_XFA
   return CPDFSDK_BAAnnot::IsAppearanceValid();
@@ -804,7 +809,8 @@
   CPDFSDK_FormFillEnvironment* pFormFillEnv = pPageView->GetFormFillEnv();
 
 #ifdef PDF_ENABLE_XFA
-  CPDFXFA_Context* pContext = pFormFillEnv->GetXFAContext();
+  auto* pContext =
+      static_cast<CPDFXFA_Context*>(pFormFillEnv->GetDocExtension());
   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
     XFA_EVENTTYPE eEventType = GetXFAEventType(type, data->bWillCommit);
 
diff --git a/fpdfsdk/cpdfsdk_widgethandler.cpp b/fpdfsdk/cpdfsdk_widgethandler.cpp
index 74e7512..77353b0 100644
--- a/fpdfsdk/cpdfsdk_widgethandler.cpp
+++ b/fpdfsdk/cpdfsdk_widgethandler.cpp
@@ -221,7 +221,8 @@
 
 #ifdef PDF_ENABLE_XFA
   CPDFSDK_PageView* pPageView = pAnnot->GetPageView();
-  CPDFXFA_Context* pContext = pPageView->GetFormFillEnv()->GetXFAContext();
+  CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(
+      pPageView->GetFormFillEnv()->GetDocExtension());
   if (pContext->GetFormType() == FormType::kXFAForeground) {
     if (!pWidget->IsAppearanceValid() && !pWidget->GetValue().IsEmpty())
       pWidget->ResetXFAAppearance(false);
diff --git a/fpdfsdk/fpdf_formfill.cpp b/fpdfsdk/fpdf_formfill.cpp
index 166497f..d260754 100644
--- a/fpdfsdk/fpdf_formfill.cpp
+++ b/fpdfsdk/fpdf_formfill.cpp
@@ -329,8 +329,10 @@
   pFormFillEnv->ClearAllFocusedAnnots();
   // If the document was closed first, it's possible the XFA document
   // is now a nullptr.
-  if (pFormFillEnv->GetXFAContext())
-    pFormFillEnv->GetXFAContext()->SetFormFillEnv(nullptr);
+  auto* pContext =
+      static_cast<CPDFXFA_Context*>(pFormFillEnv->GetDocExtension());
+  if (pContext)
+    pContext->SetFormFillEnv(nullptr);
 #endif  // PDF_ENABLE_XFA
   delete pFormFillEnv;
 }
diff --git a/fpdfsdk/fpdf_save.cpp b/fpdfsdk/fpdf_save.cpp
index 6275c01..2dfd759 100644
--- a/fpdfsdk/fpdf_save.cpp
+++ b/fpdfsdk/fpdf_save.cpp
@@ -47,7 +47,7 @@
   if (!pContext)
     return false;
 
-  if (!pContext->ContainsXFAForm())
+  if (!pContext->ContainsExtensionForm())
     return true;
 
   CXFA_FFDocView* pXFADocView = pContext->GetXFADocView();
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
index 88605ca..bc3a357 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
@@ -204,6 +204,11 @@
   return 0xFFFFFFFF;
 }
 
+bool CPDFXFA_Context::ContainsExtensionForm() const {
+  return m_FormType == FormType::kXFAFull ||
+         m_FormType == FormType::kXFAForeground;
+}
+
 void CPDFXFA_Context::ClearChangeMark() {
   if (m_pFormFillEnv)
     m_pFormFillEnv->ClearChangeMark();
@@ -305,7 +310,7 @@
 }
 
 void CPDFXFA_Context::SendPostSaveToXFADoc() {
-  if (!ContainsXFAForm())
+  if (!ContainsExtensionForm())
     return;
 
   CXFA_FFDocView* pXFADocView = GetXFADocView();
@@ -325,7 +330,7 @@
 
 void CPDFXFA_Context::SendPreSaveToXFADoc(
     std::vector<RetainPtr<IFX_SeekableStream>>* fileList) {
-  if (!ContainsXFAForm())
+  if (!ContainsExtensionForm())
     return;
 
   CXFA_FFDocView* pXFADocView = GetXFADocView();
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_context.h b/fpdfsdk/fpdfxfa/cpdfxfa_context.h
index 0617d19..d81d983 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_context.h
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_context.h
@@ -43,11 +43,6 @@
   CXFA_FFDoc* GetXFADoc() { return m_pXFADoc.get(); }
   CXFA_FFDocView* GetXFADocView() const { return m_pXFADocView.Get(); }
   FormType GetFormType() const { return m_FormType; }
-  bool ContainsXFAForm() const {
-    return m_FormType == FormType::kXFAFull ||
-           m_FormType == FormType::kXFAForeground;
-  }
-
   CPDFSDK_FormFillEnvironment* GetFormFillEnv() const {
     return m_pFormFillEnv.Get();
   }
@@ -62,6 +57,7 @@
   int GetPageCount() const override;
   void DeletePage(int page_index) override;
   uint32_t GetUserPermissions() const override;
+  bool ContainsExtensionForm() const override;
 
   // IFXA_AppProvider:
   WideString GetLanguage() override;
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
index 8dd06a5..fe51b80 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
@@ -365,7 +365,7 @@
 void CPDFXFA_DocEnvironment::SetCurrentPage(CXFA_FFDoc* hDoc,
                                             int32_t iCurPage) {
   if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv() ||
-      !m_pContext->ContainsXFAForm() || iCurPage < 0 ||
+      !m_pContext->ContainsExtensionForm() || iCurPage < 0 ||
       iCurPage >= m_pContext->GetFormFillEnv()->GetPageCount()) {
     return;
   }
@@ -420,7 +420,7 @@
   if (hDoc != m_pContext->GetXFADoc())
     return;
 
-  if (!m_pContext->ContainsXFAForm())
+  if (!m_pContext->ContainsExtensionForm())
     return;
 
   CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_widgethandler.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_widgethandler.cpp
index 5c5b9e9..98c4541 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_widgethandler.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_widgethandler.cpp
@@ -329,7 +329,8 @@
   if (!pFormFillEnv)
     return false;
 
-  CPDFXFA_Context* pContext = pFormFillEnv->GetXFAContext();
+  auto* pContext =
+      static_cast<CPDFXFA_Context*>(pFormFillEnv->GetDocExtension());
   if (!pContext)
     return false;
 
@@ -570,7 +571,7 @@
   if (!pFormFillEnv)
     return nullptr;
 
-  CPDFXFA_Context* pDoc = pFormFillEnv->GetXFAContext();
+  auto* pDoc = static_cast<CPDFXFA_Context*>(pFormFillEnv->GetDocExtension());
   if (!pDoc)
     return nullptr;
 
diff --git a/fxjs/cjs_app.cpp b/fxjs/cjs_app.cpp
index 3b79ced..992fd98 100644
--- a/fxjs/cjs_app.cpp
+++ b/fxjs/cjs_app.cpp
@@ -22,9 +22,7 @@
 #define JS_STR_PLATFORM L"WIN"
 #define JS_STR_LANGUAGE L"ENU"
 #define JS_NUM_VIEWERVERSION 8
-#ifdef PDF_ENABLE_XFA
 #define JS_NUM_VIEWERVERSION_XFA 11
-#endif  // PDF_ENABLE_XFA
 #define JS_NUM_FORMSVERSION 7
 
 const JSPropertySpec CJS_App::PropertySpecs[] = {
@@ -146,11 +144,12 @@
 }
 
 CJS_Result CJS_App::get_viewer_version(CJS_Runtime* pRuntime) {
-#ifdef PDF_ENABLE_XFA
-  if (pRuntime->GetFormFillEnv()->ContainsXFAForm())
-    return CJS_Result::Success(pRuntime->NewNumber(JS_NUM_VIEWERVERSION_XFA));
-#endif  // PDF_ENABLE_XFA
-  return CJS_Result::Success(pRuntime->NewNumber(JS_NUM_VIEWERVERSION));
+  CPDF_Document::Extension* pContext =
+      pRuntime->GetFormFillEnv()->GetDocExtension();
+  int version = pContext && pContext->ContainsExtensionForm()
+                    ? JS_NUM_VIEWERVERSION_XFA
+                    : JS_NUM_VIEWERVERSION;
+  return CJS_Result::Success(pRuntime->NewNumber(version));
 }
 
 CJS_Result CJS_App::set_viewer_version(CJS_Runtime* pRuntime,
@@ -159,15 +158,12 @@
 }
 
 CJS_Result CJS_App::get_platform(CJS_Runtime* pRuntime) {
-#ifdef PDF_ENABLE_XFA
   CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv();
-  if (!pFormFillEnv)
-    return CJS_Result::Failure(JSMessage::kBadObjectError);
-
-  WideString platform = pFormFillEnv->GetPlatform();
-  if (!platform.IsEmpty())
-    return CJS_Result::Success(pRuntime->NewString(platform.AsStringView()));
-#endif
+  if (pFormFillEnv) {
+    WideString platform = pFormFillEnv->GetPlatform();
+    if (!platform.IsEmpty())
+      return CJS_Result::Success(pRuntime->NewString(platform.AsStringView()));
+  }
   return CJS_Result::Success(pRuntime->NewString(JS_STR_PLATFORM));
 }
 
@@ -177,15 +173,12 @@
 }
 
 CJS_Result CJS_App::get_language(CJS_Runtime* pRuntime) {
-#ifdef PDF_ENABLE_XFA
   CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv();
-  if (!pFormFillEnv)
-    return CJS_Result::Failure(JSMessage::kBadObjectError);
-
-  WideString language = pFormFillEnv->GetLanguage();
-  if (!language.IsEmpty())
-    return CJS_Result::Success(pRuntime->NewString(language.AsStringView()));
-#endif
+  if (pFormFillEnv) {
+    WideString language = pFormFillEnv->GetLanguage();
+    if (!language.IsEmpty())
+      return CJS_Result::Success(pRuntime->NewString(language.AsStringView()));
+  }
   return CJS_Result::Success(pRuntime->NewString(JS_STR_LANGUAGE));
 }