| 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 |