Fix API test after r241728
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WebKitCocoa / PasteMixedContent.mm
1 /*
2  * Copyright (C) 2018 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 WK_API_ENABLED
29
30 #import "PlatformUtilities.h"
31 #import "TestURLSchemeHandler.h"
32 #import "TestWKWebView.h"
33 #import <WebKit/WKPreferencesRef.h>
34 #import <WebKit/WKPreferencesRefPrivate.h>
35 #import <WebKit/WKWebViewPrivate.h>
36 #import <wtf/RetainPtr.h>
37 #import <wtf/text/WTFString.h>
38
39 namespace TestWebKitAPI {
40
41 #if PLATFORM(MAC)
42
43 static NSString *imagePath()
44 {
45     return [[NSBundle mainBundle] pathForResource:@"icon" ofType:@"png" inDirectory:@"TestWebKitAPI.resources"];
46 }
47
48 void writeTypesAndDataToPasteboard(id type, ...)
49 {
50     NSMutableArray<NSString *> *types = [NSMutableArray array];
51     NSMutableArray *data = [NSMutableArray array];
52     va_list argumentList;
53     if (type) {
54         ASSERT([type isKindOfClass:[NSString class]]);
55         [types addObject:type];
56         va_start(argumentList, type);
57         NSUInteger index = 1;
58         id object = va_arg(argumentList, id);
59         while (object) {
60             if (index % 2)
61                 [data addObject:object];
62             else {
63                 ASSERT([object isKindOfClass:[NSString class]]);
64                 [types addObject:object];
65             }
66             ++index;
67             object = va_arg(argumentList, id);
68         }
69         va_end(argumentList);
70     }
71
72     if (types.count != data.count) {
73         NSLog(@"Expected number of types: %tu to match number of data items: %tu", types.count, data.count);
74         ASSERT_NOT_REACHED();
75         return;
76     }
77
78     [[NSPasteboard generalPasteboard] declareTypes:types owner:nil];
79     [types enumerateObjectsUsingBlock:[&] (NSString *type, NSUInteger index, BOOL *) {
80         id dataToWrite = data[index];
81         if ([dataToWrite isKindOfClass:[NSData class]])
82             [[NSPasteboard generalPasteboard] setData:dataToWrite forType:type];
83         else if ([dataToWrite isKindOfClass:[NSString class]])
84             [[NSPasteboard generalPasteboard] setString:dataToWrite forType:type];
85         else
86             [[NSPasteboard generalPasteboard] setPropertyList:dataToWrite forType:type];
87     }];
88 }
89
90 static RetainPtr<TestWKWebView> setUpWebView()
91 {
92     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400)]);
93     WKPreferencesSetCustomPasteboardDataEnabled((__bridge WKPreferencesRef)[webView configuration].preferences, true);
94     [webView synchronouslyLoadTestPageNamed:@"DataTransfer"];
95     return webView;
96 }
97
98 static NSString *markupString()
99 {
100     // The script tag and mouseover listener attribute in the markup string below should be omitted during
101     // sanitization while pasting.
102     return @"<script>foo()</script><strong onmouseover='javascript:void(0)'>HELLO WORLD</strong>";
103 }
104
105 TEST(PasteMixedContent, ImageFileAndPlainText)
106 {
107     auto webView = setUpWebView();
108     writeTypesAndDataToPasteboard(NSFilenamesPboardType, @[ imagePath() ], NSPasteboardTypeString, imagePath(), nil);
109     [webView paste:nil];
110
111     EXPECT_WK_STREQ("Files", [webView stringByEvaluatingJavaScript:@"types.textContent"]);
112     EXPECT_WK_STREQ("(FILE, image/png)", [webView stringByEvaluatingJavaScript:@"items.textContent"]);
113     EXPECT_WK_STREQ("('icon.png', image/png)", [webView stringByEvaluatingJavaScript:@"files.textContent"]);
114     EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"urlData.textContent"]);
115     EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"textData.textContent"]);
116     EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"htmlData.textContent"]);
117     EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"rawHTMLData.textContent"]);
118 }
119
120 TEST(PasteMixedContent, ImageFileAndWebArchive)
121 {
122     auto webView = setUpWebView();
123     NSURL *mainResourceURL = [NSURL fileURLWithPath:@"/some/nonexistent/file.html"];
124     auto mainResource = adoptNS([[WebResource alloc] initWithData:[markupString() dataUsingEncoding:NSUTF8StringEncoding] URL:mainResourceURL MIMEType:@"text/html" textEncodingName:@"utf-8" frameName:nil]);
125     auto archive = adoptNS([[WebArchive alloc] initWithMainResource:mainResource.get() subresources:nil subframeArchives:nil]);
126     writeTypesAndDataToPasteboard(NSFilenamesPboardType, @[ imagePath() ], WebArchivePboardType, [archive data], nil);
127     [webView paste:nil];
128
129     EXPECT_WK_STREQ("Files, text/html", [webView stringByEvaluatingJavaScript:@"types.textContent"]);
130     EXPECT_WK_STREQ("(STRING, text/html), (FILE, image/png)", [webView stringByEvaluatingJavaScript:@"items.textContent"]);
131     EXPECT_WK_STREQ("('icon.png', image/png)", [webView stringByEvaluatingJavaScript:@"files.textContent"]);
132     EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"urlData.textContent"]);
133     EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"textData.textContent"]);
134     EXPECT_WK_STREQ("HELLO WORLD", [webView stringByEvaluatingJavaScript:@"htmlData.textContent"]);
135     EXPECT_FALSE([[webView stringByEvaluatingJavaScript:@"rawHTMLData.textContent"] containsString:@"script"]);
136 }
137
138 TEST(PasteMixedContent, ImageFileAndHTML)
139 {
140     auto webView = setUpWebView();
141     writeTypesAndDataToPasteboard(NSFilenamesPboardType, @[ imagePath() ], NSPasteboardTypeHTML, markupString(), nil);
142     [webView paste:nil];
143
144     EXPECT_WK_STREQ("Files, text/html", [webView stringByEvaluatingJavaScript:@"types.textContent"]);
145     EXPECT_WK_STREQ("(STRING, text/html), (FILE, image/png)", [webView stringByEvaluatingJavaScript:@"items.textContent"]);
146     EXPECT_WK_STREQ("('icon.png', image/png)", [webView stringByEvaluatingJavaScript:@"files.textContent"]);
147     EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"urlData.textContent"]);
148     EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"textData.textContent"]);
149     EXPECT_WK_STREQ("HELLO WORLD", [webView stringByEvaluatingJavaScript:@"htmlData.textContent"]);
150     EXPECT_FALSE([[webView stringByEvaluatingJavaScript:@"rawHTMLData.textContent"] containsString:@"script"]);
151 }
152
153 TEST(PasteMixedContent, ImageFileAndRTF)
154 {
155     auto webView = setUpWebView();
156     auto text = adoptNS([[NSMutableAttributedString alloc] init]);
157     [text appendAttributedString:[[NSAttributedString alloc] initWithString:@"link to "]];
158     [text appendAttributedString:[[NSAttributedString alloc] initWithString:@"apple" attributes:@{ NSLinkAttributeName: [NSURL URLWithString:@"https://www.apple.com/"] }]];
159     NSData *rtfData = [text RTFFromRange:NSMakeRange(0, [text length]) documentAttributes:@{ }];
160     writeTypesAndDataToPasteboard(NSFilenamesPboardType, @[ imagePath() ], NSPasteboardTypeRTF, rtfData, nil);
161     [webView paste:nil];
162
163     EXPECT_WK_STREQ("Files, text/html", [webView stringByEvaluatingJavaScript:@"types.textContent"]);
164     EXPECT_WK_STREQ("(STRING, text/html), (FILE, image/png)", [webView stringByEvaluatingJavaScript:@"items.textContent"]);
165     EXPECT_WK_STREQ("('icon.png', image/png)", [webView stringByEvaluatingJavaScript:@"files.textContent"]);
166     EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"urlData.textContent"]);
167     EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"textData.textContent"]);
168     EXPECT_WK_STREQ("link to apple", [webView stringByEvaluatingJavaScript:@"htmlData.textContent"]);
169     EXPECT_WK_STREQ("https://www.apple.com/", [webView stringByEvaluatingJavaScript:@"htmlData.querySelector('a').href"]);
170 }
171
172 TEST(PasteMixedContent, ImageFileAndURL)
173 {
174     auto webView = setUpWebView();
175     writeTypesAndDataToPasteboard(NSURLPboardType, @"https://www.webkit.org/", NSFilenamesPboardType, @[ imagePath() ], nil);
176     [webView paste:nil];
177
178     EXPECT_WK_STREQ("Files, text/uri-list", [webView stringByEvaluatingJavaScript:@"types.textContent"]);
179     EXPECT_WK_STREQ("(STRING, text/uri-list), (FILE, image/png)", [webView stringByEvaluatingJavaScript:@"items.textContent"]);
180     EXPECT_WK_STREQ("('icon.png', image/png)", [webView stringByEvaluatingJavaScript:@"files.textContent"]);
181     EXPECT_WK_STREQ("https://www.webkit.org/", [webView stringByEvaluatingJavaScript:@"urlData.textContent"]);
182     EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"textData.textContent"]);
183     EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"htmlData.textContent"]);
184 }
185
186 TEST(PasteMixedContent, ImageFileWithHTMLAndURL)
187 {
188     auto webView = setUpWebView();
189     writeTypesAndDataToPasteboard(NSURLPboardType, @"https://www.webkit.org/", NSPasteboardTypeHTML, markupString(), NSFilenamesPboardType, @[ imagePath() ], nil);
190     [webView paste:nil];
191
192     EXPECT_WK_STREQ("Files, text/uri-list, text/html", [webView stringByEvaluatingJavaScript:@"types.textContent"]);
193     EXPECT_WK_STREQ("(STRING, text/uri-list), (STRING, text/html), (FILE, image/png)", [webView stringByEvaluatingJavaScript:@"items.textContent"]);
194     EXPECT_WK_STREQ("('icon.png', image/png)", [webView stringByEvaluatingJavaScript:@"files.textContent"]);
195     EXPECT_WK_STREQ("https://www.webkit.org/", [webView stringByEvaluatingJavaScript:@"urlData.textContent"]);
196     EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"textData.textContent"]);
197     EXPECT_WK_STREQ("HELLO WORLD", [webView stringByEvaluatingJavaScript:@"htmlData.textContent"]);
198     EXPECT_FALSE([[webView stringByEvaluatingJavaScript:@"rawHTMLData.textContent"] containsString:@"script"]);
199 }
200
201 TEST(PasteMixedContent, ImageDataAndPlainText)
202 {
203     auto webView = setUpWebView();
204     writeTypesAndDataToPasteboard(NSPasteboardTypeString, @"Hello world", NSPasteboardTypePNG, [NSData dataWithContentsOfFile:imagePath()], nil);
205     [webView paste:nil];
206
207     EXPECT_WK_STREQ("Files, text/plain", [webView stringByEvaluatingJavaScript:@"types.textContent"]);
208     EXPECT_WK_STREQ("(STRING, text/plain), (FILE, image/png)", [webView stringByEvaluatingJavaScript:@"items.textContent"]);
209     EXPECT_WK_STREQ("('image.png', image/png)", [webView stringByEvaluatingJavaScript:@"files.textContent"]);
210     EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"urlData.textContent"]);
211     EXPECT_WK_STREQ("Hello world", [webView stringByEvaluatingJavaScript:@"textData.textContent"]);
212     EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"htmlData.textContent"]);
213 }
214
215 TEST(PasteMixedContent, ImageDataAndPlainTextAndURL)
216 {
217     auto webView = setUpWebView();
218     writeTypesAndDataToPasteboard(NSPasteboardTypeString, imagePath(), NSURLPboardType, imagePath(), NSPasteboardTypePNG, [NSData dataWithContentsOfFile:imagePath()], nil);
219     [webView paste:nil];
220
221     EXPECT_WK_STREQ("Files", [webView stringByEvaluatingJavaScript:@"types.textContent"]);
222     EXPECT_WK_STREQ("(FILE, image/png)", [webView stringByEvaluatingJavaScript:@"items.textContent"]);
223     EXPECT_WK_STREQ("('image.png', image/png)", [webView stringByEvaluatingJavaScript:@"files.textContent"]);
224     EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"urlData.textContent"]);
225     EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"textData.textContent"]);
226     EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"htmlData.textContent"]);
227 }
228
229 TEST(PasteMixedContent, ImageDataAndPlainTextAndURLAndHTML)
230 {
231     auto webView = setUpWebView();
232     writeTypesAndDataToPasteboard(NSPasteboardTypeString, imagePath(), NSURLPboardType, imagePath(), NSPasteboardTypeHTML, markupString(), NSPasteboardTypePNG, [NSData dataWithContentsOfFile:imagePath()], nil);
233     [webView paste:nil];
234
235     EXPECT_WK_STREQ("Files, text/html", [webView stringByEvaluatingJavaScript:@"types.textContent"]);
236     EXPECT_WK_STREQ("(STRING, text/html), (FILE, image/png)", [webView stringByEvaluatingJavaScript:@"items.textContent"]);
237     EXPECT_WK_STREQ("('image.png', image/png)", [webView stringByEvaluatingJavaScript:@"files.textContent"]);
238     EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"urlData.textContent"]);
239     EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"textData.textContent"]);
240     EXPECT_WK_STREQ("HELLO WORLD", [webView stringByEvaluatingJavaScript:@"htmlData.textContent"]);
241     EXPECT_FALSE([[webView stringByEvaluatingJavaScript:@"rawHTMLData.textContent"] containsString:@"script"]);
242 }
243
244 TEST(PasteMixedContent, PasteURLWrittenToPasteboardUsingWriteObjects)
245 {
246     NSString *urlToCopy = @"https://www.webkit.org/";
247
248     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400)]);
249     [webView synchronouslyLoadHTMLString:@"<body contenteditable></body><script>document.body.focus()</script>"];
250     [[NSPasteboard generalPasteboard] clearContents];
251     [[NSPasteboard generalPasteboard] writeObjects:@[ [NSURL URLWithString:urlToCopy] ]];
252     [webView paste:nil];
253
254     EXPECT_WK_STREQ([webView stringByEvaluatingJavaScript:@"document.querySelector('a').href"], urlToCopy);
255     EXPECT_WK_STREQ([webView stringByEvaluatingJavaScript:@"document.querySelector('a').textContent"], urlToCopy);
256 }
257
258 TEST(PasteMixedContent, PasteOneOrMoreURLs)
259 {
260     NSURL *appleURL = [NSURL URLWithString:@"https://www.apple.com/"];
261     NSURL *webKitURL = [NSURL URLWithString:@"https://webkit.org/"];
262
263     auto webView = setUpWebView();
264     auto runTest = [webView] (NSString *description, NSString *expectedURLString, Function<void(NSPasteboard *)>&& writeURLsToPasteboard) {
265         NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
266
267         [pasteboard clearContents];
268         writeURLsToPasteboard(pasteboard);
269         [webView stringByEvaluatingJavaScript:@"reset(); document.body.focus()"];
270         [webView paste:nil];
271
272         EXPECT_WK_STREQ(expectedURLString, [webView stringByEvaluatingJavaScript:@"urlData.textContent"]);
273         EXPECT_WK_STREQ("(STRING, text/uri-list)", [webView stringByEvaluatingJavaScript:@"items.textContent"]);
274         EXPECT_WK_STREQ("text/uri-list", [webView stringByEvaluatingJavaScript:@"types.textContent"]);
275     };
276
277     runTest(@"Write multiple URLs.", @"https://www.apple.com/\nhttps://webkit.org/", ^(NSPasteboard *pasteboard) {
278         [pasteboard writeObjects:@[appleURL, webKitURL]];
279     });
280
281     runTest(@"Declare legacy URL and write URL to pasteboard.", @"https://www.apple.com/", ^(NSPasteboard *pasteboard) {
282         [pasteboard declareTypes:@[NSURLPboardType] owner:nil];
283         [appleURL writeToPasteboard:pasteboard];
284     });
285
286     runTest(@"Declare legacy URL and set a URL string.", @"https://www.apple.com/", ^(NSPasteboard *pasteboard) {
287         [pasteboard declareTypes:@[NSURLPboardType] owner:nil];
288         [pasteboard setString:appleURL.absoluteString forType:NSURLPboardType];
289     });
290
291     runTest(@"Declare legacy URL and set a property list.", @"https://www.apple.com/", ^(NSPasteboard *pasteboard) {
292         [pasteboard declareTypes:@[NSURLPboardType] owner:nil];
293         [pasteboard setPropertyList:@[@"/", @"https://www.apple.com"] forType:NSURLPboardType];
294     });
295
296     runTest(@"Declare URL UTI and set a URL string.", @"https://www.apple.com/", ^(NSPasteboard *pasteboard) {
297         [pasteboard declareTypes:@[(__bridge NSString *)kUTTypeURL] owner:nil];
298         [pasteboard setString:appleURL.absoluteString forType:(__bridge NSString *)kUTTypeURL];
299     });
300 }
301
302 #endif // PLATFORM(MAC)
303
304 TEST(PasteMixedContent, CopyAndPasteWithCustomPasteboardDataOnly)
305 {
306     NSString *markupForSource = @"<body oncopy=\"event.preventDefault(); event.clipboardData.setData('foo', 'bar')\">hello</body>";
307     NSString *markupForDestination = @"<input autofocus onpaste=\"event.preventDefault(); this.value = event.clipboardData.getData('foo')\">";
308
309     auto schemeHandler = adoptNS([[TestURLSchemeHandler alloc] init]);
310     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
311     [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"same"];
312     [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"different"];
313     WKPreferencesSetCustomPasteboardDataEnabled((__bridge WKPreferencesRef)[configuration preferences], true);
314
315     auto source = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400) configuration:configuration.get()]);
316     [source synchronouslyLoadHTMLString:markupForSource baseURL:[NSURL URLWithString:@"same://"]];
317     [source selectAll:nil];
318     [source _executeEditCommand:@"copy" argument:nil completion:nil];
319
320     auto destination = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400) configuration:configuration.get()]);
321     [destination synchronouslyLoadHTMLString:markupForDestination baseURL:[NSURL URLWithString:@"same://"]];
322     [destination paste:nil];
323     EXPECT_WK_STREQ("bar", [destination stringByEvaluatingJavaScript:@"document.querySelector('input').value"]);
324 #if PLATFORM(IOS_FAMILY)
325     EXPECT_TRUE([destination canPerformAction:@selector(paste:) withSender:nil]);
326 #endif
327
328     [destination synchronouslyLoadHTMLString:markupForDestination baseURL:[NSURL URLWithString:@"different://"]];
329     [destination paste:nil];
330     EXPECT_WK_STREQ("", [destination stringByEvaluatingJavaScript:@"document.querySelector('input').value"]);
331 #if PLATFORM(IOS_FAMILY)
332     EXPECT_FALSE([destination canPerformAction:@selector(paste:) withSender:nil]);
333 #endif
334 }
335
336 } // namespace TestWebKitAPI
337
338 #endif // WK_API_ENABLED