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