1 // Copyright 2017 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "fxjs/global_timer.h"
8
9 #include <map>
10
11 #include "core/fxcrt/cfx_timer.h"
12 #include "fxjs/cjs_app.h"
13 #include "third_party/base/check.h"
14 #include "third_party/base/containers/contains.h"
15 #include "third_party/base/no_destructor.h"
16
17 namespace {
18
19 using TimerMap = std::map<int32_t, GlobalTimer*>;
GetGlobalTimerMap()20 TimerMap& GetGlobalTimerMap() {
21 static pdfium::base::NoDestructor<TimerMap> timer_map;
22 return *timer_map;
23 }
24
25 } // namespace
26
GlobalTimer(CJS_App * pObj,CJS_Runtime * pRuntime,Type nType,const WideString & script,uint32_t dwElapse,uint32_t dwTimeOut)27 GlobalTimer::GlobalTimer(CJS_App* pObj,
28 CJS_Runtime* pRuntime,
29 Type nType,
30 const WideString& script,
31 uint32_t dwElapse,
32 uint32_t dwTimeOut)
33 : m_nType(nType),
34 m_nTimerID(pRuntime->GetTimerHandler()->SetTimer(dwElapse, Trigger)),
35 m_dwTimeOut(dwTimeOut),
36 m_swJScript(script),
37 m_pRuntime(pRuntime),
38 m_pEmbedApp(pObj) {
39 if (HasValidID()) {
40 DCHECK(!pdfium::Contains(GetGlobalTimerMap(), m_nTimerID));
41 GetGlobalTimerMap()[m_nTimerID] = this;
42 }
43 }
44
~GlobalTimer()45 GlobalTimer::~GlobalTimer() {
46 if (!HasValidID())
47 return;
48
49 if (m_pRuntime && m_pRuntime->GetTimerHandler())
50 m_pRuntime->GetTimerHandler()->KillTimer(m_nTimerID);
51
52 DCHECK(pdfium::Contains(GetGlobalTimerMap(), m_nTimerID));
53 GetGlobalTimerMap().erase(m_nTimerID);
54 }
55
56 // static
Trigger(int32_t nTimerID)57 void GlobalTimer::Trigger(int32_t nTimerID) {
58 auto it = GetGlobalTimerMap().find(nTimerID);
59 if (it == GetGlobalTimerMap().end())
60 return;
61
62 GlobalTimer* pTimer = it->second;
63 if (pTimer->m_bProcessing)
64 return;
65
66 pTimer->m_bProcessing = true;
67 if (pTimer->m_pEmbedApp)
68 pTimer->m_pEmbedApp->TimerProc(pTimer);
69
70 // Timer proc may have destroyed timer, find it again.
71 it = GetGlobalTimerMap().find(nTimerID);
72 if (it == GetGlobalTimerMap().end())
73 return;
74
75 pTimer = it->second;
76 pTimer->m_bProcessing = false;
77 if (pTimer->IsOneShot())
78 pTimer->m_pEmbedApp->CancelProc(pTimer);
79 }
80
81 // static
Cancel(int32_t nTimerID)82 void GlobalTimer::Cancel(int32_t nTimerID) {
83 auto it = GetGlobalTimerMap().find(nTimerID);
84 if (it == GetGlobalTimerMap().end())
85 return;
86
87 GlobalTimer* pTimer = it->second;
88 pTimer->m_pEmbedApp->CancelProc(pTimer);
89 }
90
HasValidID() const91 bool GlobalTimer::HasValidID() const {
92 return m_nTimerID != CFX_Timer::HandlerIface::kInvalidTimerID;
93 }
94