Diff
Modified: trunk/Source/WebCore/ChangeLog (228576 => 228577)
--- trunk/Source/WebCore/ChangeLog 2018-02-16 21:38:53 UTC (rev 228576)
+++ trunk/Source/WebCore/ChangeLog 2018-02-16 21:39:38 UTC (rev 228577)
@@ -1,3 +1,84 @@
+2018-02-16 Basuke Suzuki <[email protected]>
+
+ [Curl] Unify logic of ResourceHandleCurlDelegate into ResourceHandle
+ https://bugs.webkit.org/show_bug.cgi?id=182578
+
+ Reconstruct the classes to match Curl port network layer more similar
+ structure with other ports. Move CurlRequest handling into ResourceHandle
+ and makes CurlResourceHandleDelegate simple life cycle. Also its duty is
+ for most of incoming data and event handling from CurRequest.
+
+ Reviewed by Alex Christensen.
+
+ No new tests because there's no new behavior.
+
+ * platform/Curl.cmake:
+ * platform/network/ResourceHandle.h:
+ * platform/network/ResourceHandleInternal.h:
+ (WebCore::ResourceHandleInternal::ResourceHandleInternal):
+ * platform/network/curl/CurlCacheManager.cpp:
+ (WebCore::CurlCacheManager::didReceiveResponse):
+ * platform/network/curl/CurlDownload.cpp:
+ (WebCore::CurlDownload::~CurlDownload):
+ (WebCore::CurlDownload::createCurlRequest):
+ (WebCore::CurlDownload::curlDidReceiveResponse):
+ (WebCore::CurlDownload::curlDidReceiveBuffer):
+ (WebCore::CurlDownload::curlDidComplete):
+ (WebCore::CurlDownload::curlDidFailWithError):
+ (WebCore::CurlDownload::willSendRequest):
+ * platform/network/curl/CurlDownload.h:
+ * platform/network/curl/CurlRequest.cpp:
+ (WebCore::CurlRequest::CurlRequest):
+ (WebCore::CurlRequest::cancel):
+ (WebCore::CurlRequest::callClient):
+ (WebCore::CurlRequest::willSendData):
+ (WebCore::CurlRequest::didReceiveData):
+ (WebCore::CurlRequest::didReceiveDataFromMultipart):
+ (WebCore::CurlRequest::didCompleteTransfer):
+ (WebCore::CurlRequest::invokeDidReceiveResponse):
+ * platform/network/curl/CurlRequest.h:
+ (WebCore::CurlRequest::create):
+ (WebCore::CurlRequest::invalidateClient):
+ (WebCore::CurlRequest::setClient): Deleted.
+ * platform/network/curl/CurlRequestClient.h:
+ * platform/network/curl/CurlResourceHandleDelegate.cpp: Added.
+ (WebCore::CurlResourceHandleDelegate::CurlResourceHandleDelegate):
+ (WebCore::CurlResourceHandleDelegate::ref):
+ (WebCore::CurlResourceHandleDelegate::deref):
+ (WebCore::CurlResourceHandleDelegate::cancelledOrClientless):
+ (WebCore::CurlResourceHandleDelegate::client const):
+ (WebCore::CurlResourceHandleDelegate::d):
+ (WebCore::CurlResourceHandleDelegate::curlDidSendData):
+ (WebCore::handleCookieHeaders):
+ (WebCore::CurlResourceHandleDelegate::curlDidReceiveResponse):
+ (WebCore::CurlResourceHandleDelegate::curlDidReceiveBuffer):
+ (WebCore::CurlResourceHandleDelegate::curlDidComplete):
+ (WebCore::CurlResourceHandleDelegate::curlDidFailWithError):
+ * platform/network/curl/CurlResourceHandleDelegate.h: Added.
+ (WebCore::CurlResourceHandleDelegate::response const):
+ * platform/network/curl/ResourceHandleCurl.cpp:
+ (WebCore::ResourceHandleInternal::~ResourceHandleInternal):
+ (WebCore::ResourceHandle::start):
+ (WebCore::ResourceHandle::cancel):
+ (WebCore::ResourceHandle::cancelledOrClientless):
+ (WebCore::ResourceHandle::createCurlRequest):
+ (WebCore::ResourceHandle::delegate):
+ (WebCore::ResourceHandle::platformSetDefersLoading):
+ (WebCore::ResourceHandle::didReceiveAuthenticationChallenge):
+ (WebCore::ResourceHandle::receivedCredential):
+ (WebCore::ResourceHandle::receivedRequestToContinueWithoutCredential):
+ (WebCore::ResourceHandle::getCredential):
+ (WebCore::ResourceHandle::restartRequestWithCredential):
+ (WebCore::ResourceHandle::platformLoadResourceSynchronously):
+ (WebCore::ResourceHandle::platformContinueSynchronousDidReceiveResponse):
+ (WebCore::ResourceHandle::continueAfterDidReceiveResponse):
+ (WebCore::ResourceHandle::shouldRedirectAsGET):
+ (WebCore::ResourceHandle::willSendRequest):
+ (WebCore::ResourceHandle::continueAfterWillSendRequest):
+ (WebCore::ResourceHandle::handleDataURL):
+ * platform/network/curl/ResourceHandleCurlDelegate.cpp: Removed.
+ * platform/network/curl/ResourceHandleCurlDelegate.h: Removed.
+
2018-02-16 Youenn Fablet <[email protected]>
Use ResourceLoader to load appcache manifest
Modified: trunk/Source/WebCore/platform/Curl.cmake (228576 => 228577)
--- trunk/Source/WebCore/platform/Curl.cmake 2018-02-16 21:38:53 UTC (rev 228576)
+++ trunk/Source/WebCore/platform/Curl.cmake 2018-02-16 21:39:38 UTC (rev 228577)
@@ -18,6 +18,7 @@
platform/network/curl/CurlMultipartHandle.cpp
platform/network/curl/CurlRequest.cpp
platform/network/curl/CurlRequestScheduler.cpp
+ platform/network/curl/CurlResourceHandleDelegate.cpp
platform/network/curl/CurlSSLHandle.cpp
platform/network/curl/CurlSSLVerifier.cpp
platform/network/curl/DNSCurl.cpp
@@ -25,7 +26,6 @@
platform/network/curl/ProxyServerCurl.cpp
platform/network/curl/ResourceErrorCurl.cpp
platform/network/curl/ResourceHandleCurl.cpp
- platform/network/curl/ResourceHandleCurlDelegate.cpp
platform/network/curl/ResourceResponseCurl.cpp
platform/network/curl/SocketStreamHandleImplCurl.cpp
platform/network/curl/SynchronousLoaderClientCurl.cpp
Modified: trunk/Source/WebCore/platform/network/ResourceHandle.h (228576 => 228577)
--- trunk/Source/WebCore/platform/network/ResourceHandle.h 2018-02-16 21:38:53 UTC (rev 228576)
+++ trunk/Source/WebCore/platform/network/ResourceHandle.h 2018-02-16 21:39:38 UTC (rev 228577)
@@ -36,6 +36,10 @@
#include <wtf/RetainPtr.h>
#endif
+#if USE(CURL)
+#include "CurlResourceHandleDelegate.h"
+#endif
+
#if USE(SOUP)
typedef struct _GTlsCertificate GTlsCertificate;
typedef struct _SoupSession SoupSession;
@@ -92,6 +96,11 @@
class SharedBuffer;
class Timer;
+#if USE(CURL)
+class CurlRequest;
+class CurlResourceHandleDelegate;
+#endif
+
class ResourceHandle : public RefCounted<ResourceHandle>, public AuthenticationClient {
public:
WEBCORE_EXPORT static RefPtr<ResourceHandle> create(NetworkingContext*, const ResourceRequest&, ResourceHandleClient*, bool defersLoading, bool shouldContentSniff, bool shouldContentEncodingSniff);
@@ -185,6 +194,15 @@
MonotonicTime m_requestTime;
#endif
+#if USE(CURL)
+ bool cancelledOrClientless();
+ CurlResourceHandleDelegate* delegate();
+
+ void continueAfterDidReceiveResponse();
+ void willSendRequest();
+ void continueAfterWillSendRequest(ResourceRequest&&);
+#endif
+
bool hasAuthenticationChallenge() const;
void clearAuthentication();
WEBCORE_EXPORT virtual void cancel();
@@ -278,6 +296,17 @@
void timeoutFired();
#endif
+#if USE(CURL)
+ Ref<CurlRequest> createCurlRequest(ResourceRequest&);
+
+ bool shouldRedirectAsGET(const ResourceRequest&, bool crossOrigin);
+
+ std::optional<std::pair<String, String>> getCredential(ResourceRequest&, bool);
+ void restartRequestWithCredential(const String& user, const String& password);
+
+ void handleDataURL();
+#endif
+
friend class ResourceHandleInternal;
std::unique_ptr<ResourceHandleInternal> d;
};
Modified: trunk/Source/WebCore/platform/network/ResourceHandleInternal.h (228576 => 228577)
--- trunk/Source/WebCore/platform/network/ResourceHandleInternal.h 2018-02-16 21:38:53 UTC (rev 228576)
+++ trunk/Source/WebCore/platform/network/ResourceHandleInternal.h 2018-02-16 21:39:38 UTC (rev 228577)
@@ -37,13 +37,8 @@
#include <pal/spi/cf/CFNetworkSPI.h>
#endif
-#if USE(CURL) && PLATFORM(WIN)
-#include <winsock2.h>
-#include <windows.h>
-#endif
-
#if USE(CURL)
-#include "ResourceHandleCurlDelegate.h"
+#include "CurlRequest.h"
#endif
#if USE(SOUP)
@@ -81,7 +76,7 @@
, m_defersLoading(defersLoading)
, m_shouldContentSniff(shouldContentSniff)
, m_shouldContentEncodingSniff(shouldContentEncodingSniff)
-#if USE(CFURLCONNECTION)
+#if USE(CFURLCONNECTION) || USE(CURL)
, m_currentRequest(request)
#endif
#if USE(SOUP)
@@ -132,8 +127,14 @@
RetainPtr<CFURLStorageSessionRef> m_storageSession;
#endif
#if USE(CURL)
- RefPtr<ResourceHandleCurlDelegate> m_delegate;
- ResourceResponse m_response;
+ std::unique_ptr<CurlResourceHandleDelegate> m_delegate;
+
+ ResourceRequest m_currentRequest;
+ bool m_cancelled { false };
+ unsigned m_redirectCount { 0 };
+ unsigned m_authFailureCount { 0 };
+ bool m_addedCacheValidationHeaders { false };
+ RefPtr<CurlRequest> m_curlRequest;
#endif
#if USE(SOUP)
Modified: trunk/Source/WebCore/platform/network/curl/CurlCacheManager.cpp (228576 => 228577)
--- trunk/Source/WebCore/platform/network/curl/CurlCacheManager.cpp 2018-02-16 21:38:53 UTC (rev 228576)
+++ trunk/Source/WebCore/platform/network/curl/CurlCacheManager.cpp 2018-02-16 21:39:38 UTC (rev 228577)
@@ -199,10 +199,6 @@
if (m_disabled)
return;
- ResourceHandleInternal* d = job.getInternal();
- if (!d->m_delegate->hasHandle())
- return;
-
const String& url = ""
removeCacheEntryClient(url, &job);
Modified: trunk/Source/WebCore/platform/network/curl/CurlDownload.cpp (228576 => 228577)
--- trunk/Source/WebCore/platform/network/curl/CurlDownload.cpp 2018-02-16 21:38:53 UTC (rev 228576)
+++ trunk/Source/WebCore/platform/network/curl/CurlDownload.cpp 2018-02-16 21:39:38 UTC (rev 228577)
@@ -40,7 +40,7 @@
CurlDownload::~CurlDownload()
{
if (m_curlRequest)
- m_curlRequest->setClient(nullptr);
+ m_curlRequest->invalidateClient();
}
void CurlDownload::init(CurlDownloadListener& listener, const URL& url)
@@ -76,10 +76,11 @@
Ref<CurlRequest> CurlDownload::createCurlRequest(ResourceRequest& request)
{
- return CurlRequest::create(request, this);
+ auto curlRequest = CurlRequest::create(request, *this);
+ return curlRequest;
}
-void CurlDownload::curlDidReceiveResponse(const CurlResponse& response)
+void CurlDownload::curlDidReceiveResponse(CurlRequest& request, const CurlResponse& response)
{
ASSERT(isMainThread());
@@ -96,11 +97,11 @@
if (m_listener)
m_listener->didReceiveResponse(m_response);
- m_curlRequest->completeDidReceiveResponse();
+ request.completeDidReceiveResponse();
}
-void CurlDownload::curlDidReceiveBuffer(Ref<SharedBuffer>&& buffer)
+void CurlDownload::curlDidReceiveBuffer(CurlRequest& request, Ref<SharedBuffer>&& buffer)
{
ASSERT(isMainThread());
@@ -111,7 +112,7 @@
m_listener->didReceiveDataOfLength(buffer->size());
}
-void CurlDownload::curlDidComplete()
+void CurlDownload::curlDidComplete(CurlRequest& request)
{
ASSERT(isMainThread());
@@ -119,8 +120,8 @@
return;
if (!m_destination.isEmpty()) {
- if (m_curlRequest && !m_curlRequest->getDownloadedFilePath().isEmpty())
- FileSystem::moveFile(m_curlRequest->getDownloadedFilePath(), m_destination);
+ if (!request.getDownloadedFilePath().isEmpty())
+ FileSystem::moveFile(request.getDownloadedFilePath(), m_destination);
}
if (m_listener)
@@ -127,7 +128,7 @@
m_listener->didFinish();
}
-void CurlDownload::curlDidFailWithError(const ResourceError& resourceError)
+void CurlDownload::curlDidFailWithError(CurlRequest& request, const ResourceError& resourceError)
{
ASSERT(isMainThread());
@@ -134,8 +135,8 @@
if (m_isCancelled)
return;
- if (m_deletesFileUponFailure && m_curlRequest && !m_curlRequest->getDownloadedFilePath().isEmpty())
- FileSystem::deleteFile(m_curlRequest->getDownloadedFilePath());
+ if (m_deletesFileUponFailure && !request.getDownloadedFilePath().isEmpty())
+ FileSystem::deleteFile(request.getDownloadedFilePath());
if (m_listener)
m_listener->didFail();
@@ -194,7 +195,6 @@
}
m_curlRequest->cancel();
- m_curlRequest->setClient(nullptr);
m_curlRequest = createCurlRequest(newRequest);
m_curlRequest->start();
Modified: trunk/Source/WebCore/platform/network/curl/CurlDownload.h (228576 => 228577)
--- trunk/Source/WebCore/platform/network/curl/CurlDownload.h 2018-02-16 21:38:53 UTC (rev 228576)
+++ trunk/Source/WebCore/platform/network/curl/CurlDownload.h 2018-02-16 21:39:38 UTC (rev 228577)
@@ -70,11 +70,11 @@
private:
Ref<CurlRequest> createCurlRequest(ResourceRequest&);
- void curlDidSendData(unsigned long long, unsigned long long) override { }
- void curlDidReceiveResponse(const CurlResponse&) override;
- void curlDidReceiveBuffer(Ref<SharedBuffer>&&) override;
- void curlDidComplete() override;
- void curlDidFailWithError(const ResourceError&) override;
+ void curlDidSendData(CurlRequest&, unsigned long long, unsigned long long) override { }
+ void curlDidReceiveResponse(CurlRequest&, const CurlResponse&) override;
+ void curlDidReceiveBuffer(CurlRequest&, Ref<SharedBuffer>&&) override;
+ void curlDidComplete(CurlRequest&) override;
+ void curlDidFailWithError(CurlRequest&, const ResourceError&) override;
bool shouldRedirectAsGET(const ResourceRequest&, bool crossOrigin);
void willSendRequest();
Modified: trunk/Source/WebCore/platform/network/curl/CurlRequest.cpp (228576 => 228577)
--- trunk/Source/WebCore/platform/network/curl/CurlRequest.cpp 2018-02-16 21:38:53 UTC (rev 228576)
+++ trunk/Source/WebCore/platform/network/curl/CurlRequest.cpp 2018-02-16 21:39:38 UTC (rev 228577)
@@ -39,13 +39,12 @@
CurlRequest::CurlRequest(const ResourceRequest&request, CurlRequestClient* client, bool shouldSuspend, bool enableMultipart)
: m_request(request.isolatedCopy())
+ , m_client(client)
, m_shouldSuspend(shouldSuspend)
, m_enableMultipart(enableMultipart)
, m_formDataStream(m_request.httpBody())
{
ASSERT(isMainThread());
-
- setClient(client);
}
void CurlRequest::setUserPass(const String& user, const String& password)
@@ -125,6 +124,7 @@
setRequestPaused(false);
setCallbackPaused(false);
+ invalidateClient();
}
void CurlRequest::suspend()
@@ -142,18 +142,18 @@
}
/* `this` is protected inside this method. */
-void CurlRequest::callClient(WTF::Function<void(CurlRequestClient&)> task)
+void CurlRequest::callClient(WTF::Function<void(CurlRequest&, CurlRequestClient&)> task)
{
if (isMainThread()) {
if (CurlRequestClient* client = m_client) {
RefPtr<CurlRequestClient> protectedClient(client);
- task(*client);
+ task(*this, *client);
}
} else {
- callOnMainThread([protectedThis = makeRef(*this), task = WTFMove(task)]() mutable {
+ callOnMainThread([this, protectedThis = makeRef(*this), task = WTFMove(task)]() mutable {
if (CurlRequestClient* client = protectedThis->m_client) {
RefPtr<CurlRequestClient> protectedClient(client);
- task(*client);
+ task(*this, *client);
}
});
}
@@ -259,8 +259,8 @@
return CURL_READFUNC_ABORT;
}
- callClient([this, totalReadSize = m_formDataStream.totalReadSize(), totalSize = m_formDataStream.totalSize()](CurlRequestClient& client) {
- client.curlDidSendData(totalReadSize, totalSize);
+ callClient([totalReadSize = m_formDataStream.totalReadSize(), totalSize = m_formDataStream.totalSize()](CurlRequest& request, CurlRequestClient& client) {
+ client.curlDidSendData(request, totalReadSize, totalSize);
});
return *sendBytes;
@@ -361,8 +361,8 @@
if (m_multipartHandle)
m_multipartHandle->didReceiveData(buffer);
else {
- callClient([buffer = WTFMove(buffer)](CurlRequestClient& client) mutable {
- client.curlDidReceiveBuffer(WTFMove(buffer));
+ callClient([buffer = WTFMove(buffer)](CurlRequest& request, CurlRequestClient& client) mutable {
+ client.curlDidReceiveBuffer(request, WTFMove(buffer));
});
}
}
@@ -393,8 +393,8 @@
auto receiveBytes = buffer->size();
if (receiveBytes) {
- callClient([buffer = WTFMove(buffer)](CurlRequestClient& client) mutable {
- client.curlDidReceiveBuffer(WTFMove(buffer));
+ callClient([buffer = WTFMove(buffer)](CurlRequest& request, CurlRequestClient& client) mutable {
+ client.curlDidReceiveBuffer(request, WTFMove(buffer));
});
}
}
@@ -421,8 +421,8 @@
m_networkLoadMetrics = *metrics;
finalizeTransfer();
- callClient([](CurlRequestClient& client) {
- client.curlDidComplete();
+ callClient([](CurlRequest& request, CurlRequestClient& client) {
+ client.curlDidComplete(request);
});
}
} else {
@@ -432,8 +432,8 @@
resourceError.setSslErrors(m_sslVerifier->sslErrors());
finalizeTransfer();
- callClient([error = resourceError.isolatedCopy()](CurlRequestClient& client) {
- client.curlDidFailWithError(error);
+ callClient([error = resourceError.isolatedCopy()](CurlRequest& request, CurlRequestClient& client) {
+ client.curlDidFailWithError(request, error);
});
}
}
@@ -533,8 +533,8 @@
m_didNotifyResponse = true;
m_actionAfterInvoke = behaviorAfterInvoke;
- callClient([response = response.isolatedCopy()](CurlRequestClient& client) {
- client.curlDidReceiveResponse(response);
+ callClient([response = response.isolatedCopy()](CurlRequest& request, CurlRequestClient& client) {
+ client.curlDidReceiveResponse(request, response);
});
}
Modified: trunk/Source/WebCore/platform/network/curl/CurlRequest.h (228576 => 228577)
--- trunk/Source/WebCore/platform/network/curl/CurlRequest.h 2018-02-16 21:38:53 UTC (rev 228576)
+++ trunk/Source/WebCore/platform/network/curl/CurlRequest.h 2018-02-16 21:39:38 UTC (rev 228577)
@@ -56,14 +56,14 @@
Yes = true
};
- static Ref<CurlRequest> create(const ResourceRequest& request, CurlRequestClient* client, ShouldSuspend shouldSuspend = ShouldSuspend::No, EnableMultipart enableMultipart = EnableMultipart::No)
+ static Ref<CurlRequest> create(const ResourceRequest& request, CurlRequestClient& client, ShouldSuspend shouldSuspend = ShouldSuspend::No, EnableMultipart enableMultipart = EnableMultipart::No)
{
- return adoptRef(*new CurlRequest(request, client, shouldSuspend == ShouldSuspend::Yes, enableMultipart == EnableMultipart::Yes));
+ return adoptRef(*new CurlRequest(request, &client, shouldSuspend == ShouldSuspend::Yes, enableMultipart == EnableMultipart::Yes));
}
virtual ~CurlRequest() = default;
- void setClient(CurlRequestClient* client) { m_client = client; }
+ void invalidateClient() { m_client = nullptr; }
void setUserPass(const String&, const String&);
void start(bool isSyncRequest = false);
@@ -102,7 +102,7 @@
void startWithJobManager();
- void callClient(WTF::Function<void(CurlRequestClient&)>);
+ void callClient(WTF::Function<void(CurlRequest&, CurlRequestClient&)>);
// Transfer processing of Request body, Response header/body
// Called by worker thread in case of async, main thread in case of sync.
Modified: trunk/Source/WebCore/platform/network/curl/CurlRequestClient.h (228576 => 228577)
--- trunk/Source/WebCore/platform/network/curl/CurlRequestClient.h 2018-02-16 21:38:53 UTC (rev 228576)
+++ trunk/Source/WebCore/platform/network/curl/CurlRequestClient.h 2018-02-16 21:39:38 UTC (rev 228577)
@@ -29,6 +29,7 @@
namespace WebCore {
+class CurlRequest;
class CurlResponse;
class ResourceError;
class SharedBuffer;
@@ -38,11 +39,11 @@
virtual void ref() = 0;
virtual void deref() = 0;
- virtual void curlDidSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) = 0;
- virtual void curlDidReceiveResponse(const CurlResponse&) = 0;
- virtual void curlDidReceiveBuffer(Ref<SharedBuffer>&&) = 0;
- virtual void curlDidComplete() = 0;
- virtual void curlDidFailWithError(const ResourceError&) = 0;
+ virtual void curlDidSendData(CurlRequest&, unsigned long long bytesSent, unsigned long long totalBytesToBeSent) = 0;
+ virtual void curlDidReceiveResponse(CurlRequest&, const CurlResponse&) = 0;
+ virtual void curlDidReceiveBuffer(CurlRequest&, Ref<SharedBuffer>&&) = 0;
+ virtual void curlDidComplete(CurlRequest&) = 0;
+ virtual void curlDidFailWithError(CurlRequest&, const ResourceError&) = 0;
};
} // namespace WebCore
Added: trunk/Source/WebCore/platform/network/curl/CurlResourceHandleDelegate.cpp (0 => 228577)
--- trunk/Source/WebCore/platform/network/curl/CurlResourceHandleDelegate.cpp (rev 0)
+++ trunk/Source/WebCore/platform/network/curl/CurlResourceHandleDelegate.cpp 2018-02-16 21:39:38 UTC (rev 228577)
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2004, 2006 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006 Michael Emmel [email protected]
+ * Copyright (C) 2017 Sony Interactive Entertainment Inc.
+ * All rights reserved.
+ * Copyright (C) 2017 NAVER Corp.
+ *
+ * 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. ``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
+ * 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 "CurlResourceHandleDelegate.h"
+
+#include "CurlCacheManager.h"
+#include "CurlRequest.h"
+#include "NetworkStorageSession.h"
+#include "ResourceHandle.h"
+#include "ResourceHandleClient.h"
+#include "ResourceHandleInternal.h"
+
+#include <wtf/CompletionHandler.h>
+
+#if USE(CURL)
+
+namespace WebCore {
+
+CurlResourceHandleDelegate::CurlResourceHandleDelegate(ResourceHandle& handle)
+ : m_handle(handle)
+{
+
+}
+
+void CurlResourceHandleDelegate::ref()
+{
+ m_handle.ref();
+}
+
+void CurlResourceHandleDelegate::deref()
+{
+ m_handle.deref();
+}
+
+bool CurlResourceHandleDelegate::cancelledOrClientless()
+{
+ return m_handle.cancelledOrClientless();
+}
+
+ResourceHandleClient* CurlResourceHandleDelegate::client() const
+{
+ return m_handle.client();
+}
+
+ResourceHandleInternal* CurlResourceHandleDelegate::d()
+{
+ return m_handle.getInternal();
+}
+
+void CurlResourceHandleDelegate::curlDidSendData(CurlRequest& request, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
+{
+ ASSERT(isMainThread());
+
+ if (cancelledOrClientless())
+ return;
+
+ client()->didSendData(&m_handle, bytesSent, totalBytesToBeSent);
+}
+
+static void handleCookieHeaders(const CurlResponse& response)
+{
+ static const auto setCookieHeader = "set-cookie: ";
+
+ const auto& storageSession = NetworkStorageSession::defaultStorageSession();
+ const auto& cookieJar = storageSession.cookieStorage();
+ for (const auto& header : response.headers) {
+ if (header.startsWithIgnoringASCIICase(setCookieHeader)) {
+ const auto contents = header.right(header.length() - strlen(setCookieHeader));
+ cookieJar.setCookiesFromHTTPResponse(storageSession, response.url, contents);
+ }
+ }
+}
+
+void CurlResourceHandleDelegate::curlDidReceiveResponse(CurlRequest& request, const CurlResponse& receivedResponse)
+{
+ ASSERT(isMainThread());
+ ASSERT(!d()->m_defersLoading);
+
+ if (cancelledOrClientless())
+ return;
+
+ m_response = ResourceResponse(receivedResponse);
+ m_response.setDeprecatedNetworkLoadMetrics(request.getNetworkLoadMetrics());
+
+ handleCookieHeaders(receivedResponse);
+
+ if (m_response.shouldRedirect()) {
+ m_handle.willSendRequest();
+ return;
+ }
+
+ if (m_response.isUnauthorized()) {
+ AuthenticationChallenge challenge(receivedResponse, d()->m_authFailureCount, m_response, &m_handle);
+ m_handle.didReceiveAuthenticationChallenge(challenge);
+ d()->m_authFailureCount++;
+ return;
+ }
+
+ if (m_response.isNotModified()) {
+ URL cacheUrl = m_response.url();
+ cacheUrl.removeFragmentIdentifier();
+
+ if (CurlCacheManager::singleton().getCachedResponse(cacheUrl, m_response)) {
+ if (d()->m_addedCacheValidationHeaders) {
+ m_response.setHTTPStatusCode(200);
+ m_response.setHTTPStatusText("OK");
+ }
+ }
+ }
+
+ CurlCacheManager::singleton().didReceiveResponse(m_handle, m_response);
+
+ m_handle.didReceiveResponse(ResourceResponse(m_response), [this, protectedHandle = makeRef(m_handle)] {
+ m_handle.continueAfterDidReceiveResponse();
+ });
+}
+
+void CurlResourceHandleDelegate::curlDidReceiveBuffer(CurlRequest& request, Ref<SharedBuffer>&& buffer)
+{
+ ASSERT(isMainThread());
+
+ if (cancelledOrClientless())
+ return;
+
+ CurlCacheManager::singleton().didReceiveData(m_handle, buffer->data(), buffer->size());
+ client()->didReceiveBuffer(&m_handle, WTFMove(buffer), buffer->size());
+}
+
+void CurlResourceHandleDelegate::curlDidComplete(CurlRequest& request)
+{
+ ASSERT(isMainThread());
+
+ if (cancelledOrClientless())
+ return;
+
+ m_response.setDeprecatedNetworkLoadMetrics(request.getNetworkLoadMetrics());
+
+ CurlCacheManager::singleton().didFinishLoading(m_handle);
+ client()->didFinishLoading(&m_handle);
+}
+
+void CurlResourceHandleDelegate::curlDidFailWithError(CurlRequest& request, const ResourceError& resourceError)
+{
+ ASSERT(isMainThread());
+
+ if (cancelledOrClientless())
+ return;
+
+ CurlCacheManager::singleton().didFail(m_handle);
+ client()->didFail(&m_handle, resourceError);
+}
+
+
+} // namespace WebCore
+
+#endif
Added: trunk/Source/WebCore/platform/network/curl/CurlResourceHandleDelegate.h (0 => 228577)
--- trunk/Source/WebCore/platform/network/curl/CurlResourceHandleDelegate.h (rev 0)
+++ trunk/Source/WebCore/platform/network/curl/CurlResourceHandleDelegate.h 2018-02-16 21:39:38 UTC (rev 228577)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2004, 2006 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. ``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
+ * 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
+
+#include "CurlRequestClient.h"
+#include "ResourceResponse.h"
+#include "SharedBuffer.h"
+
+#include <wtf/FastMalloc.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/Ref.h>
+
+namespace WebCore {
+
+class ResourceHandle;
+class ResourceHandleClient;
+class ResourceHandleInternal;
+
+class CurlResourceHandleDelegate : public CurlRequestClient {
+ WTF_MAKE_NONCOPYABLE(CurlResourceHandleDelegate); WTF_MAKE_FAST_ALLOCATED;
+public:
+ CurlResourceHandleDelegate(ResourceHandle&);
+
+ const ResourceResponse& response() const { return m_response; }
+
+ // CurlRequestClient methods
+
+ void ref();
+ void deref();
+
+ void curlDidSendData(CurlRequest&, unsigned long long bytesSent, unsigned long long totalBytesToBeSent) override;
+ void curlDidReceiveResponse(CurlRequest&, const CurlResponse&) override;
+ void curlDidReceiveBuffer(CurlRequest&, Ref<SharedBuffer>&&) override;
+ void curlDidComplete(CurlRequest&) override;
+ void curlDidFailWithError(CurlRequest&, const ResourceError&) override;
+
+private:
+ ResourceHandle& m_handle;
+ ResourceResponse m_response;
+
+ bool cancelledOrClientless();
+ ResourceHandleClient* client() const;
+ ResourceHandleInternal* d();
+};
+
+} // namespace WebCore
Modified: trunk/Source/WebCore/platform/network/curl/ResourceHandleCurl.cpp (228576 => 228577)
--- trunk/Source/WebCore/platform/network/curl/ResourceHandleCurl.cpp 2018-02-16 21:38:53 UTC (rev 228576)
+++ trunk/Source/WebCore/platform/network/curl/ResourceHandleCurl.cpp 2018-02-16 21:39:38 UTC (rev 228577)
@@ -32,20 +32,27 @@
#if USE(CURL)
+#include "CookieJarCurl.h"
#include "CredentialStorage.h"
+#include "CurlCacheManager.h"
#include "CurlContext.h"
+#include "CurlRequest.h"
#include "FileSystem.h"
+#include "HTTPParsers.h"
#include "Logging.h"
#include "ResourceHandleInternal.h"
+#include "SharedBuffer.h"
#include "SynchronousLoaderClient.h"
+#include "TextEncoding.h"
#include <wtf/CompletionHandler.h>
+#include <wtf/text/Base64.h>
namespace WebCore {
ResourceHandleInternal::~ResourceHandleInternal()
{
- if (m_delegate)
- m_delegate->releaseHandle();
+ if (m_curlRequest)
+ m_curlRequest->invalidateClient();
}
ResourceHandle::~ResourceHandle() = default;
@@ -56,6 +63,9 @@
CurlContext::singleton();
+ if (!d->m_delegate.get())
+ d->m_delegate = std::make_unique<CurlResourceHandleDelegate>(*this);
+
// The frame could be null if the ResourceHandle is not associated to any
// Frame, e.g. if we are downloading a file.
// If the frame is not null but the page is null this must be an attempted
@@ -71,17 +81,69 @@
return true;
}
- d->m_delegate = adoptRef(new ResourceHandleCurlDelegate(this));
- d->m_delegate->start();
+ d->m_curlRequest = createCurlRequest(d->m_currentRequest);
+
+ if (auto credential = getCredential(d->m_currentRequest, false))
+ d->m_curlRequest->setUserPass(credential->first, credential->second);
+
+ d->m_curlRequest->start();
+
return true;
}
void ResourceHandle::cancel()
{
- if (d->m_delegate)
- d->m_delegate->cancel();
+ ASSERT(isMainThread());
+
+ d->m_cancelled = true;
+
+ if (!d->m_curlRequest)
+ d->m_curlRequest->cancel();
}
+bool ResourceHandle::cancelledOrClientless()
+{
+ if (d->m_cancelled)
+ return true;
+
+ return !client();
+}
+
+Ref<CurlRequest> ResourceHandle::createCurlRequest(ResourceRequest& request)
+{
+ ASSERT(isMainThread());
+
+ // CurlCache : append additional cache information
+ d->m_addedCacheValidationHeaders = false;
+
+ bool hasCacheHeaders = request.httpHeaderFields().contains(HTTPHeaderName::IfModifiedSince) || request.httpHeaderFields().contains(HTTPHeaderName::IfNoneMatch);
+ if (!hasCacheHeaders) {
+ auto& cache = CurlCacheManager::singleton();
+ URL cacheUrl = request.url();
+ cacheUrl.removeFragmentIdentifier();
+
+ if (cache.isCached(cacheUrl)) {
+ cache.addCacheEntryClient(cacheUrl, this);
+
+ for (const auto& entry : cache.requestHeaders(cacheUrl))
+ request.addHTTPHeaderField(entry.key, entry.value);
+
+ d->m_addedCacheValidationHeaders = true;
+ }
+ }
+
+ CurlRequest::ShouldSuspend shouldSuspend = d->m_defersLoading ? CurlRequest::ShouldSuspend::Yes : CurlRequest::ShouldSuspend::No;
+ auto curlRequest = CurlRequest::create(request, *delegate(), shouldSuspend, CurlRequest::EnableMultipart::Yes);
+
+ return curlRequest;
+}
+
+CurlResourceHandleDelegate* ResourceHandle::delegate()
+{
+ ASSERT(d->m_delegate);
+ return d->m_delegate.get();
+}
+
#if OS(WINDOWS)
void ResourceHandle::setHostAllowsAnyHTTPSCertificate(const String& host)
@@ -115,8 +177,18 @@
{
ASSERT(isMainThread());
- if (d->m_delegate)
- d->m_delegate->setDefersLoading(defers);
+ if (defers == d->m_defersLoading)
+ return;
+
+ d->m_defersLoading = defers;
+
+ if (!d->m_curlRequest)
+ return;
+
+ if (d->m_defersLoading)
+ d->m_curlRequest->suspend();
+ else
+ d->m_curlRequest->resume();
}
bool ResourceHandle::shouldUseCredentialStorage()
@@ -137,10 +209,9 @@
if (challenge.failureResponse().httpStatusCode() == 401)
urlToStore = challenge.failureResponse().url();
CredentialStorage::defaultCredentialStorage().set(partition, credential, challenge.protectionSpace(), urlToStore);
-
- if (d->m_delegate)
- d->m_delegate->setAuthentication(credential.user(), credential.password());
+ restartRequestWithCredential(credential.user(), credential.password());
+
d->m_user = String();
d->m_pass = String();
// FIXME: Per the specification, the user shouldn't be asked for credentials if there were incorrect ones provided explicitly.
@@ -164,8 +235,7 @@
CredentialStorage::defaultCredentialStorage().set(partition, credential, challenge.protectionSpace(), challenge.failureResponse().url());
}
- if (d->m_delegate)
- d->m_delegate->setAuthentication(credential.user(), credential.password());
+ restartRequestWithCredential(credential.user(), credential.password());
return;
}
}
@@ -200,8 +270,7 @@
}
}
- if (d->m_delegate)
- d->m_delegate->setAuthentication(credential.user(), credential.password());
+ restartRequestWithCredential(credential.user(), credential.password());
clearAuthentication();
}
@@ -215,11 +284,8 @@
clearAuthentication();
- didReceiveResponse(ResourceResponse(d->m_response), [this, protectedThis = makeRef(*this)] {
- ASSERT(isMainThread());
-
- if (d->m_delegate)
- d->m_delegate->continueDidReceiveResponse();
+ didReceiveResponse(ResourceResponse(delegate()->response()), [this, protectedThis = makeRef(*this)] {
+ continueAfterDidReceiveResponse();
});
}
@@ -246,10 +312,59 @@
ASSERT_NOT_REACHED();
}
+std::optional<std::pair<String, String>> ResourceHandle::getCredential(ResourceRequest& request, bool redirect)
+{
+ // m_user/m_pass are credentials given manually, for instance, by the arguments passed to XMLHttpRequest.open().
+ String partition = request.cachePartition();
+
+ if (shouldUseCredentialStorage()) {
+ if (d->m_user.isEmpty() && d->m_pass.isEmpty()) {
+ // <rdar://problem/7174050> - For URLs that match the paths of those previously challenged for HTTP Basic authentication,
+ // try and reuse the credential preemptively, as allowed by RFC 2617.
+ d->m_initialCredential = CredentialStorage::defaultCredentialStorage().get(partition, request.url());
+ } else if (!redirect) {
+ // If there is already a protection space known for the URL, update stored credentials
+ // before sending a request. This makes it possible to implement logout by sending an
+ // XMLHttpRequest with known incorrect credentials, and aborting it immediately (so that
+ // an authentication dialog doesn't pop up).
+ CredentialStorage::defaultCredentialStorage().set(partition, Credential(d->m_user, d->m_pass, CredentialPersistenceNone), request.url());
+ }
+ }
+
+ String user = d->m_user;
+ String password = d->m_pass;
+
+ if (!d->m_initialCredential.isEmpty()) {
+ user = d->m_initialCredential.user();
+ password = d->m_initialCredential.password();
+ }
+
+ if (user.isEmpty() && password.isEmpty())
+ return std::nullopt;
+
+ return std::pair<String, String>(user, password);
+}
+
+void ResourceHandle::restartRequestWithCredential(const String& user, const String& password)
+{
+ ASSERT(isMainThread());
+
+ if (!d->m_curlRequest)
+ return;
+
+ bool isSyncRequest = d->m_curlRequest->isSyncRequest();
+ d->m_curlRequest->cancel();
+
+ d->m_curlRequest = createCurlRequest(d->m_currentRequest);
+ d->m_curlRequest->setUserPass(user, password);
+ d->m_curlRequest->start(isSyncRequest);
+}
+
void ResourceHandle::platformLoadResourceSynchronously(NetworkingContext* context, const ResourceRequest& request, StoredCredentialsPolicy, ResourceError& error, ResourceResponse& response, Vector<char>& data)
{
ASSERT(isMainThread());
+ auto localRequest = request;
SynchronousLoaderClient client;
bool defersLoading = false;
bool shouldContentSniff = true;
@@ -256,9 +371,19 @@
bool shouldContentEncodingSniff = true;
RefPtr<ResourceHandle> handle = adoptRef(new ResourceHandle(context, request, &client, defersLoading, shouldContentSniff, shouldContentEncodingSniff));
- handle->d->m_delegate = adoptRef(new ResourceHandleCurlDelegate(handle.get()));
- handle->d->m_delegate->dispatchSynchronousJob();
+ if (localRequest.url().protocolIsData()) {
+ handle->handleDataURL();
+ return;
+ }
+ // If defersLoading is true and we call curl_easy_perform
+ // on a paused handle, libcURL would do the transfer anyway
+ // and we would assert so force defersLoading to be false.
+ handle->d->m_defersLoading = false;
+
+ handle->d->m_curlRequest = handle->createCurlRequest(localRequest);
+ handle->d->m_curlRequest->start(true);
+
error = client.error();
data.swap(client.mutableData());
response = client.response();
@@ -268,10 +393,174 @@
{
ASSERT(isMainThread());
- if (d->m_delegate)
- d->m_delegate->platformContinueSynchronousDidReceiveResponse();
+ continueAfterDidReceiveResponse();
}
+void ResourceHandle::continueAfterDidReceiveResponse()
+{
+ ASSERT(isMainThread());
+
+ // continueDidReceiveResponse might cancel the load.
+ if (cancelledOrClientless() || !d->m_curlRequest)
+ return;
+
+ d->m_curlRequest->completeDidReceiveResponse();
+}
+
+bool ResourceHandle::shouldRedirectAsGET(const ResourceRequest& request, bool crossOrigin)
+{
+ if (request.httpMethod() == "GET" || request.httpMethod() == "HEAD")
+ return false;
+
+ if (!request.url().protocolIsInHTTPFamily())
+ return true;
+
+ if (delegate()->response().isSeeOther())
+ return true;
+
+ if ((delegate()->response().isMovedPermanently() || delegate()->response().isFound()) && (request.httpMethod() == "POST"))
+ return true;
+
+ if (crossOrigin && (request.httpMethod() == "DELETE"))
+ return true;
+
+ return false;
+}
+
+void ResourceHandle::willSendRequest()
+{
+ ASSERT(isMainThread());
+
+ static const int maxRedirects = 20;
+
+ if (d->m_redirectCount++ > maxRedirects) {
+ client()->didFail(this, ResourceError::httpError(CURLE_TOO_MANY_REDIRECTS, delegate()->response().url()));
+ return;
+ }
+
+ String location = delegate()->response().httpHeaderField(HTTPHeaderName::Location);
+ URL newURL = URL(delegate()->response().url(), location);
+ bool crossOrigin = !protocolHostAndPortAreEqual(d->m_firstRequest.url(), newURL);
+
+ ResourceRequest newRequest = d->m_firstRequest;
+ newRequest.setURL(newURL);
+
+ if (shouldRedirectAsGET(newRequest, crossOrigin)) {
+ newRequest.setHTTPMethod("GET");
+ newRequest.setHTTPBody(nullptr);
+ newRequest.clearHTTPContentType();
+ }
+
+ // Should not set Referer after a redirect from a secure resource to non-secure one.
+ if (!newURL.protocolIs("https") && protocolIs(newRequest.httpReferrer(), "https") && context()->shouldClearReferrerOnHTTPSToHTTPRedirect())
+ newRequest.clearHTTPReferrer();
+
+ d->m_user = newURL.user();
+ d->m_pass = newURL.pass();
+ newRequest.removeCredentials();
+
+ if (crossOrigin) {
+ // If the network layer carries over authentication headers from the original request
+ // in a cross-origin redirect, we want to clear those headers here.
+ newRequest.clearHTTPAuthorization();
+ newRequest.clearHTTPOrigin();
+ }
+
+ ResourceResponse responseCopy = delegate()->response();
+ client()->willSendRequestAsync(this, WTFMove(newRequest), WTFMove(responseCopy), [this, protectedThis = makeRef(*this)] (ResourceRequest&& request) {
+ continueAfterWillSendRequest(WTFMove(request));
+ });
+}
+
+void ResourceHandle::continueAfterWillSendRequest(ResourceRequest&& request)
+{
+ ASSERT(isMainThread());
+
+ // willSendRequest might cancel the load.
+ if (cancelledOrClientless() || !d->m_curlRequest)
+ return;
+
+ d->m_currentRequest = WTFMove(request);
+
+ bool isSyncRequest = d->m_curlRequest->isSyncRequest();
+ d->m_curlRequest->cancel();
+
+ d->m_curlRequest = createCurlRequest(d->m_currentRequest);
+
+ if (protocolHostAndPortAreEqual(d->m_currentRequest.url(), delegate()->response().url())) {
+ if (auto credential = getCredential(d->m_currentRequest, true))
+ d->m_curlRequest->setUserPass(credential->first, credential->second);
+ }
+
+ d->m_curlRequest->start(isSyncRequest);
+}
+
+void ResourceHandle::handleDataURL()
+{
+ ASSERT(d->m_firstRequest.url().protocolIsData());
+ String url = ""
+
+ ASSERT(client());
+
+ auto index = url.find(',');
+ if (index == notFound) {
+ client()->cannotShowURL(this);
+ return;
+ }
+
+ String mediaType = url.substring(5, index - 5);
+ String data = "" + 1);
+ auto originalSize = data.length();
+
+ bool base64 = mediaType.endsWithIgnoringASCIICase(";base64");
+ if (base64)
+ mediaType = mediaType.left(mediaType.length() - 7);
+
+ if (mediaType.isEmpty())
+ mediaType = ASCIILiteral("text/plain");
+
+ String mimeType = extractMIMETypeFromMediaType(mediaType);
+ String charset = extractCharsetFromMediaType(mediaType);
+
+ if (charset.isEmpty())
+ charset = ASCIILiteral("US-ASCII");
+
+ ResourceResponse response;
+ response.setMimeType(mimeType);
+ response.setTextEncodingName(charset);
+ response.setURL(d->m_firstRequest.url());
+
+ if (base64) {
+ data = ""
+ didReceiveResponse(WTFMove(response), [this, protectedThis = makeRef(*this)] {
+ continueAfterDidReceiveResponse();
+ });
+
+ // didReceiveResponse might cause the client to be deleted.
+ if (client()) {
+ Vector<char> out;
+ if (base64Decode(data, out, Base64IgnoreSpacesAndNewLines) && out.size() > 0)
+ client()->didReceiveBuffer(this, SharedBuffer::create(out.data(), out.size()), originalSize);
+ }
+ } else {
+ TextEncoding encoding(charset);
+ data = "" encoding);
+ didReceiveResponse(WTFMove(response), [this, protectedThis = makeRef(*this)] {
+ continueAfterDidReceiveResponse();
+ });
+
+ // didReceiveResponse might cause the client to be deleted.
+ if (client()) {
+ auto encodedData = encoding.encode(data, UnencodableHandling::URLEncodedEntities);
+ if (encodedData.size())
+ client()->didReceiveBuffer(this, SharedBuffer::create(WTFMove(encodedData)), originalSize);
+ }
+ }
+
+ if (client())
+ client()->didFinishLoading(this);
+}
+
} // namespace WebCore
#endif
Deleted: trunk/Source/WebCore/platform/network/curl/ResourceHandleCurlDelegate.cpp (228576 => 228577)
--- trunk/Source/WebCore/platform/network/curl/ResourceHandleCurlDelegate.cpp 2018-02-16 21:38:53 UTC (rev 228576)
+++ trunk/Source/WebCore/platform/network/curl/ResourceHandleCurlDelegate.cpp 2018-02-16 21:39:38 UTC (rev 228577)
@@ -1,523 +0,0 @@
-/*
- * Copyright (C) 2004, 2006 Apple Inc. All rights reserved.
- * Copyright (C) 2005, 2006 Michael Emmel [email protected]
- * Copyright (C) 2018 Sony Interactive Entertainment Inc.
- * All rights reserved.
- * Copyright (C) 2017 NAVER Corp. 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. ``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
- * 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 "ResourceHandleCurlDelegate.h"
-
-#if USE(CURL)
-
-#include "AuthenticationChallenge.h"
-#include "CookieJarCurl.h"
-#include "CredentialStorage.h"
-#include "CurlCacheManager.h"
-#include "CurlRequest.h"
-#include "HTTPParsers.h"
-#include "NetworkStorageSession.h"
-#include "ResourceHandleInternal.h"
-#include "SharedBuffer.h"
-#include "TextEncoding.h"
-#include <wtf/CompletionHandler.h>
-#include <wtf/text/Base64.h>
-
-namespace WebCore {
-
-ResourceHandleCurlDelegate::ResourceHandleCurlDelegate(ResourceHandle* handle)
- : m_handle(handle)
- , m_firstRequest(handle->firstRequest().isolatedCopy())
- , m_currentRequest(handle->firstRequest().isolatedCopy())
- , m_shouldUseCredentialStorage(handle->shouldUseCredentialStorage())
- , m_user(handle->getInternal()->m_user.isolatedCopy())
- , m_pass(handle->getInternal()->m_pass.isolatedCopy())
- , m_initialCredential(handle->getInternal()->m_initialCredential)
- , m_defersLoading(handle->getInternal()->m_defersLoading)
-{
-
-}
-
-ResourceHandleCurlDelegate::~ResourceHandleCurlDelegate()
-{
- if (m_curlRequest)
- m_curlRequest->setClient(nullptr);
-}
-
-bool ResourceHandleCurlDelegate::hasHandle() const
-{
- return !!m_handle;
-}
-
-void ResourceHandleCurlDelegate::releaseHandle()
-{
- m_handle = nullptr;
-}
-
-void ResourceHandleCurlDelegate::start()
-{
- ASSERT(isMainThread());
-
- auto credential = getCredential(m_currentRequest, false);
-
- m_curlRequest = createCurlRequest(m_currentRequest);
- m_curlRequest->setUserPass(credential.first, credential.second);
- m_curlRequest->start();
-}
-
-void ResourceHandleCurlDelegate::cancel()
-{
- ASSERT(isMainThread());
-
- releaseHandle();
-
- if (!m_curlRequest)
- m_curlRequest->cancel();
-}
-
-void ResourceHandleCurlDelegate::setDefersLoading(bool defers)
-{
- ASSERT(isMainThread());
-
- if (defers == m_defersLoading)
- return;
-
- m_defersLoading = defers;
-
- if (!m_curlRequest)
- return;
-
- if (m_defersLoading)
- m_curlRequest->suspend();
- else
- m_curlRequest->resume();
-}
-
-void ResourceHandleCurlDelegate::setAuthentication(const String& user, const String& password)
-{
- ASSERT(isMainThread());
-
- if (!m_curlRequest)
- return;
-
- bool isSyncRequest = m_curlRequest->isSyncRequest();
- m_curlRequest->cancel();
- m_curlRequest->setClient(nullptr);
-
- m_curlRequest = createCurlRequest(m_currentRequest);
- m_curlRequest->setUserPass(user, password);
- m_curlRequest->start(isSyncRequest);
-}
-
-void ResourceHandleCurlDelegate::dispatchSynchronousJob()
-{
- if (m_currentRequest.url().protocolIsData()) {
- handleDataURL();
- return;
- }
-
- // If defersLoading is true and we call curl_easy_perform
- // on a paused handle, libcURL would do the transfert anyway
- // and we would assert so force defersLoading to be false.
- m_defersLoading = false;
-
- m_curlRequest = createCurlRequest(m_currentRequest);
- m_curlRequest->start(true);
-}
-
-Ref<CurlRequest> ResourceHandleCurlDelegate::createCurlRequest(ResourceRequest& request)
-{
- ASSERT(isMainThread());
-
- // CurlCache : append additional cache information
- m_addedCacheValidationHeaders = false;
-
- bool hasCacheHeaders = request.httpHeaderFields().contains(HTTPHeaderName::IfModifiedSince) || request.httpHeaderFields().contains(HTTPHeaderName::IfNoneMatch);
- if (!hasCacheHeaders) {
- auto& cache = CurlCacheManager::singleton();
- URL cacheUrl = request.url();
- cacheUrl.removeFragmentIdentifier();
-
- if (cache.isCached(cacheUrl)) {
- cache.addCacheEntryClient(cacheUrl, m_handle);
-
- for (const auto& entry : cache.requestHeaders(cacheUrl))
- request.addHTTPHeaderField(entry.key, entry.value);
-
- m_addedCacheValidationHeaders = true;
- }
- }
-
- CurlRequest::ShouldSuspend shouldSuspend = m_defersLoading ? CurlRequest::ShouldSuspend::Yes : CurlRequest::ShouldSuspend::No;
- return CurlRequest::create(request, this, shouldSuspend, CurlRequest::EnableMultipart::Yes);
-}
-
-bool ResourceHandleCurlDelegate::cancelledOrClientless()
-{
- if (!m_handle)
- return true;
-
- return !m_handle->client();
-}
-
-void ResourceHandleCurlDelegate::curlDidSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
-{
- ASSERT(isMainThread());
-
- if (cancelledOrClientless())
- return;
-
- m_handle->client()->didSendData(m_handle, bytesSent, totalBytesToBeSent);
-}
-
-static void handleCookieHeaders(const CurlResponse& response)
-{
- static const auto setCookieHeader = "set-cookie: ";
-
- auto& defaultStorageSession = NetworkStorageSession::defaultStorageSession();
- const CookieJarCurl& cookieJar = defaultStorageSession.cookieStorage();
- for (auto header : response.headers) {
- if (header.startsWithIgnoringASCIICase(setCookieHeader)) {
- String setCookieString = header.right(header.length() - strlen(setCookieHeader));
- cookieJar.setCookiesFromHTTPResponse(defaultStorageSession, response.url, setCookieString);
- }
- }
-}
-
-void ResourceHandleCurlDelegate::curlDidReceiveResponse(const CurlResponse& receivedResponse)
-{
- ASSERT(isMainThread());
- ASSERT(!m_defersLoading);
-
- if (cancelledOrClientless())
- return;
-
- m_handle->getInternal()->m_response = ResourceResponse(receivedResponse);
-
- if (m_curlRequest)
- m_handle->getInternal()->m_response.setDeprecatedNetworkLoadMetrics(m_curlRequest->getNetworkLoadMetrics());
-
- handleCookieHeaders(receivedResponse);
-
- if (response().shouldRedirect()) {
- willSendRequest();
- return;
- }
-
- if (response().isUnauthorized()) {
- AuthenticationChallenge challenge(receivedResponse, m_authFailureCount, response(), m_handle);
- m_handle->didReceiveAuthenticationChallenge(challenge);
- m_authFailureCount++;
- return;
- }
-
- if (m_handle->client()) {
- if (response().isNotModified()) {
- URL cacheUrl = m_currentRequest.url();
- cacheUrl.removeFragmentIdentifier();
-
- if (CurlCacheManager::singleton().getCachedResponse(cacheUrl, response())) {
- if (m_addedCacheValidationHeaders) {
- response().setHTTPStatusCode(200);
- response().setHTTPStatusText("OK");
- }
- }
- }
-
- CurlCacheManager::singleton().didReceiveResponse(*m_handle, response());
-
- auto protectedThis = makeRef(*m_handle);
- m_handle->didReceiveResponse(ResourceResponse(response()), [this, protectedThis = makeRef(*this)] {
- continueAfterDidReceiveResponse();
- });
- }
-}
-
-void ResourceHandleCurlDelegate::curlDidReceiveBuffer(Ref<SharedBuffer>&& buffer)
-{
- ASSERT(isMainThread());
-
- if (cancelledOrClientless())
- return;
-
- CurlCacheManager::singleton().didReceiveData(*m_handle, buffer->data(), buffer->size());
- m_handle->client()->didReceiveBuffer(m_handle, WTFMove(buffer), buffer->size());
-}
-
-void ResourceHandleCurlDelegate::curlDidComplete()
-{
- ASSERT(isMainThread());
-
- if (cancelledOrClientless())
- return;
-
- if (m_curlRequest)
- m_handle->getInternal()->m_response.setDeprecatedNetworkLoadMetrics(m_curlRequest->getNetworkLoadMetrics());
-
- if (m_handle->client()) {
- CurlCacheManager::singleton().didFinishLoading(*m_handle);
- m_handle->client()->didFinishLoading(m_handle);
- }
-}
-
-void ResourceHandleCurlDelegate::curlDidFailWithError(const ResourceError& resourceError)
-{
- ASSERT(isMainThread());
-
- if (cancelledOrClientless())
- return;
-
- CurlCacheManager::singleton().didFail(*m_handle);
- m_handle->client()->didFail(m_handle, resourceError);
-}
-
-void ResourceHandleCurlDelegate::continueDidReceiveResponse()
-{
- ASSERT(isMainThread());
-
- continueAfterDidReceiveResponse();
-}
-
-void ResourceHandleCurlDelegate::platformContinueSynchronousDidReceiveResponse()
-{
- ASSERT(isMainThread());
-
- continueAfterDidReceiveResponse();
-}
-
-void ResourceHandleCurlDelegate::continueAfterDidReceiveResponse()
-{
- ASSERT(isMainThread());
-
- // continueDidReceiveResponse might cancel the load.
- if (cancelledOrClientless() || !m_curlRequest)
- return;
-
- m_curlRequest->completeDidReceiveResponse();
-}
-
-bool ResourceHandleCurlDelegate::shouldRedirectAsGET(const ResourceRequest& request, bool crossOrigin)
-{
- if (request.httpMethod() == "GET" || request.httpMethod() == "HEAD")
- return false;
-
- if (!request.url().protocolIsInHTTPFamily())
- return true;
-
- if (response().isSeeOther())
- return true;
-
- if ((response().isMovedPermanently() || response().isFound()) && (request.httpMethod() == "POST"))
- return true;
-
- if (crossOrigin && (request.httpMethod() == "DELETE"))
- return true;
-
- return false;
-}
-
-void ResourceHandleCurlDelegate::willSendRequest()
-{
- ASSERT(isMainThread());
-
- static const int maxRedirects = 20;
-
- if (m_redirectCount++ > maxRedirects) {
- m_handle->client()->didFail(m_handle, ResourceError::httpError(CURLE_TOO_MANY_REDIRECTS, response().url()));
- return;
- }
-
- String location = response().httpHeaderField(HTTPHeaderName::Location);
- URL newURL = URL(m_handle->getInternal()->m_response.url(), location);
- bool crossOrigin = !protocolHostAndPortAreEqual(m_firstRequest.url(), newURL);
-
- ResourceRequest newRequest = m_firstRequest;
- newRequest.setURL(newURL);
-
- if (shouldRedirectAsGET(newRequest, crossOrigin)) {
- newRequest.setHTTPMethod("GET");
- newRequest.setHTTPBody(nullptr);
- newRequest.clearHTTPContentType();
- }
-
- // Should not set Referer after a redirect from a secure resource to non-secure one.
- if (!newURL.protocolIs("https") && protocolIs(newRequest.httpReferrer(), "https") && m_handle->context()->shouldClearReferrerOnHTTPSToHTTPRedirect())
- newRequest.clearHTTPReferrer();
-
- m_user = newURL.user();
- m_pass = newURL.pass();
- newRequest.removeCredentials();
-
- if (crossOrigin) {
- // If the network layer carries over authentication headers from the original request
- // in a cross-origin redirect, we want to clear those headers here.
- newRequest.clearHTTPAuthorization();
- newRequest.clearHTTPOrigin();
- }
-
- ResourceResponse responseCopy = response();
- m_handle->client()->willSendRequestAsync(m_handle, WTFMove(newRequest), WTFMove(responseCopy), [this, protectedThis = makeRef(*this)] (ResourceRequest&& request) {
- continueWillSendRequest(WTFMove(request));
- });
-}
-
-void ResourceHandleCurlDelegate::continueWillSendRequest(ResourceRequest&& request)
-{
- ASSERT(isMainThread());
-
- continueAfterWillSendRequest(WTFMove(request));
-}
-
-void ResourceHandleCurlDelegate::continueAfterWillSendRequest(ResourceRequest&& request)
-{
- ASSERT(isMainThread());
-
- // willSendRequest might cancel the load.
- if (cancelledOrClientless() || !m_curlRequest)
- return;
-
- m_currentRequest = WTFMove(request);
-
- bool isSyncRequest = m_curlRequest->isSyncRequest();
- m_curlRequest->cancel();
- m_curlRequest->setClient(nullptr);
-
- m_curlRequest = createCurlRequest(m_currentRequest);
-
- if (protocolHostAndPortAreEqual(m_currentRequest.url(), response().url())) {
- auto credential = getCredential(m_currentRequest, true);
- m_curlRequest->setUserPass(credential.first, credential.second);
- }
-
- m_curlRequest->start(isSyncRequest);
-}
-
-ResourceResponse& ResourceHandleCurlDelegate::response()
-{
- return m_handle->getInternal()->m_response;
-}
-
-void ResourceHandleCurlDelegate::handleDataURL()
-{
- ASSERT(m_firstRequest.url().protocolIsData());
- String url = ""
-
- ASSERT(m_handle->client());
-
- auto index = url.find(',');
- if (index == notFound) {
- m_handle->client()->cannotShowURL(m_handle);
- return;
- }
-
- String mediaType = url.substring(5, index - 5);
- String data = "" + 1);
- auto originalSize = data.length();
-
- bool base64 = mediaType.endsWithIgnoringASCIICase(";base64");
- if (base64)
- mediaType = mediaType.left(mediaType.length() - 7);
-
- if (mediaType.isEmpty())
- mediaType = "text/plain";
-
- String mimeType = extractMIMETypeFromMediaType(mediaType);
- String charset = extractCharsetFromMediaType(mediaType);
-
- if (charset.isEmpty())
- charset = "US-ASCII";
-
- ResourceResponse response;
- response.setMimeType(mimeType);
- response.setTextEncodingName(charset);
- response.setURL(m_firstRequest.url());
-
- if (base64) {
- data = ""
- m_handle->didReceiveResponse(WTFMove(response), [this, protectedThis = makeRef(*this)] {
- continueAfterDidReceiveResponse();
- });
-
- // didReceiveResponse might cause the client to be deleted.
- if (m_handle->client()) {
- Vector<char> out;
- if (base64Decode(data, out, Base64IgnoreSpacesAndNewLines) && out.size() > 0)
- m_handle->client()->didReceiveBuffer(m_handle, SharedBuffer::create(out.data(), out.size()), originalSize);
- }
- } else {
- TextEncoding encoding(charset);
- data = "" encoding);
- m_handle->didReceiveResponse(WTFMove(response), [this, protectedThis = makeRef(*this)] {
- continueAfterDidReceiveResponse();
- });
-
- // didReceiveResponse might cause the client to be deleted.
- if (m_handle->client()) {
- auto encodedData = encoding.encode(data, UnencodableHandling::URLEncodedEntities);
- if (encodedData.size())
- m_handle->client()->didReceiveBuffer(m_handle, SharedBuffer::create(WTFMove(encodedData)), originalSize);
- }
- }
-
- if (m_handle->client())
- m_handle->client()->didFinishLoading(m_handle);
-}
-
-std::pair<String, String> ResourceHandleCurlDelegate::getCredential(ResourceRequest& request, bool redirect)
-{
- // m_user/m_pass are credentials given manually, for instance, by the arguments passed to XMLHttpRequest.open().
- String partition = request.cachePartition();
-
- if (m_shouldUseCredentialStorage) {
- if (m_user.isEmpty() && m_pass.isEmpty()) {
- // <rdar://problem/7174050> - For URLs that match the paths of those previously challenged for HTTP Basic authentication,
- // try and reuse the credential preemptively, as allowed by RFC 2617.
- m_initialCredential = CredentialStorage::defaultCredentialStorage().get(partition, request.url());
- } else if (!redirect) {
- // If there is already a protection space known for the URL, update stored credentials
- // before sending a request. This makes it possible to implement logout by sending an
- // XMLHttpRequest with known incorrect credentials, and aborting it immediately (so that
- // an authentication dialog doesn't pop up).
- CredentialStorage::defaultCredentialStorage().set(partition, Credential(m_user, m_pass, CredentialPersistenceNone), request.url());
- }
- }
-
- String user = m_user;
- String password = m_pass;
-
- if (!m_initialCredential.isEmpty()) {
- user = m_initialCredential.user();
- password = m_initialCredential.password();
- }
-
- if (user.isEmpty() && password.isEmpty())
- return std::pair<String, String>("", "");
-
- return std::pair<String, String>(user, password);
-}
-
-} // namespace WebCore
-
-#endif
Deleted: trunk/Source/WebCore/platform/network/curl/ResourceHandleCurlDelegate.h (228576 => 228577)
--- trunk/Source/WebCore/platform/network/curl/ResourceHandleCurlDelegate.h 2018-02-16 21:38:53 UTC (rev 228576)
+++ trunk/Source/WebCore/platform/network/curl/ResourceHandleCurlDelegate.h 2018-02-16 21:39:38 UTC (rev 228577)
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2017 NAVER Corp. All rights reserved.
- * Copyright (C) 2017 Sony Interactive Entertainment Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER OR
- * 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 USE(CURL)
-
-#include "Credential.h"
-#include "CurlRequestClient.h"
-#include "ResourceRequest.h"
-
-namespace WebCore {
-
-class CurlRequest;
-class ResourceHandle;
-class ResourceResponse;
-
-class ResourceHandleCurlDelegate final : public ThreadSafeRefCounted<ResourceHandleCurlDelegate>, public CurlRequestClient {
-public:
- ResourceHandleCurlDelegate(ResourceHandle*);
- ~ResourceHandleCurlDelegate();
-
- void ref() override { ThreadSafeRefCounted<ResourceHandleCurlDelegate>::ref(); }
- void deref() override { ThreadSafeRefCounted<ResourceHandleCurlDelegate>::deref(); }
-
- bool hasHandle() const;
- void releaseHandle();
-
- void start();
- void cancel();
-
- void setDefersLoading(bool);
- void setAuthentication(const String&, const String&);
-
- void dispatchSynchronousJob();
-
- void continueDidReceiveResponse();
- void platformContinueSynchronousDidReceiveResponse();
-
- void continueWillSendRequest(ResourceRequest&&);
-
-private:
- // Called from main thread.
- ResourceResponse& response();
-
- std::pair<String, String> getCredential(ResourceRequest&, bool);
-
- bool cancelledOrClientless();
-
- Ref<CurlRequest> createCurlRequest(ResourceRequest&);
- void curlDidSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) override;
- void curlDidReceiveResponse(const CurlResponse&) override;
- void curlDidReceiveBuffer(Ref<SharedBuffer>&&) override;
- void curlDidComplete() override;
- void curlDidFailWithError(const ResourceError&) override;
-
- void continueAfterDidReceiveResponse();
-
- bool shouldRedirectAsGET(const ResourceRequest&, bool crossOrigin);
- void willSendRequest();
- void continueAfterWillSendRequest(ResourceRequest&&);
-
- void handleDataURL();
-
- // Used by main thread.
- ResourceHandle* m_handle;
- unsigned m_authFailureCount { 0 };
- unsigned m_redirectCount { 0 };
-
- ResourceRequest m_firstRequest;
- ResourceRequest m_currentRequest;
- bool m_shouldUseCredentialStorage;
- String m_user;
- String m_pass;
- Credential m_initialCredential;
- bool m_defersLoading;
- bool m_addedCacheValidationHeaders { false };
- RefPtr<CurlRequest> m_curlRequest;
-};
-
-} // namespace WebCore
-
-#endif