Make CPWL_Timer simpler.

Remove CPWL_TimerHandler, which was an object that served two
purposes: as an interface to dispatch a timer event, and as
an interface to obtain a systemhandler. The second isn't required,
and the first is better provided by a nested pure virtual class.

Also remove the start/stop timer mechanism, timers should be
cancelled by merely deleting them.

-- CPWL_Wnd now does not get a timer by default, only specific
   subclasses will have one.

Change-Id: I5fc1305c4e1b2693d39a74bea10b677263e9e12c
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/58772
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/fpdfsdk/formfiller/cffl_button.cpp b/fpdfsdk/formfiller/cffl_button.cpp
index 06a3542..e96d6e7 100644
--- a/fpdfsdk/formfiller/cffl_button.cpp
+++ b/fpdfsdk/formfiller/cffl_button.cpp
@@ -22,7 +22,7 @@
 void CFFL_Button::OnMouseExit(CPDFSDK_PageView* pPageView) {
   m_bMouseIn = false;
   InvalidateRect(GetViewBBox(pPageView));
-  EndTimer();
+  m_pTimer.reset();
   ASSERT(m_pWidget);
 }
 
diff --git a/fpdfsdk/formfiller/cffl_formfiller.cpp b/fpdfsdk/formfiller/cffl_formfiller.cpp
index 0384468..279e9b1 100644
--- a/fpdfsdk/formfiller/cffl_formfiller.cpp
+++ b/fpdfsdk/formfiller/cffl_formfiller.cpp
@@ -83,7 +83,7 @@
 void CFFL_FormFiller::OnMouseEnter(CPDFSDK_PageView* pPageView) {}
 
 void CFFL_FormFiller::OnMouseExit(CPDFSDK_PageView* pPageView) {
-  EndTimer();
+  m_pTimer.reset();
   ASSERT(m_pWidget);
 }
 
@@ -576,7 +576,7 @@
   return GetPDFWindow(pPageView, false);
 }
 
-void CFFL_FormFiller::TimerProc() {}
+void CFFL_FormFiller::OnTimerFired() {}
 
 CFX_SystemHandler* CFFL_FormFiller::GetSystemHandler() const {
   return m_pFormFillEnv->GetSysHandler();
diff --git a/fpdfsdk/formfiller/cffl_formfiller.h b/fpdfsdk/formfiller/cffl_formfiller.h
index 4cdf1a2..3fbea81 100644
--- a/fpdfsdk/formfiller/cffl_formfiller.h
+++ b/fpdfsdk/formfiller/cffl_formfiller.h
@@ -16,13 +16,15 @@
 #include "fpdfsdk/cpdfsdk_fieldaction.h"
 #include "fpdfsdk/cpdfsdk_widget.h"
 #include "fpdfsdk/formfiller/cffl_interactiveformfiller.h"
+#include "fpdfsdk/pwl/cpwl_timer.h"
+#include "fpdfsdk/pwl/cpwl_wnd.h"
 
 class CPDFSDK_Annot;
 class CPDFSDK_FormFillEnvironment;
 class CPDFSDK_PageView;
 
 class CFFL_FormFiller : public CPWL_Wnd::ProviderIface,
-                        public CPWL_TimerHandler {
+                        public CPWL_Timer::CallbackIface {
  public:
   CFFL_FormFiller(CPDFSDK_FormFillEnvironment* pFormFillEnv,
                   CPDFSDK_Widget* pWidget);
@@ -84,9 +86,8 @@
   void SetFocusForAnnot(CPDFSDK_Annot* pAnnot, uint32_t nFlag);
   void KillFocusForAnnot(uint32_t nFlag);
 
-  // CPWL_TimerHandler:
-  void TimerProc() override;
-  CFX_SystemHandler* GetSystemHandler() const override;  // Covariant return.
+  // CPWL_Timer::CallbackIface:
+  void OnTimerFired() override;
 
   // CPWL_Wnd::ProviderIface:
   CFX_Matrix GetWindowMatrix(
@@ -133,10 +134,10 @@
   void DestroyPDFWindow(CPDFSDK_PageView* pPageView);
   void EscapeFiller(CPDFSDK_PageView* pPageView, bool bDestroyPDFWindow);
 
-
   bool IsValid() const;
   CFX_FloatRect GetPDFWindowRect() const;
 
+  CFX_SystemHandler* GetSystemHandler() const;
   CPDFSDK_PageView* GetCurPageView(bool renew);
   void SetChangeMark();
 
@@ -156,6 +157,7 @@
   bool m_bValid = false;
   UnownedPtr<CPDFSDK_FormFillEnvironment> const m_pFormFillEnv;
   UnownedPtr<CPDFSDK_Widget> m_pWidget;
+  std::unique_ptr<CPWL_Timer> m_pTimer;
   std::map<CPDFSDK_PageView*, std::unique_ptr<CPWL_Wnd>> m_Maps;
 };
 
diff --git a/fpdfsdk/pwl/BUILD.gn b/fpdfsdk/pwl/BUILD.gn
index b018d53..5726629 100644
--- a/fpdfsdk/pwl/BUILD.gn
+++ b/fpdfsdk/pwl/BUILD.gn
@@ -32,8 +32,6 @@
     "cpwl_special_button.h",
     "cpwl_timer.cpp",
     "cpwl_timer.h",
-    "cpwl_timer_handler.cpp",
-    "cpwl_timer_handler.h",
     "cpwl_wnd.cpp",
     "cpwl_wnd.h",
     "ipwl_systemhandler.h",
diff --git a/fpdfsdk/pwl/cpwl_button.cpp b/fpdfsdk/pwl/cpwl_button.cpp
index 7554254..b81afae 100644
--- a/fpdfsdk/pwl/cpwl_button.cpp
+++ b/fpdfsdk/pwl/cpwl_button.cpp
@@ -8,8 +8,6 @@
 
 #include <utility>
 
-#include "fpdfsdk/pwl/cpwl_wnd.h"
-
 CPWL_Button::CPWL_Button(
     const CreateParams& cp,
     std::unique_ptr<IPWL_SystemHandler::PerWindowData> pAttachedData)
diff --git a/fpdfsdk/pwl/cpwl_caret.cpp b/fpdfsdk/pwl/cpwl_caret.cpp
index 581ddb6..936c1c6 100644
--- a/fpdfsdk/pwl/cpwl_caret.cpp
+++ b/fpdfsdk/pwl/cpwl_caret.cpp
@@ -12,7 +12,7 @@
 #include "core/fxge/cfx_graphstatedata.h"
 #include "core/fxge/cfx_pathdata.h"
 #include "core/fxge/cfx_renderdevice.h"
-#include "fpdfsdk/pwl/cpwl_wnd.h"
+#include "third_party/base/ptr_util.h"
 
 CPWL_Caret::CPWL_Caret(
     const CreateParams& cp,
@@ -51,7 +51,7 @@
                     FXFILL_ALTERNATE);
 }
 
-void CPWL_Caret::TimerProc() {
+void CPWL_Caret::OnTimerFired() {
   m_bFlash = !m_bFlash;
   InvalidateRect(nullptr);
   // Note, |this| may no longer be viable at this point. If more work needs
@@ -73,7 +73,7 @@
     if (!IsVisible())
       return;
 
-    EndTimer();
+    m_pTimer.reset();
     CPWL_Wnd::SetVisible(false);
     // Note, |this| may no longer be viable at this point. If more work needs
     // to be done, check the return value of SetVisible().
@@ -85,8 +85,8 @@
 
     m_ptHead = ptHead;
     m_ptFoot = ptFoot;
-    EndTimer();
-    BeginTimer(kCaretFlashIntervalMs);
+    m_pTimer = pdfium::MakeUnique<CPWL_Timer>(GetSystemHandler(), this,
+                                              kCaretFlashIntervalMs);
 
     if (!CPWL_Wnd::SetVisible(true))
       return;
diff --git a/fpdfsdk/pwl/cpwl_caret.h b/fpdfsdk/pwl/cpwl_caret.h
index 482ea5b..9458ed6 100644
--- a/fpdfsdk/pwl/cpwl_caret.h
+++ b/fpdfsdk/pwl/cpwl_caret.h
@@ -9,20 +9,23 @@
 
 #include <memory>
 
+#include "fpdfsdk/pwl/cpwl_timer.h"
 #include "fpdfsdk/pwl/cpwl_wnd.h"
 
-class CPWL_Caret final : public CPWL_Wnd {
+class CPWL_Caret final : public CPWL_Wnd, public CPWL_Timer::CallbackIface {
  public:
   CPWL_Caret(const CreateParams& cp,
              std::unique_ptr<IPWL_SystemHandler::PerWindowData> pAttachedData);
   ~CPWL_Caret() override;
 
-  // CPWL_Wnd
+  // CPWL_Wnd:
   void DrawThisAppearance(CFX_RenderDevice* pDevice,
                           const CFX_Matrix& mtUser2Device) override;
   bool InvalidateRect(CFX_FloatRect* pRect) override;
   bool SetVisible(bool bVisible) override;
-  void TimerProc() override;
+
+  // CPWL_Timer::CallbackIface:
+  void OnTimerFired() override;
 
   void SetCaret(bool bVisible,
                 const CFX_PointF& ptHead,
@@ -37,6 +40,7 @@
   CFX_PointF m_ptFoot;
   float m_fWidth = 0.4f;
   CFX_FloatRect m_rcInvalid;
+  std::unique_ptr<CPWL_Timer> m_pTimer;
 };
 
 #endif  // FPDFSDK_PWL_CPWL_CARET_H_
diff --git a/fpdfsdk/pwl/cpwl_scroll_bar.cpp b/fpdfsdk/pwl/cpwl_scroll_bar.cpp
index f272a89..e1deb8f 100644
--- a/fpdfsdk/pwl/cpwl_scroll_bar.cpp
+++ b/fpdfsdk/pwl/cpwl_scroll_bar.cpp
@@ -475,9 +475,8 @@
     }
   }
 
-  EndTimer();
+  m_pTimer.reset();
   m_bMouseDown = false;
-
   return true;
 }
 
@@ -674,12 +673,10 @@
   m_sData.SubSmall();
   if (!MovePosButton(true))
     return;
+
   NotifyScrollWindow();
-
   m_bMinOrMax = true;
-
-  EndTimer();
-  BeginTimer(100);
+  m_pTimer = pdfium::MakeUnique<CPWL_Timer>(GetSystemHandler(), this, 100);
 }
 
 void CPWL_ScrollBar::OnMinButtonLBUp(const CFX_PointF& point) {}
@@ -690,12 +687,10 @@
   m_sData.AddSmall();
   if (!MovePosButton(true))
     return;
+
   NotifyScrollWindow();
-
   m_bMinOrMax = false;
-
-  EndTimer();
-  BeginTimer(100);
+  m_pTimer = pdfium::MakeUnique<CPWL_Timer>(GetSystemHandler(), this, 100);
 }
 
 void CPWL_ScrollBar::OnMaxButtonLBUp(const CFX_PointF& point) {}
@@ -888,16 +883,18 @@
   CreateButtons(cp);
 }
 
-void CPWL_ScrollBar::TimerProc() {
+void CPWL_ScrollBar::OnTimerFired() {
   PWL_SCROLL_PRIVATEDATA sTemp = m_sData;
   if (m_bMinOrMax)
     m_sData.SubSmall();
   else
     m_sData.AddSmall();
 
-  if (sTemp != m_sData) {
-    if (!MovePosButton(true))
-      return;
-    NotifyScrollWindow();
-  }
+  if (sTemp == m_sData)
+    return;
+
+  if (!MovePosButton(true))
+    return;
+
+  NotifyScrollWindow();
 }
diff --git a/fpdfsdk/pwl/cpwl_scroll_bar.h b/fpdfsdk/pwl/cpwl_scroll_bar.h
index 00fdece..6d71734 100644
--- a/fpdfsdk/pwl/cpwl_scroll_bar.h
+++ b/fpdfsdk/pwl/cpwl_scroll_bar.h
@@ -10,6 +10,7 @@
 #include <memory>
 
 #include "core/fxcrt/unowned_ptr.h"
+#include "fpdfsdk/pwl/cpwl_timer.h"
 #include "fpdfsdk/pwl/cpwl_wnd.h"
 
 struct PWL_SCROLL_INFO {
@@ -113,7 +114,7 @@
   float fSmallStep;
 };
 
-class CPWL_ScrollBar final : public CPWL_Wnd {
+class CPWL_ScrollBar final : public CPWL_Wnd, public CPWL_Timer::CallbackIface {
  public:
   CPWL_ScrollBar(
       const CreateParams& cp,
@@ -134,7 +135,9 @@
   void NotifyLButtonUp(CPWL_Wnd* child, const CFX_PointF& pos) override;
   void NotifyMouseMove(CPWL_Wnd* child, const CFX_PointF& pos) override;
   void CreateChildWnd(const CreateParams& cp) override;
-  void TimerProc() override;
+
+  // CPWL_Timer::CallbackIface:
+  void OnTimerFired() override;
 
   float GetScrollBarWidth() const;
   PWL_SCROLLBAR_TYPE GetScrollBarType() const { return m_sbType; }
@@ -173,6 +176,7 @@
   UnownedPtr<CPWL_SBButton> m_pMinButton;
   UnownedPtr<CPWL_SBButton> m_pMaxButton;
   UnownedPtr<CPWL_SBButton> m_pPosButton;
+  std::unique_ptr<CPWL_Timer> m_pTimer;
   PWL_SCROLL_PRIVATEDATA m_sData;
   bool m_bMouseDown = false;
   bool m_bMinOrMax = false;
diff --git a/fpdfsdk/pwl/cpwl_timer.cpp b/fpdfsdk/pwl/cpwl_timer.cpp
index cb02b43..9979138 100644
--- a/fpdfsdk/pwl/cpwl_timer.cpp
+++ b/fpdfsdk/pwl/cpwl_timer.cpp
@@ -8,8 +8,6 @@
 
 #include <map>
 
-#include "fpdfsdk/pwl/cpwl_timer_handler.h"
-
 namespace {
 
 std::map<int32_t, CPWL_Timer*>& GetPWLTimeMap() {
@@ -20,42 +18,27 @@
 
 }  // namespace
 
-CPWL_Timer::CPWL_Timer(CPWL_TimerHandler* pAttached,
-                       IPWL_SystemHandler* pSystemHandler)
-    : m_pAttached(pAttached), m_pSystemHandler(pSystemHandler) {
-  ASSERT(m_pAttached);
-  ASSERT(m_pSystemHandler);
+CPWL_Timer::CPWL_Timer(IPWL_SystemHandler* pSystemHandler,
+                       CallbackIface* pCallbackIface,
+                       int32_t nInterval)
+    : m_nTimerID(pSystemHandler->SetTimer(nInterval, TimerProc)),
+      m_pSystemHandler(pSystemHandler),
+      m_pCallbackIface(pCallbackIface) {
+  ASSERT(m_pCallbackIface);
+  if (HasValidID())
+    GetPWLTimeMap()[m_nTimerID] = this;
 }
 
 CPWL_Timer::~CPWL_Timer() {
-  KillPWLTimer();
-}
-
-int32_t CPWL_Timer::SetPWLTimer(int32_t nElapse) {
-  KillPWLTimer();
-
-  m_nTimerID = m_pSystemHandler->SetTimer(nElapse, TimerProc);
-  if (HasValidID())
-    GetPWLTimeMap()[m_nTimerID] = this;
-  return m_nTimerID;
-}
-
-void CPWL_Timer::KillPWLTimer() {
-  if (!HasValidID())
-    return;
-
-  m_pSystemHandler->KillTimer(m_nTimerID);
-  GetPWLTimeMap().erase(m_nTimerID);
-  m_nTimerID = IPWL_SystemHandler::kInvalidTimerID;
+  if (HasValidID()) {
+    m_pSystemHandler->KillTimer(m_nTimerID);
+    GetPWLTimeMap().erase(m_nTimerID);
+  }
 }
 
 // static
 void CPWL_Timer::TimerProc(int32_t idEvent) {
   auto it = GetPWLTimeMap().find(idEvent);
-  if (it == GetPWLTimeMap().end())
-    return;
-
-  CPWL_Timer* pTimer = it->second;
-  if (pTimer->m_pAttached)
-    pTimer->m_pAttached->TimerProc();
+  if (it != GetPWLTimeMap().end())
+    it->second->m_pCallbackIface->OnTimerFired();
 }
diff --git a/fpdfsdk/pwl/cpwl_timer.h b/fpdfsdk/pwl/cpwl_timer.h
index a77cacb..8d1a093 100644
--- a/fpdfsdk/pwl/cpwl_timer.h
+++ b/fpdfsdk/pwl/cpwl_timer.h
@@ -14,22 +14,27 @@
 
 class CPWL_Timer {
  public:
-  CPWL_Timer(CPWL_TimerHandler* pAttached, IPWL_SystemHandler* pSystemHandler);
+  class CallbackIface {
+   public:
+    virtual ~CallbackIface() = default;
+    virtual void OnTimerFired() = 0;
+  };
+
+  CPWL_Timer(IPWL_SystemHandler* pSystemHandler,
+             CallbackIface* pCallbackIface,
+             int32_t nInterval);
   ~CPWL_Timer();
 
+ private:
   static void TimerProc(int32_t idEvent);
 
-  int32_t SetPWLTimer(int32_t nElapse);
-  void KillPWLTimer();
-
- private:
   bool HasValidID() const {
     return m_nTimerID != IPWL_SystemHandler::kInvalidTimerID;
   }
 
-  int32_t m_nTimerID = IPWL_SystemHandler::kInvalidTimerID;
-  UnownedPtr<CPWL_TimerHandler> const m_pAttached;
+  const int32_t m_nTimerID;
   UnownedPtr<IPWL_SystemHandler> const m_pSystemHandler;
+  UnownedPtr<CallbackIface> const m_pCallbackIface;
 };
 
 #endif  // FPDFSDK_PWL_CPWL_TIMER_H_
diff --git a/fpdfsdk/pwl/cpwl_timer_handler.cpp b/fpdfsdk/pwl/cpwl_timer_handler.cpp
deleted file mode 100644
index d5ebc25..0000000
--- a/fpdfsdk/pwl/cpwl_timer_handler.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2017 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/pwl/cpwl_timer_handler.h"
-
-#include "fpdfsdk/pwl/cpwl_timer.h"
-#include "third_party/base/ptr_util.h"
-
-CPWL_TimerHandler::CPWL_TimerHandler() = default;
-
-CPWL_TimerHandler::~CPWL_TimerHandler() = default;
-
-void CPWL_TimerHandler::BeginTimer(int32_t nElapse) {
-  if (!m_pTimer)
-    m_pTimer = pdfium::MakeUnique<CPWL_Timer>(this, GetSystemHandler());
-  m_pTimer->SetPWLTimer(nElapse);
-}
-
-void CPWL_TimerHandler::EndTimer() {
-  if (m_pTimer)
-    m_pTimer->KillPWLTimer();
-}
-
-void CPWL_TimerHandler::TimerProc() {}
diff --git a/fpdfsdk/pwl/cpwl_timer_handler.h b/fpdfsdk/pwl/cpwl_timer_handler.h
deleted file mode 100644
index 67c117e..0000000
--- a/fpdfsdk/pwl/cpwl_timer_handler.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2017 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_PWL_CPWL_TIMER_HANDLER_H_
-#define FPDFSDK_PWL_CPWL_TIMER_HANDLER_H_
-
-#include <memory>
-
-class CPWL_Timer;
-class IPWL_SystemHandler;
-
-class CPWL_TimerHandler {
- public:
-  CPWL_TimerHandler();
-  virtual ~CPWL_TimerHandler();
-
-  virtual void TimerProc();
-  virtual IPWL_SystemHandler* GetSystemHandler() const = 0;
-
-  void BeginTimer(int32_t nElapse);
-  void EndTimer();
-
- private:
-  std::unique_ptr<CPWL_Timer> m_pTimer;
-};
-
-#endif  // FPDFSDK_PWL_CPWL_TIMER_HANDLER_H_
diff --git a/fpdfsdk/pwl/cpwl_wnd.cpp b/fpdfsdk/pwl/cpwl_wnd.cpp
index 15e4d45..0202cb4 100644
--- a/fpdfsdk/pwl/cpwl_wnd.cpp
+++ b/fpdfsdk/pwl/cpwl_wnd.cpp
@@ -652,10 +652,6 @@
   m_CreationParams.fFontSize = fFontSize;
 }
 
-IPWL_SystemHandler* CPWL_Wnd::GetSystemHandler() const {
-  return m_CreationParams.pSystemHandler.Get();
-}
-
 CFX_Color CPWL_Wnd::GetBorderLeftTopColor(BorderStyle nBorderStyle) const {
   switch (nBorderStyle) {
     case BorderStyle::BEVELED:
diff --git a/fpdfsdk/pwl/cpwl_wnd.h b/fpdfsdk/pwl/cpwl_wnd.h
index 75a271b..da6db99 100644
--- a/fpdfsdk/pwl/cpwl_wnd.h
+++ b/fpdfsdk/pwl/cpwl_wnd.h
@@ -16,7 +16,6 @@
 #include "core/fxge/cfx_color.h"
 #include "core/fxge/cfx_renderdevice.h"
 #include "fpdfsdk/pwl/cpwl_timer.h"
-#include "fpdfsdk/pwl/cpwl_timer_handler.h"
 #include "fpdfsdk/pwl/ipwl_systemhandler.h"
 
 class CPWL_Edit;
@@ -91,7 +90,7 @@
 #define PWL_DEFAULT_BLACKCOLOR CFX_Color(CFX_Color::kGray, 0)
 #define PWL_DEFAULT_WHITECOLOR CFX_Color(CFX_Color::kGray, 1)
 
-class CPWL_Wnd : public CPWL_TimerHandler, public Observable {
+class CPWL_Wnd : public Observable {
  public:
   class ProviderIface : public Observable {
    public:
@@ -139,7 +138,7 @@
 
   CPWL_Wnd(const CreateParams& cp,
            std::unique_ptr<IPWL_SystemHandler::PerWindowData> pAttachedData);
-  ~CPWL_Wnd() override;
+  virtual ~CPWL_Wnd();
 
   // Returns |true| iff this instance is still allocated.
   virtual bool InvalidateRect(CFX_FloatRect* pRect);
@@ -257,9 +256,6 @@
   virtual void OnKillFocus();
 
  protected:
-  // CPWL_TimerHandler:
-  IPWL_SystemHandler* GetSystemHandler() const override;
-
   virtual void CreateChildWnd(const CreateParams& cp);
 
   // Returns |true| iff this instance is still allocated.
@@ -274,6 +270,9 @@
   bool IsNotifying() const { return m_bNotifying; }
   bool IsValid() const { return m_bCreated; }
   CreateParams* GetCreationParams() { return &m_CreationParams; }
+  IPWL_SystemHandler* GetSystemHandler() const {
+    return m_CreationParams.pSystemHandler.Get();
+  }
 
   // Returns |true| iff this instance is still allocated.
   bool InvalidateRectMove(const CFX_FloatRect& rcOld,