Title: [244521] trunk
Revision
244521
Author
achristen...@apple.com
Date
2019-04-22 16:05:48 -0700 (Mon, 22 Apr 2019)

Log Message

REGRESSION(r230681) Do not use stored credentials if WKBundlePageResourceLoadClient.shouldUseCredentialStorage returns false
https://bugs.webkit.org/show_bug.cgi?id=197093
<rdar://problem/49708268>

Reviewed by Chris Dumez.

Source/WebKit:

Only get the StoredCredentialsPolicy from the NetworkLoadChecker if we haven't already been told not to use credentials.
Also add some test infrastructure for clearing persistent credentials added by the test.

* NetworkProcess/NetworkProcess.cpp:
(WebKit::NetworkProcess::removeCredential):
* NetworkProcess/NetworkProcess.h:
* NetworkProcess/NetworkProcess.messages.in:
* NetworkProcess/NetworkResourceLoader.cpp:
(WebKit::NetworkResourceLoader::startNetworkLoad):
* NetworkProcess/cocoa/NetworkProcessCocoa.mm:
(WebKit::NetworkProcess::removeCredential):
* UIProcess/API/Cocoa/WKProcessPool.mm:
(-[WKProcessPool _removeCredential:forProtectionSpace:completionHandler:]):
* UIProcess/API/Cocoa/WKProcessPoolPrivate.h:
* UIProcess/WebProcessPool.cpp:
(WebKit::WebProcessPool::removeCredential):
* UIProcess/WebProcessPool.h:

Tools:

Add a test that does two loads.  The first load shouldUseCredentialStorage returns true and we provide a persistent credential.
The second load shouldUseCredentialStorage returns false and we verify that a challenge is received with no suggested credential.
We also need to make the TCPServer able to handle more than one connection because we need these two loads to come from the same protection space,
and our current Cocoa implementation of NetworkSession uses two NSURLSessions that don't share a connection cache, one for loads with credentials
and one for loads without credentials, so there are two TCP connections to the same server in this test.

* TestWebKitAPI/TCPServer.cpp:
(TestWebKitAPI::TCPServer::TCPServer):
(TestWebKitAPI::TCPServer::~TCPServer):
(TestWebKitAPI::TCPServer::socketBindListen):
(TestWebKitAPI::TCPServer::waitForAndReplyToRequests): Deleted.
* TestWebKitAPI/TCPServer.h:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/BasicProposedCredentialPlugIn.mm: Added.
(-[BasicProposedCredentialPlugIn webProcessPlugIn:didCreateBrowserContextController:]):
* TestWebKitAPI/Tests/WebKitCocoa/Challenge.mm:
(respondWithChallengeThenOK):
(TestWebKitAPI::TEST):
(-[ProposedCredentialDelegate webView:didFinishNavigation:]):
(-[ProposedCredentialDelegate webView:didReceiveAuthenticationChallenge:completionHandler:]):
(TEST):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (244520 => 244521)


--- trunk/Source/WebKit/ChangeLog	2019-04-22 23:05:30 UTC (rev 244520)
+++ trunk/Source/WebKit/ChangeLog	2019-04-22 23:05:48 UTC (rev 244521)
@@ -1,3 +1,29 @@
+2019-04-22  Alex Christensen  <achristen...@webkit.org>
+
+        REGRESSION(r230681) Do not use stored credentials if WKBundlePageResourceLoadClient.shouldUseCredentialStorage returns false
+        https://bugs.webkit.org/show_bug.cgi?id=197093
+        <rdar://problem/49708268>
+
+        Reviewed by Chris Dumez.
+
+        Only get the StoredCredentialsPolicy from the NetworkLoadChecker if we haven't already been told not to use credentials.
+        Also add some test infrastructure for clearing persistent credentials added by the test.
+
+        * NetworkProcess/NetworkProcess.cpp:
+        (WebKit::NetworkProcess::removeCredential):
+        * NetworkProcess/NetworkProcess.h:
+        * NetworkProcess/NetworkProcess.messages.in:
+        * NetworkProcess/NetworkResourceLoader.cpp:
+        (WebKit::NetworkResourceLoader::startNetworkLoad):
+        * NetworkProcess/cocoa/NetworkProcessCocoa.mm:
+        (WebKit::NetworkProcess::removeCredential):
+        * UIProcess/API/Cocoa/WKProcessPool.mm:
+        (-[WKProcessPool _removeCredential:forProtectionSpace:completionHandler:]):
+        * UIProcess/API/Cocoa/WKProcessPoolPrivate.h:
+        * UIProcess/WebProcessPool.cpp:
+        (WebKit::WebProcessPool::removeCredential):
+        * UIProcess/WebProcessPool.h:
+
 2019-04-22  Chris Dumez  <cdu...@apple.com>
 
         Delayed WebProcessLaunch may break the _relatedWebView SPI

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp (244520 => 244521)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp	2019-04-22 23:05:30 UTC (rev 244520)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp	2019-04-22 23:05:48 UTC (rev 244521)
@@ -2470,6 +2470,11 @@
 }
 
 #if !PLATFORM(COCOA)
+void NetworkProcess::removeCredential(WebCore::Credential&&, WebCore::ProtectionSpace&&, CompletionHandler<void()>&& completionHandler)
+{
+    completionHandler();
+}
+
 void NetworkProcess::initializeProcess(const AuxiliaryProcessInitializationParameters&)
 {
 }

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.h (244520 => 244521)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.h	2019-04-22 23:05:30 UTC (rev 244520)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.h	2019-04-22 23:05:48 UTC (rev 244521)
@@ -72,6 +72,7 @@
 class CertificateInfo;
 class CurlProxySettings;
 class DownloadID;
+class ProtectionSpace;
 class StorageQuotaManager;
 class NetworkStorageSession;
 class ResourceError;
@@ -426,6 +427,8 @@
 
     void platformSyncAllCookies(CompletionHandler<void()>&&);
 
+    void removeCredential(WebCore::Credential&&, WebCore::ProtectionSpace&&, CompletionHandler<void()>&&);
+
     void registerURLSchemeAsSecure(const String&) const;
     void registerURLSchemeAsBypassingContentSecurityPolicy(const String&) const;
     void registerURLSchemeAsLocal(const String&) const;

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in (244520 => 244521)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in	2019-04-22 23:05:30 UTC (rev 244520)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in	2019-04-22 23:05:48 UTC (rev 244521)
@@ -171,4 +171,5 @@
     ClearAdClickAttribution(PAL::SessionID sessionID) -> () Async
     SetAdClickAttributionOverrideTimerForTesting(PAL::SessionID sessionID, bool value) -> () Async
     SetAdClickAttributionConversionURLForTesting(PAL::SessionID sessionID, URL url) -> () Async
+    RemoveCredential(WebCore::Credential credential, WebCore::ProtectionSpace protectionSpace) -> () Async
 }

Modified: trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp (244520 => 244521)


--- trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp	2019-04-22 23:05:30 UTC (rev 244520)
+++ trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp	2019-04-22 23:05:48 UTC (rev 244521)
@@ -270,7 +270,7 @@
 
     NetworkLoadParameters parameters = m_parameters;
     parameters.networkActivityTracker = m_networkActivityTracker;
-    if (m_networkLoadChecker)
+    if (parameters.storedCredentialsPolicy == WebCore::StoredCredentialsPolicy::Use && m_networkLoadChecker)
         parameters.storedCredentialsPolicy = m_networkLoadChecker->storedCredentialsPolicy();
 
     if (request.url().protocolIsBlob())

Modified: trunk/Source/WebKit/NetworkProcess/cocoa/NetworkProcessCocoa.mm (244520 => 244521)


--- trunk/Source/WebKit/NetworkProcess/cocoa/NetworkProcessCocoa.mm	2019-04-22 23:05:30 UTC (rev 244520)
+++ trunk/Source/WebKit/NetworkProcess/cocoa/NetworkProcessCocoa.mm	2019-04-22 23:05:48 UTC (rev 244521)
@@ -205,6 +205,18 @@
     }).get());
 }
 
+void NetworkProcess::removeCredential(WebCore::Credential&& credential, WebCore::ProtectionSpace&& protectionSpace, CompletionHandler<void()>&& completionHandler)
+{
+    NSURLProtectionSpace *nsSpace = protectionSpace.nsSpace();
+    NSURLCredential *nsCredential = [[[NSURLCredentialStorage sharedCredentialStorage] credentialsForProtectionSpace:nsSpace] objectForKey:credential.user()];
+    RELEASE_ASSERT(nsCredential);
+    RELEASE_ASSERT([nsCredential.user isEqualToString:credential.user()]);
+    RELEASE_ASSERT([nsCredential.password isEqualToString:credential.password()]);
+    [[NSURLCredentialStorage sharedCredentialStorage] removeCredential:nsCredential forProtectionSpace:nsSpace];
+    RELEASE_ASSERT(![[[NSURLCredentialStorage sharedCredentialStorage] credentialsForProtectionSpace:nsSpace] objectForKey:credential.user()]);
+    completionHandler();
+}
+
 #if PLATFORM(MAC)
 void NetworkProcess::setSharedHTTPCookieStorage(const Vector<uint8_t>& identifier)
 {

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKProcessPool.mm (244520 => 244521)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKProcessPool.mm	2019-04-22 23:05:30 UTC (rev 244520)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKProcessPool.mm	2019-04-22 23:05:48 UTC (rev 244521)
@@ -519,6 +519,13 @@
     _processPool->preconnectToServer(serverURL);
 }
 
+- (void)_removeCredential:(NSURLCredential *)credential forProtectionSpace:(NSURLProtectionSpace *)protectionSpace completionHandler:(void(^)())completionHandler
+{
+    _processPool->removeCredential(WebCore::Credential(credential), WebCore::ProtectionSpace(protectionSpace), [completionHandler = makeBlockPtr(completionHandler)] {
+        completionHandler();
+    });
+}
+
 - (size_t)_pluginProcessCount
 {
 #if !PLATFORM(IOS_FAMILY)

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKProcessPoolPrivate.h (244520 => 244521)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKProcessPoolPrivate.h	2019-04-22 23:05:30 UTC (rev 244520)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKProcessPoolPrivate.h	2019-04-22 23:05:48 UTC (rev 244521)
@@ -116,6 +116,9 @@
 - (void)_preconnectToServer:(NSURL *)serverURL WK_API_AVAILABLE(macos(10.13.4), ios(11.3));
 
 // Test only.
+- (void)_removeCredential:(NSURLCredential *)credential forProtectionSpace:(NSURLProtectionSpace *)protectionSpace completionHandler:(void(^)(void))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+
+// Test only.
 - (void)_setAllowsAnySSLCertificateForServiceWorker:(BOOL)allows WK_API_AVAILABLE(macos(10.13.4), ios(11.3));
 - (void)_registerURLSchemeServiceWorkersCanHandle:(NSString *)scheme WK_API_AVAILABLE(macos(10.13.4), ios(11.3));
 - (void)_getActivePagesOriginsInWebProcessForTesting:(pid_t)pid completionHandler:(void(^)(NSArray<NSString *> *))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));

Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.cpp (244520 => 244521)


--- trunk/Source/WebKit/UIProcess/WebProcessPool.cpp	2019-04-22 23:05:30 UTC (rev 244520)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.cpp	2019-04-22 23:05:48 UTC (rev 244521)
@@ -1721,6 +1721,11 @@
     m_shouldUseTestingNetworkSession = true;
 }
 
+void WebProcessPool::removeCredential(WebCore::Credential&& credential, WebCore::ProtectionSpace&& protectionSpace, CompletionHandler<void()>&& completionHandler)
+{
+    m_networkProcess->sendWithAsyncReply(Messages::NetworkProcess::RemoveCredential(credential, protectionSpace), WTFMove(completionHandler));
+}
+
 template<typename T, typename U>
 void WebProcessPool::sendSyncToNetworkingProcess(T&& message, U&& reply)
 {

Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.h (244520 => 244521)


--- trunk/Source/WebKit/UIProcess/WebProcessPool.h	2019-04-22 23:05:30 UTC (rev 244520)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.h	2019-04-22 23:05:48 UTC (rev 244521)
@@ -507,6 +507,8 @@
 
     void disableDelayedWebProcessLaunch() { m_isDelayedWebProcessLaunchDisabled = true; }
 
+    void removeCredential(WebCore::Credential&&, WebCore::ProtectionSpace&&, CompletionHandler<void()>&&);
+    
 private:
     void platformInitialize();
 

Modified: trunk/Tools/ChangeLog (244520 => 244521)


--- trunk/Tools/ChangeLog	2019-04-22 23:05:30 UTC (rev 244520)
+++ trunk/Tools/ChangeLog	2019-04-22 23:05:48 UTC (rev 244521)
@@ -1,3 +1,33 @@
+2019-04-22  Alex Christensen  <achristen...@webkit.org>
+
+        REGRESSION(r230681) Do not use stored credentials if WKBundlePageResourceLoadClient.shouldUseCredentialStorage returns false
+        https://bugs.webkit.org/show_bug.cgi?id=197093
+        <rdar://problem/49708268>
+
+        Reviewed by Chris Dumez.
+
+        Add a test that does two loads.  The first load shouldUseCredentialStorage returns true and we provide a persistent credential.
+        The second load shouldUseCredentialStorage returns false and we verify that a challenge is received with no suggested credential.
+        We also need to make the TCPServer able to handle more than one connection because we need these two loads to come from the same protection space,
+        and our current Cocoa implementation of NetworkSession uses two NSURLSessions that don't share a connection cache, one for loads with credentials
+        and one for loads without credentials, so there are two TCP connections to the same server in this test.
+
+        * TestWebKitAPI/TCPServer.cpp:
+        (TestWebKitAPI::TCPServer::TCPServer):
+        (TestWebKitAPI::TCPServer::~TCPServer):
+        (TestWebKitAPI::TCPServer::socketBindListen):
+        (TestWebKitAPI::TCPServer::waitForAndReplyToRequests): Deleted.
+        * TestWebKitAPI/TCPServer.h:
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitCocoa/BasicProposedCredentialPlugIn.mm: Added.
+        (-[BasicProposedCredentialPlugIn webProcessPlugIn:didCreateBrowserContextController:]):
+        * TestWebKitAPI/Tests/WebKitCocoa/Challenge.mm:
+        (respondWithChallengeThenOK):
+        (TestWebKitAPI::TEST):
+        (-[ProposedCredentialDelegate webView:didFinishNavigation:]):
+        (-[ProposedCredentialDelegate webView:didReceiveAuthenticationChallenge:completionHandler:]):
+        (TEST):
+
 2019-04-22  Chris Dumez  <cdu...@apple.com>
 
         Delayed WebProcessLaunch may break the _relatedWebView SPI

Modified: trunk/Tools/TestWebKitAPI/TCPServer.cpp (244520 => 244521)


--- trunk/Tools/TestWebKitAPI/TCPServer.cpp	2019-04-22 23:05:30 UTC (rev 244520)
+++ trunk/Tools/TestWebKitAPI/TCPServer.cpp	2019-04-22 23:05:48 UTC (rev 244521)
@@ -29,35 +29,39 @@
 #include <netinet/in.h>
 #include <thread>
 #include <unistd.h>
-#include <vector>
+#include <wtf/Optional.h>
 
 namespace TestWebKitAPI {
 
-TCPServer::TCPServer(Function<void(Socket)>&& socketHandler)
-    : m_socketHandler(WTFMove(socketHandler))
+TCPServer::TCPServer(Function<void(Socket)>&& connectionHandler, size_t connections)
+    : m_connectionHandler(WTFMove(connectionHandler))
 {
-    socketBindListen();
-    m_thread = std::thread(&TCPServer::waitForAndReplyToRequests, this);
+    auto listeningSocket = socketBindListen(connections);
+    ASSERT(listeningSocket);
+    m_listeningThread = std::thread([this, listeningSocket = *listeningSocket, connections] {
+        for (size_t i = 0; i < connections; ++i) {
+            Socket connectionSocket = accept(listeningSocket, nullptr, nullptr);
+            m_connectionThreads.append(std::thread([this, connectionSocket] {
+                m_connectionHandler(connectionSocket);
+                shutdown(connectionSocket, SHUT_RDWR);
+                close(connectionSocket);
+            }));
+        }
+    });
 }
 
 TCPServer::~TCPServer()
 {
-    m_thread.join();
-    if (m_listeningSocket != InvalidSocket) {
-        close(m_listeningSocket);
-        m_listeningSocket = InvalidSocket;
-    }
-    if (m_connectionSocket != InvalidSocket) {
-        close(m_connectionSocket);
-        m_connectionSocket = InvalidSocket;
-    }
+    m_listeningThread.join();
+    for (auto& connectionThreads : m_connectionThreads)
+        connectionThreads.join();
 }
 
-void TCPServer::socketBindListen()
+auto TCPServer::socketBindListen(size_t connections) -> Optional<Socket>
 {
-    m_listeningSocket = socket(PF_INET, SOCK_STREAM, 0);
-    if (m_listeningSocket == InvalidSocket)
-        return;
+    Socket listeningSocket = socket(PF_INET, SOCK_STREAM, 0);
+    if (listeningSocket == -1)
+        return WTF::nullopt;
     
     // Ports 49152-65535 are unallocated ports. Try until we find one that's free.
     for (Port port = 49152; port; port++) {
@@ -66,34 +70,22 @@
         name.sin_family = AF_INET;
         name.sin_port = htons(port);
         name.sin_addr.s_addr = htonl(INADDR_ANY);
-        if (bind(m_listeningSocket, reinterpret_cast<sockaddr*>(&name), sizeof(name)) < 0) {
+        if (bind(listeningSocket, reinterpret_cast<sockaddr*>(&name), sizeof(name)) < 0) {
             // This port is busy. Try the next port.
             continue;
         }
-        const unsigned maxConnections = 1;
-        if (listen(m_listeningSocket, maxConnections) == -1) {
+        if (listen(listeningSocket, connections) == -1) {
             // Listening failed.
-            close(m_listeningSocket);
-            m_listeningSocket = InvalidSocket;
-            return;
+            close(listeningSocket);
+            return WTF::nullopt;
         }
         m_port = port;
-        return; // Successfully set up listening port.
+        return listeningSocket; // Successfully set up listening port.
     }
     
     // Couldn't find an available port.
-    close(m_listeningSocket);
-    m_listeningSocket = InvalidSocket;
+    close(listeningSocket);
+    return WTF::nullopt;
 }
 
-void TCPServer::waitForAndReplyToRequests()
-{
-    if (m_listeningSocket == InvalidSocket)
-        return;
-    
-    m_connectionSocket = accept(m_listeningSocket, nullptr, nullptr);
-    m_socketHandler(m_connectionSocket);
-    shutdown(m_connectionSocket, SHUT_RDWR);
-}
-
 } // namespace TestWebKitAPI

Modified: trunk/Tools/TestWebKitAPI/TCPServer.h (244520 => 244521)


--- trunk/Tools/TestWebKitAPI/TCPServer.h	2019-04-22 23:05:30 UTC (rev 244520)
+++ trunk/Tools/TestWebKitAPI/TCPServer.h	2019-04-22 23:05:48 UTC (rev 244521)
@@ -27,6 +27,7 @@
 
 #include <thread>
 #include <wtf/Function.h>
+#include <wtf/Vector.h>
 
 namespace TestWebKitAPI {
 
@@ -33,24 +34,21 @@
 class TCPServer {
 public:
     using Socket = int;
-    static constexpr Socket InvalidSocket = -1;
     using Port = uint16_t;
     static constexpr Port InvalidPort = 0;
     
-    TCPServer(Function<void(Socket)>&&);
+    TCPServer(Function<void(Socket)>&&, size_t connections = 1);
     ~TCPServer();
     
     Port port() const { return m_port; }
     
 private:
-    void socketBindListen();
-    void waitForAndReplyToRequests();
+    Optional<Socket> socketBindListen(size_t connections);
 
     Port m_port { InvalidPort };
-    Socket m_listeningSocket { InvalidSocket };
-    Socket m_connectionSocket { InvalidSocket };
-    std::thread m_thread;
-    Function<void(Socket)> m_socketHandler;
+    std::thread m_listeningThread;
+    Vector<std::thread> m_connectionThreads;
+    Function<void(Socket)> m_connectionHandler;
 };
 
 } // namespace TestWebKitAPI

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (244520 => 244521)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2019-04-22 23:05:30 UTC (rev 244520)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2019-04-22 23:05:48 UTC (rev 244521)
@@ -314,6 +314,7 @@
 		5C23DF0B2246015800F454B6 /* Challenge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C23DF0A2245C9D700F454B6 /* Challenge.mm */; };
 		5C2936931D5BF70D00DEAB1E /* CookieAcceptPolicy.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C2936911D5BF63E00DEAB1E /* CookieAcceptPolicy.mm */; };
 		5C2936961D5C00ED00DEAB1E /* CookieMessage.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5C2936941D5BFD1900DEAB1E /* CookieMessage.html */; };
+		5C4259462266A68A0039AA7A /* BasicProposedCredentialPlugIn.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C42594422669E9B0039AA7A /* BasicProposedCredentialPlugIn.mm */; };
 		5C4A84951F7EEFFC00ACFC54 /* Configuration.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C4A84941F7EEFD400ACFC54 /* Configuration.mm */; };
 		5C69BDD51F82A7EF000F4F4B /* _javascript_DuringNavigation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C69BDD41F82A7EB000F4F4B /* _javascript_DuringNavigation.mm */; };
 		5C6E27A7224EEBEA00128736 /* URLCanonicalization.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C6E27A6224EEBEA00128736 /* URLCanonicalization.mm */; };
@@ -1728,6 +1729,7 @@
 		5C23DF0A2245C9D700F454B6 /* Challenge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Challenge.mm; sourceTree = "<group>"; };
 		5C2936911D5BF63E00DEAB1E /* CookieAcceptPolicy.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CookieAcceptPolicy.mm; sourceTree = "<group>"; };
 		5C2936941D5BFD1900DEAB1E /* CookieMessage.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = CookieMessage.html; sourceTree = "<group>"; };
+		5C42594422669E9B0039AA7A /* BasicProposedCredentialPlugIn.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = BasicProposedCredentialPlugIn.mm; sourceTree = "<group>"; };
 		5C4A84941F7EEFD400ACFC54 /* Configuration.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Configuration.mm; sourceTree = "<group>"; };
 		5C5E633D1D0B67940085A025 /* UniqueRef.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UniqueRef.cpp; sourceTree = "<group>"; };
 		5C69BDD41F82A7EB000F4F4B /* _javascript_DuringNavigation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _javascript_DuringNavigation.mm; sourceTree = "<group>"; };
@@ -2529,6 +2531,7 @@
 				754CEC801F6722DC00D0039A /* AutoFillAvailable.mm */,
 				2DD355351BD08378005DF4A7 /* AutoLayoutIntegration.mm */,
 				07CD32F52065B5420064A4BE /* AVFoundationPreference.mm */,
+				5C42594422669E9B0039AA7A /* BasicProposedCredentialPlugIn.mm */,
 				374B7A5E1DF36EEE00ACCB6C /* BundleEditingDelegate.mm */,
 				374B7A5F1DF36EEE00ACCB6C /* BundleEditingDelegatePlugIn.mm */,
 				374B7A621DF3734C00ACCB6C /* BundleEditingDelegateProtocol.h */,
@@ -4483,6 +4486,7 @@
 			files = (
 				37E7DD671EA071F3009B396D /* AdditionalReadAccessAllowedURLsPlugin.mm in Sources */,
 				754CEC811F6722F200D0039A /* AutoFillAvailable.mm in Sources */,
+				5C4259462266A68A0039AA7A /* BasicProposedCredentialPlugIn.mm in Sources */,
 				374B7A611DF371CF00ACCB6C /* BundleEditingDelegatePlugIn.mm in Sources */,
 				A13EBBB01B87436F00097110 /* BundleParametersPlugIn.mm in Sources */,
 				37A709AF1E3EA97E00CA5969 /* BundleRangeHandlePlugIn.mm in Sources */,

Added: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/BasicProposedCredentialPlugIn.mm (0 => 244521)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/BasicProposedCredentialPlugIn.mm	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/BasicProposedCredentialPlugIn.mm	2019-04-22 23:05:48 UTC (rev 244521)
@@ -0,0 +1,51 @@
+/*
+ * 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 <WebKit/WKBundlePage.h>
+#import <WebKit/WKBundlePageResourceLoadClient.h>
+#import <WebKit/WKWebProcessPlugIn.h>
+#import <WebKit/WKWebProcessPlugInBrowserContextControllerPrivate.h>
+
+@interface BasicProposedCredentialPlugIn : NSObject<WKWebProcessPlugIn>
+@end
+
+@implementation BasicProposedCredentialPlugIn
+
+- (void)webProcessPlugIn:(WKWebProcessPlugInController *)plugInController didCreateBrowserContextController:(WKWebProcessPlugInBrowserContextController *)browserContextController
+{
+    WKBundlePageResourceLoadClientV1 client;
+    memset(&client, 0, sizeof(client));
+    client.base.version = 1;
+    client.shouldUseCredentialStorage = [](auto...) {
+        static size_t queries { 0 };
+        ASSERT(queries < 2);
+        return !queries++;
+    };
+    WKBundlePageSetResourceLoadClient([browserContextController _bundlePageRef], &client.base);
+}
+
+@end

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/Challenge.mm (244520 => 244521)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/Challenge.mm	2019-04-22 23:05:30 UTC (rev 244520)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/Challenge.mm	2019-04-22 23:05:48 UTC (rev 244521)
@@ -29,7 +29,38 @@
 #import "TCPServer.h"
 #import "Test.h"
 #import "TestWKWebView.h"
+#import "WKWebViewConfigurationExtras.h"
+#import <WebKit/WKProcessPoolPrivate.h>
 
+static bool navigationFinished;
+
+static void respondWithChallengeThenOK(int socket)
+{
+    char readBuffer[1000];
+    auto bytesRead = ::read(socket, readBuffer, sizeof(readBuffer));
+    EXPECT_GT(bytesRead, 0);
+    EXPECT_TRUE(static_cast<size_t>(bytesRead) < sizeof(readBuffer));
+    
+    const char* challengeHeader =
+    "HTTP/1.1 401 Unauthorized\r\n"
+    "Date: Sat, 23 Mar 2019 06:29:01 GMT\r\n"
+    "Content-Length: 0\r\n"
+    "WWW-Authenticate: Basic realm=\"testrealm\"\r\n\r\n";
+    auto bytesWritten = ::write(socket, challengeHeader, strlen(challengeHeader));
+    EXPECT_EQ(static_cast<size_t>(bytesWritten), strlen(challengeHeader));
+    
+    bytesRead = ::read(socket, readBuffer, sizeof(readBuffer));
+    EXPECT_GT(bytesRead, 0);
+    EXPECT_TRUE(static_cast<size_t>(bytesRead) < sizeof(readBuffer));
+    
+    const char* responseHeader =
+    "HTTP/1.1 200 OK\r\n"
+    "Content-Length: 13\r\n\r\n"
+    "Hello, World!";
+    bytesWritten = ::write(socket, responseHeader, strlen(responseHeader));
+    EXPECT_EQ(static_cast<size_t>(bytesWritten), strlen(responseHeader));
+}
+
 #if PLATFORM(MAC)
 
 static std::pair<RetainPtr<NSURLCredential>, RetainPtr<NSString>> credentialWithIdentityAndKeychainPath()
@@ -170,7 +201,6 @@
     };
 }
 
-static bool navigationFinished;
 static RetainPtr<NSString> keychainPath;
 
 @interface ChallengeDelegate : NSObject <WKNavigationDelegate>
@@ -208,31 +238,7 @@
 
 TEST(Challenge, SecIdentity)
 {
-    TCPServer server([] (auto socket) {
-        char readBuffer[1000];
-        auto bytesRead = ::read(socket, readBuffer, sizeof(readBuffer));
-        EXPECT_GT(bytesRead, 0);
-        EXPECT_TRUE(static_cast<size_t>(bytesRead) < sizeof(readBuffer));
-        
-        const char* challengeHeader =
-        "HTTP/1.1 401 Unauthorized\r\n"
-        "Date: Sat, 23 Mar 2019 06:29:01 GMT\r\n"
-        "Content-Length: 0\r\n"
-        "WWW-Authenticate: Basic realm=\"testrealm\"\r\n\r\n";
-        auto bytesWritten = ::write(socket, challengeHeader, strlen(challengeHeader));
-        EXPECT_EQ(static_cast<size_t>(bytesWritten), strlen(challengeHeader));
-        
-        bytesRead = ::read(socket, readBuffer, sizeof(readBuffer));
-        EXPECT_GT(bytesRead, 0);
-        EXPECT_TRUE(static_cast<size_t>(bytesRead) < sizeof(readBuffer));
-        
-        const char* responseHeader =
-        "HTTP/1.1 200 OK\r\n"
-        "Content-Length: 13\r\n\r\n"
-        "Hello, World!";
-        bytesWritten = ::write(socket, responseHeader, strlen(responseHeader));
-        EXPECT_EQ(static_cast<size_t>(bytesWritten), strlen(responseHeader));
-    });
+    TCPServer server(respondWithChallengeThenOK);
 
     auto webView = adoptNS([WKWebView new]);
     auto delegate = adoptNS([ChallengeDelegate new]);
@@ -250,3 +256,55 @@
 } // namespace TestWebKitAPI
 
 #endif
+
+static bool receivedSecondChallenge;
+static RetainPtr<NSURLCredential> persistentCredential;
+
+@interface ProposedCredentialDelegate : NSObject <WKNavigationDelegate>
+@end
+
+@implementation ProposedCredentialDelegate
+
+- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation
+{
+    navigationFinished = true;
+}
+
+- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler
+{
+    static bool firstChallenge = true;
+    if (firstChallenge) {
+        firstChallenge = false;
+        persistentCredential = adoptNS([[NSURLCredential alloc] initWithUser:@"testuser" password:@"testpassword" persistence:NSURLCredentialPersistencePermanent]);
+        return completionHandler(NSURLSessionAuthChallengeUseCredential, persistentCredential.get());
+        
+    }
+    receivedSecondChallenge = true;
+    return completionHandler(NSURLSessionAuthChallengeUseCredential, nil);
+}
+
+@end
+
+TEST(Challenge, BasicProposedCredential)
+{
+    using namespace TestWebKitAPI;
+    TCPServer server(respondWithChallengeThenOK, 2);
+    auto configuration = retainPtr([WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"BasicProposedCredentialPlugIn"]);
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration.get()]);
+    auto delegate = adoptNS([ProposedCredentialDelegate new]);
+    [webView setNavigationDelegate:delegate.get()];
+    RetainPtr<NSURLRequest> request = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://127.0.0.1:%d/", server.port()]]];
+    [webView loadRequest:request.get()];
+    Util::run(&navigationFinished);
+    navigationFinished = false;
+    [webView loadRequest:request.get()];
+    Util::run(&navigationFinished);
+    EXPECT_TRUE(receivedSecondChallenge);
+    
+    NSURLProtectionSpace *protectionSpace = [[[NSURLProtectionSpace alloc] initWithHost:@"127.0.0.1" port:server.port() protocol:NSURLProtectionSpaceHTTP realm:@"testrealm" authenticationMethod:NSURLAuthenticationMethodHTTPBasic] autorelease];
+    __block bool removedCredential = false;
+    [[webView configuration].processPool _removeCredential:persistentCredential.get() forProtectionSpace:protectionSpace completionHandler:^{
+        removedCredential = true;
+    }];
+    Util::run(&removedCredential);
+}
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to