WebKit Bugzilla
Attachment 372158 Details for
Bug 198874
: Move SOAuthorization from WebKitAdditions to WebKit
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-198874-20190614175333.patch (text/plain), 230.69 KB, created by
Jiewen Tan
on 2019-06-14 17:53:34 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Jiewen Tan
Created:
2019-06-14 17:53:34 PDT
Size:
230.69 KB
patch
obsolete
>Subversion Revision: 246446 >diff --git a/Source/WTF/ChangeLog b/Source/WTF/ChangeLog >index edf2cefd4c57477779414273caccbe94f929a621..a5f229e6a167d736c947082725347665af1bef27 100644 >--- a/Source/WTF/ChangeLog >+++ b/Source/WTF/ChangeLog >@@ -1,3 +1,14 @@ >+2019-06-14 Jiewen Tan <jiewen_tan@apple.com> >+ >+ Move SOAuthorization from WebKitAdditions to WebKit >+ https://bugs.webkit.org/show_bug.cgi?id=198874 >+ <rdar://problem/47573431> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * wtf/Platform.h: >+ Adds a feature flag to detect AppSSO framework. >+ > 2019-06-12 Antoine Quint <graouts@apple.com> > > Show the web page URL when sharing an AR model >diff --git a/Source/WebCore/PAL/ChangeLog b/Source/WebCore/PAL/ChangeLog >index ee05678236157dcf1dad507e67340eab43d644a0..12bc9bd433e2fe4e83a67de3ac7e4ee922d5826b 100644 >--- a/Source/WebCore/PAL/ChangeLog >+++ b/Source/WebCore/PAL/ChangeLog >@@ -1,3 +1,20 @@ >+2019-06-14 Jiewen Tan <jiewen_tan@apple.com> >+ >+ Move SOAuthorization from WebKitAdditions to WebKit >+ https://bugs.webkit.org/show_bug.cgi?id=198874 >+ <rdar://problem/47573431> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This patch moves AppSSOSoftLink from WebKitAdditions to WebKit, and introduces >+ AuthKitSPI.h. >+ >+ * PAL.xcodeproj/project.pbxproj: >+ * pal/cocoa/AppSSOSoftLink.h: Copied from Tools/TestWebKitAPI/Tests/WebKitCocoa/TestLoadOptimizer.mm. >+ * pal/cocoa/AppSSOSoftLink.mm: Copied from Tools/TestWebKitAPI/Tests/WebKitCocoa/TestLoadOptimizer.mm. >+ * pal/spi/cf/CFNetworkSPI.h: >+ * pal/spi/cocoa/AuthKitSPI.h: Copied from Tools/TestWebKitAPI/Tests/WebKitCocoa/TestLoadOptimizer.mm. >+ > 2019-06-14 Jiewen Tan <jiewen_tan@apple.com> > > Disable AppSSO for web processes and plugin processes >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index f8e3b01c66af75dec1122097bb3fd2b8183dd94a..53c331ce716edd070904bad009dec8d768e03535 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,114 @@ >+2019-06-14 Jiewen Tan <jiewen_tan@apple.com> >+ >+ Move SOAuthorization from WebKitAdditions to WebKit >+ https://bugs.webkit.org/show_bug.cgi?id=198874 >+ <rdar://problem/47573431> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This patch basically moves everything from existing WebKitAdditions to WebKit. >+ Besides, it replaces all the load optimizer nonsenses with SOAuthorization. >+ >+ * Configurations/WebKit.xcconfig: >+ * NetworkProcess/cocoa/NetworkSessionCocoa.mm: >+ (WebKit::NetworkSessionCocoa::NetworkSessionCocoa): >+ * PluginProcess/mac/PluginProcessMac.mm: >+ (WebKit::PluginProcess::platformInitializePluginProcess): >+ * SourcesCocoa.txt: >+ * UIProcess/API/APINavigationAction.h: >+ * UIProcess/Cocoa/NavigationState.mm: >+ (WebKit::trySOAuthorization): >+ (WebKit::tryInterceptNavigation): >+ (WebKit::NavigationState::NavigationClient::decidePolicyForNavigationAction): >+ (WebKit::tryOptimizingLoad): Deleted. >+ * UIProcess/Cocoa/SOAuthorization/NavigationSOAuthorizationSession.h: Added. >+ (WebKit::NavigationSOAuthorizationSession::callback): >+ * UIProcess/Cocoa/SOAuthorization/NavigationSOAuthorizationSession.mm: Copied from Tools/TestWebKitAPI/Tests/WebKitCocoa/TestLoadOptimizer.mm. >+ (WebKit::NavigationSOAuthorizationSession::NavigationSOAuthorizationSession): >+ (WebKit::NavigationSOAuthorizationSession::~NavigationSOAuthorizationSession): >+ (WebKit::NavigationSOAuthorizationSession::shouldStartInternal): >+ (WebKit::NavigationSOAuthorizationSession::webViewDidMoveToWindow): >+ * UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h: Added. >+ * UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.mm: Added. >+ (-[WKSOSecretDelegate initWithSession:]): >+ (-[WKSOSecretDelegate webViewDidClose:]): >+ (-[WKSOSecretDelegate webView:decidePolicyForNavigationAction:decisionHandler:]): >+ (-[WKSOSecretDelegate webView:didFinishNavigation:]): >+ (WebKit::PopUpSOAuthorizationSession::PopUpSOAuthorizationSession): >+ (WebKit::PopUpSOAuthorizationSession::~PopUpSOAuthorizationSession): >+ (WebKit::PopUpSOAuthorizationSession::shouldStartInternal): >+ (WebKit::PopUpSOAuthorizationSession::fallBackToWebPathInternal): >+ (WebKit::PopUpSOAuthorizationSession::abortInternal): >+ (WebKit::PopUpSOAuthorizationSession::completeInternal): >+ (WebKit::PopUpSOAuthorizationSession::close): >+ (WebKit::PopUpSOAuthorizationSession::initSecretWebView): >+ * UIProcess/Cocoa/SOAuthorization/RedirectSOAuthorizationSession.h: Copied from Tools/TestWebKitAPI/Tests/WebKitCocoa/TestLoadOptimizer.mm. >+ * UIProcess/Cocoa/SOAuthorization/RedirectSOAuthorizationSession.mm: Added. >+ (WebKit::RedirectSOAuthorizationSession::RedirectSOAuthorizationSession): >+ (WebKit::RedirectSOAuthorizationSession::fallBackToWebPathInternal): >+ (WebKit::RedirectSOAuthorizationSession::abortInternal): >+ (WebKit::RedirectSOAuthorizationSession::completeInternal): >+ (WebKit::RedirectSOAuthorizationSession::beforeStart): >+ * UIProcess/Cocoa/SOAuthorization/SOAuthorizationCoordinator.h: Copied from Tools/TestWebKitAPI/Tests/WebKitCocoa/TestLoadOptimizer.mm. >+ * UIProcess/Cocoa/SOAuthorization/SOAuthorizationCoordinator.mm: Added. >+ (WebKit::SOAuthorizationCoordinator::SOAuthorizationCoordinator): >+ (WebKit::SOAuthorizationCoordinator::canAuthorize const): >+ (WebKit::SOAuthorizationCoordinator::tryAuthorize): >+ * UIProcess/Cocoa/SOAuthorization/SOAuthorizationNSURLExtras.h: Copied from Tools/TestWebKitAPI/Tests/WebKitCocoa/TestLoadOptimizer.mm. >+ * UIProcess/Cocoa/SOAuthorization/SOAuthorizationNSURLExtras.mm: Copied from Tools/TestWebKitAPI/Tests/WebKitCocoa/TestLoadOptimizer.mm. >+ (+[NSURL _web_canPerformAuthorizationWithURL:]): >+ * UIProcess/Cocoa/SOAuthorization/SOAuthorizationSession.h: Added. >+ (WebKit::SOAuthorizationSession::page const): >+ (WebKit::SOAuthorizationSession::state const): >+ (WebKit::SOAuthorizationSession::setState): >+ (WebKit::SOAuthorizationSession::navigationAction): >+ * UIProcess/Cocoa/SOAuthorization/SOAuthorizationSession.mm: Added. >+ (WebKit::SOAuthorizationSession::SOAuthorizationSession): >+ (WebKit::SOAuthorizationSession::~SOAuthorizationSession): >+ (WebKit::SOAuthorizationSession::releaseNavigationAction): >+ (WebKit::SOAuthorizationSession::becomeCompleted): >+ (WebKit::SOAuthorizationSession::shouldStart): >+ (WebKit::SOAuthorizationSession::start): >+ (WebKit::SOAuthorizationSession::fallBackToWebPath): >+ (WebKit::SOAuthorizationSession::abort): >+ (WebKit::SOAuthorizationSession::complete): >+ (WebKit::SOAuthorizationSession::presentViewController): >+ (WebKit::SOAuthorizationSession::dismissViewController): >+ * UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.h: Copied from Tools/TestWebKitAPI/Tests/WebKitCocoa/TestLoadOptimizer.mm. >+ * UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.mm: Added. >+ (WebKit::SubFrameSOAuthorizationSession::SubFrameSOAuthorizationSession): >+ (WebKit::SubFrameSOAuthorizationSession::fallBackToWebPathInternal): >+ (WebKit::SubFrameSOAuthorizationSession::abortInternal): >+ (WebKit::SubFrameSOAuthorizationSession::completeInternal): >+ (WebKit::SubFrameSOAuthorizationSession::beforeStart): >+ (WebKit::SubFrameSOAuthorizationSession::loadDataToFrame): >+ (WebKit::SubFrameSOAuthorizationSession::postDidCancelMessageToParent): >+ * UIProcess/Cocoa/SOAuthorization/WKSOAuthorizationDelegate.h: Renamed from Tools/TestWebKitAPI/Tests/WebKitCocoa/TestLoadOptimizer.mm. >+ * UIProcess/Cocoa/SOAuthorization/WKSOAuthorizationDelegate.mm: Added. >+ (-[WKSOAuthorizationDelegate authorization:presentViewController:withCompletion:]): >+ (-[WKSOAuthorizationDelegate authorizationDidNotHandle:]): >+ (-[WKSOAuthorizationDelegate authorizationDidCancel:]): >+ (-[WKSOAuthorizationDelegate authorizationDidComplete:]): >+ (-[WKSOAuthorizationDelegate authorization:didCompleteWithHTTPAuthorizationHeaders:]): >+ (-[WKSOAuthorizationDelegate authorization:didCompleteWithHTTPResponse:httpBody:]): >+ (-[WKSOAuthorizationDelegate authorization:didCompleteWithError:]): >+ (-[WKSOAuthorizationDelegate setSession:]): >+ * UIProcess/WebPageProxy.cpp: >+ (WebKit::WebPageProxy::decidePolicyForNavigationAction): >+ (WebKit::trySOAuthorization): >+ (WebKit::WebPageProxy::createNewPage): >+ (WebKit::tryOptimizingLoad): Deleted. >+ * UIProcess/WebPageProxy.h: >+ (WebKit::WebPageProxy::setShouldSuppressSOAuthorizationInAllNavigationPolicyDecision): >+ (WebKit::WebPageProxy::setShouldSuppressSOAuthorizationInNextNavigationPolicyDecision): >+ * UIProcess/WebsiteData/WebsiteDataStore.cpp: >+ (WebKit::WebsiteDataStore::WebsiteDataStore): >+ * UIProcess/WebsiteData/WebsiteDataStore.h: >+ (WebKit::WebsiteDataStore::soAuthorizationCoordinator): >+ * WebKit.xcodeproj/project.pbxproj: >+ * WebProcess/cocoa/WebProcessCocoa.mm: >+ (WebKit::WebProcess::platformInitializeProcess): >+ > 2019-06-14 Jiewen Tan <jiewen_tan@apple.com> > > Disable AppSSO for web processes and plugin processes >diff --git a/Source/WTF/wtf/Platform.h b/Source/WTF/wtf/Platform.h >index d56b0b29cda373526b432e544684e9609e2deee8..1eb79970a77400286c454b93ed97d7a9fbfa3282 100644 >--- a/Source/WTF/wtf/Platform.h >+++ b/Source/WTF/wtf/Platform.h >@@ -1571,3 +1571,6 @@ > #define HAVE_CORETEXT_AUTO_OPTICAL_SIZING 1 > #endif > >+#if (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 130000 || PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500) >+#define HAVE_APP_SSO 1 >+#endif >diff --git a/Source/WebCore/PAL/PAL.xcodeproj/project.pbxproj b/Source/WebCore/PAL/PAL.xcodeproj/project.pbxproj >index 365637835757f06da8d4ec6b777585e42d4eefd8..ab85e48bf85e2cc1cefc161e5cde2df4b8f0d99c 100644 >--- a/Source/WebCore/PAL/PAL.xcodeproj/project.pbxproj >+++ b/Source/WebCore/PAL/PAL.xcodeproj/project.pbxproj >@@ -120,6 +120,9 @@ > 44E1A8B021FA54EB00C3048E /* LookupSoftLink.mm in Sources */ = {isa = PBXBuildFile; fileRef = 44E1A8AE21FA54DA00C3048E /* LookupSoftLink.mm */; }; > 570AB8F120AE2E8D00B8BE87 /* SecKeyProxySPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 570AB8F020AE2E8D00B8BE87 /* SecKeyProxySPI.h */; }; > 570AB8F920AF6E3D00B8BE87 /* NSXPCConnectionSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 570AB8F820AF6E3D00B8BE87 /* NSXPCConnectionSPI.h */; }; >+ 572A107822B456F500F410C8 /* AuthKitSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 572A107722B456F500F410C8 /* AuthKitSPI.h */; }; >+ 57FD318A22B3593E008D0E8B /* AppSSOSoftLink.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57FD318922B3593E008D0E8B /* AppSSOSoftLink.mm */; }; >+ 57FD318B22B35989008D0E8B /* AppSSOSoftLink.h in Headers */ = {isa = PBXBuildFile; fileRef = 57FD318822B3592F008D0E8B /* AppSSOSoftLink.h */; }; > 63C7EDC721AFAE04006A7B99 /* NSProgressSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 63E369F921AFA83F001C14BC /* NSProgressSPI.h */; }; > 7A1656441F97B2B900BA3CE4 /* NSKeyedArchiverSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A1656431F97B2B800BA3CE4 /* NSKeyedArchiverSPI.h */; }; > 7A36D0F9223AD9AB00B0522E /* CommonCryptoSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A36D0F8223AD9AB00B0522E /* CommonCryptoSPI.h */; }; >@@ -284,6 +287,9 @@ > 44E1A8AE21FA54DA00C3048E /* LookupSoftLink.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = LookupSoftLink.mm; sourceTree = "<group>"; }; > 570AB8F020AE2E8D00B8BE87 /* SecKeyProxySPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecKeyProxySPI.h; sourceTree = "<group>"; }; > 570AB8F820AF6E3D00B8BE87 /* NSXPCConnectionSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSXPCConnectionSPI.h; sourceTree = "<group>"; }; >+ 572A107722B456F500F410C8 /* AuthKitSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AuthKitSPI.h; sourceTree = "<group>"; }; >+ 57FD318822B3592F008D0E8B /* AppSSOSoftLink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppSSOSoftLink.h; sourceTree = "<group>"; }; >+ 57FD318922B3593E008D0E8B /* AppSSOSoftLink.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AppSSOSoftLink.mm; sourceTree = "<group>"; }; > 63E369F921AFA83F001C14BC /* NSProgressSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSProgressSPI.h; sourceTree = "<group>"; }; > 7A1656431F97B2B800BA3CE4 /* NSKeyedArchiverSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSKeyedArchiverSPI.h; sourceTree = "<group>"; }; > 7A36D0F8223AD9AB00B0522E /* CommonCryptoSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommonCryptoSPI.h; sourceTree = "<group>"; }; >@@ -390,6 +396,7 @@ > isa = PBXGroup; > children = ( > 2D02E93B2056FAA700A13797 /* AudioToolboxSPI.h */, >+ 572A107722B456F500F410C8 /* AuthKitSPI.h */, > 0C2DA1221F3BEB4900DBC317 /* AVKitSPI.h */, > 0C2DA1231F3BEB4900DBC317 /* CFNSURLConnectionSPI.h */, > 7A36D0F8223AD9AB00B0522E /* CommonCryptoSPI.h */, >@@ -579,6 +586,8 @@ > 1C4876DE1F8D831300CCEEBD /* cocoa */ = { > isa = PBXGroup; > children = ( >+ 57FD318822B3592F008D0E8B /* AppSSOSoftLink.h */, >+ 57FD318922B3593E008D0E8B /* AppSSOSoftLink.mm */, > 077E87B0226A460200A2AFF0 /* AVFoundationSoftLink.h */, > 077E87AF226A460200A2AFF0 /* AVFoundationSoftLink.mm */, > F44291661FA52705002CC93E /* FileSizeFormatterCocoa.mm */, >@@ -677,7 +686,9 @@ > isa = PBXHeadersBuildPhase; > buildActionMask = 2147483647; > files = ( >+ 57FD318B22B35989008D0E8B /* AppSSOSoftLink.h in Headers */, > 2D02E93C2056FAA700A13797 /* AudioToolboxSPI.h in Headers */, >+ 572A107822B456F500F410C8 /* AuthKitSPI.h in Headers */, > 077E87B2226A460300A2AFF0 /* AVFoundationSoftLink.h in Headers */, > 0C7785891F45130F00F4EBB6 /* AVFoundationSPI.h in Headers */, > 0C2DA13E1F3BEB4900DBC317 /* AVKitSPI.h in Headers */, >@@ -843,6 +854,7 @@ > developmentRegion = en; > hasScannedForEncodings = 1; > knownRegions = ( >+ en, > English, > Japanese, > French, >@@ -884,6 +896,7 @@ > isa = PBXSourcesBuildPhase; > buildActionMask = 2147483647; > files = ( >+ 57FD318A22B3593E008D0E8B /* AppSSOSoftLink.mm in Sources */, > 077E87B1226A460200A2AFF0 /* AVFoundationSoftLink.mm in Sources */, > 0C5FFF0F1F78D9DA009EFF1A /* ClockCM.mm in Sources */, > 0CF99CA81F738437007EE793 /* CoreMediaSoftLink.cpp in Sources */, >diff --git a/Source/WebCore/PAL/pal/cocoa/AppSSOSoftLink.h b/Source/WebCore/PAL/pal/cocoa/AppSSOSoftLink.h >new file mode 100644 >index 0000000000000000000000000000000000000000..614c537ff4e2e9df2077d02c92a731a0a1c97cd8 >--- /dev/null >+++ b/Source/WebCore/PAL/pal/cocoa/AppSSOSoftLink.h >@@ -0,0 +1,43 @@ >+/* >+ * Copyright (C) 2019 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. >+ */ >+ >+#pragma once >+ >+#if HAVE(APP_SSO) >+ >+#import <AppSSO/AppSSO.h> >+#import <wtf/SoftLinking.h> >+ >+SOFT_LINK_FRAMEWORK_FOR_HEADER(PAL, AppSSO); >+ >+SOFT_LINK_CLASS_FOR_HEADER(PAL, SOAuthorization); >+ >+SOFT_LINK_CONSTANT_FOR_HEADER(PAL, AppSSO, SOAuthorizationOptionUserActionInitiated, NSString*); >+#define SOAuthorizationOptionUserActionInitiated PAL::get_AppSSO_SOAuthorizationOptionUserActionInitiated() >+ >+SOFT_LINK_CONSTANT_FOR_HEADER(PAL, AppSSO, SOErrorDomain, NSErrorDomain); >+#define SOErrorDomain PAL::get_AppSSO_SOErrorDomain() >+ >+#endif >diff --git a/Source/WebCore/PAL/pal/cocoa/AppSSOSoftLink.mm b/Source/WebCore/PAL/pal/cocoa/AppSSOSoftLink.mm >new file mode 100644 >index 0000000000000000000000000000000000000000..ef1cd20760e2665441d32ca8c4d1d704e73fd0e6 >--- /dev/null >+++ b/Source/WebCore/PAL/pal/cocoa/AppSSOSoftLink.mm >@@ -0,0 +1,44 @@ >+/* >+ * Copyright (C) 2019 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. >+ */ >+ >+#include "config.h" >+ >+#if HAVE(APP_SSO) >+ >+#import <wtf/SoftLinking.h> >+ >+SOFT_LINK_FRAMEWORK_FOR_SOURCE_WITH_EXPORT(PAL, AppSSO, PAL_EXPORT); >+ >+#if PLATFORM(MAC) >+SOFT_LINK_CLASS_FOR_SOURCE_OPTIONAL_WITH_EXPORT(PAL, AppSSO, SOAuthorization, PAL_EXPORT); >+#else >+SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT(PAL, AppSSO, SOAuthorization, PAL_EXPORT); >+#endif >+ >+SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(PAL, AppSSO, SOAuthorizationOptionUserActionInitiated, NSString*, PAL_EXPORT); >+ >+SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(PAL, AppSSO, SOErrorDomain, NSErrorDomain, PAL_EXPORT); >+ >+#endif >diff --git a/Source/WebCore/PAL/pal/spi/cf/CFNetworkSPI.h b/Source/WebCore/PAL/pal/spi/cf/CFNetworkSPI.h >index 182ff8be651a8d262cc68643f2daddd266594b75..4557085d80e03704a32bbe83bfea2597f12a6a16 100644 >--- a/Source/WebCore/PAL/pal/spi/cf/CFNetworkSPI.h >+++ b/Source/WebCore/PAL/pal/spi/cf/CFNetworkSPI.h >@@ -236,7 +236,7 @@ typedef NS_ENUM(NSInteger, NSURLSessionCompanionProxyPreference) { > #if HAVE(CFNETWORK_NSURLSESSION_STRICTRUSTEVALUATE) > + (void)_strictTrustEvaluate:(NSURLAuthenticationChallenge *)challenge queue:(dispatch_queue_t)queue completionHandler:(void (^)(NSURLAuthenticationChallenge *challenge, OSStatus trustResult))cb; > #endif >-#if HAVE(LOAD_OPTIMIZER) >+#if HAVE(APP_SSO) > + (void)_disableAppSSO; > #endif > @end >diff --git a/Source/WebCore/PAL/pal/spi/cocoa/AuthKitSPI.h b/Source/WebCore/PAL/pal/spi/cocoa/AuthKitSPI.h >new file mode 100644 >index 0000000000000000000000000000000000000000..6c82ec937b95461e59a315f927587c9c568aa906 >--- /dev/null >+++ b/Source/WebCore/PAL/pal/spi/cocoa/AuthKitSPI.h >@@ -0,0 +1,48 @@ >+/* >+ * Copyright (C) 2019 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. >+ */ >+ >+#pragma once >+ >+#if HAVE(APP_SSO) >+ >+#if USE(APPLE_INTERNAL_SDK) >+ >+#import <AuthKit/AKAuthorizationController.h> >+ >+#else >+ >+NS_ASSUME_NONNULL_BEGIN >+ >+@interface AKAuthorizationController : NSObject >+ >++ (BOOL)isURLFromAppleOwnedDomain:(NSURL *)url; >+ >+@end >+ >+NS_ASSUME_NONNULL_END >+ >+#endif // USE(APPLE_INTERNAL_SDK) >+ >+#endif // HAVE(APP_SSO) >diff --git a/Source/WebKit/Configurations/WebKit.xcconfig b/Source/WebKit/Configurations/WebKit.xcconfig >index d9dda2c97ee6442acc44a282481a5c1ca28fbd67..430f7df2b5dbdd0384da5f979055365cb9395510 100644 >--- a/Source/WebKit/Configurations/WebKit.xcconfig >+++ b/Source/WebKit/Configurations/WebKit.xcconfig >@@ -127,7 +127,14 @@ WK_URL_FORMATTING_LDFLAGS_YES = -framework URLFormatting; > WK_WEBINSPECTORUI_LDFLAGS = $(WK_WEBINSPECTORUI_LDFLAGS_$(WK_PLATFORM_NAME)); > WK_WEBINSPECTORUI_LDFLAGS_macosx = -weak_framework WebInspectorUI; > >-FRAMEWORK_AND_LIBRARY_LDFLAGS = -lobjc -framework CFNetwork -framework CoreAudio -framework CoreFoundation -framework CoreGraphics -framework CoreText -framework Foundation -framework ImageIO -framework IOKit -framework WebKitLegacy -lnetwork $(WK_ACCESSIBILITY_LDFLAGS) $(WK_APPKIT_LDFLAGS) $(WK_ASSERTION_SERVICES_LDFLAGS) $(WK_CARBON_LDFLAGS) $(WK_CORE_PDF_LDFLAGS) $(WK_CORE_PREDICTION_LDFLAGS) $(WK_CORE_SERVICES_LDFLAGS) $(WK_DEVICE_IDENTITY_LDFLAGS) $(WK_GRAPHICS_SERVICES_LDFLAGS) $(WK_IOSURFACE_LDFLAGS) $(WK_LIBSANDBOX_LDFLAGS) $(WK_LIBWEBRTC_LDFLAGS) $(WK_MOBILE_CORE_SERVICES_LDFLAGS) $(WK_MOBILE_GESTALT_LDFLAGS) $(WK_OPENGL_LDFLAGS) $(WK_PDFKIT_LDFLAGS) $(WK_SAFE_BROWSING_LDFLAGS) $(WK_SECURITY_INTERFACE_LDFLAGS) $(WK_UIKIT_LDFLAGS) $(WK_URL_FORMATTING_LDFLAGS) $(WK_WEBINSPECTORUI_LDFLAGS); >+WK_AUTHKIT_LDFLAGS = $(WK_AUTHKIT_LDFLAGS_$(WK_PLATFORM_NAME)); >+WK_AUTHKIT_LDFLAGS_iphoneos = $(WK_AUTHKIT_LDFLAGS$(WK_IOS_13)); >+WK_AUTHKIT_LDFLAGS_iphonesimulator = $(WK_AUTHKIT_LDFLAGS$(WK_IOS_13)); >+WK_AUTHKIT_LDFLAGS_IOS_SINCE_13 = -framework AuthKit; >+WK_AUTHKIT_LDFLAGS_macosx = $(WK_AUTHKIT_LDFLAGS$(WK_MACOS_1015)); >+WK_AUTHKIT_LDFLAGS_MACOS_SINCE_1015 = -framework AuthKit; >+ >+FRAMEWORK_AND_LIBRARY_LDFLAGS = -lobjc -framework CFNetwork -framework CoreAudio -framework CoreFoundation -framework CoreGraphics -framework CoreText -framework Foundation -framework ImageIO -framework IOKit -framework WebKitLegacy -lnetwork $(WK_ACCESSIBILITY_LDFLAGS) $(WK_APPKIT_LDFLAGS) $(WK_ASSERTION_SERVICES_LDFLAGS) $(WK_AUTHKIT_LDFLAGS) $(WK_CARBON_LDFLAGS) $(WK_CORE_PDF_LDFLAGS) $(WK_CORE_PREDICTION_LDFLAGS) $(WK_CORE_SERVICES_LDFLAGS) $(WK_DEVICE_IDENTITY_LDFLAGS) $(WK_GRAPHICS_SERVICES_LDFLAGS) $(WK_IOSURFACE_LDFLAGS) $(WK_LIBSANDBOX_LDFLAGS) $(WK_LIBWEBRTC_LDFLAGS) $(WK_MOBILE_CORE_SERVICES_LDFLAGS) $(WK_MOBILE_GESTALT_LDFLAGS) $(WK_OPENGL_LDFLAGS) $(WK_PDFKIT_LDFLAGS) $(WK_SAFE_BROWSING_LDFLAGS) $(WK_SECURITY_INTERFACE_LDFLAGS) $(WK_UIKIT_LDFLAGS) $(WK_URL_FORMATTING_LDFLAGS) $(WK_WEBINSPECTORUI_LDFLAGS); > > // Prevent C++ standard library basic_stringstream, operator new, delete and their related exception types from being exported as weak symbols. > UNEXPORTED_SYMBOL_LDFLAGS = -Wl,-unexported_symbol -Wl,__ZTISt9bad_alloc -Wl,-unexported_symbol -Wl,__ZTISt9exception -Wl,-unexported_symbol -Wl,__ZTSSt9bad_alloc -Wl,-unexported_symbol -Wl,__ZTSSt9exception -Wl,-unexported_symbol -Wl,__ZdlPvS_ -Wl,-unexported_symbol -Wl,__ZnwmPv -Wl,-unexported_symbol -Wl,__Znwm -Wl,-unexported_symbol -Wl,__ZNSt3__18functionIFvN7WebCore12PolicyActionEEEC2EOS4_ -Wl,-unexported_symbol -Wl,__ZNSt3__18functionIFvN7WebCore12PolicyActionEEEC1EOS4_ -Wl,-unexported_symbol -Wl,__ZNSt3__18functionIFvN7WebCore12PolicyActionEEEaSEDn -Wl,-unexported_symbol -Wl,__ZNKSt3__18functionIFvN7WebCore12PolicyActionEEEclES2_ -Wl,-unexported_symbol -Wl,__ZNSt3__18functionIFvN7WebCore12PolicyActionEEE4swapERS4_ -Wl,-unexported_symbol -Wl,__ZNSt3__18functionIFvN7WebCore12PolicyActionEEEC1ERKS4_ -Wl,-unexported_symbol -Wl,__ZNSt3__18functionIFvN7WebCore12PolicyActionEEEC2ERKS4_ -Wl,-unexported_symbol -Wl,__ZNSt3__18functionIFvN7WebCore12PolicyActionEEED1Ev -Wl,-unexported_symbol -Wl,__ZNSt3__18functionIFvN7WebCore12PolicyActionEEED2Ev -Wl,-unexported_symbol -Wl,__ZNSt3__18functionIFvN7WebCore12PolicyActionEEEaSERKS4_ -Wl,-unexported_symbol -Wl,__ZTVNSt3__117bad_function_callE -Wl,-unexported_symbol -Wl,__ZTCNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE0_NS_13basic_istreamIcS2_EE -Wl,-unexported_symbol -Wl,__ZTCNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE0_NS_14basic_iostreamIcS2_EE -Wl,-unexported_symbol -Wl,__ZTCNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE16_NS_13basic_ostreamIcS2_EE -Wl,-unexported_symbol -Wl,__ZTTNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE -Wl,-unexported_symbol -Wl,__ZTVNSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEEE -Wl,-unexported_symbol -Wl,__ZTVNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE -Wl,-unexported_symbol -Wl,__ZTCNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE8_NS_13basic_ostreamIcS2_EE; >diff --git a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm >index 26250d6e4fb735c3292c48aaa07be77e2d1d7bbc..bdbf9b45cc3fe5e04ce6a0e18dd8038af21ad426 100644 >--- a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm >+++ b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm >@@ -942,8 +942,8 @@ NetworkSessionCocoa::NetworkSessionCocoa(NetworkProcess& networkProcess, Network > > NSURLSessionConfiguration *configuration = configurationForSessionID(m_sessionID); > >-#if HAVE(LOAD_OPTIMIZER) >- NETWORKSESSIONCOCOA_LOADOPTIMIZER_ADDITIONS >+#if HAVE(APP_SSO) >+ configuration._preventsAppSSO = true; > #endif > > #if USE(CFNETWORK_AUTO_ADDED_HTTP_HEADER_SUPPRESSION) >diff --git a/Source/WebKit/PluginProcess/mac/PluginProcessMac.mm b/Source/WebKit/PluginProcess/mac/PluginProcessMac.mm >index 787bcbae41055c57b4f59aae6d5f9822d31605a6..d60037fd3ec656d75d7067d32a2e34371fd0d007 100644 >--- a/Source/WebKit/PluginProcess/mac/PluginProcessMac.mm >+++ b/Source/WebKit/PluginProcess/mac/PluginProcessMac.mm >@@ -405,7 +405,7 @@ void PluginProcess::platformInitializePluginProcess(PluginProcessCreationParamet > // Disable Dark Mode in the plugin process to avoid rendering issues. > [NSApp setAppearance:[NSAppearance appearanceNamed:NSAppearanceNameAqua]]; > #endif >-#if HAVE(LOAD_OPTIMIZER) >+#if HAVE(APP_SSO) > [NSURLSession _disableAppSSO]; > #endif > } >diff --git a/Source/WebKit/SourcesCocoa.txt b/Source/WebKit/SourcesCocoa.txt >index 46617be8624c9b8d9a4ae21f1f99d3762f4eaf39..27dcf0943a71a067360089671a72b7029ffd2b93 100644 >--- a/Source/WebKit/SourcesCocoa.txt >+++ b/Source/WebKit/SourcesCocoa.txt >@@ -328,6 +328,15 @@ UIProcess/Automation/ios/WebAutomationSessionIOS.mm > > UIProcess/Automation/mac/WebAutomationSessionMac.mm > >+UIProcess/Cocoa/SOAuthorization/NavigationSOAuthorizationSession.mm >+UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.mm >+UIProcess/Cocoa/SOAuthorization/RedirectSOAuthorizationSession.mm >+UIProcess/Cocoa/SOAuthorization/SOAuthorizationCoordinator.mm >+UIProcess/Cocoa/SOAuthorization/SOAuthorizationNSURLExtras.mm >+UIProcess/Cocoa/SOAuthorization/SOAuthorizationSession.mm >+UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.mm >+UIProcess/Cocoa/SOAuthorization/WKSOAuthorizationDelegate.mm >+ > UIProcess/Cocoa/AutomationClient.mm > UIProcess/Cocoa/AutomationSessionClient.mm > UIProcess/Cocoa/DiagnosticLoggingClient.mm >diff --git a/Source/WebKit/UIProcess/API/APINavigationAction.h b/Source/WebKit/UIProcess/API/APINavigationAction.h >index c1528f8b5152af5fa78127fc56187fc0792f757f..4f81fdf1a490d5c0cbeb55e9ef9ef9466950375c 100644 >--- a/Source/WebKit/UIProcess/API/APINavigationAction.h >+++ b/Source/WebKit/UIProcess/API/APINavigationAction.h >@@ -69,8 +69,9 @@ public: > > Navigation* mainFrameNavigation() const { return m_mainFrameNavigation.get(); } > >-#if HAVE(LOAD_OPTIMIZER) >-APINAVIGATIONACTION_LOADOPTIMIZER_ADDITIONS_1 >+#if HAVE(APP_SSO) >+ bool shouldPerformSOAuthorization() { return m_shouldPerformSOAuthorization; } >+ void unsetShouldPerformSOAuthorization() { m_shouldPerformSOAuthorization = false; } > #endif > > private: >@@ -100,8 +101,8 @@ private: > WTF::URL m_originalURL; > > bool m_shouldOpenAppLinks; >-#if HAVE(LOAD_OPTIMIZER) >-APINAVIGATIONACTION_LOADOPTIMIZER_ADDITIONS_2 >+#if HAVE(APP_SSO) >+ bool m_shouldPerformSOAuthorization { true }; > #endif > > RefPtr<UserInitiatedAction> m_userInitiatedAction; >diff --git a/Source/WebKit/UIProcess/Cocoa/NavigationState.mm b/Source/WebKit/UIProcess/Cocoa/NavigationState.mm >index a4ea6b731b043e035ed7133d5158ddbbd1b7a342..325ff810be2bf31151a777df74a949b00a8bfd62 100644 >--- a/Source/WebKit/UIProcess/Cocoa/NavigationState.mm >+++ b/Source/WebKit/UIProcess/Cocoa/NavigationState.mm >@@ -40,6 +40,7 @@ > #import "Logging.h" > #import "NavigationActionData.h" > #import "PageLoadState.h" >+#import "SOAuthorizationCoordinator.h" > #import "WKBackForwardListInternal.h" > #import "WKBackForwardListItemInternal.h" > #import "WKFrameInfoInternal.h" >@@ -81,10 +82,6 @@ > #import <pal/spi/cocoa/LaunchServicesSPI.h> > #endif > >-#if USE(APPLE_INTERNAL_SDK) >-#import <WebKitAdditions/NavigationStateAdditions.mm> >-#endif >- > #if USE(QUICK_LOOK) > #import "QuickLookDocumentData.h" > #endif >@@ -474,12 +471,18 @@ bool NavigationState::NavigationClient::willGoToBackForwardListItem(WebPageProxy > } > #endif > >-#if !USE(APPLE_INTERNAL_SDK) >-static void tryOptimizingLoad(Ref<API::NavigationAction>&&, WebPageProxy&, Function<void(bool)>&& completionHandler) >+static void trySOAuthorization(Ref<API::NavigationAction>&& navigationAction, WebPageProxy& page, Function<void(bool)>&& completionHandler) > { >+#if HAVE(APP_SSO) >+ if (!navigationAction->shouldPerformSOAuthorization()) { >+ completionHandler(false); >+ return; >+ } >+ page.websiteDataStore().soAuthorizationCoordinator().tryAuthorize(WTFMove(navigationAction), page, WTFMove(completionHandler)); >+#else > completionHandler(false); >-} > #endif >+} > > static void tryInterceptNavigation(Ref<API::NavigationAction>&& navigationAction, WebPageProxy& page, WTF::Function<void(bool)>&& completionHandler) > { >@@ -489,7 +492,7 @@ static void tryInterceptNavigation(Ref<API::NavigationAction>&& navigationAction > auto* localCompletionHandler = new WTF::Function<void (bool)>([navigationAction = WTFMove(navigationAction), weakPage = makeWeakPtr(page), completionHandler = WTFMove(completionHandler)] (bool success) mutable { > ASSERT(RunLoop::isMain()); > if (!success && weakPage) { >- tryOptimizingLoad(WTFMove(navigationAction), *weakPage, WTFMove(completionHandler)); >+ trySOAuthorization(WTFMove(navigationAction), *weakPage, WTFMove(completionHandler)); > return; > } > completionHandler(success); >@@ -504,7 +507,7 @@ static void tryInterceptNavigation(Ref<API::NavigationAction>&& navigationAction > } > #endif > >- tryOptimizingLoad(WTFMove(navigationAction), page, WTFMove(completionHandler)); >+ trySOAuthorization(WTFMove(navigationAction), page, WTFMove(completionHandler)); > } > > void NavigationState::NavigationClient::decidePolicyForNavigationAction(WebPageProxy& webPageProxy, Ref<API::NavigationAction>&& navigationAction, Ref<WebFramePolicyListenerProxy>&& listener, API::Object* userInfo) >@@ -618,7 +621,7 @@ void NavigationState::NavigationClient::decidePolicyForNavigationAction(WebPageP > localListener->download(); > break; > case _WKNavigationActionPolicyAllowWithoutTryingAppLink: >- tryOptimizingLoad(WTFMove(navigationAction), webPageProxy, [localListener = WTFMove(localListener), websitePolicies = WTFMove(apiWebsitePolicies)] (bool optimizedLoad) { >+ trySOAuthorization(WTFMove(navigationAction), webPageProxy, [localListener = WTFMove(localListener), websitePolicies = WTFMove(apiWebsitePolicies)] (bool optimizedLoad) { > if (optimizedLoad) { > localListener->ignore(); > return; >diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/NavigationSOAuthorizationSession.h b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/NavigationSOAuthorizationSession.h >new file mode 100644 >index 0000000000000000000000000000000000000000..568330a10f836e770f0b98925c50fd2c120c0e1c >--- /dev/null >+++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/NavigationSOAuthorizationSession.h >@@ -0,0 +1,68 @@ >+/* >+ * Copyright (C) 2019 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. >+ */ >+ >+#pragma once >+ >+#if HAVE(APP_SSO) >+ >+#include "SOAuthorizationSession.h" >+#include "WebViewDidMoveToWindowObserver.h" >+#include <wtf/CompletionHandler.h> >+ >+namespace WebKit { >+ >+// When the WebView, owner of the page, is not in the window, the session will then pause >+// and later resume after the WebView being moved into the window. >+// The reason to apply the above rule to the whole session instead of UI session only is UI >+// can be shown out of process, in which case WebKit will not even get notified. >+// FSM: Idle => isInWindow => Active => Completed >+// Idle => !isInWindow => Waiting => become isInWindow => Active => Completed >+class NavigationSOAuthorizationSession : public WebViewDidMoveToWindowObserver, public SOAuthorizationSession { >+public: >+ using Callback = CompletionHandler<void(bool)>; >+ >+ using WebViewDidMoveToWindowObserver::weakPtrFactory; >+ using WeakValueType = WebViewDidMoveToWindowObserver::WeakValueType; >+ >+ ~NavigationSOAuthorizationSession(); >+ >+ // WebViewDidMoveToWindowObserver >+ void webViewDidMoveToWindow() final; >+ >+protected: >+ NavigationSOAuthorizationSession(SOAuthorization *, Ref<API::NavigationAction>&&, WebPageProxy&, InitiatingAction, Callback&&); >+ >+ void callback(bool intercepted) { m_callback(intercepted); } >+ >+private: >+ void shouldStartInternal() final; >+ virtual void beforeStart() = 0; >+ >+ Callback m_callback; >+}; >+ >+} // namespace WebKit >+ >+#endif >diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/NavigationSOAuthorizationSession.mm b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/NavigationSOAuthorizationSession.mm >new file mode 100644 >index 0000000000000000000000000000000000000000..4226bbece4f95c12186590aaefc2ce1d9d09999b >--- /dev/null >+++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/NavigationSOAuthorizationSession.mm >@@ -0,0 +1,74 @@ >+/* >+ * Copyright (C) 2019 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. >+ */ >+ >+#include "config.h" >+#include "NavigationSOAuthorizationSession.h" >+ >+#if HAVE(APP_SSO) >+ >+#import "WebPageProxy.h" >+#import <WebCore/ResourceResponse.h> >+ >+namespace WebKit { >+ >+NavigationSOAuthorizationSession::NavigationSOAuthorizationSession(SOAuthorization *soAuthorization, Ref<API::NavigationAction>&& navigationAction, WebPageProxy& page, InitiatingAction action, Callback&& completionHandler) >+ : SOAuthorizationSession(soAuthorization, WTFMove(navigationAction), page, action) >+ , m_callback(WTFMove(completionHandler)) >+{ >+} >+ >+NavigationSOAuthorizationSession::~NavigationSOAuthorizationSession() >+{ >+ if (m_callback) >+ m_callback(true); >+ if (state() == State::Waiting && page()) >+ page()->removeObserver(*this); >+} >+ >+void NavigationSOAuthorizationSession::shouldStartInternal() >+{ >+ auto* pagePtr = page(); >+ ASSERT(pagePtr); >+ beforeStart(); >+ if (!pagePtr->isInWindow()) { >+ setState(State::Waiting); >+ pagePtr->addObserver(*this); >+ return; >+ } >+ start(); >+} >+ >+void NavigationSOAuthorizationSession::webViewDidMoveToWindow() >+{ >+ auto* pagePtr = page(); >+ if (state() != State::Waiting || !pagePtr || !pagePtr->isInWindow()) >+ return; >+ start(); >+ pagePtr->removeObserver(*this); >+} >+ >+} // namespace WebKit >+ >+#endif >diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h >new file mode 100644 >index 0000000000000000000000000000000000000000..d50306038f206620e0360a05d18d94acd8a1fb34 >--- /dev/null >+++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h >@@ -0,0 +1,74 @@ >+/* >+ * Copyright (C) 2019 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. >+ */ >+ >+#pragma once >+ >+#if HAVE(APP_SSO) >+ >+#include "SOAuthorizationSession.h" >+ >+OBJC_CLASS WKSOSecretDelegate; >+OBJC_CLASS WKWebView; >+ >+namespace API { >+class NavigationAction; >+} >+ >+namespace WebKit { >+ >+// FSM: Idle => Active => Completed >+class PopUpSOAuthorizationSession final : public SOAuthorizationSession { >+public: >+ using NewPageCallback = CompletionHandler<void(RefPtr<WebPageProxy>&&)>; >+ using UIClientCallback = Function<void(Ref<API::NavigationAction>&&, NewPageCallback&&)>; >+ >+ static Ref<SOAuthorizationSession> create(SOAuthorization *soAuthorization, WebPageProxy& page, Ref<API::NavigationAction>&& navigationAction, NewPageCallback&& newPageCallback, UIClientCallback&& uiClientCallback) >+ { >+ return adoptRef(*new PopUpSOAuthorizationSession(soAuthorization, page, WTFMove(navigationAction), WTFMove(newPageCallback), WTFMove(uiClientCallback))); >+ } >+ ~PopUpSOAuthorizationSession(); >+ >+ void close(WKWebView *); >+ >+private: >+ PopUpSOAuthorizationSession(SOAuthorization *, WebPageProxy&, Ref<API::NavigationAction>&&, NewPageCallback&&, UIClientCallback&&); >+ >+ void shouldStartInternal() final; >+ void fallBackToWebPathInternal() final; >+ void abortInternal() final; >+ void completeInternal(WebCore::ResourceResponse&&, NSData *) final; >+ >+ void initSecretWebView(); >+ >+ NewPageCallback m_newPageCallback; >+ UIClientCallback m_uiClientCallback; >+ >+ RetainPtr<WKSOSecretDelegate> m_secretDelegate; >+ RetainPtr<WKWebView> m_secretWebView; >+}; >+ >+} // namespace WebKit >+ >+#endif >diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.mm b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.mm >new file mode 100644 >index 0000000000000000000000000000000000000000..2ab310afbf5664663a6bedc73e0d2a12f99cc83b >--- /dev/null >+++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.mm >@@ -0,0 +1,172 @@ >+/* >+ * Copyright (C) 2019 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 "PopUpSOAuthorizationSession.h" >+ >+#if HAVE(APP_SSO) >+ >+#import "WKNavigationDelegatePrivate.h" >+#import "WKUIDelegate.h" >+#import "WKWebViewConfigurationPrivate.h" >+#import "WKWebViewInternal.h" >+#import <WebCore/ResourceResponse.h> >+#import <WebKit/APINavigationAction.h> >+#import <wtf/BlockPtr.h> >+ >+@interface WKSOSecretDelegate : NSObject <WKNavigationDelegate, WKUIDelegate> { >+@package >+WeakPtr<WebKit::PopUpSOAuthorizationSession> _session; >+BOOL _isFirstNavigation; >+} >+ >+- (instancetype)initWithSession:(WebKit::PopUpSOAuthorizationSession *)session; >+ >+@end >+ >+@implementation WKSOSecretDelegate >+ >+- (instancetype)initWithSession:(WebKit::PopUpSOAuthorizationSession *)session >+{ >+ if (self = [super init]) { >+ _session = makeWeakPtr(session); >+ _isFirstNavigation = YES; >+ } >+ return self; >+} >+ >+// WKUIDelegate >+- (void)webViewDidClose:(WKWebView *)webView >+{ >+ if (!_session) >+ return; >+ _session->close(webView); >+} >+ >+// WKNavigationDelegate >+- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler >+{ >+ // FIXME<rdar://problem/48787839>: We should restrict the load to only substitute data. >+ // Use the following heuristic as a workaround right now. >+ // Ignore the first load in the secret window, which navigates to the authentication URL. >+ if (_isFirstNavigation) { >+ _isFirstNavigation = NO; >+ decisionHandler(WKNavigationActionPolicyCancel); >+ return; >+ } >+ decisionHandler(_WKNavigationActionPolicyAllowWithoutTryingAppLink); >+} >+ >+- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation >+{ >+ if (!_session) >+ return; >+ _session->close(webView); >+} >+ >+@end >+ >+namespace WebKit { >+ >+PopUpSOAuthorizationSession::PopUpSOAuthorizationSession(SOAuthorization *soAuthorization, WebPageProxy& page, Ref<API::NavigationAction>&& navigationAction, NewPageCallback&& newPageCallback, UIClientCallback&& uiClientCallback) >+ : SOAuthorizationSession(soAuthorization, WTFMove(navigationAction), page, InitiatingAction::PopUp) >+ , m_newPageCallback(WTFMove(newPageCallback)) >+ , m_uiClientCallback(WTFMove(uiClientCallback)) >+{ >+} >+ >+PopUpSOAuthorizationSession::~PopUpSOAuthorizationSession() >+{ >+ ASSERT(state() != State::Waiting); >+ if (m_newPageCallback) >+ m_newPageCallback(nullptr); >+} >+ >+void PopUpSOAuthorizationSession::shouldStartInternal() >+{ >+ ASSERT(page() && page()->isInWindow()); >+ start(); >+} >+ >+void PopUpSOAuthorizationSession::fallBackToWebPathInternal() >+{ >+ m_uiClientCallback(releaseNavigationAction(), WTFMove(m_newPageCallback)); >+} >+ >+void PopUpSOAuthorizationSession::abortInternal() >+{ >+ if (!page()) { >+ m_newPageCallback(nullptr); >+ return; >+ } >+ >+ initSecretWebView(); >+ m_newPageCallback(m_secretWebView->_page.get()); >+ [m_secretWebView evaluateJavaScript: @"window.close()" completionHandler:nil]; >+} >+ >+void PopUpSOAuthorizationSession::completeInternal(WebCore::ResourceResponse&& response, NSData *data) >+{ >+ if (response.httpStatusCode() != 200 || !page()) { >+ fallBackToWebPathInternal(); >+ return; >+ } >+ >+ initSecretWebView(); >+ m_newPageCallback(m_secretWebView->_page.get()); >+ [m_secretWebView loadData:data MIMEType:@"text/html" characterEncodingName:@"UTF-8" baseURL:response.url()]; >+} >+ >+void PopUpSOAuthorizationSession::close(WKWebView *webView) >+{ >+ if (!m_secretWebView) >+ return; >+ if (state() != State::Completed || webView != m_secretWebView.get()) { >+ ASSERT_NOT_REACHED(); >+ return; >+ } >+ m_secretWebView = nullptr; >+ WTFLogAlways("SecretWebView is cleaned."); >+} >+ >+void PopUpSOAuthorizationSession::initSecretWebView() >+{ >+ ASSERT(page()); >+ auto initiatorWebView = fromWebPageProxy(*page()); >+ auto configuration = adoptNS([initiatorWebView.configuration copy]); >+ [configuration _setRelatedWebView:initiatorWebView]; >+ m_secretWebView = adoptNS([[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration.get()]); >+ >+ m_secretDelegate = adoptNS([[WKSOSecretDelegate alloc] initWithSession:this]); >+ [m_secretWebView setUIDelegate:m_secretDelegate.get()]; >+ [m_secretWebView setNavigationDelegate:m_secretDelegate.get()]; >+ >+ m_secretWebView->_page->setShouldSuppressSOAuthorizationInAllNavigationPolicyDecision(); >+ WTFLogAlways("SecretWebView is created."); >+} >+ >+} // namespace WebKit >+ >+#endif >diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/RedirectSOAuthorizationSession.h b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/RedirectSOAuthorizationSession.h >new file mode 100644 >index 0000000000000000000000000000000000000000..fd88910e680cc4cb5a9d8ab58c4ed22e1f3d0068 >--- /dev/null >+++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/RedirectSOAuthorizationSession.h >@@ -0,0 +1,57 @@ >+/* >+ * Copyright (C) 2019 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. >+ */ >+ >+#pragma once >+ >+#if HAVE(APP_SSO) >+ >+#include "NavigationSOAuthorizationSession.h" >+ >+namespace WebKit { >+ >+class RedirectSOAuthorizationSession final : public NavigationSOAuthorizationSession { >+public: >+ using Callback = CompletionHandler<void(bool)>; >+ >+ static Ref<SOAuthorizationSession> create(SOAuthorization *soAuthorization, Ref<API::NavigationAction>&& navigationAction, WebPageProxy& page, Callback&& completionHandler) >+ { >+ return adoptRef(*new RedirectSOAuthorizationSession(soAuthorization, WTFMove(navigationAction), page, WTFMove(completionHandler))); >+ } >+ >+private: >+ RedirectSOAuthorizationSession(SOAuthorization *, Ref<API::NavigationAction>&&, WebPageProxy&, Callback&&); >+ >+ // SOAuthorizationSession >+ void fallBackToWebPathInternal() final; >+ void abortInternal() final; >+ void completeInternal(WebCore::ResourceResponse&&, NSData *) final; >+ >+ // NavigationSOAuthorizationSession >+ void beforeStart() final; >+}; >+ >+} // namespace WebKit >+ >+#endif >diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/RedirectSOAuthorizationSession.mm b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/RedirectSOAuthorizationSession.mm >new file mode 100644 >index 0000000000000000000000000000000000000000..8eef77412ccee055be91275e42a4f6baf3919a81 >--- /dev/null >+++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/RedirectSOAuthorizationSession.mm >@@ -0,0 +1,91 @@ >+/* >+ * Copyright (C) 2019 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 "RedirectSOAuthorizationSession.h" >+ >+#if HAVE(APP_SSO) >+ >+#import "DataReference.h" >+#import <WebCore/ResourceResponse.h> >+ >+namespace WebKit { >+ >+RedirectSOAuthorizationSession::RedirectSOAuthorizationSession(SOAuthorization *soAuthorization, Ref<API::NavigationAction>&& navigationAction, WebPageProxy& page, Callback&& completionHandler) >+ : NavigationSOAuthorizationSession(soAuthorization, WTFMove(navigationAction), page, InitiatingAction::Redirect, WTFMove(completionHandler)) >+{ >+} >+ >+void RedirectSOAuthorizationSession::fallBackToWebPathInternal() >+{ >+ callback(false); >+} >+ >+void RedirectSOAuthorizationSession::abortInternal() >+{ >+ callback(true); >+} >+ >+void RedirectSOAuthorizationSession::completeInternal(WebCore::ResourceResponse&& response, NSData *data) >+{ >+ auto* pagePtr = page(); >+ if ((response.httpStatusCode() != 302 && response.httpStatusCode() != 200) || !pagePtr) { >+ fallBackToWebPathInternal(); >+ return; >+ } >+ callback(true); >+ if (response.httpStatusCode() == 302) { >+#if PLATFORM(IOS) >+ auto* navigationActionPtr = navigationAction(); >+ ASSERT(navigationActionPtr); >+ // MobileSafari has a WBSURLSpoofingMitigator, which will not display the provisional URL for navigations without user gestures. >+ // For slow loads that are initiated from the MobileSafari Favorites screen, the aforementioned behavior will create a period >+ // after authentication completion where the new request to the application site loads with a blank URL and blank page. To >+ // workaround this issue, we load an html page that does a client side redirection to the application site on behalf of the >+ // request URL, instead of directly loading a new request. The html page should be super fast to load and therefore will not >+ // show an empty URL or a blank page. These changes ensure a relevant URL bar and useful page content during the load. >+ if (!navigationActionPtr->isProcessingUserGesture()) { >+ pagePtr->setShouldSuppressSOAuthorizationInNextNavigationPolicyDecision(); >+ auto html = makeString("<script>location = '", response.httpHeaderFields().get(WebCore::HTTPHeaderName::Location), "'</script>").utf8(); >+ auto data = IPC::DataReference(reinterpret_cast<const uint8_t*>(html.data()), html.length()); >+ pagePtr->loadData(data, "text/html"_s, "UTF-8"_s, navigationActionPtr->request().url()); >+ return; >+ } >+#endif >+ pagePtr->loadRequest(WebCore::ResourceRequest(response.httpHeaderFields().get(WebCore::HTTPHeaderName::Location))); >+ } >+ if (response.httpStatusCode() == 200) { >+ pagePtr->setShouldSuppressSOAuthorizationInNextNavigationPolicyDecision(); >+ pagePtr->loadData(IPC::DataReference(static_cast<const uint8_t*>(data.bytes), data.length), "text/html"_s, "UTF-8"_s, response.url().string()); >+ } >+} >+ >+void RedirectSOAuthorizationSession::beforeStart() >+{ >+} >+ >+} // namespace WebKit >+ >+#endif >diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SOAuthorizationCoordinator.h b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SOAuthorizationCoordinator.h >new file mode 100644 >index 0000000000000000000000000000000000000000..bfd3cde33779d5ae58b9cc76b961de87a7aa69d0 >--- /dev/null >+++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SOAuthorizationCoordinator.h >@@ -0,0 +1,72 @@ >+/* >+ * Copyright (C) 2019 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. >+ */ >+ >+#pragma once >+ >+#if HAVE(APP_SSO) >+ >+#include <wtf/Forward.h> >+#include <wtf/Noncopyable.h> >+#include <wtf/RetainPtr.h> >+ >+OBJC_CLASS SOAuthorization; >+OBJC_CLASS WKSOAuthorizationDelegate; >+ >+namespace API { >+class NavigationAction; >+} >+ >+namespace WebCore { >+class ResourceRequest; >+} >+ >+namespace WebKit { >+ >+class WebPageProxy; >+ >+class SOAuthorizationCoordinator { >+ WTF_MAKE_FAST_ALLOCATED; >+ WTF_MAKE_NONCOPYABLE(SOAuthorizationCoordinator); >+public: >+ SOAuthorizationCoordinator(); >+ >+ // For Navigation interception. >+ void tryAuthorize(Ref<API::NavigationAction>&&, WebPageProxy&, Function<void(bool)>&&); >+ >+ // For PopUp interception. >+ using NewPageCallback = CompletionHandler<void(RefPtr<WebPageProxy>&&)>; >+ using UIClientCallback = Function<void(Ref<API::NavigationAction>&&, NewPageCallback&&)>; >+ void tryAuthorize(Ref<API::NavigationAction>&&, WebPageProxy&, NewPageCallback&&, UIClientCallback&&); >+ >+private: >+ inline bool canAuthorize(const URL&) const; >+ >+ RetainPtr<SOAuthorization> m_soAuthorization; >+ RetainPtr<WKSOAuthorizationDelegate> m_soAuthorizationDelegate; >+}; >+ >+} // namespace WebKit >+ >+#endif >diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SOAuthorizationCoordinator.mm b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SOAuthorizationCoordinator.mm >new file mode 100644 >index 0000000000000000000000000000000000000000..db44de254f40fd4d99f8275e3241fe7dbc1f3118 >--- /dev/null >+++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SOAuthorizationCoordinator.mm >@@ -0,0 +1,93 @@ >+/* >+ * Copyright (C) 2019 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 "SOAuthorizationCoordinator.h" >+ >+#if HAVE(APP_SSO) >+ >+#import "PopUpSOAuthorizationSession.h" >+#import "RedirectSOAuthorizationSession.h" >+#import "SubFrameSOAuthorizationSession.h" >+#import "WKSOAuthorizationDelegate.h" >+#import <WebCore/ResourceRequest.h> >+#import <pal/cocoa/AppSSOSoftLink.h> >+#import <pal/spi/cf/CFNetworkSPI.h> >+#import <pal/spi/cocoa/AuthKitSPI.h> >+#import <wtf/Function.h> >+ >+namespace WebKit { >+ >+SOAuthorizationCoordinator::SOAuthorizationCoordinator() >+{ >+#if PLATFORM(MAC) >+ // In the case of base system, which doesn't have AppSSO.framework. >+ if (!PAL::getSOAuthorizationClass()) >+ return; >+#endif >+ m_soAuthorization = adoptNS([PAL::allocSOAuthorizationInstance() init]); >+ m_soAuthorizationDelegate = adoptNS([[WKSOAuthorizationDelegate alloc] init]); >+ m_soAuthorization.get().delegate = m_soAuthorizationDelegate.get(); >+ [NSURLSession _disableAppSSO]; >+} >+ >+bool SOAuthorizationCoordinator::canAuthorize(const URL& url) const >+{ >+ return m_soAuthorization && [PAL::getSOAuthorizationClass() canPerformAuthorizationWithURL:url responseCode:0]; >+} >+ >+void SOAuthorizationCoordinator::tryAuthorize(Ref<API::NavigationAction>&& navigationAction, WebPageProxy& page, Function<void(bool)>&& completionHandler) >+{ >+ if (!canAuthorize(navigationAction->request().url())) { >+ completionHandler(false); >+ return; >+ } >+ >+ // SubFrameSOAuthorizationSession should only be allowed for Apple first parties. >+ bool subframeNavigation = navigationAction->targetFrame() && !navigationAction->targetFrame()->isMainFrame(); >+ if (subframeNavigation && (!page.mainFrame() || ![AKAuthorizationController isURLFromAppleOwnedDomain:page.mainFrame()->url()])) { >+ completionHandler(false); >+ return; >+ } >+ >+ auto session = subframeNavigation ? SubFrameSOAuthorizationSession::create(m_soAuthorization.get(), WTFMove(navigationAction), page, WTFMove(completionHandler)) : RedirectSOAuthorizationSession::create(m_soAuthorization.get(), WTFMove(navigationAction), page, WTFMove(completionHandler)); >+ [m_soAuthorizationDelegate setSession:WTFMove(session)]; >+} >+ >+void SOAuthorizationCoordinator::tryAuthorize(Ref<API::NavigationAction>&& navigationAction, WebPageProxy& page, NewPageCallback&& newPageCallback, UIClientCallback&& uiClientCallback) >+{ >+ bool subframeNavigation = navigationAction->sourceFrame() && !navigationAction->sourceFrame()->isMainFrame(); >+ if (subframeNavigation || !navigationAction->isProcessingUserGesture() || !canAuthorize(navigationAction->request().url())) { >+ uiClientCallback(WTFMove(navigationAction), WTFMove(newPageCallback)); >+ return; >+ } >+ >+ auto session = PopUpSOAuthorizationSession::create(m_soAuthorization.get(), page, WTFMove(navigationAction), WTFMove(newPageCallback), WTFMove(uiClientCallback)); >+ [m_soAuthorizationDelegate setSession:WTFMove(session)]; >+} >+ >+} // namespace WebKit >+ >+#endif >diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SOAuthorizationNSURLExtras.h b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SOAuthorizationNSURLExtras.h >new file mode 100644 >index 0000000000000000000000000000000000000000..7eb609d95ddd1763c21919d090275d35aae61721 >--- /dev/null >+++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SOAuthorizationNSURLExtras.h >@@ -0,0 +1,37 @@ >+/* >+ * Copyright (C) 2019 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. >+ */ >+ >+#pragma once >+ >+#if HAVE(APP_SSO) >+ >+// FIXME rdar://problem/50028246 Remove the following once the radar is fixed. >+@interface NSURL (SOAuthorizationExtras) >+ >++ (BOOL)_web_canPerformAuthorizationWithURL:(NSURL *)url; >+ >+@end >+ >+#endif >diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SOAuthorizationNSURLExtras.mm b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SOAuthorizationNSURLExtras.mm >new file mode 100644 >index 0000000000000000000000000000000000000000..25a0edb61cb7f06ade57a2a746eae601b004abf8 >--- /dev/null >+++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SOAuthorizationNSURLExtras.mm >@@ -0,0 +1,42 @@ >+/* >+ * Copyright (C) 2019 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 "SOAuthorizationNSURLExtras.h" >+ >+#if HAVE(APP_SSO) >+ >+#import <pal/cocoa/AppSSOSoftLink.h> >+ >+@implementation NSURL (SOAuthorizationExtras) >+ >++ (BOOL)_web_canPerformAuthorizationWithURL:(NSURL *)url >+{ >+ return [PAL::getSOAuthorizationClass() canPerformAuthorizationWithURL:url responseCode:0]; >+} >+ >+@end >+ >+#endif >diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SOAuthorizationSession.h b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SOAuthorizationSession.h >new file mode 100644 >index 0000000000000000000000000000000000000000..1d1db23d9fbd52f146f048cf987892af9a82e48f >--- /dev/null >+++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SOAuthorizationSession.h >@@ -0,0 +1,121 @@ >+/* >+ * Copyright (C) 2019 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. >+ */ >+ >+#pragma once >+ >+#if HAVE(APP_SSO) >+ >+#include <AppSSO/SOBase.h> >+#include <wtf/Forward.h> >+#include <wtf/RefCounted.h> >+#include <wtf/RetainPtr.h> >+#include <wtf/WeakObjCPtr.h> >+#include <wtf/WeakPtr.h> >+ >+OBJC_CLASS SOAuthorization; >+ >+namespace API { >+class NavigationAction; >+} >+ >+namespace WebCore { >+class ResourceResponse; >+} >+ >+namespace WebKit { >+ >+class WebPageProxy; >+ >+// A session will only be executed once. >+class SOAuthorizationSession : public RefCounted<SOAuthorizationSession>, public CanMakeWeakPtr<SOAuthorizationSession> { >+public: >+ enum class InitiatingAction : uint8_t { >+ Redirect, >+ PopUp, >+ SubFrame >+ }; >+ >+ using UICallback = void (^)(BOOL, NSError *); >+ >+ virtual ~SOAuthorizationSession(); >+ >+ // Probably not start immediately. >+ void shouldStart(); >+ >+ // The following should only be called by SOAuthorizationDelegate methods. >+ void fallBackToWebPath(); >+ void abort(); >+ // Only responses that meet all of the following requirements will be processed: >+ // 1) it has the same origin as the request; >+ // 2) it has a status code of 302 or 200. >+ // Otherwise, it falls back to the web path. >+ // Only the following HTTP headers will be processed: >+ // { Set-Cookie, Location }. >+ void complete(NSHTTPURLResponse *, NSData *); >+ void presentViewController(SOAuthorizationViewController, UICallback); >+ >+protected: >+ // FSM depends on derived classes. >+ enum class State : uint8_t { >+ Idle, >+ Active, >+ Waiting, >+ Completed >+ }; >+ >+ SOAuthorizationSession(SOAuthorization *, Ref<API::NavigationAction>&&, WebPageProxy&, InitiatingAction); >+ >+ void start(); >+ WebPageProxy* page() const { return m_page.get(); } >+ State state() const { return m_state; } >+ void setState(State state) { m_state = state; } >+ const API::NavigationAction* navigationAction() { return m_navigationAction.get(); } >+ Ref<API::NavigationAction> releaseNavigationAction(); >+ >+private: >+ virtual void shouldStartInternal() = 0; >+ virtual void fallBackToWebPathInternal() = 0; >+ virtual void abortInternal() = 0; >+ virtual void completeInternal(WebCore::ResourceResponse&&, NSData *) = 0; >+ >+ void becomeCompleted(); >+ void dismissViewController(); >+ >+ State m_state { State::Idle }; >+ WeakObjCPtr<SOAuthorization *> m_soAuthorization; >+ RefPtr<API::NavigationAction> m_navigationAction; >+ WeakPtr<WebPageProxy> m_page; >+ InitiatingAction m_action; >+ >+ RetainPtr<SOAuthorizationViewController> m_viewController; >+#if PLATFORM(MAC) >+ RetainPtr<NSWindow> m_sheetWindow; >+ RetainPtr<NSObject> m_sheetWindowWillCloseObserver; >+#endif >+}; >+ >+} // namespace WebKit >+ >+#endif >diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SOAuthorizationSession.mm b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SOAuthorizationSession.mm >new file mode 100644 >index 0000000000000000000000000000000000000000..83bb5c6cb6a09d71149e792448785476c2837392 >--- /dev/null >+++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SOAuthorizationSession.mm >@@ -0,0 +1,230 @@ >+/* >+ * Copyright (C) 2019 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. >+ */ >+ >+#include "config.h" >+#include "SOAuthorizationSession.h" >+ >+#if HAVE(APP_SSO) >+ >+#import "APIHTTPCookieStore.h" >+#import "APINavigation.h" >+#import "APINavigationAction.h" >+#import "APIUIClient.h" >+#import "WKUIDelegate.h" >+#import "WebPageProxy.h" >+#import "WebSiteDataStore.h" >+#import <WebCore/ResourceResponse.h> >+#import <WebCore/SecurityOrigin.h> >+#import <pal/cocoa/AppSSOSoftLink.h> >+#import <wtf/Vector.h> >+ >+namespace WebKit { >+ >+namespace { >+ >+static Vector<WebCore::Cookie> toCookieVector(NSArray<NSHTTPCookie *> *cookies) >+{ >+ Vector<WebCore::Cookie> result; >+ result.reserveInitialCapacity(cookies.count); >+ for (id cookie in cookies) >+ result.uncheckedAppend(cookie); >+ return result; >+} >+ >+static bool isSameOrigin(const WebCore::ResourceRequest& request, const WebCore::ResourceResponse& response) >+{ >+ auto requestOrigin = WebCore::SecurityOrigin::create(request.url()); >+ return requestOrigin->isSameOriginAs(WebCore::SecurityOrigin::create(response.url()).get()); >+} >+ >+} // namespace >+ >+SOAuthorizationSession::SOAuthorizationSession(SOAuthorization *soAuthorization, Ref<API::NavigationAction>&& navigationAction, WebPageProxy& page, InitiatingAction action) >+ : m_soAuthorization(soAuthorization) >+ , m_navigationAction(WTFMove(navigationAction)) >+ , m_page(makeWeakPtr(page)) >+ , m_action(action) >+{ >+} >+ >+SOAuthorizationSession::~SOAuthorizationSession() >+{ >+ if (m_state == State::Active && !!m_soAuthorization) >+ [m_soAuthorization cancelAuthorization]; >+ if (m_state != State::Idle && m_state != State::Completed) >+ becomeCompleted(); >+} >+ >+Ref<API::NavigationAction> SOAuthorizationSession::releaseNavigationAction() >+{ >+ return m_navigationAction.releaseNonNull(); >+} >+ >+void SOAuthorizationSession::becomeCompleted() >+{ >+ ASSERT(m_state == State::Active || m_state == State::Waiting); >+ m_state = State::Completed; >+ if (m_viewController) >+ dismissViewController(); >+} >+ >+void SOAuthorizationSession::shouldStart() >+{ >+ ASSERT(m_state == State::Idle); >+ if (!m_page) >+ return; >+ shouldStartInternal(); >+} >+ >+void SOAuthorizationSession::start() >+{ >+ ASSERT((m_state == State::Idle || m_state == State::Waiting) && m_page && m_navigationAction); >+ m_state = State::Active; >+ if (!m_soAuthorization) >+ return; >+ >+ // FIXME<rdar://problem/48909336>: Replace the below with AppSSO constants. >+ auto initiatorOrigin = emptyString(); >+ if (m_navigationAction->sourceFrame()) >+ initiatorOrigin = m_navigationAction->sourceFrame()->securityOrigin().securityOrigin().toString(); >+ if (m_action == InitiatingAction::SubFrame && m_page->mainFrame()) >+ initiatorOrigin = WebCore::SecurityOrigin::create(m_page->mainFrame()->url())->toString(); >+ NSDictionary *authorizationOptions = @{ >+ SOAuthorizationOptionUserActionInitiated: @(m_navigationAction->isProcessingUserGesture()), >+ @"initiatorOrigin": (NSString *)initiatorOrigin, >+ @"initiatingAction": @(static_cast<NSInteger>(m_action)) >+ }; >+ [m_soAuthorization setAuthorizationOptions:authorizationOptions]; >+ >+ auto *nsRequest = m_navigationAction->request().nsURLRequest(WebCore::HTTPBodyUpdatePolicy::UpdateHTTPBody); >+ [m_soAuthorization beginAuthorizationWithURL:nsRequest.URL httpHeaders:nsRequest.allHTTPHeaderFields httpBody:nsRequest.HTTPBody]; >+} >+ >+void SOAuthorizationSession::fallBackToWebPath() >+{ >+ if (m_state != State::Active) >+ return; >+ becomeCompleted(); >+ fallBackToWebPathInternal(); >+} >+ >+void SOAuthorizationSession::abort() >+{ >+ if (m_state == State::Idle || m_state == State::Completed) >+ return; >+ becomeCompleted(); >+ abortInternal(); >+} >+ >+void SOAuthorizationSession::complete(NSHTTPURLResponse *httpResponse, NSData *data) >+{ >+ if (m_state != State::Active) >+ return; >+ ASSERT(m_navigationAction); >+ becomeCompleted(); >+ >+ auto response = WebCore::ResourceResponse(httpResponse); >+ if (!isSameOrigin(m_navigationAction->request(), response)) { >+ fallBackToWebPathInternal(); >+ return; >+ } >+ >+ // Set cookies. >+ auto cookies = toCookieVector([NSHTTPCookie cookiesWithResponseHeaderFields:httpResponse.allHeaderFields forURL:response.url()]); >+ if (cookies.isEmpty()) { >+ completeInternal(WTFMove(response), data); >+ return; >+ } >+ >+ if (!m_page) >+ return; >+ m_page->websiteDataStore().cookieStore().setCookies(cookies, [weakThis = makeWeakPtr(*this), response = WTFMove(response), data = adoptNS([[NSData alloc] initWithData:data])] () mutable { >+ if (!weakThis) >+ return; >+ weakThis->completeInternal(WTFMove(response), data.get()); >+ }); >+} >+ >+void SOAuthorizationSession::presentViewController(SOAuthorizationViewController viewController, UICallback uiCallback) >+{ >+ ASSERT(m_state == State::Active); >+ // Only expect at most one UI session for the whole authorization session. >+ if (!m_page || m_viewController) { >+ uiCallback(NO, adoptNS([[NSError alloc] initWithDomain:SOErrorDomain code:kSOErrorAuthorizationPresentationFailed userInfo:nil]).get()); >+ return; >+ } >+ >+ m_viewController = viewController; >+#if PLATFORM(MAC) >+ ASSERT(!m_sheetWindow); >+ m_sheetWindow = [NSWindow windowWithContentViewController:m_viewController.get()]; >+ >+ ASSERT(!m_sheetWindowWillCloseObserver); >+ m_sheetWindowWillCloseObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSWindowWillCloseNotification object:m_sheetWindow.get() queue:nil usingBlock:[weakThis = makeWeakPtr(*this)] (NSNotification *) { >+ if (!weakThis) >+ return; >+ weakThis->dismissViewController(); >+ }]; >+ >+ NSWindow *presentingWindow = m_page->platformWindow(); >+ if (!presentingWindow) { >+ uiCallback(NO, adoptNS([[NSError alloc] initWithDomain:SOErrorDomain code:kSOErrorAuthorizationPresentationFailed userInfo:nil]).get()); >+ return; >+ } >+ [presentingWindow beginSheet:m_sheetWindow.get() completionHandler:nil]; >+#elif PLATFORM(IOS) >+ UIViewController *presentingViewController = m_page->uiClient().presentingViewController(); >+ if (!presentingViewController) { >+ uiCallback(NO, adoptNS([[NSError alloc] initWithDomain:SOErrorDomain code:kSOErrorAuthorizationPresentationFailed userInfo:nil]).get()); >+ return; >+ } >+ >+ [presentingViewController presentViewController:m_viewController.get() animated:YES completion:nil]; >+#endif >+ >+ uiCallback(YES, nil); >+} >+ >+void SOAuthorizationSession::dismissViewController() >+{ >+ ASSERT(m_viewController); >+#if PLATFORM(MAC) >+ ASSERT(m_sheetWindow && m_sheetWindowWillCloseObserver); >+ >+ [[NSNotificationCenter defaultCenter] removeObserver:m_sheetWindowWillCloseObserver.get()]; >+ m_sheetWindowWillCloseObserver = nullptr; >+ >+ [[m_sheetWindow sheetParent] endSheet:m_sheetWindow.get()]; >+ m_sheetWindow = nullptr; >+#elif PLATFORM(IOS) >+ [[m_viewController presentingViewController] dismissViewControllerAnimated:YES completion:nil]; >+#endif >+ >+ m_viewController = nullptr; >+} >+ >+} // namespace WebKit >+ >+#endif >diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.h b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.h >new file mode 100644 >index 0000000000000000000000000000000000000000..3b6c3c9902c00b2541bc1d9434eb1f7e0289cb8a >--- /dev/null >+++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.h >@@ -0,0 +1,64 @@ >+/* >+ * Copyright (C) 2019 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. >+ */ >+ >+#pragma once >+ >+#if HAVE(APP_SSO) >+ >+#include "NavigationSOAuthorizationSession.h" >+ >+namespace IPC { >+class DataReference; >+} >+ >+namespace WebKit { >+ >+class SubFrameSOAuthorizationSession final : public NavigationSOAuthorizationSession { >+public: >+ using Callback = CompletionHandler<void(bool)>; >+ >+ static Ref<SOAuthorizationSession> create(SOAuthorization *soAuthorization, Ref<API::NavigationAction>&& navigationAction, WebPageProxy& page, Callback&& completionHandler) >+ { >+ return adoptRef(*new SubFrameSOAuthorizationSession(soAuthorization, WTFMove(navigationAction), page, WTFMove(completionHandler))); >+ } >+ >+private: >+ SubFrameSOAuthorizationSession(SOAuthorization *, Ref<API::NavigationAction>&&, WebPageProxy&, Callback&&); >+ >+ // SOAuthorizationSession >+ void fallBackToWebPathInternal() final; >+ void abortInternal() final; >+ void completeInternal(WebCore::ResourceResponse&&, NSData *) final; >+ >+ // NavigationSOAuthorizationSession >+ void beforeStart() final; >+ >+ void loadDataToFrame(const IPC::DataReference&, const URL&); >+ void postDidCancelMessageToParent(Function<void()>&&); >+}; >+ >+} // namespace WebKit >+ >+#endif >diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.mm b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.mm >new file mode 100644 >index 0000000000000000000000000000000000000000..5c9a8efc045954ed89159abacb082ae373982c49 >--- /dev/null >+++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.mm >@@ -0,0 +1,130 @@ >+/* >+ * Copyright (C) 2019 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 "SubFrameSOAuthorizationSession.h" >+ >+#if HAVE(APP_SSO) >+ >+#import "APIFrameHandle.h" >+#import "APINavigationAction.h" >+#import "DataReference.h" >+#import "WebPageProxy.h" >+#import "WebProcessProxy.h" >+#import <WebCore/ResourceResponse.h> >+#import <wtf/RunLoop.h> >+ >+namespace WebKit { >+using namespace WebCore; >+ >+const char* soAuthorizationPostDidStartMessageToParent = "<script>parent.postMessage('SOAuthorizationDidStart', '*');</script>"; >+const char* soAuthorizationPostDidCancelMessageToParent = "parent.postMessage('SOAuthorizationDidCancel', '*');"; >+ >+SubFrameSOAuthorizationSession::SubFrameSOAuthorizationSession(SOAuthorization *soAuthorization, Ref<API::NavigationAction>&& navigationAction, WebPageProxy& page, Callback&& completionHandler) >+ : NavigationSOAuthorizationSession(soAuthorization, WTFMove(navigationAction), page, InitiatingAction::SubFrame, WTFMove(completionHandler)) >+{ >+} >+ >+void SubFrameSOAuthorizationSession::fallBackToWebPathInternal() >+{ >+ // Instead of issuing a load, we execute the Javascript directly. This provides us a callback >+ // to ensure the final load is issued after the message is posted. >+ postDidCancelMessageToParent([weakThis = makeWeakPtr(*this)] { >+ if (!weakThis) >+ return; >+ auto* pagePtr = weakThis->page(); >+ auto* navigationActionPtr = weakThis->navigationAction(); >+ if (!pagePtr || !navigationActionPtr) >+ return; >+ >+ if (auto* targetFrame = navigationActionPtr->targetFrame()) { >+ if (auto* frame = pagePtr->process().webFrame(targetFrame->handle().frameID())) { >+ pagePtr->setShouldSuppressSOAuthorizationInNextNavigationPolicyDecision(); >+ // Issue a new load to the original URL as the original load is aborted before start. >+ frame->loadURL(navigationActionPtr->request().url()); >+ } >+ } >+ }); >+} >+ >+void SubFrameSOAuthorizationSession::abortInternal() >+{ >+ ASSERT_NOT_REACHED(); >+} >+ >+void SubFrameSOAuthorizationSession::completeInternal(WebCore::ResourceResponse&& response, NSData *data) >+{ >+ if (response.httpStatusCode() != 200) { >+ fallBackToWebPathInternal(); >+ return; >+ } >+ loadDataToFrame(IPC::DataReference(reinterpret_cast<const uint8_t*>(data.bytes), data.length), response.url()); >+} >+ >+void SubFrameSOAuthorizationSession::beforeStart() >+{ >+ // Cancelled the current load before loading the data to post SOAuthorizationDidStart to the parent frame. >+ callback(true); >+ // Currently in the middle of decidePolicyForNavigationAction, should start a new load after. >+ RunLoop::main().dispatch([weakThis = makeWeakPtr(*this)] { >+ if (!weakThis || !weakThis->page() || !weakThis->navigationAction()) >+ return; >+ // Instead of executing the Javascript directly, issuing a load. This will set the origin properly. >+ weakThis->loadDataToFrame(IPC::DataReference(reinterpret_cast<const uint8_t*>(soAuthorizationPostDidStartMessageToParent), strlen(soAuthorizationPostDidStartMessageToParent)), weakThis->navigationAction()->request().url()); >+ }); >+} >+ >+void SubFrameSOAuthorizationSession::loadDataToFrame(const IPC::DataReference& data, const URL& baseURL) >+{ >+ auto* pagePtr = page(); >+ auto* navigationActionPtr = navigationAction(); >+ if (!pagePtr || !navigationActionPtr) >+ return; >+ >+ if (auto* targetFrame = navigationActionPtr->targetFrame()) { >+ if (auto* frame = pagePtr->process().webFrame(targetFrame->handle().frameID())) { >+ pagePtr->setShouldSuppressSOAuthorizationInNextNavigationPolicyDecision(); >+ frame->loadData(data, "text/html", "UTF-8", baseURL); >+ } >+ } >+} >+ >+void SubFrameSOAuthorizationSession::postDidCancelMessageToParent(Function<void()>&& callback) >+{ >+ auto* pagePtr = page(); >+ auto* navigationActionPtr = navigationAction(); >+ if (!pagePtr || !navigationActionPtr) >+ return; >+ >+ if (auto* targetFrame = navigationActionPtr->targetFrame()) { >+ pagePtr->runJavaScriptInFrame(targetFrame->handle().frameID(), soAuthorizationPostDidCancelMessageToParent, false, [callback = WTFMove(callback)] (API::SerializedScriptValue*, bool, const ExceptionDetails&, ScriptValueCallback::Error) { >+ callback(); >+ }); >+ } >+} >+ >+} // namespace WebKit >+ >+#endif >diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/WKSOAuthorizationDelegate.h b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/WKSOAuthorizationDelegate.h >new file mode 100644 >index 0000000000000000000000000000000000000000..231dcc97c1652c6b54e48b734f1727900272db45 >--- /dev/null >+++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/WKSOAuthorizationDelegate.h >@@ -0,0 +1,47 @@ >+/* >+ * Copyright (C) 2019 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. >+ */ >+ >+#pragma once >+ >+#import <pal/cocoa/AppSSOSoftLink.h> >+#import <wtf/RefCounted.h> >+ >+#if HAVE(APP_SSO) >+ >+namespace WebKit { >+class SOAuthorizationSession; >+class WebPageProxy; >+} >+ >+@interface WKSOAuthorizationDelegate : NSObject <SOAuthorizationDelegate> { >+@package >+RefPtr<WebKit::SOAuthorizationSession> _session; >+} >+ >+- (void)setSession:(RefPtr<WebKit::SOAuthorizationSession>&&)session; >+ >+@end >+ >+#endif >diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/WKSOAuthorizationDelegate.mm b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/WKSOAuthorizationDelegate.mm >new file mode 100644 >index 0000000000000000000000000000000000000000..e0514f048e7e7f30aa43474e836b6053cc59dbaa >--- /dev/null >+++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/WKSOAuthorizationDelegate.mm >@@ -0,0 +1,120 @@ >+/* >+ * Copyright (C) 2019 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 "WKSOAuthorizationDelegate.h" >+ >+#if HAVE(APP_SSO) >+ >+#import "SOAuthorizationSession.h" >+#import <wtf/RunLoop.h> >+ >+@implementation WKSOAuthorizationDelegate >+ >+- (void)authorization:(SOAuthorization *)authorization presentViewController:(SOAuthorizationViewController)viewController withCompletion:(void (^)(BOOL success, NSError *error))completion >+{ >+ ASSERT(RunLoop::isMain() && completion); >+ if (!_session) { >+ ASSERT_NOT_REACHED(); >+ completion(NO, nil); >+ return; >+ } >+ _session->presentViewController(viewController, completion); >+} >+ >+- (void)authorizationDidNotHandle:(SOAuthorization *)authorization >+{ >+ ASSERT(RunLoop::isMain()); >+ LOG_ERROR("Could not handle AppSSO."); >+ if (!_session) { >+ ASSERT_NOT_REACHED(); >+ return; >+ } >+ _session->fallBackToWebPath(); >+} >+ >+- (void)authorizationDidCancel:(SOAuthorization *)authorization >+{ >+ ASSERT(RunLoop::isMain()); >+ if (!_session) { >+ ASSERT_NOT_REACHED(); >+ return; >+ } >+ _session->abort(); >+} >+ >+- (void)authorizationDidComplete:(SOAuthorization *)authorization >+{ >+ ASSERT(RunLoop::isMain()); >+ LOG_ERROR("Complete AppSSO without any data."); >+ if (!_session) { >+ ASSERT_NOT_REACHED(); >+ return; >+ } >+ _session->fallBackToWebPath(); >+} >+ >+- (void)authorization:(SOAuthorization *)authorization didCompleteWithHTTPAuthorizationHeaders:(NSDictionary *)httpAuthorizationHeaders >+{ >+ ASSERT(RunLoop::isMain()); >+ LOG_ERROR("Complete AppSSO with unexpected callback."); >+ if (!_session) { >+ ASSERT_NOT_REACHED(); >+ return; >+ } >+ _session->fallBackToWebPath(); >+} >+ >+- (void)authorization:(SOAuthorization *)authorization didCompleteWithHTTPResponse:(NSHTTPURLResponse *)httpResponse httpBody:(NSData *)httpBody >+{ >+ ASSERT(RunLoop::isMain()); >+ if (!_session) { >+ ASSERT_NOT_REACHED(); >+ return; >+ } >+ _session->complete(httpResponse, httpBody); >+} >+ >+- (void)authorization:(SOAuthorization *)authorization didCompleteWithError:(NSError *)error >+{ >+ ASSERT(RunLoop::isMain()); >+ LOG_ERROR("Could not complete AppSSO: %d", error.code); >+ if (!_session) { >+ ASSERT_NOT_REACHED(); >+ return; >+ } >+ _session->fallBackToWebPath(); >+} >+ >+- (void)setSession:(RefPtr<WebKit::SOAuthorizationSession>&&)session >+{ >+ _session = WTFMove(session); >+ if (_session) >+ _session->shouldStart(); >+} >+ >+@end >+ >+#endif >diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp >index 303e74fb73af8abfafda0a4b3b0722ab3c771199..15982ef2c8a870dba8860d11c253a309e8658851 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.cpp >+++ b/Source/WebKit/UIProcess/WebPageProxy.cpp >@@ -78,6 +78,7 @@ > #include "PluginProcessManager.h" > #include "PrintInfo.h" > #include "ProvisionalPageProxy.h" >+#include "SOAuthorizationCoordinator.h" > #include "SafeBrowsingWarning.h" > #include "ShareSheetCallbackID.h" > #include "SharedBufferDataReference.h" >@@ -4730,8 +4731,9 @@ void WebPageProxy::decidePolicyForNavigationAction(Ref<WebProcessProxy>&& proces > > auto navigationAction = API::NavigationAction::create(WTFMove(navigationActionData), sourceFrameInfo.get(), destinationFrameInfo.ptr(), WTF::nullopt, WTFMove(request), originalRequest.url(), shouldOpenAppLinks, WTFMove(userInitiatedActivity), mainFrameNavigation); > >-#if HAVE(LOAD_OPTIMIZER) >-WEBPAGEPROXY_LOADOPTIMIZER_ADDITIONS_3 >+#if HAVE(APP_SSO) >+ if (m_shouldSuppressSOAuthorizationInNextNavigationPolicyDecision || m_shouldSuppressSOAuthorizationInAllNavigationPolicyDecision) >+ navigationAction->unsetShouldPerformSOAuthorization(); > #endif > > m_navigationClient->decidePolicyForNavigationAction(*this, WTFMove(navigationAction), WTFMove(listener), process->transformHandlesToObjects(userData.object()).get()); >@@ -4739,8 +4741,8 @@ WEBPAGEPROXY_LOADOPTIMIZER_ADDITIONS_3 > > m_shouldSuppressAppLinksInNextNavigationPolicyDecision = false; > >-#if HAVE(LOAD_OPTIMIZER) >-WEBPAGEPROXY_LOADOPTIMIZER_ADDITIONS_4 >+#if HAVE(APP_SSO) >+ m_shouldSuppressSOAuthorizationInNextNavigationPolicyDecision = false; > #endif > } > >@@ -5029,10 +5031,10 @@ void WebPageProxy::didUpdateHistoryTitle(const String& title, const String& url, > > using NewPageCallback = CompletionHandler<void(RefPtr<WebPageProxy>&&)>; > using UIClientCallback = Function<void(Ref<API::NavigationAction>&&, NewPageCallback&&)>; >-static void tryOptimizingLoad(Ref<API::NavigationAction>&& navigationAction, WebPageProxy& page, NewPageCallback&& newPageCallback, UIClientCallback&& uiClientCallback) >+static void trySOAuthorization(Ref<API::NavigationAction>&& navigationAction, WebPageProxy& page, NewPageCallback&& newPageCallback, UIClientCallback&& uiClientCallback) > { >-#if HAVE(LOAD_OPTIMIZER) >-WEBPAGEPROXY_LOADOPTIMIZER_ADDITIONS_6 >+#if HAVE(APP_SSO) >+ page.websiteDataStore().soAuthorizationCoordinator().tryAuthorize(WTFMove(navigationAction), page, WTFMove(newPageCallback), WTFMove(uiClientCallback)); > #else > ASSERT_UNUSED(page, page.pageID()); > uiClientCallback(WTFMove(navigationAction), WTFMove(newPageCallback)); >@@ -5056,8 +5058,8 @@ void WebPageProxy::createNewPage(const FrameInfoData& originatingFrameInfoData, > > newPage->m_shouldSuppressAppLinksInNextNavigationPolicyDecision = hostsAreEqual(URL({ }, mainFrameURL), request.url()); > >-#if HAVE(LOAD_OPTIMIZER) >-WEBPAGEPROXY_LOADOPTIMIZER_ADDITIONS_5 >+#if HAVE(APP_SSO) >+ newPage->m_shouldSuppressSOAuthorizationInNextNavigationPolicyDecision = true; > #endif > }; > >@@ -5065,7 +5067,7 @@ WEBPAGEPROXY_LOADOPTIMIZER_ADDITIONS_5 > bool shouldOpenAppLinks = !hostsAreEqual(originatingFrameInfo->request().url(), request.url()); > auto navigationAction = API::NavigationAction::create(WTFMove(navigationActionData), originatingFrameInfo.ptr(), nullptr, WTF::nullopt, WTFMove(request), URL(), shouldOpenAppLinks, WTFMove(userInitiatedActivity)); > >- tryOptimizingLoad(WTFMove(navigationAction), *this, WTFMove(completionHandler), [this, protectedThis = makeRef(*this), windowFeatures = WTFMove(windowFeatures)] (Ref<API::NavigationAction>&& navigationAction, CompletionHandler<void(RefPtr<WebPageProxy>&&)>&& completionHandler) mutable { >+ trySOAuthorization(WTFMove(navigationAction), *this, WTFMove(completionHandler), [this, protectedThis = makeRef(*this), windowFeatures = WTFMove(windowFeatures)] (Ref<API::NavigationAction>&& navigationAction, CompletionHandler<void(RefPtr<WebPageProxy>&&)>&& completionHandler) mutable { > m_uiClient->createNewPage(*this, WTFMove(windowFeatures), WTFMove(navigationAction), WTFMove(completionHandler)); > }); > } >diff --git a/Source/WebKit/UIProcess/WebPageProxy.h b/Source/WebKit/UIProcess/WebPageProxy.h >index f54f67fe486ef1899b1328755cda0788f1cdb3da..681add85d60a6794a6ed38c05c432dee5afad9d2 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.h >+++ b/Source/WebKit/UIProcess/WebPageProxy.h >@@ -141,10 +141,6 @@ OBJC_CLASS _WKRemoteObjectRegistry; > #include <WebCore/WebMediaSessionManagerClient.h> > #endif > >-#if USE(APPLE_INTERNAL_SDK) >-#include <WebKitAdditions/WebPageProxyAdditions.h> >-#endif >- > #if ENABLE(MEDIA_SESSION) > namespace WebCore { > class MediaSessionMetadata; >@@ -1549,8 +1545,9 @@ public: > void removeObserver(WebViewDidMoveToWindowObserver&); > void webViewDidMoveToWindow(); > >-#if HAVE(LOAD_OPTIMIZER) >-WEBPAGEPROXY_LOADOPTIMIZER_ADDITIONS_1 >+#if HAVE(APP_SSO) >+ void setShouldSuppressSOAuthorizationInAllNavigationPolicyDecision() { m_shouldSuppressSOAuthorizationInAllNavigationPolicyDecision = true; } >+ void setShouldSuppressSOAuthorizationInNextNavigationPolicyDecision() { m_shouldSuppressSOAuthorizationInNextNavigationPolicyDecision = true; } > #endif > > Logger& logger(); >@@ -2288,8 +2285,9 @@ private: > WebCore::ResourceRequest m_decidePolicyForResponseRequest; > bool m_shouldSuppressAppLinksInNextNavigationPolicyDecision { false }; > >-#if HAVE(LOAD_OPTIMIZER) >-WEBPAGEPROXY_LOADOPTIMIZER_ADDITIONS_2 >+#if HAVE(APP_SSO) >+ bool m_shouldSuppressSOAuthorizationInNextNavigationPolicyDecision { false }; >+ bool m_shouldSuppressSOAuthorizationInAllNavigationPolicyDecision { false }; > #endif > > Deque<NativeWebMouseEvent> m_mouseEventQueue; >diff --git a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp >index c28a640f7773d40e2089094db68ca13ba76e3f52..c21dfb72754308908bae7bbba32314eeaf1dd4c6 100644 >--- a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp >+++ b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp >@@ -33,6 +33,7 @@ > #include "DeviceIdHashSaltStorage.h" > #include "MockAuthenticatorManager.h" > #include "NetworkProcessMessages.h" >+#include "SOAuthorizationCoordinator.h" > #include "ShouldGrandfatherStatistics.h" > #include "StorageAccessStatus.h" > #include "WebProcessCache.h" >@@ -103,10 +104,11 @@ WebsiteDataStore::WebsiteDataStore(Ref<WebsiteDataStoreConfiguration>&& configur > , m_authenticatorManager(makeUniqueRef<AuthenticatorManager>()) > #endif > , m_client(makeUniqueRef<WebsiteDataStoreClient>()) >-{ >-#if HAVE(LOAD_OPTIMIZER) >-WEBSITEDATASTORE_LOADOPTIMIZER_ADDITIONS_2 >+#if HAVE(APP_SSO) >+ , m_soAuthorizationCoordinator(makeUniqueRef<SOAuthorizationCoordinator>()) > #endif >+ >+{ > WTF::setProcessPrivileges(allPrivileges()); > maybeRegisterWithSessionIDMap(); > platformInitialize(); >@@ -124,10 +126,10 @@ WebsiteDataStore::WebsiteDataStore(PAL::SessionID sessionID) > , m_authenticatorManager(makeUniqueRef<AuthenticatorManager>()) > #endif > , m_client(makeUniqueRef<WebsiteDataStoreClient>()) >-{ >-#if HAVE(LOAD_OPTIMIZER) >-WEBSITEDATASTORE_LOADOPTIMIZER_ADDITIONS_2 >+#if HAVE(APP_SSO) >+ , m_soAuthorizationCoordinator(makeUniqueRef<SOAuthorizationCoordinator>()) > #endif >+{ > maybeRegisterWithSessionIDMap(); > platformInitialize(); > >diff --git a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h >index 822c3fc7637d7c5eb003c69ce94745bd382593f2..0b23501650fdcca7316ac5b5fbf45435116b4185 100644 >--- a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h >+++ b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h >@@ -56,10 +56,6 @@ > #include <WebCore/CurlProxySettings.h> > #endif > >-#if USE(APPLE_INTERNAL_SDK) >-#include <WebKitAdditions/WebsiteDataStoreAdditions.h> >-#endif >- > namespace API { > class HTTPCookieStore; > } >@@ -74,6 +70,7 @@ namespace WebKit { > class AuthenticatorManager; > class SecKeyProxyStore; > class DeviceIdHashSaltStorage; >+class SOAuthorizationCoordinator; > class WebPageProxy; > class WebProcessPool; > class WebResourceLoadStatisticsStore; >@@ -255,8 +252,8 @@ public: > WebDeviceOrientationAndMotionAccessController& deviceOrientationAndMotionAccessController() { return m_deviceOrientationAndMotionAccessController; } > #endif > >-#if HAVE(LOAD_OPTIMIZER) >-WEBSITEDATASTORE_LOADOPTIMIZER_ADDITIONS_1 >+#if HAVE(APP_SSO) >+ SOAuthorizationCoordinator& soAuthorizationCoordinator() { return m_soAuthorizationCoordinator.get(); } > #endif > > private: >@@ -336,6 +333,10 @@ private: > UniqueRef<WebsiteDataStoreClient> m_client; > > RefPtr<API::HTTPCookieStore> m_cookieStore; >+ >+#if HAVE(APP_SSO) >+ UniqueRef<SOAuthorizationCoordinator> m_soAuthorizationCoordinator; >+#endif > }; > > } >diff --git a/Source/WebKit/WebKit.xcodeproj/project.pbxproj b/Source/WebKit/WebKit.xcodeproj/project.pbxproj >index 5878a140972342095952d950c933a0830a0e34c9..a96b7d7aa5af608dd6e21dfc261488860490a19f 100644 >--- a/Source/WebKit/WebKit.xcodeproj/project.pbxproj >+++ b/Source/WebKit/WebKit.xcodeproj/project.pbxproj >@@ -1059,6 +1059,14 @@ > 57DCEDC7214F18300016B847 /* MockLocalConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 57DCEDC5214F18300016B847 /* MockLocalConnection.h */; }; > 57DCEDCB214F4E420016B847 /* MockAuthenticatorManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 57DCEDC9214F4E420016B847 /* MockAuthenticatorManager.h */; }; > 57EB2E3A21E1983E00B89CDF /* U2fHidAuthenticator.h in Headers */ = {isa = PBXBuildFile; fileRef = 57EB2E3821E1983E00B89CDF /* U2fHidAuthenticator.h */; }; >+ 57FD318022B35158008D0E8B /* NavigationSOAuthorizationSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 57FD317822B35149008D0E8B /* NavigationSOAuthorizationSession.h */; }; >+ 57FD318122B3515B008D0E8B /* PopUpSOAuthorizationSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 57FD317022B35148008D0E8B /* PopUpSOAuthorizationSession.h */; }; >+ 57FD318222B3515E008D0E8B /* RedirectSOAuthorizationSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 57FD317422B35149008D0E8B /* RedirectSOAuthorizationSession.h */; }; >+ 57FD318322B35162008D0E8B /* SOAuthorizationCoordinator.h in Headers */ = {isa = PBXBuildFile; fileRef = 57FD317222B35148008D0E8B /* SOAuthorizationCoordinator.h */; }; >+ 57FD318422B35165008D0E8B /* SOAuthorizationNSURLExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = 57FD317322B35148008D0E8B /* SOAuthorizationNSURLExtras.h */; }; >+ 57FD318522B35169008D0E8B /* SOAuthorizationSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 57FD317C22B3514A008D0E8B /* SOAuthorizationSession.h */; }; >+ 57FD318622B3516C008D0E8B /* SubFrameSOAuthorizationSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 57FD317D22B3514A008D0E8B /* SubFrameSOAuthorizationSession.h */; }; >+ 57FD318722B35170008D0E8B /* WKSOAuthorizationDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 57FD317122B35148008D0E8B /* WKSOAuthorizationDelegate.h */; }; > 587743A621C30BBE00AE9084 /* HTTPSUpgradeList.db in Resources */ = {isa = PBXBuildFile; fileRef = 587743A421C30AD800AE9084 /* HTTPSUpgradeList.db */; }; > 58E977DF21C49A00005D92A6 /* NetworkHTTPSUpgradeChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = 58E977DD21C49A00005D92A6 /* NetworkHTTPSUpgradeChecker.h */; }; > 5C0B17781E7C880E00E9123C /* NetworkSocketStreamMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C0B17741E7C879C00E9123C /* NetworkSocketStreamMessageReceiver.cpp */; }; >@@ -3499,6 +3507,22 @@ > 57DCEDCD214F51680016B847 /* MockAuthenticatorManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MockAuthenticatorManager.cpp; sourceTree = "<group>"; }; > 57EB2E3821E1983E00B89CDF /* U2fHidAuthenticator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = U2fHidAuthenticator.h; sourceTree = "<group>"; }; > 57EB2E3921E1983E00B89CDF /* U2fHidAuthenticator.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = U2fHidAuthenticator.cpp; sourceTree = "<group>"; }; >+ 57FD317022B35148008D0E8B /* PopUpSOAuthorizationSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PopUpSOAuthorizationSession.h; sourceTree = "<group>"; }; >+ 57FD317122B35148008D0E8B /* WKSOAuthorizationDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKSOAuthorizationDelegate.h; sourceTree = "<group>"; }; >+ 57FD317222B35148008D0E8B /* SOAuthorizationCoordinator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOAuthorizationCoordinator.h; sourceTree = "<group>"; }; >+ 57FD317322B35148008D0E8B /* SOAuthorizationNSURLExtras.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOAuthorizationNSURLExtras.h; sourceTree = "<group>"; }; >+ 57FD317422B35149008D0E8B /* RedirectSOAuthorizationSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RedirectSOAuthorizationSession.h; sourceTree = "<group>"; }; >+ 57FD317522B35149008D0E8B /* PopUpSOAuthorizationSession.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PopUpSOAuthorizationSession.mm; sourceTree = "<group>"; }; >+ 57FD317622B35149008D0E8B /* SOAuthorizationNSURLExtras.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SOAuthorizationNSURLExtras.mm; sourceTree = "<group>"; }; >+ 57FD317722B35149008D0E8B /* SubFrameSOAuthorizationSession.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SubFrameSOAuthorizationSession.mm; sourceTree = "<group>"; }; >+ 57FD317822B35149008D0E8B /* NavigationSOAuthorizationSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NavigationSOAuthorizationSession.h; sourceTree = "<group>"; }; >+ 57FD317922B35149008D0E8B /* SOAuthorizationCoordinator.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SOAuthorizationCoordinator.mm; sourceTree = "<group>"; }; >+ 57FD317A22B3514A008D0E8B /* RedirectSOAuthorizationSession.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RedirectSOAuthorizationSession.mm; sourceTree = "<group>"; }; >+ 57FD317B22B3514A008D0E8B /* NavigationSOAuthorizationSession.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NavigationSOAuthorizationSession.mm; sourceTree = "<group>"; }; >+ 57FD317C22B3514A008D0E8B /* SOAuthorizationSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOAuthorizationSession.h; sourceTree = "<group>"; }; >+ 57FD317D22B3514A008D0E8B /* SubFrameSOAuthorizationSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SubFrameSOAuthorizationSession.h; sourceTree = "<group>"; }; >+ 57FD317E22B3514A008D0E8B /* WKSOAuthorizationDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKSOAuthorizationDelegate.mm; sourceTree = "<group>"; }; >+ 57FD317F22B3514A008D0E8B /* SOAuthorizationSession.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SOAuthorizationSession.mm; sourceTree = "<group>"; }; > 587743A421C30AD800AE9084 /* HTTPSUpgradeList.db */ = {isa = PBXFileReference; lastKnownFileType = file; name = HTTPSUpgradeList.db; path = DerivedSources/WebKit2/HTTPSUpgradeList.db; sourceTree = BUILT_PRODUCTS_DIR; }; > 58E977DC21C499FE005D92A6 /* NetworkHTTPSUpgradeChecker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkHTTPSUpgradeChecker.cpp; sourceTree = "<group>"; }; > 58E977DD21C49A00005D92A6 /* NetworkHTTPSUpgradeChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkHTTPSUpgradeChecker.h; sourceTree = "<group>"; }; >@@ -5444,6 +5468,7 @@ > 1ABC3DF21899E415004F0626 /* Cocoa */ = { > isa = PBXGroup; > children = ( >+ 57FD316B22B3367E008D0E8B /* SOAuthorization */, > 99C81D551C20DFBE005C4C82 /* AutomationClient.h */, > 99C81D561C20DFBE005C4C82 /* AutomationClient.mm */, > 990D28B71C6539A000986977 /* AutomationSessionClient.h */, >@@ -7004,6 +7029,29 @@ > path = Mock; > sourceTree = "<group>"; > }; >+ 57FD316B22B3367E008D0E8B /* SOAuthorization */ = { >+ isa = PBXGroup; >+ children = ( >+ 57FD317822B35149008D0E8B /* NavigationSOAuthorizationSession.h */, >+ 57FD317B22B3514A008D0E8B /* NavigationSOAuthorizationSession.mm */, >+ 57FD317022B35148008D0E8B /* PopUpSOAuthorizationSession.h */, >+ 57FD317522B35149008D0E8B /* PopUpSOAuthorizationSession.mm */, >+ 57FD317422B35149008D0E8B /* RedirectSOAuthorizationSession.h */, >+ 57FD317A22B3514A008D0E8B /* RedirectSOAuthorizationSession.mm */, >+ 57FD317222B35148008D0E8B /* SOAuthorizationCoordinator.h */, >+ 57FD317922B35149008D0E8B /* SOAuthorizationCoordinator.mm */, >+ 57FD317322B35148008D0E8B /* SOAuthorizationNSURLExtras.h */, >+ 57FD317622B35149008D0E8B /* SOAuthorizationNSURLExtras.mm */, >+ 57FD317C22B3514A008D0E8B /* SOAuthorizationSession.h */, >+ 57FD317F22B3514A008D0E8B /* SOAuthorizationSession.mm */, >+ 57FD317D22B3514A008D0E8B /* SubFrameSOAuthorizationSession.h */, >+ 57FD317722B35149008D0E8B /* SubFrameSOAuthorizationSession.mm */, >+ 57FD317122B35148008D0E8B /* WKSOAuthorizationDelegate.h */, >+ 57FD317E22B3514A008D0E8B /* WKSOAuthorizationDelegate.mm */, >+ ); >+ path = SOAuthorization; >+ sourceTree = "<group>"; >+ }; > 5C1426F11C23F81700D41183 /* Downloads */ = { > isa = PBXGroup; > children = ( >@@ -9398,6 +9446,7 @@ > 2D50366B1BCDE17900E20BB3 /* NativeWebGestureEvent.h in Headers */, > 263172CF18B469490065B9C3 /* NativeWebTouchEvent.h in Headers */, > 1ADCB86B189831B30022EE5A /* NavigationActionData.h in Headers */, >+ 57FD318022B35158008D0E8B /* NavigationSOAuthorizationSession.h in Headers */, > 1ABC3DF61899E437004F0626 /* NavigationState.h in Headers */, > 1A6FBA2A11E6862700DB1371 /* NetscapeBrowserFuncs.h in Headers */, > 1A6FBD2811E69BC200DB1371 /* NetscapePlugin.h in Headers */, >@@ -9515,6 +9564,7 @@ > 1A4A9F3312B844E2008FE984 /* PluginQuirks.h in Headers */, > 7CD622781739D863005BD7FF /* PluginSandboxProfile.h in Headers */, > 1A6FB7AF11E64B6800DB1371 /* PluginView.h in Headers */, >+ 57FD318122B3515B008D0E8B /* PopUpSOAuthorizationSession.h in Headers */, > 83A0ED351F747CCF003299EB /* PreconnectTask.h in Headers */, > AAB145E6223F931200E489D8 /* PrefetchCache.h in Headers */, > E1CC1B9012D7EADF00625838 /* PrintInfo.h in Headers */, >@@ -9526,6 +9576,7 @@ > 83048AE61ACA45DC0082C832 /* ProcessThrottlerClient.h in Headers */, > A1E688701F6E2BAB007006A6 /* QuarantineSPI.h in Headers */, > A118A9EF1907AD6F00F7C92B /* QuickLookDocumentData.h in Headers */, >+ 57FD318222B3515E008D0E8B /* RedirectSOAuthorizationSession.h in Headers */, > 2D47B56D1810714E003A3AEE /* RemoteLayerBackingStore.h in Headers */, > 2DDF731518E95060004F5A66 /* RemoteLayerBackingStoreCollection.h in Headers */, > 1AB16AEA164B3A8800290D62 /* RemoteLayerTreeContext.h in Headers */, >@@ -9588,6 +9639,9 @@ > 995226D6207D184600F78420 /* SimulatedInputDispatcher.h in Headers */, > 2DAF06D618BD1A470081CEB1 /* SmartMagnificationController.h in Headers */, > 2DE6943E18BD2A68005C15E5 /* SmartMagnificationControllerMessages.h in Headers */, >+ 57FD318322B35162008D0E8B /* SOAuthorizationCoordinator.h in Headers */, >+ 57FD318422B35165008D0E8B /* SOAuthorizationNSURLExtras.h in Headers */, >+ 57FD318522B35169008D0E8B /* SOAuthorizationSession.h in Headers */, > 5272B28B1406985D0096A5D0 /* StatisticsData.h in Headers */, > 514BDED316C98EDD00E4E25E /* StatisticsRequest.h in Headers */, > 7A3FECA221F7C09700F267CD /* StorageAccessStatus.h in Headers */, >@@ -9598,6 +9652,7 @@ > 1AB31A9716BC688100F6DBC9 /* StorageManagerMessages.h in Headers */, > 1AE00D6C18327C1200087DD7 /* StringReference.h in Headers */, > 296BD85D15019BC30071F424 /* StringUtilities.h in Headers */, >+ 57FD318622B3516C008D0E8B /* SubFrameSOAuthorizationSession.h in Headers */, > 4459984222833E8700E61373 /* SyntheticEditingCommandType.h in Headers */, > 3157135F2040A9B20084F9CF /* SystemPreviewController.h in Headers */, > CE1A0BD61A48E6C60054EF74 /* TCCSPI.h in Headers */, >@@ -10156,6 +10211,7 @@ > 1DB01943211CF002009FB3E8 /* WKShareSheet.h in Headers */, > 513E462D1AD837560016234A /* WKSharingServicePickerDelegate.h in Headers */, > 93F549B41E3174B7000E7239 /* WKSnapshotConfiguration.h in Headers */, >+ 57FD318722B35170008D0E8B /* WKSOAuthorizationDelegate.h in Headers */, > 7A78FF32224191960096483E /* WKStorageAccessAlert.h in Headers */, > BC407606124FF0270068F20A /* WKString.h in Headers */, > BC40761A124FF0370068F20A /* WKStringCF.h in Headers */, >diff --git a/Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm b/Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm >index 37eb4afaef61212ebf3c2e3390fdc51bd810b9f8..bb16f8a1952d3574b2fd3ce952e1becde0dd4e56 100644 >--- a/Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm >+++ b/Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm >@@ -457,7 +457,7 @@ void WebProcess::platformInitializeProcess(const AuxiliaryProcessInitializationP > registerWithStateDumper(); > #endif > >-#if HAVE(LOAD_OPTIMIZER) >+#if HAVE(APP_SSO) > [NSURLSession _disableAppSSO]; > #endif > } >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index e3aa4e9379b70b74b726ca9930cf354aaef9b7ce..2d7bd28091d644fcad634e4743c9a36f92e8cf52 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,34 @@ >+2019-06-14 Jiewen Tan <jiewen_tan@apple.com> >+ >+ Move SOAuthorization from WebKitAdditions to WebKit >+ https://bugs.webkit.org/show_bug.cgi?id=198874 >+ <rdar://problem/47573431> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This patch moves all SOAuthorization tests from WebKitAdditions to WebKit. >+ >+ * TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig: >+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: >+ * TestWebKitAPI/Tests/WebKitCocoa/TestSOAuthorization.mm: Added. >+ (-[TestSOAuthorizationNavigationDelegate init]): >+ (-[TestSOAuthorizationNavigationDelegate webView:didFinishNavigation:]): >+ (-[TestSOAuthorizationNavigationDelegate webView:decidePolicyForNavigationAction:decisionHandler:]): >+ (-[TestSOAuthorizationNavigationDelegate webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:]): >+ (-[TestSOAuthorizationViewController viewDidAppear]): >+ (-[TestSOAuthorizationViewController viewDidDisappear]): >+ (overrideCanPerformAuthorizationWithURL): >+ (overrideSetDelegate): >+ (overrideBeginAuthorizationWithURL): >+ (overrideCancelAuthorization): >+ (overrideAddObserverForName): >+ (overrideIsURLFromAppleOwnedDomain): >+ (resetState): >+ (configureSOAuthorizationWebView): >+ (generateHtml): >+ (checkAuthorizationOptions): >+ (TestWebKitAPI::TEST): >+ > 2019-06-14 Youenn Fablet <youenn@apple.com> > > import-w3c-tests should respect WEBKIT_OUTPUTDIR >diff --git a/Tools/TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig b/Tools/TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig >index c6dfb333a5f853a9d5e899c79546540ed408432f..891a6f31cca7cf058cf59cb45e5f60c674edf5f6 100644 >--- a/Tools/TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig >+++ b/Tools/TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig >@@ -28,7 +28,14 @@ GCC_ENABLE_OBJC_EXCEPTIONS = YES; > > UNEXPORTED_SYMBOL_LDFLAGS = -Wl,-unexported_symbol -Wl,__ZN7testing4Test16TearDownTestCaseEv -Wl,-unexported_symbol -Wl,__ZN7testing4Test13SetUpTestCaseEv > >-OTHER_LDFLAGS = $(inherited) $(UNEXPORTED_SYMBOL_LDFLAGS) -lgtest -force_load $(BUILT_PRODUCTS_DIR)/libTestWebKitAPI.a -framework JavaScriptCore -framework WebKit -lWebCoreTestSupport $(OTHER_LDFLAGS_PLATFORM); >+WK_AUTHKIT_LDFLAGS = $(WK_AUTHKIT_LDFLAGS_$(WK_PLATFORM_NAME)); >+WK_AUTHKIT_LDFLAGS_iphoneos = $(WK_AUTHKIT_LDFLAGS$(WK_IOS_13)); >+WK_AUTHKIT_LDFLAGS_iphonesimulator = $(WK_AUTHKIT_LDFLAGS$(WK_IOS_13)); >+WK_AUTHKIT_LDFLAGS_IOS_SINCE_13 = -framework AuthKit; >+WK_AUTHKIT_LDFLAGS_macosx = $(WK_AUTHKIT_LDFLAGS$(WK_MACOS_1015)); >+WK_AUTHKIT_LDFLAGS_MACOS_SINCE_1015 = -framework AuthKit; >+ >+OTHER_LDFLAGS = $(inherited) $(UNEXPORTED_SYMBOL_LDFLAGS) -lgtest -force_load $(BUILT_PRODUCTS_DIR)/libTestWebKitAPI.a -framework JavaScriptCore -framework WebKit -lWebCoreTestSupport $(WK_AUTHKIT_LDFLAGS) $(OTHER_LDFLAGS_PLATFORM); > OTHER_LDFLAGS_PLATFORM[sdk=macosx*] = -framework Cocoa -framework Carbon; > > // FIXME: This should not be built on iOS. Instead we should create and use a TestWebKitAPI application. >diff --git a/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj b/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj >index f6069bd88953cc3510b087e1a0e2a2c7dfa40e56..c5c067c25372005001345643024636eb02c0fa76 100644 >--- a/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj >+++ b/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj >@@ -297,7 +297,7 @@ > 57599E2A1F071AA000A3FB8C /* IndexedDBStructuredCloneBackwardCompatibilityRead.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 57599E251F07192C00A3FB8C /* IndexedDBStructuredCloneBackwardCompatibilityRead.html */; }; > 57599E2B1F071AA000A3FB8C /* IndexedDBStructuredCloneBackwardCompatibilityWrite.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 57599E231F07192C00A3FB8C /* IndexedDBStructuredCloneBackwardCompatibilityWrite.html */; }; > 5769C50B1D9B0002000847FB /* SerializedCryptoKeyWrap.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5769C50A1D9B0001000847FB /* SerializedCryptoKeyWrap.mm */; }; >- 5774AA6821FBBF7800AF2A1B /* TestLoadOptimizer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5774AA6721FBBF7800AF2A1B /* TestLoadOptimizer.mm */; }; >+ 5774AA6821FBBF7800AF2A1B /* TestSOAuthorization.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5774AA6721FBBF7800AF2A1B /* TestSOAuthorization.mm */; }; > 5778D05622110A2600899E3B /* LoadWebArchive.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5778D05522110A2600899E3B /* LoadWebArchive.mm */; }; > 578CBD67204FB2C80083B9F2 /* LocalAuthentication.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 578CBD66204FB2C70083B9F2 /* LocalAuthentication.framework */; }; > 57901FB11CAF142D00ED64F9 /* LoadInvalidURLRequest.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 57901FB01CAF141C00ED64F9 /* LoadInvalidURLRequest.html */; }; >@@ -1743,7 +1743,7 @@ > 57599E251F07192C00A3FB8C /* IndexedDBStructuredCloneBackwardCompatibilityRead.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = IndexedDBStructuredCloneBackwardCompatibilityRead.html; sourceTree = "<group>"; }; > 57599E261F07192C00A3FB8C /* IndexedDBStructuredCloneBackwardCompatibility.sqlite3-shm */ = {isa = PBXFileReference; lastKnownFileType = file; path = "IndexedDBStructuredCloneBackwardCompatibility.sqlite3-shm"; sourceTree = "<group>"; }; > 5769C50A1D9B0001000847FB /* SerializedCryptoKeyWrap.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SerializedCryptoKeyWrap.mm; sourceTree = "<group>"; }; >- 5774AA6721FBBF7800AF2A1B /* TestLoadOptimizer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = TestLoadOptimizer.mm; sourceTree = "<group>"; }; >+ 5774AA6721FBBF7800AF2A1B /* TestSOAuthorization.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = TestSOAuthorization.mm; sourceTree = "<group>"; }; > 5778D05522110A2600899E3B /* LoadWebArchive.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = LoadWebArchive.mm; sourceTree = "<group>"; }; > 578CBD66204FB2C70083B9F2 /* LocalAuthentication.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LocalAuthentication.framework; path = System/Library/Frameworks/LocalAuthentication.framework; sourceTree = SDKROOT; }; > 57901FAC1CAF12C200ED64F9 /* LoadInvalidURLRequest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LoadInvalidURLRequest.mm; sourceTree = "<group>"; }; >@@ -2735,7 +2735,7 @@ > 515BE1701D428BD100DD7C68 /* StoreBlobThenDelete.mm */, > 1C734B5220788C4800F430EA /* SystemColors.mm */, > 2D70059521EDA0C6003463CB /* TabOutOfWebView.mm */, >- 5774AA6721FBBF7800AF2A1B /* TestLoadOptimizer.mm */, >+ 5774AA6721FBBF7800AF2A1B /* TestSOAuthorization.mm */, > F4CD74C720FDB49600DE3794 /* TestURLSchemeHandler.h */, > F4CD74C820FDB49600DE3794 /* TestURLSchemeHandler.mm */, > C22FA32A228F8708009D7988 /* TextWidth.mm */, >@@ -4472,10 +4472,10 @@ > F4F5BB5221667BAA002D06B9 /* TestFontOptions.mm in Sources */, > F45E15762112CE6200307E82 /* TestInputDelegate.mm in Sources */, > F45D3891215A7B4B002A2979 /* TestInspectorBar.mm in Sources */, >- 5774AA6821FBBF7800AF2A1B /* TestLoadOptimizer.mm in Sources */, > 2D1C04A71D76298B000A6816 /* TestNavigationDelegate.mm in Sources */, > A14FC5901B8AE36F00D107EB /* TestProtocol.mm in Sources */, > 7CCE7EAE1A411A3400447C4C /* TestsController.cpp in Sources */, >+ 5774AA6821FBBF7800AF2A1B /* TestSOAuthorization.mm in Sources */, > F4CD74C920FDB49600DE3794 /* TestURLSchemeHandler.mm in Sources */, > 2EFF06D41D8AEDBB0004BB30 /* TestWKWebView.mm in Sources */, > F4517B672054C49500C26721 /* TestWKWebViewController.mm in Sources */, >diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/TestLoadOptimizer.mm b/Tools/TestWebKitAPI/Tests/WebKitCocoa/TestLoadOptimizer.mm >deleted file mode 100644 >index 36f29c5978ec439a0b26739be67e4ff4ca630ac9..0000000000000000000000000000000000000000 >--- a/Tools/TestWebKitAPI/Tests/WebKitCocoa/TestLoadOptimizer.mm >+++ /dev/null >@@ -1,30 +0,0 @@ >-/* >- * Copyright (C) 2019 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" >- >-#if HAVE(LOAD_OPTIMIZER) >-#import <WebKitAdditions/TestLoadOptimizerAdditions.mm> >-#endif >diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/TestSOAuthorization.mm b/Tools/TestWebKitAPI/Tests/WebKitCocoa/TestSOAuthorization.mm >new file mode 100644 >index 0000000000000000000000000000000000000000..8c947a5f17a62286791ec9709138175d05c6330d >--- /dev/null >+++ b/Tools/TestWebKitAPI/Tests/WebKitCocoa/TestSOAuthorization.mm >@@ -0,0 +1,1852 @@ >+/* >+ * Copyright (C) 2019 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 "InstanceMethodSwizzler.h" >+#import "PlatformUtilities.h" >+#import "TestWKWebView.h" >+#import <WebKit/WKNavigationDelegatePrivate.h> >+#import <WebKit/WKNavigationPrivate.h> >+#import <pal/cocoa/AppSSOSoftLink.h> >+#import <pal/spi/cocoa/AuthKitSPI.h> >+#import <wtf/BlockPtr.h> >+#import <wtf/RetainPtr.h> >+#import <wtf/StringPrintStream.h> >+#import <wtf/URL.h> >+#import <wtf/text/WTFString.h> >+ >+static bool navigationCompleted = false; >+static bool authorizationPerformed = false; >+static bool authorizationCancelled = false; >+static bool uiShowed = false; >+static bool newWindowCreated = false; >+static bool haveHttpBody = false; >+static String finalURL; >+static SOAuthorization* gAuthorization; >+static id<SOAuthorizationDelegate> gDelegate; >+#if PLATFORM(MAC) >+static BlockPtr<void(NSNotification *)> gNotificationCallback; >+#endif >+static RetainPtr<WKWebView> gNewWindow; >+ >+static const char* openerTemplate = >+"<html>" >+"<button onclick='clickMe()' style='width:400px;height:400px'>window.open</button>" >+"<script>" >+"function clickMe()" >+"{" >+" window.addEventListener('message', receiveMessage, false);" >+" newWindow = window.open('%s');" >+" %s" >+" if (!newWindow)" >+" return;" >+" const pollTimer = window.setInterval(function() {" >+" if (newWindow.closed) {" >+" window.clearInterval(pollTimer);" >+" window.webkit.messageHandlers.testHandler.postMessage('WindowClosed.');" >+" }" >+" }, 200);" >+"}" >+"function receiveMessage(event)" >+"{" >+" if (event.origin == 'http://www.example.com') {" >+" window.webkit.messageHandlers.testHandler.postMessage(event.data);" >+" %s" >+" }" >+"}" >+"</script>" >+"</html>"; >+ >+static const char* newWindowResponseTemplate = >+"<html>" >+"<script>" >+"window.opener.postMessage('Hello.', '*');" >+"%s" >+"</script>" >+"</html>"; >+ >+static const char* parentTemplate = >+"<html>" >+"<iframe src='%s'></iframe>" >+"<script>" >+"function receiveMessage(event)" >+"{" >+" window.webkit.messageHandlers.testHandler.postMessage(event.origin);" >+" window.webkit.messageHandlers.testHandler.postMessage(event.data);" >+"}" >+"window.addEventListener('message', receiveMessage, false);" >+"</script>" >+"</html>"; >+ >+static const char* iframeTemplate = >+"<html>" >+"<script>" >+"parent.postMessage('Hello.', '*');" >+"</script>" >+"</html>"; >+ >+static const char* samlResponse = >+"<html>" >+"<script>" >+"window.webkit.messageHandlers.testHandler.postMessage('SAML');" >+"</script>" >+"</html>"; >+ >+@interface TestSOAuthorizationNavigationDelegate : NSObject <WKNavigationDelegate, WKUIDelegate> >+@property bool isDefaultPolicy; >+- (instancetype)init; >+@end >+ >+@implementation TestSOAuthorizationNavigationDelegate >+ >+- (instancetype)init >+{ >+ if (self = [super init]) >+ self.isDefaultPolicy = true; >+ 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 >+{ >+ 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 = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration]; >+ [gNewWindow setNavigationDelegate:self]; >+ return gNewWindow.get(); >+} >+ >+@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 >+ >+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<SOAuthorizationDelegate> 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; >+} >+ >+#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 [NSNumber numberWithBool:YES]; >+} >+#endif >+ >+static bool overrideIsURLFromAppleOwnedDomain(id, SEL, NSURL *) >+{ >+ return true; >+} >+ >+static void resetState() >+{ >+ navigationCompleted = false; >+ authorizationPerformed = false; >+ authorizationCancelled = false; >+ uiShowed = false; >+ newWindowCreated = false; >+ haveHttpBody = false; >+ finalURL = emptyString(); >+ gAuthorization = nullptr; >+ gDelegate = nullptr; >+#if PLATFORM(MAC) >+ gNotificationCallback = nullptr; >+#endif >+ gNewWindow = nullptr; >+} >+ >+static void configureSOAuthorizationWebView(TestWKWebView *webView, TestSOAuthorizationNavigationDelegate *delegate) >+{ >+ [webView setNavigationDelegate:delegate]; >+ [webView setUIDelegate:delegate]; >+} >+ >+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(); >+} >+ >+// FIXME<rdar://problem/48909336>: Replace the below with AppSSO constants. >+static void checkAuthorizationOptions(bool userActionInitiated, String initiatorOrigin, int initiatingAction) >+{ >+ EXPECT_TRUE(gAuthorization); >+ // FIXME: Remove the selector once the iOS bots has been updated to a recent SDK. >+ auto selector = NSSelectorFromString(@"authorizationOptions"); >+ if ([gAuthorization respondsToSelector:selector]) { >+ EXPECT_EQ(((NSNumber *)[gAuthorization performSelector:selector][SOAuthorizationOptionUserActionInitiated]).boolValue, userActionInitiated); >+ EXPECT_WK_STREQ([gAuthorization performSelector:selector][@"initiatorOrigin"], initiatorOrigin); >+ EXPECT_EQ(((NSNumber *)[gAuthorization performSelector:selector][@"initiatingAction"]).intValue, initiatingAction); >+ } >+} >+ >+namespace TestWebKitAPI { >+ >+TEST(SOAuthorizationRedirect, NoInterceptions) >+{ >+ resetState(); >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&navigationCompleted); >+ >+ EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL); >+} >+ >+TEST(SOAuthorizationRedirect, InterceptionError) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&navigationCompleted); >+ >+ EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL); >+} >+ >+TEST(SOAuthorizationRedirect, InterceptionDoNotHandle) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(false, "", 0); >+ >+ [gDelegate authorizationDidNotHandle:gAuthorization]; >+ Util::run(&navigationCompleted); >+ >+ EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL); >+} >+ >+TEST(SOAuthorizationRedirect, InterceptionCancel) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(false, "", 0); >+ >+ [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(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(false, "", 0); >+ >+ [gDelegate authorizationDidComplete:gAuthorization]; >+ Util::run(&navigationCompleted); >+ >+ EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL); >+} >+ >+TEST(SOAuthorizationRedirect, InterceptionUnexpectedCompletion) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(false, "", 0); >+ >+ [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(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(false, "", 0); >+ >+ RetainPtr<NSURL> 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(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ // Force App Links with a request.URL that has a different host than the current one (empty host) and ShouldOpenExternalURLsPolicy::ShouldAllow. >+ auto testURL = URL(URL(), "https://www.example.com"); >+#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, "", 0); >+#elif PLATFORM(IOS) >+ checkAuthorizationOptions(true, "null", 0); >+#endif >+ >+ RetainPtr<NSURL> 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(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ // Force App Links with a request.URL that has a different host than the current one (empty host) and ShouldOpenExternalURLsPolicy::ShouldAllow. >+ auto testURL = URL(URL(), "https://www.example.com"); >+#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, "", 0); >+#elif PLATFORM(IOS) >+ checkAuthorizationOptions(true, "null", 0); >+#endif >+ >+ RetainPtr<NSURL> 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(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> 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([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ [delegate setIsDefaultPolicy:false]; >+ >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(false, "", 0); >+ >+ RetainPtr<NSURL> 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(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(false, "", 0); >+ >+ RetainPtr<NSURL> 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(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(false, "", 0); >+ >+ RetainPtr<NSURL> 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(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(false, "", 0); >+ >+ RetainPtr<NSURL> 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(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ auto testURL = URL(URL(), "https://www.example.com"); >+#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, "", 0); >+#elif PLATFORM(IOS) >+ checkAuthorizationOptions(true, "null", 0); >+#endif >+ >+ RetainPtr<NSURL> 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(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(false, "", 0); >+ >+ auto redirectURL = URL(URL(), "https://www.example.com"); >+ 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(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ [webView setNavigationDelegate:delegate.get()]; >+ [webView setUIDelegate:delegate.get()]; >+ >+ // The session will be waiting since the web view is is not int the window. >+ [webView removeFromSuperview]; >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::sleep(0.5); >+ EXPECT_FALSE(authorizationPerformed); >+ >+ // Should activate the session. >+ [webView addToTestWindow]; >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(false, "", 0); >+ >+ RetainPtr<NSURL> 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, InterceptionSucceedWithActiveSessionDidMoveWindow) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(false, "", 0); >+ >+ // Should be a no op. >+ [webView addToTestWindow]; >+ >+ RetainPtr<NSURL> 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(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ for (int i = 0; i < 2; i++) { >+ authorizationPerformed = false; >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(false, "", 0); >+ >+ navigationCompleted = false; >+ RetainPtr<NSURL> 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(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(cancelAuthorization), reinterpret_cast<IMP>(overrideCancelAuthorization)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(false, "", 0); >+ >+ // Suppress the last active session. >+ authorizationPerformed = false; >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&authorizationCancelled); >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(false, "", 0); >+ >+ RetainPtr<NSURL> 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(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ [webView setNavigationDelegate:delegate.get()]; >+ [webView setUIDelegate:delegate.get()]; >+ >+ // The session will be waiting since the web view is is not int the window. >+ [webView removeFromSuperview]; >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::sleep(0.5); >+ EXPECT_FALSE(authorizationPerformed); >+ >+ // Suppress the last waiting session. >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::sleep(0.5); >+ EXPECT_FALSE(authorizationPerformed); >+ >+ // Activate the last session. >+ [webView addToTestWindow]; >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(false, "", 0); >+ >+ RetainPtr<NSURL> 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(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ // 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, "", 0); >+ >+ // 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()]; >+ [webView waitForMessage:@"SAML"]; >+} >+ >+TEST(SOAuthorizationRedirect, AuthorizationOptions) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadHTMLString:@"" baseURL:(NSURL *)URL(URL(), "http://www.webkit.org")]; >+ Util::run(&navigationCompleted); >+ [webView evaluateJavaScript: @"location = 'http://www.example.com'" completionHandler:nil]; >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(true, "http://www.webkit.org", 0); >+} >+ >+TEST(SOAuthorizationRedirect, InterceptionDidNotHandleTwice) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&authorizationPerformed); >+ >+ // Test passes if no crashes. >+ [gDelegate authorizationDidNotHandle:gAuthorization]; >+ [gDelegate authorizationDidNotHandle:gAuthorization]; >+} >+ >+TEST(SOAuthorizationRedirect, InterceptionCompleteTwice) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&authorizationPerformed); >+ >+ // Test passes if no crashes. >+ RetainPtr<NSURL> 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()]; >+} >+ >+// FIXME(175204): Enable the iOS tests once the bug is fixed. >+#if PLATFORM(MAC) >+TEST(SOAuthorizationRedirect, InterceptionSucceedWithUI) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&authorizationPerformed); >+ >+ 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<NSURL> 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(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&authorizationPerformed); >+ >+ 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(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&authorizationPerformed); >+ >+ 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(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(cancelAuthorization), reinterpret_cast<IMP>(overrideCancelAuthorization)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&authorizationPerformed); >+ >+ 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); >+ Util::run(&authorizationPerformed); >+ EXPECT_FALSE(uiShowed); >+ >+ RetainPtr<NSURL> 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(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&authorizationPerformed); >+ >+ 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(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; >+ Util::run(&authorizationPerformed); >+ >+ auto viewController = adoptNS([[TestSOAuthorizationViewController alloc] init]); >+ auto view = adoptNS([[NSView alloc] initWithFrame:NSZeroRect]); >+ { >+ InstanceMethodSwizzler swizzler4([NSNotificationCenter class], @selector(addObserverForName:object:queue:usingBlock:), reinterpret_cast<IMP>(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); >+} >+#endif >+ >+TEST(SOAuthorizationPopUp, NoInterceptions) >+{ >+ resetState(); >+ >+ RetainPtr<NSURL> 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([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadHTMLString:testHtml baseURL:testURL.get()]; >+ Util::run(&navigationCompleted); >+ >+ 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_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(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ auto iframeTestHtml = generateHtml(openerTemplate, testURL.get().absoluteString); >+ auto testHtml = makeString("<iframe style='width:400px;height:400px' srcdoc=\"", iframeTestHtml, "\" />"); >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadHTMLString:testHtml baseURL:baseURL.get()]; >+ Util::run(&navigationCompleted); >+ >+ // The new window will not navigate to the testURL as the iframe has unique origin. >+ [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1]; >+ Util::run(&newWindowCreated); >+ EXPECT_FALSE(authorizationPerformed); >+} >+#endif >+ >+TEST(SOAuthorizationPopUp, NoInterceptionsWithoutUserGesture) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ // The default value of javaScriptCanOpenWindowsAutomatically is NO on iOS, and YES on macOS. >+ auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]); >+ configuration.get().preferences.javaScriptCanOpenWindowsAutomatically = YES; >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400) configuration:configuration.get()]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView _evaluateJavaScriptWithoutUserGesture: @"window.open('http://www.example.com')" completionHandler:nil]; >+ Util::run(&newWindowCreated); >+ EXPECT_FALSE(authorizationPerformed); >+} >+ >+TEST(SOAuthorizationPopUp, InterceptionError) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ RetainPtr<NSURL> 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([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadHTMLString:testHtml baseURL:baseURL.get()]; >+ Util::run(&navigationCompleted); >+ >+#if PLATFORM(MAC) >+ [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1]; >+#elif PLATFORM(IOS) >+ [webView evaluateJavaScript: @"clickMe()" completionHandler:nil]; >+#endif >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(true, "file://", 1); >+ >+ authorizationPerformed = false; >+ navigationCompleted = false; >+ [gDelegate authorization:gAuthorization didCompleteWithError:adoptNS([[NSError alloc] initWithDomain:NSCocoaErrorDomain code:0 userInfo:nil]).get()]; >+ Util::run(&newWindowCreated); >+ Util::run(&navigationCompleted); >+ EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL); >+ EXPECT_FALSE(authorizationPerformed); // Don't intercept the first navigation in the new window. >+} >+ >+TEST(SOAuthorizationPopUp, InterceptionCancel) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ RetainPtr<NSURL> 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([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadHTMLString:testHtml baseURL:baseURL.get()]; >+ Util::run(&navigationCompleted); >+ >+#if PLATFORM(MAC) >+ [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1]; >+#elif PLATFORM(IOS) >+ [webView evaluateJavaScript: @"clickMe()" completionHandler:nil]; >+#endif >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(true, "file://", 1); >+ >+ // The secret WKWebView needs to be destroyed right the way. >+ @autoreleasepool { >+ [gDelegate authorizationDidCancel:gAuthorization]; >+ } >+ [webView waitForMessage:@"WindowClosed."]; >+} >+ >+TEST(SOAuthorizationPopUp, InterceptionSucceedCloseByItself) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ auto testURL = URL(URL(), "http://www.example.com"); >+ auto testHtml = generateHtml(openerTemplate, testURL.string()); >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadHTMLString:testHtml baseURL:baseURL.get()]; >+ Util::run(&navigationCompleted); >+ >+#if PLATFORM(MAC) >+ [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1]; >+#elif PLATFORM(IOS) >+ [webView evaluateJavaScript: @"clickMe()" completionHandler:nil]; >+#endif >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(true, "file://", 1); >+ >+ auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:nil]); >+ auto resonseHtmlCString = generateHtml(newWindowResponseTemplate, "window.close();").utf8(); // The pop up closes itself. >+ // The secret WKWebView needs to be destroyed right the way. >+ @autoreleasepool { >+ [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:resonseHtmlCString.data() length:resonseHtmlCString.length()]).get()]; >+ } >+ [webView waitForMessage:@"Hello."]; >+ [webView waitForMessage:@"WindowClosed."]; >+} >+ >+TEST(SOAuthorizationPopUp, InterceptionSucceedCloseByParent) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ auto testURL = URL(URL(), "http://www.example.com"); >+ auto testHtml = generateHtml(openerTemplate, testURL.string(), "", "event.source.close();"); // The parent closes the pop up. >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadHTMLString:testHtml baseURL:baseURL.get()]; >+ Util::run(&navigationCompleted); >+ >+#if PLATFORM(MAC) >+ [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1]; >+#elif PLATFORM(IOS) >+ [webView evaluateJavaScript: @"clickMe()" completionHandler:nil]; >+#endif >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(true, "file://", 1); >+ >+ auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:nil]); >+ auto resonseHtmlCString = generateHtml(newWindowResponseTemplate, "").utf8(); >+ // The secret WKWebView needs to be destroyed right the way. >+ @autoreleasepool { >+ [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:resonseHtmlCString.data() length:resonseHtmlCString.length()]).get()]; >+ } >+ [webView waitForMessage:@"Hello."]; >+ [webView waitForMessage:@"WindowClosed."]; >+} >+ >+TEST(SOAuthorizationPopUp, InterceptionSucceedCloseByWebKit) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ auto testURL = URL(URL(), "http://www.example.com"); >+ auto testHtml = generateHtml(openerTemplate, testURL.string()); >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadHTMLString:testHtml baseURL:baseURL.get()]; >+ Util::run(&navigationCompleted); >+ >+#if PLATFORM(MAC) >+ [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1]; >+#elif PLATFORM(IOS) >+ [webView evaluateJavaScript: @"clickMe()" completionHandler:nil]; >+#endif >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(true, "file://", 1); >+ >+ auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:nil]); >+ auto resonseHtmlCString = generateHtml(newWindowResponseTemplate, "").utf8(); >+ // The secret WKWebView needs to be destroyed right the way. >+ @autoreleasepool { >+ [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:resonseHtmlCString.data() length:resonseHtmlCString.length()]).get()]; >+ } >+ [webView waitForMessage:@"Hello."]; >+ [webView waitForMessage:@"WindowClosed."]; >+} >+ >+TEST(SOAuthorizationPopUp, InterceptionSucceedWithOtherHttpStatusCode) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ RetainPtr<NSURL> 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([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadHTMLString:testHtml baseURL:baseURL.get()]; >+ Util::run(&navigationCompleted); >+ >+#if PLATFORM(MAC) >+ [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1]; >+#elif PLATFORM(IOS) >+ [webView evaluateJavaScript: @"clickMe()" completionHandler:nil]; >+#endif >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(true, "file://", 1); >+ >+ // Will fallback to web path. >+ navigationCompleted = false; >+ authorizationPerformed = false; >+ auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:400 HTTPVersion:@"HTTP/1.1" headerFields:nil]); >+ auto resonseHtmlCString = generateHtml(newWindowResponseTemplate, "").utf8(); >+ [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:resonseHtmlCString.data() length:resonseHtmlCString.length()]).get()]; >+ Util::run(&newWindowCreated); >+ Util::run(&navigationCompleted); >+ EXPECT_WK_STREQ(testURL.get().absoluteString, finalURL); >+ EXPECT_FALSE(authorizationPerformed); >+} >+ >+// Setting cookie is ensured by other tests. Here is to cover if the whole authentication handshake can be completed. >+TEST(SOAuthorizationPopUp, InterceptionSucceedWithCookie) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ auto testURL = URL(URL(), "http://www.example.com"); >+ auto testHtml = generateHtml(openerTemplate, testURL.string()); >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadHTMLString:testHtml baseURL:baseURL.get()]; >+ Util::run(&navigationCompleted); >+ >+#if PLATFORM(MAC) >+ [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1]; >+#elif PLATFORM(IOS) >+ [webView evaluateJavaScript: @"clickMe()" completionHandler:nil]; >+#endif >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(true, "file://", 1); >+ >+ auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Set-Cookie" : @"sessionid=38afes7a8;"}]); >+ auto resonseHtmlCString = generateHtml(newWindowResponseTemplate, "").utf8(); >+ // The secret WKWebView needs to be destroyed right the way. >+ @autoreleasepool { >+ [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:resonseHtmlCString.data() length:resonseHtmlCString.length()]).get()]; >+ } >+ [webView waitForMessage:@"Hello."]; >+ [webView waitForMessage:@"WindowClosed."]; >+} >+ >+TEST(SOAuthorizationPopUp, InterceptionSucceedTwice) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ auto testURL = URL(URL(), "http://www.example.com"); >+ auto testHtml = generateHtml(openerTemplate, testURL.string()); >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadHTMLString:testHtml baseURL:baseURL.get()]; >+ Util::run(&navigationCompleted); >+ >+ for (int i = 0; i < 2; i++) { >+ authorizationPerformed = false; >+#if PLATFORM(MAC) >+ [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1]; >+#elif PLATFORM(IOS) >+ [webView evaluateJavaScript: @"clickMe()" completionHandler:nil]; >+#endif >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(true, "file://", 1); >+ >+ auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:nil]); >+ auto resonseHtmlCString = generateHtml(newWindowResponseTemplate, "").utf8(); >+ // The secret WKWebView needs to be destroyed right the way. >+ @autoreleasepool { >+ [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:resonseHtmlCString.data() length:resonseHtmlCString.length()]).get()]; >+ } >+ [webView waitForMessage:@"Hello."]; >+ [webView waitForMessage:@"WindowClosed."]; >+ } >+} >+ >+TEST(SOAuthorizationPopUp, InterceptionSucceedSuppressActiveSession) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler4(PAL::getSOAuthorizationClass(), @selector(cancelAuthorization), reinterpret_cast<IMP>(overrideCancelAuthorization)); >+ >+ RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ auto testURL = URL(URL(), "http://www.example.com"); >+ auto testHtml = generateHtml(openerTemplate, testURL.string()); >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadHTMLString:testHtml baseURL:baseURL.get()]; >+ Util::run(&navigationCompleted); >+ >+#if PLATFORM(MAC) >+ [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1]; >+#elif PLATFORM(IOS) >+ [webView evaluateJavaScript: @"clickMe()" completionHandler:nil]; >+#endif >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(true, "file://", 1); >+ >+ // Suppress the last active session. >+ auto newWebView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400) configuration:webView.get().configuration]); >+ configureSOAuthorizationWebView(newWebView.get(), delegate.get()); >+ >+ navigationCompleted = false; >+ [newWebView loadHTMLString:testHtml baseURL:baseURL.get()]; >+ Util::run(&navigationCompleted); >+ >+ authorizationPerformed = false; >+#if PLATFORM(MAC) >+ [newWebView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1]; >+#elif PLATFORM(IOS) >+ [newWebView evaluateJavaScript: @"clickMe()" completionHandler:nil]; >+#endif >+ Util::run(&authorizationCancelled); >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(true, "file://", 1); >+ >+ navigationCompleted = false; >+ [webView evaluateJavaScript: @"newWindow" completionHandler:^(id result, NSError *) { >+ EXPECT_TRUE(result == adoptNS([NSNull null]).get()); >+ navigationCompleted = true; >+ }]; >+ Util::run(&navigationCompleted); >+ >+ auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:nil]); >+ auto resonseHtmlCString = generateHtml(newWindowResponseTemplate, "").utf8(); >+ // The secret WKWebView needs to be destroyed right the way. >+ @autoreleasepool { >+ [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:resonseHtmlCString.data() length:resonseHtmlCString.length()]).get()]; >+ } >+ [newWebView waitForMessage:@"Hello."]; >+ [newWebView waitForMessage:@"WindowClosed."]; >+} >+ >+TEST(SOAuthorizationPopUp, InterceptionSucceedNewWindowNavigation) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ auto testURL = URL(URL(), "http://www.example.com"); >+ auto testHtml = generateHtml(openerTemplate, testURL.string(), makeString("newWindow.location = '", baseURL.get().absoluteString.UTF8String, "';")); // Starts a new navigation on the new window. >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadHTMLString:testHtml baseURL:baseURL.get()]; >+ Util::run(&navigationCompleted); >+ >+#if PLATFORM(MAC) >+ [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1]; >+#elif PLATFORM(IOS) >+ [webView evaluateJavaScript: @"clickMe()" completionHandler:nil]; >+#endif >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(true, "file://", 1); >+ >+ auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:nil]); >+ auto resonseHtmlCString = generateHtml(newWindowResponseTemplate, "").utf8(); >+ // The secret WKWebView needs to be destroyed right the way. >+ @autoreleasepool { >+ [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:resonseHtmlCString.data() length:resonseHtmlCString.length()]).get()]; >+ } >+ [webView waitForMessage:@"Hello."]; >+ [webView waitForMessage:@"WindowClosed."]; >+} >+ >+TEST(SOAuthorizationPopUp, AuthorizationOptions) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ auto testURL = URL(URL(), "http://www.example.com"); >+ auto testHtml = generateHtml(openerTemplate, testURL.string()); >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadHTMLString:testHtml baseURL:(NSURL *)URL(URL(), "http://www.webkit.org")]; >+ Util::run(&navigationCompleted); >+ >+#if PLATFORM(MAC) >+ [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:1]; >+#elif PLATFORM(IOS) >+ [webView evaluateJavaScript: @"clickMe()" completionHandler:nil]; >+#endif >+ Util::run(&authorizationPerformed); >+ checkAuthorizationOptions(true, "http://www.webkit.org", 1); >+} >+ >+TEST(SOAuthorizationSubFrame, NoInterceptions) >+{ >+ resetState(); >+ RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"GetSessionCookie" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ auto testHtml = generateHtml(parentTemplate, testURL.get().absoluteString); >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadHTMLString:testHtml baseURL:baseURL.get()]; >+ [webView waitForMessage:@""]; >+} >+ >+TEST(SOAuthorizationSubFrame, NoInterceptionsNonAppleFirstPartyMainFrame) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ auto testHtml = generateHtml(parentTemplate, URL(URL(), "http://www.example.com").string()); >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadHTMLString:testHtml baseURL:(NSURL *)URL(URL(), "http://www.webkit.org")]; >+ // Try to wait until the iframe load is finished. >+ Util::sleep(0.5); >+ // Make sure we don't intercept the iframe. >+ EXPECT_FALSE(authorizationPerformed); >+} >+ >+TEST(SOAuthorizationSubFrame, InterceptionError) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ ClassMethodSwizzler swizzler4([AKAuthorizationController class], @selector(isURLFromAppleOwnedDomain:), reinterpret_cast<IMP>(overrideIsURLFromAppleOwnedDomain)); >+ >+ RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"GetSessionCookie" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ auto testHtml = generateHtml(parentTemplate, testURL.get().absoluteString); >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadHTMLString:testHtml baseURL:baseURL.get()]; >+ [webView waitForMessage:@"null"]; >+ [webView waitForMessage:@"SOAuthorizationDidStart"]; >+ checkAuthorizationOptions(false, "file://", 2); >+ >+ [gDelegate authorization:gAuthorization didCompleteWithError:adoptNS([[NSError alloc] initWithDomain:NSCocoaErrorDomain code:0 userInfo:nil]).get()]; >+ [webView waitForMessage:@"null"]; >+ [webView waitForMessage:@"SOAuthorizationDidCancel"]; >+ [webView waitForMessage:@""]; >+ // Trys to wait until the iframe load is finished. >+ Util::sleep(0.5); >+ // Make sure we don't load the request of the iframe to the main frame. >+ EXPECT_WK_STREQ("", finalURL); >+} >+ >+TEST(SOAuthorizationSubFrame, InterceptionSuccess) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ ClassMethodSwizzler swizzler4([AKAuthorizationController class], @selector(isURLFromAppleOwnedDomain:), reinterpret_cast<IMP>(overrideIsURLFromAppleOwnedDomain)); >+ >+ auto testURL = URL(URL(), "http://www.example.com"); >+ auto testHtml = generateHtml(parentTemplate, testURL.string()); >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadHTMLString:testHtml baseURL:nil]; >+ [webView waitForMessage:@"http://www.example.com"]; >+ [webView waitForMessage:@"SOAuthorizationDidStart"]; >+ checkAuthorizationOptions(false, "null", 2); >+ >+ auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:nil]); >+ auto iframeHtmlCString = generateHtml(iframeTemplate, "").utf8(); >+ [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:iframeHtmlCString.data() length:iframeHtmlCString.length()]).get()]; >+ [webView waitForMessage:@"http://www.example.com"]; >+ [webView waitForMessage:@"Hello."]; >+} >+ >+TEST(SOAuthorizationSubFrame, InterceptionSucceedWithOtherHttpStatusCode) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ ClassMethodSwizzler swizzler4([AKAuthorizationController class], @selector(isURLFromAppleOwnedDomain:), reinterpret_cast<IMP>(overrideIsURLFromAppleOwnedDomain)); >+ >+ RetainPtr<NSURL> baseURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"GetSessionCookie" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+ auto testHtml = generateHtml(parentTemplate, testURL.get().absoluteString); >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadHTMLString:testHtml baseURL:baseURL.get()]; >+ [webView waitForMessage:@"null"]; >+ [webView waitForMessage:@"SOAuthorizationDidStart"]; >+ checkAuthorizationOptions(false, "file://", 2); >+ >+ // Will fallback to web path. >+ auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL.get() statusCode:400 HTTPVersion:@"HTTP/1.1" headerFields:nil]); >+ auto iframeHtmlCString = generateHtml(iframeTemplate, "").utf8(); >+ [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:iframeHtmlCString.data() length:iframeHtmlCString.length()]).get()]; >+ [webView waitForMessage:@"null"]; >+ [webView waitForMessage:@"SOAuthorizationDidCancel"]; >+ [webView waitForMessage:@""]; >+ // Trys to wait until the iframe load is finished. >+ Util::sleep(0.5); >+ // Make sure we don't load the request of the iframe to the main frame. >+ EXPECT_WK_STREQ("", finalURL); >+} >+ >+// Setting cookie is ensured by other tests. Here is to cover if the whole authentication handshake can be completed. >+TEST(SOAuthorizationSubFrame, InterceptionSucceedWithCookie) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ ClassMethodSwizzler swizzler4([AKAuthorizationController class], @selector(isURLFromAppleOwnedDomain:), reinterpret_cast<IMP>(overrideIsURLFromAppleOwnedDomain)); >+ >+ auto testURL = URL(URL(), "http://www.example.com"); >+ auto testHtml = generateHtml(parentTemplate, testURL.string()); >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadHTMLString:testHtml baseURL:nil]; >+ [webView waitForMessage:@"http://www.example.com"]; >+ [webView waitForMessage:@"SOAuthorizationDidStart"]; >+ checkAuthorizationOptions(false, "null", 2); >+ >+ auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"Set-Cookie" : @"sessionid=38afes7a8;"}]); >+ auto iframeHtmlCString = generateHtml(iframeTemplate, "").utf8(); >+ [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:iframeHtmlCString.data() length:iframeHtmlCString.length()]).get()]; >+ [webView waitForMessage:@"http://www.example.com"]; >+ [webView waitForMessage:@"Hello."]; >+} >+ >+TEST(SOAuthorizationSubFrame, InterceptionSuccessTwice) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ ClassMethodSwizzler swizzler4([AKAuthorizationController class], @selector(isURLFromAppleOwnedDomain:), reinterpret_cast<IMP>(overrideIsURLFromAppleOwnedDomain)); >+ >+ auto testURL = URL(URL(), "http://www.example.com"); >+ auto testHtml = generateHtml(parentTemplate, testURL.string()); >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ for (int i = 0; i < 2; i++) { >+ authorizationPerformed = false; >+ navigationCompleted = false; >+ >+ [webView loadHTMLString:testHtml baseURL:nil]; >+ [webView waitForMessage:@"http://www.example.com"]; >+ [webView waitForMessage:@"SOAuthorizationDidStart"]; >+ checkAuthorizationOptions(false, "null", 2); >+ >+ auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:testURL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:nil]); >+ auto iframeHtmlCString = generateHtml(iframeTemplate, "").utf8(); >+ [gDelegate authorization:gAuthorization didCompleteWithHTTPResponse:response.get() httpBody:adoptNS([[NSData alloc] initWithBytes:iframeHtmlCString.data() length:iframeHtmlCString.length()]).get()]; >+ [webView waitForMessage:@"http://www.example.com"]; >+ [webView waitForMessage:@"Hello."]; >+ } >+} >+ >+TEST(SOAuthorizationSubFrame, AuthorizationOptions) >+{ >+ resetState(); >+ ClassMethodSwizzler swizzler1(PAL::getSOAuthorizationClass(), @selector(canPerformAuthorizationWithURL:responseCode:), reinterpret_cast<IMP>(overrideCanPerformAuthorizationWithURL)); >+ InstanceMethodSwizzler swizzler2(PAL::getSOAuthorizationClass(), @selector(setDelegate:), reinterpret_cast<IMP>(overrideSetDelegate)); >+ InstanceMethodSwizzler swizzler3(PAL::getSOAuthorizationClass(), @selector(beginAuthorizationWithURL:httpHeaders:httpBody:), reinterpret_cast<IMP>(overrideBeginAuthorizationWithURL)); >+ >+ auto testURL = URL(URL(), "http://www.example.com"); >+ auto testHtml = generateHtml(parentTemplate, testURL.string()); >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); >+ auto delegate = adoptNS([[TestSOAuthorizationNavigationDelegate alloc] init]); >+ configureSOAuthorizationWebView(webView.get(), delegate.get()); >+ >+ [webView loadHTMLString:testHtml baseURL:(NSURL *)URL(URL(), "http://www.apple.com")]; >+ [webView waitForMessage:@"http://www.example.com"]; >+ [webView waitForMessage:@"SOAuthorizationDidStart"]; >+ checkAuthorizationOptions(false, "http://www.apple.com", 2); >+} >+ >+} // namespace TestWebKitAPI >+ >+#endif
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 198874
:
372158
|
372164
|
372265