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);
}
}