/* * Copyright (C) 2019-2022 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #import "config.h" #import "Test.h" #if HAVE(APP_SSO) #import "ClassMethodSwizzler.h" #import "HTTPServer.h" #import "InstanceMethodSwizzler.h" #import "PlatformUtilities.h" #import "TestWKWebView.h" #import #import #import #import #import #import #import #import #import #import #import #import #import static bool navigationCompleted = false; static bool policyForAppSSOPerformed = false; static bool authorizationPerformed = false; static bool authorizationCancelled = false; static bool uiShowed = false; static bool newWindowCreated = false; static bool haveHttpBody = false; static bool navigationPolicyDecided = false; static bool allMessagesReceived = false; static String finalURL; static SOAuthorization* gAuthorization; static id gDelegate; #if PLATFORM(MAC) static BlockPtr gNotificationCallback; #endif static RetainPtr gNewWindow; static const char* openerTemplate = "" "" "" ""; static const char* newWindowResponseTemplate = "" "" ""; static const char* parentTemplate = "" "" "" "" ""; static const char* iframeTemplate = "" "" ""; static const char* samlResponse = "" "" ""; @interface TestSOAuthorizationBasicDelegate : NSObject @end @implementation TestSOAuthorizationBasicDelegate - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { EXPECT_FALSE(navigationCompleted); navigationCompleted = true; finalURL = navigation._request.URL.absoluteString; } @end @interface TestSOAuthorizationDelegate : NSObject @property bool isDefaultPolicy; @property bool shouldOpenExternalSchemes; @property bool allowSOAuthorizationLoad; @property bool isAsyncExecution; - (instancetype)init; @end @implementation TestSOAuthorizationDelegate - (instancetype)init { if (self = [super init]) { self.isDefaultPolicy = true; self.shouldOpenExternalSchemes = false; self.allowSOAuthorizationLoad = true; self.isAsyncExecution = false; } return self; } - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { EXPECT_FALSE(navigationCompleted); navigationCompleted = true; finalURL = navigation._request.URL.absoluteString; } - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { navigationPolicyDecided = true; EXPECT_EQ(navigationAction._shouldOpenExternalSchemes, self.shouldOpenExternalSchemes); if (self.isDefaultPolicy) { decisionHandler(WKNavigationActionPolicyAllow); return; } decisionHandler(_WKNavigationActionPolicyAllowWithoutTryingAppLink); } - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures { EXPECT_FALSE(newWindowCreated); newWindowCreated = true; gNewWindow = adoptNS([[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration]); [gNewWindow setNavigationDelegate:self]; return gNewWindow.get(); } - (void)_webView:(WKWebView *)webView decidePolicyForSOAuthorizationLoadWithCurrentPolicy:(_WKSOAuthorizationLoadPolicy)policy forExtension:(NSString *)extension completionHandler:(void (^)(_WKSOAuthorizationLoadPolicy policy))completionHandler { EXPECT_EQ(policy, _WKSOAuthorizationLoadPolicyAllow); EXPECT_TRUE([extension isEqual:@"Test"]); policyForAppSSOPerformed = true; if (!self.isAsyncExecution) { if (self.allowSOAuthorizationLoad) completionHandler(policy); else completionHandler(_WKSOAuthorizationLoadPolicyIgnore); return; } auto allowSOAuthorizationLoad = self.allowSOAuthorizationLoad; dispatch_async(dispatch_get_main_queue(), ^() { if (allowSOAuthorizationLoad) completionHandler(_WKSOAuthorizationLoadPolicyAllow); else completionHandler(_WKSOAuthorizationLoadPolicyIgnore); }); } #if PLATFORM(IOS) - (UIViewController *)_presentingViewControllerForWebView:(WKWebView *)webView { return nil; } #endif @end #if PLATFORM(MAC) @interface TestSOAuthorizationViewController : NSViewController #elif PLATFORM(IOS) @interface TestSOAuthorizationViewController : UIViewController #endif @end @implementation TestSOAuthorizationViewController - (void)viewDidAppear { EXPECT_FALSE(uiShowed); uiShowed = true; } - (void)viewDidDisappear { EXPECT_TRUE(uiShowed); uiShowed = false; } @end @interface TestSOAuthorizationScriptMessageHandler : NSObject @end @implementation TestSOAuthorizationScriptMessageHandler { RetainPtr _messages; RetainPtr _expectedMessages; } - (instancetype)initWithExpectation:(NSArray *)expectedMessages { _messages = adoptNS([[NSMutableArray alloc] init]); _expectedMessages = expectedMessages; return self; } - (void)extendExpectations:(NSArray *)additionalMessages { _expectedMessages = [_expectedMessages arrayByAddingObjectsFromArray:additionalMessages]; allMessagesReceived = false; } - (void)resetExpectations:(NSArray *)expectedMessages { _messages = adoptNS([[NSMutableArray alloc] init]); _expectedMessages = expectedMessages; allMessagesReceived = false; } - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { auto curIndex = [_messages count]; [_messages addObject:message.body]; if ([_messages count] == [_expectedMessages count]) allMessagesReceived = true; if (curIndex < [_expectedMessages count] && [_expectedMessages objectAtIndex:curIndex] != [NSNull null]) EXPECT_WK_STREQ([_expectedMessages objectAtIndex:curIndex], [_messages objectAtIndex:curIndex]); } @end static bool overrideCanPerformAuthorizationWithURL(id, SEL, NSURL *url, NSInteger) { if (![url.lastPathComponent isEqual:@"simple.html"] && ![url.host isEqual:@"www.example.com"] && ![url.lastPathComponent isEqual:@"GetSessionCookie.html"]) return false; return true; } static void overrideSetDelegate(id self, SEL, id delegate) { gAuthorization = self; gDelegate = delegate; } static void overrideBeginAuthorizationWithURL(id, SEL, NSURL *url, NSDictionary *headers, NSData *body) { EXPECT_TRUE(headers != nil); EXPECT_TRUE((body == nil) ^ haveHttpBody); EXPECT_FALSE(authorizationPerformed); authorizationPerformed = true; } static void overrideCancelAuthorization(id, SEL) { EXPECT_FALSE(authorizationCancelled); authorizationCancelled = true; } using GetAuthorizationHintsCallback = void (^)(SOAuthorizationHints *authorizationHints, NSError *error); static void overrideGetAuthorizationHintsWithURL(id, SEL, NSURL *url, NSInteger responseCode, GetAuthorizationHintsCallback completion) { EXPECT_EQ(responseCode, 0l); auto soAuthorizationHintsCore = adoptNS([PAL::allocSOAuthorizationHintsCoreInstance() initWithLocalizedExtensionBundleDisplayName:@"Test"]); auto soAuthorizationHints = adoptNS([PAL::allocSOAuthorizationHintsInstance() initWithAuthorizationHintsCore:soAuthorizationHintsCore.get()]); completion(soAuthorizationHints.get(), nullptr); } #if PLATFORM(MAC) using NotificationCallback = void (^)(NSNotification *note); static id overrideAddObserverForName(id, SEL, NSNotificationName name, id, NSOperationQueue *, NotificationCallback block) { if ([name isEqual:NSWindowWillCloseNotification]) gNotificationCallback = makeBlockPtr(block); return @YES; } #endif static bool overrideIsURLFromAppleOwnedDomain(id, SEL, NSURL *) { return true; } static void resetState() { navigationCompleted = false; policyForAppSSOPerformed = false; authorizationPerformed = false; authorizationCancelled = false; uiShowed = false; newWindowCreated = false; haveHttpBody = false; navigationPolicyDecided = false; allMessagesReceived = false; finalURL = emptyString(); gAuthorization = nullptr; gDelegate = nullptr; #if PLATFORM(MAC) gNotificationCallback = nullptr; #endif gNewWindow = nullptr; } enum class OpenExternalSchemesPolicy : bool { Allow, Disallow }; static void configureSOAuthorizationWebView(TestWKWebView *webView, TestSOAuthorizationDelegate *delegate, OpenExternalSchemesPolicy policy = OpenExternalSchemesPolicy::Disallow) { [webView setNavigationDelegate:delegate]; [webView setUIDelegate:delegate]; delegate.shouldOpenExternalSchemes = policy == OpenExternalSchemesPolicy::Allow; } static String generateHtml(const char* templateHtml, const String& substitute, const String& optionalSubstitute1 = emptyString(), const String& optionalSubstitute2 = emptyString()) { StringPrintStream stream; stream.printf(templateHtml, substitute.utf8().data(), optionalSubstitute1.utf8().data(), optionalSubstitute2.utf8().data()); return stream.toString(); } static void checkAuthorizationOptions(bool userActionInitiated, String initiatorOrigin, int initiatingAction) { EXPECT_TRUE(gAuthorization); EXPECT_EQ(((NSNumber *)[gAuthorization authorizationOptions][SOAuthorizationOptionUserActionInitiated]).boolValue, userActionInitiated); EXPECT_WK_STREQ([gAuthorization authorizationOptions][SOAuthorizationOptionInitiatorOrigin], initiatorOrigin); EXPECT_EQ(((NSNumber *)[gAuthorization authorizationOptions][SOAuthorizationOptionInitiatingAction]).intValue, initiatingAction); } #define SWIZZLE_SOAUTH(SOAuthClass) \ ClassMethodSwizzler swizzler1(SOAuthClass, @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast(overrideCanPerformAuthorizationWithURL)); \ InstanceMethodSwizzler swizzler2(SOAuthClass, @selector(setDelegate:), reinterpret_cast(overrideSetDelegate)); \ InstanceMethodSwizzler swizzler3(SOAuthClass, @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast(overrideBeginAuthorizationWithURL)); \ InstanceMethodSwizzler swizzler4(SOAuthClass, @selector(cancelAuthorization), reinterpret_cast(overrideCancelAuthorization)); \ InstanceMethodSwizzler swizzler5(SOAuthClass, @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast(overrideGetAuthorizationHintsWithURL)); #define SWIZZLE_AKAUTH() \ ClassMethodSwizzler swizzler6([AKAuthorizationController class], @selector(isURLFromAppleOwnedDomain:), reinterpret_cast(overrideIsURLFromAppleOwnedDomain)); \ namespace TestWebKitAPI { TEST(SOAuthorizationRedirect, NoInterceptions) { resetState(); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&navigationCompleted); EXPECT_FALSE(policyForAppSSOPerformed); EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL); } TEST(SOAuthorizationRedirect, DisableSSO) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]); auto preferences = configuration.get().preferences; EXPECT_TRUE(preferences._isExtensibleSSOEnabled); preferences._extensibleSSOEnabled = NO; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get()]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&navigationCompleted); EXPECT_FALSE(policyForAppSSOPerformed); EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL); } TEST(SOAuthorizationRedirect, InterceptionError) { resetState(); // This test relies on us not swizzling most of the SOAuthorizationClass methods. ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast(overrideCanPerformAuthorizationWithURL)); InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(getAuthorizationHintsWithURL:responseCode:completion:), reinterpret_cast(overrideGetAuthorizationHintsWithURL)); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&navigationCompleted); EXPECT_TRUE(policyForAppSSOPerformed); EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL); } TEST(SOAuthorizationRedirect, InterceptionDoNotHandle) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); checkAuthorizationOptions(false, emptyString(), 0); EXPECT_TRUE(policyForAppSSOPerformed); [gDelegate authorizationDidNotHandle:gAuthorization]; Util::run(&navigationCompleted); EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL); } TEST(SOAuthorizationRedirect, InterceptionCancel) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); checkAuthorizationOptions(false, emptyString(), 0); EXPECT_TRUE(policyForAppSSOPerformed); [gDelegate authorizationDidCancel:gAuthorization]; // FIXME: Find a delegate method that can detect load cancels. Util::sleep(0.5); EXPECT_WK_STREQ("", webView.get()._committedURL.absoluteString); } TEST(SOAuthorizationRedirect, InterceptionCompleteWithoutData) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); checkAuthorizationOptions(false, emptyString(), 0); EXPECT_TRUE(policyForAppSSOPerformed); [gDelegate authorizationDidComplete:gAuthorization]; Util::run(&navigationCompleted); EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL); } TEST(SOAuthorizationRedirect, InterceptionUnexpectedCompletion) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); checkAuthorizationOptions(false, emptyString(), 0); EXPECT_TRUE(policyForAppSSOPerformed); [gDelegate authorization:gAuthorization didCompleteWithHTTPAuthorizationHeaders:adoptNS([[NSDictionary alloc] init]).get()]; Util::run(&navigationCompleted); EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL); } // { Default delegate method, No App Links } TEST(SOAuthorizationRedirect, InterceptionSucceed1) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationBasicDelegate alloc] init]); [webView setNavigationDelegate:delegate.get()]; [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); checkAuthorizationOptions(false, emptyString(), 0); EXPECT_FALSE(policyForAppSSOPerformed); // The delegate isn't registered, so this won't be set. #if PLATFORM(MAC) EXPECT_TRUE(gAuthorization.enableEmbeddedAuthorizationViewController); #elif PLATFORM(IOS) EXPECT_FALSE(gAuthorization.enableEmbeddedAuthorizationViewController); #endif RetainPtr redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]); [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()]; Util::run(&navigationCompleted); #if PLATFORM(IOS) navigationCompleted = false; Util::run(&navigationCompleted); #endif EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL); } // { Default delegate method, With App Links } TEST(SOAuthorizationRedirect, InterceptionSucceed2) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationBasicDelegate alloc] init]); [webView setNavigationDelegate:delegate.get()]; // Force App Links with a request.URL that has a different host than the current one (empty host) and ShouldOpenExternalURLsPolicy::ShouldAllow. URL testURL { "https://www.example.com"_str }; #if PLATFORM(MAC) [webView _loadRequest:[NSURLRequest requestWithURL:testURL] shouldOpenExternalURLs:YES]; #elif PLATFORM(IOS) // Here we force RedirectSOAuthorizationSession to go to the with user gestures route. [webView evaluateJavaScript: [NSString stringWithFormat:@"location = '%@'", (id)testURL.string()] completionHandler:nil]; #endif Util::run(&authorizationPerformed); #if PLATFORM(MAC) checkAuthorizationOptions(false, emptyString(), 0); #elif PLATFORM(IOS) checkAuthorizationOptions(true, "null"_s, 0); #endif EXPECT_FALSE(policyForAppSSOPerformed); // The delegate isn't registered, so this won't be set. RetainPtr redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]); [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()]; Util::run(&navigationCompleted); EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL); } // { Custom delegate method, With App Links } TEST(SOAuthorizationRedirect, InterceptionSucceed3) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); // Force App Links with a request.URL that has a different host than the current one (empty host) and ShouldOpenExternalURLsPolicy::ShouldAllow. URL testURL { "https://www.example.com"_str }; #if PLATFORM(MAC) [webView _loadRequest:[NSURLRequest requestWithURL:testURL] shouldOpenExternalURLs:YES]; #elif PLATFORM(IOS) // Here we force RedirectSOAuthorizationSession to go to the with user gestures route. [webView evaluateJavaScript: [NSString stringWithFormat:@"location = '%@'", (id)testURL.string()] completionHandler:nil]; #endif Util::run(&authorizationPerformed); EXPECT_TRUE(gAuthorization.enableEmbeddedAuthorizationViewController); #if PLATFORM(MAC) checkAuthorizationOptions(false, emptyString(), 0); #elif PLATFORM(IOS) checkAuthorizationOptions(true, "null"_s, 0); #endif EXPECT_TRUE(policyForAppSSOPerformed); RetainPtr redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]); [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()]; Util::run(&navigationCompleted); EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL); } // { _WKNavigationActionPolicyAllowWithoutTryingAppLink, No App Links } TEST(SOAuthorizationRedirect, InterceptionSucceed4) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); // A separate delegate that implements decidePolicyForNavigationAction. auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [delegate setIsDefaultPolicy:false]; [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); checkAuthorizationOptions(false, emptyString(), 0); EXPECT_TRUE(policyForAppSSOPerformed); RetainPtr redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]); [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()]; Util::run(&navigationCompleted); #if PLATFORM(IOS) navigationCompleted = false; Util::run(&navigationCompleted); #endif EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL); } TEST(SOAuthorizationRedirect, InterceptionSucceedWithOtherHttpStatusCode) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); checkAuthorizationOptions(false, emptyString(), 0); EXPECT_TRUE(policyForAppSSOPerformed); RetainPtr redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:400 HTTPVersion:@"HTTP/1.1" headerFields:nil]); [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()]; Util::run(&navigationCompleted); EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL); } TEST(SOAuthorizationRedirect, InterceptionSucceedWithCookie) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); checkAuthorizationOptions(false, emptyString(), 0); EXPECT_TRUE(policyForAppSSOPerformed); RetainPtr redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Set-Cookie" : @"sessionid=38afes7a8;", @"Location" : [redirectURL absoluteString] }]); [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()]; Util::run(&navigationCompleted); #if PLATFORM(IOS) navigationCompleted = false; Util::run(&navigationCompleted); #endif EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL); navigationCompleted = false; [webView evaluateJavaScript: @"document.cookie" completionHandler:^(NSString *result, NSError *) { EXPECT_WK_STREQ("sessionid=38afes7a8", [result UTF8String]); navigationCompleted = true; }]; Util::run(&navigationCompleted); } TEST(SOAuthorizationRedirect, InterceptionSucceedWithCookies) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); checkAuthorizationOptions(false, emptyString(), 0); EXPECT_TRUE(policyForAppSSOPerformed); RetainPtr redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; 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] }]); [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()]; Util::run(&navigationCompleted); #if PLATFORM(IOS) navigationCompleted = false; Util::run(&navigationCompleted); #endif EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL); navigationCompleted = false; [webView evaluateJavaScript: @"document.cookie" completionHandler:^(NSString *result, NSError *) { EXPECT_WK_STREQ("id=a3fWa; qwerty=219ffwef9w0f; sessionid=38afes7a8", [result UTF8String]); navigationCompleted = true; }]; Util::run(&navigationCompleted); } // The redirected URL has a different domain than the test URL. TEST(SOAuthorizationRedirect, InterceptionSucceedWithRedirectionAndCookie) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); URL testURL { "https://www.example.com"_str }; #if PLATFORM(MAC) [webView loadRequest:[NSURLRequest requestWithURL:testURL]]; #elif PLATFORM(IOS) // Here we force RedirectSOAuthorizationSession to go to the with user gestures route. [webView evaluateJavaScript: [NSString stringWithFormat:@"location = '%@'", (id)testURL.string()] completionHandler:nil]; #endif Util::run(&authorizationPerformed); #if PLATFORM(MAC) checkAuthorizationOptions(false, emptyString(), 0); #elif PLATFORM(IOS) checkAuthorizationOptions(true, "null"_s, 0); #endif EXPECT_TRUE(policyForAppSSOPerformed); RetainPtr redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Set-Cookie" : @"sessionid=38afes7a8;", @"Location" : [redirectURL absoluteString] }]); [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()]; Util::run(&navigationCompleted); EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL); navigationCompleted = false; [webView evaluateJavaScript: @"document.cookie" completionHandler:^(NSString *result, NSError *) { EXPECT_WK_STREQ("", [result UTF8String]); navigationCompleted = true; }]; Util::run(&navigationCompleted); } TEST(SOAuthorizationRedirect, InterceptionSucceedWithDifferentOrigin) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); checkAuthorizationOptions(false, emptyString(), 0); EXPECT_TRUE(policyForAppSSOPerformed); URL redirectURL { "https://www.example.com"_str }; auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:redirectURL statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : redirectURL.string() }]); [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()]; Util::run(&navigationCompleted); EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL); } TEST(SOAuthorizationRedirect, InterceptionSucceedWithWaitingSession) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); // The session will be waiting since the web view is is not in the window. [webView removeFromSuperview]; [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&navigationPolicyDecided); EXPECT_FALSE(policyForAppSSOPerformed); EXPECT_FALSE(authorizationPerformed); // Should activate the session. [webView addToTestWindow]; Util::run(&authorizationPerformed); checkAuthorizationOptions(false, emptyString(), 0); EXPECT_TRUE(policyForAppSSOPerformed); RetainPtr redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]); [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()]; Util::run(&navigationCompleted); #if PLATFORM(IOS) navigationCompleted = false; Util::run(&navigationCompleted); #endif EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL); } TEST(SOAuthorizationRedirect, InterceptionAbortedWithWaitingSession) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL1 = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; RetainPtr testURL2 = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); // The session will be waiting since the web view is is not in the window. [webView removeFromSuperview]; [webView loadRequest:[NSURLRequest requestWithURL:testURL1.get()]]; Util::run(&navigationPolicyDecided); EXPECT_FALSE(policyForAppSSOPerformed); EXPECT_FALSE(authorizationPerformed); [webView loadRequest:[NSURLRequest requestWithURL:testURL2.get()]]; // Should activate the session. [webView addToTestWindow]; // The waiting session should be aborted as the previous navigation is overwritten by a new navigation. Util::run(&navigationCompleted); EXPECT_FALSE(policyForAppSSOPerformed); EXPECT_FALSE(authorizationPerformed); } TEST(SOAuthorizationRedirect, InterceptionSucceedWithActiveSessionDidMoveWindow) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); checkAuthorizationOptions(false, emptyString(), 0); EXPECT_TRUE(policyForAppSSOPerformed); // Should be a no op. [webView addToTestWindow]; RetainPtr redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]); [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()]; Util::run(&navigationCompleted); #if PLATFORM(IOS) navigationCompleted = false; Util::run(&navigationCompleted); #endif EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL); } TEST(SOAuthorizationRedirect, InterceptionSucceedTwice) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); for (int i = 0; i < 2; i++) { authorizationPerformed = false; policyForAppSSOPerformed = false; [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); checkAuthorizationOptions(false, emptyString(), 0); EXPECT_TRUE(policyForAppSSOPerformed); navigationCompleted = false; RetainPtr redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]); [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()]; Util::run(&navigationCompleted); #if PLATFORM(IOS) navigationCompleted = false; Util::run(&navigationCompleted); #endif EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL); } } TEST(SOAuthorizationRedirect, InterceptionSucceedSuppressActiveSession) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); checkAuthorizationOptions(false, emptyString(), 0); EXPECT_TRUE(policyForAppSSOPerformed); // Suppress the last active session. authorizationPerformed = false; policyForAppSSOPerformed = false; [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationCancelled); Util::run(&authorizationPerformed); checkAuthorizationOptions(false, emptyString(), 0); EXPECT_TRUE(policyForAppSSOPerformed); RetainPtr redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]); [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()]; Util::run(&navigationCompleted); #if PLATFORM(IOS) navigationCompleted = false; Util::run(&navigationCompleted); #endif EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL); } TEST(SOAuthorizationRedirect, InterceptionSucceedSuppressWaitingSession) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); // The session will be waiting since the web view is is not int the window. [webView removeFromSuperview]; [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&navigationPolicyDecided); EXPECT_FALSE(authorizationPerformed); EXPECT_FALSE(policyForAppSSOPerformed); // Suppress the last waiting session. navigationPolicyDecided = false; [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&navigationPolicyDecided); EXPECT_FALSE(authorizationPerformed); EXPECT_FALSE(policyForAppSSOPerformed); // Activate the last session. [webView addToTestWindow]; Util::run(&authorizationPerformed); checkAuthorizationOptions(false, emptyString(), 0); EXPECT_TRUE(policyForAppSSOPerformed); RetainPtr redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]); [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()]; Util::run(&navigationCompleted); #if PLATFORM(IOS) navigationCompleted = false; Util::run(&navigationCompleted); #endif EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL); } TEST(SOAuthorizationRedirect, InterceptionSucceedSAML) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]); auto messageHandler = adoptNS([[TestSOAuthorizationScriptMessageHandler alloc] initWithExpectation:@[@"SAML"]]); [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"testHandler"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get()]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); // Add a http body to the request to mimic a SAML request. auto request = adoptNS([NSMutableURLRequest requestWithURL:testURL.get()]); [request setHTTPBody:adoptNS([[NSData alloc] init]).get()]; haveHttpBody = true; [webView loadRequest:request.get()]; Util::run(&authorizationPerformed); checkAuthorizationOptions(false, emptyString(), 0); EXPECT_TRUE(policyForAppSSOPerformed); // Pass a HTTP 200 response with a html to mimic a SAML response. auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:nil]); [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:samlResponse length:strlen(samlResponse)]).get()]; Util::run(&allMessagesReceived); } TEST(SOAuthorizationRedirect, InterceptionSucceedSAMLWithPSON) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr baseURL = [[NSBundle mainBundle] URLForResource:@"simple3" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; URL testURL { "http://www.example.com"_str }; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:baseURL.get()]]; Util::run(&navigationCompleted); // PSON: file:/// => example.com [webView loadRequest:[NSURLRequest requestWithURL:(NSURL *)testURL]]; Util::run(&authorizationPerformed); EXPECT_TRUE(policyForAppSSOPerformed); navigationCompleted = false; // Pass a HTTP 200 response with a html to mimic a SAML response. auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:(NSURL *)testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:nil]); [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:samlResponse length:strlen(samlResponse)]).get()]; Util::run(&navigationCompleted); authorizationPerformed = false; navigationPolicyDecided = false; policyForAppSSOPerformed = false; [webView _evaluateJavaScriptWithoutUserGesture:@"location = 'http://www.example.com'" completionHandler:nil]; Util::run(&navigationPolicyDecided); EXPECT_TRUE(policyForAppSSOPerformed); } TEST(SOAuthorizationRedirect, AuthorizationOptions) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get()); [webView loadHTMLString:@"" baseURL:(NSURL *)URL { "http://www.webkit.org"_str }]; Util::run(&navigationCompleted); [delegate setShouldOpenExternalSchemes:true]; [webView evaluateJavaScript: @"location = 'http://www.example.com'" completionHandler:nil]; Util::run(&authorizationPerformed); checkAuthorizationOptions(true, "http://www.webkit.org"_s, 0); EXPECT_TRUE(policyForAppSSOPerformed); } TEST(SOAuthorizationRedirect, InterceptionDidNotHandleTwice) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); EXPECT_TRUE(policyForAppSSOPerformed); // Test passes if no crashes. [gDelegate authorizationDidNotHandle:gAuthorization]; [gDelegate authorizationDidNotHandle:gAuthorization]; } TEST(SOAuthorizationRedirect, InterceptionCompleteTwice) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); EXPECT_TRUE(policyForAppSSOPerformed); // Test passes if no crashes. RetainPtr redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]); [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()]; [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()]; } TEST(SOAuthorizationRedirect, SOAuthorizationLoadPolicyIgnore) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [delegate setAllowSOAuthorizationLoad:false]; [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&navigationCompleted); EXPECT_TRUE(policyForAppSSOPerformed); EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL); } TEST(SOAuthorizationRedirect, SOAuthorizationLoadPolicyAllowAsync) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); checkAuthorizationOptions(false, ""_s, 0); EXPECT_TRUE(policyForAppSSOPerformed); RetainPtr redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]); [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()]; Util::run(&navigationCompleted); #if PLATFORM(IOS) navigationCompleted = false; Util::run(&navigationCompleted); #endif EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL); } TEST(SOAuthorizationRedirect, SOAuthorizationLoadPolicyIgnoreAsync) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [delegate setAllowSOAuthorizationLoad:false]; [delegate setIsAsyncExecution:true]; [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&navigationCompleted); EXPECT_TRUE(policyForAppSSOPerformed); EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL); } // FIXME(175204): Enable the iOS tests once the bug is fixed. #if PLATFORM(MAC) TEST(SOAuthorizationRedirect, InterceptionSucceedWithUI) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); EXPECT_TRUE(policyForAppSSOPerformed); auto viewController = adoptNS([[TestSOAuthorizationViewController alloc] init]); auto view = adoptNS([[NSView alloc] initWithFrame:NSZeroRect]); [viewController setView:view.get()]; [gDelegate authorization:gAuthorization presentViewController:viewController.get() withCompletion:^(BOOL success, NSError *) { EXPECT_TRUE(success); }]; Util::run(&uiShowed); RetainPtr redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]); [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()]; Util::run(&navigationCompleted); EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL); EXPECT_FALSE(uiShowed); } TEST(SOAuthorizationRedirect, InterceptionCancelWithUI) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); EXPECT_TRUE(policyForAppSSOPerformed); auto viewController = adoptNS([[TestSOAuthorizationViewController alloc] init]); auto view = adoptNS([[NSView alloc] initWithFrame:NSZeroRect]); [viewController setView:view.get()]; [gDelegate authorization:gAuthorization presentViewController:viewController.get() withCompletion:^(BOOL success, NSError *) { EXPECT_TRUE(success); }]; Util::run(&uiShowed); [gDelegate authorizationDidCancel:gAuthorization]; // FIXME: Find a delegate method that can detect load cancels. Util::sleep(0.5); EXPECT_WK_STREQ("", webView.get()._committedURL.absoluteString); EXPECT_FALSE(uiShowed); } TEST(SOAuthorizationRedirect, InterceptionErrorWithUI) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); EXPECT_TRUE(policyForAppSSOPerformed); auto viewController = adoptNS([[TestSOAuthorizationViewController alloc] init]); auto view = adoptNS([[NSView alloc] initWithFrame:NSZeroRect]); [viewController setView:view.get()]; [gDelegate authorization:gAuthorization presentViewController:viewController.get() withCompletion:^(BOOL success, NSError *) { EXPECT_TRUE(success); }]; Util::run(&uiShowed); [gDelegate authorization:gAuthorization didCompleteWithError:adoptNS([[NSError alloc] initWithDomain:NSCocoaErrorDomain code:0 userInfo:nil]).get()]; Util::run(&navigationCompleted); EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL); EXPECT_FALSE(uiShowed); } TEST(SOAuthorizationRedirect, InterceptionSucceedSuppressActiveSessionWithUI) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); EXPECT_TRUE(policyForAppSSOPerformed); auto viewController = adoptNS([[TestSOAuthorizationViewController alloc] init]); auto view = adoptNS([[NSView alloc] initWithFrame:NSZeroRect]); [viewController setView:view.get()]; [gDelegate authorization:gAuthorization presentViewController:viewController.get() withCompletion:^(BOOL success, NSError *) { EXPECT_TRUE(success); }]; Util::run(&uiShowed); // Suppress the last active session. authorizationPerformed = false; [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationCancelled); EXPECT_TRUE(policyForAppSSOPerformed); Util::run(&authorizationPerformed); EXPECT_FALSE(uiShowed); RetainPtr redirectURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:302 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Location" : [redirectURL absoluteString] }]); [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] init]).get()]; Util::run(&navigationCompleted); EXPECT_WK_STREQ(redirectURL.get().absoluteString, finalURL); } TEST(SOAuthorizationRedirect, ShowUITwice) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); EXPECT_TRUE(policyForAppSSOPerformed); auto viewController = adoptNS([[TestSOAuthorizationViewController alloc] init]); auto view = adoptNS([[NSView alloc] initWithFrame:NSZeroRect]); [viewController setView:view.get()]; [gDelegate authorization:gAuthorization presentViewController:viewController.get() withCompletion:^(BOOL success, NSError *) { EXPECT_TRUE(success); }]; Util::run(&uiShowed); uiShowed = false; [gDelegate authorization:gAuthorization presentViewController:viewController.get() withCompletion:^(BOOL success, NSError *error) { EXPECT_FALSE(success); EXPECT_EQ(error.code, kSOErrorAuthorizationPresentationFailed); EXPECT_WK_STREQ(error.domain, "com.apple.AppSSO.AuthorizationError"); uiShowed = true; }]; Util::run(&uiShowed); } #endif #if PLATFORM(MAC) TEST(SOAuthorizationRedirect, NSNotificationCenter) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); EXPECT_TRUE(policyForAppSSOPerformed); auto viewController = adoptNS([[TestSOAuthorizationViewController alloc] init]); auto view = adoptNS([[NSView alloc] initWithFrame:NSZeroRect]); { InstanceMethodSwizzler swizzler4([NSNotificationCenter class], @selector(addObserverForName:object:queue:usingBlock:), reinterpret_cast(overrideAddObserverForName)); [viewController setView:view.get()]; [gDelegate authorization:gAuthorization presentViewController:viewController.get() withCompletion:^(BOOL success, NSError *) { EXPECT_TRUE(success); }]; Util::run(&uiShowed); } gNotificationCallback(nullptr); EXPECT_FALSE(uiShowed); } TEST(SOAuthorizationRedirect, DismissUIDuringMiniaturization) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); EXPECT_TRUE(policyForAppSSOPerformed); auto viewController = adoptNS([[TestSOAuthorizationViewController alloc] init]); auto view = adoptNS([[NSView alloc] initWithFrame:NSZeroRect]); [viewController setView:view.get()]; [gDelegate authorization:gAuthorization presentViewController:viewController.get() withCompletion:^(BOOL success, NSError *) { EXPECT_TRUE(success); }]; Util::run(&uiShowed); bool didEndSheet = false; auto *hostWindow = [webView hostWindow]; auto observer = adoptNS([[NSNotificationCenter defaultCenter] addObserverForName:NSWindowDidEndSheetNotification object:hostWindow queue:nil usingBlock:[&didEndSheet] (NSNotification *) { didEndSheet = true; }]); [hostWindow miniaturize:hostWindow]; // Dimiss the UI [gDelegate authorizationDidCancel:gAuthorization]; EXPECT_FALSE(didEndSheet); // UI is only dimissed after the hostWindow is deminimized. [hostWindow deminiaturize:hostWindow]; EXPECT_TRUE(didEndSheet); } TEST(SOAuthorizationRedirect, DismissUIDuringHiding) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); EXPECT_TRUE(policyForAppSSOPerformed); auto viewController = adoptNS([[TestSOAuthorizationViewController alloc] init]); auto view = adoptNS([[NSView alloc] initWithFrame:NSZeroRect]); [viewController setView:view.get()]; [gDelegate authorization:gAuthorization presentViewController:viewController.get() withCompletion:^(BOOL success, NSError *) { EXPECT_TRUE(success); }]; Util::run(&uiShowed); bool didEndSheet = false; auto observer = adoptNS([[NSNotificationCenter defaultCenter] addObserverForName:NSWindowDidEndSheetNotification object:[webView hostWindow] queue:nil usingBlock:[&didEndSheet] (NSNotification *) { didEndSheet = true; }]); [NSApp hide:NSApp]; // Dimiss the UI [gDelegate authorizationDidCancel:gAuthorization]; EXPECT_FALSE(didEndSheet); // UI is only dimissed after the hostApp is unhidden. [NSApp unhide:NSApp]; EXPECT_TRUE(didEndSheet); } TEST(SOAuthorizationRedirect, DismissUIDuringMiniaturizationThenAnother) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); EXPECT_TRUE(policyForAppSSOPerformed); auto viewController1 = adoptNS([[TestSOAuthorizationViewController alloc] init]); auto view1 = adoptNS([[NSView alloc] initWithFrame:NSZeroRect]); [viewController1 setView:view1.get()]; [gDelegate authorization:gAuthorization presentViewController:viewController1.get() withCompletion:^(BOOL success, NSError *) { EXPECT_TRUE(success); }]; Util::run(&uiShowed); bool didEndSheet = false; auto *hostWindow = [webView hostWindow]; auto observer = adoptNS([[NSNotificationCenter defaultCenter] addObserverForName:NSWindowDidEndSheetNotification object:hostWindow queue:nil usingBlock:[&didEndSheet] (NSNotification *) { didEndSheet = true; }]); [hostWindow miniaturize:hostWindow]; // Dimiss the UI [gDelegate authorizationDidCancel:gAuthorization]; EXPECT_FALSE(didEndSheet); // Load another AppSSO request. authorizationPerformed = false; policyForAppSSOPerformed = false; [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); EXPECT_TRUE(policyForAppSSOPerformed); // UI is only dimissed after the hostApp is unhidden. [hostWindow deminiaturize:hostWindow]; EXPECT_TRUE(didEndSheet); } TEST(SOAuthorizationRedirect, DismissUIDuringHidingThenAnother) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get(), OpenExternalSchemesPolicy::Allow); [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); EXPECT_TRUE(policyForAppSSOPerformed); auto viewController = adoptNS([[TestSOAuthorizationViewController alloc] init]); auto view = adoptNS([[NSView alloc] initWithFrame:NSZeroRect]); [viewController setView:view.get()]; [gDelegate authorization:gAuthorization presentViewController:viewController.get() withCompletion:^(BOOL success, NSError *) { EXPECT_TRUE(success); }]; Util::run(&uiShowed); bool didEndSheet = false; auto observer = adoptNS([[NSNotificationCenter defaultCenter] addObserverForName:NSWindowDidEndSheetNotification object:[webView hostWindow] queue:nil usingBlock:[&didEndSheet] (NSNotification *) { didEndSheet = true; }]); [NSApp hide:NSApp]; // Dimiss the UI [gDelegate authorizationDidCancel:gAuthorization]; EXPECT_FALSE(didEndSheet); // Load another AppSSO request. authorizationPerformed = false; policyForAppSSOPerformed = false; [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; Util::run(&authorizationPerformed); EXPECT_TRUE(policyForAppSSOPerformed); // UI is only dimissed after the hostApp is unhidden. [NSApp unhide:NSApp]; EXPECT_TRUE(didEndSheet); } #endif TEST(SOAuthorizationPopUp, NoInterceptions) { resetState(); RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto testHtml = generateHtml(openerTemplate, testURL.get().absoluteString); auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]); auto delegate = adoptNS([[TestSOAuthorizationDelegate alloc] init]); configureSOAuthorizationWebView(webView.get(), delegate.get()); [webView loadHTMLString:testHtml baseURL:testURL.get()]; Util::run(&navigationCompleted); [delegate setShouldOpenExternalSchemes:true]; navigationCompleted = false; #if PLATFORM(MAC) [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1]; #elif PLATFORM(IOS) [webView evaluateJavaScript: @"clickMe()" completionHandler:nil]; #endif Util::run(&newWindowCreated); Util::run(&navigationCompleted); EXPECT_FALSE(policyForAppSSOPerformed); EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL); } // FIXME(172614): Enable the following test for iOS once the bug is fixed. #if PLATFORM(MAC) TEST(SOAuthorizationPopUp, NoInterceptionsSubFrame) { resetState(); SWIZZLE_SOAUTH(PAL::getSOAuthorizationClass()); RetainPtr baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; RetainPtr testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; auto iframeTestHtml = generateHtml(openerTemplate, testURL.get().absoluteString); auto testHtml = makeString("