Adopt the new UIAlertController API to replace UIActionSheet.
authorenrica@apple.com <enrica@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 6 Jun 2014 22:06:25 +0000 (22:06 +0000)
committerenrica@apple.com <enrica@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 6 Jun 2014 22:06:25 +0000 (22:06 +0000)
https://bugs.webkit.org/show_bug.cgi?id=133582
<rdar://problem/16845223>

Reviewed by Joseph Pecoraro.

UIActionSheet is deprecated. We need to move out action sheets
implementation to UIAlertView.

* UIProcess/API/Cocoa/_WKElementAction.h:
* UIProcess/API/Cocoa/_WKElementAction.mm:
* UIProcess/ios/WKActionSheet.h:
* UIProcess/ios/WKActionSheet.mm:
(-[WKActionSheet presentSheetFromRect:]):
(-[WKActionSheet doneWithSheet]):
(-[WKActionSheet willRotate]):
(-[WKActionSheet updateSheetPosition]):
(-[WKActionSheet _didRotateAndLayout]):
(-[WKActionSheet didRotate]):
* UIProcess/ios/WKActionSheetAssistant.h:
* UIProcess/ios/WKActionSheetAssistant.mm:
(-[WKActionSheetAssistant _createSheetWithElementActions:showLinkTitle:]):
(-[WKActionSheetAssistant showImageSheet]):
(-[WKActionSheetAssistant showLinkSheet]):
(-[WKActionSheetAssistant showDataDetectorsSheet]):
(-[WKActionSheetAssistant cleanupSheet]):
(-[WKActionSheetAssistant actionSheet:clickedButtonAtIndex:]): Deleted.
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _longPressRecognized:]):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@169664 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/API/Cocoa/_WKElementAction.h
Source/WebKit2/UIProcess/API/Cocoa/_WKElementAction.mm
Source/WebKit2/UIProcess/ios/WKActionSheet.h
Source/WebKit2/UIProcess/ios/WKActionSheet.mm
Source/WebKit2/UIProcess/ios/WKActionSheetAssistant.h
Source/WebKit2/UIProcess/ios/WKActionSheetAssistant.mm
Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm

index 3574742..17e672e 100644 (file)
@@ -1,3 +1,35 @@
+2014-06-06  Enrica Casucci  <enrica@apple.com>
+
+        Adopt the new UIAlertController API to replace UIActionSheet.
+        https://bugs.webkit.org/show_bug.cgi?id=133582
+        <rdar://problem/16845223>
+
+        Reviewed by Joseph Pecoraro.
+
+        UIActionSheet is deprecated. We need to move out action sheets
+        implementation to UIAlertView.
+
+        * UIProcess/API/Cocoa/_WKElementAction.h:
+        * UIProcess/API/Cocoa/_WKElementAction.mm:
+        * UIProcess/ios/WKActionSheet.h:
+        * UIProcess/ios/WKActionSheet.mm:
+        (-[WKActionSheet presentSheetFromRect:]):
+        (-[WKActionSheet doneWithSheet]):
+        (-[WKActionSheet willRotate]):
+        (-[WKActionSheet updateSheetPosition]):
+        (-[WKActionSheet _didRotateAndLayout]):
+        (-[WKActionSheet didRotate]):
+        * UIProcess/ios/WKActionSheetAssistant.h:
+        * UIProcess/ios/WKActionSheetAssistant.mm:
+        (-[WKActionSheetAssistant _createSheetWithElementActions:showLinkTitle:]):
+        (-[WKActionSheetAssistant showImageSheet]):
+        (-[WKActionSheetAssistant showLinkSheet]):
+        (-[WKActionSheetAssistant showDataDetectorsSheet]):
+        (-[WKActionSheetAssistant cleanupSheet]):
+        (-[WKActionSheetAssistant actionSheet:clickedButtonAtIndex:]): Deleted.
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView _longPressRecognized:]):
+
 2014-06-06  Gavin Barraclough  <baraclough@apple.com>
 
         Should boost ChildProcesses on iOS
 2014-06-06  Gavin Barraclough  <baraclough@apple.com>
 
         Should boost ChildProcesses on iOS
index 7e3a35d..8f2816c 100644 (file)
@@ -32,6 +32,7 @@
 #import <WebKit/_WKActivatedElementInfo.h>
 
 typedef void (^WKElementActionHandler)(_WKActivatedElementInfo *);
 #import <WebKit/_WKActivatedElementInfo.h>
 
 typedef void (^WKElementActionHandler)(_WKActivatedElementInfo *);
+typedef BOOL (^WKElementActionDismissalHandler)(void);
 
 typedef NS_ENUM(NSInteger, _WKElementActionType) {
     _WKElementActionTypeCustom,
 
 typedef NS_ENUM(NSInteger, _WKElementActionType) {
     _WKElementActionTypeCustom,
@@ -51,6 +52,7 @@ WK_CLASS_AVAILABLE(10_10, 8_0)
 
 @property (nonatomic, readonly) _WKElementActionType type;
 @property (nonatomic, readonly) NSString* title;
 
 @property (nonatomic, readonly) _WKElementActionType type;
 @property (nonatomic, readonly) NSString* title;
+@property (nonatomic, copy) WKElementActionDismissalHandler dismissalHandler;
 
 @end
 
 
 @end
 
index f49d7bb..37c5fc1 100644 (file)
@@ -47,6 +47,7 @@ typedef void (^WKElementActionHandlerInternal)(WKContentView *, _WKActivatedElem
 @implementation _WKElementAction  {
     RetainPtr<NSString> _title;
     WKElementActionHandlerInternal _actionHandler;
 @implementation _WKElementAction  {
     RetainPtr<NSString> _title;
     WKElementActionHandlerInternal _actionHandler;
+    WKElementActionDismissalHandler _dismissalHandler;
 }
 
 - (id)_initWithTitle:(NSString *)title actionHandler:(WKElementActionHandlerInternal)handler type:(_WKElementActionType)type
 }
 
 - (id)_initWithTitle:(NSString *)title actionHandler:(WKElementActionHandlerInternal)handler type:(_WKElementActionType)type
@@ -63,6 +64,7 @@ typedef void (^WKElementActionHandlerInternal)(WKContentView *, _WKActivatedElem
 - (void)dealloc
 {
     [_actionHandler release];
 - (void)dealloc
 {
     [_actionHandler release];
+    [_dismissalHandler release];
 
     [super dealloc];
 }
 
     [super dealloc];
 }
index ae608e4..1249f2a 100644 (file)
 
 #if PLATFORM(IOS)
 
 
 #if PLATFORM(IOS)
 
-#import <UIKit/UIActionSheet.h>
+#import <UIKit/UIAlertController.h>
 #import <UIKit/UIPopoverController.h>
 
 @protocol WKActionSheetDelegate;
 @class WKContentView;
 
 #import <UIKit/UIPopoverController.h>
 
 @protocol WKActionSheetDelegate;
 @class WKContentView;
 
-@interface WKActionSheet : UIActionSheet
+@interface WKActionSheet : UIAlertController
 
 @property (nonatomic, assign) id <WKActionSheetDelegate> sheetDelegate;
 @property (nonatomic) UIPopoverArrowDirection arrowDirections;
 
 @property (nonatomic, assign) id <WKActionSheetDelegate> sheetDelegate;
 @property (nonatomic) UIPopoverArrowDirection arrowDirections;
@@ -42,7 +42,7 @@
 - (void)updateSheetPosition;
 @end
 
 - (void)updateSheetPosition;
 @end
 
-@protocol WKActionSheetDelegate<UIActionSheetDelegate>
+@protocol WKActionSheetDelegate
 @required
 - (UIView *)hostViewForSheet;
 - (CGRect)initialPresentationRectInHostViewForSheet;
 @required
 - (UIView *)hostViewForSheet;
 - (CGRect)initialPresentationRectInHostViewForSheet;
index 4548ef4..bd8b7b6 100644 (file)
 #if PLATFORM(IOS)
 
 #import "WKContentViewInteraction.h"
 #if PLATFORM(IOS)
 
 #import "WKContentViewInteraction.h"
-#import <UIKit/UIActionSheet_Private.h>
+#import <UIKit/UIAlertController_Private.h>
 #import <UIKit/UIWindow_Private.h>
 
 @implementation WKActionSheet {
     id <WKActionSheetDelegate> _sheetDelegate;
 #import <UIKit/UIWindow_Private.h>
 
 @implementation WKActionSheet {
     id <WKActionSheetDelegate> _sheetDelegate;
-    id <UIActionSheetDelegate> _delegateWhileRotating;
     WKContentView *_view;
     UIPopoverArrowDirection _arrowDirections;
     BOOL _isRotating;
     WKContentView *_view;
     UIPopoverArrowDirection _arrowDirections;
     BOOL _isRotating;
+    BOOL _readyToPresentAfterRotation;
+
+    RetainPtr<UIViewController> _presentedViewControllerWhileRotating;
+    RetainPtr<id <UIPopoverPresentationControllerDelegate>> _popoverPresentationControllerDelegateWhileRotating;
 }
 
 - (id)initWithView:(WKContentView *)view
 }
 
 - (id)initWithView:(WKContentView *)view
     if (!view)
         return NO;
 
     if (!view)
         return NO;
 
-    if (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPhone) {
-        [self presentFromRect:presentationRect
-                       inView:view
-                    direction:_arrowDirections
-    allowInteractionWithViews:nil
-              backgroundStyle:UIPopoverBackgroundStyleDefault
-                     animated:YES];
-    } else
-        [self showInView:view]; 
+    UIViewController *presentedViewController = _presentedViewControllerWhileRotating.get() ? _presentedViewControllerWhileRotating.get() : self;
+    presentedViewController.modalPresentationStyle = UIModalPresentationPopover;
+
+    UIPopoverPresentationController *presentationController = presentedViewController.popoverPresentationController;
+    presentationController.sourceView = view;
+    presentationController.sourceRect = presentationRect;
+    presentationController.permittedArrowDirections = _arrowDirections;
+
+    if (_popoverPresentationControllerDelegateWhileRotating)
+        presentationController.delegate = _popoverPresentationControllerDelegateWhileRotating.get();
+
+    UIViewController *presentingViewController = [view.window rootViewController];
+    [presentingViewController presentViewController:presentedViewController animated:YES completion:NULL];
 
     return YES;
 }
 
 - (void)doneWithSheet
 {
 
     return YES;
 }
 
 - (void)doneWithSheet
 {
-    _delegateWhileRotating = nil;
+    _presentedViewControllerWhileRotating = nil;
+    _popoverPresentationControllerDelegateWhileRotating = nil;
 
 
-    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(didRotate) object:nil];
+    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_didRotateAndLayout) object:nil];
 }
 
 #pragma mark - Rotation handling code
 
 - (void)willRotate
 {
 }
 
 #pragma mark - Rotation handling code
 
 - (void)willRotate
 {
-    ASSERT(UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPhone);
+    // We want to save the view controller that is currently being presented to re-present it after rotation.
+    // Here are the various possible states that we have to handle:
+    // a) topViewController presenting ourselves (alertViewController) -> nominal case.
+    //    There is no need to save the presented view controller, which is self.
+    // b) topViewController presenting ourselves presenting a content view controller ->
+    //    This happens if one of the actions in the action sheet presented a different view controller inside the popover,
+    //    using a current context presentation. This is for example the case with the Data Detectors action "Add to Contacts".
+    // c) topViewController presenting that content view controller directly.
+    //    This happens if we were in the (b) case and then rotated the device. Since we dismiss the popover during the
+    //    rotation, we take this opportunity to simplify the view controller hierarchy and simply re-present the content
+    //    view controller, without re-presenting the alert controller.
+
+    UIView *view = [_sheetDelegate hostViewForSheet];
+    UIViewController *presentingViewController = view.window.rootViewController;
+
+    // topPresentedViewController is either self (cases (a) and (b) above) or an action's view controller
+    // (case (c) above).
+    UIViewController *topPresentedViewController = [presentingViewController presentedViewController];
+
+    // We only have something to do if we're showing a popover (that we have to reposition).
+    // Otherwise the default UIAlertController behaviour is enough.
+    if ([topPresentedViewController presentationController].presentationStyle != UIModalPresentationPopover)
+        return;
 
     if (_isRotating)
         return;
 
 
     if (_isRotating)
         return;
 
-    // Clear the delegate so that the method:
-    // - (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
-    // is not called when the ActionSheet is dismissed below. Delegate is re-instated after rotation.
-    _delegateWhileRotating = [self delegate];
-    self.delegate = nil;
     _isRotating = YES;
     _isRotating = YES;
+    _readyToPresentAfterRotation = NO;
+
+    UIViewController *presentedViewController = nil;
+    if ([self presentingViewController] != nil) {
+        // Handle cases (a) and (b) above (we (UIAlertController) are still in the presentation hierarchy).
+        // Save the view controller presented by one of the actions if there is one.
+        // (In the (a) case, presentedViewController will be nil).
+
+        presentedViewController = [self presentedViewController];
+    } else {
+        // Handle case (c) above.
+        // The view controller that we want to save is the top presented view controller, since we
+        // are not presenting it anymore.
+
+        presentedViewController = topPresentedViewController;
+    }
 
 
-    [self dismissWithClickedButtonIndex:[self cancelButtonIndex] animated:NO];
+    _presentedViewControllerWhileRotating = presentedViewController;
+
+    // Save the popover presentation controller's delegate, because in case (b) we're going to use
+    // a different popoverPresentationController after rotation to re-present the action view controller,
+    // and that action is still expecting delegate callbacks when the popover is dismissed.
+    _popoverPresentationControllerDelegateWhileRotating = [topPresentedViewController popoverPresentationController].delegate;
+
+    [presentingViewController dismissViewControllerAnimated:NO completion:^{
+        [self updateSheetPosition];
+    }];
 }
 
 - (void)updateSheetPosition
 {
 }
 
 - (void)updateSheetPosition
 {
-    ASSERT(UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPhone);
+    UIViewController *presentedViewController = _presentedViewControllerWhileRotating.get() ? _presentedViewControllerWhileRotating.get() : self;
+
+    // There are two asynchronous events which might trigger this call, and we have to wait for both of them before doing something.
+    // - One runloop iteration after rotation (to let the Web content re-layout, see below)
+    // - The completion of the view controller dismissal in willRotate.
+    // (We cannot present something again until the dismissal is done)
+
+    BOOL isBeingPresented = [presentedViewController presentingViewController] || [self presentingViewController];
 
 
-    if (!_isRotating)
+    if (!_isRotating || !_readyToPresentAfterRotation || isBeingPresented)
         return;
 
         return;
 
-    _isRotating = NO;
-    
-    CGRect presentationRect = [_sheetDelegate presentationRectInHostViewForSheet];
-    if (!CGRectIsEmpty(presentationRect)) {
-        // Re-present the popover only if we are still pointing to content onscreen.
+    CGRect presentationRect = [_sheetDelegate initialPresentationRectInHostViewForSheet];
+    BOOL wasPresentedViewControllerModal = [_presentedViewControllerWhileRotating isModalInPopover];
+
+    if (!CGRectIsEmpty(presentationRect) || wasPresentedViewControllerModal) {
+        // Re-present the popover only if we are still pointing to content onscreen, or if we can't dismiss it without losing information.
+        // (if the view controller is modal)
+
         CGRect intersection = CGRectIntersection([[_sheetDelegate hostViewForSheet] bounds], presentationRect);
         CGRect intersection = CGRectIntersection([[_sheetDelegate hostViewForSheet] bounds], presentationRect);
-        if (!CGRectIsEmpty(intersection)) {
-            self.delegate = _delegateWhileRotating;
+        if (!CGRectIsEmpty(intersection))
             [self presentSheetFromRect:intersection];
             [self presentSheetFromRect:intersection];
-            return;
-        }
+        else if (wasPresentedViewControllerModal)
+            [self presentSheet];
+
+        _presentedViewControllerWhileRotating = nil;
+        _popoverPresentationControllerDelegateWhileRotating = nil;
     }
     }
-    
-    // Cancel the sheet as there is either no view or the content has now moved off screen.
-    [_delegateWhileRotating actionSheet:self clickedButtonAtIndex:[self cancelButtonIndex]];
+}
+
+- (void)_didRotateAndLayout
+{
+    _isRotating = NO;
+    _readyToPresentAfterRotation = YES;
+    [_view _updatePositionInformation];
+    [self updateSheetPosition];
 }
 
 - (void)didRotate
 {
 }
 
 - (void)didRotate
 {
-    ASSERT(UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPhone);
+    // Handle the rotation on the next run loop interation as this
+    // allows the onOrientationChange event to fire, and the element node may
+    // be removed.
+    // <rdar://problem/9360929> Should re-present popover after layout rather than on the next runloop
 
 
-    [_view _updatePositionInformation];
+    [self performSelector:@selector(_didRotateAndLayout) withObject:nil afterDelay:0];
 }
 
 @end
 }
 
 @end
index 94bbf0b..0e4a99a 100644 (file)
@@ -27,7 +27,7 @@
 
 #import "WKActionSheet.h"
 
 
 #import "WKActionSheet.h"
 
-#import <UIKit/UIActionSheet.h>
+#import <DataDetectorsUI/DDDetectionController.h>
 #import <UIKit/UIPopoverController.h>
 #import <WebKit/WKDeclarationSpecifiers.h>
 #import <wtf/RetainPtr.h>
 #import <UIKit/UIPopoverController.h>
 #import <WebKit/WKDeclarationSpecifiers.h>
 #import <wtf/RetainPtr.h>
@@ -39,7 +39,7 @@ namespace WebKit {
 class WebPageProxy;
 }
 
 class WebPageProxy;
 }
 
-@interface WKActionSheetAssistant : NSObject <WKActionSheetDelegate>
+@interface WKActionSheetAssistant : NSObject <WKActionSheetDelegate, DDDetectionControllerInteractionDelegate>
 
 - (id)initWithView:(WKContentView *)view;
 - (void)showLinkSheet;
 
 - (id)initWithView:(WKContentView *)view;
 - (void)showLinkSheet;
index a2f4a17..7bc0cd5 100644 (file)
 #import "WebPageProxy.h"
 #import "_WKActivatedElementInfoInternal.h"
 #import "_WKElementActionInternal.h"
 #import "WebPageProxy.h"
 #import "_WKActivatedElementInfoInternal.h"
 #import "_WKElementActionInternal.h"
+#import <DataDetectorsUI/DDAction.h>
 #import <DataDetectorsUI/DDDetectionController.h>
 #import <SafariServices/SSReadingList.h>
 #import <TCC/TCC.h>
 #import <DataDetectorsUI/DDDetectionController.h>
 #import <SafariServices/SSReadingList.h>
 #import <TCC/TCC.h>
-#import <UIKit/UIActionSheet_Private.h>
+#import <UIKit/UIAlertController_Private.h>
 #import <UIKit/UIView.h>
 #import <UIKit/UIViewController_Private.h>
 #import <UIKit/UIWindow_Private.h>
 #import <UIKit/UIView.h>
 #import <UIKit/UIViewController_Private.h>
 #import <UIKit/UIWindow_Private.h>
@@ -66,7 +67,6 @@ using namespace WebKit;
 @implementation WKActionSheetAssistant {
     RetainPtr<WKActionSheet> _interactionSheet;
     RetainPtr<_WKActivatedElementInfo> _elementInfo;
 @implementation WKActionSheetAssistant {
     RetainPtr<WKActionSheet> _interactionSheet;
     RetainPtr<_WKActivatedElementInfo> _elementInfo;
-    RetainPtr<NSArray> _elementActions;
     WKContentView *_view;
 }
 
     WKContentView *_view;
 }
 
@@ -159,18 +159,6 @@ using namespace WebKit;
     return [_interactionSheet presentSheetFromRect:presentationRect];
 }
 
     return [_interactionSheet presentSheetFromRect:presentationRect];
 }
 
-- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
-{
-    ASSERT(actionSheet == _interactionSheet);
-    if (actionSheet != _interactionSheet)
-        return;
-
-    if (_elementActions && buttonIndex < (NSInteger)[_elementActions count])
-        [[_elementActions objectAtIndex:buttonIndex] _runActionWithElementInfo:_elementInfo.get() view:_view];
-
-    [self cleanupSheet];
-}
-
 - (void)updateSheetPosition
 {
     [_interactionSheet updateSheetPosition];
 - (void)updateSheetPosition
 {
     [_interactionSheet updateSheetPosition];
@@ -187,8 +175,7 @@ using namespace WebKit;
 
     _interactionSheet = adoptNS([[WKActionSheet alloc] initWithView:_view]);
     _interactionSheet.get().sheetDelegate = self;
 
     _interactionSheet = adoptNS([[WKActionSheet alloc] initWithView:_view]);
     _interactionSheet.get().sheetDelegate = self;
-    _interactionSheet.get().actionSheetStyle = UIActionSheetStyleAutomatic;
-    _interactionSheet.get().delegate = self;
+    _interactionSheet.get().preferredStyle = UIAlertControllerStyleActionSheet;
 
     NSString *titleString = nil;
     BOOL titleIsURL = NO;
 
     NSString *titleString = nil;
     BOOL titleIsURL = NO;
@@ -204,18 +191,26 @@ using namespace WebKit;
 
     if ([titleString length]) {
         [_interactionSheet setTitle:titleString];
 
     if ([titleString length]) {
         [_interactionSheet setTitle:titleString];
-        if (titleIsURL) {
-            [[_interactionSheet _titleLabel] setLineBreakMode:NSLineBreakByTruncatingMiddle];
-            [_interactionSheet setTitleMaxLineCount:2];
-        } else
-            [[_interactionSheet _titleLabel] setLineBreakMode:NSLineBreakByTruncatingTail];
+        // We should configure the text field's line breaking mode correctly here, based on whether
+        // the title is an URL or not, but the appropriate UIAlertController SPIs are not available yet.
+        // The code that used to do this in the UIActionSheet world has been saved for reference in
+        // <rdar://problem/17049781> Configure the UIAlertController's title appropriately.
     }
 
     }
 
-    _elementActions = adoptNS([actions copy]);
-    for (_WKElementAction *action in _elementActions.get())
-        [_interactionSheet addButtonWithTitle:[action title]];
+    for (_WKElementAction *action in actions) {
+        [_interactionSheet _addActionWithTitle:[action title] style:UIAlertActionStyleDefault handler:^{
+            [action _runActionWithElementInfo:_elementInfo.get() view:_view];
+            [self cleanupSheet];
+        } shouldDismissHandler:^{
+            return (BOOL)(!action.dismissalHandler || action.dismissalHandler());
+        }];
+    }
 
 
-    [_interactionSheet setCancelButtonIndex:[_interactionSheet addButtonWithTitle:WEB_UI_STRING_KEY("Cancel", "Cancel button label in button bar", "Title for Cancel button label in button bar")]];
+    [_interactionSheet addAction:[UIAlertAction actionWithTitle:WEB_UI_STRING_KEY("Cancel", "Cancel button label in button bar", "Title for Cancel button label in button bar")
+                                                          style:UIAlertActionStyleCancel
+                                                        handler:^(UIAlertAction *action) {
+                                                            [self cleanupSheet];
+                                                        }]];
     _view.page->startInteractionWithElementAtPosition(_view.positionInformation.point);
 }
 
     _view.page->startInteractionWithElementAtPosition(_view.positionInformation.point);
 }
 
@@ -252,7 +247,7 @@ using namespace WebKit;
     _elementInfo = std::move(elementInfo);
 
     if (![_interactionSheet presentSheet])
     _elementInfo = std::move(elementInfo);
 
     if (![_interactionSheet presentSheet])
-        [self actionSheet:_interactionSheet.get() clickedButtonAtIndex:[_interactionSheet cancelButtonIndex]];
+        [self cleanupSheet];
 }
 
 - (void)showLinkSheet
 }
 
 - (void)showLinkSheet
@@ -288,7 +283,7 @@ using namespace WebKit;
     _elementInfo = std::move(elementInfo);
 
     if (![_interactionSheet presentSheet])
     _elementInfo = std::move(elementInfo);
 
     if (![_interactionSheet presentSheet])
-        [self actionSheet:_interactionSheet.get() clickedButtonAtIndex:[_interactionSheet cancelButtonIndex]];
+        [self cleanupSheet];
 }
 
 - (void)showDataDetectorsSheet
 }
 
 - (void)showDataDetectorsSheet
@@ -308,33 +303,26 @@ using namespace WebKit;
     NSMutableArray *elementActions = [NSMutableArray array];
     for (NSUInteger actionNumber = 0; actionNumber < [dataDetectorsActions count]; actionNumber++) {
         DDAction *action = [dataDetectorsActions objectAtIndex:actionNumber];
     NSMutableArray *elementActions = [NSMutableArray array];
     for (NSUInteger actionNumber = 0; actionNumber < [dataDetectorsActions count]; actionNumber++) {
         DDAction *action = [dataDetectorsActions objectAtIndex:actionNumber];
-        [elementActions addObject:[_WKElementAction elementActionWithTitle:[action localizedName] actionHandler:^(_WKActivatedElementInfo *actionInfo) {
-            UIPopoverController *popoverController = nil;
-            if (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPhone) {
-                [_interactionSheet setUserInteractionEnabled:NO];
-                // <rdar://problem/11015751> Action sheet becomes black if a button is clicked twice on iPad
-                // prevent any further tap on the sheet while DD is loading its view controller, otherwise UIActionSheet goes amok
-
-                popoverController = [_interactionSheet _relinquishPopoverController];
-            }
-
+        _WKElementAction *elementAction = [_WKElementAction elementActionWithTitle:[action localizedName] actionHandler:^(_WKActivatedElementInfo *actionInfo) {
             [[getDDDetectionControllerClass() sharedController] performAction:action
             [[getDDDetectionControllerClass() sharedController] performAction:action
-                                                                       inView:[self superviewForSheet]
-                                                        withPopoverController:popoverController
+                                                          fromAlertController:_interactionSheet.get()
                                                           interactionDelegate:self];
                                                           interactionDelegate:self];
-        }]];
+        }];
+        elementAction.dismissalHandler = ^{
+            return (BOOL)!action.hasUserInterface;
+        };
+        [elementActions addObject:elementAction];
     }
 
     [self _createSheetWithElementActions:elementActions showLinkTitle:NO];
     if (!_interactionSheet)
         return;
 
     }
 
     [self _createSheetWithElementActions:elementActions showLinkTitle:NO];
     if (!_interactionSheet)
         return;
 
-    // The implicit second button is "cancel", which is swallowed by the popover at presentation time.
-    if (_interactionSheet.get().numberOfButtons <= 2)
+    if (elementActions.count <= 1)
         _interactionSheet.get().arrowDirections = UIPopoverArrowDirectionUp | UIPopoverArrowDirectionDown;
 
     if (![_interactionSheet presentSheet])
         _interactionSheet.get().arrowDirections = UIPopoverArrowDirectionUp | UIPopoverArrowDirectionDown;
 
     if (![_interactionSheet presentSheet])
-        [self actionSheet:_interactionSheet.get() clickedButtonAtIndex:[_interactionSheet cancelButtonIndex]];
+        [self cleanupSheet];
 }
 
 - (void)cleanupSheet
 }
 
 - (void)cleanupSheet
@@ -343,11 +331,8 @@ using namespace WebKit;
 
     [_interactionSheet doneWithSheet];
     [_interactionSheet setSheetDelegate:nil];
 
     [_interactionSheet doneWithSheet];
     [_interactionSheet setSheetDelegate:nil];
-    [_interactionSheet setDelegate:nil];
     _interactionSheet = nil;
     _elementInfo = nil;
     _interactionSheet = nil;
     _elementInfo = nil;
-
-    _elementActions = nil;
 }
 
 @end
 }
 
 @end
index 5de25f5..813aa03 100644 (file)
@@ -757,8 +757,10 @@ static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UI
 
     if ([gestureRecognizer state] == UIGestureRecognizerStateBegan) {
         SEL action = [self _actionForLongPress];
 
     if ([gestureRecognizer state] == UIGestureRecognizerStateBegan) {
         SEL action = [self _actionForLongPress];
-        if (action)
+        if (action) {
             [self performSelector:action];
             [self performSelector:action];
+            [self _cancelLongPressGestureRecognizer];
+        }
     }
 }
 
     }
 }