From ca97a8ee99cad1ddb6a69e14cc7a501b3e8092a4 Mon Sep 17 00:00:00 2001 From: tsepez Date: Mon, 1 Aug 2016 10:10:36 -0700 Subject: Watch for destruction of CPDFSDK_widget during callback Speculative fix since I had trouble with the repro. BUG=632709 Review-Url: https://codereview.chromium.org/2197793002 --- fpdfsdk/fsdk_baseform.cpp | 32 +++++++++++++++++++++++++++++++- fpdfsdk/include/fsdk_baseform.h | 34 ++++++++++++++++++++++++---------- fpdfsdk/javascript/Field.cpp | 6 +++++- 3 files changed, 60 insertions(+), 12 deletions(-) diff --git a/fpdfsdk/fsdk_baseform.cpp b/fpdfsdk/fsdk_baseform.cpp index 287c5cf17e..1b1d40b3a0 100644 --- a/fpdfsdk/fsdk_baseform.cpp +++ b/fpdfsdk/fsdk_baseform.cpp @@ -28,6 +28,7 @@ #include "fpdfsdk/javascript/ijs_context.h" #include "fpdfsdk/javascript/ijs_runtime.h" #include "fpdfsdk/pdfwindow/PWL_Utils.h" +#include "third_party/base/stl_util.h" #ifdef PDF_ENABLE_XFA #include "fpdfsdk/fpdfxfa/include/fpdfxfa_doc.h" @@ -49,6 +50,22 @@ PDFSDK_FieldAction::PDFSDK_FieldAction() bFieldFull(FALSE), bRC(TRUE) {} +CPDFSDK_Widget::Observer::Observer(CPDFSDK_Widget** pWatchedPtr) + : m_pWatchedPtr(pWatchedPtr) { + (*m_pWatchedPtr)->AddObserver(this); +} + +CPDFSDK_Widget::Observer::~Observer() { + if (m_pWatchedPtr) + (*m_pWatchedPtr)->RemoveObserver(this); +} + +void CPDFSDK_Widget::Observer::OnWidgetDestroyed() { + ASSERT(m_pWatchedPtr); + *m_pWatchedPtr = nullptr; + m_pWatchedPtr = nullptr; +} + CPDFSDK_Widget::CPDFSDK_Widget(CPDF_Annot* pAnnot, CPDFSDK_PageView* pPageView, CPDFSDK_InterForm* pInterForm) @@ -64,7 +81,20 @@ CPDFSDK_Widget::CPDFSDK_Widget(CPDF_Annot* pAnnot, { } -CPDFSDK_Widget::~CPDFSDK_Widget() {} +CPDFSDK_Widget::~CPDFSDK_Widget() { + for (auto* pObserver : m_Observers) + pObserver->OnWidgetDestroyed(); +} + +void CPDFSDK_Widget::AddObserver(Observer* pObserver) { + ASSERT(!pdfium::ContainsKey(m_Observers, pObserver)); + m_Observers.insert(pObserver); +} + +void CPDFSDK_Widget::RemoveObserver(Observer* pObserver) { + ASSERT(pdfium::ContainsKey(m_Observers, pObserver)); + m_Observers.erase(pObserver); +} #ifdef PDF_ENABLE_XFA CXFA_FFWidget* CPDFSDK_Widget::GetMixXFAWidget() const { diff --git a/fpdfsdk/include/fsdk_baseform.h b/fpdfsdk/include/fsdk_baseform.h index 91603aa41f..d386c7fa2d 100644 --- a/fpdfsdk/include/fsdk_baseform.h +++ b/fpdfsdk/include/fsdk_baseform.h @@ -8,6 +8,7 @@ #define FPDFSDK_INCLUDE_FSDK_BASEFORM_H_ #include +#include #include #include "core/fpdfdoc/include/ipdf_formnotify.h" @@ -62,6 +63,17 @@ struct PDFSDK_FieldAction { class CPDFSDK_Widget : public CPDFSDK_BAAnnot { public: + class Observer { + public: + explicit Observer(CPDFSDK_Widget** pWatchedPtr); + ~Observer(); + + void OnWidgetDestroyed(); + + private: + CPDFSDK_Widget** m_pWatchedPtr; + }; + #ifdef PDF_ENABLE_XFA CXFA_FFWidget* GetMixXFAWidget() const; CXFA_FFWidget* GetGroupMixXFAWidget(); @@ -91,6 +103,9 @@ class CPDFSDK_Widget : public CPDFSDK_BAAnnot { CPDFSDK_InterForm* pInterForm); ~CPDFSDK_Widget() override; + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + // CPDFSDK_Annot CFX_ByteString GetSubType() const override; CPDF_Action GetAAction(CPDF_AAction::AActionType eAAT) override; @@ -172,6 +187,14 @@ class CPDFSDK_Widget : public CPDFSDK_BAAnnot { int32_t GetAppearanceAge() const; int32_t GetValueAge() const; + FX_BOOL IsWidgetAppearanceValid(CPDF_Annot::AppearanceMode mode); + void DrawAppearance(CFX_RenderDevice* pDevice, + const CFX_Matrix* pUser2Device, + CPDF_Annot::AppearanceMode mode, + const CPDF_RenderOptions* pOptions) override; + + FX_BOOL HitTest(FX_FLOAT pageX, FX_FLOAT pageY); + private: void ResetAppearance_PushButton(); void ResetAppearance_CheckBox(); @@ -194,20 +217,11 @@ class CPDFSDK_Widget : public CPDFSDK_BAAnnot { void AddImageToAppearance(const CFX_ByteString& sAPType, CPDF_Stream* pImage); void RemoveAppearance(const CFX_ByteString& sAPType); - public: - FX_BOOL IsWidgetAppearanceValid(CPDF_Annot::AppearanceMode mode); - void DrawAppearance(CFX_RenderDevice* pDevice, - const CFX_Matrix* pUser2Device, - CPDF_Annot::AppearanceMode mode, - const CPDF_RenderOptions* pOptions) override; - - FX_BOOL HitTest(FX_FLOAT pageX, FX_FLOAT pageY); - - private: CPDFSDK_InterForm* const m_pInterForm; FX_BOOL m_bAppModified; int32_t m_nAppAge; int32_t m_nValueAge; + std::set m_Observers; #ifdef PDF_ENABLE_XFA mutable CXFA_FFWidget* m_hMixXFAWidget; diff --git a/fpdfsdk/javascript/Field.cpp b/fpdfsdk/javascript/Field.cpp index 38309cfac5..937b3c6e61 100644 --- a/fpdfsdk/javascript/Field.cpp +++ b/fpdfsdk/javascript/Field.cpp @@ -229,8 +229,12 @@ void Field::UpdateFormField(CPDFSDK_Document* pDocument, if (nFieldType == FIELDTYPE_COMBOBOX || nFieldType == FIELDTYPE_TEXTFIELD) { for (CPDFSDK_Widget* pWidget : widgets) { FX_BOOL bFormatted = FALSE; + CPDFSDK_Widget::Observer observer(&pWidget); CFX_WideString sValue = pWidget->OnFormat(bFormatted); - pWidget->ResetAppearance(bFormatted ? sValue.c_str() : nullptr, FALSE); + if (pWidget) { + pWidget->ResetAppearance(bFormatted ? sValue.c_str() : nullptr, + FALSE); + } } } else { for (CPDFSDK_Widget* pWidget : widgets) { -- cgit v1.2.3