OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/svg/graphics/SVGImage.h" | 5 #include "core/svg/graphics/SVGImage.h" |
6 | 6 |
7 #include "core/svg/graphics/SVGImageChromeClient.h" | 7 #include "core/svg/graphics/SVGImageChromeClient.h" |
8 #include "platform/SharedBuffer.h" | 8 #include "platform/SharedBuffer.h" |
9 #include "platform/Timer.h" | 9 #include "platform/Timer.h" |
10 #include "platform/geometry/FloatRect.h" | 10 #include "platform/geometry/FloatRect.h" |
| 11 #include "platform/testing/UnitTestHelpers.h" |
11 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
12 #include "third_party/skia/include/core/SkCanvas.h" | 13 #include "third_party/skia/include/core/SkCanvas.h" |
13 #include "third_party/skia/include/utils/SkNullCanvas.h" | 14 #include "third_party/skia/include/utils/SkNullCanvas.h" |
14 #include "wtf/PtrUtil.h" | 15 #include "wtf/PtrUtil.h" |
15 | 16 |
16 namespace blink { | 17 namespace blink { |
17 namespace { | 18 class SVGImageTest : public ::testing::Test { |
18 | |
19 class MockTaskRunner : public WebTaskRunner { | |
20 public: | |
21 void setTime(double newTime) { m_time = newTime; } | |
22 | |
23 MockTaskRunner() | |
24 : WebTaskRunner(), m_time(0.0), m_currentTask(nullptr) | |
25 { } | |
26 | |
27 virtual ~MockTaskRunner() | |
28 { | |
29 if (m_currentTask) | |
30 delete m_currentTask; | |
31 } | |
32 | |
33 private: | |
34 void postTask(const WebTraceLocation&, Task*) override { } | |
35 void postDelayedTask(const WebTraceLocation&, Task* task, double) override | |
36 { | |
37 if (m_currentTask) | |
38 delete m_currentTask; | |
39 m_currentTask = task; | |
40 | |
41 } | |
42 bool runsTasksOnCurrentThread() override { return true; } | |
43 std::unique_ptr<WebTaskRunner> clone() override { return nullptr; } | |
44 double virtualTimeSeconds() const override { return 0.0; } | |
45 double monotonicallyIncreasingVirtualTimeSeconds() const override { return m
_time; } | |
46 SingleThreadTaskRunner* taskRunner() override { return nullptr; } | |
47 | |
48 double m_time; | |
49 Task* m_currentTask; | |
50 }; | |
51 | |
52 class MockTimer : public TaskRunnerTimer<SVGImageChromeClient> { | |
53 public: | |
54 using TimerFiredFunction = typename TaskRunnerTimer<SVGImageChromeClient>::T
imerFiredFunction; | |
55 | |
56 MockTimer(SVGImageChromeClient* o, TimerFiredFunction f) | |
57 : TaskRunnerTimer(&m_taskRunner, o, f) | |
58 { | |
59 } | |
60 | |
61 void fire() | |
62 { | |
63 fired(); | |
64 stop(); | |
65 } | |
66 | |
67 void setTime(double newTime) | |
68 { | |
69 m_taskRunner.setTime(newTime); | |
70 } | |
71 | |
72 private: | |
73 MockTaskRunner m_taskRunner; | |
74 }; | |
75 | |
76 } // namespace | |
77 | |
78 class SVGImageTest : public testing::Test { | |
79 public: | 19 public: |
80 SVGImage& image() { return *m_image; } | 20 SVGImage& image() { return *m_image; } |
81 | 21 |
82 void load(const char* data, bool shouldPause) | 22 void load(const char* data, bool shouldPause) |
83 { | 23 { |
84 m_observer = new PauseControlImageObserver(shouldPause); | 24 m_observer = new PauseControlImageObserver(shouldPause); |
85 m_image = SVGImage::create(m_observer); | 25 m_image = SVGImage::create(m_observer); |
86 m_image->setData(SharedBuffer::create(data, strlen(data)), true); | 26 m_image->setData(SharedBuffer::create(data, strlen(data)), true); |
87 } | 27 } |
88 | 28 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 "}" | 76 "}" |
137 "</style>" | 77 "</style>" |
138 "<path class='spinner' fill='none' d='M 8,1.125 A 6.875,6.875 0 1 1 1.125,8'
stroke-width='2' stroke='blue'/>" | 78 "<path class='spinner' fill='none' d='M 8,1.125 A 6.875,6.875 0 1 1 1.125,8'
stroke-width='2' stroke='blue'/>" |
139 "</svg>"; | 79 "</svg>"; |
140 | 80 |
141 TEST_F(SVGImageTest, TimelineSuspendAndResume) | 81 TEST_F(SVGImageTest, TimelineSuspendAndResume) |
142 { | 82 { |
143 const bool shouldPause = true; | 83 const bool shouldPause = true; |
144 load(kAnimatedDocument, shouldPause); | 84 load(kAnimatedDocument, shouldPause); |
145 SVGImageChromeClient& chromeClient = image().chromeClientForTesting(); | 85 SVGImageChromeClient& chromeClient = image().chromeClientForTesting(); |
146 MockTimer* timer = new MockTimer(&chromeClient, &SVGImageChromeClient::anima
tionTimerFired); | 86 Timer<SVGImageChromeClient>* timer = new Timer<SVGImageChromeClient>(&chrome
Client, &SVGImageChromeClient::animationTimerFired); |
147 chromeClient.setTimer(wrapUnique(timer)); | 87 chromeClient.setTimer(wrapUnique(timer)); |
148 | 88 |
149 // Simulate a draw. Cause a frame (timer) to be scheduled. | 89 // Simulate a draw. Cause a frame (timer) to be scheduled. |
150 pumpFrame(); | 90 pumpFrame(); |
151 EXPECT_TRUE(image().hasAnimations()); | 91 EXPECT_TRUE(image().hasAnimations()); |
152 EXPECT_TRUE(timer->isActive()); | 92 EXPECT_TRUE(timer->isActive()); |
153 | 93 |
154 // Fire the timer/trigger a frame update. Since the observer always returns | 94 // Fire the timer/trigger a frame update. Since the observer always returns |
155 // true for shouldPauseAnimation, this will result in the timeline being | 95 // true for shouldPauseAnimation, this will result in the timeline being |
156 // suspended. | 96 // suspended. |
157 timer->fire(); | 97 // TODO(alexclarke): Move over to using base::TimeDelta and base::TimeTicks
so we can avoid computations like this. |
| 98 testing::runDelayedTasks(1.0 + timer->nextFireInterval() * 1000.0); |
158 EXPECT_TRUE(chromeClient.isSuspended()); | 99 EXPECT_TRUE(chromeClient.isSuspended()); |
159 EXPECT_FALSE(timer->isActive()); | 100 EXPECT_FALSE(timer->isActive()); |
160 | 101 |
161 // Simulate a draw. This should resume the animation again. | 102 // Simulate a draw. This should resume the animation again. |
162 pumpFrame(); | 103 pumpFrame(); |
163 EXPECT_TRUE(timer->isActive()); | 104 EXPECT_TRUE(timer->isActive()); |
164 EXPECT_FALSE(chromeClient.isSuspended()); | 105 EXPECT_FALSE(chromeClient.isSuspended()); |
165 } | 106 } |
166 | 107 |
167 TEST_F(SVGImageTest, ResetAnimation) | 108 TEST_F(SVGImageTest, ResetAnimation) |
168 { | 109 { |
169 const bool shouldPause = false; | 110 const bool shouldPause = false; |
170 load(kAnimatedDocument, shouldPause); | 111 load(kAnimatedDocument, shouldPause); |
171 SVGImageChromeClient& chromeClient = image().chromeClientForTesting(); | 112 SVGImageChromeClient& chromeClient = image().chromeClientForTesting(); |
172 MockTimer* timer = new MockTimer(&chromeClient, &SVGImageChromeClient::anima
tionTimerFired); | 113 Timer<SVGImageChromeClient>* timer = new Timer<SVGImageChromeClient>(&chrome
Client, &SVGImageChromeClient::animationTimerFired); |
173 chromeClient.setTimer(wrapUnique(timer)); | 114 chromeClient.setTimer(wrapUnique(timer)); |
174 | 115 |
175 // Simulate a draw. Cause a frame (timer) to be scheduled. | 116 // Simulate a draw. Cause a frame (timer) to be scheduled. |
176 pumpFrame(); | 117 pumpFrame(); |
177 EXPECT_TRUE(image().hasAnimations()); | 118 EXPECT_TRUE(image().hasAnimations()); |
178 EXPECT_TRUE(timer->isActive()); | 119 EXPECT_TRUE(timer->isActive()); |
179 | 120 |
180 // Reset the animation. This will suspend the timeline but not cancel the | 121 // Reset the animation. This will suspend the timeline but not cancel the |
181 // timer. | 122 // timer. |
182 image().resetAnimation(); | 123 image().resetAnimation(); |
183 EXPECT_TRUE(chromeClient.isSuspended()); | 124 EXPECT_TRUE(chromeClient.isSuspended()); |
184 EXPECT_TRUE(timer->isActive()); | 125 EXPECT_TRUE(timer->isActive()); |
185 | 126 |
186 // Fire the timer/trigger a frame update. The timeline will remain | 127 // Fire the timer/trigger a frame update. The timeline will remain |
187 // suspended and no frame will be scheduled. | 128 // suspended and no frame will be scheduled. |
188 timer->fire(); | 129 // TODO(alexclarke): Move over to using base::TimeDelta and base::TimeTicks
so we can avoid computations like this. |
| 130 testing::runDelayedTasks(1.0 + timer->nextFireInterval() * 1000.0); |
189 EXPECT_TRUE(chromeClient.isSuspended()); | 131 EXPECT_TRUE(chromeClient.isSuspended()); |
190 EXPECT_FALSE(timer->isActive()); | 132 EXPECT_FALSE(timer->isActive()); |
191 | 133 |
192 // Simulate a draw. This should resume the animation again. | 134 // Simulate a draw. This should resume the animation again. |
193 pumpFrame(); | 135 pumpFrame(); |
194 EXPECT_FALSE(chromeClient.isSuspended()); | 136 EXPECT_FALSE(chromeClient.isSuspended()); |
195 EXPECT_TRUE(timer->isActive()); | 137 EXPECT_TRUE(timer->isActive()); |
196 } | 138 } |
197 | 139 |
198 } // namespace blink | 140 } // namespace blink |
OLD | NEW |