Title: [250361] trunk
Revision
250361
Author
wenson_hs...@apple.com
Date
2019-09-25 15:30:55 -0700 (Wed, 25 Sep 2019)

Log Message

Page temporarily jumps to an excessively small viewport scale while loading usatoday.com
https://bugs.webkit.org/show_bug.cgi?id=202224
<rdar://problem/52906640>

Reviewed by Tim Horton.

Source/WebCore:

On some pages (e.g. usatoday.com), the content width of the page temporarily becomes very large during page
load. This causes a couple of viewport scaling behaviors (notably, the existing shrink-to-fit heuristic in
ViewportConfiguration::initialScaleFromSize, as well as the new iPad-specific content-aware shrink-to-fit
heuristic in WebPage::immediatelyShrinkToFitContent) to cause the page to shrink down excessively in an attempt
to fit all the content to the viewport. This causes a very ugly flash as the page appears zoomed out initially
during page load, before zooming back in.

To fix this, we add some sanity checks to these viewport scaling heuristics. In ViewportConfiguration's
initialScaleFromSize method, in the codepath where an initial scale is not specified, we always scale to fit the
contents of the page; instead, detect the case where the content width is enormous (with a threshold arbitrarily
chosen to be 1920) and fall back to the scaling to fit the viewport's width, if such a width has been explicitly
set. This ensures that we avoid excessive shrinking in the case where content is extremely wide, but also that
we do scale the viewport down to fit all the content in the case where the content isn't extremely wide (e.g. on
daringfireball.com).

See WebKit ChangeLog for more detail.

Test: fast/viewport/ios/shrink-to-fit-large-content-width.html

* page/ViewportConfiguration.cpp:
(WebCore::ViewportConfiguration::initialScaleFromSize const):

Source/WebKit:

Tweaks the content-aware shrink-to-fit algorithm to bail in the case where the content width is extremely large,
such that it bails instead of attempting to fit the entire content of the page. See WebCore ChangeLog for more
details.

* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::immediatelyShrinkToFitContent):

LayoutTests:

Adds a new layout test to verify that when the content width of the page is excessively large and an explicit
viewport width is specified, we don't attempt to zoom out to fit the larger content width, and instead zoom to
fit the explicit viewport width.

* fast/viewport/ios/shrink-to-fit-large-content-width-expected.txt: Added.
* fast/viewport/ios/shrink-to-fit-large-content-width.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (250360 => 250361)


--- trunk/LayoutTests/ChangeLog	2019-09-25 22:30:33 UTC (rev 250360)
+++ trunk/LayoutTests/ChangeLog	2019-09-25 22:30:55 UTC (rev 250361)
@@ -1,3 +1,18 @@
+2019-09-25  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        Page temporarily jumps to an excessively small viewport scale while loading usatoday.com
+        https://bugs.webkit.org/show_bug.cgi?id=202224
+        <rdar://problem/52906640>
+
+        Reviewed by Tim Horton.
+
+        Adds a new layout test to verify that when the content width of the page is excessively large and an explicit
+        viewport width is specified, we don't attempt to zoom out to fit the larger content width, and instead zoom to
+        fit the explicit viewport width.
+
+        * fast/viewport/ios/shrink-to-fit-large-content-width-expected.txt: Added.
+        * fast/viewport/ios/shrink-to-fit-large-content-width.html: Added.
+
 2019-09-25  Zalan Bujtas  <za...@apple.com>
 
         Adjust tap position to avoid double-tap issue across tests.

Added: trunk/LayoutTests/fast/viewport/ios/shrink-to-fit-large-content-width-expected.txt (0 => 250361)


--- trunk/LayoutTests/fast/viewport/ios/shrink-to-fit-large-content-width-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/viewport/ios/shrink-to-fit-large-content-width-expected.txt	2019-09-25 22:30:55 UTC (rev 250361)
@@ -0,0 +1,10 @@
+This test verifies that a page with a constant width viewport and a very large content width, the page is scaled such that the constant viewport width spans the width of the viewport. To test manually, load the page and verify that only the top bar spans the full width of the page.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS innerWidth is 1000
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/viewport/ios/shrink-to-fit-large-content-width.html (0 => 250361)


--- trunk/LayoutTests/fast/viewport/ios/shrink-to-fit-large-content-width.html	                        (rev 0)
+++ trunk/LayoutTests/fast/viewport/ios/shrink-to-fit-large-content-width.html	2019-09-25 22:30:55 UTC (rev 250361)
@@ -0,0 +1,49 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ shouldIgnoreMetaViewport=true ] -->
+<html>
+<head>
+<meta name="viewport" content="width=1000">
+<style>
+body, html {
+    margin: 0;
+}
+
+#top-bar {
+    width: 1000px;
+    height: 100px;
+    background: linear-gradient(to right, red 0%, green 50%, blue 100%);
+}
+
+#bottom-bar {
+    width: 8000px;
+    height: 100px;
+    background: linear-gradient(to right, red 0%, green 50%, blue 100%);
+}
+
+#description {
+    width: 300px;
+    overflow: scroll;
+}
+</style>
+<script src=""
+<script src=""
+<script>
+jsTestIsAsync = true;
+
+description("This test verifies that a page with a constant width viewport and a very large content width, the page is scaled such that the constant viewport width spans the width of the viewport. To test manually, load the page and verify that only the top bar spans the full width of the page.");
+
+addEventListener("load", async () => {
+    if (!window.testRunner)
+        return;
+
+    await UIHelper.ensurePresentationUpdate();
+    shouldBe("innerWidth", "1000");
+    finishJSTest();
+});
+</script>
+</head>
+<body>
+<div id="top-bar"></div>
+<div id="bottom-bar"></div>
+<div id="description"></div>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (250360 => 250361)


--- trunk/Source/WebCore/ChangeLog	2019-09-25 22:30:33 UTC (rev 250360)
+++ trunk/Source/WebCore/ChangeLog	2019-09-25 22:30:55 UTC (rev 250361)
@@ -1,5 +1,35 @@
 2019-09-25  Wenson Hsieh  <wenson_hs...@apple.com>
 
+        Page temporarily jumps to an excessively small viewport scale while loading usatoday.com
+        https://bugs.webkit.org/show_bug.cgi?id=202224
+        <rdar://problem/52906640>
+
+        Reviewed by Tim Horton.
+
+        On some pages (e.g. usatoday.com), the content width of the page temporarily becomes very large during page
+        load. This causes a couple of viewport scaling behaviors (notably, the existing shrink-to-fit heuristic in
+        ViewportConfiguration::initialScaleFromSize, as well as the new iPad-specific content-aware shrink-to-fit
+        heuristic in WebPage::immediatelyShrinkToFitContent) to cause the page to shrink down excessively in an attempt
+        to fit all the content to the viewport. This causes a very ugly flash as the page appears zoomed out initially
+        during page load, before zooming back in.
+
+        To fix this, we add some sanity checks to these viewport scaling heuristics. In ViewportConfiguration's
+        initialScaleFromSize method, in the codepath where an initial scale is not specified, we always scale to fit the
+        contents of the page; instead, detect the case where the content width is enormous (with a threshold arbitrarily
+        chosen to be 1920) and fall back to the scaling to fit the viewport's width, if such a width has been explicitly
+        set. This ensures that we avoid excessive shrinking in the case where content is extremely wide, but also that
+        we do scale the viewport down to fit all the content in the case where the content isn't extremely wide (e.g. on
+        daringfireball.com).
+
+        See WebKit ChangeLog for more detail.
+
+        Test: fast/viewport/ios/shrink-to-fit-large-content-width.html
+
+        * page/ViewportConfiguration.cpp:
+        (WebCore::ViewportConfiguration::initialScaleFromSize const):
+
+2019-09-25  Wenson Hsieh  <wenson_hs...@apple.com>
+
         [iPadOS] [DataActivation] Focus moves away after focusing input fields on www.att.com
         https://bugs.webkit.org/show_bug.cgi?id=202167
         <rdar://problem/55185021>

Modified: trunk/Source/WebCore/page/ViewportConfiguration.cpp (250360 => 250361)


--- trunk/Source/WebCore/page/ViewportConfiguration.cpp	2019-09-25 22:30:33 UTC (rev 250360)
+++ trunk/Source/WebCore/page/ViewportConfiguration.cpp	2019-09-25 22:30:55 UTC (rev 250361)
@@ -266,8 +266,13 @@
     // If not, it is up to us to determine the initial scale.
     // We want a scale small enough to fit the document width-wise.
     double initialScale = 0;
-    if (width > 0 && !shouldIgnoreVerticalScalingConstraints())
-        initialScale = m_viewLayoutSize.width() / width;
+    if (!shouldIgnoreVerticalScalingConstraints()) {
+        static const double maximumContentWidthBeforePreferringExplicitWidthToAvoidExcessiveScaling = 1920;
+        if (width > maximumContentWidthBeforePreferringExplicitWidthToAvoidExcessiveScaling && m_configuration.widthIsSet && 0 < m_configuration.width && m_configuration.width < width)
+            initialScale = m_viewLayoutSize.width() / m_configuration.width;
+        else if (width > 0)
+            initialScale = m_viewLayoutSize.width() / width;
+    }
 
     // Prevent the initial scale from shrinking to a height smaller than our view's minimum height.
     if (height > 0 && height * initialScale < m_viewLayoutSize.height() && !shouldIgnoreHorizontalScalingConstraints())

Modified: trunk/Source/WebKit/ChangeLog (250360 => 250361)


--- trunk/Source/WebKit/ChangeLog	2019-09-25 22:30:33 UTC (rev 250360)
+++ trunk/Source/WebKit/ChangeLog	2019-09-25 22:30:55 UTC (rev 250361)
@@ -1,3 +1,18 @@
+2019-09-25  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        Page temporarily jumps to an excessively small viewport scale while loading usatoday.com
+        https://bugs.webkit.org/show_bug.cgi?id=202224
+        <rdar://problem/52906640>
+
+        Reviewed by Tim Horton.
+
+        Tweaks the content-aware shrink-to-fit algorithm to bail in the case where the content width is extremely large,
+        such that it bails instead of attempting to fit the entire content of the page. See WebCore ChangeLog for more
+        details.
+
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::immediatelyShrinkToFitContent):
+
 2019-09-25  Alex Christensen  <achristen...@webkit.org>
 
         Don't fall back to default session if session can't be found for cookie operations

Modified: trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (250360 => 250361)


--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2019-09-25 22:30:33 UTC (rev 250360)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2019-09-25 22:30:55 UTC (rev 250361)
@@ -3434,6 +3434,7 @@
 
     static const int toleratedHorizontalScrollingDistance = 20;
     static const int maximumExpandedLayoutWidth = 1280;
+    static const int maximumContentWidthBeforeAvoidingShrinkToFit = 1920;
 
     auto scaledViewWidth = [&] () -> int {
         return std::round(m_viewportConfiguration.viewLayoutSize().width() / m_viewportConfiguration.initialScale());
@@ -3443,7 +3444,7 @@
     int originalViewWidth = scaledViewWidth();
     int originalLayoutWidth = m_viewportConfiguration.layoutWidth();
     int originalHorizontalOverflowAmount = originalContentWidth - originalViewWidth;
-    if (originalHorizontalOverflowAmount <= toleratedHorizontalScrollingDistance || originalLayoutWidth >= maximumExpandedLayoutWidth || originalContentWidth <= originalViewWidth)
+    if (originalHorizontalOverflowAmount <= toleratedHorizontalScrollingDistance || originalLayoutWidth >= maximumExpandedLayoutWidth || originalContentWidth <= originalViewWidth || originalContentWidth > maximumContentWidthBeforeAvoidingShrinkToFit)
         return false;
 
     auto changeMinimumEffectiveDeviceWidth = [this, mainDocument] (int targetLayoutWidth) -> bool {
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to