Title: [229063] trunk
Revision
229063
Author
wenson_hs...@apple.com
Date
2018-02-27 09:16:31 -0800 (Tue, 27 Feb 2018)

Log Message

[Extra zoom mode] Implement additional SPI for adjusting viewport shrink-to-fit behavior
https://bugs.webkit.org/show_bug.cgi?id=183100
<rdar://problem/37840987>

Reviewed by Tim Horton.

Source/WebCore:

Introduce new customization options to ViewportConfiguration. The first is m_forceHorizontalShrinkToFit, which
(when set to true) forces the viewport to scale using shrink-to-fit heuristics, regardless of whether
"shrink-to-fit=no" is specified via viewport parameters or if content width did not exceed minimum layout size.
The second is m_viewSize, which reflects the true size of the viewport. See WebKit ChangeLog for more details.

Tests: ViewportSizingTests.ForceShrinkToFitViewportOverridesViewportParameters
       ViewportSizingTests.ShrinkToFitViewportWithMinimumAllowedLayoutWidth

* page/ViewportConfiguration.cpp:
(WebCore::ViewportConfiguration::ViewportConfiguration):
(WebCore::ViewportConfiguration::setMinimumLayoutSize):

Plumb the real size of the view alongside the minimum layout size when updating the minimum layout size.

(WebCore::ViewportConfiguration::setForceHorizontalShrinkToFit):
(WebCore::ViewportConfiguration::shouldIgnoreHorizontalScalingConstraints const):

Bail early and return true if forceHorizontalShrinkToFit is set. This forces shrink-to-fit even in cases where
"shrink-to-fit" is set to "no", or content dimensions don't exceed layout dimensions.

(WebCore::ViewportConfiguration::initialScaleFromSize const):

Use view dimensions rather than minimum layout dimensions when computing the initial scale. Minimum layout size
is no longer always equal to the size of the view if the client has specified a minimum allowed layout width. As
such, when computing the initial scale, to ensure that the content (which was laid out using the minimum layout
size) fits within the real viewport, we need to divide real viewport dimensions by content dimensions.

(WebCore::ViewportConfiguration::minimumScale const):

Similarly, use view size instead of minimum layout size to compute minimum scale.

(WebCore::ViewportConfiguration::description const):
* page/ViewportConfiguration.h:

Source/WebKit:

Add new SPI hooks to provide finer control over certain aspects of the shrink-to-fit viewport heuristic.
Currently, in certain cases of iPad multitasking, Safari allows shrinking content to fit by default. This means
that even when "width=device-width" is used, if the contents of the page are too wide to fit within the
viewport's width, we'll adjust the initial scale such that the viewport can fit all of the content.

However, in certain viewport dimensions, this heuristic is insufficient to ensure that pages are laid out and
displayed properly within the viewport. Namely, one could imagine that an element with a hard-coded width that
is larger than the real viewport width would cause all other elements with dimensions relative to the body to be
excessively shrunk down once shrink-to-fit is applied, so the page would still look broken even if the contents
of the page all fit within the viewport.

To mitigate this, we decouple the notions of minimum layout size from the size of the actual viewport (which we
simply refer to as "view size"). This allows us to introduce a mechanism where we lay out the page at a given
minimum layout size that is larger than the size of the view; later, when we determine the initial scale, we
then apply shrink-to-fit scaling using the view size rather than the minimum layout size. This grants us the
ability to lay out content as if our view were large, but still ensure that the contents of the page fit within
the actual view.

* Shared/VisibleContentRectUpdateInfo.cpp:
(WebKit::VisibleContentRectUpdateInfo::encode const):
(WebKit::VisibleContentRectUpdateInfo::decode):
(WebKit::operator<<):
* Shared/VisibleContentRectUpdateInfo.h:
(WebKit::VisibleContentRectUpdateInfo::VisibleContentRectUpdateInfo):
(WebKit::VisibleContentRectUpdateInfo::forceHorizontalShrinkToFit const):
(WebKit::operator==):

Plumb the forceHorizontalShrinkToFit flag through VisibleContentRectUpdateInfo.

* Shared/WebPageCreationParameters.cpp:
(WebKit::WebPageCreationParameters::encode const):
(WebKit::WebPageCreationParameters::decode):
* Shared/WebPageCreationParameters.h:

Plumb viewSize through IPC to WebPage.

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _initializeWithConfiguration:]):

Start off WKWebView flags at their initial values.

(-[WKWebView _minimumAllowedLayoutWidth]):
(-[WKWebView _setMinimumAllowedLayoutWidth:]):

This provides the minimum width at which the page will lay out, such that if the view width dips below this
value, we'll use this minimum allowed layout width instead. 0 by default.

(-[WKWebView activeMinimumLayoutSizes:]):

Refactor this from a static function to a helper method on WKWebView that computes both the minimum layout size
(which takes minimum allowed layout width into account) as well as the real view size. Refactor all call sites
to use this new method, and also propagate the view size down via IPC, alongside the minimum layout size.

(-[WKWebView _dispatchSetMinimumLayoutSize:viewSize:]):
(-[WKWebView _frameOrBoundsChanged]):
(-[WKWebView _setMinimumLayoutSizeOverride:]):
(-[WKWebView _setForceHorizontalViewportShrinkToFit:]):
(-[WKWebView _forceHorizontalViewportShrinkToFit]):

Setting this flag to YES forces us to always shrink-to-fit in the horizontal axis. NO by default.

(-[WKWebView _beginAnimatedResizeWithUpdates:]):
(-[WKWebView _endAnimatedResize]):
(activeMinimumLayoutSize): Deleted.

More refactoring to replace activeMinimumLayoutSize() with -activeMinimumLayoutSizes:.

(-[WKWebView _dispatchSetMinimumLayoutSize:]): Deleted.
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::creationParameters):
* UIProcess/WebPageProxy.h:
* UIProcess/ios/WKContentView.mm:
(-[WKContentView didUpdateVisibleRect:unobscuredRect:unobscuredRectInScrollViewCoordinates:obscuredInsets:unobscuredSafeAreaInsets:inputViewBounds:scale:minimumScale:inStableState:isChangingObscuredInsetsInteractively:enclosedInScrollableAncestorView:]):

Pass _forceHorizontalViewportShrinkToFit into the visible content rect update.

* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::dynamicViewportSizeUpdate):
(WebKit::WebPageProxy::setViewportConfigurationMinimumLayoutSize):

Plumb viewSize alongside the existing minimumLayoutSize.

* WebProcess/WebPage/WebPage.cpp:
(WebKit::m_credentialsMessenger):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::setViewportConfigurationMinimumLayoutSize):
(WebKit::WebPage::dynamicViewportSizeUpdate):
(WebKit::WebPage::updateVisibleContentRects):

Set forceHorizontalShrinkToFit on the viewport configuration here.

Tools:

Add API tests that exercise -_setMinimumAllowedLayoutWidth: and -_setForceHorizontalViewportShrinkToFit:. See
WebKit ChangeLog for more detail.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/ios/ViewportSizingTests.mm: Added.
(TestWebKitAPI::while):
(viewportTestPageMarkup):
(TestWebKitAPI::TEST):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (229062 => 229063)


--- trunk/Source/WebCore/ChangeLog	2018-02-27 16:43:22 UTC (rev 229062)
+++ trunk/Source/WebCore/ChangeLog	2018-02-27 17:16:31 UTC (rev 229063)
@@ -1,5 +1,47 @@
 2018-02-27  Wenson Hsieh  <wenson_hs...@apple.com>
 
+        [Extra zoom mode] Implement additional SPI for adjusting viewport shrink-to-fit behavior
+        https://bugs.webkit.org/show_bug.cgi?id=183100
+        <rdar://problem/37840987>
+
+        Reviewed by Tim Horton.
+
+        Introduce new customization options to ViewportConfiguration. The first is m_forceHorizontalShrinkToFit, which
+        (when set to true) forces the viewport to scale using shrink-to-fit heuristics, regardless of whether
+        "shrink-to-fit=no" is specified via viewport parameters or if content width did not exceed minimum layout size.
+        The second is m_viewSize, which reflects the true size of the viewport. See WebKit ChangeLog for more details.
+
+        Tests: ViewportSizingTests.ForceShrinkToFitViewportOverridesViewportParameters
+               ViewportSizingTests.ShrinkToFitViewportWithMinimumAllowedLayoutWidth
+
+        * page/ViewportConfiguration.cpp:
+        (WebCore::ViewportConfiguration::ViewportConfiguration):
+        (WebCore::ViewportConfiguration::setMinimumLayoutSize):
+
+        Plumb the real size of the view alongside the minimum layout size when updating the minimum layout size.
+
+        (WebCore::ViewportConfiguration::setForceHorizontalShrinkToFit):
+        (WebCore::ViewportConfiguration::shouldIgnoreHorizontalScalingConstraints const):
+
+        Bail early and return true if forceHorizontalShrinkToFit is set. This forces shrink-to-fit even in cases where
+        "shrink-to-fit" is set to "no", or content dimensions don't exceed layout dimensions.
+
+        (WebCore::ViewportConfiguration::initialScaleFromSize const):
+
+        Use view dimensions rather than minimum layout dimensions when computing the initial scale. Minimum layout size
+        is no longer always equal to the size of the view if the client has specified a minimum allowed layout width. As
+        such, when computing the initial scale, to ensure that the content (which was laid out using the minimum layout
+        size) fits within the real viewport, we need to divide real viewport dimensions by content dimensions.
+
+        (WebCore::ViewportConfiguration::minimumScale const):
+
+        Similarly, use view size instead of minimum layout size to compute minimum scale.
+
+        (WebCore::ViewportConfiguration::description const):
+        * page/ViewportConfiguration.h:
+
+2018-02-27  Wenson Hsieh  <wenson_hs...@apple.com>
+
         Unreviewed, fix the debug build after r228877.
 
         In the case where CAN_DISALLOW_USER_INSTALLED_FONTS is enabled, this function doesn't return anything when

Modified: trunk/Source/WebCore/page/ViewportConfiguration.cpp (229062 => 229063)


--- trunk/Source/WebCore/page/ViewportConfiguration.cpp	2018-02-27 16:43:22 UTC (rev 229062)
+++ trunk/Source/WebCore/page/ViewportConfiguration.cpp	2018-02-27 17:16:31 UTC (rev 229063)
@@ -49,6 +49,7 @@
     : m_minimumLayoutSize(1024, 768)
     , m_canIgnoreScalingConstraints(false)
     , m_forceAlwaysUserScalable(false)
+    , m_forceHorizontalShrinkToFit(false)
 {
     // Setup a reasonable default configuration to avoid computing infinite scale/sizes.
     // Those are the original iPhone configuration.
@@ -82,12 +83,14 @@
     return true;
 }
 
-bool ViewportConfiguration::setMinimumLayoutSize(const FloatSize& minimumLayoutSize)
+bool ViewportConfiguration::setMinimumLayoutSize(const FloatSize& minimumLayoutSize, const FloatSize& viewSize)
 {
-    if (m_minimumLayoutSize == minimumLayoutSize)
+    if (m_minimumLayoutSize == minimumLayoutSize && m_viewSize == viewSize)
         return false;
 
     m_minimumLayoutSize = minimumLayoutSize;
+    m_viewSize = viewSize;
+
     updateConfiguration();
     return true;
 }
@@ -103,6 +106,15 @@
     return true;
 }
 
+bool ViewportConfiguration::setForceHorizontalShrinkToFit(bool forceHorizontalShrinkToFit)
+{
+    if (m_forceHorizontalShrinkToFit == forceHorizontalShrinkToFit)
+        return false;
+
+    m_forceHorizontalShrinkToFit = forceHorizontalShrinkToFit;
+    return true;
+}
+
 bool ViewportConfiguration::setCanIgnoreScalingConstraints(bool canIgnoreScalingConstraints)
 {
     if (canIgnoreScalingConstraints == m_canIgnoreScalingConstraints)
@@ -123,6 +135,9 @@
     if (!m_canIgnoreScalingConstraints)
         return false;
 
+    if (m_forceHorizontalShrinkToFit)
+        return true;
+
     if (!m_configuration.allowsShrinkToFit)
         return false;
 
@@ -167,14 +182,14 @@
 
     // If not, it is up to us to determine the initial scale.
     // We want a scale small enough to fit the document width-wise.
-    const FloatSize& minimumLayoutSize = m_minimumLayoutSize;
     double initialScale = 0;
     if (width > 0 && !shouldIgnoreVerticalScalingConstraints())
-        initialScale = minimumLayoutSize.width() / width;
+        initialScale = m_viewSize.width() / width;
 
     // Prevent the initial scale from shrinking to a height smaller than our view's minimum height.
-    if (height > 0 && height * initialScale < minimumLayoutSize.height() && !shouldIgnoreHorizontalScalingConstraints())
-        initialScale = minimumLayoutSize.height() / height;
+    if (height > 0 && height * initialScale < m_viewSize.height() && !shouldIgnoreHorizontalScalingConstraints())
+        initialScale = m_viewSize.height() / height;
+
     return std::min(std::max(initialScale, shouldIgnoreScalingConstraints ? m_defaultConfiguration.minimumScale : m_configuration.minimumScale), m_configuration.maximumScale);
 }
 
@@ -200,14 +215,13 @@
     if (m_forceAlwaysUserScalable)
         minimumScale = std::min(minimumScale, forceAlwaysUserScalableMinimumScale);
 
-    const FloatSize& minimumLayoutSize = m_minimumLayoutSize;
     double contentWidth = m_contentSize.width();
-    if (contentWidth > 0 && contentWidth * minimumScale < minimumLayoutSize.width() && !shouldIgnoreVerticalScalingConstraints())
-        minimumScale = minimumLayoutSize.width() / contentWidth;
+    if (contentWidth > 0 && contentWidth * minimumScale < m_viewSize.width() && !shouldIgnoreVerticalScalingConstraints())
+        minimumScale = m_viewSize.width() / contentWidth;
 
     double contentHeight = m_contentSize.height();
-    if (contentHeight > 0 && contentHeight * minimumScale < minimumLayoutSize.height() && !shouldIgnoreHorizontalScalingConstraints())
-        minimumScale = minimumLayoutSize.height() / contentHeight;
+    if (contentHeight > 0 && contentHeight * minimumScale < m_viewSize.height() && !shouldIgnoreHorizontalScalingConstraints())
+        minimumScale = m_viewSize.height() / contentHeight;
 
     minimumScale = std::min(std::max(minimumScale, m_configuration.minimumScale), m_configuration.maximumScale);
 
@@ -490,6 +504,7 @@
     ts.dumpProperty("ignoring horizontal scaling constraints", shouldIgnoreHorizontalScalingConstraints() ? "true" : "false");
     ts.dumpProperty("ignoring vertical scaling constraints", shouldIgnoreVerticalScalingConstraints() ? "true" : "false");
     ts.dumpProperty("avoids unsafe area", avoidsUnsafeArea() ? "true" : "false");
+    ts.dumpProperty("force horizontal shrink to fit", m_forceHorizontalShrinkToFit ? "true" : "false");
     
     ts.endGroup();
 

Modified: trunk/Source/WebCore/page/ViewportConfiguration.h (229062 => 229063)


--- trunk/Source/WebCore/page/ViewportConfiguration.h	2018-02-27 16:43:22 UTC (rev 229062)
+++ trunk/Source/WebCore/page/ViewportConfiguration.h	2018-02-27 17:16:31 UTC (rev 229063)
@@ -75,11 +75,13 @@
     WEBCORE_EXPORT bool setContentsSize(const IntSize&);
 
     const FloatSize& minimumLayoutSize() const { return m_minimumLayoutSize; }
-    WEBCORE_EXPORT bool setMinimumLayoutSize(const FloatSize&);
+    WEBCORE_EXPORT bool setMinimumLayoutSize(const FloatSize&, const FloatSize& viewSize);
 
     const ViewportArguments& viewportArguments() const { return m_viewportArguments; }
     WEBCORE_EXPORT bool setViewportArguments(const ViewportArguments&);
 
+    WEBCORE_EXPORT bool setForceHorizontalShrinkToFit(bool);
+
     WEBCORE_EXPORT bool setCanIgnoreScalingConstraints(bool);
     void setForceAlwaysUserScalable(bool forceAlwaysUserScalable) { m_forceAlwaysUserScalable = forceAlwaysUserScalable; }
 
@@ -120,10 +122,12 @@
     Parameters m_defaultConfiguration;
     IntSize m_contentSize;
     FloatSize m_minimumLayoutSize;
+    FloatSize m_viewSize;
     ViewportArguments m_viewportArguments;
 
     bool m_canIgnoreScalingConstraints;
     bool m_forceAlwaysUserScalable;
+    bool m_forceHorizontalShrinkToFit;
 };
 
 WTF::TextStream& operator<<(WTF::TextStream&, const ViewportConfiguration::Parameters&);

Modified: trunk/Source/WebKit/ChangeLog (229062 => 229063)


--- trunk/Source/WebKit/ChangeLog	2018-02-27 16:43:22 UTC (rev 229062)
+++ trunk/Source/WebKit/ChangeLog	2018-02-27 17:16:31 UTC (rev 229063)
@@ -1,3 +1,105 @@
+2018-02-27  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [Extra zoom mode] Implement additional SPI for adjusting viewport shrink-to-fit behavior
+        https://bugs.webkit.org/show_bug.cgi?id=183100
+        <rdar://problem/37840987>
+
+        Reviewed by Tim Horton.
+
+        Add new SPI hooks to provide finer control over certain aspects of the shrink-to-fit viewport heuristic.
+        Currently, in certain cases of iPad multitasking, Safari allows shrinking content to fit by default. This means
+        that even when "width=device-width" is used, if the contents of the page are too wide to fit within the
+        viewport's width, we'll adjust the initial scale such that the viewport can fit all of the content.
+
+        However, in certain viewport dimensions, this heuristic is insufficient to ensure that pages are laid out and
+        displayed properly within the viewport. Namely, one could imagine that an element with a hard-coded width that
+        is larger than the real viewport width would cause all other elements with dimensions relative to the body to be
+        excessively shrunk down once shrink-to-fit is applied, so the page would still look broken even if the contents
+        of the page all fit within the viewport.
+
+        To mitigate this, we decouple the notions of minimum layout size from the size of the actual viewport (which we
+        simply refer to as "view size"). This allows us to introduce a mechanism where we lay out the page at a given
+        minimum layout size that is larger than the size of the view; later, when we determine the initial scale, we
+        then apply shrink-to-fit scaling using the view size rather than the minimum layout size. This grants us the
+        ability to lay out content as if our view were large, but still ensure that the contents of the page fit within
+        the actual view.
+
+        * Shared/VisibleContentRectUpdateInfo.cpp:
+        (WebKit::VisibleContentRectUpdateInfo::encode const):
+        (WebKit::VisibleContentRectUpdateInfo::decode):
+        (WebKit::operator<<):
+        * Shared/VisibleContentRectUpdateInfo.h:
+        (WebKit::VisibleContentRectUpdateInfo::VisibleContentRectUpdateInfo):
+        (WebKit::VisibleContentRectUpdateInfo::forceHorizontalShrinkToFit const):
+        (WebKit::operator==):
+
+        Plumb the forceHorizontalShrinkToFit flag through VisibleContentRectUpdateInfo.
+
+        * Shared/WebPageCreationParameters.cpp:
+        (WebKit::WebPageCreationParameters::encode const):
+        (WebKit::WebPageCreationParameters::decode):
+        * Shared/WebPageCreationParameters.h:
+
+        Plumb viewSize through IPC to WebPage.
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _initializeWithConfiguration:]):
+
+        Start off WKWebView flags at their initial values.
+
+        (-[WKWebView _minimumAllowedLayoutWidth]):
+        (-[WKWebView _setMinimumAllowedLayoutWidth:]):
+
+        This provides the minimum width at which the page will lay out, such that if the view width dips below this
+        value, we'll use this minimum allowed layout width instead. 0 by default.
+
+        (-[WKWebView activeMinimumLayoutSizes:]):
+
+        Refactor this from a static function to a helper method on WKWebView that computes both the minimum layout size
+        (which takes minimum allowed layout width into account) as well as the real view size. Refactor all call sites
+        to use this new method, and also propagate the view size down via IPC, alongside the minimum layout size.
+
+        (-[WKWebView _dispatchSetMinimumLayoutSize:viewSize:]):
+        (-[WKWebView _frameOrBoundsChanged]):
+        (-[WKWebView _setMinimumLayoutSizeOverride:]):
+        (-[WKWebView _setForceHorizontalViewportShrinkToFit:]):
+        (-[WKWebView _forceHorizontalViewportShrinkToFit]):
+
+        Setting this flag to YES forces us to always shrink-to-fit in the horizontal axis. NO by default.
+
+        (-[WKWebView _beginAnimatedResizeWithUpdates:]):
+        (-[WKWebView _endAnimatedResize]):
+        (activeMinimumLayoutSize): Deleted.
+
+        More refactoring to replace activeMinimumLayoutSize() with -activeMinimumLayoutSizes:.
+
+        (-[WKWebView _dispatchSetMinimumLayoutSize:]): Deleted.
+        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::creationParameters):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/ios/WKContentView.mm:
+        (-[WKContentView didUpdateVisibleRect:unobscuredRect:unobscuredRectInScrollViewCoordinates:obscuredInsets:unobscuredSafeAreaInsets:inputViewBounds:scale:minimumScale:inStableState:isChangingObscuredInsetsInteractively:enclosedInScrollableAncestorView:]):
+
+        Pass _forceHorizontalViewportShrinkToFit into the visible content rect update.
+
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::dynamicViewportSizeUpdate):
+        (WebKit::WebPageProxy::setViewportConfigurationMinimumLayoutSize):
+
+        Plumb viewSize alongside the existing minimumLayoutSize.
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::m_credentialsMessenger):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::setViewportConfigurationMinimumLayoutSize):
+        (WebKit::WebPage::dynamicViewportSizeUpdate):
+        (WebKit::WebPage::updateVisibleContentRects):
+
+        Set forceHorizontalShrinkToFit on the viewport configuration here.
+
 2018-02-27  Tim Horton  <timothy_hor...@apple.com>
 
         Stop using deprecated CADisplay SPI

Modified: trunk/Source/WebKit/Shared/VisibleContentRectUpdateInfo.cpp (229062 => 229063)


--- trunk/Source/WebKit/Shared/VisibleContentRectUpdateInfo.cpp	2018-02-27 16:43:22 UTC (rev 229062)
+++ trunk/Source/WebKit/Shared/VisibleContentRectUpdateInfo.cpp	2018-02-27 17:16:31 UTC (rev 229063)
@@ -53,6 +53,7 @@
     encoder << m_isFirstUpdateForNewViewSize;
     encoder << m_isChangingObscuredInsetsInteractively;
     encoder << m_allowShrinkToFit;
+    encoder << m_forceHorizontalShrinkToFit;
     encoder << m_enclosedInScrollableAncestorView;
 }
 
@@ -92,6 +93,8 @@
         return false;
     if (!decoder.decode(result.m_allowShrinkToFit))
         return false;
+    if (!decoder.decode(result.m_forceHorizontalShrinkToFit))
+        return false;
     if (!decoder.decode(result.m_enclosedInScrollableAncestorView))
         return false;
 
@@ -130,6 +133,8 @@
         ts.dumpProperty("enclosedInScrollableAncestorView", info.enclosedInScrollableAncestorView());
 
     ts.dumpProperty("timestamp", info.timestamp().secondsSinceEpoch().value());
+    ts.dumpProperty("allowShrinkToFit", info.allowShrinkToFit());
+    ts.dumpProperty("forceHorizontalShrinkToFit", info.forceHorizontalShrinkToFit());
     if (info.horizontalVelocity())
         ts.dumpProperty("horizontalVelocity", info.horizontalVelocity());
     if (info.verticalVelocity())

Modified: trunk/Source/WebKit/Shared/VisibleContentRectUpdateInfo.h (229062 => 229063)


--- trunk/Source/WebKit/Shared/VisibleContentRectUpdateInfo.h	2018-02-27 16:43:22 UTC (rev 229062)
+++ trunk/Source/WebKit/Shared/VisibleContentRectUpdateInfo.h	2018-02-27 17:16:31 UTC (rev 229063)
@@ -45,7 +45,7 @@
 public:
     VisibleContentRectUpdateInfo() = default;
 
-    VisibleContentRectUpdateInfo(const WebCore::FloatRect& exposedContentRect, const WebCore::FloatRect& unobscuredContentRect, const WebCore::FloatRect& unobscuredRectInScrollViewCoordinates, const WebCore::FloatRect& unobscuredContentRectRespectingInputViewBounds, const WebCore::FloatRect& customFixedPositionRect, const WebCore::FloatBoxExtent& obscuredInsets, const WebCore::FloatBoxExtent& unobscuredSafeAreaInsets, double scale, bool inStableState, bool isFirstUpdateForNewViewSize, bool isChangingObscuredInsetsInteractively, bool allowShrinkToFit, bool enclosedInScrollableAncestorView, MonotonicTime timestamp, double horizontalVelocity, double verticalVelocity, double scaleChangeRate, uint64_t lastLayerTreeTransactionId)
+    VisibleContentRectUpdateInfo(const WebCore::FloatRect& exposedContentRect, const WebCore::FloatRect& unobscuredContentRect, const WebCore::FloatRect& unobscuredRectInScrollViewCoordinates, const WebCore::FloatRect& unobscuredContentRectRespectingInputViewBounds, const WebCore::FloatRect& customFixedPositionRect, const WebCore::FloatBoxExtent& obscuredInsets, const WebCore::FloatBoxExtent& unobscuredSafeAreaInsets, double scale, bool inStableState, bool isFirstUpdateForNewViewSize, bool isChangingObscuredInsetsInteractively, bool allowShrinkToFit, bool forceHorizontalShrinkToFit, bool enclosedInScrollableAncestorView, MonotonicTime timestamp, double horizontalVelocity, double verticalVelocity, double scaleChangeRate, uint64_t lastLayerTreeTransactionId)
         : m_exposedContentRect(exposedContentRect)
         , m_unobscuredContentRect(unobscuredContentRect)
         , m_unobscuredContentRectRespectingInputViewBounds(unobscuredContentRectRespectingInputViewBounds)
@@ -63,6 +63,7 @@
         , m_isFirstUpdateForNewViewSize(isFirstUpdateForNewViewSize)
         , m_isChangingObscuredInsetsInteractively(isChangingObscuredInsetsInteractively)
         , m_allowShrinkToFit(allowShrinkToFit)
+        , m_forceHorizontalShrinkToFit(forceHorizontalShrinkToFit)
         , m_enclosedInScrollableAncestorView(enclosedInScrollableAncestorView)
     {
     }
@@ -80,6 +81,7 @@
     bool isFirstUpdateForNewViewSize() const { return m_isFirstUpdateForNewViewSize; }
     bool isChangingObscuredInsetsInteractively() const { return m_isChangingObscuredInsetsInteractively; }
     bool allowShrinkToFit() const { return m_allowShrinkToFit; }
+    bool forceHorizontalShrinkToFit() const { return m_forceHorizontalShrinkToFit; }
     bool enclosedInScrollableAncestorView() const { return m_enclosedInScrollableAncestorView; }
 
     MonotonicTime timestamp() const { return m_timestamp; }
@@ -112,6 +114,7 @@
     bool m_isFirstUpdateForNewViewSize { false };
     bool m_isChangingObscuredInsetsInteractively { false };
     bool m_allowShrinkToFit { false };
+    bool m_forceHorizontalShrinkToFit { false };
     bool m_enclosedInScrollableAncestorView { false };
 };
 
@@ -130,6 +133,7 @@
         && a.inStableState() == b.inStableState()
         && a.isFirstUpdateForNewViewSize() == b.isFirstUpdateForNewViewSize()
         && a.allowShrinkToFit() == b.allowShrinkToFit()
+        && a.forceHorizontalShrinkToFit() == b.forceHorizontalShrinkToFit()
         && a.enclosedInScrollableAncestorView() == b.enclosedInScrollableAncestorView();
 }
 

Modified: trunk/Source/WebKit/Shared/WebPageCreationParameters.cpp (229062 => 229063)


--- trunk/Source/WebKit/Shared/WebPageCreationParameters.cpp	2018-02-27 16:43:22 UTC (rev 229062)
+++ trunk/Source/WebKit/Shared/WebPageCreationParameters.cpp	2018-02-27 17:16:31 UTC (rev 229063)
@@ -88,6 +88,7 @@
     encoder << textAutosizingWidth;
     encoder << ignoresViewportScaleLimits;
     encoder << viewportConfigurationMinimumLayoutSize;
+    encoder << viewportConfigurationViewSize;
     encoder << maximumUnobscuredSize;
 #endif
 #if PLATFORM(COCOA)
@@ -244,6 +245,8 @@
         return std::nullopt;
     if (!decoder.decode(parameters.viewportConfigurationMinimumLayoutSize))
         return std::nullopt;
+    if (!decoder.decode(parameters.viewportConfigurationViewSize))
+        return std::nullopt;
     if (!decoder.decode(parameters.maximumUnobscuredSize))
         return std::nullopt;
 #endif

Modified: trunk/Source/WebKit/Shared/WebPageCreationParameters.h (229062 => 229063)


--- trunk/Source/WebKit/Shared/WebPageCreationParameters.h	2018-02-27 16:43:22 UTC (rev 229062)
+++ trunk/Source/WebKit/Shared/WebPageCreationParameters.h	2018-02-27 17:16:31 UTC (rev 229063)
@@ -145,6 +145,7 @@
     float textAutosizingWidth;
     bool ignoresViewportScaleLimits;
     WebCore::FloatSize viewportConfigurationMinimumLayoutSize;
+    WebCore::FloatSize viewportConfigurationViewSize;
     WebCore::FloatSize maximumUnobscuredSize;
 #endif
 #if PLATFORM(COCOA)

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm (229062 => 229063)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm	2018-02-27 16:43:22 UTC (rev 229062)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm	2018-02-27 17:16:31 UTC (rev 229063)
@@ -189,6 +189,11 @@
     ResizingWithDocumentHidden,
 };
 
+struct ActiveViewportLayoutSizes {
+    WebCore::FloatSize minimumLayoutSize;
+    WebCore::FloatSize viewSize;
+};
+
 #endif // PLATFORM(IOS)
 
 #if PLATFORM(IOS)
@@ -302,6 +307,8 @@
     std::optional<int32_t> _lastSentDeviceOrientation;
 
     BOOL _allowsViewportShrinkToFit;
+    BOOL _forceHorizontalViewportShrinkToFit;
+    CGFloat _minimumAllowedLayoutWidth;
 
     BOOL _hasCommittedLoadForMainFrame;
     BOOL _needsResetViewStateAfterCommitLoadForMainFrame;
@@ -698,7 +705,16 @@
 
 #if PLATFORM(IOS)
     _dragInteractionPolicy = _WKDragInteractionPolicyDefault;
+#if ENABLE(EXTRA_ZOOM_MODE)
+    _minimumAllowedLayoutWidth = 320;
+    _allowsViewportShrinkToFit = YES;
+    _forceHorizontalViewportShrinkToFit = YES;
+#else
+    _minimumAllowedLayoutWidth = 0;
+    _allowsViewportShrinkToFit = NO;
+    _forceHorizontalViewportShrinkToFit = NO;
 #endif
+#endif // PLATFORM(IOS)
 }
 
 - (void)_setUpSQLiteDatabaseTrackerClient
@@ -2481,25 +2497,45 @@
     return UIEdgeInsetsAdd([_scrollView _contentScrollInset], self.safeAreaInsets, [_scrollView _edgesApplyingSafeAreaInsetsToContentInset]);
 }
 
-static WebCore::FloatSize activeMinimumLayoutSize(WKWebView *webView, const CGRect& bounds)
+- (CGFloat)_minimumAllowedLayoutWidth
 {
-    if (webView->_overridesMinimumLayoutSize)
-        return WebCore::FloatSize(webView->_minimumLayoutSizeOverride);
+    return _minimumAllowedLayoutWidth;
+}
 
+- (void)_setMinimumAllowedLayoutWidth:(CGFloat)minimumAllowedLayoutWidth
+{
+    if (_minimumAllowedLayoutWidth == minimumAllowedLayoutWidth)
+        return;
+
+    _minimumAllowedLayoutWidth = minimumAllowedLayoutWidth;
+
+    auto sizes = [self activeMinimumLayoutSizes:self.bounds];
+    [self _dispatchSetMinimumLayoutSize:sizes.minimumLayoutSize viewSize:sizes.viewSize];
+}
+
+- (ActiveViewportLayoutSizes)activeMinimumLayoutSizes:(const CGRect&)bounds
+{
+    if (_overridesMinimumLayoutSize)
+        return { WebCore::FloatSize(_minimumLayoutSizeOverride), WebCore::FloatSize(_minimumLayoutSizeOverride) };
+
+    ActiveViewportLayoutSizes sizes;
 #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000
-    return WebCore::FloatSize(UIEdgeInsetsInsetRect(CGRectMake(0, 0, bounds.size.width, bounds.size.height), webView._scrollViewSystemContentInset).size);
+    sizes.viewSize = WebCore::FloatSize(UIEdgeInsetsInsetRect(CGRectMake(0, 0, bounds.size.width, bounds.size.height), self._scrollViewSystemContentInset).size);
 #else
-    return WebCore::FloatSize(bounds.size);
+    sizes.viewSize = WebCore::FloatSize { bounds.size };
 #endif
+
+    sizes.minimumLayoutSize = { std::max<float>(sizes.viewSize.width(), self._minimumAllowedLayoutWidth), sizes.viewSize.height() };
+    return sizes;
 }
 
-- (void)_dispatchSetMinimumLayoutSize:(WebCore::FloatSize)minimumLayoutSize
+- (void)_dispatchSetMinimumLayoutSize:(WebCore::FloatSize)minimumLayoutSize viewSize:(WebCore::FloatSize)viewSize
 {
     if (_lastSentMinimumLayoutSize && CGSizeEqualToSize(_lastSentMinimumLayoutSize.value(), minimumLayoutSize))
         return;
 
-    LOG_WITH_STREAM(VisibleRects, stream << "-[WKWebView " << _page->pageID() << " _dispatchSetMinimumLayoutSize:] " << minimumLayoutSize << " contentZoomScale " << contentZoomScale(self));
-    _page->setViewportConfigurationMinimumLayoutSize(minimumLayoutSize);
+    LOG_WITH_STREAM(VisibleRects, stream << "-[WKWebView " << _page->pageID() << " _dispatchSetMinimumLayoutSize:] " << minimumLayoutSize << " viewSize " << viewSize << " contentZoomScale " << contentZoomScale(self));
+    _page->setViewportConfigurationMinimumLayoutSize(minimumLayoutSize, viewSize);
     _lastSentMinimumLayoutSize = minimumLayoutSize;
 }
 
@@ -2527,8 +2563,10 @@
     [_scrollView setFrame:bounds];
 
     if (_dynamicViewportUpdateMode == DynamicViewportUpdateMode::NotResizing) {
-        if (!_overridesMinimumLayoutSize)
-            [self _dispatchSetMinimumLayoutSize:activeMinimumLayoutSize(self, self.bounds)];
+        if (!_overridesMinimumLayoutSize) {
+            auto sizes = [self activeMinimumLayoutSizes:self.bounds];
+            [self _dispatchSetMinimumLayoutSize:sizes.minimumLayoutSize viewSize:sizes.viewSize];
+        }
         if (!_overridesMaximumUnobscuredSize)
             [self _dispatchSetMaximumUnobscuredSize:WebCore::FloatSize(bounds.size)];
 
@@ -4902,7 +4940,7 @@
     _minimumLayoutSizeOverride = minimumLayoutSizeOverride;
 
     if (_dynamicViewportUpdateMode == DynamicViewportUpdateMode::NotResizing)
-        [self _dispatchSetMinimumLayoutSize:WebCore::FloatSize(minimumLayoutSizeOverride)];
+        [self _dispatchSetMinimumLayoutSize:WebCore::FloatSize(minimumLayoutSizeOverride) viewSize:WebCore::FloatSize(minimumLayoutSizeOverride)];
 
 }
 
@@ -5009,6 +5047,20 @@
         [self _dispatchSetMaximumUnobscuredSize:WebCore::FloatSize(size)];
 }
 
+- (void)_setForceHorizontalViewportShrinkToFit:(BOOL)forceHorizontalViewportShrinkToFit
+{
+    if (_forceHorizontalViewportShrinkToFit == forceHorizontalViewportShrinkToFit)
+        return;
+
+    _forceHorizontalViewportShrinkToFit = forceHorizontalViewportShrinkToFit;
+    [self _scheduleVisibleContentRectUpdate];
+}
+
+- (BOOL)_forceHorizontalViewportShrinkToFit
+{
+    return _forceHorizontalViewportShrinkToFit;
+}
+
 - (void)_setAllowsViewportShrinkToFit:(BOOL)allowShrinkToFit
 {
     _allowsViewportShrinkToFit = allowShrinkToFit;
@@ -5050,8 +5102,8 @@
 
     _dynamicViewportUpdateMode = DynamicViewportUpdateMode::ResizingWithAnimation;
 
-    WebCore::FloatSize oldMinimumLayoutSize = activeMinimumLayoutSize(self, oldBounds);
-    WebCore::FloatSize oldMaximumUnobscuredSize = activeMaximumUnobscuredSize(self, oldBounds);
+    auto oldSizes = [self activeMinimumLayoutSizes:self.bounds];
+    auto oldMaximumUnobscuredSize = activeMaximumUnobscuredSize(self, oldBounds);
     int32_t oldOrientation = activeOrientation(self);
     UIEdgeInsets oldObscuredInsets = _obscuredInsets;
 
@@ -5058,19 +5110,19 @@
     updateBlock();
 
     CGRect newBounds = self.bounds;
-    WebCore::FloatSize newMinimumLayoutSize = activeMinimumLayoutSize(self, newBounds);
-    WebCore::FloatSize newMaximumUnobscuredSize = activeMaximumUnobscuredSize(self, newBounds);
+    auto newSizes = [self activeMinimumLayoutSizes:newBounds];
+    auto newMaximumUnobscuredSize = activeMaximumUnobscuredSize(self, newBounds);
     int32_t newOrientation = activeOrientation(self);
     UIEdgeInsets newObscuredInsets = _obscuredInsets;
     CGRect futureUnobscuredRectInSelfCoordinates = UIEdgeInsetsInsetRect(newBounds, _obscuredInsets);
     CGRect contentViewBounds = [_contentView bounds];
 
-    ASSERT_WITH_MESSAGE(!(_overridesMinimumLayoutSize && newMinimumLayoutSize.isEmpty()), "Clients controlling the layout size should maintain a valid layout size to minimize layouts.");
-    if (CGRectIsEmpty(newBounds) || newMinimumLayoutSize.isEmpty() || CGRectIsEmpty(futureUnobscuredRectInSelfCoordinates) || CGRectIsEmpty(contentViewBounds)) {
+    ASSERT_WITH_MESSAGE(!(_overridesMinimumLayoutSize && newSizes.minimumLayoutSize.isEmpty()), "Clients controlling the layout size should maintain a valid layout size to minimize layouts.");
+    if (CGRectIsEmpty(newBounds) || newSizes.minimumLayoutSize.isEmpty() || CGRectIsEmpty(futureUnobscuredRectInSelfCoordinates) || CGRectIsEmpty(contentViewBounds)) {
         _dynamicViewportUpdateMode = DynamicViewportUpdateMode::NotResizing;
         [self _frameOrBoundsChanged];
         if (_overridesMinimumLayoutSize)
-            [self _dispatchSetMinimumLayoutSize:WebCore::FloatSize(newMinimumLayoutSize)];
+            [self _dispatchSetMinimumLayoutSize:newSizes.minimumLayoutSize viewSize:newSizes.viewSize];
         if (_overridesMaximumUnobscuredSize)
             [self _dispatchSetMaximumUnobscuredSize:WebCore::FloatSize(newMaximumUnobscuredSize)];
         if (_overridesInterfaceOrientation)
@@ -5081,7 +5133,7 @@
     }
 
     if (CGRectEqualToRect(oldBounds, newBounds)
-        && oldMinimumLayoutSize == newMinimumLayoutSize
+        && oldSizes.minimumLayoutSize == newSizes.minimumLayoutSize
         && oldMaximumUnobscuredSize == newMaximumUnobscuredSize
         && oldOrientation == newOrientation
         && UIEdgeInsetsEqualToEdgeInsets(oldObscuredInsets, newObscuredInsets)) {
@@ -5101,13 +5153,13 @@
     [_resizeAnimationView addSubview:[_contentView unscaledView]];
 
     CGSize contentSizeInContentViewCoordinates = contentViewBounds.size;
-    [_scrollView setMinimumZoomScale:std::min(newMinimumLayoutSize.width() / contentSizeInContentViewCoordinates.width, [_scrollView minimumZoomScale])];
-    [_scrollView setMaximumZoomScale:std::max(newMinimumLayoutSize.width() / contentSizeInContentViewCoordinates.width, [_scrollView maximumZoomScale])];
+    [_scrollView setMinimumZoomScale:std::min(newSizes.minimumLayoutSize.width() / contentSizeInContentViewCoordinates.width, [_scrollView minimumZoomScale])];
+    [_scrollView setMaximumZoomScale:std::max(newSizes.minimumLayoutSize.width() / contentSizeInContentViewCoordinates.width, [_scrollView maximumZoomScale])];
 
     // Compute the new scale to keep the current content width in the scrollview.
     CGFloat oldWebViewWidthInContentViewCoordinates = oldUnobscuredContentRect.width();
     CGFloat visibleContentViewWidthInContentCoordinates = std::min(contentSizeInContentViewCoordinates.width, oldWebViewWidthInContentViewCoordinates);
-    CGFloat targetScale = newMinimumLayoutSize.width() / visibleContentViewWidthInContentCoordinates;
+    CGFloat targetScale = newSizes.minimumLayoutSize.width() / visibleContentViewWidthInContentCoordinates;
     CGFloat resizeAnimationViewAnimationScale = targetScale / contentZoomScale(self);
     [_resizeAnimationView setTransform:CGAffineTransformMakeScale(resizeAnimationViewAnimationScale, resizeAnimationViewAnimationScale)];
 
@@ -5147,11 +5199,11 @@
     UIEdgeInsets unobscuredSafeAreaInsets = [self _computedUnobscuredSafeAreaInset];
     WebCore::FloatBoxExtent unobscuredSafeAreaInsetsExtent(unobscuredSafeAreaInsets.top, unobscuredSafeAreaInsets.right, unobscuredSafeAreaInsets.bottom, unobscuredSafeAreaInsets.left);
 
-    _lastSentMinimumLayoutSize = newMinimumLayoutSize;
+    _lastSentMinimumLayoutSize = newSizes.minimumLayoutSize;
     _lastSentMaximumUnobscuredSize = newMaximumUnobscuredSize;
     _lastSentDeviceOrientation = newOrientation;
 
-    _page->dynamicViewportSizeUpdate(newMinimumLayoutSize, newMaximumUnobscuredSize, visibleRectInContentCoordinates, unobscuredRectInContentCoordinates, futureUnobscuredRectInSelfCoordinates, unobscuredSafeAreaInsetsExtent, targetScale, newOrientation);
+    _page->dynamicViewportSizeUpdate(newSizes.minimumLayoutSize, newSizes.viewSize, newMaximumUnobscuredSize, visibleRectInContentCoordinates, unobscuredRectInContentCoordinates, futureUnobscuredRectInSelfCoordinates, unobscuredSafeAreaInsetsExtent, targetScale, newOrientation);
     if (WebKit::DrawingAreaProxy* drawingArea = _page->drawingArea())
         drawingArea->setSize(WebCore::IntSize(newBounds.size));
 }
@@ -5216,12 +5268,12 @@
     [self _scheduleVisibleContentRectUpdate];
 
     CGRect newBounds = self.bounds;
-    WebCore::FloatSize newMinimumLayoutSize = activeMinimumLayoutSize(self, newBounds);
-    WebCore::FloatSize newMaximumUnobscuredSize = activeMaximumUnobscuredSize(self, newBounds);
+    auto newSizes = [self activeMinimumLayoutSizes:newBounds];
+    auto newMaximumUnobscuredSize = activeMaximumUnobscuredSize(self, newBounds);
     int32_t newOrientation = activeOrientation(self);
 
-    if (!_lastSentMinimumLayoutSize || newMinimumLayoutSize != _lastSentMinimumLayoutSize.value())
-        [self _dispatchSetMinimumLayoutSize:WebCore::FloatSize(newMinimumLayoutSize)];
+    if (!_lastSentMinimumLayoutSize || newSizes.minimumLayoutSize != _lastSentMinimumLayoutSize.value())
+        [self _dispatchSetMinimumLayoutSize:newSizes.minimumLayoutSize viewSize:newSizes.viewSize];
     if (!_lastSentMaximumUnobscuredSize || newMaximumUnobscuredSize != _lastSentMaximumUnobscuredSize.value())
         [self _dispatchSetMaximumUnobscuredSize:WebCore::FloatSize(newMaximumUnobscuredSize)];
     if (!_lastSentDeviceOrientation || newOrientation != _lastSentDeviceOrientation.value())

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h (229062 => 229063)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h	2018-02-27 16:43:22 UTC (rev 229062)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h	2018-02-27 17:16:31 UTC (rev 229063)
@@ -204,6 +204,8 @@
 @property (nonatomic, setter=_setInterfaceOrientationOverride:) UIInterfaceOrientation _interfaceOrientationOverride;
 
 @property (nonatomic, setter=_setAllowsViewportShrinkToFit:) BOOL _allowsViewportShrinkToFit;
+@property (nonatomic, setter=_setForceHorizontalViewportShrinkToFit:) BOOL _forceHorizontalViewportShrinkToFit WK_API_AVAILABLE(ios(WK_IOS_TBA));
+@property (nonatomic, setter=_setMinimumAllowedLayoutWidth:) CGFloat _minimumAllowedLayoutWidth WK_API_AVAILABLE(ios(WK_IOS_TBA));
 
 // FIXME: Remove these three properties once we expose WKWebViewContentProvider as API.
 @property (nonatomic, readonly, getter=_isDisplayingPDF) BOOL _displayingPDF;

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (229062 => 229063)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2018-02-27 16:43:22 UTC (rev 229062)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2018-02-27 17:16:31 UTC (rev 229063)
@@ -5853,6 +5853,7 @@
     parameters.mimeTypesWithCustomContentProviders = m_pageClient.mimeTypesWithCustomContentProviders();
     parameters.ignoresViewportScaleLimits = m_forceAlwaysUserScalable;
     parameters.viewportConfigurationMinimumLayoutSize = m_viewportConfigurationMinimumLayoutSize;
+    parameters.viewportConfigurationViewSize = m_viewportConfigurationViewSize;
     parameters.maximumUnobscuredSize = m_maximumUnobscuredSize;
 #endif
 

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (229062 => 229063)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2018-02-27 16:43:22 UTC (rev 229062)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2018-02-27 17:16:31 UTC (rev 229063)
@@ -532,10 +532,10 @@
     void overflowScrollWillStartScroll();
     void overflowScrollDidEndScroll();
 
-    void dynamicViewportSizeUpdate(const WebCore::FloatSize& minimumLayoutSize, const WebCore::FloatSize& maximumUnobscuredSize, const WebCore::FloatRect& targetExposedContentRect, const WebCore::FloatRect& targetUnobscuredRect, const WebCore::FloatRect& targetUnobscuredRectInScrollViewCoordinates, const WebCore::FloatBoxExtent& unobscuredSafeAreaInsets, double targetScale, int32_t deviceOrientation);
+    void dynamicViewportSizeUpdate(const WebCore::FloatSize& minimumLayoutSize, const WebCore::FloatSize& viewSize, const WebCore::FloatSize& maximumUnobscuredSize, const WebCore::FloatRect& targetExposedContentRect, const WebCore::FloatRect& targetUnobscuredRect, const WebCore::FloatRect& targetUnobscuredRectInScrollViewCoordinates, const WebCore::FloatBoxExtent& unobscuredSafeAreaInsets, double targetScale, int32_t deviceOrientation);
     void synchronizeDynamicViewportUpdate();
 
-    void setViewportConfigurationMinimumLayoutSize(const WebCore::FloatSize&);
+    void setViewportConfigurationMinimumLayoutSize(const WebCore::FloatSize&, const WebCore::FloatSize& viewSize);
     void setMaximumUnobscuredSize(const WebCore::FloatSize&);
     void setDeviceOrientation(int32_t);
     int32_t deviceOrientation() const { return m_deviceOrientation; }
@@ -2088,6 +2088,7 @@
     std::unique_ptr<NodeAssistanceArguments> m_deferredNodeAssistanceArguments;
     bool m_forceAlwaysUserScalable { false };
     WebCore::FloatSize m_viewportConfigurationMinimumLayoutSize;
+    WebCore::FloatSize m_viewportConfigurationViewSize;
     WebCore::FloatSize m_maximumUnobscuredSize;
 #endif
 

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentView.mm (229062 => 229063)


--- trunk/Source/WebKit/UIProcess/ios/WKContentView.mm	2018-02-27 16:43:22 UTC (rev 229062)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentView.mm	2018-02-27 17:16:31 UTC (rev 229063)
@@ -425,6 +425,7 @@
         _sizeChangedSinceLastVisibleContentRectUpdate,
         isChangingObscuredInsetsInteractively,
         _webView._allowsViewportShrinkToFit,
+        _webView._forceHorizontalViewportShrinkToFit,
         enclosedInScrollableAncestorView,
         timestamp,
         velocityData.horizontalVelocity,

Modified: trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm (229062 => 229063)


--- trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm	2018-02-27 16:43:22 UTC (rev 229062)
+++ trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm	2018-02-27 17:16:31 UTC (rev 229063)
@@ -304,7 +304,7 @@
     m_pageClient.overflowScrollDidEndScroll();
 }
 
-void WebPageProxy::dynamicViewportSizeUpdate(const FloatSize& minimumLayoutSize, const WebCore::FloatSize& maximumUnobscuredSize, const FloatRect& targetExposedContentRect, const FloatRect& targetUnobscuredRect, const FloatRect& targetUnobscuredRectInScrollViewCoordinates, const WebCore::FloatBoxExtent& unobscuredSafeAreaInsets, double targetScale, int32_t deviceOrientation)
+void WebPageProxy::dynamicViewportSizeUpdate(const FloatSize& minimumLayoutSize, const FloatSize& viewSize, const WebCore::FloatSize& maximumUnobscuredSize, const FloatRect& targetExposedContentRect, const FloatRect& targetUnobscuredRect, const FloatRect& targetUnobscuredRectInScrollViewCoordinates, const WebCore::FloatBoxExtent& unobscuredSafeAreaInsets, double targetScale, int32_t deviceOrientation)
 {
     if (!isValid())
         return;
@@ -313,7 +313,7 @@
 
     m_dynamicViewportSizeUpdateWaitingForTarget = true;
     m_dynamicViewportSizeUpdateWaitingForLayerTreeCommit = true;
-    m_process->send(Messages::WebPage::DynamicViewportSizeUpdate(minimumLayoutSize, maximumUnobscuredSize, targetExposedContentRect, targetUnobscuredRect, targetUnobscuredRectInScrollViewCoordinates, unobscuredSafeAreaInsets, targetScale, deviceOrientation, ++m_currentDynamicViewportSizeUpdateID), m_pageID);
+    m_process->send(Messages::WebPage::DynamicViewportSizeUpdate(minimumLayoutSize, viewSize, maximumUnobscuredSize, targetExposedContentRect, targetUnobscuredRect, targetUnobscuredRectInScrollViewCoordinates, unobscuredSafeAreaInsets, targetScale, deviceOrientation, ++m_currentDynamicViewportSizeUpdateID), m_pageID);
 }
 
 void WebPageProxy::synchronizeDynamicViewportUpdate()
@@ -353,12 +353,13 @@
     m_dynamicViewportSizeUpdateWaitingForLayerTreeCommit = false;
 }
 
-void WebPageProxy::setViewportConfigurationMinimumLayoutSize(const WebCore::FloatSize& size)
+void WebPageProxy::setViewportConfigurationMinimumLayoutSize(const WebCore::FloatSize& size, const WebCore::FloatSize& viewSize)
 {
     m_viewportConfigurationMinimumLayoutSize = size;
+    m_viewportConfigurationViewSize = viewSize;
 
     if (isValid())
-        m_process->send(Messages::WebPage::SetViewportConfigurationMinimumLayoutSize(size), m_pageID);
+        m_process->send(Messages::WebPage::SetViewportConfigurationMinimumLayoutSize(size, viewSize), m_pageID);
 }
 
 void WebPageProxy::setForceAlwaysUserScalable(bool userScalable)

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (229062 => 229063)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2018-02-27 16:43:22 UTC (rev 229062)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2018-02-27 17:16:31 UTC (rev 229063)
@@ -604,7 +604,7 @@
 #endif
 
 #if PLATFORM(IOS)
-    setViewportConfigurationMinimumLayoutSize(parameters.viewportConfigurationMinimumLayoutSize);
+    setViewportConfigurationMinimumLayoutSize(parameters.viewportConfigurationMinimumLayoutSize, parameters.viewportConfigurationViewSize);
     setMaximumUnobscuredSize(parameters.maximumUnobscuredSize);
 #endif
 }

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (229062 => 229063)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2018-02-27 16:43:22 UTC (rev 229062)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2018-02-27 17:16:31 UTC (rev 229063)
@@ -867,10 +867,10 @@
     void updateVisibilityState(bool isInitialState = false);
 
 #if PLATFORM(IOS)
-    void setViewportConfigurationMinimumLayoutSize(const WebCore::FloatSize&);
+    void setViewportConfigurationMinimumLayoutSize(const WebCore::FloatSize&, const WebCore::FloatSize& viewSize);
     void setMaximumUnobscuredSize(const WebCore::FloatSize&);
     void setDeviceOrientation(int32_t);
-    void dynamicViewportSizeUpdate(const WebCore::FloatSize& minimumLayoutSize, const WebCore::FloatSize& maximumUnobscuredSize, const WebCore::FloatRect& targetExposedContentRect, const WebCore::FloatRect& targetUnobscuredRect, const WebCore::FloatRect& targetUnobscuredRectInScrollViewCoordinates, const WebCore::FloatBoxExtent& targetUnobscuredSafeAreaInsets, double scale, int32_t deviceOrientation, uint64_t dynamicViewportSizeUpdateID);
+    void dynamicViewportSizeUpdate(const WebCore::FloatSize& minimumLayoutSize, const WebCore::FloatSize& viewSize, const WebCore::FloatSize& maximumUnobscuredSize, const WebCore::FloatRect& targetExposedContentRect, const WebCore::FloatRect& targetUnobscuredRect, const WebCore::FloatRect& targetUnobscuredRectInScrollViewCoordinates, const WebCore::FloatBoxExtent& targetUnobscuredSafeAreaInsets, double scale, int32_t deviceOrientation, uint64_t dynamicViewportSizeUpdateID);
     void synchronizeDynamicViewportUpdate(double& newTargetScale, WebCore::FloatPoint& newScrollPosition, uint64_t& nextValidLayerTreeTransactionID);
     std::optional<float> scaleFromUIProcess(const VisibleContentRectUpdateInfo&) const;
     void updateVisibleContentRects(const VisibleContentRectUpdateInfo&, MonotonicTime oldestTimestamp);

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (229062 => 229063)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2018-02-27 16:43:22 UTC (rev 229062)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2018-02-27 17:16:31 UTC (rev 229063)
@@ -41,10 +41,10 @@
     KeyEvent(WebKit::WebKeyboardEvent event)
     MouseEvent(WebKit::WebMouseEvent event)
 #if PLATFORM(IOS)
-    SetViewportConfigurationMinimumLayoutSize(WebCore::FloatSize size)
+    SetViewportConfigurationMinimumLayoutSize(WebCore::FloatSize size, WebCore::FloatSize viewSize)
     SetMaximumUnobscuredSize(WebCore::FloatSize size)
     SetDeviceOrientation(int32_t deviceOrientation)
-    DynamicViewportSizeUpdate(WebCore::FloatSize minimumLayoutSize, WebCore::FloatSize maximumUnobscuredSize, WebCore::FloatRect targetExposedContentRect, WebCore::FloatRect targetUnobscuredRect, WebCore::FloatRect targetUnobscuredRectInScrollViewCoordinates, WebCore::RectEdges<float> targetUnobscuredSafeAreaInsets, double scale, int32_t deviceOrientation, uint64_t dynamicViewportSizeUpdateID)
+    DynamicViewportSizeUpdate(WebCore::FloatSize minimumLayoutSize, WebCore::FloatSize viewSize, WebCore::FloatSize maximumUnobscuredSize, WebCore::FloatRect targetExposedContentRect, WebCore::FloatRect targetUnobscuredRect, WebCore::FloatRect targetUnobscuredRectInScrollViewCoordinates, WebCore::RectEdges<float> targetUnobscuredSafeAreaInsets, double scale, int32_t deviceOrientation, uint64_t dynamicViewportSizeUpdateID)
     SynchronizeDynamicViewportUpdate() -> (double newTargetScale, WebCore::FloatPoint newScrollPosition, uint64_t nextValidLayerTreeTransactionID)
 
     HandleTap(WebCore::IntPoint point, uint64_t lastLayerTreeTransactionId)

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


--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2018-02-27 16:43:22 UTC (rev 229062)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2018-02-27 17:16:31 UTC (rev 229063)
@@ -2851,10 +2851,10 @@
     }
 }
 
-void WebPage::setViewportConfigurationMinimumLayoutSize(const FloatSize& size)
+void WebPage::setViewportConfigurationMinimumLayoutSize(const FloatSize& size, const FloatSize& viewSize)
 {
-    LOG_WITH_STREAM(VisibleRects, stream << "WebPage " << m_pageID << " setViewportConfigurationMinimumLayoutSize " << size);
-    if (m_viewportConfiguration.setMinimumLayoutSize(size))
+    LOG_WITH_STREAM(VisibleRects, stream << "WebPage " << m_pageID << " setViewportConfigurationMinimumLayoutSize " << size << " viewSize " << viewSize);
+    if (m_viewportConfiguration.setMinimumLayoutSize(size, viewSize))
         viewportConfigurationChanged();
 }
 
@@ -2889,12 +2889,12 @@
     }
 }
 
-void WebPage::dynamicViewportSizeUpdate(const FloatSize& minimumLayoutSize, const WebCore::FloatSize& maximumUnobscuredSize, const FloatRect& targetExposedContentRect, const FloatRect& targetUnobscuredRect, const WebCore::FloatRect& targetUnobscuredRectInScrollViewCoordinates, const WebCore::FloatBoxExtent& targetUnobscuredSafeAreaInsets, double targetScale, int32_t deviceOrientation, uint64_t dynamicViewportSizeUpdateID)
+void WebPage::dynamicViewportSizeUpdate(const FloatSize& minimumLayoutSize, const FloatSize& viewSize, const WebCore::FloatSize& maximumUnobscuredSize, const FloatRect& targetExposedContentRect, const FloatRect& targetUnobscuredRect, const WebCore::FloatRect& targetUnobscuredRectInScrollViewCoordinates, const WebCore::FloatBoxExtent& targetUnobscuredSafeAreaInsets, double targetScale, int32_t deviceOrientation, uint64_t dynamicViewportSizeUpdateID)
 {
     SetForScope<bool> dynamicSizeUpdateGuard(m_inDynamicSizeUpdate, true);
     // FIXME: this does not handle the cases where the content would change the content size or scroll position from _javascript_.
     // To handle those cases, we would need to redo this computation on every change until the next visible content rect update.
-    LOG_WITH_STREAM(VisibleRects, stream << "\nWebPage::dynamicViewportSizeUpdate - minimumLayoutSize " << minimumLayoutSize << " targetUnobscuredRect " << targetUnobscuredRect << " targetExposedContentRect " << targetExposedContentRect << " targetScale " << targetScale);
+    LOG_WITH_STREAM(VisibleRects, stream << "\nWebPage::dynamicViewportSizeUpdate - minimumLayoutSize " << minimumLayoutSize << " viewSize " << viewSize << " targetUnobscuredRect " << targetUnobscuredRect << " targetExposedContentRect " << targetExposedContentRect << " targetScale " << targetScale);
 
     FrameView& frameView = *m_page->mainFrame().view();
     IntSize oldContentSize = frameView.contentsSize();
@@ -2927,7 +2927,7 @@
     }
 
     LOG_WITH_STREAM(VisibleRects, stream << "WebPage::dynamicViewportSizeUpdate setting minimum layout size to " << minimumLayoutSize);
-    m_viewportConfiguration.setMinimumLayoutSize(minimumLayoutSize);
+    m_viewportConfiguration.setMinimumLayoutSize(minimumLayoutSize, viewSize);
     IntSize newLayoutSize = m_viewportConfiguration.layoutSize();
 
     if (setFixedLayoutSize(newLayoutSize))
@@ -3307,7 +3307,9 @@
     if (scrollPosition != frameView.scrollPosition())
         m_dynamicSizeUpdateHistory.clear();
 
-    if (m_viewportConfiguration.setCanIgnoreScalingConstraints(m_ignoreViewportScalingConstraints && visibleContentRectUpdateInfo.allowShrinkToFit()))
+    bool didUpdateForceHorizontalShrinkToFit = m_viewportConfiguration.setForceHorizontalShrinkToFit(visibleContentRectUpdateInfo.forceHorizontalShrinkToFit());
+    bool didUpdateCanIgnoreViewportScalingConstraints = m_viewportConfiguration.setCanIgnoreScalingConstraints(m_ignoreViewportScalingConstraints && visibleContentRectUpdateInfo.allowShrinkToFit());
+    if (didUpdateForceHorizontalShrinkToFit || didUpdateCanIgnoreViewportScalingConstraints)
         viewportConfigurationChanged();
 
     frameView.setUnobscuredContentSize(visibleContentRectUpdateInfo.unobscuredContentRect().size());

Modified: trunk/Tools/ChangeLog (229062 => 229063)


--- trunk/Tools/ChangeLog	2018-02-27 16:43:22 UTC (rev 229062)
+++ trunk/Tools/ChangeLog	2018-02-27 17:16:31 UTC (rev 229063)
@@ -1,3 +1,20 @@
+2018-02-27  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [Extra zoom mode] Implement additional SPI for adjusting viewport shrink-to-fit behavior
+        https://bugs.webkit.org/show_bug.cgi?id=183100
+        <rdar://problem/37840987>
+
+        Reviewed by Tim Horton.
+
+        Add API tests that exercise -_setMinimumAllowedLayoutWidth: and -_setForceHorizontalViewportShrinkToFit:. See
+        WebKit ChangeLog for more detail.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/ios/ViewportSizingTests.mm: Added.
+        (TestWebKitAPI::while):
+        (viewportTestPageMarkup):
+        (TestWebKitAPI::TEST):
+
 2018-02-27  Yusuke Suzuki  <utatane....@gmail.com>
 
         Unreviewed, skip FTL tests if FTL is disabled

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (229062 => 229063)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2018-02-27 16:43:22 UTC (rev 229062)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2018-02-27 17:16:31 UTC (rev 229063)
@@ -90,6 +90,7 @@
 		2E14A5291D3FE96B0010F35B /* autoplaying-video-with-audio.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E14A5281D3FE8B80010F35B /* autoplaying-video-with-audio.html */; };
 		2E1B7B001D41ABA7007558B4 /* large-video-seek-after-ending.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E1B7AFF1D41A95F007558B4 /* large-video-seek-after-ending.html */; };
 		2E1B7B021D41B1B9007558B4 /* large-video-hides-controls-after-seek-to-end.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E1B7B011D41B1B3007558B4 /* large-video-hides-controls-after-seek-to-end.html */; };
+		2E1B881F2040EE5300FFF6A9 /* ViewportSizingTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2E1B881E2040EE5300FFF6A9 /* ViewportSizingTests.mm */; };
 		2E1DFDED1D42A51100714A00 /* large-videos-with-audio.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E1DFDEC1D42A41C00714A00 /* large-videos-with-audio.html */; };
 		2E1DFDEF1D42A6F200714A00 /* large-videos-with-audio-autoplay.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E1DFDEE1D42A6EB00714A00 /* large-videos-with-audio-autoplay.html */; };
 		2E1DFDF11D42E1E400714A00 /* large-video-seek-to-beginning-and-play-after-ending.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E1DFDF01D42E14400714A00 /* large-video-seek-to-beginning-and-play-after-ending.html */; };
@@ -1221,6 +1222,7 @@
 		2E14A5281D3FE8B80010F35B /* autoplaying-video-with-audio.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "autoplaying-video-with-audio.html"; sourceTree = "<group>"; };
 		2E1B7AFF1D41A95F007558B4 /* large-video-seek-after-ending.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "large-video-seek-after-ending.html"; sourceTree = "<group>"; };
 		2E1B7B011D41B1B3007558B4 /* large-video-hides-controls-after-seek-to-end.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "large-video-hides-controls-after-seek-to-end.html"; sourceTree = "<group>"; };
+		2E1B881E2040EE5300FFF6A9 /* ViewportSizingTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ViewportSizingTests.mm; sourceTree = "<group>"; };
 		2E1DFDEC1D42A41C00714A00 /* large-videos-with-audio.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "large-videos-with-audio.html"; sourceTree = "<group>"; };
 		2E1DFDEE1D42A6EB00714A00 /* large-videos-with-audio-autoplay.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "large-videos-with-audio-autoplay.html"; sourceTree = "<group>"; };
 		2E1DFDF01D42E14400714A00 /* large-video-seek-to-beginning-and-play-after-ending.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "large-video-seek-to-beginning-and-play-after-ending.html"; sourceTree = "<group>"; };
@@ -2303,6 +2305,7 @@
 				F4D4F3B71E4E36E400BB2767 /* DataInteractionTests.mm */,
 				7560917719259C59009EF06E /* MemoryCacheAddImageToCacheIOS.mm */,
 				F46849BD1EEF58E400B937FE /* UIPasteboardTests.mm */,
+				2E1B881E2040EE5300FFF6A9 /* ViewportSizingTests.mm */,
 				514958BD1F7427AC00E87BAD /* WKWebViewAutofillTests.mm */,
 			);
 			path = ios;
@@ -3666,6 +3669,7 @@
 				7C83E03A1D0A602700FEBCF3 /* UtilitiesCocoa.mm in Sources */,
 				7C83E0C61D0A654E00FEBCF3 /* VideoControlsManager.mm in Sources */,
 				115EB3431EE0BA03003C2C0A /* ViewportSizeForViewportUnits.mm in Sources */,
+				2E1B881F2040EE5300FFF6A9 /* ViewportSizingTests.mm in Sources */,
 				6356FB221EC4E0BA0044BF18 /* VisibleContentRect.mm in Sources */,
 				83779C381F82FECE007CDA8A /* VisitedLinkStore.mm in Sources */,
 				0F139E771A423A5B00F590F5 /* WeakObjCPtr.mm in Sources */,

Added: trunk/Tools/TestWebKitAPI/Tests/ios/ViewportSizingTests.mm (0 => 229063)


--- trunk/Tools/TestWebKitAPI/Tests/ios/ViewportSizingTests.mm	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/ios/ViewportSizingTests.mm	2018-02-27 17:16:31 UTC (rev 229063)
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+
+#if WK_API_ENABLED && PLATFORM(IOS)
+
+#import "PlatformUtilities.h"
+#import "TestWKWebView.h"
+#import <WebKit/WKWebViewPrivate.h>
+
+using namespace TestWebKitAPI;
+
+@implementation TestWKWebView (ViewportTestingHelpers)
+
+- (BOOL)scaleIsApproximately:(CGFloat)expectedScale
+{
+    static const double maximumExpectedScaleDifference = 0.001;
+    return ABS(self.scrollView.zoomScale - expectedScale) < maximumExpectedScaleDifference;
+}
+
+- (void)expectScaleToBecome:(CGFloat)expectedScale
+{
+    while (![self scaleIsApproximately:expectedScale])
+        [self waitForNextPresentationUpdate];
+}
+
+@end
+
+static NSString *viewportTestPageMarkup(NSString *viewportMetaContent, int contentWidth, int contentHeight)
+{
+    return [NSString stringWithFormat:@"<meta name='viewport' content='%@'><body style='margin: 0'><div style='width: %dpx; height: %dpx; background-color: red'></div>", viewportMetaContent, contentWidth, contentHeight];
+}
+
+namespace TestWebKitAPI {
+
+TEST(ViewportSizingTests, ForceShrinkToFitViewportOverridesViewportParameters)
+{
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]);
+    [webView _setAllowsViewportShrinkToFit:YES];
+    [webView _setForceHorizontalViewportShrinkToFit:NO];
+    [webView synchronouslyLoadHTMLString:viewportTestPageMarkup(@"width=device-width, shrink-to-fit=no", 600, 100)];
+    [webView expectScaleToBecome:1];
+
+    [webView _setForceHorizontalViewportShrinkToFit:YES];
+    [webView expectScaleToBecome:0.667];
+
+    [webView _setForceHorizontalViewportShrinkToFit:NO];
+    [webView expectScaleToBecome:1];
+}
+
+TEST(ViewportSizingTests, ShrinkToFitViewportWithMinimumAllowedLayoutWidth)
+{
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)]);
+    [webView _setAllowsViewportShrinkToFit:YES];
+    [webView _setForceHorizontalViewportShrinkToFit:YES];
+    [webView _setMinimumAllowedLayoutWidth:0];
+    [webView synchronouslyLoadHTMLString:viewportTestPageMarkup(@"width=device-width, initial-scale=1", 400, 100)];
+    [webView expectScaleToBecome:0.5];
+    EXPECT_WK_STREQ("200", [webView stringByEvaluatingJavaScript:@"document.body.clientWidth"]);
+
+    [webView _setMinimumAllowedLayoutWidth:400];
+    [webView waitForNextPresentationUpdate];
+    EXPECT_WK_STREQ("400", [webView stringByEvaluatingJavaScript:@"document.body.clientWidth"]);
+    EXPECT_TRUE([webView scaleIsApproximately:0.5]);
+
+    [webView _setMinimumAllowedLayoutWidth:100];
+    [webView waitForNextPresentationUpdate];
+    EXPECT_WK_STREQ("200", [webView stringByEvaluatingJavaScript:@"document.body.clientWidth"]);
+    EXPECT_TRUE([webView scaleIsApproximately:0.5]);
+}
+
+} // namespace TestWebKitAPI
+
+#endif // WK_API_ENABLED && PLATFORM(IOS)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to