Changeset 240301 in webkit
- Timestamp:
- Jan 22, 2019 3:21:45 PM (5 years ago)
- Location:
- trunk/Tools
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Tools/ChangeLog
r240299 r240301 1 2019-01-22 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [iOS] Multiple WKWebViewAutofillTests are flaky failures 4 https://bugs.webkit.org/show_bug.cgi?id=189165 5 <rdar://problem/47433765> 6 7 Reviewed by Tim Horton. 8 9 These tests are currently flaky because they expect an invocation of "Element.blur()" in the web process to 10 immediately dispatch an IPC message to notify the UI process that the element has been blurred. In particular, 11 the -textInputHasAutofillContext helper assumes that waiting for the next remote layer tree commit in the UI 12 process in sufficient to ensure that any previous action that blurred the focused element in the web process 13 would make its way to the UI process by the time the layer tree commit is finished. 14 15 However, WebPage::elementDidBlur sends its IPC message to the UI process asynchronously, using callOnMainThread. 16 This means that if a layer tree flush was already scheduled in the web process before the element was blurred, 17 the element blur IPC message to the UI process will lose the race against the layer tree commit, and the test 18 will fail because it asks for -_autofillContext too early. 19 20 To fix this, we tweak these tests to actually wait until the intended input session change triggered by script 21 is handled in the UI process. 22 23 * TestWebKitAPI/Tests/ios/WKWebViewAutofillTests.mm: 24 25 Tweak some of these tests to wait for input session changes before checking for the presence of an autofill 26 context. The only exception is an existing test that doesn't allow programmatic focus to begin input sessions 27 by default; to fix this test, we simply wait for _WKInputDelegate to be invoked, instead of waiting for a new 28 input session. 29 30 (-[AutofillTestView textInputHasAutofillContext]): 31 32 Remove the incorrect presentation update here. This helper now assumes that the UI process is up to date. 33 34 * TestWebKitAPI/cocoa/TestWKWebView.h: 35 * TestWebKitAPI/cocoa/TestWKWebView.mm: 36 (nextInputSessionChangeCount): 37 38 Monotonically increasing identifier that's incremented whenever an input session is started in the UI process. 39 This includes changing the focused element from one to another. 40 41 (-[TestWKWebView initWithFrame:configuration:addToWindow:]): 42 (-[TestWKWebView didStartFormControlInteraction]): 43 (-[TestWKWebView didEndFormControlInteraction]): 44 (-[TestWKWebView evaluateJavaScriptAndWaitForInputSessionToChange:]): 45 46 Add a helper to evaluate JavaScript and wait for this script to cause some change in the input session. This 47 handles three cases: (1) changing focus from an element that doesn't require an input session to one that does, 48 (2) changing focus between elements that require input sessions, and (3) changing focus from an input session 49 that doesn't require an input session to one that doesn't. 50 1 51 2019-01-22 David Kilzer <ddkilzer@apple.com> 2 52 -
trunk/Tools/TestWebKitAPI/Tests/ios/WKWebViewAutofillTests.mm
r237266 r240301 65 65 - (BOOL)textInputHasAutofillContext 66 66 { 67 [self waitForNextPresentationUpdate];68 67 NSURL *url = [self._autofillInputView._autofillContext objectForKey:@"_WebViewURL"]; 69 68 if (![url isKindOfClass:[NSURL class]]) … … 82 81 auto webView = adoptNS([[AutofillTestView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); 83 82 [webView synchronouslyLoadHTMLString:@"<input id='user' type='email'><input id='password' type='password'>"]; 84 [webView stringByEvaluatingJavaScript:@"user.focus()"];83 [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"user.focus()"]; 85 84 EXPECT_TRUE([webView textInputHasAutofillContext]); 86 85 87 [webView stringByEvaluatingJavaScript:@"password.focus()"];86 [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"password.focus()"]; 88 87 EXPECT_TRUE([webView textInputHasAutofillContext]); 89 88 … … 93 92 EXPECT_WK_STREQ("famos", [webView stringByEvaluatingJavaScript:@"password.value"]); 94 93 95 [webView stringByEvaluatingJavaScript:@"document.activeElement.blur()"];94 [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.activeElement.blur()"]; 96 95 EXPECT_FALSE([webView textInputHasAutofillContext]); 97 96 } … … 101 100 auto webView = adoptNS([[AutofillTestView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); 102 101 [webView synchronouslyLoadHTMLString:@"<input id='user' type='email'><input type='radio' name='radio_button' value='radio'><input id='password' type='password'>"]; 103 [webView stringByEvaluatingJavaScript:@"user.focus()"];102 [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"user.focus()"]; 104 103 EXPECT_TRUE([webView textInputHasAutofillContext]); 105 104 106 [webView stringByEvaluatingJavaScript:@"password.focus()"];105 [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"password.focus()"]; 107 106 EXPECT_TRUE([webView textInputHasAutofillContext]); 108 107 … … 113 112 EXPECT_WK_STREQ("famos", [webView stringByEvaluatingJavaScript:@"password.value"]); 114 113 115 [webView stringByEvaluatingJavaScript:@"document.activeElement.blur()"];114 [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.activeElement.blur()"]; 116 115 EXPECT_FALSE([webView textInputHasAutofillContext]); 117 116 } … … 121 120 auto webView = adoptNS([[AutofillTestView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); 122 121 [webView synchronouslyLoadHTMLString:@"<input id='text1' type='email'><input id='text2' type='text'>"]; 123 [webView stringByEvaluatingJavaScript:@"text1.focus()"];122 [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"text1.focus()"]; 124 123 EXPECT_FALSE([webView textInputHasAutofillContext]); 125 124 126 [webView stringByEvaluatingJavaScript:@"text2.focus()"];125 [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"text2.focus()"]; 127 126 EXPECT_FALSE([webView textInputHasAutofillContext]); 128 127 } … … 132 131 auto webView = adoptNS([[AutofillTestView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); 133 132 [webView synchronouslyLoadHTMLString:@"<input id='password' type='password'>"]; 134 [webView stringByEvaluatingJavaScript:@"password.focus()"];133 [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"password.focus()"]; 135 134 EXPECT_TRUE([webView textInputHasAutofillContext]); 136 135 … … 140 139 EXPECT_WK_STREQ("famos", [webView stringByEvaluatingJavaScript:@"password.value"]); 141 140 142 [webView stringByEvaluatingJavaScript:@"document.activeElement.blur()"];141 [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.activeElement.blur()"]; 143 142 EXPECT_FALSE([webView textInputHasAutofillContext]); 144 143 } … … 148 147 auto webView = adoptNS([[AutofillTestView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); 149 148 [webView synchronouslyLoadHTMLString:@"<input id='textfield' type='text'>"]; 150 [webView stringByEvaluatingJavaScript:@"textfield.focus()"];149 [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"textfield.focus()"]; 151 150 EXPECT_FALSE([webView textInputHasAutofillContext]); 152 151 } … … 156 155 auto webView = adoptNS([[AutofillTestView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); 157 156 [webView synchronouslyLoadHTMLString:@"<input id='user' type='email'><input id='password' type='password'><input id='confirm_password' type='password'>"]; 158 [webView stringByEvaluatingJavaScript:@"user.focus()"];157 [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"user.focus()"]; 159 158 EXPECT_FALSE([webView textInputHasAutofillContext]); 160 159 161 [webView stringByEvaluatingJavaScript:@"password.focus()"];160 [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"password.focus()"]; 162 161 EXPECT_FALSE([webView textInputHasAutofillContext]); 163 162 164 [webView stringByEvaluatingJavaScript:@"confirm_password.focus()"];163 [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"confirm_password.focus()"]; 165 164 EXPECT_FALSE([webView textInputHasAutofillContext]); 166 165 } … … 175 174 ClassMethodSwizzler swizzler([UIKeyboard class], @selector(isInHardwareKeyboardMode), reinterpret_cast<IMP>(overrideIsInHardwareKeyboardMode)); 176 175 176 bool done = false; 177 177 auto webView = adoptNS([[AutofillTestView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); 178 [(TestInputDelegate *)[webView _inputDelegate] setFocusStartsInputSessionPolicyHandler:[] (WKWebView *, id <_WKFocusedElementInfo>) -> _WKFocusStartsInputSessionPolicy { 178 [(TestInputDelegate *)[webView _inputDelegate] setFocusStartsInputSessionPolicyHandler:[&done] (WKWebView *, id <_WKFocusedElementInfo>) -> _WKFocusStartsInputSessionPolicy { 179 done = true; 179 180 return _WKFocusStartsInputSessionPolicyAuto; 180 181 }]; 181 182 [webView synchronouslyLoadHTMLString:@"<input id='user' type='email'><input id='password' type='password'>"]; 182 183 [webView stringByEvaluatingJavaScript:@"user.focus()"]; 184 Util::run(&done); 183 185 184 186 EXPECT_FALSE([webView textInputHasAutofillContext]); -
trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h
r238471 r240301 88 88 @property (nonatomic, readonly) NSArray<NSValue *> *selectionViewRectsInContentCoordinates; 89 89 - (_WKActivatedElementInfo *)activatedElementAtPosition:(CGPoint)position; 90 - (void)evaluateJavaScriptAndWaitForInputSessionToChange:(NSString *)script; 90 91 @end 91 92 #endif -
trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm
r238921 r240301 250 250 @end 251 251 252 #if PLATFORM(IOS_FAMILY) 253 254 using InputSessionChangeCount = NSUInteger; 255 static InputSessionChangeCount nextInputSessionChangeCount() 256 { 257 static InputSessionChangeCount gInputSessionChangeCount = 0; 258 return ++gInputSessionChangeCount; 259 } 260 261 #endif 262 252 263 @implementation TestWKWebView { 253 264 RetainPtr<TestWKWebViewHostWindow> _hostWindow; … … 255 266 #if PLATFORM(IOS_FAMILY) 256 267 std::unique_ptr<ClassMethodSwizzler> _sharedCalloutBarSwizzler; 268 InputSessionChangeCount _inputSessionChangeCount; 257 269 #endif 258 270 } … … 290 302 // FIXME: Remove this workaround once <https://webkit.org/b/175204> is fixed. 291 303 _sharedCalloutBarSwizzler = std::make_unique<ClassMethodSwizzler>([UICalloutBar class], @selector(sharedCalloutBar), reinterpret_cast<IMP>(suppressUICalloutBar)); 304 _inputSessionChangeCount = 0; 292 305 #endif 293 306 … … 410 423 } 411 424 425 #if PLATFORM(IOS_FAMILY) 426 427 - (void)didStartFormControlInteraction 428 { 429 _inputSessionChangeCount = nextInputSessionChangeCount(); 430 } 431 432 - (void)didEndFormControlInteraction 433 { 434 _inputSessionChangeCount = 0; 435 } 436 437 #endif // PLATFORM(IOS_FAMILY) 438 412 439 @end 413 440 … … 415 442 416 443 @implementation TestWKWebView (IOSOnly) 444 445 - (void)evaluateJavaScriptAndWaitForInputSessionToChange:(NSString *)script 446 { 447 auto initialChangeCount = _inputSessionChangeCount; 448 BOOL hasEmittedWarning = NO; 449 NSTimeInterval secondsToWaitUntilWarning = 2; 450 NSTimeInterval startTime = [NSDate timeIntervalSinceReferenceDate]; 451 452 [self objectByEvaluatingJavaScript:script]; 453 while ([[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantPast]]) { 454 if (_inputSessionChangeCount != initialChangeCount) 455 break; 456 457 if (hasEmittedWarning || startTime + secondsToWaitUntilWarning >= [NSDate timeIntervalSinceReferenceDate]) 458 continue; 459 460 NSLog(@"Warning: expecting input session change count to differ from %tu", initialChangeCount); 461 hasEmittedWarning = YES; 462 } 463 } 417 464 418 465 - (UIView <UITextInputPrivate, UITextInputMultiDocument> *)textInputContentView
Note: See TracChangeset
for help on using the changeset viewer.