- Revision
- 213170
- Author
- commit-qu...@webkit.org
- Date
- 2017-02-28 13:28:58 -0800 (Tue, 28 Feb 2017)
Log Message
Add delegate method to handle images with alternate data.
https://bugs.webkit.org/show_bug.cgi?id=168785
<rdar://problem/28776219>
Add delegate methods to WKUIDelegatePrivate so that a WebKit client can provide alternate URL or data for an image
before long-press or preview. When an image has alternate URL or data, we can change the actions accordingly.
Patch by Yongjun Zhang <yongjun_zh...@apple.com> on 2017-02-28
Reviewed by Enrica Casucci.
* UIProcess/API/Cocoa/WKUIDelegatePrivate.h: Add two delegate methods _webView:getAlternateURLFromImage:completionHandler:
and _webView:alternateURLFromImage:userInfo;
* UIProcess/API/Cocoa/_WKActivatedElementInfo.h: Add an readonly property userInfo so that alternate data can be
carried by _WKActivatedElementInfo and be processed by WebKit client.
* UIProcess/API/Cocoa/_WKActivatedElementInfo.mm:
(-[_WKActivatedElementInfo _initWithType:URL:location:title:ID:rect:image:]):
(-[_WKActivatedElementInfo _initWithType:URL:location:title:ID:rect:image:userInfo:]): A new initializer that also takes userInfo.
(-[_WKActivatedElementInfo userInfo]):
* UIProcess/API/Cocoa/_WKActivatedElementInfoInternal.h: A new delegate method for WKActionSheetAssistantDelegate to fetch
alternate data before showing image sheet.
* UIProcess/ios/WKActionSheetAssistant.h:
* UIProcess/ios/WKActionSheetAssistant.mm:
(-[WKActionSheetAssistant showImageSheet]): Before showing the image sheet, if the image doesn't have linked URL (i.e. not a image
link), try to fetch its alternate URL and data.
(-[WKActionSheetAssistant defaultActionsForImageSheet:]): Drive-by fix. We always use positionInformation's URL to populate the
actions, however, we should use elementInfo's URL since the two URLs could mismatch.
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView actionSheetAssistant:getAlternateURLForImage:completion:]):
(-[WKContentView _presentedViewControllerForPreviewItemController:]): Before previewing an image, synchronously get alternate
data for the image and update the actions accordingly.
Modified Paths
Diff
Modified: trunk/Source/WebKit2/ChangeLog (213169 => 213170)
--- trunk/Source/WebKit2/ChangeLog 2017-02-28 21:26:27 UTC (rev 213169)
+++ trunk/Source/WebKit2/ChangeLog 2017-02-28 21:28:58 UTC (rev 213170)
@@ -1,3 +1,35 @@
+2017-02-28 Yongjun Zhang <yongjun_zh...@apple.com>
+
+ Add delegate method to handle images with alternate data.
+ https://bugs.webkit.org/show_bug.cgi?id=168785
+ <rdar://problem/28776219>
+
+ Add delegate methods to WKUIDelegatePrivate so that a WebKit client can provide alternate URL or data for an image
+ before long-press or preview. When an image has alternate URL or data, we can change the actions accordingly.
+
+ Reviewed by Enrica Casucci.
+
+ * UIProcess/API/Cocoa/WKUIDelegatePrivate.h: Add two delegate methods _webView:getAlternateURLFromImage:completionHandler:
+ and _webView:alternateURLFromImage:userInfo;
+ * UIProcess/API/Cocoa/_WKActivatedElementInfo.h: Add an readonly property userInfo so that alternate data can be
+ carried by _WKActivatedElementInfo and be processed by WebKit client.
+ * UIProcess/API/Cocoa/_WKActivatedElementInfo.mm:
+ (-[_WKActivatedElementInfo _initWithType:URL:location:title:ID:rect:image:]):
+ (-[_WKActivatedElementInfo _initWithType:URL:location:title:ID:rect:image:userInfo:]): A new initializer that also takes userInfo.
+ (-[_WKActivatedElementInfo userInfo]):
+ * UIProcess/API/Cocoa/_WKActivatedElementInfoInternal.h: A new delegate method for WKActionSheetAssistantDelegate to fetch
+ alternate data before showing image sheet.
+ * UIProcess/ios/WKActionSheetAssistant.h:
+ * UIProcess/ios/WKActionSheetAssistant.mm:
+ (-[WKActionSheetAssistant showImageSheet]): Before showing the image sheet, if the image doesn't have linked URL (i.e. not a image
+ link), try to fetch its alternate URL and data.
+ (-[WKActionSheetAssistant defaultActionsForImageSheet:]): Drive-by fix. We always use positionInformation's URL to populate the
+ actions, however, we should use elementInfo's URL since the two URLs could mismatch.
+ * UIProcess/ios/WKContentViewInteraction.mm:
+ (-[WKContentView actionSheetAssistant:getAlternateURLForImage:completion:]):
+ (-[WKContentView _presentedViewControllerForPreviewItemController:]): Before previewing an image, synchronously get alternate
+ data for the image and update the actions accordingly.
+
2017-02-28 Brady Eidson <beid...@apple.com>
Refactor WebViewImpl creation in preparation for supporting multiple WebsiteDataStores.
Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKUIDelegatePrivate.h (213169 => 213170)
--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKUIDelegatePrivate.h 2017-02-28 21:26:27 UTC (rev 213169)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKUIDelegatePrivate.h 2017-02-28 21:28:58 UTC (rev 213170)
@@ -84,6 +84,8 @@
- (UIViewController *)_webView:(WKWebView *)webView previewViewControllerForURL:(NSURL *)url defaultActions:(NSArray<_WKElementAction *> *)actions elementInfo:(_WKActivatedElementInfo *)elementInfo WK_API_AVAILABLE(ios(9.0));
- (UIViewController *)_webView:(WKWebView *)webView previewViewControllerForAnimatedImageAtURL:(NSURL *)url defaultActions:(NSArray<_WKElementAction *> *)actions elementInfo:(_WKActivatedElementInfo *)elementInfo imageSize:(CGSize)imageSize WK_API_AVAILABLE(ios(9.0));
- (UIViewController *)_presentingViewControllerForWebView:(WKWebView *)webView WK_API_AVAILABLE(ios(10.0));
+- (void)_webView:(WKWebView *)webView getAlternateURLFromImage:(UIImage *)image completionHandler:(void (^)(NSURL *alternateURL, NSDictionary *userInfo))completionHandler WK_API_AVAILABLE(ios(WK_IOS_TBA));
+- (NSURL *)_webView:(WKWebView *)webView alternateURLFromImage:(UIImage *)image userInfo:(NSDictionary **)userInfo WK_API_AVAILABLE(ios(WK_IOS_TBA));
#else
- (NSMenu *)_webView:(WKWebView *)webView contextMenu:(NSMenu *)menu forElement:(_WKContextMenuElementInfo *)element WK_API_AVAILABLE(macosx(10.12));
- (NSMenu *)_webView:(WKWebView *)webView contextMenu:(NSMenu *)menu forElement:(_WKContextMenuElementInfo *)element userInfo:(id <NSSecureCoding>)userInfo WK_API_AVAILABLE(macosx(10.12));
Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKActivatedElementInfo.h (213169 => 213170)
--- trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKActivatedElementInfo.h 2017-02-28 21:26:27 UTC (rev 213169)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKActivatedElementInfo.h 2017-02-28 21:28:58 UTC (rev 213170)
@@ -48,6 +48,7 @@
@property (nonatomic, readonly) CGRect boundingRect;
@property (nonatomic, readonly) NSString *ID WK_API_AVAILABLE(macosx(10.12), ios(10.0));
#if TARGET_OS_IPHONE
+@property (nonatomic, readonly) NSDictionary *userInfo;
@property (nonatomic, readonly, copy) UIImage *image;
#else
@property (nonatomic, readonly, copy) NSImage *image;
Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKActivatedElementInfo.mm (213169 => 213170)
--- trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKActivatedElementInfo.mm 2017-02-28 21:26:27 UTC (rev 213169)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKActivatedElementInfo.mm 2017-02-28 21:28:58 UTC (rev 213170)
@@ -47,6 +47,7 @@
RefPtr<WebKit::ShareableBitmap> _image;
#if PLATFORM(IOS)
RetainPtr<UIImage> _uiImage;
+ RetainPtr<NSDictionary> _userInfo;
#endif
#if PLATFORM(MAC)
RetainPtr<NSImage> _nsImage;
@@ -55,6 +56,11 @@
- (instancetype)_initWithType:(_WKActivatedElementType)type URL:(NSURL *)url location:(CGPoint)location title:(NSString *)title ID:(NSString *)ID rect:(CGRect)rect image:(WebKit::ShareableBitmap*)image
{
+ return [self _initWithType:type URL:url location:location title:title ID:ID rect:rect image:image userInfo:nil];
+}
+
+- (instancetype)_initWithType:(_WKActivatedElementType)type URL:(NSURL *)url location:(CGPoint)location title:(NSString *)title ID:(NSString *)ID rect:(CGRect)rect image:(WebKit::ShareableBitmap*)image userInfo:(NSDictionary *)userInfo
+{
if (!(self = [super init]))
return nil;
@@ -65,6 +71,9 @@
_type = type;
_image = image;
_ID = ID;
+#if PLATFORM(IOS)
+ _userInfo = adoptNS([userInfo copy]);
+#endif
return self;
}
@@ -90,6 +99,11 @@
}
#if PLATFORM(IOS)
+- (NSDictionary *)userInfo
+{
+ return _userInfo.get();
+}
+
- (UIImage *)image
{
if (_uiImage)
Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKActivatedElementInfoInternal.h (213169 => 213170)
--- trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKActivatedElementInfoInternal.h 2017-02-28 21:26:27 UTC (rev 213169)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKActivatedElementInfoInternal.h 2017-02-28 21:28:58 UTC (rev 213170)
@@ -34,6 +34,7 @@
@interface _WKActivatedElementInfo ()
- (instancetype)_initWithType:(_WKActivatedElementType)type URL:(NSURL *)url location:(CGPoint)location title:(NSString *)title ID:(NSString *)ID rect:(CGRect)rect image:(WebKit::ShareableBitmap*)image;
+- (instancetype)_initWithType:(_WKActivatedElementType)type URL:(NSURL *)url location:(CGPoint)location title:(NSString *)title ID:(NSString *)ID rect:(CGRect)rect image:(WebKit::ShareableBitmap*)image userInfo:(NSDictionary *)userInfo;
@property (nonatomic, readonly) CGPoint _interactionLocation;
Modified: trunk/Source/WebKit2/UIProcess/ios/WKActionSheetAssistant.h (213169 => 213170)
--- trunk/Source/WebKit2/UIProcess/ios/WKActionSheetAssistant.h 2017-02-28 21:26:27 UTC (rev 213169)
+++ trunk/Source/WebKit2/UIProcess/ios/WKActionSheetAssistant.h 2017-02-28 21:28:58 UTC (rev 213170)
@@ -58,6 +58,7 @@
- (void)actionSheetAssistantDidStopInteraction:(WKActionSheetAssistant *)assistant;
- (NSDictionary *)dataDetectionContextForActionSheetAssistant:(WKActionSheetAssistant *)assistant;
- (NSString *)selectedTextForActionSheetAssistant:(WKActionSheetAssistant *)assistant;
+- (void)actionSheetAssistant:(WKActionSheetAssistant *)assistant getAlternateURLForImage:(UIImage *)image completion:(void (^)(NSURL *alternateURL, NSDictionary *userInfo))completion;
@end
Modified: trunk/Source/WebKit2/UIProcess/ios/WKActionSheetAssistant.mm (213169 => 213170)
--- trunk/Source/WebKit2/UIProcess/ios/WKActionSheetAssistant.mm 2017-02-28 21:26:27 UTC (rev 213169)
+++ trunk/Source/WebKit2/UIProcess/ios/WKActionSheetAssistant.mm 2017-02-28 21:28:58 UTC (rev 213170)
@@ -334,26 +334,44 @@
const auto& positionInformation = [delegate positionInformationForActionSheetAssistant:self];
- NSURL *targetURL = [NSURL _web_URLWithWTFString:positionInformation.url];
- auto elementBounds = positionInformation.bounds;
- auto elementInfo = adoptNS([[_WKActivatedElementInfo alloc] _initWithType:_WKActivatedElementTypeImage URL:targetURL location:positionInformation.request.point title:positionInformation.title ID:positionInformation.idAttribute rect:elementBounds image:positionInformation.image.get()]);
- if ([delegate respondsToSelector:@selector(actionSheetAssistant:showCustomSheetForElement:)] && [delegate actionSheetAssistant:self showCustomSheetForElement:elementInfo.get()])
- return;
- auto defaultActions = [self defaultActionsForImageSheet:elementInfo.get()];
+ void (^showImageSheetWithAlternateURLBlock)(NSURL*, NSDictionary *userInfo) = ^(NSURL *alternateURL, NSDictionary *userInfo) {
+ NSURL *targetURL = [NSURL _web_URLWithWTFString:positionInformation.url] ?: alternateURL;
+ auto elementBounds = positionInformation.bounds;
+ auto elementInfo = adoptNS([[_WKActivatedElementInfo alloc] _initWithType:_WKActivatedElementTypeImage URL:targetURL location:positionInformation.request.point title:positionInformation.title ID:positionInformation.idAttribute rect:elementBounds image:positionInformation.image.get() userInfo:userInfo]);
+ if ([delegate respondsToSelector:@selector(actionSheetAssistant:showCustomSheetForElement:)] && [delegate actionSheetAssistant:self showCustomSheetForElement:elementInfo.get()])
+ return;
+ auto defaultActions = [self defaultActionsForImageSheet:elementInfo.get()];
- RetainPtr<NSArray> actions = [delegate actionSheetAssistant:self decideActionsForElement:elementInfo.get() defaultActions:WTFMove(defaultActions)];
+ RetainPtr<NSArray> actions = [delegate actionSheetAssistant:self decideActionsForElement:elementInfo.get() defaultActions:WTFMove(defaultActions)];
- if (![actions count])
- return;
+ if (![actions count])
+ return;
- [self _createSheetWithElementActions:actions.get() showLinkTitle:YES];
- if (!_interactionSheet)
+ if (!alternateURL && userInfo) {
+ [UIApp _cancelAllTouches];
+ return;
+ }
+
+ [self _createSheetWithElementActions:actions.get() showLinkTitle:YES];
+ if (!_interactionSheet)
+ return;
+
+ _elementInfo = WTFMove(elementInfo);
+
+ if (![_interactionSheet presentSheet:[self _shouldPresentAtTouchLocationForElementRect:elementBounds] ? WKActionSheetPresentAtTouchLocation : WKActionSheetPresentAtElementRect])
+ [self cleanupSheet];
+ };
+
+ if (positionInformation.url.isEmpty() && positionInformation.image && [delegate respondsToSelector:@selector(actionSheetAssistant:getAlternateURLForImage:completion:)]) {
+ RetainPtr<UIImage> uiImage = adoptNS([[UIImage alloc] initWithCGImage:positionInformation.image->makeCGImageCopy().get()]);
+
+ [delegate actionSheetAssistant:self getAlternateURLForImage:uiImage.get() completion:^(NSURL *alternateURL, NSDictionary *userInfo) {
+ showImageSheetWithAlternateURLBlock(alternateURL, userInfo);
+ }];
return;
+ }
- _elementInfo = WTFMove(elementInfo);
-
- if (![_interactionSheet presentSheet:[self _shouldPresentAtTouchLocationForElementRect:elementBounds] ? WKActionSheetPresentAtTouchLocation : WKActionSheetPresentAtElementRect])
- [self cleanupSheet];
+ showImageSheetWithAlternateURLBlock(nil, nil);
}
- (BOOL)_shouldPresentAtTouchLocationForElementRect:(CGRect)elementRect
@@ -436,11 +454,10 @@
if (!delegate)
return nil;
- const auto& positionInformation = [delegate positionInformationForActionSheetAssistant:self];
- NSURL *targetURL = [NSURL _web_URLWithWTFString:positionInformation.url];
+ NSURL *targetURL = [elementInfo URL];
auto defaultActions = adoptNS([[NSMutableArray alloc] init]);
- if (!positionInformation.url.isEmpty()) {
+ if (targetURL) {
[self _appendOpenActionsForURL:targetURL actions:defaultActions.get() elementInfo:elementInfo];
[defaultActions addObject:[_WKElementAction _elementActionWithType:_WKElementActionTypeShare assistant:self]];
}
Modified: trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm (213169 => 213170)
--- trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm 2017-02-28 21:26:27 UTC (rev 213169)
+++ trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm 2017-02-28 21:28:58 UTC (rev 213170)
@@ -4012,6 +4012,17 @@
return [self selectedText];
}
+- (void)actionSheetAssistant:(WKActionSheetAssistant *)assistant getAlternateURLForImage:(UIImage *)image completion:(void (^)(NSURL *alternateURL, NSDictionary *userInfo))completion
+{
+ id <WKUIDelegatePrivate> uiDelegate = static_cast<id <WKUIDelegatePrivate>>([_webView UIDelegate]);
+ if ([uiDelegate respondsToSelector:@selector(_webView:getAlternateURLFromImage:completionHandler:)]) {
+ [uiDelegate _webView:_webView getAlternateURLFromImage:image completionHandler:^(NSURL *alternateURL, NSDictionary *userInfo) {
+ completion(alternateURL, userInfo);
+ }];
+ } else
+ completion(nil, nil);
+}
+
@end
@implementation WKContentView (WKTesting)
@@ -4257,12 +4268,27 @@
if (!isValidURLForImagePreview)
return nil;
- RetainPtr<_WKActivatedElementInfo> elementInfo = adoptNS([[_WKActivatedElementInfo alloc] _initWithType:_WKActivatedElementTypeImage URL:targetURL location:_positionInformation.request.point title:_positionInformation.title ID:_positionInformation.idAttribute rect:_positionInformation.bounds image:_positionInformation.image.get()]);
+ RetainPtr<NSURL> alternateURL = targetURL;
+ RetainPtr<NSDictionary> imageInfo;
+ RetainPtr<CGImageRef> cgImage = _positionInformation.image->makeCGImageCopy();
+ RetainPtr<UIImage> uiImage = adoptNS([[UIImage alloc] initWithCGImage:cgImage.get()]);
+ if ([uiDelegate respondsToSelector:@selector(_webView:alternateURLFromImage:userInfo:)]) {
+ NSDictionary *userInfo;
+ alternateURL = [uiDelegate _webView:_webView alternateURLFromImage:uiImage.get() userInfo:&userInfo];
+ imageInfo = userInfo;
+ }
+
+ RetainPtr<_WKActivatedElementInfo> elementInfo = adoptNS([[_WKActivatedElementInfo alloc] _initWithType:_WKActivatedElementTypeImage URL:alternateURL.get() location:_positionInformation.request.point title:_positionInformation.title ID:_positionInformation.idAttribute rect:_positionInformation.bounds image:_positionInformation.image.get() userInfo:imageInfo.get()]);
_page->startInteractionWithElementAtPosition(_positionInformation.request.point);
if ([uiDelegate respondsToSelector:@selector(_webView:willPreviewImageWithURL:)])
[uiDelegate _webView:_webView willPreviewImageWithURL:targetURL];
- return [[[WKImagePreviewViewController alloc] initWithCGImage:_positionInformation.image->makeCGImageCopy() defaultActions:[_actionSheetAssistant defaultActionsForImageSheet:elementInfo.get()] elementInfo:elementInfo] autorelease];
+
+ auto defaultActions = [_actionSheetAssistant defaultActionsForImageSheet:elementInfo.get()];
+ if (imageInfo && [uiDelegate respondsToSelector:@selector(_webView:actionsForElement:defaultActions:)])
+ defaultActions = [uiDelegate _webView:_webView actionsForElement:elementInfo.get() defaultActions:defaultActions.get()];
+
+ return [[[WKImagePreviewViewController alloc] initWithCGImage:cgImage defaultActions:defaultActions elementInfo:elementInfo] autorelease];
}
return nil;