[iOS] Respect type fidelities when copying image elements to the pasteboard
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / ios / ActionSheetTests.mm
1 /*
2  * Copyright (C) 2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #if PLATFORM(IOS)
29
30 #import "InstanceMethodSwizzler.h"
31 #import "PlatformUtilities.h"
32 #import "TestWKWebView.h"
33 #import "UIKitSPI.h"
34 #import <MobileCoreServices/MobileCoreServices.h>
35 #import <WebKit/WKUIDelegatePrivate.h>
36 #import <WebKit/WKWebViewPrivate.h>
37 #import <WebKit/_WKActivatedElementInfo.h>
38 #import <WebKit/_WKElementAction.h>
39 #import <wtf/BlockPtr.h>
40 #import <wtf/RetainPtr.h>
41 #import <wtf/SoftLinking.h>
42
43 @interface ActionSheetObserver : NSObject<WKUIDelegatePrivate>
44 @property (nonatomic) BlockPtr<NSArray *(_WKActivatedElementInfo *, NSArray *)> presentationHandler;
45 @end
46
47 @implementation ActionSheetObserver
48
49 - (NSArray *)_webView:(WKWebView *)webView actionsForElement:(_WKActivatedElementInfo *)element defaultActions:(NSArray<_WKElementAction *> *)defaultActions
50 {
51     return _presentationHandler ? _presentationHandler(element, defaultActions) : defaultActions;
52 }
53
54 @end
55
56 namespace TestWebKitAPI {
57
58 class IPadUserInterfaceSwizzler {
59 public:
60     IPadUserInterfaceSwizzler()
61         : m_swizzler([UIDevice class], @selector(userInterfaceIdiom), reinterpret_cast<IMP>(padUserInterfaceIdiom))
62     {
63     }
64 private:
65     static UIUserInterfaceIdiom padUserInterfaceIdiom()
66     {
67         return UIUserInterfaceIdiomPad;
68     }
69     InstanceMethodSwizzler m_swizzler;
70 };
71
72 TEST(ActionSheetTests, ImageMapDoesNotDestroySelection)
73 {
74     IPadUserInterfaceSwizzler iPadUserInterface;
75
76     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)]);
77     auto observer = adoptNS([[ActionSheetObserver alloc] init]);
78     [webView setUIDelegate:observer.get()];
79     [webView synchronouslyLoadTestPageNamed:@"image-map"];
80     [webView stringByEvaluatingJavaScript:@"selectTextNode(h1.childNodes[0])"];
81
82     EXPECT_WK_STREQ("Hello world", [webView stringByEvaluatingJavaScript:@"getSelection().toString()"]);
83
84     __block bool done = false;
85     [observer setPresentationHandler:^(_WKActivatedElementInfo *element, NSArray *actions) {
86         done = true;
87         return actions;
88     }];
89     [webView _simulateLongPressActionAtLocation:CGPointMake(200, 200)];
90     TestWebKitAPI::Util::run(&done);
91
92     EXPECT_WK_STREQ("Hello world", [webView stringByEvaluatingJavaScript:@"getSelection().toString()"]);
93 }
94
95 #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000
96
97 static void presentActionSheetAndChooseAction(WKWebView *webView, ActionSheetObserver *observer, CGPoint location, _WKElementActionType actionType)
98 {
99     __block RetainPtr<_WKElementAction> copyAction;
100     __block RetainPtr<_WKActivatedElementInfo> copyElement;
101     __block bool done = false;
102     [observer setPresentationHandler:^(_WKActivatedElementInfo *element, NSArray *actions) {
103         copyElement = element;
104         for (_WKElementAction *action in actions) {
105             if (action.type == actionType)
106                 copyAction = action;
107         }
108         done = true;
109         return @[ copyAction.get() ];
110     }];
111     [webView _simulateLongPressActionAtLocation:location];
112     TestWebKitAPI::Util::run(&done);
113
114     EXPECT_TRUE(!!copyAction);
115     EXPECT_TRUE(!!copyElement);
116     [copyAction runActionWithElementInfo:copyElement.get()];
117 }
118
119 TEST(ActionSheetTests, CopyImageElementWithHREF)
120 {
121     UIApplicationInitialize();
122     [UIPasteboard generalPasteboard].items = @[ ];
123
124     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
125     auto observer = adoptNS([[ActionSheetObserver alloc] init]);
126     [webView setUIDelegate:observer.get()];
127     [webView synchronouslyLoadTestPageNamed:@"image-in-link-and-input"];
128
129     presentActionSheetAndChooseAction(webView.get(), observer.get(), CGPointMake(100, 50), _WKElementActionTypeCopy);
130
131     __block bool done = false;
132     [webView _doAfterNextPresentationUpdate:^() {
133         NSArray <NSString *> *pasteboardTypes = [[UIPasteboard generalPasteboard] pasteboardTypes];
134         EXPECT_EQ(2UL, pasteboardTypes.count);
135         EXPECT_WK_STREQ((NSString *)kUTTypePNG, pasteboardTypes.firstObject);
136         EXPECT_WK_STREQ((NSString *)kUTTypeURL, pasteboardTypes.lastObject);
137         NSArray <NSItemProvider *> *itemProviders = [[UIPasteboard generalPasteboard] itemProviders];
138         EXPECT_EQ(1UL, itemProviders.count);
139         NSItemProvider *itemProvider = itemProviders.firstObject;
140         EXPECT_EQ(2UL, itemProvider.registeredTypeIdentifiers.count);
141         EXPECT_WK_STREQ((NSString *)kUTTypePNG, itemProvider.registeredTypeIdentifiers.firstObject);
142         EXPECT_WK_STREQ((NSString *)kUTTypeURL, itemProvider.registeredTypeIdentifiers.lastObject);
143         done = true;
144     }];
145     TestWebKitAPI::Util::run(&done);
146 }
147
148 TEST(ActionSheetTests, CopyImageElementWithoutHREF)
149 {
150     UIApplicationInitialize();
151     [UIPasteboard generalPasteboard].items = @[ ];
152
153     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
154     auto observer = adoptNS([[ActionSheetObserver alloc] init]);
155     [webView setUIDelegate:observer.get()];
156     [webView synchronouslyLoadTestPageNamed:@"image-and-contenteditable"];
157
158     presentActionSheetAndChooseAction(webView.get(), observer.get(), CGPointMake(100, 100), _WKElementActionTypeCopy);
159
160     __block bool done = false;
161     [webView _doAfterNextPresentationUpdate:^() {
162         NSArray <NSString *> *pasteboardTypes = [[UIPasteboard generalPasteboard] pasteboardTypes];
163         EXPECT_EQ(1UL, pasteboardTypes.count);
164         EXPECT_WK_STREQ((NSString *)kUTTypePNG, pasteboardTypes.firstObject);
165         NSArray <NSItemProvider *> *itemProviders = [[UIPasteboard generalPasteboard] itemProviders];
166         EXPECT_EQ(1UL, itemProviders.count);
167         NSItemProvider *itemProvider = itemProviders.firstObject;
168         EXPECT_EQ(1UL, itemProvider.registeredTypeIdentifiers.count);
169         EXPECT_WK_STREQ((NSString *)kUTTypePNG, itemProvider.registeredTypeIdentifiers.firstObject);
170         done = true;
171     }];
172     TestWebKitAPI::Util::run(&done);
173 }
174
175 #endif // __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000
176
177 } // namespace TestWebKitAPI
178
179 #endif // PLATFORM(IOS)