Title: [219279] trunk/Source/WebCore
Revision
219279
Author
[email protected]
Date
2017-07-08 19:58:36 -0700 (Sat, 08 Jul 2017)

Log Message

[Curl] Safe access and life cycle management of bare Curl handle
by wrapping with C++ class
https://bugs.webkit.org/show_bug.cgi?id=174002

Patch by Basuke Suzuki <[email protected]> on 2017-07-08
Reviewed by Alex Christensen.

* platform/network/ResourceHandle.h:
* platform/network/ResourceHandleInternal.h:
* platform/network/curl/CookieJarCurl.cpp:
(WebCore::setCookiesFromDOM):
(WebCore::cookiesForSession):
* platform/network/curl/CurlContext.cpp:
(WebCore::CurlContext::CurlContext):
(WebCore::CurlContext::~CurlContext):
(WebCore::CurlContext::initCookieSession):
(WebCore::CurlShareHandle::CurlShareHandle):
(WebCore::CurlShareHandle::~CurlShareHandle):
(WebCore::CurlShareHandle::lockCallback):
(WebCore::CurlShareHandle::unlockCallback):
(WebCore::CurlShareHandle::mutexFor):
(WebCore::CurlMultiHandle::CurlMultiHandle):
(WebCore::CurlMultiHandle::~CurlMultiHandle):
(WebCore::CurlMultiHandle::addHandle):
(WebCore::CurlMultiHandle::removeHandle):
(WebCore::CurlMultiHandle::getFdSet):
(WebCore::CurlMultiHandle::perform):
(WebCore::CurlMultiHandle::readInfo):
(WebCore::CurlHandle::CurlHandle):
(WebCore::CurlHandle::~CurlHandle):
(WebCore::CurlHandle::perform):
(WebCore::CurlHandle::pause):
(WebCore::CurlHandle::enableShareHandle):
(WebCore::CurlHandle::setPrivateData):
(WebCore::CurlHandle::setUrl):
(WebCore::CurlHandle::clearUrl):
(WebCore::CurlHandle::clearRequestHeaders):
(WebCore::CurlHandle::appendRequestHeader):
(WebCore::CurlHandle::enableRequestHeaders):
(WebCore::CurlHandle::enableHttpGetRequest):
(WebCore::CurlHandle::enableHttpHeadRequest):
(WebCore::CurlHandle::enableHttpPostRequest):
(WebCore::CurlHandle::setPostFields):
(WebCore::CurlHandle::setPostFieldLarge):
(WebCore::CurlHandle::enableHttpPutRequest):
(WebCore::CurlHandle::setInFileSizeLarge):
(WebCore::CurlHandle::setHttpCustomRequest):
(WebCore::CurlHandle::enableAcceptEncoding):
(WebCore::CurlHandle::enableAllowedProtocols):
(WebCore::CurlHandle::enableFollowLocation):
(WebCore::CurlHandle::enableAutoReferer):
(WebCore::CurlHandle::enableHttpAuthentication):
(WebCore::CurlHandle::setHttpAuthUserPass):
(WebCore::CurlHandle::enableCAInfoIfExists):
(WebCore::CurlHandle::setSslVerifyPeer):
(WebCore::CurlHandle::setSslVerifyHost):
(WebCore::CurlHandle::setSslCert):
(WebCore::CurlHandle::setSslCertType):
(WebCore::CurlHandle::setSslKeyPassword):
(WebCore::CurlHandle::enableCookieJarIfExists):
(WebCore::CurlHandle::setCookieList):
(WebCore::CurlHandle::getCookieList):
(WebCore::CurlHandle::clearCookieList):
(WebCore::CurlHandle::enableProxyIfExists):
(WebCore::CurlHandle::enableTimeout):
(WebCore::CurlHandle::setHeaderCallbackFunction):
(WebCore::CurlHandle::setWriteCallbackFunction):
(WebCore::CurlHandle::setReadCallbackFunction):
(WebCore::CurlHandle::setSslCtxCallbackFunction):
(WebCore::CurlHandle::getEffectiveURL):
(WebCore::CurlHandle::getPrimaryPort):
(WebCore::CurlHandle::getResponseCode):
(WebCore::CurlHandle::getContentLenghtDownload):
(WebCore::CurlHandle::getHttpAuthAvail):
(WebCore::CurlHandle::getTimes):
(WebCore::CurlHandle::maxCurlOffT):
(WebCore::CurlHandle::expectedSizeOfCurlOffT):
(WebCore::CurlHandle::enableVerboseIfUsed):
(WebCore::CurlHandle::enableStdErrIfUsed):
(WebCore::CurlContext::getEffectiveURL): Deleted.
(WebCore::CurlContext::createMultiHandle): Deleted.
(WebCore::CurlContext::mutexFor): Deleted.
(WebCore::CurlContext::lock): Deleted.
(WebCore::CurlContext::unlock): Deleted.
* platform/network/curl/CurlContext.h:
(WebCore::CurlGlobal::CurlGlobal):
(WebCore::CurlGlobal::~CurlGlobal):
(WebCore::CurlShareHandle::handle):
(WebCore::CurlContext::shareHandle):
(WebCore::CurlHandle::handle):
(WebCore::CurlHandle::url):
(WebCore::CurlContext::curlShareHandle): Deleted.
* platform/network/curl/CurlDownload.cpp:
(WebCore::CurlDownload::~CurlDownload):
(WebCore::CurlDownload::init):
(WebCore::CurlDownload::start):
(WebCore::CurlDownload::cancel):
(WebCore::CurlDownload::getUrl):
(WebCore::CurlDownload::addHeaders):
(WebCore::CurlDownload::didReceiveHeader):
(WebCore::CurlDownload::writeCallback):
* platform/network/curl/CurlDownload.h:
* platform/network/curl/CurlJobManager.cpp:
(WebCore::CurlJobManager::CurlJobManager):
(WebCore::CurlJobManager::~CurlJobManager):
(WebCore::CurlJobManager::addToCurl):
(WebCore::CurlJobManager::removeFromCurl):
(WebCore::CurlJobManager::workerThread):
* platform/network/curl/CurlJobManager.h:
(WebCore::CurlJobManager::getMultiHandle): Deleted.
* platform/network/curl/ResourceHandleCurl.cpp:
(WebCore::ResourceHandleInternal::~ResourceHandleInternal):
(WebCore::ResourceHandle::platformSetDefersLoading):
(WebCore::ResourceHandle::didReceiveAuthenticationChallenge):
(WebCore::ResourceHandle::receivedCredential):
(WebCore::ResourceHandle::receivedRequestToContinueWithoutCredential):
(WebCore::calculateWebTimingInformations):
(WebCore::handleLocalReceiveResponse):
(WebCore::writeCallback):
(WebCore::getProtectionSpace):
(WebCore::headerCallback):
(WebCore::readCallback):
(WebCore::setupFormData):
(WebCore::ResourceHandle::setupPUT):
(WebCore::ResourceHandle::setupPOST):
(WebCore::ResourceHandle::dispatchSynchronousJob):
(WebCore::ResourceHandle::applyAuthentication):
(WebCore::ResourceHandle::initialize):
(WebCore::ResourceHandle::handleCurlMsg):
* platform/network/curl/ResourceHandleManager.cpp:
(WebCore::ResourceHandleManager::ResourceHandleManager):
(WebCore::ResourceHandleManager::~ResourceHandleManager):
(WebCore::ResourceHandleManager::downloadTimerCallback):
(WebCore::ResourceHandleManager::removeFromCurl):
(WebCore::ResourceHandleManager::startJob):
* platform/network/curl/ResourceHandleManager.h:
* platform/network/curl/SSLHandle.cpp:
(WebCore::setSSLClientCertificate):
(WebCore::certVerifyCallback):
(WebCore::setSSLVerifyOptions):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (219278 => 219279)


--- trunk/Source/WebCore/ChangeLog	2017-07-08 23:59:04 UTC (rev 219278)
+++ trunk/Source/WebCore/ChangeLog	2017-07-09 02:58:36 UTC (rev 219279)
@@ -1,3 +1,145 @@
+2017-07-08  Basuke Suzuki  <[email protected]>
+
+        [Curl] Safe access and life cycle management of bare Curl handle
+        by wrapping with C++ class
+        https://bugs.webkit.org/show_bug.cgi?id=174002
+
+        Reviewed by Alex Christensen.
+
+        * platform/network/ResourceHandle.h:
+        * platform/network/ResourceHandleInternal.h:
+        * platform/network/curl/CookieJarCurl.cpp:
+        (WebCore::setCookiesFromDOM):
+        (WebCore::cookiesForSession):
+        * platform/network/curl/CurlContext.cpp:
+        (WebCore::CurlContext::CurlContext):
+        (WebCore::CurlContext::~CurlContext):
+        (WebCore::CurlContext::initCookieSession):
+        (WebCore::CurlShareHandle::CurlShareHandle):
+        (WebCore::CurlShareHandle::~CurlShareHandle):
+        (WebCore::CurlShareHandle::lockCallback):
+        (WebCore::CurlShareHandle::unlockCallback):
+        (WebCore::CurlShareHandle::mutexFor):
+        (WebCore::CurlMultiHandle::CurlMultiHandle):
+        (WebCore::CurlMultiHandle::~CurlMultiHandle):
+        (WebCore::CurlMultiHandle::addHandle):
+        (WebCore::CurlMultiHandle::removeHandle):
+        (WebCore::CurlMultiHandle::getFdSet):
+        (WebCore::CurlMultiHandle::perform):
+        (WebCore::CurlMultiHandle::readInfo):
+        (WebCore::CurlHandle::CurlHandle):
+        (WebCore::CurlHandle::~CurlHandle):
+        (WebCore::CurlHandle::perform):
+        (WebCore::CurlHandle::pause):
+        (WebCore::CurlHandle::enableShareHandle):
+        (WebCore::CurlHandle::setPrivateData):
+        (WebCore::CurlHandle::setUrl):
+        (WebCore::CurlHandle::clearUrl):
+        (WebCore::CurlHandle::clearRequestHeaders):
+        (WebCore::CurlHandle::appendRequestHeader):
+        (WebCore::CurlHandle::enableRequestHeaders):
+        (WebCore::CurlHandle::enableHttpGetRequest):
+        (WebCore::CurlHandle::enableHttpHeadRequest):
+        (WebCore::CurlHandle::enableHttpPostRequest):
+        (WebCore::CurlHandle::setPostFields):
+        (WebCore::CurlHandle::setPostFieldLarge):
+        (WebCore::CurlHandle::enableHttpPutRequest):
+        (WebCore::CurlHandle::setInFileSizeLarge):
+        (WebCore::CurlHandle::setHttpCustomRequest):
+        (WebCore::CurlHandle::enableAcceptEncoding):
+        (WebCore::CurlHandle::enableAllowedProtocols):
+        (WebCore::CurlHandle::enableFollowLocation):
+        (WebCore::CurlHandle::enableAutoReferer):
+        (WebCore::CurlHandle::enableHttpAuthentication):
+        (WebCore::CurlHandle::setHttpAuthUserPass):
+        (WebCore::CurlHandle::enableCAInfoIfExists):
+        (WebCore::CurlHandle::setSslVerifyPeer):
+        (WebCore::CurlHandle::setSslVerifyHost):
+        (WebCore::CurlHandle::setSslCert):
+        (WebCore::CurlHandle::setSslCertType):
+        (WebCore::CurlHandle::setSslKeyPassword):
+        (WebCore::CurlHandle::enableCookieJarIfExists):
+        (WebCore::CurlHandle::setCookieList):
+        (WebCore::CurlHandle::getCookieList):
+        (WebCore::CurlHandle::clearCookieList):
+        (WebCore::CurlHandle::enableProxyIfExists):
+        (WebCore::CurlHandle::enableTimeout):
+        (WebCore::CurlHandle::setHeaderCallbackFunction):
+        (WebCore::CurlHandle::setWriteCallbackFunction):
+        (WebCore::CurlHandle::setReadCallbackFunction):
+        (WebCore::CurlHandle::setSslCtxCallbackFunction):
+        (WebCore::CurlHandle::getEffectiveURL):
+        (WebCore::CurlHandle::getPrimaryPort):
+        (WebCore::CurlHandle::getResponseCode):
+        (WebCore::CurlHandle::getContentLenghtDownload):
+        (WebCore::CurlHandle::getHttpAuthAvail):
+        (WebCore::CurlHandle::getTimes):
+        (WebCore::CurlHandle::maxCurlOffT):
+        (WebCore::CurlHandle::expectedSizeOfCurlOffT):
+        (WebCore::CurlHandle::enableVerboseIfUsed):
+        (WebCore::CurlHandle::enableStdErrIfUsed):
+        (WebCore::CurlContext::getEffectiveURL): Deleted.
+        (WebCore::CurlContext::createMultiHandle): Deleted.
+        (WebCore::CurlContext::mutexFor): Deleted.
+        (WebCore::CurlContext::lock): Deleted.
+        (WebCore::CurlContext::unlock): Deleted.
+        * platform/network/curl/CurlContext.h:
+        (WebCore::CurlGlobal::CurlGlobal):
+        (WebCore::CurlGlobal::~CurlGlobal):
+        (WebCore::CurlShareHandle::handle):
+        (WebCore::CurlContext::shareHandle):
+        (WebCore::CurlHandle::handle):
+        (WebCore::CurlHandle::url):
+        (WebCore::CurlContext::curlShareHandle): Deleted.
+        * platform/network/curl/CurlDownload.cpp:
+        (WebCore::CurlDownload::~CurlDownload):
+        (WebCore::CurlDownload::init):
+        (WebCore::CurlDownload::start):
+        (WebCore::CurlDownload::cancel):
+        (WebCore::CurlDownload::getUrl):
+        (WebCore::CurlDownload::addHeaders):
+        (WebCore::CurlDownload::didReceiveHeader):
+        (WebCore::CurlDownload::writeCallback):
+        * platform/network/curl/CurlDownload.h:
+        * platform/network/curl/CurlJobManager.cpp:
+        (WebCore::CurlJobManager::CurlJobManager):
+        (WebCore::CurlJobManager::~CurlJobManager):
+        (WebCore::CurlJobManager::addToCurl):
+        (WebCore::CurlJobManager::removeFromCurl):
+        (WebCore::CurlJobManager::workerThread):
+        * platform/network/curl/CurlJobManager.h:
+        (WebCore::CurlJobManager::getMultiHandle): Deleted.
+        * platform/network/curl/ResourceHandleCurl.cpp:
+        (WebCore::ResourceHandleInternal::~ResourceHandleInternal):
+        (WebCore::ResourceHandle::platformSetDefersLoading):
+        (WebCore::ResourceHandle::didReceiveAuthenticationChallenge):
+        (WebCore::ResourceHandle::receivedCredential):
+        (WebCore::ResourceHandle::receivedRequestToContinueWithoutCredential):
+        (WebCore::calculateWebTimingInformations):
+        (WebCore::handleLocalReceiveResponse):
+        (WebCore::writeCallback):
+        (WebCore::getProtectionSpace):
+        (WebCore::headerCallback):
+        (WebCore::readCallback):
+        (WebCore::setupFormData):
+        (WebCore::ResourceHandle::setupPUT):
+        (WebCore::ResourceHandle::setupPOST):
+        (WebCore::ResourceHandle::dispatchSynchronousJob):
+        (WebCore::ResourceHandle::applyAuthentication):
+        (WebCore::ResourceHandle::initialize):
+        (WebCore::ResourceHandle::handleCurlMsg):
+        * platform/network/curl/ResourceHandleManager.cpp:
+        (WebCore::ResourceHandleManager::ResourceHandleManager):
+        (WebCore::ResourceHandleManager::~ResourceHandleManager):
+        (WebCore::ResourceHandleManager::downloadTimerCallback):
+        (WebCore::ResourceHandleManager::removeFromCurl):
+        (WebCore::ResourceHandleManager::startJob):
+        * platform/network/curl/ResourceHandleManager.h:
+        * platform/network/curl/SSLHandle.cpp:
+        (WebCore::setSSLClientCertificate):
+        (WebCore::certVerifyCallback):
+        (WebCore::setSSLVerifyOptions):
+
 2017-07-08  Antoine Quint  <[email protected]>
 
         REGRESSION: "visibility:hidden" does not hide play button for video elements

Modified: trunk/Source/WebCore/platform/network/ResourceHandle.h (219278 => 219279)


--- trunk/Source/WebCore/platform/network/ResourceHandle.h	2017-07-08 23:59:04 UTC (rev 219278)
+++ trunk/Source/WebCore/platform/network/ResourceHandle.h	2017-07-09 02:58:36 UTC (rev 219279)
@@ -295,12 +295,10 @@
 #if USE(CURL)
     void dispatchSynchronousJob();
 
-    void setupPOST(struct curl_slist**);
-    void setupPUT(struct curl_slist**);
+    void setupPOST();
+    void setupPUT();
 
     void applyAuthentication();
-
-    char m_curlErrorBuffer[CURL_ERROR_SIZE];
 #endif
 
     friend class ResourceHandleInternal;

Modified: trunk/Source/WebCore/platform/network/ResourceHandleInternal.h (219278 => 219279)


--- trunk/Source/WebCore/platform/network/ResourceHandleInternal.h	2017-07-08 23:59:04 UTC (rev 219278)
+++ trunk/Source/WebCore/platform/network/ResourceHandleInternal.h	2017-07-09 02:58:36 UTC (rev 219279)
@@ -43,7 +43,7 @@
 #endif
 
 #if USE(CURL)
-#include <curl/curl.h>
+#include "CurlContext.h"
 #include "FormDataStreamCurl.h"
 #include "MultipartHandle.h"
 #endif
@@ -137,9 +137,8 @@
     RetainPtr<CFURLStorageSessionRef> m_storageSession;
 #endif
 #if USE(CURL)
-    CURL* m_handle { nullptr };
-    char* m_url { nullptr };
-    struct curl_slist* m_customHeaders { nullptr };
+    CurlHandle m_curlHandle;
+
     ResourceResponse m_response;
     bool m_cancelled { false };
     unsigned short m_authFailureCount { 0 };

Modified: trunk/Source/WebCore/platform/network/curl/CookieJarCurl.cpp (219278 => 219279)


--- trunk/Source/WebCore/platform/network/curl/CookieJarCurl.cpp	2017-07-08 23:59:04 UTC (rev 219278)
+++ trunk/Source/WebCore/platform/network/curl/CookieJarCurl.cpp	2017-07-09 02:58:36 UTC (rev 219279)
@@ -242,19 +242,11 @@
 
 void setCookiesFromDOM(const NetworkStorageSession&, const URL&, const URL& url, const String& value)
 {
-    const CurlContext& context = CurlContext::singleton();
+    CurlHandle curlHandle;
 
-    CURL* curl = curl_easy_init();
+    curlHandle.enableShareHandle();
+    curlHandle.enableCookieJarIfExists();
 
-    if (!curl)
-        return;
-
-    const char* cookieJarFileName = context.getCookieJarFileName();
-    CURLSH* curlsh = context.curlShareHandle();
-
-    curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookieJarFileName);
-    curl_easy_setopt(curl, CURLOPT_SHARE, curlsh);
-
     // CURL accepts cookies in either Set-Cookie or Netscape file format.
     // However with Set-Cookie format, there is no way to specify that we
     // should not allow cookies to be read from subdomains, which is the
@@ -266,26 +258,17 @@
 
     CString strCookie(reinterpret_cast<const char*>(cookie.characters8()), cookie.length());
 
-    curl_easy_setopt(curl, CURLOPT_COOKIELIST, strCookie.data());
-
-    curl_easy_cleanup(curl);
+    curlHandle.setCookieList(strCookie.data());
 }
 
 static String cookiesForSession(const NetworkStorageSession&, const URL&, const URL& url, bool httponly)
 {
     String cookies;
-    CURL* curl = curl_easy_init();
 
-    if (!curl)
-        return cookies;
+    CurlHandle curlHandle;
+    curlHandle.enableShareHandle();
 
-    CURLSH* curlsh = CurlContext::singleton().curlShareHandle();
-
-    curl_easy_setopt(curl, CURLOPT_SHARE, curlsh);
-
-    struct curl_slist* list = 0;
-    curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &list);
-
+    struct curl_slist* list = curlHandle.getCookieList();
     if (list) {
         String domain = url.host();
         String path = url.path();
@@ -299,11 +282,8 @@
         }
 
         cookies = cookiesBuilder.toString();
-        curl_slist_free_all(list);
     }
 
-    curl_easy_cleanup(curl);
-
     return cookies;
 }
 

Modified: trunk/Source/WebCore/platform/network/curl/CurlContext.cpp (219278 => 219279)


--- trunk/Source/WebCore/platform/network/curl/CurlContext.cpp	2017-07-08 23:59:04 UTC (rev 219278)
+++ trunk/Source/WebCore/platform/network/curl/CurlContext.cpp	2017-07-09 02:58:36 UTC (rev 219279)
@@ -102,16 +102,9 @@
 // CurlContext -------------------------------------------------------------------
 
 CurlContext::CurlContext()
-    : m_cookieJarFileName(cookieJarPath())
-    , m_certificatePath(certificatePath())
+: m_cookieJarFileName { cookieJarPath() }
+, m_certificatePath { certificatePath() }
 {
-    curl_global_init(CURL_GLOBAL_ALL);
-    m_curlShareHandle = curl_share_init();
-    curl_share_setopt(m_curlShareHandle, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
-    curl_share_setopt(m_curlShareHandle, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
-    curl_share_setopt(m_curlShareHandle, CURLSHOPT_LOCKFUNC, lock);
-    curl_share_setopt(m_curlShareHandle, CURLSHOPT_UNLOCKFUNC, unlock);
-
     initCookieSession();
 
     m_ignoreSSLErrors = getenv("WEBKIT_IGNORE_SSL_ERRORS");
@@ -127,9 +120,6 @@
 
 CurlContext::~CurlContext()
 {
-    curl_share_cleanup(m_curlShareHandle);
-    curl_global_cleanup();
-
 #ifndef NDEBUG
     if (m_logFile)
         fclose(m_logFile);
@@ -148,7 +138,7 @@
     if (!curl)
         return;
 
-    curl_easy_setopt(curl, CURLOPT_SHARE, curlShareHandle());
+    curl_easy_setopt(curl, CURLOPT_SHARE, m_shareHandle.handle());
 
     if (!m_cookieJarFileName.isNull()) {
         curl_easy_setopt(curl, CURLOPT_COOKIEFILE, m_cookieJarFileName.data());
@@ -188,37 +178,52 @@
     setProxyInfo(info);
 }
 
-// Curl Utilities =======================
 
-URL CurlContext::getEffectiveURL(CURL* handle)
+
+// CurlShareHandle --------------------------------------------
+
+CurlShareHandle::CurlShareHandle()
 {
-    const char* url;
-    CURLcode err = curl_easy_getinfo(handle, CURLINFO_EFFECTIVE_URL, &url);
-    if (CURLE_OK != err)
-        return URL();
-    return URL(URL(), url);
+    m_shareHandle = curl_share_init();
+    curl_share_setopt(m_shareHandle, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
+    curl_share_setopt(m_shareHandle, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
+    curl_share_setopt(m_shareHandle, CURLSHOPT_LOCKFUNC, lockCallback);
+    curl_share_setopt(m_shareHandle, CURLSHOPT_UNLOCKFUNC, unlockCallback);
 }
 
-CURLM* CurlContext::createMultiHandle()
+CurlShareHandle::~CurlShareHandle()
 {
-    return curl_multi_init();
+    if (m_shareHandle) {
+        curl_share_cleanup(m_shareHandle);
+        m_shareHandle = nullptr;
+    }
 }
 
-// Shared Resource management =======================
+void CurlShareHandle::lockCallback(CURL*, curl_lock_data data, curl_lock_access, void*)
+{
+    if (Lock* mutex = mutexFor(data))
+        mutex->lock();
+}
 
-Lock* CurlContext::mutexFor(curl_lock_data data)
+void CurlShareHandle::unlockCallback(CURL*, curl_lock_data data, void*)
 {
-    DEPRECATED_DEFINE_STATIC_LOCAL(Lock, cookieMutex, ());
-    DEPRECATED_DEFINE_STATIC_LOCAL(Lock, dnsMutex, ());
-    DEPRECATED_DEFINE_STATIC_LOCAL(Lock, shareMutex, ());
+    if (Lock* mutex = mutexFor(data))
+        mutex->unlock();
+}
 
+Lock* CurlShareHandle::mutexFor(curl_lock_data data)
+{
+    static NeverDestroyed<Lock> cookieMutex;
+    static NeverDestroyed<Lock> dnsMutex;
+    static NeverDestroyed<Lock> shareMutex;
+
     switch (data) {
     case CURL_LOCK_DATA_COOKIE:
-        return &cookieMutex;
+        return &cookieMutex.get();
     case CURL_LOCK_DATA_DNS:
-        return &dnsMutex;
+        return &dnsMutex.get();
     case CURL_LOCK_DATA_SHARE:
-        return &shareMutex;
+        return &shareMutex.get();
     default:
         ASSERT_NOT_REACHED();
         return nullptr;
@@ -225,21 +230,467 @@
     }
 }
 
-// libcurl does not implement its own thread synchronization primitives.
-// these two functions provide mutexes for cookies, and for the global DNS
-// cache.
-void CurlContext::lock(CURL* /* handle */, curl_lock_data data, curl_lock_access /* access */, void* /* userPtr */)
+// CurlMultiHandle --------------------------------------------
+
+CurlMultiHandle::CurlMultiHandle()
 {
-    if (Lock* mutex = mutexFor(data))
-        mutex->lock();
+    CurlContext::singleton();
+
+    m_multiHandle = curl_multi_init();
 }
 
-void CurlContext::unlock(CURL* /* handle */, curl_lock_data data, void* /* userPtr */)
+CurlMultiHandle::~CurlMultiHandle()
 {
-    if (Lock* mutex = mutexFor(data))
-        mutex->unlock();
+    if (m_multiHandle) {
+        curl_multi_cleanup(m_multiHandle);
+        m_multiHandle = nullptr;
+    }
 }
 
+CURLMcode CurlMultiHandle::addHandle(CURL* handle)
+{
+    return curl_multi_add_handle(m_multiHandle, handle);
 }
 
+CURLMcode CurlMultiHandle::removeHandle(CURL* handle)
+{
+    return curl_multi_remove_handle(m_multiHandle, handle);
+}
+
+CURLMcode CurlMultiHandle::getFdSet(fd_set& readFdSet, fd_set& writeFdSet, fd_set& excFdSet, int& maxFd)
+{
+    FD_ZERO(&readFdSet);
+    FD_ZERO(&writeFdSet);
+    FD_ZERO(&excFdSet);
+    maxFd = 0;
+
+    return curl_multi_fdset(m_multiHandle, &readFdSet, &writeFdSet, &excFdSet, &maxFd);
+}
+
+CURLMcode CurlMultiHandle::perform(int& runningHandles)
+{
+    return curl_multi_perform(m_multiHandle, &runningHandles);
+}
+
+CURLMsg* CurlMultiHandle::readInfo(int& messagesInQueue)
+{
+    return curl_multi_info_read(m_multiHandle, &messagesInQueue);
+}
+
+// CurlHandle -------------------------------------------------
+
+CurlHandle::CurlHandle()
+{
+    CurlContext::singleton();
+
+    m_handle = curl_easy_init();
+    curl_easy_setopt(m_handle, CURLOPT_ERRORBUFFER, m_errorBuffer);
+}
+
+CurlHandle::~CurlHandle()
+{
+    clearCookieList();
+    clearUrl();
+    clearRequestHeaders();
+
+    if (m_handle) {
+        curl_easy_cleanup(m_handle);
+        m_handle = nullptr;
+    }
+}
+
+CURLcode CurlHandle::perform()
+{
+    return curl_easy_perform(m_handle);
+}
+
+CURLcode CurlHandle::pause(int bitmask)
+{
+    return curl_easy_pause(m_handle, CURLPAUSE_ALL);
+}
+
+void CurlHandle::enableShareHandle()
+{
+    curl_easy_setopt(m_handle, CURLOPT_SHARE, CurlContext::singleton().shareHandle().handle());
+}
+
+void CurlHandle::setPrivateData(void* userData)
+{
+    curl_easy_setopt(m_handle, CURLOPT_PRIVATE, userData);
+}
+
+void CurlHandle::setUrl(const String& url)
+{
+    clearUrl();
+
+    // url is in ASCII so latin1() will only convert it to char* without character translation.
+    m_url = fastStrDup(url.latin1().data());
+    curl_easy_setopt(m_handle, CURLOPT_URL, m_url);
+}
+
+void CurlHandle::clearUrl()
+{
+    if (m_url) {
+        fastFree(m_url);
+        m_url = nullptr;
+    }
+}
+
+void CurlHandle::clearRequestHeaders()
+{
+    if (m_requestHeaders) {
+        curl_slist_free_all(m_requestHeaders);
+        m_requestHeaders = nullptr;
+    }
+}
+
+void CurlHandle::appendRequestHeader(const String& name, const String& value)
+{
+    String header(name);
+
+    if (value.isEmpty()) {
+        // Insert the ; to tell curl that this header has an empty value.
+        header.append(";");
+    } else {
+        header.append(": ");
+        header.append(value);
+    }
+
+    appendRequestHeader(header);
+}
+
+void CurlHandle::appendRequestHeader(const String& header)
+{
+    m_requestHeaders = curl_slist_append(m_requestHeaders, header.latin1().data());
+}
+
+void CurlHandle::enableRequestHeaders()
+{
+    if (m_requestHeaders)
+        curl_easy_setopt(m_handle, CURLOPT_HTTPHEADER, m_requestHeaders);
+}
+
+void CurlHandle::enableHttpGetRequest()
+{
+    curl_easy_setopt(m_handle, CURLOPT_HTTPGET, 1L);
+}
+
+void CurlHandle::enableHttpHeadRequest()
+{
+    curl_easy_setopt(m_handle, CURLOPT_NOBODY, 1L);
+}
+
+void CurlHandle::enableHttpPostRequest()
+{
+    curl_easy_setopt(m_handle, CURLOPT_POST, 1L);
+    curl_easy_setopt(m_handle, CURLOPT_POSTFIELDSIZE, 0L);
+}
+
+void CurlHandle::setPostFields(const char* data, long size)
+{
+    curl_easy_setopt(m_handle, CURLOPT_POSTFIELDS, data);
+    curl_easy_setopt(m_handle, CURLOPT_POSTFIELDSIZE, size);
+}
+
+void CurlHandle::setPostFieldLarge(curl_off_t size)
+{
+    if (expectedSizeOfCurlOffT() != sizeof(long long))
+        size = static_cast<int>(size);
+
+    curl_easy_setopt(m_handle, CURLOPT_POSTFIELDSIZE_LARGE, size);
+}
+
+void CurlHandle::enableHttpPutRequest()
+{
+    curl_easy_setopt(m_handle, CURLOPT_UPLOAD, 1L);
+    curl_easy_setopt(m_handle, CURLOPT_INFILESIZE, 0L);
+}
+
+void CurlHandle::setInFileSizeLarge(curl_off_t size)
+{
+    if (expectedSizeOfCurlOffT() != sizeof(long long))
+        size = static_cast<int>(size);
+
+    curl_easy_setopt(m_handle, CURLOPT_INFILESIZE_LARGE, size);
+}
+
+void CurlHandle::setHttpCustomRequest(const String& method)
+{
+    curl_easy_setopt(m_handle, CURLOPT_CUSTOMREQUEST, method.ascii().data());
+}
+
+void CurlHandle::enableAcceptEncoding()
+{
+    // enable all supported built-in compressions (gzip and deflate) through Accept-Encoding:
+    curl_easy_setopt(m_handle, CURLOPT_ENCODING, "");
+}
+
+void CurlHandle::enableAllowedProtocols()
+{
+    static const long allowedProtocols = CURLPROTO_FILE | CURLPROTO_FTP | CURLPROTO_FTPS | CURLPROTO_HTTP | CURLPROTO_HTTPS;
+
+    curl_easy_setopt(m_handle, CURLOPT_PROTOCOLS, allowedProtocols);
+    curl_easy_setopt(m_handle, CURLOPT_REDIR_PROTOCOLS, allowedProtocols);
+}
+
+void CurlHandle::enableFollowLocation()
+{
+    static const long maxNumberOfRedirectCount = 10;
+
+    curl_easy_setopt(m_handle, CURLOPT_FOLLOWLOCATION, 1L);
+    curl_easy_setopt(m_handle, CURLOPT_MAXREDIRS, maxNumberOfRedirectCount);
+}
+
+void CurlHandle::enableAutoReferer()
+{
+    curl_easy_setopt(m_handle, CURLOPT_AUTOREFERER, 1L);
+}
+
+void CurlHandle::enableHttpAuthentication(long option)
+{
+    curl_easy_setopt(m_handle, CURLOPT_HTTPAUTH, option);
+}
+
+void CurlHandle::setHttpAuthUserPass(const String& user, const String& password)
+{
+    String userpass = emptyString();
+
+    if (!user.isEmpty() || !password.isEmpty())
+        userpass = user + ":" + password;
+
+    curl_easy_setopt(m_handle, CURLOPT_USERPWD, userpass.utf8().data());
+}
+
+void CurlHandle::enableCAInfoIfExists()
+{
+    const char* certPath = CurlContext::singleton().getCertificatePath();
+    if (certPath)
+        curl_easy_setopt(m_handle, CURLOPT_CAINFO, certPath);
+}
+
+void CurlHandle::setSslVerifyPeer(VerifyPeer verifyPeer)
+{
+    curl_easy_setopt(m_handle, CURLOPT_SSL_VERIFYPEER, static_cast<long>(verifyPeer));
+}
+
+void CurlHandle::setSslVerifyHost(VerifyHost verifyHost)
+{
+    curl_easy_setopt(m_handle, CURLOPT_SSL_VERIFYHOST, static_cast<long>(verifyHost));
+}
+
+void CurlHandle::setSslCert(const char* cert)
+{
+    curl_easy_setopt(m_handle, CURLOPT_SSLCERT, cert);
+}
+
+void CurlHandle::setSslCertType(const char* type)
+{
+    curl_easy_setopt(m_handle, CURLOPT_SSLCERTTYPE, type);
+}
+
+void CurlHandle::setSslKeyPassword(const char* password)
+{
+    curl_easy_setopt(m_handle, CURLOPT_KEYPASSWD, password);
+}
+
+void CurlHandle::enableCookieJarIfExists()
+{
+    const char* cookieJar = CurlContext::singleton().getCookieJarFileName();
+    if (cookieJar)
+        curl_easy_setopt(m_handle, CURLOPT_COOKIEJAR, cookieJar);
+}
+
+void CurlHandle::setCookieList(const char* cookieList)
+{
+    if (!cookieList)
+        return;
+
+    curl_easy_setopt(m_handle, CURLOPT_COOKIELIST, cookieList);
+}
+
+struct curl_slist* CurlHandle::getCookieList()
+{
+    clearCookieList();
+
+    curl_easy_getinfo(m_handle, CURLINFO_COOKIELIST, &m_cookieList);
+
+    return m_cookieList;
+}
+
+void CurlHandle::clearCookieList()
+{
+    if (!m_cookieList)
+        curl_slist_free_all(m_cookieList);
+}
+
+void CurlHandle::enableProxyIfExists()
+{
+    auto& proxy = CurlContext::singleton().proxyInfo();
+
+    if (proxy.type != CurlProxyType::Invalid) {
+        curl_easy_setopt(m_handle, CURLOPT_PROXY, proxy.url().utf8().data());
+        curl_easy_setopt(m_handle, CURLOPT_PROXYTYPE, proxy.type);
+    }
+}
+
+void CurlHandle::enableTimeout()
+{
+    static const long dnsCacheTimeout = 5 * 60; // [sec.]
+
+    curl_easy_setopt(m_handle, CURLOPT_DNS_CACHE_TIMEOUT, dnsCacheTimeout);
+}
+
+void CurlHandle::setHeaderCallbackFunction(curl_write_callback callbackFunc, void* userData)
+{
+    curl_easy_setopt(m_handle, CURLOPT_HEADERFUNCTION, callbackFunc);
+    curl_easy_setopt(m_handle, CURLOPT_HEADERDATA, userData);
+}
+
+void CurlHandle::setWriteCallbackFunction(curl_write_callback callbackFunc, void* userData)
+{
+    curl_easy_setopt(m_handle, CURLOPT_WRITEFUNCTION, callbackFunc);
+    curl_easy_setopt(m_handle, CURLOPT_WRITEDATA, userData);
+}
+
+void CurlHandle::setReadCallbackFunction(curl_read_callback callbackFunc, void* userData)
+{
+    curl_easy_setopt(m_handle, CURLOPT_READFUNCTION, callbackFunc);
+    curl_easy_setopt(m_handle, CURLOPT_READDATA, userData);
+}
+
+void CurlHandle::setSslCtxCallbackFunction(curl_ssl_ctx_callback callbackFunc, void* userData)
+{
+    curl_easy_setopt(m_handle, CURLOPT_SSL_CTX_DATA, userData);
+    curl_easy_setopt(m_handle, CURLOPT_SSL_CTX_FUNCTION, callbackFunc);
+}
+
+URL CurlHandle::getEffectiveURL()
+{
+    CURLcode errCd = CURLE_FAILED_INIT;
+    char* url = ""
+
+    if (m_handle)
+        errCd = curl_easy_getinfo(m_handle, CURLINFO_EFFECTIVE_URL, &url);
+
+    if ((errCd == CURLE_OK) && url)
+        return URL(URL(), url);
+
+    return URL();
+}
+
+CURLcode CurlHandle::getPrimaryPort(long& port)
+{
+    CURLcode errCd = CURLE_FAILED_INIT;
+    port = 0;
+
+    if (m_handle)
+        errCd = curl_easy_getinfo(m_handle, CURLINFO_PRIMARY_PORT, &port);
+
+    return errCd;
+}
+
+CURLcode CurlHandle::getResponseCode(long& responseCode)
+{
+    CURLcode errCd = CURLE_FAILED_INIT;
+    responseCode = 0L;
+
+    if (m_handle)
+        errCd = curl_easy_getinfo(m_handle, CURLINFO_RESPONSE_CODE, &responseCode);
+
+    return errCd;
+}
+
+CURLcode CurlHandle::getContentLenghtDownload(long long& contentLength)
+{
+    CURLcode errCd = CURLE_FAILED_INIT;
+    contentLength = 0;
+
+    if (m_handle) {
+        double tmpContentLength = 0;
+
+        errCd = curl_easy_getinfo(m_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &tmpContentLength);
+        if (errCd == CURLE_OK)
+            contentLength = static_cast<long long>(tmpContentLength);
+    }
+
+    return errCd;
+}
+
+CURLcode CurlHandle::getHttpAuthAvail(long& httpAuthAvail)
+{
+    CURLcode errCd = CURLE_FAILED_INIT;
+
+    if (m_handle)
+        errCd = curl_easy_getinfo(m_handle, CURLINFO_HTTPAUTH_AVAIL, &httpAuthAvail);
+
+    return errCd;
+}
+
+CURLcode CurlHandle::getTimes(double& namelookup, double& connect, double& appconnect, double& pretransfer)
+{
+    CURLcode errCd = CURLE_FAILED_INIT;
+
+    if (!m_handle)
+        return errCd;
+
+    errCd = curl_easy_getinfo(m_handle, CURLINFO_NAMELOOKUP_TIME, &namelookup);
+    if (errCd != CURLE_OK)
+        return errCd;
+
+    errCd = curl_easy_getinfo(m_handle, CURLINFO_CONNECT_TIME, &connect);
+    if (errCd != CURLE_OK)
+        return errCd;
+
+    errCd = curl_easy_getinfo(m_handle, CURLINFO_APPCONNECT_TIME, &appconnect);
+    if (errCd != CURLE_OK)
+        return errCd;
+
+    errCd = curl_easy_getinfo(m_handle, CURLINFO_PRETRANSFER_TIME, &pretransfer);
+    if (errCd != CURLE_OK)
+        return errCd;
+
+    return errCd;
+}
+
+long long CurlHandle::maxCurlOffT()
+{
+    static const long long maxCurlOffT = (1LL << (expectedSizeOfCurlOffT() * 8 - 1)) - 1;
+
+    return maxCurlOffT;
+}
+
+int CurlHandle::expectedSizeOfCurlOffT()
+{
+    // The size of a curl_off_t could be different in WebKit and in cURL depending on
+    // compilation flags of both.
+    static int expectedSizeOfCurlOffT = 0;
+    if (!expectedSizeOfCurlOffT) {
+        curl_version_info_data* infoData = curl_version_info(CURLVERSION_NOW);
+        if (infoData->features & CURL_VERSION_LARGEFILE)
+            expectedSizeOfCurlOffT = sizeof(long long);
+        else
+            expectedSizeOfCurlOffT = sizeof(int);
+    }
+
+    return expectedSizeOfCurlOffT;
+}
+
+#ifndef NDEBUG
+
+void CurlHandle::enableVerboseIfUsed()
+{
+    if (CurlContext::singleton().isVerbose())
+        curl_easy_setopt(m_handle, CURLOPT_VERBOSE, 1);
+}
+
+void CurlHandle::enableStdErrIfUsed()
+{
+    if (CurlContext::singleton().getLogFile())
+        curl_easy_setopt(m_handle, CURLOPT_VERBOSE, 1);
+}
+
 #endif
+
+}
+
+#endif

Modified: trunk/Source/WebCore/platform/network/curl/CurlContext.h (219278 => 219279)


--- trunk/Source/WebCore/platform/network/curl/CurlContext.h	2017-07-08 23:59:04 UTC (rev 219278)
+++ trunk/Source/WebCore/platform/network/curl/CurlContext.h	2017-07-09 02:58:36 UTC (rev 219279)
@@ -29,6 +29,7 @@
 #include "URL.h"
 
 #include <wtf/Lock.h>
+#include <wtf/NeverDestroyed.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/Threading.h>
 
@@ -50,7 +51,44 @@
     Socks5Hostname = CURLPROXY_SOCKS5_HOSTNAME
 };
 
-class CurlContext {
+// CurlGlobal --------------------------------------------
+// to make the initialization of libcurl happen before other initialization of CurlContext
+
+class CurlGlobal {
+protected:
+    CurlGlobal()
+    {
+        curl_global_init(CURL_GLOBAL_ALL);
+    }
+    
+    virtual ~CurlGlobal()
+    {
+        curl_global_cleanup();
+    }
+};
+
+// CurlShareHandle --------------------------------------------
+
+class CurlShareHandle {
+    WTF_MAKE_NONCOPYABLE(CurlShareHandle);
+
+public:
+    CurlShareHandle();
+    ~CurlShareHandle();
+
+    CURLSH* handle() const { return m_shareHandle; }
+
+private:
+    static void lockCallback(CURL*, curl_lock_data, curl_lock_access, void*);
+    static void unlockCallback(CURL*, curl_lock_data, void*);
+    static Lock* mutexFor(curl_lock_data);
+
+    CURLSH* m_shareHandle { nullptr };
+};
+
+// CurlContext --------------------------------------------
+
+class CurlContext : public CurlGlobal {
     WTF_MAKE_NONCOPYABLE(CurlContext);
 
 public:
@@ -70,12 +108,10 @@
         return shared;
     }
 
-    ~CurlContext();
+    virtual ~CurlContext();
 
-    CURLSH* curlShareHandle() const { return m_curlShareHandle; }
+    const CurlShareHandle& shareHandle() { return m_shareHandle; }
 
-    CURLM* createMultiHandle();
-
     // Cookie
     const char* getCookieJarFileName() const { return m_cookieJarFileName.data(); }
     void setCookieJarFileName(const char* cookieJarFileName) { m_cookieJarFileName = CString(cookieJarFileName); }
@@ -89,9 +125,6 @@
     void setProxyInfo(const ProxyInfo& info) { m_proxy = info;  }
     void setProxyInfo(const String& host = emptyString(), unsigned long port = 0, CurlProxyType = CurlProxyType::HTTP, const String& username = emptyString(), const String& password = emptyString());
 
-    // Utilities
-    URL getEffectiveURL(CURL* handle);
-
 #ifndef NDEBUG
     FILE* getLogFile() const { return m_logFile; }
     bool isVerbose() const { return m_verbose; }
@@ -98,22 +131,15 @@
 #endif
 
 private:
-
-    CURLSH* m_curlShareHandle { nullptr };
-
+    ProxyInfo m_proxy;
     CString m_cookieJarFileName;
-
     CString m_certificatePath;
+    CurlShareHandle m_shareHandle;
     bool m_ignoreSSLErrors { false };
 
-    ProxyInfo m_proxy;
-
     CurlContext();
     void initCookieSession();
 
-    static void lock(CURL*, curl_lock_data, curl_lock_access, void*);
-    static void unlock(CURL*, curl_lock_data, void*);
-    static Lock* mutexFor(curl_lock_data);
 
 #ifndef NDEBUG
     FILE* m_logFile { nullptr };
@@ -121,4 +147,129 @@
 #endif
 };
 
+// CurlMultiHandle --------------------------------------------
+
+class CurlMultiHandle {
+    WTF_MAKE_NONCOPYABLE(CurlMultiHandle);
+
+public:
+    CurlMultiHandle();
+    ~CurlMultiHandle();
+
+    CURLMcode addHandle(CURL*);
+    CURLMcode removeHandle(CURL*);
+
+    CURLMcode getFdSet(fd_set&, fd_set&, fd_set&, int&);
+    CURLMcode perform(int&);
+    CURLMsg* readInfo(int&);
+
+private:
+    CURLM* m_multiHandle { nullptr };
+};
+
+
+
+// CurlHandle -------------------------------------------------
+
+class CurlHandle {
+    WTF_MAKE_NONCOPYABLE(CurlHandle);
+
+public:
+    enum VerifyPeer {
+        VerifyPeerDisable = 0L,
+        VerifyPeerEnable = 1L
+    };
+
+    enum VerifyHost {
+        VerifyHostLooseNameCheck = 0,
+        VerifyHostStrictNameCheck = 2
+    };
+
+    CurlHandle();
+    ~CurlHandle();
+
+    CURL* handle() const { return m_handle; }
+
+    CURLcode perform();
+    CURLcode pause(int);
+
+    void enableShareHandle();
+    void setPrivateData(void* userData);
+
+    void setUrl(const String&);
+    const char* url() const { return m_url; }
+
+    void clearRequestHeaders();
+    void appendRequestHeader(const String&, const String&);
+    void appendRequestHeader(const String&);
+    void enableRequestHeaders();
+
+    void enableHttpGetRequest();
+    void enableHttpHeadRequest();
+    void enableHttpPostRequest();
+    void setPostFields(const char*, long);
+    void setPostFieldLarge(curl_off_t);
+    void enableHttpPutRequest();
+    void setInFileSizeLarge(curl_off_t);
+    void setHttpCustomRequest(const String&);
+
+    void enableAcceptEncoding();
+    void enableAllowedProtocols();
+
+    void enableFollowLocation();
+    void enableAutoReferer();
+
+    void enableHttpAuthentication(long);
+    void setHttpAuthUserPass(const String&, const String&);
+
+    void enableCAInfoIfExists();
+    void setSslVerifyPeer(VerifyPeer);
+    void setSslVerifyHost(VerifyHost);
+    void setSslCert(const char*);
+    void setSslCertType(const char*);
+    void setSslKeyPassword(const char*);
+
+    void enableCookieJarIfExists();
+    void setCookieList(const char*);
+    struct curl_slist* getCookieList();
+
+    void enableProxyIfExists();
+
+    void enableTimeout();
+
+    // Callback function
+    void setHeaderCallbackFunction(curl_write_callback, void*);
+    void setWriteCallbackFunction(curl_write_callback, void*);
+    void setReadCallbackFunction(curl_read_callback, void*);
+    void setSslCtxCallbackFunction(curl_ssl_ctx_callback, void*);
+
+    // Status
+    URL getEffectiveURL();
+    CURLcode getPrimaryPort(long&);
+    CURLcode getResponseCode(long&);
+    CURLcode getContentLenghtDownload(long long&);
+    CURLcode getHttpAuthAvail(long&);
+    CURLcode getTimes(double&, double&, double&, double&);
+
+    static long long maxCurlOffT();
+
+#ifndef NDEBUG
+    void enableVerboseIfUsed();
+    void enableStdErrIfUsed();
+#endif
+
+private:
+    void clearUrl();
+    void clearCookieList();
+
+    static int expectedSizeOfCurlOffT();
+
+    CURL* m_handle { nullptr };
+    char m_errorBuffer[CURL_ERROR_SIZE] { };
+
+    char* m_url { nullptr };
+    struct curl_slist* m_requestHeaders { nullptr };
+    struct curl_slist* m_cookieList { nullptr };
+};
+
 }

Modified: trunk/Source/WebCore/platform/network/curl/CurlDownload.cpp (219278 => 219279)


--- trunk/Source/WebCore/platform/network/curl/CurlDownload.cpp	2017-07-08 23:59:04 UTC (rev 219278)
+++ trunk/Source/WebCore/platform/network/curl/CurlDownload.cpp	2017-07-09 02:58:36 UTC (rev 219279)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2013 Apple Inc.  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
@@ -47,16 +48,6 @@
 
 CurlDownload::~CurlDownload()
 {
-    {
-        LockHolder locker(m_mutex);
-
-        if (m_url)
-            fastFree(m_url);
-
-        if (m_customHeaders)
-            curl_slist_free_all(m_customHeaders);
-    }
-
     closeFile();
     moveFileToDestination();
 }
@@ -68,29 +59,16 @@
 
     LockHolder locker(m_mutex);
 
-    m_curlHandle = curl_easy_init();
+    m_curlHandle.enableShareHandle();
 
-    String urlStr = url.string();
-    m_url = fastStrDup(urlStr.latin1().data());
+    m_curlHandle.setUrl(url);
+    m_curlHandle.setPrivateData(this);
+    m_curlHandle.setHeaderCallbackFunction(headerCallback, this);
+    m_curlHandle.setWriteCallbackFunction(writeCallback, this);
+    m_curlHandle.enableFollowLocation();
+    m_curlHandle.enableHttpAuthentication(CURLAUTH_ANY);
+    m_curlHandle.enableCAInfoIfExists();
 
-    curl_easy_setopt(m_curlHandle, CURLOPT_URL, m_url);
-    curl_easy_setopt(m_curlHandle, CURLOPT_PRIVATE, this);
-    curl_easy_setopt(m_curlHandle, CURLOPT_WRITEFUNCTION, writeCallback);
-    curl_easy_setopt(m_curlHandle, CURLOPT_WRITEDATA, this);
-    curl_easy_setopt(m_curlHandle, CURLOPT_HEADERFUNCTION, headerCallback);
-    curl_easy_setopt(m_curlHandle, CURLOPT_WRITEHEADER, this);
-    curl_easy_setopt(m_curlHandle, CURLOPT_FOLLOWLOCATION, 1);
-    curl_easy_setopt(m_curlHandle, CURLOPT_MAXREDIRS, 10);
-    curl_easy_setopt(m_curlHandle, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
-
-    const char* certPath = getenv("CURL_CA_BUNDLE_PATH");
-    if (certPath)
-        curl_easy_setopt(m_curlHandle, CURLOPT_CAINFO, certPath);
-
-    CURLSH* curlsh = CurlContext::singleton().curlShareHandle();
-    if (curlsh)
-        curl_easy_setopt(m_curlHandle, CURLOPT_SHARE, curlsh);
-
     m_listener = listener;
 }
 
@@ -109,12 +87,12 @@
 bool CurlDownload::start()
 {
     ref(); // CurlJobManager will call deref when the download has finished.
-    return CurlJobManager::singleton().add(m_curlHandle);
+    return CurlJobManager::singleton().add(m_curlHandle.handle());
 }
 
 bool CurlDownload::cancel()
 {
-    return CurlJobManager::singleton().remove(m_curlHandle);
+    return CurlJobManager::singleton().remove(m_curlHandle.handle());
 }
 
 String CurlDownload::getTempPath() const
@@ -126,7 +104,7 @@
 String CurlDownload::getUrl() const
 {
     LockHolder locker(m_mutex);
-    return String(m_url);
+    return String(m_curlHandle.url());
 }
 
 ResourceResponse CurlDownload::getResponse() const
@@ -168,9 +146,9 @@
 {
     LockHolder locker(m_mutex);
 
+    m_curlHandle.clearRequestHeaders();
+
     if (request.httpHeaderFields().size() > 0) {
-        struct curl_slist* headers = 0;
-
         HTTPHeaderMap customHeaders = request.httpHeaderFields();
         HTTPHeaderMap::const_iterator end = customHeaders.end();
         for (HTTPHeaderMap::const_iterator it = customHeaders.begin(); it != end; ++it) {
@@ -183,14 +161,11 @@
                 headerString.append(": ");
                 headerString.append(value);
             }
-            CString headerLatin1 = headerString.latin1();
-            headers = curl_slist_append(headers, headerLatin1.data());
+
+            m_curlHandle.appendRequestHeader(headerString);
         }
 
-        if (headers) {
-            curl_easy_setopt(m_curlHandle, CURLOPT_HTTPHEADER, headers);
-            m_customHeaders = headers;
-        }
+        m_curlHandle.enableRequestHeaders();
     }
 }
 
@@ -201,11 +176,10 @@
     if (header == "\r\n" || header == "\n") {
 
         long httpCode = 0;
-        CURLcode err = curl_easy_getinfo(m_curlHandle, CURLINFO_RESPONSE_CODE, &httpCode);
-        UNUSED_PARAM(err);
+        m_curlHandle.getResponseCode(httpCode);
 
         if (httpCode >= 200 && httpCode < 300) {
-            URL url = ""
+            URL url = ""
             callOnMainThread([this, url = "" protectedThis = makeRef(*this)] {
                 m_response.setURL(url);
                 m_response.setMimeType(extractMIMETypeFromMediaType(m_response.httpHeaderField(HTTPHeaderName::ContentType)));
@@ -270,13 +244,13 @@
         m_listener->didFail();
 }
 
-size_t CurlDownload::writeCallback(void* ptr, size_t size, size_t nmemb, void* data)
+size_t CurlDownload::writeCallback(char* ptr, size_t size, size_t nmemb, void* data)
 {
     size_t totalSize = size * nmemb;
     CurlDownload* download = reinterpret_cast<CurlDownload*>(data);
 
     if (download)
-        download->didReceiveData(ptr, totalSize);
+        download->didReceiveData(static_cast<void*>(ptr), totalSize);
 
     return totalSize;
 }

Modified: trunk/Source/WebCore/platform/network/curl/CurlDownload.h (219278 => 219279)


--- trunk/Source/WebCore/platform/network/curl/CurlDownload.h	2017-07-08 23:59:04 UTC (rev 219278)
+++ trunk/Source/WebCore/platform/network/curl/CurlDownload.h	2017-07-09 02:58:36 UTC (rev 219279)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2013 Apple Inc.  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
@@ -36,6 +37,7 @@
 #include <winsock2.h>
 #endif
 
+#include "CurlContext.h"
 #include "CurlJobManager.h"
 
 namespace WebCore {
@@ -89,7 +91,7 @@
     void didFinish();
     void didFail();
 
-    static size_t writeCallback(void* ptr, size_t, size_t nmemb, void* data);
+    static size_t writeCallback(char* ptr, size_t, size_t nmemb, void* data);
     static size_t headerCallback(char* ptr, size_t, size_t nmemb, void* data);
 
     static void downloadFinishedCallback(CurlDownload*);
@@ -97,9 +99,8 @@
     static void receivedDataCallback(CurlDownload*, int size);
     static void receivedResponseCallback(CurlDownload*);
 
-    CURL* m_curlHandle { nullptr };
-    struct curl_slist* m_customHeaders { nullptr };
-    char* m_url { nullptr };
+    CurlHandle m_curlHandle;
+
     String m_tempPath;
     String m_destination;
     WebCore::PlatformFileHandle m_tempHandle { invalidPlatformFileHandle };

Modified: trunk/Source/WebCore/platform/network/curl/CurlJobManager.cpp (219278 => 219279)


--- trunk/Source/WebCore/platform/network/curl/CurlJobManager.cpp	2017-07-08 23:59:04 UTC (rev 219278)
+++ trunk/Source/WebCore/platform/network/curl/CurlJobManager.cpp	2017-07-09 02:58:36 UTC (rev 219279)
@@ -29,8 +29,6 @@
 #if USE(CURL)
 #include "CurlJobManager.h"
 
-#include "CurlContext.h"
-
 #include <wtf/MainThread.h>
 #include <wtf/text/CString.h>
 
@@ -40,13 +38,12 @@
 
 CurlJobManager::CurlJobManager()
 {
-    m_curlMultiHandle = CurlContext::singleton().createMultiHandle();
+
 }
 
 CurlJobManager::~CurlJobManager()
 {
     stopThread();
-    curl_multi_cleanup(m_curlMultiHandle);
 }
 
 bool CurlJobManager::add(CURL* curlHandle)
@@ -135,7 +132,7 @@
 
 bool CurlJobManager::addToCurl(CURL* curlHandle)
 {
-    CURLMcode retval = curl_multi_add_handle(m_curlMultiHandle, curlHandle);
+    CURLMcode retval = m_curlMultiHandle.addHandle(curlHandle);
     if (retval == CURLM_OK) {
         m_activeHandleList.append(curlHandle);
         return true;
@@ -149,11 +146,10 @@
 
     if (handlePos < 0)
         return true;
-    
-    CURLMcode retval = curl_multi_remove_handle(m_curlMultiHandle, curlHandle);
+
+    CURLMcode retval = m_curlMultiHandle.removeHandle(curlHandle);
     if (retval == CURLM_OK) {
         m_activeHandleList.remove(handlePos);
-        curl_easy_cleanup(curlHandle);
         return true;
     }
     return false;
@@ -173,7 +169,6 @@
             fd_set fdread;
             fd_set fdwrite;
             fd_set fdexcep;
-
             int maxfd = 0;
 
             const int selectTimeoutMS = 5;
@@ -182,10 +177,8 @@
             timeout.tv_sec = 0;
             timeout.tv_usec = selectTimeoutMS * 1000; // select waits microseconds
 
-            FD_ZERO(&fdread);
-            FD_ZERO(&fdwrite);
-            FD_ZERO(&fdexcep);
-            curl_multi_fdset(getMultiHandle(), &fdread, &fdwrite, &fdexcep, &maxfd);
+            m_curlMultiHandle.getFdSet(fdread, fdwrite, fdexcep, maxfd);
+
             // When the 3 file descriptors are empty, winsock will return -1
             // and bail out, stopping the file download. So make sure we
             // have valid file descriptors before calling select.
@@ -193,12 +186,11 @@
                 rc = ::select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
         } while (rc == -1 && errno == EINTR);
 
-        int activeCount = 0;
-        while (curl_multi_perform(getMultiHandle(), &activeCount) == CURLM_CALL_MULTI_PERFORM) { }
+        int runningHandles = 0;
+        while (m_curlMultiHandle.perform(runningHandles) == CURLM_CALL_MULTI_PERFORM) { }
 
         int messagesInQueue = 0;
-        CURLMsg* msg = curl_multi_info_read(getMultiHandle(), &messagesInQueue);
-
+        CURLMsg* msg = m_curlMultiHandle.readInfo(messagesInQueue);
         if (!msg)
             continue;
 

Modified: trunk/Source/WebCore/platform/network/curl/CurlJobManager.h (219278 => 219279)


--- trunk/Source/WebCore/platform/network/curl/CurlJobManager.h	2017-07-08 23:59:04 UTC (rev 219278)
+++ trunk/Source/WebCore/platform/network/curl/CurlJobManager.h	2017-07-09 02:58:36 UTC (rev 219279)
@@ -26,6 +26,8 @@
 
 #pragma once
 
+#include "CurlContext.h"
+
 #include <wtf/Lock.h>
 #include <wtf/Threading.h>
 #include <wtf/Vector.h>
@@ -35,7 +37,6 @@
 #include <winsock2.h>
 #endif
 
-#include <curl/curl.h>
 
 namespace WebCore {
 
@@ -74,8 +75,6 @@
 
     void updateHandleList();
 
-    CURLM* getMultiHandle() const { return m_curlMultiHandle; }
-
     bool runThread() const { LockHolder locker(m_mutex); return m_runThread; }
     void setRunThread(bool runThread) { LockHolder locker(m_mutex); m_runThread = runThread; }
 
@@ -85,7 +84,6 @@
     void workerThread();
 
     RefPtr<Thread> m_thread;
-    CURLM* m_curlMultiHandle { nullptr };
     Vector<CURL*> m_pendingHandleList;
     Vector<CURL*> m_activeHandleList;
     Vector<CURL*> m_removedHandleList;
@@ -92,6 +90,8 @@
     mutable Lock m_mutex;
     bool m_runThread { false };
 
+    CurlMultiHandle m_curlMultiHandle;
+
     friend class CurlJob;
 };
 

Modified: trunk/Source/WebCore/platform/network/curl/ResourceHandleCurl.cpp (219278 => 219279)


--- trunk/Source/WebCore/platform/network/curl/ResourceHandleCurl.cpp	2017-07-08 23:59:04 UTC (rev 219278)
+++ trunk/Source/WebCore/platform/network/curl/ResourceHandleCurl.cpp	2017-07-09 02:58:36 UTC (rev 219279)
@@ -1,6 +1,7 @@
 /*
  * 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.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -49,9 +50,7 @@
 
 ResourceHandleInternal::~ResourceHandleInternal()
 {
-    fastFree(m_url);
-    if (m_customHeaders)
-        curl_slist_free_all(m_customHeaders);
+
 }
 
 ResourceHandle::~ResourceHandle()
@@ -105,16 +104,16 @@
 
 void ResourceHandle::platformSetDefersLoading(bool defers)
 {
-    if (!d->m_handle)
+    if (!d->m_curlHandle.handle())
         return;
 
     if (defers) {
-        CURLcode error = curl_easy_pause(d->m_handle, CURLPAUSE_ALL);
+        CURLcode error = d->m_curlHandle.pause(CURLPAUSE_ALL);
         // If we could not defer the handle, so don't do it.
         if (error != CURLE_OK)
             return;
     } else {
-        CURLcode error = curl_easy_pause(d->m_handle, CURLPAUSE_CONT);
+        CURLcode error = d->m_curlHandle.pause(CURLPAUSE_CONT);
         if (error != CURLE_OK)
             // Restarting the handle has failed so just cancel it.
             cancel();
@@ -150,8 +149,7 @@
             urlToStore = challenge.failureResponse().url();
         CredentialStorage::defaultCredentialStorage().set(partition, credential, challenge.protectionSpace(), urlToStore);
         
-        String userpass = credential.user() + ":" + credential.password();
-        curl_easy_setopt(d->m_handle, CURLOPT_USERPWD, userpass.utf8().data());
+        d->m_curlHandle.setHttpAuthUserPass(credential.user(), credential.password());
 
         d->m_user = String();
         d->m_pass = String();
@@ -175,8 +173,8 @@
                     // Store the credential back, possibly adding it as a default for this directory.
                     CredentialStorage::defaultCredentialStorage().set(partition, credential, challenge.protectionSpace(), challenge.failureResponse().url());
                 }
-                String userpass = credential.user() + ":" + credential.password();
-                curl_easy_setopt(d->m_handle, CURLOPT_USERPWD, userpass.utf8().data());
+
+                d->m_curlHandle.setHttpAuthUserPass(credential.user(), credential.password());
                 return;
             }
         }
@@ -207,9 +205,7 @@
         }
     }
 
-    String userpass = credential.user() + ":" + credential.password();
-    curl_easy_setopt(d->m_handle, CURLOPT_USERPWD, userpass.utf8().data());
-
+    d->m_curlHandle.setHttpAuthUserPass(credential.user(), credential.password());
     clearAuthentication();
 }
 
@@ -218,9 +214,7 @@
     if (challenge != d->m_currentWebChallenge)
         return;
 
-    String userpass = emptyString();
-    curl_easy_setopt(d->m_handle, CURLOPT_USERPWD, userpass.utf8().data());
-
+    d->m_curlHandle.setHttpAuthUserPass("", "");
     clearAuthentication();
 }
 
@@ -253,10 +247,7 @@
     double connectTime = 0;
     double appConnectTime = 0;
 
-    curl_easy_getinfo(d->m_handle, CURLINFO_NAMELOOKUP_TIME, &dnslookupTime);
-    curl_easy_getinfo(d->m_handle, CURLINFO_CONNECT_TIME, &connectTime);
-    curl_easy_getinfo(d->m_handle, CURLINFO_APPCONNECT_TIME, &appConnectTime);
-    curl_easy_getinfo(d->m_handle, CURLINFO_PRETRANSFER_TIME, &preTransferTime);
+    d->m_curlHandle.getTimes(preTransferTime, dnslookupTime, connectTime, appConnectTime);
 
     d->m_response.deprecatedNetworkLoadMetrics().domainLookupStart = Seconds(0);
     d->m_response.deprecatedNetworkLoadMetrics().domainLookupEnd = Seconds(dnslookupTime);
@@ -272,7 +263,7 @@
 }
 #endif
 
-static void handleLocalReceiveResponse(CURL* handle, ResourceHandle* job, ResourceHandleInternal* d)
+static void handleLocalReceiveResponse(ResourceHandle* job, ResourceHandleInternal* d)
 {
     // since the code in headerCallback will not have run for local files
     // the code to set the URL and fire didReceiveResponse is never run,
@@ -279,7 +270,7 @@
     // which means the ResourceLoader's response does not contain the URL.
     // Run the code here for local files to resolve the issue.
     // TODO: See if there is a better approach for handling this.
-    URL url = ""
+    URL url = ""
     ASSERT(url.isValid());
     d->m_response.setURL(url);
     if (d->client())
@@ -287,9 +278,8 @@
     d->m_response.setResponseFired(true);
 }
 
-
 // called with data after all headers have been processed via headerCallback
-static size_t writeCallback(void* ptr, size_t size, size_t nmemb, void* data)
+static size_t writeCallback(char* ptr, size_t size, size_t nmemb, void* data)
 {
     ResourceHandle* job = static_cast<ResourceHandle*>(data);
     ResourceHandleInternal* d = job->getInternal();
@@ -304,14 +294,13 @@
     // this shouldn't be necessary but apparently is. CURL writes the data
     // of html page even if it is a redirect that was handled internally
     // can be observed e.g. on gmail.com
-    CURL* h = d->m_handle;
     long httpCode = 0;
-    CURLcode err = curl_easy_getinfo(h, CURLINFO_RESPONSE_CODE, &httpCode);
-    if (CURLE_OK == err && httpCode >= 300 && httpCode < 400)
+    CURLcode errCd = d->m_curlHandle.getResponseCode(httpCode);
+    if (CURLE_OK == errCd && httpCode >= 300 && httpCode < 400)
         return totalSize;
 
     if (!d->m_response.responseFired()) {
-        handleLocalReceiveResponse(h, job, d);
+        handleLocalReceiveResponse(job, d);
         if (d->m_cancelled)
             return 0;
     }
@@ -319,8 +308,8 @@
     if (d->m_multipartHandle)
         d->m_multipartHandle->contentReceived(static_cast<const char*>(ptr), totalSize);
     else if (d->client()) {
-        d->client()->didReceiveData(job, static_cast<char*>(ptr), totalSize, 0);
-        CurlCacheManager::getInstance().didReceiveData(*job, static_cast<char*>(ptr), totalSize);
+        d->client()->didReceiveData(job, ptr, totalSize, 0);
+        CurlCacheManager::getInstance().didReceiveData(*job, ptr, totalSize);
     }
 
     return totalSize;
@@ -396,21 +385,23 @@
         value = value.substring(1, length - 2);
 }
 
-static bool getProtectionSpace(CURL* h, const ResourceResponse& response, ProtectionSpace& protectionSpace)
+static bool getProtectionSpace(ResourceHandle* job, const ResourceResponse& response, ProtectionSpace& protectionSpace)
 {
+    ResourceHandleInternal* d = job->getInternal();
+
     CURLcode err;
 
     long port = 0;
-    err = curl_easy_getinfo(h, CURLINFO_PRIMARY_PORT, &port);
+    err = d->m_curlHandle.getPrimaryPort(port);
     if (err != CURLE_OK)
         return false;
 
     long availableAuth = CURLAUTH_NONE;
-    err = curl_easy_getinfo(h, CURLINFO_HTTPAUTH_AVAIL, &availableAuth);
+    err = d->m_curlHandle.getHttpAuthAvail(availableAuth);
     if (err != CURLE_OK)
         return false;
 
-    URL url = ""
+    URL url = ""
     if (!url.isValid())
         return false;
 
@@ -480,10 +471,8 @@
     * accept also \n.
     */
     if (header == String("\r\n") || header == String("\n")) {
-        CURL* h = d->m_handle;
-
         long httpCode = 0;
-        curl_easy_getinfo(h, CURLINFO_RESPONSE_CODE, &httpCode);
+        d->m_curlHandle.getResponseCode(httpCode);
 
         if (!httpCode) {
             // Comes here when receiving 200 Connection Established. Just return.
@@ -495,11 +484,11 @@
             return totalSize;
         }
 
-        double contentLength = 0;
-        curl_easy_getinfo(h, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &contentLength);
-        d->m_response.setExpectedContentLength(static_cast<long long int>(contentLength));
+        long long contentLength = 0;
+        d->m_curlHandle.getContentLenghtDownload(contentLength);
+        d->m_response.setExpectedContentLength(contentLength);
 
-        d->m_response.setURL(CurlContext::singleton().getEffectiveURL(h));
+        d->m_response.setURL(d->m_curlHandle.getEffectiveURL());
 
         d->m_response.setHTTPStatusCode(httpCode);
         d->m_response.setMimeType(extractMIMETypeFromMediaType(d->m_response.httpHeaderField(HTTPHeaderName::ContentType)).convertToASCIILowercase());
@@ -530,7 +519,7 @@
             }
         } else if (isHttpAuthentication(httpCode)) {
             ProtectionSpace protectionSpace;
-            if (getProtectionSpace(d->m_handle, d->m_response, protectionSpace)) {
+            if (getProtectionSpace(job, d->m_response, protectionSpace)) {
                 Credential credential;
                 AuthenticationChallenge challenge(protectionSpace, credential, d->m_authFailureCount, d->m_response, ResourceError());
                 challenge.setAuthenticationClient(job);
@@ -573,7 +562,7 @@
             // curl will follow the redirections internally. Thus this header callback
             // will be called more than one time with the line starting "HTTP" for one job.
             long httpCode = 0;
-            curl_easy_getinfo(d->m_handle, CURLINFO_RESPONSE_CODE, &httpCode);
+            d->m_curlHandle.getResponseCode(httpCode);
 
             String httpCodeString = String::number(httpCode);
             int statusCodePos = header.find(httpCodeString);
@@ -594,7 +583,7 @@
 Iterate through FormData elements and upload files.
 Carefully respect the given buffer size and fill the rest of the data at the next calls.
 */
-size_t readCallback(void* ptr, size_t size, size_t nmemb, void* data)
+size_t readCallback(char* ptr, size_t size, size_t nmemb, void* data)
 {
     ResourceHandle* job = static_cast<ResourceHandle*>(data);
     ResourceHandleInternal* d = job->getInternal();
@@ -635,24 +624,14 @@
     return size;
 }
 
-static void setupFormData(ResourceHandle* job, CURLoption sizeOption, struct curl_slist** headers)
+static void setupFormData(ResourceHandle* job, bool isPostRequest)
 {
     ResourceHandleInternal* d = job->getInternal();
     Vector<FormDataElement> elements = job->firstRequest().httpBody()->elements();
     size_t numElements = elements.size();
 
-    // The size of a curl_off_t could be different in WebKit and in cURL depending on
-    // compilation flags of both.
-    static int expectedSizeOfCurlOffT = 0;
-    if (!expectedSizeOfCurlOffT) {
-        curl_version_info_data* infoData = curl_version_info(CURLVERSION_NOW);
-        if (infoData->features & CURL_VERSION_LARGEFILE)
-            expectedSizeOfCurlOffT = sizeof(long long);
-        else
-            expectedSizeOfCurlOffT = sizeof(int);
-    }
+    static const long long maxCurlOffT = d->m_curlHandle.maxCurlOffT();
 
-    static const long long maxCurlOffT = (1LL << (expectedSizeOfCurlOffT * 8 - 1)) - 1;
     // Obtain the total size of the form data
     curl_off_t size = 0;
     bool chunkedTransfer = false;
@@ -677,39 +656,36 @@
 
     // cURL guesses that we want chunked encoding as long as we specify the header
     if (chunkedTransfer)
-        *headers = curl_slist_append(*headers, "Transfer-Encoding: chunked");
+        d->m_curlHandle.appendRequestHeader("Transfer-Encoding: chunked");
     else {
-        if (sizeof(long long) == expectedSizeOfCurlOffT)
-            curl_easy_setopt(d->m_handle, sizeOption, (long long)size);
+        if (isPostRequest)
+            d->m_curlHandle.setPostFieldLarge(size);
         else
-            curl_easy_setopt(d->m_handle, sizeOption, (int)size);
+            d->m_curlHandle.setInFileSizeLarge(size);
     }
 
-    curl_easy_setopt(d->m_handle, CURLOPT_READFUNCTION, readCallback);
-    curl_easy_setopt(d->m_handle, CURLOPT_READDATA, job);
+    d->m_curlHandle.setReadCallbackFunction(readCallback, job);
 }
 
-void ResourceHandle::setupPUT(struct curl_slist** headers)
+void ResourceHandle::setupPUT()
 {
     ResourceHandleInternal* d = getInternal();
-    curl_easy_setopt(d->m_handle, CURLOPT_UPLOAD, TRUE);
-    curl_easy_setopt(d->m_handle, CURLOPT_INFILESIZE, 0);
+    d->m_curlHandle.enableHttpPutRequest();
 
     // Disable the Expect: 100 continue header
-    *headers = curl_slist_append(*headers, "Expect:");
+    d->m_curlHandle.appendRequestHeader("Expect:");
 
     size_t numElements = getFormElementsCount(this);
     if (!numElements)
         return;
 
-    setupFormData(this, CURLOPT_INFILESIZE_LARGE, headers);
+    setupFormData(this, false);
 }
 
-void ResourceHandle::setupPOST(struct curl_slist** headers)
+void ResourceHandle::setupPOST()
 {
     ResourceHandleInternal* d = getInternal();
-    curl_easy_setopt(d->m_handle, CURLOPT_POST, TRUE);
-    curl_easy_setopt(d->m_handle, CURLOPT_POSTFIELDSIZE, 0);
+    d->m_curlHandle.enableHttpPostRequest();
 
     size_t numElements = getFormElementsCount(this);
     if (!numElements)
@@ -718,14 +694,12 @@
     // Do not stream for simple POST data
     if (numElements == 1) {
         firstRequest().httpBody()->flatten(d->m_postBytes);
-        if (d->m_postBytes.size()) {
-            curl_easy_setopt(d->m_handle, CURLOPT_POSTFIELDSIZE, d->m_postBytes.size());
-            curl_easy_setopt(d->m_handle, CURLOPT_POSTFIELDS, d->m_postBytes.data());
-        }
+        if (d->m_postBytes.size())
+            d->m_curlHandle.setPostFields(d->m_postBytes.data(), d->m_postBytes.size());
         return;
     }
 
-    setupFormData(this, CURLOPT_POSTFIELDSIZE_LARGE, headers);
+    setupFormData(this, true);
 }
 
 void ResourceHandle::handleDataURL()
@@ -808,7 +782,7 @@
     initialize();
 
     // curl_easy_perform blocks until the transfert is finished.
-    CURLcode ret = curl_easy_perform(d->m_handle);
+    CURLcode ret = d->m_curlHandle.perform();
 
     if (ret != CURLE_OK) {
         ResourceError error(ASCIILiteral(errorDomainCurl), ret, kurl, String(curl_easy_strerror(ret)));
@@ -822,8 +796,6 @@
 #if ENABLE(WEB_TIMING)
     calculateWebTimingInformations(d);
 #endif
-
-    curl_easy_cleanup(d->m_handle);
 }
 
 void ResourceHandle::applyAuthentication()
@@ -854,7 +826,7 @@
     if (!d->m_initialCredential.isEmpty()) {
         user = d->m_initialCredential.user();
         password = d->m_initialCredential.password();
-        curl_easy_setopt(d->m_handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
+        d->m_curlHandle.enableHttpAuthentication(CURLAUTH_BASIC);
     }
 
     // It seems we need to set CURLOPT_USERPWD even if username and password is empty.
@@ -861,8 +833,7 @@
     // Otherwise cURL will not automatically continue with a new request after a 401 response.
 
     // curl CURLOPT_USERPWD expects username:password
-    String userpass = user + ":" + password;
-    curl_easy_setopt(d->m_handle, CURLOPT_USERPWD, userpass.utf8().data());
+    d->m_curlHandle.setHttpAuthUserPass(user, password);
 }
 
 void ResourceHandle::initialize()
@@ -869,7 +840,6 @@
 {
     CurlContext& context = CurlContext::singleton();
 
-    static const int allowedProtocols = CURLPROTO_FILE | CURLPROTO_FTP | CURLPROTO_FTPS | CURLPROTO_HTTP | CURLPROTO_HTTPS;
     URL url = ""
 
     // Remove any fragment part, otherwise curl will send it as part of the request.
@@ -889,62 +859,44 @@
         d->m_response.setMimeType(MIMETypeRegistry::getMIMETypeForPath(url));
     }
 
-    d->m_handle = curl_easy_init();
-
     if (d->m_defersLoading) {
-        CURLcode error = curl_easy_pause(d->m_handle, CURLPAUSE_ALL);
+        CURLcode error = d->m_curlHandle.pause(CURLPAUSE_ALL);
         // If we did not pause the handle, we would ASSERT in the
         // header callback. So just assert here.
         ASSERT_UNUSED(error, error == CURLE_OK);
     }
+
 #ifndef NDEBUG
-    if (context.isVerbose())
-        curl_easy_setopt(d->m_handle, CURLOPT_VERBOSE, 1);
-    if (context.getLogFile())
-        curl_easy_setopt(d->m_handle, CURLOPT_STDERR, context.getLogFile());
+    d->m_curlHandle.enableVerboseIfUsed();
+    d->m_curlHandle.enableStdErrIfUsed();
 #endif
-    curl_easy_setopt(d->m_handle, CURLOPT_SSL_VERIFYPEER, 1L);
-    curl_easy_setopt(d->m_handle, CURLOPT_SSL_VERIFYHOST, 2L);
-    curl_easy_setopt(d->m_handle, CURLOPT_PRIVATE, this);
-    curl_easy_setopt(d->m_handle, CURLOPT_ERRORBUFFER, m_curlErrorBuffer);
-    curl_easy_setopt(d->m_handle, CURLOPT_WRITEFUNCTION, writeCallback);
-    curl_easy_setopt(d->m_handle, CURLOPT_WRITEDATA, this);
-    curl_easy_setopt(d->m_handle, CURLOPT_HEADERFUNCTION, headerCallback);
-    curl_easy_setopt(d->m_handle, CURLOPT_WRITEHEADER, this);
-    curl_easy_setopt(d->m_handle, CURLOPT_AUTOREFERER, 1);
-    curl_easy_setopt(d->m_handle, CURLOPT_FOLLOWLOCATION, 1);
-    curl_easy_setopt(d->m_handle, CURLOPT_MAXREDIRS, 10);
-    curl_easy_setopt(d->m_handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
-    curl_easy_setopt(d->m_handle, CURLOPT_SHARE, CurlContext::singleton().curlShareHandle());
-    curl_easy_setopt(d->m_handle, CURLOPT_DNS_CACHE_TIMEOUT, 60 * 5); // 5 minutes
-    curl_easy_setopt(d->m_handle, CURLOPT_PROTOCOLS, allowedProtocols);
-    curl_easy_setopt(d->m_handle, CURLOPT_REDIR_PROTOCOLS, allowedProtocols);
+
+    d->m_curlHandle.setSslVerifyPeer(CurlHandle::VerifyPeerEnable);
+    d->m_curlHandle.setSslVerifyHost(CurlHandle::VerifyHostStrictNameCheck);
+    d->m_curlHandle.setPrivateData(this);
+    d->m_curlHandle.setWriteCallbackFunction(writeCallback, this);
+    d->m_curlHandle.setHeaderCallbackFunction(headerCallback, this);
+    d->m_curlHandle.enableAutoReferer();
+    d->m_curlHandle.enableFollowLocation();
+    d->m_curlHandle.enableHttpAuthentication(CURLAUTH_ANY);
+    d->m_curlHandle.enableShareHandle();
+    d->m_curlHandle.enableTimeout();
+    d->m_curlHandle.enableAllowedProtocols();
     setSSLClientCertificate(this);
 
-    if (context.shouldIgnoreSSLErrors())
-        curl_easy_setopt(d->m_handle, CURLOPT_SSL_VERIFYPEER, false);
+    if (CurlContext::singleton().shouldIgnoreSSLErrors())
+        d->m_curlHandle.setSslVerifyPeer(CurlHandle::VerifyPeerDisable);
     else
         setSSLVerifyOptions(this);
 
-    const char* certificate = context.getCertificatePath();
-    if (certificate)
-        curl_easy_setopt(d->m_handle, CURLOPT_CAINFO, certificate);
+    d->m_curlHandle.enableCAInfoIfExists();
 
-    // enable gzip and deflate through Accept-Encoding:
-    curl_easy_setopt(d->m_handle, CURLOPT_ENCODING, "");
+    d->m_curlHandle.enableAcceptEncoding();
+    d->m_curlHandle.setUrl(urlString);
+    d->m_curlHandle.enableCookieJarIfExists();
 
-    // url must remain valid through the request
-    ASSERT(!d->m_url);
+    d->m_curlHandle.clearRequestHeaders();
 
-    // url is in ASCII so latin1() will only convert it to char* without character translation.
-    d->m_url = fastStrDup(urlString.latin1().data());
-    curl_easy_setopt(d->m_handle, CURLOPT_URL, d->m_url);
-
-    const char* cookieJar = context.getCookieJarFileName();
-    if (cookieJar)
-        curl_easy_setopt(d->m_handle, CURLOPT_COOKIEJAR, cookieJar);
-
-    struct curl_slist* headers = 0;
     if (firstRequest().httpHeaderFields().size() > 0) {
         HTTPHeaderMap customHeaders = firstRequest().httpHeaderFields();
 
@@ -963,50 +915,29 @@
             d->m_addedCacheValidationHeaders = true;
         }
 
-        HTTPHeaderMap::const_iterator end = customHeaders.end();
-        for (HTTPHeaderMap::const_iterator it = customHeaders.begin(); it != end; ++it) {
-            String key = it->key;
-            String value = it->value;
-            String headerString(key);
-            if (value.isEmpty()) {
-                // Insert the ; to tell curl that this header has an empty value.
-                headerString.append(";");
-            } else {
-                headerString.append(": ");
-                headerString.append(value);
-            }
-            CString headerLatin1 = headerString.latin1();
-            headers = curl_slist_append(headers, headerLatin1.data());
-        }
+        for (auto customHeader : customHeaders)
+            d->m_curlHandle.appendRequestHeader(customHeader.key, customHeader.value);
     }
 
     String method = firstRequest().httpMethod();
     if ("GET" == method)
-        curl_easy_setopt(d->m_handle, CURLOPT_HTTPGET, TRUE);
+        d->m_curlHandle.enableHttpGetRequest();
     else if ("POST" == method)
-        setupPOST(&headers);
+        setupPOST();
     else if ("PUT" == method)
-        setupPUT(&headers);
+        setupPUT();
     else if ("HEAD" == method)
-        curl_easy_setopt(d->m_handle, CURLOPT_NOBODY, TRUE);
+        d->m_curlHandle.enableHttpHeadRequest();
     else {
-        curl_easy_setopt(d->m_handle, CURLOPT_CUSTOMREQUEST, method.ascii().data());
-        setupPUT(&headers);
+        d->m_curlHandle.setHttpCustomRequest(method);
+        setupPUT();
     }
 
-    if (headers) {
-        curl_easy_setopt(d->m_handle, CURLOPT_HTTPHEADER, headers);
-        d->m_customHeaders = headers;
-    }
+    d->m_curlHandle.enableRequestHeaders();
 
     applyAuthentication();
 
-    // Set proxy options if we have them.
-    auto& proxy = CurlContext::singleton().proxyInfo();
-    if (proxy.type != CurlProxyType::Invalid) {
-        curl_easy_setopt(d->m_handle, CURLOPT_PROXY, proxy.url().utf8().data());
-        curl_easy_setopt(d->m_handle, CURLOPT_PROXYTYPE, proxy.type);
-    }
+    d->m_curlHandle.enableProxyIfExists();
 }
 
 void ResourceHandle::handleCurlMsg(CURLMsg* msg)
@@ -1018,7 +949,7 @@
         calculateWebTimingInformations(d);
 #endif
         if (!d->m_response.responseFired()) {
-            handleLocalReceiveResponse(d->m_handle, this, d);
+            handleLocalReceiveResponse(this, d);
             if (d->m_cancelled)
                 return;
         }
@@ -1031,7 +962,7 @@
             CurlCacheManager::getInstance().didFinishLoading(*this);
         }
     } else {
-        URL url = ""
+        URL url = ""
 #ifndef NDEBUG
         fprintf(stderr, "Curl ERROR for url='', error: '%s'\n", url.string().utf8().data(), curl_easy_strerror(msg->data.result));
 #endif

Modified: trunk/Source/WebCore/platform/network/curl/ResourceHandleManager.cpp (219278 => 219279)


--- trunk/Source/WebCore/platform/network/curl/ResourceHandleManager.cpp	2017-07-08 23:59:04 UTC (rev 219278)
+++ trunk/Source/WebCore/platform/network/curl/ResourceHandleManager.cpp	2017-07-09 02:58:36 UTC (rev 219279)
@@ -41,7 +41,6 @@
 #if USE(CURL)
 
 #include "CredentialStorage.h"
-#include "CurlContext.h"
 #include "HTTPHeaderNames.h"
 #include "HTTPParsers.h"
 #include "MultipartHandle.h"
@@ -81,12 +80,12 @@
     : m_downloadTimer(*this, &ResourceHandleManager::downloadTimerCallback)
     , m_runningJobs(0)
 {
-    m_curlMultiHandle = CurlContext::singleton().createMultiHandle();
+
 }
 
 ResourceHandleManager::~ResourceHandleManager()
 {
-    curl_multi_cleanup(m_curlMultiHandle);
+
 }
 
 ResourceHandleManager* ResourceHandleManager::sharedInstance()
@@ -113,10 +112,8 @@
     // Retry 'select' if it was interrupted by a process signal.
     int rc = 0;
     do {
-        FD_ZERO(&fdread);
-        FD_ZERO(&fdwrite);
-        FD_ZERO(&fdexcep);
-        curl_multi_fdset(m_curlMultiHandle, &fdread, &fdwrite, &fdexcep, &maxfd);
+        m_curlMultiHandle.getFdSet(fdread, fdwrite, fdexcep, maxfd);
+
         // When the 3 file descriptors are empty, winsock will return -1
         // and bail out, stopping the file download. So make sure we
         // have valid file descriptors before calling select.
@@ -132,13 +129,13 @@
     }
 
     int runningHandles = 0;
-    while (curl_multi_perform(m_curlMultiHandle, &runningHandles) == CURLM_CALL_MULTI_PERFORM) { }
+    while (m_curlMultiHandle.perform(runningHandles) == CURLM_CALL_MULTI_PERFORM) { }
 
     // check the curl messages indicating completed transfers
     // and free their resources
     while (true) {
-        int messagesInQueue;
-        CURLMsg* msg = curl_multi_info_read(m_curlMultiHandle, &messagesInQueue);
+        int messagesInQueue = 0;
+        CURLMsg* msg = m_curlMultiHandle.readInfo(messagesInQueue);
         if (!msg)
             break;
 
@@ -152,7 +149,6 @@
         if (!job)
             continue;
         ResourceHandleInternal* d = job->getInternal();
-        ASSERT(d->m_handle == handle);
 
         if (d->m_cancelled) {
             removeFromCurl(job);
@@ -175,13 +171,12 @@
 void ResourceHandleManager::removeFromCurl(ResourceHandle* job)
 {
     ResourceHandleInternal* d = job->getInternal();
-    ASSERT(d->m_handle);
-    if (!d->m_handle)
+    ASSERT(d->m_curlHandle.handle());
+    if (!d->m_curlHandle.handle())
         return;
     m_runningJobs--;
-    curl_multi_remove_handle(m_curlMultiHandle, d->m_handle);
-    curl_easy_cleanup(d->m_handle);
-    d->m_handle = 0;
+
+    m_curlMultiHandle.removeHandle(d->m_curlHandle.handle());
     job->deref();
 }
 
@@ -227,7 +222,9 @@
     job->initialize();
 
     m_runningJobs++;
-    CURLMcode ret = curl_multi_add_handle(m_curlMultiHandle, job->getInternal()->m_handle);
+
+    CURLMcode ret = m_curlMultiHandle.addHandle(job->getInternal()->m_curlHandle.handle());
+
     // don't call perform, because events must be async
     // timeout will occur and do curl_multi_perform
     if (ret && ret != CURLM_CALL_MULTI_PERFORM) {

Modified: trunk/Source/WebCore/platform/network/curl/ResourceHandleManager.h (219278 => 219279)


--- trunk/Source/WebCore/platform/network/curl/ResourceHandleManager.h	2017-07-08 23:59:04 UTC (rev 219278)
+++ trunk/Source/WebCore/platform/network/curl/ResourceHandleManager.h	2017-07-09 02:58:36 UTC (rev 219279)
@@ -28,6 +28,7 @@
 #ifndef ResourceHandleManager_h
 #define ResourceHandleManager_h
 
+#include "CurlContext.h"
 #include "Frame.h"
 #include "Timer.h"
 #include "ResourceHandleClient.h"
@@ -37,7 +38,6 @@
 #include <windows.h>
 #endif
 
-#include <curl/curl.h>
 #include <wtf/Vector.h>
 #include <wtf/text/CString.h>
 #include <wtf/text/WTFString.h>
@@ -60,9 +60,10 @@
     bool startScheduledJobs();
 
     Timer m_downloadTimer;
-    CURLM* m_curlMultiHandle;
     Vector<ResourceHandle*> m_resourceHandleList;
     int m_runningJobs;
+
+    CurlMultiHandle m_curlMultiHandle;
 };
 
 }

Modified: trunk/Source/WebCore/platform/network/curl/SSLHandle.cpp (219278 => 219279)


--- trunk/Source/WebCore/platform/network/curl/SSLHandle.cpp	2017-07-08 23:59:04 UTC (rev 219278)
+++ trunk/Source/WebCore/platform/network/curl/SSLHandle.cpp	2017-07-09 02:58:36 UTC (rev 219279)
@@ -75,9 +75,10 @@
 
     ResourceHandleInternal* d = handle->getInternal();
     clientCertificate clientInfo = it->value;
-    curl_easy_setopt(d->m_handle, CURLOPT_SSLCERT, std::get<0>(clientInfo).utf8().data());
-    curl_easy_setopt(d->m_handle, CURLOPT_SSLCERTTYPE, "P12");
-    curl_easy_setopt(d->m_handle, CURLOPT_SSLCERTPASSWD, std::get<1>(clientInfo).utf8().data());
+
+    d->m_curlHandle.setSslCert(std::get<0>(clientInfo).utf8().data());
+    d->m_curlHandle.setSslCertType("P12");
+    d->m_curlHandle.setSslKeyPassword(std::get<1>(clientInfo).utf8().data());
 }
 
 bool sslIgnoreHTTPSCertificate(const String& host, const ListHashSet<String>& certificates)
@@ -221,7 +222,7 @@
     if (ok) {
         // if the host and the certificate are stored for the current handle that means is enabled,
         // so don't need to curl verifies the authenticity of the peer's certificate
-        curl_easy_setopt(d->m_handle, CURLOPT_SSL_VERIFYPEER, false);
+        d->m_curlHandle.setSslVerifyPeer(CurlHandle::VerifyPeerDisable);
     }
     return ok;
 }
@@ -236,8 +237,8 @@
 void setSSLVerifyOptions(ResourceHandle* handle)
 {
     ResourceHandleInternal* d = handle->getInternal();
-    curl_easy_setopt(d->m_handle, CURLOPT_SSL_CTX_DATA, handle);
-    curl_easy_setopt(d->m_handle, CURLOPT_SSL_CTX_FUNCTION, sslctxfun);
+
+    d->m_curlHandle.setSslCtxCallbackFunction(sslctxfun, handle);
 }
 
 }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to