Process Swap on Navigation causes many webpages to hang due to attempted process...
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WebKitCocoa / UserInitiatedActionInNavigationAction.mm
1 /*
2  * Copyright (C) 2014 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 "Test.h"
32 #import <WebKit/WKNavigationActionPrivate.h>
33 #import <WebKit/WKWebViewPrivate.h>
34 #import <WebKit/_WKUserInitiatedAction.h>
35 #import <wtf/RetainPtr.h>
36 #import <wtf/mac/AppKitCompatibilityDeclarations.h>
37
38 #if WK_API_ENABLED
39
40 static bool finishedNavigation;
41
42 @interface UserInitiatedActionInNavigationActionDelegate : NSObject <WKNavigationDelegate>
43 @property (nonatomic, copy, nullable) void (^policyForNavigationAction)(WKNavigationAction *, void (^)(WKNavigationActionPolicy));
44 @end
45
46 @implementation UserInitiatedActionInNavigationActionDelegate
47
48 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
49 {
50     if (_policyForNavigationAction) {
51         _policyForNavigationAction(navigationAction, decisionHandler);
52         return;
53     }
54
55     decisionHandler(WKNavigationActionPolicyAllow);
56 }
57
58 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
59 {
60     finishedNavigation = true;
61 }
62
63 @end
64
65 class UserInitiatedActionTest : public testing::Test {
66 public:
67     RetainPtr<WKWebView> webView;
68     RetainPtr<NSWindow> window;
69     RetainPtr<UserInitiatedActionInNavigationActionDelegate> delegate;
70     RetainPtr<NSURL> URL;
71
72     virtual void SetUp()
73     {
74         webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
75
76         window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSWindowStyleMaskBorderless backing:NSBackingStoreBuffered defer:YES]);
77         [[window contentView] addSubview:webView.get()];
78
79         delegate = adoptNS([[UserInitiatedActionInNavigationActionDelegate alloc] init]);
80         [webView setNavigationDelegate:delegate.get()];
81
82         URL = [[NSBundle mainBundle] URLForResource:@"open-multiple-external-url" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
83     }
84
85     NSURL *URLWithFragment(NSString *fragment)
86     {
87         NSURLComponents *URLComponents = [[NSURLComponents alloc] initWithURL:URL.get() resolvingAgainstBaseURL:NO];
88         URLComponents.fragment = fragment;
89         return URLComponents.URL;
90     }
91
92     void loadTest(NSString *test)
93     {
94         [webView loadRequest:[NSURLRequest requestWithURL:URLWithFragment(test)]];
95         TestWebKitAPI::Util::run(&finishedNavigation);
96         finishedNavigation = false;
97     }
98
99     void click()
100     {
101         NSPoint clickPoint = NSMakePoint(100, 100);
102
103         [[webView hitTest:clickPoint] mouseDown:[NSEvent mouseEventWithType:NSEventTypeLeftMouseDown location:clickPoint modifierFlags:0 timestamp:0 windowNumber:[window windowNumber] context:nil eventNumber:0 clickCount:1 pressure:1]];
104         [[webView hitTest:clickPoint] mouseUp:[NSEvent mouseEventWithType:NSEventTypeLeftMouseUp location:clickPoint modifierFlags:0 timestamp:0 windowNumber:[window windowNumber] context:nil eventNumber:0 clickCount:1 pressure:1]];
105     }
106 };
107
108 TEST_F(UserInitiatedActionTest, MailtoInNormalLoop)
109 {
110     loadTest(@"normalLoop");
111
112     __block _WKUserInitiatedAction *initialUserInitiatedAction = nil;
113     __block unsigned count = 0;
114     __block bool finishedPolicy = false;
115     delegate.get().policyForNavigationAction = ^(WKNavigationAction *navigationAction, void (^decisionHandler)(WKNavigationActionPolicy)) {
116         if ([navigationAction.request.URL.scheme isEqualToString:@"about"]) {
117             decisionHandler(WKNavigationActionPolicyAllow);
118             return;
119         }
120         
121         EXPECT_WK_STREQ(@"mailto", navigationAction.request.URL.scheme);
122         EXPECT_FALSE(navigationAction._canHandleRequest);
123         
124         if (count == 0) {
125             EXPECT_TRUE(navigationAction._isUserInitiated);
126             EXPECT_NOT_NULL(navigationAction._userInitiatedAction);
127             EXPECT_FALSE(navigationAction._userInitiatedAction.consumed);
128
129             initialUserInitiatedAction = navigationAction._userInitiatedAction;
130
131             [navigationAction._userInitiatedAction consume];
132         } else {
133             EXPECT_TRUE(navigationAction._isUserInitiated);
134             EXPECT_EQ(initialUserInitiatedAction, navigationAction._userInitiatedAction);
135             EXPECT_TRUE(navigationAction._userInitiatedAction.consumed);
136         }
137
138         if (++count == 3)
139             finishedPolicy = true;
140     
141         decisionHandler(WKNavigationActionPolicyCancel);
142     };
143
144     click();
145
146     TestWebKitAPI::Util::run(&finishedPolicy);
147 }
148
149 TEST_F(UserInitiatedActionTest, MailtoInLoopAfterTimer)
150 {
151     loadTest(@"loopAfterTimer");
152
153     __block _WKUserInitiatedAction *initialUserInitiatedAction = nil;
154     __block unsigned count = 0;
155     __block bool finishedPolicy = false;
156     delegate.get().policyForNavigationAction = ^(WKNavigationAction *navigationAction, void (^decisionHandler)(WKNavigationActionPolicy)) {
157         if ([navigationAction.request.URL.scheme isEqualToString:@"about"]) {
158             decisionHandler(WKNavigationActionPolicyAllow);
159             return;
160         }
161
162         EXPECT_WK_STREQ(@"mailto", navigationAction.request.URL.scheme);
163         EXPECT_FALSE(navigationAction._canHandleRequest);
164         
165         if (count == 0) {
166             EXPECT_TRUE(navigationAction._isUserInitiated);
167             EXPECT_NOT_NULL(navigationAction._userInitiatedAction);
168             EXPECT_FALSE(navigationAction._userInitiatedAction.consumed);
169
170             initialUserInitiatedAction = navigationAction._userInitiatedAction;
171
172             [navigationAction._userInitiatedAction consume];
173         } else {
174             EXPECT_TRUE(navigationAction._isUserInitiated);
175             EXPECT_EQ(initialUserInitiatedAction, navigationAction._userInitiatedAction);
176             EXPECT_TRUE(navigationAction._userInitiatedAction.consumed);
177         }
178
179         if (++count == 3)
180             finishedPolicy = true;
181     
182         decisionHandler(WKNavigationActionPolicyCancel);
183     };
184
185     click();
186
187     TestWebKitAPI::Util::run(&finishedPolicy);
188 }
189
190 TEST_F(UserInitiatedActionTest, MailtoInLoopAfterPostMessage)
191 {
192     loadTest(@"loopAfterPostMessage");
193
194     __block _WKUserInitiatedAction *initialUserInitiatedAction = nil;
195     __block unsigned count = 0;
196     __block bool finishedPolicy = false;
197     delegate.get().policyForNavigationAction = ^(WKNavigationAction *navigationAction, void (^decisionHandler)(WKNavigationActionPolicy)) {
198         if ([navigationAction.request.URL.scheme isEqualToString:@"about"]) {
199             decisionHandler(WKNavigationActionPolicyAllow);
200             return;
201         }
202
203         EXPECT_WK_STREQ(@"mailto", navigationAction.request.URL.scheme);
204         EXPECT_FALSE(navigationAction._canHandleRequest);
205         
206         if (count == 0) {
207             EXPECT_TRUE(navigationAction._isUserInitiated);
208             EXPECT_NOT_NULL(navigationAction._userInitiatedAction);
209             EXPECT_FALSE(navigationAction._userInitiatedAction.consumed);
210
211             initialUserInitiatedAction = navigationAction._userInitiatedAction;
212
213             [navigationAction._userInitiatedAction consume];
214         } else {
215             EXPECT_TRUE(navigationAction._isUserInitiated);
216             EXPECT_EQ(initialUserInitiatedAction, navigationAction._userInitiatedAction);
217             EXPECT_TRUE(navigationAction._userInitiatedAction.consumed);
218         }
219
220         if (++count == 3)
221             finishedPolicy = true;
222     
223         decisionHandler(WKNavigationActionPolicyCancel);
224     };
225
226     click();
227
228     TestWebKitAPI::Util::run(&finishedPolicy);
229 }
230
231 TEST_F(UserInitiatedActionTest, MailtoInLoopAfterLongTimer)
232 {
233     loadTest(@"loopAfterLongTimer");
234
235     __block unsigned count = 0;
236     __block bool finishedPolicy = false;
237     delegate.get().policyForNavigationAction = ^(WKNavigationAction *navigationAction, void (^decisionHandler)(WKNavigationActionPolicy)) {
238         if ([navigationAction.request.URL.scheme isEqualToString:@"about"]) {
239             decisionHandler(WKNavigationActionPolicyAllow);
240             return;
241         }
242
243         EXPECT_WK_STREQ(@"mailto", navigationAction.request.URL.scheme);
244         EXPECT_FALSE(navigationAction._canHandleRequest);
245         
246         EXPECT_FALSE(navigationAction._isUserInitiated);
247         EXPECT_NULL(navigationAction._userInitiatedAction);
248
249         if (++count == 3)
250             finishedPolicy = true;
251     
252         decisionHandler(WKNavigationActionPolicyCancel);
253     };
254
255     click();
256
257     TestWebKitAPI::Util::run(&finishedPolicy);
258 }
259
260 #endif
261
262 #endif