Pass a hint from the extension to decidePolicyForSOAuthorizationLoadWithCurrentPolicy
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WebKitCocoa / TestSOAuthorization.mm
1 /*
2  * Copyright (C) 2019 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 #import "Test.h"
28
29 #if HAVE(APP_SSO)
30
31 #import "ClassMethodSwizzler.h"
32 #import "InstanceMethodSwizzler.h"
33 #import "PlatformUtilities.h"
34 #import "TCPServer.h"
35 #import "TestWKWebView.h"
36 #import <WebKit/WKNavigationActionPrivate.h>
37 #import <WebKit/WKNavigationDelegatePrivate.h>
38 #import <WebKit/WKNavigationPrivate.h>
39 #import <WebKit/WKWebViewPrivate.h>
40 #import <pal/cocoa/AppSSOSoftLink.h>
41 #import <pal/spi/cocoa/AuthKitSPI.h>
42 #import <wtf/BlockPtr.h>
43 #import <wtf/RetainPtr.h>
44 #import <wtf/StringPrintStream.h>
45 #import <wtf/URL.h>
46 #import <wtf/text/StringConcatenateNumbers.h>
47 #import <wtf/text/WTFString.h>
48
49 static bool navigationCompleted = false;
50 static bool authorizationPerformed = false;
51 static bool authorizationCancelled = false;
52 static bool uiShowed = false;
53 static bool newWindowCreated = false;
54 static bool haveHttpBody = false;
55 static bool navigationPolicyDecided = false;
56 static bool allMessagesReceived = false;
57 static String finalURL;
58 static SOAuthorization* gAuthorization;
59 static id<SOAuthorizationDelegate> gDelegate;
60 #if PLATFORM(MAC)
61 static BlockPtr<void(NSNotification *)> gNotificationCallback;
62 #endif
63 static RetainPtr<WKWebView> gNewWindow;
64
65 static const char* openerTemplate =
66 "<html>"
67 "<button onclick='clickMe()' style='width:400px;height:400px'>window.open</button>"
68 "<script>"
69 "function clickMe()"
70 "{"
71 "    window.addEventListener('message', receiveMessage, false);"
72 "    newWindow = window.open('%s');"
73 "    %s"
74 "    if (!newWindow)"
75 "        return;"
76 "    const pollTimer = window.setInterval(function() {"
77 "        if (newWindow.closed) {"
78 "            window.clearInterval(pollTimer);"
79 "            window.webkit.messageHandlers.testHandler.postMessage('WindowClosed.');"
80 "        }"
81 "    }, 200);"
82 "}"
83 "function receiveMessage(event)"
84 "{"
85 "    if (event.origin == 'http://www.example.com') {"
86 "        window.webkit.messageHandlers.testHandler.postMessage(event.data);"
87 "        %s"
88 "    }"
89 "}"
90 "</script>"
91 "</html>";
92
93 static const char* newWindowResponseTemplate =
94 "<html>"
95 "<script>"
96 "window.opener.postMessage('Hello.', '*');"
97 "%s"
98 "</script>"
99 "</html>";
100
101 static const char* parentTemplate =
102 "<html>"
103 "<meta name='referrer' content='origin' />"
104 "<iframe src='%s'></iframe>"
105 "<script>"
106 "function receiveMessage(event)"
107 "{"
108 "    window.webkit.messageHandlers.testHandler.postMessage(event.origin);"
109 "    window.webkit.messageHandlers.testHandler.postMessage(event.data);"
110 "}"
111 "window.addEventListener('message', receiveMessage, false);"
112 "</script>"
113 "</html>";
114
115 static const char* iframeTemplate =
116 "<html>"
117 "<script>"
118 "parent.postMessage('Hello.', '*');"
119 "%s"
120 "</script>"
121 "</html>";
122
123 static const char* samlResponse =
124 "<html>"
125 "<script>"
126 "window.webkit.messageHandlers.testHandler.postMessage('SAML');"
127 "</script>"
128 "</html>";
129
130 @interface TestSOAuthorizationBasicDelegate : NSObject <WKNavigationDelegate>
131 @end
132
133 @implementation TestSOAuthorizationBasicDelegate
134
135 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
136 {
137     EXPECT_FALSE(navigationCompleted);
138     navigationCompleted = true;
139     finalURL = navigation._request.URL.absoluteString;
140 }
141
142 @end
143
144 @interface TestSOAuthorizationDelegate : NSObject <WKNavigationDelegate, WKUIDelegate>
145 @property bool isDefaultPolicy;
146 @property bool shouldOpenExternalSchemes;
147 @property bool allowSOAuthorizationLoad;
148 @property bool isAsyncExecution;
149 - (instancetype)init;
150 @end
151
152 @implementation TestSOAuthorizationDelegate
153
154 - (instancetype)init
155 {
156     if (self = [super init]) {
157         self.isDefaultPolicy = true;
158         self.shouldOpenExternalSchemes = false;
159         self.allowSOAuthorizationLoad = true;
160         self.isAsyncExecution = false;
161     }
162     return self;
163 }
164
165 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
166 {
167     EXPECT_FALSE(navigationCompleted);
168     navigationCompleted = true;
169     finalURL = navigation._request.URL.absoluteString;
170 }
171
172 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
173 {
174     navigationPolicyDecided = true;
175     EXPECT_EQ(navigationAction._shouldOpenExternalSchemes, self.shouldOpenExternalSchemes);
176     if (self.isDefaultPolicy) {
177         decisionHandler(WKNavigationActionPolicyAllow);
178         return;
179     }
180     decisionHandler(_WKNavigationActionPolicyAllowWithoutTryingAppLink);
181 }
182
183 - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
184 {
185     EXPECT_FALSE(newWindowCreated);
186     newWindowCreated = true;
187     gNewWindow = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];
188     [gNewWindow setNavigationDelegate:self];
189     return gNewWindow.get();
190 }
191
192 - (void)_webView:(WKWebView *)webView decidePolicyForSOAuthorizationLoadWithCurrentPolicy:(_WKSOAuthorizationLoadPolicy)policy forExtension:(NSString *)extension completionHandler:(void (^)(_WKSOAuthorizationLoadPolicy policy))completionHandler
193 {
194     EXPECT_EQ(policy, _WKSOAuthorizationLoadPolicyAllow);
195     EXPECT_TRUE([extension isEqual:@"Test"]);
196     if (!self.isAsyncExecution) {
197         if (self.allowSOAuthorizationLoad)
198             completionHandler(policy);
199         else
200             completionHandler(_WKSOAuthorizationLoadPolicyIgnore);
201         return;
202     }
203
204     auto allowSOAuthorizationLoad = self.allowSOAuthorizationLoad;
205     dispatch_async(dispatch_get_main_queue(), ^() {
206         if (allowSOAuthorizationLoad)
207             completionHandler(_WKSOAuthorizationLoadPolicyAllow);
208         else
209             completionHandler(_WKSOAuthorizationLoadPolicyIgnore);
210     });
211 }
212
213 #if PLATFORM(IOS)
214 - (UIViewController *)_presentingViewControllerForWebView:(WKWebView *)webView
215 {
216     return nil;
217 }
218 #endif
219
220 @end
221
222 #if PLATFORM(MAC)
223 @interface TestSOAuthorizationViewController : NSViewController
224 #elif PLATFORM(IOS)
225 @interface TestSOAuthorizationViewController : UIViewController
226 #endif
227 @end
228
229 @implementation TestSOAuthorizationViewController
230
231 - (void)viewDidAppear
232 {
233     EXPECT_FALSE(uiShowed);
234     uiShowed = true;
235 }
236
237 - (void)viewDidDisappear
238 {
239     EXPECT_TRUE(uiShowed);
240     uiShowed = false;
241 }
242
243 @end
244
245 @interface TestSOAuthorizationScriptMessageHandler : NSObject <WKScriptMessageHandler>
246 @end
247
248 @implementation TestSOAuthorizationScriptMessageHandler {
249     RetainPtr<NSMutableArray> _messages;
250 }
251
252 - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
253 {
254     if (!_messages)
255         _messages = adoptNS([[NSMutableArray alloc] init]);
256     [_messages addObject:message.body];
257
258     if ([message.body isEqual:@""]) {
259         allMessagesReceived = true;
260         EXPECT_EQ([_messages count], 5u);
261         EXPECT_WK_STREQ("SOAuthorizationDidStart", [_messages objectAtIndex:1]);
262         EXPECT_WK_STREQ("SOAuthorizationDidCancel", [_messages objectAtIndex:3]);
263         EXPECT_WK_STREQ("", [_messages objectAtIndex:4]);
264     }
265
266     if ([message.body isEqual:@"Hello."]) {
267         allMessagesReceived = true;
268         EXPECT_EQ([_messages count], 4u);
269         EXPECT_WK_STREQ("SOAuthorizationDidStart", [_messages objectAtIndex:1]);
270         EXPECT_WK_STREQ("Hello.", [_messages objectAtIndex:3]);
271     }
272 }
273
274 @end
275
276 static bool overrideCanPerformAuthorizationWithURL(id, SEL, NSURL *url, NSInteger)
277 {
278     if (![url.lastPathComponent isEqual:@"simple.html"] && ![url.host isEqual:@"www.example.com"] && ![url.lastPathComponent isEqual:@"GetSessionCookie.html"])
279         return false;
280     return true;
281 }
282
283 static void overrideSetDelegate(id self, SEL, id<SOAuthorizationDelegate> delegate)
284 {
285     gAuthorization = self;
286     gDelegate = delegate;
287 }
288
289 static void overrideBeginAuthorizationWithURL(id, SEL, NSURL *url, NSDictionary *headers, NSData *body)
290 {
291     EXPECT_TRUE(headers != nil);
292     EXPECT_TRUE((body == nil) ^ haveHttpBody);
293     EXPECT_FALSE(authorizationPerformed);
294     authorizationPerformed = true;
295 }
296
297 static void overrideCancelAuthorization(id, SEL)
298 {
299     EXPECT_FALSE(authorizationCancelled);
300     authorizationCancelled = true;
301 }
302
303 using GetAuthorizationHintsCallback = void (^)(SOAuthorizationHints *authorizationHints, NSError *error);
304 static void overrideGetAuthorizationHintsWithURL(id, SEL, NSURL *url, NSInteger responseCode, GetAuthorizationHintsCallback completion)
305 {
306     EXPECT_EQ(responseCode, 0l);
307     auto soAuthorizationHintsCore = adoptNS([PAL::allocSOAuthorizationHintsCoreInstance() initWithLocalizedExtensionBundleDisplayName:@"Test"]);
308     auto soAuthorizationHints = adoptNS([PAL::allocSOAuthorizationHintsInstance() initWithAuthorizationHintsCore:soAuthorizationHintsCore.get()]);
309     completion(soAuthorizationHints.get(), nullptr);
310 }
311
312 #if PLATFORM(MAC)
313 using NotificationCallback = void (^)(NSNotification *note);
314 static id overrideAddObserverForName(id, SEL, NSNotificationName name, id, NSOperationQueue *, NotificationCallback block)
315 {
316     if ([name isEqual:NSWindowWillCloseNotification])
317         gNotificationCallback = makeBlockPtr(block);
318     return @YES;
319 }
320 #endif
321
322 static bool overrideIsURLFromAppleOwnedDomain(id, SEL, NSURL *)
323 {
324     return true;
325 }
326
327 static void resetState()
328 {
329     navigationCompleted = false;
330     authorizationPerformed = false;
331     authorizationCancelled = false;
332     uiShowed = false;
333     newWindowCreated = false;
334     haveHttpBody = false;
335     navigationPolicyDecided = false;
336     allMessagesReceived = false;
337     finalURL = emptyString();
338     gAuthorization = nullptr;
339     gDelegate = nullptr;
340 #if PLATFORM(MAC)
341     gNotificationCallback = nullptr;
342 #endif
343     gNewWindow = nullptr;
344 }
345
346 enum class OpenExternalSchemesPolicy : bool {
347     Allow,
348     Disallow
349 };
350
351 static void configureSOAuthorizationWebView(TestWKWebView *webView, TestSOAuthorizationDelegate *delegate, OpenExternalSchemesPolicy policy = OpenExternalSchemesPolicy::Disallow)
352 {
353     [webView setNavigationDelegate:delegate];
354     [webView setUIDelegate:delegate];
355     delegate.shouldOpenExternalSchemes = policy == OpenExternalSchemesPolicy::Allow;
356 }
357
358 static String generateHtml(const char* templateHtml, const String& substitute, const String& optionalSubstitute1 = emptyString(), const String& optionalSubstitute2 = emptyString())
359 {
360     StringPrintStream stream;
361     stream.printf(templateHtml, substitute.utf8().data(), optionalSubstitute1.utf8().data(), optionalSubstitute2.utf8().data());
362     return stream.toString();
363 }
364
365 // FIXME<rdar://problem/48909336>: Replace the below with AppSSO constants.
366 static void checkAuthorizationOptions(bool userActionInitiated, String initiatorOrigin, int initiatingAction)
367 {
368     EXPECT_TRUE(gAuthorization);
369     // FIXME: Remove the selector once the iOS bots has been updated to a recent SDK.
370     auto selector = NSSelectorFromString(@"authorizationOptions");
371     if ([gAuthorization respondsToSelector:selector]) {
372         EXPECT_EQ(((NSNumber *)[gAuthorization performSelector:selector][SOAuthorizationOptionUserActionInitiated]).boolValue, userActionInitiated);
373         EXPECT_WK_STREQ([gAuthorization performSelector:selector][@"initiatorOrigin"], initiatorOrigin);
374         EXPECT_EQ(((NSNumber *)[gAuthorization performSelector:selector][@"initiatingAction"]).intValue, initiatingAction);
375     }
376 }
377
378 namespace TestWebKitAPI {
379
380 TEST(SOAuthorizationRedirect, NoInterceptions)
381 {
382     resetState();
383     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
384
385     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
386     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
387     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
388
389     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
390     Util::run(&navigationCompleted);
391
392     EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL);
393 }
394
395 TEST(SOAuthorizationRedirect, InterceptionError)
396 {
397     resetState();
398     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
399     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
400
401     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
402
403     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
404     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
405     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
406
407     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
408     Util::run(&navigationCompleted);
409
410     EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL);
411 }
412
413 TEST(SOAuthorizationRedirect, InterceptionDoNotHandle)
414 {
415     resetState();
416     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
417     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
418     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
419     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
420
421     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
422
423     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
424     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
425     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
426
427     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
428     Util::run(&authorizationPerformed);
429     checkAuthorizationOptions(false, "", 0);
430
431     [gDelegate authorizationDidNotHandle:gAuthorization];
432     Util::run(&navigationCompleted);
433
434     EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL);
435 }
436
437 TEST(SOAuthorizationRedirect, InterceptionCancel)
438 {
439     resetState();
440     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
441     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
442     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
443     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
444
445     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
446
447     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
448     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
449     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
450
451     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
452     Util::run(&authorizationPerformed);
453     checkAuthorizationOptions(false, "", 0);
454
455     [gDelegate authorizationDidCancel:gAuthorization];
456     // FIXME: Find a delegate method that can detect load cancels.
457     Util::sleep(0.5);
458     EXPECT_WK_STREQ("", webView.get()._committedURL.absoluteString);
459 }
460
461 TEST(SOAuthorizationRedirect, InterceptionCompleteWithoutData)
462 {
463     resetState();
464     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
465     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
466     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
467     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
468
469     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
470
471     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
472     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
473     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
474
475     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
476     Util::run(&authorizationPerformed);
477     checkAuthorizationOptions(false, "", 0);
478
479     [gDelegate authorizationDidComplete:gAuthorization];
480     Util::run(&navigationCompleted);
481
482     EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL);
483 }
484
485 TEST(SOAuthorizationRedirect, InterceptionUnexpectedCompletion)
486 {
487     resetState();
488     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
489     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
490     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
491     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
492
493     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
494
495     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
496     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
497     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
498
499     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
500     Util::run(&authorizationPerformed);
501     checkAuthorizationOptions(false, "", 0);
502
503     [gDelegate authorization:gAuthorization didCompleteWithHTTPAuthorizationHeaders:adoptNS([[NSDictionary alloc] init]).get()];
504     Util::run(&navigationCompleted);
505
506     EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL);
507 }
508
509 // { Default delegate method, No App Links }
510 TEST(SOAuthorizationRedirect, InterceptionSucceed1)
511 {
512     resetState();
513     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
514     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
515     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
516     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
517
518     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
519
520     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
521     auto delegate = adoptNS([[TestSOAuthorizationBasicDelegate alloc] init]);
522     [webView setNavigationDelegate:delegate.get()];
523
524     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
525     Util::run(&authorizationPerformed);
526     checkAuthorizationOptions(false, "", 0);
527 #if PLATFORM(MAC)
528     EXPECT_TRUE(gAuthorization.enableEmbeddedAuthorizationViewController);
529 #elif PLATFORM(IOS)
530     EXPECT_FALSE(gAuthorization.enableEmbeddedAuthorizationViewController);
531 #endif
532
533     RetainPtr<NSURL> redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
534     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]);
535     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()];
536     Util::run(&navigationCompleted);
537 #if PLATFORM(IOS)
538     navigationCompleted = false;
539     Util::run(&navigationCompleted);
540 #endif
541     EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL);
542 }
543
544 // { Default delegate method, With App Links }
545 TEST(SOAuthorizationRedirect, InterceptionSucceed2)
546 {
547     resetState();
548     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
549     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
550     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
551     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
552
553     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
554     auto delegate = adoptNS([[TestSOAuthorizationBasicDelegate alloc] init]);
555     [webView setNavigationDelegate:delegate.get()];
556
557     // Force App Links with a request.URL that has a different host than the current one (empty host) and ShouldOpenExternalURLsPolicy::ShouldAllow.
558     auto testURL = URL(URL(), "https://www.example.com");
559 #if PLATFORM(MAC)
560     [webView _loadRequest:[NSURLRequest requestWithURL:testURL] shouldOpenExternalURLs:YES];
561 #elif PLATFORM(IOS)
562     // Here we force RedirectSOAuthorizationSession to go to the with user gestures route.
563     [webView evaluateJavaScript: [NSString stringWithFormat:@"location = '%@'", (id)testURL.string()] completionHandler:nil];
564 #endif
565     Util::run(&authorizationPerformed);
566 #if PLATFORM(MAC)
567     checkAuthorizationOptions(false, "", 0);
568 #elif PLATFORM(IOS)
569     checkAuthorizationOptions(true, "null", 0);
570 #endif
571
572     RetainPtr<NSURL> redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
573     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]);
574     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()];
575     Util::run(&navigationCompleted);
576     EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL);
577 }
578
579 // { Custom delegate method, With App Links }
580 TEST(SOAuthorizationRedirect, InterceptionSucceed3)
581 {
582     resetState();
583     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
584     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
585     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
586     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
587
588     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
589     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
590     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
591     EXPECT_TRUE(gAuthorization.enableEmbeddedAuthorizationViewController);
592
593     // Force App Links with a request.URL that has a different host than the current one (empty host) and ShouldOpenExternalURLsPolicy::ShouldAllow.
594     auto testURL = URL(URL(), "https://www.example.com");
595 #if PLATFORM(MAC)
596     [webView _loadRequest:[NSURLRequest requestWithURL:testURL] shouldOpenExternalURLs:YES];
597 #elif PLATFORM(IOS)
598     // Here we force RedirectSOAuthorizationSession to go to the with user gestures route.
599     [webView evaluateJavaScript: [NSString stringWithFormat:@"location = '%@'", (id)testURL.string()] completionHandler:nil];
600 #endif
601     Util::run(&authorizationPerformed);
602 #if PLATFORM(MAC)
603     checkAuthorizationOptions(false, "", 0);
604 #elif PLATFORM(IOS)
605     checkAuthorizationOptions(true, "null", 0);
606 #endif
607
608     RetainPtr<NSURL> redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
609     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]);
610     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()];
611     Util::run(&navigationCompleted);
612     EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL);
613 }
614
615 // { _WKNavigationActionPolicyAllowWithoutTryingAppLink, No App Links }
616 TEST(SOAuthorizationRedirect, InterceptionSucceed4)
617 {
618     resetState();
619     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
620     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
621     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
622     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
623
624     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
625
626     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
627     // A separate delegate that implements decidePolicyForNavigationAction.
628     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
629     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
630     [delegate setIsDefaultPolicy:false];
631
632     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
633     Util::run(&authorizationPerformed);
634     checkAuthorizationOptions(false, "", 0);
635
636     RetainPtr<NSURL> redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
637     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]);
638     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()];
639     Util::run(&navigationCompleted);
640 #if PLATFORM(IOS)
641     navigationCompleted = false;
642     Util::run(&navigationCompleted);
643 #endif
644     EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL);
645 }
646
647 TEST(SOAuthorizationRedirect, InterceptionSucceedWithOtherHttpStatusCode)
648 {
649     resetState();
650     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
651     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
652     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
653     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
654
655     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
656
657     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
658     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
659     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
660
661     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
662     Util::run(&authorizationPerformed);
663     checkAuthorizationOptions(false, "", 0);
664
665     RetainPtr<NSURL> redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
666     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:400 HTTPVersion:@"HTTP/1.1" headerFields:nil]);
667     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()];
668     Util::run(&navigationCompleted);
669     EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL);
670 }
671
672 TEST(SOAuthorizationRedirect, InterceptionSucceedWithCookie)
673 {
674     resetState();
675     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
676     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
677     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
678     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
679
680     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
681
682     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
683     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
684     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
685
686     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
687     Util::run(&authorizationPerformed);
688     checkAuthorizationOptions(false, "", 0);
689
690     RetainPtr<NSURL> redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
691     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Set-Cookie" : @"sessionid=38afes7a8;", @"Location" : [redirectURL absoluteString] }]);
692     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()];
693     Util::run(&navigationCompleted);
694 #if PLATFORM(IOS)
695     navigationCompleted = false;
696     Util::run(&navigationCompleted);
697 #endif
698     EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL);
699
700     navigationCompleted = false;
701     [webView evaluateJavaScript: @"document.cookie" completionHandler:^(NSString *result, NSError *) {
702         EXPECT_WK_STREQ("sessionid=38afes7a8", [result UTF8String]);
703         navigationCompleted = true;
704     }];
705     Util::run(&navigationCompleted);
706 }
707
708 TEST(SOAuthorizationRedirect, InterceptionSucceedWithCookies)
709 {
710     resetState();
711     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
712     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
713     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
714     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
715
716     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
717
718     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
719     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
720     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
721
722     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
723     Util::run(&authorizationPerformed);
724     checkAuthorizationOptions(false, "", 0);
725
726     RetainPtr<NSURL> redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
727     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Set-Cookie" : @"sessionid=38afes7a8, qwerty=219ffwef9w0f, id=a3fWa;", @"Location" : [redirectURL absoluteString] }]);
728     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()];
729     Util::run(&navigationCompleted);
730 #if PLATFORM(IOS)
731     navigationCompleted = false;
732     Util::run(&navigationCompleted);
733 #endif
734     EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL);
735
736     navigationCompleted = false;
737     [webView evaluateJavaScript: @"document.cookie" completionHandler:^(NSString *result, NSError *) {
738         EXPECT_WK_STREQ("id=a3fWa; qwerty=219ffwef9w0f; sessionid=38afes7a8", [result UTF8String]);
739         navigationCompleted = true;
740     }];
741     Util::run(&navigationCompleted);
742 }
743
744 // The redirected URL has a different domain than the test URL.
745 TEST(SOAuthorizationRedirect, InterceptionSucceedWithRedirectionAndCookie)
746 {
747     resetState();
748     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
749     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
750     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
751     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
752
753     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
754     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
755     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
756
757     auto testURL = URL(URL(), "https://www.example.com");
758 #if PLATFORM(MAC)
759     [webView loadRequest:[NSURLRequest requestWithURL:testURL]];
760 #elif PLATFORM(IOS)
761     // Here we force RedirectSOAuthorizationSession to go to the with user gestures route.
762     [webView evaluateJavaScript: [NSString stringWithFormat:@"location = '%@'", (id)testURL.string()] completionHandler:nil];
763 #endif
764     Util::run(&authorizationPerformed);
765 #if PLATFORM(MAC)
766     checkAuthorizationOptions(false, "", 0);
767 #elif PLATFORM(IOS)
768     checkAuthorizationOptions(true, "null", 0);
769 #endif
770
771     RetainPtr<NSURL> redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
772     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Set-Cookie" : @"sessionid=38afes7a8;", @"Location" : [redirectURL absoluteString] }]);
773     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()];
774     Util::run(&navigationCompleted);
775     EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL);
776
777     navigationCompleted = false;
778     [webView evaluateJavaScript: @"document.cookie" completionHandler:^(NSString *result, NSError *) {
779         EXPECT_WK_STREQ("", [result UTF8String]);
780         navigationCompleted = true;
781     }];
782     Util::run(&navigationCompleted);
783 }
784
785 TEST(SOAuthorizationRedirect, InterceptionSucceedWithDifferentOrigin)
786 {
787     resetState();
788     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
789     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
790     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
791     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
792
793     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
794
795     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
796     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
797     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
798
799     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
800     Util::run(&authorizationPerformed);
801     checkAuthorizationOptions(false, "", 0);
802
803     auto redirectURL = URL(URL(), "https://www.example.com");
804     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:redirectURL statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : redirectURL.string() }]);
805     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()];
806     Util::run(&navigationCompleted);
807     EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL);
808 }
809
810 TEST(SOAuthorizationRedirect, InterceptionSucceedWithWaitingSession)
811 {
812     resetState();
813     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
814     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
815     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
816     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
817
818     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
819
820     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
821     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
822     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
823
824     // The session will be waiting since the web view is is not in the window.
825     [webView removeFromSuperview];
826     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
827     Util::run(&navigationPolicyDecided);
828     EXPECT_FALSE(authorizationPerformed);
829
830     // Should activate the session.
831     [webView addToTestWindow];
832     Util::run(&authorizationPerformed);
833     checkAuthorizationOptions(false, "", 0);
834
835     RetainPtr<NSURL> redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
836     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]);
837     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()];
838     Util::run(&navigationCompleted);
839 #if PLATFORM(IOS)
840     navigationCompleted = false;
841     Util::run(&navigationCompleted);
842 #endif
843     EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL);
844 }
845
846 TEST(SOAuthorizationRedirect, InterceptionAbortedWithWaitingSession)
847 {
848     resetState();
849     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
850     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
851     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
852     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
853
854     RetainPtr<NSURL> testURL1 = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
855     RetainPtr<NSURL> testURL2 = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
856
857     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
858     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
859     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
860
861     // The session will be waiting since the web view is is not in the window.
862     [webView removeFromSuperview];
863     [webView loadRequest:[NSURLRequest requestWithURL:testURL1.get()]];
864     Util::run(&navigationPolicyDecided);
865     EXPECT_FALSE(authorizationPerformed);
866
867     [webView loadRequest:[NSURLRequest requestWithURL:testURL2.get()]];
868     // Should activate the session.
869     [webView addToTestWindow];
870
871     // The waiting session should be aborted as the previous navigation is overwritten by a new navigation.
872     Util::run(&navigationCompleted);
873     EXPECT_FALSE(authorizationPerformed);
874 }
875
876 TEST(SOAuthorizationRedirect, InterceptionSucceedWithActiveSessionDidMoveWindow)
877 {
878     resetState();
879     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
880     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
881     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
882     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
883
884     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
885
886     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
887     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
888     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
889
890     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
891     Util::run(&authorizationPerformed);
892     checkAuthorizationOptions(false, "", 0);
893
894     // Should be a no op.
895     [webView addToTestWindow];
896
897     RetainPtr<NSURL> redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
898     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]);
899     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()];
900     Util::run(&navigationCompleted);
901 #if PLATFORM(IOS)
902     navigationCompleted = false;
903     Util::run(&navigationCompleted);
904 #endif
905     EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL);
906 }
907
908 TEST(SOAuthorizationRedirect, InterceptionSucceedTwice)
909 {
910     resetState();
911     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
912     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
913     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
914     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
915
916     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
917
918     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
919     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
920     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
921
922     for (int i = 0; i < 2; i++) {
923         authorizationPerformed = false;
924         [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
925         Util::run(&authorizationPerformed);
926         checkAuthorizationOptions(false, "", 0);
927
928         navigationCompleted = false;
929         RetainPtr<NSURL> redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
930         auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]);
931         [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()];
932         Util::run(&navigationCompleted);
933 #if PLATFORM(IOS)
934         navigationCompleted = false;
935         Util::run(&navigationCompleted);
936 #endif
937         EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL);
938     }
939 }
940
941 TEST(SOAuthorizationRedirect, InterceptionSucceedSuppressActiveSession)
942 {
943     resetState();
944     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
945     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
946     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
947     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(cancelAuthorization), reinterpret_cast<IMP>(overrideCancelAuthorization));
948     InstanceMethodSwizzler swizzler5(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
949
950     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
951
952     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
953     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
954     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
955
956     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
957     Util::run(&authorizationPerformed);
958     checkAuthorizationOptions(false, "", 0);
959
960     // Suppress the last active session.
961     authorizationPerformed = false;
962     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
963     Util::run(&authorizationCancelled);
964     Util::run(&authorizationPerformed);
965     checkAuthorizationOptions(false, "", 0);
966
967     RetainPtr<NSURL> redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
968     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]);
969     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()];
970     Util::run(&navigationCompleted);
971 #if PLATFORM(IOS)
972     navigationCompleted = false;
973     Util::run(&navigationCompleted);
974 #endif
975     EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL);
976 }
977
978 TEST(SOAuthorizationRedirect, InterceptionSucceedSuppressWaitingSession)
979 {
980     resetState();
981     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
982     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
983     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
984     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
985
986     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
987
988     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
989     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
990     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
991
992     // The session will be waiting since the web view is is not int the window.
993     [webView removeFromSuperview];
994     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
995     Util::run(&navigationPolicyDecided);
996     EXPECT_FALSE(authorizationPerformed);
997
998     // Suppress the last waiting session.
999     navigationPolicyDecided = false;
1000     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1001     Util::run(&navigationPolicyDecided);
1002     EXPECT_FALSE(authorizationPerformed);
1003
1004     // Activate the last session.
1005     [webView addToTestWindow];
1006     Util::run(&authorizationPerformed);
1007     checkAuthorizationOptions(false, "", 0);
1008
1009     RetainPtr<NSURL> redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1010     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]);
1011     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()];
1012     Util::run(&navigationCompleted);
1013 #if PLATFORM(IOS)
1014     navigationCompleted = false;
1015     Util::run(&navigationCompleted);
1016 #endif
1017     EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL);
1018 }
1019
1020 TEST(SOAuthorizationRedirect, InterceptionSucceedSAML)
1021 {
1022     resetState();
1023     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1024     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1025     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1026     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1027
1028     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1029
1030     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
1031     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1032     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
1033
1034     // Add a http body to the request to mimic a SAML request.
1035     auto request = adoptNS([NSMutableURLRequest requestWithURL:testURL.get()]);
1036     [request setHTTPBody:adoptNS([[NSData alloc] init]).get()];
1037     haveHttpBody = true;
1038
1039     [webView loadRequest:request.get()];
1040     Util::run(&authorizationPerformed);
1041     checkAuthorizationOptions(false, "", 0);
1042
1043     // Pass a HTTP 200 response with a html to mimic a SAML response.
1044     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:nil]);
1045     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:samlResponse length:strlen(samlResponse)]).get()];
1046     [webView waitForMessage:@"SAML"];
1047 }
1048
1049 TEST(SOAuthorizationRedirect, InterceptionSucceedSAMLWithPSON)
1050 {
1051     resetState();
1052     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1053     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1054     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1055     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1056
1057     RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple3" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1058     auto testURL = URL(URL(), "http://www.example.com");
1059
1060     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
1061     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1062     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
1063
1064     [webView loadRequest:[NSURLRequest requestWithURL:baseURL.get()]];
1065     Util::run(&navigationCompleted);
1066
1067     // PSON: file:/// => example.com
1068     [webView loadRequest:[NSURLRequest requestWithURL:(NSURL *)testURL]];
1069     Util::run(&authorizationPerformed);
1070
1071     navigationCompleted = false;
1072     // Pass a HTTP 200 response with a html to mimic a SAML response.
1073     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:(NSURL *)testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:nil]);
1074     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:samlResponse length:strlen(samlResponse)]).get()];
1075     Util::run(&navigationCompleted);
1076
1077     authorizationPerformed = false;
1078     navigationPolicyDecided = false;
1079     [webView _evaluateJavaScriptWithoutUserGesture:@"location = 'http://www.example.com'" completionHandler:nil];
1080     Util::run(&navigationPolicyDecided);
1081 }
1082
1083 TEST(SOAuthorizationRedirect, AuthorizationOptions)
1084 {
1085     resetState();
1086     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1087     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1088     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1089     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1090
1091     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
1092     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1093     configureSOAuthorizationWebView(webView.get(), delegate.get());
1094
1095     [webView loadHTMLString:@"" baseURL:(NSURL *)URL(URL(), "http://www.webkit.org")];
1096     Util::run(&navigationCompleted);
1097
1098     [delegate setShouldOpenExternalSchemes:true];
1099     [webView evaluateJavaScript: @"location = 'http://www.example.com'" completionHandler:nil];
1100     Util::run(&authorizationPerformed);
1101     checkAuthorizationOptions(true, "http://www.webkit.org", 0);
1102 }
1103
1104 TEST(SOAuthorizationRedirect, InterceptionDidNotHandleTwice)
1105 {
1106     resetState();
1107     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1108     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1109     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1110     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1111
1112     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1113
1114     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
1115     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1116     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
1117
1118     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1119     Util::run(&authorizationPerformed);
1120
1121     // Test passes if no crashes.
1122     [gDelegate authorizationDidNotHandle:gAuthorization];
1123     [gDelegate authorizationDidNotHandle:gAuthorization];
1124 }
1125
1126 TEST(SOAuthorizationRedirect, InterceptionCompleteTwice)
1127 {
1128     resetState();
1129     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1130     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1131     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1132     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1133
1134     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1135
1136     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
1137     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1138     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
1139
1140     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1141     Util::run(&authorizationPerformed);
1142
1143     // Test passes if no crashes.
1144     RetainPtr<NSURL> redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1145     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]);
1146     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()];
1147     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()];
1148 }
1149
1150 TEST(SOAuthorizationRedirect, SOAuthorizationLoadPolicyIgnore)
1151 {
1152     resetState();
1153     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1154     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1155
1156     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1157
1158     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
1159     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1160     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
1161     [delegate setAllowSOAuthorizationLoad:false];
1162
1163     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1164     Util::run(&navigationCompleted);
1165
1166     EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL);
1167 }
1168
1169 TEST(SOAuthorizationRedirect, SOAuthorizationLoadPolicyAllowAsync)
1170 {
1171     resetState();
1172     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1173     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1174     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1175     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1176
1177     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1178
1179     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
1180     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1181     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
1182
1183     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1184     Util::run(&authorizationPerformed);
1185     checkAuthorizationOptions(false, "", 0);
1186
1187     RetainPtr<NSURL> redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1188     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]);
1189     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()];
1190     Util::run(&navigationCompleted);
1191 #if PLATFORM(IOS)
1192     navigationCompleted = false;
1193     Util::run(&navigationCompleted);
1194 #endif
1195     EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL);
1196 }
1197
1198 TEST(SOAuthorizationRedirect, SOAuthorizationLoadPolicyIgnoreAsync)
1199 {
1200     resetState();
1201     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1202     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1203
1204     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1205
1206     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
1207     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1208     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
1209     [delegate setAllowSOAuthorizationLoad:false];
1210     [delegate setIsAsyncExecution:true];
1211
1212     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1213     Util::run(&navigationCompleted);
1214
1215     EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL);
1216 }
1217
1218
1219 // FIXME(175204): Enable the iOS tests once the bug is fixed.
1220 #if PLATFORM(MAC)
1221 TEST(SOAuthorizationRedirect, InterceptionSucceedWithUI)
1222 {
1223     resetState();
1224     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1225     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1226     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1227     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1228
1229     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1230
1231     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
1232     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1233     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
1234
1235     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1236     Util::run(&authorizationPerformed);
1237
1238     auto viewController = adoptNS([[TestSOAuthorizationViewController alloc] init]);
1239     auto view = adoptNS([[NSView alloc] initWithFrame:NSZeroRect]);
1240     [viewController setView:view.get()];
1241
1242     [gDelegate authorization:gAuthorization presentViewController:viewController.get() withCompletion:^(BOOL success, NSError *) {
1243         EXPECT_TRUE(success);
1244     }];
1245     Util::run(&uiShowed);
1246
1247     RetainPtr<NSURL> redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1248     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]);
1249     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()];
1250     Util::run(&navigationCompleted);
1251     EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL);
1252     EXPECT_FALSE(uiShowed);
1253 }
1254
1255 TEST(SOAuthorizationRedirect, InterceptionCancelWithUI)
1256 {
1257     resetState();
1258     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1259     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1260     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1261     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1262
1263     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1264
1265     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
1266     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1267     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
1268
1269     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1270     Util::run(&authorizationPerformed);
1271
1272     auto viewController = adoptNS([[TestSOAuthorizationViewController alloc] init]);
1273     auto view = adoptNS([[NSView alloc] initWithFrame:NSZeroRect]);
1274     [viewController setView:view.get()];
1275
1276     [gDelegate authorization:gAuthorization presentViewController:viewController.get() withCompletion:^(BOOL success, NSError *) {
1277         EXPECT_TRUE(success);
1278     }];
1279     Util::run(&uiShowed);
1280
1281     [gDelegate authorizationDidCancel:gAuthorization];
1282     // FIXME: Find a delegate method that can detect load cancels.
1283     Util::sleep(0.5);
1284     EXPECT_WK_STREQ("", webView.get()._committedURL.absoluteString);
1285     EXPECT_FALSE(uiShowed);
1286 }
1287
1288 TEST(SOAuthorizationRedirect, InterceptionErrorWithUI)
1289 {
1290     resetState();
1291     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1292     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1293     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1294     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1295
1296     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1297
1298     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
1299     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1300     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
1301
1302     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1303     Util::run(&authorizationPerformed);
1304
1305     auto viewController = adoptNS([[TestSOAuthorizationViewController alloc] init]);
1306     auto view = adoptNS([[NSView alloc] initWithFrame:NSZeroRect]);
1307     [viewController setView:view.get()];
1308
1309     [gDelegate authorization:gAuthorization presentViewController:viewController.get() withCompletion:^(BOOL success, NSError *) {
1310         EXPECT_TRUE(success);
1311     }];
1312     Util::run(&uiShowed);
1313
1314     [gDelegate authorization:gAuthorization didCompleteWithError:adoptNS([[NSError alloc] initWithDomain:NSCocoaErrorDomain code:0 userInfo:nil]).get()];
1315     Util::run(&navigationCompleted);
1316     EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL);
1317     EXPECT_FALSE(uiShowed);
1318 }
1319
1320 TEST(SOAuthorizationRedirect, InterceptionSucceedSuppressActiveSessionWithUI)
1321 {
1322     resetState();
1323     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1324     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1325     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1326     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(cancelAuthorization), reinterpret_cast<IMP>(overrideCancelAuthorization));
1327     InstanceMethodSwizzler swizzler5(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1328
1329     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1330
1331     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
1332     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1333     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
1334
1335     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1336     Util::run(&authorizationPerformed);
1337
1338     auto viewController = adoptNS([[TestSOAuthorizationViewController alloc] init]);
1339     auto view = adoptNS([[NSView alloc] initWithFrame:NSZeroRect]);
1340     [viewController setView:view.get()];
1341
1342     [gDelegate authorization:gAuthorization presentViewController:viewController.get() withCompletion:^(BOOL success, NSError *) {
1343         EXPECT_TRUE(success);
1344     }];
1345     Util::run(&uiShowed);
1346
1347     // Suppress the last active session.
1348     authorizationPerformed = false;
1349     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1350     Util::run(&authorizationCancelled);
1351     Util::run(&authorizationPerformed);
1352     EXPECT_FALSE(uiShowed);
1353
1354     RetainPtr<NSURL> redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1355     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]);
1356     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()];
1357     Util::run(&navigationCompleted);
1358     EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL);
1359 }
1360
1361 TEST(SOAuthorizationRedirect, ShowUITwice)
1362 {
1363     resetState();
1364     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1365     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1366     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1367     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1368
1369     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1370
1371     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
1372     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1373     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
1374
1375     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1376     Util::run(&authorizationPerformed);
1377
1378     auto viewController = adoptNS([[TestSOAuthorizationViewController alloc] init]);
1379     auto view = adoptNS([[NSView alloc] initWithFrame:NSZeroRect]);
1380     [viewController setView:view.get()];
1381
1382     [gDelegate authorization:gAuthorization presentViewController:viewController.get() withCompletion:^(BOOL success, NSError *) {
1383         EXPECT_TRUE(success);
1384     }];
1385     Util::run(&uiShowed);
1386
1387     uiShowed = false;
1388     [gDelegate authorization:gAuthorization presentViewController:viewController.get() withCompletion:^(BOOL success, NSError *error) {
1389         EXPECT_FALSE(success);
1390         EXPECT_EQ(error.code, kSOErrorAuthorizationPresentationFailed);
1391         EXPECT_WK_STREQ(error.domain, "com.apple.AppSSO.AuthorizationError");
1392         uiShowed = true;
1393     }];
1394     Util::run(&uiShowed);
1395 }
1396 #endif
1397
1398 #if PLATFORM(MAC)
1399 TEST(SOAuthorizationRedirect, NSNotificationCenter)
1400 {
1401     resetState();
1402     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1403     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1404     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1405     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1406
1407     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1408
1409     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
1410     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1411     configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow);
1412
1413     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1414     Util::run(&authorizationPerformed);
1415
1416     auto viewController = adoptNS([[TestSOAuthorizationViewController alloc] init]);
1417     auto view = adoptNS([[NSView alloc] initWithFrame:NSZeroRect]);
1418     {
1419         InstanceMethodSwizzler swizzler4([NSNotificationCenter class], @selector(addObserverForName:object:queue:usingBlock:), reinterpret_cast<IMP>(overrideAddObserverForName));
1420         [viewController setView:view.get()];
1421         [gDelegate authorization:gAuthorization presentViewController:viewController.get() withCompletion:^(BOOL success, NSError *) {
1422             EXPECT_TRUE(success);
1423         }];
1424         Util::run(&uiShowed);
1425     }
1426
1427     gNotificationCallback(nullptr);
1428     EXPECT_FALSE(uiShowed);
1429 }
1430 #endif
1431
1432 TEST(SOAuthorizationPopUp, NoInterceptions)
1433 {
1434     resetState();
1435
1436     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1437     auto testHtml = generateHtml(openerTemplate, testURL.get().absoluteString);
1438
1439     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]);
1440     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1441     configureSOAuthorizationWebView(webView.get(), delegate.get());
1442
1443     [webView loadHTMLString:testHtml baseURL:testURL.get()];
1444     Util::run(&navigationCompleted);
1445
1446     [delegate setShouldOpenExternalSchemes:true];
1447     navigationCompleted = false;
1448 #if PLATFORM(MAC)
1449     [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1];
1450 #elif PLATFORM(IOS)
1451     [webView evaluateJavaScript: @"clickMe()" completionHandler:nil];
1452 #endif
1453     Util::run(&newWindowCreated);
1454     Util::run(&navigationCompleted);
1455     EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL);
1456 }
1457
1458 // FIXME(172614): Enable the following test for iOS once the bug is fixed.
1459 #if PLATFORM(MAC)
1460 TEST(SOAuthorizationPopUp, NoInterceptionsSubFrame)
1461 {
1462     resetState();
1463     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1464     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1465     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1466     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1467
1468     RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1469     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1470     auto iframeTestHtml = generateHtml(openerTemplate, testURL.get().absoluteString);
1471     auto testHtml = makeString("<iframe style='width:400px;height:400px' srcdoc=\"", iframeTestHtml, "\" />");
1472
1473     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]);
1474     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1475     configureSOAuthorizationWebView(webView.get(), delegate.get());
1476
1477     [webView loadHTMLString:testHtml baseURL:baseURL.get()];
1478     Util::run(&navigationCompleted);
1479
1480     // The new window will not navigate to the testURL as the iframe has unique origin.
1481     [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1];
1482     Util::run(&newWindowCreated);
1483     EXPECT_FALSE(authorizationPerformed);
1484 }
1485 #endif
1486
1487 TEST(SOAuthorizationPopUp, NoInterceptionsWithoutUserGesture)
1488 {
1489     resetState();
1490     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1491     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1492     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1493     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1494
1495     // The default value of javaScriptCanOpenWindowsAutomatically is NO on iOS, and YES on macOS.
1496     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
1497     configuration.get().preferences.javaScriptCanOpenWindowsAutomatically = YES;
1498
1499     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400) configuration:configuration.get()]);
1500     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1501     configureSOAuthorizationWebView(webView.get(), delegate.get());
1502
1503     [webView _evaluateJavaScriptWithoutUserGesture: @"window.open('http://www.example.com')" completionHandler:nil];
1504     Util::run(&newWindowCreated);
1505     EXPECT_FALSE(authorizationPerformed);
1506 }
1507
1508 TEST(SOAuthorizationPopUp, InterceptionError)
1509 {
1510     resetState();
1511     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1512     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1513     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1514     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1515
1516     RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1517     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1518     auto testHtml = generateHtml(openerTemplate, testURL.get().absoluteString);
1519
1520     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]);
1521     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1522     configureSOAuthorizationWebView(webView.get(), delegate.get());
1523
1524     [webView loadHTMLString:testHtml baseURL:baseURL.get()];
1525     Util::run(&navigationCompleted);
1526
1527     [delegate setShouldOpenExternalSchemes:true];
1528 #if PLATFORM(MAC)
1529     [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1];
1530 #elif PLATFORM(IOS)
1531     [webView evaluateJavaScript: @"clickMe()" completionHandler:nil];
1532 #endif
1533     Util::run(&authorizationPerformed);
1534     checkAuthorizationOptions(true, "file://", 1);
1535
1536     authorizationPerformed = false;
1537     navigationCompleted = false;
1538     [gDelegate authorization:gAuthorization didCompleteWithError:adoptNS([[NSError alloc] initWithDomain:NSCocoaErrorDomain code:0 userInfo:nil]).get()];
1539     Util::run(&newWindowCreated);
1540     Util::run(&navigationCompleted);
1541     EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL);
1542     EXPECT_FALSE(authorizationPerformed); // Don't intercept the first navigation in the new window.
1543 }
1544
1545 TEST(SOAuthorizationPopUp, InterceptionCancel)
1546 {
1547     resetState();
1548     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1549     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1550     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1551     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1552
1553     RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1554     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1555     auto testHtml = generateHtml(openerTemplate, testURL.get().absoluteString);
1556
1557     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]);
1558     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1559     configureSOAuthorizationWebView(webView.get(), delegate.get());
1560
1561     [webView loadHTMLString:testHtml baseURL:baseURL.get()];
1562     Util::run(&navigationCompleted);
1563
1564 #if PLATFORM(MAC)
1565     [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1];
1566 #elif PLATFORM(IOS)
1567     [webView evaluateJavaScript: @"clickMe()" completionHandler:nil];
1568 #endif
1569     Util::run(&authorizationPerformed);
1570     checkAuthorizationOptions(true, "file://", 1);
1571
1572     // The secret WKWebView needs to be destroyed right the way.
1573     @autoreleasepool {
1574         [gDelegate authorizationDidCancel:gAuthorization];
1575     }
1576     [webView waitForMessage:@"WindowClosed."];
1577 }
1578
1579 TEST(SOAuthorizationPopUp, InterceptionSucceedCloseByItself)
1580 {
1581     resetState();
1582     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1583     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1584     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1585     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1586
1587     RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1588     auto testURL = URL(URL(), "http://www.example.com");
1589     auto testHtml = generateHtml(openerTemplate, testURL.string());
1590
1591     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]);
1592     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1593     configureSOAuthorizationWebView(webView.get(), delegate.get());
1594
1595     [webView loadHTMLString:testHtml baseURL:baseURL.get()];
1596     Util::run(&navigationCompleted);
1597
1598 #if PLATFORM(MAC)
1599     [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1];
1600 #elif PLATFORM(IOS)
1601     [webView evaluateJavaScript: @"clickMe()" completionHandler:nil];
1602 #endif
1603     Util::run(&authorizationPerformed);
1604     checkAuthorizationOptions(true, "file://", 1);
1605
1606     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:nil]);
1607     auto resonseHtmlCString = generateHtml(newWindowResponseTemplate, "window.close();").utf8(); // The pop up closes itself.
1608     // The secret WKWebView needs to be destroyed right the way.
1609     @autoreleasepool {
1610         [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:resonseHtmlCString.data() length:resonseHtmlCString.length()]).get()];
1611     }
1612     [webView waitForMessage:@"Hello."];
1613     [webView waitForMessage:@"WindowClosed."];
1614 }
1615
1616 TEST(SOAuthorizationPopUp, InterceptionSucceedCloseByParent)
1617 {
1618     resetState();
1619     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1620     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1621     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1622     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1623
1624     RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1625     auto testURL = URL(URL(), "http://www.example.com");
1626     auto testHtml = generateHtml(openerTemplate, testURL.string(), "", "event.source.close();"); // The parent closes the pop up.
1627
1628     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]);
1629     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1630     configureSOAuthorizationWebView(webView.get(), delegate.get());
1631
1632     [webView loadHTMLString:testHtml baseURL:baseURL.get()];
1633     Util::run(&navigationCompleted);
1634
1635 #if PLATFORM(MAC)
1636     [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1];
1637 #elif PLATFORM(IOS)
1638     [webView evaluateJavaScript: @"clickMe()" completionHandler:nil];
1639 #endif
1640     Util::run(&authorizationPerformed);
1641     checkAuthorizationOptions(true, "file://", 1);
1642
1643     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:nil]);
1644     auto resonseHtmlCString = generateHtml(newWindowResponseTemplate, "").utf8();
1645     // The secret WKWebView needs to be destroyed right the way.
1646     @autoreleasepool {
1647         [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:resonseHtmlCString.data() length:resonseHtmlCString.length()]).get()];
1648     }
1649     [webView waitForMessage:@"Hello."];
1650     [webView waitForMessage:@"WindowClosed."];
1651 }
1652
1653 TEST(SOAuthorizationPopUp, InterceptionSucceedCloseByWebKit)
1654 {
1655     resetState();
1656     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1657     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1658     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1659     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1660
1661     RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1662     auto testURL = URL(URL(), "http://www.example.com");
1663     auto testHtml = generateHtml(openerTemplate, testURL.string());
1664
1665     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]);
1666     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1667     configureSOAuthorizationWebView(webView.get(), delegate.get());
1668
1669     [webView loadHTMLString:testHtml baseURL:baseURL.get()];
1670     Util::run(&navigationCompleted);
1671
1672 #if PLATFORM(MAC)
1673     [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1];
1674 #elif PLATFORM(IOS)
1675     [webView evaluateJavaScript: @"clickMe()" completionHandler:nil];
1676 #endif
1677     Util::run(&authorizationPerformed);
1678     checkAuthorizationOptions(true, "file://", 1);
1679
1680     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:nil]);
1681     auto resonseHtmlCString = generateHtml(newWindowResponseTemplate, "").utf8();
1682     // The secret WKWebView needs to be destroyed right the way.
1683     @autoreleasepool {
1684         [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:resonseHtmlCString.data() length:resonseHtmlCString.length()]).get()];
1685     }
1686     [webView waitForMessage:@"Hello."];
1687     [webView waitForMessage:@"WindowClosed."];
1688 }
1689
1690 TEST(SOAuthorizationPopUp, InterceptionSucceedWithOtherHttpStatusCode)
1691 {
1692     resetState();
1693     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1694     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1695     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1696     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1697
1698     RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1699     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1700     auto testHtml = generateHtml(openerTemplate, testURL.get().absoluteString);
1701
1702     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]);
1703     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1704     configureSOAuthorizationWebView(webView.get(), delegate.get());
1705
1706     [webView loadHTMLString:testHtml baseURL:baseURL.get()];
1707     Util::run(&navigationCompleted);
1708
1709     [delegate setShouldOpenExternalSchemes:true];
1710 #if PLATFORM(MAC)
1711     [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1];
1712 #elif PLATFORM(IOS)
1713     [webView evaluateJavaScript: @"clickMe()" completionHandler:nil];
1714 #endif
1715     Util::run(&authorizationPerformed);
1716     checkAuthorizationOptions(true, "file://", 1);
1717
1718     // Will fallback to web path.
1719     navigationCompleted = false;
1720     authorizationPerformed = false;
1721     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:400 HTTPVersion:@"HTTP/1.1" headerFields:nil]);
1722     auto resonseHtmlCString = generateHtml(newWindowResponseTemplate, "").utf8();
1723     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:resonseHtmlCString.data() length:resonseHtmlCString.length()]).get()];
1724     Util::run(&newWindowCreated);
1725     Util::run(&navigationCompleted);
1726     EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL);
1727     EXPECT_FALSE(authorizationPerformed);
1728 }
1729
1730 // Setting cookie is ensured by other tests. Here is to cover if the whole authentication handshake can be completed.
1731 TEST(SOAuthorizationPopUp, InterceptionSucceedWithCookie)
1732 {
1733     resetState();
1734     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1735     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1736     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1737     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1738
1739     RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1740     auto testURL = URL(URL(), "http://www.example.com");
1741     auto testHtml = generateHtml(openerTemplate, testURL.string());
1742
1743     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]);
1744     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1745     configureSOAuthorizationWebView(webView.get(), delegate.get());
1746
1747     [webView loadHTMLString:testHtml baseURL:baseURL.get()];
1748     Util::run(&navigationCompleted);
1749
1750 #if PLATFORM(MAC)
1751     [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1];
1752 #elif PLATFORM(IOS)
1753     [webView evaluateJavaScript: @"clickMe()" completionHandler:nil];
1754 #endif
1755     Util::run(&authorizationPerformed);
1756     checkAuthorizationOptions(true, "file://", 1);
1757
1758     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Set-Cookie" : @"sessionid=38afes7a8;"}]);
1759     auto resonseHtmlCString = generateHtml(newWindowResponseTemplate, "").utf8();
1760     // The secret WKWebView needs to be destroyed right the way.
1761     @autoreleasepool {
1762         [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:resonseHtmlCString.data() length:resonseHtmlCString.length()]).get()];
1763     }
1764     [webView waitForMessage:@"Hello."];
1765     [webView waitForMessage:@"WindowClosed."];
1766 }
1767
1768 TEST(SOAuthorizationPopUp, InterceptionSucceedTwice)
1769 {
1770     resetState();
1771     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1772     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1773     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1774     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1775
1776     RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1777     auto testURL = URL(URL(), "http://www.example.com");
1778     auto testHtml = generateHtml(openerTemplate, testURL.string());
1779
1780     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]);
1781     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1782     configureSOAuthorizationWebView(webView.get(), delegate.get());
1783
1784     [webView loadHTMLString:testHtml baseURL:baseURL.get()];
1785     Util::run(&navigationCompleted);
1786
1787     for (int i = 0; i < 2; i++) {
1788         authorizationPerformed = false;
1789 #if PLATFORM(MAC)
1790         [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1];
1791 #elif PLATFORM(IOS)
1792         [webView evaluateJavaScript: @"clickMe()" completionHandler:nil];
1793 #endif
1794         Util::run(&authorizationPerformed);
1795         checkAuthorizationOptions(true, "file://", 1);
1796
1797         auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:nil]);
1798         auto resonseHtmlCString = generateHtml(newWindowResponseTemplate, "").utf8();
1799         // The secret WKWebView needs to be destroyed right the way.
1800         @autoreleasepool {
1801             [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:resonseHtmlCString.data() length:resonseHtmlCString.length()]).get()];
1802         }
1803         [webView waitForMessage:@"Hello."];
1804         [webView waitForMessage:@"WindowClosed."];
1805     }
1806 }
1807
1808 TEST(SOAuthorizationPopUp, InterceptionSucceedSuppressActiveSession)
1809 {
1810     resetState();
1811     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1812     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1813     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1814     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(cancelAuthorization), reinterpret_cast<IMP>(overrideCancelAuthorization));
1815     InstanceMethodSwizzler swizzler5(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1816
1817     RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1818     auto testURL = URL(URL(), "http://www.example.com");
1819     auto testHtml = generateHtml(openerTemplate, testURL.string());
1820
1821     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]);
1822     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1823     configureSOAuthorizationWebView(webView.get(), delegate.get());
1824
1825     [webView loadHTMLString:testHtml baseURL:baseURL.get()];
1826     Util::run(&navigationCompleted);
1827
1828 #if PLATFORM(MAC)
1829     [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1];
1830 #elif PLATFORM(IOS)
1831     [webView evaluateJavaScript: @"clickMe()" completionHandler:nil];
1832 #endif
1833     Util::run(&authorizationPerformed);
1834     checkAuthorizationOptions(true, "file://", 1);
1835
1836     // Suppress the last active session.
1837     auto newWebView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400) configuration:webView.get().configuration]);
1838     configureSOAuthorizationWebView(newWebView.get(), delegate.get());
1839
1840     navigationCompleted = false;
1841     [newWebView loadHTMLString:testHtml baseURL:baseURL.get()];
1842     Util::run(&navigationCompleted);
1843
1844     authorizationPerformed = false;
1845 #if PLATFORM(MAC)
1846     [newWebView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1];
1847 #elif PLATFORM(IOS)
1848     [newWebView evaluateJavaScript: @"clickMe()" completionHandler:nil];
1849 #endif
1850     Util::run(&authorizationCancelled);
1851     Util::run(&authorizationPerformed);
1852     checkAuthorizationOptions(true, "file://", 1);
1853
1854     navigationCompleted = false;
1855     [webView evaluateJavaScript: @"newWindow" completionHandler:^(id result, NSError *) {
1856         EXPECT_TRUE(result == adoptNS([NSNull null]).get());
1857         navigationCompleted = true;
1858     }];
1859     Util::run(&navigationCompleted);
1860
1861     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:nil]);
1862     auto resonseHtmlCString = generateHtml(newWindowResponseTemplate, "").utf8();
1863     // The secret WKWebView needs to be destroyed right the way.
1864     @autoreleasepool {
1865         [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:resonseHtmlCString.data() length:resonseHtmlCString.length()]).get()];
1866     }
1867     [newWebView waitForMessage:@"Hello."];
1868     [newWebView waitForMessage:@"WindowClosed."];
1869 }
1870
1871 TEST(SOAuthorizationPopUp, InterceptionSucceedNewWindowNavigation)
1872 {
1873     resetState();
1874     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1875     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1876     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1877     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1878
1879     RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1880     auto testURL = URL(URL(), "http://www.example.com");
1881     auto testHtml = generateHtml(openerTemplate, testURL.string(), makeString("newWindow.location = '", baseURL.get().absoluteString.UTF8String, "';")); // Starts a new navigation on the new window.
1882
1883     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]);
1884     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1885     configureSOAuthorizationWebView(webView.get(), delegate.get());
1886
1887     [webView loadHTMLString:testHtml baseURL:baseURL.get()];
1888     Util::run(&navigationCompleted);
1889
1890 #if PLATFORM(MAC)
1891     [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1];
1892 #elif PLATFORM(IOS)
1893     [webView evaluateJavaScript: @"clickMe()" completionHandler:nil];
1894 #endif
1895     Util::run(&authorizationPerformed);
1896     checkAuthorizationOptions(true, "file://", 1);
1897
1898     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:nil]);
1899     auto resonseHtmlCString = generateHtml(newWindowResponseTemplate, "").utf8();
1900     // The secret WKWebView needs to be destroyed right the way.
1901     @autoreleasepool {
1902         [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:resonseHtmlCString.data() length:resonseHtmlCString.length()]).get()];
1903     }
1904     [webView waitForMessage:@"Hello."];
1905     [webView waitForMessage:@"WindowClosed."];
1906 }
1907
1908 TEST(SOAuthorizationPopUp, AuthorizationOptions)
1909 {
1910     resetState();
1911     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1912     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1913     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1914     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1915
1916     auto testURL = URL(URL(), "http://www.example.com");
1917     auto testHtml = generateHtml(openerTemplate, testURL.string());
1918
1919     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]);
1920     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1921     configureSOAuthorizationWebView(webView.get(), delegate.get());
1922
1923     [webView loadHTMLString:testHtml baseURL:(NSURL *)URL(URL(), "http://www.webkit.org")];
1924     Util::run(&navigationCompleted);
1925
1926 #if PLATFORM(MAC)
1927     [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1];
1928 #elif PLATFORM(IOS)
1929     [webView evaluateJavaScript: @"clickMe()" completionHandler:nil];
1930 #endif
1931     Util::run(&authorizationPerformed);
1932     checkAuthorizationOptions(true, "http://www.webkit.org", 1);
1933 }
1934
1935 TEST(SOAuthorizationPopUp, SOAuthorizationLoadPolicyIgnore)
1936 {
1937     resetState();
1938     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1939     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1940
1941     auto testURL = URL(URL(), "http://www.example.com");
1942     auto testHtml = generateHtml(openerTemplate, testURL.string());
1943
1944     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
1945     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1946     configureSOAuthorizationWebView(webView.get(), delegate.get());
1947     [delegate setAllowSOAuthorizationLoad:false];
1948
1949     [webView loadHTMLString:testHtml baseURL:(NSURL *)URL(URL(), "http://www.webkit.org")];
1950     Util::run(&navigationCompleted);
1951
1952 #if PLATFORM(MAC)
1953     [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1];
1954 #elif PLATFORM(IOS)
1955     [webView evaluateJavaScript: @"clickMe()" completionHandler:nil];
1956 #endif
1957     Util::run(&newWindowCreated);
1958     EXPECT_FALSE(authorizationPerformed);
1959 }
1960
1961 TEST(SOAuthorizationPopUp, SOAuthorizationLoadPolicyAllowAsync)
1962 {
1963     resetState();
1964     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
1965     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
1966     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
1967     InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
1968
1969     RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1970     auto testURL = URL(URL(), "http://www.example.com");
1971     auto testHtml = generateHtml(openerTemplate, testURL.string());
1972
1973     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]);
1974     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
1975     configureSOAuthorizationWebView(webView.get(), delegate.get());
1976     [delegate setIsAsyncExecution:true];
1977
1978     [webView loadHTMLString:testHtml baseURL:baseURL.get()];
1979     Util::run(&navigationCompleted);
1980
1981 #if PLATFORM(MAC)
1982     [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1];
1983 #elif PLATFORM(IOS)
1984     [webView evaluateJavaScript: @"clickMe()" completionHandler:nil];
1985 #endif
1986     Util::run(&authorizationPerformed);
1987     checkAuthorizationOptions(true, "file://", 1);
1988
1989     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:nil]);
1990     auto resonseHtmlCString = generateHtml(newWindowResponseTemplate, "window.close();").utf8(); // The pop up closes itself.
1991     // The secret WKWebView needs to be destroyed right the way.
1992     @autoreleasepool {
1993         [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:resonseHtmlCString.data() length:resonseHtmlCString.length()]).get()];
1994     }
1995     [webView waitForMessage:@"Hello."];
1996     [webView waitForMessage:@"WindowClosed."];
1997 }
1998
1999
2000 TEST(SOAuthorizationPopUp, SOAuthorizationLoadPolicyIgnoreAsync)
2001 {
2002     resetState();
2003     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
2004     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
2005
2006     auto testURL = URL(URL(), "http://www.example.com");
2007     auto testHtml = generateHtml(openerTemplate, testURL.string());
2008
2009     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
2010     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
2011     configureSOAuthorizationWebView(webView.get(), delegate.get());
2012     [delegate setAllowSOAuthorizationLoad:false];
2013     [delegate setIsAsyncExecution:true];
2014
2015     [webView loadHTMLString:testHtml baseURL:(NSURL *)URL(URL(), "http://www.webkit.org")];
2016     Util::run(&navigationCompleted);
2017
2018 #if PLATFORM(MAC)
2019     [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1];
2020 #elif PLATFORM(IOS)
2021     [webView evaluateJavaScript: @"clickMe()" completionHandler:nil];
2022 #endif
2023     Util::run(&newWindowCreated);
2024     EXPECT_FALSE(authorizationPerformed);
2025 }
2026
2027 TEST(SOAuthorizationSubFrame, NoInterceptions)
2028 {
2029     resetState();
2030     RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
2031     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"GetSessionCookie" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
2032     auto testHtml = generateHtml(parentTemplate, testURL.get().absoluteString);
2033
2034     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
2035     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
2036     configureSOAuthorizationWebView(webView.get(), delegate.get());
2037
2038     [webView loadHTMLString:testHtml baseURL:baseURL.get()];
2039     [webView waitForMessage:@""];
2040 }
2041
2042 TEST(SOAuthorizationSubFrame, NoInterceptionsNonAppleFirstPartyMainFrame)
2043 {
2044     resetState();
2045     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
2046     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
2047     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
2048     InstanceMethodSwizzler swizzler5(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
2049
2050     auto testHtml = generateHtml(parentTemplate, URL(URL(), "http://www.example.com").string());
2051
2052     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
2053     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
2054     configureSOAuthorizationWebView(webView.get(), delegate.get());
2055
2056     [webView loadHTMLString:testHtml baseURL:(NSURL *)URL(URL(), "http://www.webkit.org")];
2057     // Try to wait until the iframe load is finished.
2058     Util::sleep(0.5);
2059     // Make sure we don't intercept the iframe.
2060     EXPECT_FALSE(authorizationPerformed);
2061 }
2062
2063 TEST(SOAuthorizationSubFrame, InterceptionError)
2064 {
2065     resetState();
2066     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
2067     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
2068     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
2069     ClassMethodSwizzler swizzler4([AKAuthorizationController class], @selector(isURLFromAppleOwnedDomain:), reinterpret_cast<IMP>(overrideIsURLFromAppleOwnedDomain));
2070     InstanceMethodSwizzler swizzler5(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
2071
2072     RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
2073     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"GetSessionCookie" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
2074     auto testHtml = generateHtml(parentTemplate, testURL.get().absoluteString);
2075
2076     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
2077     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
2078     configureSOAuthorizationWebView(webView.get(), delegate.get());
2079
2080     [webView loadHTMLString:testHtml baseURL:baseURL.get()];
2081     [webView waitForMessage:@"null"];
2082     [webView waitForMessage:@"SOAuthorizationDidStart"];
2083     checkAuthorizationOptions(false, "file://", 2);
2084
2085     [gDelegate authorization:gAuthorization didCompleteWithError:adoptNS([[NSError alloc] initWithDomain:NSCocoaErrorDomain code:0 userInfo:nil]).get()];
2086     [webView waitForMessage:@"null"];
2087     [webView waitForMessage:@"SOAuthorizationDidCancel"];
2088     [webView waitForMessage:@""];
2089     // Trys to wait until the iframe load is finished.
2090     Util::sleep(0.5);
2091     // Make sure we don't load the request of the iframe to the main frame.
2092     EXPECT_WK_STREQ("", finalURL);
2093 }
2094
2095 TEST(SOAuthorizationSubFrame, InterceptionSuccess)
2096 {
2097     resetState();
2098     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
2099     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
2100     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
2101     ClassMethodSwizzler swizzler4([AKAuthorizationController class], @selector(isURLFromAppleOwnedDomain:), reinterpret_cast<IMP>(overrideIsURLFromAppleOwnedDomain));
2102     InstanceMethodSwizzler swizzler5(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
2103
2104     auto testURL = URL(URL(), "http://www.example.com");
2105     auto testHtml = generateHtml(parentTemplate, testURL.string());
2106
2107     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
2108     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
2109     configureSOAuthorizationWebView(webView.get(), delegate.get());
2110
2111     [webView loadHTMLString:testHtml baseURL:nil];
2112     [webView waitForMessage:@"http://www.example.com"];
2113     [webView waitForMessage:@"SOAuthorizationDidStart"];
2114     checkAuthorizationOptions(false, "null", 2);
2115
2116     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:nil]);
2117     auto iframeHtmlCString = generateHtml(iframeTemplate, "").utf8();
2118     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:iframeHtmlCString.data() length:iframeHtmlCString.length()]).get()];
2119     [webView waitForMessage:@"http://www.example.com"];
2120     [webView waitForMessage:@"Hello."];
2121 }
2122
2123 TEST(SOAuthorizationSubFrame, InterceptionSucceedWithOtherHttpStatusCode)
2124 {
2125     resetState();
2126     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
2127     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
2128     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
2129     ClassMethodSwizzler swizzler4([AKAuthorizationController class], @selector(isURLFromAppleOwnedDomain:), reinterpret_cast<IMP>(overrideIsURLFromAppleOwnedDomain));
2130     InstanceMethodSwizzler swizzler5(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
2131
2132     RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
2133     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"GetSessionCookie" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
2134     auto testHtml = generateHtml(parentTemplate, testURL.get().absoluteString);
2135
2136     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
2137     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
2138     configureSOAuthorizationWebView(webView.get(), delegate.get());
2139
2140     [webView loadHTMLString:testHtml baseURL:baseURL.get()];
2141     [webView waitForMessage:@"null"];
2142     [webView waitForMessage:@"SOAuthorizationDidStart"];
2143     checkAuthorizationOptions(false, "file://", 2);
2144
2145     // Will fallback to web path.
2146     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:400 HTTPVersion:@"HTTP/1.1" headerFields:nil]);
2147     auto iframeHtmlCString = generateHtml(iframeTemplate, "").utf8();
2148     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:iframeHtmlCString.data() length:iframeHtmlCString.length()]).get()];
2149     [webView waitForMessage:@"null"];
2150     [webView waitForMessage:@"SOAuthorizationDidCancel"];
2151     [webView waitForMessage:@""];
2152     // Trys to wait until the iframe load is finished.
2153     Util::sleep(0.5);
2154     // Make sure we don't load the request of the iframe to the main frame.
2155     EXPECT_WK_STREQ("", finalURL);
2156 }
2157
2158 // Setting cookie is ensured by other tests. Here is to cover if the whole authentication handshake can be completed.
2159 TEST(SOAuthorizationSubFrame, InterceptionSucceedWithCookie)
2160 {
2161     resetState();
2162     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
2163     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
2164     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
2165     ClassMethodSwizzler swizzler4([AKAuthorizationController class], @selector(isURLFromAppleOwnedDomain:), reinterpret_cast<IMP>(overrideIsURLFromAppleOwnedDomain));
2166     InstanceMethodSwizzler swizzler5(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
2167
2168     auto testURL = URL(URL(), "http://www.example.com");
2169     auto testHtml = generateHtml(parentTemplate, testURL.string());
2170
2171     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
2172     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
2173     configureSOAuthorizationWebView(webView.get(), delegate.get());
2174
2175     [webView loadHTMLString:testHtml baseURL:nil];
2176     [webView waitForMessage:@"http://www.example.com"];
2177     [webView waitForMessage:@"SOAuthorizationDidStart"];
2178     checkAuthorizationOptions(false, "null", 2);
2179
2180     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Set-Cookie" : @"sessionid=38afes7a8;"}]);
2181     auto iframeHtmlCString = generateHtml(iframeTemplate, "").utf8();
2182     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:iframeHtmlCString.data() length:iframeHtmlCString.length()]).get()];
2183     [webView waitForMessage:@"http://www.example.com"];
2184     [webView waitForMessage:@"Hello."];
2185 }
2186
2187 TEST(SOAuthorizationSubFrame, InterceptionSuccessTwice)
2188 {
2189     resetState();
2190     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
2191     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
2192     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
2193     ClassMethodSwizzler swizzler4([AKAuthorizationController class], @selector(isURLFromAppleOwnedDomain:), reinterpret_cast<IMP>(overrideIsURLFromAppleOwnedDomain));
2194     InstanceMethodSwizzler swizzler5(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
2195
2196     auto testURL = URL(URL(), "http://www.example.com");
2197     auto testHtml = generateHtml(parentTemplate, testURL.string());
2198
2199     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
2200     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
2201     configureSOAuthorizationWebView(webView.get(), delegate.get());
2202
2203     for (int i = 0; i < 2; i++) {
2204         authorizationPerformed = false;
2205         navigationCompleted = false;
2206
2207         [webView loadHTMLString:testHtml baseURL:nil];
2208         [webView waitForMessage:@"http://www.example.com"];
2209         [webView waitForMessage:@"SOAuthorizationDidStart"];
2210         checkAuthorizationOptions(false, "null", 2);
2211
2212         auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:nil]);
2213         auto iframeHtmlCString = generateHtml(iframeTemplate, "").utf8();
2214         [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:iframeHtmlCString.data() length:iframeHtmlCString.length()]).get()];
2215         [webView waitForMessage:@"http://www.example.com"];
2216         [webView waitForMessage:@"Hello."];
2217     }
2218 }
2219
2220 TEST(SOAuthorizationSubFrame, AuthorizationOptions)
2221 {
2222     resetState();
2223     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
2224     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
2225     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
2226     ClassMethodSwizzler swizzler4([AKAuthorizationController class], @selector(isURLFromAppleOwnedDomain:), reinterpret_cast<IMP>(overrideIsURLFromAppleOwnedDomain));
2227     InstanceMethodSwizzler swizzler5(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
2228
2229     auto testURL = URL(URL(), "http://www.example.com");
2230     auto testHtml = generateHtml(parentTemplate, testURL.string());
2231
2232     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
2233     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
2234     configureSOAuthorizationWebView(webView.get(), delegate.get());
2235
2236     [webView loadHTMLString:testHtml baseURL:(NSURL *)URL(URL(), "http://www.apple.com")];
2237     [webView waitForMessage:@"http://www.example.com"];
2238     [webView waitForMessage:@"SOAuthorizationDidStart"];
2239     checkAuthorizationOptions(false, "http://www.apple.com", 2);
2240 }
2241
2242 TEST(SOAuthorizationSubFrame, SOAuthorizationLoadPolicyIgnore)
2243 {
2244     resetState();
2245     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
2246     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
2247
2248     auto testURL = URL(URL(), "http://www.example.com");
2249     auto testHtml = generateHtml(parentTemplate, testURL.string());
2250
2251     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
2252     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
2253     configureSOAuthorizationWebView(webView.get(), delegate.get());
2254     [delegate setAllowSOAuthorizationLoad:false];
2255
2256     [webView loadHTMLString:testHtml baseURL:(NSURL *)URL(URL(), "http://www.apple.com")];
2257     // Try to wait until the iframe load is finished.
2258     Util::sleep(0.5);
2259     // Make sure we don't intercept the iframe.
2260     EXPECT_FALSE(authorizationPerformed);
2261 }
2262
2263 TEST(SOAuthorizationSubFrame, SOAuthorizationLoadPolicyAllowAsync)
2264 {
2265     resetState();
2266     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
2267     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
2268     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
2269     ClassMethodSwizzler swizzler4([AKAuthorizationController class], @selector(isURLFromAppleOwnedDomain:), reinterpret_cast<IMP>(overrideIsURLFromAppleOwnedDomain));
2270     InstanceMethodSwizzler swizzler5(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
2271
2272     auto testURL = URL(URL(), "http://www.example.com");
2273     auto testHtml = generateHtml(parentTemplate, testURL.string());
2274
2275     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
2276     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
2277     configureSOAuthorizationWebView(webView.get(), delegate.get());
2278     [delegate setIsAsyncExecution:true];
2279
2280     [webView loadHTMLString:testHtml baseURL:nil];
2281     [webView waitForMessage:@"http://www.example.com"];
2282     [webView waitForMessage:@"SOAuthorizationDidStart"];
2283     checkAuthorizationOptions(false, "null", 2);
2284
2285     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:nil]);
2286     auto iframeHtmlCString = generateHtml(iframeTemplate, "").utf8();
2287     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:iframeHtmlCString.data() length:iframeHtmlCString.length()]).get()];
2288     [webView waitForMessage:@"http://www.example.com"];
2289     [webView waitForMessage:@"Hello."];
2290 }
2291
2292 TEST(SOAuthorizationSubFrame, SOAuthorizationLoadPolicyIgnoreAsync)
2293 {
2294     resetState();
2295     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
2296     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
2297
2298     auto testURL = URL(URL(), "http://www.example.com");
2299     auto testHtml = generateHtml(parentTemplate, testURL.string());
2300
2301     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
2302     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
2303     configureSOAuthorizationWebView(webView.get(), delegate.get());
2304     [delegate setAllowSOAuthorizationLoad:false];
2305     [delegate setIsAsyncExecution:true];
2306
2307     [webView loadHTMLString:testHtml baseURL:(NSURL *)URL(URL(), "http://www.apple.com")];
2308     // Try to wait until the iframe load is finished.
2309     Util::sleep(0.5);
2310     // Make sure we don't intercept the iframe.
2311     EXPECT_FALSE(authorizationPerformed);
2312 }
2313
2314 TEST(SOAuthorizationSubFrame, InterceptionErrorWithReferrer)
2315 {
2316     resetState();
2317     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
2318     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
2319     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
2320     ClassMethodSwizzler swizzler4([AKAuthorizationController class], @selector(isURLFromAppleOwnedDomain:), reinterpret_cast<IMP>(overrideIsURLFromAppleOwnedDomain));
2321     InstanceMethodSwizzler swizzler5(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
2322
2323     TCPServer server([parentHtml = generateHtml(parentTemplate, "simple.html"), frameHtml = generateHtml(iframeTemplate, "parent.postMessage('Referrer: ' + document.referrer, '*');")] (int socket) {
2324         NSString *firstResponse = [NSString stringWithFormat:
2325             @"HTTP/1.1 200 OK\r\n"
2326             "Content-Length: %d\r\n\r\n"
2327             "%@",
2328             parentHtml.length(),
2329             (id)parentHtml
2330         ];
2331         NSString *secondResponse = [NSString stringWithFormat:
2332             @"HTTP/1.1 200 OK\r\n"
2333             "Content-Length: %d\r\n\r\n"
2334             "%@",
2335             frameHtml.length(),
2336             (id)frameHtml
2337         ];
2338
2339         TCPServer::read(socket);
2340         TCPServer::write(socket, firstResponse.UTF8String, firstResponse.length);
2341         TCPServer::read(socket);
2342         TCPServer::write(socket, secondResponse.UTF8String, secondResponse.length);
2343     });
2344
2345     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
2346     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
2347     configureSOAuthorizationWebView(webView.get(), delegate.get());
2348
2349     auto origin = makeString("http://127.0.0.1:", static_cast<unsigned>(server.port()));
2350     [webView _loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:(id)origin]] shouldOpenExternalURLs:NO];
2351     [webView waitForMessage:(id)origin];
2352     [webView waitForMessage:@"SOAuthorizationDidStart"];
2353
2354     [gDelegate authorization:gAuthorization didCompleteWithError:adoptNS([[NSError alloc] initWithDomain:NSCocoaErrorDomain code:0 userInfo:nil]).get()];
2355     [webView waitForMessage:(id)origin];
2356     [webView waitForMessage:@"SOAuthorizationDidCancel"];
2357     [webView waitForMessage:(id)makeString("Referrer: ", origin, "/")]; // Referrer policy requires '/' after origin.
2358 }
2359
2360 TEST(SOAuthorizationSubFrame, InterceptionErrorMessageOrder)
2361 {
2362     resetState();
2363     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
2364     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
2365     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
2366     ClassMethodSwizzler swizzler4([AKAuthorizationController class], @selector(isURLFromAppleOwnedDomain:), reinterpret_cast<IMP>(overrideIsURLFromAppleOwnedDomain));
2367     InstanceMethodSwizzler swizzler5(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
2368
2369     RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
2370     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"GetSessionCookie" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
2371     auto testHtml = generateHtml(parentTemplate, testURL.get().absoluteString);
2372
2373     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
2374     auto messageHandler = adoptNS([[TestSOAuthorizationScriptMessageHandler alloc] init]);
2375     [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"testHandler"];
2376
2377     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get()]);
2378     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
2379     configureSOAuthorizationWebView(webView.get(), delegate.get());
2380
2381     [webView loadHTMLString:testHtml baseURL:baseURL.get()];
2382     Util::run(&authorizationPerformed);
2383     [gDelegate authorization:gAuthorization didCompleteWithError:adoptNS([[NSError alloc] initWithDomain:NSCocoaErrorDomain code:0 userInfo:nil]).get()];
2384     Util::run(&allMessagesReceived);
2385 }
2386
2387 TEST(SOAuthorizationSubFrame, InterceptionSuccessMessageOrder)
2388 {
2389     resetState();
2390     ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL));
2391     InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate));
2392     InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL));
2393     ClassMethodSwizzler swizzler4([AKAuthorizationController class], @selector(isURLFromAppleOwnedDomain:), reinterpret_cast<IMP>(overrideIsURLFromAppleOwnedDomain));
2394     InstanceMethodSwizzler swizzler5(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast<IMP>(overrideGetAuthorizationHintsWithURL));
2395
2396     auto testURL = URL(URL(), "http://www.example.com");
2397     auto testHtml = generateHtml(parentTemplate, testURL.string());
2398
2399     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
2400     auto messageHandler = adoptNS([[TestSOAuthorizationScriptMessageHandler alloc] init]);
2401     [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"testHandler"];
2402
2403     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get()]);
2404     auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]);
2405     configureSOAuthorizationWebView(webView.get(), delegate.get());
2406
2407     [webView loadHTMLString:testHtml baseURL:nil];
2408     Util::run(&authorizationPerformed);
2409
2410     auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:nil]);
2411     auto iframeHtmlCString = generateHtml(iframeTemplate, "").utf8();
2412     [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:iframeHtmlCString.data() length:iframeHtmlCString.length()]).get()];
2413     Util::run(&allMessagesReceived);
2414 }
2415
2416 } // namespace TestWebKitAPI
2417
2418 #endif