Merge CPDFXFA_App into CPDFXFA_Document.

This Cl moves the CPDFXFA_App code into CPDFXFA_Document.

Review-Url: https://codereview.chromium.org/2424993002
diff --git a/BUILD.gn b/BUILD.gn
index d35f97d..6503a6c 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1054,8 +1054,6 @@
 if (pdf_enable_xfa) {
   static_library("fpdfxfa") {
     sources = [
-      "fpdfsdk/fpdfxfa/cpdfxfa_app.cpp",
-      "fpdfsdk/fpdfxfa/cpdfxfa_app.h",
       "fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp",
       "fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.h",
       "fpdfsdk/fpdfxfa/cpdfxfa_document.cpp",
diff --git a/fpdfsdk/cpdfsdk_formfillenvironment.cpp b/fpdfsdk/cpdfsdk_formfillenvironment.cpp
index 2c44211..3907845 100644
--- a/fpdfsdk/cpdfsdk_formfillenvironment.cpp
+++ b/fpdfsdk/cpdfsdk_formfillenvironment.cpp
@@ -19,10 +19,6 @@
 #include "fpdfsdk/javascript/ijs_runtime.h"
 #include "third_party/base/ptr_util.h"
 
-#ifdef PDF_ENABLE_XFA
-#include "fpdfsdk/fpdfxfa/cpdfxfa_app.h"
-#endif  // PDF_ENABLE_XFA
-
 namespace {
 
 // NOTE: |bsUTF16LE| must outlive the use of the result. Care must be taken
diff --git a/fpdfsdk/fpdfdoc_unittest.cpp b/fpdfsdk/fpdfdoc_unittest.cpp
index adc135e..7ac8ce6 100644
--- a/fpdfsdk/fpdfdoc_unittest.cpp
+++ b/fpdfsdk/fpdfdoc_unittest.cpp
@@ -19,7 +19,6 @@
 #include "third_party/base/ptr_util.h"
 
 #ifdef PDF_ENABLE_XFA
-#include "fpdfsdk/fpdfxfa/cpdfxfa_app.h"
 #include "fpdfsdk/fpdfxfa/cpdfxfa_document.h"
 #endif  // PDF_ENABLE_XFA
 
diff --git a/fpdfsdk/fpdfeditpage.cpp b/fpdfsdk/fpdfeditpage.cpp
index 0b20a00..3f56d90 100644
--- a/fpdfsdk/fpdfeditpage.cpp
+++ b/fpdfsdk/fpdfeditpage.cpp
@@ -29,7 +29,6 @@
 #include "third_party/base/stl_util.h"
 
 #ifdef PDF_ENABLE_XFA
-#include "fpdfsdk/fpdfxfa/cpdfxfa_app.h"
 #include "fpdfsdk/fpdfxfa/cpdfxfa_document.h"
 #include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
 #endif  // PDF_ENABLE_XFA
diff --git a/fpdfsdk/fpdfformfill.cpp b/fpdfsdk/fpdfformfill.cpp
index 0f44b1d..7a884c7 100644
--- a/fpdfsdk/fpdfformfill.cpp
+++ b/fpdfsdk/fpdfformfill.cpp
@@ -27,7 +27,6 @@
 #include "third_party/base/stl_util.h"
 
 #ifdef PDF_ENABLE_XFA
-#include "fpdfsdk/fpdfxfa/cpdfxfa_app.h"
 #include "fpdfsdk/fpdfxfa/cpdfxfa_document.h"
 #include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
 #include "xfa/fxfa/xfa_ffdocview.h"
diff --git a/fpdfsdk/fpdfsave.cpp b/fpdfsdk/fpdfsave.cpp
index c98bb77..9676e44 100644
--- a/fpdfsdk/fpdfsave.cpp
+++ b/fpdfsdk/fpdfsave.cpp
@@ -19,7 +19,6 @@
 #include "public/fpdf_edit.h"
 
 #ifdef PDF_ENABLE_XFA
-#include "fpdfsdk/fpdfxfa/cpdfxfa_app.h"
 #include "fpdfsdk/fpdfxfa/cpdfxfa_document.h"
 #include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h"
 #include "public/fpdf_formfill.h"
diff --git a/fpdfsdk/fpdfview.cpp b/fpdfsdk/fpdfview.cpp
index f8e8e47..d7ddab8 100644
--- a/fpdfsdk/fpdfview.cpp
+++ b/fpdfsdk/fpdfview.cpp
@@ -37,7 +37,6 @@
 #include "third_party/base/ptr_util.h"
 
 #ifdef PDF_ENABLE_XFA
-#include "fpdfsdk/fpdfxfa/cpdfxfa_app.h"
 #include "fpdfsdk/fpdfxfa/cpdfxfa_document.h"
 #include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
 #include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h"
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_app.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_app.cpp
deleted file mode 100644
index 27ca1e0..0000000
--- a/fpdfsdk/fpdfxfa/cpdfxfa_app.cpp
+++ /dev/null
@@ -1,268 +0,0 @@
-// Copyright 2014 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#include "fpdfsdk/fpdfxfa/cpdfxfa_app.h"
-
-#include <memory>
-
-#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
-#include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h"
-#include "fpdfsdk/fsdk_define.h"
-#include "fpdfsdk/javascript/cjs_runtime.h"
-#include "fxjs/fxjs_v8.h"
-#include "xfa/fxfa/xfa_ffapp.h"
-#include "xfa/fxfa/xfa_fontmgr.h"
-
-CPDFXFA_App::CPDFXFA_App() {
-  m_pXFAApp = pdfium::MakeUnique<CXFA_FFApp>(this);
-  m_pXFAApp->SetDefaultFontMgr(pdfium::MakeUnique<CXFA_DefFontMgr>());
-}
-
-CPDFXFA_App::~CPDFXFA_App() {}
-
-v8::Isolate* CPDFXFA_App::GetJSERuntime() const {
-  if (!m_pFormFillEnv)
-    return nullptr;
-
-  // XFA requires V8, if we have V8 then we have a CJS_Runtime and not the stub.
-  CJS_Runtime* runtime =
-      static_cast<CJS_Runtime*>(m_pFormFillEnv->GetJSRuntime());
-  return runtime->GetIsolate();
-}
-
-void CPDFXFA_App::SetFormFillEnv(CPDFSDK_FormFillEnvironment* pFormFillEnv) {
-  m_pFormFillEnv = pFormFillEnv;
-}
-
-void CPDFXFA_App::GetAppName(CFX_WideString& wsName) {
-  if (m_pFormFillEnv)
-    wsName = m_pFormFillEnv->FFI_GetAppName();
-}
-
-void CPDFXFA_App::GetLanguage(CFX_WideString& wsLanguage) {
-  if (m_pFormFillEnv)
-    wsLanguage = m_pFormFillEnv->GetLanguage();
-}
-
-void CPDFXFA_App::GetPlatform(CFX_WideString& wsPlatform) {
-  if (m_pFormFillEnv) {
-    wsPlatform = m_pFormFillEnv->GetPlatform();
-  }
-}
-
-void CPDFXFA_App::Beep(uint32_t dwType) {
-  if (m_pFormFillEnv)
-    m_pFormFillEnv->JS_appBeep(dwType);
-}
-
-int32_t CPDFXFA_App::MsgBox(const CFX_WideString& wsMessage,
-                            const CFX_WideString& wsTitle,
-                            uint32_t dwIconType,
-                            uint32_t dwButtonType) {
-  if (!m_pFormFillEnv)
-    return -1;
-
-  uint32_t iconType = 0;
-  int iButtonType = 0;
-  switch (dwIconType) {
-    case XFA_MBICON_Error:
-      iconType |= 0;
-      break;
-    case XFA_MBICON_Warning:
-      iconType |= 1;
-      break;
-    case XFA_MBICON_Question:
-      iconType |= 2;
-      break;
-    case XFA_MBICON_Status:
-      iconType |= 3;
-      break;
-  }
-  switch (dwButtonType) {
-    case XFA_MB_OK:
-      iButtonType |= 0;
-      break;
-    case XFA_MB_OKCancel:
-      iButtonType |= 1;
-      break;
-    case XFA_MB_YesNo:
-      iButtonType |= 2;
-      break;
-    case XFA_MB_YesNoCancel:
-      iButtonType |= 3;
-      break;
-  }
-  int32_t iRet = m_pFormFillEnv->JS_appAlert(wsMessage.c_str(), wsTitle.c_str(),
-                                             iButtonType, iconType);
-  switch (iRet) {
-    case 1:
-      return XFA_IDOK;
-    case 2:
-      return XFA_IDCancel;
-    case 3:
-      return XFA_IDNo;
-    case 4:
-      return XFA_IDYes;
-  }
-  return XFA_IDYes;
-}
-
-CFX_WideString CPDFXFA_App::Response(const CFX_WideString& wsQuestion,
-                                     const CFX_WideString& wsTitle,
-                                     const CFX_WideString& wsDefaultAnswer,
-                                     FX_BOOL bMark) {
-  CFX_WideString wsAnswer;
-  if (!m_pFormFillEnv)
-    return wsAnswer;
-
-  int nLength = 2048;
-  char* pBuff = new char[nLength];
-  nLength = m_pFormFillEnv->JS_appResponse(wsQuestion.c_str(), wsTitle.c_str(),
-                                           wsDefaultAnswer.c_str(), nullptr,
-                                           bMark, pBuff, nLength);
-  if (nLength > 0) {
-    nLength = nLength > 2046 ? 2046 : nLength;
-    pBuff[nLength] = 0;
-    pBuff[nLength + 1] = 0;
-    wsAnswer = CFX_WideString::FromUTF16LE(
-        reinterpret_cast<const unsigned short*>(pBuff),
-        nLength / sizeof(unsigned short));
-  }
-  delete[] pBuff;
-  return wsAnswer;
-}
-
-IFX_SeekableReadStream* CPDFXFA_App::DownloadURL(const CFX_WideString& wsURL) {
-  return m_pFormFillEnv ? m_pFormFillEnv->DownloadFromURL(wsURL.c_str())
-                        : nullptr;
-}
-
-FX_BOOL CPDFXFA_App::PostRequestURL(const CFX_WideString& wsURL,
-                                    const CFX_WideString& wsData,
-                                    const CFX_WideString& wsContentType,
-                                    const CFX_WideString& wsEncode,
-                                    const CFX_WideString& wsHeader,
-                                    CFX_WideString& wsResponse) {
-  if (!m_pFormFillEnv)
-    return FALSE;
-
-  wsResponse = m_pFormFillEnv->PostRequestURL(
-      wsURL.c_str(), wsData.c_str(), wsContentType.c_str(), wsEncode.c_str(),
-      wsHeader.c_str());
-  return TRUE;
-}
-
-FX_BOOL CPDFXFA_App::PutRequestURL(const CFX_WideString& wsURL,
-                                   const CFX_WideString& wsData,
-                                   const CFX_WideString& wsEncode) {
-  return m_pFormFillEnv &&
-         m_pFormFillEnv->PutRequestURL(wsURL.c_str(), wsData.c_str(),
-                                       wsEncode.c_str());
-}
-
-void CPDFXFA_App::LoadString(int32_t iStringID, CFX_WideString& wsString) {
-  switch (iStringID) {
-    case XFA_IDS_ValidateFailed:
-      wsString = L"%s validation failed";
-      return;
-    case XFA_IDS_CalcOverride:
-      wsString = L"Calculate Override";
-      return;
-    case XFA_IDS_ModifyField:
-      wsString = L"Are you sure you want to modify this field?";
-      return;
-    case XFA_IDS_NotModifyField:
-      wsString = L"You are not allowed to modify this field.";
-      return;
-    case XFA_IDS_AppName:
-      wsString = L"pdfium";
-      return;
-    case XFA_IDS_Unable_TO_SET:
-      wsString = L"Unable to set ";
-      return;
-    case XFA_IDS_INVAlID_PROP_SET:
-      wsString = L"Invalid property set operation.";
-      return;
-    case XFA_IDS_NOT_DEFAUL_VALUE:
-      wsString = L" doesn't have a default property.";
-      return;
-    case XFA_IDS_UNABLE_SET_LANGUAGE:
-      wsString = L"Unable to set language value.";
-      return;
-    case XFA_IDS_UNABLE_SET_NUMPAGES:
-      wsString = L"Unable to set numPages value.";
-      return;
-    case XFA_IDS_UNABLE_SET_PLATFORM:
-      wsString = L"Unable to set platform value.";
-      return;
-    case XFA_IDS_UNABLE_SET_VARIATION:
-      wsString = L"Unable to set variation value.";
-      return;
-    case XFA_IDS_UNABLE_SET_VERSION:
-      wsString = L"Unable to set version value.";
-      return;
-    case XFA_IDS_UNABLE_SET_READY:
-      wsString = L"Unable to set ready value.";
-      return;
-    case XFA_IDS_COMPILER_ERROR:
-      wsString = L"Compiler error.";
-      return;
-    case XFA_IDS_DIVIDE_ZERO:
-      wsString = L"Divide by zero.";
-      return;
-    case XFA_IDS_ACCESS_PROPERTY_IN_NOT_OBJECT:
-      wsString =
-          L"An attempt was made to reference property '%s' of a non-object in "
-          L"SOM expression %s.";
-      return;
-    case XFA_IDS_INDEX_OUT_OF_BOUNDS:
-      wsString = L"Index value is out of bounds.";
-      return;
-    case XFA_IDS_INCORRECT_NUMBER_OF_METHOD:
-      wsString = L"Incorrect number of parameters calling method '%s'.";
-      return;
-    case XFA_IDS_ARGUMENT_MISMATCH:
-      wsString = L"Argument mismatch in property or function argument.";
-      return;
-    case XFA_IDS_NOT_HAVE_PROPERTY:
-      wsString = L"'%s' doesn't have property '%s'.";
-      return;
-    case XFA_IDS_VIOLATE_BOUNDARY:
-      wsString =
-          L"The element [%s] has violated its allowable number of occurrences.";
-      return;
-    case XFA_IDS_SERVER_DENY:
-      wsString = L"Server does not permit.";
-      return;
-    case XFA_IDS_ValidateLimit:
-      wsString =
-          L"Message limit exceeded. Remaining %d validation errors not "
-          L"reported.";
-      return;
-    case XFA_IDS_ValidateNullWarning:
-      wsString =
-          L"%s cannot be blank. To ignore validations for %s, click Ignore.";
-      return;
-    case XFA_IDS_ValidateNullError:
-      wsString = L"%s cannot be blank.";
-      return;
-    case XFA_IDS_ValidateWarning:
-      wsString =
-          L"The value you entered for %s is invalid. To ignore validations for "
-          L"%s, click Ignore.";
-      return;
-    case XFA_IDS_ValidateError:
-      wsString = L"The value you entered for %s is invalid.";
-      return;
-  }
-}
-
-IFWL_AdapterTimerMgr* CPDFXFA_App::GetTimerMgr() {
-  CXFA_FWLAdapterTimerMgr* pAdapter = nullptr;
-  if (m_pFormFillEnv)
-    pAdapter = new CXFA_FWLAdapterTimerMgr(m_pFormFillEnv);
-  return pAdapter;
-}
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_app.h b/fpdfsdk/fpdfxfa/cpdfxfa_app.h
deleted file mode 100644
index 763f88d..0000000
--- a/fpdfsdk/fpdfxfa/cpdfxfa_app.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2014 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#ifndef FPDFSDK_FPDFXFA_CPDFXFA_APP_H_
-#define FPDFSDK_FPDFXFA_CPDFXFA_APP_H_
-
-#include "third_party/base/ptr_util.h"
-#include "xfa/fxfa/fxfa.h"
-
-class CPDFSDK_FormFillEnvironment;
-class CJS_Runtime;
-
-class CPDFXFA_App : public IXFA_AppProvider {
- public:
-  CPDFXFA_App();
-  ~CPDFXFA_App() override;
-
-  CXFA_FFApp* GetXFAApp() { return m_pXFAApp.get(); }
-
-  void SetFormFillEnv(CPDFSDK_FormFillEnvironment* pFormFillEnv);
-
-  v8::Isolate* GetJSERuntime() const;
-
-  // IFXA_AppProvider:
-  void GetLanguage(CFX_WideString& wsLanguage) override;
-  void GetPlatform(CFX_WideString& wsPlatform) override;
-  void GetAppName(CFX_WideString& wsName) override;
-
-  void Beep(uint32_t dwType) override;
-  int32_t MsgBox(const CFX_WideString& wsMessage,
-                 const CFX_WideString& wsTitle,
-                 uint32_t dwIconType,
-                 uint32_t dwButtonType) override;
-  CFX_WideString Response(const CFX_WideString& wsQuestion,
-                          const CFX_WideString& wsTitle,
-                          const CFX_WideString& wsDefaultAnswer,
-                          FX_BOOL bMark) override;
-
-  IFX_SeekableReadStream* DownloadURL(const CFX_WideString& wsURL) override;
-  FX_BOOL PostRequestURL(const CFX_WideString& wsURL,
-                         const CFX_WideString& wsData,
-                         const CFX_WideString& wsContentType,
-                         const CFX_WideString& wsEncode,
-                         const CFX_WideString& wsHeader,
-                         CFX_WideString& wsResponse) override;
-  FX_BOOL PutRequestURL(const CFX_WideString& wsURL,
-                        const CFX_WideString& wsData,
-                        const CFX_WideString& wsEncode) override;
-
-  void LoadString(int32_t iStringID, CFX_WideString& wsString) override;
-  IFWL_AdapterTimerMgr* GetTimerMgr() override;
-
- private:
-  CPDFSDK_FormFillEnvironment* m_pFormFillEnv;  // Not owned.
-  std::unique_ptr<CXFA_FFApp> m_pXFAApp;
-};
-
-#endif  // FPDFSDK_FPDFXFA_CPDFXFA_APP_H_
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_document.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_document.cpp
index b04b950..0b840e4 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_document.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_document.cpp
@@ -10,10 +10,10 @@
 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
 #include "fpdfsdk/cpdfsdk_interform.h"
 #include "fpdfsdk/cpdfsdk_pageview.h"
-#include "fpdfsdk/fpdfxfa/cpdfxfa_app.h"
 #include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
 #include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h"
 #include "fpdfsdk/fsdk_define.h"
+#include "fpdfsdk/javascript/cjs_runtime.h"
 #include "fpdfsdk/javascript/ijs_runtime.h"
 #include "public/fpdf_formfill.h"
 #include "third_party/base/ptr_util.h"
@@ -23,6 +23,7 @@
 #include "xfa/fxfa/xfa_ffdocview.h"
 #include "xfa/fxfa/xfa_ffpageview.h"
 #include "xfa/fxfa/xfa_ffwidgethandler.h"
+#include "xfa/fxfa/xfa_fontmgr.h"
 
 #ifndef _WIN32
 extern void SetLastError(int err);
@@ -36,16 +37,16 @@
       m_pXFADocView(nullptr),
       m_nLoadStatus(FXFA_LOADSTATUS_PRELOAD),
       m_nPageCount(0),
-      m_DocEnv(this) {}
+      m_DocEnv(this) {
+  m_pXFAApp = pdfium::MakeUnique<CXFA_FFApp>(this);
+  m_pXFAApp->SetDefaultFontMgr(pdfium::MakeUnique<CXFA_DefFontMgr>());
+}
 
 CPDFXFA_Document::~CPDFXFA_Document() {
   m_nLoadStatus = FXFA_LOADSTATUS_CLOSING;
 
   // Must happen before we remove the form fill environment.
-  if (m_pXFADoc) {
-    if (CXFA_FFApp* pApp = GetApp()->GetXFAApp())
-      CloseXFADoc(pApp->GetDocHandler());
-  }
+  CloseXFADoc();
 
   if (m_pFormFillEnv) {
     m_pFormFillEnv->ClearAllFocusedAnnots();
@@ -58,20 +59,14 @@
   m_nLoadStatus = FXFA_LOADSTATUS_CLOSED;
 }
 
-void CPDFXFA_Document::CloseXFADoc(CXFA_FFDocHandler* pDoc) {
-  if (!pDoc)
+void CPDFXFA_Document::CloseXFADoc() {
+  if (!m_pXFADoc)
     return;
   m_pXFADoc->CloseDoc();
   m_pXFADoc.reset();
   m_pXFADocView = nullptr;
 }
 
-CPDFXFA_App* CPDFXFA_Document::GetApp() {
-  if (!m_pApp)
-    m_pApp = pdfium::MakeUnique<CPDFXFA_App>();
-  return m_pApp.get();
-}
-
 void CPDFXFA_Document::SetFormFillEnv(
     CPDFSDK_FormFillEnvironment* pFormFillEnv) {
   // The layout data can have pointers back into the script context. That
@@ -80,7 +75,6 @@
   if (m_pXFADoc && m_pXFADoc->GetXFADoc())
     m_pXFADoc->GetXFADoc()->ClearLayoutData();
 
-  GetApp()->SetFormFillEnv(pFormFillEnv);
   m_pFormFillEnv = pFormFillEnv;
 }
 
@@ -92,7 +86,7 @@
 
   m_XFAPageList.RemoveAll();
 
-  CXFA_FFApp* pApp = GetApp()->GetXFAApp();
+  CXFA_FFApp* pApp = GetXFAApp();
   if (!pApp)
     return FALSE;
 
@@ -111,12 +105,12 @@
   m_pXFADoc->StartLoad();
   int iStatus = m_pXFADoc->DoLoad(nullptr);
   if (iStatus != XFA_PARSESTATUS_Done) {
-    CloseXFADoc(pDocHandler);
+    CloseXFADoc();
     SetLastError(FPDF_ERR_XFALOAD);
     return FALSE;
   }
   m_pXFADoc->StopLoad();
-  m_pXFADoc->GetXFADoc()->InitScriptContext(GetApp()->GetJSERuntime());
+  m_pXFADoc->GetXFADoc()->InitScriptContext(GetJSERuntime());
 
   if (m_pXFADoc->GetDocType() == XFA_DOCTYPE_Dynamic)
     m_iDocType = DOCTYPE_DYNAMIC_XFA;
@@ -125,7 +119,7 @@
 
   m_pXFADocView = m_pXFADoc->CreateDocView(XFA_DOCVIEW_View);
   if (m_pXFADocView->StartLayout() < 0) {
-    CloseXFADoc(pDocHandler);
+    CloseXFADoc();
     SetLastError(FPDF_ERR_XFALAYOUT);
     return FALSE;
   }
@@ -224,3 +218,243 @@
   if (m_pFormFillEnv)
     m_pFormFillEnv->ClearChangeMark();
 }
+
+v8::Isolate* CPDFXFA_Document::GetJSERuntime() const {
+  if (!m_pFormFillEnv)
+    return nullptr;
+
+  // XFA requires V8, if we have V8 then we have a CJS_Runtime and not the stub.
+  CJS_Runtime* runtime =
+      static_cast<CJS_Runtime*>(m_pFormFillEnv->GetJSRuntime());
+  return runtime->GetIsolate();
+}
+
+void CPDFXFA_Document::GetAppName(CFX_WideString& wsName) {
+  if (m_pFormFillEnv)
+    wsName = m_pFormFillEnv->FFI_GetAppName();
+}
+
+void CPDFXFA_Document::GetLanguage(CFX_WideString& wsLanguage) {
+  if (m_pFormFillEnv)
+    wsLanguage = m_pFormFillEnv->GetLanguage();
+}
+
+void CPDFXFA_Document::GetPlatform(CFX_WideString& wsPlatform) {
+  if (m_pFormFillEnv)
+    wsPlatform = m_pFormFillEnv->GetPlatform();
+}
+
+void CPDFXFA_Document::Beep(uint32_t dwType) {
+  if (m_pFormFillEnv)
+    m_pFormFillEnv->JS_appBeep(dwType);
+}
+
+int32_t CPDFXFA_Document::MsgBox(const CFX_WideString& wsMessage,
+                                 const CFX_WideString& wsTitle,
+                                 uint32_t dwIconType,
+                                 uint32_t dwButtonType) {
+  if (!m_pFormFillEnv)
+    return -1;
+
+  uint32_t iconType = 0;
+  int iButtonType = 0;
+  switch (dwIconType) {
+    case XFA_MBICON_Error:
+      iconType |= 0;
+      break;
+    case XFA_MBICON_Warning:
+      iconType |= 1;
+      break;
+    case XFA_MBICON_Question:
+      iconType |= 2;
+      break;
+    case XFA_MBICON_Status:
+      iconType |= 3;
+      break;
+  }
+  switch (dwButtonType) {
+    case XFA_MB_OK:
+      iButtonType |= 0;
+      break;
+    case XFA_MB_OKCancel:
+      iButtonType |= 1;
+      break;
+    case XFA_MB_YesNo:
+      iButtonType |= 2;
+      break;
+    case XFA_MB_YesNoCancel:
+      iButtonType |= 3;
+      break;
+  }
+  int32_t iRet = m_pFormFillEnv->JS_appAlert(wsMessage.c_str(), wsTitle.c_str(),
+                                             iButtonType, iconType);
+  switch (iRet) {
+    case 1:
+      return XFA_IDOK;
+    case 2:
+      return XFA_IDCancel;
+    case 3:
+      return XFA_IDNo;
+    case 4:
+      return XFA_IDYes;
+  }
+  return XFA_IDYes;
+}
+
+CFX_WideString CPDFXFA_Document::Response(const CFX_WideString& wsQuestion,
+                                          const CFX_WideString& wsTitle,
+                                          const CFX_WideString& wsDefaultAnswer,
+                                          FX_BOOL bMark) {
+  CFX_WideString wsAnswer;
+  if (!m_pFormFillEnv)
+    return wsAnswer;
+
+  int nLength = 2048;
+  char* pBuff = new char[nLength];
+  nLength = m_pFormFillEnv->JS_appResponse(wsQuestion.c_str(), wsTitle.c_str(),
+                                           wsDefaultAnswer.c_str(), nullptr,
+                                           bMark, pBuff, nLength);
+  if (nLength > 0) {
+    nLength = nLength > 2046 ? 2046 : nLength;
+    pBuff[nLength] = 0;
+    pBuff[nLength + 1] = 0;
+    wsAnswer = CFX_WideString::FromUTF16LE(
+        reinterpret_cast<const unsigned short*>(pBuff),
+        nLength / sizeof(unsigned short));
+  }
+  delete[] pBuff;
+  return wsAnswer;
+}
+
+IFX_SeekableReadStream* CPDFXFA_Document::DownloadURL(
+    const CFX_WideString& wsURL) {
+  return m_pFormFillEnv ? m_pFormFillEnv->DownloadFromURL(wsURL.c_str())
+                        : nullptr;
+}
+
+FX_BOOL CPDFXFA_Document::PostRequestURL(const CFX_WideString& wsURL,
+                                         const CFX_WideString& wsData,
+                                         const CFX_WideString& wsContentType,
+                                         const CFX_WideString& wsEncode,
+                                         const CFX_WideString& wsHeader,
+                                         CFX_WideString& wsResponse) {
+  if (!m_pFormFillEnv)
+    return FALSE;
+
+  wsResponse = m_pFormFillEnv->PostRequestURL(
+      wsURL.c_str(), wsData.c_str(), wsContentType.c_str(), wsEncode.c_str(),
+      wsHeader.c_str());
+  return TRUE;
+}
+
+FX_BOOL CPDFXFA_Document::PutRequestURL(const CFX_WideString& wsURL,
+                                        const CFX_WideString& wsData,
+                                        const CFX_WideString& wsEncode) {
+  return m_pFormFillEnv &&
+         m_pFormFillEnv->PutRequestURL(wsURL.c_str(), wsData.c_str(),
+                                       wsEncode.c_str());
+}
+
+void CPDFXFA_Document::LoadString(int32_t iStringID, CFX_WideString& wsString) {
+  switch (iStringID) {
+    case XFA_IDS_ValidateFailed:
+      wsString = L"%s validation failed";
+      return;
+    case XFA_IDS_CalcOverride:
+      wsString = L"Calculate Override";
+      return;
+    case XFA_IDS_ModifyField:
+      wsString = L"Are you sure you want to modify this field?";
+      return;
+    case XFA_IDS_NotModifyField:
+      wsString = L"You are not allowed to modify this field.";
+      return;
+    case XFA_IDS_AppName:
+      wsString = L"pdfium";
+      return;
+    case XFA_IDS_Unable_TO_SET:
+      wsString = L"Unable to set ";
+      return;
+    case XFA_IDS_INVAlID_PROP_SET:
+      wsString = L"Invalid property set operation.";
+      return;
+    case XFA_IDS_NOT_DEFAUL_VALUE:
+      wsString = L" doesn't have a default property.";
+      return;
+    case XFA_IDS_UNABLE_SET_LANGUAGE:
+      wsString = L"Unable to set language value.";
+      return;
+    case XFA_IDS_UNABLE_SET_NUMPAGES:
+      wsString = L"Unable to set numPages value.";
+      return;
+    case XFA_IDS_UNABLE_SET_PLATFORM:
+      wsString = L"Unable to set platform value.";
+      return;
+    case XFA_IDS_UNABLE_SET_VARIATION:
+      wsString = L"Unable to set variation value.";
+      return;
+    case XFA_IDS_UNABLE_SET_VERSION:
+      wsString = L"Unable to set version value.";
+      return;
+    case XFA_IDS_UNABLE_SET_READY:
+      wsString = L"Unable to set ready value.";
+      return;
+    case XFA_IDS_COMPILER_ERROR:
+      wsString = L"Compiler error.";
+      return;
+    case XFA_IDS_DIVIDE_ZERO:
+      wsString = L"Divide by zero.";
+      return;
+    case XFA_IDS_ACCESS_PROPERTY_IN_NOT_OBJECT:
+      wsString =
+          L"An attempt was made to reference property '%s' of a non-object in "
+          L"SOM expression %s.";
+      return;
+    case XFA_IDS_INDEX_OUT_OF_BOUNDS:
+      wsString = L"Index value is out of bounds.";
+      return;
+    case XFA_IDS_INCORRECT_NUMBER_OF_METHOD:
+      wsString = L"Incorrect number of parameters calling method '%s'.";
+      return;
+    case XFA_IDS_ARGUMENT_MISMATCH:
+      wsString = L"Argument mismatch in property or function argument.";
+      return;
+    case XFA_IDS_NOT_HAVE_PROPERTY:
+      wsString = L"'%s' doesn't have property '%s'.";
+      return;
+    case XFA_IDS_VIOLATE_BOUNDARY:
+      wsString =
+          L"The element [%s] has violated its allowable number of occurrences.";
+      return;
+    case XFA_IDS_SERVER_DENY:
+      wsString = L"Server does not permit.";
+      return;
+    case XFA_IDS_ValidateLimit:
+      wsString =
+          L"Message limit exceeded. Remaining %d validation errors not "
+          L"reported.";
+      return;
+    case XFA_IDS_ValidateNullWarning:
+      wsString =
+          L"%s cannot be blank. To ignore validations for %s, click Ignore.";
+      return;
+    case XFA_IDS_ValidateNullError:
+      wsString = L"%s cannot be blank.";
+      return;
+    case XFA_IDS_ValidateWarning:
+      wsString =
+          L"The value you entered for %s is invalid. To ignore validations for "
+          L"%s, click Ignore.";
+      return;
+    case XFA_IDS_ValidateError:
+      wsString = L"The value you entered for %s is invalid.";
+      return;
+  }
+}
+
+IFWL_AdapterTimerMgr* CPDFXFA_Document::GetTimerMgr() {
+  CXFA_FWLAdapterTimerMgr* pAdapter = nullptr;
+  if (m_pFormFillEnv)
+    pAdapter = new CXFA_FWLAdapterTimerMgr(m_pFormFillEnv);
+  return pAdapter;
+}
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_document.h b/fpdfsdk/fpdfxfa/cpdfxfa_document.h
index 00a9f25..ab0d757 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_document.h
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_document.h
@@ -9,10 +9,10 @@
 
 #include <memory>
 
-#include "fpdfsdk/fpdfxfa/cpdfxfa_app.h"
 #include "fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.h"
 #include "xfa/fxfa/xfa_ffdoc.h"
 
+class CJS_Runtime;
 class CPDFSDK_FormFillEnvironment;
 class CPDFXFA_Page;
 class CXFA_FFDocHandler;
@@ -27,17 +27,18 @@
   FXFA_LOADSTATUS_CLOSED
 };
 
-class CPDFXFA_Document {
+class CPDFXFA_Document : public IXFA_AppProvider {
  public:
   CPDFXFA_Document(std::unique_ptr<CPDF_Document> pPDFDoc);
-  ~CPDFXFA_Document();
+  ~CPDFXFA_Document() override;
 
   FX_BOOL LoadXFADoc();
   CPDF_Document* GetPDFDoc() { return m_pPDFDoc.get(); }
   CXFA_FFDoc* GetXFADoc() { return m_pXFADoc.get(); }
   CXFA_FFDocView* GetXFADocView() { return m_pXFADocView; }
   int GetDocType() const { return m_iDocType; }
-  CPDFXFA_App* GetApp();  // Creates if needed.
+  v8::Isolate* GetJSERuntime() const;
+  CXFA_FFApp* GetXFAApp() { return m_pXFAApp.get(); }
 
   CPDFSDK_FormFillEnvironment* GetFormFillEnv() const { return m_pFormFillEnv; }
   void SetFormFillEnv(CPDFSDK_FormFillEnvironment* pFormFillEnv);
@@ -52,6 +53,34 @@
 
   void ClearChangeMark();
 
+  // IFXA_AppProvider:
+  void GetLanguage(CFX_WideString& wsLanguage) override;
+  void GetPlatform(CFX_WideString& wsPlatform) override;
+  void GetAppName(CFX_WideString& wsName) override;
+
+  void Beep(uint32_t dwType) override;
+  int32_t MsgBox(const CFX_WideString& wsMessage,
+                 const CFX_WideString& wsTitle,
+                 uint32_t dwIconType,
+                 uint32_t dwButtonType) override;
+  CFX_WideString Response(const CFX_WideString& wsQuestion,
+                          const CFX_WideString& wsTitle,
+                          const CFX_WideString& wsDefaultAnswer,
+                          FX_BOOL bMark) override;
+  IFX_SeekableReadStream* DownloadURL(const CFX_WideString& wsURL) override;
+  FX_BOOL PostRequestURL(const CFX_WideString& wsURL,
+                         const CFX_WideString& wsData,
+                         const CFX_WideString& wsContentType,
+                         const CFX_WideString& wsEncode,
+                         const CFX_WideString& wsHeader,
+                         CFX_WideString& wsResponse) override;
+  FX_BOOL PutRequestURL(const CFX_WideString& wsURL,
+                        const CFX_WideString& wsData,
+                        const CFX_WideString& wsEncode) override;
+
+  void LoadString(int32_t iStringID, CFX_WideString& wsString) override;
+  IFWL_AdapterTimerMgr* GetTimerMgr() override;
+
  protected:
   friend class CPDFXFA_DocEnvironment;
 
@@ -66,7 +95,7 @@
   CFX_ArrayTemplate<CPDFXFA_Page*>* GetXFAPageList() { return &m_XFAPageList; }
 
  private:
-  void CloseXFADoc(CXFA_FFDocHandler* pDoc);
+  void CloseXFADoc();
 
   int m_iDocType;
 
@@ -74,7 +103,8 @@
   std::unique_ptr<CXFA_FFDoc> m_pXFADoc;
   CPDFSDK_FormFillEnvironment* m_pFormFillEnv;  // not owned.
   CXFA_FFDocView* m_pXFADocView;  // not owned.
-  std::unique_ptr<CPDFXFA_App> m_pApp;
+  std::unique_ptr<CXFA_FFApp> m_pXFAApp;
+  std::unique_ptr<CJS_Runtime> m_pRuntime;
   CFX_ArrayTemplate<CPDFXFA_Page*> m_XFAPageList;
   LoadStatus m_nLoadStatus;
   int m_nPageCount;
diff --git a/fpdfsdk/javascript/cjs_runtime.cpp b/fpdfsdk/javascript/cjs_runtime.cpp
index 637fa0a..ca1c112 100644
--- a/fpdfsdk/javascript/cjs_runtime.cpp
+++ b/fpdfsdk/javascript/cjs_runtime.cpp
@@ -32,7 +32,6 @@
 #include "third_party/base/stl_util.h"
 
 #ifdef PDF_ENABLE_XFA
-#include "fpdfsdk/fpdfxfa/cpdfxfa_app.h"
 #include "fxjs/cfxjse_value.h"
 #endif  // PDF_ENABLE_XFA