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

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

Issue 2443613002: Rename classes related to top controls (Closed)
Patch Set: fix test Created 4 years, 1 month 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 "core/frame/TopControls.h"
31
32 #include "core/dom/ClientRect.h"
33 #include "core/frame/FrameHost.h"
34 #include "core/frame/FrameView.h"
35 #include "core/frame/LocalFrame.h"
36 #include "core/frame/VisualViewport.h"
37 #include "core/page/Page.h"
38 #include "platform/testing/URLTestHelpers.h"
39 #include "public/platform/Platform.h"
40 #include "public/platform/WebURLLoaderMockFactory.h"
41 #include "public/web/WebCache.h"
42 #include "public/web/WebElement.h"
43 #include "public/web/WebSettings.h"
44 #include "testing/gmock/include/gmock/gmock.h"
45 #include "testing/gtest/include/gtest/gtest.h"
46 #include "web/WebLocalFrameImpl.h"
47 #include "web/tests/FrameTestHelpers.h"
48
49 namespace blink {
50
51 // These tests cover top controls scrolling on main-thread.
52 // The animation for completing a partial show/hide is done in compositor so
53 // it is not covered here.
54 class TopControlsTest : public testing::Test {
55 public:
56 TopControlsTest() : m_baseURL("http://www.test.com/") {
57 registerMockedHttpURLLoad("large-div.html");
58 registerMockedHttpURLLoad("overflow-scrolling.html");
59 registerMockedHttpURLLoad("iframe-scrolling.html");
60 registerMockedHttpURLLoad("iframe-scrolling-inner.html");
61 registerMockedHttpURLLoad("percent-height.html");
62 registerMockedHttpURLLoad("vh-height.html");
63 registerMockedHttpURLLoad("vh-height-width-800.html");
64 registerMockedHttpURLLoad("vh-height-width-800-extra-wide.html");
65 }
66
67 ~TopControlsTest() override {
68 Platform::current()->getURLLoaderMockFactory()->unregisterAllURLs();
69 WebCache::clear();
70 }
71
72 WebViewImpl* initialize(const std::string& pageName = "large-div.html") {
73 RuntimeEnabledFeatures::setInertTopControlsEnabled(true);
74
75 // Load a page with large body and set viewport size to 400x400 to ensure
76 // main frame is scrollable.
77 m_helper.initializeAndLoad(m_baseURL + pageName, true, nullptr, nullptr,
78 nullptr, &configureSettings);
79
80 webViewImpl()->resize(IntSize(400, 400));
81 return webViewImpl();
82 }
83
84 static void configureSettings(WebSettings* settings) {
85 settings->setJavaScriptEnabled(true);
86 settings->setAcceleratedCompositingEnabled(true);
87 settings->setPreferCompositingToLCDTextEnabled(true);
88 // Android settings
89 settings->setViewportEnabled(true);
90 settings->setViewportMetaEnabled(true);
91 settings->setShrinksViewportContentToFit(true);
92 settings->setMainFrameResizesAreOrientationChanges(true);
93 }
94
95 void registerMockedHttpURLLoad(const std::string& fileName) {
96 URLTestHelpers::registerMockedURLFromBaseURL(
97 WebString::fromUTF8(m_baseURL.c_str()),
98 WebString::fromUTF8(fileName.c_str()));
99 }
100
101 WebGestureEvent generateEvent(WebInputEvent::Type type,
102 int deltaX = 0,
103 int deltaY = 0) {
104 WebGestureEvent event;
105 event.type = type;
106 event.sourceDevice = WebGestureDeviceTouchscreen;
107 event.x = 100;
108 event.y = 100;
109 if (type == WebInputEvent::GestureScrollUpdate) {
110 event.data.scrollUpdate.deltaX = deltaX;
111 event.data.scrollUpdate.deltaY = deltaY;
112 }
113 return event;
114 }
115
116 void verticalScroll(float deltaY) {
117 webViewImpl()->handleInputEvent(
118 generateEvent(WebInputEvent::GestureScrollBegin));
119 webViewImpl()->handleInputEvent(
120 generateEvent(WebInputEvent::GestureScrollUpdate, 0, deltaY));
121 webViewImpl()->handleInputEvent(
122 generateEvent(WebInputEvent::GestureScrollEnd));
123 }
124
125 Element* getElementById(const WebString& id) {
126 return static_cast<Element*>(
127 webViewImpl()->mainFrame()->document().getElementById(id));
128 }
129
130 WebViewImpl* webViewImpl() const { return m_helper.webView(); }
131 LocalFrame* frame() const {
132 return m_helper.webView()->mainFrameImpl()->frame();
133 }
134 VisualViewport& visualViewport() const {
135 return m_helper.webView()->page()->frameHost().visualViewport();
136 }
137
138 private:
139 std::string m_baseURL;
140 FrameTestHelpers::WebViewHelper m_helper;
141 };
142
143 #define EXPECT_SIZE_EQ(expected, actual) \
144 do { \
145 EXPECT_FLOAT_EQ((expected).width(), (actual).width()); \
146 EXPECT_FLOAT_EQ((expected).height(), (actual).height()); \
147 } while (false)
148
149 // Disable these tests on Mac OSX until further investigation.
150 // Local build on Mac is OK but the bot fails. This is not an issue as
151 // Top Controls are currently only used on Android.
152 #if OS(MACOSX)
153 #define MAYBE(test) DISABLED_##test
154 #else
155 #define MAYBE(test) test
156 #endif
157
158 // Scrolling down should hide top controls.
159 TEST_F(TopControlsTest, MAYBE(HideOnScrollDown)) {
160 WebViewImpl* webView = initialize();
161 // initialize top controls to be shown.
162 webView->resizeWithTopControls(webView->size(), 50.f, true);
163 webView->topControls().setShownRatio(1);
164
165 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollBegin));
166 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
167
168 // Top controls should be scrolled partially and page should not scroll.
169 webView->handleInputEvent(
170 generateEvent(WebInputEvent::GestureScrollUpdate, 0, -25.f));
171 EXPECT_FLOAT_EQ(25.f, webView->topControls().contentOffset());
172 EXPECT_SIZE_EQ(ScrollOffset(0, 0), frame()->view()->scrollOffset());
173
174 // Top controls should consume 25px and become hidden. Excess scroll should be
175 // consumed by the page.
176 webView->handleInputEvent(
177 generateEvent(WebInputEvent::GestureScrollUpdate, 0, -40.f));
178 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
179 EXPECT_SIZE_EQ(ScrollOffset(0, 15), frame()->view()->scrollOffset());
180
181 // Only page should consume scroll
182 webView->handleInputEvent(
183 generateEvent(WebInputEvent::GestureScrollUpdate, 0, -20.f));
184 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
185 EXPECT_SIZE_EQ(ScrollOffset(0, 35), frame()->view()->scrollOffset());
186 }
187
188 // Scrolling up should show top controls.
189 TEST_F(TopControlsTest, MAYBE(ShowOnScrollUp)) {
190 WebViewImpl* webView = initialize();
191 // initialize top controls to be hidden.
192 webView->resizeWithTopControls(webView->size(), 50.f, false);
193 webView->topControls().setShownRatio(0);
194
195 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollBegin));
196 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
197
198 webView->handleInputEvent(
199 generateEvent(WebInputEvent::GestureScrollUpdate, 0, 10.f));
200 EXPECT_FLOAT_EQ(10.f, webView->topControls().contentOffset());
201 EXPECT_SIZE_EQ(ScrollOffset(0, 0), frame()->view()->scrollOffset());
202
203 webView->handleInputEvent(
204 generateEvent(WebInputEvent::GestureScrollUpdate, 0, 50.f));
205 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
206 EXPECT_SIZE_EQ(ScrollOffset(0, 0), frame()->view()->scrollOffset());
207 }
208
209 // Scrolling up after previous scroll downs should cause top controls to be
210 // shown only after all previously scrolled down amount is compensated.
211 TEST_F(TopControlsTest, MAYBE(ScrollDownThenUp)) {
212 WebViewImpl* webView = initialize();
213 // initialize top controls to be shown and position page at 100px.
214 webView->resizeWithTopControls(webView->size(), 50.f, true);
215 webView->topControls().setShownRatio(1);
216 frame()->view()->getScrollableArea()->setScrollOffset(ScrollOffset(0, 100),
217 ProgrammaticScroll);
218
219 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollBegin));
220 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
221
222 // Scroll down to completely hide top controls. Excess deltaY (100px) should
223 // be consumed by the page.
224 webView->handleInputEvent(
225 generateEvent(WebInputEvent::GestureScrollUpdate, 0, -150.f));
226 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
227 EXPECT_SIZE_EQ(ScrollOffset(0, 200), frame()->view()->scrollOffset());
228
229 // Scroll up and ensure the top controls does not move until we recover 100px
230 // previously scrolled.
231 webView->handleInputEvent(
232 generateEvent(WebInputEvent::GestureScrollUpdate, 0, 40.f));
233 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
234 EXPECT_SIZE_EQ(ScrollOffset(0, 160), frame()->view()->scrollOffset());
235
236 webView->handleInputEvent(
237 generateEvent(WebInputEvent::GestureScrollUpdate, 0, 60.f));
238 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
239 EXPECT_SIZE_EQ(ScrollOffset(0, 100), frame()->view()->scrollOffset());
240
241 // Now we have hit the threshold so further scroll up should be consumed by
242 // top controls.
243 webView->handleInputEvent(
244 generateEvent(WebInputEvent::GestureScrollUpdate, 0, 30.f));
245 EXPECT_FLOAT_EQ(30.f, webView->topControls().contentOffset());
246 EXPECT_SIZE_EQ(ScrollOffset(0, 100), frame()->view()->scrollOffset());
247
248 // Once top control is fully shown then page should consume any excess scroll.
249 webView->handleInputEvent(
250 generateEvent(WebInputEvent::GestureScrollUpdate, 0, 70.f));
251 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
252 EXPECT_SIZE_EQ(ScrollOffset(0, 50), frame()->view()->scrollOffset());
253 }
254
255 // Scrolling down should always cause visible top controls to start hiding even
256 // if we have been scrolling up previously.
257 TEST_F(TopControlsTest, MAYBE(ScrollUpThenDown)) {
258 WebViewImpl* webView = initialize();
259 // initialize top controls to be hidden and position page at 100px.
260 webView->resizeWithTopControls(webView->size(), 50.f, false);
261 webView->topControls().setShownRatio(0);
262 frame()->view()->getScrollableArea()->setScrollOffset(ScrollOffset(0, 100),
263 ProgrammaticScroll);
264
265 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollBegin));
266 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
267
268 // Scroll up to completely show top controls. Excess deltaY (50px) should be
269 // consumed by the page.
270 webView->handleInputEvent(
271 generateEvent(WebInputEvent::GestureScrollUpdate, 0, 100.f));
272 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
273 EXPECT_SIZE_EQ(ScrollOffset(0, 50), frame()->view()->scrollOffset());
274
275 // Scroll down and ensure only top controls is scrolled
276 webView->handleInputEvent(
277 generateEvent(WebInputEvent::GestureScrollUpdate, 0, -40.f));
278 EXPECT_FLOAT_EQ(10.f, webView->topControls().contentOffset());
279 EXPECT_SIZE_EQ(ScrollOffset(0, 50), frame()->view()->scrollOffset());
280
281 webView->handleInputEvent(
282 generateEvent(WebInputEvent::GestureScrollUpdate, 0, -60.f));
283 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
284 EXPECT_SIZE_EQ(ScrollOffset(0, 100), frame()->view()->scrollOffset());
285 }
286
287 // Top controls should not consume horizontal scroll.
288 TEST_F(TopControlsTest, MAYBE(HorizontalScroll)) {
289 WebViewImpl* webView = initialize();
290 // initialize top controls to be shown.
291 webView->resizeWithTopControls(webView->size(), 50.f, true);
292 webView->topControls().setShownRatio(1);
293
294 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollBegin));
295 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
296
297 // Top controls should not consume horizontal scroll.
298 webView->handleInputEvent(
299 generateEvent(WebInputEvent::GestureScrollUpdate, -110.f, -100.f));
300 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
301 EXPECT_SIZE_EQ(ScrollOffset(110, 50), frame()->view()->scrollOffset());
302
303 webView->handleInputEvent(
304 generateEvent(WebInputEvent::GestureScrollUpdate, -40.f, 0));
305 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
306 EXPECT_SIZE_EQ(ScrollOffset(150, 50), frame()->view()->scrollOffset());
307 }
308
309 // Page scale should not impact top controls scrolling
310 TEST_F(TopControlsTest, MAYBE(PageScaleHasNoImpact)) {
311 WebViewImpl* webView = initialize();
312 webViewImpl()->setDefaultPageScaleLimits(0.25f, 5);
313 webView->setPageScaleFactor(2.0);
314
315 // Initialize top controls to be shown.
316 webView->resizeWithTopControls(webView->size(), 50.f, true);
317 webView->topControls().setShownRatio(1);
318
319 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollBegin));
320 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
321
322 // Top controls should be scrolled partially and page should not scroll.
323 webView->handleInputEvent(
324 generateEvent(WebInputEvent::GestureScrollUpdate, 0, -20.f));
325 EXPECT_FLOAT_EQ(30.f, webView->topControls().contentOffset());
326 EXPECT_SIZE_EQ(ScrollOffset(0, 0),
327 frame()->view()->getScrollableArea()->scrollOffset());
328
329 // Top controls should consume 30px and become hidden. Excess scroll should be
330 // consumed by the page at 2x scale.
331 webView->handleInputEvent(
332 generateEvent(WebInputEvent::GestureScrollUpdate, 0, -70.f));
333 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
334 EXPECT_SIZE_EQ(ScrollOffset(0, 20),
335 frame()->view()->getScrollableArea()->scrollOffset());
336
337 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollEnd));
338
339 // Change page scale and test.
340 webView->setPageScaleFactor(0.5);
341
342 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollBegin));
343 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
344 EXPECT_SIZE_EQ(ScrollOffset(0, 20),
345 frame()->view()->getScrollableArea()->scrollOffset());
346
347 webView->handleInputEvent(
348 generateEvent(WebInputEvent::GestureScrollUpdate, 0, 50.f));
349 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
350 EXPECT_SIZE_EQ(ScrollOffset(0, 20),
351 frame()->view()->getScrollableArea()->scrollOffset());
352
353 // At 0.5x scale scrolling 10px should take us to the top of the page.
354 webView->handleInputEvent(
355 generateEvent(WebInputEvent::GestureScrollUpdate, 0, 10.f));
356 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
357 EXPECT_SIZE_EQ(ScrollOffset(0, 0),
358 frame()->view()->getScrollableArea()->scrollOffset());
359 }
360
361 // Some scroll deltas result in a shownRatio that can't be realized in a
362 // floating-point number. Make sure that if the top controls aren't fully
363 // scrolled, scrollBy doesn't return any excess delta. i.e. There should be no
364 // slippage between the content and top controls.
365 TEST_F(TopControlsTest, MAYBE(FloatingPointSlippage)) {
366 WebViewImpl* webView = initialize();
367 webViewImpl()->setDefaultPageScaleLimits(0.25f, 5);
368 webView->setPageScaleFactor(2.0);
369
370 // Initialize top controls to be shown.
371 webView->resizeWithTopControls(webView->size(), 50.f, true);
372 webView->topControls().setShownRatio(1);
373
374 webView->topControls().scrollBegin();
375 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
376
377 // This will result in a 20px scroll to the top controls so the show ratio
378 // will be 30/50 == 0.6 which is not representible in a float. Make sure
379 // that scroll still consumes the whole delta.
380 FloatSize remainingDelta = webView->topControls().scrollBy(FloatSize(0, 10));
381 EXPECT_EQ(0, remainingDelta.height());
382 }
383
384 // Scrollable subregions should scroll before top controls
385 TEST_F(TopControlsTest, MAYBE(ScrollableSubregionScrollFirst)) {
386 WebViewImpl* webView = initialize("overflow-scrolling.html");
387 webView->resizeWithTopControls(webView->size(), 50.f, true);
388 webView->topControls().setShownRatio(1);
389 frame()->view()->getScrollableArea()->setScrollOffset(ScrollOffset(0, 50),
390 ProgrammaticScroll);
391
392 // Test scroll down
393 // Scroll down should scroll the overflow div first but top controls and main
394 // frame should not scroll.
395 verticalScroll(-800.f);
396 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
397 EXPECT_SIZE_EQ(ScrollOffset(0, 50), frame()->view()->scrollOffset());
398
399 // Continued scroll down should start hiding top controls but main frame
400 // should not scroll.
401 verticalScroll(-40.f);
402 EXPECT_FLOAT_EQ(10.f, webView->topControls().contentOffset());
403 EXPECT_SIZE_EQ(ScrollOffset(0, 50), frame()->view()->scrollOffset());
404
405 // Continued scroll down should scroll down the main frame
406 verticalScroll(-40.f);
407 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
408 EXPECT_SIZE_EQ(ScrollOffset(0, 80), frame()->view()->scrollOffset());
409
410 // Test scroll up
411 // scroll up should scroll overflow div first
412 verticalScroll(800.f);
413 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
414 EXPECT_SIZE_EQ(ScrollOffset(0, 80), frame()->view()->scrollOffset());
415
416 // Continued scroll up should start showing top controls but main frame should
417 // not scroll.
418 verticalScroll(40.f);
419 EXPECT_FLOAT_EQ(40.f, webView->topControls().contentOffset());
420 EXPECT_SIZE_EQ(ScrollOffset(0, 80), frame()->view()->scrollOffset());
421
422 // Continued scroll down up scroll up the main frame
423 verticalScroll(40.f);
424 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
425 EXPECT_SIZE_EQ(ScrollOffset(0, 50), frame()->view()->scrollOffset());
426 }
427
428 // Scrollable iframes should scroll before top controls
429 TEST_F(TopControlsTest, MAYBE(ScrollableIframeScrollFirst)) {
430 WebViewImpl* webView = initialize("iframe-scrolling.html");
431 webView->resizeWithTopControls(webView->size(), 50.f, true);
432 webView->topControls().setShownRatio(1);
433 frame()->view()->getScrollableArea()->setScrollOffset(ScrollOffset(0, 50),
434 ProgrammaticScroll);
435
436 // Test scroll down
437 // Scroll down should scroll the iframe first but top controls and main frame
438 // should not scroll.
439 verticalScroll(-800.f);
440 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
441 EXPECT_SIZE_EQ(ScrollOffset(0, 50), frame()->view()->scrollOffset());
442
443 // Continued scroll down should start hiding top controls but main frame
444 // should not scroll.
445 verticalScroll(-40.f);
446 EXPECT_FLOAT_EQ(10.f, webView->topControls().contentOffset());
447 EXPECT_SIZE_EQ(ScrollOffset(0, 50), frame()->view()->scrollOffset());
448
449 // Continued scroll down should scroll down the main frame
450 verticalScroll(-40.f);
451 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
452 EXPECT_SIZE_EQ(ScrollOffset(0, 80), frame()->view()->scrollOffset());
453
454 // Test scroll up
455 // scroll up should scroll iframe first
456 verticalScroll(800.f);
457 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
458 EXPECT_SIZE_EQ(ScrollOffset(0, 80), frame()->view()->scrollOffset());
459
460 // Continued scroll up should start showing top controls but main frame should
461 // not scroll.
462 verticalScroll(40.f);
463 EXPECT_FLOAT_EQ(40.f, webView->topControls().contentOffset());
464 EXPECT_SIZE_EQ(ScrollOffset(0, 80), frame()->view()->scrollOffset());
465
466 // Continued scroll down up scroll up the main frame
467 verticalScroll(40.f);
468 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
469 EXPECT_SIZE_EQ(ScrollOffset(0, 50), frame()->view()->scrollOffset());
470 }
471
472 // Top controls visibility should remain consistent when height is changed.
473 TEST_F(TopControlsTest, MAYBE(HeightChangeMaintainsVisibility)) {
474 WebViewImpl* webView = initialize();
475 webView->resizeWithTopControls(webView->size(), 20.f, false);
476 webView->topControls().setShownRatio(0);
477
478 webView->resizeWithTopControls(webView->size(), 20.f, false);
479 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
480
481 webView->resizeWithTopControls(webView->size(), 40.f, false);
482 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
483
484 // Scroll up to show top controls.
485 verticalScroll(40.f);
486 EXPECT_FLOAT_EQ(40.f, webView->topControls().contentOffset());
487
488 // Changing height of a fully shown top controls should correctly adjust
489 // content offset
490 webView->resizeWithTopControls(webView->size(), 30.f, false);
491 EXPECT_FLOAT_EQ(30.f, webView->topControls().contentOffset());
492 }
493
494 // Zero delta should not have any effect on top controls.
495 TEST_F(TopControlsTest, MAYBE(ZeroHeightMeansNoEffect)) {
496 WebViewImpl* webView = initialize();
497 webView->resizeWithTopControls(webView->size(), 0, false);
498 webView->topControls().setShownRatio(0);
499 frame()->view()->getScrollableArea()->setScrollOffset(ScrollOffset(0, 100),
500 ProgrammaticScroll);
501
502 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
503
504 verticalScroll(20.f);
505 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
506 EXPECT_SIZE_EQ(ScrollOffset(0, 80), frame()->view()->scrollOffset());
507
508 verticalScroll(-30.f);
509 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
510 EXPECT_SIZE_EQ(ScrollOffset(0, 110), frame()->view()->scrollOffset());
511
512 webView->topControls().setShownRatio(1);
513 EXPECT_FLOAT_EQ(0.f, webView->topControls().contentOffset());
514 }
515
516 // Top controls should not hide when scrolling up past limit
517 TEST_F(TopControlsTest, MAYBE(ScrollUpPastLimitDoesNotHide)) {
518 WebViewImpl* webView = initialize();
519 // Initialize top controls to be shown
520 webView->resizeWithTopControls(webView->size(), 50.f, true);
521 webView->topControls().setShownRatio(1);
522 // Use 2x scale so that both visual viewport and frameview are scrollable
523 webView->setPageScaleFactor(2.0);
524
525 // Fully scroll frameview but visualviewport remains scrollable
526 webView->mainFrame()->setScrollOffset(WebSize(0, 10000));
527 visualViewport().setLocation(FloatPoint(0, 0));
528 verticalScroll(-10.f);
529 EXPECT_FLOAT_EQ(40, webView->topControls().contentOffset());
530
531 webView->topControls().setShownRatio(1);
532 // Fully scroll visual veiwport but frameview remains scrollable
533 webView->mainFrame()->setScrollOffset(WebSize(0, 0));
534 visualViewport().setLocation(FloatPoint(0, 10000));
535 verticalScroll(-20.f);
536 EXPECT_FLOAT_EQ(30, webView->topControls().contentOffset());
537
538 webView->topControls().setShownRatio(1);
539 // Fully scroll both frameview and visual viewport
540 webView->mainFrame()->setScrollOffset(WebSize(0, 10000));
541 visualViewport().setLocation(FloatPoint(0, 10000));
542 verticalScroll(-30.f);
543 // Top controls should not move because neither frameview nor visual viewport
544 // are scrollable
545 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
546 }
547
548 // Top controls should honor its constraints
549 TEST_F(TopControlsTest, MAYBE(StateConstraints)) {
550 WebViewImpl* webView = initialize();
551 webView->resizeWithTopControls(webView->size(), 50.f, false);
552 frame()->view()->getScrollableArea()->setScrollOffset(ScrollOffset(0, 100),
553 ProgrammaticScroll);
554
555 // Setting permitted state should change the content offset to match the
556 // constraint.
557 webView->updateTopControlsState(WebTopControlsShown, WebTopControlsShown,
558 false);
559 EXPECT_FLOAT_EQ(50.f, webView->topControls().contentOffset());
560
561 // Only shown state is permitted so controls cannot hide
562 verticalScroll(-20.f);
563 EXPECT_FLOAT_EQ(50, webView->topControls().contentOffset());
564 EXPECT_SIZE_EQ(ScrollOffset(0, 120), frame()->view()->scrollOffset());
565
566 // Setting permitted state should change content offset to match the
567 // constraint.
568 webView->updateTopControlsState(WebTopControlsHidden, WebTopControlsHidden,
569 false);
570 EXPECT_FLOAT_EQ(0, webView->topControls().contentOffset());
571
572 // Only hidden state is permitted so controls cannot show
573 verticalScroll(30.f);
574 EXPECT_FLOAT_EQ(0, webView->topControls().contentOffset());
575 EXPECT_SIZE_EQ(ScrollOffset(0, 90), frame()->view()->scrollOffset());
576
577 // Setting permitted state to "both" should not change content offset.
578 webView->updateTopControlsState(WebTopControlsBoth, WebTopControlsBoth,
579 false);
580 EXPECT_FLOAT_EQ(0, webView->topControls().contentOffset());
581
582 // Both states are permitted so controls can either show or hide
583 verticalScroll(50.f);
584 EXPECT_FLOAT_EQ(50, webView->topControls().contentOffset());
585 EXPECT_SIZE_EQ(ScrollOffset(0, 90), frame()->view()->scrollOffset());
586
587 verticalScroll(-50.f);
588 EXPECT_FLOAT_EQ(0, webView->topControls().contentOffset());
589 EXPECT_SIZE_EQ(ScrollOffset(0, 90), frame()->view()->scrollOffset());
590
591 // Setting permitted state to "both" should not change an in-flight offset.
592 verticalScroll(20.f);
593 EXPECT_FLOAT_EQ(20, webView->topControls().contentOffset());
594 webView->updateTopControlsState(WebTopControlsBoth, WebTopControlsBoth,
595 false);
596 EXPECT_FLOAT_EQ(20, webView->topControls().contentOffset());
597
598 // An animated state change shouldn't cause a change to the content offset
599 // since it'll be driven from the compositor.
600 webView->updateTopControlsState(WebTopControlsHidden, WebTopControlsHidden,
601 true);
602 EXPECT_FLOAT_EQ(20, webView->topControls().contentOffset());
603
604 webView->updateTopControlsState(WebTopControlsShown, WebTopControlsShown,
605 true);
606 EXPECT_FLOAT_EQ(20, webView->topControls().contentOffset());
607
608 // Setting just the constraint should affect the content offset.
609 webView->updateTopControlsState(WebTopControlsHidden, WebTopControlsBoth,
610 false);
611 EXPECT_FLOAT_EQ(0, webView->topControls().contentOffset());
612
613 webView->updateTopControlsState(WebTopControlsShown, WebTopControlsBoth,
614 false);
615 EXPECT_FLOAT_EQ(50, webView->topControls().contentOffset());
616 }
617
618 // Ensure that top controls do not affect the layout by showing and hiding
619 // except for position: fixed elements.
620 TEST_F(TopControlsTest, MAYBE(DontAffectLayoutHeight)) {
621 // Initialize with the top controls showing.
622 WebViewImpl* webView = initialize("percent-height.html");
623 webView->resizeWithTopControls(WebSize(400, 300), 100.f, true);
624 webView->updateTopControlsState(WebTopControlsBoth, WebTopControlsShown,
625 false);
626 webView->topControls().setShownRatio(1);
627 webView->updateAllLifecyclePhases();
628
629 ASSERT_EQ(100.f, webView->topControls().contentOffset());
630
631 // When the top controls are showing, there's 300px for the layout height so
632 // 50% should result in both the position:fixed and position: absolute divs
633 // having 150px of height.
634 Element* absPos = getElementById(WebString::fromUTF8("abs"));
635 Element* fixedPos = getElementById(WebString::fromUTF8("fixed"));
636 EXPECT_FLOAT_EQ(150.f, absPos->getBoundingClientRect()->height());
637 EXPECT_FLOAT_EQ(150.f, fixedPos->getBoundingClientRect()->height());
638
639 // The layout size on the FrameView should not include the top controls.
640 EXPECT_EQ(300, frame()->view()->layoutSize(IncludeScrollbars).height());
641
642 // Hide the top controls.
643 verticalScroll(-100.f);
644 webView->resizeWithTopControls(WebSize(400, 400), 100.f, false);
645 webView->updateAllLifecyclePhases();
646
647 ASSERT_EQ(0.f, webView->topControls().contentOffset());
648
649 // Hiding the top controls shouldn't change the height of the initial
650 // containing block for non-position: fixed. Position: fixed however should
651 // use the entire height of the viewport however.
652 EXPECT_FLOAT_EQ(150.f, absPos->getBoundingClientRect()->height());
653 EXPECT_FLOAT_EQ(200.f, fixedPos->getBoundingClientRect()->height());
654
655 // The layout size should not change as a result of top controls hiding.
656 EXPECT_EQ(300, frame()->view()->layoutSize(IncludeScrollbars).height());
657 }
658
659 // Ensure that top controls do not affect vh units.
660 TEST_F(TopControlsTest, MAYBE(DontAffectVHUnits)) {
661 // Initialize with the top controls showing.
662 WebViewImpl* webView = initialize("vh-height.html");
663 webView->resizeWithTopControls(WebSize(400, 300), 100.f, true);
664 webView->updateTopControlsState(WebTopControlsBoth, WebTopControlsShown,
665 false);
666 webView->topControls().setShownRatio(1);
667 webView->updateAllLifecyclePhases();
668
669 ASSERT_EQ(100.f, webView->topControls().contentOffset());
670
671 // 'vh' units should be based on the viewport when the top controls are
672 // hidden.
673 Element* absPos = getElementById(WebString::fromUTF8("abs"));
674 Element* fixedPos = getElementById(WebString::fromUTF8("fixed"));
675 EXPECT_FLOAT_EQ(200.f, absPos->getBoundingClientRect()->height());
676 EXPECT_FLOAT_EQ(200.f, fixedPos->getBoundingClientRect()->height());
677
678 // The size used for viewport units should not be reduced by the top
679 // controls.
680 EXPECT_EQ(400, frame()->view()->viewportSizeForViewportUnits().height());
681
682 // Hide the top controls.
683 verticalScroll(-100.f);
684 webView->resizeWithTopControls(WebSize(400, 400), 100.f, false);
685 webView->updateAllLifecyclePhases();
686
687 ASSERT_EQ(0.f, webView->topControls().contentOffset());
688
689 // vh units should be static with respect to the top controls so neighter
690 // <div> should change size are a result of the top controls hiding.
691 EXPECT_FLOAT_EQ(200.f, absPos->getBoundingClientRect()->height());
692 EXPECT_FLOAT_EQ(200.f, fixedPos->getBoundingClientRect()->height());
693
694 // The viewport size used for vh units should not change as a result of top
695 // controls hiding.
696 EXPECT_EQ(400, frame()->view()->viewportSizeForViewportUnits().height());
697 }
698
699 // Ensure that on a legacy page (there's a non-1 minimum scale) 100vh units fill
700 // the viewport, with top controls hidden, when the viewport encompasses the
701 // layout width.
702 TEST_F(TopControlsTest, MAYBE(DontAffectVHUnitsWithScale)) {
703 // Initialize with the top controls showing.
704 WebViewImpl* webView = initialize("vh-height-width-800.html");
705 webView->resizeWithTopControls(WebSize(400, 300), 100.f, true);
706 webView->updateTopControlsState(WebTopControlsBoth, WebTopControlsShown,
707 false);
708 webView->topControls().setShownRatio(1);
709 webView->updateAllLifecyclePhases();
710
711 ASSERT_EQ(100.f, webView->topControls().contentOffset());
712
713 // Device viewport is 400px but the page is width=800 so minimum-scale
714 // should be 0.5. This is also the scale at which the viewport fills the
715 // layout width.
716 ASSERT_EQ(0.5f, webView->minimumPageScaleFactor());
717
718 // We should size vh units so that 100vh fills the viewport at min-scale so
719 // we have to account for the minimum page scale factor. Since both boxes
720 // are 50vh, and layout scale = 0.5, we have a vh viewport of 400 / 0.5 = 800
721 // so we expect 50vh to be 400px.
722 Element* absPos = getElementById(WebString::fromUTF8("abs"));
723 Element* fixedPos = getElementById(WebString::fromUTF8("fixed"));
724 EXPECT_FLOAT_EQ(400.f, absPos->getBoundingClientRect()->height());
725 EXPECT_FLOAT_EQ(400.f, fixedPos->getBoundingClientRect()->height());
726
727 // The size used for viewport units should not be reduced by the top
728 // controls.
729 EXPECT_EQ(800, frame()->view()->viewportSizeForViewportUnits().height());
730
731 // Hide the top controls.
732 verticalScroll(-100.f);
733 webView->resizeWithTopControls(WebSize(400, 400), 100.f, false);
734 webView->updateAllLifecyclePhases();
735
736 ASSERT_EQ(0.f, webView->topControls().contentOffset());
737
738 // vh units should be static with respect to the top controls so neighter
739 // <div> should change size are a result of the top controls hiding.
740 EXPECT_FLOAT_EQ(400.f, absPos->getBoundingClientRect()->height());
741 EXPECT_FLOAT_EQ(400.f, fixedPos->getBoundingClientRect()->height());
742
743 // The viewport size used for vh units should not change as a result of top
744 // controls hiding.
745 EXPECT_EQ(800, frame()->view()->viewportSizeForViewportUnits().height());
746 }
747
748 // Ensure that on a legacy page (there's a non-1 minimum scale) whose viewport
749 // at minimum-scale is larger than the layout size, 100vh units fill the
750 // viewport, with top controls hidden, when the viewport is scaled such that
751 // its width equals the layout width.
752 TEST_F(TopControlsTest, MAYBE(DontAffectVHUnitsUseLayoutSize)) {
753 // Initialize with the top controls showing.
754 WebViewImpl* webView = initialize("vh-height-width-800-extra-wide.html");
755 webView->resizeWithTopControls(WebSize(400, 300), 100.f, true);
756 webView->updateTopControlsState(WebTopControlsBoth, WebTopControlsShown,
757 false);
758 webView->topControls().setShownRatio(1);
759 webView->updateAllLifecyclePhases();
760
761 ASSERT_EQ(100.f, webView->topControls().contentOffset());
762
763 // Device viewport is 400px and page is width=800 but there's an element
764 // that's 1600px wide so the minimum scale is 0.25 to encompass that.
765 ASSERT_EQ(0.25f, webView->minimumPageScaleFactor());
766
767 // The viewport will match the layout width at scale=0.5 so the height used
768 // for vh should be (300 / 0.5) for the layout height + (100 / 0.5) for top
769 // controls = 800.
770 EXPECT_EQ(800, frame()->view()->viewportSizeForViewportUnits().height());
771 }
772
773 // This tests that the viewport remains anchored when top controls are brought
774 // in while the document is fully scrolled. This normally causes clamping of the
775 // visual viewport to keep it bounded by the layout viewport so we're testing
776 // that the viewport anchoring logic is working to keep the view unchanged.
777 TEST_F(TopControlsTest, MAYBE(AnchorViewportDuringTopControlsAdjustment)) {
778 int contentHeight = 1016;
779 int layoutViewportHeight = 500;
780 int visualViewportHeight = 500;
781 int topControlsHeight = 100;
782 int pageScale = 2;
783 int minScale = 1;
784
785 // Initialize with the top controls showing.
786 WebViewImpl* webView = initialize("large-div.html");
787 webViewImpl()->setDefaultPageScaleLimits(minScale, 5);
788 webView->resizeWithTopControls(WebSize(800, layoutViewportHeight),
789 topControlsHeight, true);
790 webView->updateTopControlsState(WebTopControlsBoth, WebTopControlsShown,
791 false);
792 webView->topControls().setShownRatio(1);
793 webView->updateAllLifecyclePhases();
794
795 FrameView* view = frame()->view();
796 ScrollableArea* rootViewport = frame()->view()->getScrollableArea();
797
798 int expectedVisualOffset =
799 ((layoutViewportHeight + topControlsHeight / minScale) * pageScale -
800 (visualViewportHeight + topControlsHeight)) /
801 pageScale;
802 int expectedLayoutOffset =
803 contentHeight - (layoutViewportHeight + topControlsHeight / minScale);
804 int expectedRootOffset = expectedVisualOffset + expectedLayoutOffset;
805
806 // Zoom in to 2X and fully scroll both viewports.
807 webView->setPageScaleFactor(pageScale);
808 {
809 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollBegin));
810 webView->handleInputEvent(
811 generateEvent(WebInputEvent::GestureScrollUpdate, 0, -10000));
812
813 ASSERT_EQ(0.f, webView->topControls().contentOffset());
814
815 EXPECT_EQ(expectedVisualOffset, visualViewport().scrollOffset().height());
816 EXPECT_EQ(expectedLayoutOffset,
817 view->layoutViewportScrollableArea()->scrollOffset().height());
818 EXPECT_EQ(expectedRootOffset, rootViewport->scrollOffset().height());
819
820 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollEnd));
821 }
822
823 // Commit the top controls resize so that the top controls do not shrink the
824 // layout size. This should not have moved any of the viewports.
825 webView->resizeWithTopControls(
826 WebSize(800, layoutViewportHeight + topControlsHeight), topControlsHeight,
827 false);
828 webView->updateAllLifecyclePhases();
829 ASSERT_EQ(expectedVisualOffset, visualViewport().scrollOffset().height());
830 ASSERT_EQ(expectedLayoutOffset,
831 view->layoutViewportScrollableArea()->scrollOffset().height());
832 ASSERT_EQ(expectedRootOffset, rootViewport->scrollOffset().height());
833
834 // Now scroll back up just enough to show the top controls. The top controls
835 // should shrink both viewports but the layout viewport by a greater amount.
836 // This means the visual viewport's offset must be clamped to keep it within
837 // the layout viewport. Make sure we adjust the scroll position to account
838 // for this and keep the visual viewport at the same location relative to
839 // the document (i.e. the user shouldn't see a movement).
840 {
841 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollBegin));
842 webView->handleInputEvent(
843 generateEvent(WebInputEvent::GestureScrollUpdate, 0, 80));
844
845 visualViewport().clampToBoundaries();
846 view->setScrollOffset(view->scrollOffset(), ProgrammaticScroll);
847
848 ASSERT_EQ(80.f, webView->topControls().contentOffset());
849 EXPECT_EQ(expectedRootOffset, rootViewport->scrollOffset().height());
850
851 webView->handleInputEvent(generateEvent(WebInputEvent::GestureScrollEnd));
852 }
853 }
854
855 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/web/tests/RootScrollerTest.cpp ('k') | third_party/WebKit/Source/web/tests/VisualViewportTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698