Modify test to validate tabbing over links and highlights

The CL modifies the existing test for tabbing over links and highlights.
We recently added support for tabbing to links and highlights in
https://pdfium-review.googlesource.com/c/pdfium/+/60011.

This adds more test coverage for FPDFAnnot_SetFocusableSubtypes() API
and adds slightly more test coverage for
FPDFAnnot_GetFocusableSubtypes() API.

Bug: chromium:994500
Change-Id: I9357425117a9fe421132e906f8c6049ef5db3079
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/67710
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/fpdfsdk/cpdfsdk_baannothandler_embeddertest.cpp b/fpdfsdk/cpdfsdk_baannothandler_embeddertest.cpp
index 6d7fd2e..e22409f 100644
--- a/fpdfsdk/cpdfsdk_baannothandler_embeddertest.cpp
+++ b/fpdfsdk/cpdfsdk_baannothandler_embeddertest.cpp
@@ -2,20 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <vector>
+
 #include "fpdfsdk/cpdfsdk_annotiterator.h"
 #include "fpdfsdk/cpdfsdk_baannothandler.h"
 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
 #include "fpdfsdk/cpdfsdk_helpers.h"
 #include "fpdfsdk/cpdfsdk_pageview.h"
-#include "public/fpdf_annot.h"
 #include "testing/embedder_test.h"
 
 class CPDFSDK_BAAnnotHandlerTest : public EmbedderTest {
  public:
   void SetUp() override {
-    // Test behaviour with currently supported annot i.e. Widget.
-    // TODO(crbug.com/994500): Add an API that can set list of focusable
-    // subtypes once other annots(links & highlights) are also supported.
     EmbedderTest::SetUp();
     SetUpBAAnnotHandler();
   }
@@ -30,43 +28,70 @@
     m_page = LoadPage(0);
     ASSERT_TRUE(m_page);
 
-    CPDFSDK_FormFillEnvironment* pFormFillEnv =
+    m_pFormFillEnv =
         CPDFSDKFormFillEnvironmentFromFPDFFormHandle(form_handle());
-    ASSERT_TRUE(pFormFillEnv);
-    m_pPageView = pFormFillEnv->GetPageView(IPDFPageFromFPDFPage(m_page), true);
+    ASSERT_TRUE(m_pFormFillEnv);
+    m_pPageView =
+        m_pFormFillEnv->GetPageView(IPDFPageFromFPDFPage(m_page), true);
     ASSERT_TRUE(m_pPageView);
 
     CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
-        pFormFillEnv->GetAnnotHandlerMgr();
+        m_pFormFillEnv->GetAnnotHandlerMgr();
     ASSERT_TRUE(pAnnotHandlerMgr);
     m_pBAAnnotHandler = pAnnotHandlerMgr->m_pBAAnnotHandler.get();
     ASSERT_TRUE(m_pBAAnnotHandler);
   }
 
+  CPDFSDK_FormFillEnvironment* GetFormFillEnv() const { return m_pFormFillEnv; }
   CPDFSDK_PageView* GetPageView() const { return m_pPageView; }
   CPDFSDK_BAAnnotHandler* GetBAAnnotHandler() const {
     return m_pBAAnnotHandler;
   }
 
+  CPDFSDK_Annot* GetNthFocusableAnnot(size_t n) {
+    DCHECK_NE(n, 0);
+    CPDFSDK_AnnotIterator ai(GetPageView(),
+                             m_pFormFillEnv->GetFocusableAnnotSubtypes());
+    CPDFSDK_Annot* pAnnot = ai.GetFirstAnnot();
+    ASSERT(pAnnot);
+
+    for (size_t i = 1; i < n; i++) {
+      pAnnot = ai.GetNextAnnot(pAnnot);
+      ASSERT(pAnnot);
+    }
+
+    return pAnnot;
+  }
+
  private:
   FPDF_PAGE m_page = nullptr;
   CPDFSDK_PageView* m_pPageView = nullptr;
+  CPDFSDK_FormFillEnvironment* m_pFormFillEnv = nullptr;
   CPDFSDK_BAAnnotHandler* m_pBAAnnotHandler = nullptr;
 };
 
 TEST_F(CPDFSDK_BAAnnotHandlerTest, TabToLinkOrHighlightAnnot) {
-  // TODO(crbug.com/994500): Create annot iterator with list of supported
-  // focusable subtypes as provided by host.
-  CPDFSDK_AnnotIterator ai(GetPageView(), CPDF_Annot::Subtype::LINK);
-  CPDFSDK_Annot* pAnnot = ai.GetFirstAnnot();
+  std::vector<CPDF_Annot::Subtype> focusable_annot_types = {
+      CPDF_Annot::Subtype::WIDGET, CPDF_Annot::Subtype::LINK,
+      CPDF_Annot::Subtype::HIGHLIGHT};
+
+  GetFormFillEnv()->SetFocusableAnnotSubtypes(focusable_annot_types);
+
+  // Get link annot.
+  CPDFSDK_Annot* pAnnot = GetNthFocusableAnnot(2);
   ASSERT_TRUE(pAnnot);
   EXPECT_EQ(pAnnot->GetAnnotSubtype(), CPDF_Annot::Subtype::LINK);
 
-  ObservedPtr<CPDFSDK_Annot> pNonWidgetAnnot(pAnnot);
+  ObservedPtr<CPDFSDK_Annot> pLinkAnnot(pAnnot);
+  EXPECT_TRUE(GetBAAnnotHandler()->OnSetFocus(&pLinkAnnot, 0));
+  EXPECT_TRUE(GetBAAnnotHandler()->OnKillFocus(&pLinkAnnot, 0));
 
-  // TODO(crbug.com/994500): Change expected value as true once
-  // links & highlights are supported.
-  EXPECT_FALSE(GetBAAnnotHandler()->OnSetFocus(&pNonWidgetAnnot, 0));
+  // Get highlight annot.
+  pAnnot = GetNthFocusableAnnot(4);
+  ASSERT_TRUE(pAnnot);
+  EXPECT_EQ(pAnnot->GetAnnotSubtype(), CPDF_Annot::Subtype::HIGHLIGHT);
 
-  EXPECT_FALSE(GetBAAnnotHandler()->OnKillFocus(&pNonWidgetAnnot, 0));
+  ObservedPtr<CPDFSDK_Annot> pHighlightAnnot(pAnnot);
+  EXPECT_TRUE(GetBAAnnotHandler()->OnSetFocus(&pHighlightAnnot, 0));
+  EXPECT_TRUE(GetBAAnnotHandler()->OnKillFocus(&pHighlightAnnot, 0));
 }
diff --git a/fpdfsdk/fpdf_annot_embeddertest.cpp b/fpdfsdk/fpdf_annot_embeddertest.cpp
index c45ab50..4c25c43 100644
--- a/fpdfsdk/fpdf_annot_embeddertest.cpp
+++ b/fpdfsdk/fpdf_annot_embeddertest.cpp
@@ -2456,6 +2456,7 @@
   std::vector<FPDF_ANNOTATION_SUBTYPE> subtypes(count, FPDF_ANNOT_UNKNOWN);
   EXPECT_FALSE(FPDFAnnot_GetFocusableSubtypes(form_handle(), subtypes.data(),
                                               count - 1));
+  EXPECT_FALSE(FPDFAnnot_GetFocusableSubtypes(nullptr, subtypes.data(), count));
 
   EXPECT_TRUE(
       FPDFAnnot_GetFocusableSubtypes(form_handle(), subtypes.data(), count));