We should pass minimumEffectiveDeviceWidth to web process on new page creation.
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 6 Apr 2019 03:41:26 +0000 (03:41 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 6 Apr 2019 03:41:26 +0000 (03:41 +0000)
https://bugs.webkit.org/show_bug.cgi?id=196077
<rdar://problem/49108202>

Patch by Yongjun Zhang <yongjun_zhang@apple.com> on 2019-04-05
Reviewed by Chris Dumez.

Source/WebCore:

If the page doesn't specify it requires to use the device width in viewport tag, we should try to scale down
the page to fit the window width.

Test: fast/viewport/ios/shrink-to-fit-for-page-without-viewport-meta.html

* page/ViewportConfiguration.cpp:
(WebCore::ViewportConfiguration::updateDefaultConfiguration): Also update the minimum layout size
    when the default configuration is changed.
(WebCore::ViewportConfiguration::nativeWebpageParametersWithShrinkToFit): Make sure we fit the content
    to window width.

Source/WebKit:

When a new web view is created, it is possible we don't have the web content process till a load
is requested. This patch stashes minimumEffectiveDeviceWidth in WebPageProxy.cpp and passes that
value down to web process via WebPageCreationParameters when a new process is created, just like
we did for other values like viewportConfigurationLayoutSizeScaleFactor or viewportConfigurationViewLayoutSize.

* Shared/WebPageCreationParameters.cpp:
(WebKit::WebPageCreationParameters::encode const): Encode viewportConfigurationMinimumEffectiveDeviceWidth value.
(WebKit::WebPageCreationParameters::decode): Decode viewportConfigurationMinimumEffectiveDeviceWidth value.
* Shared/WebPageCreationParameters.h:
* UIProcess/API/Cocoa/WKWebView.mm: Now that we stash the minimumEffectiveDeviceWidth value in WebPageProxy, we
    don't need the iVar in WKWebView any more.
(-[WKWebView _dispatchSetViewLayoutSize:]): Use _page->minimumEffectiveDeviceWidth().
(-[WKWebView _setViewScale:]): Ditto.
(-[WKWebView _setMinimumEffectiveDeviceWidth:]): Ditto.
(-[WKWebView _minimumEffectiveDeviceWidth]): Ditto.
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::creationParameters): Also add viewportConfigurationMinimumEffectiveDeviceWidth to
    web process creation parameter.
* UIProcess/WebPageProxy.h:
(WebKit::WebPageProxy::minimumEffectiveDeviceWidth const): Returns m_viewportConfigurationMinimumEffectiveDeviceWidth.
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::setViewportConfigurationViewLayoutSize): Pass parameters.viewportConfigurationMinimumEffectiveDeviceWidth
    to web process.
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::WebPage): Take viewportConfigurationMinimumEffectiveDeviceWidth value from the parameter and
    set that to viewport configuration.

Tools:

Add an API test to verify the minimumEffectDeviceWidth is passed to web content process
on new web view.

* TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:

LayoutTests:

Add a layout test to verify the page shrinks to fit the window width when ignoreMetaViewport
flag is turned on.

* fast/viewport/ios/shrink-to-fit-for-page-without-viewport-meta-expected.txt: Added.
* fast/viewport/ios/shrink-to-fit-for-page-without-viewport-meta.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@243961 268f45cc-cd09-0410-ab3c-d52691b4dbfc

15 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/viewport/ios/shrink-to-fit-for-page-without-viewport-meta-expected.txt [new file with mode: 0644]
LayoutTests/fast/viewport/ios/shrink-to-fit-for-page-without-viewport-meta.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/page/ViewportConfiguration.cpp
Source/WebKit/ChangeLog
Source/WebKit/Shared/WebPageCreationParameters.cpp
Source/WebKit/Shared/WebPageCreationParameters.h
Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit/UIProcess/WebPageProxy.cpp
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm

index 4a25ec3..dc00e28 100644 (file)
@@ -1,3 +1,17 @@
+2019-04-05  Yongjun Zhang  <yongjun_zhang@apple.com>
+
+        We should pass minimumEffectiveDeviceWidth to web process on new page creation.
+        https://bugs.webkit.org/show_bug.cgi?id=196077
+        <rdar://problem/49108202>
+
+        Reviewed by Chris Dumez.
+
+        Add a layout test to verify the page shrinks to fit the window width when ignoreMetaViewport
+        flag is turned on.
+
+        * fast/viewport/ios/shrink-to-fit-for-page-without-viewport-meta-expected.txt: Added.
+        * fast/viewport/ios/shrink-to-fit-for-page-without-viewport-meta.html: Added.
+
 2019-04-05  Jer Noble  <jer.noble@apple.com>
 
         [Cocoa] Deactivate the audio session before the WebProcess suspends.
diff --git a/LayoutTests/fast/viewport/ios/shrink-to-fit-for-page-without-viewport-meta-expected.txt b/LayoutTests/fast/viewport/ios/shrink-to-fit-for-page-without-viewport-meta-expected.txt
new file mode 100644 (file)
index 0000000..fb0428c
--- /dev/null
@@ -0,0 +1,4 @@
+window size: [1208, 2069]
+zoom scale: 0.26
+
+
diff --git a/LayoutTests/fast/viewport/ios/shrink-to-fit-for-page-without-viewport-meta.html b/LayoutTests/fast/viewport/ios/shrink-to-fit-for-page-without-viewport-meta.html
new file mode 100644 (file)
index 0000000..f74df8a
--- /dev/null
@@ -0,0 +1,54 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ shouldIgnoreMetaViewport=true ] -->
+
+<html>
+<head>
+     <script src="../../../resources/ui-helper.js"></script>
+     <script>
+     if (window.testRunner) {
+         testRunner.dumpAsText();
+         testRunner.waitUntilDone();
+     }
+
+     async function finishTest() {
+         const appendOutput = message => {
+             output.appendChild(document.createTextNode(message));
+             output.appendChild(document.createElement("br"));
+         };
+
+         appendOutput(`window size: [${innerWidth}, ${innerHeight}]`);
+         appendOutput(`zoom scale: ${(await UIHelper.zoomScale()).toFixed(2)}`);
+         appendOutput("");
+
+         await Promise.all([UIHelper.ensureVisibleContentRectUpdate(), UIHelper.ensurePresentationUpdate()]);
+
+         testRunner.notifyDone();
+     }
+
+    window.addEventListener("load", async () => {
+        await UIHelper.setMinimumEffectiveWidth(320);
+        setTimeout(finishTest, 0);
+    }, false);
+    </script>
+
+    <style>
+        #container {
+            position:relative;
+            top:20px;
+            width:100%;
+        }
+        #wide {
+            width:100%;
+            min-width: 1200px;
+            height: 2200px;
+            background-color: blue;
+        }
+    </style>
+</head>
+
+<body>
+<div id="container">
+<div id="wide"></div>
+</div>
+<pre id="output"></pre>
+</body>
+</html>
index 0bf4d33..6e79c4c 100644 (file)
@@ -1,3 +1,22 @@
+2019-04-05  Yongjun Zhang  <yongjun_zhang@apple.com>
+
+        We should pass minimumEffectiveDeviceWidth to web process on new page creation.
+        https://bugs.webkit.org/show_bug.cgi?id=196077
+        <rdar://problem/49108202>
+
+        Reviewed by Chris Dumez.
+
+        If the page doesn't specify it requires to use the device width in viewport tag, we should try to scale down
+        the page to fit the window width.
+
+        Test: fast/viewport/ios/shrink-to-fit-for-page-without-viewport-meta.html
+
+        * page/ViewportConfiguration.cpp:
+        (WebCore::ViewportConfiguration::updateDefaultConfiguration): Also update the minimum layout size
+            when the default configuration is changed.
+        (WebCore::ViewportConfiguration::nativeWebpageParametersWithShrinkToFit): Make sure we fit the content
+            to window width.
+
 2019-04-05  Jer Noble  <jer.noble@apple.com>
 
         [Cocoa] Deactivate the audio session before the WebProcess suspends.
index 7980099..23e3609 100644 (file)
@@ -177,6 +177,7 @@ bool ViewportConfiguration::setCanIgnoreScalingConstraints(bool canIgnoreScaling
     
     m_canIgnoreScalingConstraints = canIgnoreScalingConstraints;
     updateDefaultConfiguration();
+    updateMinimumLayoutSize();
     updateConfiguration();
     return true;
 }
@@ -353,6 +354,7 @@ ViewportConfiguration::Parameters ViewportConfiguration::nativeWebpageParameters
     Parameters parameters = ViewportConfiguration::nativeWebpageParametersWithoutShrinkToFit();
     parameters.allowsShrinkToFit = true;
     parameters.minimumScale = 0.25;
+    parameters.initialScaleIsSet = false;
     return parameters;
 }
 
index 1a062b5..00f25de 100644 (file)
@@ -1,3 +1,38 @@
+2019-04-05  Yongjun Zhang  <yongjun_zhang@apple.com>
+
+        We should pass minimumEffectiveDeviceWidth to web process on new page creation.
+        https://bugs.webkit.org/show_bug.cgi?id=196077
+        <rdar://problem/49108202>
+
+        Reviewed by Chris Dumez.
+
+        When a new web view is created, it is possible we don't have the web content process till a load
+        is requested. This patch stashes minimumEffectiveDeviceWidth in WebPageProxy.cpp and passes that
+        value down to web process via WebPageCreationParameters when a new process is created, just like
+        we did for other values like viewportConfigurationLayoutSizeScaleFactor or viewportConfigurationViewLayoutSize.
+
+        * Shared/WebPageCreationParameters.cpp:
+        (WebKit::WebPageCreationParameters::encode const): Encode viewportConfigurationMinimumEffectiveDeviceWidth value.
+        (WebKit::WebPageCreationParameters::decode): Decode viewportConfigurationMinimumEffectiveDeviceWidth value.
+        * Shared/WebPageCreationParameters.h:
+        * UIProcess/API/Cocoa/WKWebView.mm: Now that we stash the minimumEffectiveDeviceWidth value in WebPageProxy, we
+            don't need the iVar in WKWebView any more.
+        (-[WKWebView _dispatchSetViewLayoutSize:]): Use _page->minimumEffectiveDeviceWidth().
+        (-[WKWebView _setViewScale:]): Ditto.
+        (-[WKWebView _setMinimumEffectiveDeviceWidth:]): Ditto.
+        (-[WKWebView _minimumEffectiveDeviceWidth]): Ditto.
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::creationParameters): Also add viewportConfigurationMinimumEffectiveDeviceWidth to
+            web process creation parameter.
+        * UIProcess/WebPageProxy.h:
+        (WebKit::WebPageProxy::minimumEffectiveDeviceWidth const): Returns m_viewportConfigurationMinimumEffectiveDeviceWidth.
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::setViewportConfigurationViewLayoutSize): Pass parameters.viewportConfigurationMinimumEffectiveDeviceWidth
+            to web process.
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::WebPage): Take viewportConfigurationMinimumEffectiveDeviceWidth value from the parameter and
+            set that to viewport configuration.
+
 2019-04-05  Jer Noble  <jer.noble@apple.com>
 
         [Cocoa] Deactivate the audio session before the WebProcess suspends.
index 9831a66..18b25b1 100644 (file)
@@ -90,6 +90,7 @@ void WebPageCreationParameters::encode(IPC::Encoder& encoder) const
     encoder << ignoresViewportScaleLimits;
     encoder << viewportConfigurationViewLayoutSize;
     encoder << viewportConfigurationLayoutSizeScaleFactor;
+    encoder << viewportConfigurationMinimumEffectiveDeviceWidth;
     encoder << viewportConfigurationViewSize;
     encoder << maximumUnobscuredSize;
     encoder << deviceOrientation;
@@ -268,6 +269,8 @@ Optional<WebPageCreationParameters> WebPageCreationParameters::decode(IPC::Decod
         return WTF::nullopt;
     if (!decoder.decode(parameters.viewportConfigurationLayoutSizeScaleFactor))
         return WTF::nullopt;
+    if (!decoder.decode(parameters.viewportConfigurationMinimumEffectiveDeviceWidth))
+        return WTF::nullopt;
     if (!decoder.decode(parameters.viewportConfigurationViewSize))
         return WTF::nullopt;
     if (!decoder.decode(parameters.maximumUnobscuredSize))
index 45eba4d..ab3b8e0 100644 (file)
@@ -148,6 +148,7 @@ struct WebPageCreationParameters {
     bool ignoresViewportScaleLimits;
     WebCore::FloatSize viewportConfigurationViewLayoutSize;
     double viewportConfigurationLayoutSizeScaleFactor;
+    double viewportConfigurationMinimumEffectiveDeviceWidth;
     WebCore::FloatSize viewportConfigurationViewSize;
     WebCore::FloatSize maximumUnobscuredSize;
     int32_t deviceOrientation { 0 };
index 85c3273..a7f6a5e 100644 (file)
@@ -382,7 +382,6 @@ static Optional<WebCore::ScrollbarOverlayStyle> toCoreScrollbarStyle(_WKOverlayS
     RetainPtr<WKTextFinderClient> _textFinderClient;
 #endif
     _WKSelectionAttributes _selectionAttributes;
-    CGFloat _minimumEffectiveDeviceWidth;
 }
 
 - (instancetype)initWithFrame:(CGRect)frame
@@ -2844,7 +2843,7 @@ static WebCore::FloatPoint constrainContentOffset(WebCore::FloatPoint contentOff
         return;
 
     LOG_WITH_STREAM(VisibleRects, stream << "-[WKWebView " << _page->pageID() << " _dispatchSetViewLayoutSize:] " << viewLayoutSize << " contentZoomScale " << contentZoomScale(self));
-    _page->setViewportConfigurationViewLayoutSize(viewLayoutSize, _page->layoutSizeScaleFactor(), _minimumEffectiveDeviceWidth);
+    _page->setViewportConfigurationViewLayoutSize(viewLayoutSize, _page->layoutSizeScaleFactor(), _page->minimumEffectiveDeviceWidth());
     _lastSentViewLayoutSize = viewLayoutSize;
 }
 
@@ -5688,24 +5687,27 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
     if (_page->layoutSizeScaleFactor() == viewScale)
         return;
 
-    _page->setViewportConfigurationViewLayoutSize([self activeViewLayoutSize:self.bounds], viewScale, _minimumEffectiveDeviceWidth);
+    _page->setViewportConfigurationViewLayoutSize([self activeViewLayoutSize:self.bounds], viewScale, _page->minimumEffectiveDeviceWidth());
 #endif
 }
 
 - (void)_setMinimumEffectiveDeviceWidth:(CGFloat)minimumEffectiveDeviceWidth
 {
-    if (_minimumEffectiveDeviceWidth == minimumEffectiveDeviceWidth)
+#if PLATFORM(IOS_FAMILY)
+    if (_page->minimumEffectiveDeviceWidth() == minimumEffectiveDeviceWidth)
         return;
 
-    _minimumEffectiveDeviceWidth = minimumEffectiveDeviceWidth;
-#if PLATFORM(IOS_FAMILY)
-    _page->setViewportConfigurationViewLayoutSize([self activeViewLayoutSize:self.bounds], _page->layoutSizeScaleFactor(), _minimumEffectiveDeviceWidth);
+    _page->setViewportConfigurationViewLayoutSize([self activeViewLayoutSize:self.bounds], _page->layoutSizeScaleFactor(), minimumEffectiveDeviceWidth);
 #endif
 }
 
 - (CGFloat)_minimumEffectiveDeviceWidth
 {
-    return _minimumEffectiveDeviceWidth;
+#if PLATFORM(IOS_FAMILY)
+    return _page->minimumEffectiveDeviceWidth();
+#else
+    return 0;
+#endif
 }
 
 #pragma mark scrollperf methods
index 42f43f2..be1611f 100644 (file)
@@ -7023,6 +7023,7 @@ WebPageCreationParameters WebPageProxy::creationParameters(WebProcessProxy& proc
     parameters.ignoresViewportScaleLimits = m_forceAlwaysUserScalable;
     parameters.viewportConfigurationViewLayoutSize = m_viewportConfigurationViewLayoutSize;
     parameters.viewportConfigurationLayoutSizeScaleFactor = m_viewportConfigurationLayoutSizeScaleFactor;
+    parameters.viewportConfigurationMinimumEffectiveDeviceWidth = m_viewportConfigurationMinimumEffectiveDeviceWidth;
     parameters.maximumUnobscuredSize = m_maximumUnobscuredSize;
     parameters.deviceOrientation = m_deviceOrientation;
     parameters.keyboardIsAttached = isInHardwareKeyboardMode();
index 0b22019..a1c83ac 100644 (file)
@@ -700,6 +700,7 @@ public:
     void setForceAlwaysUserScalable(bool);
     bool forceAlwaysUserScalable() const { return m_forceAlwaysUserScalable; }
     double layoutSizeScaleFactor() const { return m_viewportConfigurationLayoutSizeScaleFactor; }
+    double minimumEffectiveDeviceWidth() const { return m_viewportConfigurationMinimumEffectiveDeviceWidth; }
     void setIsScrollingOrZooming(bool);
     void requestRectsForGranularityWithSelectionOffset(WebCore::TextGranularity, uint32_t offset, WTF::Function<void(const Vector<WebCore::SelectionRect>&, CallbackBase::Error)>&&);
     void requestRectsAtSelectionOffsetWithText(int32_t offset, const String&, WTF::Function<void(const Vector<WebCore::SelectionRect>&, CallbackBase::Error)>&&);
@@ -2420,6 +2421,7 @@ WEBPAGEPROXY_LOADOPTIMIZER_ADDITIONS_2
     bool m_forceAlwaysUserScalable { false };
     WebCore::FloatSize m_viewportConfigurationViewLayoutSize;
     double m_viewportConfigurationLayoutSizeScaleFactor { 1 };
+    double m_viewportConfigurationMinimumEffectiveDeviceWidth { 0 };
     WebCore::FloatSize m_maximumUnobscuredSize;
 #endif
 
index c54d355..b96f894 100644 (file)
@@ -329,6 +329,7 @@ void WebPageProxy::setViewportConfigurationViewLayoutSize(const WebCore::FloatSi
 {
     m_viewportConfigurationViewLayoutSize = size;
     m_viewportConfigurationLayoutSizeScaleFactor = scaleFactor;
+    m_viewportConfigurationMinimumEffectiveDeviceWidth = minimumEffectiveDeviceWidth;
 
     if (hasRunningProcess())
         m_process->send(Messages::WebPage::SetViewportConfigurationViewLayoutSize(size, scaleFactor, minimumEffectiveDeviceWidth), m_pageID);
index df559d7..06233c7 100644 (file)
@@ -660,7 +660,7 @@ WebPage::WebPage(uint64_t pageID, WebPageCreationParameters&& parameters)
 #endif
 
 #if PLATFORM(IOS_FAMILY)
-    setViewportConfigurationViewLayoutSize(parameters.viewportConfigurationViewLayoutSize, parameters.viewportConfigurationLayoutSizeScaleFactor, 0);
+    setViewportConfigurationViewLayoutSize(parameters.viewportConfigurationViewLayoutSize, parameters.viewportConfigurationLayoutSizeScaleFactor, parameters.viewportConfigurationMinimumEffectiveDeviceWidth);
     setMaximumUnobscuredSize(parameters.maximumUnobscuredSize);
 #endif
 
index 02cf621..7c49237 100644 (file)
@@ -1,3 +1,16 @@
+2019-04-05  Yongjun Zhang  <yongjun_zhang@apple.com>
+
+        We should pass minimumEffectiveDeviceWidth to web process on new page creation.
+        https://bugs.webkit.org/show_bug.cgi?id=196077
+        <rdar://problem/49108202>
+
+        Reviewed by Chris Dumez.
+
+        Add an API test to verify the minimumEffectDeviceWidth is passed to web content process
+        on new web view.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
+
 2019-04-05  Saam Barati  <sbarati@apple.com>
 
         Make compare-results understand MotionMark
index 8573272..8664df3 100644 (file)
@@ -5886,4 +5886,57 @@ TEST(ProcessSwap, QuickLookRequestsPasswordAfterSwap)
     didFinishQuickLookLoad = false;
 }
 
+static const char* minimumWidthPageBytes = R"PSONRESOURCE(
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+div {
+    margin: 0;
+    width: 100%;
+    height: 10000px;
+}
+</style>
+</head>
+<body>
+<div>Test</a>
+</body>
+</html>
+)PSONRESOURCE";
+
+TEST(ProcessSwap, PassMinimumDeviceWidthOnNewWebView)
+{
+    auto processPoolConfiguration = psonProcessPoolConfiguration();
+    auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
+
+    auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    [webViewConfiguration setProcessPool:processPool.get()];
+    auto handler = adoptNS([[PSONScheme alloc] init]);
+    [handler addMappingFromURLString:@"pson://www.webkit.org/main.html" toData:minimumWidthPageBytes];
+    [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
+
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
+
+    auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
+    [webView setNavigationDelegate:navigationDelegate.get()];
+
+    auto preferences = [[webView configuration] preferences];
+    [preferences _setShouldIgnoreMetaViewport:YES];
+    [webView _setMinimumEffectiveDeviceWidth:1024];
+
+    auto* request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
+    [webView loadRequest:request];
+
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    bool finishedRunningScript = false;
+    [webView evaluateJavaScript:@"window.innerWidth" completionHandler: [&] (id result, NSError *error) {
+        NSNumber *width = (NSNumber *)result;
+        EXPECT_EQ(1024, [width intValue]);
+        finishedRunningScript = true;
+    }];
+    TestWebKitAPI::Util::run(&finishedRunningScript);
+}
+
 #endif