Display content of the annotation when mouse hover.

Each annotation has its contents, and users should be able to see the
contents. In this patch, PDFium creates a Popup annotation for each
annotation and stores the author and the content. When a user mouse
hover on the annotation, PDFium draws the corresponding Popup annotation
and displays the content.

Also, roll DEPS for testing/corpus to 5867fa6.

BUG=62625

Review-Url: https://codereview.chromium.org/2273893002
diff --git a/BUILD.gn b/BUILD.gn
index 982c57a..9ded5b5 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -69,6 +69,7 @@
     "fpdfsdk/cpdfsdk_annothandlermgr.cpp",
     "fpdfsdk/cpdfsdk_annotiterator.cpp",
     "fpdfsdk/cpdfsdk_baannot.cpp",
+    "fpdfsdk/cpdfsdk_baannothandler.cpp",
     "fpdfsdk/cpdfsdk_bfannothandler.cpp",
     "fpdfsdk/cpdfsdk_datetime.cpp",
     "fpdfsdk/cpdfsdk_interform.cpp",
@@ -96,6 +97,7 @@
     "fpdfsdk/include/cpdfsdk_annothandlermgr.h",
     "fpdfsdk/include/cpdfsdk_annotiterator.h",
     "fpdfsdk/include/cpdfsdk_baannot.h",
+    "fpdfsdk/include/cpdfsdk_baannothandler.h",
     "fpdfsdk/include/cpdfsdk_bfannothandler.h",
     "fpdfsdk/include/cpdfsdk_datetime.h",
     "fpdfsdk/include/cpdfsdk_interform.h",
diff --git a/DEPS b/DEPS
index d168db7..7729241 100644
--- a/DEPS
+++ b/DEPS
@@ -14,7 +14,7 @@
   'gmock_revision': '29763965ab52f24565299976b936d1265cb6a271',
   'gtest_revision': '8245545b6dc9c4703e6496d1efd19e975ad2b038',
   'icu_revision': '2341038bf72869a5683a893a2b319a48ffec7f62',
-  'pdfium_tests_revision': 'afbac944ba4b41252e4bd16372f27806bc0ed924',
+  'pdfium_tests_revision': '5867fa68fa3e00016d3e31374e84eb01a3db6ac7',
   'skia_revision': '3bf7509c3f68aefbe5f8b2ea5888319a71a91d2d',
   'tools_memory_revision': '427f10475e1a8d72424c29d00bf689122b738e5d',
   'trace_event_revision': '54b8455be9505c2cb0cf5c26bb86739c236471aa',
diff --git a/core/fpdfdoc/cpdf_annot.cpp b/core/fpdfdoc/cpdf_annot.cpp
index 10360ea..e79acab 100644
--- a/core/fpdfdoc/cpdf_annot.cpp
+++ b/core/fpdfdoc/cpdf_annot.cpp
@@ -21,7 +21,9 @@
 CPDF_Annot::CPDF_Annot(CPDF_Dictionary* pDict, CPDF_Document* pDocument)
     : m_pAnnotDict(pDict),
       m_pDocument(pDocument),
-      m_sSubtype(m_pAnnotDict->GetStringBy("Subtype")) {
+      m_sSubtype(m_pAnnotDict->GetStringBy("Subtype")),
+      m_bOpenState(false),
+      m_pPopupAnnot(nullptr) {
   GenerateAPIfNeeded();
 }
 
@@ -36,6 +38,8 @@
     CPVT_GenerateAP::GenerateHighlightAP(m_pDocument, m_pAnnotDict);
   else if (m_sSubtype == "Ink")
     CPVT_GenerateAP::GenerateInkAP(m_pDocument, m_pAnnotDict);
+  else if (m_sSubtype == "Popup")
+    CPVT_GenerateAP::GeneratePopupAP(m_pDocument, m_pAnnotDict);
   else if (m_sSubtype == "Square")
     CPVT_GenerateAP::GenerateSquareAP(m_pDocument, m_pAnnotDict);
   else if (m_sSubtype == "Squiggly")
@@ -152,6 +156,9 @@
   if (IsAnnotationHidden(m_pAnnotDict))
     return FALSE;
 
+  if (m_sSubtype == "Popup" && !m_bOpenState)
+    return FALSE;
+
   // It might happen that by the time this annotation instance was created,
   // it was flagged as "hidden" (e.g. /F 2), and hence CPVT_GenerateAP decided
   // to not "generate" its AP.
diff --git a/core/fpdfdoc/cpdf_annotlist.cpp b/core/fpdfdoc/cpdf_annotlist.cpp
index e6c93c1..4c56989 100644
--- a/core/fpdfdoc/cpdf_annotlist.cpp
+++ b/core/fpdfdoc/cpdf_annotlist.cpp
@@ -16,6 +16,40 @@
 #include "core/fpdfdoc/include/cpdf_occontext.h"
 #include "core/fxge/include/cfx_renderdevice.h"
 
+namespace {
+
+std::unique_ptr<CPDF_Annot> CreatePopupAnnot(CPDF_Annot* pAnnot,
+                                             CPDF_Document* pDocument) {
+  CPDF_Dictionary* pParentDict = pAnnot->GetAnnotDict();
+  if (!pParentDict)
+    return std::unique_ptr<CPDF_Annot>();
+
+  CFX_ByteString sContents = pParentDict->GetStringBy("Contents");
+  if (sContents.IsEmpty())
+    return std::unique_ptr<CPDF_Annot>();
+
+  CPDF_Dictionary* pAnnotDict = new CPDF_Dictionary;
+  pAnnotDict->SetAtName("Type", "Annot");
+  pAnnotDict->SetAtName("Subtype", "Popup");
+  pAnnotDict->SetAtString("T", pParentDict->GetStringBy("T"));
+  pAnnotDict->SetAtString("Contents", sContents);
+
+  CFX_FloatRect rect = pParentDict->GetRectBy("Rect");
+  rect.Normalize();
+  CFX_FloatRect popupRect(0, 0, 200, 200);
+  popupRect.Translate(rect.left, rect.bottom - popupRect.Height());
+
+  pAnnotDict->SetAtRect("Rect", popupRect);
+  pAnnotDict->SetAtInteger("F", 0);
+
+  std::unique_ptr<CPDF_Annot> pPopupAnnot(
+      new CPDF_Annot(pAnnotDict, pDocument));
+  pAnnot->SetPopupAnnot(pPopupAnnot.get());
+  return pPopupAnnot;
+}
+
+}  // namespace
+
 CPDF_AnnotList::CPDF_AnnotList(CPDF_Page* pPage)
     : m_pDocument(pPage->m_pDocument) {
   if (!pPage->m_pFormDict)
@@ -42,6 +76,12 @@
       pAnnots->RemoveAt(i + 1);
       pDict = pAnnots->GetDictAt(i);
     }
+
+    // Skip creating Popup annotation in the PDF document since PDFium provides
+    // its own Popup annotations.
+    if (pDict->GetStringBy("Subtype") == "Popup")
+      continue;
+
     m_AnnotList.push_back(
         std::unique_ptr<CPDF_Annot>(new CPDF_Annot(pDict, m_pDocument)));
     if (bRegenerateAP && pDict->GetStringBy("Subtype") == "Widget" &&
@@ -49,6 +89,14 @@
       FPDF_GenerateAP(m_pDocument, pDict);
     }
   }
+
+  size_t nAnnotListSize = m_AnnotList.size();
+  for (size_t i = 0; i < nAnnotListSize; ++i) {
+    std::unique_ptr<CPDF_Annot> pPopupAnnot(
+        CreatePopupAnnot(m_AnnotList[i].get(), m_pDocument));
+    if (pPopupAnnot)
+      m_AnnotList.push_back(std::move(pPopupAnnot));
+  }
 }
 
 CPDF_AnnotList::~CPDF_AnnotList() {}
diff --git a/core/fpdfdoc/cpvt_generateap.cpp b/core/fpdfdoc/cpvt_generateap.cpp
index 12ba4ef..d19992e 100644
--- a/core/fpdfdoc/cpvt_generateap.cpp
+++ b/core/fpdfdoc/cpvt_generateap.cpp
@@ -509,6 +509,42 @@
   return sDashStream.MakeString();
 }
 
+CFX_ByteString GetPopupContentsString(CPDF_Document* pDoc,
+                                      const CPDF_Dictionary& pAnnotDict,
+                                      CPDF_Font* pDefFont,
+                                      const CFX_ByteString& sFontName) {
+  CFX_WideString swValue(pAnnotDict.GetUnicodeTextBy("T"));
+  swValue += L'\n';
+  swValue += pAnnotDict.GetUnicodeTextBy("Contents");
+  CPVT_FontMap map(pDoc, nullptr, pDefFont, sFontName);
+
+  CPDF_VariableText::Provider prd(&map);
+  CPDF_VariableText vt;
+  vt.SetProvider(&prd);
+  vt.SetPlateRect(pAnnotDict.GetRectBy("Rect"));
+  vt.SetFontSize(12);
+  vt.SetAutoReturn(TRUE);
+  vt.SetMultiLine(TRUE);
+
+  vt.Initialize();
+  vt.SetText(swValue.c_str());
+  vt.RearrangeAll();
+  CFX_FloatPoint ptOffset(3.0f, -3.0f);
+  CFX_ByteString sContent = CPVT_GenerateAP::GenerateEditAP(
+      &map, vt.GetIterator(), ptOffset, FALSE, 0);
+
+  if (sContent.IsEmpty())
+    return CFX_ByteString();
+
+  CFX_ByteTextBuf sAppStream;
+  sAppStream << "BT\n"
+             << CPVT_GenerateAP::GenerateColorAP(
+                    CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), PaintOperation::FILL)
+             << sContent << "ET\n"
+             << "Q\n";
+  return sAppStream.MakeString();
+}
+
 CPDF_Dictionary* GenerateExtGStateDict(const CPDF_Dictionary& pAnnotDict,
                                        const CFX_ByteString& sExtGSDictName,
                                        const CFX_ByteString& sBlendMode) {
@@ -528,11 +564,39 @@
   return pExtGStateDict;
 }
 
-// Takes ownership of |pExtGStateDict|.
+CPDF_Dictionary* GenerateResourceFontDict(CPDF_Document* pDoc,
+                                          const CFX_ByteString& sFontDictName) {
+  CPDF_Dictionary* pFontDict = new CPDF_Dictionary;
+  pFontDict->SetAtName("Type", "Font");
+  pFontDict->SetAtName("Subtype", "Type1");
+  pFontDict->SetAtName("BaseFont", "Helvetica");
+  pFontDict->SetAtName("Encoding", "WinAnsiEncoding");
+  pDoc->AddIndirectObject(pFontDict);
+
+  CPDF_Dictionary* pResourceFontDict = new CPDF_Dictionary;
+  pResourceFontDict->SetAtReference(sFontDictName, pDoc, pFontDict);
+
+  return pResourceFontDict;
+}
+
+// Takes ownership of |pExtGStateDict| and |pResourceFontDict|.
+CPDF_Dictionary* GenerateResourceDict(CPDF_Dictionary* pExtGStateDict,
+                                      CPDF_Dictionary* pResourceFontDict) {
+  CPDF_Dictionary* pResourceDict = new CPDF_Dictionary;
+  if (pExtGStateDict)
+    pResourceDict->SetAt("ExtGState", pExtGStateDict);
+
+  if (pResourceFontDict)
+    pResourceDict->SetAt("Font", pResourceFontDict);
+
+  return pResourceDict;
+}
+
+// Takes ownership of |pResourceDict|.
 void GenerateAndSetAPDict(CPDF_Document* pDoc,
                           CPDF_Dictionary* pAnnotDict,
                           const CFX_ByteTextBuf& sAppStream,
-                          CPDF_Dictionary* pExtGStateDict) {
+                          CPDF_Dictionary* pResourceDict) {
   CPDF_Dictionary* pAPDict = new CPDF_Dictionary;
   pAnnotDict->SetAt("AP", pAPDict);
 
@@ -551,9 +615,6 @@
   CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect");
   pStreamDict->SetAtRect("BBox", rect);
 
-  CPDF_Dictionary* pResourceDict = new CPDF_Dictionary;
-  pResourceDict->SetAt("ExtGState", pExtGStateDict);
-
   pStreamDict->SetAt("Resources", pResourceDict);
 }
 
@@ -742,7 +803,9 @@
 
   CPDF_Dictionary* pExtGStateDict =
       GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Normal");
-  GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pExtGStateDict);
+  CPDF_Dictionary* pResourceDict =
+      GenerateResourceDict(pExtGStateDict, nullptr);
+  GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pResourceDict);
   return true;
 }
 
@@ -769,7 +832,9 @@
 
   CPDF_Dictionary* pExtGStateDict =
       GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Multiply");
-  GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pExtGStateDict);
+  CPDF_Dictionary* pResourceDict =
+      GenerateResourceDict(pExtGStateDict, nullptr);
+  GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pResourceDict);
 
   return true;
 }
@@ -824,7 +889,9 @@
 
   CPDF_Dictionary* pExtGStateDict =
       GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Normal");
-  GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pExtGStateDict);
+  CPDF_Dictionary* pResourceDict =
+      GenerateResourceDict(pExtGStateDict, nullptr);
+  GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pResourceDict);
   return true;
 }
 
@@ -847,8 +914,9 @@
 
   CPDF_Dictionary* pExtGStateDict =
       GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Normal");
-  GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pExtGStateDict);
-
+  CPDF_Dictionary* pResourceDict =
+      GenerateResourceDict(pExtGStateDict, nullptr);
+  GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pResourceDict);
   return true;
 }
 
@@ -875,7 +943,47 @@
 
   CPDF_Dictionary* pExtGStateDict =
       GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Normal");
-  GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pExtGStateDict);
+  CPDF_Dictionary* pResourceDict =
+      GenerateResourceDict(pExtGStateDict, nullptr);
+  GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pResourceDict);
+  return true;
+}
+
+bool CPVT_GenerateAP::GeneratePopupAP(CPDF_Document* pDoc,
+                                      CPDF_Dictionary* pAnnotDict) {
+  CFX_ByteTextBuf sAppStream;
+  CFX_ByteString sExtGSDictName = "GS";
+  sAppStream << "/" << sExtGSDictName << " gs\n";
+
+  sAppStream << GenerateColorAP(CPVT_Color(CPVT_Color::kRGB, 1, 1, 0),
+                                PaintOperation::FILL);
+  sAppStream << GenerateColorAP(CPVT_Color(CPVT_Color::kRGB, 0, 0, 0),
+                                PaintOperation::STROKE);
+
+  const FX_FLOAT fBorderWidth = 1;
+  sAppStream << fBorderWidth << " w\n";
+
+  CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect");
+  rect.Normalize();
+  rect.Deflate(fBorderWidth / 2, fBorderWidth / 2);
+
+  sAppStream << rect.left << " " << rect.bottom << " " << rect.Width() << " "
+             << rect.Height() << " re b\n";
+
+  CFX_ByteString sFontName = "FONT";
+  CPDF_Dictionary* pExtGStateDict =
+      GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Normal");
+  CPDF_Dictionary* pResourceFontDict =
+      GenerateResourceFontDict(pDoc, sFontName);
+  CPDF_Dictionary* pResourceDict =
+      GenerateResourceDict(pResourceFontDict, pExtGStateDict);
+
+  CPDF_Font* pDefFont = pDoc->LoadFont(pResourceFontDict);
+  if (!pDefFont)
+    return false;
+
+  sAppStream << GetPopupContentsString(pDoc, *pAnnotDict, pDefFont, sFontName);
+  GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pResourceDict);
   return true;
 }
 
@@ -923,7 +1031,9 @@
 
   CPDF_Dictionary* pExtGStateDict =
       GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Normal");
-  GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pExtGStateDict);
+  CPDF_Dictionary* pResourceDict =
+      GenerateResourceDict(pExtGStateDict, nullptr);
+  GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pResourceDict);
   return true;
 }
 
@@ -972,7 +1082,9 @@
 
   CPDF_Dictionary* pExtGStateDict =
       GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Normal");
-  GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pExtGStateDict);
+  CPDF_Dictionary* pResourceDict =
+      GenerateResourceDict(pExtGStateDict, nullptr);
+  GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pResourceDict);
   return true;
 }
 
@@ -999,7 +1111,9 @@
 
   CPDF_Dictionary* pExtGStateDict =
       GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Normal");
-  GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pExtGStateDict);
+  CPDF_Dictionary* pResourceDict =
+      GenerateResourceDict(pExtGStateDict, nullptr);
+  GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pResourceDict);
   return true;
 }
 
diff --git a/core/fpdfdoc/cpvt_generateap.h b/core/fpdfdoc/cpvt_generateap.h
index 062acf6..3fbc4cc 100644
--- a/core/fpdfdoc/cpvt_generateap.h
+++ b/core/fpdfdoc/cpvt_generateap.h
@@ -34,6 +34,7 @@
   static bool GenerateInkAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict);
   static bool GenerateListBoxAP(CPDF_Document* pDoc,
                                 CPDF_Dictionary* pAnnotDict);
+  static bool GeneratePopupAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict);
   static bool GenerateSquareAP(CPDF_Document* pDoc,
                                CPDF_Dictionary* pAnnotDict);
   static bool GenerateSquigglyAP(CPDF_Document* pDoc,
diff --git a/core/fpdfdoc/include/cpdf_annot.h b/core/fpdfdoc/include/cpdf_annot.h
index 914393a..416c540 100644
--- a/core/fpdfdoc/include/cpdf_annot.h
+++ b/core/fpdfdoc/include/cpdf_annot.h
@@ -61,6 +61,9 @@
                   const CFX_Matrix* pUser2Device,
                   const CPDF_RenderOptions* pOptions);
   CPDF_Form* GetAPForm(const CPDF_Page* pPage, AppearanceMode mode);
+  void SetOpenState(bool bOpenState) { m_bOpenState = bOpenState; }
+  CPDF_Annot* GetPopupAnnot() const { return m_pPopupAnnot; }
+  void SetPopupAnnot(CPDF_Annot* pAnnot) { m_pPopupAnnot = pAnnot; }
 
  private:
   void GenerateAPIfNeeded();
@@ -69,6 +72,11 @@
   CPDF_Document* const m_pDocument;
   const CFX_ByteString m_sSubtype;
   std::map<CPDF_Stream*, std::unique_ptr<CPDF_Form>> m_APMap;
+  // |m_bOpenState| is only set for popup annotations.
+  bool m_bOpenState;
+  // Not owned. If there is a valid pointer in |m_pPopupAnnot|,
+  // then this annot is never a popup.
+  CPDF_Annot* m_pPopupAnnot;
 };
 
 CPDF_Stream* FPDFDOC_GetAnnotAP(CPDF_Dictionary* pAnnotDict,
diff --git a/fpdfsdk/cpdfsdk_annothandlermgr.cpp b/fpdfsdk/cpdfsdk_annothandlermgr.cpp
index e7744bf..33c1ca9 100644
--- a/fpdfsdk/cpdfsdk_annothandlermgr.cpp
+++ b/fpdfsdk/cpdfsdk_annothandlermgr.cpp
@@ -10,6 +10,7 @@
 #include "fpdfsdk/include/cba_annotiterator.h"
 #include "fpdfsdk/include/cpdfsdk_annot.h"
 #include "fpdfsdk/include/cpdfsdk_baannot.h"
+#include "fpdfsdk/include/cpdfsdk_baannothandler.h"
 #include "fpdfsdk/include/cpdfsdk_bfannothandler.h"
 #include "fpdfsdk/include/cpdfsdk_datetime.h"
 #include "fpdfsdk/include/fsdk_mgr.h"
@@ -21,43 +22,22 @@
 #include "xfa/fxfa/include/xfa_ffwidget.h"
 #endif  // PDF_ENABLE_XFA
 
-CPDFSDK_AnnotHandlerMgr::CPDFSDK_AnnotHandlerMgr(CPDFDoc_Environment* pApp) {
-  m_pApp = pApp;
-
-  CPDFSDK_BFAnnotHandler* pHandler = new CPDFSDK_BFAnnotHandler(m_pApp);
-  pHandler->SetFormFiller(m_pApp->GetIFormFiller());
-  RegisterAnnotHandler(pHandler);
+CPDFSDK_AnnotHandlerMgr::CPDFSDK_AnnotHandlerMgr(CPDFDoc_Environment* pApp)
+    : m_pBAAnnotHandler(new CPDFSDK_BAAnnotHandler()),
+      m_pBFAnnotHandler(new CPDFSDK_BFAnnotHandler(pApp)),
 #ifdef PDF_ENABLE_XFA
-  CPDFSDK_XFAAnnotHandler* pXFAAnnotHandler =
-      new CPDFSDK_XFAAnnotHandler(m_pApp);
-  RegisterAnnotHandler(pXFAAnnotHandler);
+      m_pXFAAnnotHandler(new CPDFSDK_XFAAnnotHandler(pApp)),
 #endif  // PDF_ENABLE_XFA
+      m_pApp(pApp) {
+  m_pBFAnnotHandler->SetFormFiller(m_pApp->GetIFormFiller());
 }
 
 CPDFSDK_AnnotHandlerMgr::~CPDFSDK_AnnotHandlerMgr() {}
 
-void CPDFSDK_AnnotHandlerMgr::RegisterAnnotHandler(
-    IPDFSDK_AnnotHandler* pAnnotHandler) {
-  ASSERT(!GetAnnotHandler(pAnnotHandler->GetType()));
-
-  m_mapType2Handler[pAnnotHandler->GetType()].reset(pAnnotHandler);
-}
-
-void CPDFSDK_AnnotHandlerMgr::UnRegisterAnnotHandler(
-    IPDFSDK_AnnotHandler* pAnnotHandler) {
-  m_mapType2Handler.erase(pAnnotHandler->GetType());
-}
-
 CPDFSDK_Annot* CPDFSDK_AnnotHandlerMgr::NewAnnot(CPDF_Annot* pAnnot,
                                                  CPDFSDK_PageView* pPageView) {
   ASSERT(pPageView);
-
-  if (IPDFSDK_AnnotHandler* pAnnotHandler =
-          GetAnnotHandler(pAnnot->GetSubtype())) {
-    return pAnnotHandler->NewAnnot(pAnnot, pPageView);
-  }
-
-  return new CPDFSDK_BAAnnot(pAnnot, pPageView);
+  return GetAnnotHandler(pAnnot->GetSubtype())->NewAnnot(pAnnot, pPageView);
 }
 
 #ifdef PDF_ENABLE_XFA
@@ -66,22 +46,14 @@
   ASSERT(pAnnot);
   ASSERT(pPageView);
 
-  if (IPDFSDK_AnnotHandler* pAnnotHandler =
-          GetAnnotHandler(FSDK_XFAWIDGET_TYPENAME)) {
-    return pAnnotHandler->NewAnnot(pAnnot, pPageView);
-  }
-
-  return nullptr;
+  return GetAnnotHandler(FSDK_XFAWIDGET_TYPENAME)->NewAnnot(pAnnot, pPageView);
 }
 #endif  // PDF_ENABLE_XFA
 
 void CPDFSDK_AnnotHandlerMgr::ReleaseAnnot(CPDFSDK_Annot* pAnnot) {
-  if (IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot)) {
-    pAnnotHandler->OnRelease(pAnnot);
-    pAnnotHandler->ReleaseAnnot(pAnnot);
-  } else {
-    delete pAnnot;
-  }
+  IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot);
+  pAnnotHandler->OnRelease(pAnnot);
+  pAnnotHandler->ReleaseAnnot(pAnnot);
 }
 
 void CPDFSDK_AnnotHandlerMgr::Annot_OnCreate(CPDFSDK_Annot* pAnnot) {
@@ -91,33 +63,30 @@
   pPDFAnnot->GetAnnotDict()->SetAtString("M", curTime.ToPDFDateTimeString());
   pPDFAnnot->GetAnnotDict()->SetAtNumber("F", 0);
 
-  if (IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot))
-    pAnnotHandler->OnCreate(pAnnot);
+  GetAnnotHandler(pAnnot)->OnCreate(pAnnot);
 }
 
 void CPDFSDK_AnnotHandlerMgr::Annot_OnLoad(CPDFSDK_Annot* pAnnot) {
   ASSERT(pAnnot);
-
-  if (IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot))
-    pAnnotHandler->OnLoad(pAnnot);
+  GetAnnotHandler(pAnnot)->OnLoad(pAnnot);
 }
 
 IPDFSDK_AnnotHandler* CPDFSDK_AnnotHandlerMgr::GetAnnotHandler(
     CPDFSDK_Annot* pAnnot) const {
-  CPDF_Annot* pPDFAnnot = pAnnot->GetPDFAnnot();
-  if (pPDFAnnot)
-    return GetAnnotHandler(pPDFAnnot->GetSubtype());
-#ifdef PDF_ENABLE_XFA
-  if (pAnnot->GetXFAWidget())
-    return GetAnnotHandler(FSDK_XFAWIDGET_TYPENAME);
-#endif  // PDF_ENABLE_XFA
-  return nullptr;
+  return GetAnnotHandler(pAnnot->GetAnnotSubtype());
 }
 
 IPDFSDK_AnnotHandler* CPDFSDK_AnnotHandlerMgr::GetAnnotHandler(
     const CFX_ByteString& sType) const {
-  auto it = m_mapType2Handler.find(sType);
-  return it != m_mapType2Handler.end() ? it->second.get() : nullptr;
+  if (sType == "Widget")
+    return m_pBFAnnotHandler.get();
+
+#ifdef PDF_ENABLE_XFA
+  if (sType == FSDK_XFAWIDGET_TYPENAME)
+    return m_pXFAAnnotHandler.get();
+#endif  // PDF_ENABLE_XFA
+
+  return m_pBAAnnotHandler.get();
 }
 
 void CPDFSDK_AnnotHandlerMgr::Annot_OnDraw(CPDFSDK_PageView* pPageView,
@@ -126,17 +95,8 @@
                                            CFX_Matrix* pUser2Device,
                                            uint32_t dwFlags) {
   ASSERT(pAnnot);
-
-  if (IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot)) {
-    pAnnotHandler->OnDraw(pPageView, pAnnot, pDevice, pUser2Device, dwFlags);
-  } else {
-#ifdef PDF_ENABLE_XFA
-    if (pAnnot->IsXFAField())
-      return;
-#endif  // PDF_ENABLE_XFA
-    static_cast<CPDFSDK_BAAnnot*>(pAnnot)->DrawAppearance(
-        pDevice, pUser2Device, CPDF_Annot::Normal, nullptr);
-  }
+  GetAnnotHandler(pAnnot)->OnDraw(pPageView, pAnnot, pDevice, pUser2Device,
+                                  dwFlags);
 }
 
 FX_BOOL CPDFSDK_AnnotHandlerMgr::Annot_OnLButtonDown(
@@ -145,11 +105,8 @@
     uint32_t nFlags,
     const CFX_FloatPoint& point) {
   ASSERT(pAnnot);
-
-  if (IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot))
-    return pAnnotHandler->OnLButtonDown(pPageView, pAnnot, nFlags, point);
-
-  return FALSE;
+  return GetAnnotHandler(pAnnot)->OnLButtonDown(pPageView, pAnnot, nFlags,
+                                                point);
 }
 
 FX_BOOL CPDFSDK_AnnotHandlerMgr::Annot_OnLButtonUp(
@@ -158,11 +115,7 @@
     uint32_t nFlags,
     const CFX_FloatPoint& point) {
   ASSERT(pAnnot);
-
-  if (IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot))
-    return pAnnotHandler->OnLButtonUp(pPageView, pAnnot, nFlags, point);
-
-  return FALSE;
+  return GetAnnotHandler(pAnnot)->OnLButtonUp(pPageView, pAnnot, nFlags, point);
 }
 
 FX_BOOL CPDFSDK_AnnotHandlerMgr::Annot_OnLButtonDblClk(
@@ -171,11 +124,8 @@
     uint32_t nFlags,
     const CFX_FloatPoint& point) {
   ASSERT(pAnnot);
-
-  if (IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot))
-    return pAnnotHandler->OnLButtonDblClk(pPageView, pAnnot, nFlags, point);
-
-  return FALSE;
+  return GetAnnotHandler(pAnnot)->OnLButtonDblClk(pPageView, pAnnot, nFlags,
+                                                  point);
 }
 
 FX_BOOL CPDFSDK_AnnotHandlerMgr::Annot_OnMouseMove(
@@ -184,11 +134,7 @@
     uint32_t nFlags,
     const CFX_FloatPoint& point) {
   ASSERT(pAnnot);
-
-  if (IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot))
-    return pAnnotHandler->OnMouseMove(pPageView, pAnnot, nFlags, point);
-
-  return FALSE;
+  return GetAnnotHandler(pAnnot)->OnMouseMove(pPageView, pAnnot, nFlags, point);
 }
 
 FX_BOOL CPDFSDK_AnnotHandlerMgr::Annot_OnMouseWheel(
@@ -198,12 +144,8 @@
     short zDelta,
     const CFX_FloatPoint& point) {
   ASSERT(pAnnot);
-
-  if (IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot)) {
-    return pAnnotHandler->OnMouseWheel(pPageView, pAnnot, nFlags, zDelta,
-                                       point);
-  }
-  return FALSE;
+  return GetAnnotHandler(pAnnot)->OnMouseWheel(pPageView, pAnnot, nFlags,
+                                               zDelta, point);
 }
 
 FX_BOOL CPDFSDK_AnnotHandlerMgr::Annot_OnRButtonDown(
@@ -212,11 +154,8 @@
     uint32_t nFlags,
     const CFX_FloatPoint& point) {
   ASSERT(pAnnot);
-
-  if (IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot))
-    return pAnnotHandler->OnRButtonDown(pPageView, pAnnot, nFlags, point);
-
-  return FALSE;
+  return GetAnnotHandler(pAnnot)->OnRButtonDown(pPageView, pAnnot, nFlags,
+                                                point);
 }
 
 FX_BOOL CPDFSDK_AnnotHandlerMgr::Annot_OnRButtonUp(
@@ -225,61 +164,48 @@
     uint32_t nFlags,
     const CFX_FloatPoint& point) {
   ASSERT(pAnnot);
-
-  if (IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot))
-    return pAnnotHandler->OnRButtonUp(pPageView, pAnnot, nFlags, point);
-
-  return FALSE;
+  return GetAnnotHandler(pAnnot)->OnRButtonUp(pPageView, pAnnot, nFlags, point);
 }
 
 void CPDFSDK_AnnotHandlerMgr::Annot_OnMouseEnter(CPDFSDK_PageView* pPageView,
                                                  CPDFSDK_Annot* pAnnot,
                                                  uint32_t nFlag) {
   ASSERT(pAnnot);
-
-  if (IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot))
-    pAnnotHandler->OnMouseEnter(pPageView, pAnnot, nFlag);
+  GetAnnotHandler(pAnnot)->OnMouseEnter(pPageView, pAnnot, nFlag);
 }
 
 void CPDFSDK_AnnotHandlerMgr::Annot_OnMouseExit(CPDFSDK_PageView* pPageView,
                                                 CPDFSDK_Annot* pAnnot,
                                                 uint32_t nFlag) {
   ASSERT(pAnnot);
-
-  if (IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot))
-    pAnnotHandler->OnMouseExit(pPageView, pAnnot, nFlag);
+  GetAnnotHandler(pAnnot)->OnMouseExit(pPageView, pAnnot, nFlag);
 }
 
 FX_BOOL CPDFSDK_AnnotHandlerMgr::Annot_OnChar(CPDFSDK_Annot* pAnnot,
                                               uint32_t nChar,
                                               uint32_t nFlags) {
-  if (IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot))
-    return pAnnotHandler->OnChar(pAnnot, nChar, nFlags);
-
-  return FALSE;
+  return GetAnnotHandler(pAnnot)->OnChar(pAnnot, nChar, nFlags);
 }
 
 FX_BOOL CPDFSDK_AnnotHandlerMgr::Annot_OnKeyDown(CPDFSDK_Annot* pAnnot,
                                                  int nKeyCode,
                                                  int nFlag) {
-  if (!m_pApp->FFI_IsCTRLKeyDown(nFlag) && !m_pApp->FFI_IsALTKeyDown(nFlag)) {
-    CPDFSDK_PageView* pPage = pAnnot->GetPageView();
-    CPDFSDK_Annot* pFocusAnnot = pPage->GetFocusAnnot();
-    if (pFocusAnnot && (nKeyCode == FWL_VKEY_Tab)) {
-      CPDFSDK_Annot* pNext =
-          GetNextAnnot(pFocusAnnot, !m_pApp->FFI_IsSHIFTKeyDown(nFlag));
+  if (m_pApp->FFI_IsCTRLKeyDown(nFlag) || m_pApp->FFI_IsALTKeyDown(nFlag))
+    return GetAnnotHandler(pAnnot)->OnKeyDown(pAnnot, nKeyCode, nFlag);
 
-      if (pNext && pNext != pFocusAnnot) {
-        CPDFSDK_Document* pDocument = pPage->GetSDKDocument();
-        pDocument->SetFocusAnnot(pNext);
-        return TRUE;
-      }
+  CPDFSDK_PageView* pPage = pAnnot->GetPageView();
+  CPDFSDK_Annot* pFocusAnnot = pPage->GetFocusAnnot();
+  if (pFocusAnnot && (nKeyCode == FWL_VKEY_Tab)) {
+    CPDFSDK_Annot* pNext =
+        GetNextAnnot(pFocusAnnot, !m_pApp->FFI_IsSHIFTKeyDown(nFlag));
+
+    if (pNext && pNext != pFocusAnnot) {
+      CPDFSDK_Document* pDocument = pPage->GetSDKDocument();
+      pDocument->SetFocusAnnot(pNext);
+      return TRUE;
     }
   }
 
-  if (IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot))
-    return pAnnotHandler->OnKeyDown(pAnnot, nKeyCode, nFlag);
-
   return FALSE;
 }
 
@@ -293,24 +219,18 @@
                                                   uint32_t nFlag) {
   ASSERT(pAnnot);
 
-  if (IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot)) {
-    if (pAnnotHandler->OnSetFocus(pAnnot, nFlag)) {
-      CPDFSDK_PageView* pPage = pAnnot->GetPageView();
-      pPage->GetSDKDocument();
-      return TRUE;
-    }
-  }
-  return FALSE;
+  if (!GetAnnotHandler(pAnnot)->OnSetFocus(pAnnot, nFlag))
+    return FALSE;
+
+  CPDFSDK_PageView* pPage = pAnnot->GetPageView();
+  pPage->GetSDKDocument();
+  return TRUE;
 }
 
 FX_BOOL CPDFSDK_AnnotHandlerMgr::Annot_OnKillFocus(CPDFSDK_Annot* pAnnot,
                                                    uint32_t nFlag) {
   ASSERT(pAnnot);
-
-  if (IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot))
-    return pAnnotHandler->OnKillFocus(pAnnot, nFlag);
-
-  return FALSE;
+  return GetAnnotHandler(pAnnot)->OnKillFocus(pAnnot, nFlag);
 }
 
 #ifdef PDF_ENABLE_XFA
@@ -334,20 +254,17 @@
     CPDFSDK_PageView* pPageView,
     CPDFSDK_Annot* pAnnot) {
   ASSERT(pAnnot);
-  if (IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot))
-    return pAnnotHandler->GetViewBBox(pPageView, pAnnot);
-
-  return pAnnot->GetRect();
+  return GetAnnotHandler(pAnnot)->GetViewBBox(pPageView, pAnnot);
 }
 
 FX_BOOL CPDFSDK_AnnotHandlerMgr::Annot_OnHitTest(CPDFSDK_PageView* pPageView,
                                                  CPDFSDK_Annot* pAnnot,
                                                  const CFX_FloatPoint& point) {
   ASSERT(pAnnot);
-  if (IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot)) {
-    if (pAnnotHandler->CanAnswer(pAnnot))
-      return pAnnotHandler->HitTest(pPageView, pAnnot, point);
-  }
+  IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot);
+  if (pAnnotHandler->CanAnswer(pAnnot))
+    return pAnnotHandler->HitTest(pPageView, pAnnot, point);
+
   return FALSE;
 }
 
diff --git a/fpdfsdk/cpdfsdk_baannot.cpp b/fpdfsdk/cpdfsdk_baannot.cpp
index d1d3a0f..5e3e145 100644
--- a/fpdfsdk/cpdfsdk_baannot.cpp
+++ b/fpdfsdk/cpdfsdk_baannot.cpp
@@ -23,6 +23,10 @@
   return m_pAnnot;
 }
 
+CPDF_Annot* CPDFSDK_BAAnnot::GetPDFPopupAnnot() const {
+  return m_pAnnot->GetPopupAnnot();
+}
+
 CPDF_Dictionary* CPDFSDK_BAAnnot::GetAnnotDict() const {
   return m_pAnnot->GetAnnotDict();
 }
@@ -396,3 +400,8 @@
   m_pAnnot->DrawAppearance(m_pPageView->GetPDFPage(), pDevice, pUser2Device,
                            CPDF_Annot::Normal, nullptr);
 }
+
+void CPDFSDK_BAAnnot::SetOpenState(bool bOpenState) {
+  if (CPDF_Annot* pAnnot = m_pAnnot->GetPopupAnnot())
+    pAnnot->SetOpenState(bOpenState);
+}
diff --git a/fpdfsdk/cpdfsdk_baannothandler.cpp b/fpdfsdk/cpdfsdk_baannothandler.cpp
new file mode 100644
index 0000000..2fe3623
--- /dev/null
+++ b/fpdfsdk/cpdfsdk_baannothandler.cpp
@@ -0,0 +1,219 @@
+// Copyright 2016 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
+
+#include "fpdfsdk/include/cpdfsdk_baannothandler.h"
+
+#include <memory>
+#include <vector>
+
+#include "core/fpdfapi/fpdf_page/include/cpdf_page.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
+#include "core/fpdfdoc/include/cpdf_interform.h"
+#include "fpdfsdk/formfiller/cffl_formfiller.h"
+#include "fpdfsdk/include/cpdfsdk_annot.h"
+#include "fpdfsdk/include/cpdfsdk_baannot.h"
+#include "fpdfsdk/include/fsdk_mgr.h"
+
+#ifdef PDF_ENABLE_XFA
+#include "fpdfsdk/fpdfxfa/include/fpdfxfa_doc.h"
+#endif  // PDF_ENABLE_XFA
+
+namespace {
+
+void UpdateAnnotRects(CPDFSDK_PageView* pPageView, CPDFSDK_BAAnnot* pBAAnnot) {
+  std::vector<CFX_FloatRect> rects;
+  rects.push_back(pBAAnnot->GetRect());
+  if (CPDF_Annot* pPopupAnnot = pBAAnnot->GetPDFPopupAnnot())
+    rects.push_back(pPopupAnnot->GetRect());
+  pPageView->UpdateRects(rects);
+}
+
+}  // namespace
+
+CPDFSDK_BAAnnotHandler::CPDFSDK_BAAnnotHandler() {}
+
+CPDFSDK_BAAnnotHandler::~CPDFSDK_BAAnnotHandler() {}
+
+CFX_ByteString CPDFSDK_BAAnnotHandler::GetType() {
+  return CFX_ByteString("");
+}
+
+FX_BOOL CPDFSDK_BAAnnotHandler::CanAnswer(CPDFSDK_Annot* pAnnot) {
+  return FALSE;
+}
+
+CPDFSDK_Annot* CPDFSDK_BAAnnotHandler::NewAnnot(CPDF_Annot* pAnnot,
+                                                CPDFSDK_PageView* pPage) {
+  return new CPDFSDK_BAAnnot(pAnnot, pPage);
+}
+
+#ifdef PDF_ENABLE_XFA
+CPDFSDK_Annot* CPDFSDK_BAAnnotHandler::NewAnnot(CXFA_FFWidget* hWidget,
+                                                CPDFSDK_PageView* pPage) {
+  return nullptr;
+}
+#endif  // PDF_ENABLE_XFA
+
+void CPDFSDK_BAAnnotHandler::ReleaseAnnot(CPDFSDK_Annot* pAnnot) {
+  delete pAnnot;
+}
+
+void CPDFSDK_BAAnnotHandler::DeleteAnnot(CPDFSDK_Annot* pAnnot) {}
+
+void CPDFSDK_BAAnnotHandler::OnDraw(CPDFSDK_PageView* pPageView,
+                                    CPDFSDK_Annot* pAnnot,
+                                    CFX_RenderDevice* pDevice,
+                                    CFX_Matrix* pUser2Device,
+                                    uint32_t dwFlags) {
+#ifdef PDF_ENABLE_XFA
+  if (pAnnot->IsXFAField())
+    return;
+#endif  // PDF_ENABLE_XFA
+  static_cast<CPDFSDK_BAAnnot*>(pAnnot)->DrawAppearance(
+      pDevice, pUser2Device, CPDF_Annot::Normal, nullptr);
+}
+
+void CPDFSDK_BAAnnotHandler::OnDrawSleep(CPDFSDK_PageView* pPageView,
+                                         CPDFSDK_Annot* pAnnot,
+                                         CFX_RenderDevice* pDevice,
+                                         CFX_Matrix* pUser2Device,
+                                         const CFX_FloatRect& rcWindow,
+                                         uint32_t dwFlags) {}
+
+void CPDFSDK_BAAnnotHandler::OnDelete(CPDFSDK_Annot* pAnnot) {}
+
+void CPDFSDK_BAAnnotHandler::OnRelease(CPDFSDK_Annot* pAnnot) {}
+
+void CPDFSDK_BAAnnotHandler::OnMouseEnter(CPDFSDK_PageView* pPageView,
+                                          CPDFSDK_Annot* pAnnot,
+                                          uint32_t nFlag) {
+  CPDFSDK_BAAnnot* pBAAnnot = static_cast<CPDFSDK_BAAnnot*>(pAnnot);
+  pBAAnnot->SetOpenState(true);
+  UpdateAnnotRects(pPageView, pBAAnnot);
+}
+
+void CPDFSDK_BAAnnotHandler::OnMouseExit(CPDFSDK_PageView* pPageView,
+                                         CPDFSDK_Annot* pAnnot,
+                                         uint32_t nFlag) {
+  CPDFSDK_BAAnnot* pBAAnnot = static_cast<CPDFSDK_BAAnnot*>(pAnnot);
+  pBAAnnot->SetOpenState(false);
+  UpdateAnnotRects(pPageView, pBAAnnot);
+}
+
+FX_BOOL CPDFSDK_BAAnnotHandler::OnLButtonDown(CPDFSDK_PageView* pPageView,
+                                              CPDFSDK_Annot* pAnnot,
+                                              uint32_t nFlags,
+                                              const CFX_FloatPoint& point) {
+  return FALSE;
+}
+
+FX_BOOL CPDFSDK_BAAnnotHandler::OnLButtonUp(CPDFSDK_PageView* pPageView,
+                                            CPDFSDK_Annot* pAnnot,
+                                            uint32_t nFlags,
+                                            const CFX_FloatPoint& point) {
+  return FALSE;
+}
+
+FX_BOOL CPDFSDK_BAAnnotHandler::OnLButtonDblClk(CPDFSDK_PageView* pPageView,
+                                                CPDFSDK_Annot* pAnnot,
+                                                uint32_t nFlags,
+                                                const CFX_FloatPoint& point) {
+  return FALSE;
+}
+
+FX_BOOL CPDFSDK_BAAnnotHandler::OnMouseMove(CPDFSDK_PageView* pPageView,
+                                            CPDFSDK_Annot* pAnnot,
+                                            uint32_t nFlags,
+                                            const CFX_FloatPoint& point) {
+  return FALSE;
+}
+
+FX_BOOL CPDFSDK_BAAnnotHandler::OnMouseWheel(CPDFSDK_PageView* pPageView,
+                                             CPDFSDK_Annot* pAnnot,
+                                             uint32_t nFlags,
+                                             short zDelta,
+                                             const CFX_FloatPoint& point) {
+  return FALSE;
+}
+
+FX_BOOL CPDFSDK_BAAnnotHandler::OnRButtonDown(CPDFSDK_PageView* pPageView,
+                                              CPDFSDK_Annot* pAnnot,
+                                              uint32_t nFlags,
+                                              const CFX_FloatPoint& point) {
+  return FALSE;
+}
+
+FX_BOOL CPDFSDK_BAAnnotHandler::OnRButtonUp(CPDFSDK_PageView* pPageView,
+                                            CPDFSDK_Annot* pAnnot,
+                                            uint32_t nFlags,
+                                            const CFX_FloatPoint& point) {
+  return FALSE;
+}
+
+FX_BOOL CPDFSDK_BAAnnotHandler::OnRButtonDblClk(CPDFSDK_PageView* pPageView,
+                                                CPDFSDK_Annot* pAnnot,
+                                                uint32_t nFlags,
+                                                const CFX_FloatPoint& point) {
+  return FALSE;
+}
+
+FX_BOOL CPDFSDK_BAAnnotHandler::OnChar(CPDFSDK_Annot* pAnnot,
+                                       uint32_t nChar,
+                                       uint32_t nFlags) {
+  return FALSE;
+}
+
+FX_BOOL CPDFSDK_BAAnnotHandler::OnKeyDown(CPDFSDK_Annot* pAnnot,
+                                          int nKeyCode,
+                                          int nFlag) {
+  return FALSE;
+}
+
+FX_BOOL CPDFSDK_BAAnnotHandler::OnKeyUp(CPDFSDK_Annot* pAnnot,
+                                        int nKeyCode,
+                                        int nFlag) {
+  return FALSE;
+}
+
+void CPDFSDK_BAAnnotHandler::OnDeSelected(CPDFSDK_Annot* pAnnot) {}
+
+void CPDFSDK_BAAnnotHandler::OnSelected(CPDFSDK_Annot* pAnnot) {}
+
+void CPDFSDK_BAAnnotHandler::OnCreate(CPDFSDK_Annot* pAnnot) {}
+
+void CPDFSDK_BAAnnotHandler::OnLoad(CPDFSDK_Annot* pAnnot) {}
+
+FX_BOOL CPDFSDK_BAAnnotHandler::OnSetFocus(CPDFSDK_Annot* pAnnot,
+                                           uint32_t nFlag) {
+  return FALSE;
+}
+
+FX_BOOL CPDFSDK_BAAnnotHandler::OnKillFocus(CPDFSDK_Annot* pAnnot,
+                                            uint32_t nFlag) {
+  return FALSE;
+}
+
+#ifdef PDF_ENABLE_XFA
+FX_BOOL CPDFSDK_BAAnnotHandler::OnXFAChangedFocus(CPDFSDK_Annot* pOldAnnot,
+                                                  CPDFSDK_Annot* pNewAnnot) {
+  return TRUE;
+}
+#endif  // PDF_ENABLE_XFA
+
+CFX_FloatRect CPDFSDK_BAAnnotHandler::GetViewBBox(CPDFSDK_PageView* pPageView,
+                                                  CPDFSDK_Annot* pAnnot) {
+  return pAnnot->GetRect();
+}
+
+FX_BOOL CPDFSDK_BAAnnotHandler::HitTest(CPDFSDK_PageView* pPageView,
+                                        CPDFSDK_Annot* pAnnot,
+                                        const CFX_FloatPoint& point) {
+  ASSERT(pPageView);
+  ASSERT(pAnnot);
+
+  CFX_FloatRect rect = GetViewBBox(pPageView, pAnnot);
+  return rect.Contains(point.x, point.y);
+}
diff --git a/fpdfsdk/fsdk_mgr.cpp b/fpdfsdk/fsdk_mgr.cpp
index 9f16098..fda00e0 100644
--- a/fpdfsdk/fsdk_mgr.cpp
+++ b/fpdfsdk/fsdk_mgr.cpp
@@ -602,6 +602,8 @@
   CPDFSDK_AnnotIterator annotIterator(this, false);
   while (CPDFSDK_Annot* pSDKAnnot = annotIterator.Next()) {
     CFX_FloatRect rc = pAnnotMgr->Annot_OnGetViewBBox(this, pSDKAnnot);
+    if (pSDKAnnot->GetAnnotSubtype() == "Popup")
+      continue;
     if (rc.Contains(pageX, pageY))
       return pSDKAnnot;
   }
@@ -833,13 +835,13 @@
 FX_BOOL CPDFSDK_PageView::OnMouseMove(const CFX_FloatPoint& point, int nFlag) {
   CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv();
   CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr = pEnv->GetAnnotHandlerMgr();
-  if (CPDFSDK_Annot* pFXAnnot = GetFXWidgetAtPoint(point.x, point.y)) {
+  if (CPDFSDK_Annot* pFXAnnot = GetFXAnnotAtPoint(point.x, point.y)) {
     if (m_CaptureWidget && m_CaptureWidget != pFXAnnot) {
       m_bExitWidget = TRUE;
       m_bEnterWidget = FALSE;
       pAnnotHandlerMgr->Annot_OnMouseExit(this, m_CaptureWidget, nFlag);
     }
-    m_CaptureWidget = (CPDFSDK_Widget*)pFXAnnot;
+    m_CaptureWidget = pFXAnnot;
     m_bOnWidget = TRUE;
     if (!m_bEnterWidget) {
       m_bEnterWidget = TRUE;
diff --git a/fpdfsdk/include/cpdfsdk_annothandlermgr.h b/fpdfsdk/include/cpdfsdk_annothandlermgr.h
index 2d09326..2ff35f8 100644
--- a/fpdfsdk/include/cpdfsdk_annothandlermgr.h
+++ b/fpdfsdk/include/cpdfsdk_annothandlermgr.h
@@ -18,10 +18,13 @@
 class CPDF_Annot;
 class CPDFDoc_Environment;
 class CPDFSDK_Annot;
+class CPDFSDK_BAAnnotHandler;
+class CPDFSDK_BFAnnotHandler;
 class CPDFSDK_PageView;
 class IPDFSDK_AnnotHandler;
 
 #ifdef PDF_ENABLE_XFA
+class CPDFSDK_XFAAnnotHandler;
 class CXFA_FFWidget;
 #endif  // PDF_ENABLE_XFA
 
@@ -30,9 +33,6 @@
   explicit CPDFSDK_AnnotHandlerMgr(CPDFDoc_Environment* pApp);
   virtual ~CPDFSDK_AnnotHandlerMgr();
 
-  void RegisterAnnotHandler(IPDFSDK_AnnotHandler* pAnnotHandler);
-  void UnRegisterAnnotHandler(IPDFSDK_AnnotHandler* pAnnotHandler);
-
   virtual CPDFSDK_Annot* NewAnnot(CPDF_Annot* pAnnot,
                                   CPDFSDK_PageView* pPageView);
 #ifdef PDF_ENABLE_XFA
@@ -112,8 +112,12 @@
   IPDFSDK_AnnotHandler* GetAnnotHandler(const CFX_ByteString& sType) const;
   CPDFSDK_Annot* GetNextAnnot(CPDFSDK_Annot* pSDKAnnot, FX_BOOL bNext);
 
-  std::map<CFX_ByteString, std::unique_ptr<IPDFSDK_AnnotHandler>>
-      m_mapType2Handler;
+  std::unique_ptr<CPDFSDK_BAAnnotHandler> m_pBAAnnotHandler;
+  std::unique_ptr<CPDFSDK_BFAnnotHandler> m_pBFAnnotHandler;
+#ifdef PDF_ENABLE_XFA
+  std::unique_ptr<CPDFSDK_XFAAnnotHandler> m_pXFAAnnotHandler;
+#endif  // PDF_ENABLE_XFA
+
   CPDFDoc_Environment* m_pApp;
 };
 
diff --git a/fpdfsdk/include/cpdfsdk_baannot.h b/fpdfsdk/include/cpdfsdk_baannot.h
index e83cb0f..0f41738 100644
--- a/fpdfsdk/include/cpdfsdk_baannot.h
+++ b/fpdfsdk/include/cpdfsdk_baannot.h
@@ -37,6 +37,7 @@
                     CPDF_RenderOptions* pOptions) override;
 
   CPDF_Dictionary* GetAnnotDict() const;
+  CPDF_Annot* GetPDFPopupAnnot() const;
 
   void SetContents(const CFX_WideString& sContents);
   CFX_WideString GetContents() const;
@@ -96,6 +97,8 @@
                        const CFX_ByteString& sContents,
                        const CFX_ByteString& sAPState = "");
 
+  void SetOpenState(bool bState);
+
  protected:
   CPDF_Annot* m_pAnnot;
 };
diff --git a/fpdfsdk/include/cpdfsdk_baannothandler.h b/fpdfsdk/include/cpdfsdk_baannothandler.h
new file mode 100644
index 0000000..c1936a7
--- /dev/null
+++ b/fpdfsdk/include/cpdfsdk_baannothandler.h
@@ -0,0 +1,114 @@
+// Copyright 2016 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 FPDFSDK_INCLUDE_CPDFSDK_BAANNOTHANDLER_H_
+#define FPDFSDK_INCLUDE_CPDFSDK_BAANNOTHANDLER_H_
+
+#include "core/fxcrt/include/fx_basic.h"
+#include "core/fxcrt/include/fx_coordinates.h"
+#include "fpdfsdk/include/ipdfsdk_annothandler.h"
+
+class CFFL_IFormFiller;
+class CFX_Matrix;
+class CFX_RenderDevice;
+class CPDF_Annot;
+class CPDFDoc_Environment;
+class CPDFSDK_Annot;
+class CPDFSDK_PageView;
+
+#ifdef PDF_ENABLE_XFA
+class CXFA_FFWidget;
+#endif  // PDF_ENABLE_XFA
+
+class CPDFSDK_BAAnnotHandler : public IPDFSDK_AnnotHandler {
+ public:
+  CPDFSDK_BAAnnotHandler();
+  ~CPDFSDK_BAAnnotHandler() override;
+
+  CFX_ByteString GetType() override;
+  FX_BOOL CanAnswer(CPDFSDK_Annot* pAnnot) override;
+  CPDFSDK_Annot* NewAnnot(CPDF_Annot* pAnnot, CPDFSDK_PageView* pPage) override;
+#ifdef PDF_ENABLE_XFA
+  CPDFSDK_Annot* NewAnnot(CXFA_FFWidget* hWidget,
+                          CPDFSDK_PageView* pPage) override;
+#endif  // PDF_ENABLE_XFA
+  void ReleaseAnnot(CPDFSDK_Annot* pAnnot) override;
+  void DeleteAnnot(CPDFSDK_Annot* pAnnot) override;
+  CFX_FloatRect GetViewBBox(CPDFSDK_PageView* pPageView,
+                            CPDFSDK_Annot* pAnnot) override;
+  FX_BOOL HitTest(CPDFSDK_PageView* pPageView,
+                  CPDFSDK_Annot* pAnnot,
+                  const CFX_FloatPoint& point) override;
+  void OnDraw(CPDFSDK_PageView* pPageView,
+              CPDFSDK_Annot* pAnnot,
+              CFX_RenderDevice* pDevice,
+              CFX_Matrix* pUser2Device,
+              uint32_t dwFlags) override;
+  void OnDrawSleep(CPDFSDK_PageView* pPageView,
+                   CPDFSDK_Annot* pAnnot,
+                   CFX_RenderDevice* pDevice,
+                   CFX_Matrix* pUser2Device,
+                   const CFX_FloatRect& rcWindow,
+                   uint32_t dwFlags) override;
+  void OnCreate(CPDFSDK_Annot* pAnnot) override;
+  void OnLoad(CPDFSDK_Annot* pAnnot) override;
+  void OnDelete(CPDFSDK_Annot* pAnnot) override;
+  void OnRelease(CPDFSDK_Annot* pAnnot) override;
+  void OnMouseEnter(CPDFSDK_PageView* pPageView,
+                    CPDFSDK_Annot* pAnnot,
+                    uint32_t nFlag) override;
+  void OnMouseExit(CPDFSDK_PageView* pPageView,
+                   CPDFSDK_Annot* pAnnot,
+                   uint32_t nFlag) override;
+  FX_BOOL OnLButtonDown(CPDFSDK_PageView* pPageView,
+                        CPDFSDK_Annot* pAnnot,
+                        uint32_t nFlags,
+                        const CFX_FloatPoint& point) override;
+  FX_BOOL OnLButtonUp(CPDFSDK_PageView* pPageView,
+                      CPDFSDK_Annot* pAnnot,
+                      uint32_t nFlags,
+                      const CFX_FloatPoint& point) override;
+  FX_BOOL OnLButtonDblClk(CPDFSDK_PageView* pPageView,
+                          CPDFSDK_Annot* pAnnot,
+                          uint32_t nFlags,
+                          const CFX_FloatPoint& point) override;
+  FX_BOOL OnMouseMove(CPDFSDK_PageView* pPageView,
+                      CPDFSDK_Annot* pAnnot,
+                      uint32_t nFlags,
+                      const CFX_FloatPoint& point) override;
+  FX_BOOL OnMouseWheel(CPDFSDK_PageView* pPageView,
+                       CPDFSDK_Annot* pAnnot,
+                       uint32_t nFlags,
+                       short zDelta,
+                       const CFX_FloatPoint& point) override;
+  FX_BOOL OnRButtonDown(CPDFSDK_PageView* pPageView,
+                        CPDFSDK_Annot* pAnnot,
+                        uint32_t nFlags,
+                        const CFX_FloatPoint& point) override;
+  FX_BOOL OnRButtonUp(CPDFSDK_PageView* pPageView,
+                      CPDFSDK_Annot* pAnnot,
+                      uint32_t nFlags,
+                      const CFX_FloatPoint& point) override;
+  FX_BOOL OnRButtonDblClk(CPDFSDK_PageView* pPageView,
+                          CPDFSDK_Annot* pAnnot,
+                          uint32_t nFlags,
+                          const CFX_FloatPoint& point) override;
+  FX_BOOL OnChar(CPDFSDK_Annot* pAnnot,
+                 uint32_t nChar,
+                 uint32_t nFlags) override;
+  FX_BOOL OnKeyDown(CPDFSDK_Annot* pAnnot, int nKeyCode, int nFlag) override;
+  FX_BOOL OnKeyUp(CPDFSDK_Annot* pAnnot, int nKeyCode, int nFlag) override;
+  void OnDeSelected(CPDFSDK_Annot* pAnnot) override;
+  void OnSelected(CPDFSDK_Annot* pAnnot) override;
+  FX_BOOL OnSetFocus(CPDFSDK_Annot* pAnnot, uint32_t nFlag) override;
+  FX_BOOL OnKillFocus(CPDFSDK_Annot* pAnnot, uint32_t nFlag) override;
+#ifdef PDF_ENABLE_XFA
+  FX_BOOL OnXFAChangedFocus(CPDFSDK_Annot* pOldAnnot,
+                            CPDFSDK_Annot* pNewAnnot) override;
+#endif  // PDF_ENABLE_XFA
+};
+
+#endif  // FPDFSDK_INCLUDE_CPDFSDK_BAANNOTHANDLER_H_
diff --git a/fpdfsdk/include/fsdk_mgr.h b/fpdfsdk/include/fsdk_mgr.h
index 2892407..924cd44 100644
--- a/fpdfsdk/include/fsdk_mgr.h
+++ b/fpdfsdk/include/fsdk_mgr.h
@@ -616,10 +616,8 @@
   std::unique_ptr<CPDF_AnnotList> m_pAnnotList;
   std::vector<CPDFSDK_Annot*> m_fxAnnotArray;
   CPDFSDK_Document* const m_pSDKDoc;
-#ifdef PDF_ENABLE_XFA
   CPDFSDK_Annot* m_CaptureWidget;
-#else  // PDF_ENABLE_XFA
-  CPDFSDK_Widget* m_CaptureWidget;
+#ifndef PDF_ENABLE_XFA
   FX_BOOL m_bTakeOverPage;
 #endif  // PDF_ENABLE_XFA
   FX_BOOL m_bEnterWidget;
diff --git a/testing/SUPPRESSIONS b/testing/SUPPRESSIONS
index f97e38c..49c9970 100644
--- a/testing/SUPPRESSIONS
+++ b/testing/SUPPRESSIONS
@@ -281,6 +281,9 @@
 all_trigger_print.pdf * * *
 all_trigger_run_js_lunchurl.pdf mac * *
 all_trigger_run_js_maildoc.pdf mac * *
+annotation_highlight_author_content.pdf mac * *
+annotation_highlight_long_content.pdf mac * *
+annotation_highlight_no_author.pdf mac * *
 app_launchurl.pdf mac * *
 appstoredescription3.1_en_updated.pdf mac * *
 bookmark.pdf * * *