⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 288039 in webkit


Ignore:
Timestamp:
Jan 14, 2022, 4:56:22 PM (5 years ago)
Author:
Wenson Hsieh
Message:

[iOS] Occasional crash under -[UITargetedPreview initWithView:parameters:target:] when focusing form controls
​https://bugs.webkit.org/show_bug.cgi?id=235248
rdar://79220540

Reviewed by Tim Horton and Aditya Keerthi.

Source/WebKit:

It's possible for -resizableSnapshotViewFromRect:afterScreenUpdates:withCapInsets: to return a nil snapshot
view in the case where a screen update has not been performed yet (among other scenarios). In the case where
UIKit returns nil when we're creating the targeted preview for the context menu when focusing a select element
or file input, we'll crash due to an Objective-C exception in the initializer of UITargetedPreview. Mitigate
this by falling back to an empty UIView after requesting the snapshot view to make our code robust against this
scenario.

Test: KeyboardInputTests.DoNotCrashWhenFocusingSelectWithoutViewSnapshot

  • UIProcess/ios/WKContentViewInteraction.mm:

(createFallbackTargetedPreview):

Tools:

Add an API test that exercises the crash by forcing -resizableSnapshotViewFromRect:afterScreenUpdates:withCapInsets:
to return nil via swizzling.

  • TestWebKitAPI/Tests/ios/KeyboardInputTestsIOS.mm:

(TestWebKitAPI::nilResizableSnapshotViewFromRect):
(TestWebKitAPI::TEST):

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r288034 r288039  
     12022-01-14  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [iOS] Occasional crash under -[UITargetedPreview initWithView:parameters:target:] when focusing form controls
     4        https://bugs.webkit.org/show_bug.cgi?id=235248
     5        rdar://79220540
     6
     7        Reviewed by Tim Horton and Aditya Keerthi.
     8
     9        It's possible for `-resizableSnapshotViewFromRect:afterScreenUpdates:withCapInsets:` to return a `nil` snapshot
     10        view in the case where a screen update has not been performed yet (among other scenarios). In the case where
     11        UIKit returns `nil` when we're creating the targeted preview for the context menu when focusing a select element
     12        or file input, we'll crash due to an Objective-C exception in the initializer of UITargetedPreview. Mitigate
     13        this by falling back to an empty UIView after requesting the snapshot view to make our code robust against this
     14        scenario.
     15
     16        Test: KeyboardInputTests.DoNotCrashWhenFocusingSelectWithoutViewSnapshot
     17
     18        * UIProcess/ios/WKContentViewInteraction.mm:
     19        (createFallbackTargetedPreview):
     20
    1212022-01-14  Dean Jackson  <dino@apple.com>
    222
  • trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm

    r288032 r288039  
    86478647        [parameters setBackgroundColor:backgroundColor];
    86488648
    8649     UIView *snapshotView = [rootView resizableSnapshotViewFromRect:frameInRootViewCoordinates afterScreenUpdates:NO withCapInsets:UIEdgeInsetsZero];
     8649    RetainPtr snapshotView = [rootView resizableSnapshotViewFromRect:frameInRootViewCoordinates afterScreenUpdates:NO withCapInsets:UIEdgeInsetsZero];
     8650    if (!snapshotView)
     8651        snapshotView = adoptNS([UIView new]);
    86508652
    86518653    CGRect frameInContainerViewCoordinates = [rootView convertRect:frameInRootViewCoordinates toView:containerView];
    … …  
    86548656        return nil;
    86558657
    8656     snapshotView.frame = frameInContainerViewCoordinates;
     8658    [snapshotView setFrame:frameInContainerViewCoordinates];
    86578659
    86588660    CGPoint centerInContainerViewCoordinates = CGPointMake(CGRectGetMidX(frameInContainerViewCoordinates), CGRectGetMidY(frameInContainerViewCoordinates));
    86598661    auto target = adoptNS([[UIPreviewTarget alloc] initWithContainer:containerView center:centerInContainerViewCoordinates]);
    86608662
    8661     return adoptNS([[UITargetedPreview alloc] initWithView:snapshotView parameters:parameters.get() target:target.get()]);
     8663    return adoptNS([[UITargetedPreview alloc] initWithView:snapshotView.get() parameters:parameters.get() target:target.get()]);
    86628664}
    86638665
  • trunk/Tools/ChangeLog

    r288038 r288039  
     12022-01-14  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [iOS] Occasional crash under -[UITargetedPreview initWithView:parameters:target:] when focusing form controls
     4        https://bugs.webkit.org/show_bug.cgi?id=235248
     5        rdar://79220540
     6
     7        Reviewed by Tim Horton and Aditya Keerthi.
     8
     9        Add an API test that exercises the crash by forcing `-resizableSnapshotViewFromRect:afterScreenUpdates:withCapInsets:`
     10        to return nil via swizzling.
     11
     12        * TestWebKitAPI/Tests/ios/KeyboardInputTestsIOS.mm:
     13        (TestWebKitAPI::nilResizableSnapshotViewFromRect):
     14        (TestWebKitAPI::TEST):
     15
    1162022-01-07  Jonathan Bedard  <jbedard@apple.com>
    217
  • trunk/Tools/TestWebKitAPI/Tests/ios/KeyboardInputTestsIOS.mm

    r286552 r288039  
    827827}
    828828
     829static UIView * nilResizableSnapshotViewFromRect(id, SEL, CGRect, BOOL, UIEdgeInsets)
     830{
     831    return nil;
     832}
     833
     834TEST(KeyboardInputTests, DoNotCrashWhenFocusingSelectWithoutViewSnapshot)
     835{
     836    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
     837    auto delegate = adoptNS([TestInputDelegate new]);
     838    [webView _setInputDelegate:delegate.get()];
     839    [delegate setFocusStartsInputSessionPolicyHandler:[](WKWebView *, id <_WKFocusedElementInfo>) {
     840        return _WKFocusStartsInputSessionPolicyAllow;
     841    }];
     842
     843    [webView synchronouslyLoadHTMLString:@"<select id='select'><option>foo</option><option>bar</option></select>"];
     844
     845    InstanceMethodSwizzler swizzler { UIView.class, @selector(resizableSnapshotViewFromRect:afterScreenUpdates:withCapInsets:), reinterpret_cast<IMP>(nilResizableSnapshotViewFromRect) };
     846    [webView stringByEvaluatingJavaScript:@"select.focus()"];
     847    [webView waitForNextPresentationUpdate];
     848}
     849
    829850} // namespace TestWebKitAPI
    830851
Note: See TracChangeset for help on using the changeset viewer.