[iOS] Respect scrolling="no" on composited frames
https://bugs.webkit.org/show_bug.cgi?id=197972
<rdar://problem/50252398>

Reviewed by Simon Fraser.

Source/WebKit:

* UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h:
* UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm:
(WebKit::ScrollingTreeScrollingNodeDelegateIOS::commitStateAfterChildren):

Disallow scrolling based on canHaveScrollbars, similar to main frame.

(WebKit::ScrollingTreeScrollingNodeDelegateIOS::repositionScrollingLayers):
(WebKit::ScrollingTreeScrollingNodeDelegateIOS::scrollView const):

Factor into a function.

LayoutTests:

* fast/scrolling/ios/body-overflow-hidden-frame-expected.html:
* fast/scrolling/ios/body-overflow-hidden-frame.html:

Also fix overflow:hidden test so that the frame content forces composition.

* fast/scrolling/ios/frame-scrolling-no-expected.html: Added.
* fast/scrolling/ios/frame-scrolling-no.html: Added.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@245465 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 9aa7bd1..dfd3758 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,19 @@
+2019-05-17  Antti Koivisto  <antti@apple.com>
+
+        [iOS] Respect scrolling="no" on composited frames
+        https://bugs.webkit.org/show_bug.cgi?id=197972
+        <rdar://problem/50252398>
+
+        Reviewed by Simon Fraser.
+
+        * fast/scrolling/ios/body-overflow-hidden-frame-expected.html:
+        * fast/scrolling/ios/body-overflow-hidden-frame.html:
+
+        Also fix overflow:hidden test so that the frame content forces composition.
+
+        * fast/scrolling/ios/frame-scrolling-no-expected.html: Added.
+        * fast/scrolling/ios/frame-scrolling-no.html: Added.
+
 2019-05-16  Greg Doolittle  <gr3g@apple.com>
 
         AX: Unship some ARIA string reflectors that are to-be-replaced by element reflection
diff --git a/LayoutTests/fast/scrolling/ios/body-overflow-hidden-frame-expected.html b/LayoutTests/fast/scrolling/ios/body-overflow-hidden-frame-expected.html
index 4192583..4a6fbbc 100644
--- a/LayoutTests/fast/scrolling/ios/body-overflow-hidden-frame-expected.html
+++ b/LayoutTests/fast/scrolling/ios/body-overflow-hidden-frame-expected.html
@@ -11,7 +11,7 @@
     <html>
     <style>
     body { overflow: hidden }
-    .scroll-content { width: 500px; height: 5000px; border: 2px solid green; }
+    .scroll-content { width: 500px; height: 5000px; border: 2px solid green; transform:translateZ(0) }
     </style>
     <body>
     <div class='scroll-content'>
diff --git a/LayoutTests/fast/scrolling/ios/body-overflow-hidden-frame.html b/LayoutTests/fast/scrolling/ios/body-overflow-hidden-frame.html
index 02fccbf..ee06a5f 100644
--- a/LayoutTests/fast/scrolling/ios/body-overflow-hidden-frame.html
+++ b/LayoutTests/fast/scrolling/ios/body-overflow-hidden-frame.html
@@ -32,7 +32,7 @@
     <html>
     <style>
     body { overflow: hidden }
-    .scroll-content { width: 500px; height: 5000px; border: 2px solid green; }
+    .scroll-content { width: 500px; height: 5000px; border: 2px solid green; transform:translateZ(0) }
     </style>
     <body>
     <div class='scroll-content'>
diff --git a/LayoutTests/fast/scrolling/ios/frame-scrolling-no-expected.html b/LayoutTests/fast/scrolling/ios/frame-scrolling-no-expected.html
new file mode 100644
index 0000000..dd5bc08
--- /dev/null
+++ b/LayoutTests/fast/scrolling/ios/frame-scrolling-no-expected.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ internal:AsyncOverflowScrollingEnabled=true internal:AsyncFrameScrollingEnabled=true ] -->
+<html>
+<head>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<style>
+body { overflow: hidden }
+.scroll-content { width: 500px; height: 5000px; border: 2px solid green; }
+</style>
+<body>
+<iframe scrolling="no" srcdoc="
+    <html>
+    <style>
+    .scroll-content { width: 500px; height: 5000px; border: 2px solid green; transform:translateZ(0) }
+    </style>
+    <body>
+    <div class='scroll-content'>
+    This document shouldn't be scrollable.
+    </div>
+    </body>
+    </html>
+" width=500 height=500>
+</iframe>
+</body>
+</html>
diff --git a/LayoutTests/fast/scrolling/ios/frame-scrolling-no.html b/LayoutTests/fast/scrolling/ios/frame-scrolling-no.html
new file mode 100644
index 0000000..d95156d
--- /dev/null
+++ b/LayoutTests/fast/scrolling/ios/frame-scrolling-no.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ internal:AsyncOverflowScrollingEnabled=true internal:AsyncFrameScrollingEnabled=true ] -->
+<html>
+<head>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<script src="../../../resources/basic-gestures.js"></script>
+<style>
+body { overflow: hidden }
+.scroll-content { width: 500px; height: 5000px; border: 2px solid green; }
+</style>
+<script>
+if (window.testRunner)
+    testRunner.waitUntilDone();
+
+function waitPromise(delay)
+{
+    return new Promise(resolve => setTimeout(resolve, delay));
+}
+
+async function runTest() {
+    if (!window.testRunner)
+        return;
+
+    await touchAndDragFromPointToPoint(150, 300, 150, 150);
+    await liftUpAtPoint(150, 150);
+    await waitPromise(50);
+
+    testRunner.notifyDone();
+}
+</script>
+<body onload="runTest()">
+<iframe scrolling="no" srcdoc="
+    <html>
+    <style>
+    .scroll-content { width: 500px; height: 5000px; border: 2px solid green; transform:translateZ(0) }
+    </style>
+    <body>
+    <div class='scroll-content'>
+    This document shouldn't be scrollable.
+    </div>
+    </body>
+    </html>
+" width=500 height=500>
+</iframe>
+</body>
+</html>
diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog
index 55a3e99..2d00df8 100644
--- a/Source/WebKit/ChangeLog
+++ b/Source/WebKit/ChangeLog
@@ -1,3 +1,22 @@
+2019-05-17  Antti Koivisto  <antti@apple.com>
+
+        [iOS] Respect scrolling="no" on composited frames
+        https://bugs.webkit.org/show_bug.cgi?id=197972
+        <rdar://problem/50252398>
+
+        Reviewed by Simon Fraser.
+
+        * UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h:
+        * UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm:
+        (WebKit::ScrollingTreeScrollingNodeDelegateIOS::commitStateAfterChildren):
+
+        Disallow scrolling based on canHaveScrollbars, similar to main frame.
+
+        (WebKit::ScrollingTreeScrollingNodeDelegateIOS::repositionScrollingLayers):
+        (WebKit::ScrollingTreeScrollingNodeDelegateIOS::scrollView const):
+
+        Factor into a function.
+
 2019-05-17  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         Unreviewed. Fix variations shown in GTK emoji chooser after r245460.
diff --git a/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h b/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h
index 051f186..b0c00ee 100644
--- a/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h
+++ b/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h
@@ -33,6 +33,7 @@
 #include <WebCore/ScrollingTreeScrollingNodeDelegate.h>
 
 OBJC_CLASS CALayer;
+OBJC_CLASS UIScrollView;
 OBJC_CLASS WKScrollingNodeScrollViewDelegate;
 
 namespace WebCore {
@@ -73,6 +74,8 @@
 #endif
 
 private:
+    UIScrollView *scrollView() const;
+
     RetainPtr<CALayer> m_scrollLayer;
     RetainPtr<CALayer> m_scrolledContentsLayer;
     RetainPtr<WKScrollingNodeScrollViewDelegate> m_scrollViewDelegate;
diff --git a/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm b/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm
index a0ca888..921bac1 100644
--- a/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm
+++ b/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm
@@ -234,9 +234,7 @@
         || scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrollPosition)
         || scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrollOrigin)) {
         BEGIN_BLOCK_OBJC_EXCEPTIONS
-        UIScrollView *scrollView = (UIScrollView *)[scrollLayer() delegate];
-        ASSERT([scrollView isKindOfClass:[UIScrollView self]]);
-
+        UIScrollView *scrollView = this->scrollView();
         if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrollContainerLayer)) {
             if (!m_scrollViewDelegate)
                 m_scrollViewDelegate = adoptNS([[WKScrollingNodeScrollViewDelegate alloc] initWithScrollingTreeNodeDelegate:this]);
@@ -272,21 +270,18 @@
     // FIXME: If only one axis snaps in 2D scrolling, the other axis will decelerate fast as well. Is this what we want?
     if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::HorizontalSnapOffsets) || scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::VerticalSnapOffsets)) {
         BEGIN_BLOCK_OBJC_EXCEPTIONS
-        UIScrollView *scrollView = (UIScrollView *)[scrollLayer() delegate];
-        ASSERT([scrollView isKindOfClass:[UIScrollView self]]);
-
-        scrollView.decelerationRate = scrollingNode().horizontalSnapOffsets().size() || scrollingNode().verticalSnapOffsets().size() ? UIScrollViewDecelerationRateFast : UIScrollViewDecelerationRateNormal;
-#endif
+        scrollView().decelerationRate = scrollingNode().horizontalSnapOffsets().size() || scrollingNode().verticalSnapOffsets().size() ? UIScrollViewDecelerationRateFast : UIScrollViewDecelerationRateNormal;
         END_BLOCK_OBJC_EXCEPTIONS
     }
+#endif
 
     if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrollableAreaParams)) {
         BEGIN_BLOCK_OBJC_EXCEPTIONS
-        UIScrollView *scrollView = (UIScrollView *)[scrollLayer() delegate];
-        ASSERT([scrollView isKindOfClass:[UIScrollView self]]);
+        UIScrollView *scrollView = this->scrollView();
 
         [scrollView setShowsHorizontalScrollIndicator:!scrollingNode().horizontalScrollbarHiddenByStyle()];
         [scrollView setShowsVerticalScrollIndicator:!scrollingNode().verticalScrollbarHiddenByStyle()];
+        [scrollView setScrollEnabled:scrollingNode().canHaveScrollbars()];
 
         END_BLOCK_OBJC_EXCEPTIONS
     }
@@ -302,9 +297,7 @@
     auto scrollPosition = scrollingNode().currentScrollPosition();
 
     BEGIN_BLOCK_OBJC_EXCEPTIONS
-    UIScrollView *scrollView = (UIScrollView *)[scrollLayer() delegate];
-    ASSERT([scrollView isKindOfClass:[UIScrollView self]]);
-    [scrollView setContentOffset:scrollPosition];
+    [scrollView() setContentOffset:scrollPosition];
     END_BLOCK_OBJC_EXCEPTIONS
 }
 
@@ -339,6 +332,13 @@
     scrollingTree().currentSnapPointIndicesDidChange(scrollingNode().scrollingNodeID(), horizontal, vertical);
 }
 
+UIScrollView *ScrollingTreeScrollingNodeDelegateIOS::scrollView() const
+{
+    UIScrollView *scrollView = (UIScrollView *)[scrollLayer() delegate];
+    ASSERT([scrollView isKindOfClass:[UIScrollView self]]);
+    return scrollView;
+}
+
 #if ENABLE(POINTER_EVENTS)
 void ScrollingTreeScrollingNodeDelegateIOS::computeActiveTouchActionsForGestureRecognizer(UIGestureRecognizer* gestureRecognizer)
 {