Move CPWL_Timer to CFX_Timer.
First step in consolidating a bunch of distinct timer
implementations. Add unit test while we're at it.
Change-Id: I05a58bb486a392773667de8a2e3a0781ebc03512
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/59050
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fxcrt/BUILD.gn b/core/fxcrt/BUILD.gn
index b582acc..83cf2f7 100644
--- a/core/fxcrt/BUILD.gn
+++ b/core/fxcrt/BUILD.gn
@@ -22,6 +22,8 @@
"cfx_readonlymemorystream.h",
"cfx_seekablestreamproxy.cpp",
"cfx_seekablestreamproxy.h",
+ "cfx_timer.cpp",
+ "cfx_timer.h",
"cfx_utf8decoder.cpp",
"cfx_utf8decoder.h",
"cfx_utf8encoder.cpp",
@@ -134,6 +136,7 @@
"bytestring_unittest.cpp",
"cfx_bitstream_unittest.cpp",
"cfx_seekablestreamproxy_unittest.cpp",
+ "cfx_timer_unittest.cpp",
"cfx_widetextbuf_unittest.cpp",
"fx_bidi_unittest.cpp",
"fx_coordinates_unittest.cpp",
diff --git a/fpdfsdk/pwl/cpwl_timer.cpp b/core/fxcrt/cfx_timer.cpp
similarity index 68%
rename from fpdfsdk/pwl/cpwl_timer.cpp
rename to core/fxcrt/cfx_timer.cpp
index a501c7f..057cda6 100644
--- a/fpdfsdk/pwl/cpwl_timer.cpp
+++ b/core/fxcrt/cfx_timer.cpp
@@ -4,23 +4,23 @@
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-#include "fpdfsdk/pwl/cpwl_timer.h"
+#include "core/fxcrt/cfx_timer.h"
#include <map>
namespace {
-std::map<int32_t, CPWL_Timer*>& GetPWLTimeMap() {
+std::map<int32_t, CFX_Timer*>& GetPWLTimeMap() {
// Leak the object at shutdown.
- static auto* timeMap = new std::map<int32_t, CPWL_Timer*>;
+ static auto* timeMap = new std::map<int32_t, CFX_Timer*>;
return *timeMap;
}
} // namespace
-CPWL_Timer::CPWL_Timer(TimerHandlerIface* pTimerHandler,
- CallbackIface* pCallbackIface,
- int32_t nInterval)
+CFX_Timer::CFX_Timer(TimerHandlerIface* pTimerHandler,
+ CallbackIface* pCallbackIface,
+ int32_t nInterval)
: m_nTimerID(pTimerHandler->SetTimer(nInterval, TimerProc)),
m_pTimerHandler(pTimerHandler),
m_pCallbackIface(pCallbackIface) {
@@ -29,7 +29,7 @@
GetPWLTimeMap()[m_nTimerID] = this;
}
-CPWL_Timer::~CPWL_Timer() {
+CFX_Timer::~CFX_Timer() {
if (HasValidID()) {
m_pTimerHandler->KillTimer(m_nTimerID);
GetPWLTimeMap().erase(m_nTimerID);
@@ -37,7 +37,7 @@
}
// static
-void CPWL_Timer::TimerProc(int32_t idEvent) {
+void CFX_Timer::TimerProc(int32_t idEvent) {
auto it = GetPWLTimeMap().find(idEvent);
if (it != GetPWLTimeMap().end())
it->second->m_pCallbackIface->OnTimerFired();
diff --git a/fpdfsdk/pwl/cpwl_timer.h b/core/fxcrt/cfx_timer.h
similarity index 71%
rename from fpdfsdk/pwl/cpwl_timer.h
rename to core/fxcrt/cfx_timer.h
index 2258674..fa97dda 100644
--- a/fpdfsdk/pwl/cpwl_timer.h
+++ b/core/fxcrt/cfx_timer.h
@@ -4,15 +4,15 @@
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-#ifndef FPDFSDK_PWL_CPWL_TIMER_H_
-#define FPDFSDK_PWL_CPWL_TIMER_H_
+#ifndef CORE_FXCRT_CFX_TIMER_H_
+#define CORE_FXCRT_CFX_TIMER_H_
#include "core/fxcrt/timerhandler_iface.h"
#include "core/fxcrt/unowned_ptr.h"
-class CPWL_TimerHandler;
+class CFX_TimerHandler;
-class CPWL_Timer {
+class CFX_Timer {
public:
class CallbackIface {
public:
@@ -20,21 +20,21 @@
virtual void OnTimerFired() = 0;
};
- CPWL_Timer(TimerHandlerIface* pTimerHandler,
- CallbackIface* pCallbackIface,
- int32_t nInterval);
- ~CPWL_Timer();
-
- private:
- static void TimerProc(int32_t idEvent);
+ CFX_Timer(TimerHandlerIface* pTimerHandler,
+ CallbackIface* pCallbackIface,
+ int32_t nInterval);
+ ~CFX_Timer();
bool HasValidID() const {
return m_nTimerID != TimerHandlerIface::kInvalidTimerID;
}
+ private:
+ static void TimerProc(int32_t idEvent);
+
const int32_t m_nTimerID;
UnownedPtr<TimerHandlerIface> const m_pTimerHandler;
UnownedPtr<CallbackIface> const m_pCallbackIface;
};
-#endif // FPDFSDK_PWL_CPWL_TIMER_H_
+#endif // CORE_FXCRT_CFX_TIMER_H_
diff --git a/core/fxcrt/cfx_timer_unittest.cpp b/core/fxcrt/cfx_timer_unittest.cpp
new file mode 100644
index 0000000..b95de72
--- /dev/null
+++ b/core/fxcrt/cfx_timer_unittest.cpp
@@ -0,0 +1,85 @@
+// Copyright 2019 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.
+
+#include "core/fxcrt/cfx_timer.h"
+
+#include <memory>
+
+#include "core/fxcrt/timerhandler_iface.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/base/ptr_util.h"
+
+using testing::_;
+using testing::DoAll;
+using testing::Return;
+using testing::SaveArg;
+
+class MockTimerScheduler : public TimerHandlerIface {
+ public:
+ MOCK_METHOD2(SetTimer, int(int32_t uElapse, TimerCallback lpTimerFunc));
+ MOCK_METHOD1(KillTimer, void(int32_t nID));
+};
+
+class MockTimerCallback : public CFX_Timer::CallbackIface {
+ public:
+ MOCK_METHOD0(OnTimerFired, void());
+};
+
+TEST(CFX_Timer, ValidTimers) {
+ TimerHandlerIface::TimerCallback fn1 = nullptr;
+ TimerHandlerIface::TimerCallback fn2 = nullptr;
+
+ MockTimerScheduler scheduler;
+ EXPECT_CALL(scheduler, SetTimer(100, _))
+ .WillOnce(DoAll(SaveArg<1>(&fn1), Return(1001)));
+ EXPECT_CALL(scheduler, SetTimer(200, _))
+ .WillOnce(DoAll(SaveArg<1>(&fn2), Return(1002)));
+ EXPECT_CALL(scheduler, KillTimer(1001));
+ EXPECT_CALL(scheduler, KillTimer(1002));
+
+ MockTimerCallback cb1;
+ EXPECT_CALL(cb1, OnTimerFired()).Times(1);
+
+ MockTimerCallback cb2;
+ EXPECT_CALL(cb2, OnTimerFired()).Times(2);
+
+ auto timer1 = pdfium::MakeUnique<CFX_Timer>(&scheduler, &cb1, 100);
+ auto timer2 = pdfium::MakeUnique<CFX_Timer>(&scheduler, &cb2, 200);
+ EXPECT_TRUE(timer1->HasValidID());
+ EXPECT_TRUE(timer2->HasValidID());
+
+ // Fire some timers.
+ ASSERT_TRUE(fn1);
+ ASSERT_TRUE(fn2);
+ (*fn1)(1001);
+ (*fn1)(1002);
+ (*fn1)(1002);
+}
+
+TEST(CFX_Timer, MisbehavingEmbedder) {
+ TimerHandlerIface::TimerCallback fn1 = nullptr;
+
+ MockTimerScheduler scheduler;
+ EXPECT_CALL(scheduler, SetTimer(100, _))
+ .WillOnce(DoAll(SaveArg<1>(&fn1), Return(1001)));
+ EXPECT_CALL(scheduler, KillTimer(1001));
+
+ MockTimerCallback cb1;
+ EXPECT_CALL(cb1, OnTimerFired()).Times(0);
+
+ {
+ auto timer1 = pdfium::MakeUnique<CFX_Timer>(&scheduler, &cb1, 100);
+ EXPECT_TRUE(timer1->HasValidID());
+
+ // Fire callback with bad arguments.
+ ASSERT_TRUE(fn1);
+ (*fn1)(-1);
+ (*fn1)(0);
+ (*fn1)(1002);
+ }
+
+ // Fire callback against stale timer.
+ (*fn1)(1001);
+}
diff --git a/fpdfsdk/formfiller/cffl_formfiller.h b/fpdfsdk/formfiller/cffl_formfiller.h
index 9d8aa35..93e57c5 100644
--- a/fpdfsdk/formfiller/cffl_formfiller.h
+++ b/fpdfsdk/formfiller/cffl_formfiller.h
@@ -11,11 +11,11 @@
#include <memory>
#include "core/fpdfdoc/cba_fontmap.h"
+#include "core/fxcrt/cfx_timer.h"
#include "core/fxcrt/unowned_ptr.h"
#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"
#include "fpdfsdk/pwl/ipwl_systemhandler.h"
@@ -24,7 +24,7 @@
class CPDFSDK_PageView;
class CFFL_FormFiller : public CPWL_Wnd::ProviderIface,
- public CPWL_Timer::CallbackIface {
+ public CFX_Timer::CallbackIface {
public:
CFFL_FormFiller(CPDFSDK_FormFillEnvironment* pFormFillEnv,
CPDFSDK_Widget* pWidget);
@@ -86,7 +86,7 @@
void SetFocusForAnnot(CPDFSDK_Annot* pAnnot, uint32_t nFlag);
void KillFocusForAnnot(uint32_t nFlag);
- // CPWL_Timer::CallbackIface:
+ // CFX_Timer::CallbackIface:
void OnTimerFired() override;
// CPWL_Wnd::ProviderIface:
@@ -157,7 +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::unique_ptr<CFX_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 5726629..94396e3 100644
--- a/fpdfsdk/pwl/BUILD.gn
+++ b/fpdfsdk/pwl/BUILD.gn
@@ -30,8 +30,6 @@
"cpwl_scroll_bar.h",
"cpwl_special_button.cpp",
"cpwl_special_button.h",
- "cpwl_timer.cpp",
- "cpwl_timer.h",
"cpwl_wnd.cpp",
"cpwl_wnd.h",
"ipwl_systemhandler.h",
diff --git a/fpdfsdk/pwl/cpwl_caret.cpp b/fpdfsdk/pwl/cpwl_caret.cpp
index 5be6ff0..739fd37 100644
--- a/fpdfsdk/pwl/cpwl_caret.cpp
+++ b/fpdfsdk/pwl/cpwl_caret.cpp
@@ -85,8 +85,8 @@
m_ptHead = ptHead;
m_ptFoot = ptFoot;
- m_pTimer = pdfium::MakeUnique<CPWL_Timer>(GetTimerHandler(), this,
- kCaretFlashIntervalMs);
+ m_pTimer = pdfium::MakeUnique<CFX_Timer>(GetTimerHandler(), this,
+ kCaretFlashIntervalMs);
if (!CPWL_Wnd::SetVisible(true))
return;
diff --git a/fpdfsdk/pwl/cpwl_caret.h b/fpdfsdk/pwl/cpwl_caret.h
index 9458ed6..71788ef 100644
--- a/fpdfsdk/pwl/cpwl_caret.h
+++ b/fpdfsdk/pwl/cpwl_caret.h
@@ -9,10 +9,10 @@
#include <memory>
-#include "fpdfsdk/pwl/cpwl_timer.h"
+#include "core/fxcrt/cfx_timer.h"
#include "fpdfsdk/pwl/cpwl_wnd.h"
-class CPWL_Caret final : public CPWL_Wnd, public CPWL_Timer::CallbackIface {
+class CPWL_Caret final : public CPWL_Wnd, public CFX_Timer::CallbackIface {
public:
CPWL_Caret(const CreateParams& cp,
std::unique_ptr<IPWL_SystemHandler::PerWindowData> pAttachedData);
@@ -24,7 +24,7 @@
bool InvalidateRect(CFX_FloatRect* pRect) override;
bool SetVisible(bool bVisible) override;
- // CPWL_Timer::CallbackIface:
+ // CFX_Timer::CallbackIface:
void OnTimerFired() override;
void SetCaret(bool bVisible,
@@ -40,7 +40,7 @@
CFX_PointF m_ptFoot;
float m_fWidth = 0.4f;
CFX_FloatRect m_rcInvalid;
- std::unique_ptr<CPWL_Timer> m_pTimer;
+ std::unique_ptr<CFX_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 209c465..bf4d1da 100644
--- a/fpdfsdk/pwl/cpwl_scroll_bar.cpp
+++ b/fpdfsdk/pwl/cpwl_scroll_bar.cpp
@@ -676,7 +676,7 @@
NotifyScrollWindow();
m_bMinOrMax = true;
- m_pTimer = pdfium::MakeUnique<CPWL_Timer>(GetTimerHandler(), this, 100);
+ m_pTimer = pdfium::MakeUnique<CFX_Timer>(GetTimerHandler(), this, 100);
}
void CPWL_ScrollBar::OnMinButtonLBUp(const CFX_PointF& point) {}
@@ -690,7 +690,7 @@
NotifyScrollWindow();
m_bMinOrMax = false;
- m_pTimer = pdfium::MakeUnique<CPWL_Timer>(GetTimerHandler(), this, 100);
+ m_pTimer = pdfium::MakeUnique<CFX_Timer>(GetTimerHandler(), this, 100);
}
void CPWL_ScrollBar::OnMaxButtonLBUp(const CFX_PointF& point) {}
diff --git a/fpdfsdk/pwl/cpwl_scroll_bar.h b/fpdfsdk/pwl/cpwl_scroll_bar.h
index 6d71734..f6bb2b9 100644
--- a/fpdfsdk/pwl/cpwl_scroll_bar.h
+++ b/fpdfsdk/pwl/cpwl_scroll_bar.h
@@ -9,8 +9,8 @@
#include <memory>
+#include "core/fxcrt/cfx_timer.h"
#include "core/fxcrt/unowned_ptr.h"
-#include "fpdfsdk/pwl/cpwl_timer.h"
#include "fpdfsdk/pwl/cpwl_wnd.h"
struct PWL_SCROLL_INFO {
@@ -114,7 +114,7 @@
float fSmallStep;
};
-class CPWL_ScrollBar final : public CPWL_Wnd, public CPWL_Timer::CallbackIface {
+class CPWL_ScrollBar final : public CPWL_Wnd, public CFX_Timer::CallbackIface {
public:
CPWL_ScrollBar(
const CreateParams& cp,
@@ -136,7 +136,7 @@
void NotifyMouseMove(CPWL_Wnd* child, const CFX_PointF& pos) override;
void CreateChildWnd(const CreateParams& cp) override;
- // CPWL_Timer::CallbackIface:
+ // CFX_Timer::CallbackIface:
void OnTimerFired() override;
float GetScrollBarWidth() const;
@@ -176,7 +176,7 @@
UnownedPtr<CPWL_SBButton> m_pMinButton;
UnownedPtr<CPWL_SBButton> m_pMaxButton;
UnownedPtr<CPWL_SBButton> m_pPosButton;
- std::unique_ptr<CPWL_Timer> m_pTimer;
+ std::unique_ptr<CFX_Timer> m_pTimer;
PWL_SCROLL_PRIVATEDATA m_sData;
bool m_bMouseDown = false;
bool m_bMinOrMax = false;
diff --git a/fpdfsdk/pwl/cpwl_wnd.h b/fpdfsdk/pwl/cpwl_wnd.h
index 45e6955..9be574f 100644
--- a/fpdfsdk/pwl/cpwl_wnd.h
+++ b/fpdfsdk/pwl/cpwl_wnd.h
@@ -11,11 +11,11 @@
#include <vector>
#include "core/fpdfdoc/cpdf_formcontrol.h"
+#include "core/fxcrt/cfx_timer.h"
#include "core/fxcrt/observed_ptr.h"
#include "core/fxcrt/unowned_ptr.h"
#include "core/fxge/cfx_color.h"
#include "core/fxge/cfx_renderdevice.h"
-#include "fpdfsdk/pwl/cpwl_timer.h"
#include "fpdfsdk/pwl/ipwl_systemhandler.h"
class CPWL_Edit;