Use credentials from a URL with NetworkSession like we did with ResourceHandle
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 23 Jan 2016 09:44:10 +0000 (09:44 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 23 Jan 2016 09:44:10 +0000 (09:44 +0000)
https://bugs.webkit.org/show_bug.cgi?id=153328

Patch by Alex Christensen <achristensen@webkit.org> on 2016-01-23
Reviewed by Alexey Proskuryakov.

Source/WebCore:

This patch fixes at least http/tests/xmlhttprequest/basic-auth-credentials-escaping.html when using NetworkSession.

* platform/network/ProtectionSpaceBase.h:
(WebCore::ProtectionSpaceBase::encodingRequiresPlatformData):
* platform/network/ResourceRequestBase.h:
Add some WEBCORE_EXPORT macros for functions that are now used in WebKit2.

Source/WebKit2:

* NetworkProcess/NetworkLoad.cpp:
(WebKit::NetworkLoad::NetworkLoad):
createDataTaskWithRequest is being removed, so use std::make_unique<NetworkDataTask> directly instead.
Also, create the task even if we are deferring loading.  Don't call resume if we are deferring loading.
* NetworkProcess/NetworkSession.h:
Callbacks are not just used in NetworkSessionTaskClient, so declare them outside.
The NetworkDataTask now takes a ResourceRequest so we can strip its credentials.
* NetworkProcess/cocoa/NetworkSessionCocoa.mm:
(-[WKNetworkSessionDelegate URLSession:task:didReceiveChallenge:completionHandler:]):
Try credentials stored with the NetworkDataTask before asking the client for credentials.
(WebKit::NetworkSession::~NetworkSession):
(WebKit::NetworkSession::dataTaskForIdentifier):
(WebKit::NetworkSession::takeDownloadID):
(WebKit::NetworkDataTask::NetworkDataTask):
Strip the credentials from the url before creating the task because we do not know the authentication type.
We will use these credentials when a challenge is received.
(WebKit::NetworkDataTask::~NetworkDataTask):
(WebKit::NetworkDataTask::tryPasswordBasedAuthentication):
If we have credentials from the initial URL, try using them if it is appropriate.
(WebKit::NetworkDataTask::cancel):
(WebKit::NetworkSession::createDataTaskWithRequest): Deleted.
* Shared/Authentication/AuthenticationManager.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@195509 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/network/ProtectionSpaceBase.h
Source/WebCore/platform/network/ResourceRequestBase.h
Source/WebKit2/ChangeLog
Source/WebKit2/NetworkProcess/NetworkLoad.cpp
Source/WebKit2/NetworkProcess/NetworkSession.h
Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm
Source/WebKit2/Shared/Authentication/AuthenticationManager.h

index 7827210..d38b574 100644 (file)
@@ -1,3 +1,17 @@
+2016-01-23  Alex Christensen  <achristensen@webkit.org>
+
+        Use credentials from a URL with NetworkSession like we did with ResourceHandle
+        https://bugs.webkit.org/show_bug.cgi?id=153328
+
+        Reviewed by Alexey Proskuryakov.
+
+        This patch fixes at least http/tests/xmlhttprequest/basic-auth-credentials-escaping.html when using NetworkSession.
+
+        * platform/network/ProtectionSpaceBase.h:
+        (WebCore::ProtectionSpaceBase::encodingRequiresPlatformData):
+        * platform/network/ResourceRequestBase.h:
+        Add some WEBCORE_EXPORT macros for functions that are now used in WebKit2.
+
 2016-01-23  Brady Eidson  <beidson@apple.com>
 
         Modern IDB: Implement clearing object stores and opening cursors in the SQLite backend.
index 02149f5..78e5200 100644 (file)
@@ -68,7 +68,7 @@ public:
     WEBCORE_EXPORT ProtectionSpaceAuthenticationScheme authenticationScheme() const;
     
     bool receivesCredentialSecurely() const;
-    bool isPasswordBased() const;
+    WEBCORE_EXPORT bool isPasswordBased() const;
 
     bool encodingRequiresPlatformData() const { return false; }
 
index 2565c46..3463909 100644 (file)
@@ -65,7 +65,7 @@ namespace WebCore {
         WEBCORE_EXPORT const URL& url() const;
         WEBCORE_EXPORT void setURL(const URL& url);
 
-        void removeCredentials();
+        WEBCORE_EXPORT void removeCredentials();
 
         WEBCORE_EXPORT ResourceRequestCachePolicy cachePolicy() const;
         WEBCORE_EXPORT void setCachePolicy(ResourceRequestCachePolicy cachePolicy);
index f714dc0..5fc88ea 100644 (file)
@@ -1,3 +1,33 @@
+2016-01-23  Alex Christensen  <achristensen@webkit.org>
+
+        Use credentials from a URL with NetworkSession like we did with ResourceHandle
+        https://bugs.webkit.org/show_bug.cgi?id=153328
+
+        Reviewed by Alexey Proskuryakov.
+
+        * NetworkProcess/NetworkLoad.cpp:
+        (WebKit::NetworkLoad::NetworkLoad):
+        createDataTaskWithRequest is being removed, so use std::make_unique<NetworkDataTask> directly instead.
+        Also, create the task even if we are deferring loading.  Don't call resume if we are deferring loading.
+        * NetworkProcess/NetworkSession.h:
+        Callbacks are not just used in NetworkSessionTaskClient, so declare them outside.
+        The NetworkDataTask now takes a ResourceRequest so we can strip its credentials.
+        * NetworkProcess/cocoa/NetworkSessionCocoa.mm:
+        (-[WKNetworkSessionDelegate URLSession:task:didReceiveChallenge:completionHandler:]):
+        Try credentials stored with the NetworkDataTask before asking the client for credentials.
+        (WebKit::NetworkSession::~NetworkSession):
+        (WebKit::NetworkSession::dataTaskForIdentifier):
+        (WebKit::NetworkSession::takeDownloadID):
+        (WebKit::NetworkDataTask::NetworkDataTask):
+        Strip the credentials from the url before creating the task because we do not know the authentication type.
+        We will use these credentials when a challenge is received.
+        (WebKit::NetworkDataTask::~NetworkDataTask):
+        (WebKit::NetworkDataTask::tryPasswordBasedAuthentication):
+        If we have credentials from the initial URL, try using them if it is appropriate.
+        (WebKit::NetworkDataTask::cancel):
+        (WebKit::NetworkSession::createDataTaskWithRequest): Deleted.
+        * Shared/Authentication/AuthenticationManager.h:
+
 2016-01-22  Dan Bernstein  <mitz@apple.com>
 
         <rdar://problem/24304228> REGRESSION (r184215): Staged XPC services load non-staged shims
index 0dbca37..3cc6798 100644 (file)
@@ -50,13 +50,12 @@ NetworkLoad::NetworkLoad(NetworkLoadClient& client, const NetworkLoadParameters&
     , m_currentRequest(parameters.request)
 {
 #if USE(NETWORK_SESSION)
-    if (!parameters.defersLoading) {
-        if (auto* networkSession = SessionTracker::networkSession(parameters.sessionID)) {
-            m_task = networkSession->createDataTaskWithRequest(parameters.request, *this);
+    if (auto* networkSession = SessionTracker::networkSession(parameters.sessionID)) {
+        m_task = std::make_unique<NetworkDataTask>(*networkSession, *this, parameters.request);
+        if (!parameters.defersLoading)
             m_task->resume();
-        } else
-            ASSERT_NOT_REACHED();
-    }
+    } else
+        ASSERT_NOT_REACHED();
 #else
     m_handle = ResourceHandle::create(m_networkingContext.get(), parameters.request, this, parameters.defersLoading, parameters.contentSniffingPolicy == SniffContent);
 #endif
index df59e94..83256f7 100644 (file)
@@ -41,6 +41,7 @@ OBJC_CLASS WKNetworkSessionDelegate;
 #include <wtf/RefCounted.h>
 #include <wtf/RetainPtr.h>
 #include <wtf/WeakPtr.h>
+#include <wtf/text/WTFString.h>
 
 namespace WebCore {
 class AuthenticationChallenge;
@@ -63,13 +64,14 @@ enum class AuthenticationChallengeDisposition {
 class NetworkSession;
 class PendingDownload;
 
+typedef std::function<void(const WebCore::ResourceRequest&)> RedirectCompletionHandler;
+typedef std::function<void(AuthenticationChallengeDisposition, const WebCore::Credential&)> ChallengeCompletionHandler;
+typedef std::function<void(WebCore::PolicyAction)> ResponseCompletionHandler;
+
 class NetworkSessionTaskClient {
 public:
-    typedef std::function<void(const WebCore::ResourceRequest&)> RedirectCompletionHandler;
     virtual void willPerformHTTPRedirection(const WebCore::ResourceResponse&, const WebCore::ResourceRequest&, RedirectCompletionHandler) = 0;
-    typedef std::function<void(AuthenticationChallengeDisposition, const WebCore::Credential&)> ChallengeCompletionHandler;
     virtual void didReceiveChallenge(const WebCore::AuthenticationChallenge&, ChallengeCompletionHandler) = 0;
-    typedef std::function<void(WebCore::PolicyAction)> ResponseCompletionHandler;
     virtual void didReceiveResponse(const WebCore::ResourceResponse&, ResponseCompletionHandler) = 0;
     virtual void didReceiveData(RefPtr<WebCore::SharedBuffer>&&) = 0;
     virtual void didCompleteWithError(const WebCore::ResourceError&) = 0;
@@ -81,11 +83,7 @@ public:
 class NetworkDataTask {
     friend class NetworkSession;
 public:
-#if PLATFORM(COCOA)
-    explicit NetworkDataTask(NetworkSession&, NetworkSessionTaskClient&, RetainPtr<NSURLSessionDataTask>&&);
-#else
-    explicit NetworkDataTask(NetworkSession&, NetworkSessionTaskClient&);
-#endif
+    explicit NetworkDataTask(NetworkSession&, NetworkSessionTaskClient&, const WebCore::ResourceRequest&);
 
     void suspend();
     void cancel();
@@ -111,12 +109,15 @@ public:
         ASSERT(!m_pendingDownload);
         m_pendingDownload = &pendingDownload;
     }
+    bool tryPasswordBasedAuthentication(const WebCore::AuthenticationChallenge&, ChallengeCompletionHandler);
     
 private:
     NetworkSession& m_session;
     NetworkSessionTaskClient& m_client;
     PendingDownload* m_pendingDownload { nullptr };
     DownloadID m_pendingDownloadID;
+    String m_user;
+    String m_password;
 #if PLATFORM(COCOA)
     RetainPtr<NSURLSessionDataTask> m_task;
 #endif
@@ -133,8 +134,6 @@ public:
     ~NetworkSession();
 
     static NetworkSession& defaultSession();
-    
-    std::unique_ptr<NetworkDataTask> createDataTaskWithRequest(const WebCore::ResourceRequest&, NetworkSessionTaskClient&);
 
     NetworkDataTask* dataTaskForIdentifier(NetworkDataTask::TaskIdentifier);
 
index 069fe89..5376f17 100644 (file)
@@ -110,10 +110,16 @@ static NSURLSessionAuthChallengeDisposition toNSURLSessionAuthChallengeDispositi
 {
     if (auto* networkDataTask = _session->dataTaskForIdentifier(task.taskIdentifier)) {
         auto completionHandlerCopy = Block_copy(completionHandler);
-        networkDataTask->client().didReceiveChallenge(challenge, [completionHandlerCopy](WebKit::AuthenticationChallengeDisposition disposition, const WebCore::Credential& credential) {
+        auto challengeCompletionHandler = [completionHandlerCopy](WebKit::AuthenticationChallengeDisposition disposition, const WebCore::Credential& credential)
+        {
             completionHandlerCopy(toNSURLSessionAuthChallengeDisposition(disposition), credential.nsCredential());
             Block_release(completionHandlerCopy);
-        });
+        };
+        
+        if (networkDataTask->tryPasswordBasedAuthentication(challenge, challengeCompletionHandler))
+            return;
+        
+        networkDataTask->client().didReceiveChallenge(challenge, challengeCompletionHandler);
     }
 }
 
@@ -229,11 +235,6 @@ NetworkSession::~NetworkSession()
     [m_session invalidateAndCancel];
 }
 
-std::unique_ptr<NetworkDataTask> NetworkSession::createDataTaskWithRequest(const WebCore::ResourceRequest& request, NetworkSessionTaskClient& client)
-{
-    return std::make_unique<NetworkDataTask>(*this, client, [m_session dataTaskWithRequest:request.nsURLRequest(WebCore::UpdateHTTPBody)]);
-}
-
 NetworkDataTask* NetworkSession::dataTaskForIdentifier(NetworkDataTask::TaskIdentifier taskIdentifier)
 {
     ASSERT(isMainThread());
@@ -263,13 +264,20 @@ DownloadID NetworkSession::takeDownloadID(NetworkDataTask::TaskIdentifier taskId
     return downloadID;
 }
 
-NetworkDataTask::NetworkDataTask(NetworkSession& session, NetworkSessionTaskClient& client, RetainPtr<NSURLSessionDataTask>&& task)
+NetworkDataTask::NetworkDataTask(NetworkSession& session, NetworkSessionTaskClient& client, const WebCore::ResourceRequest& requestWithCredentials)
     : m_session(session)
     , m_client(client)
-    , m_task(WTFMove(task))
 {
-    ASSERT(!m_session.m_dataTaskMap.contains(taskIdentifier()));
     ASSERT(isMainThread());
+
+    auto request = requestWithCredentials;
+    m_user = request.url().user();
+    m_password = request.url().pass();
+    request.removeCredentials();
+    
+    m_task = [m_session.m_session dataTaskWithRequest:request.nsURLRequest(WebCore::UpdateHTTPBody)];
+    
+    ASSERT(!m_session.m_dataTaskMap.contains(taskIdentifier()));
     m_session.m_dataTaskMap.add(taskIdentifier(), this);
 }
 
@@ -281,6 +289,21 @@ NetworkDataTask::~NetworkDataTask()
     m_session.m_dataTaskMap.remove(taskIdentifier());
 }
 
+bool NetworkDataTask::tryPasswordBasedAuthentication(const WebCore::AuthenticationChallenge& challenge, ChallengeCompletionHandler completionHandler)
+{
+    if (!challenge.protectionSpace().isPasswordBased())
+        return false;
+
+    if (!m_user.isNull() && !m_password.isNull()) {
+        completionHandler(AuthenticationChallengeDisposition::UseCredential, WebCore::Credential(m_user, m_password, WebCore::CredentialPersistenceForSession));
+        m_user = String();
+        m_password = String();
+        return true;
+    }
+
+    return false;
+}
+    
 void NetworkDataTask::cancel()
 {
     [m_task cancel];
index 773ee2a..08e59a5 100644 (file)
@@ -56,7 +56,6 @@ public:
     static const char* supplementName();
 
 #if USE(NETWORK_SESSION)
-    typedef NetworkSessionTaskClient::ChallengeCompletionHandler ChallengeCompletionHandler;
     void didReceiveAuthenticationChallenge(uint64_t pageID, uint64_t frameID, const WebCore::AuthenticationChallenge&, ChallengeCompletionHandler);
     void didReceiveAuthenticationChallenge(PendingDownload&, const WebCore::AuthenticationChallenge&, ChallengeCompletionHandler);
     void continueCanAuthenticateAgainstProtectionSpace(DownloadID, bool canAuthenticate);