[ServiceWorker] Implement WebServiceWorkerContextClient::openWindow().
[chromium-blink-merge.git] / content / renderer / input / input_scroll_elasticity_controller_unittest.cc
blob3adaa055a65ac4cda09b1047b90437971406cb24
1 // Copyright 2014 The Chromium 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.
5 #include "cc/input/input_handler.h"
6 #include "content/renderer/input/input_scroll_elasticity_controller.h"
7 #include "testing/gtest/include/gtest/gtest.h"
8 #include "third_party/WebKit/public/web/WebInputEvent.h"
10 namespace content {
11 namespace {
13 enum Phase {
14 PhaseNone = blink::WebMouseWheelEvent::PhaseNone,
15 PhaseBegan = blink::WebMouseWheelEvent::PhaseBegan,
16 PhaseStationary = blink::WebMouseWheelEvent::PhaseStationary,
17 PhaseChanged = blink::WebMouseWheelEvent::PhaseChanged,
18 PhaseEnded = blink::WebMouseWheelEvent::PhaseEnded,
19 PhaseCancelled = blink::WebMouseWheelEvent::PhaseCancelled,
20 PhaseMayBegin = blink::WebMouseWheelEvent::PhaseMayBegin,
23 class MockScrollElasticityHelper : public cc::ScrollElasticityHelper {
24 public:
25 MockScrollElasticityHelper()
26 : set_stretch_amount_count_(0),
27 request_animate_count_(0) {}
28 ~MockScrollElasticityHelper() override {}
30 // cc::ScrollElasticityHelper implementation:
31 gfx::Vector2dF StretchAmount() const override { return stretch_amount_; }
32 void SetStretchAmount(const gfx::Vector2dF& stretch_amount) override {
33 set_stretch_amount_count_ += 1;
34 stretch_amount_ = stretch_amount;
36 gfx::ScrollOffset ScrollOffset() const override { return scroll_offset_; }
37 gfx::ScrollOffset MaxScrollOffset() const override {
38 return max_scroll_offset_;
40 void ScrollBy(const gfx::Vector2dF& delta) override {
41 scroll_offset_ += gfx::ScrollOffset(delta);
43 void RequestAnimate() override { request_animate_count_ += 1; }
45 // Counters for number of times functions were called.
46 int request_animate_count() const { return request_animate_count_; }
47 int set_stretch_amount_count() const { return set_stretch_amount_count_; }
49 void SetScrollOffsetAndMaxScrollOffset(
50 const gfx::ScrollOffset& scroll_offset,
51 const gfx::ScrollOffset& max_scroll_offset) {
52 scroll_offset_ = scroll_offset;
53 max_scroll_offset_ = max_scroll_offset;
56 private:
57 gfx::Vector2dF stretch_amount_;
58 int set_stretch_amount_count_;
59 int request_animate_count_;
61 gfx::ScrollOffset scroll_offset_;
62 gfx::ScrollOffset max_scroll_offset_;
65 class ScrollElasticityControllerTest : public testing::Test {
66 public:
67 ScrollElasticityControllerTest()
68 : controller_(&helper_),
69 input_event_count_(0),
70 current_time_(base::TimeTicks::FromInternalValue(100000000ull)) {}
71 ~ScrollElasticityControllerTest() override {}
73 void SendMouseWheelEvent(
74 Phase phase,
75 Phase momentum_phase,
76 const gfx::Vector2dF& event_delta = gfx::Vector2dF(),
77 const gfx::Vector2dF& overscroll_delta = gfx::Vector2dF()) {
78 blink::WebMouseWheelEvent event;
79 event.phase = static_cast<blink::WebMouseWheelEvent::Phase>(phase);
80 event.momentumPhase =
81 static_cast<blink::WebMouseWheelEvent::Phase>(momentum_phase);
82 event.deltaX = -event_delta.x();
83 event.deltaY = -event_delta.y();
84 TickCurrentTime();
85 event.timeStampSeconds = (current_time_ - base::TimeTicks()).InSecondsF();
87 cc::InputHandlerScrollResult scroll_result;
88 scroll_result.did_overscroll_root = !overscroll_delta.IsZero();
89 scroll_result.unused_scroll_delta = overscroll_delta;
91 controller_.ObserveWheelEventAndResult(event, scroll_result);
92 input_event_count_ += 1;
95 const base::TimeTicks& TickCurrentTime() {
96 current_time_ += base::TimeDelta::FromSecondsD(1 / 60.f);
97 return current_time_;
99 void TickCurrentTimeAndAnimate() {
100 TickCurrentTime();
101 controller_.Animate(current_time_);
104 MockScrollElasticityHelper helper_;
105 InputScrollElasticityController controller_;
106 int input_event_count_;
107 base::TimeTicks current_time_;
110 // Verify that stretching only occurs in one axis at a time, and that it
111 // is biased to the Y axis.
112 TEST_F(ScrollElasticityControllerTest, Axis) {
113 helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(0, 0),
114 gfx::ScrollOffset(0, 0));
116 // If we push equally in the X and Y directions, we should see a stretch only
117 // in the Y direction.
118 SendMouseWheelEvent(PhaseBegan, PhaseNone);
119 SendMouseWheelEvent(PhaseChanged, PhaseNone, gfx::Vector2dF(10, 10),
120 gfx::Vector2dF(10, 10));
121 EXPECT_EQ(1, helper_.set_stretch_amount_count());
122 EXPECT_EQ(0.f, helper_.StretchAmount().x());
123 EXPECT_LT(0.f, helper_.StretchAmount().y());
124 helper_.SetStretchAmount(gfx::Vector2dF());
125 EXPECT_EQ(2, helper_.set_stretch_amount_count());
126 SendMouseWheelEvent(PhaseEnded, PhaseNone);
127 EXPECT_EQ(0, helper_.request_animate_count());
129 // If we push more in the X direction than the Y direction, we should see a
130 // stretch only in the X direction. This decision should be based on the
131 // input delta, not the actual overscroll delta.
132 SendMouseWheelEvent(PhaseBegan, PhaseNone);
133 SendMouseWheelEvent(PhaseChanged, PhaseNone, gfx::Vector2dF(-25, 10),
134 gfx::Vector2dF(-25, 40));
135 EXPECT_EQ(3, helper_.set_stretch_amount_count());
136 EXPECT_GT(0.f, helper_.StretchAmount().x());
137 EXPECT_EQ(0.f, helper_.StretchAmount().y());
138 helper_.SetStretchAmount(gfx::Vector2dF());
139 EXPECT_EQ(4, helper_.set_stretch_amount_count());
140 SendMouseWheelEvent(PhaseEnded, PhaseNone);
141 EXPECT_EQ(0, helper_.request_animate_count());
144 // Verify that we need a total overscroll delta of at least 10 in a pinned
145 // direction before we start stretching.
146 TEST_F(ScrollElasticityControllerTest, MinimumDeltaBeforeStretch) {
147 // We should not start stretching while we are not pinned in the direction
148 // of the scroll (even if there is an overscroll delta). We have to wait for
149 // the regular scroll to eat all of the events.
150 helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 5),
151 gfx::ScrollOffset(10, 10));
152 SendMouseWheelEvent(PhaseMayBegin, PhaseNone);
153 SendMouseWheelEvent(PhaseBegan, PhaseNone);
154 SendMouseWheelEvent(PhaseChanged, PhaseNone, gfx::Vector2dF(0, 10),
155 gfx::Vector2dF(0, 10));
156 SendMouseWheelEvent(PhaseChanged, PhaseNone, gfx::Vector2dF(0, 10),
157 gfx::Vector2dF(0, 10));
158 EXPECT_EQ(0, helper_.set_stretch_amount_count());
160 // Now pin the -X and +Y direction. The first event will not generate a
161 // stretch
162 // because it is below the delta threshold of 10.
163 helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(0, 10),
164 gfx::ScrollOffset(10, 10));
165 SendMouseWheelEvent(PhaseChanged, PhaseNone, gfx::Vector2dF(0, 10),
166 gfx::Vector2dF(0, 8));
167 EXPECT_EQ(0, helper_.set_stretch_amount_count());
169 // Make the next scroll be in the -X direction more than the +Y direction,
170 // which will erase the memory of the previous unused delta of 8.
171 SendMouseWheelEvent(PhaseChanged, PhaseNone, gfx::Vector2dF(-10, 5),
172 gfx::Vector2dF(-8, 10));
173 EXPECT_EQ(0, helper_.set_stretch_amount_count());
175 // Now push against the pinned +Y direction again by 8. We reset the
176 // previous delta, so this will not generate a stretch.
177 SendMouseWheelEvent(PhaseChanged, PhaseNone, gfx::Vector2dF(0, 10),
178 gfx::Vector2dF(0, 8));
179 EXPECT_EQ(0, helper_.set_stretch_amount_count());
181 // Push against +Y by another 8. This gets us above the delta threshold of
182 // 10, so we should now have had the stretch set, and it should be in the
183 // +Y direction. The scroll in the -X direction should have been forgotten.
184 SendMouseWheelEvent(PhaseChanged, PhaseNone, gfx::Vector2dF(0, 10),
185 gfx::Vector2dF(0, 8));
186 EXPECT_EQ(1, helper_.set_stretch_amount_count());
187 EXPECT_EQ(0.f, helper_.StretchAmount().x());
188 EXPECT_LT(0.f, helper_.StretchAmount().y());
190 // End the gesture. Because there is a non-zero stretch, we should be in the
191 // animated state, and should have had a frame requested.
192 EXPECT_EQ(0, helper_.request_animate_count());
193 SendMouseWheelEvent(PhaseEnded, PhaseNone);
194 EXPECT_EQ(1, helper_.request_animate_count());
197 // Verify that an stretch caused by a momentum scroll will switch to the
198 // animating mode, where input events are ignored, and the stretch is updated
199 // while animating.
200 TEST_F(ScrollElasticityControllerTest, MomentumAnimate) {
201 // Do an active scroll, then switch to the momentum phase and scroll for a
202 // bit.
203 helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 5),
204 gfx::ScrollOffset(10, 10));
205 SendMouseWheelEvent(PhaseBegan, PhaseNone);
206 SendMouseWheelEvent(PhaseChanged, PhaseNone, gfx::Vector2dF(0, -80),
207 gfx::Vector2dF(0, 0));
208 SendMouseWheelEvent(PhaseChanged, PhaseNone, gfx::Vector2dF(0, -80),
209 gfx::Vector2dF(0, 0));
210 SendMouseWheelEvent(PhaseChanged, PhaseNone, gfx::Vector2dF(0, -80),
211 gfx::Vector2dF(0, 0));
212 SendMouseWheelEvent(PhaseEnded, PhaseNone);
213 SendMouseWheelEvent(PhaseNone, PhaseBegan);
214 SendMouseWheelEvent(PhaseNone, PhaseChanged, gfx::Vector2dF(0, -80),
215 gfx::Vector2dF(0, 0));
216 SendMouseWheelEvent(PhaseNone, PhaseChanged, gfx::Vector2dF(0, -80),
217 gfx::Vector2dF(0, 0));
218 SendMouseWheelEvent(PhaseNone, PhaseChanged, gfx::Vector2dF(0, -80),
219 gfx::Vector2dF(0, 0));
220 EXPECT_EQ(0, helper_.set_stretch_amount_count());
222 // Hit the -Y edge and overscroll slightly, but not enough to go over the
223 // threshold to cause a stretch.
224 helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 0),
225 gfx::ScrollOffset(10, 10));
226 SendMouseWheelEvent(PhaseNone, PhaseChanged, gfx::Vector2dF(0, -80),
227 gfx::Vector2dF(0, -8));
228 EXPECT_EQ(0, helper_.set_stretch_amount_count());
229 EXPECT_EQ(0, helper_.request_animate_count());
231 // Take another step, this time going over the threshold. This should update
232 // the stretch amount, and then switch to the animating mode.
233 SendMouseWheelEvent(PhaseNone, PhaseChanged, gfx::Vector2dF(0, -80),
234 gfx::Vector2dF(0, -80));
235 EXPECT_EQ(1, helper_.set_stretch_amount_count());
236 EXPECT_EQ(1, helper_.request_animate_count());
237 EXPECT_GT(-1.f, helper_.StretchAmount().y());
239 // Subsequent momentum events should do nothing.
240 SendMouseWheelEvent(PhaseNone, PhaseChanged, gfx::Vector2dF(0, -80),
241 gfx::Vector2dF(0, -80));
242 SendMouseWheelEvent(PhaseNone, PhaseChanged, gfx::Vector2dF(0, -80),
243 gfx::Vector2dF(0, -80));
244 SendMouseWheelEvent(PhaseNone, PhaseEnded, gfx::Vector2dF(0, -80),
245 gfx::Vector2dF(0, -80));
246 EXPECT_EQ(1, helper_.set_stretch_amount_count());
247 EXPECT_EQ(1, helper_.request_animate_count());
249 // Subsequent animate events should update the stretch amount and request
250 // another frame.
251 TickCurrentTimeAndAnimate();
252 EXPECT_EQ(2, helper_.set_stretch_amount_count());
253 EXPECT_EQ(2, helper_.request_animate_count());
254 EXPECT_GT(-1.f, helper_.StretchAmount().y());
256 // Touching the trackpad (a PhaseMayBegin event) should disable animation.
257 SendMouseWheelEvent(PhaseMayBegin, PhaseNone);
258 TickCurrentTimeAndAnimate();
259 EXPECT_EQ(2, helper_.set_stretch_amount_count());
260 EXPECT_EQ(2, helper_.request_animate_count());
262 // Releasing the trackpad should re-enable animation.
263 SendMouseWheelEvent(PhaseCancelled, PhaseNone);
264 EXPECT_EQ(2, helper_.set_stretch_amount_count());
265 EXPECT_EQ(3, helper_.request_animate_count());
266 TickCurrentTimeAndAnimate();
267 EXPECT_EQ(3, helper_.set_stretch_amount_count());
268 EXPECT_EQ(4, helper_.request_animate_count());
270 // Keep animating frames until the stretch returns to rest.
271 int stretch_count = 3;
272 int animate_count = 4;
273 while (1) {
274 TickCurrentTimeAndAnimate();
275 if (helper_.StretchAmount().IsZero()) {
276 stretch_count += 1;
277 EXPECT_EQ(stretch_count, helper_.set_stretch_amount_count());
278 EXPECT_EQ(animate_count, helper_.request_animate_count());
279 break;
281 stretch_count += 1;
282 animate_count += 1;
283 EXPECT_EQ(stretch_count, helper_.set_stretch_amount_count());
284 EXPECT_EQ(animate_count, helper_.request_animate_count());
287 // After coming to rest, no subsequent animate calls change anything.
288 TickCurrentTimeAndAnimate();
289 EXPECT_EQ(stretch_count, helper_.set_stretch_amount_count());
290 EXPECT_EQ(animate_count, helper_.request_animate_count());
293 // Verify that an stretch opposing a scroll is correctly resolved.
294 TEST_F(ScrollElasticityControllerTest, ReconcileStretchAndScroll) {
295 SendMouseWheelEvent(PhaseBegan, PhaseNone);
297 // Verify completely knocking out the scroll in the -Y direction.
298 helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 5),
299 gfx::ScrollOffset(10, 10));
300 helper_.SetStretchAmount(gfx::Vector2dF(0, -10));
301 controller_.ReconcileStretchAndScroll();
302 EXPECT_EQ(helper_.StretchAmount(), gfx::Vector2dF(0, -5));
303 EXPECT_EQ(helper_.ScrollOffset(), gfx::ScrollOffset(5, 0));
305 // Verify partially knocking out the scroll in the -Y direction.
306 helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 8),
307 gfx::ScrollOffset(10, 10));
308 helper_.SetStretchAmount(gfx::Vector2dF(0, -5));
309 controller_.ReconcileStretchAndScroll();
310 EXPECT_EQ(helper_.StretchAmount(), gfx::Vector2dF(0, 0));
311 EXPECT_EQ(helper_.ScrollOffset(), gfx::ScrollOffset(5, 3));
313 // Verify completely knocking out the scroll in the +X direction.
314 helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 5),
315 gfx::ScrollOffset(10, 10));
316 helper_.SetStretchAmount(gfx::Vector2dF(10, 0));
317 controller_.ReconcileStretchAndScroll();
318 EXPECT_EQ(helper_.StretchAmount(), gfx::Vector2dF(5, 0));
319 EXPECT_EQ(helper_.ScrollOffset(), gfx::ScrollOffset(10, 5));
321 // Verify partially knocking out the scroll in the +X and +Y directions.
322 helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(2, 3),
323 gfx::ScrollOffset(10, 10));
324 helper_.SetStretchAmount(gfx::Vector2dF(5, 5));
325 controller_.ReconcileStretchAndScroll();
326 EXPECT_EQ(helper_.StretchAmount(), gfx::Vector2dF(0, 0));
327 EXPECT_EQ(helper_.ScrollOffset(), gfx::ScrollOffset(7, 8));
330 } // namespace
331 } // namespace content