Title: [259551] trunk/Tools
Revision
259551
Author
[email protected]
Date
2020-04-05 09:49:59 -0700 (Sun, 05 Apr 2020)

Log Message

RequestTextInputContext.Simple iframe sub-tests may sometimes fail
https://bugs.webkit.org/show_bug.cgi?id=210010
<rdar://problem/61303697>

Reviewed by Simon Fraser and Darin Adler.

Make the iframe sub tests wait until the DOM Load event has fired in the main frame.
When it fires this means that all immediate child frames (like the one added by these
sub tests) have fired their DOM Load event. This ensures deterministic results.

Also while I am here, extract out the iframe sub-tests into their own TEST() method
for testing and debugging convenience. I also fixed up -performAfterLoading so that
it wouldn't leak the user script string and made it work if called more than once in the
same TEST() by caching this script and only adding it to the user content controller
once. Moreover, removed duplication by writing it in terms of -performAfterReceivingMessage.

* TestWebKitAPI/Tests/WebKitCocoa/RequestTextInputContext.mm:
(TEST):
(webViewLoadHTMLStringAndWaitForDOMLoadEvent): Helper function to load an HTML string
into a web view and wait until a DOM Load event is fired at the main frame.
* TestWebKitAPI/cocoa/TestWKWebView.h:
* TestWebKitAPI/cocoa/TestWKWebView.mm:
(-[TestWKWebView performAfterLoading:]): Modernized and simplified. Modified user script
to use addEventListener() instead of onload as the latter overrides any existing load handler.
This user script is also added only to the main frame since all existing callers just
want to know that all main frame and immediate child frames loaded. Also listen for the load
event during the capture phase, which is a tiny bit faster to receive, instead of the bubbling
phase. See second paragraph above for more details on the changes I made to this function.

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (259550 => 259551)


--- trunk/Tools/ChangeLog	2020-04-05 16:34:39 UTC (rev 259550)
+++ trunk/Tools/ChangeLog	2020-04-05 16:49:59 UTC (rev 259551)
@@ -1,3 +1,35 @@
+2020-04-05  Daniel Bates  <[email protected]>
+
+        RequestTextInputContext.Simple iframe sub-tests may sometimes fail
+        https://bugs.webkit.org/show_bug.cgi?id=210010
+        <rdar://problem/61303697>
+
+        Reviewed by Simon Fraser and Darin Adler.
+
+        Make the iframe sub tests wait until the DOM Load event has fired in the main frame.
+        When it fires this means that all immediate child frames (like the one added by these
+        sub tests) have fired their DOM Load event. This ensures deterministic results.
+
+        Also while I am here, extract out the iframe sub-tests into their own TEST() method
+        for testing and debugging convenience. I also fixed up -performAfterLoading so that
+        it wouldn't leak the user script string and made it work if called more than once in the
+        same TEST() by caching this script and only adding it to the user content controller
+        once. Moreover, removed duplication by writing it in terms of -performAfterReceivingMessage.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/RequestTextInputContext.mm:
+        (TEST):
+        (webViewLoadHTMLStringAndWaitForDOMLoadEvent): Helper function to load an HTML string
+        into a web view and wait until a DOM Load event is fired at the main frame.
+        * TestWebKitAPI/cocoa/TestWKWebView.h:
+        * TestWebKitAPI/cocoa/TestWKWebView.mm:
+        (-[TestWKWebView performAfterLoading:]): Modernized and simplified. Modified user script
+        to use addEventListener() instead of onload as the latter overrides any existing load handler.
+        This user script is also added only to the main frame since all existing callers just
+        want to know that all main frame and immediate child frames loaded. Also listen for the load
+        event during the capture phase, which is a tiny bit faster to receive, instead of the bubbling
+        phase. See second paragraph above for more details on the changes I made to this function.
+
+
 2020-04-04  Wenson Hsieh  <[email protected]>
 
         Add a fourth round of logging to help diagnose <webkit.org/b/209685>

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/RequestTextInputContext.mm (259550 => 259551)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/RequestTextInputContext.mm	2020-04-05 16:34:39 UTC (rev 259550)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/RequestTextInputContext.mm	2020-04-05 16:49:59 UTC (rev 259551)
@@ -97,23 +97,6 @@
     EXPECT_EQ(1UL, contexts.count);
     EXPECT_EQ(CGRectMake(0, 0, 100, 100), contexts[0].boundingRect);
 
-    // Basic inputs inside subframe.
-
-    [webView synchronouslyLoadHTMLString:applyIframe(@"<input type='text' style='width: 50px; height: 50px;'>")];
-    contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView bounds]];
-    EXPECT_EQ(1UL, contexts.count);
-    EXPECT_EQ(CGRectMake(0, 200, 50, 50), contexts[0].boundingRect);
-
-    [webView synchronouslyLoadHTMLString:applyIframe(@"<textarea style='width: 100px; height: 100px;'></textarea>")];
-    contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView bounds]];
-    EXPECT_EQ(1UL, contexts.count);
-    EXPECT_EQ(CGRectMake(0, 200, 100, 100), contexts[0].boundingRect);
-
-    [webView synchronouslyLoadHTMLString:applyIframe(@"<div contenteditable style='width: 100px; height: 100px;'></div>")];
-    contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView bounds]];
-    EXPECT_EQ(1UL, contexts.count);
-    EXPECT_EQ(CGRectMake(0, 200, 100, 100), contexts[0].boundingRect);
-
     // Read only inputs; should not be included.
 
     [webView synchronouslyLoadHTMLString:applyStyle(@"<input type='text' style='width: 50px; height: 50px;' readonly>")];
@@ -167,6 +150,39 @@
     EXPECT_EQ(CGRectMake(0, 0, 100, 100), contexts[1].boundingRect);
 }
 
+// Consider moving this to TestWKWebView if it could be useful to other tests.
+static void webViewLoadHTMLStringAndWaitForDOMLoadEvent(TestWKWebView *webView, NSString *htmlString)
+{
+    ASSERT(webView); // Make passing a nil web view a more obvious failure than a hang.
+    bool didFireDOMLoadEvent = false;
+    [webView performAfterLoading:[&] { didFireDOMLoadEvent = true; }];
+    [webView loadHTMLString:htmlString baseURL:nil];
+    TestWebKitAPI::Util::run(&didFireDOMLoadEvent);
+}
+
+TEST(RequestTextInputContext, Iframe)
+{
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+
+    NSArray<_WKTextInputContext *> *contexts;
+
+    webViewLoadHTMLStringAndWaitForDOMLoadEvent(webView.get(), applyIframe(@"<input type='text' style='width: 50px; height: 50px;'>"));
+    contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView bounds]];
+    EXPECT_EQ(1UL, contexts.count);
+    EXPECT_EQ(CGRectMake(0, 200, 50, 50), contexts[0].boundingRect);
+
+    webViewLoadHTMLStringAndWaitForDOMLoadEvent(webView.get(), applyIframe(@"<textarea style='width: 100px; height: 100px;'></textarea>"));
+    contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView bounds]];
+    EXPECT_EQ(1UL, contexts.count);
+    EXPECT_EQ(CGRectMake(0, 200, 100, 100), contexts[0].boundingRect);
+
+    webViewLoadHTMLStringAndWaitForDOMLoadEvent(webView.get(), applyIframe(@"<div contenteditable style='width: 100px; height: 100px;'></div>"));
+    contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView bounds]];
+    EXPECT_EQ(1UL, contexts.count);
+    EXPECT_EQ(CGRectMake(0, 200, 100, 100), contexts[0].boundingRect);
+}
+
 TEST(RequestTextInputContext, DISABLED_FocusTextInputContext)
 {
     RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);

Modified: trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h (259550 => 259551)


--- trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h	2020-04-05 16:34:39 UTC (rev 259550)
+++ trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h	2020-04-05 16:49:59 UTC (rev 259551)
@@ -78,7 +78,11 @@
 - (void)clearMessageHandlers:(NSArray *)messageNames;
 - (void)performAfterReceivingMessage:(NSString *)message action:(dispatch_block_t)action;
 - (void)waitForMessage:(NSString *)message;
+
+// This function waits until a DOM load event is fired.
+// FIXME: Rename this function to better describe what "after loading" means.
 - (void)performAfterLoading:(dispatch_block_t)actions;
+
 - (void)waitForNextPresentationUpdate;
 - (void)forceDarkMode;
 - (NSString *)stylePropertyAtSelectionStart:(NSString *)propertyName;

Modified: trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm (259550 => 259551)


--- trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm	2020-04-05 16:34:39 UTC (rev 259550)
+++ trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm	2020-04-05 16:49:59 UTC (rev 259551)
@@ -399,6 +399,7 @@
 @implementation TestWKWebView {
     RetainPtr<TestWKWebViewHostWindow> _hostWindow;
     RetainPtr<TestMessageHandler> _testHandler;
+    RetainPtr<WKUserScript> _onloadScript;
 #if PLATFORM(IOS_FAMILY)
     std::unique_ptr<ClassMethodSwizzler> _sharedCalloutBarSwizzler;
     InputSessionChangeCount _inputSessionChangeCount;
@@ -502,15 +503,13 @@
 
 - (void)performAfterLoading:(dispatch_block_t)actions
 {
-    TestMessageHandler *handler = [[TestMessageHandler alloc] init];
-    [handler addMessage:@"loaded" withHandler:actions];
-
-    NSString *_onloadScript_ = @"window._onload_ = () => window.webkit.messageHandlers.onloadHandler.postMessage('loaded')";
-    WKUserScript *script = [[WKUserScript alloc] initWithSource:onloadScript injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
-
-    WKUserContentController* contentController = [[self configuration] userContentController];
-    [contentController addUserScript:script];
-    [contentController addScriptMessageHandler:handler name:@"onloadHandler"];
+    NSString *const viewDidLoadMessage = @"TestWKWebViewDidLoad";
+    if (!_onloadScript) {
+        NSString *_onloadScript_ = [NSString stringWithFormat:@"window.addEventListener('load', () => window.webkit.messageHandlers.testHandler.postMessage('%@'), true /* useCapture */)", viewDidLoadMessage];
+        _onloadScript = adoptNS([[WKUserScript alloc] initWithSource:onloadScript injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]);
+        [self.configuration.userContentController addUserScript:_onloadScript.get()];
+    }
+    [self performAfterReceivingMessage:viewDidLoadMessage action:actions];
 }
 
 - (void)waitForNextPresentationUpdate
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to