URL set by document.open() is not communicated to the UIProcess
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WebKitCocoa / OpenAndCloseWindow.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 #import "PlatformUtilities.h"
29 #import <WebKit/WKPreferences.h>
30 #import <WebKit/WKUIDelegatePrivate.h>
31 #import <WebKit/WKWebView.h>
32 #import <WebKit/WKWebViewConfiguration.h>
33 #import <WebKit/WKWindowFeaturesPrivate.h>
34 #import <wtf/RetainPtr.h>
35
36 @class OpenAndCloseWindowUIDelegate;
37 @class OpenAndCloseWindowUIDelegateAsync;
38 @class CheckWindowFeaturesUIDelegate;
39
40 static bool isDone;
41 static RetainPtr<WKWebView> openedWebView;
42 static RetainPtr<WKWindowFeatures> openWindowFeatures;
43 static RetainPtr<OpenAndCloseWindowUIDelegate> sharedUIDelegate;
44 static RetainPtr<OpenAndCloseWindowUIDelegateAsync> sharedUIDelegateAsync;
45 static RetainPtr<CheckWindowFeaturesUIDelegate> sharedCheckWindowFeaturesUIDelegate;
46
47 static void resetToConsistentState()
48 {
49     isDone = false;
50     openedWebView = nil;
51     sharedUIDelegate = nil;
52     sharedUIDelegateAsync = nil;
53     sharedCheckWindowFeaturesUIDelegate = nil;
54 }
55
56 @interface OpenAndCloseWindowUIDelegate : NSObject <WKUIDelegate>
57 @property (nonatomic, assign) WKWebView *expectedClosingView;
58 @end
59
60 @implementation OpenAndCloseWindowUIDelegate
61
62 - (void)webViewDidClose:(WKWebView *)webView
63 {
64     EXPECT_EQ(_expectedClosingView, webView);
65     isDone = true;
66 }
67
68 - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
69 {
70     openedWebView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration]);
71     [openedWebView setUIDelegate:sharedUIDelegate.get()];
72     _expectedClosingView = openedWebView.get();
73     return openedWebView.get();
74 }
75
76 @end
77
78 TEST(WebKit, OpenAndCloseWindow)
79 {
80     resetToConsistentState();
81
82     RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
83
84     sharedUIDelegate = adoptNS([[OpenAndCloseWindowUIDelegate alloc] init]);
85     [webView setUIDelegate:sharedUIDelegate.get()];
86
87     [webView configuration].preferences.javaScriptCanOpenWindowsAutomatically = YES;
88
89     NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"open-and-close-window" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
90     [webView loadRequest:request];
91
92     TestWebKitAPI::Util::run(&isDone);
93 }
94
95 @interface OpenAndCloseWindowUIDelegateAsync : OpenAndCloseWindowUIDelegate
96 @property (nonatomic) BOOL shouldCallback;
97 @property (nonatomic, assign) id savedCompletionHandler;
98 @property (nonatomic) BOOL shouldCallbackWithNil;
99 @end
100
101 @implementation OpenAndCloseWindowUIDelegateAsync
102
103 - (void)dealloc
104 {
105     [_savedCompletionHandler release];
106     [super dealloc];
107 }
108
109 - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
110 {
111     ASSERT_NOT_REACHED();
112     return nil;
113 }
114
115 - (void)_webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures completionHandler:(void (^)(WKWebView *webView))completionHandler
116 {
117     if (_shouldCallback) {
118         if (!_shouldCallbackWithNil) {
119             dispatch_async(dispatch_get_main_queue(), ^ {
120                 openedWebView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration]);
121                 [openedWebView setUIDelegate:sharedUIDelegateAsync.get()];
122                 self.expectedClosingView = openedWebView.get();
123                 completionHandler(openedWebView.get());
124             });
125         } else {
126             dispatch_async(dispatch_get_main_queue(), ^ {
127                 self.expectedClosingView = webView;
128                 completionHandler(nil);
129             });
130         }
131         return;
132     }
133
134     _savedCompletionHandler = [completionHandler copy];
135     isDone = true;
136 }
137
138 @end
139
140 TEST(WebKit, OpenAndCloseWindowAsync)
141 {
142     resetToConsistentState();
143
144     RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
145
146     sharedUIDelegateAsync = adoptNS([[OpenAndCloseWindowUIDelegateAsync alloc] init]);
147     sharedUIDelegateAsync.get().shouldCallback = YES;
148     [webView setUIDelegate:sharedUIDelegateAsync.get()];
149
150     [webView configuration].preferences.javaScriptCanOpenWindowsAutomatically = YES;
151
152     NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"open-and-close-window" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
153     [webView loadRequest:request];
154
155     TestWebKitAPI::Util::run(&isDone);
156 }
157
158 TEST(WebKit, OpenAsyncWithNil)
159 {
160     resetToConsistentState();
161
162     RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
163
164     sharedUIDelegateAsync = adoptNS([[OpenAndCloseWindowUIDelegateAsync alloc] init]);
165     sharedUIDelegateAsync.get().shouldCallback = YES;
166     sharedUIDelegateAsync.get().shouldCallbackWithNil = YES;
167     [webView setUIDelegate:sharedUIDelegateAsync.get()];
168
169     [webView configuration].preferences.javaScriptCanOpenWindowsAutomatically = YES;
170
171     NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"open-and-close-window" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
172     [webView loadRequest:request];
173
174     TestWebKitAPI::Util::run(&isDone);
175 }
176
177 // https://bugs.webkit.org/show_bug.cgi?id=171083 - Try to figure out why this fails for some configs but not others, and resolve.
178 //TEST(WebKit, OpenAndCloseWindowAsyncCallbackException)
179 //{
180 //    resetToConsistentState();
181 //
182 //    RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
183 //
184 //    sharedUIDelegateAsync = adoptNS([[OpenAndCloseWindowUIDelegateAsync alloc] init]);
185 //    sharedUIDelegateAsync.get().shouldCallback = NO;
186 //    [webView setUIDelegate:sharedUIDelegateAsync.get()];
187 //
188 //    [webView configuration].preferences.javaScriptCanOpenWindowsAutomatically = YES;
189 //
190 //    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"open-and-close-window" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
191 //    [webView loadRequest:request];
192 //
193 //    TestWebKitAPI::Util::run(&isDone);
194 //
195 //    bool caughtException = false;
196 //    @try {
197 //        sharedUIDelegateAsync = nil;
198 //        openedWebView = nil;
199 //        webView = nil;
200 //    }
201 //    @catch (NSException *) {
202 //        caughtException = true;
203 //    }
204 //
205 //    EXPECT_EQ(caughtException, true);
206 //}
207
208
209 @interface CheckWindowFeaturesUIDelegate : NSObject <WKUIDelegate>
210
211 @property (nullable, nonatomic, readonly) NSNumber *menuBarVisibility;
212 @property (nullable, nonatomic, readonly) NSNumber *statusBarVisibility;
213 @property (nullable, nonatomic, readonly) NSNumber *toolbarsVisibility;
214
215 @end
216
217 @implementation CheckWindowFeaturesUIDelegate
218
219 - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
220 {
221     openWindowFeatures = windowFeatures;
222     isDone = true;
223
224     return nil;
225 }
226
227 @end
228
229 TEST(WebKit, OpenWindowFeatures)
230 {
231     resetToConsistentState();
232
233     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
234
235     sharedCheckWindowFeaturesUIDelegate = adoptNS([[CheckWindowFeaturesUIDelegate alloc] init]);
236     [webView setUIDelegate:sharedCheckWindowFeaturesUIDelegate.get()];
237     [webView configuration].preferences.javaScriptCanOpenWindowsAutomatically = YES;
238     NSString *windowOpenFormatString = @"window.open(\"about:blank\", \"_blank\", \"%@\")";
239
240     [webView evaluateJavaScript:@"window.open(\"about:blank\")" completionHandler:nil];
241     TestWebKitAPI::Util::run(&isDone);
242     isDone = false;
243
244 //  https://bugs.webkit.org/show_bug.cgi?id=174271 - WebCore currently doesn't distinguish between unspecified (nil) and false
245 //  for the following window features.
246 //  EXPECT_TRUE([openWindowFeatures menuBarVisibility] == nil);
247 //  EXPECT_TRUE([openWindowFeatures statusBarVisibility] == nil);
248 //  EXPECT_TRUE([openWindowFeatures toolbarsVisibility] == nil);
249 //  EXPECT_TRUE([openWindowFeatures allowsResizing] == nil);
250 //  EXPECT_TRUE([openWindowFeatures _locationBarVisibility] == nil);
251 //  EXPECT_TRUE([openWindowFeatures _scrollbarsVisibility] == nil);
252 //  EXPECT_TRUE([openWindowFeatures _fullscreenDisplay] == nil);
253 //  EXPECT_TRUE([openWindowFeatures _dialogDisplay] == nil);
254     openWindowFeatures = nullptr;
255
256     NSString *featuresStringAllSpecifiedAndTrue = @"menubar=yes,status=yes,toolbar=yes,resizable=yes,location=yes,scrollbars=yes,fullscreen=yes";
257     [webView evaluateJavaScript:[NSString stringWithFormat:windowOpenFormatString, featuresStringAllSpecifiedAndTrue] completionHandler:nil];
258     TestWebKitAPI::Util::run(&isDone);
259     isDone = false;
260
261     EXPECT_TRUE([openWindowFeatures menuBarVisibility].boolValue);
262     EXPECT_TRUE([openWindowFeatures statusBarVisibility].boolValue);
263     EXPECT_TRUE([openWindowFeatures toolbarsVisibility].boolValue);
264     EXPECT_TRUE([openWindowFeatures allowsResizing].boolValue);
265     EXPECT_TRUE([openWindowFeatures _locationBarVisibility].boolValue);
266     EXPECT_TRUE([openWindowFeatures _scrollbarsVisibility].boolValue);
267     EXPECT_TRUE([openWindowFeatures _fullscreenDisplay].boolValue);
268     openWindowFeatures = nullptr;
269
270     NSString *featuresStringAllSpecifiedAndFalse = @"menubar=no,status=no,toolbar=no,resizable=no,location=no,scrollbars=no,fullscreen=no";
271     [webView evaluateJavaScript:[NSString stringWithFormat:windowOpenFormatString, featuresStringAllSpecifiedAndFalse] completionHandler:nil];
272     TestWebKitAPI::Util::run(&isDone);
273     isDone = false;
274
275     EXPECT_FALSE([openWindowFeatures menuBarVisibility].boolValue);
276     EXPECT_FALSE([openWindowFeatures statusBarVisibility ].boolValue);
277     EXPECT_FALSE([openWindowFeatures toolbarsVisibility].boolValue);
278 //  https://bugs.webkit.org/show_bug.cgi?id=174388 - This property doesn't accurately reflect the parameters passed by the webpage.
279 //  EXPECT_FALSE([openWindowFeatures allowsResizing].boolValue);
280     EXPECT_FALSE([openWindowFeatures _locationBarVisibility].boolValue);
281     EXPECT_FALSE([openWindowFeatures _scrollbarsVisibility].boolValue);
282     EXPECT_FALSE([openWindowFeatures _fullscreenDisplay].boolValue);
283     openWindowFeatures = nullptr;
284 }
285
286 @interface OpenWindowThenDocumentOpenUIDelegate : NSObject <WKUIDelegate>
287 @end
288
289 @implementation OpenWindowThenDocumentOpenUIDelegate
290
291 - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
292 {
293     openedWebView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration]);
294     [openedWebView setUIDelegate:sharedUIDelegate.get()];
295     return openedWebView.get();
296 }
297
298 @end
299
300 TEST(WebKit, OpenWindowThenDocumentOpen)
301 {
302     resetToConsistentState();
303
304     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
305
306     auto uiDelegate = adoptNS([[OpenWindowThenDocumentOpenUIDelegate alloc] init]);
307     [webView setUIDelegate:uiDelegate.get()];
308     [webView configuration].preferences.javaScriptCanOpenWindowsAutomatically = YES;
309
310     NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"open-window-then-write-to-it" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
311     [webView loadRequest:request];
312
313     while (!openedWebView)
314         TestWebKitAPI::Util::sleep(0.1);
315
316     // Both WebViews should have the same URL because of document.open().
317     while (![[[openedWebView URL] absoluteString] isEqualToString:[[webView URL] absoluteString]])
318         TestWebKitAPI::Util::sleep(0.1);
319 }