Long pressing a phone number with spaces in it results in a link sheet instead of...
authortimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 14 Nov 2017 17:44:17 +0000 (17:44 +0000)
committertimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 14 Nov 2017 17:44:17 +0000 (17:44 +0000)
https://bugs.webkit.org/show_bug.cgi?id=179646
<rdar://problem/35337288>

Reviewed by Simon Fraser.

Source/WebCore:

* editing/cocoa/DataDetection.h:
* editing/cocoa/DataDetection.mm:
(WebCore::DataDetection::canBePresentedByDataDetectors):
(WebCore::DataDetection::isDataDetectorLink):
Expose canBePresentedByDataDetectors, which tests if the URL's
scheme is one of Data Detectors' known long-press schemes.

Source/WebKit:

* UIProcess/ios/WKActionSheetAssistant.mm:
(-[WKActionSheetAssistant showImageSheet]):
(-[WKActionSheetAssistant showLinkSheet]):
(-[WKActionSheetAssistant showDataDetectorsSheet]):
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _actionForLongPressFromPositionInformation:]):
(-[WKContentView _interactionShouldBeginFromPreviewItemController:forPosition:]):
Make use of canBePresentedByDataDetectors with our WebCore URL instead
of (sometimes unsucessfully) reparsing the URL with NSURL's parser.
Also, avoid a few unnecessary round-trips through String when converting
from URL to NSURL.

Tools:

* TestWebKitAPI/Tests/ios/ActionSheetTests.mm:
(-[ActionSheetObserver _dataDetectionContextForWebView:]):
(TestWebKitAPI::TEST):
Add a test that ensures that a phone number with spaces in it
invokes a data detectors sheet, not a normal link sheet.

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

Source/WebCore/ChangeLog
Source/WebCore/editing/cocoa/DataDetection.h
Source/WebCore/editing/cocoa/DataDetection.mm
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/ios/WKActionSheetAssistant.mm
Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/ios/ActionSheetTests.mm

index fd32c59..abddaf2 100644 (file)
@@ -1,3 +1,18 @@
+2017-11-14  Tim Horton  <timothy_horton@apple.com>
+
+        Long pressing a phone number with spaces in it results in a link sheet instead of a data detectors sheet
+        https://bugs.webkit.org/show_bug.cgi?id=179646
+        <rdar://problem/35337288>
+
+        Reviewed by Simon Fraser.
+
+        * editing/cocoa/DataDetection.h:
+        * editing/cocoa/DataDetection.mm:
+        (WebCore::DataDetection::canBePresentedByDataDetectors):
+        (WebCore::DataDetection::isDataDetectorLink):
+        Expose canBePresentedByDataDetectors, which tests if the URL's
+        scheme is one of Data Detectors' known long-press schemes.
+
 2017-11-14  Michael Catanzaro  <mcatanzaro@igalia.com>
 
         [GTK][WPE] Don't require brotli
index 21de062..f25faae 100644 (file)
@@ -62,6 +62,7 @@ public:
 #endif
     WEBCORE_EXPORT static NSArray *detectContentInRange(RefPtr<Range>& contextRange, DataDetectorTypes, NSDictionary *context);
 #if PLATFORM(IOS)
+    WEBCORE_EXPORT static bool canBePresentedByDataDetectors(const URL&);
     WEBCORE_EXPORT static bool isDataDetectorLink(Element&);
     WEBCORE_EXPORT static String dataDetectorIdentifier(Element&);
     WEBCORE_EXPORT static bool shouldCancelDefaultAction(Element&);
index 8f5ec93..f3e67e5 100644 (file)
@@ -152,12 +152,18 @@ RetainPtr<DDActionContext> DataDetection::detectItemAroundHitTestResult(const Hi
 #endif // PLATFORM(MAC)
 
 #if PLATFORM(IOS)
+
+bool DataDetection::canBePresentedByDataDetectors(const URL& url)
+{
+    return [softLink_DataDetectorsCore_DDURLTapAndHoldSchemes() containsObject:(NSString *)url.protocol().toStringWithoutCopying().convertToASCIILowercase()];
+}
+
 bool DataDetection::isDataDetectorLink(Element& element)
 {
     if (!is<HTMLAnchorElement>(element))
         return false;
 
-    return [softLink_DataDetectorsCore_DDURLTapAndHoldSchemes() containsObject:(NSString *)downcast<HTMLAnchorElement>(element).href().protocol().toStringWithoutCopying().convertToASCIILowercase()];
+    return canBePresentedByDataDetectors(downcast<HTMLAnchorElement>(element).href());
 }
 
 bool DataDetection::requiresExtendedContext(Element& element)
index 9e23638..13269b9 100644 (file)
@@ -1,3 +1,23 @@
+2017-11-14  Tim Horton  <timothy_horton@apple.com>
+
+        Long pressing a phone number with spaces in it results in a link sheet instead of a data detectors sheet
+        https://bugs.webkit.org/show_bug.cgi?id=179646
+        <rdar://problem/35337288>
+
+        Reviewed by Simon Fraser.
+
+        * UIProcess/ios/WKActionSheetAssistant.mm:
+        (-[WKActionSheetAssistant showImageSheet]):
+        (-[WKActionSheetAssistant showLinkSheet]):
+        (-[WKActionSheetAssistant showDataDetectorsSheet]):
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView _actionForLongPressFromPositionInformation:]):
+        (-[WKContentView _interactionShouldBeginFromPreviewItemController:forPosition:]):
+        Make use of canBePresentedByDataDetectors with our WebCore URL instead
+        of (sometimes unsucessfully) reparsing the URL with NSURL's parser.
+        Also, avoid a few unnecessary round-trips through String when converting
+        from URL to NSURL.
+
 2017-11-14  Brent Fulgham  <bfulgham@apple.com>
 
         REGRESSION(r224799): WebKit crashes on Sierra due to sandbox violation
index 9ce8417..81e1412 100644 (file)
@@ -40,6 +40,7 @@
 #import "_WKActivatedElementInfoInternal.h"
 #import "_WKElementActionInternal.h"
 #import <UIKit/UIView.h>
+#import <WebCore/DataDetection.h>
 #import <WebCore/LocalizedStrings.h>
 #import <WebCore/PathUtilities.h>
 #import <WebCore/WebCoreNSURLExtras.h>
@@ -348,7 +349,9 @@ static const CGFloat presentationElementRectPadding = 15;
         return;
 
     void (^showImageSheetWithAlternateURLBlock)(NSURL*, NSDictionary *userInfo) = ^(NSURL *alternateURL, NSDictionary *userInfo) {
-        NSURL *targetURL = [NSURL _web_URLWithWTFString:_positionInformation->url] ?: alternateURL;
+        NSURL *targetURL = _positionInformation->url;
+        if (!targetURL)
+            targetURL = 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()])
@@ -509,7 +512,7 @@ static WKActionSheetPresentationStyle presentationStyleForView(UIView *view, con
     if (![self synchronouslyRetrievePositionInformation])
         return;
 
-    NSURL *targetURL = [NSURL _web_URLWithWTFString:_positionInformation->url];
+    NSURL *targetURL = _positionInformation->url;
     if (!targetURL) {
         _needsLinkIndicator = NO;
         return;
@@ -552,11 +555,11 @@ static WKActionSheetPresentationStyle presentationStyleForView(UIView *view, con
     if (![self synchronouslyRetrievePositionInformation])
         return;
 
-    NSURL *targetURL = [NSURL _web_URLWithWTFString:_positionInformation->url];
-    if (!targetURL)
+    if (!WebCore::DataDetection::canBePresentedByDataDetectors(_positionInformation->url))
         return;
 
-    if (![[getDDDetectionControllerClass() tapAndHoldSchemes] containsObject:[targetURL scheme]])
+    NSURL *targetURL = _positionInformation->url;
+    if (!targetURL)
         return;
 
     DDDetectionController *controller = [getDDDetectionControllerClass() sharedController];
index e3621ca..88b5c06 100644 (file)
@@ -66,6 +66,7 @@
 #import <CoreText/CTFontDescriptor.h>
 #import <MobileCoreServices/UTCoreTypes.h>
 #import <WebCore/Color.h>
+#import <WebCore/DataDetection.h>
 #import <WebCore/FloatQuad.h>
 #import <WebCore/NotImplemented.h>
 #import <WebCore/Pasteboard.h>
@@ -1252,8 +1253,7 @@ static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UI
 
     if (positionInformation.isLink) {
 #if ENABLE(DATA_DETECTION)
-        NSURL *targetURL = [NSURL URLWithString:positionInformation.url];
-        if ([[getDDDetectionControllerClass() tapAndHoldSchemes] containsObject:targetURL.scheme.lowercaseString])
+        if (DataDetection::canBePresentedByDataDetectors(positionInformation.url))
             return @selector(_showDataDetectorsSheet);
 #endif
         return @selector(_showLinkSheet);
@@ -4915,7 +4915,7 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
             return NO;
         if (linkURL.protocolIsInHTTPFamily())
             return YES;
-        if ([[getDDDetectionControllerClass() tapAndHoldSchemes] containsObject:linkURL.protocol().toString().convertToASCIILowercase()])
+        if (DataDetection::canBePresentedByDataDetectors(linkURL))
             return YES;
         return NO;
     }
index faef3db..07d17e9 100644 (file)
@@ -1,3 +1,17 @@
+2017-11-14  Tim Horton  <timothy_horton@apple.com>
+
+        Long pressing a phone number with spaces in it results in a link sheet instead of a data detectors sheet
+        https://bugs.webkit.org/show_bug.cgi?id=179646
+        <rdar://problem/35337288>
+
+        Reviewed by Simon Fraser.
+
+        * TestWebKitAPI/Tests/ios/ActionSheetTests.mm:
+        (-[ActionSheetObserver _dataDetectionContextForWebView:]):
+        (TestWebKitAPI::TEST):
+        Add a test that ensures that a phone number with spaces in it
+        invokes a data detectors sheet, not a normal link sheet.
+
 2017-11-14  Emilio Cobos Álvarez  <emilio@crisal.io>
 
         Add committer status for Emilio Cobos Álvarez.
index 07d1d07..643e824 100644 (file)
@@ -42,6 +42,7 @@
 
 @interface ActionSheetObserver : NSObject<WKUIDelegatePrivate>
 @property (nonatomic) BlockPtr<NSArray *(_WKActivatedElementInfo *, NSArray *)> presentationHandler;
+@property (nonatomic) BlockPtr<NSDictionary *(void)> dataDetectionContextHandler;
 @end
 
 @implementation ActionSheetObserver
     return _presentationHandler ? _presentationHandler(element, defaultActions) : defaultActions;
 }
 
+- (NSDictionary *)_dataDetectionContextForWebView:(WKWebView *)WebView
+{
+    return _dataDetectionContextHandler ? _dataDetectionContextHandler() : @{ };
+}
+
 @end
 
 namespace TestWebKitAPI {
@@ -92,6 +98,48 @@ TEST(ActionSheetTests, ImageMapDoesNotDestroySelection)
     EXPECT_WK_STREQ("Hello world", [webView stringByEvaluatingJavaScript:@"getSelection().toString()"]);
 }
 
+TEST(ActionSheetTests, DataDetectorsLinkIsNotPresentedAsALink)
+{
+    IPadUserInterfaceSwizzler iPadUserInterface;
+
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)]);
+    auto observer = adoptNS([[ActionSheetObserver alloc] init]);
+    [webView setUIDelegate:observer.get()];
+
+    auto runTest = ^(NSString *phoneNumber) {
+        [webView synchronouslyLoadHTMLString:[NSString stringWithFormat:@"<a style='position: absolute; top: 0; left: 0;' href='tel:%@'>telephone number</a>", phoneNumber]];
+
+        __block bool done = false;
+        __block bool succeeded = true;
+
+        // We shouldn't present a normal action sheet, but instead a data detectors sheet.
+        [observer setDataDetectionContextHandler:^{
+            done = true;
+            return @{ };
+        }];
+        [observer setPresentationHandler:^(_WKActivatedElementInfo *, NSArray *) {
+            done = true;
+            succeeded = false;
+            return @[ ];
+        }];
+        [webView _simulateLongPressActionAtLocation:CGPointMake(5, 5)];
+        TestWebKitAPI::Util::run(&done);
+
+        return succeeded;
+    };
+
+    EXPECT_TRUE(runTest(@"4089961010"));
+    EXPECT_TRUE(runTest(@"408 996 1010"));
+    EXPECT_TRUE(runTest(@"1-866-MY-APPLE"));
+    EXPECT_TRUE(runTest(@"(123) 456 - 7890"));
+    EXPECT_TRUE(runTest(@"01 23 45 67 00"));
+    EXPECT_TRUE(runTest(@"+33 (0)1 23 34 45 56"));
+    EXPECT_TRUE(runTest(@"(0)1 12 23 34 56"));
+    EXPECT_TRUE(runTest(@"010-1-800-MY-APPLE"));
+    EXPECT_TRUE(runTest(@"+1-408-1234567"));
+    EXPECT_TRUE(runTest(@"08080808080"));
+}
+
 #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000
 
 static void presentActionSheetAndChooseAction(WKWebView *webView, ActionSheetObserver *observer, CGPoint location, _WKElementActionType actionType)