3c1428474e841040433da393a3c9f89bb221c2ad
[WebKit.git] / Tools / TestWebKitAPI / Tests / WebKit2Cocoa / DecidePolicyForNavigationAction.mm
1 /*
2  * Copyright (C) 2014-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(MAC)
29
30 #import "PlatformUtilities.h"
31 #import <wtf/RetainPtr.h>
32 #import <wtf/mac/AppKitCompatibilityDeclarations.h>
33
34 #if WK_API_ENABLED
35
36 static bool createdWebView;
37 static bool decidedPolicy;
38 static bool finishedNavigation;
39 static RetainPtr<WKNavigationAction> action;
40 static RetainPtr<WKWebView> newWebView;
41
42 static NSString *firstURL = @"data:text/html,First";
43 static NSString *secondURL = @"data:text/html,Second";
44
45 @interface DecidePolicyForNavigationActionController : NSObject <WKNavigationDelegate, WKUIDelegate>
46 @end
47
48 @implementation DecidePolicyForNavigationActionController
49
50 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
51 {
52     decisionHandler(webView == newWebView.get() ? WKNavigationActionPolicyCancel : WKNavigationActionPolicyAllow);
53
54     action = navigationAction;
55     decidedPolicy = true;
56 }
57
58 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
59 {
60     finishedNavigation = true;
61 }
62
63 - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
64 {
65     action = navigationAction;
66     newWebView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration]);
67
68     createdWebView = true;
69     return newWebView.get();
70 }
71
72 @end
73
74 TEST(WebKit2, DecidePolicyForNavigationActionReload)
75 {
76     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
77
78     auto window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSWindowStyleMaskBorderless backing:NSBackingStoreBuffered defer:YES]);
79     [[window contentView] addSubview:webView.get()];
80
81     auto controller = adoptNS([[DecidePolicyForNavigationActionController alloc] init]);
82     [webView setNavigationDelegate:controller.get()];
83     [webView setUIDelegate:controller.get()];
84
85     finishedNavigation = false;
86     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:firstURL]]];
87     TestWebKitAPI::Util::run(&finishedNavigation);
88
89     decidedPolicy = false;
90     [webView reload];
91     TestWebKitAPI::Util::run(&decidedPolicy);
92
93     EXPECT_EQ(WKNavigationTypeReload, [action navigationType]);
94     EXPECT_TRUE([action sourceFrame] != [action targetFrame]);
95     EXPECT_EQ(nil, [action sourceFrame]);
96     EXPECT_WK_STREQ(firstURL, [[[action request] URL] absoluteString]);
97     EXPECT_WK_STREQ(firstURL, [[[[action targetFrame] request] URL] absoluteString]);
98     EXPECT_EQ(webView.get(), [[action targetFrame] webView]);
99
100     newWebView = nullptr;
101     action = nullptr;
102 }
103
104 TEST(WebKit2, DecidePolicyForNavigationActionReloadFromOrigin)
105 {
106     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
107
108     auto window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSWindowStyleMaskBorderless backing:NSBackingStoreBuffered defer:YES]);
109     [[window contentView] addSubview:webView.get()];
110
111     auto controller = adoptNS([[DecidePolicyForNavigationActionController alloc] init]);
112     [webView setNavigationDelegate:controller.get()];
113     [webView setUIDelegate:controller.get()];
114
115     finishedNavigation = false;
116     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:firstURL]]];
117     TestWebKitAPI::Util::run(&finishedNavigation);
118
119     decidedPolicy = false;
120     [webView reloadFromOrigin];
121     TestWebKitAPI::Util::run(&decidedPolicy);
122
123     EXPECT_EQ(WKNavigationTypeReload, [action navigationType]);
124     EXPECT_TRUE([action sourceFrame] != [action targetFrame]);
125     EXPECT_EQ(nil, [action sourceFrame]);
126     EXPECT_WK_STREQ(firstURL, [[[action request] URL] absoluteString]);
127     EXPECT_WK_STREQ(firstURL, [[[[action targetFrame] request] URL] absoluteString]);
128     EXPECT_EQ(webView.get(), [[action targetFrame] webView]);
129
130     newWebView = nullptr;
131     action = nullptr;
132 }
133
134 TEST(WebKit2, DecidePolicyForNavigationActionGoBack)
135 {
136     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
137
138     auto window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSWindowStyleMaskBorderless backing:NSBackingStoreBuffered defer:YES]);
139     [[window contentView] addSubview:webView.get()];
140
141     auto controller = adoptNS([[DecidePolicyForNavigationActionController alloc] init]);
142     [webView setNavigationDelegate:controller.get()];
143     [webView setUIDelegate:controller.get()];
144
145     finishedNavigation = false;
146     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:firstURL]]];
147     TestWebKitAPI::Util::run(&finishedNavigation);
148
149     finishedNavigation = false;
150     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:secondURL]]];
151     TestWebKitAPI::Util::run(&finishedNavigation);
152
153     decidedPolicy = false;
154     [webView goBack];
155     TestWebKitAPI::Util::run(&decidedPolicy);
156
157     EXPECT_EQ(WKNavigationTypeBackForward, [action navigationType]);
158     EXPECT_TRUE([action sourceFrame] != [action targetFrame]);
159     EXPECT_EQ(nil, [action sourceFrame]);
160     EXPECT_WK_STREQ(firstURL, [[[action request] URL] absoluteString]);
161     EXPECT_WK_STREQ(secondURL, [[[[action targetFrame] request] URL] absoluteString]);
162     EXPECT_EQ(webView.get(), [[action targetFrame] webView]);
163
164     newWebView = nullptr;
165     action = nullptr;
166 }
167
168 TEST(WebKit2, DecidePolicyForNavigationActionGoForward)
169 {
170     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
171
172     auto window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSWindowStyleMaskBorderless backing:NSBackingStoreBuffered defer:YES]);
173     [[window contentView] addSubview:webView.get()];
174
175     auto controller = adoptNS([[DecidePolicyForNavigationActionController alloc] init]);
176     [webView setNavigationDelegate:controller.get()];
177     [webView setUIDelegate:controller.get()];
178
179     finishedNavigation = false;
180     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:firstURL]]];
181     TestWebKitAPI::Util::run(&finishedNavigation);
182
183     finishedNavigation = false;
184     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:secondURL]]];
185     TestWebKitAPI::Util::run(&finishedNavigation);
186
187     finishedNavigation = false;
188     [webView goBack];
189     TestWebKitAPI::Util::run(&finishedNavigation);
190
191     decidedPolicy = false;
192     [webView goForward];
193     TestWebKitAPI::Util::run(&decidedPolicy);
194
195     EXPECT_EQ(WKNavigationTypeBackForward, [action navigationType]);
196     EXPECT_TRUE([action sourceFrame] != [action targetFrame]);
197     EXPECT_EQ(nil, [action sourceFrame]);
198     EXPECT_WK_STREQ(secondURL, [[[action request] URL] absoluteString]);
199     EXPECT_WK_STREQ(firstURL, [[[[action targetFrame] request] URL] absoluteString]);
200     EXPECT_EQ(webView.get(), [[action targetFrame] webView]);
201
202     newWebView = nullptr;
203     action = nullptr;
204 }
205
206 TEST(WebKit2, DecidePolicyForNavigationActionOpenNewWindowAndDeallocSourceWebView)
207 {
208     auto controller = adoptNS([[DecidePolicyForNavigationActionController alloc] init]);
209
210     @autoreleasepool {
211         auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
212
213         auto window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSWindowStyleMaskBorderless backing:NSBackingStoreBuffered defer:YES]);
214         [[window contentView] addSubview:webView.get()];
215
216         [webView setNavigationDelegate:controller.get()];
217         [webView setUIDelegate:controller.get()];
218
219         createdWebView = false;
220         [webView loadHTMLString:@"<script>window.open('http://webkit.org/destination.html')</script>" baseURL:[NSURL URLWithString:@"http://webkit.org"]];
221         TestWebKitAPI::Util::run(&createdWebView);
222     }
223
224     decidedPolicy = false;
225     [newWebView setNavigationDelegate:controller.get()];
226     TestWebKitAPI::Util::run(&decidedPolicy);
227
228     EXPECT_EQ(WKNavigationTypeOther, [action navigationType]);
229     EXPECT_TRUE([action sourceFrame] != [action targetFrame]);
230     EXPECT_EQ(nil, [[action sourceFrame] webView]);
231     EXPECT_EQ(newWebView.get(), [[action targetFrame] webView]);
232
233     newWebView = nullptr;
234     action = nullptr;
235 }
236
237 TEST(WebKit2, DecidePolicyForNavigationActionForTargetedHyperlink)
238 {
239     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
240
241     auto window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSWindowStyleMaskBorderless backing:NSBackingStoreBuffered defer:YES]);
242     [[window contentView] addSubview:webView.get()];
243
244     auto controller = adoptNS([[DecidePolicyForNavigationActionController alloc] init]);
245     [webView setNavigationDelegate:controller.get()];
246     [webView setUIDelegate:controller.get()];
247
248     finishedNavigation = false;
249     [webView loadHTMLString:@"<a style=\"display: block; height: 100%\" href=\"https://webkit.org/destination2.html\" target=\"B\">" baseURL:[NSURL URLWithString:@"http://webkit.org"]];
250     TestWebKitAPI::Util::run(&finishedNavigation);
251
252     createdWebView = false;
253     [webView evaluateJavaScript:@"window.open(\"https://webkit.org/destination1.html\", \"B\")" completionHandler:nil];
254     TestWebKitAPI::Util::run(&createdWebView);
255
256     EXPECT_EQ(WKNavigationTypeOther, [action navigationType]);
257     EXPECT_TRUE([action sourceFrame] != [action targetFrame]);
258     EXPECT_EQ(nil, [action targetFrame]);
259     EXPECT_EQ(webView.get(), [[action sourceFrame] webView]);
260     EXPECT_WK_STREQ("http", [[[action sourceFrame] securityOrigin] protocol]);
261     EXPECT_WK_STREQ("webkit.org", [[[action sourceFrame] securityOrigin] host]);
262
263     // Wait for newWebView to ask to load its initial document.
264     decidedPolicy = false;
265     [newWebView setNavigationDelegate:controller.get()];
266     TestWebKitAPI::Util::run(&decidedPolicy);
267
268     decidedPolicy = false;
269     [newWebView setNavigationDelegate:controller.get()];
270     NSPoint clickPoint = NSMakePoint(100, 100);
271     [[webView hitTest:clickPoint] mouseDown:[NSEvent mouseEventWithType:NSEventTypeLeftMouseDown location:clickPoint modifierFlags:0 timestamp:0 windowNumber:[window windowNumber] context:nil eventNumber:0 clickCount:1 pressure:1]];
272     [[webView hitTest:clickPoint] mouseUp:[NSEvent mouseEventWithType:NSEventTypeLeftMouseUp location:clickPoint modifierFlags:0 timestamp:0 windowNumber:[window windowNumber] context:nil eventNumber:0 clickCount:1 pressure:1]];
273     TestWebKitAPI::Util::run(&decidedPolicy);
274
275     EXPECT_EQ(WKNavigationTypeLinkActivated, [action navigationType]);
276     EXPECT_TRUE([action sourceFrame] != [action targetFrame]);
277     EXPECT_EQ(webView.get(), [[action sourceFrame] webView]);
278     EXPECT_EQ(newWebView.get(), [[action targetFrame] webView]);
279     EXPECT_WK_STREQ("http", [[[action sourceFrame] securityOrigin] protocol]);
280     EXPECT_WK_STREQ("webkit.org", [[[action sourceFrame] securityOrigin] host]);
281
282     newWebView = nullptr;
283     action = nullptr;
284 }
285
286 TEST(WebKit2, DecidePolicyForNavigationActionForTargetedWindowOpen)
287 {
288     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
289
290     auto window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSWindowStyleMaskBorderless backing:NSBackingStoreBuffered defer:YES]);
291     [[window contentView] addSubview:webView.get()];
292
293     auto controller = adoptNS([[DecidePolicyForNavigationActionController alloc] init]);
294     [webView setNavigationDelegate:controller.get()];
295     [webView setUIDelegate:controller.get()];
296
297     finishedNavigation = false;
298     [webView loadHTMLString:@"<a style=\"display: block; height: 100%\" href=\"javascript:window.open('https://webkit.org/destination2.html', 'B')\">" baseURL:[NSURL URLWithString:@"http://webkit.org"]];
299     TestWebKitAPI::Util::run(&finishedNavigation);
300
301     createdWebView = false;
302     [webView evaluateJavaScript:@"window.open(\"https://webkit.org/destination1.html\", \"B\")" completionHandler:nil];
303     TestWebKitAPI::Util::run(&createdWebView);
304
305     EXPECT_EQ(WKNavigationTypeOther, [action navigationType]);
306     EXPECT_TRUE([action sourceFrame] != [action targetFrame]);
307     EXPECT_EQ(nil, [action targetFrame]);
308     EXPECT_EQ(webView.get(), [[action sourceFrame] webView]);
309     EXPECT_WK_STREQ("http", [[[action sourceFrame] securityOrigin] protocol]);
310     EXPECT_WK_STREQ("webkit.org", [[[action sourceFrame] securityOrigin] host]);
311
312     // Wait for newWebView to ask to load its initial document.
313     decidedPolicy = false;
314     [newWebView setNavigationDelegate:controller.get()];
315     TestWebKitAPI::Util::run(&decidedPolicy);
316
317     decidedPolicy = false;
318     [newWebView setNavigationDelegate:controller.get()];
319     NSPoint clickPoint = NSMakePoint(100, 100);
320     [[webView hitTest:clickPoint] mouseDown:[NSEvent mouseEventWithType:NSEventTypeLeftMouseDown location:clickPoint modifierFlags:0 timestamp:0 windowNumber:[window windowNumber] context:nil eventNumber:0 clickCount:1 pressure:1]];
321     [[webView hitTest:clickPoint] mouseUp:[NSEvent mouseEventWithType:NSEventTypeLeftMouseUp location:clickPoint modifierFlags:0 timestamp:0 windowNumber:[window windowNumber] context:nil eventNumber:0 clickCount:1 pressure:1]];
322     TestWebKitAPI::Util::run(&decidedPolicy);
323
324     EXPECT_EQ(WKNavigationTypeOther, [action navigationType]);
325     EXPECT_TRUE([action sourceFrame] != [action targetFrame]);
326     EXPECT_EQ(webView.get(), [[action sourceFrame] webView]);
327     EXPECT_EQ(newWebView.get(), [[action targetFrame] webView]);
328     EXPECT_WK_STREQ("http", [[[action sourceFrame] securityOrigin] protocol]);
329     EXPECT_WK_STREQ("webkit.org", [[[action sourceFrame] securityOrigin] host]);
330
331     newWebView = nullptr;
332     action = nullptr;
333 }
334
335 TEST(WebKit2, DecidePolicyForNavigationActionForTargetedFormSubmission)
336 {
337     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
338
339     auto window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSWindowStyleMaskBorderless backing:NSBackingStoreBuffered defer:YES]);
340     [[window contentView] addSubview:webView.get()];
341
342     auto controller = adoptNS([[DecidePolicyForNavigationActionController alloc] init]);
343     [webView setNavigationDelegate:controller.get()];
344     [webView setUIDelegate:controller.get()];
345
346     finishedNavigation = false;
347     [webView loadHTMLString:@"<form action=\"https://webkit.org/destination1.html\" target=\"B\"><input type=\"submit\" name=\"submit\" value=\"Submit\" style=\"-webkit-appearance: none; height: 100%; width: 100%\"></form>" baseURL:[NSURL URLWithString:@"http://webkit.org"]];
348     TestWebKitAPI::Util::run(&finishedNavigation);
349
350     createdWebView = false;
351     [webView evaluateJavaScript:@"window.open(\"https://webkit.org/destination2.html\", \"B\")" completionHandler:nil];
352     TestWebKitAPI::Util::run(&createdWebView);
353
354     EXPECT_EQ(WKNavigationTypeOther, [action navigationType]);
355     EXPECT_TRUE([action sourceFrame] != [action targetFrame]);
356     EXPECT_EQ(nil, [action targetFrame]);
357     EXPECT_EQ(webView.get(), [[action sourceFrame] webView]);
358     EXPECT_WK_STREQ("http", [[[action sourceFrame] securityOrigin] protocol]);
359     EXPECT_WK_STREQ("webkit.org", [[[action sourceFrame] securityOrigin] host]);
360
361     // Wait for newWebView to ask to load its initial document.
362     decidedPolicy = false;
363     [newWebView setNavigationDelegate:controller.get()];
364     TestWebKitAPI::Util::run(&decidedPolicy);
365
366     decidedPolicy = false;
367     NSPoint clickPoint = NSMakePoint(100, 100);
368     [[webView hitTest:clickPoint] mouseDown:[NSEvent mouseEventWithType:NSEventTypeLeftMouseDown location:clickPoint modifierFlags:0 timestamp:0 windowNumber:[window windowNumber] context:nil eventNumber:0 clickCount:1 pressure:1]];
369     [[webView hitTest:clickPoint] mouseUp:[NSEvent mouseEventWithType:NSEventTypeLeftMouseUp location:clickPoint modifierFlags:0 timestamp:0 windowNumber:[window windowNumber] context:nil eventNumber:0 clickCount:1 pressure:1]];
370     TestWebKitAPI::Util::run(&decidedPolicy);
371
372     EXPECT_EQ(WKNavigationTypeFormSubmitted, [action navigationType]);
373     EXPECT_TRUE([action sourceFrame] != [action targetFrame]);
374     EXPECT_EQ(webView.get(), [[action sourceFrame] webView]);
375     EXPECT_EQ(newWebView.get(), [[action targetFrame] webView]);
376     EXPECT_WK_STREQ("http", [[[action sourceFrame] securityOrigin] protocol]);
377     EXPECT_WK_STREQ("webkit.org", [[[action sourceFrame] securityOrigin] host]);
378
379     newWebView = nullptr;
380     action = nullptr;
381 }
382
383 #endif
384
385 #endif