Handle null annot case outside of CPDFSDK_AnnotHandlerMgr.

The work done by CPDFSDK_AnnotHandlerMgr::Annot_OnKeyDown() when the
annot argument is null is better handled by the pageview itself before
calling into the CPDFSDK_AnnotHandlerMgr. This makes the annot handler
manager simpler because it doesn't have to call back into the page view
to find an annot. Instead, it performs a single purpose: dispatching
based on the kind of annot it sees.

-- Remove some stray includes.
-- Use incomplete types in .cpp where sufficient.
-- Consistent naming of NewAnnotForXFA() (vs NewXFAAnnot()).
-- Make XFAPageIfNotBackedByPDFPage() a method of the page view.
-- Remove some specific subclass information from handler mgr, and use
   the virtual interface to ensure uniformity among handler calls,
   despite introducing some notreached stubs.

Change-Id: I4d68cba6035cbb25d003fda96afe3dd91ed2b6fc
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/85190
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/fpdfsdk/cpdfsdk_annothandlermgr.cpp b/fpdfsdk/cpdfsdk_annothandlermgr.cpp
index 4fe7094..abf22c1 100644
--- a/fpdfsdk/cpdfsdk_annothandlermgr.cpp
+++ b/fpdfsdk/cpdfsdk_annothandlermgr.cpp
@@ -8,39 +8,22 @@
 
 #include <utility>
 
-#include "core/fpdfapi/parser/cpdf_number.h"
-#include "core/fpdfapi/parser/cpdf_string.h"
 #include "core/fpdfdoc/cpdf_annot.h"
 #include "fpdfsdk/cpdfsdk_annot.h"
-#include "fpdfsdk/cpdfsdk_annotiterator.h"
 #include "fpdfsdk/cpdfsdk_baannot.h"
-#include "fpdfsdk/cpdfsdk_baannothandler.h"
 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
 #include "fpdfsdk/cpdfsdk_pageview.h"
 #include "fpdfsdk/cpdfsdk_widget.h"
-#include "fpdfsdk/cpdfsdk_widgethandler.h"
-#include "fpdfsdk/pwl/cpwl_wnd.h"
-#include "public/fpdf_fwlevent.h"
+#include "fpdfsdk/ipdfsdk_annothandler.h"
 #include "third_party/base/check.h"
 
 #ifdef PDF_ENABLE_XFA
-#include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
 #include "fpdfsdk/fpdfxfa/cpdfxfa_widget.h"
-#include "fpdfsdk/fpdfxfa/cpdfxfa_widgethandler.h"
-
-namespace {
-
-CPDFXFA_Page* XFAPageIfNotBackedByPDFPage(CPDFSDK_PageView* pPageView) {
-  auto* pPage = static_cast<CPDFXFA_Page*>(pPageView->GetXFAPage());
-  return pPage && !pPage->AsPDFPage() ? pPage : nullptr;
-}
-
-}  // namespace
 #endif  // PDF_ENABLE_XFA
 
 CPDFSDK_AnnotHandlerMgr::CPDFSDK_AnnotHandlerMgr(
-    std::unique_ptr<CPDFSDK_BAAnnotHandler> pBAAnnotHandler,
-    std::unique_ptr<CPDFSDK_WidgetHandler> pWidgetHandler,
+    std::unique_ptr<IPDFSDK_AnnotHandler> pBAAnnotHandler,
+    std::unique_ptr<IPDFSDK_AnnotHandler> pWidgetHandler,
     std::unique_ptr<IPDFSDK_AnnotHandler> pXFAWidgetHandler)
     : m_pBAAnnotHandler(std::move(pBAAnnotHandler)),
       m_pWidgetHandler(std::move(pWidgetHandler)),
@@ -68,13 +51,12 @@
 }
 
 #ifdef PDF_ENABLE_XFA
-std::unique_ptr<CPDFSDK_Annot> CPDFSDK_AnnotHandlerMgr::NewXFAAnnot(
-    CXFA_FFWidget* pAnnot,
+std::unique_ptr<CPDFSDK_Annot> CPDFSDK_AnnotHandlerMgr::NewAnnotForXFA(
+    CXFA_FFWidget* pFFWidget,
     CPDFSDK_PageView* pPageView) {
-  DCHECK(pAnnot);
+  DCHECK(pFFWidget);
   DCHECK(pPageView);
-  return static_cast<CPDFXFA_WidgetHandler*>(m_pXFAWidgetHandler.get())
-      ->NewAnnotForXFA(pAnnot, pPageView);
+  return m_pXFAWidgetHandler->NewAnnotForXFA(pFFWidget, pPageView);
 }
 #endif  // PDF_ENABLE_XFA
 
@@ -248,41 +230,6 @@
                                               CPDFSDK_Annot* pAnnot,
                                               FWL_VKEYCODE nKeyCode,
                                               Mask<FWL_EVENTFLAG> nFlag) {
-  if (!pAnnot) {
-    // If pressed key is not tab then no action is needed.
-    if (nKeyCode != FWL_VKEY_Tab)
-      return false;
-
-    // If ctrl key or alt key is pressed, then no action is needed.
-    if (CPWL_Wnd::IsCTRLKeyDown(nFlag) || CPWL_Wnd::IsALTKeyDown(nFlag))
-      return false;
-
-    ObservedPtr<CPDFSDK_Annot> end_annot(
-        CPWL_Wnd::IsSHIFTKeyDown(nFlag) ? GetLastFocusableAnnot(pPageView)
-                                        : GetFirstFocusableAnnot(pPageView));
-    return end_annot && pPageView->GetFormFillEnv()->SetFocusAnnot(&end_annot);
-  }
-
-  if (CPWL_Wnd::IsCTRLKeyDown(nFlag) || CPWL_Wnd::IsALTKeyDown(nFlag)) {
-    return GetAnnotHandler(pAnnot)->OnKeyDown(pAnnot, nKeyCode, nFlag);
-  }
-  ObservedPtr<CPDFSDK_Annot> pObservedAnnot(pAnnot);
-  CPDFSDK_Annot* pFocusAnnot = pPageView->GetFocusAnnot();
-  if (pFocusAnnot && (nKeyCode == FWL_VKEY_Tab)) {
-    ObservedPtr<CPDFSDK_Annot> pNext(CPWL_Wnd::IsSHIFTKeyDown(nFlag)
-                                         ? GetPrevAnnot(pFocusAnnot)
-                                         : GetNextAnnot(pFocusAnnot));
-    if (!pNext)
-      return false;
-    if (pNext.Get() != pFocusAnnot) {
-      pPageView->GetFormFillEnv()->SetFocusAnnot(&pNext);
-      return true;
-    }
-  }
-
-  // Check |pAnnot| again because JS may have destroyed it in |GetNextAnnot|
-  if (!pObservedAnnot)
-    return false;
 
   return GetAnnotHandler(pAnnot)->OnKeyDown(pAnnot, nKeyCode, nFlag);
 }
@@ -305,6 +252,7 @@
     ObservedPtr<CPDFSDK_Annot>* pAnnot,
     int index,
     bool selected) {
+  DCHECK(pAnnot->HasObservable());
   return GetAnnotHandler(pAnnot->Get())
       ->SetIndexSelected(pAnnot, index, selected);
 }
@@ -312,6 +260,7 @@
 bool CPDFSDK_AnnotHandlerMgr::Annot_IsIndexSelected(
     ObservedPtr<CPDFSDK_Annot>* pAnnot,
     int index) {
+  DCHECK(pAnnot->HasObservable());
   return GetAnnotHandler(pAnnot->Get())->IsIndexSelected(pAnnot, index);
 }
 
@@ -324,8 +273,7 @@
   bool bXFA = (pSetXFAWidget && pSetXFAWidget->GetXFAFFWidget()) ||
               (pKillXFAWidget && pKillXFAWidget->GetXFAFFWidget());
 
-  return !bXFA || static_cast<CPDFXFA_WidgetHandler*>(m_pXFAWidgetHandler.get())
-                      ->OnXFAChangedFocus(pKillAnnot, pSetAnnot);
+  return !bXFA || m_pXFAWidgetHandler->OnXFAChangedFocus(pKillAnnot, pSetAnnot);
 }
 #endif  // PDF_ENABLE_XFA
 
@@ -346,53 +294,3 @@
 
   return false;
 }
-
-CPDFSDK_Annot* CPDFSDK_AnnotHandlerMgr::GetNextAnnot(
-    CPDFSDK_Annot* pSDKAnnot) const {
-  CPDFSDK_PageView* pPageView = pSDKAnnot->GetPageView();
-#ifdef PDF_ENABLE_XFA
-  CPDFXFA_Page* pXFAPage = XFAPageIfNotBackedByPDFPage(pPageView);
-  if (pXFAPage)
-    return pXFAPage->GetNextXFAAnnot(pSDKAnnot);
-#endif  // PDF_ENABLE_XFA
-  CPDFSDK_AnnotIterator ai(
-      pPageView, pPageView->GetFormFillEnv()->GetFocusableAnnotSubtypes());
-  return ai.GetNextAnnot(pSDKAnnot);
-}
-
-CPDFSDK_Annot* CPDFSDK_AnnotHandlerMgr::GetPrevAnnot(
-    CPDFSDK_Annot* pSDKAnnot) const {
-  CPDFSDK_PageView* pPageView = pSDKAnnot->GetPageView();
-#ifdef PDF_ENABLE_XFA
-  CPDFXFA_Page* pXFAPage = XFAPageIfNotBackedByPDFPage(pPageView);
-  if (pXFAPage)
-    return pXFAPage->GetPrevXFAAnnot(pSDKAnnot);
-#endif  // PDF_ENABLE_XFA
-  CPDFSDK_AnnotIterator ai(
-      pPageView, pPageView->GetFormFillEnv()->GetFocusableAnnotSubtypes());
-  return ai.GetPrevAnnot(pSDKAnnot);
-}
-
-CPDFSDK_Annot* CPDFSDK_AnnotHandlerMgr::GetFirstFocusableAnnot(
-    CPDFSDK_PageView* page_view) const {
-#ifdef PDF_ENABLE_XFA
-  CPDFXFA_Page* pXFAPage = XFAPageIfNotBackedByPDFPage(page_view);
-  if (pXFAPage)
-    return pXFAPage->GetFirstXFAAnnot(page_view);
-#endif  // PDF_ENABLE_XFA
-  CPDFSDK_AnnotIterator ai(
-      page_view, page_view->GetFormFillEnv()->GetFocusableAnnotSubtypes());
-  return ai.GetFirstAnnot();
-}
-
-CPDFSDK_Annot* CPDFSDK_AnnotHandlerMgr::GetLastFocusableAnnot(
-    CPDFSDK_PageView* page_view) const {
-#ifdef PDF_ENABLE_XFA
-  CPDFXFA_Page* pXFAPage = XFAPageIfNotBackedByPDFPage(page_view);
-  if (pXFAPage)
-    return pXFAPage->GetLastXFAAnnot(page_view);
-#endif  // PDF_ENABLE_XFA
-  CPDFSDK_AnnotIterator ai(
-      page_view, page_view->GetFormFillEnv()->GetFocusableAnnotSubtypes());
-  return ai.GetLastAnnot();
-}
diff --git a/fpdfsdk/cpdfsdk_annothandlermgr.h b/fpdfsdk/cpdfsdk_annothandlermgr.h
index 3abcd97..2e8d1ce 100644
--- a/fpdfsdk/cpdfsdk_annothandlermgr.h
+++ b/fpdfsdk/cpdfsdk_annothandlermgr.h
@@ -13,14 +13,11 @@
 #include "core/fxcrt/fx_coordinates.h"
 #include "core/fxcrt/mask.h"
 #include "fpdfsdk/cpdfsdk_annot.h"
-#include "fpdfsdk/pwl/cpwl_wnd.h"
 #include "public/fpdf_fwlevent.h"
 
 class CFX_Matrix;
 class CFX_RenderDevice;
 class CPDFSDK_FormFillEnvironment;
-class CPDFSDK_BAAnnotHandler;
-class CPDFSDK_WidgetHandler;
 class CPDFSDK_PageView;
 class IPDFSDK_AnnotHandler;
 
@@ -31,8 +28,8 @@
 class CPDFSDK_AnnotHandlerMgr {
  public:
   CPDFSDK_AnnotHandlerMgr(
-      std::unique_ptr<CPDFSDK_BAAnnotHandler> pBAAnnotHandler,
-      std::unique_ptr<CPDFSDK_WidgetHandler> pWidgetHandler,
+      std::unique_ptr<IPDFSDK_AnnotHandler> pBAAnnotHandler,
+      std::unique_ptr<IPDFSDK_AnnotHandler> pWidgetHandler,
       std::unique_ptr<IPDFSDK_AnnotHandler> pXFAWidgetHandler);
 
   ~CPDFSDK_AnnotHandlerMgr();
@@ -42,8 +39,8 @@
   std::unique_ptr<CPDFSDK_Annot> NewAnnot(CPDF_Annot* pAnnot,
                                           CPDFSDK_PageView* pPageView);
 #ifdef PDF_ENABLE_XFA
-  std::unique_ptr<CPDFSDK_Annot> NewXFAAnnot(CXFA_FFWidget* pAnnot,
-                                             CPDFSDK_PageView* pPageView);
+  std::unique_ptr<CPDFSDK_Annot> NewAnnotForXFA(CXFA_FFWidget* pFFWidget,
+                                                CPDFSDK_PageView* pPageView);
 #endif  // PDF_ENABLE_XFA
   void ReleaseAnnot(std::unique_ptr<CPDFSDK_Annot> pAnnot);
 
@@ -133,15 +130,11 @@
   IPDFSDK_AnnotHandler* GetAnnotHandler(CPDFSDK_Annot* pAnnot) const;
   IPDFSDK_AnnotHandler* GetAnnotHandlerOfType(
       CPDF_Annot::Subtype nAnnotSubtype) const;
-  CPDFSDK_Annot* GetNextAnnot(CPDFSDK_Annot* pSDKAnnot) const;
-  CPDFSDK_Annot* GetPrevAnnot(CPDFSDK_Annot* pSDKAnnot) const;
-  CPDFSDK_Annot* GetFirstFocusableAnnot(CPDFSDK_PageView* page_view) const;
-  CPDFSDK_Annot* GetLastFocusableAnnot(CPDFSDK_PageView* page_view) const;
 
   // |m_pBAAnnotHandler| and |m_pWidgetHandler| are always present, but
   // |m_pXFAWidgetHandler| is only present in XFA mode.
-  std::unique_ptr<CPDFSDK_BAAnnotHandler> const m_pBAAnnotHandler;
-  std::unique_ptr<CPDFSDK_WidgetHandler> const m_pWidgetHandler;
+  std::unique_ptr<IPDFSDK_AnnotHandler> const m_pBAAnnotHandler;
+  std::unique_ptr<IPDFSDK_AnnotHandler> const m_pWidgetHandler;
   std::unique_ptr<IPDFSDK_AnnotHandler> const m_pXFAWidgetHandler;
 };
 
diff --git a/fpdfsdk/cpdfsdk_baannothandler_embeddertest.cpp b/fpdfsdk/cpdfsdk_baannothandler_embeddertest.cpp
index feb2ebb..9beb114 100644
--- a/fpdfsdk/cpdfsdk_baannothandler_embeddertest.cpp
+++ b/fpdfsdk/cpdfsdk_baannothandler_embeddertest.cpp
@@ -40,7 +40,8 @@
     CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
         m_pFormFillEnv->GetAnnotHandlerMgr();
     ASSERT_TRUE(pAnnotHandlerMgr);
-    m_pBAAnnotHandler = pAnnotHandlerMgr->m_pBAAnnotHandler.get();
+    m_pBAAnnotHandler = static_cast<CPDFSDK_BAAnnotHandler*>(
+        pAnnotHandlerMgr->m_pBAAnnotHandler.get());
     ASSERT_TRUE(m_pBAAnnotHandler);
   }
 
diff --git a/fpdfsdk/cpdfsdk_pageview.cpp b/fpdfsdk/cpdfsdk_pageview.cpp
index 035d7d1..da3500e 100644
--- a/fpdfsdk/cpdfsdk_pageview.cpp
+++ b/fpdfsdk/cpdfsdk_pageview.cpp
@@ -17,6 +17,7 @@
 #include "core/fxcrt/autorestorer.h"
 #include "fpdfsdk/cpdfsdk_annot.h"
 #include "fpdfsdk/cpdfsdk_annotiteration.h"
+#include "fpdfsdk/cpdfsdk_annotiterator.h"
 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
 #include "fpdfsdk/cpdfsdk_helpers.h"
 #include "fpdfsdk/cpdfsdk_interactiveform.h"
@@ -27,7 +28,6 @@
 #ifdef PDF_ENABLE_XFA
 #include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
 #include "fpdfsdk/fpdfxfa/cpdfxfa_widget.h"
-#include "xfa/fxfa/cxfa_ffdocview.h"
 #include "xfa/fxfa/cxfa_ffpageview.h"
 #endif  // PDF_ENABLE_XFA
 
@@ -128,7 +128,7 @@
 
   CPDFSDK_AnnotHandlerMgr* pAnnotHandler = m_pFormFillEnv->GetAnnotHandlerMgr();
   std::unique_ptr<CPDFSDK_Annot> pNewAnnot =
-      pAnnotHandler->NewXFAAnnot(pPDFAnnot, this);
+      pAnnotHandler->NewAnnotForXFA(pPDFAnnot, this);
   DCHECK(pNewAnnot);
   pSDKAnnot = pNewAnnot.get();
   // TODO(thestig): See if |m_SDKAnnotArray|, which takes ownership of
@@ -165,6 +165,11 @@
 
   return true;
 }
+
+CPDFXFA_Page* CPDFSDK_PageView::XFAPageIfNotBackedByPDFPage() {
+  auto* pPage = static_cast<CPDFXFA_Page*>(GetXFAPage());
+  return pPage && !pPage->AsPDFPage() ? pPage : nullptr;
+}
 #endif  // PDF_ENABLE_XFA
 
 CPDF_Document* CPDFSDK_PageView::GetPDFDocument() {
@@ -216,6 +221,46 @@
   return WideString();
 }
 
+CPDFSDK_Annot* CPDFSDK_PageView::GetNextAnnot(CPDFSDK_Annot* pAnnot) {
+#ifdef PDF_ENABLE_XFA
+  CPDFXFA_Page* pXFAPage = XFAPageIfNotBackedByPDFPage();
+  if (pXFAPage)
+    return pXFAPage->GetNextXFAAnnot(pAnnot);
+#endif  // PDF_ENABLE_XFA
+  CPDFSDK_AnnotIterator ai(this, GetFormFillEnv()->GetFocusableAnnotSubtypes());
+  return ai.GetNextAnnot(pAnnot);
+}
+
+CPDFSDK_Annot* CPDFSDK_PageView::GetPrevAnnot(CPDFSDK_Annot* pAnnot) {
+#ifdef PDF_ENABLE_XFA
+  CPDFXFA_Page* pXFAPage = XFAPageIfNotBackedByPDFPage();
+  if (pXFAPage)
+    return pXFAPage->GetPrevXFAAnnot(pAnnot);
+#endif  // PDF_ENABLE_XFA
+  CPDFSDK_AnnotIterator ai(this, GetFormFillEnv()->GetFocusableAnnotSubtypes());
+  return ai.GetPrevAnnot(pAnnot);
+}
+
+CPDFSDK_Annot* CPDFSDK_PageView::GetFirstFocusableAnnot() {
+#ifdef PDF_ENABLE_XFA
+  CPDFXFA_Page* pXFAPage = XFAPageIfNotBackedByPDFPage();
+  if (pXFAPage)
+    return pXFAPage->GetFirstXFAAnnot(this);
+#endif  // PDF_ENABLE_XFA
+  CPDFSDK_AnnotIterator ai(this, GetFormFillEnv()->GetFocusableAnnotSubtypes());
+  return ai.GetFirstAnnot();
+}
+
+CPDFSDK_Annot* CPDFSDK_PageView::GetLastFocusableAnnot() {
+#ifdef PDF_ENABLE_XFA
+  CPDFXFA_Page* pXFAPage = XFAPageIfNotBackedByPDFPage();
+  if (pXFAPage)
+    return pXFAPage->GetLastXFAAnnot(this);
+#endif  // PDF_ENABLE_XFA
+  CPDFSDK_AnnotIterator ai(this, GetFormFillEnv()->GetFocusableAnnotSubtypes());
+  return ai.GetLastAnnot();
+}
+
 WideString CPDFSDK_PageView::GetSelectedText() {
   if (CPDFSDK_Annot* pAnnot = GetFocusAnnot()) {
     CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
@@ -488,10 +533,47 @@
 
 bool CPDFSDK_PageView::OnKeyDown(FWL_VKEYCODE nKeyCode,
                                  Mask<FWL_EVENTFLAG> nFlag) {
+  CPDFSDK_Annot* pAnnot = GetFocusAnnot();
   CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
       m_pFormFillEnv->GetAnnotHandlerMgr();
-  return pAnnotHandlerMgr->Annot_OnKeyDown(this, GetFocusAnnot(), nKeyCode,
-                                           nFlag);
+
+  if (!pAnnot) {
+    // If pressed key is not tab then no action is needed.
+    if (nKeyCode != FWL_VKEY_Tab)
+      return false;
+
+    // If ctrl key or alt key is pressed, then no action is needed.
+    if (CPWL_Wnd::IsCTRLKeyDown(nFlag) || CPWL_Wnd::IsALTKeyDown(nFlag))
+      return false;
+
+    ObservedPtr<CPDFSDK_Annot> end_annot(CPWL_Wnd::IsSHIFTKeyDown(nFlag)
+                                             ? GetLastFocusableAnnot()
+                                             : GetFirstFocusableAnnot());
+    return end_annot && m_pFormFillEnv->SetFocusAnnot(&end_annot);
+  }
+
+  if (CPWL_Wnd::IsCTRLKeyDown(nFlag) || CPWL_Wnd::IsALTKeyDown(nFlag))
+    return pAnnotHandlerMgr->Annot_OnKeyDown(this, pAnnot, nKeyCode, nFlag);
+
+  ObservedPtr<CPDFSDK_Annot> pObservedAnnot(pAnnot);
+  CPDFSDK_Annot* pFocusAnnot = GetFocusAnnot();
+  if (pFocusAnnot && (nKeyCode == FWL_VKEY_Tab)) {
+    ObservedPtr<CPDFSDK_Annot> pNext(CPWL_Wnd::IsSHIFTKeyDown(nFlag)
+                                         ? GetPrevAnnot(pFocusAnnot)
+                                         : GetNextAnnot(pFocusAnnot));
+    if (!pNext)
+      return false;
+    if (pNext.Get() != pFocusAnnot) {
+      GetFormFillEnv()->SetFocusAnnot(&pNext);
+      return true;
+    }
+  }
+
+  // Check |pAnnot| again because JS may have destroyed it in |GetNextAnnot|
+  if (!pObservedAnnot)
+    return false;
+
+  return pAnnotHandlerMgr->Annot_OnKeyDown(this, pAnnot, nKeyCode, nFlag);
 }
 
 bool CPDFSDK_PageView::OnKeyUp(FWL_VKEYCODE nKeyCode,
@@ -517,13 +599,12 @@
 
     while (CXFA_FFWidget* pXFAAnnot = pWidgetHandler->MoveToNext()) {
       std::unique_ptr<CPDFSDK_Annot> pNewAnnot =
-          pAnnotHandlerMgr->NewXFAAnnot(pXFAAnnot, this);
+          pAnnotHandlerMgr->NewAnnotForXFA(pXFAAnnot, this);
       DCHECK(pNewAnnot);
       CPDFSDK_Annot* pAnnot = pNewAnnot.get();
       m_SDKAnnotArray.push_back(pNewAnnot.release());
       pAnnotHandlerMgr->Annot_OnLoad(pAnnot);
     }
-
     return;
   }
 #endif  // PDF_ENABLE_XFA
diff --git a/fpdfsdk/cpdfsdk_pageview.h b/fpdfsdk/cpdfsdk_pageview.h
index 10df234..da074aa 100644
--- a/fpdfsdk/cpdfsdk_pageview.h
+++ b/fpdfsdk/cpdfsdk_pageview.h
@@ -25,6 +25,11 @@
 class CPDFSDK_FormFillEnvironment;
 class CPDFSDK_InteractiveForm;
 
+#ifdef PDF_ENABLE_XFA
+class CPDFXFA_Page;
+class CXFA_FFWidget;
+#endif  // PDF_ENABLE_XFA
+
 class CPDFSDK_PageView final : public CPDF_Page::View {
  public:
   CPDFSDK_PageView(CPDFSDK_FormFillEnvironment* pFormFillEnv, IPDF_Page* page);
@@ -37,6 +42,10 @@
 
   void LoadFXAnnots();
   CPDFSDK_Annot* GetFocusAnnot();
+  CPDFSDK_Annot* GetNextAnnot(CPDFSDK_Annot* pAnnot);
+  CPDFSDK_Annot* GetPrevAnnot(CPDFSDK_Annot* pAnnot);
+  CPDFSDK_Annot* GetFirstFocusableAnnot();
+  CPDFSDK_Annot* GetLastFocusableAnnot();
   bool IsValidAnnot(const CPDF_Annot* p) const;
   bool IsValidSDKAnnot(const CPDFSDK_Annot* p) const;
 
@@ -100,6 +109,10 @@
   void TakePageOwnership() { m_pOwnsPage.Reset(ToPDFPage(m_page)); }
 
  private:
+#ifdef PDF_ENABLE_XFA
+  CPDFXFA_Page* XFAPageIfNotBackedByPDFPage();
+#endif
+
   CPDFSDK_Annot* GetFXAnnotAtPoint(const CFX_PointF& point);
   CPDFSDK_Annot* GetFXWidgetAtPoint(const CFX_PointF& point);
 
diff --git a/fpdfsdk/cpdfsdk_widgethandler.h b/fpdfsdk/cpdfsdk_widgethandler.h
index 452d77d..519f462 100644
--- a/fpdfsdk/cpdfsdk_widgethandler.h
+++ b/fpdfsdk/cpdfsdk_widgethandler.h
@@ -23,6 +23,7 @@
   CPDFSDK_WidgetHandler();
   ~CPDFSDK_WidgetHandler() override;
 
+  // IPDFSDK_AnnotHandler:
   bool CanAnswer(CPDFSDK_Annot* pAnnot) override;
   std::unique_ptr<CPDFSDK_Annot> NewAnnot(CPDF_Annot* pAnnot,
                                           CPDFSDK_PageView* pPageView) override;
@@ -46,7 +47,6 @@
               const CFX_Matrix& mtUser2Device,
               bool bDrawAnnots) override;
   void OnLoad(CPDFSDK_Annot* pAnnot) override;
-
   void OnMouseEnter(CPDFSDK_PageView* pPageView,
                     ObservedPtr<CPDFSDK_Annot>* pAnnot,
                     Mask<FWL_EVENTFLAG> nFlag) override;
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_widgethandler.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_widgethandler.cpp
index 4524b78..9c46c8c 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_widgethandler.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_widgethandler.cpp
@@ -217,10 +217,10 @@
 }
 
 std::unique_ptr<CPDFSDK_Annot> CPDFXFA_WidgetHandler::NewAnnotForXFA(
-    CXFA_FFWidget* pAnnot,
+    CXFA_FFWidget* pFFWidget,
     CPDFSDK_PageView* pPageView) {
   CHECK(pPageView);
-  return std::make_unique<CPDFXFA_Widget>(pAnnot, pPageView);
+  return std::make_unique<CPDFXFA_Widget>(pFFWidget, pPageView);
 }
 
 void CPDFXFA_WidgetHandler::OnDraw(CPDFSDK_PageView* pPageView,
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_widgethandler.h b/fpdfsdk/fpdfxfa/cpdfxfa_widgethandler.h
index 47bf3ec..58a3e09 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_widgethandler.h
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_widgethandler.h
@@ -107,11 +107,11 @@
                         int index,
                         bool selected) override;
   bool IsIndexSelected(ObservedPtr<CPDFSDK_Annot>* pAnnot, int index) override;
-
-  std::unique_ptr<CPDFSDK_Annot> NewAnnotForXFA(CXFA_FFWidget* pAnnot,
-                                                CPDFSDK_PageView* pPageView);
+  std::unique_ptr<CPDFSDK_Annot> NewAnnotForXFA(
+      CXFA_FFWidget* pFFWidget,
+      CPDFSDK_PageView* pPageView) override;
   bool OnXFAChangedFocus(ObservedPtr<CPDFSDK_Annot>* pOldAnnot,
-                         ObservedPtr<CPDFSDK_Annot>* pNewAnnot);
+                         ObservedPtr<CPDFSDK_Annot>* pNewAnnot) override;
 
  private:
   CXFA_FFWidgetHandler* GetXFAFFWidgetHandler(CPDFSDK_Annot* pAnnot);
diff --git a/fpdfsdk/ipdfsdk_annothandler.cpp b/fpdfsdk/ipdfsdk_annothandler.cpp
index 3662fbe..8b1270d 100644
--- a/fpdfsdk/ipdfsdk_annothandler.cpp
+++ b/fpdfsdk/ipdfsdk_annothandler.cpp
@@ -6,6 +6,24 @@
 
 #include "fpdfsdk/ipdfsdk_annothandler.h"
 
+#include "third_party/base/notreached.h"
+
 IPDFSDK_AnnotHandler::IPDFSDK_AnnotHandler() = default;
 
 IPDFSDK_AnnotHandler::~IPDFSDK_AnnotHandler() = default;
+
+#ifdef PDF_ENABLE_XFA
+std::unique_ptr<CPDFSDK_Annot> IPDFSDK_AnnotHandler::NewAnnotForXFA(
+    CXFA_FFWidget* pFFWidget,
+    CPDFSDK_PageView* pPageView) {
+  NOTREACHED();
+  return nullptr;
+}
+
+bool IPDFSDK_AnnotHandler::OnXFAChangedFocus(
+    ObservedPtr<CPDFSDK_Annot>* pOldAnnot,
+    ObservedPtr<CPDFSDK_Annot>* pNewAnnot) {
+  NOTREACHED();
+  return false;
+}
+#endif
diff --git a/fpdfsdk/ipdfsdk_annothandler.h b/fpdfsdk/ipdfsdk_annothandler.h
index 13cf286..1ea79e0 100644
--- a/fpdfsdk/ipdfsdk_annothandler.h
+++ b/fpdfsdk/ipdfsdk_annothandler.h
@@ -23,6 +23,10 @@
 class CPDFSDK_FormFillEnvironment;
 class CPDFSDK_PageView;
 
+#ifdef PDF_ENABLE_XFA
+class CXFA_FFWidget;
+#endif
+
 class IPDFSDK_AnnotHandler {
  public:
   IPDFSDK_AnnotHandler();
@@ -118,6 +122,14 @@
   virtual bool IsIndexSelected(ObservedPtr<CPDFSDK_Annot>* pAnnot,
                                int index) = 0;
 
+#ifdef PDF_ENABLE_XFA
+  virtual std::unique_ptr<CPDFSDK_Annot> NewAnnotForXFA(
+      CXFA_FFWidget* pFFWidget,
+      CPDFSDK_PageView* pPageView);
+  virtual bool OnXFAChangedFocus(ObservedPtr<CPDFSDK_Annot>* pOldAnnot,
+                                 ObservedPtr<CPDFSDK_Annot>* pNewAnnot);
+#endif  // PDF_ENABLE_XFA
+
  private:
   UnownedPtr<CPDFSDK_FormFillEnvironment> m_pFormFillEnv;
 };