Create CXFA_FFDoc via static function.

Rather than a two-step process involving a subsequent OpenDoc(),
use the static creation function pattern when the creation of
an object may fail.

Change-Id: I77ebd5ba2350ef84235ac8d8f52d6a9ab242da97
Reviewed-on: https://pdfium-review.googlesource.com/c/49991
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
index a78ad37..4290aa2 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
@@ -77,7 +77,6 @@
     return;
 
   m_pXFADocView = nullptr;
-  m_pXFADoc->CloseDoc();
   m_pXFADoc.reset();
 }
 
@@ -108,8 +107,8 @@
   if (!pApp)
     return false;
 
-  m_pXFADoc = pdfium::MakeUnique<CXFA_FFDoc>(pApp, &m_DocEnv);
-  if (!m_pXFADoc->OpenDoc(m_pPDFDoc.Get())) {
+  m_pXFADoc = CXFA_FFDoc::CreateAndOpen(pApp, &m_DocEnv, m_pPDFDoc.Get());
+  if (!m_pXFADoc) {
     SetLastError(FPDF_ERR_XFALOAD);
     return false;
   }
diff --git a/xfa/fxfa/cxfa_ffdoc.cpp b/xfa/fxfa/cxfa_ffdoc.cpp
index c2e10f6..b87e440 100644
--- a/xfa/fxfa/cxfa_ffdoc.cpp
+++ b/xfa/fxfa/cxfa_ffdoc.cpp
@@ -49,11 +49,59 @@
 
 FX_IMAGEDIB_AND_DPI::~FX_IMAGEDIB_AND_DPI() = default;
 
-CXFA_FFDoc::CXFA_FFDoc(CXFA_FFApp* pApp, IXFA_DocEnvironment* pDocEnvironment)
-    : m_pDocEnvironment(pDocEnvironment), m_pApp(pApp) {}
+// static
+std::unique_ptr<CXFA_FFDoc> CXFA_FFDoc::CreateAndOpen(
+    CXFA_FFApp* pApp,
+    IXFA_DocEnvironment* pDocEnvironment,
+    CPDF_Document* pPDFDoc) {
+  ASSERT(pApp);
+  ASSERT(pDocEnvironment);
+  ASSERT(pPDFDoc);
+
+  const CPDF_Dictionary* pRoot = pPDFDoc->GetRoot();
+  if (!pRoot)
+    return nullptr;
+
+  const CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm");
+  if (!pAcroForm)
+    return nullptr;
+
+  const CPDF_Object* pElementXFA = pAcroForm->GetDirectObjectFor("XFA");
+  if (!pElementXFA)
+    return nullptr;
+
+  // Use WrapUnique() to keep constructor private.
+  auto result =
+      pdfium::WrapUnique(new CXFA_FFDoc(pApp, pDocEnvironment, pPDFDoc));
+  if (!result->OpenDoc(pElementXFA))
+    return nullptr;
+
+  return result;
+}
+
+CXFA_FFDoc::CXFA_FFDoc(CXFA_FFApp* pApp,
+                       IXFA_DocEnvironment* pDocEnvironment,
+                       CPDF_Document* pPDFDoc)
+    : m_pDocEnvironment(pDocEnvironment),
+      m_pApp(pApp),
+      m_pPDFDoc(pPDFDoc),
+      m_pNotify(pdfium::MakeUnique<CXFA_FFNotify>(this)),
+      m_pDocument(pdfium::MakeUnique<CXFA_Document>(m_pNotify.get())) {}
 
 CXFA_FFDoc::~CXFA_FFDoc() {
-  CloseDoc();
+  if (m_DocView) {
+    m_DocView->RunDocClose();
+    m_DocView.reset();
+  }
+  if (m_pDocument)
+    m_pDocument->ClearLayoutData();
+
+  m_pDocument.reset();
+  m_pXMLDoc.reset();
+  m_pNotify.reset();
+  m_pPDFFontMgr.reset();
+  m_HashToDibDpiMap.clear();
+  m_pApp->ClearEventTargets();
 }
 
 bool CXFA_FFDoc::ParseDoc(const CPDF_Object* pElementXFA) {
@@ -103,31 +151,10 @@
   return m_DocView.get();
 }
 
-bool CXFA_FFDoc::OpenDoc(CPDF_Document* pPDFDoc) {
-  if (!pPDFDoc)
+bool CXFA_FFDoc::OpenDoc(const CPDF_Object* pElementXFA) {
+  if (!ParseDoc(pElementXFA))
     return false;
 
-  const CPDF_Dictionary* pRoot = pPDFDoc->GetRoot();
-  if (!pRoot)
-    return false;
-
-  const CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm");
-  if (!pAcroForm)
-    return false;
-
-  const CPDF_Object* pElementXFA = pAcroForm->GetDirectObjectFor("XFA");
-  if (!pElementXFA)
-    return false;
-
-  m_pPDFDoc = pPDFDoc;
-
-  m_pNotify = pdfium::MakeUnique<CXFA_FFNotify>(this);
-  m_pDocument = pdfium::MakeUnique<CXFA_Document>(m_pNotify.get());
-  if (!ParseDoc(pElementXFA)) {
-    CloseDoc();
-    return false;
-  }
-
   CFGAS_FontMgr* mgr = GetApp()->GetFDEFontMgr();
   if (!mgr)
     return false;
@@ -164,28 +191,9 @@
   return true;
 }
 
-void CXFA_FFDoc::CloseDoc() {
-  if (m_DocView) {
-    m_DocView->RunDocClose();
-    m_DocView.reset();
-  }
-  if (m_pDocument)
-    m_pDocument->ClearLayoutData();
-
-  m_pDocument.reset();
-  m_pXMLDoc.reset();
-  m_pNotify.reset();
-  m_pPDFFontMgr.reset();
-  m_HashToDibDpiMap.clear();
-  m_pApp->ClearEventTargets();
-}
-
 RetainPtr<CFX_DIBitmap> CXFA_FFDoc::GetPDFNamedImage(WideStringView wsName,
                                                      int32_t& iImageXDpi,
                                                      int32_t& iImageYDpi) {
-  if (!m_pPDFDoc)
-    return nullptr;
-
   uint32_t dwHash = FX_HashCode_GetW(wsName, false);
   auto it = m_HashToDibDpiMap.find(dwHash);
   if (it != m_HashToDibDpiMap.end()) {
diff --git a/xfa/fxfa/cxfa_ffdoc.h b/xfa/fxfa/cxfa_ffdoc.h
index 73e8d1b..7b7452c 100644
--- a/xfa/fxfa/cxfa_ffdoc.h
+++ b/xfa/fxfa/cxfa_ffdoc.h
@@ -41,7 +41,11 @@
 
 class CXFA_FFDoc {
  public:
-  CXFA_FFDoc(CXFA_FFApp* pApp, IXFA_DocEnvironment* pDocEnvironment);
+  static std::unique_ptr<CXFA_FFDoc> CreateAndOpen(
+      CXFA_FFApp* pApp,
+      IXFA_DocEnvironment* pDocEnvironment,
+      CPDF_Document* pPDFDoc);
+
   ~CXFA_FFDoc();
 
   IXFA_DocEnvironment* GetDocEnvironment() const {
@@ -52,9 +56,6 @@
 
   CXFA_FFDocView* CreateDocView();
 
-  bool OpenDoc(CPDF_Document* pPDFDoc);
-  void CloseDoc();
-
   CXFA_Document* GetXFADoc() const { return m_pDocument.get(); }
   CXFA_FFApp* GetApp() const { return m_pApp.Get(); }
   CPDF_Document* GetPDFDoc() const { return m_pPDFDoc.Get(); }
@@ -69,11 +70,15 @@
                    const RetainPtr<IFX_SeekableStream>& pFile);
 
  private:
+  CXFA_FFDoc(CXFA_FFApp* pApp,
+             IXFA_DocEnvironment* pDocEnvironment,
+             CPDF_Document* pPDFDoc);
+  bool OpenDoc(const CPDF_Object* pElementXFA);
   bool ParseDoc(const CPDF_Object* pElementXFA);
 
   UnownedPtr<IXFA_DocEnvironment> const m_pDocEnvironment;
   UnownedPtr<CXFA_FFApp> const m_pApp;
-  UnownedPtr<CPDF_Document> m_pPDFDoc;
+  UnownedPtr<CPDF_Document> const m_pPDFDoc;
   std::unique_ptr<CFX_XMLDocument> m_pXMLDoc;
   std::unique_ptr<CXFA_FFNotify> m_pNotify;
   std::unique_ptr<CXFA_Document> m_pDocument;