Add CPDSDK_Annot::AsBAAnnot() checked downcast method

XFA introduces some additional subclasses, so it doesn't hurt
to be sure in all cases before making a static cast.

Change-Id: I7447ca58be0b57201b39ba40a3fc5f47505cee58
Reviewed-on: https://pdfium-review.googlesource.com/39013
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/fpdfsdk/cpdfsdk_annot.cpp b/fpdfsdk/cpdfsdk_annot.cpp
index cfd87b3..75967a3 100644
--- a/fpdfsdk/cpdfsdk_annot.cpp
+++ b/fpdfsdk/cpdfsdk_annot.cpp
@@ -27,6 +27,10 @@
 
 CPDFSDK_Annot::~CPDFSDK_Annot() {}
 
+CPDFSDK_BAAnnot* CPDFSDK_Annot::AsBAAnnot() {
+  return nullptr;
+}
+
 #ifdef PDF_ENABLE_XFA
 
 bool CPDFSDK_Annot::IsXFAField() {
diff --git a/fpdfsdk/cpdfsdk_annot.h b/fpdfsdk/cpdfsdk_annot.h
index 459c6d0..708a223 100644
--- a/fpdfsdk/cpdfsdk_annot.h
+++ b/fpdfsdk/cpdfsdk_annot.h
@@ -20,6 +20,7 @@
 class CFX_RenderDevice;
 class CPDF_Page;
 class CPDF_RenderOptions;
+class CPDFSDK_BAAnnot;
 class CPDFSDK_PageView;
 
 #ifdef PDF_ENABLE_XFA
@@ -31,6 +32,8 @@
   explicit CPDFSDK_Annot(CPDFSDK_PageView* pPageView);
   virtual ~CPDFSDK_Annot();
 
+  virtual CPDFSDK_BAAnnot* AsBAAnnot();
+
 #ifdef PDF_ENABLE_XFA
   virtual bool IsXFAField();
   virtual CXFA_FFWidget* GetXFAWidget() const;
@@ -57,4 +60,8 @@
   UnownedPtr<CPDFSDK_PageView> const m_pPageView;
 };
 
+inline CPDFSDK_BAAnnot* ToBAAnnot(CPDFSDK_Annot* pAnnot) {
+  return pAnnot ? pAnnot->AsBAAnnot() : nullptr;
+}
+
 #endif  // FPDFSDK_CPDFSDK_ANNOT_H_
diff --git a/fpdfsdk/cpdfsdk_baannot.cpp b/fpdfsdk/cpdfsdk_baannot.cpp
index f9d1f62..6f5e3f9 100644
--- a/fpdfsdk/cpdfsdk_baannot.cpp
+++ b/fpdfsdk/cpdfsdk_baannot.cpp
@@ -26,6 +26,10 @@
 
 CPDFSDK_BAAnnot::~CPDFSDK_BAAnnot() {}
 
+CPDFSDK_BAAnnot* CPDFSDK_BAAnnot::AsBAAnnot() {
+  return this;
+}
+
 CPDF_Annot* CPDFSDK_BAAnnot::GetPDFAnnot() const {
   return m_pAnnot.Get();
 }
diff --git a/fpdfsdk/cpdfsdk_baannot.h b/fpdfsdk/cpdfsdk_baannot.h
index f2fdd30..778f757 100644
--- a/fpdfsdk/cpdfsdk_baannot.h
+++ b/fpdfsdk/cpdfsdk_baannot.h
@@ -28,6 +28,7 @@
   ~CPDFSDK_BAAnnot() override;
 
   // CPDFSDK_Annot
+  CPDFSDK_BAAnnot* AsBAAnnot() override;
   CPDF_Annot::Subtype GetAnnotSubtype() const override;
   void SetRect(const CFX_FloatRect& rect) override;
   CFX_FloatRect GetRect() const override;
diff --git a/fpdfsdk/cpdfsdk_baannothandler.cpp b/fpdfsdk/cpdfsdk_baannothandler.cpp
index ab46a96..a5969c9 100644
--- a/fpdfsdk/cpdfsdk_baannothandler.cpp
+++ b/fpdfsdk/cpdfsdk_baannothandler.cpp
@@ -72,15 +72,15 @@
     return;
 #endif  // PDF_ENABLE_XFA
   if (bDrawAnnots && pAnnot->GetAnnotSubtype() == CPDF_Annot::Subtype::POPUP) {
-    static_cast<CPDFSDK_BAAnnot*>(pAnnot)->DrawAppearance(
-        pDevice, *pUser2Device, CPDF_Annot::Normal, nullptr);
+    pAnnot->AsBAAnnot()->DrawAppearance(pDevice, *pUser2Device,
+                                        CPDF_Annot::Normal, nullptr);
   }
 }
 
 void CPDFSDK_BAAnnotHandler::OnMouseEnter(CPDFSDK_PageView* pPageView,
                                           CPDFSDK_Annot::ObservedPtr* pAnnot,
                                           uint32_t nFlag) {
-  CPDFSDK_BAAnnot* pBAAnnot = static_cast<CPDFSDK_BAAnnot*>(pAnnot->Get());
+  CPDFSDK_BAAnnot* pBAAnnot = (*pAnnot)->AsBAAnnot();
   pBAAnnot->SetOpenState(true);
   UpdateAnnotRects(pPageView, pBAAnnot);
 }
@@ -88,7 +88,7 @@
 void CPDFSDK_BAAnnotHandler::OnMouseExit(CPDFSDK_PageView* pPageView,
                                          CPDFSDK_Annot::ObservedPtr* pAnnot,
                                          uint32_t nFlag) {
-  CPDFSDK_BAAnnot* pBAAnnot = static_cast<CPDFSDK_BAAnnot*>(pAnnot->Get());
+  CPDFSDK_BAAnnot* pBAAnnot = (*pAnnot)->AsBAAnnot();
   pBAAnnot->SetOpenState(false);
   UpdateAnnotRects(pPageView, pBAAnnot);
 }
diff --git a/fpdfsdk/cpdfsdk_widgethandler.cpp b/fpdfsdk/cpdfsdk_widgethandler.cpp
index 22f5d39..7cfe74f 100644
--- a/fpdfsdk/cpdfsdk_widgethandler.cpp
+++ b/fpdfsdk/cpdfsdk_widgethandler.cpp
@@ -92,8 +92,8 @@
                                    CFX_Matrix* pUser2Device,
                                    bool bDrawAnnots) {
   if (pAnnot->IsSignatureWidget()) {
-    static_cast<CPDFSDK_BAAnnot*>(pAnnot)->DrawAppearance(
-        pDevice, *pUser2Device, CPDF_Annot::Normal, nullptr);
+    pAnnot->AsBAAnnot()->DrawAppearance(pDevice, *pUser2Device,
+                                        CPDF_Annot::Normal, nullptr);
   } else {
     if (m_pFormFiller)
       m_pFormFiller->OnDraw(pPageView, pAnnot, pDevice, pUser2Device);
diff --git a/fxjs/cjs_annot.cpp b/fxjs/cjs_annot.cpp
index 49db204..c4a4f7a 100644
--- a/fxjs/cjs_annot.cpp
+++ b/fxjs/cjs_annot.cpp
@@ -11,14 +11,6 @@
 #include "fxjs/js_define.h"
 #include "fxjs/js_resources.h"
 
-namespace {
-
-CPDFSDK_BAAnnot* ToBAAnnot(CPDFSDK_Annot* annot) {
-  return static_cast<CPDFSDK_BAAnnot*>(annot);
-}
-
-}  // namespace
-
 const JSPropertySpec CJS_Annot::PropertySpecs[] = {
     {"hidden", get_hidden_static, set_hidden_static},
     {"name", get_name_static, set_name_static},
@@ -49,7 +41,7 @@
   if (!m_pAnnot)
     return CJS_Return(JSMessage::kBadObjectError);
 
-  CPDF_Annot* pPDFAnnot = ToBAAnnot(m_pAnnot.Get())->GetPDFAnnot();
+  CPDF_Annot* pPDFAnnot = m_pAnnot->AsBAAnnot()->GetPDFAnnot();
   return CJS_Return(pRuntime->NewBoolean(
       CPDF_Annot::IsAnnotationHidden(pPDFAnnot->GetAnnotDict())));
 }
@@ -58,10 +50,12 @@
                                  v8::Local<v8::Value> vp) {
   // May invalidate m_pAnnot.
   bool bHidden = pRuntime->ToBoolean(vp);
-  if (!m_pAnnot)
+
+  CPDFSDK_BAAnnot* pBAAnnot = ToBAAnnot(m_pAnnot.Get());
+  if (!pBAAnnot)
     return CJS_Return(JSMessage::kBadObjectError);
 
-  uint32_t flags = ToBAAnnot(m_pAnnot.Get())->GetFlags();
+  uint32_t flags = pBAAnnot->GetFlags();
   if (bHidden) {
     flags |= ANNOTFLAG_HIDDEN;
     flags |= ANNOTFLAG_INVISIBLE;
@@ -73,35 +67,39 @@
     flags &= ~ANNOTFLAG_NOVIEW;
     flags |= ANNOTFLAG_PRINT;
   }
-  ToBAAnnot(m_pAnnot.Get())->SetFlags(flags);
-
+  pBAAnnot->SetFlags(flags);
   return CJS_Return();
 }
 
 CJS_Return CJS_Annot::get_name(CJS_Runtime* pRuntime) {
-  if (!m_pAnnot)
+  CPDFSDK_BAAnnot* pBAAnnot = ToBAAnnot(m_pAnnot.Get());
+  if (!pBAAnnot)
     return CJS_Return(JSMessage::kBadObjectError);
-  return CJS_Return(pRuntime->NewString(
-      ToBAAnnot(m_pAnnot.Get())->GetAnnotName().AsStringView()));
+  return CJS_Return(
+      pRuntime->NewString(pBAAnnot->GetAnnotName().AsStringView()));
 }
 
 CJS_Return CJS_Annot::set_name(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
   // May invalidate m_pAnnot.
   WideString annotName = pRuntime->ToWideString(vp);
-  if (!m_pAnnot)
+
+  CPDFSDK_BAAnnot* pBAAnnot = ToBAAnnot(m_pAnnot.Get());
+  if (!pBAAnnot)
     return CJS_Return(JSMessage::kBadObjectError);
 
-  ToBAAnnot(m_pAnnot.Get())->SetAnnotName(annotName);
+  pBAAnnot->SetAnnotName(annotName);
   return CJS_Return();
 }
 
 CJS_Return CJS_Annot::get_type(CJS_Runtime* pRuntime) {
-  if (!m_pAnnot)
+  CPDFSDK_BAAnnot* pBAAnnot = ToBAAnnot(m_pAnnot.Get());
+  if (!pBAAnnot)
     return CJS_Return(JSMessage::kBadObjectError);
+
   return CJS_Return(pRuntime->NewString(
-      WideString::FromLocal(CPDF_Annot::AnnotSubtypeToString(
-                                ToBAAnnot(m_pAnnot.Get())->GetAnnotSubtype())
-                                .AsStringView())
+      WideString::FromLocal(
+          CPDF_Annot::AnnotSubtypeToString(pBAAnnot->GetAnnotSubtype())
+              .AsStringView())
           .AsStringView()));
 }
 
diff --git a/fxjs/cjs_document.cpp b/fxjs/cjs_document.cpp
index 4ac2f15..b135805 100644
--- a/fxjs/cjs_document.cpp
+++ b/fxjs/cjs_document.cpp
@@ -1003,7 +1003,7 @@
   CPDFSDK_AnnotIteration annotIteration(pPageView, false);
   CPDFSDK_BAAnnot* pSDKBAAnnot = nullptr;
   for (const auto& pSDKAnnotCur : annotIteration) {
-    auto* pBAAnnot = static_cast<CPDFSDK_BAAnnot*>(pSDKAnnotCur.Get());
+    auto* pBAAnnot = pSDKAnnotCur->AsBAAnnot();
     if (pBAAnnot && pBAAnnot->GetAnnotName() == swAnnotName) {
       pSDKBAAnnot = pBAAnnot;
       break;
@@ -1054,7 +1054,7 @@
 
       auto* pJS_Annot =
           static_cast<CJS_Annot*>(CFXJS_Engine::GetObjectPrivate(pObj));
-      pJS_Annot->SetSDKAnnot(static_cast<CPDFSDK_BAAnnot*>(pSDKAnnotCur.Get()));
+      pJS_Annot->SetSDKAnnot(pSDKAnnotCur->AsBAAnnot());
       pRuntime->PutArrayElement(
           annots, i,
           pJS_Annot ? v8::Local<v8::Value>(pJS_Annot->ToV8Object())