Bug 187926 - WKWebView in a modal presentation dismisses its presenting view controller.
Summary: WKWebView in a modal presentation dismisses its presenting view controller.
Status: RESOLVED DUPLICATE of bug 183549
Alias: None
Product: WebKit
Classification: Unclassified
Component: New Bugs (show other bugs)
Version: Safari 11
Hardware: iPhone / iPad iOS 11
: P2 Normal
Assignee: Nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-07-23 14:39 PDT by Tom Harrington
Modified: 2018-07-27 10:32 PDT (History)
3 users (show)

See Also:


Attachments
Demo project reproducing this issue. (95.49 KB, application/zip)
2018-07-23 14:39 PDT, Tom Harrington
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Tom Harrington 2018-07-23 14:39:11 PDT
Created attachment 345609 [details]
Demo project reproducing this issue.

This is similar to:

- https://bugs.webkit.org/show_bug.cgi?id=165225
- https://bugs.webkit.org/show_bug.cgi?id=185257

However it's still present as of iOS 11.4.1. A minimal sample project is attached.

The behavior is:

1. Present a view controller modally which contains a WKWebView.
2. Load a page in the WKWebView that includes an image.
3. Tap and hold on the image until the save/copy/cancel alert appears.
4. Tap "cancel" in the alert.

Expected behavior: The alert would disappear.

Actual behavior: Both the alert and the view controller presented in step 1 are dismissed.

This appears to happen because dismissViewControllerAnimated:completion: is called twice even though only one alert has been displayed.

The backtrace for the first dismiss call is:

(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 4.1
  * frame #0: 0x000000018f006130 UIKit`-[UIViewController dismissViewControllerAnimated:completion:]
    frame #1: 0x000000018f41e1a4 UIKit`__103-[UIAlertController _dismissAnimated:triggeringAction:triggeredByPopoverDimmingView:dismissCompletion:]_block_invoke.465 + 248
    frame #2: 0x000000018f005fb4 UIKit`-[UIAlertController _performAction:invokeActionBlock:dismissAndPerformActionIfNotAlreadyPerformed:] + 124
    frame #3: 0x000000018f005b94 UIKit`-[UIAlertController _dismissAnimated:triggeringAction:triggeredByPopoverDimmingView:dismissCompletion:] + 824
    frame #4: 0x000000018f005848 UIKit`-[UIAlertController _dismissWithAction:dismissCompletion:] + 68
    frame #5: 0x000000018f0056ec UIKit`-[_UIAlertControllerView interfaceAction:invokeActionHandler:completion:] + 256
    frame #6: 0x000000018f005588 UIKit`-[UIInterfaceActionGroupView interfaceAction:invokeActionHandler:completion:] + 120
    frame #7: 0x000000018f005490 UIKit`-[UIInterfaceAction _invokeHandlerWithCompletionBlock:] + 168
    frame #8: 0x000000018efff2d8 UIKit`-[UIInterfaceActionSelectionTrackingController _handleActionSelectionGestureRecognizer:] + 864
    frame #9: 0x000000018effa6e8 UIKit`-[UIGestureRecognizerTarget _sendActionWithGestureRecognizer:] + 64
    frame #10: 0x000000018f5673b4 UIKit`_UIGestureRecognizerSendTargetActions + 124
    frame #11: 0x000000018f15ce38 UIKit`_UIGestureRecognizerSendActions + 320
    frame #12: 0x000000018eff9740 UIKit`-[UIGestureRecognizer _updateGestureWithEvent:buttonEvent:] + 764
    frame #13: 0x000000018f558bd4 UIKit`_UIGestureEnvironmentUpdate + 1096
    frame #14: 0x000000018eff34d8 UIKit`-[UIGestureEnvironment _deliverEvent:toGestureRecognizers:usingBlock:] + 404
    frame #15: 0x000000018eff3010 UIKit`-[UIGestureEnvironment _updateGesturesForEvent:window:] + 276
    frame #16: 0x000000018eff2874 UIKit`-[UIWindow sendEvent:] + 3132
    frame #17: 0x000000018eff11d0 UIKit`-[UIApplication sendEvent:] + 340
    frame #18: 0x000000018f7d2d1c UIKit`__dispatchPreprocessedEventFromEventQueue + 2340
    frame #19: 0x000000018f7d52c8 UIKit`__handleEventQueueInternal + 4744
    frame #20: 0x000000018f7ce368 UIKit`__handleHIDEventFetcherDrain + 152
    frame #21: 0x00000001851b7404 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
    frame #22: 0x00000001851b6c2c CoreFoundation`__CFRunLoopDoSources0 + 276
    frame #23: 0x00000001851b479c CoreFoundation`__CFRunLoopRun + 1204
    frame #24: 0x00000001850d4da8 CoreFoundation`CFRunLoopRunSpecific + 552
    frame #25: 0x00000001870b9020 GraphicsServices`GSEventRunModal + 100
    frame #26: 0x000000018f0f1758 UIKit`UIApplicationMain + 236

The backtrace for the second one is:

(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 4.1
  * frame #0: 0x000000018f006130 UIKit`-[UIViewController dismissViewControllerAnimated:completion:]
    frame #1: 0x000000018f41e1a4 UIKit`__103-[UIAlertController _dismissAnimated:triggeringAction:triggeredByPopoverDimmingView:dismissCompletion:]_block_invoke.465 + 248
    frame #2: 0x000000018f005fb4 UIKit`-[UIAlertController _performAction:invokeActionBlock:dismissAndPerformActionIfNotAlreadyPerformed:] + 124
    frame #3: 0x000000018f005b94 UIKit`-[UIAlertController _dismissAnimated:triggeringAction:triggeredByPopoverDimmingView:dismissCompletion:] + 824
    frame #4: 0x000000018f005848 UIKit`-[UIAlertController _dismissWithAction:dismissCompletion:] + 68
    frame #5: 0x000000018f0056ec UIKit`-[_UIAlertControllerView interfaceAction:invokeActionHandler:completion:] + 256
    frame #6: 0x000000018f005588 UIKit`-[UIInterfaceActionGroupView interfaceAction:invokeActionHandler:completion:] + 120
    frame #7: 0x000000018f005490 UIKit`-[UIInterfaceAction _invokeHandlerWithCompletionBlock:] + 168
    frame #8: 0x000000018efff2d8 UIKit`-[UIInterfaceActionSelectionTrackingController _handleActionSelectionGestureRecognizer:] + 864
    frame #9: 0x000000018effa6e8 UIKit`-[UIGestureRecognizerTarget _sendActionWithGestureRecognizer:] + 64
    frame #10: 0x000000018f5673b4 UIKit`_UIGestureRecognizerSendTargetActions + 124
    frame #11: 0x000000018f15ce38 UIKit`_UIGestureRecognizerSendActions + 320
    frame #12: 0x000000018eff9740 UIKit`-[UIGestureRecognizer _updateGestureWithEvent:buttonEvent:] + 764
    frame #13: 0x000000018f558bd4 UIKit`_UIGestureEnvironmentUpdate + 1096
    frame #14: 0x000000018eff34d8 UIKit`-[UIGestureEnvironment _deliverEvent:toGestureRecognizers:usingBlock:] + 404
    frame #15: 0x000000018eff3010 UIKit`-[UIGestureEnvironment _updateGesturesForEvent:window:] + 276
    frame #16: 0x000000018eff2874 UIKit`-[UIWindow sendEvent:] + 3132
    frame #17: 0x000000018eff11d0 UIKit`-[UIApplication sendEvent:] + 340
    frame #18: 0x000000018f7d2d1c UIKit`__dispatchPreprocessedEventFromEventQueue + 2340
    frame #19: 0x000000018f7d52c8 UIKit`__handleEventQueueInternal + 4744
    frame #20: 0x000000018f7ce368 UIKit`__handleHIDEventFetcherDrain + 152
    frame #21: 0x00000001851b7404 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
    frame #22: 0x00000001851b6c2c CoreFoundation`__CFRunLoopDoSources0 + 276
    frame #23: 0x00000001851b479c CoreFoundation`__CFRunLoopRun + 1204
    frame #24: 0x00000001850d4da8 CoreFoundation`CFRunLoopRunSpecific + 552
    frame #25: 0x00000001870b9020 GraphicsServices`GSEventRunModal + 100
    frame #26: 0x000000018f0f1758 UIKit`UIApplicationMain + 236

When the attached demo app launches, there's a single button labeled "present". Tap this button and then follow the steps described above to reproduce. After tapping "cancel", the initial view controller with the "present" button reappears.
Comment 1 Tom Harrington 2018-07-23 14:44:35 PDT
Sorry, I pasted the same backtrace twice. The second one should be as follows.

(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 4.1
  * frame #0: 0x000000018f006130 UIKit`-[UIViewController dismissViewControllerAnimated:completion:]
    frame #1: 0x0000000194eb2bd8 WebKit`-[WKActionSheet doneWithSheet:] + 56
    frame #2: 0x0000000194eb62a8 WebKit`-[WKActionSheetAssistant cleanupSheet] + 128
    frame #3: 0x000000018f006058 UIKit`-[UIAlertController _invokeHandlersForAction:] + 108
    frame #4: 0x000000018f41dffc UIKit`__103-[UIAlertController _dismissAnimated:triggeringAction:triggeredByPopoverDimmingView:dismissCompletion:]_block_invoke.461 + 28
    frame #5: 0x000000018f012364 UIKit`-[UIPresentationController transitionDidFinish:] + 1320
    frame #6: 0x000000018f2a3c88 UIKit`__56-[UIPresentationController runTransitionForCurrentState]_block_invoke.436 + 188
    frame #7: 0x000000018ee15b88 UIKit`-[_UIViewControllerTransitionContext completeTransition:] + 116
    frame #8: 0x000000018ee15730 UIKit`-[UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:] + 760
    frame #9: 0x000000018ee150b8 UIKit`-[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 312
    frame #10: 0x000000018eefefcc UIKit`-[UIViewAnimationState animationDidStop:finished:] + 296
    frame #11: 0x000000018eeff06c UIKit`-[UIViewAnimationState animationDidStop:finished:] + 456
    frame #12: 0x00000001893a5504 QuartzCore`CA::Layer::run_animation_callbacks(void*) + 284
    frame #13: 0x000000010520d19c libdispatch.dylib`_dispatch_client_callout + 16
    frame #14: 0x0000000105211d2c libdispatch.dylib`_dispatch_main_queue_callback_4CF + 1180
    frame #15: 0x00000001851b7070 CoreFoundation`__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
    frame #16: 0x00000001851b4bc8 CoreFoundation`__CFRunLoopRun + 2272
    frame #17: 0x00000001850d4da8 CoreFoundation`CFRunLoopRunSpecific + 552
    frame #18: 0x00000001870b9020 GraphicsServices`GSEventRunModal + 100
    frame #19: 0x000000018f0f1758 UIKit`UIApplicationMain + 236
Comment 2 Wenson Hsieh 2018-07-27 10:27:05 PDT

*** This bug has been marked as a duplicate of bug 183549 ***
Comment 3 Wenson Hsieh 2018-07-27 10:32:03 PDT
(In reply to Tom Harrington from comment #1)
> Sorry, I pasted the same backtrace twice. The second one should be as
> follows.
> 
> (lldb) bt
> * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 4.1
>   * frame #0: 0x000000018f006130 UIKit`-[UIViewController
> dismissViewControllerAnimated:completion:]
>     frame #1: 0x0000000194eb2bd8 WebKit`-[WKActionSheet doneWithSheet:] + 56
>     frame #2: 0x0000000194eb62a8 WebKit`-[WKActionSheetAssistant
> cleanupSheet] + 128
>     frame #3: 0x000000018f006058 UIKit`-[UIAlertController
> _invokeHandlersForAction:] + 108
>     frame #4: 0x000000018f41dffc UIKit`__103-[UIAlertController
> _dismissAnimated:triggeringAction:triggeredByPopoverDimmingView:
> dismissCompletion:]_block_invoke.461 + 28
>     frame #5: 0x000000018f012364 UIKit`-[UIPresentationController
> transitionDidFinish:] + 1320
>     frame #6: 0x000000018f2a3c88 UIKit`__56-[UIPresentationController
> runTransitionForCurrentState]_block_invoke.436 + 188
>     frame #7: 0x000000018ee15b88 UIKit`-[_UIViewControllerTransitionContext
> completeTransition:] + 116
>     frame #8: 0x000000018ee15730 UIKit`-[UIViewAnimationBlockDelegate
> _didEndBlockAnimation:finished:context:] + 760
>     frame #9: 0x000000018ee150b8 UIKit`-[UIViewAnimationState
> sendDelegateAnimationDidStop:finished:] + 312
>     frame #10: 0x000000018eefefcc UIKit`-[UIViewAnimationState
> animationDidStop:finished:] + 296
>     frame #11: 0x000000018eeff06c UIKit`-[UIViewAnimationState
> animationDidStop:finished:] + 456
>     frame #12: 0x00000001893a5504
> QuartzCore`CA::Layer::run_animation_callbacks(void*) + 284
>     frame #13: 0x000000010520d19c libdispatch.dylib`_dispatch_client_callout
> + 16
>     frame #14: 0x0000000105211d2c
> libdispatch.dylib`_dispatch_main_queue_callback_4CF + 1180
>     frame #15: 0x00000001851b7070
> CoreFoundation`__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
>     frame #16: 0x00000001851b4bc8 CoreFoundation`__CFRunLoopRun + 2272
>     frame #17: 0x00000001850d4da8 CoreFoundation`CFRunLoopRunSpecific + 552
>     frame #18: 0x00000001870b9020 GraphicsServices`GSEventRunModal + 100
>     frame #19: 0x000000018f0f1758 UIKit`UIApplicationMain + 236

Thanks for the information and test app, Tom!

I believe I've fixed this in <https://bugs.webkit.org/show_bug.cgi?id=183549>, which first went into iOS 12. I installed the test app (DismissDemo) on my build of iOS 12, and could not reproduce; could you verify on any beta version of iOS 12?