Changeset 259551 in webkit


Ignore:
Timestamp:
Apr 5, 2020 9:49:59 AM (4 years ago)
Author:
dbates@webkit.org
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.

Location:
trunk/Tools
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Tools/ChangeLog

    r259541 r259551  
     12020-04-05  Daniel Bates  <dabates@apple.com>
     2
     3        RequestTextInputContext.Simple iframe sub-tests may sometimes fail
     4        https://bugs.webkit.org/show_bug.cgi?id=210010
     5        <rdar://problem/61303697>
     6
     7        Reviewed by Simon Fraser and Darin Adler.
     8
     9        Make the iframe sub tests wait until the DOM Load event has fired in the main frame.
     10        When it fires this means that all immediate child frames (like the one added by these
     11        sub tests) have fired their DOM Load event. This ensures deterministic results.
     12
     13        Also while I am here, extract out the iframe sub-tests into their own TEST() method
     14        for testing and debugging convenience. I also fixed up -performAfterLoading so that
     15        it wouldn't leak the user script string and made it work if called more than once in the
     16        same TEST() by caching this script and only adding it to the user content controller
     17        once. Moreover, removed duplication by writing it in terms of -performAfterReceivingMessage.
     18
     19        * TestWebKitAPI/Tests/WebKitCocoa/RequestTextInputContext.mm:
     20        (TEST):
     21        (webViewLoadHTMLStringAndWaitForDOMLoadEvent): Helper function to load an HTML string
     22        into a web view and wait until a DOM Load event is fired at the main frame.
     23        * TestWebKitAPI/cocoa/TestWKWebView.h:
     24        * TestWebKitAPI/cocoa/TestWKWebView.mm:
     25        (-[TestWKWebView performAfterLoading:]): Modernized and simplified. Modified user script
     26        to use addEventListener() instead of onload as the latter overrides any existing load handler.
     27        This user script is also added only to the main frame since all existing callers just
     28        want to know that all main frame and immediate child frames loaded. Also listen for the load
     29        event during the capture phase, which is a tiny bit faster to receive, instead of the bubbling
     30        phase. See second paragraph above for more details on the changes I made to this function.
     31
     32
    1332020-04-04  Wenson Hsieh  <wenson_hsieh@apple.com>
    234
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/RequestTextInputContext.mm

    r257854 r259551  
    9898    EXPECT_EQ(CGRectMake(0, 0, 100, 100), contexts[0].boundingRect);
    9999
    100     // Basic inputs inside subframe.
    101 
    102     [webView synchronouslyLoadHTMLString:applyIframe(@"<input type='text' style='width: 50px; height: 50px;'>")];
    103     contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView bounds]];
    104     EXPECT_EQ(1UL, contexts.count);
    105     EXPECT_EQ(CGRectMake(0, 200, 50, 50), contexts[0].boundingRect);
    106 
    107     [webView synchronouslyLoadHTMLString:applyIframe(@"<textarea style='width: 100px; height: 100px;'></textarea>")];
    108     contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView bounds]];
    109     EXPECT_EQ(1UL, contexts.count);
    110     EXPECT_EQ(CGRectMake(0, 200, 100, 100), contexts[0].boundingRect);
    111 
    112     [webView synchronouslyLoadHTMLString:applyIframe(@"<div contenteditable style='width: 100px; height: 100px;'></div>")];
    113     contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView bounds]];
    114     EXPECT_EQ(1UL, contexts.count);
    115     EXPECT_EQ(CGRectMake(0, 200, 100, 100), contexts[0].boundingRect);
    116 
    117100    // Read only inputs; should not be included.
    118101
     
    166149    EXPECT_EQ(CGRectMake(0, 0, 50, 50), contexts[0].boundingRect);
    167150    EXPECT_EQ(CGRectMake(0, 0, 100, 100), contexts[1].boundingRect);
     151}
     152
     153// Consider moving this to TestWKWebView if it could be useful to other tests.
     154static void webViewLoadHTMLStringAndWaitForDOMLoadEvent(TestWKWebView *webView, NSString *htmlString)
     155{
     156    ASSERT(webView); // Make passing a nil web view a more obvious failure than a hang.
     157    bool didFireDOMLoadEvent = false;
     158    [webView performAfterLoading:[&] { didFireDOMLoadEvent = true; }];
     159    [webView loadHTMLString:htmlString baseURL:nil];
     160    TestWebKitAPI::Util::run(&didFireDOMLoadEvent);
     161}
     162
     163TEST(RequestTextInputContext, Iframe)
     164{
     165    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     166    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
     167
     168    NSArray<_WKTextInputContext *> *contexts;
     169
     170    webViewLoadHTMLStringAndWaitForDOMLoadEvent(webView.get(), applyIframe(@"<input type='text' style='width: 50px; height: 50px;'>"));
     171    contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView bounds]];
     172    EXPECT_EQ(1UL, contexts.count);
     173    EXPECT_EQ(CGRectMake(0, 200, 50, 50), contexts[0].boundingRect);
     174
     175    webViewLoadHTMLStringAndWaitForDOMLoadEvent(webView.get(), applyIframe(@"<textarea style='width: 100px; height: 100px;'></textarea>"));
     176    contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView bounds]];
     177    EXPECT_EQ(1UL, contexts.count);
     178    EXPECT_EQ(CGRectMake(0, 200, 100, 100), contexts[0].boundingRect);
     179
     180    webViewLoadHTMLStringAndWaitForDOMLoadEvent(webView.get(), applyIframe(@"<div contenteditable style='width: 100px; height: 100px;'></div>"));
     181    contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView bounds]];
     182    EXPECT_EQ(1UL, contexts.count);
     183    EXPECT_EQ(CGRectMake(0, 200, 100, 100), contexts[0].boundingRect);
    168184}
    169185
  • trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h

    r256715 r259551  
    7979- (void)performAfterReceivingMessage:(NSString *)message action:(dispatch_block_t)action;
    8080- (void)waitForMessage:(NSString *)message;
     81
     82// This function waits until a DOM load event is fired.
     83// FIXME: Rename this function to better describe what "after loading" means.
    8184- (void)performAfterLoading:(dispatch_block_t)actions;
     85
    8286- (void)waitForNextPresentationUpdate;
    8387- (void)forceDarkMode;
  • trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm

    r256715 r259551  
    400400    RetainPtr<TestWKWebViewHostWindow> _hostWindow;
    401401    RetainPtr<TestMessageHandler> _testHandler;
     402    RetainPtr<WKUserScript> _onloadScript;
    402403#if PLATFORM(IOS_FAMILY)
    403404    std::unique_ptr<ClassMethodSwizzler> _sharedCalloutBarSwizzler;
     
    503504- (void)performAfterLoading:(dispatch_block_t)actions
    504505{
    505     TestMessageHandler *handler = [[TestMessageHandler alloc] init];
    506     [handler addMessage:@"loaded" withHandler:actions];
    507 
    508     NSString *onloadScript = @"window.onload = () => window.webkit.messageHandlers.onloadHandler.postMessage('loaded')";
    509     WKUserScript *script = [[WKUserScript alloc] initWithSource:onloadScript injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
    510 
    511     WKUserContentController* contentController = [[self configuration] userContentController];
    512     [contentController addUserScript:script];
    513     [contentController addScriptMessageHandler:handler name:@"onloadHandler"];
     506    NSString *const viewDidLoadMessage = @"TestWKWebViewDidLoad";
     507    if (!_onloadScript) {
     508        NSString *onloadScript = [NSString stringWithFormat:@"window.addEventListener('load', () => window.webkit.messageHandlers.testHandler.postMessage('%@'), true /* useCapture */)", viewDidLoadMessage];
     509        _onloadScript = adoptNS([[WKUserScript alloc] initWithSource:onloadScript injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]);
     510        [self.configuration.userContentController addUserScript:_onloadScript.get()];
     511    }
     512    [self performAfterReceivingMessage:viewDidLoadMessage action:actions];
    514513}
    515514
Note: See TracChangeset for help on using the changeset viewer.