Title: [246865] trunk/Source/WebKit
Revision
246865
Author
[email protected]
Date
2019-06-26 18:04:48 -0700 (Wed, 26 Jun 2019)

Log Message

Expose UIAction identifiers for _WKElementActions
https://bugs.webkit.org/show_bug.cgi?id=199246
<rdar://problem/52218950>

Reviewed by Tim Horton.

In order for clients to create a contextual menu, they are given
a set of suggested UIActions, created from _WKElementActions.
By associating identifiers (strings) with the UIActions, clients
can inspect the suggestions and make a decision on whether or
not to include them in the final menu.

* UIProcess/API/Cocoa/_WKElementAction.h: Typedef UIActionIdentifier,
add a method to create a UIAction from an _WKElementAction, and a
helper to map between identifiers and types.

* UIProcess/API/Cocoa/_WKElementAction.mm:
(elementActionTypeToUIActionIdentifier): Helper to convert between the two types.
(uiActionIdentifierToElementActionType): The inverse of above.
(+[_WKElementAction elementActionTypeForUIActionIdentifier:]): A client given
a UIAction object can use this helper method to see what _WKElementActionType it
corresponds to.
(-[_WKElementAction uiActionForElementInfo:]): Used by WKContentViewInteraction to
create a UIAction from this _WKElementAction.

* UIProcess/ios/WKContentViewInteraction.mm:
(uiActionForLegacyPreviewAction): Renamed to make it clear this is a legacy approach.
(menuFromLegacyPreviewOrDefaultActions): Split these functions to separate the legacy
and non-legacy approach.
(-[WKContentView assignLegacyDataForContextMenuInteraction]):
(-[WKContentView continueContextMenuInteraction:]):
(uiActionForPreviewAction): Deleted.
(menuFromPreviewOrDefaults): Deleted.

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (246864 => 246865)


--- trunk/Source/WebKit/ChangeLog	2019-06-27 00:54:07 UTC (rev 246864)
+++ trunk/Source/WebKit/ChangeLog	2019-06-27 01:04:48 UTC (rev 246865)
@@ -1,3 +1,39 @@
+2019-06-26  Dean Jackson  <[email protected]>
+
+        Expose UIAction identifiers for _WKElementActions
+        https://bugs.webkit.org/show_bug.cgi?id=199246
+        <rdar://problem/52218950>
+
+        Reviewed by Tim Horton.
+
+        In order for clients to create a contextual menu, they are given
+        a set of suggested UIActions, created from _WKElementActions.
+        By associating identifiers (strings) with the UIActions, clients
+        can inspect the suggestions and make a decision on whether or
+        not to include them in the final menu.
+
+        * UIProcess/API/Cocoa/_WKElementAction.h: Typedef UIActionIdentifier,
+        add a method to create a UIAction from an _WKElementAction, and a
+        helper to map between identifiers and types.
+
+        * UIProcess/API/Cocoa/_WKElementAction.mm:
+        (elementActionTypeToUIActionIdentifier): Helper to convert between the two types.
+        (uiActionIdentifierToElementActionType): The inverse of above.
+        (+[_WKElementAction elementActionTypeForUIActionIdentifier:]): A client given
+        a UIAction object can use this helper method to see what _WKElementActionType it
+        corresponds to.
+        (-[_WKElementAction uiActionForElementInfo:]): Used by WKContentViewInteraction to
+        create a UIAction from this _WKElementAction.
+
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (uiActionForLegacyPreviewAction): Renamed to make it clear this is a legacy approach.
+        (menuFromLegacyPreviewOrDefaultActions): Split these functions to separate the legacy
+        and non-legacy approach.
+        (-[WKContentView assignLegacyDataForContextMenuInteraction]):
+        (-[WKContentView continueContextMenuInteraction:]):
+        (uiActionForPreviewAction): Deleted.
+        (menuFromPreviewOrDefaults): Deleted.
+
 2019-06-26  Wenson Hsieh  <[email protected]>
 
         [iPadOS] Fix another crash in -[UIPreviewTarget initWithContainer:center:transform:] when generating a fallback targeted preview

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKElementAction.h (246864 => 246865)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKElementAction.h	2019-06-27 00:54:07 UTC (rev 246864)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKElementAction.h	2019-06-27 01:04:48 UTC (rev 246865)
@@ -30,8 +30,11 @@
 #import <WebKit/WKBase.h>
 #import <WebKit/_WKActivatedElementInfo.h>
 
+@class UIAction;
 @class UIImage;
 
+typedef NSString *UIActionIdentifier;
+
 typedef void (^WKElementActionHandler)(_WKActivatedElementInfo *);
 typedef BOOL (^WKElementActionDismissalHandler)(void);
 
@@ -42,8 +45,8 @@
     _WKElementActionTypeSaveImage,
 #if !defined(TARGET_OS_IOS) || TARGET_OS_IOS
     _WKElementActionTypeAddToReadingList,
-    _WKElementActionTypeOpenInDefaultBrowser WK_API_AVAILABLE(ios(9_0)),
-    _WKElementActionTypeOpenInExternalApplication WK_API_AVAILABLE(ios(9_0)),
+    _WKElementActionTypeOpenInDefaultBrowser WK_API_AVAILABLE(ios(9.0)),
+    _WKElementActionTypeOpenInExternalApplication WK_API_AVAILABLE(ios(9.0)),
 #endif
     _WKElementActionTypeShare WK_API_AVAILABLE(macos(10.12), ios(10.0)),
     _WKElementActionTypeOpenInNewTab WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA)),
@@ -59,10 +62,13 @@
 + (instancetype)elementActionWithType:(_WKElementActionType)type customTitle:(NSString *)title;
 + (instancetype)elementActionWithTitle:(NSString *)title actionHandler:(WKElementActionHandler)handler;
 
-+ (UIImage *)imageForElementActionType:(_WKElementActionType)actionType WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
++ (UIImage *)imageForElementActionType:(_WKElementActionType)actionType WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(13.0));
++ (_WKElementActionType)elementActionTypeForUIActionIdentifier:(UIActionIdentifier)identifier WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(13.0));
 
-- (void)runActionWithElementInfo:(_WKActivatedElementInfo *)info WK_API_AVAILABLE(ios(9_0));
+- (void)runActionWithElementInfo:(_WKActivatedElementInfo *)info WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(9.0));
 
+- (UIAction *)uiActionForElementInfo:(_WKActivatedElementInfo *)elementInfo WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(13.0));
+
 @property (nonatomic, readonly) _WKElementActionType type;
 @property (nonatomic, readonly) NSString* title;
 @property (nonatomic, copy) WKElementActionDismissalHandler dismissalHandler;

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKElementAction.mm (246864 => 246865)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKElementAction.mm	2019-06-27 00:54:07 UTC (rev 246864)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKElementAction.mm	2019-06-27 01:04:48 UTC (rev 246865)
@@ -50,6 +50,20 @@
 
 typedef void (^WKElementActionHandlerInternal)(WKActionSheetAssistant *, _WKActivatedElementInfo *);
 
+static UIActionIdentifier const WKElementActionTypeCustomIdentifier = @"WKElementActionTypeCustom";
+static UIActionIdentifier const WKElementActionTypeOpenIdentifier = @"WKElementActionTypeOpen";
+static UIActionIdentifier const WKElementActionTypeCopyIdentifier = @"WKElementActionTypeCopy";
+static UIActionIdentifier const WKElementActionTypeSaveImageIdentifier = @"WKElementActionTypeSaveImage";
+#if !defined(TARGET_OS_IOS) || TARGET_OS_IOS
+static UIActionIdentifier const WKElementActionTypeAddToReadingListIdentifier = @"WKElementActionTypeAddToReadingList";
+static UIActionIdentifier const WKElementActionTypeOpenInDefaultBrowserIdentifier = @"WKElementActionTypeOpenInDefaultBrowser";
+static UIActionIdentifier const WKElementActionTypeOpenInExternalApplicationIdentifier = @"WKElementActionTypeOpenInExternalApplication";
+#endif
+static UIActionIdentifier const WKElementActionTypeShareIdentifier = @"WKElementActionTypeShare";
+static UIActionIdentifier const WKElementActionTypeOpenInNewTabIdentifier = @"WKElementActionTypeOpenInNewTab";
+static UIActionIdentifier const WKElementActionTypeOpenInNewWindowIdentifier = @"WKElementActionTypeOpenInNewWindow";
+static UIActionIdentifier const WKElementActionTypeDownloadIdentifier = @"WKElementActionTypeDownload";
+
 @implementation _WKElementAction  {
     RetainPtr<NSString> _title;
     WKElementActionHandlerInternal _actionHandler;
@@ -188,6 +202,99 @@
 }
 #endif
 
+#if USE(UICONTEXTMENU)
+static UIActionIdentifier elementActionTypeToUIActionIdentifier(_WKElementActionType actionType)
+{
+    switch (actionType) {
+    case _WKElementActionTypeCustom:
+        return WKElementActionTypeCustomIdentifier;
+    case _WKElementActionTypeOpen:
+        return WKElementActionTypeOpenIdentifier;
+    case _WKElementActionTypeCopy:
+        return WKElementActionTypeCopyIdentifier;
+    case _WKElementActionTypeSaveImage:
+        return WKElementActionTypeSaveImageIdentifier;
+#if !defined(TARGET_OS_IOS) || TARGET_OS_IOS
+    case _WKElementActionTypeAddToReadingList:
+        return WKElementActionTypeAddToReadingListIdentifier;
+    case _WKElementActionTypeOpenInDefaultBrowser:
+        return WKElementActionTypeOpenInDefaultBrowserIdentifier;
+    case _WKElementActionTypeOpenInExternalApplication:
+        return WKElementActionTypeOpenInExternalApplicationIdentifier;
+#endif
+    case _WKElementActionTypeShare:
+        return WKElementActionTypeShareIdentifier;
+    case _WKElementActionTypeOpenInNewTab:
+        return WKElementActionTypeOpenInNewTabIdentifier;
+    case _WKElementActionTypeOpenInNewWindow:
+        return WKElementActionTypeOpenInNewWindowIdentifier;
+    case _WKElementActionTypeDownload:
+        return WKElementActionTypeDownloadIdentifier;
+    }
+}
+
+static _WKElementActionType uiActionIdentifierToElementActionType(UIActionIdentifier identifier)
+{
+    if ([identifier isEqualToString:WKElementActionTypeCustomIdentifier])
+        return _WKElementActionTypeCustom;
+    if ([identifier isEqualToString:WKElementActionTypeOpenIdentifier])
+        return _WKElementActionTypeOpen;
+    if ([identifier isEqualToString:WKElementActionTypeCopyIdentifier])
+        return _WKElementActionTypeCopy;
+    if ([identifier isEqualToString:WKElementActionTypeSaveImageIdentifier])
+        return _WKElementActionTypeSaveImage;
+#if !defined(TARGET_OS_IOS) || TARGET_OS_IOS
+    if ([identifier isEqualToString:WKElementActionTypeAddToReadingListIdentifier])
+        return _WKElementActionTypeAddToReadingList;
+    if ([identifier isEqualToString:WKElementActionTypeOpenInDefaultBrowserIdentifier])
+        return _WKElementActionTypeOpenInDefaultBrowser;
+    if ([identifier isEqualToString:WKElementActionTypeOpenInExternalApplicationIdentifier])
+        return _WKElementActionTypeOpenInExternalApplication;
+#endif
+    if ([identifier isEqualToString:WKElementActionTypeShareIdentifier])
+        return _WKElementActionTypeShare;
+    if ([identifier isEqualToString:WKElementActionTypeOpenInNewTabIdentifier])
+        return _WKElementActionTypeOpenInNewTab;
+    if ([identifier isEqualToString:WKElementActionTypeOpenInNewWindowIdentifier])
+        return _WKElementActionTypeOpenInNewWindow;
+    if ([identifier isEqualToString:WKElementActionTypeDownloadIdentifier])
+        return _WKElementActionTypeDownload;
+
+    return _WKElementActionTypeCustom;
+}
+
++ (_WKElementActionType)elementActionTypeForUIActionIdentifier:(UIActionIdentifier)identifier
+{
+    return uiActionIdentifierToElementActionType(identifier);
+}
+
+- (UIAction *)uiActionForElementInfo:(_WKActivatedElementInfo *)elementInfo
+{
+    UIImage *image = [_WKElementAction imageForElementActionType:self.type];
+    UIActionIdentifier identifier = elementActionTypeToUIActionIdentifier(self.type);
+
+    return [UIAction actionWithTitle:self.title image:image identifier:identifier handler:[weakSelf = WeakObjCPtr<_WKElementAction>(self), weakElementInfo = WeakObjCPtr<_WKActivatedElementInfo>(elementInfo)] (UIAction *) {
+        auto strongSelf = weakSelf.get();
+        if (!strongSelf)
+            return;
+        auto strongElementInfo = weakElementInfo.get();
+        if (!strongElementInfo)
+            return;
+        [strongSelf runActionWithElementInfo:strongElementInfo.get()];
+    }];
+}
+#else
++ (_WKElementActionType)elementActionTypeForUIActionIdentifier:(UIActionIdentifier)identifier
+{
+    return _WKElementActionTypeCustom;
+}
+
+- (UIAction *)uiActionForElementInfo:(_WKActivatedElementInfo *)elementInfo
+{
+    return nil;
+}
+#endif
+
 @end
 
 #endif // PLATFORM(IOS_FAMILY)

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (246864 => 246865)


--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2019-06-27 00:54:07 UTC (rev 246864)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2019-06-27 01:04:48 UTC (rev 246865)
@@ -7530,7 +7530,7 @@
 }
 
 ALLOW_DEPRECATED_DECLARATIONS_BEGIN
-static NSArray<WKPreviewAction *> *wkPreviewActionsFromElementActions(NSArray<_WKElementAction *> *elementActions, _WKActivatedElementInfo *elementInfo)
+static NSArray<WKPreviewAction *> *wkLegacyPreviewActionsFromElementActions(NSArray<_WKElementAction *> *elementActions, _WKActivatedElementInfo *elementInfo)
 {
     NSMutableArray<WKPreviewAction *> *previewActions = [NSMutableArray arrayWithCapacity:[elementActions count]];
     for (_WKElementAction *elementAction in elementActions) {
@@ -7543,7 +7543,7 @@
     return previewActions;
 }
 
-static UIAction *uiActionForPreviewAction(UIPreviewAction *previewAction, UIViewController *previewViewController)
+static UIAction *uiActionForLegacyPreviewAction(UIPreviewAction *previewAction, UIViewController *previewViewController)
 {
     // UIPreviewActionItem.image is SPI, so no external clients will be able
     // to provide glyphs for actions <rdar://problem/50151855>.
@@ -7555,38 +7555,44 @@
 }
 ALLOW_DEPRECATED_DECLARATIONS_END
 
-static NSArray<UIMenuElement *> *menuElementsFromPreviewOrDefaults(UIViewController *previewViewController, const RetainPtr<NSArray>& defaultElementActions, RetainPtr<_WKActivatedElementInfo> elementInfo)
+static NSArray<UIMenuElement *> *menuElementsFromLegacyPreview(UIViewController *previewViewController)
 {
-    auto actions = [NSMutableArray arrayWithCapacity:defaultElementActions.get().count];
+    if (previewViewController)
+        return nil;
 
-    // One of the delegates may have provided a UIViewController with a previewActionItems array. If so,
-    // we need to convert each UIPreviewActionItem into a UIAction.
-    if (previewViewController) {
-        ALLOW_DEPRECATED_DECLARATIONS_BEGIN
-        NSArray<id<UIPreviewActionItem>> *previewActions = previewViewController.previewActionItems;
-        for (UIPreviewAction *previewAction in previewActions)
-            [actions addObject:uiActionForPreviewAction(previewAction, previewViewController)];
-        ALLOW_DEPRECATED_DECLARATIONS_END
-    }
+    ALLOW_DEPRECATED_DECLARATIONS_BEGIN
+    NSArray<id<UIPreviewActionItem>> *previewActions = previewViewController.previewActionItems;
+    if (!previewActions || ![previewActions count])
+        return nil;
 
-    if (![actions count]) {
-        // We either didn't get a custom preview UIViewController, or it didn't provide any actions
-        // so we should use the default set.
-        for (_WKElementAction *elementAction in defaultElementActions.get()) {
-            UIImage *image = [_WKElementAction imageForElementActionType:elementAction.type];
+    auto actions = [NSMutableArray arrayWithCapacity:previewActions.count];
 
-            [actions addObject:[UIAction actionWithTitle:elementAction.title image:image identifier:nil handler:^(UIAction *) {
-                [elementAction runActionWithElementInfo:elementInfo.get()];
-            }]];
-        }
-    }
+    for (UIPreviewAction *previewAction in previewActions)
+        [actions addObject:uiActionForLegacyPreviewAction(previewAction, previewViewController)];
+    ALLOW_DEPRECATED_DECLARATIONS_END
 
     return actions;
 }
 
-static UIMenu *menuFromPreviewOrDefaults(UIViewController *previewViewController, const RetainPtr<NSArray>& defaultElementActions, RetainPtr<_WKActivatedElementInfo> elementInfo, NSString *title)
+static NSArray<UIMenuElement *> *menuElementsFromDefaultActions(const RetainPtr<NSArray>& defaultElementActions, RetainPtr<_WKActivatedElementInfo> elementInfo)
 {
-    auto actions = menuElementsFromPreviewOrDefaults(previewViewController, defaultElementActions, elementInfo);
+    if (!defaultElementActions || !defaultElementActions.get().count)
+        return nil;
+
+    auto actions = [NSMutableArray arrayWithCapacity:defaultElementActions.get().count];
+
+    for (_WKElementAction *elementAction in defaultElementActions.get())
+        [actions addObject:[elementAction uiActionForElementInfo:elementInfo.get()]];
+
+    return actions;
+}
+
+static UIMenu *menuFromLegacyPreviewOrDefaultActions(UIViewController *previewViewController, const RetainPtr<NSArray>& defaultElementActions, RetainPtr<_WKActivatedElementInfo> elementInfo, NSString *title)
+{
+    auto actions = menuElementsFromLegacyPreview(previewViewController);
+    if (!actions)
+        actions = menuElementsFromDefaultActions(defaultElementActions, elementInfo);
+
     return [UIMenu menuWithTitle:title children:actions];
 }
 
@@ -7634,7 +7640,7 @@
 
         ALLOW_DEPRECATED_DECLARATIONS_BEGIN
         if ([uiDelegate respondsToSelector:@selector(webView:previewingViewControllerForElement:defaultActions:)]) {
-            auto defaultActions = wkPreviewActionsFromElementActions(defaultActionsFromAssistant.get(), elementInfo.get());
+            auto defaultActions = wkLegacyPreviewActionsFromElementActions(defaultActionsFromAssistant.get(), elementInfo.get());
             auto previewElementInfo = adoptNS([[WKPreviewElementInfo alloc] _initWithLinkURL:url]);
             previewViewController = [uiDelegate webView:_webView previewingViewControllerForElement:previewElementInfo.get() defaultActions:defaultActions];
         } else if ([uiDelegate respondsToSelector:@selector(_webView:previewViewControllerForURL:defaultActions:elementInfo:)])
@@ -7655,7 +7661,7 @@
                 if (_showLinkPreviews && dataDetectorsResult && dataDetectorsResult.get().previewProvider)
                     _contextMenuLegacyPreviewController = dataDetectorsResult.get().previewProvider();
                 if (dataDetectorsResult && dataDetectorsResult.get().actionProvider) {
-                    auto menuElements = menuElementsFromPreviewOrDefaults(nil, defaultActionsFromAssistant, elementInfo);
+                    auto menuElements = menuElementsFromDefaultActions(defaultActionsFromAssistant, elementInfo);
                     _contextMenuLegacyMenu = dataDetectorsResult.get().actionProvider(menuElements);
                 }
                 END_BLOCK_OBJC_EXCEPTIONS;
@@ -7665,7 +7671,7 @@
 #endif
 
         auto menuTitle = titleForMenu(true, _showLinkPreviews, url, _positionInformation.title);
-        _contextMenuLegacyMenu = menuFromPreviewOrDefaults(previewViewController, defaultActionsFromAssistant, elementInfo, menuTitle);
+        _contextMenuLegacyMenu = menuFromLegacyPreviewOrDefaultActions(previewViewController, defaultActionsFromAssistant, elementInfo, menuTitle);
 
     } else if (_positionInformation.isImage) {
         NSURL *nsURL = (NSURL *)url;
@@ -7693,7 +7699,7 @@
         ALLOW_DEPRECATED_DECLARATIONS_END
 
         auto menuTitle = titleForMenu(false, _showLinkPreviews, url, _positionInformation.title);
-        _contextMenuLegacyMenu = menuFromPreviewOrDefaults(previewViewController, defaultActionsFromAssistant, elementInfo, menuTitle);
+        _contextMenuLegacyMenu = menuFromLegacyPreviewOrDefaultActions(previewViewController, defaultActionsFromAssistant, elementInfo, menuTitle);
     }
 
     _contextMenuLegacyPreviewController = _showLinkPreviews ? previewViewController : nullptr;
@@ -7839,7 +7845,7 @@
             auto elementInfo = adoptNS([[_WKActivatedElementInfo alloc] _initWithInteractionInformationAtPosition:strongSelf->_positionInformation]);
             RetainPtr<NSArray<_WKElementAction *>> defaultActionsFromAssistant = strongSelf->_positionInformation.isLink ? [strongSelf->_actionSheetAssistant defaultActionsForLinkSheet:elementInfo.get()] : [strongSelf->_actionSheetAssistant defaultActionsForImageSheet:elementInfo.get()];
 
-            auto menuElements = menuElementsFromPreviewOrDefaults(nil, defaultActionsFromAssistant, elementInfo);
+            auto menuElements = menuElementsFromDefaultActions(defaultActionsFromAssistant, elementInfo);
 
             if (actionProviderFromUIDelegate)
                 return actionProviderFromUIDelegate(menuElements);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to