1 // Copyright 2015 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef TESTING_EMBEDDER_TEST_TIMER_HANDLING_DELEGATE_H_
6 #define TESTING_EMBEDDER_TEST_TIMER_HANDLING_DELEGATE_H_
7 
8 #include <map>
9 #include <string>
10 #include <utility>
11 #include <vector>
12 
13 #include "testing/embedder_test.h"
14 #include "testing/fx_string_testhelpers.h"
15 
16 class EmbedderTestTimerHandlingDelegate final : public EmbedderTest::Delegate {
17  public:
18   struct AlertRecord {
19     std::wstring message;
20     std::wstring title;
21     int type;
22     int icon;
23   };
24 
25   struct Timer {
26     int id;
27     int interval;
28     TimerCallback fn;
29   };
30 
Alert(FPDF_WIDESTRING message,FPDF_WIDESTRING title,int type,int icon)31   int Alert(FPDF_WIDESTRING message,
32             FPDF_WIDESTRING title,
33             int type,
34             int icon) override {
35     alerts_.push_back(
36         {GetPlatformWString(message), GetPlatformWString(title), type, icon});
37     return 0;
38   }
39 
SetTimer(int msecs,TimerCallback fn)40   int SetTimer(int msecs, TimerCallback fn) override {
41     int id = fail_next_timer_ ? 0 : ++next_timer_id_;
42     expiry_to_timer_map_.insert(
43         std::pair<int, Timer>(msecs + fake_elapsed_msecs_, {id, msecs, fn}));
44     fail_next_timer_ = false;
45     return id;
46   }
47 
KillTimer(int id)48   void KillTimer(int id) override {
49     for (auto iter = expiry_to_timer_map_.begin();
50          iter != expiry_to_timer_map_.end(); ++iter) {
51       if (iter->second.id == id) {
52         expiry_to_timer_map_.erase(iter);
53         break;
54       }
55     }
56   }
57 
AdvanceTime(int increment_msecs)58   void AdvanceTime(int increment_msecs) {
59     fake_elapsed_msecs_ += increment_msecs;
60     while (1) {
61       auto iter = expiry_to_timer_map_.begin();
62       if (iter == expiry_to_timer_map_.end()) {
63         break;
64       }
65       if (iter->first > fake_elapsed_msecs_) {
66         break;
67       }
68       Timer t = iter->second;
69       expiry_to_timer_map_.erase(iter);
70       expiry_to_timer_map_.insert(
71           std::pair<int, Timer>(fake_elapsed_msecs_ + t.interval, t));
72       t.fn(t.id);  // Fire timer.
73     }
74   }
75 
GetAlerts()76   const std::vector<AlertRecord>& GetAlerts() const { return alerts_; }
77 
SetFailNextTimer()78   void SetFailNextTimer() { fail_next_timer_ = true; }
79 
80  private:
81   std::multimap<int, Timer> expiry_to_timer_map_;  // Keyed by timeout.
82   bool fail_next_timer_ = false;
83   int next_timer_id_ = 0;
84   int fake_elapsed_msecs_ = 0;
85   std::vector<AlertRecord> alerts_;
86 };
87 
88 #endif  // TESTING_EMBEDDER_TEST_TIMER_HANDLING_DELEGATE_H_
89