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);