Make CFGAS_FontMgr a per-process singleton.

Avoid having to worry about garbage collecting it and its descendants.

-- Introduce CFGAS_GEModule singleton, (parallel to CFX_GEModule)
-- Remove unused RemoveFont() method.
-- Remove SkipFontLoadForTest(), doesn't affect success.
-- Remove comment about reloading FontMgr, we only do it once.
-- Move EnumFonts() up in header, we call it before others.

Change-Id: Ieef1e9fe0c73b8103eed49c27e4db87964534aae
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/73330
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/fpdfsdk/fpdfxfa/BUILD.gn b/fpdfsdk/fpdfxfa/BUILD.gn
index b7a6bc4..6fae96f 100644
--- a/fpdfsdk/fpdfxfa/BUILD.gn
+++ b/fpdfsdk/fpdfxfa/BUILD.gn
@@ -28,6 +28,7 @@
     "../../core/fxcrt",
     "../../fxbarcode",
     "../../fxjs",
+    "../../xfa/fgas",
     "../../xfa/fwl",
     "../../xfa/fxfa",
     "../../xfa/fxfa/parser",
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
index 947a253..1c28350 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
@@ -27,6 +27,7 @@
 #include "public/fpdf_formfill.h"
 #include "third_party/base/stl_util.h"
 #include "v8/include/cppgc/allocation.h"
+#include "xfa/fgas/font/cfgas_gemodule.h"
 #include "xfa/fxfa/cxfa_eventparam.h"
 #include "xfa/fxfa/cxfa_ffapp.h"
 #include "xfa/fxfa/cxfa_ffdoc.h"
@@ -86,11 +87,13 @@
 }  // namespace
 
 void CPDFXFA_ModuleInit() {
+  CFGAS_GEModule::Create();
   BC_Library_Init();
 }
 
 void CPDFXFA_ModuleDestroy() {
   BC_Library_Destroy();
+  CFGAS_GEModule::Destroy();
 }
 
 CPDFXFA_Context::CPDFXFA_Context(CPDF_Document* pPDFDoc)
diff --git a/testing/fuzzers/pdf_bidi_fuzzer.cc b/testing/fuzzers/pdf_bidi_fuzzer.cc
index fb6caf6..ad8801a 100644
--- a/testing/fuzzers/pdf_bidi_fuzzer.cc
+++ b/testing/fuzzers/pdf_bidi_fuzzer.cc
@@ -8,21 +8,20 @@
 #include "core/fxcrt/widestring.h"
 #include "core/fxge/cfx_font.h"
 #include "core/fxge/fx_font.h"
-#include "xfa/fgas/font/cfgas_fontmgr.h"
 #include "xfa/fgas/font/cfgas_gefont.h"
+#include "xfa/fgas/font/cfgas_gemodule.h"
 #include "xfa/fgas/layout/cfx_char.h"
 #include "xfa/fgas/layout/cfx_rtfbreak.h"
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  auto fontmgr = std::make_unique<CFGAS_FontMgr>();
-
+  CFGAS_GEModule::Create();
   auto font = std::make_unique<CFX_Font>();
   font->LoadSubst("Arial", true, 0, FXFONT_FW_NORMAL, 0, 0, 0);
   assert(font);
 
   CFX_RTFBreak rtf_break(FX_LAYOUTSTYLE_ExpandTab);
   rtf_break.SetLineBreakTolerance(1);
-  rtf_break.SetFont(CFGAS_GEFont::LoadFont(std::move(font), fontmgr.get()));
+  rtf_break.SetFont(CFGAS_GEFont::LoadFont(std::move(font)));
   rtf_break.SetFontSize(12);
 
   WideString input =
@@ -34,5 +33,6 @@
   std::vector<CFX_Char> chars =
       rtf_break.GetCurrentLineForTesting()->m_LineChars;
   CFX_Char::BidiLine(&chars, chars.size());
+  CFGAS_GEModule::Destroy();
   return 0;
 }
diff --git a/testing/xfa_js_embedder_test.cpp b/testing/xfa_js_embedder_test.cpp
index 9c692d9..2eb1947 100644
--- a/testing/xfa_js_embedder_test.cpp
+++ b/testing/xfa_js_embedder_test.cpp
@@ -11,7 +11,6 @@
 #include "fxjs/xfa/cfxjse_engine.h"
 #include "fxjs/xfa/cfxjse_value.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "xfa/fxfa/cxfa_ffapp.h"
 
 XFAJSEmbedderTest::XFAJSEmbedderTest() = default;
 
@@ -19,12 +18,9 @@
 
 void XFAJSEmbedderTest::SetUp() {
   JSEmbedderTest::SetUp();
-  CXFA_FFApp::SkipFontLoadForTesting(true);
 }
 
 void XFAJSEmbedderTest::TearDown() {
-  CXFA_FFApp::SkipFontLoadForTesting(false);
-
   value_.reset();
   script_context_ = nullptr;
 
diff --git a/testing/xfa_test_environment.cpp b/testing/xfa_test_environment.cpp
index b62faeb..07afb93 100644
--- a/testing/xfa_test_environment.cpp
+++ b/testing/xfa_test_environment.cpp
@@ -10,9 +10,7 @@
 #include "core/fxge/cfx_fontmgr.h"
 #include "core/fxge/cfx_gemodule.h"
 #include "core/fxge/systemfontinfo_iface.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/base/logging.h"
-#include "xfa/fgas/font/cfgas_fontmgr.h"
+#include "xfa/fgas/font/cfgas_gemodule.h"
 
 namespace {
 
@@ -31,20 +29,14 @@
 }
 
 void XFATestEnvironment::SetUp() {
-  // This font loading is slow, but we do it only once per binary
-  // execution, not once per test.
   CFX_GEModule::Get()->GetFontMgr()->SetSystemFontInfo(
       CFX_GEModule::Get()->GetPlatform()->CreateDefaultSystemFontInfo());
 
-  font_mgr_ = std::make_unique<CFGAS_FontMgr>();
-  CHECK(font_mgr_->EnumFonts());
+  // The font loading that takes place in CFGAS_GEModule::Create() is slow,
+  // but we do it only once per binary execution, not once per test.
+  CFGAS_GEModule::Create();
 }
 
 void XFATestEnvironment::TearDown() {
-  font_mgr_.reset();
-}
-
-// static
-CFGAS_FontMgr* XFATestEnvironment::GetGlobalFontManager() {
-  return g_env->font_mgr_.get();
+  CFGAS_GEModule::Destroy();
 }
diff --git a/testing/xfa_test_environment.h b/testing/xfa_test_environment.h
index af991ac..fd18601 100644
--- a/testing/xfa_test_environment.h
+++ b/testing/xfa_test_environment.h
@@ -13,12 +13,6 @@
 #error "XFA must be enabled"
 #endif
 
-class CFGAS_FontMgr;
-
-// XFATestEnvironement loads a CFGAS_FontMgr, whose time is linear in the
-// number of times it is loaded. So, if a test suite has a lot of tests that
-// need a font manager they can end up executing very, very slowly.
-
 class XFATestEnvironment : public testing::Environment {
  public:
   XFATestEnvironment();
@@ -27,12 +21,6 @@
   // testing::TestEnvironment:
   void SetUp() override;
   void TearDown() override;
-
-  // Does not create if not present.
-  static CFGAS_FontMgr* GetGlobalFontManager();
-
- private:
-  std::unique_ptr<CFGAS_FontMgr> font_mgr_;
 };
 
 #endif  // TESTING_XFA_UNIT_TEST_SUPPORT_H_
diff --git a/xfa/fde/cfde_texteditengine.cpp b/xfa/fde/cfde_texteditengine.cpp
index 292a89f..2e36c60 100644
--- a/xfa/fde/cfde_texteditengine.cpp
+++ b/xfa/fde/cfde_texteditengine.cpp
@@ -10,6 +10,7 @@
 #include <limits>
 #include <utility>
 
+#include "core/fxcrt/fx_extension.h"
 #include "core/fxge/text_char_pos.h"
 #include "xfa/fde/cfde_textout.h"
 #include "xfa/fde/cfde_wordbreak_data.h"
diff --git a/xfa/fde/cfde_texteditengine_unittest.cpp b/xfa/fde/cfde_texteditengine_unittest.cpp
index 6195cdb..83014e8 100644
--- a/xfa/fde/cfde_texteditengine_unittest.cpp
+++ b/xfa/fde/cfde_texteditengine_unittest.cpp
@@ -37,8 +37,7 @@
   ~CFDE_TextEditEngineTest() override {}
 
   void SetUp() override {
-    font_ = CFGAS_GEFont::LoadFont(L"Arial Black", 0, 0,
-                                   XFATestEnvironment::GetGlobalFontManager());
+    font_ = CFGAS_GEFont::LoadFont(L"Arial Black", 0, 0);
     ASSERT_TRUE(font_);
 
     engine_ = std::make_unique<CFDE_TextEditEngine>();
@@ -46,7 +45,10 @@
     engine_->SetFontSize(12.0f);
   }
 
-  void TearDown() override { engine_.reset(); }
+  void TearDown() override {
+    engine_.reset();
+    font_.Reset();
+  }
 
   CFDE_TextEditEngine* engine() const { return engine_.get(); }
 
diff --git a/xfa/fde/cfde_textout.cpp b/xfa/fde/cfde_textout.cpp
index 25e3d4b..7049b75 100644
--- a/xfa/fde/cfde_textout.cpp
+++ b/xfa/fde/cfde_textout.cpp
@@ -11,6 +11,7 @@
 
 #include "build/build_config.h"
 #include "core/fxcrt/fx_coordinates.h"
+#include "core/fxcrt/fx_extension.h"
 #include "core/fxcrt/fx_system.h"
 #include "core/fxge/cfx_font.h"
 #include "core/fxge/cfx_pathdata.h"
diff --git a/xfa/fgas/BUILD.gn b/xfa/fgas/BUILD.gn
index 7860fbd..fe2057d 100644
--- a/xfa/fgas/BUILD.gn
+++ b/xfa/fgas/BUILD.gn
@@ -21,6 +21,8 @@
     "font/cfgas_fontmgr.h",
     "font/cfgas_gefont.cpp",
     "font/cfgas_gefont.h",
+    "font/cfgas_gemodule.cpp",
+    "font/cfgas_gemodule.h",
     "font/cfgas_pdffontmgr.cpp",
     "font/cfgas_pdffontmgr.h",
     "font/fgas_fontutils.cpp",
diff --git a/xfa/fgas/font/cfgas_defaultfontmanager.cpp b/xfa/fgas/font/cfgas_defaultfontmanager.cpp
index 4115b7b..c28b21b 100644
--- a/xfa/fgas/font/cfgas_defaultfontmanager.cpp
+++ b/xfa/fgas/font/cfgas_defaultfontmanager.cpp
@@ -7,15 +7,17 @@
 #include "xfa/fgas/font/cfgas_defaultfontmanager.h"
 
 #include "core/fxge/fx_font.h"
+#include "xfa/fgas/font/cfgas_fontmgr.h"
 #include "xfa/fgas/font/cfgas_gefont.h"
+#include "xfa/fgas/font/cfgas_gemodule.h"
 #include "xfa/fgas/font/fgas_fontutils.h"
 
 // static
 RetainPtr<CFGAS_GEFont> CFGAS_DefaultFontManager::GetFont(
-    CFGAS_FontMgr* pFontMgr,
     WideStringView wsFontFamily,
     uint32_t dwFontStyles) {
   WideString wsFontName(wsFontFamily);
+  CFGAS_FontMgr* pFontMgr = CFGAS_GEModule::Get()->GetFontMgr();
   RetainPtr<CFGAS_GEFont> pFont =
       pFontMgr->LoadFont(wsFontName.c_str(), dwFontStyles, 0xFFFF);
   if (pFont)
@@ -56,8 +58,8 @@
 
 // static
 RetainPtr<CFGAS_GEFont> CFGAS_DefaultFontManager::GetDefaultFont(
-    CFGAS_FontMgr* pFontMgr,
     uint32_t dwFontStyles) {
+  CFGAS_FontMgr* pFontMgr = CFGAS_GEModule::Get()->GetFontMgr();
   RetainPtr<CFGAS_GEFont> pFont =
       pFontMgr->LoadFont(L"Arial Narrow", dwFontStyles, 0xFFFF);
   if (pFont)
diff --git a/xfa/fgas/font/cfgas_defaultfontmanager.h b/xfa/fgas/font/cfgas_defaultfontmanager.h
index 32fb372..bb78189 100644
--- a/xfa/fgas/font/cfgas_defaultfontmanager.h
+++ b/xfa/fgas/font/cfgas_defaultfontmanager.h
@@ -11,15 +11,12 @@
 #include "core/fxcrt/retain_ptr.h"
 
 class CFGAS_GEFont;
-class CFGAS_FontMgr;
 
 class CFGAS_DefaultFontManager {
  public:
-  static RetainPtr<CFGAS_GEFont> GetFont(CFGAS_FontMgr* pFontMgr,
-                                         WideStringView wsFontFamily,
+  static RetainPtr<CFGAS_GEFont> GetFont(WideStringView wsFontFamily,
                                          uint32_t dwFontStyles);
-  static RetainPtr<CFGAS_GEFont> GetDefaultFont(CFGAS_FontMgr* pFontMgr,
-                                                uint32_t dwFontStyles);
+  static RetainPtr<CFGAS_GEFont> GetDefaultFont(uint32_t dwFontStyles);
 
   CFGAS_DefaultFontManager() = delete;
   CFGAS_DefaultFontManager(const CFGAS_DefaultFontManager&) = delete;
diff --git a/xfa/fgas/font/cfgas_fontmgr.cpp b/xfa/fgas/font/cfgas_fontmgr.cpp
index 8b2de13..500660e 100644
--- a/xfa/fgas/font/cfgas_fontmgr.cpp
+++ b/xfa/fgas/font/cfgas_fontmgr.cpp
@@ -192,9 +192,8 @@
     return nullptr;
 
   uint16_t newCodePage = FX_GetCodePageFromCharset(pFD->uCharSet);
-  const wchar_t* pFontFace = pFD->wsFontFace;
   RetainPtr<CFGAS_GEFont> pFont =
-      CFGAS_GEFont::LoadFont(pFontFace, dwFontStyles, newCodePage, this);
+      CFGAS_GEFont::LoadFont(pFD->wsFontFace, dwFontStyles, newCodePage);
   if (!pFont)
     return nullptr;
 
@@ -676,7 +675,7 @@
   if (!pInternalFont->LoadFile(std::move(pFontStream), iFaceIndex))
     return nullptr;
 
-  return CFGAS_GEFont::LoadFont(std::move(pInternalFont), this);
+  return CFGAS_GEFont::LoadFont(std::move(pInternalFont));
 }
 
 void CFGAS_FontMgr::MatchFonts(
@@ -778,7 +777,7 @@
     return nullptr;
 
   RetainPtr<CFGAS_GEFont> pFont =
-      CFGAS_GEFont::LoadFont(pFD->wsFontFace, dwFontStyles, wCodePage, this);
+      CFGAS_GEFont::LoadFont(pFD->wsFontFace, dwFontStyles, wCodePage);
 #else   // defined(OS_WIN)
   std::vector<CFX_FontDescriptorInfo>* sortedFontInfos =
       m_Hash2CandidateList[dwHash].get();
@@ -853,7 +852,7 @@
     return nullptr;
 
   RetainPtr<CFGAS_GEFont> pFont =
-      CFGAS_GEFont::LoadFont(pFD->wsFontFace, dwFontStyles, wCodePage, this);
+      CFGAS_GEFont::LoadFont(pFD->wsFontFace, dwFontStyles, wCodePage);
   if (!pFont)
     return nullptr;
 
diff --git a/xfa/fgas/font/cfgas_fontmgr.h b/xfa/fgas/font/cfgas_fontmgr.h
index c91cc8c..dda900d 100644
--- a/xfa/fgas/font/cfgas_fontmgr.h
+++ b/xfa/fgas/font/cfgas_fontmgr.h
@@ -16,7 +16,6 @@
 #include "build/build_config.h"
 #include "core/fxcrt/fx_extension.h"
 #include "core/fxcrt/fx_string.h"
-#include "core/fxcrt/observed_ptr.h"
 #include "core/fxcrt/retain_ptr.h"
 #include "core/fxge/cfx_face.h"
 #include "core/fxge/fx_freetype.h"
@@ -95,11 +94,12 @@
 
 #endif  // defined(OS_WIN)
 
-class CFGAS_FontMgr final : public Observable {
+class CFGAS_FontMgr {
  public:
   CFGAS_FontMgr();
   ~CFGAS_FontMgr();
 
+  bool EnumFonts();
   RetainPtr<CFGAS_GEFont> GetFontByCodePage(uint16_t wCodePage,
                                             uint32_t dwFontStyles,
                                             const wchar_t* pszFontFamily);
@@ -109,7 +109,6 @@
   RetainPtr<CFGAS_GEFont> LoadFont(const wchar_t* pszFontFamily,
                                    uint32_t dwFontStyles,
                                    uint16_t wCodePage);
-  bool EnumFonts();
 
  private:
   RetainPtr<CFGAS_GEFont> GetFontByUnicodeImpl(wchar_t wUnicode,
diff --git a/xfa/fgas/font/cfgas_gefont.cpp b/xfa/fgas/font/cfgas_gefont.cpp
index 5719662..3144b55 100644
--- a/xfa/fgas/font/cfgas_gefont.cpp
+++ b/xfa/fgas/font/cfgas_gefont.cpp
@@ -16,30 +16,29 @@
 #include "core/fxge/cfx_substfont.h"
 #include "core/fxge/cfx_unicodeencodingex.h"
 #include "core/fxge/fx_font.h"
+#include "xfa/fgas/font/cfgas_fontmgr.h"
+#include "xfa/fgas/font/cfgas_gemodule.h"
 #include "xfa/fgas/font/fgas_fontutils.h"
 
 // static
 RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(const wchar_t* pszFontFamily,
                                                uint32_t dwFontStyles,
-                                               uint16_t wCodePage,
-                                               CFGAS_FontMgr* pFontMgr) {
+                                               uint16_t wCodePage) {
 #if defined(OS_WIN)
-  auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr);
+  auto pFont = pdfium::MakeRetain<CFGAS_GEFont>();
   if (!pFont->LoadFontInternal(pszFontFamily, dwFontStyles, wCodePage))
     return nullptr;
   return pFont;
 #else
-  if (!pFontMgr)
-    return nullptr;
-  return pFontMgr->GetFontByCodePage(wCodePage, dwFontStyles, pszFontFamily);
+  return CFGAS_GEModule::Get()->GetFontMgr()->GetFontByCodePage(
+      wCodePage, dwFontStyles, pszFontFamily);
 #endif
 }
 
 // static
 RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(
-    const RetainPtr<CPDF_Font>& pPDFFont,
-    CFGAS_FontMgr* pFontMgr) {
-  auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr);
+    const RetainPtr<CPDF_Font>& pPDFFont) {
+  auto pFont = pdfium::MakeRetain<CFGAS_GEFont>();
   if (!pFont->LoadFontInternal(pPDFFont))
     return nullptr;
 
@@ -48,25 +47,24 @@
 
 // static
 RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(
-    std::unique_ptr<CFX_Font> pInternalFont,
-    CFGAS_FontMgr* pFontMgr) {
-  auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr);
+    std::unique_ptr<CFX_Font> pInternalFont) {
+  auto pFont = pdfium::MakeRetain<CFGAS_GEFont>();
   if (!pFont->LoadFontInternal(std::move(pInternalFont)))
     return nullptr;
+
   return pFont;
 }
 
 // static
 RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadStockFont(
     CPDF_Document* pDoc,
-    CFGAS_FontMgr* pMgr,
     const ByteString& font_family) {
   RetainPtr<CPDF_Font> stock_font =
       CPDF_Font::GetStockFont(pDoc, font_family.AsStringView());
-  return stock_font ? CFGAS_GEFont::LoadFont(stock_font, pMgr) : nullptr;
+  return stock_font ? CFGAS_GEFont::LoadFont(stock_font) : nullptr;
 }
 
-CFGAS_GEFont::CFGAS_GEFont(CFGAS_FontMgr* pFontMgr) : m_pFontMgr(pFontMgr) {}
+CFGAS_GEFont::CFGAS_GEFont() = default;
 
 CFGAS_GEFont::~CFGAS_GEFont() = default;
 
@@ -246,15 +244,16 @@
       }
     }
   }
-  if (!m_pFontMgr || !bRecursive)
+  if (!bRecursive)
     return {0xFFFF, nullptr};
 
+  CFGAS_FontMgr* pFontMgr = CFGAS_GEModule::Get()->GetFontMgr();
   WideString wsFamily = GetFamilyName();
   RetainPtr<CFGAS_GEFont> pFont =
-      m_pFontMgr->GetFontByUnicode(wUnicode, GetFontStyles(), wsFamily.c_str());
+      pFontMgr->GetFontByUnicode(wUnicode, GetFontStyles(), wsFamily.c_str());
 #if !defined(OS_WIN)
   if (!pFont)
-    pFont = m_pFontMgr->GetFontByUnicode(wUnicode, GetFontStyles(), nullptr);
+    pFont = pFontMgr->GetFontByUnicode(wUnicode, GetFontStyles(), nullptr);
 #endif
   if (!pFont || pFont == this)  // Avoids direct cycles below.
     return {0xFFFF, nullptr};
diff --git a/xfa/fgas/font/cfgas_gefont.h b/xfa/fgas/font/cfgas_gefont.h
index 1649d8d..97daf3d 100644
--- a/xfa/fgas/font/cfgas_gefont.h
+++ b/xfa/fgas/font/cfgas_gefont.h
@@ -14,11 +14,11 @@
 
 #include "build/build_config.h"
 #include "core/fxcrt/fx_coordinates.h"
+#include "core/fxcrt/fx_string.h"
 #include "core/fxcrt/fx_system.h"
 #include "core/fxcrt/maybe_owned.h"
 #include "core/fxcrt/retain_ptr.h"
 #include "third_party/base/optional.h"
-#include "xfa/fgas/font/cfgas_fontmgr.h"
 
 class CFX_Font;
 class CFX_UnicodeEncodingEx;
@@ -31,16 +31,10 @@
 
   static RetainPtr<CFGAS_GEFont> LoadFont(const wchar_t* pszFontFamily,
                                           uint32_t dwFontStyles,
-                                          uint16_t wCodePage,
-                                          CFGAS_FontMgr* pFontMgr);
-  static RetainPtr<CFGAS_GEFont> LoadFont(const RetainPtr<CPDF_Font>& pPDFFont,
-                                          CFGAS_FontMgr* pFontMgr);
-  static RetainPtr<CFGAS_GEFont> LoadFont(
-      std::unique_ptr<CFX_Font> pInternalFont,
-      CFGAS_FontMgr* pFontMgr);
-
+                                          uint16_t wCodePage);
+  static RetainPtr<CFGAS_GEFont> LoadFont(const RetainPtr<CPDF_Font>& pFont);
+  static RetainPtr<CFGAS_GEFont> LoadFont(std::unique_ptr<CFX_Font> pFont);
   static RetainPtr<CFGAS_GEFont> LoadStockFont(CPDF_Document* pDoc,
-                                               CFGAS_FontMgr* pMgr,
                                                const ByteString& font_family);
 
   uint32_t GetFontStyles() const;
@@ -60,7 +54,7 @@
   }
 
  private:
-  explicit CFGAS_GEFont(CFGAS_FontMgr* pFontMgr);
+  CFGAS_GEFont();
   ~CFGAS_GEFont() override;
 
 #if defined(OS_WIN)
@@ -80,7 +74,6 @@
   Optional<uint32_t> m_dwLogFontStyle;
   RetainPtr<CPDF_Font> m_pPDFFont;  // Must come before |m_pFont|.
   MaybeOwned<CFX_Font> m_pFont;     // Must come before |m_pFontEncoding|.
-  ObservedPtr<CFGAS_FontMgr> const m_pFontMgr;
   std::unique_ptr<CFX_UnicodeEncodingEx> m_pFontEncoding;
   std::map<wchar_t, int32_t> m_CharWidthMap;
   std::map<wchar_t, FX_RECT> m_BBoxMap;
diff --git a/xfa/fgas/font/cfgas_gemodule.cpp b/xfa/fgas/font/cfgas_gemodule.cpp
new file mode 100644
index 0000000..cc8fb26
--- /dev/null
+++ b/xfa/fgas/font/cfgas_gemodule.cpp
@@ -0,0 +1,38 @@
+// Copyright 2020 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.
+
+#include "xfa/fgas/font/cfgas_gemodule.h"
+
+#include "xfa/fgas/font/cfgas_fontmgr.h"
+
+namespace {
+
+CFGAS_GEModule* g_module = nullptr;
+
+}  // namespace
+
+// static
+void CFGAS_GEModule::Create() {
+  ASSERT(!g_module);
+  g_module = new CFGAS_GEModule();
+  g_module->GetFontMgr()->EnumFonts();
+}
+
+// static
+void CFGAS_GEModule::Destroy() {
+  ASSERT(g_module);
+  delete g_module;
+  g_module = nullptr;
+}
+
+// static
+CFGAS_GEModule* CFGAS_GEModule::Get() {
+  ASSERT(g_module);
+  return g_module;
+}
+
+CFGAS_GEModule::CFGAS_GEModule()
+    : font_mgr_(std::make_unique<CFGAS_FontMgr>()) {}
+
+CFGAS_GEModule::~CFGAS_GEModule() = default;
diff --git a/xfa/fgas/font/cfgas_gemodule.h b/xfa/fgas/font/cfgas_gemodule.h
new file mode 100644
index 0000000..0518123
--- /dev/null
+++ b/xfa/fgas/font/cfgas_gemodule.h
@@ -0,0 +1,27 @@
+// Copyright 2020 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.
+
+#ifndef XFA_FGAS_FONT_CFGAS_GEMODULE_H_
+#define XFA_FGAS_FONT_CFGAS_GEMODULE_H_
+
+#include <memory>
+
+class CFGAS_FontMgr;
+
+class CFGAS_GEModule {
+ public:
+  static void Create();
+  static void Destroy();
+  static CFGAS_GEModule* Get();
+
+  CFGAS_FontMgr* GetFontMgr() { return font_mgr_.get(); }
+
+ private:
+  CFGAS_GEModule();
+  ~CFGAS_GEModule();
+
+  std::unique_ptr<CFGAS_FontMgr> font_mgr_;
+};
+
+#endif  // XFA_FGAS_FONT_CFGAS_GEMODULE_H_
diff --git a/xfa/fgas/font/cfgas_pdffontmgr.cpp b/xfa/fgas/font/cfgas_pdffontmgr.cpp
index b55ca40..731812a 100644
--- a/xfa/fgas/font/cfgas_pdffontmgr.cpp
+++ b/xfa/fgas/font/cfgas_pdffontmgr.cpp
@@ -28,10 +28,8 @@
 
 }  // namespace
 
-CFGAS_PDFFontMgr::CFGAS_PDFFontMgr(CPDF_Document* pDoc, CFGAS_FontMgr* pFontMgr)
-    : m_pDoc(pDoc), m_pFontMgr(pFontMgr) {
+CFGAS_PDFFontMgr::CFGAS_PDFFontMgr(CPDF_Document* pDoc) : m_pDoc(pDoc) {
   ASSERT(pDoc);
-  ASSERT(pFontMgr);
 }
 
 CFGAS_PDFFontMgr::~CFGAS_PDFFontMgr() = default;
@@ -69,7 +67,7 @@
     if (!pPDFFont || !pPDFFont->IsEmbedded())
       return nullptr;
 
-    return CFGAS_GEFont::LoadFont(pPDFFont, m_pFontMgr.Get());
+    return CFGAS_GEFont::LoadFont(pPDFFont);
   }
   return nullptr;
 }
diff --git a/xfa/fgas/font/cfgas_pdffontmgr.h b/xfa/fgas/font/cfgas_pdffontmgr.h
index 750ff7c..8c3b01e 100644
--- a/xfa/fgas/font/cfgas_pdffontmgr.h
+++ b/xfa/fgas/font/cfgas_pdffontmgr.h
@@ -20,7 +20,7 @@
 
 class CFGAS_PDFFontMgr final : public Observable {
  public:
-  CFGAS_PDFFontMgr(CPDF_Document* pDoc, CFGAS_FontMgr* pFontMgr);
+  explicit CFGAS_PDFFontMgr(CPDF_Document* pDoc);
   ~CFGAS_PDFFontMgr();
 
   RetainPtr<CFGAS_GEFont> GetFont(WideStringView wsFontFamily,
@@ -42,7 +42,6 @@
                              bool bStrictMatch);
 
   UnownedPtr<CPDF_Document> const m_pDoc;
-  ObservedPtr<CFGAS_FontMgr> const m_pFontMgr;
   std::map<ByteString, RetainPtr<CFGAS_GEFont>> m_FontMap;
 };
 
diff --git a/xfa/fgas/layout/cfx_rtfbreak.cpp b/xfa/fgas/layout/cfx_rtfbreak.cpp
index 2040372..5b290b9 100644
--- a/xfa/fgas/layout/cfx_rtfbreak.cpp
+++ b/xfa/fgas/layout/cfx_rtfbreak.cpp
@@ -9,6 +9,7 @@
 #include <algorithm>
 
 #include "build/build_config.h"
+#include "core/fxcrt/fx_extension.h"
 #include "core/fxcrt/fx_safe_types.h"
 #include "core/fxge/text_char_pos.h"
 #include "third_party/base/containers/adapters.h"
diff --git a/xfa/fgas/layout/cfx_rtfbreak_unittest.cpp b/xfa/fgas/layout/cfx_rtfbreak_unittest.cpp
index e104a2f..4261a43 100644
--- a/xfa/fgas/layout/cfx_rtfbreak_unittest.cpp
+++ b/xfa/fgas/layout/cfx_rtfbreak_unittest.cpp
@@ -12,7 +12,6 @@
 #include "core/fxge/cfx_font.h"
 #include "core/fxge/cfx_gemodule.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "testing/xfa_test_environment.h"
 #include "xfa/fgas/font/cfgas_fontmgr.h"
 #include "xfa/fgas/font/cfgas_gefont.h"
 #include "xfa/fgas/layout/cfx_char.h"
@@ -20,8 +19,7 @@
 class CFX_RTFBreakTest : public testing::Test {
  public:
   void SetUp() override {
-    font_ = CFGAS_GEFont::LoadFont(L"Arial Black", 0, 0,
-                                   XFATestEnvironment::GetGlobalFontManager());
+    font_ = CFGAS_GEFont::LoadFont(L"Arial Black", 0, 0);
     ASSERT_TRUE(font_);
   }
 
diff --git a/xfa/fgas/layout/cfx_txtbreak.cpp b/xfa/fgas/layout/cfx_txtbreak.cpp
index 07bacab..139e0a3 100644
--- a/xfa/fgas/layout/cfx_txtbreak.cpp
+++ b/xfa/fgas/layout/cfx_txtbreak.cpp
@@ -9,6 +9,7 @@
 #include <algorithm>
 
 #include "build/build_config.h"
+#include "core/fxcrt/fx_extension.h"
 #include "core/fxcrt/fx_safe_types.h"
 #include "core/fxge/text_char_pos.h"
 #include "third_party/base/containers/adapters.h"
diff --git a/xfa/fgas/layout/cfx_txtbreak_unittest.cpp b/xfa/fgas/layout/cfx_txtbreak_unittest.cpp
index 792f006..8d1ed6d 100644
--- a/xfa/fgas/layout/cfx_txtbreak_unittest.cpp
+++ b/xfa/fgas/layout/cfx_txtbreak_unittest.cpp
@@ -9,7 +9,6 @@
 
 #include "core/fxge/cfx_font.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "testing/xfa_test_environment.h"
 #include "xfa/fgas/font/cfgas_fontmgr.h"
 #include "xfa/fgas/font/cfgas_gefont.h"
 #include "xfa/fgas/layout/cfx_char.h"
@@ -17,8 +16,7 @@
 class CFX_TxtBreakTest : public testing::Test {
  public:
   void SetUp() override {
-    font_ = CFGAS_GEFont::LoadFont(L"Arial Black", 0, 0,
-                                   XFATestEnvironment::GetGlobalFontManager());
+    font_ = CFGAS_GEFont::LoadFont(L"Arial Black", 0, 0);
     ASSERT_TRUE(font_);
   }
 
diff --git a/xfa/fwl/theme/cfwl_widgettp.cpp b/xfa/fwl/theme/cfwl_widgettp.cpp
index a5a7355..b914066 100644
--- a/xfa/fwl/theme/cfwl_widgettp.cpp
+++ b/xfa/fwl/theme/cfwl_widgettp.cpp
@@ -239,15 +239,10 @@
   m_wsFamily = wsFontFamily;
   m_dwStyles = dwFontStyles;
   m_dwCodePage = dwCodePage;
-  if (!m_pFontMgr) {
-    m_pFontMgr = std::make_unique<CFGAS_FontMgr>();
-    if (!m_pFontMgr->EnumFonts())
-      m_pFontMgr = nullptr;
-  }
 
   // TODO(tsepez): check usage of c_str() below.
   m_pFont = CFGAS_GEFont::LoadFont(wsFontFamily.unterminated_c_str(),
-                                   dwFontStyles, dwCodePage, m_pFontMgr.get());
+                                   dwFontStyles, dwCodePage);
   return !!m_pFont;
 }
 
diff --git a/xfa/fwl/theme/cfwl_widgettp.h b/xfa/fwl/theme/cfwl_widgettp.h
index 798e6aa..042b884 100644
--- a/xfa/fwl/theme/cfwl_widgettp.h
+++ b/xfa/fwl/theme/cfwl_widgettp.h
@@ -17,7 +17,6 @@
 #include "xfa/fxgraphics/cxfa_graphics.h"
 
 class CFDE_TextOut;
-class CFGAS_FontMgr;
 class CFGAS_GEFont;
 class CFWL_ThemeBackground;
 class CFWL_ThemeText;
@@ -94,7 +93,6 @@
   WideString m_wsFamily;
   uint32_t m_dwStyles;
   uint32_t m_dwCodePage;
-  std::unique_ptr<CFGAS_FontMgr> m_pFontMgr;
   RetainPtr<CFGAS_GEFont> m_pFont;
 };
 
diff --git a/xfa/fxfa/cxfa_ffapp.cpp b/xfa/fxfa/cxfa_ffapp.cpp
index 47b8b0b..dbcdeec 100644
--- a/xfa/fxfa/cxfa_ffapp.cpp
+++ b/xfa/fxfa/cxfa_ffapp.cpp
@@ -10,7 +10,6 @@
 #include <memory>
 #include <utility>
 
-#include "xfa/fgas/font/cfgas_fontmgr.h"
 #include "xfa/fwl/cfwl_notedriver.h"
 #include "xfa/fwl/cfwl_widgetmgr.h"
 #include "xfa/fxfa/cxfa_ffdoc.h"
@@ -19,17 +18,6 @@
 #include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h"
 #include "xfa/fxfa/cxfa_fwltheme.h"
 
-namespace {
-
-bool g_skipFontLoadForTesting = false;
-
-}  // namespace
-
-// static
-void CXFA_FFApp::SkipFontLoadForTesting(bool skip) {
-  g_skipFontLoadForTesting = skip;
-}
-
 CXFA_FFApp::CXFA_FFApp(IXFA_AppProvider* pProvider)
     : m_pProvider(pProvider), m_pXFAFontMgr(std::make_unique<CXFA_FontMgr>()) {
   // Ensure fully initialized before making objects based on |this|.
@@ -45,17 +33,6 @@
   visitor->Trace(m_pFWLApp);
 }
 
-CFGAS_FontMgr* CXFA_FFApp::GetFGASFontMgr() {
-  if (!m_pFGASFontMgr) {
-    m_pFGASFontMgr = std::make_unique<CFGAS_FontMgr>();
-    if (!g_skipFontLoadForTesting) {
-      if (!m_pFGASFontMgr->EnumFonts())
-        m_pFGASFontMgr = nullptr;
-    }
-  }
-  return m_pFGASFontMgr.get();
-}
-
 bool CXFA_FFApp::LoadFWLTheme(CXFA_FFDoc* doc) {
   auto* fwl_theme = cppgc::MakeGarbageCollected<CXFA_FWLTheme>(
       GetHeap()->GetAllocationHandle(), this);
diff --git a/xfa/fxfa/cxfa_ffapp.h b/xfa/fxfa/cxfa_ffapp.h
index cc068dd..d1f90e0 100644
--- a/xfa/fxfa/cxfa_ffapp.h
+++ b/xfa/fxfa/cxfa_ffapp.h
@@ -25,8 +25,6 @@
 class CXFA_FFApp : public cppgc::GarbageCollected<CXFA_FFApp>,
                    public CFWL_App::AdapterIface {
  public:
-  static void SkipFontLoadForTesting(bool skip);
-
   CONSTRUCT_VIA_MAKE_GARBAGE_COLLECTED;
   ~CXFA_FFApp() override;
 
@@ -39,8 +37,6 @@
 
   bool LoadFWLTheme(CXFA_FFDoc* doc);
   CFWL_WidgetMgr* GetFWLWidgetMgr() const { return m_pFWLApp->GetWidgetMgr(); }
-  CFGAS_FontMgr* GetFGASFontMgr();
-
   IXFA_AppProvider* GetAppProvider() const { return m_pProvider.Get(); }
   CFWL_App* GetFWLApp() const { return m_pFWLApp; }
   CXFA_FontMgr* GetXFAFontMgr() const { return m_pXFAFontMgr.get(); }
@@ -57,10 +53,6 @@
   // you get a use-after-free. The m_pFWLTheme can try to cleanup a GEFont
   // when it frees, so make sure it gets cleaned up first. That requires
   // m_pFWLApp to be cleaned up as well.
-  //
-  // TODO(dsinclair): The GEFont should have the FontMgr as the pointer instead
-  // of the DEFFontMgr so this goes away. Bug 561.
-  std::unique_ptr<CFGAS_FontMgr> m_pFGASFontMgr;
   std::unique_ptr<CXFA_FontMgr> m_pXFAFontMgr;
   cppgc::Member<CXFA_FWLAdapterWidgetMgr> m_pAdapterWidgetMgr;
   cppgc::Member<CXFA_FWLTheme> m_pFWLTheme;
diff --git a/xfa/fxfa/cxfa_ffdoc.cpp b/xfa/fxfa/cxfa_ffdoc.cpp
index dc557e6..4ab61d6 100644
--- a/xfa/fxfa/cxfa_ffdoc.cpp
+++ b/xfa/fxfa/cxfa_ffdoc.cpp
@@ -232,14 +232,9 @@
   if (!BuildDoc(pXML))
     return false;
 
-  CFGAS_FontMgr* mgr = GetApp()->GetFGASFontMgr();
-  if (!mgr)
-    return false;
-
   // At this point we've got an XFA document and we want to always return
   // true to signify the load succeeded.
-  m_pPDFFontMgr = std::make_unique<CFGAS_PDFFontMgr>(GetPDFDoc(), mgr);
-
+  m_pPDFFontMgr = std::make_unique<CFGAS_PDFFontMgr>(GetPDFDoc());
   m_FormType = FormType::kXFAForeground;
   CXFA_Node* pConfig = ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Config));
   if (!pConfig)
diff --git a/xfa/fxfa/cxfa_fontmgr.cpp b/xfa/fxfa/cxfa_fontmgr.cpp
index 7f7f4b1..b20b778 100644
--- a/xfa/fxfa/cxfa_fontmgr.cpp
+++ b/xfa/fxfa/cxfa_fontmgr.cpp
@@ -42,21 +42,19 @@
       return pFont;
   }
   if (!pFont) {
-    pFont = CFGAS_DefaultFontManager::GetFont(hDoc->GetApp()->GetFGASFontMgr(),
-                                              wsFontFamily, dwFontStyles);
+    pFont = CFGAS_DefaultFontManager::GetFont(wsFontFamily, dwFontStyles);
   }
   if (!pFont && pMgr) {
     pFont = pMgr->GetFont(wsEnglishName.AsStringView(), dwFontStyles, false);
     if (pFont)
       return pFont;
   }
-  if (!pFont) {
-    pFont = CFGAS_DefaultFontManager::GetDefaultFont(
-        hDoc->GetApp()->GetFGASFontMgr(), dwFontStyles);
-  }
+  if (!pFont)
+    pFont = CFGAS_DefaultFontManager::GetDefaultFont(dwFontStyles);
+
   if (!pFont) {
     pFont = CFGAS_GEFont::LoadStockFont(
-        hDoc->GetPDFDoc(), hDoc->GetApp()->GetFGASFontMgr(),
+        hDoc->GetPDFDoc(),
         ByteString::Format("%ls", WideString(wsFontFamily).c_str()));
   }
   if (pFont)
diff --git a/xfa/fxfa/cxfa_fwltheme.cpp b/xfa/fxfa/cxfa_fwltheme.cpp
index 5fabf10..5929cce 100644
--- a/xfa/fxfa/cxfa_fwltheme.cpp
+++ b/xfa/fxfa/cxfa_fwltheme.cpp
@@ -9,7 +9,9 @@
 #include "core/fxcrt/fx_codepage.h"
 #include "third_party/base/stl_util.h"
 #include "xfa/fde/cfde_textout.h"
+#include "xfa/fgas/font/cfgas_fontmgr.h"
 #include "xfa/fgas/font/cfgas_gefont.h"
+#include "xfa/fgas/font/cfgas_gemodule.h"
 #include "xfa/fwl/cfwl_barcode.h"
 #include "xfa/fwl/cfwl_caret.h"
 #include "xfa/fwl/cfwl_checkbox.h"
@@ -68,16 +70,11 @@
     m_pCalendarFont =
         m_pApp->GetXFAFontMgr()->GetFont(doc, g_FWLTheme_CalFonts[i], 0);
   }
-
   if (!m_pCalendarFont) {
-    CFGAS_FontMgr* font_mgr = m_pApp->GetFGASFontMgr();
-    if (font_mgr) {
-      m_pCalendarFont = font_mgr->GetFontByCodePage(
-          FX_CODEPAGE_MSWin_WesternEuropean, 0, nullptr);
-    }
+    m_pCalendarFont = CFGAS_GEModule::Get()->GetFontMgr()->GetFontByCodePage(
+        FX_CODEPAGE_MSWin_WesternEuropean, 0, nullptr);
   }
-
-  return m_pCalendarFont != nullptr;
+  return !!m_pCalendarFont;
 }
 
 void CXFA_FWLTheme::DrawBackground(const CFWL_ThemeBackground& pParams) {