Index: third_party/WebKit/Source/web/tests/VisualViewportTest.cpp |
diff --git a/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp b/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp |
index a3d93f8b9213da36344ea7898fbb32fefe6c90a5..bfb02439d49014a4410cb0f9db3b82ad795b2fd9 100644 |
--- a/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp |
+++ b/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp |
@@ -16,6 +16,7 @@ |
#include "core/layout/api/LayoutViewItem.h" |
#include "core/layout/compositing/PaintLayerCompositor.h" |
#include "core/page/Page.h" |
+#include "core/paint/PaintLayer.h" |
#include "platform/PlatformGestureEvent.h" |
#include "platform/geometry/DoublePoint.h" |
#include "platform/geometry/DoubleRect.h" |
@@ -96,6 +97,7 @@ using namespace blink; |
using ::testing::_; |
using ::testing::PrintToString; |
using ::testing::Mock; |
+using blink::URLTestHelpers::toKURL; |
namespace blink { |
::std::ostream& operator<<(::std::ostream& os, const WebContextMenuData& data) { |
@@ -2080,4 +2082,288 @@ TEST_P(VisualViewportTest, RotationAnchoringWithRootScroller) { |
RuntimeEnabledFeatures::setSetRootScrollerEnabled(wasRootScrollerEnabled); |
} |
+static void configureAndroidCompositing(WebSettings* settings) { |
+ settings->setAcceleratedCompositingEnabled(true); |
+ settings->setPreferCompositingToLCDTextEnabled(true); |
+ settings->setViewportMetaEnabled(true); |
+ settings->setViewportEnabled(true); |
+ settings->setMainFrameResizesAreOrientationChanges(true); |
+ settings->setShrinksViewportContentToFit(true); |
+} |
+ |
+// Make sure a composited background-attachment:fixed background gets resized |
+// when using inert (non-layout affecting) browser controls. |
+TEST_P(VisualViewportTest, ResizeCompositedAndFixedBackground) { |
+ bool originalInertTopControls = |
+ RuntimeEnabledFeatures::inertTopControlsEnabled(); |
+ RuntimeEnabledFeatures::setInertTopControlsEnabled(true); |
+ |
+ std::unique_ptr<FrameTestHelpers::TestWebViewClient> |
+ fakeCompositingWebViewClient = |
+ wrapUnique(new FrameTestHelpers::TestWebViewClient()); |
+ FrameTestHelpers::WebViewHelper webViewHelper; |
+ WebViewImpl* webViewImpl = webViewHelper.initialize( |
+ true, nullptr, fakeCompositingWebViewClient.get(), nullptr, |
+ &configureAndroidCompositing); |
+ |
+ int pageWidth = 640; |
+ int pageHeight = 480; |
+ float browserControlsHeight = 50.0f; |
+ int smallestHeight = pageHeight - browserControlsHeight; |
+ |
+ webViewImpl->resizeWithBrowserControls(WebSize(pageWidth, pageHeight), |
+ browserControlsHeight, false); |
+ |
+ URLTestHelpers::registerMockedURLLoad(toKURL("http://example.com/foo.png"), |
+ "white-1x1.png"); |
+ WebURL baseURL = URLTestHelpers::toKURL("http://example.com/"); |
+ FrameTestHelpers::loadHTMLString(webViewImpl->mainFrame(), |
+ "<!DOCTYPE html>" |
+ "<style>" |
+ " body {" |
+ " background: url('foo.png');" |
+ " background-attachment: fixed;" |
+ " background-size: cover;" |
+ " background-repeat: no-repeat;" |
+ " }" |
+ " div { height:1000px; width: 200px; }" |
+ "</style>" |
+ "<div></div>", |
+ baseURL); |
+ webViewImpl->updateAllLifecyclePhases(); |
+ |
+ Document* document = |
+ toLocalFrame(webViewImpl->page()->mainFrame())->document(); |
+ PaintLayerCompositor* compositor = document->layoutView()->compositor(); |
+ |
+ ASSERT_TRUE(compositor->needsFixedRootBackgroundLayer( |
+ document->layoutView()->layer())); |
+ ASSERT_TRUE(compositor->fixedRootBackgroundLayer()); |
+ |
+ ASSERT_EQ(pageWidth, compositor->fixedRootBackgroundLayer()->size().width()); |
+ ASSERT_EQ(pageHeight, |
+ compositor->fixedRootBackgroundLayer()->size().height()); |
+ ASSERT_EQ(pageWidth, document->view()->layoutSize().width()); |
+ ASSERT_EQ(smallestHeight, document->view()->layoutSize().height()); |
+ |
+ webViewImpl->resizeWithBrowserControls(WebSize(pageWidth, smallestHeight), |
+ browserControlsHeight, true); |
+ |
+ // The layout size should not have changed. |
+ ASSERT_EQ(pageWidth, document->view()->layoutSize().width()); |
+ ASSERT_EQ(smallestHeight, document->view()->layoutSize().height()); |
+ |
+ // The background layer's size should have changed though. |
+ EXPECT_EQ(pageWidth, compositor->fixedRootBackgroundLayer()->size().width()); |
+ EXPECT_EQ(smallestHeight, |
+ compositor->fixedRootBackgroundLayer()->size().height()); |
+ |
+ webViewImpl->resizeWithBrowserControls(WebSize(pageWidth, pageHeight), |
+ browserControlsHeight, true); |
+ |
+ // The background layer's size should change again. |
+ EXPECT_EQ(pageWidth, compositor->fixedRootBackgroundLayer()->size().width()); |
+ EXPECT_EQ(pageHeight, |
+ compositor->fixedRootBackgroundLayer()->size().height()); |
+ |
+ RuntimeEnabledFeatures::setInertTopControlsEnabled(originalInertTopControls); |
+} |
+ |
+static void configureAndroidNonCompositing(WebSettings* settings) { |
+ settings->setAcceleratedCompositingEnabled(true); |
+ settings->setPreferCompositingToLCDTextEnabled(false); |
+ settings->setViewportMetaEnabled(true); |
+ settings->setViewportEnabled(true); |
+ settings->setMainFrameResizesAreOrientationChanges(true); |
+ settings->setShrinksViewportContentToFit(true); |
+} |
+ |
+// Make sure a non-composited background-attachment:fixed background gets |
+// resized when using inert (non-layout affecting) browser controls. |
+TEST_P(VisualViewportTest, ResizeNonCompositedAndFixedBackground) { |
+ bool originalInertTopControls = |
+ RuntimeEnabledFeatures::inertTopControlsEnabled(); |
+ RuntimeEnabledFeatures::setInertTopControlsEnabled(true); |
+ |
+ FrameTestHelpers::WebViewHelper webViewHelper; |
+ WebViewImpl* webViewImpl = webViewHelper.initialize( |
+ true, nullptr, nullptr, nullptr, &configureAndroidNonCompositing); |
+ |
+ int pageWidth = 640; |
+ int pageHeight = 480; |
+ float browserControlsHeight = 50.0f; |
+ int smallestHeight = pageHeight - browserControlsHeight; |
+ |
+ webViewImpl->resizeWithBrowserControls(WebSize(pageWidth, pageHeight), |
+ browserControlsHeight, false); |
+ |
+ URLTestHelpers::registerMockedURLLoad(toKURL("http://example.com/foo.png"), |
+ "white-1x1.png"); |
+ WebURL baseURL = URLTestHelpers::toKURL("http://example.com/"); |
+ FrameTestHelpers::loadHTMLString(webViewImpl->mainFrame(), |
+ "<!DOCTYPE html>" |
+ "<style>" |
+ " body {" |
+ " margin: 0px;" |
+ " background: url('foo.png');" |
+ " background-attachment: fixed;" |
+ " background-size: cover;" |
+ " background-repeat: no-repeat;" |
+ " }" |
+ " div { height:1000px; width: 200px; }" |
+ "</style>" |
+ "<div></div>", |
+ baseURL); |
+ webViewImpl->updateAllLifecyclePhases(); |
+ |
+ Document* document = |
+ toLocalFrame(webViewImpl->page()->mainFrame())->document(); |
+ PaintLayerCompositor* compositor = document->layoutView()->compositor(); |
+ |
+ ASSERT_FALSE(compositor->needsFixedRootBackgroundLayer( |
+ document->layoutView()->layer())); |
+ ASSERT_FALSE(compositor->fixedRootBackgroundLayer()); |
+ |
+ document->view()->setTracksPaintInvalidations(true); |
+ webViewImpl->resizeWithBrowserControls(WebSize(pageWidth, smallestHeight), |
+ browserControlsHeight, true); |
+ |
+ // The layout size should not have changed. |
+ ASSERT_EQ(pageWidth, document->view()->layoutSize().width()); |
+ ASSERT_EQ(smallestHeight, document->view()->layoutSize().height()); |
+ |
+ const RasterInvalidationTracking* invalidationTracking = |
+ document->layoutView() |
+ ->layer() |
+ ->graphicsLayerBacking() |
+ ->getRasterInvalidationTracking(); |
+ // If no invalidations occured, this will be a nullptr. |
+ ASSERT_TRUE(invalidationTracking); |
+ |
+ const auto* rasterInvalidations = |
+ &invalidationTracking->trackedRasterInvalidations; |
+ |
+ bool rootLayerScrolling = GetParam(); |
+ |
+ // Without root-layer-scrolling, the LayoutView is the size of the document |
+ // content so invalidating it for background-attachment: fixed |
+ // overinvalidates as we should only need to invalidate the viewport size. |
+ int expectedHeight = rootLayerScrolling ? 430 : 1000; |
+ |
+ // The entire viewport should have been invalidated. |
+ EXPECT_EQ(1u, rasterInvalidations->size()); |
+ EXPECT_EQ(IntRect(0, 0, 640, expectedHeight), (*rasterInvalidations)[0].rect); |
+ document->view()->setTracksPaintInvalidations(false); |
+ |
+ invalidationTracking = document->layoutView() |
+ ->layer() |
+ ->graphicsLayerBacking() |
+ ->getRasterInvalidationTracking(); |
+ ASSERT_FALSE(invalidationTracking); |
+ |
+ document->view()->setTracksPaintInvalidations(true); |
+ webViewImpl->resizeWithBrowserControls(WebSize(pageWidth, pageHeight), |
+ browserControlsHeight, true); |
+ |
+ invalidationTracking = document->layoutView() |
+ ->layer() |
+ ->graphicsLayerBacking() |
+ ->getRasterInvalidationTracking(); |
+ ASSERT_TRUE(invalidationTracking); |
+ rasterInvalidations = &invalidationTracking->trackedRasterInvalidations; |
+ |
+ // Once again, the entire page should have been invalidated. |
+ expectedHeight = rootLayerScrolling ? 480 : 1000; |
+ EXPECT_EQ(1u, rasterInvalidations->size()); |
+ EXPECT_EQ(IntRect(0, 0, 640, expectedHeight), (*rasterInvalidations)[0].rect); |
+ |
+ document->view()->setTracksPaintInvalidations(false); |
+ RuntimeEnabledFeatures::setInertTopControlsEnabled(originalInertTopControls); |
+} |
+ |
+// Make sure a browser control resize with background-attachment:not-fixed |
+// background doesn't cause invalidation or layout. |
+TEST_P(VisualViewportTest, ResizeNonFixedBackgroundNoLayoutOrInvalidation) { |
+ bool originalInertTopControls = |
+ RuntimeEnabledFeatures::inertTopControlsEnabled(); |
+ RuntimeEnabledFeatures::setInertTopControlsEnabled(true); |
+ |
+ std::unique_ptr<FrameTestHelpers::TestWebViewClient> |
+ fakeCompositingWebViewClient = |
+ wrapUnique(new FrameTestHelpers::TestWebViewClient()); |
+ FrameTestHelpers::WebViewHelper webViewHelper; |
+ WebViewImpl* webViewImpl = webViewHelper.initialize( |
+ true, nullptr, fakeCompositingWebViewClient.get(), nullptr, |
+ &configureAndroidCompositing); |
+ |
+ int pageWidth = 640; |
+ int pageHeight = 480; |
+ float browserControlsHeight = 50.0f; |
+ int smallestHeight = pageHeight - browserControlsHeight; |
+ |
+ webViewImpl->resizeWithBrowserControls(WebSize(pageWidth, pageHeight), |
+ browserControlsHeight, false); |
+ |
+ URLTestHelpers::registerMockedURLLoad(toKURL("http://example.com/foo.png"), |
+ "white-1x1.png"); |
+ WebURL baseURL = URLTestHelpers::toKURL("http://example.com/"); |
+ // This time the background is the default attachment. |
+ FrameTestHelpers::loadHTMLString(webViewImpl->mainFrame(), |
+ "<!DOCTYPE html>" |
+ "<style>" |
+ " body {" |
+ " margin: 0px;" |
+ " background: url('foo.png');" |
+ " background-size: cover;" |
+ " background-repeat: no-repeat;" |
+ " }" |
+ " div { height:1000px; width: 200px; }" |
+ "</style>" |
+ "<div></div>", |
+ baseURL); |
+ webViewImpl->updateAllLifecyclePhases(); |
+ |
+ Document* document = |
+ toLocalFrame(webViewImpl->page()->mainFrame())->document(); |
+ |
+ // A resize will do a layout synchronously so manually check that we don't |
+ // setNeedsLayout from viewportSizeChanged. |
+ document->view()->viewportSizeChanged(false, true); |
+ unsigned needsLayoutObjects = 0; |
+ unsigned totalObjects = 0; |
+ bool isSubtree = false; |
+ EXPECT_FALSE(document->view()->needsLayout()); |
+ document->view()->countObjectsNeedingLayout(needsLayoutObjects, totalObjects, |
+ isSubtree); |
+ EXPECT_EQ(0u, needsLayoutObjects); |
+ |
+ // Do a real resize to check for invalidations. |
+ document->view()->setTracksPaintInvalidations(true); |
+ webViewImpl->resizeWithBrowserControls(WebSize(pageWidth, smallestHeight), |
+ browserControlsHeight, true); |
+ |
+ // The layout size should not have changed. |
+ ASSERT_EQ(pageWidth, document->view()->layoutSize().width()); |
+ ASSERT_EQ(smallestHeight, document->view()->layoutSize().height()); |
+ |
+ const RasterInvalidationTracking* invalidationTracking = |
+ document->layoutView() |
+ ->layer() |
+ ->graphicsLayerBacking() |
+ ->getRasterInvalidationTracking(); |
+ |
+ // No invalidations should have occured in FrameView scrolling. If |
+ // root-layer-scrolls is on, an invalidation is necessary for now, see the |
+ // comment and TODO in FrameView::viewportSizeChanged. |
+ // http://crbug.com/568847. |
+ bool rootLayerScrolling = GetParam(); |
+ if (rootLayerScrolling) |
+ EXPECT_TRUE(invalidationTracking); |
+ else |
+ EXPECT_FALSE(invalidationTracking); |
+ |
+ document->view()->setTracksPaintInvalidations(false); |
+ RuntimeEnabledFeatures::setInertTopControlsEnabled(originalInertTopControls); |
+} |
+ |
} // namespace |