Diff
Modified: trunk/Source/WebCore/ChangeLog (197525 => 197526)
--- trunk/Source/WebCore/ChangeLog 2016-03-03 23:57:13 UTC (rev 197525)
+++ trunk/Source/WebCore/ChangeLog 2016-03-04 00:21:34 UTC (rev 197526)
@@ -1,3 +1,17 @@
+2016-03-03 Alex Christensen <[email protected]>
+
+ Use CredentialStorage with NetworkSession
+ https://bugs.webkit.org/show_bug.cgi?id=154939
+
+ Reviewed by Darin Adler.
+
+ This makes the credential-based http tests pass when using NetworkSession.
+
+ * platform/network/CredentialBase.h:
+ (WebCore::CredentialBase::encodingRequiresPlatformData):
+ * platform/network/CredentialStorage.h:
+ WEBCORE_EXPORT more things that are newly used in WebKit2.
+
2016-03-03 Zalan Bujtas <[email protected]>
Subpixel rendering: Make collapsed borders painting subpixel aware.
Modified: trunk/Source/WebCore/platform/network/CredentialBase.h (197525 => 197526)
--- trunk/Source/WebCore/platform/network/CredentialBase.h 2016-03-03 23:57:13 UTC (rev 197525)
+++ trunk/Source/WebCore/platform/network/CredentialBase.h 2016-03-04 00:21:34 UTC (rev 197526)
@@ -51,7 +51,7 @@
bool encodingRequiresPlatformData() const { return false; }
- static bool compare(const Credential&, const Credential&);
+ WEBCORE_EXPORT static bool compare(const Credential&, const Credential&);
protected:
WEBCORE_EXPORT CredentialBase();
Modified: trunk/Source/WebCore/platform/network/CredentialStorage.h (197525 => 197526)
--- trunk/Source/WebCore/platform/network/CredentialStorage.h 2016-03-03 23:57:13 UTC (rev 197525)
+++ trunk/Source/WebCore/platform/network/CredentialStorage.h 2016-03-04 00:21:34 UTC (rev 197526)
@@ -43,9 +43,9 @@
WEBCORE_EXPORT static CredentialStorage& defaultCredentialStorage();
// WebCore session credential storage.
- void set(const Credential&, const ProtectionSpace&, const URL&);
+ WEBCORE_EXPORT void set(const Credential&, const ProtectionSpace&, const URL&);
WEBCORE_EXPORT Credential get(const ProtectionSpace&);
- void remove(const ProtectionSpace&);
+ WEBCORE_EXPORT void remove(const ProtectionSpace&);
// OS persistent storage.
WEBCORE_EXPORT Credential getFromPersistentStorage(const ProtectionSpace&);
@@ -58,7 +58,7 @@
// These methods work for authentication schemes that support sending credentials without waiting for a request. E.g., for HTTP Basic authentication scheme
// a client should assume that all paths at or deeper than the depth of a known protected resource share are within the same protection space.
- bool set(const Credential&, const URL&); // Returns true if the URL corresponds to a known protection space, so credentials could be updated.
+ WEBCORE_EXPORT bool set(const Credential&, const URL&); // Returns true if the URL corresponds to a known protection space, so credentials could be updated.
WEBCORE_EXPORT Credential get(const URL&);
private:
Modified: trunk/Source/WebKit2/ChangeLog (197525 => 197526)
--- trunk/Source/WebKit2/ChangeLog 2016-03-03 23:57:13 UTC (rev 197525)
+++ trunk/Source/WebKit2/ChangeLog 2016-03-04 00:21:34 UTC (rev 197526)
@@ -1,3 +1,53 @@
+2016-03-03 Alex Christensen <[email protected]>
+
+ Use CredentialStorage with NetworkSession
+ https://bugs.webkit.org/show_bug.cgi?id=154939
+
+ Reviewed by Darin Adler.
+
+ * config.h:
+ Added compile-time flag to help us be able to keep track and remove this code when we can.
+ * NetworkProcess/NetworkDataTask.h:
+ (WebKit::NetworkDataTask::pendingDownloadLocation):
+ * NetworkProcess/NetworkProcess.cpp:
+ (WebKit::NetworkProcess::clearCachedCredentials):
+ (WebKit::NetworkProcess::ensurePrivateBrowsingSession):
+ * NetworkProcess/NetworkSession.h:
+ (WebKit::NetworkSession::sessionID):
+ * NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:
+ (WebKit::applyBasicAuthorizationHeader):
+ (WebKit::NetworkDataTask::NetworkDataTask):
+ Use a credential storage and preemptively apply basic authentication headers if we have credentials from the storage.
+ This is analogous to code in ResourceHandle::createNSURLConnection.
+
+ (WebKit::NetworkDataTask::didReceiveChallenge):
+ Make this look more like ResourceHandle::didReceiveAuthenticationChallenge.
+ The call to tryPasswordBasedAuthentication was moved from the delegate callback to here.
+
+ (WebKit::NetworkDataTask::willPerformHTTPRedirection):
+ Use credentials from the credential storage if they exist. This is analogous to code in ResourceHandle::willSendRequest.
+
+ (WebKit::NetworkDataTask::tryPasswordBasedAuthentication):
+ Use credentials from the credential storage if they exist. This is analogous to code in ResourceHandle::tryHandlePasswordBasedAuthentication.
+
+ * NetworkProcess/cocoa/NetworkSessionCocoa.mm:
+ (-[WKNetworkSessionDelegate URLSession:task:didReceiveChallenge:completionHandler:]):
+ If we are given a credential with CredentialPersistenceForSession, put it in the credential storage and give
+ CFNetwork a credential with CredentialPersistenceNone so it won't automatically be used again until the credential
+ storage says its ok to use again. This gives us the ability to clear session credentials when logout credentials are used.
+ This is analogous to code in ResourceHandle::receivedCredential.
+
+ (WebKit::NetworkSession::defaultSession):
+ (WebKit::NetworkSession::NetworkSession):
+ (WebKit::NetworkSession::~NetworkSession):
+ (WebKit::NetworkSession::dataTaskForIdentifier):
+ (WebKit::NetworkSession::clearCredentials): Deleted.
+ * WebProcess/WebProcess.cpp:
+ (WebKit::WebProcess::clearCachedCredentials):
+ (WebKit::WebProcess::focusedWebPage):
+ We no longer need to clear credentials from the NSURLSessions because we don't store session credentials in them.
+ Instead, calling CredentialStorage.clearCredentials is sufficient.
+
2016-03-03 Andy Estes <[email protected]>
Adopt CFNetwork storage partitioning SPI
Modified: trunk/Source/WebKit2/NetworkProcess/NetworkDataTask.h (197525 => 197526)
--- trunk/Source/WebKit2/NetworkProcess/NetworkDataTask.h 2016-03-03 23:57:13 UTC (rev 197525)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkDataTask.h 2016-03-04 00:21:34 UTC (rev 197526)
@@ -27,6 +27,7 @@
#define NetworkDataTask_h
#include "SandboxExtension.h"
+#include <WebCore/Credential.h>
#include <WebCore/FrameLoaderTypes.h>
#include <WebCore/ResourceHandleTypes.h>
#include <WebCore/ResourceLoaderOptions.h>
@@ -122,12 +123,13 @@
const String& pendingDownloadLocation() { return m_pendingDownloadLocation; }
WebCore::ResourceRequest currentRequest();
String suggestedFilename();
- bool tryPasswordBasedAuthentication(const WebCore::AuthenticationChallenge&, ChallengeCompletionHandler);
void willPerformHTTPRedirection(const WebCore::ResourceResponse&, WebCore::ResourceRequest&&, RedirectCompletionHandler);
void transferSandboxExtensionToDownload(Download&);
private:
NetworkDataTask(NetworkSession&, NetworkDataTaskClient&, const WebCore::ResourceRequest&, WebCore::StoredCredentials, WebCore::ContentSniffingPolicy, bool shouldClearReferrerOnHTTPSToHTTPRedirect);
+
+ bool tryPasswordBasedAuthentication(const WebCore::AuthenticationChallenge&, ChallengeCompletionHandler);
enum FailureType {
NoFailure,
@@ -145,6 +147,9 @@
DownloadID m_pendingDownloadID;
String m_user;
String m_password;
+#if USE(CREDENTIAL_STORAGE_WITH_NETWORK_SESSION)
+ WebCore::Credential m_initialCredential;
+#endif
WebCore::StoredCredentials m_storedCredentials;
String m_lastHTTPMethod;
String m_pendingDownloadLocation;
Modified: trunk/Source/WebKit2/NetworkProcess/NetworkProcess.cpp (197525 => 197526)
--- trunk/Source/WebKit2/NetworkProcess/NetworkProcess.cpp 2016-03-03 23:57:13 UTC (rev 197525)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkProcess.cpp 2016-03-04 00:21:34 UTC (rev 197526)
@@ -273,7 +273,7 @@
void NetworkProcess::clearCachedCredentials()
{
NetworkStorageSession::defaultStorageSession().credentialStorage().clearCredentials();
-#if USE(NETWORK_SESSION)
+#if USE(NETWORK_SESSION) && !USE(CREDENTIAL_STORAGE_WITH_NETWORK_SESSION)
NetworkSession::defaultSession().clearCredentials();
#endif
}
Modified: trunk/Source/WebKit2/NetworkProcess/NetworkSession.h (197525 => 197526)
--- trunk/Source/WebKit2/NetworkProcess/NetworkSession.h 2016-03-03 23:57:13 UTC (rev 197525)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkSession.h 2016-03-04 00:21:34 UTC (rev 197526)
@@ -53,9 +53,12 @@
NetworkSession(Type, WebCore::SessionID, CustomProtocolManager*);
~NetworkSession();
+ WebCore::SessionID sessionID() { return m_sessionID; }
static void setCustomProtocolManager(CustomProtocolManager*);
static NetworkSession& defaultSession();
+#if !USE(CREDENTIAL_STORAGE_WITH_NETWORK_SESSION)
void clearCredentials();
+#endif
NetworkDataTask* dataTaskForIdentifier(NetworkDataTask::TaskIdentifier, WebCore::StoredCredentials);
@@ -64,6 +67,7 @@
DownloadID takeDownloadID(NetworkDataTask::TaskIdentifier);
private:
+ WebCore::SessionID m_sessionID;
HashMap<NetworkDataTask::TaskIdentifier, NetworkDataTask*> m_dataTaskMapWithCredentials;
HashMap<NetworkDataTask::TaskIdentifier, NetworkDataTask*> m_dataTaskMapWithoutCredentials;
HashMap<NetworkDataTask::TaskIdentifier, DownloadID> m_downloadMap;
Modified: trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm (197525 => 197526)
--- trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm 2016-03-03 23:57:13 UTC (rev 197525)
+++ trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm 2016-03-04 00:21:34 UTC (rev 197526)
@@ -31,18 +31,27 @@
#import "Download.h"
#import "DownloadProxyMessages.h"
#import "NetworkProcess.h"
+#import "SessionTracker.h"
#import "WebCoreArgumentCoders.h"
#import <WebCore/AuthenticationChallenge.h>
#import <WebCore/CFNetworkSPI.h>
#import <WebCore/NetworkStorageSession.h>
#import <WebCore/ResourceRequest.h>
#import <wtf/MainThread.h>
+#import <wtf/text/Base64.h>
@interface NSURLSessionTask ()
@property (readwrite, copy) NSString *_pathToDownloadTaskFile;
@end
namespace WebKit {
+#if USE(CREDENTIAL_STORAGE_WITH_NETWORK_SESSION)
+static void applyBasicAuthorizationHeader(WebCore::ResourceRequest& request, const WebCore::Credential& credential)
+{
+ String authenticationHeader = "Basic " + base64Encode(String(credential.user() + ":" + credential.password()).utf8());
+ request.setHTTPHeaderField(WebCore::HTTPHeaderName::Authorization, authenticationHeader);
+}
+#endif
NetworkDataTask::NetworkDataTask(NetworkSession& session, NetworkDataTaskClient& client, const WebCore::ResourceRequest& requestWithCredentials, WebCore::StoredCredentials storedCredentials, WebCore::ContentSniffingPolicy shouldContentSniff, bool shouldClearReferrerOnHTTPSToHTTPRedirect)
: m_failureTimer(*this, &NetworkDataTask::failureTimerFired)
@@ -66,10 +75,31 @@
}
auto request = requestWithCredentials;
- m_user = request.url().user();
- m_password = request.url().pass();
- request.removeCredentials();
+ auto url = ""
+ if (storedCredentials == WebCore::AllowStoredCredentials && url.protocolIsInHTTPFamily()) {
+ m_user = url.user();
+ m_password = url.pass();
+ request.removeCredentials();
+ url = ""
+#if USE(CREDENTIAL_STORAGE_WITH_NETWORK_SESSION)
+ if (auto storageSession = SessionTracker::storageSession(m_session.sessionID())) {
+ if (m_user.isEmpty() && m_password.isEmpty())
+ m_initialCredential = storageSession->credentialStorage().get(url);
+ else
+ storageSession->credentialStorage().set(WebCore::Credential(m_user, m_password, WebCore::CredentialPersistenceNone), url);
+ } else
+ RELEASE_ASSERT_NOT_REACHED();
+#endif
+ }
+
+#if USE(CREDENTIAL_STORAGE_WITH_NETWORK_SESSION)
+ if (!m_initialCredential.isEmpty()) {
+ // FIXME: Support Digest authentication, and Proxy-Authorization.
+ applyBasicAuthorizationHeader(request, m_initialCredential);
+ }
+#endif
+
NSURLRequest *nsRequest = request.nsURLRequest(WebCore::UpdateHTTPBody);
if (shouldContentSniff == WebCore::DoNotSniffContent) {
NSMutableURLRequest *mutableRequest = [[nsRequest mutableCopy] autorelease];
@@ -116,6 +146,16 @@
void NetworkDataTask::didReceiveChallenge(const WebCore::AuthenticationChallenge& challenge, ChallengeCompletionHandler completionHandler)
{
+ // Proxy authentication is handled by CFNetwork internally. We can get here if the user cancels
+ // CFNetwork authentication dialog, and we shouldn't ask the client to display another one in that case.
+ if (challenge.protectionSpace().isProxy()) {
+ completionHandler(AuthenticationChallengeDisposition::UseCredential, { });
+ return;
+ }
+
+ if (tryPasswordBasedAuthentication(challenge, completionHandler))
+ return;
+
if (m_client)
m_client->didReceiveChallenge(challenge, completionHandler);
}
@@ -172,6 +212,23 @@
// we want to strip here because the redirect is cross-origin.
request.clearHTTPAuthorization();
request.clearHTTPOrigin();
+#if USE(CREDENTIAL_STORAGE_WITH_NETWORK_SESSION)
+ } else {
+ // Only consider applying authentication credentials if this is actually a redirect and the redirect
+ // URL didn't include credentials of its own.
+ if (m_user.isEmpty() && m_password.isEmpty() && !redirectResponse.isNull()) {
+ if (auto storageSession = SessionTracker::storageSession(m_session.sessionID())) {
+ auto credential = storageSession->credentialStorage().get(request.url());
+ if (!credential.isEmpty()) {
+ m_initialCredential = credential;
+
+ // FIXME: Support Digest authentication, and Proxy-Authorization.
+ applyBasicAuthorizationHeader(request, m_initialCredential);
+ }
+ } else
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+#endif
}
if (m_client)
@@ -230,7 +287,34 @@
m_password = String();
return true;
}
-
+
+#if USE(CREDENTIAL_STORAGE_WITH_NETWORK_SESSION)
+ if (m_storedCredentials == WebCore::AllowStoredCredentials) {
+ if (auto storageSession = SessionTracker::storageSession(m_session.sessionID())) {
+ if (!m_initialCredential.isEmpty() || challenge.previousFailureCount()) {
+ // The stored credential wasn't accepted, stop using it.
+ // There is a race condition here, since a different credential might have already been stored by another ResourceHandle,
+ // but the observable effect should be very minor, if any.
+ storageSession->credentialStorage().remove(challenge.protectionSpace());
+ }
+
+ if (!challenge.previousFailureCount()) {
+ auto credential = storageSession->credentialStorage().get(challenge.protectionSpace());
+ if (!credential.isEmpty() && credential != m_initialCredential) {
+ ASSERT(credential.persistence() == WebCore::CredentialPersistenceNone);
+ if (challenge.failureResponse().httpStatusCode() == 401) {
+ // Store the credential back, possibly adding it as a default for this directory.
+ storageSession->credentialStorage().set(credential, challenge.protectionSpace(), challenge.failureResponse().url());
+ }
+ completionHandler(AuthenticationChallengeDisposition::UseCredential, credential);
+ return true;
+ }
+ }
+ } else
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+#endif
+
if (!challenge.proposedCredential().isEmpty() && !challenge.previousFailureCount()) {
completionHandler(AuthenticationChallengeDisposition::UseCredential, challenge.proposedCredential());
return true;
Modified: trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm (197525 => 197526)
--- trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm 2016-03-03 23:57:13 UTC (rev 197525)
+++ trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm 2016-03-04 00:21:34 UTC (rev 197526)
@@ -119,16 +119,30 @@
{
auto storedCredentials = session.configuration.URLCredentialStorage ? WebCore::StoredCredentials::AllowStoredCredentials : WebCore::StoredCredentials::DoNotAllowStoredCredentials;
if (auto* networkDataTask = _session->dataTaskForIdentifier(task.taskIdentifier, storedCredentials)) {
+ WebCore::AuthenticationChallenge authenticationChallenge(challenge);
auto completionHandlerCopy = Block_copy(completionHandler);
- auto challengeCompletionHandler = [completionHandlerCopy](WebKit::AuthenticationChallengeDisposition disposition, const WebCore::Credential& credential)
+ auto sessionID = _session->sessionID();
+ auto challengeCompletionHandler = [completionHandlerCopy, sessionID, authenticationChallenge](WebKit::AuthenticationChallengeDisposition disposition, const WebCore::Credential& credential)
{
- completionHandlerCopy(toNSURLSessionAuthChallengeDisposition(disposition), credential.nsCredential());
+#if !USE(CREDENTIAL_STORAGE_WITH_NETWORK_SESSION)
+ UNUSED_PARAM(sessionID);
+ UNUSED_PARAM(authenticationChallenge);
+#else
+ if (credential.persistence() == WebCore::CredentialPersistenceForSession && authenticationChallenge.protectionSpace().authenticationScheme() != WebCore::ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested) {
+
+ WebCore::Credential nonPersistentCredential(credential.user(), credential.password(), WebCore::CredentialPersistenceNone);
+ WebCore::URL urlToStore;
+ if (authenticationChallenge.failureResponse().httpStatusCode() == 401)
+ urlToStore = authenticationChallenge.failureResponse().url();
+ if (auto storageSession = WebKit::SessionTracker::storageSession(sessionID))
+ storageSession->credentialStorage().set(nonPersistentCredential, authenticationChallenge.protectionSpace(), urlToStore);
+
+ completionHandlerCopy(toNSURLSessionAuthChallengeDisposition(disposition), nonPersistentCredential.nsCredential());
+ } else
+#endif
+ completionHandlerCopy(toNSURLSessionAuthChallengeDisposition(disposition), credential.nsCredential());
Block_release(completionHandlerCopy);
};
-
- if (networkDataTask->tryPasswordBasedAuthentication(challenge, challengeCompletionHandler))
- return;
-
networkDataTask->didReceiveChallenge(challenge, challengeCompletionHandler);
}
}
@@ -243,6 +257,7 @@
}
NetworkSession::NetworkSession(Type type, WebCore::SessionID sessionID, CustomProtocolManager* customProtocolManager)
+ : m_sessionID(sessionID)
{
m_sessionDelegate = adoptNS([[WKNetworkSessionDelegate alloc] initWithNetworkSession:*this]);
@@ -272,6 +287,7 @@
[m_sessionWithoutCredentialStorage invalidateAndCancel];
}
+#if !USE(CREDENTIAL_STORAGE_WITH_NETWORK_SESSION)
void NetworkSession::clearCredentials()
{
ASSERT(m_dataTaskMapWithCredentials.isEmpty());
@@ -279,6 +295,7 @@
ASSERT(m_downloadMap.isEmpty());
m_sessionWithCredentialStorage = [NSURLSession sessionWithConfiguration:m_sessionWithCredentialStorage.get().configuration delegate:static_cast<id>(m_sessionDelegate.get()) delegateQueue:[NSOperationQueue mainQueue]];
}
+#endif
NetworkDataTask* NetworkSession::dataTaskForIdentifier(NetworkDataTask::TaskIdentifier taskIdentifier, WebCore::StoredCredentials storedCredentials)
{
Modified: trunk/Source/WebKit2/WebProcess/WebProcess.cpp (197525 => 197526)
--- trunk/Source/WebKit2/WebProcess/WebProcess.cpp 2016-03-03 23:57:13 UTC (rev 197525)
+++ trunk/Source/WebKit2/WebProcess/WebProcess.cpp 2016-03-04 00:21:34 UTC (rev 197526)
@@ -505,7 +505,7 @@
void WebProcess::clearCachedCredentials()
{
NetworkStorageSession::defaultStorageSession().credentialStorage().clearCredentials();
-#if USE(NETWORK_SESSION)
+#if USE(NETWORK_SESSION) && !USE(CREDENTIAL_STORAGE_WITH_NETWORK_SESSION)
NetworkSession::defaultSession().clearCredentials();
#endif
}
Modified: trunk/Source/WebKit2/config.h (197525 => 197526)
--- trunk/Source/WebKit2/config.h 2016-03-03 23:57:13 UTC (rev 197525)
+++ trunk/Source/WebKit2/config.h 2016-03-04 00:21:34 UTC (rev 197526)
@@ -76,7 +76,12 @@
#ifndef USE_NETWORK_SESSION
#define USE_NETWORK_SESSION 0
#endif
+
+// FIXME: We should work towards not using CredentialStorage in WebKit2 to not have problems with digest authentication.
+#ifndef USE_CREDENTIAL_STORAGE_WITH_NETWORK_SESSION
+#define USE_CREDENTIAL_STORAGE_WITH_NETWORK_SESSION 1
#endif
+#endif
#ifndef HAVE_SEC_ACCESS_CONTROL
#if PLATFORM(IOS) || PLATFORM(MAC)