Introduce common superclass GCedLocaleIface

Allows replacement of a raw pointer with a member in the xfa/fxfa
layer, while at the same time keeping the lower xfa/fgas layer
unaware of GC entirely.

Bug: pdfium:1563
Change-Id: If2ae33d8316084c114dfef9e5665a387d4bf7fd0
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/74073
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/fxjs/xfa/cfxjse_formcalc_context.cpp b/fxjs/xfa/cfxjse_formcalc_context.cpp
index 388b4b8..393184f 100644
--- a/fxjs/xfa/cfxjse_formcalc_context.cpp
+++ b/fxjs/xfa/cfxjse_formcalc_context.cpp
@@ -21,7 +21,6 @@
 #include "fxjs/xfa/cjx_object.h"
 #include "third_party/base/stl_util.h"
 #include "xfa/fgas/crt/cfgas_decimal.h"
-#include "xfa/fgas/crt/locale_iface.h"
 #include "xfa/fxfa/cxfa_ffnotify.h"
 #include "xfa/fxfa/fm2js/cxfa_fmparser.h"
 #include "xfa/fxfa/fm2js/cxfa_fmtojavascriptdepth.h"
@@ -30,6 +29,7 @@
 #include "xfa/fxfa/parser/cxfa_node.h"
 #include "xfa/fxfa/parser/cxfa_thisproxy.h"
 #include "xfa/fxfa/parser/cxfa_timezoneprovider.h"
+#include "xfa/fxfa/parser/gced_locale_iface.h"
 #include "xfa/fxfa/parser/xfa_utils.h"
 
 using pdfium::fxjse::kClassTag;
@@ -411,9 +411,9 @@
   return pHostObj ? pHostObj->AsFormCalcContext() : nullptr;
 }
 
-LocaleIface* LocaleFromString(CXFA_Document* pDoc,
-                              CXFA_LocaleMgr* pMgr,
-                              ByteStringView bsLocale) {
+GCedLocaleIface* LocaleFromString(CXFA_Document* pDoc,
+                                  CXFA_LocaleMgr* pMgr,
+                                  ByteStringView bsLocale) {
   if (!bsLocale.IsEmpty())
     return pMgr->GetLocaleByName(WideString::FromUTF8(bsLocale));
 
@@ -2372,7 +2372,7 @@
 
   CXFA_Document* pDoc = ToFormCalcContext(pThis)->GetDocument();
   CXFA_LocaleMgr* pMgr = pDoc->GetLocaleMgr();
-  LocaleIface* pLocale = nullptr;
+  GCedLocaleIface* pLocale = nullptr;
   if (bsLocale.IsEmpty()) {
     CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
     pLocale = pThisNode->GetLocale();
@@ -2465,7 +2465,7 @@
     return ByteString();
 
   CXFA_LocaleMgr* pMgr = pDoc->GetLocaleMgr();
-  LocaleIface* pLocale = LocaleFromString(pDoc, pMgr, bsLocale);
+  GCedLocaleIface* pLocale = LocaleFromString(pDoc, pMgr, bsLocale);
   if (!pLocale)
     return ByteString();
 
@@ -2488,7 +2488,7 @@
     return ByteString();
 
   CXFA_LocaleMgr* pMgr = pDoc->GetLocaleMgr();
-  LocaleIface* pLocale = LocaleFromString(pDoc, pMgr, bsLocale);
+  GCedLocaleIface* pLocale = LocaleFromString(pDoc, pMgr, bsLocale);
   if (!pLocale)
     return ByteString();
 
@@ -2509,7 +2509,7 @@
     return ByteString();
 
   CXFA_LocaleMgr* pMgr = pDoc->GetLocaleMgr();
-  LocaleIface* pLocale = LocaleFromString(pDoc, pMgr, bsLocale);
+  GCedLocaleIface* pLocale = LocaleFromString(pDoc, pMgr, bsLocale);
   if (!pLocale)
     return ByteString();
 
@@ -3698,7 +3698,7 @@
   CXFA_Document* pDoc = pContext->GetDocument();
   CXFA_LocaleMgr* pMgr = pDoc->GetLocaleMgr();
   CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
-  LocaleIface* pLocale = pThisNode->GetLocale();
+  GCedLocaleIface* pLocale = pThisNode->GetLocale();
   WideString wsPattern = WideString::FromUTF8(bsPattern.AsStringView());
   WideString wsValue = WideString::FromUTF8(bsValue.AsStringView());
   bool bPatternIsString;
@@ -3875,7 +3875,7 @@
   CXFA_Document* pDoc = pContext->GetDocument();
   CXFA_LocaleMgr* pMgr = pDoc->GetLocaleMgr();
   CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
-  LocaleIface* pLocale = pThisNode->GetLocale();
+  GCedLocaleIface* pLocale = pThisNode->GetLocale();
   WideString wsPattern = WideString::FromUTF8(bsPattern.AsStringView());
   WideString wsValue = WideString::FromUTF8(bsValue.AsStringView());
   bool bPatternIsString;
diff --git a/xfa/fxfa/parser/BUILD.gn b/xfa/fxfa/parser/BUILD.gn
index ce9a045..c2153a6 100644
--- a/xfa/fxfa/parser/BUILD.gn
+++ b/xfa/fxfa/parser/BUILD.gn
@@ -668,6 +668,7 @@
     "cxfa_xsl.h",
     "cxfa_zpl.cpp",
     "cxfa_zpl.h",
+    "gced_locale_iface.h",
     "xfa_basic_data.cpp",
     "xfa_basic_data.h",
     "xfa_document_datamerger_imp.cpp",
diff --git a/xfa/fxfa/parser/cxfa_localemgr.cpp b/xfa/fxfa/parser/cxfa_localemgr.cpp
index 6975bc6..e1b7b5c 100644
--- a/xfa/fxfa/parser/cxfa_localemgr.cpp
+++ b/xfa/fxfa/parser/cxfa_localemgr.cpp
@@ -1146,9 +1146,10 @@
 void CXFA_LocaleMgr::Trace(cppgc::Visitor* visitor) const {
   ContainerTrace(visitor, m_LocaleArray);
   ContainerTrace(visitor, m_XMLLocaleArray);
+  visitor->Trace(m_pDefLocale);
 }
 
-LocaleIface* CXFA_LocaleMgr::GetDefLocale() {
+GCedLocaleIface* CXFA_LocaleMgr::GetDefLocale() {
   if (m_pDefLocale)
     return m_pDefLocale;
 
@@ -1202,9 +1203,10 @@
   }
 }
 
-LocaleIface* CXFA_LocaleMgr::GetLocaleByName(const WideString& wsLocaleName) {
+GCedLocaleIface* CXFA_LocaleMgr::GetLocaleByName(
+    const WideString& wsLocaleName) {
   for (size_t i = 0; i < m_LocaleArray.size(); i++) {
-    LocaleIface* pLocale = m_LocaleArray[i];
+    GCedLocaleIface* pLocale = m_LocaleArray[i];
     if (pLocale->GetName() == wsLocaleName)
       return pLocale;
   }
@@ -1212,7 +1214,7 @@
     return nullptr;
 
   for (size_t i = 0; i < m_XMLLocaleArray.size(); i++) {
-    LocaleIface* pLocale = m_XMLLocaleArray[i];
+    GCedLocaleIface* pLocale = m_XMLLocaleArray[i];
     if (pLocale->GetName() == wsLocaleName)
       return pLocale;
   }
@@ -1225,7 +1227,7 @@
   return pLocale;
 }
 
-void CXFA_LocaleMgr::SetDefLocale(LocaleIface* pLocale) {
+void CXFA_LocaleMgr::SetDefLocale(GCedLocaleIface* pLocale) {
   m_pDefLocale = pLocale;
 }
 
diff --git a/xfa/fxfa/parser/cxfa_localemgr.h b/xfa/fxfa/parser/cxfa_localemgr.h
index 12455b1..8cb6f04 100644
--- a/xfa/fxfa/parser/cxfa_localemgr.h
+++ b/xfa/fxfa/parser/cxfa_localemgr.h
@@ -16,11 +16,11 @@
 #include "v8/include/cppgc/garbage-collected.h"
 #include "v8/include/cppgc/member.h"
 #include "xfa/fgas/crt/locale_mgr_iface.h"
+#include "xfa/fxfa/parser/gced_locale_iface.h"
 
 class CXFA_Node;
 class CXFA_NodeLocale;
 class CXFA_XMLLocale;
-class LocaleIface;
 
 class CXFA_LocaleMgr : public cppgc::GarbageCollected<CXFA_LocaleMgr>,
                        public LocaleMgrIface {
@@ -30,10 +30,10 @@
 
   void Trace(cppgc::Visitor* visitor) const;
 
-  LocaleIface* GetDefLocale() override;
-  LocaleIface* GetLocaleByName(const WideString& wsLocaleName) override;
+  GCedLocaleIface* GetDefLocale() override;
+  GCedLocaleIface* GetLocaleByName(const WideString& wsLocaleName) override;
 
-  void SetDefLocale(LocaleIface* pLocale);
+  void SetDefLocale(GCedLocaleIface* pLocale);
   WideString GetConfigLocaleName(CXFA_Node* pConfig);
 
  private:
@@ -47,9 +47,7 @@
   UnownedPtr<cppgc::Heap> m_pHeap;
   std::vector<cppgc::Member<CXFA_NodeLocale>> m_LocaleArray;
   std::vector<cppgc::Member<CXFA_XMLLocale>> m_XMLLocaleArray;
-
-  // Raw, owned by m_LocaleArray or m_XMLLocaleArray, may be GC'd after them.
-  LocaleIface* m_pDefLocale = nullptr;
+  cppgc::Member<GCedLocaleIface> m_pDefLocale;
 
   WideString m_wsConfigLocale;
   uint16_t m_dwDeflcid;
diff --git a/xfa/fxfa/parser/cxfa_localevalue.cpp b/xfa/fxfa/parser/cxfa_localevalue.cpp
index 5049b09..15bbdbc 100644
--- a/xfa/fxfa/parser/cxfa_localevalue.cpp
+++ b/xfa/fxfa/parser/cxfa_localevalue.cpp
@@ -68,7 +68,7 @@
   CPPGC_STACK_ALLOCATED();  // Raw/Unowned pointers allowed.
 
  public:
-  ScopedLocale(CXFA_LocaleMgr* pLocaleMgr, LocaleIface* pNewLocale)
+  ScopedLocale(CXFA_LocaleMgr* pLocaleMgr, GCedLocaleIface* pNewLocale)
       : m_pLocaleMgr(pLocaleMgr),
         m_pNewLocale(pNewLocale),
         m_pOrigLocale(pNewLocale ? m_pLocaleMgr->GetDefLocale() : nullptr) {
@@ -86,8 +86,8 @@
 
  private:
   UnownedPtr<CXFA_LocaleMgr> const m_pLocaleMgr;
-  LocaleIface* const m_pNewLocale;
-  LocaleIface* const m_pOrigLocale;
+  GCedLocaleIface* const m_pNewLocale;
+  GCedLocaleIface* const m_pOrigLocale;
 };
 
 }  // namespace
@@ -110,7 +110,7 @@
 CXFA_LocaleValue::CXFA_LocaleValue(uint32_t dwType,
                                    const WideString& wsValue,
                                    const WideString& wsFormat,
-                                   LocaleIface* pLocale,
+                                   GCedLocaleIface* pLocale,
                                    CXFA_LocaleMgr* pLocaleMgr)
     : m_pLocaleMgr(pLocaleMgr),
       m_dwType(dwType),
@@ -125,7 +125,7 @@
 
 bool CXFA_LocaleValue::ValidateValue(const WideString& wsValue,
                                      const WideString& wsPattern,
-                                     LocaleIface* pLocale,
+                                     GCedLocaleIface* pLocale,
                                      WideString* pMatchFormat) {
   if (!m_pLocaleMgr)
     return false;
@@ -268,7 +268,7 @@
 
 bool CXFA_LocaleValue::FormatPatterns(WideString& wsResult,
                                       const WideString& wsFormat,
-                                      LocaleIface* pLocale,
+                                      GCedLocaleIface* pLocale,
                                       XFA_VALUEPICTURE eValueType) const {
   wsResult.clear();
   for (const auto& pattern : CFGAS_StringFormatter::SplitOnBars(wsFormat)) {
@@ -280,7 +280,7 @@
 
 bool CXFA_LocaleValue::FormatSinglePattern(WideString& wsResult,
                                            const WideString& wsFormat,
-                                           LocaleIface* pLocale,
+                                           GCedLocaleIface* pLocale,
                                            XFA_VALUEPICTURE eValueType) const {
   if (!m_pLocaleMgr)
     return false;
@@ -556,7 +556,7 @@
 
 bool CXFA_LocaleValue::ParsePatternValue(const WideString& wsValue,
                                          const WideString& wsPattern,
-                                         LocaleIface* pLocale) {
+                                         GCedLocaleIface* pLocale) {
   if (!m_pLocaleMgr)
     return false;
 
@@ -673,7 +673,7 @@
 
 bool CXFA_LocaleValue::ValidateNumericTemp(const WideString& wsNumeric,
                                            const WideString& wsFormat,
-                                           LocaleIface* pLocale) {
+                                           GCedLocaleIface* pLocale) {
   if (wsFormat.IsEmpty() || wsNumeric.IsEmpty())
     return true;
 
diff --git a/xfa/fxfa/parser/cxfa_localevalue.h b/xfa/fxfa/parser/cxfa_localevalue.h
index cb154ef..437a3c6 100644
--- a/xfa/fxfa/parser/cxfa_localevalue.h
+++ b/xfa/fxfa/parser/cxfa_localevalue.h
@@ -13,9 +13,9 @@
 #include "v8/include/cppgc/macros.h"
 #include "xfa/fxfa/parser/cxfa_node.h"
 
-class LocaleIface;
 class CFX_DateTime;
 class CXFA_LocaleMgr;
+class GCedLocaleIface;
 
 #define XFA_VT_NULL 0
 #define XFA_VT_BOOLEAN 1
@@ -39,7 +39,7 @@
   CXFA_LocaleValue(uint32_t dwType,
                    const WideString& wsValue,
                    const WideString& wsFormat,
-                   LocaleIface* pLocale,
+                   GCedLocaleIface* pLocale,
                    CXFA_LocaleMgr* pLocaleMgr);
   CXFA_LocaleValue(const CXFA_LocaleValue& that);
   ~CXFA_LocaleValue();
@@ -48,18 +48,18 @@
 
   bool ValidateValue(const WideString& wsValue,
                      const WideString& wsPattern,
-                     LocaleIface* pLocale,
+                     GCedLocaleIface* pLocale,
                      WideString* pMatchFormat);
 
   bool FormatPatterns(WideString& wsResult,
                       const WideString& wsFormat,
-                      LocaleIface* pLocale,
+                      GCedLocaleIface* pLocale,
                       XFA_VALUEPICTURE eValueType) const;
 
   void GetNumericFormat(WideString& wsFormat, int32_t nIntLen, int32_t nDecLen);
   bool ValidateNumericTemp(const WideString& wsNumeric,
                            const WideString& wsFormat,
-                           LocaleIface* pLocale);
+                           GCedLocaleIface* pLocale);
 
   bool IsValid() const { return m_bValid; }
   const WideString& GetValue() const { return m_wsValue; }
@@ -72,7 +72,7 @@
  private:
   bool FormatSinglePattern(WideString& wsResult,
                            const WideString& wsFormat,
-                           LocaleIface* pLocale,
+                           GCedLocaleIface* pLocale,
                            XFA_VALUEPICTURE eValueType) const;
   bool ValidateCanonicalValue(const WideString& wsValue, uint32_t dwVType);
   bool ValidateCanonicalDate(const WideString& wsDate, CFX_DateTime* unDate);
@@ -83,7 +83,7 @@
 
   bool ParsePatternValue(const WideString& wsValue,
                          const WideString& wsPattern,
-                         LocaleIface* pLocale);
+                         GCedLocaleIface* pLocale);
 
   UnownedPtr<CXFA_LocaleMgr> m_pLocaleMgr;
   WideString m_wsValue;
diff --git a/xfa/fxfa/parser/cxfa_node.cpp b/xfa/fxfa/parser/cxfa_node.cpp
index 5ef4e5a..55dc84a 100644
--- a/xfa/fxfa/parser/cxfa_node.cpp
+++ b/xfa/fxfa/parser/cxfa_node.cpp
@@ -1391,7 +1391,7 @@
   return pParentOfValueNode ? pParentOfValueNode->GetContainerNode() : nullptr;
 }
 
-LocaleIface* CXFA_Node::GetLocale() {
+GCedLocaleIface* CXFA_Node::GetLocale() {
   Optional<WideString> localeName = GetLocaleName();
   if (!localeName.has_value())
     return nullptr;
@@ -2527,7 +2527,7 @@
   if (wsRawValue.IsEmpty())
     return XFA_EventError::kError;
 
-  LocaleIface* pLocale = GetLocale();
+  GCedLocaleIface* pLocale = GetLocale();
   if (!pLocale)
     return XFA_EventError::kNotExist;
 
@@ -4675,7 +4675,7 @@
   XFA_Element eType = pNode->GetElementType();
   if (!wsPicture.IsEmpty()) {
     CXFA_LocaleMgr* pLocaleMgr = GetDocument()->GetLocaleMgr();
-    LocaleIface* pLocale = GetLocale();
+    GCedLocaleIface* pLocale = GetLocale();
     CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(this);
     bValidate =
         widgetValue.ValidateValue(wsValue, wsPicture, pLocale, &wsPicture);
@@ -4824,7 +4824,8 @@
   if (wsPicture.IsEmpty())
     return wsValue;
 
-  if (LocaleIface* pLocale = GetLocale()) {
+  GCedLocaleIface* pLocale = GetLocale();
+  if (pLocale) {
     CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(this);
     CXFA_LocaleMgr* pLocaleMgr = GetDocument()->GetLocaleMgr();
     switch (widgetValue.GetType()) {
@@ -4863,7 +4864,7 @@
     return wsValue;
 
   CXFA_LocaleMgr* pLocaleMgr = GetDocument()->GetLocaleMgr();
-  LocaleIface* pLocale = GetLocale();
+  GCedLocaleIface* pLocale = GetLocale();
   CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(this);
   if (widgetValue.ValidateValue(wsValue, wsPicture, pLocale, &wsPicture)) {
     widgetValue = CXFA_LocaleValue(widgetValue.GetType(), wsValue, wsPicture,
@@ -4882,7 +4883,8 @@
     return wsValue;
 
   WideString wsFormattedValue = wsValue;
-  if (LocaleIface* pLocale = GetLocale()) {
+  GCedLocaleIface* pLocale = GetLocale();
+  if (pLocale) {
     CXFA_Value* pNodeValue = GetChild<CXFA_Value>(0, XFA_Element::Value, false);
     if (!pNodeValue)
       return wsValue;
diff --git a/xfa/fxfa/parser/cxfa_node.h b/xfa/fxfa/parser/cxfa_node.h
index 024e988..eeb6e31 100644
--- a/xfa/fxfa/parser/cxfa_node.h
+++ b/xfa/fxfa/parser/cxfa_node.h
@@ -45,7 +45,7 @@
 class CXFA_Validate;
 class CXFA_Value;
 class CXFA_WidgetLayoutData;
-class LocaleIface;
+class GCedLocaleIface;
 
 #define XFA_NODEFILTER_Children 0x01
 #define XFA_NODEFILTER_Properties 0x02
@@ -198,7 +198,7 @@
   bool RemoveBindItem(CXFA_Node* pFormNode);
   bool HasBindItem() const;
   CXFA_Node* GetContainerNode();
-  LocaleIface* GetLocale();
+  GCedLocaleIface* GetLocale();
   Optional<WideString> GetLocaleName();
   XFA_AttributeValue GetIntact();
   WideString GetNameExpression();
diff --git a/xfa/fxfa/parser/cxfa_nodelocale.h b/xfa/fxfa/parser/cxfa_nodelocale.h
index 8ad9222..f6fdac9 100644
--- a/xfa/fxfa/parser/cxfa_nodelocale.h
+++ b/xfa/fxfa/parser/cxfa_nodelocale.h
@@ -10,22 +10,20 @@
 #include "fxjs/gc/heap.h"
 #include "v8/include/cppgc/garbage-collected.h"
 #include "v8/include/cppgc/member.h"
-#include "xfa/fgas/crt/locale_iface.h"
 #include "xfa/fxfa/fxfa_basic.h"
+#include "xfa/fxfa/parser/gced_locale_iface.h"
 
 class CXFA_Node;
 
 WideString XFA_PatternToString(LocaleIface::NumSubcategory category);
 
-class CXFA_NodeLocale final : public cppgc::GarbageCollected<CXFA_NodeLocale>,
-                              public LocaleIface {
+class CXFA_NodeLocale final : public GCedLocaleIface {
  public:
   CONSTRUCT_VIA_MAKE_GARBAGE_COLLECTED;
   ~CXFA_NodeLocale() override;
 
-  void Trace(cppgc::Visitor* visitor) const;
-
-  // LocaleIface
+  // GCedLocaleIface:
+  void Trace(cppgc::Visitor* visitor) const override;
   WideString GetName() const override;
   WideString GetDecimalSymbol() const override;
   WideString GetGroupingSymbol() const override;
diff --git a/xfa/fxfa/parser/cxfa_xmllocale.h b/xfa/fxfa/parser/cxfa_xmllocale.h
index 1fc2a98..c693cbd 100644
--- a/xfa/fxfa/parser/cxfa_xmllocale.h
+++ b/xfa/fxfa/parser/cxfa_xmllocale.h
@@ -13,13 +13,12 @@
 #include "fxjs/gc/heap.h"
 #include "third_party/base/span.h"
 #include "v8/include/cppgc/garbage-collected.h"
-#include "xfa/fgas/crt/locale_iface.h"
+#include "xfa/fxfa/parser/gced_locale_iface.h"
 
 class CFX_XMLDocument;
 class CFX_XMLElement;
 
-class CXFA_XMLLocale final : public cppgc::GarbageCollected<CXFA_XMLLocale>,
-                             public LocaleIface {
+class CXFA_XMLLocale final : public GCedLocaleIface {
  public:
   // Object is created on cppgc heap.
   static CXFA_XMLLocale* Create(cppgc::Heap* heap, pdfium::span<uint8_t> data);
@@ -27,9 +26,8 @@
   CONSTRUCT_VIA_MAKE_GARBAGE_COLLECTED;
   ~CXFA_XMLLocale() override;
 
-  void Trace(cppgc::Visitor* visitor) const;
-
-  // LocaleIface
+  // GCedLocaleIface:
+  void Trace(cppgc::Visitor* visitor) const override;
   WideString GetName() const override;
   WideString GetDecimalSymbol() const override;
   WideString GetGroupingSymbol() const override;
diff --git a/xfa/fxfa/parser/gced_locale_iface.h b/xfa/fxfa/parser/gced_locale_iface.h
new file mode 100644
index 0000000..2d88deb
--- /dev/null
+++ b/xfa/fxfa/parser/gced_locale_iface.h
@@ -0,0 +1,19 @@
+// 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef XFA_FXFA_PARSER_GCED_LOCALE_IFACE_H_
+#define XFA_FXFA_PARSER_GCED_LOCALE_IFACE_H_
+
+#include "v8/include/cppgc/garbage-collected.h"
+#include "xfa/fgas/crt/locale_iface.h"
+
+class GCedLocaleIface : public cppgc::GarbageCollected<GCedLocaleIface>,
+                        public LocaleIface {
+ public:
+  virtual void Trace(cppgc::Visitor* visitor) const = 0;
+};
+
+#endif  // XFA_FXFA_PARSER_GCED_LOCALE_IFACE_H_