| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2015 Google Inc. All rights reserved. | 2 * Copyright (C) 2015 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 #include "core/frame/TopControls.h" | 30 #include "core/frame/TopControls.h" |
| 31 | 31 |
| 32 #include "core/dom/ClientRect.h" | |
| 33 #include "core/frame/FrameHost.h" | 32 #include "core/frame/FrameHost.h" |
| 34 #include "core/frame/FrameView.h" | 33 #include "core/frame/FrameView.h" |
| 35 #include "core/frame/LocalFrame.h" | 34 #include "core/frame/LocalFrame.h" |
| 36 #include "core/layout/LayoutView.h" | 35 #include "core/layout/LayoutView.h" |
| 37 #include "core/page/Page.h" | 36 #include "core/page/Page.h" |
| 38 #include "platform/testing/URLTestHelpers.h" | 37 #include "platform/testing/URLTestHelpers.h" |
| 39 #include "public/platform/Platform.h" | 38 #include "public/platform/Platform.h" |
| 40 #include "public/platform/WebUnitTestSupport.h" | 39 #include "public/platform/WebUnitTestSupport.h" |
| 41 #include "public/web/WebElement.h" | |
| 42 #include "public/web/WebSettings.h" | 40 #include "public/web/WebSettings.h" |
| 43 #include "testing/gmock/include/gmock/gmock.h" | 41 #include "testing/gmock/include/gmock/gmock.h" |
| 44 #include "testing/gtest/include/gtest/gtest.h" | 42 #include "testing/gtest/include/gtest/gtest.h" |
| 45 #include "web/WebLocalFrameImpl.h" | 43 #include "web/WebLocalFrameImpl.h" |
| 46 #include "web/tests/FrameTestHelpers.h" | 44 #include "web/tests/FrameTestHelpers.h" |
| 47 | 45 |
| 48 namespace blink { | 46 namespace blink { |
| 49 | 47 |
| 50 // These tests cover top controls scrolling on main-thread. | 48 // These tests cover top controls scrolling on main-thread. |
| 51 // The animation for completing a partial show/hide is done in compositor so | 49 // The animation for completing a partial show/hide is done in compositor so |
| 52 // it is not covered here. | 50 // it is not covered here. |
| 53 class TopControlsTest : public testing::Test { | 51 class TopControlsTest : public testing::Test { |
| 54 public: | 52 public: |
| 55 TopControlsTest() | 53 TopControlsTest() |
| 56 : m_baseURL("http://www.test.com/") | 54 : m_baseURL("http://www.test.com/") |
| 57 { | 55 { |
| 58 registerMockedHttpURLLoad("large-div.html"); | 56 registerMockedHttpURLLoad("large-div.html"); |
| 59 registerMockedHttpURLLoad("overflow-scrolling.html"); | 57 registerMockedHttpURLLoad("overflow-scrolling.html"); |
| 60 registerMockedHttpURLLoad("iframe-scrolling.html"); | 58 registerMockedHttpURLLoad("iframe-scrolling.html"); |
| 61 registerMockedHttpURLLoad("iframe-scrolling-inner.html"); | 59 registerMockedHttpURLLoad("iframe-scrolling-inner.html"); |
| 62 registerMockedHttpURLLoad("percent-height.html"); | |
| 63 registerMockedHttpURLLoad("vh-height.html"); | |
| 64 registerMockedHttpURLLoad("vh-height-width-800.html"); | |
| 65 registerMockedHttpURLLoad("vh-height-width-800-extra-wide.html"); | |
| 66 } | 60 } |
| 67 | 61 |
| 68 ~TopControlsTest() override | 62 ~TopControlsTest() override |
| 69 { | 63 { |
| 70 Platform::current()->unitTestSupport()->unregisterAllMockedURLs(); | 64 Platform::current()->unitTestSupport()->unregisterAllMockedURLs(); |
| 71 } | 65 } |
| 72 | 66 |
| 73 WebViewImpl* initialize(const std::string& pageName = "large-div.html") | 67 WebViewImpl* initialize(const std::string& pageName = "large-div.html") |
| 74 { | 68 { |
| 75 // Load a page with large body and set viewport size to 400x400 to ensur
e | 69 // Load a page with large body and set viewport size to 400x400 to ensur
e |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 return event; | 105 return event; |
| 112 } | 106 } |
| 113 | 107 |
| 114 void verticalScroll(float deltaY) | 108 void verticalScroll(float deltaY) |
| 115 { | 109 { |
| 116 webViewImpl()->handleInputEvent(generateEvent(WebInputEvent::GestureScro
llBegin)); | 110 webViewImpl()->handleInputEvent(generateEvent(WebInputEvent::GestureScro
llBegin)); |
| 117 webViewImpl()->handleInputEvent(generateEvent(WebInputEvent::GestureScro
llUpdate, 0, deltaY)); | 111 webViewImpl()->handleInputEvent(generateEvent(WebInputEvent::GestureScro
llUpdate, 0, deltaY)); |
| 118 webViewImpl()->handleInputEvent(generateEvent(WebInputEvent::GestureScro
llEnd)); | 112 webViewImpl()->handleInputEvent(generateEvent(WebInputEvent::GestureScro
llEnd)); |
| 119 } | 113 } |
| 120 | 114 |
| 121 PassRefPtrWillBeRawPtr<Element> getElementById(const WebString& id) | |
| 122 { | |
| 123 return static_cast<PassRefPtrWillBeRawPtr<Element>>( | |
| 124 webViewImpl()->mainFrame()->document().getElementById(id)); | |
| 125 } | |
| 126 | |
| 127 | |
| 128 WebViewImpl* webViewImpl() const { return m_helper.webViewImpl(); } | 115 WebViewImpl* webViewImpl() const { return m_helper.webViewImpl(); } |
| 129 LocalFrame* frame() const { return m_helper.webViewImpl()->mainFrameImpl()->
frame(); } | 116 LocalFrame* frame() const { return m_helper.webViewImpl()->mainFrameImpl()->
frame(); } |
| 130 VisualViewport& visualViewport() const { return m_helper.webViewImpl()->page
()->frameHost().visualViewport(); } | 117 VisualViewport& visualViewport() const { return m_helper.webViewImpl()->page
()->frameHost().visualViewport(); } |
| 131 | 118 |
| 132 private: | 119 private: |
| 133 std::string m_baseURL; | 120 std::string m_baseURL; |
| 134 FrameTestHelpers::WebViewHelper m_helper; | 121 FrameTestHelpers::WebViewHelper m_helper; |
| 135 }; | 122 }; |
| 136 | 123 |
| 137 #define EXPECT_POINT_EQ(expected, actual) \ | 124 #define EXPECT_POINT_EQ(expected, actual) \ |
| (...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 550 // Both states are permitted so controls can either show or hide | 537 // Both states are permitted so controls can either show or hide |
| 551 verticalScroll(50.f); | 538 verticalScroll(50.f); |
| 552 EXPECT_FLOAT_EQ(50, webView->topControls().contentOffset()); | 539 EXPECT_FLOAT_EQ(50, webView->topControls().contentOffset()); |
| 553 EXPECT_POINT_EQ(IntPoint(0, 90), frame()->view()->scrollPosition()); | 540 EXPECT_POINT_EQ(IntPoint(0, 90), frame()->view()->scrollPosition()); |
| 554 | 541 |
| 555 verticalScroll(-50.f); | 542 verticalScroll(-50.f); |
| 556 EXPECT_FLOAT_EQ(0, webView->topControls().contentOffset()); | 543 EXPECT_FLOAT_EQ(0, webView->topControls().contentOffset()); |
| 557 EXPECT_POINT_EQ(IntPoint(0, 90), frame()->view()->scrollPosition()); | 544 EXPECT_POINT_EQ(IntPoint(0, 90), frame()->view()->scrollPosition()); |
| 558 } | 545 } |
| 559 | 546 |
| 560 // Ensure that top controls do not affect the layout by showing and hiding | |
| 561 // except for position: fixed elements. | |
| 562 TEST_F(TopControlsTest, MAYBE(DontAffectLayoutHeight)) | |
| 563 { | |
| 564 // Initialize with the top controls showing. | |
| 565 WebViewImpl* webView = initialize("percent-height.html"); | |
| 566 webView->setTopControlsHeight(100.f, true); | |
| 567 webView->updateTopControlsState( | |
| 568 WebTopControlsBoth, WebTopControlsShown, false); | |
| 569 webView->topControls().setShownRatio(1); | |
| 570 webView->resize(WebSize(400, 300)); | |
| 571 webView->updateAllLifecyclePhases(); | |
| 572 | |
| 573 ASSERT_EQ(100.f, webView->topControls().contentOffset()); | |
| 574 | |
| 575 // When the top controls are showing, there's 300px for the layout height so | |
| 576 // 50% should result in both the position:fixed and position: absolute divs | |
| 577 // having 150px of height. | |
| 578 RefPtrWillBeRawPtr<Element> absPos = | |
| 579 getElementById(WebString::fromUTF8("abs")); | |
| 580 RefPtrWillBeRawPtr<Element> fixedPos = | |
| 581 getElementById(WebString::fromUTF8("fixed")); | |
| 582 EXPECT_FLOAT_EQ(150.f, absPos->getBoundingClientRect()->height()); | |
| 583 EXPECT_FLOAT_EQ(150.f, fixedPos->getBoundingClientRect()->height()); | |
| 584 | |
| 585 // The layout size on the FrameView should not include the top controls. | |
| 586 EXPECT_EQ(300, frame()->view()->layoutSize(IncludeScrollbars).height()); | |
| 587 | |
| 588 // Hide the top controls. | |
| 589 verticalScroll(-100.f); | |
| 590 webView->setTopControlsHeight(100.f, false); | |
| 591 webView->resize(WebSize(400, 400)); | |
| 592 webView->updateAllLifecyclePhases(); | |
| 593 | |
| 594 ASSERT_EQ(0.f, webView->topControls().contentOffset()); | |
| 595 | |
| 596 // Hiding the top controls shouldn't change the height of the initial | |
| 597 // containing block for non-position: fixed. Position: fixed however should | |
| 598 // use the entire height of the viewport however. | |
| 599 EXPECT_FLOAT_EQ(150.f, absPos->getBoundingClientRect()->height()); | |
| 600 EXPECT_FLOAT_EQ(200.f, fixedPos->getBoundingClientRect()->height()); | |
| 601 | |
| 602 // The layout size should not change as a result of top controls hiding. | |
| 603 EXPECT_EQ(300, frame()->view()->layoutSize(IncludeScrollbars).height()); | |
| 604 } | |
| 605 | |
| 606 // Ensure that top controls do not affect vh units. | |
| 607 TEST_F(TopControlsTest, MAYBE(DontAffectVHUnits)) | |
| 608 { | |
| 609 // Initialize with the top controls showing. | |
| 610 WebViewImpl* webView = initialize("vh-height.html"); | |
| 611 webView->setTopControlsHeight(100.f, true); | |
| 612 webView->updateTopControlsState( | |
| 613 WebTopControlsBoth, WebTopControlsShown, false); | |
| 614 webView->topControls().setShownRatio(1); | |
| 615 webView->resize(WebSize(400, 300)); | |
| 616 webView->updateAllLifecyclePhases(); | |
| 617 | |
| 618 ASSERT_EQ(100.f, webView->topControls().contentOffset()); | |
| 619 | |
| 620 // 'vh' units should be based on the viewport when the top controls are | |
| 621 // hidden. | |
| 622 RefPtrWillBeRawPtr<Element> absPos = | |
| 623 getElementById(WebString::fromUTF8("abs")); | |
| 624 RefPtrWillBeRawPtr<Element> fixedPos = | |
| 625 getElementById(WebString::fromUTF8("fixed")); | |
| 626 EXPECT_FLOAT_EQ(200.f, absPos->getBoundingClientRect()->height()); | |
| 627 EXPECT_FLOAT_EQ(200.f, fixedPos->getBoundingClientRect()->height()); | |
| 628 | |
| 629 // The size used for viewport units should not be reduced by the top | |
| 630 // controls. | |
| 631 EXPECT_EQ(400, frame()->view()->viewportSizeForViewportUnits().height()); | |
| 632 | |
| 633 // Hide the top controls. | |
| 634 verticalScroll(-100.f); | |
| 635 webView->setTopControlsHeight(100.f, false); | |
| 636 webView->resize(WebSize(400, 400)); | |
| 637 webView->updateAllLifecyclePhases(); | |
| 638 | |
| 639 ASSERT_EQ(0.f, webView->topControls().contentOffset()); | |
| 640 | |
| 641 // vh units should be static with respect to the top controls so neighter | |
| 642 // <div> should change size are a result of the top controls hiding. | |
| 643 EXPECT_FLOAT_EQ(200.f, absPos->getBoundingClientRect()->height()); | |
| 644 EXPECT_FLOAT_EQ(200.f, fixedPos->getBoundingClientRect()->height()); | |
| 645 | |
| 646 // The viewport size used for vh units should not change as a result of top | |
| 647 // controls hiding. | |
| 648 EXPECT_EQ(400, frame()->view()->viewportSizeForViewportUnits().height()); | |
| 649 } | |
| 650 | |
| 651 // Ensure that on a legacy page (there's a non-1 minimum scale) 100vh units fill | |
| 652 // the viewport, with top controls hidden, when the viewport encompasses the | |
| 653 // layout width. | |
| 654 TEST_F(TopControlsTest, MAYBE(DontAffectVHUnitsWithScale)) | |
| 655 { | |
| 656 // Initialize with the top controls showing. | |
| 657 WebViewImpl* webView = initialize("vh-height-width-800.html"); | |
| 658 webView->setTopControlsHeight(100.f, true); | |
| 659 webView->updateTopControlsState( | |
| 660 WebTopControlsBoth, WebTopControlsShown, false); | |
| 661 webView->topControls().setShownRatio(1); | |
| 662 webView->resize(WebSize(400, 300)); | |
| 663 webView->updateAllLifecyclePhases(); | |
| 664 | |
| 665 ASSERT_EQ(100.f, webView->topControls().contentOffset()); | |
| 666 | |
| 667 // Device viewport is 400px but the page is width=800 so minimum-scale | |
| 668 // should be 0.5. This is also the scale at which the viewport fills the | |
| 669 // layout width. | |
| 670 ASSERT_EQ(0.5f, webView->minimumPageScaleFactor()); | |
| 671 | |
| 672 // We should size vh units so that 100vh fills the viewport at min-scale so | |
| 673 // we have to account for the minimum page scale factor. Since both boxes | |
| 674 // are 50vh, and layout scale = 0.5, we have a vh viewport of 400 / 0.5 = 80
0 | |
| 675 // so we expect 50vh to be 400px. | |
| 676 RefPtrWillBeRawPtr<Element> absPos = | |
| 677 getElementById(WebString::fromUTF8("abs")); | |
| 678 RefPtrWillBeRawPtr<Element> fixedPos = | |
| 679 getElementById(WebString::fromUTF8("fixed")); | |
| 680 EXPECT_FLOAT_EQ(400.f, absPos->getBoundingClientRect()->height()); | |
| 681 EXPECT_FLOAT_EQ(400.f, fixedPos->getBoundingClientRect()->height()); | |
| 682 | |
| 683 // The size used for viewport units should not be reduced by the top | |
| 684 // controls. | |
| 685 EXPECT_EQ(800, frame()->view()->viewportSizeForViewportUnits().height()); | |
| 686 | |
| 687 // Hide the top controls. | |
| 688 verticalScroll(-100.f); | |
| 689 webView->setTopControlsHeight(100.f, false); | |
| 690 webView->resize(WebSize(400, 400)); | |
| 691 webView->updateAllLifecyclePhases(); | |
| 692 | |
| 693 ASSERT_EQ(0.f, webView->topControls().contentOffset()); | |
| 694 | |
| 695 // vh units should be static with respect to the top controls so neighter | |
| 696 // <div> should change size are a result of the top controls hiding. | |
| 697 EXPECT_FLOAT_EQ(400.f, absPos->getBoundingClientRect()->height()); | |
| 698 EXPECT_FLOAT_EQ(400.f, fixedPos->getBoundingClientRect()->height()); | |
| 699 | |
| 700 // The viewport size used for vh units should not change as a result of top | |
| 701 // controls hiding. | |
| 702 EXPECT_EQ(800, frame()->view()->viewportSizeForViewportUnits().height()); | |
| 703 } | |
| 704 | |
| 705 // Ensure that on a legacy page (there's a non-1 minimum scale) whose viewport | |
| 706 // at minimum-scale is larger than the layout size, 100vh units fill the | |
| 707 // viewport, with top controls hidden, when the viewport is scaled such that | |
| 708 // its width equals the layout width. | |
| 709 TEST_F(TopControlsTest, MAYBE(DontAffectVHUnitsUseLayoutSize)) | |
| 710 { | |
| 711 // Initialize with the top controls showing. | |
| 712 WebViewImpl* webView = initialize("vh-height-width-800-extra-wide.html"); | |
| 713 webView->setTopControlsHeight(100.f, true); | |
| 714 webView->updateTopControlsState( | |
| 715 WebTopControlsBoth, WebTopControlsShown, false); | |
| 716 webView->topControls().setShownRatio(1); | |
| 717 webView->resize(WebSize(400, 300)); | |
| 718 webView->updateAllLifecyclePhases(); | |
| 719 | |
| 720 ASSERT_EQ(100.f, webView->topControls().contentOffset()); | |
| 721 | |
| 722 // Device viewport is 400px and page is width=800 but there's an element | |
| 723 // that's 1600px wide so the minimum scale is 0.25 to encompass that. | |
| 724 ASSERT_EQ(0.25f, webView->minimumPageScaleFactor()); | |
| 725 | |
| 726 // The viewport will match the layout width at scale=0.5 so the height used | |
| 727 // for vh should be (300 / 0.5) for the layout height + (100 / 0.5) for top | |
| 728 // controls = 800. | |
| 729 EXPECT_EQ(800, frame()->view()->viewportSizeForViewportUnits().height()); | |
| 730 } | |
| 731 | |
| 732 } // namespace blink | 547 } // namespace blink |
| OLD | NEW |