REGRESSION (r237331): DismissingActionSheetShouldNotDismissPresentingViewController...
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / ios / ActionSheetTests.mm
index 07d1d07..bf7da79 100644 (file)
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "config.h"
+#import "config.h"
+#import "Test.h"
 
-#if PLATFORM(IOS)
+#if PLATFORM(IOS_FAMILY)
 
+#import "ClassMethodSwizzler.h"
 #import "InstanceMethodSwizzler.h"
 #import "PlatformUtilities.h"
+#import "TestNavigationDelegate.h"
 #import "TestWKWebView.h"
+#import "TestWKWebViewController.h"
 #import "UIKitSPI.h"
 #import <MobileCoreServices/MobileCoreServices.h>
 #import <WebKit/WKUIDelegatePrivate.h>
@@ -42,6 +46,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 {
@@ -69,6 +79,70 @@ private:
     InstanceMethodSwizzler m_swizzler;
 };
 
+static RetainPtr<UIViewController> gOverrideViewControllerForFullscreenPresentation;
+static void setOverrideViewControllerForFullscreenPresentation(UIViewController *viewController)
+{
+    gOverrideViewControllerForFullscreenPresentation = viewController;
+}
+
+static UIViewController *overrideViewControllerForFullscreenPresentation()
+{
+    return gOverrideViewControllerForFullscreenPresentation.get();
+}
+
+TEST(ActionSheetTests, DISABLED_DismissingActionSheetShouldNotDismissPresentingViewController)
+{
+    IPadUserInterfaceSwizzler iPadUserInterface;
+    UIApplicationInitialize();
+
+    auto navigationDelegate = adoptNS([[TestNavigationDelegate alloc] init]);
+    auto window = adoptNS([[TestWKWebViewControllerWindow alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)]);
+    auto rootViewController = adoptNS([[UIViewController alloc] init]);
+    auto navigationController = adoptNS([[UINavigationController alloc] initWithRootViewController:rootViewController.get()]);
+    auto observer = adoptNS([[ActionSheetObserver alloc] init]);
+    [window setRootViewController:navigationController.get()];
+    [window makeKeyAndVisible];
+
+    auto webViewController = adoptNS([[TestWKWebViewController alloc] initWithFrame:CGRectMake(0, 0, 1024, 768) configuration:nil]);
+    TestWKWebView *webView = [webViewController webView];
+    webView.UIDelegate = observer.get();
+    [webView synchronouslyLoadTestPageNamed:@"link-and-input"];
+    [webView setNavigationDelegate:navigationDelegate.get()];
+    [rootViewController presentViewController:webViewController.get() animated:NO completion:nil];
+
+    // Since TestWebKitAPI is not a UI application, +[UIViewController _viewControllerForFullScreenPresentationFromView:]
+    // returns nil. To ensure that we actually present the action sheet from the web view controller, we mock this for the
+    // time being until https://webkit.org/b/175204 is fixed.
+    setOverrideViewControllerForFullscreenPresentation(webViewController.get());
+    ClassMethodSwizzler swizzler([UIViewController class], @selector(_viewControllerForFullScreenPresentationFromView:), reinterpret_cast<IMP>(overrideViewControllerForFullscreenPresentation));
+
+    [observer setPresentationHandler:^(_WKActivatedElementInfo *, NSArray *actions) {
+        // Killing the web content process should dismiss the action sheet.
+        // This should not tell the web view controller to dismiss in the process.
+        [webView _killWebContentProcess];
+        return actions;
+    }];
+
+    __block bool done = false;
+    [navigationDelegate setWebContentProcessDidTerminate:^(WKWebView *) {
+        dispatch_async(dispatch_get_main_queue(), ^{
+            done = true;
+        });
+    }];
+
+    __block bool didDismissWebViewController = false;
+    [webViewController setDismissalHandler:^{
+        didDismissWebViewController = true;
+    }];
+
+    [webView _simulateLongPressActionAtLocation:CGPointMake(100, 100)];
+    TestWebKitAPI::Util::run(&done);
+
+    EXPECT_FALSE(didDismissWebViewController);
+    EXPECT_NULL([webViewController presentedViewController]);
+    EXPECT_NOT_NULL([webViewController presentingViewController]);
+}
+
 TEST(ActionSheetTests, ImageMapDoesNotDestroySelection)
 {
     IPadUserInterfaceSwizzler iPadUserInterface;
@@ -92,7 +166,49 @@ TEST(ActionSheetTests, ImageMapDoesNotDestroySelection)
     EXPECT_WK_STREQ("Hello world", [webView stringByEvaluatingJavaScript:@"getSelection().toString()"]);
 }
 
-#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000
+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 !PLATFORM(WATCHOS) && !PLATFORM(APPLETV)
 
 static void presentActionSheetAndChooseAction(WKWebView *webView, ActionSheetObserver *observer, CGPoint location, _WKElementActionType actionType)
 {
@@ -116,6 +232,47 @@ static void presentActionSheetAndChooseAction(WKWebView *webView, ActionSheetObs
     [copyAction runActionWithElementInfo:copyElement.get()];
 }
 
+TEST(ActionSheetTests, CopyImageElementWithHREFAndTitle)
+{
+    UIApplicationInitialize();
+    [UIPasteboard generalPasteboard].items = @[ ];
+
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
+    auto observer = adoptNS([[ActionSheetObserver alloc] init]);
+    [webView setUIDelegate:observer.get()];
+    [webView synchronouslyLoadTestPageNamed:@"image-in-link-and-input"];
+    [webView stringByEvaluatingJavaScript:@"document.querySelector('a').setAttribute('title', 'hello world')"];
+
+    presentActionSheetAndChooseAction(webView.get(), observer.get(), CGPointMake(100, 50), _WKElementActionTypeCopy);
+
+    __block bool done = false;
+    __block RetainPtr<NSItemProvider> itemProvider;
+    [webView _doAfterNextPresentationUpdate:^() {
+        NSArray <NSString *> *pasteboardTypes = [[UIPasteboard generalPasteboard] pasteboardTypes];
+        EXPECT_EQ(2UL, pasteboardTypes.count);
+        EXPECT_WK_STREQ((__bridge NSString *)kUTTypePNG, pasteboardTypes.firstObject);
+        EXPECT_WK_STREQ((__bridge NSString *)kUTTypeURL, pasteboardTypes.lastObject);
+        NSArray <NSItemProvider *> *itemProviders = [[UIPasteboard generalPasteboard] itemProviders];
+        EXPECT_EQ(1UL, itemProviders.count);
+        itemProvider = itemProviders.firstObject;
+        EXPECT_EQ(2UL, [itemProvider registeredTypeIdentifiers].count);
+        EXPECT_WK_STREQ((__bridge NSString *)kUTTypePNG, [itemProvider registeredTypeIdentifiers].firstObject);
+        EXPECT_WK_STREQ((__bridge NSString *)kUTTypeURL, [itemProvider registeredTypeIdentifiers].lastObject);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+
+    __block bool doneLoading = false;
+    [itemProvider loadObjectOfClass:[NSURL class] completionHandler:^(id <NSItemProviderReading> result, NSError *) {
+        EXPECT_TRUE([result isKindOfClass:[NSURL class]]);
+        NSURL *url = (NSURL *)result;
+        EXPECT_WK_STREQ("https://www.apple.com/", url.absoluteString);
+        EXPECT_WK_STREQ("hello world", url._title);
+        doneLoading = true;
+    }];
+    TestWebKitAPI::Util::run(&doneLoading);
+}
+
 TEST(ActionSheetTests, CopyImageElementWithHREF)
 {
     UIApplicationInitialize();
@@ -129,20 +286,31 @@ TEST(ActionSheetTests, CopyImageElementWithHREF)
     presentActionSheetAndChooseAction(webView.get(), observer.get(), CGPointMake(100, 50), _WKElementActionTypeCopy);
 
     __block bool done = false;
+    __block RetainPtr<NSItemProvider> itemProvider;
     [webView _doAfterNextPresentationUpdate:^() {
         NSArray <NSString *> *pasteboardTypes = [[UIPasteboard generalPasteboard] pasteboardTypes];
         EXPECT_EQ(2UL, pasteboardTypes.count);
-        EXPECT_WK_STREQ((NSString *)kUTTypePNG, pasteboardTypes.firstObject);
-        EXPECT_WK_STREQ((NSString *)kUTTypeURL, pasteboardTypes.lastObject);
+        EXPECT_WK_STREQ((__bridge NSString *)kUTTypePNG, pasteboardTypes.firstObject);
+        EXPECT_WK_STREQ((__bridge NSString *)kUTTypeURL, pasteboardTypes.lastObject);
         NSArray <NSItemProvider *> *itemProviders = [[UIPasteboard generalPasteboard] itemProviders];
         EXPECT_EQ(1UL, itemProviders.count);
-        NSItemProvider *itemProvider = itemProviders.firstObject;
-        EXPECT_EQ(2UL, itemProvider.registeredTypeIdentifiers.count);
-        EXPECT_WK_STREQ((NSString *)kUTTypePNG, itemProvider.registeredTypeIdentifiers.firstObject);
-        EXPECT_WK_STREQ((NSString *)kUTTypeURL, itemProvider.registeredTypeIdentifiers.lastObject);
+        itemProvider = itemProviders.firstObject;
+        EXPECT_EQ(2UL, [itemProvider registeredTypeIdentifiers].count);
+        EXPECT_WK_STREQ((__bridge NSString *)kUTTypePNG, [itemProvider registeredTypeIdentifiers].firstObject);
+        EXPECT_WK_STREQ((__bridge NSString *)kUTTypeURL, [itemProvider registeredTypeIdentifiers].lastObject);
         done = true;
     }];
     TestWebKitAPI::Util::run(&done);
+
+    __block bool doneLoading = false;
+    [itemProvider loadObjectOfClass:[NSURL class] completionHandler:^(id <NSItemProviderReading> result, NSError *) {
+        EXPECT_TRUE([result isKindOfClass:[NSURL class]]);
+        NSURL *url = (NSURL *)result;
+        EXPECT_WK_STREQ("https://www.apple.com/", url.absoluteString);
+        EXPECT_WK_STREQ("https://www.apple.com/", url._title);
+        doneLoading = true;
+    }];
+    TestWebKitAPI::Util::run(&doneLoading);
 }
 
 TEST(ActionSheetTests, CopyImageElementWithoutHREF)
@@ -161,19 +329,43 @@ TEST(ActionSheetTests, CopyImageElementWithoutHREF)
     [webView _doAfterNextPresentationUpdate:^() {
         NSArray <NSString *> *pasteboardTypes = [[UIPasteboard generalPasteboard] pasteboardTypes];
         EXPECT_EQ(1UL, pasteboardTypes.count);
-        EXPECT_WK_STREQ((NSString *)kUTTypePNG, pasteboardTypes.firstObject);
+        EXPECT_WK_STREQ((__bridge NSString *)kUTTypePNG, pasteboardTypes.firstObject);
         NSArray <NSItemProvider *> *itemProviders = [[UIPasteboard generalPasteboard] itemProviders];
         EXPECT_EQ(1UL, itemProviders.count);
         NSItemProvider *itemProvider = itemProviders.firstObject;
         EXPECT_EQ(1UL, itemProvider.registeredTypeIdentifiers.count);
-        EXPECT_WK_STREQ((NSString *)kUTTypePNG, itemProvider.registeredTypeIdentifiers.firstObject);
+        EXPECT_WK_STREQ((__bridge NSString *)kUTTypePNG, itemProvider.registeredTypeIdentifiers.firstObject);
         done = true;
     }];
     TestWebKitAPI::Util::run(&done);
 }
 
-#endif // __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000
+TEST(ActionSheetTests, CopyLinkWritesURLAndPlainText)
+{
+    UIApplicationInitialize();
+    [UIPasteboard generalPasteboard].items = @[ ];
+
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
+    auto observer = adoptNS([[ActionSheetObserver alloc] init]);
+    [webView setUIDelegate:observer.get()];
+    [webView synchronouslyLoadTestPageNamed:@"link-and-input"];
+
+    presentActionSheetAndChooseAction(webView.get(), observer.get(), CGPointMake(100, 100), _WKElementActionTypeCopy);
+
+    [webView synchronouslyLoadTestPageNamed:@"DataTransfer"];
+    [webView paste:nil];
+
+    EXPECT_WK_STREQ("text/uri-list, text/plain", [webView stringByEvaluatingJavaScript:@"types.textContent"]);
+    EXPECT_WK_STREQ("(STRING, text/uri-list), (STRING, text/plain)", [webView stringByEvaluatingJavaScript:@"items.textContent"]);
+    EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"files.textContent"]);
+    EXPECT_WK_STREQ("https://www.apple.com/", [webView stringByEvaluatingJavaScript:@"textData.textContent"]);
+    EXPECT_WK_STREQ("https://www.apple.com/", [webView stringByEvaluatingJavaScript:@"urlData.textContent"]);
+    EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"htmlData.textContent"]);
+    EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"rawHTMLData.textContent"]);
+}
+
+#endif // !PLATFORM(WATCHOS) && !PLATFORM(APPLETV)
 
 } // namespace TestWebKitAPI
 
-#endif // PLATFORM(IOS)
+#endif // PLATFORM(IOS_FAMILY)