Diff
Modified: trunk/Source/WebCore/ChangeLog (218636 => 218637)
--- trunk/Source/WebCore/ChangeLog 2017-06-21 16:25:16 UTC (rev 218636)
+++ trunk/Source/WebCore/ChangeLog 2017-06-21 16:48:43 UTC (rev 218637)
@@ -1,3 +1,80 @@
+2017-06-21 Basuke Suzuki <[email protected]>
+
+ [Curl] Extract CurlDownloadManager as shared background task handler
+ https://bugs.webkit.org/show_bug.cgi?id=173557
+
+ Curl resource handling should be shared by other part of Curl
+ network stack. CurlDownloadManager is extracted as stand alone
+ CurlManager singleton class to be ready for others
+ (i.e. ResourceHandle).
+
+ Reviewed by Alex Christensen.
+
+ * PlatformWinCairo.cmake:
+ * platform/network/curl/CookieJarCurl.cpp:
+ (WebCore::setCookiesFromDOM):
+ (WebCore::cookiesForSession):
+ * platform/network/curl/CurlDownload.cpp:
+ (WebCore::CurlDownload::init):
+ (WebCore::CurlDownload::start):
+ (WebCore::CurlDownload::cancel):
+ (WebCore::CurlDownload::didReceiveHeader):
+ (WebCore::CurlDownload::handleCurlMsg):
+ (WebCore::CurlDownloadManager::CurlDownloadManager): Deleted.
+ (WebCore::CurlDownloadManager::~CurlDownloadManager): Deleted.
+ (WebCore::CurlDownloadManager::add): Deleted.
+ (WebCore::CurlDownloadManager::remove): Deleted.
+ (WebCore::CurlDownloadManager::getActiveDownloadCount): Deleted.
+ (WebCore::CurlDownloadManager::getPendingDownloadCount): Deleted.
+ (WebCore::CurlDownloadManager::startThreadIfNeeded): Deleted.
+ (WebCore::CurlDownloadManager::stopThread): Deleted.
+ (WebCore::CurlDownloadManager::stopThreadIfIdle): Deleted.
+ (WebCore::CurlDownloadManager::updateHandleList): Deleted.
+ (WebCore::CurlDownloadManager::addToCurl): Deleted.
+ (WebCore::CurlDownloadManager::removeFromCurl): Deleted.
+ (WebCore::CurlDownloadManager::downloadThread): Deleted.
+ * platform/network/curl/CurlDownload.h:
+ (WebCore::CurlDownloadManager::getMultiHandle): Deleted.
+ (WebCore::CurlDownloadManager::runThread): Deleted.
+ (WebCore::CurlDownloadManager::setRunThread): Deleted.
+ * platform/network/curl/CurlManager.cpp: Added.
+ (WebCore::CurlManager::CurlManager):
+ (WebCore::CurlManager::~CurlManager):
+ (WebCore::CurlManager::add):
+ (WebCore::CurlManager::remove):
+ (WebCore::CurlManager::getActiveCount):
+ (WebCore::CurlManager::getPendingCount):
+ (WebCore::CurlManager::startThreadIfNeeded):
+ (WebCore::CurlManager::stopThread):
+ (WebCore::CurlManager::stopThreadIfIdle):
+ (WebCore::CurlManager::updateHandleList):
+ (WebCore::CurlManager::addToCurl):
+ (WebCore::CurlManager::removeFromCurl):
+ (WebCore::CurlManager::workerThread):
+ (WebCore::CurlUtils::getEffectiveURL):
+ (WebCore::CurlSharedResources::mutexFor):
+ (WebCore::CurlSharedResources::lock):
+ (WebCore::CurlSharedResources::unlock):
+ * platform/network/curl/CurlManager.h: Added.
+ (WebCore::CurlManager::singleton):
+ (WebCore::CurlManager::getCurlShareHandle):
+ (WebCore::CurlManager::getMultiHandle):
+ (WebCore::CurlManager::runThread):
+ (WebCore::CurlManager::setRunThread):
+ * platform/network/curl/ResourceHandleManager.cpp:
+ (WebCore::ResourceHandleManager::ResourceHandleManager):
+ (WebCore::ResourceHandleManager::~ResourceHandleManager):
+ (WebCore::handleLocalReceiveResponse):
+ (WebCore::getProtectionSpace):
+ (WebCore::headerCallback):
+ (WebCore::ResourceHandleManager::downloadTimerCallback):
+ (WebCore::getCurlEffectiveURL): Deleted.
+ (WebCore::sharedResourceMutex): Deleted.
+ (WebCore::curl_lock_callback): Deleted.
+ (WebCore::curl_unlock_callback): Deleted.
+ (WebCore::ResourceHandleManager::getCurlShareHandle): Deleted.
+ * platform/network/curl/ResourceHandleManager.h:
+
2017-06-21 Jeremy Jones <[email protected]>
Include audio/vnd.wave as a valid mime-type for wav files.
Modified: trunk/Source/WebCore/PlatformWinCairo.cmake (218636 => 218637)
--- trunk/Source/WebCore/PlatformWinCairo.cmake 2017-06-21 16:25:16 UTC (rev 218636)
+++ trunk/Source/WebCore/PlatformWinCairo.cmake 2017-06-21 16:48:43 UTC (rev 218637)
@@ -34,6 +34,7 @@
platform/network/curl/CurlCacheEntry.cpp
platform/network/curl/CurlCacheManager.cpp
platform/network/curl/CurlDownload.cpp
+ platform/network/curl/CurlManager.cpp
platform/network/curl/DNSCurl.cpp
platform/network/curl/FormDataStreamCurl.cpp
platform/network/curl/MultipartHandle.cpp
Modified: trunk/Source/WebCore/platform/network/curl/CookieJarCurl.cpp (218636 => 218637)
--- trunk/Source/WebCore/platform/network/curl/CookieJarCurl.cpp 2017-06-21 16:25:16 UTC (rev 218636)
+++ trunk/Source/WebCore/platform/network/curl/CookieJarCurl.cpp 2017-06-21 16:48:43 UTC (rev 218637)
@@ -1,4 +1,6 @@
/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -20,9 +22,10 @@
#if USE(CURL)
#include "Cookie.h"
+#include "CurlManager.h"
#include "NotImplemented.h"
+#include "ResourceHandleManager.h"
#include "URL.h"
-#include "ResourceHandleManager.h"
#include <wtf/DateMath.h>
#include <wtf/HashMap.h>
@@ -246,7 +249,7 @@
return;
const char* cookieJarFileName = ResourceHandleManager::sharedInstance()->getCookieJarFileName();
- CURLSH* curlsh = ResourceHandleManager::sharedInstance()->getCurlShareHandle();
+ CURLSH* curlsh = CurlManager::singleton().getCurlShareHandle();
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookieJarFileName);
curl_easy_setopt(curl, CURLOPT_SHARE, curlsh);
@@ -275,7 +278,7 @@
if (!curl)
return cookies;
- CURLSH* curlsh = ResourceHandleManager::sharedInstance()->getCurlShareHandle();
+ CURLSH* curlsh = CurlManager::singleton().getCurlShareHandle();
curl_easy_setopt(curl, CURLOPT_SHARE, curlsh);
Modified: trunk/Source/WebCore/platform/network/curl/CurlDownload.cpp (218636 => 218637)
--- trunk/Source/WebCore/platform/network/curl/CurlDownload.cpp 2017-06-21 16:25:16 UTC (rev 218636)
+++ trunk/Source/WebCore/platform/network/curl/CurlDownload.cpp 2017-06-21 16:48:43 UTC (rev 218637)
@@ -31,7 +31,6 @@
#include "HTTPHeaderNames.h"
#include "HTTPParsers.h"
-#include "ResourceHandleManager.h"
#include "ResourceRequest.h"
#include <wtf/MainThread.h>
#include <wtf/text/CString.h>
@@ -40,197 +39,8 @@
namespace WebCore {
-// CurlDownloadManager -------------------------------------------------------------------
-
-CurlDownloadManager::CurlDownloadManager()
-{
- curl_global_init(CURL_GLOBAL_ALL);
- m_curlMultiHandle = curl_multi_init();
-}
-
-CurlDownloadManager::~CurlDownloadManager()
-{
- stopThread();
- curl_multi_cleanup(m_curlMultiHandle);
- curl_global_cleanup();
-}
-
-bool CurlDownloadManager::add(CURL* curlHandle)
-{
- {
- LockHolder locker(m_mutex);
- m_pendingHandleList.append(curlHandle);
- }
-
- startThreadIfNeeded();
-
- return true;
-}
-
-bool CurlDownloadManager::remove(CURL* curlHandle)
-{
- LockHolder locker(m_mutex);
-
- m_removedHandleList.append(curlHandle);
-
- return true;
-}
-
-int CurlDownloadManager::getActiveDownloadCount() const
-{
- LockHolder locker(m_mutex);
- return m_activeHandleList.size();
-}
-
-int CurlDownloadManager::getPendingDownloadCount() const
-{
- LockHolder locker(m_mutex);
- return m_pendingHandleList.size();
-}
-
-void CurlDownloadManager::startThreadIfNeeded()
-{
- if (!runThread()) {
- if (m_thread)
- m_thread->waitForCompletion();
- setRunThread(true);
- m_thread = Thread::create(downloadThread, this, "downloadThread");
- }
-}
-
-void CurlDownloadManager::stopThread()
-{
- setRunThread(false);
-
- if (m_thread) {
- m_thread->waitForCompletion();
- m_thread = nullptr;
- }
-}
-
-void CurlDownloadManager::stopThreadIfIdle()
-{
- if (!getActiveDownloadCount() && !getPendingDownloadCount())
- setRunThread(false);
-}
-
-void CurlDownloadManager::updateHandleList()
-{
- LockHolder locker(m_mutex);
-
- // Remove curl easy handles from multi list
- int size = m_removedHandleList.size();
- for (int i = 0; i < size; i++) {
- removeFromCurl(m_removedHandleList[0]);
- m_removedHandleList.remove(0);
- }
-
- // Add pending curl easy handles to multi list
- size = m_pendingHandleList.size();
- for (int i = 0; i < size; i++) {
- addToCurl(m_pendingHandleList[0]);
- m_pendingHandleList.remove(0);
- }
-}
-
-bool CurlDownloadManager::addToCurl(CURL* curlHandle)
-{
- CURLMcode retval = curl_multi_add_handle(m_curlMultiHandle, curlHandle);
- if (retval == CURLM_OK) {
- m_activeHandleList.append(curlHandle);
- return true;
- }
- return false;
-}
-
-bool CurlDownloadManager::removeFromCurl(CURL* curlHandle)
-{
- int handlePos = m_activeHandleList.find(curlHandle);
-
- if (handlePos < 0)
- return true;
-
- CURLMcode retval = curl_multi_remove_handle(m_curlMultiHandle, curlHandle);
- if (retval == CURLM_OK) {
- m_activeHandleList.remove(handlePos);
- curl_easy_cleanup(curlHandle);
- return true;
- }
- return false;
-}
-
-void CurlDownloadManager::downloadThread(void* data)
-{
- CurlDownloadManager* downloadManager = reinterpret_cast<CurlDownloadManager*>(data);
-
- while (downloadManager->runThread()) {
-
- downloadManager->updateHandleList();
-
- // Retry 'select' if it was interrupted by a process signal.
- int rc = 0;
- do {
- fd_set fdread;
- fd_set fdwrite;
- fd_set fdexcep;
-
- int maxfd = 0;
-
- const int selectTimeoutMS = 5;
-
- struct timeval timeout;
- timeout.tv_sec = 0;
- timeout.tv_usec = selectTimeoutMS * 1000; // select waits microseconds
-
- FD_ZERO(&fdread);
- FD_ZERO(&fdwrite);
- FD_ZERO(&fdexcep);
- curl_multi_fdset(downloadManager->getMultiHandle(), &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.
- if (maxfd >= 0)
- rc = ::select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
- } while (rc == -1 && errno == EINTR);
-
- int activeDownloadCount = 0;
- while (curl_multi_perform(downloadManager->getMultiHandle(), &activeDownloadCount) == CURLM_CALL_MULTI_PERFORM) { }
-
- int messagesInQueue = 0;
- CURLMsg* msg = curl_multi_info_read(downloadManager->getMultiHandle(), &messagesInQueue);
-
- if (!msg)
- continue;
-
- CurlDownload* download = 0;
- CURLcode err = curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &download);
- UNUSED_PARAM(err);
-
- if (msg->msg == CURLMSG_DONE) {
- if (download) {
- if (msg->data.result == CURLE_OK) {
- callOnMainThread([download] {
- download->didFinish();
- download->deref(); // This matches the ref() in CurlDownload::start().
- });
- } else {
- callOnMainThread([download] {
- download->didFail();
- download->deref(); // This matches the ref() in CurlDownload::start().
- });
- }
- }
- downloadManager->removeFromCurl(msg->easy_handle);
- }
-
- downloadManager->stopThreadIfIdle();
- }
-}
-
// CurlDownload --------------------------------------------------------------------------
-CurlDownloadManager CurlDownload::m_downloadManager;
-
CurlDownload::CurlDownload() = default;
CurlDownload::~CurlDownload()
@@ -275,7 +85,7 @@
if (certPath)
curl_easy_setopt(m_curlHandle, CURLOPT_CAINFO, certPath);
- CURLSH* curlsh = ResourceHandleManager::sharedInstance()->getCurlShareHandle();
+ CURLSH* curlsh = CurlManager::singleton().getCurlShareHandle();
if (curlsh)
curl_easy_setopt(m_curlHandle, CURLOPT_SHARE, curlsh);
@@ -297,12 +107,12 @@
bool CurlDownload::start()
{
ref(); // CurlDownloadManager::downloadThread will call deref when the download has finished.
- return m_downloadManager.add(m_curlHandle);
+ return CurlManager::singleton().add(m_curlHandle);
}
bool CurlDownload::cancel()
{
- return m_downloadManager.remove(m_curlHandle);
+ return CurlManager::singleton().remove(m_curlHandle);
}
String CurlDownload::getTempPath() const
@@ -393,7 +203,7 @@
UNUSED_PARAM(err);
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)));
@@ -506,6 +316,29 @@
download->didReceiveResponse();
}
+CurlJobAction CurlDownload::handleCurlMsg(CURLMsg* msg)
+{
+ switch (msg->msg) {
+ case CURLMSG_DONE: {
+ if (msg->data.result == CURLE_OK) {
+ callOnMainThread([this] {
+ didFinish();
+ deref(); // This matches the ref() in CurlDownload::start().
+ });
+ } else {
+ callOnMainThread([this] {
+ didFail();
+ deref(); // This matches the ref() in CurlDownload::start().
+ });
+ }
+ return CurlJobAction::Finished;
+ }
+ default: {
+ return CurlJobAction::None;
+ }
+ }
}
+}
+
#endif
Modified: trunk/Source/WebCore/platform/network/curl/CurlDownload.h (218636 => 218637)
--- trunk/Source/WebCore/platform/network/curl/CurlDownload.h 2017-06-21 16:25:16 UTC (rev 218636)
+++ trunk/Source/WebCore/platform/network/curl/CurlDownload.h 2017-06-21 16:48:43 UTC (rev 218637)
@@ -36,47 +36,10 @@
#include <winsock2.h>
#endif
-#include <curl/curl.h>
+#include "CurlManager.h"
namespace WebCore {
-class CurlDownloadManager {
-public:
- CurlDownloadManager();
- ~CurlDownloadManager();
-
- bool add(CURL* curlHandle);
- bool remove(CURL* curlHandle);
-
- int getActiveDownloadCount() const;
- int getPendingDownloadCount() const;
-
-private:
- void startThreadIfNeeded();
- void stopThread();
- void stopThreadIfIdle();
-
- 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; }
-
- bool addToCurl(CURL* curlHandle);
- bool removeFromCurl(CURL* curlHandle);
-
- static void downloadThread(void* data);
-
- RefPtr<Thread> m_thread;
- CURLM* m_curlMultiHandle { nullptr };
- Vector<CURL*> m_pendingHandleList;
- Vector<CURL*> m_activeHandleList;
- Vector<CURL*> m_removedHandleList;
- mutable Lock m_mutex;
- bool m_runThread { false };
-};
-
class CurlDownloadListener {
public:
virtual void didReceiveResponse() { }
@@ -85,7 +48,7 @@
virtual void didFail() { }
};
-class CurlDownload : public ThreadSafeRefCounted<CurlDownload> {
+class CurlDownload : public ThreadSafeRefCounted<CurlDownload>, public CurlJob {
public:
CurlDownload();
~CurlDownload();
@@ -107,6 +70,8 @@
void setDestination(const String& destination) { m_destination = destination; }
+ virtual CurlJobAction handleCurlMsg(CURLMsg*);
+
private:
void closeFile();
void moveFileToDestination();
@@ -142,10 +107,6 @@
bool m_deletesFileUponFailure { false };
mutable Lock m_mutex;
CurlDownloadListener* m_listener { nullptr };
-
- static CurlDownloadManager m_downloadManager;
-
- friend class CurlDownloadManager;
};
}
Added: trunk/Source/WebCore/platform/network/curl/CurlManager.cpp (0 => 218637)
--- trunk/Source/WebCore/platform/network/curl/CurlManager.cpp (rev 0)
+++ trunk/Source/WebCore/platform/network/curl/CurlManager.cpp 2017-06-21 16:48:43 UTC (rev 218637)
@@ -0,0 +1,288 @@
+/*
+ * 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(CURL)
+#include "CurlManager.h"
+
+#include <wtf/MainThread.h>
+#include <wtf/text/CString.h>
+
+using namespace WebCore;
+
+namespace WebCore {
+
+class CurlSharedResources {
+public:
+ static void lock(CURL*, curl_lock_data, curl_lock_access, void*);
+ static void unlock(CURL*, curl_lock_data, void*);
+
+private:
+ static Lock* mutexFor(curl_lock_data);
+};
+
+// CurlDownloadManager -------------------------------------------------------------------
+
+CurlManager::CurlManager()
+{
+ curl_global_init(CURL_GLOBAL_ALL);
+ m_curlMultiHandle = curl_multi_init();
+ 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, CurlSharedResources::lock);
+ curl_share_setopt(m_curlShareHandle, CURLSHOPT_UNLOCKFUNC, CurlSharedResources::unlock);
+}
+
+CurlManager::~CurlManager()
+{
+ stopThread();
+ curl_multi_cleanup(m_curlMultiHandle);
+ curl_share_cleanup(m_curlShareHandle);
+ curl_global_cleanup();
+}
+
+bool CurlManager::add(CURL* curlHandle)
+{
+ ASSERT(isMainThread());
+
+ {
+ LockHolder locker(m_mutex);
+ m_pendingHandleList.append(curlHandle);
+ }
+
+ startThreadIfNeeded();
+
+ return true;
+}
+
+bool CurlManager::remove(CURL* curlHandle)
+{
+ LockHolder locker(m_mutex);
+
+ m_removedHandleList.append(curlHandle);
+
+ return true;
+}
+
+int CurlManager::getActiveCount() const
+{
+ LockHolder locker(m_mutex);
+ return m_activeHandleList.size();
+}
+
+int CurlManager::getPendingCount() const
+{
+ LockHolder locker(m_mutex);
+ return m_pendingHandleList.size();
+}
+
+void CurlManager::startThreadIfNeeded()
+{
+ ASSERT(isMainThread());
+
+ if (!runThread()) {
+ if (m_thread)
+ m_thread->waitForCompletion();
+ setRunThread(true);
+ m_thread = Thread::create(workerThread, this, "curlThread");
+ }
+}
+
+void CurlManager::stopThread()
+{
+ ASSERT(isMainThread());
+
+ setRunThread(false);
+
+ if (m_thread) {
+ m_thread->waitForCompletion();
+ m_thread = nullptr;
+ }
+}
+
+void CurlManager::stopThreadIfIdle()
+{
+ if (!getActiveCount() && !getPendingCount())
+ setRunThread(false);
+}
+
+void CurlManager::updateHandleList()
+{
+ LockHolder locker(m_mutex);
+
+ // Remove curl easy handles from multi list
+ int size = m_removedHandleList.size();
+ for (int i = 0; i < size; i++) {
+ removeFromCurl(m_removedHandleList[0]);
+ m_removedHandleList.remove(0);
+ }
+
+ // Add pending curl easy handles to multi list
+ size = m_pendingHandleList.size();
+ for (int i = 0; i < size; i++) {
+ addToCurl(m_pendingHandleList[0]);
+ m_pendingHandleList.remove(0);
+ }
+}
+
+bool CurlManager::addToCurl(CURL* curlHandle)
+{
+ CURLMcode retval = curl_multi_add_handle(m_curlMultiHandle, curlHandle);
+ if (retval == CURLM_OK) {
+ m_activeHandleList.append(curlHandle);
+ return true;
+ }
+ return false;
+}
+
+bool CurlManager::removeFromCurl(CURL* curlHandle)
+{
+ int handlePos = m_activeHandleList.find(curlHandle);
+
+ if (handlePos < 0)
+ return true;
+
+ CURLMcode retval = curl_multi_remove_handle(m_curlMultiHandle, curlHandle);
+ if (retval == CURLM_OK) {
+ m_activeHandleList.remove(handlePos);
+ curl_easy_cleanup(curlHandle);
+ return true;
+ }
+ return false;
+}
+
+void CurlManager::workerThread(void* data)
+{
+ ASSERT(!isMainThread());
+
+ CurlManager* manager = reinterpret_cast<CurlManager*>(data);
+
+ while (manager->runThread()) {
+
+ manager->updateHandleList();
+
+ // Retry 'select' if it was interrupted by a process signal.
+ int rc = 0;
+ do {
+ fd_set fdread;
+ fd_set fdwrite;
+ fd_set fdexcep;
+
+ int maxfd = 0;
+
+ const int selectTimeoutMS = 5;
+
+ struct timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = selectTimeoutMS * 1000; // select waits microseconds
+
+ FD_ZERO(&fdread);
+ FD_ZERO(&fdwrite);
+ FD_ZERO(&fdexcep);
+ curl_multi_fdset(manager->getMultiHandle(), &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.
+ if (maxfd >= 0)
+ rc = ::select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
+ } while (rc == -1 && errno == EINTR);
+
+ int activeCount = 0;
+ while (curl_multi_perform(manager->getMultiHandle(), &activeCount) == CURLM_CALL_MULTI_PERFORM) { }
+
+ int messagesInQueue = 0;
+ CURLMsg* msg = curl_multi_info_read(manager->getMultiHandle(), &messagesInQueue);
+
+ if (!msg)
+ continue;
+
+
+ CurlJob* job = nullptr;
+ CURLcode err = curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &job);
+ UNUSED_PARAM(err);
+ ASSERT(job);
+
+ CurlJobAction action = ""
+
+ if (action == CurlJobAction::Finished)
+ manager->removeFromCurl(msg->easy_handle);
+
+ manager->stopThreadIfIdle();
+ }
+}
+
+// CURL Utilities
+
+URL CurlUtils::getEffectiveURL(CURL* handle)
+{
+ const char* url;
+ CURLcode err = curl_easy_getinfo(handle, CURLINFO_EFFECTIVE_URL, &url);
+ if (CURLE_OK != err)
+ return URL();
+ return URL(URL(), url);
+}
+
+// Shared Resource management =======================
+
+Lock* CurlSharedResources::mutexFor(curl_lock_data data)
+{
+ DEPRECATED_DEFINE_STATIC_LOCAL(Lock, cookieMutex, ());
+ DEPRECATED_DEFINE_STATIC_LOCAL(Lock, dnsMutex, ());
+ DEPRECATED_DEFINE_STATIC_LOCAL(Lock, shareMutex, ());
+
+ switch (data) {
+ case CURL_LOCK_DATA_COOKIE:
+ return &cookieMutex;
+ case CURL_LOCK_DATA_DNS:
+ return &dnsMutex;
+ case CURL_LOCK_DATA_SHARE:
+ return &shareMutex;
+ default:
+ ASSERT_NOT_REACHED();
+ return nullptr;
+ }
+}
+
+// libcurl does not implement its own thread synchronization primitives.
+// these two functions provide mutexes for cookies, and for the global DNS
+// cache.
+void CurlSharedResources::lock(CURL* /* handle */, curl_lock_data data, curl_lock_access /* access */, void* /* userPtr */)
+{
+ if (Lock* mutex = CurlSharedResources::mutexFor(data))
+ mutex->lock();
+}
+
+void CurlSharedResources::unlock(CURL* /* handle */, curl_lock_data data, void* /* userPtr */)
+{
+ if (Lock* mutex = CurlSharedResources::mutexFor(data))
+ mutex->unlock();
+}
+
+}
+
+#endif
Added: trunk/Source/WebCore/platform/network/curl/CurlManager.h (0 => 218637)
--- trunk/Source/WebCore/platform/network/curl/CurlManager.h (rev 0)
+++ trunk/Source/WebCore/platform/network/curl/CurlManager.h 2017-06-21 16:48:43 UTC (rev 218637)
@@ -0,0 +1,107 @@
+/*
+ * 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <curl/curl.h>
+#include <wtf/Lock.h>
+#include <wtf/Threading.h>
+
+#if PLATFORM(WIN)
+#include <windows.h>
+#include <winsock2.h>
+#endif
+
+#include "URL.h"
+
+namespace WebCore {
+
+enum class CurlJobAction { None, Finished };
+
+class CurlJob {
+public:
+ virtual CurlJobAction handleCurlMsg(CURLMsg*) = 0;
+};
+
+class CurlManager {
+public:
+ static CurlManager& singleton()
+ {
+ // Since it's a static variable, if the class has already been created,
+ // It won't be created again.
+ // And it **is** thread-safe in C++11.
+
+ static CurlManager shared;
+ return shared;
+ }
+
+ CurlManager();
+ virtual ~CurlManager();
+
+ bool add(CURL* curlHandle);
+ bool remove(CURL* curlHandle);
+
+ int getActiveCount() const;
+ int getPendingCount() const;
+
+ CURLSH* getCurlShareHandle() const { return m_curlShareHandle; }
+
+private:
+ void startThreadIfNeeded();
+ void stopThread();
+ void stopThreadIfIdle();
+
+ 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; }
+
+ bool addToCurl(CURL* curlHandle);
+ bool removeFromCurl(CURL* curlHandle);
+
+ static void workerThread(void* data);
+
+ RefPtr<Thread> m_thread;
+ CURLM* m_curlMultiHandle { nullptr };
+ Vector<CURL*> m_pendingHandleList;
+ Vector<CURL*> m_activeHandleList;
+ Vector<CURL*> m_removedHandleList;
+ mutable Lock m_mutex;
+ bool m_runThread { false };
+
+ CURLSH* m_curlShareHandle { nullptr };
+
+ friend class CurlJob;
+};
+
+class CurlUtils {
+public:
+ static URL getEffectiveURL(CURL* handle);
+};
+
+}
Modified: trunk/Source/WebCore/platform/network/curl/ResourceHandleManager.cpp (218636 => 218637)
--- trunk/Source/WebCore/platform/network/curl/ResourceHandleManager.cpp 2017-06-21 16:25:16 UTC (rev 218636)
+++ trunk/Source/WebCore/platform/network/curl/ResourceHandleManager.cpp 2017-06-21 16:48:43 UTC (rev 218637)
@@ -42,6 +42,7 @@
#include "CredentialStorage.h"
#include "CurlCacheManager.h"
+#include "CurlManager.h"
#include "HTTPHeaderNames.h"
#include "HTTPParsers.h"
#include "MIMETypeRegistry.h"
@@ -87,15 +88,6 @@
const int maxRunningJobs = 128;
const char* const errorDomainCurl = "CurlErrorDomain";
-URL getCurlEffectiveURL(CURL* handle)
-{
- const char* url;
- CURLcode err = curl_easy_getinfo(handle, CURLINFO_EFFECTIVE_URL, &url);
- if (CURLE_OK != err)
- return URL();
- return URL(URL(), url);
-}
-
static const bool ignoreSSLErrors = getenv("WEBKIT_IGNORE_SSL_ERRORS");
static CString certificatePath()
@@ -151,25 +143,6 @@
#endif
}
-static Lock* sharedResourceMutex(curl_lock_data data)
-{
- DEPRECATED_DEFINE_STATIC_LOCAL(Lock, cookieMutex, ());
- DEPRECATED_DEFINE_STATIC_LOCAL(Lock, dnsMutex, ());
- DEPRECATED_DEFINE_STATIC_LOCAL(Lock, shareMutex, ());
-
- switch (data) {
- case CURL_LOCK_DATA_COOKIE:
- return &cookieMutex;
- case CURL_LOCK_DATA_DNS:
- return &dnsMutex;
- case CURL_LOCK_DATA_SHARE:
- return &shareMutex;
- default:
- ASSERT_NOT_REACHED();
- return NULL;
- }
-}
-
#if ENABLE(WEB_TIMING)
static void calculateWebTimingInformations(ResourceHandleInternal* d)
{
@@ -197,21 +170,6 @@
}
#endif
-// libcurl does not implement its own thread synchronization primitives.
-// these two functions provide mutexes for cookies, and for the global DNS
-// cache.
-static void curl_lock_callback(CURL* /* handle */, curl_lock_data data, curl_lock_access /* access */, void* /* userPtr */)
-{
- if (Lock* mutex = sharedResourceMutex(data))
- mutex->lock();
-}
-
-static void curl_unlock_callback(CURL* /* handle */, curl_lock_data data, void* /* userPtr */)
-{
- if (Lock* mutex = sharedResourceMutex(data))
- mutex->unlock();
-}
-
inline static bool isHttpInfo(int statusCode)
{
return 100 <= statusCode && statusCode < 200;
@@ -235,20 +193,17 @@
ResourceHandleManager::ResourceHandleManager()
: m_downloadTimer(*this, &ResourceHandleManager::downloadTimerCallback)
, m_cookieJarFileName(cookieJarPath())
- , m_certificatePath (certificatePath())
+ , m_certificatePath(certificatePath())
, m_runningJobs(0)
#ifndef NDEBUG
, m_logFile(nullptr)
#endif
{
- curl_global_init(CURL_GLOBAL_ALL);
+ CURLSH* h = CurlManager::singleton().getCurlShareHandle();
+ m_curlShareHandle = h;
m_curlMultiHandle = curl_multi_init();
- 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, curl_lock_callback);
- curl_share_setopt(m_curlShareHandle, CURLSHOPT_UNLOCKFUNC, curl_unlock_callback);
+
initCookieSession();
#ifndef NDEBUG
@@ -261,10 +216,8 @@
ResourceHandleManager::~ResourceHandleManager()
{
curl_multi_cleanup(m_curlMultiHandle);
- curl_share_cleanup(m_curlShareHandle);
if (m_cookieJarFileName)
fastFree(m_cookieJarFileName);
- curl_global_cleanup();
#ifndef NDEBUG
if (m_logFile)
@@ -272,11 +225,6 @@
#endif
}
-CURLSH* ResourceHandleManager::getCurlShareHandle() const
-{
- return m_curlShareHandle;
-}
-
void ResourceHandleManager::setCookieJarFileName(const char* cookieJarFileName)
{
m_cookieJarFileName = fastStrDup(cookieJarFileName);
@@ -302,7 +250,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())
@@ -413,7 +361,7 @@
if (err != CURLE_OK)
return false;
- URL url = ""
+ URL url = ""
if (!url.isValid())
return false;
@@ -502,7 +450,7 @@
curl_easy_getinfo(h, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &contentLength);
d->m_response.setExpectedContentLength(static_cast<long long int>(contentLength));
- d->m_response.setURL(getCurlEffectiveURL(h));
+ d->m_response.setURL(CurlUtils::getEffectiveURL(h));
d->m_response.setHTTPStatusCode(httpCode);
d->m_response.setMimeType(extractMIMETypeFromMediaType(d->m_response.httpHeaderField(HTTPHeaderName::ContentType)).convertToASCIILowercase());
@@ -709,7 +657,7 @@
CurlCacheManager::getInstance().didFinishLoading(*job);
}
} 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.h (218636 => 218637)
--- trunk/Source/WebCore/platform/network/curl/ResourceHandleManager.h 2017-06-21 16:25:16 UTC (rev 218636)
+++ trunk/Source/WebCore/platform/network/curl/ResourceHandleManager.h 2017-06-21 16:48:43 UTC (rev 218637)
@@ -57,8 +57,6 @@
void add(ResourceHandle*);
void cancel(ResourceHandle*);
- CURLSH* getCurlShareHandle() const;
-
void setCookieJarFileName(const char* cookieJarFileName);
const char* getCookieJarFileName() const;
@@ -100,8 +98,6 @@
#endif
};
-URL getCurlEffectiveURL(CURL*);
-
}
#endif