Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(40)

Side by Side Diff: Source/web/tests/TopControlsTest.cpp

Issue 893683003: Implement top controls show/hide functionality for main thread scrolling (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Address nitp Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2015 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 #include "config.h"
31 #include "core/frame/TopControls.h"
32
33 #include "core/frame/LocalFrame.h"
34 #include "core/rendering/RenderView.h"
35 #include "core/testing/URLTestHelpers.h"
36 #include "public/platform/Platform.h"
37 #include "public/platform/WebUnitTestSupport.h"
38 #include "public/web/WebSettings.h"
39 #include "web/WebLocalFrameImpl.h"
40 #include "web/tests/FrameTestHelpers.h"
41
42 #include <gmock/gmock.h>
43 #include <gtest/gtest.h>
44
45 using namespace blink;
46
47 namespace {
48
49 // These tests cover top controls scrolling on main-thread.
50 // The animation for completing a partial show/hide is done in compositor so
51 // it is not covered here.
52 class TopControlsTest : public testing::Test {
53 public:
54 TopControlsTest()
55 : m_baseURL("http://www.test.com/")
56 {
57 registerMockedHttpURLLoad("large-div.html");
58 registerMockedHttpURLLoad("overflow-scrolling.html");
59 }
60
61 ~TopControlsTest()
62 {
63 Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
64 }
65
66 WebViewImpl* initialize(const std::string& pageName = "large-div.html")
67 {
68 // Load a page with large body and set viewport size to 400x400 to ensur e
69 // main frame is scrollable.
70 m_helper.initializeAndLoad(m_baseURL + pageName, true, 0, 0, &configureS ettings);
71
72 webViewImpl()->resize(IntSize(400, 400));
73 return webViewImpl();
74 }
75
76 static void configureSettings(WebSettings* settings)
77 {
78 settings->setJavaScriptEnabled(true);
79 settings->setAcceleratedCompositingEnabled(true);
80 settings->setPreferCompositingToLCDTextEnabled(true);
81 settings->setPinchVirtualViewportEnabled(true);
82 // Android settings
83 settings->setViewportEnabled(true);
84 settings->setViewportMetaEnabled(true);
85 settings->setShrinksViewportContentToFit(true);
86 settings->setMainFrameResizesAreOrientationChanges(true);
87 }
88
89 void registerMockedHttpURLLoad(const std::string& fileName)
90 {
91 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseU RL.c_str()), WebString::fromUTF8(fileName.c_str()));
92 }
93
94 WebGestureEvent generateEvent(WebInputEvent::Type type, int deltaX = 0, int deltaY = 0)
95 {
96 WebGestureEvent event;
97 event.type = type;
98 event.x = 100;
99 event.y = 100;
100 if (type == WebInputEvent::GestureScrollUpdate) {
101 event.data.scrollUpdate.deltaX = deltaX;
102 event.data.scrollUpdate.deltaY = deltaY;
103 }
104 return event;
105 }
106
107 void verticalScroll(float deltaY)
108 {
109 webViewImpl()->handleInputEvent(generateEvent(WebInputEvent::GestureScro llBegin));
110 webViewImpl()->handleInputEvent(generateEvent(WebInputEvent::GestureScro llUpdate, 0, deltaY));
111 webViewImpl()->handleInputEvent(generateEvent(WebInputEvent::GestureScro llEnd));
112 }
113
114 WebViewImpl* webViewImpl() const { return m_helper.webViewImpl(); }
115 LocalFrame* frame() const { return m_helper.webViewImpl()->mainFrameImpl()-> frame(); }
116
117 private:
118 std::string m_baseURL;
119 FrameTestHelpers::WebViewHelper m_helper;
120
121 // To prevent platform differences in content rendering, use mock
122 // scrollbars. This is especially needed for Mac, where the presence
123 // or absence of a mouse will change frame sizes because of different
124 // scrollbar themes.
125 FrameTestHelpers::UseMockScrollbarSettings m_useMockScrollbars;
126 };
127
128 #define EXPECT_POINT_EQ(expected, actual) \
129 do { \
130 EXPECT_DOUBLE_EQ((expected).x(), (actual).x()); \
131 EXPECT_DOUBLE_EQ((expected).y(), (actual).y()); \
132 } while (false)
133
134 // Disable these tests on Mac OSX until further investigation.
135 // Local build on Mac is OK but the bot fails. This is not an issue as
136 // Top Controls are currently only used on Android.
Rick Byers 2015/02/19 16:38:39 This might have something to do with the Mac-speci
majidvp 2015/02/19 19:18:02 I will look into the rubber-band as a potential ca
137 #if !OS(MACOSX)
138
139 // Scrolling down should hide top controls.
140 TEST_F(TopControlsTest, HideOnScrollDown)
141 {
142 WebViewImpl* webView = initialize();
143 // initialize top controls to be shown.
144 webView->setTopControlsHeight(50.f, true);
145 webView->topControls().setShownRatio(1);
146
147 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollBegin));
148 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
149
150 // Top controls should be scrolled partially and page should not scroll.
151 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollUpdate, 0, -20.f));
152 EXPECT_FLOAT_EQ(30.f, webView->topControls().contentOffset());
153 EXPECT_POINT_EQ(IntPoint(0, 0), frame()->view()->scrollPosition());
154
155 // Top controls should consume 30px and become hidden. Excess scroll should be consumed by the page.
156 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollUpdate, 0, -40.f));
157 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
158 EXPECT_POINT_EQ(IntPoint(0, 10), frame()->view()->scrollPosition());
159
160 // Only page should consume scroll
161 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollUpdate, 0, -20.f));
162 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
163 EXPECT_POINT_EQ(IntPoint(0, 30), frame()->view()->scrollPosition());
164 }
165
166 // Scrolling up should show top controls.
167 TEST_F(TopControlsTest, ShowOnScrollUp)
168 {
169 WebViewImpl* webView = initialize();
170 // initialize top controls to be hidden.
171 webView->setTopControlsHeight(50.f, false);
172 webView->topControls().setShownRatio(0);
173
174 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollBegin));
175 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
176
177 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollUpdate, 0, 10.f));
178 EXPECT_FLOAT_EQ(10.f, webView->topControls().contentOffset());
179 EXPECT_POINT_EQ(IntPoint(0, 0), frame()->view()->scrollPosition());
180
181 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollUpdate, 0, 50.f));
182 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
183 EXPECT_POINT_EQ(IntPoint(0, 0), frame()->view()->scrollPosition());
184 }
185
186 // Scrolling up after previous scroll downs should cause top controls to be
187 // shown only after all previously scrolled down amount is compensated.
188 TEST_F(TopControlsTest, ScrollDownThenUp)
189 {
190 WebViewImpl* webView = initialize();
191 // initialize top controls to be shown and position page at 100px.
192 webView->setTopControlsHeight(50.f, true);
193 webView->topControls().setShownRatio(1);
194 frame()->view()->setScrollPosition(IntPoint(0, 100));
195
196 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollBegin));
197 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
198
199 // Scroll down to completely hide top controls. Excess deltaY (100px) should be consumed by the page.
200 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollUpdate, 0, -150.f));
201 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
202 EXPECT_POINT_EQ(IntPoint(0, 200), frame()->view()->scrollPosition());
203
204 // Scroll up and ensure the top controls does not move until we recover 100p x previously scrolled.
205 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollUpdate, 0, 40.f));
206 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
207 EXPECT_POINT_EQ(IntPoint(0, 160), frame()->view()->scrollPosition());
208
209 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollUpdate, 0, 60.f));
210 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
211 EXPECT_POINT_EQ(IntPoint(0, 100), frame()->view()->scrollPosition());
212
213 // Now we have hit the threshold so further scroll up should be consumed by top controls.
214 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollUpdate, 0, 30.f));
215 EXPECT_FLOAT_EQ(30.f, webView->topControls().contentOffset());
216 EXPECT_POINT_EQ(IntPoint(0, 100), frame()->view()->scrollPosition());
217
218 // Once top control is fully shown then page should consume any excess scrol l.
219 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollUpdate, 0, 70.f));
220 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
221 EXPECT_POINT_EQ(IntPoint(0, 50), frame()->view()->scrollPosition());
222 }
223
224 // Scrolling down should always cause visible top controls to start hiding even
225 // if we have been scrolling up previously.
226 TEST_F(TopControlsTest, ScrollUpThenDown)
227 {
228 WebViewImpl* webView = initialize();
229 // initialize top controls to be hidden and position page at 100px.
230 webView->setTopControlsHeight(50.f, false);
231 webView->topControls().setShownRatio(0);
232 frame()->view()->setScrollPosition(IntPoint(0, 100));
233
234 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollBegin));
235 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
236
237 // Scroll up to completely show top controls. Excess deltaY (50px) should be consumed by the page.
238 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollUpdate, 0, 100.f));
239 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
240 EXPECT_POINT_EQ(IntPoint(0, 50), frame()->view()->scrollPosition());
241
242 // Scroll down and ensure only top controls is scrolled
243 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollUpdate, 0, -40.f));
244 EXPECT_FLOAT_EQ(10.f, webView->topControls().contentOffset());
245 EXPECT_POINT_EQ(IntPoint(0, 50), frame()->view()->scrollPosition());
246
247 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollUpdate, 0, -60.f));
248 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
249 EXPECT_POINT_EQ(IntPoint(0, 100), frame()->view()->scrollPosition());
250 }
251
252 // Top controls should not consume horizontal scroll.
253 TEST_F(TopControlsTest, HorizontalScroll)
254 {
255 WebViewImpl* webView = initialize();
256 // initialize top controls to be shown.
257 webView->setTopControlsHeight(50.f, true);
258 webView->topControls().setShownRatio(1);
259
260 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollBegin));
261 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
262
263 // Top controls should not consume horizontal scroll.
264 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollUpdate, -110.f, -100.f));
265 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
266 EXPECT_POINT_EQ(IntPoint(110, 50), frame()->view()->scrollPosition());
267
268 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollUpdate, -40.f, 0));
269 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
270 EXPECT_POINT_EQ(IntPoint(150, 50), frame()->view()->scrollPosition());
271 }
272
273 // Scrollables subregions should scroll before top controls
Rick Byers 2015/02/19 16:38:39 You've also verified this works properly with ifra
majidvp 2015/02/19 19:18:02 It works with iframes and I added a test to cover
274 TEST_F(TopControlsTest, ScrollableSubregionScrollFirst)
275 {
276 WebViewImpl* webView = initialize("overflow-scrolling.html");
277 webView->setTopControlsHeight(50.f, true);
278 webView->topControls().setShownRatio(1);
279 frame()->view()->setScrollPosition(IntPoint(0, 50));
280
281 // Test scroll down
282 // Scroll down should scroll the overflow div first but top controls and mai n frame should not scroll.
283 verticalScroll(-800.f);
284 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
285 EXPECT_POINT_EQ(IntPoint(0, 50), frame()->view()->scrollPosition());
286
287 // Continued scroll down should start hiding top controls but main frame sho uld not scroll.
288 verticalScroll(-40.f);
289 EXPECT_FLOAT_EQ(10.f, webView->topControls().contentOffset());
290 EXPECT_POINT_EQ(IntPoint(0, 50), frame()->view()->scrollPosition());
291
292 // Continued scroll down should scroll down the main frame
293 verticalScroll(-40.f);
294 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
295 EXPECT_POINT_EQ(IntPoint(0, 80), frame()->view()->scrollPosition());
296
297 // Test scroll up
298 // scroll up should scroll overflow div first
299 verticalScroll(800.f);
300 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
301 EXPECT_POINT_EQ(IntPoint(0, 80), frame()->view()->scrollPosition());
302
303 // Continued scroll up should start showing top controls but main frame shou ld not scroll.
304 verticalScroll(40.f);
305 EXPECT_FLOAT_EQ(40.f, webView->topControls().contentOffset());
306 EXPECT_POINT_EQ(IntPoint(0, 80), frame()->view()->scrollPosition());
307
308 // Continued scroll down up scroll up the main frame
309 verticalScroll(40.f);
310 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
311 EXPECT_POINT_EQ(IntPoint(0, 50), frame()->view()->scrollPosition());
312 }
313
314 // Top controls visibility should remain consistent when height is changed.
315 TEST_F(TopControlsTest, HeightChangeMaintainsVisibility)
316 {
317 WebViewImpl* webView = initialize();
318 webView->setTopControlsHeight(20.f, false);
319 webView->topControls().setShownRatio(0);
320
321 webView->setTopControlsHeight(20.f, false);
322 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
323
324 webView->setTopControlsHeight(40.f, false);
325 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
326
327 // Scroll up to show top controls.
328 verticalScroll(40.f);
329 EXPECT_FLOAT_EQ(40.f, webView->topControls().contentOffset());
330
331 // Changing height of a fully shown top controls should correctly adjust con tent offset
332 webView->setTopControlsHeight(30.f, false);
333 EXPECT_FLOAT_EQ(30.f, webView->topControls().contentOffset());
334 }
335
336 // Zero delta should not have any effect on top controls.
337 TEST_F(TopControlsTest, ZeroHeightMeansNoEffect)
338 {
339 WebViewImpl* webView = initialize();
340 webView->setTopControlsHeight(0, false);
341 webView->topControls().setShownRatio(0);
342 frame()->view()->setScrollPosition(IntPoint(0, 100));
343
344 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
345
346 verticalScroll(20.f);
347 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
348 EXPECT_POINT_EQ(IntPoint(0, 80), frame()->view()->scrollPosition());
349
350 verticalScroll(-30.f);
351 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
352 EXPECT_POINT_EQ(IntPoint(0, 110), frame()->view()->scrollPosition());
353
354 webView->topControls().setShownRatio(1);
355 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
356 }
357
358 // Top controls should honor its constraints
359 TEST_F(TopControlsTest, StateConstraints)
360 {
361 WebViewImpl* webView = initialize();
362 webView->setTopControlsHeight(50.f, false);
363 frame()->view()->setScrollPosition(IntPoint(0, 100));
364
365 // Setting permitted state should not change content offset
366 webView->updateTopControlsState(WebTopControlsShown, WebTopControlsShown, fa lse);
367 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
368
369 // Showing is permitted
370 webView->topControls().setShownRatio(1);
371 EXPECT_FLOAT_EQ(50, webView->topControls().contentOffset());
372
373 // Only shown state is permitted so controls cannot hide
374 verticalScroll(-20.f);
375 EXPECT_FLOAT_EQ(50, webView->topControls().contentOffset());
376 EXPECT_POINT_EQ(IntPoint(0, 120), frame()->view()->scrollPosition());
377
378 // Setting permitted state should not change content offset
379 webView->updateTopControlsState(WebTopControlsHidden, WebTopControlsHidden, false);
380 EXPECT_FLOAT_EQ(50, webView->topControls().contentOffset());
381
382 // Hiding is permitted
383 webView->topControls().setShownRatio(0);
384 EXPECT_FLOAT_EQ(0, webView->topControls().contentOffset());
385
386 // Only hidden state is permitted so controls cannot show
387 verticalScroll(30.f);
388 EXPECT_FLOAT_EQ(0, webView->topControls().contentOffset());
389 EXPECT_POINT_EQ(IntPoint(0, 90), frame()->view()->scrollPosition());
390
391 // Setting permitted state should not change content offset
392 webView->updateTopControlsState(WebTopControlsBoth, WebTopControlsBoth, fals e);
393 EXPECT_FLOAT_EQ(0, webView->topControls().contentOffset());
394
395 // Both states are permitted so controls can either show or hide
396 verticalScroll(50.f);
397 EXPECT_FLOAT_EQ(50, webView->topControls().contentOffset());
398 EXPECT_POINT_EQ(IntPoint(0, 90), frame()->view()->scrollPosition());
399
400 verticalScroll(-50.f);
401 EXPECT_FLOAT_EQ(0, webView->topControls().contentOffset());
402 EXPECT_POINT_EQ(IntPoint(0, 90), frame()->view()->scrollPosition());
403 }
404
405 #endif
406 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698