blob: cef55e3857d8286d47af21ddb5255d2285c34d65 [file] [log] [blame]
Mohsen Izadi9830436c2017-12-21 18:02:461// Copyright 2017 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.
4
5#include "content/browser/renderer_host/overscroll_controller.h"
6
7#include <memory>
8
9#include "base/containers/queue.h"
10#include "content/browser/renderer_host/overscroll_controller_delegate.h"
11#include "content/common/input/synthetic_web_input_event_builders.h"
12#include "content/test/test_overscroll_delegate.h"
13#include "testing/gtest/include/gtest/gtest.h"
chaopeng1d469b02018-04-05 15:41:0714#include "third_party/WebKit/public/platform/WebInputEvent.h"
Mohsen Izadi9830436c2017-12-21 18:02:4615
16namespace content {
17
18class OverscrollControllerTest : public ::testing::Test {
19 protected:
20 OverscrollControllerTest() {}
21 ~OverscrollControllerTest() override {}
22
23 void SetUp() override {
24 delegate_ = std::make_unique<TestOverscrollDelegate>(gfx::Size(400, 300));
25 controller_ = std::make_unique<OverscrollController>();
26 controller_->set_delegate(delegate_.get());
27 }
28
29 void TearDown() override {
30 controller_ = nullptr;
31 delegate_ = nullptr;
32 }
33
34 // Creates and sends a mouse-wheel event to the overscroll controller. Returns
35 // |true| if the event is consumed by the overscroll controller.
36 bool SimulateMouseWheel(float dx, float dy) {
37 DCHECK(!current_event_);
38 current_event_ = std::make_unique<blink::WebMouseWheelEvent>(
39 SyntheticWebMouseWheelEventBuilder::Build(0, 0, dx, dy, 0, true));
40 return controller_->WillHandleEvent(*current_event_);
41 }
42
chaopeng1d469b02018-04-05 15:41:0743 // Creates and sends a gesture event to the overscroll controller. Returns
44 // |true| if the event is consumed by the overscroll controller.
45 bool SimulateGestureEvent(blink::WebInputEvent::Type type,
46 blink::WebGestureDevice source_device) {
47 DCHECK(!current_event_);
48 current_event_ = std::make_unique<blink::WebGestureEvent>(
49 SyntheticWebGestureEventBuilder::Build(type, source_device));
50 return controller_->WillHandleEvent(*current_event_);
51 }
52
Mohsen Izadi9830436c2017-12-21 18:02:4653 // Creates and sends a gesture-scroll-update event to the overscroll
54 // controller. Returns |true| if the event is consumed by the overscroll
55 // controller.
56 bool SimulateGestureScrollUpdate(float dx,
57 float dy,
chaopeng1d469b02018-04-05 15:41:0758 blink::WebGestureDevice device,
59 bool inertial_update) {
Mohsen Izadi9830436c2017-12-21 18:02:4660 DCHECK(!current_event_);
chaopeng1d469b02018-04-05 15:41:0761 auto event = std::make_unique<blink::WebGestureEvent>(
Mohsen Izadi9830436c2017-12-21 18:02:4662 SyntheticWebGestureEventBuilder::BuildScrollUpdate(dx, dy, 0, device));
chaopeng1d469b02018-04-05 15:41:0763 if (inertial_update) {
64 event->data.scroll_update.inertial_phase =
65 blink::WebGestureEvent::kMomentumPhase;
66 }
67 current_event_ = std::move(event);
Mohsen Izadi9830436c2017-12-21 18:02:4668 return controller_->WillHandleEvent(*current_event_);
69 }
70
71 // Notifies the overscroll controller that the current event is ACKed.
72 void SimulateAck(bool processed) {
73 DCHECK(current_event_);
74 controller_->ReceivedEventACK(*current_event_, processed);
75 current_event_ = nullptr;
76 }
77
78 TestOverscrollDelegate* delegate() const { return delegate_.get(); }
79
80 OverscrollMode controller_mode() const {
81 return controller_->overscroll_mode_;
82 }
83
84 OverscrollSource controller_source() const {
85 return controller_->overscroll_source_;
86 }
87
88 private:
89 std::unique_ptr<TestOverscrollDelegate> delegate_;
90 std::unique_ptr<OverscrollController> controller_;
91
92 // Keeps track of the last event that has been processed by the overscroll
93 // controller which is not yet ACKed. Will be null if no event is processed or
94 // the last event is ACKed.
95 std::unique_ptr<blink::WebInputEvent> current_event_;
96
97 DISALLOW_COPY_AND_ASSIGN(OverscrollControllerTest);
98};
99
100// Tests that if a mouse-wheel is consumed by content before overscroll is
101// initiated, overscroll will not initiate anymore.
102TEST_F(OverscrollControllerTest, MouseWheelConsumedPreventsOverscroll) {
103 // Simulate a mouse-wheel, ACK it as not processed, simulate the corresponding
104 // gesture scroll-update event, and ACK it is not processed. Since it is not
105 // passing the start threshold, no overscroll should happen.
106 EXPECT_FALSE(SimulateMouseWheel(10, 0));
107 SimulateAck(false);
chaopeng1d469b02018-04-05 15:41:07108 EXPECT_FALSE(SimulateGestureScrollUpdate(
109 10, 0, blink::kWebGestureDeviceTouchpad, false));
Mohsen Izadi9830436c2017-12-21 18:02:46110 SimulateAck(false);
111 EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
112 EXPECT_EQ(OverscrollSource::NONE, controller_source());
113 EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
114 EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
115
116 // Simulate a mouse-wheel and ACK it as processed. No gesture scroll-update
117 // needs to be simulated. Still no overscroll.
118 EXPECT_FALSE(SimulateMouseWheel(10, 0));
119 SimulateAck(true);
120 EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
121 EXPECT_EQ(OverscrollSource::NONE, controller_source());
122 EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
123 EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
124
125 // Simulate a mouse-wheel and the corresponding gesture scroll-update both
126 // ACKed as not processed. Although the scroll passes overscroll start
127 // threshold, no overscroll should happen since the previous mouse-wheel was
128 // marked as processed.
129 EXPECT_FALSE(SimulateMouseWheel(100, 0));
130 SimulateAck(false);
chaopeng1d469b02018-04-05 15:41:07131 EXPECT_FALSE(SimulateGestureScrollUpdate(
132 100, 0, blink::kWebGestureDeviceTouchpad, false));
Mohsen Izadi9830436c2017-12-21 18:02:46133 SimulateAck(false);
134 EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
135 EXPECT_EQ(OverscrollSource::NONE, controller_source());
136 EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
137 EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
138}
139
chaopeng1d469b02018-04-05 15:41:07140// Verifying the inertial scroll event completes overscroll. After that we will
141// ignore the following inertial scroll events until new sequence start.
142TEST_F(OverscrollControllerTest,
143 InertialGestureScrollUpdateCompletesOverscroll) {
144 EXPECT_FALSE(SimulateGestureEvent(blink::WebInputEvent::kGestureScrollBegin,
145 blink::kWebGestureDeviceTouchpad));
146 SimulateAck(false);
147
148 EXPECT_FALSE(SimulateGestureScrollUpdate(
149 200, 0, blink::kWebGestureDeviceTouchpad, false));
150 SimulateAck(false);
151 EXPECT_EQ(OVERSCROLL_EAST, controller_mode());
152 EXPECT_EQ(OverscrollSource::TOUCHPAD, controller_source());
153 EXPECT_EQ(OVERSCROLL_EAST, delegate()->current_mode());
154 EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
155
156 // Inertial update event complete the overscroll action.
157 EXPECT_FALSE(SimulateGestureScrollUpdate(
158 100, 0, blink::kWebGestureDeviceTouchpad, true));
159 SimulateAck(false);
160 EXPECT_EQ(OVERSCROLL_EAST, controller_mode());
161 EXPECT_EQ(OverscrollSource::TOUCHPAD, controller_source());
162 EXPECT_EQ(OVERSCROLL_EAST, delegate()->current_mode());
163 EXPECT_EQ(OVERSCROLL_EAST, delegate()->completed_mode());
164
165 // Next Inertial update event would be consumed by overscroll controller.
166 EXPECT_TRUE(SimulateGestureScrollUpdate(
167 100, 0, blink::kWebGestureDeviceTouchpad, true));
168}
169
Mohsen Izadi9830436c2017-12-21 18:02:46170} // namespace content