Changeset 246583 in webkit


Ignore:
Timestamp:
Jun 19, 2019 2:43:57 AM (5 years ago)
Author:
dino@apple.com
Message:

UIContextMenuInteraction implementation for WKContentView
https://bugs.webkit.org/show_bug.cgi?id=198986
<rdar://problem/51875189>

Reviewed by Andy Estes.

Source/WebCore/PAL:

Include + soft link DDContextMenuAction.

  • pal/spi/ios/DataDetectorsUISPI.h:

Source/WebKit:

Implement UIContextMenuInteraction and its delegate as a
replacement for UIPreviewItemController in iOS 13.

In order to preserve existing behaviour as much as possible,
we check for the implementation of new WebKit API to configure
the menu. If that is not present, we attempt to convert
the results of the existing WebKit WKPreviewAction delegates
into something that works with UIContextMenus.

  • UIProcess/ios/WKContentViewInteraction.h:
  • UIProcess/ios/WKContentViewInteraction.mm:

(-[WKContentView setupInteraction]):
(-[WKContentView _contentsOfUserInterfaceItem:]):
(-[WKContentView _registerPreview]):
(-[WKContentView _unregisterPreview]):
(-[WKContentView _showLinkPreviewsPreferenceChanged:]):
(needsDeprecatedPreviewAPI):
(uiActionForPreviewAction):
(menuFromPreviewOrDefaults):
(titleForMenu):
(-[WKContentView assignLegacyDataForContextMenuInteraction]):
(-[WKContentView contextMenuInteraction:configurationForMenuAtLocation:]):
(-[WKContentView _contextMenuInteraction:configurationForMenuAtLocation:completion:]):
(-[WKContentView continueContextMenuInteraction:]):
(uiImageForImage):
(createTargetedPreview):
(-[WKContentView _targetedPreview]):
(-[WKContentView contextMenuInteraction:previewForHighlightingMenuWithConfiguration:]):
(-[WKContentView contextMenuInteractionWillPresent:]):
(-[WKContentView contextMenuInteraction:previewForDismissingMenuWithConfiguration:]):
(-[WKContentView contextMenuInteraction:willCommitWithAnimator:]):
(-[WKContentView contextMenuInteractionDidEnd:]):
(-[WKContentView shouldUsePreviewForLongPress]): Deleted.

Source/WTF:

Add USE_UICONTEXTMENU for iOS 13+.

  • wtf/Platform.h:
Location:
trunk/Source
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r246554 r246583  
     12019-06-18  Dean Jackson  <dino@apple.com>
     2
     3        UIContextMenuInteraction implementation for WKContentView
     4        https://bugs.webkit.org/show_bug.cgi?id=198986
     5        <rdar://problem/51875189>
     6
     7        Reviewed by Andy Estes.
     8
     9        Add USE_UICONTEXTMENU for iOS 13+.
     10
     11        * wtf/Platform.h:
     12
    1132019-06-18  Kenneth Russell  <kbr@chromium.org>
    214
  • trunk/Source/WTF/wtf/Platform.h

    r246554 r246583  
    15861586#define HAVE_APP_SSO 1
    15871587#endif
     1588
     1589#if PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 130000
     1590#define USE_UICONTEXTMENU 1
     1591#endif
  • trunk/Source/WebCore/PAL/ChangeLog

    r246542 r246583  
     12019-06-18  Dean Jackson  <dino@apple.com>
     2
     3        UIContextMenuInteraction implementation for WKContentView
     4        https://bugs.webkit.org/show_bug.cgi?id=198986
     5        <rdar://problem/51875189>
     6
     7        Reviewed by Andy Estes.
     8
     9        Include + soft link DDContextMenuAction.
     10
     11        * pal/spi/ios/DataDetectorsUISPI.h:
     12
    1132019-06-18  Jiewen Tan  <jiewen_tan@apple.com>
    214
  • trunk/Source/WebCore/PAL/pal/spi/ios/DataDetectorsUISPI.h

    r242801 r246583  
    3232
    3333#import <DataDetectorsUI/DDAction.h>
     34#if HAVE(LINK_PREVIEW) && USE(UICONTEXTMENU)
     35#import <DataDetectorsUI/DDContextMenuAction.h>
     36#endif
    3437#import <DataDetectorsUI/DDDetectionController.h>
    3538
     
    4649@property (readonly) NSString *actionUTI;
    4750@end
     51
     52#if HAVE(LINK_PREVIEW) && USE(UICONTEXTMENU)
     53@class UIContextMenuConfiguration;
     54@interface DDContextMenuAction
     55+ (UIContextMenuConfiguration *)contextMenuConfigurationWithURL:(NSURL *)URL inView:(UIView *)view context:(NSDictionary *)context menuIdentifier:(NSString *)menuIdentifier;
     56@end
     57#endif
    4858
    4959@protocol DDDetectionControllerInteractionDelegate <NSObject>
     
    7181
    7282SOFT_LINK_PRIVATE_FRAMEWORK(DataDetectorsUI)
     83#if HAVE(LINK_PREVIEW) && USE(UICONTEXTMENU)
     84SOFT_LINK_CLASS(DataDetectorsUI, DDContextMenuAction);
     85#endif
    7386SOFT_LINK_CLASS(DataDetectorsUI, DDDetectionController)
    7487SOFT_LINK_CONSTANT(DataDetectorsUI, kDataDetectorsLeadingText, const NSString *)
  • trunk/Source/WebKit/ChangeLog

    r246580 r246583  
     12019-06-18  Dean Jackson  <dino@apple.com>
     2
     3        UIContextMenuInteraction implementation for WKContentView
     4        https://bugs.webkit.org/show_bug.cgi?id=198986
     5        <rdar://problem/51875189>
     6
     7        Reviewed by Andy Estes.
     8
     9        Implement UIContextMenuInteraction and its delegate as a
     10        replacement for UIPreviewItemController in iOS 13.
     11
     12        In order to preserve existing behaviour as much as possible,
     13        we check for the implementation of new WebKit API to configure
     14        the menu. If that is not present, we attempt to convert
     15        the results of the existing WebKit WKPreviewAction delegates
     16        into something that works with UIContextMenus.
     17
     18        * UIProcess/ios/WKContentViewInteraction.h:
     19        * UIProcess/ios/WKContentViewInteraction.mm:
     20        (-[WKContentView setupInteraction]):
     21        (-[WKContentView _contentsOfUserInterfaceItem:]):
     22        (-[WKContentView _registerPreview]):
     23        (-[WKContentView _unregisterPreview]):
     24        (-[WKContentView _showLinkPreviewsPreferenceChanged:]):
     25        (needsDeprecatedPreviewAPI):
     26        (uiActionForPreviewAction):
     27        (menuFromPreviewOrDefaults):
     28        (titleForMenu):
     29        (-[WKContentView assignLegacyDataForContextMenuInteraction]):
     30        (-[WKContentView contextMenuInteraction:configurationForMenuAtLocation:]):
     31        (-[WKContentView _contextMenuInteraction:configurationForMenuAtLocation:completion:]):
     32        (-[WKContentView continueContextMenuInteraction:]):
     33        (uiImageForImage):
     34        (createTargetedPreview):
     35        (-[WKContentView _targetedPreview]):
     36        (-[WKContentView contextMenuInteraction:previewForHighlightingMenuWithConfiguration:]):
     37        (-[WKContentView contextMenuInteractionWillPresent:]):
     38        (-[WKContentView contextMenuInteraction:previewForDismissingMenuWithConfiguration:]):
     39        (-[WKContentView contextMenuInteraction:willCommitWithAnimator:]):
     40        (-[WKContentView contextMenuInteractionDidEnd:]):
     41        (-[WKContentView shouldUsePreviewForLongPress]): Deleted.
     42
    1432019-06-18  Ryan Haddad  <ryanhaddad@apple.com>
    244
  • trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h

    r246347 r246583  
    8888
    8989#if HAVE(LINK_PREVIEW)
     90#import <UIKit/UIPreviewAction_Private.h>
    9091#import <UIKit/UIPreviewItemController.h>
    9192#endif
     
    10671068@end
    10681069
     1070@interface UIPreviewAction ()
     1071@property (nonatomic, strong) UIImage *image;
     1072@end
     1073
    10691074#endif // USE(APPLE_INTERNAL_SDK)
    10701075
     
    11801185@end
    11811186
     1187#if HAVE(LINK_PREVIEW) && USE(UICONTEXTMENU)
     1188@interface UIContextMenuConfiguration (NeededUntil51288435Fixed)
     1189@property (nonatomic, copy) id <NSCopying> identifier;
     1190@property (nonatomic, copy) UIContextMenuContentPreviewProvider previewProvider;
     1191@property (nonatomic, copy) UIContextMenuActionProvider actionProvider;
     1192@end
     1193#endif
     1194
    11821195WTF_EXTERN_C_BEGIN
    11831196
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h

    r246580 r246583  
    4040@class WKWindowFeatures;
    4141
     42#if TARGET_OS_IOS
     43@class WKContextMenuElementInfo;
     44@class UIContextMenuConfiguration;
     45@protocol UIContextMenuInteractionCommitAnimating;
     46#endif
     47
    4248/*! A class conforming to the WKUIDelegate protocol provides methods for
    4349 presenting native UI on behalf of a webpage.
     
    151157 @param previewingViewController The view controller that is being popped.
    152158 */
    153 - (void)webView:(WKWebView *)webView commitPreviewingViewController:(UIViewController *)previewingViewController WK_API_DEPRECATED("This API will be replaced", ios(10.0, WK_IOS_TBA));
     159- (void)webView:(WKWebView *)webView commitPreviewingViewController:(UIViewController *)previewingViewController WK_API_DEPRECATED("webView:contextMenuForElement:willCommitWithAnimator:", ios(10.0, WK_IOS_TBA));
    154160
    155161#endif // TARGET_OS_IPHONE
     162
     163#if TARGET_OS_IOS
     164
     165/**
     166 * @abstract Called when a context menu interaction begins.
     167 *
     168 * @param webView The web view invoking the delegate method.
     169 * @param elementInfo The elementInfo for the element the user is touching.
     170 * @param completionHandler A completion handler to call once a it has been decided whether or not to show a context menu.
     171 * Pass a valid UIContextMenuConfiguration to show a context menu, or pass nil to not show a context menu.
     172 */
     173
     174- (void)webView:(WKWebView *)webView contextMenuConfigurationForElement:(WKContextMenuElementInfo *)elementInfo completionHandler:(void (^)(UIContextMenuConfiguration * _Nullable configuration))completionHandler WK_API_AVAILABLE(ios(WK_IOS_TBA));
     175
     176/**
     177 * @abstract Called when the context menu configured by the UIContextMenuConfiguration from
     178 * webView:contextMenuConfigurationForElement:completionHandler: is committed.
     179 *
     180 * @param webView The web view invoking the delegate method.
     181 * @param elementInfo The elementInfo for the element the user is touching.
     182 * @param animator The animator to use for the commit animation.
     183 */
     184
     185- (void)webView:(WKWebView *)webView contextMenuForElement:(WKContextMenuElementInfo *)elementInfo willCommitWithAnimator:(id<UIContextMenuInteractionCommitAnimating>)animator WK_API_AVAILABLE(ios(WK_IOS_TBA));
     186
     187/**
     188 * @abstract Called when the context menu will be presented.
     189 *
     190 * @param webView The web view invoking the delegate method.
     191 * @param elementInfo The elementInfo for the element the user is touching.
     192 */
     193
     194- (void)webView:(WKWebView *)webView contextMenuWillPresentForElement:(WKContextMenuElementInfo *)elementInfo WK_API_AVAILABLE(ios(WK_IOS_TBA));
     195
     196/**
     197 * @abstract Called when the context menu ends.
     198 *
     199 * @param webView The web view invoking the delegate method.
     200 * @param elementInfo The elementInfo for the element the user is touching.
     201 */
     202
     203- (void)webView:(WKWebView *)webView contextMenuDidEndForElement:(WKContextMenuElementInfo *)elementInfo WK_API_AVAILABLE(ios(WK_IOS_TBA));
     204
     205#endif // TARGET_OS_IOS
    156206
    157207#if !TARGET_OS_IPHONE
  • trunk/Source/WebKit/UIProcess/WKImagePreviewViewController.mm

    r245831 r246583  
    3232#import <WebCore/IntSize.h>
    3333#import <_WKElementAction.h>
    34 
    35 #if HAVE(LINK_PREVIEW)
    36 #if USE(APPLE_INTERNAL_SDK) && __has_include(<WebKitAdditions/WKImagePreviewViewControllerAdditions.mm>)
    37 #include <WebKitAdditions/WKImagePreviewViewControllerAdditions.mm>
    38 #else
    39 static void setAdditionalPreviewActionInfo(UIPreviewAction *, _WKElementAction *)
    40 {
    41 }
    42 #endif
    43 #endif
    4434
    4535@implementation WKImagePreviewViewController {
     
    113103            [imageAction runActionWithElementInfo:_activatedElementInfo.get()];
    114104        }];
    115         setAdditionalPreviewActionInfo(previewAction, imageAction);
     105        previewAction.image = [_WKElementAction imageForElementActionType:imageAction.type];
    116106
    117107        [previewActions addObject:previewAction];
  • trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h

    r246546 r246583  
    6060#import <wtf/text/WTFString.h>
    6161
    62 #if USE(APPLE_INTERNAL_SDK) && __has_include(<WebKitAdditions/WKInteractionPreviewAdditions.h>)
    63 #import <WebKitAdditions/WKInteractionPreviewAdditions.h>
    64 #endif
    65 
    6662namespace API {
    6763class OpenPanelParameters;
     
    10298@class WebEvent;
    10399@class WKActionSheetAssistant;
     100@class WKContextMenuElementInfo;
    104101@class WKDrawingCoordinator;
    105102@class WKFocusedFormControlView;
     
    246243    Vector<bool> _focusStateStack;
    247244#if HAVE(LINK_PREVIEW)
    248 #if USE(LONG_PRESS_FOR_LINK_PREVIEW)
    249     LONG_PRESS_LINK_PREVIEW_MEMBERS
     245#if USE(UICONTEXTMENU)
     246    RetainPtr<UIContextMenuInteraction> _contextMenuInteraction;
     247    RetainPtr<WKContextMenuElementInfo> _contextMenuElementInfo;
     248    BOOL _showLinkPreviews;
     249    RetainPtr<UIViewController> _contextMenuLegacyPreviewController;
     250    RetainPtr<UIMenu> _contextMenuLegacyMenu;
     251    BOOL _contextMenuHasRequestedLegacyData;
    250252#else
    251253    RetainPtr<UIPreviewItemController> _previewItemController;
     
    533535
    534536#if HAVE(LINK_PREVIEW)
    535 #if USE(LONG_PRESS_FOR_LINK_PREVIEW)
    536 @interface WKContentView (WKInteractionPreview) <LONG_PRESS_LINK_PREVIEW_PROTOCOL>
     537#if USE(UICONTEXTMENU)
     538@interface WKContentView (WKInteractionPreview) <UIContextMenuInteractionDelegate>
    537539#else
    538540@interface WKContentView (WKInteractionPreview) <UIPreviewItemDelegate>
    539541#endif
    540 
    541 @property (nonatomic, readonly) BOOL shouldUsePreviewForLongPress;
    542 
    543542- (void)_registerPreview;
    544543- (void)_unregisterPreview;
    545 
    546544@end
    547545#endif
  • trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm

    r246570 r246583  
    3030
    3131#import "APIUIClient.h"
     32#import "CompletionHandlerCallChecker.h"
    3233#import "DocumentEditingContext.h"
    3334#import "EditableImageController.h"
     
    106107#import <pal/spi/ios/DataDetectorsUISPI.h>
    107108#import <pal/spi/ios/GraphicsServicesSPI.h>
     109#import <wtf/BlockObjCExceptions.h>
     110#import <wtf/BlockPtr.h>
    108111#import <wtf/Optional.h>
    109112#import <wtf/RetainPtr.h>
     
    152155#endif
    153156
    154 #if USE(APPLE_INTERNAL_SDK) && __has_include(<WebKitAdditions/WKInteractionPreviewAdditions.h>)
    155 #import <WebKitAdditions/WKInteractionPreviewAdditions.h>
     157#if HAVE(LINK_PREVIEW) && USE(UICONTEXTMENU)
     158static NSString * const webkitShowLinkPreviewsPreferenceKey = @"WebKitShowLinkPreviews";
     159static NSString * const webkitShowLinkPreviewsPreferenceChangedNotification = @"WebKitShowLinkPreviewsPreferenceChanged";
    156160#endif
    157161
     
    765769    [_highlightLongPressGestureRecognizer setDelegate:self];
    766770
    767 #if HAVE(LINK_PREVIEW)
    768     if (!self.shouldUsePreviewForLongPress)
    769 #endif
    770     {
    771         [self addGestureRecognizer:_highlightLongPressGestureRecognizer.get()];
    772 
    773         [self _createAndConfigureLongPressGestureRecognizer];
    774     }
     771#if HAVE(LINK_PREVIEW) && !USE(UICONTEXTMENU)
     772    [self addGestureRecognizer:_highlightLongPressGestureRecognizer.get()];
     773    [self _createAndConfigureLongPressGestureRecognizer];
     774#endif
    775775
    776776#if ENABLE(DATA_INTERACTION)
     
    73687368#if HAVE(LINK_PREVIEW)
    73697369    if ([userInterfaceItem isEqualToString:@"linkPreviewPopoverContents"]) {
    7370 #if USE(LONG_PRESS_FOR_LINK_PREVIEW)
     7370#if USE(UICONTEXTMENU)
    73717371        return @{ userInterfaceItem: @{ @"pageURL": WTF::userVisibleString(_positionInformation.url) } };
    73727372#else
     
    74127412}
    74137413
    7414 #if USE(LONG_PRESS_FOR_LINK_PREVIEW)
    7415 #include <WebKitAdditions/WKInteractionPreviewAdditions.mm>
     7414#if USE(UICONTEXTMENU)
     7415
     7416@implementation WKContentView (WKInteractionPreview)
     7417
     7418- (void)_registerPreview
     7419{
     7420    if (!_webView.allowsLinkPreview)
     7421        return;
     7422
     7423    _contextMenuInteraction = adoptNS([[UIContextMenuInteraction alloc] initWithDelegate:self]);
     7424    _contextMenuHasRequestedLegacyData = NO;
     7425    [self addInteraction:_contextMenuInteraction.get()];
     7426
     7427    [self _showLinkPreviewsPreferenceChanged:nil];
     7428
     7429    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_showLinkPreviewsPreferenceChanged:) name:webkitShowLinkPreviewsPreferenceChangedNotification object:nil];
     7430}
     7431
     7432- (void)_unregisterPreview
     7433{
     7434    if (!_contextMenuInteraction)
     7435        return;
     7436
     7437    [self removeInteraction:_contextMenuInteraction.get()];
     7438    _contextMenuInteraction = nil;
     7439
     7440    [[NSNotificationCenter defaultCenter] removeObserver:self name:webkitShowLinkPreviewsPreferenceChangedNotification object:nil];
     7441}
     7442
     7443- (void)_showLinkPreviewsPreferenceChanged:(NSNotification *)notification
     7444{
     7445    Boolean keyExistsAndHasValidFormat = false;
     7446    Boolean prefValue = CFPreferencesGetAppBooleanValue((__bridge CFStringRef)webkitShowLinkPreviewsPreferenceKey, kCFPreferencesCurrentApplication, &keyExistsAndHasValidFormat);
     7447    if (keyExistsAndHasValidFormat)
     7448        _showLinkPreviews = prefValue;
     7449    else
     7450        _showLinkPreviews = YES;
     7451}
     7452
     7453static bool needsDeprecatedPreviewAPI(id<WKUIDelegate> delegate)
     7454{
     7455    // FIXME: Replace these with booleans in UIDelegate.h.
     7456    return delegate
     7457    && ![delegate respondsToSelector:@selector(_webView:contextMenuConfigurationForElement:completionHandler:)]
     7458    && ![delegate respondsToSelector:@selector(webView:contextMenuConfigurationForElement:completionHandler:)]
     7459    && ![delegate respondsToSelector:@selector(_webView:contextMenuForElement:willCommitWithAnimator:)]
     7460    && ![delegate respondsToSelector:@selector(webView:contextMenuForElement:willCommitWithAnimator:)]
     7461    && ![delegate respondsToSelector:@selector(_webView:contextMenuWillPresentForElement:)]
     7462    && ![delegate respondsToSelector:@selector(webView:contextMenuWillPresentForElement:)]
     7463    && ![delegate respondsToSelector:@selector(_webView:contextMenuDidEndForElement:)]
     7464    && ![delegate respondsToSelector:@selector(webView:contextMenuDidEndForElement:)]
     7465    && ([delegate respondsToSelector:@selector(webView:shouldPreviewElement:)]
     7466        || [delegate respondsToSelector:@selector(webView:previewingViewControllerForElement:defaultActions:)]
     7467        || [delegate respondsToSelector:@selector(webView:commitPreviewingViewController:)]
     7468        || [delegate respondsToSelector:@selector(_webView:previewViewControllerForURL:defaultActions:elementInfo:)]
     7469        || [delegate respondsToSelector:@selector(_webView:previewViewControllerForURL:)]
     7470        || [delegate respondsToSelector:@selector(_webView:previewViewControllerForImage:alternateURL:defaultActions:elementInfo:)]);
     7471}
     7472
     7473ALLOW_DEPRECATED_DECLARATIONS_BEGIN
     7474static NSArray<WKPreviewAction *> *wkPreviewActionsFromElementActions(NSArray<_WKElementAction *> *elementActions, _WKActivatedElementInfo *elementInfo)
     7475{
     7476    NSMutableArray<WKPreviewAction *> *previewActions = [NSMutableArray arrayWithCapacity:[elementActions count]];
     7477    for (_WKElementAction *elementAction in elementActions) {
     7478        WKPreviewAction *previewAction = [WKPreviewAction actionWithIdentifier:previewIdentifierForElementAction(elementAction) title:elementAction.title style:UIPreviewActionStyleDefault handler:^(UIPreviewAction *, UIViewController *) {
     7479            [elementAction runActionWithElementInfo:elementInfo];
     7480        }];
     7481        previewAction.image = [_WKElementAction imageForElementActionType:elementAction.type];
     7482        [previewActions addObject:previewAction];
     7483    }
     7484    return previewActions;
     7485}
     7486
     7487static UIAction *uiActionForPreviewAction(UIPreviewAction *previewAction, UIViewController *previewViewController)
     7488{
     7489    // UIPreviewActionItem.image is SPI, so no external clients will be able
     7490    // to provide glyphs for actions <rdar://problem/50151855>.
     7491    // However, they should migrate to the new API.
     7492
     7493    return [UIAction actionWithTitle:previewAction.title image:previewAction.image identifier:nil handler:^(UIAction *action) {
     7494        previewAction.handler(previewAction, previewViewController);
     7495    }];
     7496}
     7497ALLOW_DEPRECATED_DECLARATIONS_END
     7498
     7499static NSArray<UIMenuElement *> *menuElementsFromPreviewOrDefaults(UIViewController *previewViewController, const RetainPtr<NSArray>& defaultElementActions, RetainPtr<_WKActivatedElementInfo> elementInfo)
     7500{
     7501    auto actions = [NSMutableArray arrayWithCapacity:defaultElementActions.get().count];
     7502
     7503    // One of the delegates may have provided a UIViewController with a previewActionItems array. If so,
     7504    // we need to convert each UIPreviewActionItem into a UIAction.
     7505    if (previewViewController) {
     7506        ALLOW_DEPRECATED_DECLARATIONS_BEGIN
     7507        NSArray<id<UIPreviewActionItem>> *previewActions = previewViewController.previewActionItems;
     7508        for (UIPreviewAction *previewAction in previewActions)
     7509            [actions addObject:uiActionForPreviewAction(previewAction, previewViewController)];
     7510        ALLOW_DEPRECATED_DECLARATIONS_END
     7511    }
     7512
     7513    if (![actions count]) {
     7514        // We either didn't get a custom preview UIViewController, or it didn't provide any actions
     7515        // so we should use the default set.
     7516        for (_WKElementAction *elementAction in defaultElementActions.get()) {
     7517            UIImage *image = [_WKElementAction imageForElementActionType:elementAction.type];
     7518
     7519            [actions addObject:[UIAction actionWithTitle:elementAction.title image:image identifier:nil handler:^(UIAction *) {
     7520                [elementAction runActionWithElementInfo:elementInfo.get()];
     7521            }]];
     7522        }
     7523    }
     7524
     7525    return actions;
     7526}
     7527
     7528static UIMenu *menuFromPreviewOrDefaults(UIViewController *previewViewController, const RetainPtr<NSArray>& defaultElementActions, RetainPtr<_WKActivatedElementInfo> elementInfo, NSString *title)
     7529{
     7530    auto actions = menuElementsFromPreviewOrDefaults(previewViewController, defaultElementActions, elementInfo);
     7531    return [UIMenu menuWithTitle:title children:actions];
     7532}
     7533
     7534static NSString *titleForMenu(bool isLink, bool showLinkPreviews, const URL& url, const String& title)
     7535{
     7536    if (isLink && !showLinkPreviews) {
     7537        if (!url.isEmpty()) {
     7538            if (WTF::protocolIsJavaScript(url))
     7539                return WEB_UI_STRING_KEY("JavaScript", "JavaScript Action Sheet Title", "Title for action sheet for JavaScript link");
     7540            return WTF::userVisibleString(url);
     7541        }
     7542    } else if (!isLink && !title.isEmpty())
     7543        return title;
     7544
     7545    return nil;
     7546}
     7547
     7548- (void)assignLegacyDataForContextMenuInteraction
     7549{
     7550    ASSERT(!_contextMenuHasRequestedLegacyData);
     7551    if (_contextMenuHasRequestedLegacyData)
     7552        return;
     7553    _contextMenuHasRequestedLegacyData = YES;
     7554
     7555    if (!_webView)
     7556        return;
     7557    auto uiDelegate = static_cast<id<WKUIDelegatePrivate>>(_webView.UIDelegate);
     7558    if (!uiDelegate)
     7559        return;
     7560
     7561    const auto& url = _positionInformation.url;
     7562
     7563    _page->startInteractionWithElementAtPosition(_positionInformation.request.point);
     7564
     7565    UIViewController *previewViewController = nil;
     7566
     7567    auto elementInfo = adoptNS([[_WKActivatedElementInfo alloc] _initWithInteractionInformationAtPosition:_positionInformation]);
     7568
     7569    if (_positionInformation.isLink) {
     7570        _longPressCanClick = NO;
     7571
     7572        RetainPtr<NSArray<_WKElementAction *>> defaultActionsFromAssistant = [_actionSheetAssistant defaultActionsForLinkSheet:elementInfo.get()];
     7573
     7574        // FIXME: Animated images go here.
     7575
     7576        ALLOW_DEPRECATED_DECLARATIONS_BEGIN
     7577        if ([uiDelegate respondsToSelector:@selector(webView:previewingViewControllerForElement:defaultActions:)]) {
     7578            auto defaultActions = wkPreviewActionsFromElementActions(defaultActionsFromAssistant.get(), elementInfo.get());
     7579            auto previewElementInfo = adoptNS([[WKPreviewElementInfo alloc] _initWithLinkURL:url]);
     7580            previewViewController = [uiDelegate webView:_webView previewingViewControllerForElement:previewElementInfo.get() defaultActions:defaultActions];
     7581        } else if ([uiDelegate respondsToSelector:@selector(_webView:previewViewControllerForURL:defaultActions:elementInfo:)])
     7582            previewViewController = [uiDelegate _webView:_webView previewViewControllerForURL:url defaultActions:defaultActionsFromAssistant.get() elementInfo:elementInfo.get()];
     7583        else if ([uiDelegate respondsToSelector:@selector(_webView:previewViewControllerForURL:)])
     7584            previewViewController = [uiDelegate _webView:_webView previewViewControllerForURL:url];
     7585        ALLOW_DEPRECATED_DECLARATIONS_END
     7586
     7587#if USE(DATA_DETECTORS_FOR_DEFAULT_PREVIEW)
     7588        // Previously, UIPreviewItemController would detect the case where there was no previewViewController
     7589        // and create one. We need to replicate this code for the new API.
     7590        if (!previewViewController) {
     7591            auto ddContextMenuActionClass = getDDContextMenuActionClass();
     7592            if ([ddContextMenuActionClass respondsToSelector:@selector(contextMenuConfigurationForURL:identifier:selectedText:results:inView:context:menuIdentifier:)]) {
     7593                BEGIN_BLOCK_OBJC_EXCEPTIONS;
     7594                NSDictionary *context = [self dataDetectionContextForPositionInformation:_positionInformation];
     7595                RetainPtr<UIContextMenuConfiguration> dataDetectorsResult = [ddContextMenuActionClass contextMenuConfigurationForURL:url identifier:_positionInformation.dataDetectorIdentifier selectedText:self.selectedText results:_positionInformation.dataDetectorResults.get() inView:self context:context menuIdentifier:nil];
     7596                if (_showLinkPreviews && dataDetectorsResult && dataDetectorsResult.get().previewProvider)
     7597                    _contextMenuLegacyPreviewController = dataDetectorsResult.get().previewProvider();
     7598                if (dataDetectorsResult && dataDetectorsResult.get().actionProvider) {
     7599                    auto menuElements = menuElementsFromPreviewOrDefaults(nil, defaultActionsFromAssistant, elementInfo);
     7600                    _contextMenuLegacyMenu = dataDetectorsResult.get().actionProvider(menuElements);
     7601                }
     7602                END_BLOCK_OBJC_EXCEPTIONS;
     7603            }
     7604            return;
     7605        }
     7606#endif
     7607
     7608        auto menuTitle = titleForMenu(true, _showLinkPreviews, url, _positionInformation.title);
     7609        _contextMenuLegacyMenu = menuFromPreviewOrDefaults(previewViewController, defaultActionsFromAssistant, elementInfo, menuTitle);
     7610
     7611    } else if (_positionInformation.isImage) {
     7612        NSURL *nsURL = (NSURL *)url;
     7613        RetainPtr<NSDictionary> imageInfo;
     7614        ASSERT(_positionInformation.image);
     7615        auto cgImage = _positionInformation.image->makeCGImageCopy();
     7616        auto uiImage = adoptNS([[UIImage alloc] initWithCGImage:cgImage.get()]);
     7617
     7618        if ([uiDelegate respondsToSelector:@selector(_webView:alternateURLFromImage:userInfo:)]) {
     7619            NSDictionary *userInfo;
     7620            nsURL = [uiDelegate _webView:_webView alternateURLFromImage:uiImage.get() userInfo:&userInfo];
     7621            imageInfo = userInfo;
     7622        }
     7623
     7624        ALLOW_DEPRECATED_DECLARATIONS_BEGIN
     7625        if ([uiDelegate respondsToSelector:@selector(_webView:willPreviewImageWithURL:)])
     7626            [uiDelegate _webView:_webView willPreviewImageWithURL:_positionInformation.imageURL];
     7627
     7628        RetainPtr<NSArray<_WKElementAction *>> defaultActionsFromAssistant = [_actionSheetAssistant defaultActionsForImageSheet:elementInfo.get()];
     7629
     7630        if (imageInfo && [uiDelegate respondsToSelector:@selector(_webView:previewViewControllerForImage:alternateURL:defaultActions:elementInfo:)])
     7631            previewViewController = [uiDelegate _webView:_webView previewViewControllerForImage:uiImage.get() alternateURL:nsURL defaultActions:defaultActionsFromAssistant.get() elementInfo:elementInfo.get()];
     7632        else
     7633            previewViewController = [[WKImagePreviewViewController alloc] initWithCGImage:cgImage defaultActions:defaultActionsFromAssistant.get() elementInfo:elementInfo.get()];
     7634        ALLOW_DEPRECATED_DECLARATIONS_END
     7635
     7636        auto menuTitle = titleForMenu(false, _showLinkPreviews, url, _positionInformation.title);
     7637        _contextMenuLegacyMenu = menuFromPreviewOrDefaults(previewViewController, defaultActionsFromAssistant, elementInfo, menuTitle);
     7638    }
     7639
     7640    _contextMenuLegacyPreviewController = _showLinkPreviews ? previewViewController : nullptr;
     7641}
     7642
     7643- (UIContextMenuConfiguration *)contextMenuInteraction:(UIContextMenuInteraction *)interaction configurationForMenuAtLocation:(CGPoint)location
     7644{
     7645    // Required to conform to UIContextMenuInteractionDelegate, but SPI version should be called instead.
     7646    ASSERT_NOT_REACHED();
     7647    return nil;
     7648}
     7649
     7650- (void)_contextMenuInteraction:(UIContextMenuInteraction *)interaction configurationForMenuAtLocation:(CGPoint)location completion:(void(^)(UIContextMenuConfiguration *))completion
     7651{
     7652    if (!_webView)
     7653        return completion(nil);
     7654
     7655    if (!_webView.configuration._longPressActionsEnabled)
     7656        return completion(nil);
     7657
     7658    const auto position = [interaction locationInView:self];
     7659    WebKit::InteractionInformationRequest request { WebCore::roundedIntPoint(position) };
     7660    request.includeSnapshot = true;
     7661    request.includeLinkIndicator = true;
     7662
     7663    [self doAfterPositionInformationUpdate:[weakSelf = WeakObjCPtr<WKContentView>(self), completion = makeBlockPtr(completion)] (WebKit::InteractionInformationAtPosition) {
     7664        auto strongSelf = weakSelf.get();
     7665        if (!strongSelf)
     7666            return completion(nil);
     7667        [strongSelf continueContextMenuInteraction:completion.get()];
     7668    } forRequest:request];
     7669}
     7670
     7671- (void)continueContextMenuInteraction:(void(^)(UIContextMenuConfiguration *))completion
     7672{
     7673    if (!_positionInformation.touchCalloutEnabled)
     7674        return completion(nil);
     7675
     7676    if (!_positionInformation.isLink && !_positionInformation.isImage && !_positionInformation.isAttachment)
     7677        return completion(nil);
     7678
     7679    URL linkURL = _positionInformation.url;
     7680
     7681    if (_positionInformation.isLink && linkURL.isEmpty())
     7682        return completion(nil);
     7683
     7684    auto uiDelegate = static_cast<id<WKUIDelegatePrivate>>(_webView.UIDelegate);
     7685    if (!uiDelegate)
     7686        return completion(nil);
     7687
     7688    if (needsDeprecatedPreviewAPI(uiDelegate)) {
     7689
     7690        if (_positionInformation.isLink) {
     7691            ALLOW_DEPRECATED_DECLARATIONS_BEGIN
     7692            if ([uiDelegate respondsToSelector:@selector(webView:shouldPreviewElement:)]) {
     7693                auto previewElementInfo = adoptNS([[WKPreviewElementInfo alloc] _initWithLinkURL:linkURL]);
     7694                if (![uiDelegate webView:_webView shouldPreviewElement:previewElementInfo.get()])
     7695                    return completion(nil);
     7696            }
     7697            ALLOW_DEPRECATED_DECLARATIONS_END
     7698
     7699            // FIXME: Support JavaScript urls here. But make sure they don't show a preview.
     7700            // <rdar://problem/50572283>
     7701            if (!linkURL.protocolIsInHTTPFamily()) {
     7702#if ENABLE(DATA_DETECTION)
     7703                if (!WebCore::DataDetection::canBePresentedByDataDetectors(linkURL))
     7704                    return completion(nil);
     7705#endif
     7706            }
     7707        }
     7708
     7709        _contextMenuLegacyPreviewController = nullptr;
     7710        _contextMenuLegacyMenu = nullptr;
     7711        _contextMenuHasRequestedLegacyData = NO;
     7712
     7713        UIContextMenuActionProvider actionMenuProvider = [weakSelf = WeakObjCPtr<WKContentView>(self)] (NSArray<UIMenuElement *> *suggestedActions) -> UIMenu * {
     7714            auto strongSelf = weakSelf.get();
     7715            if (!strongSelf)
     7716                return nil;
     7717            if (!strongSelf->_contextMenuHasRequestedLegacyData)
     7718                [strongSelf assignLegacyDataForContextMenuInteraction];
     7719
     7720            return strongSelf->_contextMenuLegacyMenu.get();
     7721        };
     7722
     7723        UIContextMenuContentPreviewProvider contentPreviewProvider = [weakSelf = WeakObjCPtr<WKContentView>(self)] () -> UIViewController * {
     7724            auto strongSelf = weakSelf.get();
     7725            if (!strongSelf)
     7726                return nil;
     7727            if (!strongSelf->_contextMenuHasRequestedLegacyData)
     7728                [strongSelf assignLegacyDataForContextMenuInteraction];
     7729
     7730            return strongSelf->_contextMenuLegacyPreviewController.get();
     7731        };
     7732
     7733        // FIXME: Should we provide an identifier and ASSERT in delegates if we don't match?
     7734        return completion([UIContextMenuConfiguration configurationWithIdentifier:nil previewProvider:contentPreviewProvider actionProvider:actionMenuProvider]);
     7735    }
     7736
     7737    auto completionBlock = makeBlockPtr([completion = makeBlockPtr(completion), linkURL = WTFMove(linkURL), weakSelf = WeakObjCPtr<WKContentView>(self)] (UIContextMenuConfiguration *configurationFromWKUIDelegate) mutable {
     7738
     7739        auto strongSelf = weakSelf.get();
     7740        if (!strongSelf)
     7741            return completion(nil);
     7742
     7743        if (!configurationFromWKUIDelegate) {
     7744
     7745            strongSelf->_contextMenuElementInfo = nil;
     7746
     7747            // At this point we have an object we might want to show a context menu for, but the
     7748            // client was unable to handle it. Before giving up, we ask DataDetectors.
     7749
     7750#if ENABLE(DATA_DETECTION)
     7751            // FIXME: Support JavaScript urls here. But make sure they don't show a preview.
     7752            // <rdar://problem/50572283>
     7753            if (!linkURL.protocolIsInHTTPFamily() && !WebCore::DataDetection::canBePresentedByDataDetectors(linkURL))
     7754                return completion(nil);
     7755
     7756            BEGIN_BLOCK_OBJC_EXCEPTIONS;
     7757            auto ddContextMenuActionClass = getDDContextMenuActionClass();
     7758            if ([ddContextMenuActionClass respondsToSelector:@selector(contextMenuConfigurationWithURL:inView:context:menuIdentifier:)]) {
     7759                NSDictionary *context = [strongSelf dataDetectionContextForPositionInformation:strongSelf->_positionInformation];
     7760                UIContextMenuConfiguration *configurationFromDD = [ddContextMenuActionClass contextMenuConfigurationForURL:linkURL identifier:strongSelf->_positionInformation.dataDetectorIdentifier selectedText:[strongSelf selectedText] results:strongSelf->_positionInformation.dataDetectorResults.get() inView:strongSelf.get() context:context menuIdentifier:nil];
     7761                if (strongSelf->_showLinkPreviews)
     7762                    return completion(configurationFromDD);
     7763                return completion([UIContextMenuConfiguration configurationWithIdentifier:[configurationFromDD identifier] previewProvider:[configurationFromDD previewProvider] actionProvider:[configurationFromDD actionProvider]]);
     7764            }
     7765            END_BLOCK_OBJC_EXCEPTIONS;
     7766#endif
     7767            return completion(nil);
     7768        }
     7769
     7770        id<NSCopying> identifier = [configurationFromWKUIDelegate identifier];
     7771        UIContextMenuContentPreviewProvider contentPreviewProvider = [configurationFromWKUIDelegate previewProvider];
     7772        UIContextMenuActionProvider actionMenuProvider = [configurationFromWKUIDelegate actionProvider];
     7773
     7774        auto actionProviderWrapper = [actionProviderFromUIDelegate = makeBlockPtr(actionMenuProvider), weakSelf = WTFMove(weakSelf)] (NSArray<UIMenuElement *> *suggestedActions) -> UIMenu * {
     7775            auto strongSelf = weakSelf.get();
     7776            if (!strongSelf)
     7777                return nil;
     7778
     7779            auto elementInfo = adoptNS([[_WKActivatedElementInfo alloc] _initWithInteractionInformationAtPosition:strongSelf->_positionInformation]);
     7780            RetainPtr<NSArray<_WKElementAction *>> defaultActionsFromAssistant = strongSelf->_positionInformation.isLink ? [strongSelf->_actionSheetAssistant defaultActionsForLinkSheet:elementInfo.get()] : [strongSelf->_actionSheetAssistant defaultActionsForImageSheet:elementInfo.get()];
     7781
     7782            auto menuElements = menuElementsFromPreviewOrDefaults(nil, defaultActionsFromAssistant, elementInfo);
     7783
     7784            if (actionProviderFromUIDelegate)
     7785                return actionProviderFromUIDelegate(menuElements);
     7786
     7787            auto title = titleForMenu(strongSelf->_positionInformation.isLink, strongSelf->_showLinkPreviews, strongSelf->_positionInformation.url, strongSelf->_positionInformation.title);
     7788            return [UIMenu menuWithTitle:title children:menuElements];
     7789        };
     7790
     7791        completion([UIContextMenuConfiguration configurationWithIdentifier:identifier previewProvider:contentPreviewProvider actionProvider:actionProviderWrapper]);
     7792    });
     7793
     7794    _contextMenuElementInfo = wrapper(API::ContextMenuElementInfo::create(_positionInformation));
     7795    if ([uiDelegate respondsToSelector:@selector(_webView:contextMenuConfigurationForElement:completionHandler:)]) {
     7796        auto checker = WebKit::CompletionHandlerCallChecker::create(uiDelegate, @selector(_webView:contextMenuConfigurationForElement:completionHandler:));
     7797        [uiDelegate _webView:_webView contextMenuConfigurationForElement:_contextMenuElementInfo.get() completionHandler:makeBlockPtr([completionBlock = WTFMove(completionBlock), checker = WTFMove(checker)] (UIContextMenuConfiguration *configuration) {
     7798            if (checker->completionHandlerHasBeenCalled())
     7799                return;
     7800            checker->didCallCompletionHandler();
     7801            completionBlock(configuration);
     7802        }).get()];
     7803    } else if (_positionInformation.isLink && [uiDelegate respondsToSelector:@selector(webView:contextMenuConfigurationForElement:completionHandler:)]) {
     7804        auto checker = WebKit::CompletionHandlerCallChecker::create(uiDelegate, @selector(webView:contextMenuConfigurationForElement:completionHandler:));
     7805        [uiDelegate webView:_webView contextMenuConfigurationForElement:_contextMenuElementInfo.get() completionHandler:makeBlockPtr([completionBlock = WTFMove(completionBlock), checker = WTFMove(checker)] (UIContextMenuConfiguration *configuration) {
     7806            if (checker->completionHandlerHasBeenCalled())
     7807                return;
     7808            checker->didCallCompletionHandler();
     7809            completionBlock(configuration);
     7810        }).get()];
     7811    } else
     7812        completionBlock(nil);
     7813}
     7814
     7815static RetainPtr<UIImage> uiImageForImage(WebCore::Image* image)
     7816{
     7817    if (!image)
     7818        return nil;
     7819
     7820    auto cgImage = image->nativeImage();
     7821    if (!cgImage)
     7822        return nil;
     7823
     7824    return adoptNS([[UIImage alloc] initWithCGImage:cgImage.get()]);
     7825}
     7826
     7827// FIXME: This should be merged with createTargetedDragPreview in DragDropInteractionState.
     7828static RetainPtr<UITargetedPreview> createTargetedPreview(UIImage *image, UIView *rootView, UIView *previewContainer, const WebCore::FloatRect& frameInRootViewCoordinates, const Vector<WebCore::FloatRect>& clippingRectsInFrameCoordinates, UIColor *backgroundColor)
     7829{
     7830    if (frameInRootViewCoordinates.isEmpty() || !image)
     7831        return nil;
     7832
     7833    WebCore::FloatRect frameInContainerCoordinates = [rootView convertRect:frameInRootViewCoordinates toView:previewContainer];
     7834    if (frameInContainerCoordinates.isEmpty())
     7835        return nil;
     7836
     7837    WebCore::FloatSize scalingRatio = frameInContainerCoordinates.size() / frameInRootViewCoordinates.size();
     7838    NSMutableArray *clippingRectValuesInFrameCoordinates = [NSMutableArray arrayWithCapacity:clippingRectsInFrameCoordinates.size()];
     7839
     7840    for (auto rect : clippingRectsInFrameCoordinates) {
     7841        rect.scale(scalingRatio);
     7842        [clippingRectValuesInFrameCoordinates addObject:[NSValue valueWithCGRect:rect]];
     7843    }
     7844
     7845    RetainPtr<UIPreviewParameters> parameters;
     7846    if (clippingRectValuesInFrameCoordinates.count)
     7847        parameters = adoptNS([[UIPreviewParameters alloc] initWithTextLineRects:clippingRectValuesInFrameCoordinates]);
     7848    else
     7849        parameters = adoptNS([[UIPreviewParameters alloc] init]);
     7850
     7851    if (backgroundColor)
     7852        [parameters setBackgroundColor:backgroundColor];
     7853
     7854    CGPoint centerInContainerCoordinates = { CGRectGetMidX(frameInContainerCoordinates), CGRectGetMidY(frameInContainerCoordinates) };
     7855    auto target = adoptNS([[UIPreviewTarget alloc] initWithContainer:previewContainer center:centerInContainerCoordinates]);
     7856
     7857    auto imageView = adoptNS([[UIImageView alloc] initWithImage:image]);
     7858    [imageView setFrame:frameInContainerCoordinates];
     7859    return adoptNS([[UITargetedPreview alloc] initWithView:imageView.get() parameters:parameters.get() target:target.get()]);
     7860}
     7861
     7862- (UITargetedPreview *)_targetedPreview
     7863{
     7864    if (_positionInformation.isLink && _positionInformation.linkIndicator.contentImage) {
     7865        [self _startSuppressingSelectionAssistantForReason:WebKit::InteractionIsHappening];
     7866
     7867        auto indicator = _positionInformation.linkIndicator;
     7868        auto textIndicatorImage = uiImageForImage(indicator.contentImage.get());
     7869
     7870        return createTargetedPreview(textIndicatorImage.get(), self, self.unscaledView, indicator.textBoundingRectInRootViewCoordinates, indicator.textRectsInBoundingRectCoordinates, [UIColor colorWithCGColor:cachedCGColor(indicator.estimatedBackgroundColor)]).autorelease();
     7871    }
     7872
     7873    if ((_positionInformation.isAttachment || _positionInformation.isImage) && _positionInformation.image) {
     7874        [self _startSuppressingSelectionAssistantForReason:WebKit::InteractionIsHappening];
     7875
     7876        RetainPtr<CGImageRef> cgImage = _positionInformation.image->makeCGImageCopy();
     7877        auto image = adoptNS([[UIImage alloc] initWithCGImage:cgImage.get()]);
     7878
     7879        return createTargetedPreview(image.get(), self, self.unscaledView, _positionInformation.bounds, { }, nil).autorelease();
     7880    }
     7881
     7882    return nil;
     7883}
     7884
     7885- (UITargetedPreview *)contextMenuInteraction:(UIContextMenuInteraction *)interaction previewForHighlightingMenuWithConfiguration:(UIContextMenuConfiguration *)configuration
     7886{
     7887    return [self _targetedPreview];
     7888}
     7889
     7890- (void)contextMenuInteractionWillPresent:(UIContextMenuInteraction *)interaction
     7891{
     7892    if (!_webView)
     7893        return;
     7894    auto uiDelegate = static_cast<id<WKUIDelegatePrivate>>(_webView.UIDelegate);
     7895    if (!uiDelegate)
     7896        return;
     7897    if ([uiDelegate respondsToSelector:@selector(webView:contextMenuWillPresentForElement:)])
     7898        [uiDelegate webView:_webView contextMenuWillPresentForElement:_contextMenuElementInfo.get()];
     7899    else if ([uiDelegate respondsToSelector:@selector(_webView:contextMenuWillPresentForElement:)]) {
     7900        ALLOW_DEPRECATED_DECLARATIONS_BEGIN
     7901        [uiDelegate _webView:_webView contextMenuWillPresentForElement:_contextMenuElementInfo.get()];
     7902        ALLOW_DEPRECATED_DECLARATIONS_END
     7903    }
     7904}
     7905
     7906- (UITargetedPreview *)contextMenuInteraction:(UIContextMenuInteraction *)interaction previewForDismissingMenuWithConfiguration:(UIContextMenuConfiguration *)configuration
     7907{
     7908    return [self _targetedPreview];
     7909}
     7910
     7911- (void)contextMenuInteraction:(UIContextMenuInteraction *)interaction willCommitWithAnimator:(id<UIContextMenuInteractionCommitAnimating>)animator
     7912{
     7913    if (!_webView)
     7914        return;
     7915
     7916    [self _stopSuppressingSelectionAssistantForReason:WebKit::InteractionIsHappening];
     7917
     7918    auto uiDelegate = static_cast<id<WKUIDelegatePrivate>>(_webView.UIDelegate);
     7919    if (!uiDelegate)
     7920        return;
     7921
     7922    if (needsDeprecatedPreviewAPI(uiDelegate)) {
     7923
     7924        if (_positionInformation.isImage) {
     7925            if ([uiDelegate respondsToSelector:@selector(_webView:commitPreviewedImageWithURL:)]) {
     7926                const auto& imageURL = _positionInformation.imageURL;
     7927                if (imageURL.isEmpty() || !(imageURL.protocolIsInHTTPFamily() || imageURL.protocolIs("data")))
     7928                    return;
     7929                ALLOW_DEPRECATED_DECLARATIONS_BEGIN
     7930                [uiDelegate _webView:_webView commitPreviewedImageWithURL:(NSURL *)imageURL];
     7931                ALLOW_DEPRECATED_DECLARATIONS_END
     7932            }
     7933            return;
     7934        }
     7935
     7936        if ([uiDelegate respondsToSelector:@selector(webView:commitPreviewingViewController:)]) {
     7937            ALLOW_DEPRECATED_DECLARATIONS_BEGIN
     7938            if (auto viewController = _contextMenuLegacyPreviewController.get())
     7939                [uiDelegate webView:_webView commitPreviewingViewController:viewController];
     7940            ALLOW_DEPRECATED_DECLARATIONS_END
     7941            return;
     7942        }
     7943
     7944        if ([uiDelegate respondsToSelector:@selector(_webView:commitPreviewedViewController:)]) {
     7945            ALLOW_DEPRECATED_DECLARATIONS_BEGIN
     7946            if (auto viewController = _contextMenuLegacyPreviewController.get())
     7947                [uiDelegate _webView:_webView commitPreviewedViewController:viewController];
     7948            ALLOW_DEPRECATED_DECLARATIONS_END
     7949            return;
     7950        }
     7951
     7952        return;
     7953    }
     7954
     7955    if ([uiDelegate respondsToSelector:@selector(webView:contextMenuForElement:willCommitWithAnimator:)])
     7956        [uiDelegate webView:_webView contextMenuForElement:_contextMenuElementInfo.get() willCommitWithAnimator:animator];
     7957    else if ([uiDelegate respondsToSelector:@selector(_webView:contextMenuForElement:willCommitWithAnimator:)]) {
     7958        ALLOW_DEPRECATED_DECLARATIONS_BEGIN
     7959        [uiDelegate _webView:_webView contextMenuForElement:_contextMenuElementInfo.get() willCommitWithAnimator:animator];
     7960        ALLOW_DEPRECATED_DECLARATIONS_END
     7961    }
     7962}
     7963
     7964- (void)contextMenuInteractionDidEnd:(UIContextMenuInteraction *)interaction
     7965{
     7966    if (!_webView)
     7967        return;
     7968
     7969    [self _stopSuppressingSelectionAssistantForReason:WebKit::InteractionIsHappening];
     7970
     7971    // FIXME: This delegate is being called more than once by UIKit. <rdar://problem/51550291>
     7972    // This conditional avoids the WKUIDelegate being called twice too.
     7973    if (!_contextMenuElementInfo) {
     7974        auto uiDelegate = static_cast<id<WKUIDelegatePrivate>>(_webView.UIDelegate);
     7975        if ([uiDelegate respondsToSelector:@selector(webView:contextMenuDidEndForElement:)])
     7976            [uiDelegate webView:_webView contextMenuDidEndForElement:_contextMenuElementInfo.get()];
     7977        else if ([uiDelegate respondsToSelector:@selector(_webView:contextMenuDidEndForElement:)]) {
     7978            ALLOW_DEPRECATED_DECLARATIONS_BEGIN
     7979            [uiDelegate _webView:_webView contextMenuDidEndForElement:_contextMenuElementInfo.get()];
     7980            ALLOW_DEPRECATED_DECLARATIONS_END
     7981        }
     7982    }
     7983
     7984    _contextMenuLegacyPreviewController = nullptr;
     7985    _contextMenuLegacyMenu = nullptr;
     7986    _contextMenuHasRequestedLegacyData = NO;
     7987    _contextMenuElementInfo = nullptr;
     7988}
     7989
     7990@end
     7991
    74167992#else
    74177993
    74187994@implementation WKContentView (WKInteractionPreview)
    7419 
    7420 - (BOOL)shouldUsePreviewForLongPress
    7421 {
    7422     return NO;
    7423 }
    74247995
    74257996- (void)_registerPreview
     
    77678338@end
    77688339
    7769 #endif // USE(LONG_PRESS_FOR_LINK_PREVIEW)
     8340#endif // USE(UICONTEXTMENU)
    77708341
    77718342#endif // HAVE(LINK_PREVIEW)
Note: See TracChangeset for help on using the changeset viewer.