| OLD | NEW |
| (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 | |
| OLD | NEW |