Add support for DataDetectors in WK (iOS).
authorenrica@apple.com <enrica@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 26 Jan 2016 02:18:13 +0000 (02:18 +0000)
committerenrica@apple.com <enrica@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 26 Jan 2016 02:18:13 +0000 (02:18 +0000)
https://bugs.webkit.org/show_bug.cgi?id=152989
rdar://problem/22855960

Reviewed by Tim Horton.

Source/WebCore:

Adding new helper functions for data detection related tasks.
The patch also fixes a bug when creating DOM ranges from DDQueryRange
spanning multiple fragments.

* editing/cocoa/DataDetection.h:
* editing/cocoa/DataDetection.mm:
(WebCore::DataDetection::isDataDetectorLink):
(WebCore::DataDetection::dataDetectorIdentifier):
(WebCore::detectItemAtPositionWithRange):
(WebCore::DataDetection::detectItemAroundHitTestResult):
(WebCore::resultIsURL):
(WebCore::removeResultLinksFromAnchor):
(WebCore::searchForLinkRemovingExistingDDLinks):
(WebCore::DataDetection::detectContentInRange):

Source/WebKit2:

Moving InteractionInformationAtPosition files to platform folder,
since this is only used on iOS and changing from .cpp to .mm.
The structure is extended to include data detection specific fields
and the relevant encode/decode functions have been updated to
handle the new fields.
The patch also adds a new WKUIDelegatePrivate method to allow
the client to provide additional context for data detection actions.

* Platform/spi/ios/UIKitSPI.h:
* Shared/InteractionInformationAtPosition.cpp: Removed.
* Shared/InteractionInformationAtPosition.h: Removed.
* Shared/ios/InteractionInformationAtPosition.h: Copied from Shared/InteractionInformationAtPosition.h.
* Shared/ios/InteractionInformationAtPosition.mm: Copied from Shared/InteractionInformationAtPosition.cpp.
(WebKit::InteractionInformationAtPosition::encode):
(WebKit::InteractionInformationAtPosition::decode):
* UIProcess/API/Cocoa/WKUIDelegatePrivate.h:
* UIProcess/WebPageProxy.h:
* UIProcess/ios/WKActionSheetAssistant.h:
* UIProcess/ios/WKActionSheetAssistant.mm:
(-[WKActionSheetAssistant showDataDetectorsSheet]):
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView actionSheetAssistantDidStopInteraction:]):
(-[WKContentView dataDetectionContextForActionSheetAssistant:]):
(-[WKContentView selectedTextForActionSheetAssistant:]):
(-[WKContentView _dataForPreviewItemController:atPosition:type:]):
* UIProcess/ios/WebPageProxyIOS.mm:
* WebKit2.xcodeproj/project.pbxproj:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::getPositionInformation):

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

15 files changed:
Source/WebCore/ChangeLog
Source/WebCore/editing/cocoa/DataDetection.h
Source/WebCore/editing/cocoa/DataDetection.mm
Source/WebKit2/ChangeLog
Source/WebKit2/Platform/spi/ios/UIKitSPI.h
Source/WebKit2/Shared/ios/InteractionInformationAtPosition.h [moved from Source/WebKit2/Shared/InteractionInformationAtPosition.h with 92% similarity]
Source/WebKit2/Shared/ios/InteractionInformationAtPosition.mm [moved from Source/WebKit2/Shared/InteractionInformationAtPosition.cpp with 64% similarity]
Source/WebKit2/UIProcess/API/Cocoa/WKUIDelegatePrivate.h
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/UIProcess/ios/WKActionSheetAssistant.h
Source/WebKit2/UIProcess/ios/WKActionSheetAssistant.mm
Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm
Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm
Source/WebKit2/WebKit2.xcodeproj/project.pbxproj
Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm

index f833480..ce151fb 100644 (file)
@@ -1,3 +1,26 @@
+2016-01-25  Enrica Casucci  <enrica@apple.com>
+
+        Add support for DataDetectors in WK (iOS).
+        https://bugs.webkit.org/show_bug.cgi?id=152989
+        rdar://problem/22855960
+
+        Reviewed by Tim Horton.
+
+        Adding new helper functions for data detection related tasks.
+        The patch also fixes a bug when creating DOM ranges from DDQueryRange
+        spanning multiple fragments.
+
+        * editing/cocoa/DataDetection.h:
+        * editing/cocoa/DataDetection.mm:
+        (WebCore::DataDetection::isDataDetectorLink):
+        (WebCore::DataDetection::dataDetectorIdentifier):
+        (WebCore::detectItemAtPositionWithRange):
+        (WebCore::DataDetection::detectItemAroundHitTestResult):
+        (WebCore::resultIsURL):
+        (WebCore::removeResultLinksFromAnchor):
+        (WebCore::searchForLinkRemovingExistingDDLinks):
+        (WebCore::DataDetection::detectContentInRange):
+
 2016-01-25  Myles C. Maxfield  <mmaxfield@apple.com>
 
         Remove broken cache from CSSFontFaceSource
index e428e56..0c55ec7 100644 (file)
 
 #import <wtf/RefPtr.h>
 #import <wtf/RetainPtr.h>
+#import <wtf/text/WTFString.h>
 
 OBJC_CLASS DDActionContext;
 OBJC_CLASS NSArray;
 
 namespace WebCore {
 
+class Element;
 class FloatRect;
 class HitTestResult;
 class Range;
@@ -55,6 +57,8 @@ public:
     WEBCORE_EXPORT static RetainPtr<DDActionContext> detectItemAroundHitTestResult(const HitTestResult&, FloatRect& detectedDataBoundingBox, RefPtr<Range>& detectedDataRange);
 #endif
     WEBCORE_EXPORT static NSArray *detectContentInRange(RefPtr<Range>& contextRange, DataDetectorTypes);
+    WEBCORE_EXPORT static bool isDataDetectorLink(Element*);
+    WEBCORE_EXPORT static String dataDetectorIdentifier(Element*);
 };
 
 } // namespace WebCore
index c94ac66..bed95c6 100644 (file)
 #import "VisibleUnits.h"
 #import "htmlediting.h"
 
-#if PLATFORM(IOS)
 const char *dataDetectorsURLScheme = "x-apple-data-detectors";
 const char *dataDetectorsAttributeTypeKey = "x-apple-data-detectors-type";
 const char *dataDetectorsAttributeResultKey = "x-apple-data-detectors-result";
-#endif
 
 namespace WebCore {
 
+bool DataDetection::isDataDetectorLink(Element* element)
+{
+    return element->getAttribute(dataDetectorsURLScheme) == "true";
+}
+
+String DataDetection::dataDetectorIdentifier(Element* element)
+{
+    return element->getAttribute(dataDetectorsAttributeResultKey);
+}
+
 #if PLATFORM(MAC)
 
 static RetainPtr<DDActionContext> detectItemAtPositionWithRange(VisiblePosition position, RefPtr<Range> contextRange, FloatRect& detectedDataBoundingBox, RefPtr<Range>& detectedDataRange)
@@ -145,7 +153,7 @@ RetainPtr<DDActionContext> DataDetection::detectItemAroundHitTestResult(const Hi
     return detectItemAtPositionWithRange(position, contextRange, detectedDataBoundingBox, detectedDataRange);
 }
 #endif // PLATFORM(MAC)
-    
+
 #if PLATFORM(IOS)
     
 static BOOL resultIsURL(DDResultRef result)
@@ -190,7 +198,7 @@ static void removeResultLinksFromAnchor(Node* node, Node* nodeParent)
     if (!node)
         return;
     
-    BOOL nodeIsDDAnchor = is<HTMLAnchorElement>(*node) && downcast<Element>(*node).getAttribute(get_DataDetectorsCore_DDURLScheme()) == "true";
+    BOOL nodeIsDDAnchor = is<HTMLAnchorElement>(*node) && downcast<Element>(*node).getAttribute(dataDetectorsURLScheme) == "true";
     
     RefPtr<NodeList> children = node->childNodes();
     unsigned childCount = children->length();
@@ -219,7 +227,7 @@ static bool searchForLinkRemovingExistingDDLinks(Node* startNode, Node* endNode)
     Node *node = startNode;
     while (node) {
         if (is<HTMLAnchorElement>(*node)) {
-            if (downcast<Element>(*node).getAttribute(get_DataDetectorsCore_DDURLScheme()) != "true")
+            if (downcast<Element>(*node).getAttribute(dataDetectorsURLScheme) != "true")
                 return true;
             removeResultLinksFromAnchor(node, node->parentElement());
         }
@@ -230,7 +238,7 @@ static bool searchForLinkRemovingExistingDDLinks(Node* startNode, Node* endNode)
             node = startNode->parentNode();
             while (node) {
                 if (is<HTMLAnchorElement>(*node)) {
-                    if (downcast<Element>(*node).getAttribute(get_DataDetectorsCore_DDURLScheme()) != "true")
+                    if (downcast<Element>(*node).getAttribute(dataDetectorsURLScheme) != "true")
                         return true;
                     removeResultLinksFromAnchor(node, node->parentElement());
                 }
@@ -448,8 +456,12 @@ NSArray *DataDetection::detectContentInRange(RefPtr<Range>& contextRange, DataDe
         CFIndex fragmentIndex = queryRange.start.queryIndex;
         if (fragmentIndex == queryRange.end.queryIndex)
             fragmentRanges.append(TextIterator::subrange(currentRange.get(), queryRange.start.offset, queryRange.end.offset - queryRange.start.offset));
-        else
-            fragmentRanges.append(currentRange);
+        else {
+            if (!queryRange.start.offset)
+                fragmentRanges.append(currentRange);
+            else
+                fragmentRanges.append(Range::create(currentRange->ownerDocument(), &currentRange->startContainer(), currentRange->startOffset() + queryRange.start.offset, &currentRange->endContainer(), currentRange->endOffset()));
+        }
         
         while (fragmentIndex < queryRange.end.queryIndex) {
             fragmentIndex++;
index 6157736..8a01016 100644 (file)
@@ -1,3 +1,41 @@
+2016-01-25  Enrica Casucci  <enrica@apple.com>
+
+        Add support for DataDetectors in WK (iOS).
+        https://bugs.webkit.org/show_bug.cgi?id=152989
+        rdar://problem/22855960
+
+        Reviewed by Tim Horton.
+
+        Moving InteractionInformationAtPosition files to platform folder,
+        since this is only used on iOS and changing from .cpp to .mm.
+        The structure is extended to include data detection specific fields
+        and the relevant encode/decode functions have been updated to
+        handle the new fields.
+        The patch also adds a new WKUIDelegatePrivate method to allow
+        the client to provide additional context for data detection actions.
+
+        * Platform/spi/ios/UIKitSPI.h:
+        * Shared/InteractionInformationAtPosition.cpp: Removed.
+        * Shared/InteractionInformationAtPosition.h: Removed.
+        * Shared/ios/InteractionInformationAtPosition.h: Copied from Shared/InteractionInformationAtPosition.h.
+        * Shared/ios/InteractionInformationAtPosition.mm: Copied from Shared/InteractionInformationAtPosition.cpp.
+        (WebKit::InteractionInformationAtPosition::encode):
+        (WebKit::InteractionInformationAtPosition::decode):
+        * UIProcess/API/Cocoa/WKUIDelegatePrivate.h:
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/ios/WKActionSheetAssistant.h:
+        * UIProcess/ios/WKActionSheetAssistant.mm:
+        (-[WKActionSheetAssistant showDataDetectorsSheet]):
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView actionSheetAssistantDidStopInteraction:]):
+        (-[WKContentView dataDetectionContextForActionSheetAssistant:]):
+        (-[WKContentView selectedTextForActionSheetAssistant:]):
+        (-[WKContentView _dataForPreviewItemController:atPosition:type:]):
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        * WebKit2.xcodeproj/project.pbxproj:
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::getPositionInformation):
+
 2016-01-25  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r195543.
index 1b8fcf2..f0efc5d 100644 (file)
@@ -842,5 +842,7 @@ extern NSString *const UIKeyInputPageUp;
 extern NSString *const UIKeyInputPageDown;
 
 extern const NSString *UIPreviewDataLink;
+extern const NSString *UIPreviewDataDDResult;
+extern const NSString *UIPreviewDataDDContext;
 
 WTF_EXTERN_C_END
@@ -47,6 +47,9 @@ struct InteractionInformationAtPosition {
     bool isImage { false };
     bool isAnimatedImage { false };
     bool isClickableElement { false };
+#if ENABLE(DATA_DETECTION)
+    bool isDataDetectorLink { false };
+#endif
     String url;
     String imageURL;
     String title;
@@ -54,6 +57,10 @@ struct InteractionInformationAtPosition {
     RefPtr<ShareableBitmap> image;
 
     WebCore::TextIndicatorData linkIndicator;
+#if ENABLE(DATA_DETECTION)
+    String dataDetectorIdentifier;
+    RetainPtr<NSArray> dataDetectorResults;
+#endif
 
     void encode(IPC::ArgumentEncoder&) const;
     static bool decode(IPC::ArgumentDecoder&, InteractionInformationAtPosition&);
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "config.h"
-#include "InteractionInformationAtPosition.h"
+#import "config.h"
+#import "InteractionInformationAtPosition.h"
 
-#include "Arguments.h"
-#include "WebCoreArgumentCoders.h"
+#import "ArgumentCodersCF.h"
+#import "Arguments.h"
+#import "WebCoreArgumentCoders.h"
+#import <WebCore/DataDetectorsCoreSPI.h>
+#import <WebCore/SoftLinking.h>
+
+SOFT_LINK_PRIVATE_FRAMEWORK(DataDetectorsCore)
+SOFT_LINK_CLASS(DataDetectorsCore, DDScannerResult)
 
 namespace WebKit {
 
 #if PLATFORM(IOS)
+
 void InteractionInformationAtPosition::encode(IPC::ArgumentEncoder& encoder) const
 {
     encoder << point;
@@ -53,6 +60,19 @@ void InteractionInformationAtPosition::encode(IPC::ArgumentEncoder& encoder) con
     if (image)
         image->createHandle(handle, SharedMemory::Protection::ReadOnly);
     encoder << handle;
+#if ENABLE(DATA_DETECTION)
+    encoder << isDataDetectorLink;
+    if (isDataDetectorLink) {
+        encoder << dataDetectorIdentifier;
+        RetainPtr<NSMutableData> data = adoptNS([[NSMutableData alloc] init]);
+        RetainPtr<NSKeyedArchiver> archiver = adoptNS([[NSKeyedArchiver alloc] initForWritingWithMutableData:data.get()]);
+        [archiver setRequiresSecureCoding:YES];
+        [archiver encodeObject:dataDetectorResults.get() forKey:@"dataDetectorResults"];
+        [archiver finishEncoding];
+        
+        IPC::encode(encoder, reinterpret_cast<CFDataRef>(data.get()));        
+    }
+#endif
 }
 
 bool InteractionInformationAtPosition::decode(IPC::ArgumentDecoder& decoder, InteractionInformationAtPosition& result)
@@ -106,6 +126,30 @@ bool InteractionInformationAtPosition::decode(IPC::ArgumentDecoder& decoder, Int
     if (!handle.isNull())
         result.image = ShareableBitmap::create(handle, SharedMemory::Protection::ReadOnly);
 
+#if ENABLE(DATA_DETECTION)
+    if (!decoder.decode(result.isDataDetectorLink))
+        return false;
+    
+    if (result.isDataDetectorLink) {
+        if (!decoder.decode(result.dataDetectorIdentifier))
+            return false;
+        RetainPtr<CFDataRef> data;
+        if (!IPC::decode(decoder, data))
+            return false;
+        
+        RetainPtr<NSKeyedUnarchiver> unarchiver = adoptNS([[NSKeyedUnarchiver alloc] initForReadingWithData:(NSData *)data.get()]);
+        [unarchiver setRequiresSecureCoding:YES];
+        @try {
+            result.dataDetectorResults = [unarchiver decodeObjectOfClasses:[NSSet setWithArray:@[ [NSArray class], getDDScannerResultClass()] ] forKey:@"dataDetectorResults"];
+        } @catch (NSException *exception) {
+            LOG_ERROR("Failed to decode NSArray of DDScanResult: %@", exception);
+            return false;
+        }
+        
+        [unarchiver finishDecoding];
+    }
+#endif
+
     return true;
 }
 #endif
index 70af43c..ffc7228 100644 (file)
@@ -59,7 +59,7 @@ struct UIEdgeInsets;
 - (void)_webViewDidExitFullscreen:(WKWebView *)webView WK_AVAILABLE(10_11, 8_3);
 
 - (void)_webView:(WKWebView *)webView imageOrMediaDocumentSizeChanged:(CGSize)size WK_AVAILABLE(WK_MAC_TBA, WK_IOS_TBA);
-
+- (NSDictionary *)_dataDetectionContextForWebView:(WKWebView *)webView WK_AVAILABLE(WK_MAC_TBA, WK_IOS_TBA);
 #if TARGET_OS_IPHONE
 - (BOOL)_webView:(WKWebView *)webView shouldIncludeAppLinkActionsForElement:(_WKActivatedElementInfo *)element WK_AVAILABLE(NA, 9_0);
 - (NSArray *)_webView:(WKWebView *)webView actionsForElement:(_WKActivatedElementInfo *)element defaultActions:(WK_ARRAY(_WKElementAction *) *)defaultActions;
index d4e579a..0aba67c 100644 (file)
@@ -38,7 +38,6 @@
 #include "EditingRange.h"
 #include "EditorState.h"
 #include "GeolocationPermissionRequestManagerProxy.h"
-#include "InteractionInformationAtPosition.h"
 #include "LayerTreeContext.h"
 #include "MessageSender.h"
 #include "NotificationPermissionRequestManagerProxy.h"
index face0cc..c855e2d 100644 (file)
@@ -55,6 +55,8 @@ struct InteractionInformationAtPosition;
 - (void)updatePositionInformationForActionSheetAssistant:(WKActionSheetAssistant *)assistant;
 - (void)actionSheetAssistant:(WKActionSheetAssistant *)assistant willStartInteractionWithElement:(_WKActivatedElementInfo *)element;
 - (void)actionSheetAssistantDidStopInteraction:(WKActionSheetAssistant *)assistant;
+- (NSDictionary *)dataDetectionContextForActionSheetAssistant:(WKActionSheetAssistant *)assistant;
+- (NSString *)selectedTextForActionSheetAssistant:(WKActionSheetAssistant *)assistant;
 
 @end
 
index 66a2178..8321135 100644 (file)
@@ -59,6 +59,10 @@ SOFT_LINK_PRIVATE_FRAMEWORK(TCC)
 SOFT_LINK(TCC, TCCAccessPreflight, TCCAccessPreflightResult, (CFStringRef service, CFDictionaryRef options), (service, options))
 SOFT_LINK_CONSTANT(TCC, kTCCServicePhotos, CFStringRef)
 
+@interface DDDetectionController (StagingToRemove)
+- (NSArray *)actionsForURL:(NSURL *)url identifier:(NSString *)identifier selectedText:(NSString *)selectedText results:(NSArray *)results context:(NSDictionary *)context;
+@end
+
 using namespace WebKit;
 
 #if HAVE(APP_LINKS)
@@ -414,14 +418,27 @@ static LSAppLink *appLinkForURL(NSURL *url)
     if (!delegate)
         return;
 
-    NSURL *targetURL = [NSURL URLWithString:[delegate positionInformationForActionSheetAssistant:self].url];
+    const WebKit::InteractionInformationAtPosition& positionInformation = [delegate positionInformationForActionSheetAssistant:self];
+    NSURL *targetURL = [NSURL _web_URLWithWTFString:positionInformation.url];
     if (!targetURL)
         return;
 
     if (![[getDDDetectionControllerClass() tapAndHoldSchemes] containsObject:[targetURL scheme]])
         return;
 
-    NSArray *dataDetectorsActions = [[getDDDetectionControllerClass() sharedController] actionsForAnchor:nil url:targetURL forFrame:nil];
+    DDDetectionController *controller = [getDDDetectionControllerClass() sharedController];
+    NSArray *dataDetectorsActions = nil;
+    if ([controller respondsToSelector:@selector(actionsForURL:identifier:selectedText:results:context:)]) {
+        NSDictionary *context = nil;
+        NSString *textAtSelection = nil;
+
+        if ([delegate respondsToSelector:@selector(dataDetectionContextForActionSheetAssistant:)])
+            context = [delegate dataDetectionContextForActionSheetAssistant:self];
+        if ([delegate respondsToSelector:@selector(selectedTextForActionSheetAssistant:)])
+            textAtSelection = [delegate selectedTextForActionSheetAssistant:self];
+        dataDetectorsActions = [controller actionsForURL:targetURL identifier:positionInformation.dataDetectorIdentifier selectedText:textAtSelection results:positionInformation.dataDetectorResults.get() context:context];
+    } else
+        dataDetectorsActions = [controller actionsForAnchor:nil url:targetURL forFrame:nil];
     if ([dataDetectorsActions count] == 0)
         return;
 
index 83a0723..5dd88c7 100644 (file)
@@ -62,6 +62,7 @@
 #import <MobileCoreServices/UTCoreTypes.h>
 #import <WebCore/Color.h>
 #import <WebCore/CoreGraphicsSPI.h>
+#import <WebCore/DataDetectorsCoreSPI.h>
 #import <WebCore/FloatQuad.h>
 #import <WebCore/Pasteboard.h>
 #import <WebCore/Path.h>
@@ -237,6 +238,10 @@ const CGFloat minimumTapHighlightRadius = 2.0;
 @end
 #endif
 
+@interface DDDetectionController (StagingToRemove)
+- (DDResultRef)resultForURL:(NSURL *)url identifier:(NSString *)identifier selectedText:(NSString *)selectedText results:(NSArray *)results context:(NSDictionary *)context extendedContext:(NSDictionary **)extendedContext;
+@end
+
 @interface WKFocusedElementInfo : NSObject <_WKFocusedElementInfo>
 - (instancetype)initWithAssistedNodeInformation:(const AssistedNodeInformation&)information isUserInitiated:(BOOL)isUserInitiated;
 @end
@@ -3471,6 +3476,20 @@ static bool isAssistableInputType(InputType type)
     _page->stopInteraction();
 }
 
+- (NSDictionary *)dataDetectionContextForActionSheetAssistant:(WKActionSheetAssistant *)assistant
+{
+    NSDictionary *context = nil;
+    id <WKUIDelegatePrivate> uiDelegate = static_cast<id <WKUIDelegatePrivate>>([_webView UIDelegate]);
+    if ([uiDelegate respondsToSelector:@selector(_dataDetectionContextForWebView:)])
+        context = [uiDelegate _dataDetectionContextForWebView:_webView];
+    return context;
+}
+
+- (NSString *)selectedTextForActionSheetAssistant:(WKActionSheetAssistant *)assistant
+{
+    return [self selectedText];
+}
+
 @end
 
 #if HAVE(LINK_PREVIEW)
@@ -3545,7 +3564,7 @@ static bool isAssistableInputType(InputType type)
         return nil;
 
     String absoluteLinkURL = _positionInformation.url;
-    if (!useImageURLForLink && (absoluteLinkURL.isEmpty() || !WebCore::protocolIsInHTTPFamily(absoluteLinkURL))) {
+    if (!useImageURLForLink && (absoluteLinkURL.isEmpty() || (!WebCore::protocolIsInHTTPFamily(absoluteLinkURL) && !_positionInformation.isDataDetectorLink))) {
         if (canShowLinkPreview && !canShowImagePreview)
             return nil;
         canShowLinkPreview = NO;
@@ -3558,6 +3577,22 @@ static bool isAssistableInputType(InputType type)
             dataForPreview[UIPreviewDataLink] = [NSURL _web_URLWithWTFString:_positionInformation.imageURL];
         else
             dataForPreview[UIPreviewDataLink] = [NSURL _web_URLWithWTFString:_positionInformation.url];
+        if (_positionInformation.isDataDetectorLink) {
+            NSDictionary *context = nil;
+            id <WKUIDelegatePrivate> uiDelegate = static_cast<id <WKUIDelegatePrivate>>([_webView UIDelegate]);
+            if ([uiDelegate respondsToSelector:@selector(_dataDetectionContextForWebView:)])
+                context = [uiDelegate _dataDetectionContextForWebView:_webView];
+
+            DDDetectionController *controller = [getDDDetectionControllerClass() sharedController];
+            if ([controller respondsToSelector:@selector(resultForURL:identifier:selectedText:results:context:extendedContext:)]) {
+                NSDictionary *newContext = nil;
+                DDResultRef ddResult = [controller resultForURL:dataForPreview[UIPreviewDataLink] identifier:_positionInformation.dataDetectorIdentifier selectedText:[self selectedText] results:_positionInformation.dataDetectorResults.get() context:context extendedContext:&newContext];
+                if (ddResult)
+                    dataForPreview[UIPreviewDataDDResult] = (__bridge id)ddResult;
+                if (newContext)
+                    dataForPreview[UIPreviewDataDDContext] = newContext;
+            }
+        }
     } else if (canShowImagePreview) {
         *type = UIPreviewItemTypeImage;
         dataForPreview[UIPreviewDataLink] = [NSURL _web_URLWithWTFString:_positionInformation.imageURL];
index 13541e7..4bded8a 100644 (file)
@@ -31,6 +31,7 @@
 #import "APIUIClient.h"
 #import "DataReference.h"
 #import "EditingRange.h"
+#import "InteractionInformationAtPosition.h"
 #import "NativeWebKeyboardEvent.h"
 #import "PageClient.h"
 #import "RemoteLayerTreeDrawingAreaProxy.h"
index b36976f..c46835d 100644 (file)
                C574A58112E66681002DFE98 /* PasteboardTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = C574A57F12E66681002DFE98 /* PasteboardTypes.h */; };
                C574A58212E66681002DFE98 /* PasteboardTypes.mm in Sources */ = {isa = PBXBuildFile; fileRef = C574A58012E66681002DFE98 /* PasteboardTypes.mm */; };
                C58CDF2A1887548B00871536 /* InteractionInformationAtPosition.h in Headers */ = {isa = PBXBuildFile; fileRef = C58CDF281887548B00871536 /* InteractionInformationAtPosition.h */; };
-               C58CDF2D1887609F00871536 /* InteractionInformationAtPosition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C58CDF2B1887609F00871536 /* InteractionInformationAtPosition.cpp */; };
-               C58CDF2E1887609F00871536 /* InteractionInformationAtPosition.h in Headers */ = {isa = PBXBuildFile; fileRef = C58CDF2C1887609F00871536 /* InteractionInformationAtPosition.h */; };
                C59C4A5818B81174007BDCB6 /* AssistedNodeInformation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C59C4A5618B81174007BDCB6 /* AssistedNodeInformation.cpp */; };
                C59C4A5918B81174007BDCB6 /* AssistedNodeInformation.h in Headers */ = {isa = PBXBuildFile; fileRef = C59C4A5718B81174007BDCB6 /* AssistedNodeInformation.h */; };
+               C5BCE5DE1C50766300CDE3FA /* InteractionInformationAtPosition.mm in Sources */ = {isa = PBXBuildFile; fileRef = C5BCE5DB1C50761D00CDE3FA /* InteractionInformationAtPosition.mm */; };
+               C5BCE5DF1C50766A00CDE3FA /* InteractionInformationAtPosition.h in Headers */ = {isa = PBXBuildFile; fileRef = C5BCE5DA1C50761D00CDE3FA /* InteractionInformationAtPosition.h */; };
                C5E1AFE816B20B67006CC1F2 /* WKWebArchive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC329DA516ACE5A900316DE2 /* WKWebArchive.cpp */; };
                C5E1AFE916B20B75006CC1F2 /* WKWebArchive.h in Headers */ = {isa = PBXBuildFile; fileRef = BC329DA616ACE5A900316DE2 /* WKWebArchive.h */; settings = {ATTRIBUTES = (Private, ); }; };
                C5E1AFEA16B20B7B006CC1F2 /* WKWebArchiveResource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC329DA916ACE5BF00316DE2 /* WKWebArchiveResource.cpp */; };
                C574A57F12E66681002DFE98 /* PasteboardTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PasteboardTypes.h; sourceTree = "<group>"; };
                C574A58012E66681002DFE98 /* PasteboardTypes.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PasteboardTypes.mm; sourceTree = "<group>"; };
                C58CDF281887548B00871536 /* InteractionInformationAtPosition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InteractionInformationAtPosition.h; sourceTree = "<group>"; };
-               C58CDF2B1887609F00871536 /* InteractionInformationAtPosition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InteractionInformationAtPosition.cpp; sourceTree = "<group>"; };
-               C58CDF2C1887609F00871536 /* InteractionInformationAtPosition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InteractionInformationAtPosition.h; sourceTree = "<group>"; };
                C59C4A5618B81174007BDCB6 /* AssistedNodeInformation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AssistedNodeInformation.cpp; sourceTree = "<group>"; };
                C59C4A5718B81174007BDCB6 /* AssistedNodeInformation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AssistedNodeInformation.h; sourceTree = "<group>"; };
+               C5BCE5DA1C50761D00CDE3FA /* InteractionInformationAtPosition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InteractionInformationAtPosition.h; path = ios/InteractionInformationAtPosition.h; sourceTree = "<group>"; };
+               C5BCE5DB1C50761D00CDE3FA /* InteractionInformationAtPosition.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = InteractionInformationAtPosition.mm; path = ios/InteractionInformationAtPosition.mm; sourceTree = "<group>"; };
                C5FA1ED118E1062200B3F402 /* WKAirPlayRoutePicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WKAirPlayRoutePicker.h; path = ios/forms/WKAirPlayRoutePicker.h; sourceTree = "<group>"; };
                C5FA1ED218E1062200B3F402 /* WKAirPlayRoutePicker.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = WKAirPlayRoutePicker.mm; path = ios/forms/WKAirPlayRoutePicker.mm; sourceTree = "<group>"; };
                C98C48A31B6FD4C300145103 /* WebMediaSessionFocusManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebMediaSessionFocusManager.cpp; sourceTree = "<group>"; };
                                1AC75A1A1B3368270056745B /* HangDetectionDisabler.h */,
                                F638954F133BEF38008941D5 /* HTTPCookieAcceptPolicy.h */,
                                BCCF6B2312C93E7A008F9C35 /* ImageOptions.h */,
-                               C58CDF2B1887609F00871536 /* InteractionInformationAtPosition.cpp */,
-                               C58CDF2C1887609F00871536 /* InteractionInformationAtPosition.h */,
                                1A92DC1212F8BAB90017AF65 /* LayerTreeContext.cpp */,
                                1A92DC1012F8BA460017AF65 /* LayerTreeContext.h */,
                                2D50366A1BCDE17900E20BB3 /* NativeWebGestureEvent.h */,
                        children = (
                                A7E93CEB192531AA00A1DC48 /* ChildProcessIOS.mm */,
                                2DA9449D1884E4F000ED86DB /* GestureTypes.h */,
+                               C5BCE5DA1C50761D00CDE3FA /* InteractionInformationAtPosition.h */,
+                               C5BCE5DB1C50761D00CDE3FA /* InteractionInformationAtPosition.mm */,
                                2DA944971884E4F000ED86DB /* NativeWebKeyboardEventIOS.mm */,
                                2DA944981884E4F000ED86DB /* NativeWebTouchEventIOS.mm */,
                                A118A9EC1907AD6F00F7C92B /* QuickLookDocumentData.cpp */,
                                C5E1AFED16B21017006CC1F2 /* APIWebArchive.h in Headers */,
                                C5E1AFEF16B21029006CC1F2 /* APIWebArchiveResource.h in Headers */,
                                1A4832C81A9BC13C008B4DFE /* APIWebsiteDataRecord.h in Headers */,
+                               C5BCE5DF1C50766A00CDE3FA /* InteractionInformationAtPosition.h in Headers */,
                                1A3635AA1A3144A300ED6197 /* APIWebsiteDataStore.h in Headers */,
                                1A6563E51B7A8C50009CF787 /* APIWindowFeatures.h in Headers */,
                                1AD4C1931B39F33200ABC28E /* ApplicationStateTracker.h in Headers */,
                                BCA8C6B011E3C08700812FB7 /* InjectedBundlePageUIClient.h in Headers */,
                                BC33E0D112408E8600360F3F /* InjectedBundleRangeHandle.h in Headers */,
                                BC14DF77120B5B7900826C0C /* InjectedBundleScriptWorld.h in Headers */,
-                               C58CDF2E1887609F00871536 /* InteractionInformationAtPosition.h in Headers */,
                                C58CDF2A1887548B00871536 /* InteractionInformationAtPosition.h in Headers */,
                                1AE49A4911FFA8CE0048B464 /* JSNPMethod.h in Headers */,
                                1AE4987811FF7FAA0048B464 /* JSNPObject.h in Headers */,
                                BCA8C6AF11E3C08700812FB7 /* InjectedBundlePageUIClient.cpp in Sources */,
                                BC33E0D212408E8600360F3F /* InjectedBundleRangeHandle.cpp in Sources */,
                                BC14DF78120B5B7900826C0C /* InjectedBundleScriptWorld.cpp in Sources */,
-                               C58CDF2D1887609F00871536 /* InteractionInformationAtPosition.cpp in Sources */,
                                1AE49A4A11FFA8CE0048B464 /* JSNPMethod.cpp in Sources */,
                                1AE4987911FF7FAA0048B464 /* JSNPObject.cpp in Sources */,
                                BCE0937714FB128C001138D9 /* LayerHostingContext.mm in Sources */,
                                512F58F912A88A5400629530 /* WKCredential.cpp in Sources */,
                                BC4075F7124FF0270068F20A /* WKData.cpp in Sources */,
                                1AFF49001833DE78009AB15A /* WKDeprecatedFunctions.cpp in Sources */,
+                               C5BCE5DE1C50766300CDE3FA /* InteractionInformationAtPosition.mm in Sources */,
                                BC4075F9124FF0270068F20A /* WKDictionary.cpp in Sources */,
                                BC017D0816260FF4007054F5 /* WKDOMDocument.mm in Sources */,
                                BC017D0A16260FF4007054F5 /* WKDOMElement.mm in Sources */,
index 92caed1..18ac8c0 100644 (file)
@@ -50,6 +50,7 @@
 #import "WebProcess.h"
 #import <CoreText/CTFont.h>
 #import <WebCore/Chrome.h>
+#import <WebCore/DataDetection.h>
 #import <WebCore/DiagnosticLoggingClient.h>
 #import <WebCore/DiagnosticLoggingKeys.h>
 #import <WebCore/Element.h>
@@ -2202,6 +2203,13 @@ void WebPage::getPositionInformation(const IntPoint& point, InteractionInformati
                         if (textIndicator)
                             info.linkIndicator = textIndicator->data();
                     }
+#if ENABLE(DATA_DETECTION)
+                    info.isDataDetectorLink = DataDetection::isDataDetectorLink(element);
+                    if (info.isDataDetectorLink) {
+                        info.dataDetectorIdentifier = DataDetection::dataDetectorIdentifier(element);
+                        info.dataDetectorResults = element->document().frame()->dataDetectionResults();
+                    }
+#endif
                 } else if (element->renderer() && element->renderer()->isRenderImage()) {
                     info.isImage = true;
                     auto& renderImage = downcast<RenderImage>(*(element->renderer()));