Move CPDFXFA_Context creation to FPDFDOC_InitFormFillEnvironment()

Currently the CPDFXFA_Context creation occurs in LoadDocumentImpl()
regardless of whether --disable-xfa has been passed to pdfium_test.
We want to defer the context creation to
FPDFDOC_InitFormFillEnvironment() and make it conditional to whether the
runtime flag has been passed.

Add a new field |xfa_disabled| to version 2 of _FPDF_FORMFILLINFO.
|xfa_disabled| was selected over |xfa_enabled| to allow for backwards
compatibility, as |xfa_disabled| defaults to false/0 upon
initialization.

This CL changes when the embedder gets a callback for when XFA is not
supported.

Fixed: pdfium:1433
Bug: pdfium:1433
Change-Id: I01da4fd75127815728d2c4dae357e4f22447a6c9
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/64770
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/fpdfsdk/cpdfsdk_helpers.cpp b/fpdfsdk/cpdfsdk_helpers.cpp
index 4583e0c..144149d 100644
--- a/fpdfsdk/cpdfsdk_helpers.cpp
+++ b/fpdfsdk/cpdfsdk_helpers.cpp
@@ -362,7 +362,9 @@
         RaiseUnsupportedError(static_cast<int>(err));
     }
   }
+}
 
+void ReportUnsupportedXFA(CPDF_Document* pDoc) {
   // XFA Forms
   if (!pDoc->GetExtension() && CPDF_InteractiveForm(pDoc).HasXFAForm())
     RaiseUnsupportedError(FPDF_UNSP_DOC_XFAFORM);
diff --git a/fpdfsdk/cpdfsdk_helpers.h b/fpdfsdk/cpdfsdk_helpers.h
index f59f105..327ec4c 100644
--- a/fpdfsdk/cpdfsdk_helpers.h
+++ b/fpdfsdk/cpdfsdk_helpers.h
@@ -264,6 +264,7 @@
 void SetPDFUnsupportInfo(UNSUPPORT_INFO* unsp_info);
 UNSUPPORT_INFO* GetPDFUnssuportInto();
 void ReportUnsupportedFeatures(CPDF_Document* pDoc);
+void ReportUnsupportedXFA(CPDF_Document* pDoc);
 void CheckForUnsupportedAnnot(const CPDF_Annot* pAnnot);
 void ProcessParseError(CPDF_Parser::Error err);
 
diff --git a/fpdfsdk/fpdf_formfill.cpp b/fpdfsdk/fpdf_formfill.cpp
index 873ea01..5f64337 100644
--- a/fpdfsdk/fpdf_formfill.cpp
+++ b/fpdfsdk/fpdf_formfill.cpp
@@ -297,20 +297,24 @@
   if (!pDocument)
     return nullptr;
 
-#ifdef PDF_ENABLE_XFA
-  // If the CPDFXFA_Context has a FormFillEnvironment already then we've done
-  // this and can just return the old Env. Otherwise, we'll end up setting a new
-  // environment into the XFADocument and, that could get weird.
-  auto* pContext = static_cast<CPDFXFA_Context*>(pDocument->GetExtension());
-  if (pContext && pContext->GetFormFillEnv()) {
-    return FPDFFormHandleFromCPDFSDKFormFillEnvironment(
-        pContext->GetFormFillEnv());
-  }
-#endif
-
   std::unique_ptr<IPDFSDK_AnnotHandler> pXFAHandler;
 #ifdef PDF_ENABLE_XFA
-  pXFAHandler = pdfium::MakeUnique<CPDFXFA_WidgetHandler>();
+  CPDFXFA_Context* pContext = nullptr;
+  if (!formInfo->xfa_disabled) {
+    if (!pDocument->GetExtension()) {
+      pDocument->SetExtension(pdfium::MakeUnique<CPDFXFA_Context>(pDocument));
+    }
+
+    // If the CPDFXFA_Context has a FormFillEnvironment already then we've done
+    // this and can just return the old Env. Otherwise, we'll end up setting a
+    // new environment into the XFADocument and, that could get weird.
+    pContext = static_cast<CPDFXFA_Context*>(pDocument->GetExtension());
+    if (pContext->GetFormFillEnv()) {
+      return FPDFFormHandleFromCPDFSDKFormFillEnvironment(
+          pContext->GetFormFillEnv());
+    }
+    pXFAHandler = pdfium::MakeUnique<CPDFXFA_WidgetHandler>();
+  }
 #endif  // PDF_ENABLE_XFA
 
   auto pFormFillEnv = pdfium::MakeUnique<CPDFSDK_FormFillEnvironment>(
@@ -324,6 +328,8 @@
     pContext->SetFormFillEnv(pFormFillEnv.get());
 #endif  // PDF_ENABLE_XFA
 
+  ReportUnsupportedXFA(pDocument);
+
   return FPDFFormHandleFromCPDFSDKFormFillEnvironment(
       pFormFillEnv.release());  // Caller takes ownership.
 }
diff --git a/fpdfsdk/fpdf_view.cpp b/fpdfsdk/fpdf_view.cpp
index 8f7a3b7..da25308 100644
--- a/fpdfsdk/fpdf_view.cpp
+++ b/fpdfsdk/fpdf_view.cpp
@@ -95,10 +95,6 @@
     return nullptr;
   }
 
-#ifdef PDF_ENABLE_XFA
-  pDocument->SetExtension(pdfium::MakeUnique<CPDFXFA_Context>(pDocument.get()));
-#endif  // PDF_ENABLE_XFA
-
   ReportUnsupportedFeatures(pDocument.get());
   return FPDFDocumentFromCPDFDocument(pDocument.release());
 }
diff --git a/public/fpdf_formfill.h b/public/fpdf_formfill.h
index 9979a4a..95c24b4 100644
--- a/public/fpdf_formfill.h
+++ b/public/fpdf_formfill.h
@@ -720,6 +720,13 @@
 
   /* Version 2 - Experimental. */
   /*
+   * Whether the XFA module is disabled when built with the XFA module.
+   * Interface Version:
+   *       Ignored if |version| < 2.
+   */
+  FPDF_BOOL xfa_disabled;
+
+  /*
    * Method: FFI_DisplayCaret
    *       This method will show the caret at specified position.
    * Interface Version:
diff --git a/samples/pdfium_test.cc b/samples/pdfium_test.cc
index d38227d..dc539dd 100644
--- a/samples/pdfium_test.cc
+++ b/samples/pdfium_test.cc
@@ -903,6 +903,8 @@
   FPDF_FORMFILLINFO_PDFiumTest form_callbacks = {};
 #ifdef PDF_ENABLE_XFA
   form_callbacks.version = 2;
+  form_callbacks.xfa_disabled =
+      options.disable_xfa || options.disable_javascript;
 #else   // PDF_ENABLE_XFA
   form_callbacks.version = 1;
 #endif  // PDF_ENABLE_XFA