Refactor HasXFAField into HasFormInfo

The existing API is too restrictive for collection the metrics
information that we want. Specifically it only tells us if there are
XFA forms in the document, but not AcroForms. This refactoring makes
the method more general, so that non-XFA information is provided
also. This change in semantics of the return value required some
changes at the call sites of the API.

BUG=chromium:775519

Change-Id: Id421c66c09b47196c252c64cdc2c711ca1911de0
Reviewed-on: https://pdfium-review.googlesource.com/16210
Commit-Queue: Ryan Harrison <rharrison@chromium.org>
Reviewed-by: Henrique Nakashima <hnakashima@chromium.org>
Reviewed-by: dsinclair <dsinclair@chromium.org>
diff --git a/fpdfsdk/cpdfsdk_pageview.cpp b/fpdfsdk/cpdfsdk_pageview.cpp
index 516b0eb..c1b5221 100644
--- a/fpdfsdk/cpdfsdk_pageview.cpp
+++ b/fpdfsdk/cpdfsdk_pageview.cpp
@@ -88,7 +88,7 @@
   if (!pPage)
     return;
 
-  if (pPage->GetContext()->GetDocType() == XFA_DocType::kFull) {
+  if (pPage->GetContext()->GetFormType() == FormType::kXFAFull) {
     CFX_RectF rectClip(
         static_cast<float>(pClip.left), static_cast<float>(pClip.top),
         static_cast<float>(pClip.Width()), static_cast<float>(pClip.Height()));
@@ -176,11 +176,8 @@
     return false;
 
   CPDFXFA_Page* pPage = pAnnot->GetPDFXFAPage();
-  if (!pPage ||
-      (pPage->GetContext()->GetDocType() != XFA_DocType::kForegroundOnly &&
-       pPage->GetContext()->GetDocType() != XFA_DocType::kFull)) {
+  if (!pPage || !pPage->GetContext()->ContainsXFAForm())
     return false;
-  }
 
   CPDFSDK_Annot::ObservedPtr pObserved(pAnnot);
   if (GetFocusAnnot() == pAnnot)
@@ -429,7 +426,7 @@
 
 #ifdef PDF_ENABLE_XFA
   RetainPtr<CPDFXFA_Page> protector(m_page);
-  if (m_pFormFillEnv->GetXFAContext()->GetDocType() == XFA_DocType::kFull) {
+  if (m_pFormFillEnv->GetXFAContext()->GetFormType() == FormType::kXFAFull) {
     CXFA_FFPageView* pageView = m_page->GetXFAPageView();
     std::unique_ptr<IXFA_WidgetIterator> pWidgetHandler(
         pageView->CreateWidgetIterator(
@@ -486,20 +483,18 @@
     return -1;
 
 #ifdef PDF_ENABLE_XFA
-  switch (m_page->GetContext()->GetDocType()) {
-    case XFA_DocType::kFull: {
+  switch (m_page->GetContext()->GetFormType()) {
+    case FormType::kXFAFull: {
       CXFA_FFPageView* pPageView = m_page->GetXFAPageView();
       return pPageView ? pPageView->GetPageIndex() : -1;
     }
-    case XFA_DocType::kForegroundOnly:
-    case XFA_DocType::kNone:
-      return GetPageIndexForStaticPDF();
-    default:
-      return -1;
+    case FormType::kNone:
+    case FormType::kAcroForm:
+    case FormType::kXFAForeground:
+      break;
   }
-#else   // PDF_ENABLE_XFA
-  return GetPageIndexForStaticPDF();
 #endif  // PDF_ENABLE_XFA
+  return GetPageIndexForStaticPDF();
 }
 
 bool CPDFSDK_PageView::IsValidAnnot(const CPDF_Annot* p) const {
diff --git a/fpdfsdk/cpdfsdk_widget.cpp b/fpdfsdk/cpdfsdk_widget.cpp
index 0e121e8..0c52512 100644
--- a/fpdfsdk/cpdfsdk_widget.cpp
+++ b/fpdfsdk/cpdfsdk_widget.cpp
@@ -72,7 +72,7 @@
 #ifdef PDF_ENABLE_XFA
 CXFA_FFWidget* CPDFSDK_Widget::GetMixXFAWidget() const {
   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
-  if (pContext->GetDocType() == XFA_DocType::kForegroundOnly) {
+  if (pContext->GetFormType() == FormType::kXFAForeground) {
     if (!m_hMixXFAWidget) {
       if (CXFA_FFDocView* pDocView = pContext->GetXFADocView()) {
         WideString sName;
@@ -95,7 +95,7 @@
 
 CXFA_FFWidget* CPDFSDK_Widget::GetGroupMixXFAWidget() {
   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
-  if (pContext->GetDocType() != XFA_DocType::kForegroundOnly)
+  if (pContext->GetFormType() != FormType::kXFAForeground)
     return nullptr;
 
   CXFA_FFDocView* pDocView = pContext->GetXFADocView();
@@ -108,7 +108,7 @@
 
 CXFA_FFWidgetHandler* CPDFSDK_Widget::GetXFAWidgetHandler() const {
   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
-  if (pContext->GetDocType() != XFA_DocType::kForegroundOnly)
+  if (pContext->GetFormType() != FormType::kXFAForeground)
     return nullptr;
 
   if (!m_pWidgetHandler) {
@@ -506,9 +506,8 @@
 bool CPDFSDK_Widget::IsAppearanceValid() {
 #ifdef PDF_ENABLE_XFA
   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
-  XFA_DocType nDocType = pContext->GetDocType();
-  if (nDocType != XFA_DocType::kNone &&
-      nDocType != XFA_DocType::kForegroundOnly)
+  FormType formType = pContext->GetFormType();
+  if (formType == FormType::kXFAFull)
     return true;
 #endif  // PDF_ENABLE_XFA
   return CPDFSDK_BAAnnot::IsAppearanceValid();
diff --git a/fpdfsdk/cpdfsdk_widgethandler.cpp b/fpdfsdk/cpdfsdk_widgethandler.cpp
index 44c1c66..3eb8e5d 100644
--- a/fpdfsdk/cpdfsdk_widgethandler.cpp
+++ b/fpdfsdk/cpdfsdk_widgethandler.cpp
@@ -242,7 +242,7 @@
 #ifdef PDF_ENABLE_XFA
   CPDFSDK_PageView* pPageView = pAnnot->GetPageView();
   CPDFXFA_Context* pContext = pPageView->GetFormFillEnv()->GetXFAContext();
-  if (pContext->GetDocType() == XFA_DocType::kForegroundOnly) {
+  if (pContext->GetFormType() == FormType::kXFAForeground) {
     if (!pWidget->IsAppearanceValid() && !pWidget->GetValue().IsEmpty())
       pWidget->ResetAppearance(false);
   }
diff --git a/fpdfsdk/fpdfformfill.cpp b/fpdfsdk/fpdfformfill.cpp
index 9e8b69e..d70b678 100644
--- a/fpdfsdk/fpdfformfill.cpp
+++ b/fpdfsdk/fpdfformfill.cpp
@@ -33,13 +33,15 @@
 #include "xfa/fxfa/cxfa_ffpageview.h"
 #include "xfa/fxfa/cxfa_ffwidget.h"
 
-static_assert(static_cast<int>(XFA_DocType::kNone) == XFADOCTYPE_NONE,
-              "PDF doctype must match");
-static_assert(static_cast<int>(XFA_DocType::kFull) == XFADOCTYPE_FULL,
-              "Dynamic XFA doctype must match");
-static_assert(static_cast<int>(XFA_DocType::kForegroundOnly) ==
-                  XFADOCTYPE_FOREGROUNDONLY,
-              "Static XFA doctype must match");
+static_assert(static_cast<int>(FormType::kNone) == FORMTYPE_NONE,
+              "None form types must match");
+static_assert(static_cast<int>(FormType::kAcroForm) == FORMTYPE_ACRO_FORM,
+              "AcroForm form types must match");
+static_assert(static_cast<int>(FormType::kXFAFull) == FORMTYPE_XFA_FULL,
+              "XFA full form types must match");
+static_assert(static_cast<int>(FormType::kXFAForeground) ==
+                  FORMTYPE_XFA_FOREGROUND,
+              "XFA foreground form types must match");
 #endif  // PDF_ENABLE_XFA
 
 namespace {
@@ -457,10 +459,8 @@
     return;
 
   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
-  if (pContext->GetDocType() != XFA_DocType::kFull &&
-      pContext->GetDocType() != XFA_DocType::kForegroundOnly) {
+  if (!pContext->ContainsXFAForm())
     return;
-  }
 
   static_cast<CXFA_FFWidget*>(hWidget)->Undo();
 }
@@ -471,8 +471,7 @@
     return;
 
   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
-  if (pContext->GetDocType() != XFA_DocType::kFull &&
-      pContext->GetDocType() != XFA_DocType::kForegroundOnly)
+  if (!pContext->ContainsXFAForm())
     return;
 
   static_cast<CXFA_FFWidget*>(hWidget)->Redo();
@@ -484,8 +483,7 @@
     return;
 
   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
-  if (pContext->GetDocType() != XFA_DocType::kFull &&
-      pContext->GetDocType() != XFA_DocType::kForegroundOnly)
+  if (!pContext->ContainsXFAForm())
     return;
 
   static_cast<CXFA_FFWidget*>(hWidget)->SelectAll();
@@ -499,8 +497,7 @@
     return;
 
   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
-  if (pContext->GetDocType() != XFA_DocType::kFull &&
-      pContext->GetDocType() != XFA_DocType::kForegroundOnly)
+  if (!pContext->ContainsXFAForm())
     return;
 
   WideString wsCpText;
@@ -531,8 +528,7 @@
     return;
 
   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
-  if (pContext->GetDocType() != XFA_DocType::kFull &&
-      pContext->GetDocType() != XFA_DocType::kForegroundOnly)
+  if (!pContext->ContainsXFAForm())
     return;
 
   WideString wsCpText;
@@ -563,8 +559,7 @@
     return;
 
   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
-  if (pContext->GetDocType() != XFA_DocType::kFull &&
-      pContext->GetDocType() != XFA_DocType::kForegroundOnly)
+  if (!pContext->ContainsXFAForm())
     return;
 
   WideString wstr = WideString::FromUTF16LE(wsText, size);
@@ -581,8 +576,7 @@
     return;
 
   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
-  if (pContext->GetDocType() != XFA_DocType::kFull &&
-      pContext->GetDocType() != XFA_DocType::kForegroundOnly)
+  if (!pContext->ContainsXFAForm())
     return;
 
   CFX_PointF ptPopup;
@@ -602,8 +596,7 @@
     return;
 
   auto* pContext = static_cast<CPDFXFA_Context*>(document);
-  if (pContext->GetDocType() != XFA_DocType::kFull &&
-      pContext->GetDocType() != XFA_DocType::kForegroundOnly)
+  if (!pContext->ContainsXFAForm())
     return;
 
   CFX_PointF ptPopup;
diff --git a/fpdfsdk/fpdfformfill_embeddertest.cpp b/fpdfsdk/fpdfformfill_embeddertest.cpp
index f5151cc..7a9ebcf 100644
--- a/fpdfsdk/fpdfformfill_embeddertest.cpp
+++ b/fpdfsdk/fpdfformfill_embeddertest.cpp
@@ -565,6 +565,26 @@
   TestAndCloseSaved(300, 300, md5_3);
 }
 
+TEST_F(FPDFFormFillEmbeddertest, HasFormInfoNone) {
+  EXPECT_TRUE(OpenDocument("hello_world.pdf"));
+  EXPECT_EQ(FORMTYPE_NONE, FPDF_GetFormType(document_));
+}
+
+TEST_F(FPDFFormFillEmbeddertest, HasFormInfoAcroForm) {
+  EXPECT_TRUE(OpenDocument("text_form.pdf"));
+  EXPECT_EQ(FORMTYPE_ACRO_FORM, FPDF_GetFormType(document_));
+}
+
+TEST_F(FPDFFormFillEmbeddertest, HasFormInfoXFAFull) {
+  EXPECT_TRUE(OpenDocument("simple_xfa.pdf"));
+  EXPECT_EQ(FORMTYPE_XFA_FULL, FPDF_GetFormType(document_));
+}
+
+TEST_F(FPDFFormFillEmbeddertest, HasFormInfoXFAForeground) {
+  EXPECT_TRUE(OpenDocument("bug_216.pdf"));
+  EXPECT_EQ(FORMTYPE_XFA_FOREGROUND, FPDF_GetFormType(document_));
+}
+
 TEST_F(FPDFFormFillTextFormEmbeddertest, GetSelectedTextEmptyAndBasicKeyboard) {
   // Test empty selection.
   CheckSelection(L"");
diff --git a/fpdfsdk/fpdfsave.cpp b/fpdfsdk/fpdfsave.cpp
index 783a913..5acdef0 100644
--- a/fpdfsdk/fpdfsave.cpp
+++ b/fpdfsdk/fpdfsave.cpp
@@ -48,10 +48,8 @@
   if (!pContext)
     return false;
 
-  if (pContext->GetDocType() != XFA_DocType::kFull &&
-      pContext->GetDocType() != XFA_DocType::kForegroundOnly) {
+  if (!pContext->ContainsXFAForm())
     return true;
-  }
 
   CXFA_FFDocView* pXFADocView = pContext->GetXFADocView();
   if (!pXFADocView)
@@ -192,8 +190,7 @@
   if (!pContext)
     return false;
 
-  if (pContext->GetDocType() != XFA_DocType::kFull &&
-      pContext->GetDocType() != XFA_DocType::kForegroundOnly)
+  if (!pContext->ContainsXFAForm())
     return true;
 
   CXFA_FFDocView* pXFADocView = pContext->GetXFADocView();
@@ -215,8 +212,7 @@
 
 bool SendPreSaveToXFADoc(CPDFXFA_Context* pContext,
                          std::vector<RetainPtr<IFX_SeekableStream>>* fileList) {
-  if (pContext->GetDocType() != XFA_DocType::kFull &&
-      pContext->GetDocType() != XFA_DocType::kForegroundOnly)
+  if (!pContext->ContainsXFAForm())
     return true;
 
   CXFA_FFDocView* pXFADocView = pContext->GetXFADocView();
diff --git a/fpdfsdk/fpdfview.cpp b/fpdfsdk/fpdfview.cpp
index 9a8e8eb..98a5b32 100644
--- a/fpdfsdk/fpdfview.cpp
+++ b/fpdfsdk/fpdfview.cpp
@@ -565,30 +565,28 @@
       password);
 }
 
-FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_HasXFAField(FPDF_DOCUMENT document,
-                                                     int* docType) {
+FPDF_EXPORT int FPDF_CALLCONV FPDF_GetFormType(FPDF_DOCUMENT document) {
   if (!document)
     return false;
 
   const CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
   if (!pDoc)
-    return false;
+    return FORMTYPE_NONE;
 
   const CPDF_Dictionary* pRoot = pDoc->GetRoot();
   if (!pRoot)
-    return false;
+    return FORMTYPE_NONE;
 
   CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm");
   if (!pAcroForm)
-    return false;
+    return FORMTYPE_NONE;
 
   CPDF_Object* pXFA = pAcroForm->GetObjectFor("XFA");
   if (!pXFA)
-    return false;
+    return FORMTYPE_ACRO_FORM;
 
-  bool bDynamicXFA = pRoot->GetBooleanFor("NeedsRendering", false);
-  *docType = bDynamicXFA ? XFADOCTYPE_FULL : XFADOCTYPE_FOREGROUNDONLY;
-  return true;
+  bool needsRendering = pRoot->GetBooleanFor("NeedsRendering", false);
+  return needsRendering ? FORMTYPE_XFA_FULL : FORMTYPE_XFA_FOREGROUND;
 }
 
 #ifdef PDF_ENABLE_XFA
diff --git a/fpdfsdk/fpdfview_c_api_test.c b/fpdfsdk/fpdfview_c_api_test.c
index bf1a0c4..1526ffa 100644
--- a/fpdfsdk/fpdfview_c_api_test.c
+++ b/fpdfsdk/fpdfview_c_api_test.c
@@ -210,7 +210,7 @@
     CHK(FPDF_SetFormFieldHighlightAlpha);
     CHK(FPDF_RemoveFormFieldHighlight);
     CHK(FPDF_FFLDraw);
-    CHK(FPDF_HasXFAField);
+    CHK(FPDF_GetFormType);
 #ifdef PDF_ENABLE_XFA
     CHK(FPDF_LoadXFA);
     CHK(FPDF_Widget_Undo);
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
index 692306a..95f1efc 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
@@ -36,7 +36,7 @@
 #endif
 
 CPDFXFA_Context::CPDFXFA_Context(std::unique_ptr<CPDF_Document> pPDFDoc)
-    : m_iDocType(XFA_DocType::kNone),
+    : m_FormType(FormType::kNone),
       m_pPDFDoc(std::move(pPDFDoc)),
       m_pFormFillEnv(nullptr),
       m_pXFADocView(nullptr),
@@ -117,10 +117,10 @@
   m_pXFADoc->StopLoad();
   m_pXFADoc->GetXFADoc()->InitScriptContext(GetJSERuntime());
 
-  if (m_pXFADoc->GetDocType() == XFA_DocType::kFull)
-    m_iDocType = XFA_DocType::kFull;
+  if (m_pXFADoc->GetFormType() == FormType::kXFAFull)
+    m_FormType = FormType::kXFAFull;
   else
-    m_iDocType = XFA_DocType::kForegroundOnly;
+    m_FormType = FormType::kXFAForeground;
 
   m_pXFADocView = m_pXFADoc->CreateDocView();
   if (m_pXFADocView->StartLayout() < 0) {
@@ -140,17 +140,17 @@
   if (!m_pPDFDoc && !m_pXFADoc)
     return 0;
 
-  switch (m_iDocType) {
-    case XFA_DocType::kNone:
-    case XFA_DocType::kForegroundOnly:
+  switch (m_FormType) {
+    case FormType::kNone:
+    case FormType::kAcroForm:
+    case FormType::kXFAForeground:
       if (m_pPDFDoc)
         return m_pPDFDoc->GetPageCount();
-    case XFA_DocType::kFull:
+    case FormType::kXFAFull:
       if (m_pXFADoc)
         return m_pXFADocView->CountPageViews();
-    default:
-      return 0;
   }
+  return 0;
 }
 
 RetainPtr<CPDFXFA_Page> CPDFXFA_Context::GetXFAPage(int page_index) {
@@ -183,7 +183,7 @@
   if (!m_pXFADoc)
     return nullptr;
 
-  if (m_iDocType != XFA_DocType::kFull)
+  if (m_FormType != FormType::kXFAFull)
     return nullptr;
 
   for (auto& pTempPage : m_XFAPageList) {
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_context.h b/fpdfsdk/fpdfxfa/cpdfxfa_context.h
index 52af64a..f5b62f5 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_context.h
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_context.h
@@ -40,7 +40,11 @@
   CPDF_Document* GetPDFDoc() { return m_pPDFDoc.get(); }
   CXFA_FFDoc* GetXFADoc() { return m_pXFADoc.get(); }
   CXFA_FFDocView* GetXFADocView() { return m_pXFADocView.Get(); }
-  XFA_DocType GetDocType() const { return m_iDocType; }
+  FormType GetFormType() const { return m_FormType; }
+  bool ContainsXFAForm() const {
+    return m_FormType == FormType::kXFAFull ||
+           m_FormType == FormType::kXFAForeground;
+  }
   v8::Isolate* GetJSERuntime() const;
   CXFA_FFApp* GetXFAApp() { return m_pXFAApp.get(); }
 
@@ -101,7 +105,7 @@
  private:
   void CloseXFADoc();
 
-  XFA_DocType m_iDocType;
+  FormType m_FormType;
   std::unique_ptr<CPDF_Document> m_pPDFDoc;
   std::unique_ptr<CXFA_FFDoc> m_pXFADoc;
   Observable<CPDFSDK_FormFillEnvironment>::ObservedPtr m_pFormFillEnv;
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
index 91322ee..a5cdd3c 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
@@ -55,7 +55,7 @@
   if (!m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv())
     return;
 
-  if (m_pContext->GetDocType() != XFA_DocType::kFull)
+  if (m_pContext->GetFormType() != FormType::kXFAFull)
     return;
 
   RetainPtr<CPDFXFA_Page> pPage = m_pContext->GetXFAPage(pPageView);
@@ -76,7 +76,7 @@
       !m_pContext->GetFormFillEnv() || !m_pContext->GetXFADocView())
     return;
 
-  if (m_pContext->GetDocType() != XFA_DocType::kFull)
+  if (m_pContext->GetFormType() != FormType::kXFAFull)
     return;
 
   CXFA_FFWidgetHandler* pWidgetHandler =
@@ -289,7 +289,7 @@
 
 void CPDFXFA_DocEnvironment::WidgetPostAdd(CXFA_FFWidget* hWidget,
                                            CXFA_WidgetAcc* pWidgetData) {
-  if (m_pContext->GetDocType() != XFA_DocType::kFull || !hWidget)
+  if (m_pContext->GetFormType() != FormType::kXFAFull || !hWidget)
     return;
 
   CXFA_FFPageView* pPageView = hWidget->GetPageView();
@@ -307,7 +307,7 @@
 
 void CPDFXFA_DocEnvironment::WidgetPreRemove(CXFA_FFWidget* hWidget,
                                              CXFA_WidgetAcc* pWidgetData) {
-  if (m_pContext->GetDocType() != XFA_DocType::kFull || !hWidget)
+  if (m_pContext->GetFormType() != FormType::kXFAFull || !hWidget)
     return;
 
   CXFA_FFPageView* pPageView = hWidget->GetPageView();
@@ -334,7 +334,7 @@
 int32_t CPDFXFA_DocEnvironment::GetCurrentPage(CXFA_FFDoc* hDoc) {
   if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv())
     return -1;
-  if (m_pContext->GetDocType() != XFA_DocType::kFull)
+  if (m_pContext->GetFormType() != FormType::kXFAFull)
     return -1;
 
   CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
@@ -347,7 +347,7 @@
 void CPDFXFA_DocEnvironment::SetCurrentPage(CXFA_FFDoc* hDoc,
                                             int32_t iCurPage) {
   if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv() ||
-      m_pContext->GetDocType() != XFA_DocType::kFull || iCurPage < 0 ||
+      m_pContext->GetFormType() != FormType::kXFAFull || iCurPage < 0 ||
       iCurPage >= m_pContext->GetFormFillEnv()->GetPageCount()) {
     return;
   }
@@ -407,10 +407,8 @@
   if (hDoc != m_pContext->GetXFADoc())
     return;
 
-  if (m_pContext->GetDocType() != XFA_DocType::kFull &&
-      m_pContext->GetDocType() != XFA_DocType::kForegroundOnly) {
+  if (!m_pContext->ContainsXFAForm())
     return;
-  }
 
   CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
   if (!pFormFillEnv)
@@ -506,7 +504,7 @@
   if (hDoc != m_pContext->GetXFADoc())
     return;
 
-  if (m_pContext->GetDocType() != XFA_DocType::kFull)
+  if (m_pContext->GetFormType() != FormType::kXFAFull)
     return;
 
   CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
@@ -606,10 +604,8 @@
 }
 
 bool CPDFXFA_DocEnvironment::OnBeforeNotifySubmit() {
-  if (m_pContext->GetDocType() != XFA_DocType::kFull &&
-      m_pContext->GetDocType() != XFA_DocType::kForegroundOnly) {
+  if (!m_pContext->ContainsXFAForm())
     return true;
-  }
 
   if (!m_pContext->GetXFADocView())
     return true;
@@ -658,8 +654,7 @@
 }
 
 void CPDFXFA_DocEnvironment::OnAfterNotifySubmit() {
-  if (m_pContext->GetDocType() != XFA_DocType::kFull &&
-      m_pContext->GetDocType() != XFA_DocType::kForegroundOnly)
+  if (!m_pContext->ContainsXFAForm())
     return;
 
   if (!m_pContext->GetXFADocView())
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_page.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_page.cpp
index fa10a92..fbea90d 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_page.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_page.cpp
@@ -64,15 +64,15 @@
   if (!m_pContext || m_iPageIndex < 0)
     return false;
 
-  switch (m_pContext->GetDocType()) {
-    case XFA_DocType::kNone:
-    case XFA_DocType::kForegroundOnly:
+  switch (m_pContext->GetFormType()) {
+    case FormType::kNone:
+    case FormType::kAcroForm:
+    case FormType::kXFAForeground:
       return LoadPDFPage();
-    case XFA_DocType::kFull:
+    case FormType::kXFAFull:
       return LoadXFAPageView();
-    default:
-      return false;
   }
+  return false;
 }
 
 bool CPDFXFA_Page::LoadPDFPage(CPDF_Dictionary* pageDict) {
@@ -89,20 +89,15 @@
   if (!m_pPDFPage && !m_pXFAPageView)
     return 0.0f;
 
-  switch (m_pContext->GetDocType()) {
-    case XFA_DocType::kFull: {
-      if (m_pXFAPageView)
-        return m_pXFAPageView->GetPageViewRect().width;
-      break;
-    }
-    case XFA_DocType::kForegroundOnly:
-    case XFA_DocType::kNone: {
+  switch (m_pContext->GetFormType()) {
+    case FormType::kNone:
+    case FormType::kAcroForm:
+    case FormType::kXFAForeground:
       if (m_pPDFPage)
         return m_pPDFPage->GetPageWidth();
-      break;
-    }
-    default:
-      return 0.0f;
+    case FormType::kXFAFull:
+      if (m_pXFAPageView)
+        return m_pXFAPageView->GetPageViewRect().width;
   }
 
   return 0.0f;
@@ -112,20 +107,15 @@
   if (!m_pPDFPage && !m_pXFAPageView)
     return 0.0f;
 
-  switch (m_pContext->GetDocType()) {
-    case XFA_DocType::kNone:
-    case XFA_DocType::kForegroundOnly: {
+  switch (m_pContext->GetFormType()) {
+    case FormType::kNone:
+    case FormType::kAcroForm:
+    case FormType::kXFAForeground:
       if (m_pPDFPage)
         return m_pPDFPage->GetPageHeight();
-      break;
-    }
-    case XFA_DocType::kFull: {
+    case FormType::kXFAFull:
       if (m_pXFAPageView)
         return m_pXFAPageView->GetPageViewRect().height;
-      break;
-    }
-    default:
-      return 0.0f;
   }
 
   return 0.0f;
@@ -182,22 +172,17 @@
   if (!m_pPDFPage && !m_pXFAPageView)
     return CFX_Matrix();
 
-  switch (m_pContext->GetDocType()) {
-    case XFA_DocType::kFull: {
-      if (m_pXFAPageView) {
-        return m_pXFAPageView->GetDisplayMatrix(
-            CFX_Rect(xPos, yPos, xSize, ySize), iRotate);
-      }
-      break;
-    }
-    case XFA_DocType::kNone:
-    case XFA_DocType::kForegroundOnly: {
+  switch (m_pContext->GetFormType()) {
+    case FormType::kNone:
+    case FormType::kAcroForm:
+    case FormType::kXFAForeground:
       if (m_pPDFPage)
         return m_pPDFPage->GetDisplayMatrix(xPos, yPos, xSize, ySize, iRotate);
-      break;
-    }
-    default:
-      return CFX_Matrix();
+    case FormType::kXFAFull:
+      if (m_pXFAPageView)
+        return m_pXFAPageView->GetDisplayMatrix(
+            CFX_Rect(xPos, yPos, xSize, ySize), iRotate);
   }
+
   return CFX_Matrix();
 }
diff --git a/fpdfsdk/javascript/app.cpp b/fpdfsdk/javascript/app.cpp
index f29a098..eec4681 100644
--- a/fpdfsdk/javascript/app.cpp
+++ b/fpdfsdk/javascript/app.cpp
@@ -282,8 +282,7 @@
     return false;
 #ifdef PDF_ENABLE_XFA
   CPDFXFA_Context* pXFAContext = pRuntime->GetFormFillEnv()->GetXFAContext();
-  if (pXFAContext->GetDocType() == XFA_DocType::kFull ||
-      pXFAContext->GetDocType() == XFA_DocType::kForegroundOnly) {
+  if (pXFAContext->ContainsXFAForm()) {
     vp << JS_NUM_VIEWERVERSION_XFA;
     return true;
   }
diff --git a/public/fpdf_formfill.h b/public/fpdf_formfill.h
index 1e0d305..0204c84 100644
--- a/public/fpdf_formfill.h
+++ b/public/fpdf_formfill.h
@@ -12,10 +12,11 @@
 
 typedef void* FPDF_FORMHANDLE;
 
-#define XFADOCTYPE_NONE 0  // Document contains no XFA forms
-#define XFADOCTYPE_FULL 1  // XFA forms are specified using the entire XFA spec
-#define XFADOCTYPE_FOREGROUNDONLY \
-  2  // XFA forms are specified using the XFAF subset
+#define FORMTYPE_NONE 0       // Document contains no forms
+#define FORMTYPE_ACRO_FORM 1  // Forms are specified using AcroForm spec
+#define FORMTYPE_XFA_FULL 2   // Forms are specified using the entire XFA spec
+#define FORMTYPE_XFA_FOREGROUND \
+  3  // Forms are specified using the XFAF subset of XFA spec
 
 // Exported Functions
 #ifdef __cplusplus
@@ -1607,20 +1608,19 @@
 #endif
 
 /**
- * Function: FPDF_HasXFAField
- *                      This method is designed to check whether a pdf document
- *has XFA fields.
+ * Experimental API
+ * Function: FPDF_GetFormType
+ *                      Returns the type of form contained in the PDF document.
  * Parameters:
  *                      document                -       Handle to document.
  *Returned by FPDF_LoadDocument function.
  *                      docType                 -       Document type defined as
- *XFADOCTYPE_xxx.
+ *FORMTYPE_xxx.
  * Return Value:
- *                      TRUE indicates that the input document has XFA fields,
- *otherwise FALSE.
+ *                      Integer value representing one of the FORMTYPE_xxx
+ *values.
  **/
-FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_HasXFAField(FPDF_DOCUMENT document,
-                                                     int* docType);
+FPDF_EXPORT int FPDF_CALLCONV FPDF_GetFormType(FPDF_DOCUMENT document);
 
 #ifdef PDF_ENABLE_XFA
 /**
diff --git a/samples/pdfium_test.cc b/samples/pdfium_test.cc
index a638fd0..644aee7 100644
--- a/samples/pdfium_test.cc
+++ b/samples/pdfium_test.cc
@@ -1430,10 +1430,10 @@
   form_callbacks.form_handle = form.get();
 
 #ifdef PDF_ENABLE_XFA
-  int doc_type = XFADOCTYPE_NONE;
-  if (FPDF_HasXFAField(doc.get(), &doc_type) && doc_type != XFADOCTYPE_NONE &&
-      !FPDF_LoadXFA(doc.get())) {
-    fprintf(stderr, "LoadXFA unsuccessful, continuing anyway.\n");
+  int doc_type = FPDF_GetFormType(doc.get());
+  if (doc_type == FORMTYPE_XFA_FULL || doc_type == FORMTYPE_XFA_FOREGROUND) {
+    if (!FPDF_LoadXFA(doc.get()))
+      fprintf(stderr, "LoadXFA unsuccessful, continuing anyway.\n");
   }
 #endif  // PDF_ENABLE_XFA
 
diff --git a/testing/embedder_test.cpp b/testing/embedder_test.cpp
index 41be0c0..2694977 100644
--- a/testing/embedder_test.cpp
+++ b/testing/embedder_test.cpp
@@ -205,11 +205,9 @@
   }
   *form_handle = SetupFormFillEnvironment(*document);
 #ifdef PDF_ENABLE_XFA
-  int docType = XFADOCTYPE_NONE;
-  if (FPDF_HasXFAField(*document, &docType)) {
-    if (docType != XFADOCTYPE_NONE)
-      (void)FPDF_LoadXFA(*document);
-  }
+  int doc_type = FPDF_GetFormType(*document);
+  if (doc_type == FORMTYPE_XFA_FULL || doc_type == FORMTYPE_XFA_FOREGROUND)
+    FPDF_LoadXFA(*document);
 #endif  // PDF_ENABLE_XFA
   (void)FPDF_GetDocPermissions(*document);
   return true;
diff --git a/xfa/fxfa/cxfa_ffdoc.cpp b/xfa/fxfa/cxfa_ffdoc.cpp
index 23b3df6..fed20ca 100644
--- a/xfa/fxfa/cxfa_ffdoc.cpp
+++ b/xfa/fxfa/cxfa_ffdoc.cpp
@@ -160,7 +160,7 @@
       m_pApp(pApp),
       m_pNotify(nullptr),
       m_pPDFDoc(nullptr),
-      m_dwDocType(XFA_DocType::kForegroundOnly) {}
+      m_FormType(FormType::kXFAForeground) {}
 
 CXFA_FFDoc::~CXFA_FFDoc() {
   CloseDoc();
@@ -244,7 +244,7 @@
   m_pPDFFontMgr = pdfium::MakeUnique<CFGAS_PDFFontMgr>(
       GetPDFDoc(), GetApp()->GetFDEFontMgr());
 
-  m_dwDocType = XFA_DocType::kForegroundOnly;
+  m_FormType = FormType::kXFAForeground;
   CXFA_Node* pConfig = ToNode(
       m_pDocumentParser->GetDocument()->GetXFAObject(XFA_HASHCODE_Config));
   if (!pConfig)
@@ -265,7 +265,7 @@
 
   WideString wsType;
   if (pDynamicRender->TryContent(wsType) && wsType == L"required")
-    m_dwDocType = XFA_DocType::kFull;
+    m_FormType = FormType::kXFAFull;
 }
 
 CXFA_FFDocView* CXFA_FFDoc::CreateDocView() {
diff --git a/xfa/fxfa/cxfa_ffdoc.h b/xfa/fxfa/cxfa_ffdoc.h
index c85c951..490b023 100644
--- a/xfa/fxfa/cxfa_ffdoc.h
+++ b/xfa/fxfa/cxfa_ffdoc.h
@@ -54,7 +54,7 @@
   IXFA_DocEnvironment* GetDocEnvironment() const {
     return m_pDocEnvironment.Get();
   }
-  XFA_DocType GetDocType() const { return m_dwDocType; }
+  FormType GetFormType() const { return m_FormType; }
 
   int32_t StartLoad();
   int32_t DoLoad();
@@ -91,7 +91,7 @@
   std::map<uint32_t, FX_IMAGEDIB_AND_DPI> m_HashToDibDpiMap;
   std::unique_ptr<CXFA_FFDocView> m_DocView;
   std::unique_ptr<CFGAS_PDFFontMgr> m_pPDFFontMgr;
-  XFA_DocType m_dwDocType;
+  FormType m_FormType;
 };
 
 #endif  // XFA_FXFA_CXFA_FFDOC_H_
diff --git a/xfa/fxfa/cxfa_ffdocview.cpp b/xfa/fxfa/cxfa_ffdocview.cpp
index 0e895b6..3ac705c 100644
--- a/xfa/fxfa/cxfa_ffdocview.cpp
+++ b/xfa/fxfa/cxfa_ffdocview.cpp
@@ -622,7 +622,7 @@
 }
 
 bool CXFA_FFDocView::IsStaticNotify() {
-  return m_pDoc->GetDocType() == XFA_DocType::kForegroundOnly;
+  return m_pDoc->GetFormType() == FormType::kXFAForeground;
 }
 
 void CXFA_FFDocView::AddCalculateWidgetAcc(CXFA_WidgetAcc* pWidgetAcc) {
diff --git a/xfa/fxfa/fxfa.h b/xfa/fxfa/fxfa.h
index 9f5432e..ee74fc1 100644
--- a/xfa/fxfa/fxfa.h
+++ b/xfa/fxfa/fxfa.h
@@ -40,8 +40,13 @@
 #define XFA_IDNo 3
 #define XFA_IDYes 4
 
-// Note, values match fpdf_formfill.h XFADOCTYPE_* flags.
-enum class XFA_DocType { kNone = 0, kFull = 1, kForegroundOnly = 2 };
+// Note, values must match fpdf_formfill.h FORMTYPE_* flags.
+enum class FormType {
+  kNone = 0,
+  kAcroForm = 1,
+  kXFAFull = 2,
+  kXFAForeground = 3
+};
 
 #define XFA_PARSESTATUS_StatusErr -3
 #define XFA_PARSESTATUS_StreamErr -2