<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[244886] tags/Safari-608.1.20.1</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/244886">244886</a></dd>
<dt>Author</dt> <dd>alancoon@apple.com</dd>
<dt>Date</dt> <dd>2019-05-02 14:08:35 -0700 (Thu, 02 May 2019)</dd>
</dl>

<h3>Log Message</h3>
<pre>Cherry-pick <a href="http://trac.webkit.org/projects/webkit/changeset/244849">r244849</a>. rdar://problem/50063091

    [iOS] Add a version of viewport shrink-to-fit heuristics that preserves page layout
    https://bugs.webkit.org/show_bug.cgi?id=197342
    <rdar://problem/50063091>

    Reviewed by Tim Horton.

    Source/WebCore:

    Adds support for a new shrink-to-fit heuristic that attempts to lay out the contents of the page at a larger
    width in order to shrink content to fit the viewport. See WebKit ChangeLog for more details.

    Tests: fast/viewport/ios/shrink-to-fit-content-constant-width.html
           fast/viewport/ios/shrink-to-fit-content-large-width-breakpoint.html
           fast/viewport/ios/shrink-to-fit-content-no-viewport.html
           fast/viewport/ios/shrink-to-fit-content-responsive-viewport-with-horizontal-overflow.html
           fast/viewport/ios/shrink-to-fit-content-temporary-overflow.html

    * page/ViewportConfiguration.cpp:
    (WebCore::ViewportConfiguration::setMinimumEffectiveDeviceWidth):
    (WebCore::ViewportConfiguration::setIsKnownToLayOutWiderThanViewport):
    (WebCore::ViewportConfiguration::description const):
    * page/ViewportConfiguration.h:
    (WebCore::ViewportConfiguration::canIgnoreScalingConstraints const):
    (WebCore::ViewportConfiguration::minimumEffectiveDeviceWidth const):

    Add several new getters and setters in ViewportConfiguration.

    (WebCore::ViewportConfiguration::isKnownToLayOutWiderThanViewport const):
    (WebCore::ViewportConfiguration::shouldIgnoreMinimumEffectiveDeviceWidth const):

    Importantly, only allow ignoring the minimum effective device width in webpages with responsive viewports, if
    they also have *not* laid out wider than the viewport.

    (WebCore::ViewportConfiguration::setForceAlwaysUserScalable):

    Source/WebKit:

    This patch introduces a new shrink-to-fit heuristic that attempts to lay out the contents of the page at a
    larger width in order to shrink content to fit the viewport. This is similar to existing shrink-to-fit behaviors
    used for viewport sizing in multitasking mode, except that it not only scales the view, but additionally expands
    the layout size, such that the overall layout of the page is preserved. In fact, the reason we ended up
    reverting the existing flavor of shrink-to-fit in all cases except for multitasking was that page layout was not
    preserved, which caused elements that poke out of the viewport to make the rest of the page look out of
    proportion — see <rdar://problem/23818102> and related radars.

    Covered by 5 new layout tests, and by adjusting a couple of existing layout tests. See comments below for more
    details.

    * Platform/Logging.h:

    Add a new ViewportSizing logging channel. This will only log on pages that overflow the viewport and shrink to
    fit as a result.

    * Shared/WebPreferences.yaml:

    Turn IgnoreViewportScalingConstraints off by default. This preference currently controls whether we allow
    shrink-to-fit behaviors, and is only used by Safari when it is in multitasking mode. The value of this
    preference is currenly *on* by default, and is turned off almost immediately during every page load after the
    first visible content rect update, wherein visibleContentRectUpdateInfo.allowShrinkToFit() is false.

    However, this sometimes causes a brief jitter during page load; to fix this, make the default value for
    IgnoreViewportScalingConstraints false, and change the logic in WebPage::updateVisibleContentRects to
    setCanIgnoreScalingConstraints to true if either the IgnoreViewportScalingConstraints preference (not only
    affected by an internal debug switch) is true, or WKWebView SPI is used to enable the behavior.

    * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
    (WebKit::WebFrameLoaderClient::dispatchDidFinishDocumentLoad):
    (WebKit::WebFrameLoaderClient::dispatchDidFinishLoad):

    Add a new hook for WebFrameLoaderClient to call into WebPage when document load finishes. Also, tweak
    dispatchDidFinishLoad to take a WebFrame& instead of a WebFrame* in a drive-by fix (the frame is assumed to be
    non-null anyways).

    * WebProcess/WebPage/WebPage.cpp:
    (WebKit::WebPage::didCommitLoad):
    (WebKit::WebPage::didFinishDocumentLoad):
    (WebKit::WebPage::didFinishLoad):

    When finishing document load or finishing the overall load, kick off the shrink-to-fit timer; when committing a
    load, cancel the timer.

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

    Don't allow the minimum effective device width from the client to stomp over any minimum effective device width
    set as a result of the new shrink-to-fit heuristic; on some pages that load quickly, this can result in a race
    where the minimum effective device width (i.e. a value that lower-bounds the minimum layout width) is first set
    by the shrink-to-fit heuristic, and then set to an incorrect value by the client.

    In the near future, web view SPI used to set the minimum effective device width should actually be removed
    altogether, since the new shrink-to-fit heuristic supersedes any need for the client to fiddle with the minimum
    effective device width.

    (WebKit::WebPage::dynamicViewportSizeUpdate):

    When performing a dynamic viewport size update, additionally re-run the shrink-to-fit heuristic. This allows
    the minimum layout size of the viewport to be updated, if necessary. An example of where this matters is when a
    web page is *below* a tablet/desktop layout breakpoint in portrait device orientation, but then exceeds this
    layout breakpoint in landscape orientation. In this scenario, rotating the device should swap between these two
    page layouts.

    (WebKit::WebPage::resetViewportDefaultConfiguration):
    (WebKit::WebPage::scheduleShrinkToFitContent):
    (WebKit::WebPage::shrinkToFitContentTimerFired):
    (WebKit::WebPage::immediatelyShrinkToFitContent):

    Leverage the existing capability for a viewport to have a "minimum effective device width" to grant the viewport
    a larger layout size than it would normally have, and then scale down to fit within the bounds of the view. One
    challenge with this overall approach is that laying out at a larger width may cause the page to lay out even
    wider in response, which may actually worsen horizontal scrolling. To mitigate this, we only attempt to lay out
    at the current content width once; if laying out at this width reduced the amount of horizontal scrolling by any
    amount, then proceed with this layout width; otherwise, revert to the previous layout width.

    (WebKit::WebPage::shouldIgnoreMetaViewport const):

    Pull some common logic out into a readonly getter.

    (WebKit::WebPage::updateVisibleContentRects):

    See the comment below WebPreferences.yaml, above.

    LayoutTests:

    Introduces new layout tests, and adjusts some existing tests. See comments below.

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

    Add a new layout test to exercise the scenario where a constant width viewport narrower than the view is used.

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

    Add a new layout test to exercise the scenario where a responsive website that lays out larger than the view
    width ends up with even more horizontal scrolling when laying out at the initial content width. In this
    scenario, we shouldn't try to expand the viewport to try and encompass the content width, since that would only
    induce even worse horizontal scrolling.

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

    Add a new layout test for the case where there is no viewport, but content lays out wider than the view.

    * fast/viewport/ios/shrink-to-fit-content-responsive-viewport-with-horizontal-overflow-expected.txt: Added.
    * fast/viewport/ios/shrink-to-fit-content-responsive-viewport-with-horizontal-overflow.html: Added.

    Add a new layout test for the case where the page has opted for a responsive viewport (device-width, initial
    scale 1), but has laid out wider than the viewport anyways. In this case, we want to shrink the contents down to
    fit inside the view.

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

    Add a new layout test to exercise the case where, during page load, content width temporarily increases, and
    then decreases such that it once again fits within the viewport. In this case, we don't want to expand the
    viewport to be as wide as the large temporary width of the page.

    * fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden-expected.txt:
    * fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden.html:
    * fast/viewport/ios/width-is-device-width-overflowing-expected.txt:
    * fast/viewport/ios/width-is-device-width-overflowing.html:

    Tweak these 2 existing layout tests to include "shrink-to-fit=no", to prevent the new heuristics from shrinking
    the page to fit on device classes that use native viewports by default.

    * platform/ipad/fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden-expected.txt:
    * platform/ipad/fast/viewport/ios/width-is-device-width-overflowing-expected.txt:

    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244849 268f45cc-cd09-0410-ab3c-d52691b4dbfc</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#tagsSafari6081201LayoutTestsChangeLog">tags/Safari-608.1.20.1/LayoutTests/ChangeLog</a></li>
<li><a href="#tagsSafari6081201LayoutTestsfastviewportioswidthisdevicewidthoverflowingbodyoverflowhiddenexpectedtxt">tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden-expected.txt</a></li>
<li><a href="#tagsSafari6081201LayoutTestsfastviewportioswidthisdevicewidthoverflowingbodyoverflowhiddenhtml">tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden.html</a></li>
<li><a href="#tagsSafari6081201LayoutTestsfastviewportioswidthisdevicewidthoverflowingexpectedtxt">tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/width-is-device-width-overflowing-expected.txt</a></li>
<li><a href="#tagsSafari6081201LayoutTestsfastviewportioswidthisdevicewidthoverflowinghtml">tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/width-is-device-width-overflowing.html</a></li>
<li><a href="#tagsSafari6081201LayoutTestsplatformipadfastviewportioswidthisdevicewidthoverflowingbodyoverflowhiddenexpectedtxt">tags/Safari-608.1.20.1/LayoutTests/platform/ipad/fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden-expected.txt</a></li>
<li><a href="#tagsSafari6081201LayoutTestsplatformipadfastviewportioswidthisdevicewidthoverflowingexpectedtxt">tags/Safari-608.1.20.1/LayoutTests/platform/ipad/fast/viewport/ios/width-is-device-width-overflowing-expected.txt</a></li>
<li><a href="#tagsSafari6081201SourceWebCoreChangeLog">tags/Safari-608.1.20.1/Source/WebCore/ChangeLog</a></li>
<li><a href="#tagsSafari6081201SourceWebCorepageViewportConfigurationcpp">tags/Safari-608.1.20.1/Source/WebCore/page/ViewportConfiguration.cpp</a></li>
<li><a href="#tagsSafari6081201SourceWebCorepageViewportConfigurationh">tags/Safari-608.1.20.1/Source/WebCore/page/ViewportConfiguration.h</a></li>
<li><a href="#tagsSafari6081201SourceWebKitChangeLog">tags/Safari-608.1.20.1/Source/WebKit/ChangeLog</a></li>
<li><a href="#tagsSafari6081201SourceWebKitPlatformLoggingh">tags/Safari-608.1.20.1/Source/WebKit/Platform/Logging.h</a></li>
<li><a href="#tagsSafari6081201SourceWebKitSharedWebPreferencesyaml">tags/Safari-608.1.20.1/Source/WebKit/Shared/WebPreferences.yaml</a></li>
<li><a href="#tagsSafari6081201SourceWebKitWebProcessWebCoreSupportWebFrameLoaderClientcpp">tags/Safari-608.1.20.1/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp</a></li>
<li><a href="#tagsSafari6081201SourceWebKitWebProcessWebPageWebPagecpp">tags/Safari-608.1.20.1/Source/WebKit/WebProcess/WebPage/WebPage.cpp</a></li>
<li><a href="#tagsSafari6081201SourceWebKitWebProcessWebPageWebPageh">tags/Safari-608.1.20.1/Source/WebKit/WebProcess/WebPage/WebPage.h</a></li>
<li><a href="#tagsSafari6081201SourceWebKitWebProcessWebPageiosWebPageIOSmm">tags/Safari-608.1.20.1/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#tagsSafari6081201LayoutTestsfastviewportiosshrinktofitcontentconstantwidthexpectedtxt">tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-constant-width-expected.txt</a></li>
<li><a href="#tagsSafari6081201LayoutTestsfastviewportiosshrinktofitcontentconstantwidthhtml">tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-constant-width.html</a></li>
<li><a href="#tagsSafari6081201LayoutTestsfastviewportiosshrinktofitcontentlargewidthbreakpointexpectedtxt">tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-large-width-breakpoint-expected.txt</a></li>
<li><a href="#tagsSafari6081201LayoutTestsfastviewportiosshrinktofitcontentlargewidthbreakpointhtml">tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-large-width-breakpoint.html</a></li>
<li><a href="#tagsSafari6081201LayoutTestsfastviewportiosshrinktofitcontentnoviewportexpectedtxt">tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-no-viewport-expected.txt</a></li>
<li><a href="#tagsSafari6081201LayoutTestsfastviewportiosshrinktofitcontentnoviewporthtml">tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-no-viewport.html</a></li>
<li><a href="#tagsSafari6081201LayoutTestsfastviewportiosshrinktofitcontentresponsiveviewportwithhorizontaloverflowexpectedtxt">tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-responsive-viewport-with-horizontal-overflow-expected.txt</a></li>
<li><a href="#tagsSafari6081201LayoutTestsfastviewportiosshrinktofitcontentresponsiveviewportwithhorizontaloverflowhtml">tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-responsive-viewport-with-horizontal-overflow.html</a></li>
<li><a href="#tagsSafari6081201LayoutTestsfastviewportiosshrinktofitcontenttemporaryoverflowexpectedtxt">tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-temporary-overflow-expected.txt</a></li>
<li><a href="#tagsSafari6081201LayoutTestsfastviewportiosshrinktofitcontenttemporaryoverflowhtml">tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-temporary-overflow.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="tagsSafari6081201LayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: tags/Safari-608.1.20.1/LayoutTests/ChangeLog (244885 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/LayoutTests/ChangeLog     2019-05-02 21:08:26 UTC (rev 244885)
+++ tags/Safari-608.1.20.1/LayoutTests/ChangeLog        2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -1,5 +1,234 @@
</span><span class="cx"> 2019-05-02  Alan Coon  <alancoon@apple.com>
</span><span class="cx"> 
</span><ins>+        Cherry-pick r244849. rdar://problem/50063091
+
+    [iOS] Add a version of viewport shrink-to-fit heuristics that preserves page layout
+    https://bugs.webkit.org/show_bug.cgi?id=197342
+    <rdar://problem/50063091>
+    
+    Reviewed by Tim Horton.
+    
+    Source/WebCore:
+    
+    Adds support for a new shrink-to-fit heuristic that attempts to lay out the contents of the page at a larger
+    width in order to shrink content to fit the viewport. See WebKit ChangeLog for more details.
+    
+    Tests: fast/viewport/ios/shrink-to-fit-content-constant-width.html
+           fast/viewport/ios/shrink-to-fit-content-large-width-breakpoint.html
+           fast/viewport/ios/shrink-to-fit-content-no-viewport.html
+           fast/viewport/ios/shrink-to-fit-content-responsive-viewport-with-horizontal-overflow.html
+           fast/viewport/ios/shrink-to-fit-content-temporary-overflow.html
+    
+    * page/ViewportConfiguration.cpp:
+    (WebCore::ViewportConfiguration::setMinimumEffectiveDeviceWidth):
+    (WebCore::ViewportConfiguration::setIsKnownToLayOutWiderThanViewport):
+    (WebCore::ViewportConfiguration::description const):
+    * page/ViewportConfiguration.h:
+    (WebCore::ViewportConfiguration::canIgnoreScalingConstraints const):
+    (WebCore::ViewportConfiguration::minimumEffectiveDeviceWidth const):
+    
+    Add several new getters and setters in ViewportConfiguration.
+    
+    (WebCore::ViewportConfiguration::isKnownToLayOutWiderThanViewport const):
+    (WebCore::ViewportConfiguration::shouldIgnoreMinimumEffectiveDeviceWidth const):
+    
+    Importantly, only allow ignoring the minimum effective device width in webpages with responsive viewports, if
+    they also have *not* laid out wider than the viewport.
+    
+    (WebCore::ViewportConfiguration::setForceAlwaysUserScalable):
+    
+    Source/WebKit:
+    
+    This patch introduces a new shrink-to-fit heuristic that attempts to lay out the contents of the page at a
+    larger width in order to shrink content to fit the viewport. This is similar to existing shrink-to-fit behaviors
+    used for viewport sizing in multitasking mode, except that it not only scales the view, but additionally expands
+    the layout size, such that the overall layout of the page is preserved. In fact, the reason we ended up
+    reverting the existing flavor of shrink-to-fit in all cases except for multitasking was that page layout was not
+    preserved, which caused elements that poke out of the viewport to make the rest of the page look out of
+    proportion — see <rdar://problem/23818102> and related radars.
+    
+    Covered by 5 new layout tests, and by adjusting a couple of existing layout tests. See comments below for more
+    details.
+    
+    * Platform/Logging.h:
+    
+    Add a new ViewportSizing logging channel. This will only log on pages that overflow the viewport and shrink to
+    fit as a result.
+    
+    * Shared/WebPreferences.yaml:
+    
+    Turn IgnoreViewportScalingConstraints off by default. This preference currently controls whether we allow
+    shrink-to-fit behaviors, and is only used by Safari when it is in multitasking mode. The value of this
+    preference is currenly *on* by default, and is turned off almost immediately during every page load after the
+    first visible content rect update, wherein visibleContentRectUpdateInfo.allowShrinkToFit() is false.
+    
+    However, this sometimes causes a brief jitter during page load; to fix this, make the default value for
+    IgnoreViewportScalingConstraints false, and change the logic in WebPage::updateVisibleContentRects to
+    setCanIgnoreScalingConstraints to true if either the IgnoreViewportScalingConstraints preference (not only
+    affected by an internal debug switch) is true, or WKWebView SPI is used to enable the behavior.
+    
+    * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
+    (WebKit::WebFrameLoaderClient::dispatchDidFinishDocumentLoad):
+    (WebKit::WebFrameLoaderClient::dispatchDidFinishLoad):
+    
+    Add a new hook for WebFrameLoaderClient to call into WebPage when document load finishes. Also, tweak
+    dispatchDidFinishLoad to take a WebFrame& instead of a WebFrame* in a drive-by fix (the frame is assumed to be
+    non-null anyways).
+    
+    * WebProcess/WebPage/WebPage.cpp:
+    (WebKit::WebPage::didCommitLoad):
+    (WebKit::WebPage::didFinishDocumentLoad):
+    (WebKit::WebPage::didFinishLoad):
+    
+    When finishing document load or finishing the overall load, kick off the shrink-to-fit timer; when committing a
+    load, cancel the timer.
+    
+    * WebProcess/WebPage/WebPage.h:
+    * WebProcess/WebPage/ios/WebPageIOS.mm:
+    (WebKit::WebPage::setViewportConfigurationViewLayoutSize):
+    
+    Don't allow the minimum effective device width from the client to stomp over any minimum effective device width
+    set as a result of the new shrink-to-fit heuristic; on some pages that load quickly, this can result in a race
+    where the minimum effective device width (i.e. a value that lower-bounds the minimum layout width) is first set
+    by the shrink-to-fit heuristic, and then set to an incorrect value by the client.
+    
+    In the near future, web view SPI used to set the minimum effective device width should actually be removed
+    altogether, since the new shrink-to-fit heuristic supersedes any need for the client to fiddle with the minimum
+    effective device width.
+    
+    (WebKit::WebPage::dynamicViewportSizeUpdate):
+    
+    When performing a dynamic viewport size update, additionally re-run the shrink-to-fit heuristic. This allows
+    the minimum layout size of the viewport to be updated, if necessary. An example of where this matters is when a
+    web page is *below* a tablet/desktop layout breakpoint in portrait device orientation, but then exceeds this
+    layout breakpoint in landscape orientation. In this scenario, rotating the device should swap between these two
+    page layouts.
+    
+    (WebKit::WebPage::resetViewportDefaultConfiguration):
+    (WebKit::WebPage::scheduleShrinkToFitContent):
+    (WebKit::WebPage::shrinkToFitContentTimerFired):
+    (WebKit::WebPage::immediatelyShrinkToFitContent):
+    
+    Leverage the existing capability for a viewport to have a "minimum effective device width" to grant the viewport
+    a larger layout size than it would normally have, and then scale down to fit within the bounds of the view. One
+    challenge with this overall approach is that laying out at a larger width may cause the page to lay out even
+    wider in response, which may actually worsen horizontal scrolling. To mitigate this, we only attempt to lay out
+    at the current content width once; if laying out at this width reduced the amount of horizontal scrolling by any
+    amount, then proceed with this layout width; otherwise, revert to the previous layout width.
+    
+    (WebKit::WebPage::shouldIgnoreMetaViewport const):
+    
+    Pull some common logic out into a readonly getter.
+    
+    (WebKit::WebPage::updateVisibleContentRects):
+    
+    See the comment below WebPreferences.yaml, above.
+    
+    LayoutTests:
+    
+    Introduces new layout tests, and adjusts some existing tests. See comments below.
+    
+    * fast/viewport/ios/shrink-to-fit-content-constant-width-expected.txt: Added.
+    * fast/viewport/ios/shrink-to-fit-content-constant-width.html: Added.
+    
+    Add a new layout test to exercise the scenario where a constant width viewport narrower than the view is used.
+    
+    * fast/viewport/ios/shrink-to-fit-content-large-width-breakpoint-expected.txt: Added.
+    * fast/viewport/ios/shrink-to-fit-content-large-width-breakpoint.html: Added.
+    
+    Add a new layout test to exercise the scenario where a responsive website that lays out larger than the view
+    width ends up with even more horizontal scrolling when laying out at the initial content width. In this
+    scenario, we shouldn't try to expand the viewport to try and encompass the content width, since that would only
+    induce even worse horizontal scrolling.
+    
+    * fast/viewport/ios/shrink-to-fit-content-no-viewport-expected.txt: Added.
+    * fast/viewport/ios/shrink-to-fit-content-no-viewport.html: Added.
+    
+    Add a new layout test for the case where there is no viewport, but content lays out wider than the view.
+    
+    * fast/viewport/ios/shrink-to-fit-content-responsive-viewport-with-horizontal-overflow-expected.txt: Added.
+    * fast/viewport/ios/shrink-to-fit-content-responsive-viewport-with-horizontal-overflow.html: Added.
+    
+    Add a new layout test for the case where the page has opted for a responsive viewport (device-width, initial
+    scale 1), but has laid out wider than the viewport anyways. In this case, we want to shrink the contents down to
+    fit inside the view.
+    
+    * fast/viewport/ios/shrink-to-fit-content-temporary-overflow-expected.txt: Added.
+    * fast/viewport/ios/shrink-to-fit-content-temporary-overflow.html: Added.
+    
+    Add a new layout test to exercise the case where, during page load, content width temporarily increases, and
+    then decreases such that it once again fits within the viewport. In this case, we don't want to expand the
+    viewport to be as wide as the large temporary width of the page.
+    
+    * fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden-expected.txt:
+    * fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden.html:
+    * fast/viewport/ios/width-is-device-width-overflowing-expected.txt:
+    * fast/viewport/ios/width-is-device-width-overflowing.html:
+    
+    Tweak these 2 existing layout tests to include "shrink-to-fit=no", to prevent the new heuristics from shrinking
+    the page to fit on device classes that use native viewports by default.
+    
+    * platform/ipad/fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden-expected.txt:
+    * platform/ipad/fast/viewport/ios/width-is-device-width-overflowing-expected.txt:
+    
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244849 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2019-05-01  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+            [iOS] Add a version of viewport shrink-to-fit heuristics that preserves page layout
+            https://bugs.webkit.org/show_bug.cgi?id=197342
+            <rdar://problem/50063091>
+
+            Reviewed by Tim Horton.
+
+            Introduces new layout tests, and adjusts some existing tests. See comments below.
+
+            * fast/viewport/ios/shrink-to-fit-content-constant-width-expected.txt: Added.
+            * fast/viewport/ios/shrink-to-fit-content-constant-width.html: Added.
+
+            Add a new layout test to exercise the scenario where a constant width viewport narrower than the view is used.
+
+            * fast/viewport/ios/shrink-to-fit-content-large-width-breakpoint-expected.txt: Added.
+            * fast/viewport/ios/shrink-to-fit-content-large-width-breakpoint.html: Added.
+
+            Add a new layout test to exercise the scenario where a responsive website that lays out larger than the view
+            width ends up with even more horizontal scrolling when laying out at the initial content width. In this
+            scenario, we shouldn't try to expand the viewport to try and encompass the content width, since that would only
+            induce even worse horizontal scrolling.
+
+            * fast/viewport/ios/shrink-to-fit-content-no-viewport-expected.txt: Added.
+            * fast/viewport/ios/shrink-to-fit-content-no-viewport.html: Added.
+
+            Add a new layout test for the case where there is no viewport, but content lays out wider than the view.
+
+            * fast/viewport/ios/shrink-to-fit-content-responsive-viewport-with-horizontal-overflow-expected.txt: Added.
+            * fast/viewport/ios/shrink-to-fit-content-responsive-viewport-with-horizontal-overflow.html: Added.
+
+            Add a new layout test for the case where the page has opted for a responsive viewport (device-width, initial
+            scale 1), but has laid out wider than the viewport anyways. In this case, we want to shrink the contents down to
+            fit inside the view.
+
+            * fast/viewport/ios/shrink-to-fit-content-temporary-overflow-expected.txt: Added.
+            * fast/viewport/ios/shrink-to-fit-content-temporary-overflow.html: Added.
+
+            Add a new layout test to exercise the case where, during page load, content width temporarily increases, and
+            then decreases such that it once again fits within the viewport. In this case, we don't want to expand the
+            viewport to be as wide as the large temporary width of the page.
+
+            * fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden-expected.txt:
+            * fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden.html:
+            * fast/viewport/ios/width-is-device-width-overflowing-expected.txt:
+            * fast/viewport/ios/width-is-device-width-overflowing.html:
+
+            Tweak these 2 existing layout tests to include "shrink-to-fit=no", to prevent the new heuristics from shrinking
+            the page to fit on device classes that use native viewports by default.
+
+            * platform/ipad/fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden-expected.txt:
+            * platform/ipad/fast/viewport/ios/width-is-device-width-overflowing-expected.txt:
+
+2019-05-02  Alan Coon  <alancoon@apple.com>
+
</ins><span class="cx">         Cherry-pick r244823. rdar://problem/46677392
</span><span class="cx"> 
</span><span class="cx">     XMLHttpRequest should propagate user gestures for media playback
</span></span></pre></div>
<a id="tagsSafari6081201LayoutTestsfastviewportiosshrinktofitcontentconstantwidthexpectedtxt"></a>
<div class="addfile"><h4>Added: tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-constant-width-expected.txt (0 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-constant-width-expected.txt                           (rev 0)
+++ tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-constant-width-expected.txt      2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+This test verifies that a page with a constant width viewport smaller than the actual view width is scaled to fit the view. To test manually, load the page and verify that the bar spans the full width of the page.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS minScale is expectedScale
+PASS innerWidth is 300
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="tagsSafari6081201LayoutTestsfastviewportiosshrinktofitcontentconstantwidthhtml"></a>
<div class="addfile"><h4>Added: tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-constant-width.html (0 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-constant-width.html                           (rev 0)
+++ tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-constant-width.html      2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -0,0 +1,45 @@
</span><ins>+<!DOCTYPE html> <!-- webkit-test-runner [ shouldIgnoreMetaViewport=true ] -->
+<html>
+<head>
+<meta name="viewport" content="width=300">
+<style>
+body, html {
+    margin: 0;
+}
+
+#bar {
+    width: 100%;
+    height: 100px;
+    background: linear-gradient(to right, red 0%, green 50%, blue 100%);
+}
+
+#description {
+    width: 300px;
+    overflow: scroll;
+}
+</style>
+<script src="../../../resources/ui-helper.js"></script>
+<script src="../../../resources/js-test.js"></script>
+<script>
+jsTestIsAsync = true;
+
+description("This test verifies that a page with a constant width viewport smaller than the actual view width is scaled to fit the view. To test manually, load the page and verify that the bar spans the full width of the page.");
+
+addEventListener("load", async () => {
+    if (!window.testRunner)
+        return;
+
+    await UIHelper.ensurePresentationUpdate();
+    minScale = (await UIHelper.minimumZoomScale()).toFixed(2);
+    expectedScale = (screen.width / 300).toFixed(2);
+    shouldBe("minScale", "expectedScale");
+    shouldBe("innerWidth", "300");
+    finishJSTest();
+});
+</script>
+</head>
+<body>
+<div id="bar"></div>
+<div id="description"></div>
+</body>
+</html>
</ins></span></pre></div>
<a id="tagsSafari6081201LayoutTestsfastviewportiosshrinktofitcontentlargewidthbreakpointexpectedtxt"></a>
<div class="addfile"><h4>Added: tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-large-width-breakpoint-expected.txt (0 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-large-width-breakpoint-expected.txt                           (rev 0)
+++ tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-large-width-breakpoint-expected.txt      2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+This test verifies that the shrink-to-fit-content heuristic doesn't induce more horizontal scrolling than we would otherwise have. To run the test manually, load the page and check that the bar almost entirely fits within the viewport, with no more than 480px of horizontal scrolling (on a 320px-wide device) and 20px of scrolling (on a 768px-wide device).
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS minScale is 1
+PASS 800 is >= document.scrollingElement.scrollWidth
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="tagsSafari6081201LayoutTestsfastviewportiosshrinktofitcontentlargewidthbreakpointhtml"></a>
<div class="addfile"><h4>Added: tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-large-width-breakpoint.html (0 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-large-width-breakpoint.html                           (rev 0)
+++ tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-large-width-breakpoint.html      2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -0,0 +1,52 @@
</span><ins>+<!DOCTYPE html> <!-- webkit-test-runner [ shouldIgnoreMetaViewport=true ] -->
+<html>
+<head>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<style>
+body, html {
+    margin: 0;
+    width: 100%;
+    height: 100%;
+}
+
+@media screen and (min-width: 780px) {
+    #bar {
+        min-width: 10000px;
+    }
+}
+
+.bar {
+    width: 800px;
+    height: 100px;
+    background: linear-gradient(to right, red 0%, green 50%, blue 100%);
+}
+
+#description {
+    width: 300px;
+    overflow: scroll;
+}
+</style>
+<script src="../../../resources/ui-helper.js"></script>
+<script src="../../../resources/js-test.js"></script>
+<script>
+jsTestIsAsync = true;
+
+description("This test verifies that the shrink-to-fit-content heuristic doesn't induce more horizontal scrolling than we would otherwise have. To run the test manually, load the page and check that the bar almost entirely fits within the viewport, with no more than 480px of horizontal scrolling (on a 320px-wide device) and 20px of scrolling (on a 768px-wide device).");
+
+addEventListener("load", async () => {
+    if (!window.testRunner)
+        return;
+
+    await UIHelper.ensurePresentationUpdate();
+    minScale = await UIHelper.minimumZoomScale();
+    shouldBe("minScale", "1");
+    shouldBeGreaterThanOrEqual("800", "document.scrollingElement.scrollWidth");
+    finishJSTest();
+});
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="bar" class="bar"></div>
+</body>
+</html>
</ins></span></pre></div>
<a id="tagsSafari6081201LayoutTestsfastviewportiosshrinktofitcontentnoviewportexpectedtxt"></a>
<div class="addfile"><h4>Added: tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-no-viewport-expected.txt (0 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-no-viewport-expected.txt                              (rev 0)
+++ tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-no-viewport-expected.txt 2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+This test verifies that a page with a no viewport but with content larger than the actual view width is scaled to fit the view. To test manually, load the page and verify that the bar spans the full width of the page.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS minScale is expectedScale
+PASS innerWidth became 1000
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="tagsSafari6081201LayoutTestsfastviewportiosshrinktofitcontentnoviewporthtml"></a>
<div class="addfile"><h4>Added: tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-no-viewport.html (0 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-no-viewport.html                              (rev 0)
+++ tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-no-viewport.html 2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -0,0 +1,46 @@
</span><ins>+<!DOCTYPE html> <!-- webkit-test-runner [ shouldIgnoreMetaViewport=true ] -->
+<html>
+<head>
+<meta name="viewport">
+<style>
+body, html {
+    margin: 0;
+    width: 100%;
+    height: 100%;
+}
+
+#bar {
+    width: 1000px;
+    height: 100px;
+    background: linear-gradient(to right, red 0%, green 50%, blue 100%);
+}
+
+#description {
+    width: 300px;
+    overflow: scroll;
+}
+</style>
+<script src="../../../resources/ui-helper.js"></script>
+<script src="../../../resources/js-test.js"></script>
+<script>
+jsTestIsAsync = true;
+
+description("This test verifies that a page with a no viewport but with content larger than the actual view width is scaled to fit the view. To test manually, load the page and verify that the bar spans the full width of the page.");
+
+addEventListener("load", async () => {
+    if (!window.testRunner)
+        return;
+
+    await UIHelper.ensurePresentationUpdate();
+    minScale = (await UIHelper.minimumZoomScale()).toFixed(2);
+    expectedScale = (screen.width / 1000).toFixed(2);
+    shouldBe("minScale", "expectedScale");
+    shouldBecomeEqual("innerWidth", "1000", finishJSTest);
+});
+</script>
+</head>
+<body>
+<div id="bar"></div>
+<div id="description"></div>
+</body>
+</html>
</ins></span></pre></div>
<a id="tagsSafari6081201LayoutTestsfastviewportiosshrinktofitcontentresponsiveviewportwithhorizontaloverflowexpectedtxt"></a>
<div class="addfile"><h4>Added: tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-responsive-viewport-with-horizontal-overflow-expected.txt (0 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-responsive-viewport-with-horizontal-overflow-expected.txt                             (rev 0)
+++ tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-responsive-viewport-with-horizontal-overflow-expected.txt        2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+This test verifies that the shrink-to-fit-content heuristic prevents horizontal scrolling by shrinking the page, even when a page specifies a responsive viewport. To run the test manually, load the page and check that the bar entirely fits within the viewport, and the page is not horizontally scrollable.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS minScale is expectedScale
+PASS innerWidth became 960
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="tagsSafari6081201LayoutTestsfastviewportiosshrinktofitcontentresponsiveviewportwithhorizontaloverflowhtml"></a>
<div class="addfile"><h4>Added: tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-responsive-viewport-with-horizontal-overflow.html (0 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-responsive-viewport-with-horizontal-overflow.html                             (rev 0)
+++ tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-responsive-viewport-with-horizontal-overflow.html        2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -0,0 +1,46 @@
</span><ins>+<!DOCTYPE html> <!-- webkit-test-runner [ shouldIgnoreMetaViewport=true ] -->
+<html>
+<head>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<style>
+body, html {
+    margin: 0;
+    width: 100%;
+    height: 100%;
+}
+
+.bar {
+    width: 960px;
+    height: 100px;
+    background: linear-gradient(to right, red 0%, green 50%, blue 100%);
+}
+
+#description {
+    width: 300px;
+    overflow: scroll;
+}
+</style>
+<script src="../../../resources/ui-helper.js"></script>
+<script src="../../../resources/js-test.js"></script>
+<script>
+jsTestIsAsync = true;
+
+description("This test verifies that the shrink-to-fit-content heuristic prevents horizontal scrolling by shrinking the page, even when a page specifies a responsive viewport. To run the test manually, load the page and check that the bar entirely fits within the viewport, and the page is not horizontally scrollable.");
+
+addEventListener("load", async () => {
+    if (!window.testRunner)
+        return;
+
+    await UIHelper.ensurePresentationUpdate();
+    minScale = (await UIHelper.minimumZoomScale()).toFixed(2);
+    expectedScale = (screen.width / 960).toFixed(2);
+    shouldBe("minScale", "expectedScale");
+    shouldBecomeEqual("innerWidth", "960", finishJSTest);
+});
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div class="bar"></div>
+</body>
+</html>
</ins></span></pre></div>
<a id="tagsSafari6081201LayoutTestsfastviewportiosshrinktofitcontenttemporaryoverflowexpectedtxt"></a>
<div class="addfile"><h4>Added: tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-temporary-overflow-expected.txt (0 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-temporary-overflow-expected.txt                               (rev 0)
+++ tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-temporary-overflow-expected.txt  2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+This test verifies that a temporary change in content width does not cause the viewport width to permanently expand to try and accomodate the content. To test manually, load the page and check that the box below reads 'PASS'. This test is only intended to run on devices with less than 1200px screen width.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS minScale is 1
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="tagsSafari6081201LayoutTestsfastviewportiosshrinktofitcontenttemporaryoverflowhtml"></a>
<div class="addfile"><h4>Added: tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-temporary-overflow.html (0 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-temporary-overflow.html                               (rev 0)
+++ tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/shrink-to-fit-content-temporary-overflow.html  2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -0,0 +1,75 @@
</span><ins>+<!DOCTYPE html> <!-- webkit-test-runner [ shouldIgnoreMetaViewport=true ] -->
+<html>
+<head>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<style>
+body, html {
+    margin: 0;
+    width: 100%;
+    height: 100%;
+}
+
+.square {
+    background-color: green;
+    width: 100px;
+    height: 100px;
+}
+
+.square::before {
+    color: white;
+    content: "PASS";
+}
+
+@media screen and (min-width: 1200px) {
+    .square::before {
+        content: "FAIL";
+    }
+
+    .square {
+        background-color: red;
+    }
+}
+
+.bar {
+    width: 1500px;
+    height: 100px;
+    background: linear-gradient(to right, red 0%, green 50%, blue 100%);
+}
+
+#description {
+    width: 300px;
+    overflow: scroll;
+}
+</style>
+<script src="../../../resources/ui-helper.js"></script>
+<script src="../../../resources/js-test.js"></script>
+<script>
+jsTestIsAsync = true;
+
+description("This test verifies that a temporary change in content width does not cause the viewport width to permanently expand to try and accomodate the content. To test manually, load the page and check that the box below reads 'PASS'. This test is only intended to run on devices with less than 1200px screen width.");
+
+addEventListener("load", async () => {
+    if (!window.testRunner)
+        return;
+
+    await UIHelper.ensurePresentationUpdate();
+    minScale = await UIHelper.minimumZoomScale();
+    shouldBe("minScale", "1");
+    finishJSTest();
+});
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div class="square"></div>
+<script>
+const bar = document.createElement("div");
+bar.classList.add("bar");
+document.body.appendChild(bar);
+document.scrollingElement.scrollTo(0, 1);
+document.scrollingElement.scrollTo(0, 0);
+document.scrollingElement.scrollTop;
+bar.remove();
+</script>
+</body>
+</html>
</ins></span></pre></div>
<a id="tagsSafari6081201LayoutTestsfastviewportioswidthisdevicewidthoverflowingbodyoverflowhiddenexpectedtxt"></a>
<div class="modfile"><h4>Modified: tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden-expected.txt (244885 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden-expected.txt 2019-05-02 21:08:26 UTC (rev 244885)
+++ tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden-expected.txt    2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -1,4 +1,4 @@
</span><del>-Viewport: width=device-width
</del><ins>+Viewport: width=device-width, shrink-to-fit=no
</ins><span class="cx"> 
</span><span class="cx"> scale    1.00000
</span><span class="cx"> maxScale 5.00000
</span></span></pre></div>
<a id="tagsSafari6081201LayoutTestsfastviewportioswidthisdevicewidthoverflowingbodyoverflowhiddenhtml"></a>
<div class="modfile"><h4>Modified: tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden.html (244885 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden.html 2019-05-02 21:08:26 UTC (rev 244885)
+++ tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden.html    2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -1,8 +1,8 @@
</span><del>-<!DOCTYPE html>
</del><ins>+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
</ins><span class="cx"> 
</span><span class="cx"> <html>
</span><span class="cx"> <head>
</span><del>-    <meta name="viewport" content="width=device-width">
</del><ins>+    <meta name="viewport" content="width=device-width, shrink-to-fit=no">
</ins><span class="cx">     <script src="resources/viewport-test-utils.js"></script>
</span><span class="cx">     <style>
</span><span class="cx">         body {
</span></span></pre></div>
<a id="tagsSafari6081201LayoutTestsfastviewportioswidthisdevicewidthoverflowingexpectedtxt"></a>
<div class="modfile"><h4>Modified: tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/width-is-device-width-overflowing-expected.txt (244885 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/width-is-device-width-overflowing-expected.txt      2019-05-02 21:08:26 UTC (rev 244885)
+++ tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/width-is-device-width-overflowing-expected.txt 2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -1,4 +1,4 @@
</span><del>-Viewport: width=device-width
</del><ins>+Viewport: width=device-width, shrink-to-fit=no
</ins><span class="cx"> 
</span><span class="cx"> scale    1.00000
</span><span class="cx"> maxScale 5.00000
</span></span></pre></div>
<a id="tagsSafari6081201LayoutTestsfastviewportioswidthisdevicewidthoverflowinghtml"></a>
<div class="modfile"><h4>Modified: tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/width-is-device-width-overflowing.html (244885 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/width-is-device-width-overflowing.html      2019-05-02 21:08:26 UTC (rev 244885)
+++ tags/Safari-608.1.20.1/LayoutTests/fast/viewport/ios/width-is-device-width-overflowing.html 2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -1,8 +1,8 @@
</span><del>-<!DOCTYPE html>
</del><ins>+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
</ins><span class="cx"> 
</span><span class="cx"> <html>
</span><span class="cx"> <head>
</span><del>-    <meta name="viewport" content="width=device-width">
</del><ins>+    <meta name="viewport" content="width=device-width, shrink-to-fit=no">
</ins><span class="cx">     <script src="resources/viewport-test-utils.js"></script>
</span><span class="cx">     <style>
</span><span class="cx">         .wide {
</span></span></pre></div>
<a id="tagsSafari6081201LayoutTestsplatformipadfastviewportioswidthisdevicewidthoverflowingbodyoverflowhiddenexpectedtxt"></a>
<div class="modfile"><h4>Modified: tags/Safari-608.1.20.1/LayoutTests/platform/ipad/fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden-expected.txt (244885 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/LayoutTests/platform/ipad/fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden-expected.txt   2019-05-02 21:08:26 UTC (rev 244885)
+++ tags/Safari-608.1.20.1/LayoutTests/platform/ipad/fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden-expected.txt      2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -1,4 +1,4 @@
</span><del>-Viewport: width=device-width
</del><ins>+Viewport: width=device-width, shrink-to-fit=no
</ins><span class="cx"> 
</span><span class="cx"> scale    1.00000
</span><span class="cx"> maxScale 5.00000
</span></span></pre></div>
<a id="tagsSafari6081201LayoutTestsplatformipadfastviewportioswidthisdevicewidthoverflowingexpectedtxt"></a>
<div class="modfile"><h4>Modified: tags/Safari-608.1.20.1/LayoutTests/platform/ipad/fast/viewport/ios/width-is-device-width-overflowing-expected.txt (244885 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/LayoutTests/platform/ipad/fast/viewport/ios/width-is-device-width-overflowing-expected.txt        2019-05-02 21:08:26 UTC (rev 244885)
+++ tags/Safari-608.1.20.1/LayoutTests/platform/ipad/fast/viewport/ios/width-is-device-width-overflowing-expected.txt   2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -1,4 +1,4 @@
</span><del>-Viewport: width=device-width
</del><ins>+Viewport: width=device-width, shrink-to-fit=no
</ins><span class="cx"> 
</span><span class="cx"> scale    1.00000
</span><span class="cx"> maxScale 5.00000
</span></span></pre></div>
<a id="tagsSafari6081201SourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: tags/Safari-608.1.20.1/Source/WebCore/ChangeLog (244885 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/Source/WebCore/ChangeLog  2019-05-02 21:08:26 UTC (rev 244885)
+++ tags/Safari-608.1.20.1/Source/WebCore/ChangeLog     2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -1,5 +1,216 @@
</span><span class="cx"> 2019-05-02  Alan Coon  <alancoon@apple.com>
</span><span class="cx"> 
</span><ins>+        Cherry-pick r244849. rdar://problem/50063091
+
+    [iOS] Add a version of viewport shrink-to-fit heuristics that preserves page layout
+    https://bugs.webkit.org/show_bug.cgi?id=197342
+    <rdar://problem/50063091>
+    
+    Reviewed by Tim Horton.
+    
+    Source/WebCore:
+    
+    Adds support for a new shrink-to-fit heuristic that attempts to lay out the contents of the page at a larger
+    width in order to shrink content to fit the viewport. See WebKit ChangeLog for more details.
+    
+    Tests: fast/viewport/ios/shrink-to-fit-content-constant-width.html
+           fast/viewport/ios/shrink-to-fit-content-large-width-breakpoint.html
+           fast/viewport/ios/shrink-to-fit-content-no-viewport.html
+           fast/viewport/ios/shrink-to-fit-content-responsive-viewport-with-horizontal-overflow.html
+           fast/viewport/ios/shrink-to-fit-content-temporary-overflow.html
+    
+    * page/ViewportConfiguration.cpp:
+    (WebCore::ViewportConfiguration::setMinimumEffectiveDeviceWidth):
+    (WebCore::ViewportConfiguration::setIsKnownToLayOutWiderThanViewport):
+    (WebCore::ViewportConfiguration::description const):
+    * page/ViewportConfiguration.h:
+    (WebCore::ViewportConfiguration::canIgnoreScalingConstraints const):
+    (WebCore::ViewportConfiguration::minimumEffectiveDeviceWidth const):
+    
+    Add several new getters and setters in ViewportConfiguration.
+    
+    (WebCore::ViewportConfiguration::isKnownToLayOutWiderThanViewport const):
+    (WebCore::ViewportConfiguration::shouldIgnoreMinimumEffectiveDeviceWidth const):
+    
+    Importantly, only allow ignoring the minimum effective device width in webpages with responsive viewports, if
+    they also have *not* laid out wider than the viewport.
+    
+    (WebCore::ViewportConfiguration::setForceAlwaysUserScalable):
+    
+    Source/WebKit:
+    
+    This patch introduces a new shrink-to-fit heuristic that attempts to lay out the contents of the page at a
+    larger width in order to shrink content to fit the viewport. This is similar to existing shrink-to-fit behaviors
+    used for viewport sizing in multitasking mode, except that it not only scales the view, but additionally expands
+    the layout size, such that the overall layout of the page is preserved. In fact, the reason we ended up
+    reverting the existing flavor of shrink-to-fit in all cases except for multitasking was that page layout was not
+    preserved, which caused elements that poke out of the viewport to make the rest of the page look out of
+    proportion — see <rdar://problem/23818102> and related radars.
+    
+    Covered by 5 new layout tests, and by adjusting a couple of existing layout tests. See comments below for more
+    details.
+    
+    * Platform/Logging.h:
+    
+    Add a new ViewportSizing logging channel. This will only log on pages that overflow the viewport and shrink to
+    fit as a result.
+    
+    * Shared/WebPreferences.yaml:
+    
+    Turn IgnoreViewportScalingConstraints off by default. This preference currently controls whether we allow
+    shrink-to-fit behaviors, and is only used by Safari when it is in multitasking mode. The value of this
+    preference is currenly *on* by default, and is turned off almost immediately during every page load after the
+    first visible content rect update, wherein visibleContentRectUpdateInfo.allowShrinkToFit() is false.
+    
+    However, this sometimes causes a brief jitter during page load; to fix this, make the default value for
+    IgnoreViewportScalingConstraints false, and change the logic in WebPage::updateVisibleContentRects to
+    setCanIgnoreScalingConstraints to true if either the IgnoreViewportScalingConstraints preference (not only
+    affected by an internal debug switch) is true, or WKWebView SPI is used to enable the behavior.
+    
+    * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
+    (WebKit::WebFrameLoaderClient::dispatchDidFinishDocumentLoad):
+    (WebKit::WebFrameLoaderClient::dispatchDidFinishLoad):
+    
+    Add a new hook for WebFrameLoaderClient to call into WebPage when document load finishes. Also, tweak
+    dispatchDidFinishLoad to take a WebFrame& instead of a WebFrame* in a drive-by fix (the frame is assumed to be
+    non-null anyways).
+    
+    * WebProcess/WebPage/WebPage.cpp:
+    (WebKit::WebPage::didCommitLoad):
+    (WebKit::WebPage::didFinishDocumentLoad):
+    (WebKit::WebPage::didFinishLoad):
+    
+    When finishing document load or finishing the overall load, kick off the shrink-to-fit timer; when committing a
+    load, cancel the timer.
+    
+    * WebProcess/WebPage/WebPage.h:
+    * WebProcess/WebPage/ios/WebPageIOS.mm:
+    (WebKit::WebPage::setViewportConfigurationViewLayoutSize):
+    
+    Don't allow the minimum effective device width from the client to stomp over any minimum effective device width
+    set as a result of the new shrink-to-fit heuristic; on some pages that load quickly, this can result in a race
+    where the minimum effective device width (i.e. a value that lower-bounds the minimum layout width) is first set
+    by the shrink-to-fit heuristic, and then set to an incorrect value by the client.
+    
+    In the near future, web view SPI used to set the minimum effective device width should actually be removed
+    altogether, since the new shrink-to-fit heuristic supersedes any need for the client to fiddle with the minimum
+    effective device width.
+    
+    (WebKit::WebPage::dynamicViewportSizeUpdate):
+    
+    When performing a dynamic viewport size update, additionally re-run the shrink-to-fit heuristic. This allows
+    the minimum layout size of the viewport to be updated, if necessary. An example of where this matters is when a
+    web page is *below* a tablet/desktop layout breakpoint in portrait device orientation, but then exceeds this
+    layout breakpoint in landscape orientation. In this scenario, rotating the device should swap between these two
+    page layouts.
+    
+    (WebKit::WebPage::resetViewportDefaultConfiguration):
+    (WebKit::WebPage::scheduleShrinkToFitContent):
+    (WebKit::WebPage::shrinkToFitContentTimerFired):
+    (WebKit::WebPage::immediatelyShrinkToFitContent):
+    
+    Leverage the existing capability for a viewport to have a "minimum effective device width" to grant the viewport
+    a larger layout size than it would normally have, and then scale down to fit within the bounds of the view. One
+    challenge with this overall approach is that laying out at a larger width may cause the page to lay out even
+    wider in response, which may actually worsen horizontal scrolling. To mitigate this, we only attempt to lay out
+    at the current content width once; if laying out at this width reduced the amount of horizontal scrolling by any
+    amount, then proceed with this layout width; otherwise, revert to the previous layout width.
+    
+    (WebKit::WebPage::shouldIgnoreMetaViewport const):
+    
+    Pull some common logic out into a readonly getter.
+    
+    (WebKit::WebPage::updateVisibleContentRects):
+    
+    See the comment below WebPreferences.yaml, above.
+    
+    LayoutTests:
+    
+    Introduces new layout tests, and adjusts some existing tests. See comments below.
+    
+    * fast/viewport/ios/shrink-to-fit-content-constant-width-expected.txt: Added.
+    * fast/viewport/ios/shrink-to-fit-content-constant-width.html: Added.
+    
+    Add a new layout test to exercise the scenario where a constant width viewport narrower than the view is used.
+    
+    * fast/viewport/ios/shrink-to-fit-content-large-width-breakpoint-expected.txt: Added.
+    * fast/viewport/ios/shrink-to-fit-content-large-width-breakpoint.html: Added.
+    
+    Add a new layout test to exercise the scenario where a responsive website that lays out larger than the view
+    width ends up with even more horizontal scrolling when laying out at the initial content width. In this
+    scenario, we shouldn't try to expand the viewport to try and encompass the content width, since that would only
+    induce even worse horizontal scrolling.
+    
+    * fast/viewport/ios/shrink-to-fit-content-no-viewport-expected.txt: Added.
+    * fast/viewport/ios/shrink-to-fit-content-no-viewport.html: Added.
+    
+    Add a new layout test for the case where there is no viewport, but content lays out wider than the view.
+    
+    * fast/viewport/ios/shrink-to-fit-content-responsive-viewport-with-horizontal-overflow-expected.txt: Added.
+    * fast/viewport/ios/shrink-to-fit-content-responsive-viewport-with-horizontal-overflow.html: Added.
+    
+    Add a new layout test for the case where the page has opted for a responsive viewport (device-width, initial
+    scale 1), but has laid out wider than the viewport anyways. In this case, we want to shrink the contents down to
+    fit inside the view.
+    
+    * fast/viewport/ios/shrink-to-fit-content-temporary-overflow-expected.txt: Added.
+    * fast/viewport/ios/shrink-to-fit-content-temporary-overflow.html: Added.
+    
+    Add a new layout test to exercise the case where, during page load, content width temporarily increases, and
+    then decreases such that it once again fits within the viewport. In this case, we don't want to expand the
+    viewport to be as wide as the large temporary width of the page.
+    
+    * fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden-expected.txt:
+    * fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden.html:
+    * fast/viewport/ios/width-is-device-width-overflowing-expected.txt:
+    * fast/viewport/ios/width-is-device-width-overflowing.html:
+    
+    Tweak these 2 existing layout tests to include "shrink-to-fit=no", to prevent the new heuristics from shrinking
+    the page to fit on device classes that use native viewports by default.
+    
+    * platform/ipad/fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden-expected.txt:
+    * platform/ipad/fast/viewport/ios/width-is-device-width-overflowing-expected.txt:
+    
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244849 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2019-05-01  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+            [iOS] Add a version of viewport shrink-to-fit heuristics that preserves page layout
+            https://bugs.webkit.org/show_bug.cgi?id=197342
+            <rdar://problem/50063091>
+
+            Reviewed by Tim Horton.
+
+            Adds support for a new shrink-to-fit heuristic that attempts to lay out the contents of the page at a larger
+            width in order to shrink content to fit the viewport. See WebKit ChangeLog for more details.
+
+            Tests: fast/viewport/ios/shrink-to-fit-content-constant-width.html
+                   fast/viewport/ios/shrink-to-fit-content-large-width-breakpoint.html
+                   fast/viewport/ios/shrink-to-fit-content-no-viewport.html
+                   fast/viewport/ios/shrink-to-fit-content-responsive-viewport-with-horizontal-overflow.html
+                   fast/viewport/ios/shrink-to-fit-content-temporary-overflow.html
+
+            * page/ViewportConfiguration.cpp:
+            (WebCore::ViewportConfiguration::setMinimumEffectiveDeviceWidth):
+            (WebCore::ViewportConfiguration::setIsKnownToLayOutWiderThanViewport):
+            (WebCore::ViewportConfiguration::description const):
+            * page/ViewportConfiguration.h:
+            (WebCore::ViewportConfiguration::canIgnoreScalingConstraints const):
+            (WebCore::ViewportConfiguration::minimumEffectiveDeviceWidth const):
+
+            Add several new getters and setters in ViewportConfiguration.
+
+            (WebCore::ViewportConfiguration::isKnownToLayOutWiderThanViewport const):
+            (WebCore::ViewportConfiguration::shouldIgnoreMinimumEffectiveDeviceWidth const):
+
+            Importantly, only allow ignoring the minimum effective device width in webpages with responsive viewports, if
+            they also have *not* laid out wider than the viewport.
+
+            (WebCore::ViewportConfiguration::setForceAlwaysUserScalable):
+
+2019-05-02  Alan Coon  <alancoon@apple.com>
+
</ins><span class="cx">         Cherry-pick r244823. rdar://problem/46677392
</span><span class="cx"> 
</span><span class="cx">     XMLHttpRequest should propagate user gestures for media playback
</span></span></pre></div>
<a id="tagsSafari6081201SourceWebCorepageViewportConfigurationcpp"></a>
<div class="modfile"><h4>Modified: tags/Safari-608.1.20.1/Source/WebCore/page/ViewportConfiguration.cpp (244885 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/Source/WebCore/page/ViewportConfiguration.cpp     2019-05-02 21:08:26 UTC (rev 244885)
+++ tags/Safari-608.1.20.1/Source/WebCore/page/ViewportConfiguration.cpp        2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -586,6 +586,32 @@
</span><span class="cx">     return minimumLayoutSize.height();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool ViewportConfiguration::setMinimumEffectiveDeviceWidth(double width)
+{
+    if (WTF::areEssentiallyEqual(m_minimumEffectiveDeviceWidth, width))
+        return false;
+
+    m_minimumEffectiveDeviceWidth = width;
+
+    if (shouldIgnoreMinimumEffectiveDeviceWidth())
+        return false;
+
+    updateMinimumLayoutSize();
+    updateConfiguration();
+    return true;
+}
+
+bool ViewportConfiguration::setIsKnownToLayOutWiderThanViewport(bool value)
+{
+    if (m_isKnownToLayOutWiderThanViewport == value)
+        return false;
+
+    m_isKnownToLayOutWiderThanViewport = value;
+    updateMinimumLayoutSize();
+    updateConfiguration();
+    return true;
+}
+
</ins><span class="cx"> #ifndef NDEBUG
</span><span class="cx"> 
</span><span class="cx"> TextStream& operator<<(TextStream& ts, const ViewportConfiguration::Parameters& parameters)
</span><span class="lines">@@ -649,6 +675,7 @@
</span><span class="cx">     ts.dumpProperty("ignoring vertical scaling constraints", shouldIgnoreVerticalScalingConstraints() ? "true" : "false");
</span><span class="cx">     ts.dumpProperty("avoids unsafe area", avoidsUnsafeArea() ? "true" : "false");
</span><span class="cx">     ts.dumpProperty("minimum effective device width", m_minimumEffectiveDeviceWidth);
</span><ins>+    ts.dumpProperty("known to lay out wider than viewport", m_isKnownToLayOutWiderThanViewport ? "true" : "false");
</ins><span class="cx">     
</span><span class="cx">     ts.endGroup();
</span><span class="cx"> 
</span></span></pre></div>
<a id="tagsSafari6081201SourceWebCorepageViewportConfigurationh"></a>
<div class="modfile"><h4>Modified: tags/Safari-608.1.20.1/Source/WebCore/page/ViewportConfiguration.h (244885 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/Source/WebCore/page/ViewportConfiguration.h       2019-05-02 21:08:26 UTC (rev 244885)
+++ tags/Safari-608.1.20.1/Source/WebCore/page/ViewportConfiguration.h  2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -86,11 +86,38 @@
</span><span class="cx">     WEBCORE_EXPORT bool setViewportArguments(const ViewportArguments&);
</span><span class="cx"> 
</span><span class="cx">     WEBCORE_EXPORT bool setCanIgnoreScalingConstraints(bool);
</span><ins>+    constexpr bool canIgnoreScalingConstraints() const { return m_canIgnoreScalingConstraints; }
+
+    WEBCORE_EXPORT bool setMinimumEffectiveDeviceWidth(double);
+    constexpr double minimumEffectiveDeviceWidth() const
+    {
+        if (shouldIgnoreMinimumEffectiveDeviceWidth())
+            return 0;
+        return m_minimumEffectiveDeviceWidth;
+    }
+
+    constexpr bool isKnownToLayOutWiderThanViewport() const { return m_isKnownToLayOutWiderThanViewport; }
+    WEBCORE_EXPORT bool setIsKnownToLayOutWiderThanViewport(bool value);
+
+    constexpr bool shouldIgnoreMinimumEffectiveDeviceWidth() const
+    {
+        if (m_canIgnoreScalingConstraints)
+            return true;
+
+        if (m_viewportArguments == ViewportArguments())
+            return false;
+
+        if ((m_viewportArguments.zoom == 1. || m_viewportArguments.width == ViewportArguments::ValueDeviceWidth) && !m_isKnownToLayOutWiderThanViewport)
+            return true;
+
+        return false;
+    }
+
</ins><span class="cx">     void setForceAlwaysUserScalable(bool forceAlwaysUserScalable) { m_forceAlwaysUserScalable = forceAlwaysUserScalable; }
</span><del>-
</del><span class="cx">     double layoutSizeScaleFactor() const { return m_layoutSizeScaleFactor; }
</span><span class="cx"> 
</span><span class="cx">     WEBCORE_EXPORT IntSize layoutSize() const;
</span><ins>+    WEBCORE_EXPORT int layoutWidth() const;
</ins><span class="cx">     WEBCORE_EXPORT double initialScale() const;
</span><span class="cx">     WEBCORE_EXPORT double initialScaleIgnoringContentSize() const;
</span><span class="cx">     WEBCORE_EXPORT double minimumScale() const;
</span><span class="lines">@@ -98,7 +125,6 @@
</span><span class="cx">     double maximumScaleIgnoringAlwaysScalable() const { return m_configuration.maximumScale; }
</span><span class="cx">     WEBCORE_EXPORT bool allowsUserScaling() const;
</span><span class="cx">     WEBCORE_EXPORT bool allowsUserScalingIgnoringAlwaysScalable() const;
</span><del>-    bool allowsShrinkToFit() const;
</del><span class="cx">     bool avoidsUnsafeArea() const { return m_configuration.avoidsUnsafeArea; }
</span><span class="cx"> 
</span><span class="cx">     // Matches a width=device-width, initial-scale=1 viewport.
</span><span class="lines">@@ -120,7 +146,6 @@
</span><span class="cx">     void updateConfiguration();
</span><span class="cx">     double viewportArgumentsLength(double length) const;
</span><span class="cx">     double initialScaleFromSize(double width, double height, bool shouldIgnoreScalingConstraints) const;
</span><del>-    int layoutWidth() const;
</del><span class="cx">     int layoutHeight() const;
</span><span class="cx"> 
</span><span class="cx">     bool shouldOverrideDeviceWidthAndShrinkToFit() const;
</span><span class="lines">@@ -131,27 +156,6 @@
</span><span class="cx">     void updateDefaultConfiguration();
</span><span class="cx">     bool canOverrideConfigurationParameters() const;
</span><span class="cx"> 
</span><del>-    constexpr bool shouldIgnoreMinimumEffectiveDeviceWidth() const
-    {
-        if (m_canIgnoreScalingConstraints)
-            return true;
-
-        if (m_viewportArguments == ViewportArguments())
-            return false;
-
-        if (m_viewportArguments.width == ViewportArguments::ValueDeviceWidth || m_viewportArguments.zoom == 1.)
-            return true;
-
-        return false;
-    }
-
-    constexpr double minimumEffectiveDeviceWidth() const
-    {
-        if (shouldIgnoreMinimumEffectiveDeviceWidth())
-            return 0;
-        return m_minimumEffectiveDeviceWidth;
-    }
-
</del><span class="cx">     constexpr double forceAlwaysUserScalableMaximumScale() const
</span><span class="cx">     {
</span><span class="cx">         const double forceAlwaysUserScalableMaximumScaleIgnoringLayoutScaleFactor = 5;
</span><span class="lines">@@ -185,6 +189,7 @@
</span><span class="cx">     double m_minimumEffectiveDeviceWidth { 0 };
</span><span class="cx">     bool m_canIgnoreScalingConstraints;
</span><span class="cx">     bool m_forceAlwaysUserScalable;
</span><ins>+    bool m_isKnownToLayOutWiderThanViewport { false };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> WTF::TextStream& operator<<(WTF::TextStream&, const ViewportConfiguration::Parameters&);
</span></span></pre></div>
<a id="tagsSafari6081201SourceWebKitChangeLog"></a>
<div class="modfile"><h4>Modified: tags/Safari-608.1.20.1/Source/WebKit/ChangeLog (244885 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/Source/WebKit/ChangeLog   2019-05-02 21:08:26 UTC (rev 244885)
+++ tags/Safari-608.1.20.1/Source/WebKit/ChangeLog      2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -1,3 +1,272 @@
</span><ins>+2019-05-02  Alan Coon  <alancoon@apple.com>
+
+        Cherry-pick r244849. rdar://problem/50063091
+
+    [iOS] Add a version of viewport shrink-to-fit heuristics that preserves page layout
+    https://bugs.webkit.org/show_bug.cgi?id=197342
+    <rdar://problem/50063091>
+    
+    Reviewed by Tim Horton.
+    
+    Source/WebCore:
+    
+    Adds support for a new shrink-to-fit heuristic that attempts to lay out the contents of the page at a larger
+    width in order to shrink content to fit the viewport. See WebKit ChangeLog for more details.
+    
+    Tests: fast/viewport/ios/shrink-to-fit-content-constant-width.html
+           fast/viewport/ios/shrink-to-fit-content-large-width-breakpoint.html
+           fast/viewport/ios/shrink-to-fit-content-no-viewport.html
+           fast/viewport/ios/shrink-to-fit-content-responsive-viewport-with-horizontal-overflow.html
+           fast/viewport/ios/shrink-to-fit-content-temporary-overflow.html
+    
+    * page/ViewportConfiguration.cpp:
+    (WebCore::ViewportConfiguration::setMinimumEffectiveDeviceWidth):
+    (WebCore::ViewportConfiguration::setIsKnownToLayOutWiderThanViewport):
+    (WebCore::ViewportConfiguration::description const):
+    * page/ViewportConfiguration.h:
+    (WebCore::ViewportConfiguration::canIgnoreScalingConstraints const):
+    (WebCore::ViewportConfiguration::minimumEffectiveDeviceWidth const):
+    
+    Add several new getters and setters in ViewportConfiguration.
+    
+    (WebCore::ViewportConfiguration::isKnownToLayOutWiderThanViewport const):
+    (WebCore::ViewportConfiguration::shouldIgnoreMinimumEffectiveDeviceWidth const):
+    
+    Importantly, only allow ignoring the minimum effective device width in webpages with responsive viewports, if
+    they also have *not* laid out wider than the viewport.
+    
+    (WebCore::ViewportConfiguration::setForceAlwaysUserScalable):
+    
+    Source/WebKit:
+    
+    This patch introduces a new shrink-to-fit heuristic that attempts to lay out the contents of the page at a
+    larger width in order to shrink content to fit the viewport. This is similar to existing shrink-to-fit behaviors
+    used for viewport sizing in multitasking mode, except that it not only scales the view, but additionally expands
+    the layout size, such that the overall layout of the page is preserved. In fact, the reason we ended up
+    reverting the existing flavor of shrink-to-fit in all cases except for multitasking was that page layout was not
+    preserved, which caused elements that poke out of the viewport to make the rest of the page look out of
+    proportion — see <rdar://problem/23818102> and related radars.
+    
+    Covered by 5 new layout tests, and by adjusting a couple of existing layout tests. See comments below for more
+    details.
+    
+    * Platform/Logging.h:
+    
+    Add a new ViewportSizing logging channel. This will only log on pages that overflow the viewport and shrink to
+    fit as a result.
+    
+    * Shared/WebPreferences.yaml:
+    
+    Turn IgnoreViewportScalingConstraints off by default. This preference currently controls whether we allow
+    shrink-to-fit behaviors, and is only used by Safari when it is in multitasking mode. The value of this
+    preference is currenly *on* by default, and is turned off almost immediately during every page load after the
+    first visible content rect update, wherein visibleContentRectUpdateInfo.allowShrinkToFit() is false.
+    
+    However, this sometimes causes a brief jitter during page load; to fix this, make the default value for
+    IgnoreViewportScalingConstraints false, and change the logic in WebPage::updateVisibleContentRects to
+    setCanIgnoreScalingConstraints to true if either the IgnoreViewportScalingConstraints preference (not only
+    affected by an internal debug switch) is true, or WKWebView SPI is used to enable the behavior.
+    
+    * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
+    (WebKit::WebFrameLoaderClient::dispatchDidFinishDocumentLoad):
+    (WebKit::WebFrameLoaderClient::dispatchDidFinishLoad):
+    
+    Add a new hook for WebFrameLoaderClient to call into WebPage when document load finishes. Also, tweak
+    dispatchDidFinishLoad to take a WebFrame& instead of a WebFrame* in a drive-by fix (the frame is assumed to be
+    non-null anyways).
+    
+    * WebProcess/WebPage/WebPage.cpp:
+    (WebKit::WebPage::didCommitLoad):
+    (WebKit::WebPage::didFinishDocumentLoad):
+    (WebKit::WebPage::didFinishLoad):
+    
+    When finishing document load or finishing the overall load, kick off the shrink-to-fit timer; when committing a
+    load, cancel the timer.
+    
+    * WebProcess/WebPage/WebPage.h:
+    * WebProcess/WebPage/ios/WebPageIOS.mm:
+    (WebKit::WebPage::setViewportConfigurationViewLayoutSize):
+    
+    Don't allow the minimum effective device width from the client to stomp over any minimum effective device width
+    set as a result of the new shrink-to-fit heuristic; on some pages that load quickly, this can result in a race
+    where the minimum effective device width (i.e. a value that lower-bounds the minimum layout width) is first set
+    by the shrink-to-fit heuristic, and then set to an incorrect value by the client.
+    
+    In the near future, web view SPI used to set the minimum effective device width should actually be removed
+    altogether, since the new shrink-to-fit heuristic supersedes any need for the client to fiddle with the minimum
+    effective device width.
+    
+    (WebKit::WebPage::dynamicViewportSizeUpdate):
+    
+    When performing a dynamic viewport size update, additionally re-run the shrink-to-fit heuristic. This allows
+    the minimum layout size of the viewport to be updated, if necessary. An example of where this matters is when a
+    web page is *below* a tablet/desktop layout breakpoint in portrait device orientation, but then exceeds this
+    layout breakpoint in landscape orientation. In this scenario, rotating the device should swap between these two
+    page layouts.
+    
+    (WebKit::WebPage::resetViewportDefaultConfiguration):
+    (WebKit::WebPage::scheduleShrinkToFitContent):
+    (WebKit::WebPage::shrinkToFitContentTimerFired):
+    (WebKit::WebPage::immediatelyShrinkToFitContent):
+    
+    Leverage the existing capability for a viewport to have a "minimum effective device width" to grant the viewport
+    a larger layout size than it would normally have, and then scale down to fit within the bounds of the view. One
+    challenge with this overall approach is that laying out at a larger width may cause the page to lay out even
+    wider in response, which may actually worsen horizontal scrolling. To mitigate this, we only attempt to lay out
+    at the current content width once; if laying out at this width reduced the amount of horizontal scrolling by any
+    amount, then proceed with this layout width; otherwise, revert to the previous layout width.
+    
+    (WebKit::WebPage::shouldIgnoreMetaViewport const):
+    
+    Pull some common logic out into a readonly getter.
+    
+    (WebKit::WebPage::updateVisibleContentRects):
+    
+    See the comment below WebPreferences.yaml, above.
+    
+    LayoutTests:
+    
+    Introduces new layout tests, and adjusts some existing tests. See comments below.
+    
+    * fast/viewport/ios/shrink-to-fit-content-constant-width-expected.txt: Added.
+    * fast/viewport/ios/shrink-to-fit-content-constant-width.html: Added.
+    
+    Add a new layout test to exercise the scenario where a constant width viewport narrower than the view is used.
+    
+    * fast/viewport/ios/shrink-to-fit-content-large-width-breakpoint-expected.txt: Added.
+    * fast/viewport/ios/shrink-to-fit-content-large-width-breakpoint.html: Added.
+    
+    Add a new layout test to exercise the scenario where a responsive website that lays out larger than the view
+    width ends up with even more horizontal scrolling when laying out at the initial content width. In this
+    scenario, we shouldn't try to expand the viewport to try and encompass the content width, since that would only
+    induce even worse horizontal scrolling.
+    
+    * fast/viewport/ios/shrink-to-fit-content-no-viewport-expected.txt: Added.
+    * fast/viewport/ios/shrink-to-fit-content-no-viewport.html: Added.
+    
+    Add a new layout test for the case where there is no viewport, but content lays out wider than the view.
+    
+    * fast/viewport/ios/shrink-to-fit-content-responsive-viewport-with-horizontal-overflow-expected.txt: Added.
+    * fast/viewport/ios/shrink-to-fit-content-responsive-viewport-with-horizontal-overflow.html: Added.
+    
+    Add a new layout test for the case where the page has opted for a responsive viewport (device-width, initial
+    scale 1), but has laid out wider than the viewport anyways. In this case, we want to shrink the contents down to
+    fit inside the view.
+    
+    * fast/viewport/ios/shrink-to-fit-content-temporary-overflow-expected.txt: Added.
+    * fast/viewport/ios/shrink-to-fit-content-temporary-overflow.html: Added.
+    
+    Add a new layout test to exercise the case where, during page load, content width temporarily increases, and
+    then decreases such that it once again fits within the viewport. In this case, we don't want to expand the
+    viewport to be as wide as the large temporary width of the page.
+    
+    * fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden-expected.txt:
+    * fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden.html:
+    * fast/viewport/ios/width-is-device-width-overflowing-expected.txt:
+    * fast/viewport/ios/width-is-device-width-overflowing.html:
+    
+    Tweak these 2 existing layout tests to include "shrink-to-fit=no", to prevent the new heuristics from shrinking
+    the page to fit on device classes that use native viewports by default.
+    
+    * platform/ipad/fast/viewport/ios/width-is-device-width-overflowing-body-overflow-hidden-expected.txt:
+    * platform/ipad/fast/viewport/ios/width-is-device-width-overflowing-expected.txt:
+    
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244849 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2019-05-01  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+            [iOS] Add a version of viewport shrink-to-fit heuristics that preserves page layout
+            https://bugs.webkit.org/show_bug.cgi?id=197342
+            <rdar://problem/50063091>
+
+            Reviewed by Tim Horton.
+
+            This patch introduces a new shrink-to-fit heuristic that attempts to lay out the contents of the page at a
+            larger width in order to shrink content to fit the viewport. This is similar to existing shrink-to-fit behaviors
+            used for viewport sizing in multitasking mode, except that it not only scales the view, but additionally expands
+            the layout size, such that the overall layout of the page is preserved. In fact, the reason we ended up
+            reverting the existing flavor of shrink-to-fit in all cases except for multitasking was that page layout was not
+            preserved, which caused elements that poke out of the viewport to make the rest of the page look out of
+            proportion — see <rdar://problem/23818102> and related radars.
+
+            Covered by 5 new layout tests, and by adjusting a couple of existing layout tests. See comments below for more
+            details.
+
+            * Platform/Logging.h:
+
+            Add a new ViewportSizing logging channel. This will only log on pages that overflow the viewport and shrink to
+            fit as a result.
+
+            * Shared/WebPreferences.yaml:
+
+            Turn IgnoreViewportScalingConstraints off by default. This preference currently controls whether we allow
+            shrink-to-fit behaviors, and is only used by Safari when it is in multitasking mode. The value of this
+            preference is currenly *on* by default, and is turned off almost immediately during every page load after the
+            first visible content rect update, wherein visibleContentRectUpdateInfo.allowShrinkToFit() is false.
+
+            However, this sometimes causes a brief jitter during page load; to fix this, make the default value for
+            IgnoreViewportScalingConstraints false, and change the logic in WebPage::updateVisibleContentRects to
+            setCanIgnoreScalingConstraints to true if either the IgnoreViewportScalingConstraints preference (not only
+            affected by an internal debug switch) is true, or WKWebView SPI is used to enable the behavior.
+
+            * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
+            (WebKit::WebFrameLoaderClient::dispatchDidFinishDocumentLoad):
+            (WebKit::WebFrameLoaderClient::dispatchDidFinishLoad):
+
+            Add a new hook for WebFrameLoaderClient to call into WebPage when document load finishes. Also, tweak
+            dispatchDidFinishLoad to take a WebFrame& instead of a WebFrame* in a drive-by fix (the frame is assumed to be
+            non-null anyways).
+
+            * WebProcess/WebPage/WebPage.cpp:
+            (WebKit::WebPage::didCommitLoad):
+            (WebKit::WebPage::didFinishDocumentLoad):
+            (WebKit::WebPage::didFinishLoad):
+
+            When finishing document load or finishing the overall load, kick off the shrink-to-fit timer; when committing a
+            load, cancel the timer.
+
+            * WebProcess/WebPage/WebPage.h:
+            * WebProcess/WebPage/ios/WebPageIOS.mm:
+            (WebKit::WebPage::setViewportConfigurationViewLayoutSize):
+
+            Don't allow the minimum effective device width from the client to stomp over any minimum effective device width
+            set as a result of the new shrink-to-fit heuristic; on some pages that load quickly, this can result in a race
+            where the minimum effective device width (i.e. a value that lower-bounds the minimum layout width) is first set
+            by the shrink-to-fit heuristic, and then set to an incorrect value by the client.
+
+            In the near future, web view SPI used to set the minimum effective device width should actually be removed
+            altogether, since the new shrink-to-fit heuristic supersedes any need for the client to fiddle with the minimum
+            effective device width.
+
+            (WebKit::WebPage::dynamicViewportSizeUpdate):
+
+            When performing a dynamic viewport size update, additionally re-run the shrink-to-fit heuristic. This allows
+            the minimum layout size of the viewport to be updated, if necessary. An example of where this matters is when a
+            web page is *below* a tablet/desktop layout breakpoint in portrait device orientation, but then exceeds this
+            layout breakpoint in landscape orientation. In this scenario, rotating the device should swap between these two
+            page layouts.
+
+            (WebKit::WebPage::resetViewportDefaultConfiguration):
+            (WebKit::WebPage::scheduleShrinkToFitContent):
+            (WebKit::WebPage::shrinkToFitContentTimerFired):
+            (WebKit::WebPage::immediatelyShrinkToFitContent):
+
+            Leverage the existing capability for a viewport to have a "minimum effective device width" to grant the viewport
+            a larger layout size than it would normally have, and then scale down to fit within the bounds of the view. One
+            challenge with this overall approach is that laying out at a larger width may cause the page to lay out even
+            wider in response, which may actually worsen horizontal scrolling. To mitigate this, we only attempt to lay out
+            at the current content width once; if laying out at this width reduced the amount of horizontal scrolling by any
+            amount, then proceed with this layout width; otherwise, revert to the previous layout width.
+
+            (WebKit::WebPage::shouldIgnoreMetaViewport const):
+
+            Pull some common logic out into a readonly getter.
+
+            (WebKit::WebPage::updateVisibleContentRects):
+
+            See the comment below WebPreferences.yaml, above.
+
</ins><span class="cx"> 2019-04-30  Chris Dumez  <cdumez@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Regression(PSON) URL scheme handlers can no longer respond asynchronously
</span></span></pre></div>
<a id="tagsSafari6081201SourceWebKitPlatformLoggingh"></a>
<div class="modfile"><h4>Modified: tags/Safari-608.1.20.1/Source/WebKit/Platform/Logging.h (244885 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/Source/WebKit/Platform/Logging.h  2019-05-02 21:08:26 UTC (rev 244885)
+++ tags/Safari-608.1.20.1/Source/WebKit/Platform/Logging.h     2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -85,6 +85,7 @@
</span><span class="cx">     M(TextInput) \
</span><span class="cx">     M(ViewGestures) \
</span><span class="cx">     M(ViewState) \
</span><ins>+    M(ViewportSizing) \
</ins><span class="cx">     M(VirtualMemory) \
</span><span class="cx">     M(VisibleRects) \
</span><span class="cx">     M(WebGL) \
</span></span></pre></div>
<a id="tagsSafari6081201SourceWebKitSharedWebPreferencesyaml"></a>
<div class="modfile"><h4>Modified: tags/Safari-608.1.20.1/Source/WebKit/Shared/WebPreferences.yaml (244885 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/Source/WebKit/Shared/WebPreferences.yaml  2019-05-02 21:08:26 UTC (rev 244885)
+++ tags/Safari-608.1.20.1/Source/WebKit/Shared/WebPreferences.yaml     2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -1089,7 +1089,7 @@
</span><span class="cx"> 
</span><span class="cx"> IgnoreViewportScalingConstraints:
</span><span class="cx">   type: bool
</span><del>-  defaultValue: true
</del><ins>+  defaultValue: false
</ins><span class="cx">   category: debug
</span><span class="cx">   webcoreBinding: none
</span><span class="cx">   condition: PLATFORM(IOS_FAMILY)
</span></span></pre></div>
<a id="tagsSafari6081201SourceWebKitWebProcessWebCoreSupportWebFrameLoaderClientcpp"></a>
<div class="modfile"><h4>Modified: tags/Safari-608.1.20.1/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp (244885 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp  2019-05-02 21:08:26 UTC (rev 244885)
+++ tags/Safari-608.1.20.1/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp     2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -609,6 +609,8 @@
</span><span class="cx"> 
</span><span class="cx">     // Notify the UIProcess.
</span><span class="cx">     webPage->send(Messages::WebPageProxy::DidFinishDocumentLoadForFrame(m_frame->frameID(), navigationID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
</span><ins>+
+    webPage->didFinishDocumentLoad(*m_frame);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebFrameLoaderClient::dispatchDidFinishLoad()
</span><span class="lines">@@ -631,7 +633,7 @@
</span><span class="cx">     if (WebFrame::LoadListener* loadListener = m_frame->loadListener())
</span><span class="cx">         loadListener->didFinishLoad(m_frame);
</span><span class="cx"> 
</span><del>-    webPage->didFinishLoad(m_frame);
</del><ins>+    webPage->didFinishLoad(*m_frame);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebFrameLoaderClient::forcePageTransitionIfNeeded()
</span></span></pre></div>
<a id="tagsSafari6081201SourceWebKitWebProcessWebPageWebPagecpp"></a>
<div class="modfile"><h4>Modified: tags/Safari-608.1.20.1/Source/WebKit/WebProcess/WebPage/WebPage.cpp (244885 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/Source/WebKit/WebProcess/WebPage/WebPage.cpp      2019-05-02 21:08:26 UTC (rev 244885)
+++ tags/Safari-608.1.20.1/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -424,6 +424,9 @@
</span><span class="cx"> #if PLATFORM(WPE)
</span><span class="cx">     , m_hostFileDescriptor(WTFMove(parameters.hostFileDescriptor))
</span><span class="cx"> #endif
</span><ins>+#if ENABLE(VIEWPORT_RESIZING)
+    , m_shrinkToFitContentTimer(*this, &WebPage::shrinkToFitContentTimerFired, 0_s)
+#endif
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(m_pageID);
</span><span class="cx"> 
</span><span class="lines">@@ -5714,6 +5717,10 @@
</span><span class="cx">         viewportConfigurationChanged();
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(VIEWPORT_RESIZING)
+    m_shrinkToFitContentTimer.stop();
+#endif
+
</ins><span class="cx"> #if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
</span><span class="cx">     resetPrimarySnapshottedPlugIn();
</span><span class="cx"> #endif
</span><span class="lines">@@ -5727,13 +5734,23 @@
</span><span class="cx">     updateMainFrameScrollOffsetPinning();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebPage::didFinishLoad(WebFrame* frame)
</del><ins>+void WebPage::didFinishDocumentLoad(WebFrame& frame)
</ins><span class="cx"> {
</span><del>-    if (!frame->isMainFrame())
</del><ins>+    if (!frame.isMainFrame())
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    WebProcess::singleton().sendPrewarmInformation(frame->url());
</del><ins>+#if ENABLE(VIEWPORT_RESIZING)
+    scheduleShrinkToFitContent();
+#endif
+}
</ins><span class="cx"> 
</span><ins>+void WebPage::didFinishLoad(WebFrame& frame)
+{
+    if (!frame.isMainFrame())
+        return;
+
+    WebProcess::singleton().sendPrewarmInformation(frame.url());
+
</ins><span class="cx"> #if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
</span><span class="cx">     m_readyToFindPrimarySnapshottedPlugin = true;
</span><span class="cx">     LOG(Plugins, "Primary Plug-In Detection: triggering detection from didFinishLoad (marking as ready to detect).");
</span><span class="lines">@@ -5741,6 +5758,10 @@
</span><span class="cx"> #else
</span><span class="cx">     UNUSED_PARAM(frame);
</span><span class="cx"> #endif
</span><ins>+
+#if ENABLE(VIEWPORT_RESIZING)
+    scheduleShrinkToFitContent();
+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebPage::didInsertMenuElement(HTMLMenuElement& element)
</span></span></pre></div>
<a id="tagsSafari6081201SourceWebKitWebProcessWebPageWebPageh"></a>
<div class="modfile"><h4>Modified: tags/Safari-608.1.20.1/Source/WebKit/WebProcess/WebPage/WebPage.h (244885 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/Source/WebKit/WebProcess/WebPage/WebPage.h        2019-05-02 21:08:26 UTC (rev 244885)
+++ tags/Safari-608.1.20.1/Source/WebKit/WebProcess/WebPage/WebPage.h   2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -131,6 +131,8 @@
</span><span class="cx"> OBJC_CLASS WKAccessibilityWebPageObject;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#define ENABLE_VIEWPORT_RESIZING PLATFORM(IOS_FAMILY)
+
</ins><span class="cx"> namespace API {
</span><span class="cx"> class Array;
</span><span class="cx"> }
</span><span class="lines">@@ -349,7 +351,8 @@
</span><span class="cx">     void didCommitLoad(WebFrame*);
</span><span class="cx">     void willReplaceMultipartContent(const WebFrame&);
</span><span class="cx">     void didReplaceMultipartContent(const WebFrame&);
</span><del>-    void didFinishLoad(WebFrame*);
</del><ins>+    void didFinishDocumentLoad(WebFrame&);
+    void didFinishLoad(WebFrame&);
</ins><span class="cx">     void show();
</span><span class="cx">     String userAgent(const URL&) const;
</span><span class="cx">     String platformUserAgent(const URL&) const;
</span><span class="lines">@@ -1228,8 +1231,15 @@
</span><span class="cx">     InteractionInformationAtPosition positionInformation(const InteractionInformationRequest&);
</span><span class="cx">     WebAutocorrectionContext autocorrectionContext();
</span><span class="cx">     bool applyAutocorrectionInternal(const String& correction, const String& originalText);
</span><ins>+    bool shouldIgnoreMetaViewport() const;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(VIEWPORT_RESIZING)
+    void scheduleShrinkToFitContent();
+    void shrinkToFitContentTimerFired();
+    bool immediatelyShrinkToFitContent();
+#endif
+
</ins><span class="cx"> #if PLATFORM(IOS_FAMILY) && ENABLE(DATA_INTERACTION)
</span><span class="cx">     void requestDragStart(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition, uint64_t allowedActions);
</span><span class="cx">     void requestAdditionalItemsForDragSession(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition, uint64_t allowedActions);
</span><span class="lines">@@ -1894,6 +1904,9 @@
</span><span class="cx">     WeakPtr<RemoteObjectRegistry> m_remoteObjectRegistry;
</span><span class="cx"> #endif
</span><span class="cx">     WebCore::IntSize m_lastSentIntrinsicContentSize;
</span><ins>+#if ENABLE(VIEWPORT_RESIZING)
+    WebCore::DeferrableOneShotTimer m_shrinkToFitContentTimer;
+#endif
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="tagsSafari6081201SourceWebKitWebProcessWebPageiosWebPageIOSmm"></a>
<div class="modfile"><h4>Modified: tags/Safari-608.1.20.1/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (244885 => 244886)</h4>
<pre class="diff"><span>
<span class="info">--- tags/Safari-608.1.20.1/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm        2019-05-02 21:08:26 UTC (rev 244885)
+++ tags/Safari-608.1.20.1/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm   2019-05-02 21:08:35 UTC (rev 244886)
</span><span class="lines">@@ -2791,7 +2791,8 @@
</span><span class="cx">     LOG_WITH_STREAM(VisibleRects, stream << "WebPage " << m_pageID << " setViewportConfigurationViewLayoutSize " << size << " scaleFactor " << scaleFactor << " minimumEffectiveDeviceWidth " << minimumEffectiveDeviceWidth);
</span><span class="cx"> 
</span><span class="cx">     auto previousLayoutSizeScaleFactor = m_viewportConfiguration.layoutSizeScaleFactor();
</span><del>-    if (!m_viewportConfiguration.setViewLayoutSize(size, scaleFactor, minimumEffectiveDeviceWidth))
</del><ins>+    auto clampedMinimumEffectiveDevice = m_viewportConfiguration.isKnownToLayOutWiderThanViewport() ? WTF::nullopt : Optional<double>(minimumEffectiveDeviceWidth);
+    if (!m_viewportConfiguration.setViewLayoutSize(size, scaleFactor, WTFMove(clampedMinimumEffectiveDevice)))
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     auto zoomToInitialScale = ZoomToInitialScale::No;
</span><span class="lines">@@ -2873,8 +2874,16 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     LOG_WITH_STREAM(VisibleRects, stream << "WebPage::dynamicViewportSizeUpdate setting view layout size to " << viewLayoutSize);
</span><del>-    if (m_viewportConfiguration.setViewLayoutSize(viewLayoutSize))
</del><ins>+    bool viewportChanged = m_viewportConfiguration.setIsKnownToLayOutWiderThanViewport(false);
+    viewportChanged |= m_viewportConfiguration.setViewLayoutSize(viewLayoutSize);
+    if (viewportChanged)
</ins><span class="cx">         viewportConfigurationChanged();
</span><ins>+
+#if ENABLE(VIEWPORT_RESIZING)
+    if (immediatelyShrinkToFitContent())
+        viewportConfigurationChanged();
+#endif
+
</ins><span class="cx">     IntSize newLayoutSize = m_viewportConfiguration.layoutSize();
</span><span class="cx"> 
</span><span class="cx">     if (setFixedLayoutSize(newLayoutSize))
</span><span class="lines">@@ -3020,16 +3029,9 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     auto parametersForStandardFrame = [&] {
</span><del>-        bool shouldIgnoreMetaViewport = false;
-        if (auto* mainDocument = m_page->mainFrame().document()) {
-            auto* loader = mainDocument->loader();
-            shouldIgnoreMetaViewport = loader && loader->metaViewportPolicy() == WebCore::MetaViewportPolicy::Ignore;
-        }
-
-        if (m_page->settings().shouldIgnoreMetaViewport())
-            shouldIgnoreMetaViewport = true;
-
-        return shouldIgnoreMetaViewport ? m_viewportConfiguration.nativeWebpageParameters() : ViewportConfiguration::webpageParameters();
</del><ins>+        if (shouldIgnoreMetaViewport())
+            return m_viewportConfiguration.nativeWebpageParameters();
+        return ViewportConfiguration::webpageParameters();
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     if (!frame) {
</span><span class="lines">@@ -3049,8 +3051,85 @@
</span><span class="cx">         m_viewportConfiguration.setDefaultConfiguration(ViewportConfiguration::textDocumentParameters());
</span><span class="cx">     else
</span><span class="cx">         m_viewportConfiguration.setDefaultConfiguration(parametersForStandardFrame());
</span><ins>+    m_viewportConfiguration.setIsKnownToLayOutWiderThanViewport(false);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if ENABLE(VIEWPORT_RESIZING)
+
+void WebPage::scheduleShrinkToFitContent()
+{
+    m_shrinkToFitContentTimer.restart();
+}
+
+void WebPage::shrinkToFitContentTimerFired()
+{
+    if (immediatelyShrinkToFitContent())
+        viewportConfigurationChanged(ZoomToInitialScale::Yes);
+}
+
+bool WebPage::immediatelyShrinkToFitContent()
+{
+    if (!shouldIgnoreMetaViewport())
+        return false;
+
+    if (!m_viewportConfiguration.viewportArguments().shrinkToFit)
+        return false;
+
+    if (m_viewportConfiguration.canIgnoreScalingConstraints())
+        return false;
+
+    auto mainFrame = makeRefPtr(m_mainFrame->coreFrame());
+    if (!mainFrame)
+        return false;
+
+    auto view = makeRefPtr(mainFrame->view());
+    auto mainDocument = makeRefPtr(mainFrame->document());
+    if (!view || !mainDocument)
+        return false;
+
+    mainDocument->updateLayout();
+
+    static const int toleratedHorizontalScrollingDistance = 20;
+    static const int maximumExpandedLayoutWidth = 1280;
+    int originalContentWidth = view->contentsWidth();
+    int originalLayoutWidth = m_viewportConfiguration.layoutWidth();
+    int originalHorizontalOverflowAmount = originalContentWidth - originalLayoutWidth;
+    if (originalHorizontalOverflowAmount <= toleratedHorizontalScrollingDistance || originalLayoutWidth >= maximumExpandedLayoutWidth || originalContentWidth <= m_viewportConfiguration.viewLayoutSize().width())
+        return false;
+
+    auto changeMinimumEffectiveDeviceWidth = [this, mainDocument] (int targetLayoutWidth) -> bool {
+        if (m_viewportConfiguration.setMinimumEffectiveDeviceWidth(targetLayoutWidth)) {
+            viewportConfigurationChanged();
+            mainDocument->updateLayout();
+            return true;
+        }
+        return false;
+    };
+
+    m_viewportConfiguration.setIsKnownToLayOutWiderThanViewport(true);
+    double originalMinimumDeviceWidth = m_viewportConfiguration.minimumEffectiveDeviceWidth();
+    if (changeMinimumEffectiveDeviceWidth(std::min(maximumExpandedLayoutWidth, originalContentWidth)) && view->contentsWidth() - m_viewportConfiguration.layoutWidth() > originalHorizontalOverflowAmount) {
+        changeMinimumEffectiveDeviceWidth(originalMinimumDeviceWidth);
+        m_viewportConfiguration.setIsKnownToLayOutWiderThanViewport(false);
+    }
+
+    // FIXME (197429): Consider additionally logging an error message to the console if a responsive meta viewport tag was used.
+    RELEASE_LOG(ViewportSizing, "Shrink-to-fit: content width %d => %d; layout width %d => %d", originalContentWidth, view->contentsWidth(), originalLayoutWidth, m_viewportConfiguration.layoutWidth());
+    return true;
+}
+
+#endif // ENABLE(VIEWPORT_RESIZING)
+
+bool WebPage::shouldIgnoreMetaViewport() const
+{
+    if (auto* mainDocument = m_page->mainFrame().document()) {
+        auto* loader = mainDocument->loader();
+        if (loader && loader->metaViewportPolicy() == WebCore::MetaViewportPolicy::Ignore)
+            return true;
+    }
+    return m_page->settings().shouldIgnoreMetaViewport();
+}
+
</ins><span class="cx"> void WebPage::viewportConfigurationChanged(ZoomToInitialScale zoomToInitialScale)
</span><span class="cx"> {
</span><span class="cx">     double initialScale = m_viewportConfiguration.initialScale();
</span><span class="lines">@@ -3256,7 +3335,7 @@
</span><span class="cx">     if (scrollPosition != frameView.scrollPosition())
</span><span class="cx">         m_dynamicSizeUpdateHistory.clear();
</span><span class="cx"> 
</span><del>-    if (m_viewportConfiguration.setCanIgnoreScalingConstraints(m_ignoreViewportScalingConstraints && visibleContentRectUpdateInfo.allowShrinkToFit()))
</del><ins>+    if (m_viewportConfiguration.setCanIgnoreScalingConstraints(m_ignoreViewportScalingConstraints || visibleContentRectUpdateInfo.allowShrinkToFit()))
</ins><span class="cx">         viewportConfigurationChanged();
</span><span class="cx"> 
</span><span class="cx">     frameView.setUnobscuredContentSize(visibleContentRectUpdateInfo.unobscuredContentRect().size());
</span></span></pre>
</div>
</div>

</body>
</html>