Regression(PSON): Assertion hit under WebPageProxy::didNavigateWithNavigationData()
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WebKitCocoa / ProcessSwapOnNavigation.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 #import "config.h"
27
28 #import "PlatformUtilities.h"
29 #import "Test.h"
30 #import <WebKit/WKInspector.h>
31 #import <WebKit/WKNavigationDelegatePrivate.h>
32 #import <WebKit/WKNavigationPrivate.h>
33 #import <WebKit/WKPreferencesPrivate.h>
34 #import <WebKit/WKProcessPoolPrivate.h>
35 #import <WebKit/WKUIDelegatePrivate.h>
36 #import <WebKit/WKURLSchemeHandler.h>
37 #import <WebKit/WKURLSchemeTaskPrivate.h>
38 #import <WebKit/WKWebViewConfigurationPrivate.h>
39 #import <WebKit/WKWebViewPrivate.h>
40 #import <WebKit/WKWebsiteDataStorePrivate.h>
41 #import <WebKit/WKWebsiteDataStoreRef.h>
42 #import <WebKit/WebKit.h>
43 #import <WebKit/_WKExperimentalFeature.h>
44 #import <WebKit/_WKProcessPoolConfiguration.h>
45 #import <WebKit/_WKWebsiteDataStoreConfiguration.h>
46 #import <WebKit/_WKWebsitePolicies.h>
47 #import <wtf/Deque.h>
48 #import <wtf/HashMap.h>
49 #import <wtf/HashSet.h>
50 #import <wtf/RetainPtr.h>
51 #import <wtf/Vector.h>
52 #import <wtf/text/StringHash.h>
53 #import <wtf/text/WTFString.h>
54
55 #if WK_API_ENABLED
56
57 @interface WKProcessPool ()
58 - (WKContextRef)_contextForTesting;
59 @end
60
61 static bool done;
62 static bool failed;
63 static bool didCreateWebView;
64 static int numberOfDecidePolicyCalls;
65
66 static RetainPtr<NSMutableArray> receivedMessages = adoptNS([@[] mutableCopy]);
67 bool didReceiveAlert;
68 static bool receivedMessage;
69 static bool serverRedirected;
70 static HashSet<pid_t> seenPIDs;
71 @interface PSONMessageHandler : NSObject <WKScriptMessageHandler>
72 @end
73
74 @implementation PSONMessageHandler
75 - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
76 {
77     if ([message body])
78         [receivedMessages addObject:[message body]];
79     else
80         [receivedMessages addObject:@""];
81
82     receivedMessage = true;
83     if ([message.webView _webProcessIdentifier])
84         seenPIDs.add([message.webView _webProcessIdentifier]);
85 }
86 @end
87
88 @interface PSONNavigationDelegate : NSObject <WKNavigationDelegate> {
89     @public WKNavigationActionPolicy navigationActionPolicyToUse;
90 }
91 @end
92
93 @implementation PSONNavigationDelegate
94
95 - (instancetype) init
96 {
97     self = [super init];
98     navigationActionPolicyToUse = WKNavigationActionPolicyAllow;
99     return self;
100 }
101
102 - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error
103 {
104     seenPIDs.add([webView _webProcessIdentifier]);
105     failed = true;
106 }
107
108 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
109 {
110     seenPIDs.add([webView _webProcessIdentifier]);
111     done = true;
112 }
113
114 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
115 {
116     ++numberOfDecidePolicyCalls;
117     seenPIDs.add([webView _webProcessIdentifier]);
118     decisionHandler(navigationActionPolicyToUse);
119 }
120
121 - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation
122 {
123     seenPIDs.add([webView _webProcessIdentifier]);
124     serverRedirected = true;
125 }
126
127 @end
128
129 static RetainPtr<WKWebView> createdWebView;
130
131 @interface PSONUIDelegate : NSObject <WKUIDelegatePrivate>
132 - (instancetype)initWithNavigationDelegate:(PSONNavigationDelegate *)navigationDelegate;
133 @end
134
135 @implementation PSONUIDelegate {
136     RetainPtr<PSONNavigationDelegate> _navigationDelegate;
137 }
138
139 - (instancetype)initWithNavigationDelegate:(PSONNavigationDelegate *)navigationDelegate
140 {
141     if (!(self = [super init]))
142         return nil;
143
144     _navigationDelegate = navigationDelegate;
145     return self;
146 }
147
148 - (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
149 {
150     createdWebView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration]);
151     [createdWebView setNavigationDelegate:_navigationDelegate.get()];
152     didCreateWebView = true;
153     return createdWebView.get();
154 }
155
156 - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)())completionHandler
157 {
158     didReceiveAlert = true;
159     completionHandler();
160 }
161
162 @end
163
164 @interface PSONScheme : NSObject <WKURLSchemeHandler> {
165     const char* _bytes;
166     HashMap<String, String> _redirects;
167     HashMap<String, RetainPtr<NSData *>> _dataMappings;
168 }
169 - (instancetype)initWithBytes:(const char*)bytes;
170 - (void)addRedirectFromURLString:(NSString *)sourceURLString toURLString:(NSString *)destinationURLString;
171 - (void)addMappingFromURLString:(NSString *)urlString toData:(const char*)data;
172 @end
173
174 @implementation PSONScheme
175
176 - (instancetype)initWithBytes:(const char*)bytes
177 {
178     self = [super init];
179     _bytes = bytes;
180     return self;
181 }
182
183 - (void)addRedirectFromURLString:(NSString *)sourceURLString toURLString:(NSString *)destinationURLString
184 {
185     _redirects.set(sourceURLString, destinationURLString);
186 }
187
188 - (void)addMappingFromURLString:(NSString *)urlString toData:(const char*)data
189 {
190     _dataMappings.set(urlString, [NSData dataWithBytesNoCopy:(void*)data length:strlen(data) freeWhenDone:NO]);
191 }
192
193 - (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)task
194 {
195     NSURL *finalURL = task.request.URL;
196     auto target = _redirects.get(task.request.URL.absoluteString);
197     if (!target.isEmpty()) {
198         auto redirectResponse = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:nil expectedContentLength:0 textEncodingName:nil]);
199
200         finalURL = [NSURL URLWithString:(NSString *)target];
201         auto request = adoptNS([[NSURLRequest alloc] initWithURL:finalURL]);
202
203         [(id<WKURLSchemeTaskPrivate>)task _didPerformRedirection:redirectResponse.get() newRequest:request.get()];
204     }
205
206     RetainPtr<NSURLResponse> response = adoptNS([[NSURLResponse alloc] initWithURL:finalURL MIMEType:@"text/html" expectedContentLength:1 textEncodingName:nil]);
207     [task didReceiveResponse:response.get()];
208
209     if (auto data = _dataMappings.get([finalURL absoluteString]))
210         [task didReceiveData:data.get()];
211     else if (_bytes) {
212         RetainPtr<NSData> data = adoptNS([[NSData alloc] initWithBytesNoCopy:(void *)_bytes length:strlen(_bytes) freeWhenDone:NO]);
213         [task didReceiveData:data.get()];
214     } else
215         [task didReceiveData:[@"Hello" dataUsingEncoding:NSUTF8StringEncoding]];
216
217     [task didFinish];
218 }
219
220 - (void)webView:(WKWebView *)webView stopURLSchemeTask:(id <WKURLSchemeTask>)task
221 {
222 }
223
224 @end
225
226 static const char* testBytes = R"PSONRESOURCE(
227 <head>
228 <script>
229
230 function log(msg)
231 {
232     window.webkit.messageHandlers.pson.postMessage(msg);
233 }
234
235 window.onload = function(evt) {
236     if (window.history.state != "onloadCalled")
237         setTimeout('window.history.replaceState("onloadCalled", "");', 0);
238 }
239
240 window.onpageshow = function(evt) {
241     log("PageShow called. Persisted: " + evt.persisted + ", and window.history.state is: " + window.history.state);
242 }
243
244 </script>
245 </head>
246 )PSONRESOURCE";
247
248 #if PLATFORM(MAC)
249
250 static const char* windowOpenCrossSiteNoOpenerTestBytes = R"PSONRESOURCE(
251 <script>
252 window.onload = function() {
253     window.open("pson://www.apple.com/main.html", "_blank", "noopener");
254 }
255 </script>
256 )PSONRESOURCE";
257
258 static const char* windowOpenCrossOriginButSameSiteNoOpenerTestBytes = R"PSONRESOURCE(
259 <script>
260 window.onload = function() {
261     window.open("pson://www.webkit.org:8080/main.html", "_blank", "noopener");
262 }
263 </script>
264 )PSONRESOURCE";
265
266 static const char* windowOpenCrossSiteWithOpenerTestBytes = R"PSONRESOURCE(
267 <script>
268 window.onload = function() {
269     window.open("pson://www.apple.com/main.html");
270 }
271 </script>
272 )PSONRESOURCE";
273
274 static const char* windowOpenSameSiteNoOpenerTestBytes = R"PSONRESOURCE(
275 <script>
276 window.onload = function() {
277     if (!opener)
278         window.open("pson://www.webkit.org/main.html", "_blank", "noopener");
279 }
280 </script>
281 )PSONRESOURCE";
282
283 static const char* targetBlankCrossSiteWithOpenerTestBytes = R"PSONRESOURCE(
284 <a id="testLink" target="_blank" href="pson://www.apple.com/main.html">Link</a>
285 <script>
286 window.onload = function() {
287     testLink.click();
288 }
289 </script>
290 )PSONRESOURCE";
291
292 static const char* targetBlankCrossSiteNoOpenerTestBytes = R"PSONRESOURCE(
293 <a id="testLink" target="_blank" href="pson://www.apple.com/main.html" rel="noopener">Link</a>
294 <script>
295 window.onload = function() {
296     testLink.click();
297 }
298 </script>
299 )PSONRESOURCE";
300
301 static const char* targetBlankSameSiteNoOpenerTestBytes = R"PSONRESOURCE(
302 <a id="testLink" target="_blank" href="pson://www.webkit.org/main2.html" rel="noopener">Link</a>
303 <script>
304 window.onload = function() {
305     testLink.click();
306 }
307 </script>
308 )PSONRESOURCE";
309
310 static const char* linkToAppleTestBytes = R"PSONRESOURCE(
311 <script>
312 window.addEventListener('pageshow', function(event) {
313     if (event.persisted)
314         window.webkit.messageHandlers.pson.postMessage("Was persisted");
315 });
316 </script>
317 <a id="testLink" href="pson://www.apple.com/main.html">Navigate</a>
318 )PSONRESOURCE";
319
320 #endif // PLATFORM(MAC)
321
322 TEST(ProcessSwap, Basic)
323 {
324     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
325     processPoolConfiguration.get().processSwapsOnNavigation = YES;
326     processPoolConfiguration.get().prewarmsProcessesAutomatically = YES;
327     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
328
329     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
330     [webViewConfiguration setProcessPool:processPool.get()];
331     auto handler = adoptNS([[PSONScheme alloc] init]);
332     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
333
334     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
335     auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
336     [webView setNavigationDelegate:delegate.get()];
337
338     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main1.html"]];
339     [webView loadRequest:request];
340
341     TestWebKitAPI::Util::run(&done);
342     done = false;
343
344     auto pid1 = [webView _webProcessIdentifier];
345
346     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main2.html"]];
347     [webView loadRequest:request];
348
349     TestWebKitAPI::Util::run(&done);
350     done = false;
351
352     auto pid2 = [webView _webProcessIdentifier];
353
354     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.apple.com/main2.html"]];
355     [webView loadRequest:request];
356
357     TestWebKitAPI::Util::run(&done);
358     done = false;
359
360     auto pid3 = [webView _webProcessIdentifier];
361
362     EXPECT_EQ(pid1, pid2);
363     EXPECT_FALSE(pid2 == pid3);
364
365     // 3 loads, 3 decidePolicy calls (e.g. the load that did perform a process swap should not have generated an additional decidePolicy call)
366     EXPECT_EQ(numberOfDecidePolicyCalls, 3);
367 }
368
369 TEST(ProcessSwap, NoSwappingForeTLDPlus2)
370 {
371     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
372     processPoolConfiguration.get().processSwapsOnNavigation = YES;
373     processPoolConfiguration.get().prewarmsProcessesAutomatically = YES;
374     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
375
376     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
377     [webViewConfiguration setProcessPool:processPool.get()];
378     auto handler = adoptNS([[PSONScheme alloc] init]);
379     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
380
381     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
382     auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
383     [webView setNavigationDelegate:delegate.get()];
384
385     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www1.webkit.org/main1.html"]];
386     [webView loadRequest:request];
387
388     TestWebKitAPI::Util::run(&done);
389     done = false;
390
391     auto pid1 = [webView _webProcessIdentifier];
392
393     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www2.webkit.org/main2.html"]];
394     [webView loadRequest:request];
395
396     TestWebKitAPI::Util::run(&done);
397     done = false;
398
399     auto pid2 = [webView _webProcessIdentifier];
400
401     EXPECT_EQ(pid1, pid2);
402
403     EXPECT_EQ(numberOfDecidePolicyCalls, 2);
404 }
405
406 TEST(ProcessSwap, Back)
407 {
408     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
409     processPoolConfiguration.get().processSwapsOnNavigation = YES;
410     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
411
412     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
413     [webViewConfiguration setProcessPool:processPool.get()];
414     auto handler = adoptNS([[PSONScheme alloc] init]);
415     [handler addMappingFromURLString:@"pson://www.webkit.org/main.html" toData:testBytes];
416     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
417
418     RetainPtr<PSONMessageHandler> messageHandler = adoptNS([[PSONMessageHandler alloc] init]);
419     [[webViewConfiguration userContentController] addScriptMessageHandler:messageHandler.get() name:@"pson"];
420
421     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
422     auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
423     [webView setNavigationDelegate:delegate.get()];
424
425     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
426     [webView loadRequest:request];
427
428     TestWebKitAPI::Util::run(&receivedMessage);
429     receivedMessage = false;
430     TestWebKitAPI::Util::run(&done);
431     done = false;
432
433     auto pid1 = [webView _webProcessIdentifier];
434
435     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.apple.com/main.html"]];
436     [webView loadRequest:request];
437
438     TestWebKitAPI::Util::run(&done);
439     done = false;
440
441     auto pid2 = [webView _webProcessIdentifier];
442
443     [webView goBack];
444
445     TestWebKitAPI::Util::run(&receivedMessage);
446     receivedMessage = false;
447     TestWebKitAPI::Util::run(&done);
448     done = false;
449
450     auto pid3 = [webView _webProcessIdentifier];
451
452     // 3 loads, 3 decidePolicy calls (e.g. any load that performs a process swap should not have generated an
453     // additional decidePolicy call as a result of the process swap)
454     EXPECT_EQ(numberOfDecidePolicyCalls, 3);
455
456     EXPECT_EQ([receivedMessages count], 2u);
457     EXPECT_TRUE([receivedMessages.get()[0] isEqualToString:@"PageShow called. Persisted: false, and window.history.state is: null"]);
458     EXPECT_TRUE([receivedMessages.get()[1] isEqualToString:@"PageShow called. Persisted: true, and window.history.state is: onloadCalled"]);
459
460     EXPECT_EQ(2u, seenPIDs.size());
461
462     EXPECT_FALSE(pid1 == pid2);
463     EXPECT_FALSE(pid2 == pid3);
464     EXPECT_TRUE(pid1 == pid3);
465 }
466
467 TEST(ProcessSwap, BackWithoutSuspendedPage)
468 {
469     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
470     processPoolConfiguration.get().processSwapsOnNavigation = YES;
471     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
472
473     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
474     [webViewConfiguration setProcessPool:processPool.get()];
475     auto handler = adoptNS([[PSONScheme alloc] init]);
476     [handler addMappingFromURLString:@"pson://www.webkit.org/main.html" toData:testBytes];
477     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
478
479     RetainPtr<PSONMessageHandler> messageHandler = adoptNS([[PSONMessageHandler alloc] init]);
480     [[webViewConfiguration userContentController] addScriptMessageHandler:messageHandler.get() name:@"pson"];
481
482     auto webView1 = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
483     auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
484     [webView1 setNavigationDelegate:delegate.get()];
485
486     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
487     [webView1 loadRequest:request];
488
489     TestWebKitAPI::Util::run(&receivedMessage);
490     receivedMessage = false;
491     TestWebKitAPI::Util::run(&done);
492     done = false;
493
494     auto pid1 = [webView1 _webProcessIdentifier];
495     RetainPtr<_WKSessionState> sessionState = [webView1 _sessionState];
496     webView1 = nullptr;
497
498     auto webView2 = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
499     delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
500     [webView2 setNavigationDelegate:delegate.get()];
501
502     [webView2 _restoreSessionState:sessionState.get() andNavigate:NO];
503
504     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.apple.com/main.html"]];
505     [webView2 loadRequest:request];
506
507     TestWebKitAPI::Util::run(&done);
508     done = false;
509
510     auto pid2 = [webView2 _webProcessIdentifier];
511
512     [webView2 goBack];
513
514     TestWebKitAPI::Util::run(&receivedMessage);
515     receivedMessage = false;
516     TestWebKitAPI::Util::run(&done);
517     done = false;
518
519     auto pid3 = [webView2 _webProcessIdentifier];
520
521     EXPECT_FALSE(pid1 == pid2);
522     EXPECT_FALSE(pid2 == pid3);
523 }
524
525 #if PLATFORM(MAC)
526
527 TEST(ProcessSwap, CrossSiteWindowOpenNoOpener)
528 {
529     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
530     processPoolConfiguration.get().processSwapsOnNavigation = YES;
531     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
532
533     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
534     [webViewConfiguration setProcessPool:processPool.get()];
535     auto handler = adoptNS([[PSONScheme alloc] init]);
536     [handler addMappingFromURLString:@"pson://www.webkit.org/main.html" toData:windowOpenCrossSiteNoOpenerTestBytes];
537     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
538
539     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
540     auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
541     [webView setNavigationDelegate:navigationDelegate.get()];
542     auto uiDelegate = adoptNS([[PSONUIDelegate alloc] initWithNavigationDelegate:navigationDelegate.get()]);
543     [webView setUIDelegate:uiDelegate.get()];
544
545     numberOfDecidePolicyCalls = 0;
546     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
547     [webView loadRequest:request];
548
549     TestWebKitAPI::Util::run(&done);
550     done = false;
551
552     TestWebKitAPI::Util::run(&didCreateWebView);
553     didCreateWebView = false;
554
555     TestWebKitAPI::Util::run(&done);
556
557     EXPECT_EQ(2, numberOfDecidePolicyCalls);
558
559     auto pid1 = [webView _webProcessIdentifier];
560     EXPECT_TRUE(!!pid1);
561     auto pid2 = [createdWebView _webProcessIdentifier];
562     EXPECT_TRUE(!!pid2);
563
564     EXPECT_NE(pid1, pid2);
565 }
566
567 TEST(ProcessSwap, CrossOriginButSameSiteWindowOpenNoOpener)
568 {
569     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
570     processPoolConfiguration.get().processSwapsOnNavigation = YES;
571     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
572
573     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
574     [webViewConfiguration setProcessPool:processPool.get()];
575     auto handler = adoptNS([[PSONScheme alloc] init]);
576     [handler addMappingFromURLString:@"pson://www.webkit.org/main.html" toData:windowOpenCrossOriginButSameSiteNoOpenerTestBytes];
577     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
578
579     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
580     auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
581     [webView setNavigationDelegate:navigationDelegate.get()];
582     auto uiDelegate = adoptNS([[PSONUIDelegate alloc] initWithNavigationDelegate:navigationDelegate.get()]);
583     [webView setUIDelegate:uiDelegate.get()];
584
585     numberOfDecidePolicyCalls = 0;
586     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
587     [webView loadRequest:request];
588
589     TestWebKitAPI::Util::run(&done);
590     done = false;
591
592     TestWebKitAPI::Util::run(&didCreateWebView);
593     didCreateWebView = false;
594
595     TestWebKitAPI::Util::run(&done);
596
597     EXPECT_EQ(2, numberOfDecidePolicyCalls);
598
599     auto pid1 = [webView _webProcessIdentifier];
600     EXPECT_TRUE(!!pid1);
601     auto pid2 = [createdWebView _webProcessIdentifier];
602     EXPECT_TRUE(!!pid2);
603
604     EXPECT_EQ(pid1, pid2);
605 }
606
607 TEST(ProcessSwap, CrossSiteWindowOpenWithOpener)
608 {
609     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
610     processPoolConfiguration.get().processSwapsOnNavigation = YES;
611     processPoolConfiguration.get().processSwapsOnWindowOpenWithOpener = YES;
612     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
613
614     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
615     [webViewConfiguration setProcessPool:processPool.get()];
616     auto handler = adoptNS([[PSONScheme alloc] init]);
617     [handler addMappingFromURLString:@"pson://www.webkit.org/main.html" toData:windowOpenCrossSiteWithOpenerTestBytes];
618     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
619
620     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
621     auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
622     [webView setNavigationDelegate:navigationDelegate.get()];
623     auto uiDelegate = adoptNS([[PSONUIDelegate alloc] initWithNavigationDelegate:navigationDelegate.get()]);
624     [webView setUIDelegate:uiDelegate.get()];
625
626     numberOfDecidePolicyCalls = 0;
627     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
628     [webView loadRequest:request];
629
630     TestWebKitAPI::Util::run(&done);
631     done = false;
632
633     TestWebKitAPI::Util::run(&didCreateWebView);
634     didCreateWebView = false;
635
636     TestWebKitAPI::Util::run(&done);
637
638     EXPECT_EQ(2, numberOfDecidePolicyCalls);
639
640     auto pid1 = [webView _webProcessIdentifier];
641     EXPECT_TRUE(!!pid1);
642     auto pid2 = [createdWebView _webProcessIdentifier];
643     EXPECT_TRUE(!!pid2);
644
645     EXPECT_NE(pid1, pid2);
646 }
647
648 TEST(ProcessSwap, SameSiteWindowOpenNoOpener)
649 {
650     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
651     processPoolConfiguration.get().processSwapsOnNavigation = YES;
652     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
653
654     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
655     [webViewConfiguration setProcessPool:processPool.get()];
656     auto handler = adoptNS([[PSONScheme alloc] initWithBytes:windowOpenSameSiteNoOpenerTestBytes]);
657     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
658
659     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
660     auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
661     [webView setNavigationDelegate:navigationDelegate.get()];
662     auto uiDelegate = adoptNS([[PSONUIDelegate alloc] initWithNavigationDelegate:navigationDelegate.get()]);
663     [webView setUIDelegate:uiDelegate.get()];
664
665     numberOfDecidePolicyCalls = 0;
666     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
667     [webView loadRequest:request];
668
669     TestWebKitAPI::Util::run(&done);
670     done = false;
671
672     TestWebKitAPI::Util::run(&didCreateWebView);
673     didCreateWebView = false;
674
675     TestWebKitAPI::Util::run(&done);
676
677     EXPECT_EQ(2, numberOfDecidePolicyCalls);
678
679     auto pid1 = [webView _webProcessIdentifier];
680     EXPECT_TRUE(!!pid1);
681     auto pid2 = [createdWebView _webProcessIdentifier];
682     EXPECT_TRUE(!!pid2);
683
684     EXPECT_EQ(pid1, pid2);
685 }
686
687 TEST(ProcessSwap, CrossSiteBlankTargetWithOpener)
688 {
689     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
690     processPoolConfiguration.get().processSwapsOnNavigation = YES;
691     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
692
693     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
694     [webViewConfiguration setProcessPool:processPool.get()];
695     auto handler = adoptNS([[PSONScheme alloc] init]);
696     [handler addMappingFromURLString:@"pson://www.webkit.org/main.html" toData:targetBlankCrossSiteWithOpenerTestBytes];
697     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
698
699     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
700     auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
701     [webView setNavigationDelegate:navigationDelegate.get()];
702     auto uiDelegate = adoptNS([[PSONUIDelegate alloc] initWithNavigationDelegate:navigationDelegate.get()]);
703     [webView setUIDelegate:uiDelegate.get()];
704
705     numberOfDecidePolicyCalls = 0;
706     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
707     [webView loadRequest:request];
708
709     TestWebKitAPI::Util::run(&done);
710     done = false;
711
712     TestWebKitAPI::Util::run(&didCreateWebView);
713     didCreateWebView = false;
714
715     TestWebKitAPI::Util::run(&done);
716
717     EXPECT_EQ(3, numberOfDecidePolicyCalls);
718
719     auto pid1 = [webView _webProcessIdentifier];
720     EXPECT_TRUE(!!pid1);
721     auto pid2 = [createdWebView _webProcessIdentifier];
722     EXPECT_TRUE(!!pid2);
723
724     EXPECT_EQ(pid1, pid2);
725 }
726
727 TEST(ProcessSwap, CrossSiteBlankTargetNoOpener)
728 {
729     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
730     processPoolConfiguration.get().processSwapsOnNavigation = YES;
731     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
732
733     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
734     [webViewConfiguration setProcessPool:processPool.get()];
735     auto handler = adoptNS([[PSONScheme alloc] init]);
736     [handler addMappingFromURLString:@"pson://www.webkit.org/main.html" toData:targetBlankCrossSiteNoOpenerTestBytes];
737     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
738
739     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
740     auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
741     [webView setNavigationDelegate:navigationDelegate.get()];
742     auto uiDelegate = adoptNS([[PSONUIDelegate alloc] initWithNavigationDelegate:navigationDelegate.get()]);
743     [webView setUIDelegate:uiDelegate.get()];
744
745     numberOfDecidePolicyCalls = 0;
746     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
747     [webView loadRequest:request];
748
749     TestWebKitAPI::Util::run(&done);
750     done = false;
751
752     TestWebKitAPI::Util::run(&didCreateWebView);
753     didCreateWebView = false;
754
755     TestWebKitAPI::Util::run(&done);
756
757     EXPECT_EQ(3, numberOfDecidePolicyCalls);
758
759     auto pid1 = [webView _webProcessIdentifier];
760     EXPECT_TRUE(!!pid1);
761     auto pid2 = [createdWebView _webProcessIdentifier];
762     EXPECT_TRUE(!!pid2);
763
764     EXPECT_NE(pid1, pid2);
765 }
766
767 TEST(ProcessSwap, SameSiteBlankTargetNoOpener)
768 {
769     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
770     processPoolConfiguration.get().processSwapsOnNavigation = YES;
771     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
772
773     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
774     [webViewConfiguration setProcessPool:processPool.get()];
775     auto handler = adoptNS([[PSONScheme alloc] init]);
776     [handler addMappingFromURLString:@"pson://www.webkit.org/main.html" toData:targetBlankSameSiteNoOpenerTestBytes];
777     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
778
779     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
780     auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
781     [webView setNavigationDelegate:navigationDelegate.get()];
782     auto uiDelegate = adoptNS([[PSONUIDelegate alloc] initWithNavigationDelegate:navigationDelegate.get()]);
783     [webView setUIDelegate:uiDelegate.get()];
784
785     numberOfDecidePolicyCalls = 0;
786     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
787     [webView loadRequest:request];
788
789     TestWebKitAPI::Util::run(&done);
790     done = false;
791
792     TestWebKitAPI::Util::run(&didCreateWebView);
793     didCreateWebView = false;
794
795     TestWebKitAPI::Util::run(&done);
796
797     EXPECT_EQ(3, numberOfDecidePolicyCalls);
798
799     auto pid1 = [webView _webProcessIdentifier];
800     EXPECT_TRUE(!!pid1);
801     auto pid2 = [createdWebView _webProcessIdentifier];
802     EXPECT_TRUE(!!pid2);
803
804     EXPECT_EQ(pid1, pid2);
805 }
806
807 #endif // PLATFORM(MAC)
808
809 TEST(ProcessSwap, ServerRedirectFromNewWebView)
810 {
811     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
812     processPoolConfiguration.get().processSwapsOnNavigation = YES;
813     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
814
815     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
816     [webViewConfiguration setProcessPool:processPool.get()];
817     auto handler = adoptNS([[PSONScheme alloc] init]);
818     [handler addRedirectFromURLString:@"pson://www.webkit.org/main.html" toURLString:@"pson://www.apple.com/main.html"];
819     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"pson"];
820
821     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
822     auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
823     [webView setNavigationDelegate:delegate.get()];
824
825     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
826     [webView loadRequest:request];
827
828     TestWebKitAPI::Util::run(&serverRedirected);
829     serverRedirected = false;
830
831     seenPIDs.add([webView _webProcessIdentifier]);
832
833     TestWebKitAPI::Util::run(&done);
834     done = false;
835
836     seenPIDs.add([webView _webProcessIdentifier]);
837
838     EXPECT_FALSE(serverRedirected);
839     EXPECT_EQ(2, numberOfDecidePolicyCalls);
840     EXPECT_EQ(1u, seenPIDs.size());
841 }
842
843 TEST(ProcessSwap, ServerRedirect)
844 {
845     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
846     processPoolConfiguration.get().processSwapsOnNavigation = YES;
847     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
848
849     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
850     [webViewConfiguration setProcessPool:processPool.get()];
851     auto handler = adoptNS([[PSONScheme alloc] init]);
852     [handler addRedirectFromURLString:@"pson://www.webkit.org/main.html" toURLString:@"pson://www.apple.com/main.html"];
853     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"pson"];
854
855     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
856     auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
857     [webView setNavigationDelegate:delegate.get()];
858
859     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.google.com/main1.html"]];
860     [webView loadRequest:request];
861
862     TestWebKitAPI::Util::run(&done);
863     done = false;
864
865     auto pidAfterFirstLoad = [webView _webProcessIdentifier];
866
867     EXPECT_EQ(1, numberOfDecidePolicyCalls);
868     EXPECT_EQ(1u, seenPIDs.size());
869     EXPECT_TRUE(*seenPIDs.begin() == pidAfterFirstLoad);
870
871     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
872     [webView loadRequest:request];
873
874     TestWebKitAPI::Util::run(&serverRedirected);
875     serverRedirected = false;
876
877     seenPIDs.add([webView _webProcessIdentifier]);
878
879     TestWebKitAPI::Util::run(&done);
880     done = false;
881
882     seenPIDs.add([webView _webProcessIdentifier]);
883
884     EXPECT_FALSE(serverRedirected);
885     EXPECT_EQ(3, numberOfDecidePolicyCalls);
886     EXPECT_EQ(2u, seenPIDs.size());
887 }
888
889 TEST(ProcessSwap, ServerRedirect2)
890 {
891     // This tests a load that *starts out* to the same origin as the previous load, but then redirects to a new origin.
892     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
893     processPoolConfiguration.get().processSwapsOnNavigation = YES;
894     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
895
896     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
897     [webViewConfiguration setProcessPool:processPool.get()];
898     auto handler1 = adoptNS([[PSONScheme alloc] init]);
899     [handler1 addRedirectFromURLString:@"pson://www.webkit.org/main2.html" toURLString:@"pson://www.apple.com/main.html"];
900     [webViewConfiguration setURLSchemeHandler:handler1.get() forURLScheme:@"pson"];
901     auto handler2 = adoptNS([[PSONScheme alloc] init]);
902     [webViewConfiguration setURLSchemeHandler:handler2.get() forURLScheme:@"psonredirected"];
903
904     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
905     auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
906     [webView setNavigationDelegate:delegate.get()];
907
908     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main1.html"]];
909     [webView loadRequest:request];
910
911     TestWebKitAPI::Util::run(&done);
912     done = false;
913
914     auto pidAfterFirstLoad = [webView _webProcessIdentifier];
915
916     EXPECT_FALSE(serverRedirected);
917     EXPECT_EQ(1, numberOfDecidePolicyCalls);
918     EXPECT_EQ(1u, seenPIDs.size());
919     EXPECT_TRUE(*seenPIDs.begin() == pidAfterFirstLoad);
920
921     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main2.html"]];
922     [webView loadRequest:request];
923
924     TestWebKitAPI::Util::run(&serverRedirected);
925     serverRedirected = false;
926
927     seenPIDs.add([webView _webProcessIdentifier]);
928
929     TestWebKitAPI::Util::run(&done);
930     done = false;
931
932     seenPIDs.add([webView _webProcessIdentifier]);
933
934     EXPECT_FALSE(serverRedirected);
935     EXPECT_EQ(3, numberOfDecidePolicyCalls);
936     EXPECT_EQ(2u, seenPIDs.size());
937 }
938
939 static const char* sessionStorageTestBytes = R"PSONRESOURCE(
940 <head>
941 <script>
942
943 function log(msg)
944 {
945     window.webkit.messageHandlers.pson.postMessage(msg);
946 }
947
948 window.onload = function(evt) {
949     log(sessionStorage.psonKey);
950     sessionStorage.psonKey = "I exist!";
951 }
952
953 </script>
954 </head>
955 )PSONRESOURCE";
956
957 TEST(ProcessSwap, SessionStorage)
958 {
959     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
960     [processPoolConfiguration setProcessSwapsOnNavigation:YES];
961     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
962
963     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
964     [webViewConfiguration setProcessPool:processPool.get()];
965     auto handler = adoptNS([[PSONScheme alloc] init]);
966     [handler addMappingFromURLString:@"pson://www.webkit.org/main.html" toData:sessionStorageTestBytes];
967     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
968
969     auto messageHandler = adoptNS([[PSONMessageHandler alloc] init]);
970     [[webViewConfiguration userContentController] addScriptMessageHandler:messageHandler.get() name:@"pson"];
971
972     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
973     auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
974     [webView setNavigationDelegate:delegate.get()];
975
976     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
977     [webView loadRequest:request];
978
979     TestWebKitAPI::Util::run(&receivedMessage);
980     receivedMessage = false;
981     TestWebKitAPI::Util::run(&done);
982     done = false;
983
984     auto pid1 = [webView _webProcessIdentifier];
985
986     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.apple.com/main.html"]];
987     [webView loadRequest:request];
988
989     TestWebKitAPI::Util::run(&done);
990     done = false;
991
992     auto pid2 = [webView _webProcessIdentifier];
993
994     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
995     [webView loadRequest:request];
996
997     TestWebKitAPI::Util::run(&receivedMessage);
998     receivedMessage = false;
999     TestWebKitAPI::Util::run(&done);
1000     done = false;
1001
1002     auto pid3 = [webView _webProcessIdentifier];
1003
1004     // Verify the web pages are in different processes
1005     EXPECT_NE(pid1, pid2);
1006     EXPECT_NE(pid1, pid3);
1007     EXPECT_NE(pid2, pid3);
1008
1009     // Verify the sessionStorage values were as expected
1010     EXPECT_EQ([receivedMessages count], 2u);
1011     EXPECT_TRUE([receivedMessages.get()[0] isEqualToString:@""]);
1012     EXPECT_TRUE([receivedMessages.get()[1] isEqualToString:@"I exist!"]);
1013 }
1014
1015 static const char* mainFramesOnlyMainFrame = R"PSONRESOURCE(
1016 <script>
1017 function loaded() {
1018     setTimeout('window.frames[0].location.href = "pson://www.apple.com/main.html"', 0);
1019 }
1020 </script>
1021 <body onload="loaded();">
1022 Some text
1023 <iframe src="pson://www.webkit.org/iframe.html"></iframe>
1024 </body>
1025 )PSONRESOURCE";
1026
1027 static const char* mainFramesOnlySubframe = R"PSONRESOURCE(
1028 Some content
1029 )PSONRESOURCE";
1030
1031
1032 static const char* mainFramesOnlySubframe2 = R"PSONRESOURCE(
1033 <script>
1034     window.webkit.messageHandlers.pson.postMessage("Done");
1035 </script>
1036 )PSONRESOURCE";
1037
1038 TEST(ProcessSwap, MainFramesOnly)
1039 {
1040     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
1041     [processPoolConfiguration setProcessSwapsOnNavigation:YES];
1042     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
1043
1044     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
1045     [webViewConfiguration setProcessPool:processPool.get()];
1046     auto handler = adoptNS([[PSONScheme alloc] init]);
1047     [handler addMappingFromURLString:@"pson://www.webkit.org/main.html" toData:mainFramesOnlyMainFrame];
1048     [handler addMappingFromURLString:@"pson://www.webkit.org/iframe" toData:mainFramesOnlySubframe];
1049     [handler addMappingFromURLString:@"pson://www.apple.com/main.html" toData:mainFramesOnlySubframe2];
1050     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
1051
1052     auto messageHandler = adoptNS([[PSONMessageHandler alloc] init]);
1053     [[webViewConfiguration userContentController] addScriptMessageHandler:messageHandler.get() name:@"pson"];
1054
1055     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
1056     auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
1057     [webView setNavigationDelegate:delegate.get()];
1058
1059     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
1060     [webView loadRequest:request];
1061
1062     TestWebKitAPI::Util::run(&receivedMessage);
1063     receivedMessage = false;
1064
1065     EXPECT_EQ(1u, seenPIDs.size());
1066 }
1067
1068 TEST(ProcessSwap, OnePreviousProcessRemains)
1069 {
1070     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
1071     [processPoolConfiguration setProcessSwapsOnNavigation:YES];
1072     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
1073
1074     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
1075     [webViewConfiguration setProcessPool:processPool.get()];
1076     auto handler = adoptNS([[PSONScheme alloc] init]);
1077     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
1078
1079     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
1080     auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
1081     [webView setNavigationDelegate:delegate.get()];
1082
1083     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
1084     [webView loadRequest:request];
1085
1086     TestWebKitAPI::Util::run(&done);
1087     done = false;
1088
1089     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.apple.com/main.html"]];
1090     [webView loadRequest:request];
1091
1092     TestWebKitAPI::Util::run(&done);
1093     done = false;
1094
1095     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.google.com/main.html"]];
1096     [webView loadRequest:request];
1097
1098     TestWebKitAPI::Util::run(&done);
1099     done = false;
1100
1101     // Navigations to 3 different domains, we expect to have seen 3 different PIDs
1102     EXPECT_EQ(3u, seenPIDs.size());
1103
1104     // But only 2 of those processes should still be alive
1105     EXPECT_EQ(2u, [processPool _webProcessCountIgnoringPrewarmed]);
1106 }
1107
1108 static const char* pageCache1Bytes = R"PSONRESOURCE(
1109 <script>
1110 window.addEventListener('pageshow', function(event) {
1111     if (event.persisted)
1112         window.webkit.messageHandlers.pson.postMessage("Was persisted");
1113 });
1114 </script>
1115 )PSONRESOURCE";
1116
1117 TEST(ProcessSwap, PageCache1)
1118 {
1119     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
1120     [processPoolConfiguration setProcessSwapsOnNavigation:YES];
1121     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
1122
1123     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
1124     [webViewConfiguration setProcessPool:processPool.get()];
1125     auto handler = adoptNS([[PSONScheme alloc] init]);
1126     [handler addMappingFromURLString:@"pson://www.webkit.org/main.html" toData:pageCache1Bytes];
1127     [handler addMappingFromURLString:@"pson://www.apple.com/main.html" toData:pageCache1Bytes];
1128     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
1129
1130     auto messageHandler = adoptNS([[PSONMessageHandler alloc] init]);
1131     [[webViewConfiguration userContentController] addScriptMessageHandler:messageHandler.get() name:@"pson"];
1132
1133     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
1134     auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
1135     [webView setNavigationDelegate:delegate.get()];
1136
1137     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
1138
1139     [webView loadRequest:request];
1140     TestWebKitAPI::Util::run(&done);
1141     done = false;
1142
1143     auto pidAfterLoad1 = [webView _webProcessIdentifier];
1144
1145     EXPECT_EQ(1u, [processPool _webProcessCountIgnoringPrewarmed]);
1146
1147     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.apple.com/main.html"]];
1148
1149     [webView loadRequest:request];
1150     TestWebKitAPI::Util::run(&done);
1151     done = false;
1152
1153     auto pidAfterLoad2 = [webView _webProcessIdentifier];
1154
1155     EXPECT_EQ(2u, [processPool _webProcessCountIgnoringPrewarmed]);
1156     EXPECT_NE(pidAfterLoad1, pidAfterLoad2);
1157
1158     [webView goBack];
1159     TestWebKitAPI::Util::run(&receivedMessage);
1160     receivedMessage = false;
1161     TestWebKitAPI::Util::run(&done);
1162     done = false;
1163
1164     auto pidAfterLoad3 = [webView _webProcessIdentifier];
1165
1166     EXPECT_EQ(2u, [processPool _webProcessCountIgnoringPrewarmed]);
1167     EXPECT_EQ(pidAfterLoad1, pidAfterLoad3);
1168     EXPECT_EQ(1u, [receivedMessages count]);
1169     EXPECT_TRUE([receivedMessages.get()[0] isEqualToString:@"Was persisted" ]);
1170     EXPECT_EQ(2u, seenPIDs.size());
1171
1172     [webView goForward];
1173     TestWebKitAPI::Util::run(&receivedMessage);
1174     receivedMessage = false;
1175     TestWebKitAPI::Util::run(&done);
1176     done = false;
1177
1178     auto pidAfterLoad4 = [webView _webProcessIdentifier];
1179
1180     EXPECT_EQ(2u, [processPool _webProcessCountIgnoringPrewarmed]);
1181     EXPECT_EQ(pidAfterLoad2, pidAfterLoad4);
1182     EXPECT_EQ(2u, [receivedMessages count]);
1183     EXPECT_TRUE([receivedMessages.get()[1] isEqualToString:@"Was persisted" ]);
1184     EXPECT_EQ(2u, seenPIDs.size());
1185 }
1186
1187 TEST(ProcessSwap, NumberOfPrewarmedProcesses)
1188 {
1189     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
1190     [processPoolConfiguration setProcessSwapsOnNavigation:YES];
1191     [processPoolConfiguration setPrewarmsProcessesAutomatically:YES];
1192     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
1193
1194     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
1195     [webViewConfiguration setProcessPool:processPool.get()];
1196     auto handler = adoptNS([[PSONScheme alloc] init]);
1197     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
1198
1199     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
1200     auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
1201     [webView setNavigationDelegate:delegate.get()];
1202
1203     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
1204     [webView loadRequest:request];
1205     TestWebKitAPI::Util::run(&done);
1206     done = false;
1207
1208     EXPECT_EQ(2u, [processPool _webProcessCount]);
1209     EXPECT_EQ(1u, [processPool _webProcessCountIgnoringPrewarmed]);
1210     EXPECT_TRUE([processPool _hasPrewarmedWebProcess]);
1211
1212     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.google.com/main.html"]];
1213     [webView loadRequest:request];
1214     TestWebKitAPI::Util::run(&done);
1215     done = false;
1216
1217     EXPECT_EQ(3u, [processPool _webProcessCount]);
1218     EXPECT_EQ(2u, [processPool _webProcessCountIgnoringPrewarmed]);
1219     EXPECT_TRUE([processPool _hasPrewarmedWebProcess]);
1220 }
1221
1222 static const char* visibilityBytes = R"PSONRESOURCE(
1223 <script>
1224 window.addEventListener('pageshow', function(event) {
1225     var msg = window.location.href + " - pageshow ";
1226     msg += event.persisted ? "persisted" : "NOT persisted";
1227     window.webkit.messageHandlers.pson.postMessage(msg);
1228 });
1229
1230 window.addEventListener('pagehide', function(event) {
1231     var msg = window.location.href + " - pagehide ";
1232     msg += event.persisted ? "persisted" : "NOT persisted";
1233     window.webkit.messageHandlers.pson.postMessage(msg);
1234 });
1235 </script>
1236 )PSONRESOURCE";
1237
1238 TEST(ProcessSwap, PageShowHide)
1239 {
1240     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
1241     [processPoolConfiguration setProcessSwapsOnNavigation:YES];
1242     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
1243
1244     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
1245     [webViewConfiguration setProcessPool:processPool.get()];
1246     auto handler = adoptNS([[PSONScheme alloc] init]);
1247     [handler addMappingFromURLString:@"pson://www.webkit.org/main.html" toData:visibilityBytes];
1248     [handler addMappingFromURLString:@"pson://www.apple.com/main.html" toData:visibilityBytes];
1249     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
1250
1251     auto messageHandler = adoptNS([[PSONMessageHandler alloc] init]);
1252     [[webViewConfiguration userContentController] addScriptMessageHandler:messageHandler.get() name:@"pson"];
1253
1254     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
1255     auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
1256     [webView setNavigationDelegate:delegate.get()];
1257
1258     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
1259
1260     [webView loadRequest:request];
1261     TestWebKitAPI::Util::run(&receivedMessage);
1262     receivedMessage = false;
1263     TestWebKitAPI::Util::run(&done);
1264     done = false;
1265
1266     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.apple.com/main.html"]];
1267
1268     [webView loadRequest:request];
1269     TestWebKitAPI::Util::run(&receivedMessage);
1270     receivedMessage = false;
1271     TestWebKitAPI::Util::run(&done);
1272     done = false;
1273
1274     [webView goBack];
1275     TestWebKitAPI::Util::run(&receivedMessage);
1276     receivedMessage = false;
1277     TestWebKitAPI::Util::run(&done);
1278     done = false;
1279
1280     [webView goForward];
1281     TestWebKitAPI::Util::run(&receivedMessage);
1282     receivedMessage = false;
1283     TestWebKitAPI::Util::run(&done);
1284     done = false;
1285
1286     EXPECT_EQ(7u, [receivedMessages count]);
1287     EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pageshow NOT persisted", receivedMessages.get()[0]);
1288     EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pagehide persisted", receivedMessages.get()[1]);
1289     EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - pageshow NOT persisted", receivedMessages.get()[2]);
1290     EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - pagehide persisted", receivedMessages.get()[3]);
1291     EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pageshow persisted", receivedMessages.get()[4]);
1292     EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pagehide persisted", receivedMessages.get()[5]);
1293     EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - pageshow persisted", receivedMessages.get()[6]);
1294 }
1295
1296 // Disabling the page cache explicitly is (for some reason) not available on iOS.
1297 #if !TARGET_OS_IPHONE
1298 static const char* loadUnloadBytes = R"PSONRESOURCE(
1299 <script>
1300 window.addEventListener('unload', function(event) {
1301     var msg = window.location.href + " - unload";
1302     window.webkit.messageHandlers.pson.postMessage(msg);
1303 });
1304
1305 window.addEventListener('load', function(event) {
1306     var msg = window.location.href + " - load";
1307     window.webkit.messageHandlers.pson.postMessage(msg);
1308 });
1309 </script>
1310 )PSONRESOURCE";
1311
1312 TEST(ProcessSwap, LoadUnload)
1313 {
1314     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
1315     [processPoolConfiguration setProcessSwapsOnNavigation:YES];
1316     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
1317
1318     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
1319     [webViewConfiguration setProcessPool:processPool.get()];
1320     auto handler = adoptNS([[PSONScheme alloc] init]);
1321     [handler addMappingFromURLString:@"pson://www.webkit.org/main.html" toData:loadUnloadBytes];
1322     [handler addMappingFromURLString:@"pson://www.apple.com/main.html" toData:loadUnloadBytes];
1323     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
1324
1325     auto messageHandler = adoptNS([[PSONMessageHandler alloc] init]);
1326     [[webViewConfiguration userContentController] addScriptMessageHandler:messageHandler.get() name:@"pson"];
1327     [[webViewConfiguration preferences] _setUsesPageCache:NO];
1328
1329     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
1330     auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
1331     [webView setNavigationDelegate:delegate.get()];
1332
1333     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
1334
1335     [webView loadRequest:request];
1336     TestWebKitAPI::Util::run(&receivedMessage);
1337     receivedMessage = false;
1338     TestWebKitAPI::Util::run(&done);
1339     done = false;
1340
1341     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.apple.com/main.html"]];
1342
1343     [webView loadRequest:request];
1344     TestWebKitAPI::Util::run(&receivedMessage);
1345     receivedMessage = false;
1346     TestWebKitAPI::Util::run(&done);
1347     done = false;
1348
1349     [webView goBack];
1350     TestWebKitAPI::Util::run(&receivedMessage);
1351     receivedMessage = false;
1352     TestWebKitAPI::Util::run(&done);
1353     done = false;
1354
1355     [webView goForward];
1356     TestWebKitAPI::Util::run(&receivedMessage);
1357     receivedMessage = false;
1358     TestWebKitAPI::Util::run(&done);
1359     done = false;
1360
1361     EXPECT_EQ(7u, [receivedMessages count]);
1362     EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - load", receivedMessages.get()[0]);
1363     EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - unload", receivedMessages.get()[1]);
1364     EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - load", receivedMessages.get()[2]);
1365     EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - unload", receivedMessages.get()[3]);
1366     EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - load", receivedMessages.get()[4]);
1367     EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - unload", receivedMessages.get()[5]);
1368     EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - load", receivedMessages.get()[6]);
1369 }
1370
1371 TEST(ProcessSwap, DisableForInspector)
1372 {
1373     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
1374     processPoolConfiguration.get().processSwapsOnNavigation = YES;
1375     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
1376
1377     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
1378     [webViewConfiguration setProcessPool:processPool.get()];
1379     webViewConfiguration.get().preferences._developerExtrasEnabled = YES;
1380
1381     auto handler = adoptNS([[PSONScheme alloc] init]);
1382     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
1383
1384     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
1385     auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
1386     [webView setNavigationDelegate:delegate.get()];
1387
1388     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main1.html"]];
1389     [webView loadRequest:request];
1390
1391     TestWebKitAPI::Util::run(&done);
1392     done = false;
1393
1394     auto pid1 = [webView _webProcessIdentifier];
1395
1396     // FIXME: use ObjC equivalent for WKInspectorRef when available.
1397     WKInspectorShow(WKPageGetInspector([webView _pageRefForTransitionToWKWebView]));
1398
1399     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.apple.com/main2.html"]];
1400     [webView loadRequest:request];
1401
1402     TestWebKitAPI::Util::run(&done);
1403     done = false;
1404
1405     auto pid2 = [webView _webProcessIdentifier];
1406
1407     WKInspectorClose(WKPageGetInspector([webView _pageRefForTransitionToWKWebView]));
1408
1409     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main2.html"]];
1410     [webView loadRequest:request];
1411
1412     TestWebKitAPI::Util::run(&done);
1413     done = false;
1414
1415     auto pid3 = [webView _webProcessIdentifier];
1416
1417     EXPECT_EQ(pid1, pid2);
1418     EXPECT_FALSE(pid2 == pid3);
1419     EXPECT_EQ(numberOfDecidePolicyCalls, 3);
1420 }
1421
1422 #endif // !TARGET_OS_IPHONE
1423
1424 static const char* sameOriginBlobNavigationTestBytes = R"PSONRESOURCE(
1425 <!DOCTYPE html>
1426 <html>
1427 <body>
1428 <p><a id="link">Click here</a></p>
1429 <script>
1430 const blob = new Blob(['<!DOCTYPE html><html><p>PASS</p></html>'], {type: 'text/html'});
1431 link.href = URL.createObjectURL(blob);
1432 </script>
1433 )PSONRESOURCE";
1434
1435 TEST(ProcessSwap, SameOriginBlobNavigation)
1436 {
1437     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
1438     processPoolConfiguration.get().processSwapsOnNavigation = YES;
1439     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
1440
1441     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
1442     [webViewConfiguration setProcessPool:processPool.get()];
1443     auto handler = adoptNS([[PSONScheme alloc] initWithBytes:sameOriginBlobNavigationTestBytes]);
1444     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
1445
1446     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
1447     auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
1448     [webView setNavigationDelegate:navigationDelegate.get()];
1449     auto uiDelegate = adoptNS([[PSONUIDelegate alloc] initWithNavigationDelegate:navigationDelegate.get()]);
1450     [webView setUIDelegate:uiDelegate.get()];
1451
1452     numberOfDecidePolicyCalls = 0;
1453     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]]];
1454
1455     TestWebKitAPI::Util::run(&done);
1456     done = false;
1457     auto pid1 = [webView _webProcessIdentifier];
1458     EXPECT_TRUE(!!pid1);
1459
1460     [webView _evaluateJavaScriptWithoutUserGesture:@"document.getElementById('link').click()" completionHandler: nil];
1461
1462     TestWebKitAPI::Util::run(&done);
1463     done = false;
1464     auto pid2 = [webView _webProcessIdentifier];
1465     EXPECT_TRUE(!!pid2);
1466     EXPECT_EQ(2, numberOfDecidePolicyCalls);
1467     EXPECT_EQ(pid1, pid2);
1468 }
1469
1470 TEST(ProcessSwap, CrossOriginBlobNavigation)
1471 {
1472     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
1473     processPoolConfiguration.get().processSwapsOnNavigation = YES;
1474     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
1475
1476     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
1477     [webViewConfiguration setProcessPool:processPool.get()];
1478     auto handler = adoptNS([[PSONScheme alloc] initWithBytes:sameOriginBlobNavigationTestBytes]);
1479     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
1480
1481     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
1482     auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
1483     [webView setNavigationDelegate:navigationDelegate.get()];
1484     auto uiDelegate = adoptNS([[PSONUIDelegate alloc] initWithNavigationDelegate:navigationDelegate.get()]);
1485     [webView setUIDelegate:uiDelegate.get()];
1486
1487     numberOfDecidePolicyCalls = 0;
1488     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]]];
1489     TestWebKitAPI::Util::run(&done);
1490     done = false;
1491     auto pid1 = [webView _webProcessIdentifier];
1492     EXPECT_TRUE(!!pid1);
1493
1494     bool finishedRunningScript = false;
1495     String blobURL;
1496     [webView _evaluateJavaScriptWithoutUserGesture:@"document.getElementById('link').href" completionHandler: [&] (id result, NSError *error) {
1497         blobURL = String([NSString stringWithFormat:@"%@", result]);
1498         finishedRunningScript = true;
1499     }];
1500     TestWebKitAPI::Util::run(&finishedRunningScript);
1501
1502     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.apple.com/main.html"]]];
1503     TestWebKitAPI::Util::run(&done);
1504     done = false;
1505     auto pid2 = [webView _webProcessIdentifier];
1506     EXPECT_TRUE(!!pid2);
1507
1508     finishedRunningScript = false;
1509     String script = "document.getElementById('link').href = '" + blobURL + "'";
1510     [webView _evaluateJavaScriptWithoutUserGesture:(NSString *)script completionHandler: [&] (id result, NSError *error) {
1511         finishedRunningScript = true;
1512     }];
1513     TestWebKitAPI::Util::run(&finishedRunningScript);
1514
1515     // This navigation will fail.
1516     [webView _evaluateJavaScriptWithoutUserGesture:@"document.getElementById('link').click()" completionHandler: [&] (id result, NSError *error) {
1517         done = true;
1518     }];
1519     TestWebKitAPI::Util::run(&done);
1520     done = false;
1521     auto pid3 = [webView _webProcessIdentifier];
1522     EXPECT_TRUE(!!pid3);
1523
1524     EXPECT_EQ(2, numberOfDecidePolicyCalls);
1525     EXPECT_NE(pid1, pid2);
1526     EXPECT_EQ(pid2, pid3);
1527 }
1528
1529 TEST(ProcessSwap, NavigateToAboutBlank)
1530 {
1531     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
1532     processPoolConfiguration.get().processSwapsOnNavigation = YES;
1533     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
1534
1535     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
1536     [webViewConfiguration setProcessPool:processPool.get()];
1537     auto handler = adoptNS([[PSONScheme alloc] initWithBytes:sameOriginBlobNavigationTestBytes]);
1538     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
1539
1540     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
1541     auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
1542     [webView setNavigationDelegate:navigationDelegate.get()];
1543     auto uiDelegate = adoptNS([[PSONUIDelegate alloc] initWithNavigationDelegate:navigationDelegate.get()]);
1544     [webView setUIDelegate:uiDelegate.get()];
1545
1546     numberOfDecidePolicyCalls = 0;
1547     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]]];
1548     TestWebKitAPI::Util::run(&done);
1549     done = false;
1550     auto pid1 = [webView _webProcessIdentifier];
1551     EXPECT_TRUE(!!pid1);
1552
1553     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"about:blank"]]];
1554     TestWebKitAPI::Util::run(&done);
1555     done = false;
1556     auto pid2 = [webView _webProcessIdentifier];
1557     EXPECT_TRUE(!!pid2);
1558
1559     EXPECT_EQ(2, numberOfDecidePolicyCalls);
1560     EXPECT_EQ(pid1, pid2);
1561 }
1562
1563 TEST(ProcessSwap, NavigateToDataURL)
1564 {
1565     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
1566     processPoolConfiguration.get().processSwapsOnNavigation = YES;
1567     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
1568
1569     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
1570     [webViewConfiguration setProcessPool:processPool.get()];
1571     auto handler = adoptNS([[PSONScheme alloc] initWithBytes:sameOriginBlobNavigationTestBytes]);
1572     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
1573
1574     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
1575     auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
1576     [webView setNavigationDelegate:navigationDelegate.get()];
1577     auto uiDelegate = adoptNS([[PSONUIDelegate alloc] initWithNavigationDelegate:navigationDelegate.get()]);
1578     [webView setUIDelegate:uiDelegate.get()];
1579
1580     numberOfDecidePolicyCalls = 0;
1581     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]]];
1582     TestWebKitAPI::Util::run(&done);
1583     done = false;
1584     auto pid1 = [webView _webProcessIdentifier];
1585     EXPECT_TRUE(!!pid1);
1586
1587     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"data:text/plain,PASS"]]];
1588     TestWebKitAPI::Util::run(&done);
1589     done = false;
1590     auto pid2 = [webView _webProcessIdentifier];
1591     EXPECT_TRUE(!!pid2);
1592
1593     EXPECT_EQ(2, numberOfDecidePolicyCalls);
1594     EXPECT_EQ(pid1, pid2);
1595 }
1596
1597 TEST(ProcessSwap, ProcessReuse)
1598 {
1599     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
1600     [processPoolConfiguration setProcessSwapsOnNavigation:YES];
1601     [processPoolConfiguration setAlwaysKeepAndReuseSwappedProcesses:YES];
1602     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
1603
1604     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
1605     [webViewConfiguration setProcessPool:processPool.get()];
1606     auto handler = adoptNS([[PSONScheme alloc] init]);
1607     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
1608
1609     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
1610     auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
1611     [webView setNavigationDelegate:delegate.get()];
1612
1613     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main1.html"]];
1614     [webView loadRequest:request];
1615
1616     TestWebKitAPI::Util::run(&done);
1617     done = false;
1618
1619     auto pid1 = [webView _webProcessIdentifier];
1620
1621     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.apple.com/main.html"]];
1622     [webView loadRequest:request];
1623
1624     TestWebKitAPI::Util::run(&done);
1625     done = false;
1626
1627     auto pid2 = [webView _webProcessIdentifier];
1628
1629     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main2.html"]];
1630     [webView loadRequest:request];
1631
1632     TestWebKitAPI::Util::run(&done);
1633     done = false;
1634
1635     auto pid3 = [webView _webProcessIdentifier];
1636
1637     // Two process swaps have occurred, but we should only have ever seen 2 pids.
1638     EXPECT_EQ(2u, seenPIDs.size());
1639     EXPECT_NE(pid1, pid2);
1640     EXPECT_NE(pid2, pid3);
1641     EXPECT_EQ(pid1, pid3);
1642 }
1643
1644 TEST(ProcessSwap, ProcessReuseeTLDPlus2)
1645 {
1646     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
1647     [processPoolConfiguration setProcessSwapsOnNavigation:YES];
1648     [processPoolConfiguration setAlwaysKeepAndReuseSwappedProcesses:YES];
1649     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
1650
1651     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
1652     [webViewConfiguration setProcessPool:processPool.get()];
1653     auto handler = adoptNS([[PSONScheme alloc] init]);
1654     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
1655
1656     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
1657     auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
1658     [webView setNavigationDelegate:delegate.get()];
1659
1660     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www1.webkit.org/main1.html"]];
1661     [webView loadRequest:request];
1662
1663     TestWebKitAPI::Util::run(&done);
1664     done = false;
1665
1666     auto pid1 = [webView _webProcessIdentifier];
1667
1668     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.apple.com/main.html"]];
1669     [webView loadRequest:request];
1670
1671     TestWebKitAPI::Util::run(&done);
1672     done = false;
1673
1674     auto pid2 = [webView _webProcessIdentifier];
1675
1676     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www2.webkit.org/main2.html"]];
1677     [webView loadRequest:request];
1678
1679     TestWebKitAPI::Util::run(&done);
1680     done = false;
1681
1682     auto pid3 = [webView _webProcessIdentifier];
1683
1684     // Two process swaps have occurred, but we should only have ever seen 2 pids.
1685     EXPECT_EQ(2u, seenPIDs.size());
1686     EXPECT_NE(pid1, pid2);
1687     EXPECT_NE(pid2, pid3);
1688     EXPECT_EQ(pid1, pid3);
1689 }
1690
1691 static const char* navigateToInvalidURLTestBytes = R"PSONRESOURCE(
1692 <!DOCTYPE html>
1693 <html>
1694 <body onload="setTimeout(() => alert('DONE'), 0); location.href = 'http://A=a%B=b'">
1695 )PSONRESOURCE";
1696
1697 TEST(ProcessSwap, NavigateToInvalidURL)
1698 {
1699     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
1700     processPoolConfiguration.get().processSwapsOnNavigation = YES;
1701     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
1702
1703     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
1704     [webViewConfiguration setProcessPool:processPool.get()];
1705     auto handler = adoptNS([[PSONScheme alloc] initWithBytes:navigateToInvalidURLTestBytes]);
1706     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
1707
1708     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
1709     auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
1710     [webView setNavigationDelegate:navigationDelegate.get()];
1711     auto uiDelegate = adoptNS([[PSONUIDelegate alloc] initWithNavigationDelegate:navigationDelegate.get()]);
1712     [webView setUIDelegate:uiDelegate.get()];
1713
1714     numberOfDecidePolicyCalls = 0;
1715     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]]];
1716     TestWebKitAPI::Util::run(&done);
1717     done = false;
1718     auto pid1 = [webView _webProcessIdentifier];
1719     EXPECT_TRUE(!!pid1);
1720
1721     TestWebKitAPI::Util::run(&didReceiveAlert);
1722     didReceiveAlert = false;
1723     auto pid2 = [webView _webProcessIdentifier];
1724     EXPECT_TRUE(!!pid2);
1725
1726     EXPECT_EQ(2, numberOfDecidePolicyCalls);
1727     EXPECT_EQ(pid1, pid2);
1728 }
1729
1730 static const char* navigateToDataURLThenBackBytes = R"PSONRESOURCE(
1731 <script>
1732 onpageshow = function(event) {
1733     // Location changes need to happen outside the onload handler to generate history entries.
1734     setTimeout(function() {
1735       window.location.href = "data:text/html,<body onload='history.back()'></body>";
1736     }, 0);
1737 }
1738
1739 </script>
1740 )PSONRESOURCE";
1741
1742 TEST(ProcessSwap, NavigateToDataURLThenBack)
1743 {
1744     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
1745     processPoolConfiguration.get().processSwapsOnNavigation = YES;
1746     processPoolConfiguration.get().pageCacheEnabled = NO;
1747     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
1748
1749     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
1750     [webViewConfiguration setProcessPool:processPool.get()];
1751     auto handler = adoptNS([[PSONScheme alloc] initWithBytes:navigateToDataURLThenBackBytes]);
1752     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
1753
1754     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
1755     auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
1756     [webView setNavigationDelegate:navigationDelegate.get()];
1757
1758     numberOfDecidePolicyCalls = 0;
1759     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]]];
1760     TestWebKitAPI::Util::run(&done);
1761     done = false;
1762     auto pid1 = [webView _webProcessIdentifier];
1763
1764     TestWebKitAPI::Util::run(&done);
1765     done = false;
1766     auto pid2 = [webView _webProcessIdentifier];
1767
1768     TestWebKitAPI::Util::run(&done);
1769     done = false;
1770     auto pid3 = [webView _webProcessIdentifier];
1771
1772     EXPECT_EQ(3, numberOfDecidePolicyCalls);
1773     EXPECT_EQ(1u, seenPIDs.size());
1774     EXPECT_EQ(pid1, pid2);
1775     EXPECT_EQ(pid2, pid3);
1776 }
1777
1778 TEST(ProcessSwap, APIControlledProcessSwapping)
1779 {
1780     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
1781     auto handler = adoptNS([[PSONScheme alloc] initWithBytes:"Hello World!"]);
1782     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
1783
1784     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
1785     auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
1786     [webView setNavigationDelegate:navigationDelegate.get()];
1787
1788     numberOfDecidePolicyCalls = 0;
1789     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/1"]]];
1790     TestWebKitAPI::Util::run(&done);
1791     done = false;
1792     auto pid1 = [webView _webProcessIdentifier];
1793
1794     // Navigating from the above URL to this URL normally should not process swap.
1795     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/2"]]];
1796     TestWebKitAPI::Util::run(&done);
1797     done = false;
1798     auto pid2 = [webView _webProcessIdentifier];
1799
1800     EXPECT_EQ(1u, seenPIDs.size());
1801     EXPECT_EQ(pid1, pid2);
1802
1803     // Navigating from the above URL to this URL normally should not process swap,
1804     // but we'll explicitly ask for a swap.
1805     navigationDelegate->navigationActionPolicyToUse = _WKNavigationActionPolicyAllowInNewProcess;
1806     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webit.org/3"]]];
1807     TestWebKitAPI::Util::run(&done);
1808     done = false;
1809     auto pid3 = [webView _webProcessIdentifier];
1810
1811     EXPECT_EQ(3, numberOfDecidePolicyCalls);
1812     EXPECT_EQ(2u, seenPIDs.size());
1813     EXPECT_NE(pid1, pid3);
1814 }
1815
1816 enum class ExpectSwap { No, Yes };
1817 static void runProcessSwapDueToRelatedWebViewTest(NSURL* relatedViewURL, NSURL* targetURL, ExpectSwap expectSwap)
1818 {
1819     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
1820     processPoolConfiguration.get().processSwapsOnNavigation = YES;
1821     processPoolConfiguration.get().prewarmsProcessesAutomatically = YES;
1822     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
1823
1824     auto webView1Configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
1825     [webView1Configuration setProcessPool:processPool.get()];
1826     auto handler = adoptNS([[PSONScheme alloc] init]);
1827     [webView1Configuration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
1828
1829     auto webView1 = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webView1Configuration.get()]);
1830     auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
1831     [webView1 setNavigationDelegate:delegate.get()];
1832
1833     numberOfDecidePolicyCalls = 0;
1834     NSURLRequest *request = [NSURLRequest requestWithURL:relatedViewURL];
1835     [webView1 loadRequest:request];
1836
1837     TestWebKitAPI::Util::run(&done);
1838     done = false;
1839
1840     auto pid1 = [webView1 _webProcessIdentifier];
1841
1842     auto webView2Configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
1843     [webView2Configuration setProcessPool:processPool.get()];
1844     [webView2Configuration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
1845     webView2Configuration.get()._relatedWebView = webView1.get(); // webView2 will be related to webView1 and webView1's URL will be used for process swap decision.
1846     auto webView2 = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webView2Configuration.get()]);
1847     [webView2 setNavigationDelegate:delegate.get()];
1848
1849     request = [NSURLRequest requestWithURL:targetURL];
1850     [webView2 loadRequest:request];
1851
1852     TestWebKitAPI::Util::run(&done);
1853     done = false;
1854
1855     auto pid2 = [webView2 _webProcessIdentifier];
1856
1857     if (expectSwap == ExpectSwap::No)
1858         EXPECT_TRUE(pid1 == pid2);
1859     else
1860         EXPECT_FALSE(pid1 == pid2);
1861
1862     EXPECT_EQ(2, numberOfDecidePolicyCalls);
1863 }
1864
1865 TEST(ProcessSwap, ProcessSwapDueToRelatedView)
1866 {
1867     runProcessSwapDueToRelatedWebViewTest([NSURL URLWithString:@"pson://www.webkit.org/main1.html"], [NSURL URLWithString:@"pson://www.apple.com/main2.html"], ExpectSwap::Yes);
1868 }
1869
1870 TEST(ProcessSwap, NoProcessSwapDueToRelatedView)
1871 {
1872     runProcessSwapDueToRelatedWebViewTest([NSURL URLWithString:@"pson://www.webkit.org/main1.html"], [NSURL URLWithString:@"pson://www.webkit.org/main2.html"], ExpectSwap::No);
1873 }
1874
1875 TEST(ProcessSwap, TerminatedSuspendedPageProcess)
1876 {
1877     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
1878     processPoolConfiguration.get().processSwapsOnNavigation = YES;
1879     processPoolConfiguration.get().prewarmsProcessesAutomatically = YES;
1880     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
1881
1882     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
1883     [webViewConfiguration setProcessPool:processPool.get()];
1884     auto handler = adoptNS([[PSONScheme alloc] init]);
1885     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
1886
1887     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
1888     auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
1889     [webView setNavigationDelegate:delegate.get()];
1890
1891     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main1.html"]];
1892     [webView loadRequest:request];
1893
1894     TestWebKitAPI::Util::run(&done);
1895     done = false;
1896
1897     auto pid1 = [webView _webProcessIdentifier];
1898
1899     @autoreleasepool {
1900         auto webViewConfiguration2 = adoptNS([[WKWebViewConfiguration alloc] init]);
1901         [webViewConfiguration2 setProcessPool:processPool.get()];
1902         [webViewConfiguration2 _setRelatedWebView:webView.get()]; // Make sure it uses the same process.
1903         auto webView2 = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration2.get()]);
1904         [webView2 setNavigationDelegate:delegate.get()];
1905
1906         request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"about:blank"]];
1907         [webView2 loadRequest:request];
1908
1909         TestWebKitAPI::Util::run(&done);
1910         done = false;
1911
1912         auto pid2 = [webView2 _webProcessIdentifier];
1913         EXPECT_EQ(pid1, pid2);
1914
1915         request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.google.com/main2.html"]];
1916         [webView loadRequest:request];
1917
1918         TestWebKitAPI::Util::run(&done);
1919         done = false;
1920
1921         [webView2 _killWebContentProcessAndResetState];
1922         webView2 = nullptr;
1923         webViewConfiguration2 = nullptr;
1924     }
1925
1926     auto pid3 = [webView _webProcessIdentifier];
1927     EXPECT_NE(pid1, pid3);
1928
1929     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.apple.com/main2.html"]];
1930     [webView loadRequest:request];
1931
1932     TestWebKitAPI::Util::run(&done);
1933     done = false;
1934
1935     auto pid4 = [webView _webProcessIdentifier];
1936     EXPECT_NE(pid1, pid4);
1937     EXPECT_NE(pid3, pid4);
1938 }
1939
1940 #if PLATFORM(MAC)
1941
1942 TEST(ProcessSwap, GoBackToSuspendedPageWithMainFrameIDThatIsNotOne)
1943 {
1944     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
1945     [processPoolConfiguration setProcessSwapsOnNavigation:YES];
1946     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
1947
1948     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
1949     [webViewConfiguration setProcessPool:processPool.get()];
1950     auto handler = adoptNS([[PSONScheme alloc] init]);
1951     [handler addMappingFromURLString:@"pson://www.webkit.org/main1.html" toData:targetBlankSameSiteNoOpenerTestBytes];
1952     [handler addMappingFromURLString:@"pson://www.webkit.org/main2.html" toData:linkToAppleTestBytes];
1953     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
1954
1955     auto messageHandler = adoptNS([[PSONMessageHandler alloc] init]);
1956     [[webViewConfiguration userContentController] addScriptMessageHandler:messageHandler.get() name:@"pson"];
1957
1958     auto webView1 = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
1959     auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
1960     [webView1 setNavigationDelegate:navigationDelegate.get()];
1961     auto uiDelegate = adoptNS([[PSONUIDelegate alloc] initWithNavigationDelegate:navigationDelegate.get()]);
1962     [webView1 setUIDelegate:uiDelegate.get()];
1963
1964     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main1.html"]];
1965
1966     [webView1 loadRequest:request];
1967     TestWebKitAPI::Util::run(&done);
1968     done = false;
1969
1970     EXPECT_WK_STREQ(@"pson://www.webkit.org/main1.html", [[webView1 URL] absoluteString]);
1971     auto pid1 = [webView1 _webProcessIdentifier];
1972
1973     TestWebKitAPI::Util::run(&didCreateWebView);
1974     didCreateWebView = false;
1975
1976     TestWebKitAPI::Util::run(&done);
1977     done = false;
1978
1979     // New WKWebView has now navigated to webkit.org.
1980     EXPECT_WK_STREQ(@"pson://www.webkit.org/main2.html", [[createdWebView URL] absoluteString]);
1981     auto pid2 = [createdWebView _webProcessIdentifier];
1982     EXPECT_EQ(pid1, pid2);
1983
1984     // Click link in new WKWebView so that it navigates cross-site to apple.com.
1985     [createdWebView evaluateJavaScript:@"testLink.click()" completionHandler:nil];
1986     TestWebKitAPI::Util::run(&done);
1987     done = false;
1988
1989     // New WKWebView has now navigated to apple.com.
1990     EXPECT_WK_STREQ(@"pson://www.apple.com/main.html", [[createdWebView URL] absoluteString]);
1991     auto pid3 = [createdWebView _webProcessIdentifier];
1992     EXPECT_NE(pid1, pid3); // Should have process-swapped.
1993
1994     // Navigate back to the suspended page (should use the page cache).
1995     [createdWebView goBack];
1996     TestWebKitAPI::Util::run(&receivedMessage);
1997     receivedMessage = false;
1998
1999     EXPECT_WK_STREQ(@"pson://www.webkit.org/main2.html", [[createdWebView URL] absoluteString]);
2000     auto pid4 = [createdWebView _webProcessIdentifier];
2001     EXPECT_EQ(pid1, pid4); // Should have process-swapped to the original "suspended" process.
2002
2003     // Do a fragment navigation in the original WKWebView and make sure this does not crash.
2004     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main1.html#testLink"]];
2005     [webView1 loadRequest:request];
2006     TestWebKitAPI::Util::run(&done);
2007     done = false;
2008
2009     EXPECT_WK_STREQ(@"pson://www.webkit.org/main1.html#testLink", [[webView1 URL] absoluteString]);
2010     auto pid5 = [createdWebView _webProcessIdentifier];
2011     EXPECT_EQ(pid1, pid5);
2012 }
2013
2014 #endif // PLATFORM(MAC)
2015
2016 #endif // WK_API_ENABLED