Rip out the KillFocusAnnot call from CPDFSDK_PageView's destructor
authorOliver Chang <ochang@chromium.org>
Fri, 30 Oct 2015 19:48:49 +0000 (12:48 -0700)
committerOliver Chang <ochang@chromium.org>
Fri, 30 Oct 2015 19:48:49 +0000 (12:48 -0700)
Previously, blur event actions could potentially touch deleted PageViews
as CPDFSDK_Document deletes the PageViews one by one.

This also fixes a related issue: CPDFSDK_Document::SetFocusAnnot no
longer does anything if the document is being destroyed. Otherwise, it
eventually tries to use m_pEnv->GetSDKDocument() at which point has
already been set to NULL by FPDFDOC_ExitFormFillEnvironment.

R=tsepez@chromium.org, thestig@chromium.org
BUG=512445

Review URL: https://codereview.chromium.org/1414353007 .

fpdfsdk/include/fsdk_mgr.h
fpdfsdk/src/fsdk_mgr.cpp

index 2c063ed..2cc5282 100644 (file)
@@ -283,6 +283,7 @@ class CPDFSDK_Document {
   CPDFDoc_Environment* m_pEnv;
   CPDF_OCContext* m_pOccontent;
   FX_BOOL m_bChangeMask;
+  FX_BOOL m_bBeingDestroyed;
 };
 class CPDFSDK_PageView final {
  public:
@@ -302,6 +303,7 @@ class CPDFSDK_PageView final {
   FX_BOOL KillFocusAnnot(FX_UINT nFlag = 0) {
     return m_pSDKDoc->KillFocusAnnot(nFlag);
   }
+  void KillFocusAnnotIfNeeded();
   FX_BOOL Annot_HasAppearance(CPDF_Annot* pAnnot);
 
   CPDFSDK_Annot* AddAnnot(CPDF_Dictionary* pDict);
index 0b67701..7dba8d2 100644 (file)
@@ -408,9 +408,16 @@ CPDFSDK_Document::CPDFSDK_Document(CPDF_Document* pDoc,
       m_pFocusAnnot(nullptr),
       m_pEnv(pEnv),
       m_pOccontent(nullptr),
-      m_bChangeMask(FALSE) {}
+      m_bChangeMask(FALSE),
+      m_bBeingDestroyed(FALSE) {
+}
 
 CPDFSDK_Document::~CPDFSDK_Document() {
+  m_bBeingDestroyed = TRUE;
+
+  for (auto& it : m_pageMap)
+    it.second->KillFocusAnnotIfNeeded();
+
   for (auto& it : m_pageMap)
     delete it.second;
   m_pageMap.clear();
@@ -509,6 +516,7 @@ void CPDFSDK_Document::ReMovePageView(CPDF_Page* pPDFPage) {
   if (pPageView->IsLocked())
     return;
 
+  pPageView->KillFocusAnnotIfNeeded();
   delete pPageView;
   m_pageMap.erase(it);
 }
@@ -541,6 +549,9 @@ CPDFSDK_Annot* CPDFSDK_Document::GetFocusAnnot() {
 }
 
 FX_BOOL CPDFSDK_Document::SetFocusAnnot(CPDFSDK_Annot* pAnnot, FX_UINT nFlag) {
+  if (m_bBeingDestroyed)
+    return FALSE;
+
   if (m_pFocusAnnot == pAnnot)
     return TRUE;
 
@@ -627,14 +638,6 @@ CPDFSDK_PageView::CPDFSDK_PageView(CPDFSDK_Document* pSDKDoc, CPDF_Page* page)
 }
 
 CPDFSDK_PageView::~CPDFSDK_PageView() {
-  // if there is a focused annot on the page, we should kill the focus first.
-  if (CPDFSDK_Annot* focusedAnnot = m_pSDKDoc->GetFocusAnnot()) {
-    auto it =
-        std::find(m_fxAnnotArray.begin(), m_fxAnnotArray.end(), focusedAnnot);
-    if (it != m_fxAnnotArray.end())
-      KillFocusAnnot();
-  }
-
   CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv();
   CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr = pEnv->GetAnnotHandlerMgr();
   for (CPDFSDK_Annot* pAnnot : m_fxAnnotArray)
@@ -721,6 +724,16 @@ CPDFSDK_Annot* CPDFSDK_PageView::GetFXWidgetAtPoint(FX_FLOAT pageX,
   return nullptr;
 }
 
+void CPDFSDK_PageView::KillFocusAnnotIfNeeded() {
+  // if there is a focused annot on the page, we should kill the focus first.
+  if (CPDFSDK_Annot* focusedAnnot = m_pSDKDoc->GetFocusAnnot()) {
+    auto it =
+        std::find(m_fxAnnotArray.begin(), m_fxAnnotArray.end(), focusedAnnot);
+    if (it != m_fxAnnotArray.end())
+      KillFocusAnnot();
+  }
+}
+
 FX_BOOL CPDFSDK_PageView::Annot_HasAppearance(CPDF_Annot* pAnnot) {
   CPDF_Dictionary* pAnnotDic = pAnnot->GetAnnotDict();
   if (pAnnotDic)