Title: [280980] trunk
Revision
280980
Author
wei...@apple.com
Date
2021-08-12 13:16:51 -0700 (Thu, 12 Aug 2021)

Log Message

Allow testing of the final UIView tree on iOS platforms
https://bugs.webkit.org/show_bug.cgi?id=229016

Reviewed by Tim Horton.

Source/WebKit:

Test: remote-layer-tree/ios/uiview-tree-basic.html

* UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h:
* UIProcess/API/ios/WKWebViewTestingIOS.mm:
(allowListedClassToString):
(dumpUIView):
(-[WKWebView _uiViewTreeAsText]):
Add partner SPI called _uiViewTreeAsText that dumps the WKWebView's
UIView tree as constructed via remote layer creation. It currently
dumps some basic properties of each view and uses an allow list of
class names so changes to implementation details in frameworks below
us, like UIKit, don't cause tests to fail.

Tools:

* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::uiViewTreeAsText const):
* WebKitTestRunner/ios/UIScriptControllerIOS.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptControllerIOS::uiViewTreeAsText const):
Pipe new _uiViewTreeAsText SPI through to UIScriptController, matching the pattern
established by scrollingTreeAsText.

LayoutTests:

* remote-layer-tree: Added.
* remote-layer-tree/ios: Added.
* remote-layer-tree/ios/uiview-tree-basic-expected.txt: Added.
* remote-layer-tree/ios/uiview-tree-basic.html: Added.
Add basic test case excercising UIView tree dumping to ensure
it is working properly.

* resources/ui-helper.js:
(window.UIHelper.getUIViewTree):
Add helper to use get the UIView tree as text.

* TestExpectations:
* platform/ios/TestExpectations:
Ensure these tests are only run on iOS.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (280979 => 280980)


--- trunk/LayoutTests/ChangeLog	2021-08-12 20:16:16 UTC (rev 280979)
+++ trunk/LayoutTests/ChangeLog	2021-08-12 20:16:51 UTC (rev 280980)
@@ -1,3 +1,25 @@
+2021-08-12  Sam Weinig  <wei...@apple.com>
+
+        Allow testing of the final UIView tree on iOS platforms
+        https://bugs.webkit.org/show_bug.cgi?id=229016
+
+        Reviewed by Tim Horton.
+
+        * remote-layer-tree: Added.
+        * remote-layer-tree/ios: Added.
+        * remote-layer-tree/ios/uiview-tree-basic-expected.txt: Added.
+        * remote-layer-tree/ios/uiview-tree-basic.html: Added.
+        Add basic test case excercising UIView tree dumping to ensure
+        it is working properly.
+
+        * resources/ui-helper.js:
+        (window.UIHelper.getUIViewTree):
+        Add helper to use get the UIView tree as text.
+
+        * TestExpectations:
+        * platform/ios/TestExpectations:
+        Ensure these tests are only run on iOS.
+
 2021-08-12  Martin Robinson  <mrobin...@webkit.org>
 
         Update import of css/css-position from WPT

Modified: trunk/LayoutTests/TestExpectations (280979 => 280980)


--- trunk/LayoutTests/TestExpectations	2021-08-12 20:16:16 UTC (rev 280979)
+++ trunk/LayoutTests/TestExpectations	2021-08-12 20:16:51 UTC (rev 280980)
@@ -82,6 +82,7 @@
 editing/pasteboard/mac [ Skip ]
 fast/media/ios [ Skip ]
 fast/dom/Range/mac [ Skip ]
+remote-layer-tree/ios [ Skip ]
 inspector/page/setScreenSizeOverride.html [ Skip ]
 
 # Requires async overflow scrolling

Modified: trunk/LayoutTests/platform/ios/TestExpectations (280979 => 280980)


--- trunk/LayoutTests/platform/ios/TestExpectations	2021-08-12 20:16:16 UTC (rev 280979)
+++ trunk/LayoutTests/platform/ios/TestExpectations	2021-08-12 20:16:51 UTC (rev 280980)
@@ -18,6 +18,7 @@
 model-element [ Pass ]
 quicklook [ Pass ]
 system-preview [ Pass ]
+remote-layer-tree/ios [ Pass ]
 swipe [ Pass ]
 http/tests/swipe [ Pass ]
 

Added: trunk/LayoutTests/remote-layer-tree/ios/uiview-tree-basic-expected.txt (0 => 280980)


--- trunk/LayoutTests/remote-layer-tree/ios/uiview-tree-basic-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/remote-layer-tree/ios/uiview-tree-basic-expected.txt	2021-08-12 20:16:51 UTC (rev 280980)
@@ -0,0 +1,64 @@
+
+(UIView tree root view [class: <class not in allowed list of classes>]
+  (layer bounds [x: 0 y: 0 width: 800 height: 600])
+  (layer position [x: 400 y: 400])
+  (subviews
+    (view [class: WKScrollView]
+      (layer bounds [x: 0 y: 0 width: 800 height: 600])
+      (layer position [x: 400 y: 400])
+      (subviews
+        (view [class: WKContentView]
+          (layer bounds [x: 0 y: 0 width: 800 height: 600])
+          (layer anchorPoint [x: 0 y: 0])
+          (subviews
+            (view [class: UIView]
+              (layer bounds [x: 0 y: 0 width: 800 height: 600])
+              (layer anchorPoint [x: 0 y: 0])
+              (subviews
+                (view [class: UIView]
+                  (layer bounds [x: 0 y: 0 width: 800 height: 600])
+                  (layer position [x: 400 y: 400])
+                  (subviews
+                    (view [class: WKCompositingView]
+                      (layer bounds [x: 0 y: 0 width: 800 height: 600])
+                      (layer position [x: 400 y: 400])
+                      (subviews
+                        (view [class: WKCompositingView]
+                          (layer bounds [x: 0 y: 0 width: 800 height: 600])
+                          (layer anchorPoint [x: 0 y: 0])
+                          (subviews
+                            (view [class: WKCompositingView]
+                              (layer bounds [x: 0 y: 0 width: 800 height: 600])
+                              (layer position [x: 400 y: 400])
+                              (subviews
+                                (view [class: WKCompositingView]
+                                  (layer bounds [x: 0 y: 0 width: 0 height: 0]))
+                                (view [class: WKCompositingView]
+                                  (layer bounds [x: 0 y: 0 width: 0 height: 0])
+                                  (subviews
+                                    (view [class: WKCompositingView]
+                                      (layer bounds [x: 0 y: 0 width: 784 height: 20])
+                                      (layer position [x: 400 y: 400]))))))))))))))
+            (view [class: _UILayerHostView]
+              (layer bounds [x: 0 y: 0 width: 0 height: 0]))
+            (view [class: _UILayerHostView]
+              (layer bounds [x: 0 y: 0 width: 0 height: 0]))))
+        (view [class: UIView]
+          (layer bounds [x: 0 y: 0 width: 0 height: 0])
+          (layer anchorPoint [x: 0 y: 0]))
+        (view [class: <class not in allowed list of classes>]
+          (layer bounds [x: 0 y: 0 width: 3 height: 594])
+          (layer position [x: 795.5 y: 795.5])
+          (layer zPosition 1000)
+          (subviews
+            (view [class: UIView]
+              (layer bounds [x: 0 y: 0 width: 3 height: 594])
+              (layer position [x: 1.5 y: 1.5]))))
+        (view [class: <class not in allowed list of classes>]
+          (layer bounds [x: 0 y: 0 width: 794 height: 3])
+          (layer position [x: 400 y: 400])
+          (layer zPosition 1000)
+          (subviews
+            (view [class: UIView]
+              (layer bounds [x: 0 y: 0 width: 794 height: 3])
+              (layer position [x: 397 y: 397]))))))))

Added: trunk/LayoutTests/remote-layer-tree/ios/uiview-tree-basic.html (0 => 280980)


--- trunk/LayoutTests/remote-layer-tree/ios/uiview-tree-basic.html	                        (rev 0)
+++ trunk/LayoutTests/remote-layer-tree/ios/uiview-tree-basic.html	2021-08-12 20:16:51 UTC (rev 280980)
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src=""
+    <script>
+        if (window.testRunner) {
+            testRunner.waitUntilDone();
+            testRunner.dumpAsText();
+        }
+
+        async function doTest()
+        {
+            await UIHelper.ensureStablePresentationUpdate();
+            let tree = await UIHelper.getUIViewTree();
+
+            document.getElementById('test').remove();
+
+            let output = document.createElement('pre');
+            document.body.append(output);
+            output.textContent = tree;
+
+            testRunner.notifyDone();
+        }
+
+        window.addEventListener('load', doTest, false);
+    </script>
+</head>
+<body>
+<div id="test">
+    <div style="will-change: transform;">Hello</div>
+</div>
+</body>
+</html>

Modified: trunk/LayoutTests/resources/ui-helper.js (280979 => 280980)


--- trunk/LayoutTests/resources/ui-helper.js	2021-08-12 20:16:16 UTC (rev 280979)
+++ trunk/LayoutTests/resources/ui-helper.js	2021-08-12 20:16:51 UTC (rev 280980)
@@ -1409,6 +1409,18 @@
         });
     }
 
+    static getUIViewTree()
+    {
+        if (!this.isWebKit2() || !this.isIOSFamily())
+            return Promise.resolve();
+
+        return new Promise(resolve => {
+            testRunner.runUIScript(`(() => {
+                return uiController.uiViewTreeAsText;
+            })()`, resolve);
+        });
+    }
+
     static dragFromPointToPoint(fromX, fromY, toX, toY, duration)
     {
         if (!this.isWebKit2() || !this.isIOSFamily()) {

Modified: trunk/Source/WebKit/ChangeLog (280979 => 280980)


--- trunk/Source/WebKit/ChangeLog	2021-08-12 20:16:16 UTC (rev 280979)
+++ trunk/Source/WebKit/ChangeLog	2021-08-12 20:16:51 UTC (rev 280980)
@@ -1,3 +1,23 @@
+2021-08-12  Sam Weinig  <wei...@apple.com>
+
+        Allow testing of the final UIView tree on iOS platforms
+        https://bugs.webkit.org/show_bug.cgi?id=229016
+
+        Reviewed by Tim Horton.
+
+        Test: remote-layer-tree/ios/uiview-tree-basic.html
+
+        * UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h:
+        * UIProcess/API/ios/WKWebViewTestingIOS.mm:
+        (allowListedClassToString):
+        (dumpUIView):
+        (-[WKWebView _uiViewTreeAsText]):
+        Add partner SPI called _uiViewTreeAsText that dumps the WKWebView's
+        UIView tree as constructed via remote layer creation. It currently
+        dumps some basic properties of each view and uses an allow list of
+        class names so changes to implementation details in frameworks below
+        us, like UIKit, don't cause tests to fail.
+
 2021-08-12  Jer Noble  <jer.no...@apple.com>
 
         [macOS] Enter fullscreen animation interferes with auto-hiding menu bar

Modified: trunk/Source/WebKit/UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h (280979 => 280980)


--- trunk/Source/WebKit/UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h	2021-08-12 20:16:16 UTC (rev 280979)
+++ trunk/Source/WebKit/UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h	2021-08-12 20:16:51 UTC (rev 280980)
@@ -43,6 +43,7 @@
 @property (nonatomic, readonly) NSArray<NSValue *> *_uiTextSelectionRects;
 @property (nonatomic, readonly) CGRect _inputViewBoundsInWindow;
 @property (nonatomic, readonly) NSString *_scrollingTreeAsText;
+@property (nonatomic, readonly) NSString *_uiViewTreeAsText;
 @property (nonatomic, readonly) NSNumber *_stableStateOverride;
 @property (nonatomic, readonly) CGRect _dragCaretRect;
 @property (nonatomic, readonly, getter=_isAnimatingDragCancel) BOOL _animatingDragCancel;

Modified: trunk/Source/WebKit/UIProcess/API/ios/WKWebViewTestingIOS.mm (280979 => 280980)


--- trunk/Source/WebKit/UIProcess/API/ios/WKWebViewTestingIOS.mm	2021-08-12 20:16:16 UTC (rev 280979)
+++ trunk/Source/WebKit/UIProcess/API/ios/WKWebViewTestingIOS.mm	2021-08-12 20:16:51 UTC (rev 280980)
@@ -41,6 +41,8 @@
 #import <WebCore/ColorIOS.h>
 #import <WebCore/ColorSerialization.h>
 #import <WebCore/ElementContext.h>
+#import <wtf/SortedArrayMap.h>
+#import <wtf/text/TextStream.h>
 
 @implementation WKWebView (WKTestingIOS)
 
@@ -227,6 +229,84 @@
     return coordinator->scrollingTreeAsText();
 }
 
+static String allowListedClassToString(UIView *view)
+{
+    static constexpr ComparableASCIILiteral allowedClassesArray[] = {
+        "UIView",
+        "WKBackdropView",
+        "WKCompositingView",
+        "WKContentView",
+        "WKModelView",
+        "WKRemoteView",
+        "WKScrollView",
+        "WKSeparatedModelView"
+        "WKShapeView",
+        "WKSimpleBackdropView",
+        "WKTransformView",
+        "WKUIRemoteView",
+        "WKWebView",
+        "_UILayerHostView",
+    };
+    static constexpr SortedArraySet allowedClasses { allowedClassesArray };
+
+    String classString { NSStringFromClass(view.class) };
+    if (allowedClasses.contains(classString))
+        return classString;
+    
+    ASSERT(classString != "WKCompositingView");
+    return makeString("<class not in allowed list of classes>");
+}
+
+static void dumpUIView(TextStream& ts, UIView *view)
+{
+    auto rectToString = [] (auto rect) {
+        return makeString("[x: ", rect.origin.x, " y: ", rect.origin.x, " width: ", rect.size.width, " height: ", rect.size.height, "]");
+    };
+
+    auto pointToString = [] (auto point) {
+        return makeString("[x: ", point.x, " y: ", point.x, "]");
+    };
+
+
+    ts << "view [class: " << allowListedClassToString(view) << "]";
+
+    ts.dumpProperty("layer bounds", rectToString(view.layer.bounds));
+    
+    if (view.layer.position.x != 0 || view.layer.position.y != 0)
+        ts.dumpProperty("layer position", pointToString(view.layer.position));
+    
+    if (view.layer.zPosition != 0)
+        ts.dumpProperty("layer zPosition", makeString(view.layer.zPosition));
+    
+    if (view.layer.anchorPoint.x != 0.5 || view.layer.anchorPoint.y != 0.5)
+        ts.dumpProperty("layer anchorPoint", pointToString(view.layer.anchorPoint));
+    
+    if (view.layer.anchorPointZ != 0)
+        ts.dumpProperty("layer anchorPointZ", makeString(view.layer.anchorPointZ));
+
+    if (view.subviews.count > 0) {
+        TextStream::GroupScope scope(ts);
+        ts << "subviews";
+        for (UIView *subview in view.subviews) {
+            TextStream::GroupScope scope(ts);
+            dumpUIView(ts, subview);
+        }
+    }
+}
+
+- (NSString *)_uiViewTreeAsText
+{
+    TextStream ts(TextStream::LineMode::MultipleLine);
+
+    {
+        TextStream::GroupScope scope(ts);
+        ts << "UIView tree root ";
+        dumpUIView(ts, self);
+    }
+
+    return ts.release();
+}
+
 - (NSNumber *)_stableStateOverride
 {
     // For subclasses to override.

Modified: trunk/Tools/ChangeLog (280979 => 280980)


--- trunk/Tools/ChangeLog	2021-08-12 20:16:16 UTC (rev 280979)
+++ trunk/Tools/ChangeLog	2021-08-12 20:16:51 UTC (rev 280980)
@@ -1,3 +1,19 @@
+2021-08-12  Sam Weinig  <wei...@apple.com>
+
+        Allow testing of the final UIView tree on iOS platforms
+        https://bugs.webkit.org/show_bug.cgi?id=229016
+
+        Reviewed by Tim Horton.
+
+        * TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
+        * TestRunnerShared/UIScriptContext/UIScriptController.h:
+        (WTR::UIScriptController::uiViewTreeAsText const):
+        * WebKitTestRunner/ios/UIScriptControllerIOS.h:
+        * WebKitTestRunner/ios/UIScriptControllerIOS.mm:
+        (WTR::UIScriptControllerIOS::uiViewTreeAsText const):
+        Pipe new _uiViewTreeAsText SPI through to UIScriptController, matching the pattern
+        established by scrollingTreeAsText.
+
 2021-08-12  Devin Rousso  <drou...@apple.com>
 
         Fix some `NSAttributedString` inconsistencies between WK1 and WK2

Modified: trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl (280979 => 280980)


--- trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl	2021-08-12 20:16:16 UTC (rev 280979)
+++ trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl	2021-08-12 20:16:51 UTC (rev 280980)
@@ -332,6 +332,7 @@
     undefined replaceTextAtRange(DOMString text, long location, long length);
 
     readonly attribute DOMString scrollingTreeAsText;
+    readonly attribute DOMString uiViewTreeAsText;
 
     boolean mayContainEditableElementsInRect(unsigned long x, unsigned long y, unsigned long width, unsigned long height);
 

Modified: trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h (280979 => 280980)


--- trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h	2021-08-12 20:16:16 UTC (rev 280979)
+++ trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h	2021-08-12 20:16:51 UTC (rev 280980)
@@ -146,6 +146,7 @@
     virtual double contentOffsetY() const { notImplemented(); return 0; }
 
     virtual JSRetainPtr<JSStringRef> scrollingTreeAsText() const { notImplemented(); return nullptr; }
+    virtual JSRetainPtr<JSStringRef> uiViewTreeAsText() const { notImplemented(); return nullptr; }
 
     // Touches
 

Modified: trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.h (280979 => 280980)


--- trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.h	2021-08-12 20:16:16 UTC (rev 280979)
+++ trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.h	2021-08-12 20:16:51 UTC (rev 280980)
@@ -117,6 +117,7 @@
     JSObjectRef selectionRangeViewRects() const override;
     JSObjectRef inputViewBounds() const override;
     JSRetainPtr<JSStringRef> scrollingTreeAsText() const override;
+    JSRetainPtr<JSStringRef> uiViewTreeAsText() const override;
     JSObjectRef propertiesOfLayerWithID(uint64_t layerID) const override;
     void simulateRotation(DeviceOrientation*, JSValueRef) override;
     void simulateRotationLikeSafari(DeviceOrientation*, JSValueRef) override;

Modified: trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm (280979 => 280980)


--- trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm	2021-08-12 20:16:16 UTC (rev 280979)
+++ trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm	2021-08-12 20:16:51 UTC (rev 280980)
@@ -857,6 +857,11 @@
     return adopt(JSStringCreateWithCFString((CFStringRef)[webView() _scrollingTreeAsText]));
 }
 
+JSRetainPtr<JSStringRef> UIScriptControllerIOS::uiViewTreeAsText() const
+{
+    return adopt(JSStringCreateWithCFString((CFStringRef)[webView() _uiViewTreeAsText]));
+}
+
 JSObjectRef UIScriptControllerIOS::propertiesOfLayerWithID(uint64_t layerID) const
 {
     return JSValueToObject(m_context->jsContext(), [JSValue valueWithObject:[webView() _propertiesOfLayerWithID:layerID] inContext:[JSContext contextWithJSGlobalContextRef:m_context->jsContext()]].JSValueRef, nullptr);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to