Changeset 218637 in webkit
- Timestamp:
- Jun 21, 2017 9:48:43 AM (7 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 2 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r218634 r218637 1 2017-06-21 Basuke Suzuki <Basuke.Suzuki@sony.com> 2 3 [Curl] Extract CurlDownloadManager as shared background task handler 4 https://bugs.webkit.org/show_bug.cgi?id=173557 5 6 Curl resource handling should be shared by other part of Curl 7 network stack. CurlDownloadManager is extracted as stand alone 8 CurlManager singleton class to be ready for others 9 (i.e. ResourceHandle). 10 11 Reviewed by Alex Christensen. 12 13 * PlatformWinCairo.cmake: 14 * platform/network/curl/CookieJarCurl.cpp: 15 (WebCore::setCookiesFromDOM): 16 (WebCore::cookiesForSession): 17 * platform/network/curl/CurlDownload.cpp: 18 (WebCore::CurlDownload::init): 19 (WebCore::CurlDownload::start): 20 (WebCore::CurlDownload::cancel): 21 (WebCore::CurlDownload::didReceiveHeader): 22 (WebCore::CurlDownload::handleCurlMsg): 23 (WebCore::CurlDownloadManager::CurlDownloadManager): Deleted. 24 (WebCore::CurlDownloadManager::~CurlDownloadManager): Deleted. 25 (WebCore::CurlDownloadManager::add): Deleted. 26 (WebCore::CurlDownloadManager::remove): Deleted. 27 (WebCore::CurlDownloadManager::getActiveDownloadCount): Deleted. 28 (WebCore::CurlDownloadManager::getPendingDownloadCount): Deleted. 29 (WebCore::CurlDownloadManager::startThreadIfNeeded): Deleted. 30 (WebCore::CurlDownloadManager::stopThread): Deleted. 31 (WebCore::CurlDownloadManager::stopThreadIfIdle): Deleted. 32 (WebCore::CurlDownloadManager::updateHandleList): Deleted. 33 (WebCore::CurlDownloadManager::addToCurl): Deleted. 34 (WebCore::CurlDownloadManager::removeFromCurl): Deleted. 35 (WebCore::CurlDownloadManager::downloadThread): Deleted. 36 * platform/network/curl/CurlDownload.h: 37 (WebCore::CurlDownloadManager::getMultiHandle): Deleted. 38 (WebCore::CurlDownloadManager::runThread): Deleted. 39 (WebCore::CurlDownloadManager::setRunThread): Deleted. 40 * platform/network/curl/CurlManager.cpp: Added. 41 (WebCore::CurlManager::CurlManager): 42 (WebCore::CurlManager::~CurlManager): 43 (WebCore::CurlManager::add): 44 (WebCore::CurlManager::remove): 45 (WebCore::CurlManager::getActiveCount): 46 (WebCore::CurlManager::getPendingCount): 47 (WebCore::CurlManager::startThreadIfNeeded): 48 (WebCore::CurlManager::stopThread): 49 (WebCore::CurlManager::stopThreadIfIdle): 50 (WebCore::CurlManager::updateHandleList): 51 (WebCore::CurlManager::addToCurl): 52 (WebCore::CurlManager::removeFromCurl): 53 (WebCore::CurlManager::workerThread): 54 (WebCore::CurlUtils::getEffectiveURL): 55 (WebCore::CurlSharedResources::mutexFor): 56 (WebCore::CurlSharedResources::lock): 57 (WebCore::CurlSharedResources::unlock): 58 * platform/network/curl/CurlManager.h: Added. 59 (WebCore::CurlManager::singleton): 60 (WebCore::CurlManager::getCurlShareHandle): 61 (WebCore::CurlManager::getMultiHandle): 62 (WebCore::CurlManager::runThread): 63 (WebCore::CurlManager::setRunThread): 64 * platform/network/curl/ResourceHandleManager.cpp: 65 (WebCore::ResourceHandleManager::ResourceHandleManager): 66 (WebCore::ResourceHandleManager::~ResourceHandleManager): 67 (WebCore::handleLocalReceiveResponse): 68 (WebCore::getProtectionSpace): 69 (WebCore::headerCallback): 70 (WebCore::ResourceHandleManager::downloadTimerCallback): 71 (WebCore::getCurlEffectiveURL): Deleted. 72 (WebCore::sharedResourceMutex): Deleted. 73 (WebCore::curl_lock_callback): Deleted. 74 (WebCore::curl_unlock_callback): Deleted. 75 (WebCore::ResourceHandleManager::getCurlShareHandle): Deleted. 76 * platform/network/curl/ResourceHandleManager.h: 77 1 78 2017-06-21 Jeremy Jones <jeremyj@apple.com> 2 79 -
trunk/Source/WebCore/PlatformWinCairo.cmake
r218142 r218637 35 35 platform/network/curl/CurlCacheManager.cpp 36 36 platform/network/curl/CurlDownload.cpp 37 platform/network/curl/CurlManager.cpp 37 38 platform/network/curl/DNSCurl.cpp 38 39 platform/network/curl/FormDataStreamCurl.cpp -
trunk/Source/WebCore/platform/network/curl/CookieJarCurl.cpp
r217968 r218637 1 1 /* 2 * Copyright (C) 2011 Apple Inc. All rights reserved. 3 * 2 4 * This library is free software; you can redistribute it and/or 3 5 * modify it under the terms of the GNU Lesser General Public … … 21 23 22 24 #include "Cookie.h" 25 #include "CurlManager.h" 23 26 #include "NotImplemented.h" 27 #include "ResourceHandleManager.h" 24 28 #include "URL.h" 25 #include "ResourceHandleManager.h"26 29 27 30 #include <wtf/DateMath.h> … … 247 250 248 251 const char* cookieJarFileName = ResourceHandleManager::sharedInstance()->getCookieJarFileName(); 249 CURLSH* curlsh = ResourceHandleManager::sharedInstance()->getCurlShareHandle();252 CURLSH* curlsh = CurlManager::singleton().getCurlShareHandle(); 250 253 251 254 curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookieJarFileName); … … 276 279 return cookies; 277 280 278 CURLSH* curlsh = ResourceHandleManager::sharedInstance()->getCurlShareHandle();281 CURLSH* curlsh = CurlManager::singleton().getCurlShareHandle(); 279 282 280 283 curl_easy_setopt(curl, CURLOPT_SHARE, curlsh); -
trunk/Source/WebCore/platform/network/curl/CurlDownload.cpp
r217977 r218637 32 32 #include "HTTPHeaderNames.h" 33 33 #include "HTTPParsers.h" 34 #include "ResourceHandleManager.h"35 34 #include "ResourceRequest.h" 36 35 #include <wtf/MainThread.h> … … 41 40 namespace WebCore { 42 41 43 // CurlDownloadManager -------------------------------------------------------------------44 45 CurlDownloadManager::CurlDownloadManager()46 {47 curl_global_init(CURL_GLOBAL_ALL);48 m_curlMultiHandle = curl_multi_init();49 }50 51 CurlDownloadManager::~CurlDownloadManager()52 {53 stopThread();54 curl_multi_cleanup(m_curlMultiHandle);55 curl_global_cleanup();56 }57 58 bool CurlDownloadManager::add(CURL* curlHandle)59 {60 {61 LockHolder locker(m_mutex);62 m_pendingHandleList.append(curlHandle);63 }64 65 startThreadIfNeeded();66 67 return true;68 }69 70 bool CurlDownloadManager::remove(CURL* curlHandle)71 {72 LockHolder locker(m_mutex);73 74 m_removedHandleList.append(curlHandle);75 76 return true;77 }78 79 int CurlDownloadManager::getActiveDownloadCount() const80 {81 LockHolder locker(m_mutex);82 return m_activeHandleList.size();83 }84 85 int CurlDownloadManager::getPendingDownloadCount() const86 {87 LockHolder locker(m_mutex);88 return m_pendingHandleList.size();89 }90 91 void CurlDownloadManager::startThreadIfNeeded()92 {93 if (!runThread()) {94 if (m_thread)95 m_thread->waitForCompletion();96 setRunThread(true);97 m_thread = Thread::create(downloadThread, this, "downloadThread");98 }99 }100 101 void CurlDownloadManager::stopThread()102 {103 setRunThread(false);104 105 if (m_thread) {106 m_thread->waitForCompletion();107 m_thread = nullptr;108 }109 }110 111 void CurlDownloadManager::stopThreadIfIdle()112 {113 if (!getActiveDownloadCount() && !getPendingDownloadCount())114 setRunThread(false);115 }116 117 void CurlDownloadManager::updateHandleList()118 {119 LockHolder locker(m_mutex);120 121 // Remove curl easy handles from multi list122 int size = m_removedHandleList.size();123 for (int i = 0; i < size; i++) {124 removeFromCurl(m_removedHandleList[0]);125 m_removedHandleList.remove(0);126 }127 128 // Add pending curl easy handles to multi list129 size = m_pendingHandleList.size();130 for (int i = 0; i < size; i++) {131 addToCurl(m_pendingHandleList[0]);132 m_pendingHandleList.remove(0);133 }134 }135 136 bool CurlDownloadManager::addToCurl(CURL* curlHandle)137 {138 CURLMcode retval = curl_multi_add_handle(m_curlMultiHandle, curlHandle);139 if (retval == CURLM_OK) {140 m_activeHandleList.append(curlHandle);141 return true;142 }143 return false;144 }145 146 bool CurlDownloadManager::removeFromCurl(CURL* curlHandle)147 {148 int handlePos = m_activeHandleList.find(curlHandle);149 150 if (handlePos < 0)151 return true;152 153 CURLMcode retval = curl_multi_remove_handle(m_curlMultiHandle, curlHandle);154 if (retval == CURLM_OK) {155 m_activeHandleList.remove(handlePos);156 curl_easy_cleanup(curlHandle);157 return true;158 }159 return false;160 }161 162 void CurlDownloadManager::downloadThread(void* data)163 {164 CurlDownloadManager* downloadManager = reinterpret_cast<CurlDownloadManager*>(data);165 166 while (downloadManager->runThread()) {167 168 downloadManager->updateHandleList();169 170 // Retry 'select' if it was interrupted by a process signal.171 int rc = 0;172 do {173 fd_set fdread;174 fd_set fdwrite;175 fd_set fdexcep;176 177 int maxfd = 0;178 179 const int selectTimeoutMS = 5;180 181 struct timeval timeout;182 timeout.tv_sec = 0;183 timeout.tv_usec = selectTimeoutMS * 1000; // select waits microseconds184 185 FD_ZERO(&fdread);186 FD_ZERO(&fdwrite);187 FD_ZERO(&fdexcep);188 curl_multi_fdset(downloadManager->getMultiHandle(), &fdread, &fdwrite, &fdexcep, &maxfd);189 // When the 3 file descriptors are empty, winsock will return -1190 // and bail out, stopping the file download. So make sure we191 // have valid file descriptors before calling select.192 if (maxfd >= 0)193 rc = ::select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);194 } while (rc == -1 && errno == EINTR);195 196 int activeDownloadCount = 0;197 while (curl_multi_perform(downloadManager->getMultiHandle(), &activeDownloadCount) == CURLM_CALL_MULTI_PERFORM) { }198 199 int messagesInQueue = 0;200 CURLMsg* msg = curl_multi_info_read(downloadManager->getMultiHandle(), &messagesInQueue);201 202 if (!msg)203 continue;204 205 CurlDownload* download = 0;206 CURLcode err = curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &download);207 UNUSED_PARAM(err);208 209 if (msg->msg == CURLMSG_DONE) {210 if (download) {211 if (msg->data.result == CURLE_OK) {212 callOnMainThread([download] {213 download->didFinish();214 download->deref(); // This matches the ref() in CurlDownload::start().215 });216 } else {217 callOnMainThread([download] {218 download->didFail();219 download->deref(); // This matches the ref() in CurlDownload::start().220 });221 }222 }223 downloadManager->removeFromCurl(msg->easy_handle);224 }225 226 downloadManager->stopThreadIfIdle();227 }228 }229 230 42 // CurlDownload -------------------------------------------------------------------------- 231 232 CurlDownloadManager CurlDownload::m_downloadManager;233 43 234 44 CurlDownload::CurlDownload() = default; … … 276 86 curl_easy_setopt(m_curlHandle, CURLOPT_CAINFO, certPath); 277 87 278 CURLSH* curlsh = ResourceHandleManager::sharedInstance()->getCurlShareHandle();88 CURLSH* curlsh = CurlManager::singleton().getCurlShareHandle(); 279 89 if (curlsh) 280 90 curl_easy_setopt(m_curlHandle, CURLOPT_SHARE, curlsh); … … 298 108 { 299 109 ref(); // CurlDownloadManager::downloadThread will call deref when the download has finished. 300 return m_downloadManager.add(m_curlHandle);110 return CurlManager::singleton().add(m_curlHandle); 301 111 } 302 112 303 113 bool CurlDownload::cancel() 304 114 { 305 return m_downloadManager.remove(m_curlHandle);115 return CurlManager::singleton().remove(m_curlHandle); 306 116 } 307 117 … … 394 204 395 205 if (httpCode >= 200 && httpCode < 300) { 396 URL url = getCurlEffectiveURL(m_curlHandle);206 URL url = CurlUtils::getEffectiveURL(m_curlHandle); 397 207 callOnMainThread([this, url = url.isolatedCopy(), protectedThis = makeRef(*this)] { 398 208 m_response.setURL(url); … … 507 317 } 508 318 319 CurlJobAction CurlDownload::handleCurlMsg(CURLMsg* msg) 320 { 321 switch (msg->msg) { 322 case CURLMSG_DONE: { 323 if (msg->data.result == CURLE_OK) { 324 callOnMainThread([this] { 325 didFinish(); 326 deref(); // This matches the ref() in CurlDownload::start(). 327 }); 328 } else { 329 callOnMainThread([this] { 330 didFail(); 331 deref(); // This matches the ref() in CurlDownload::start(). 332 }); 333 } 334 return CurlJobAction::Finished; 335 } 336 default: { 337 return CurlJobAction::None; 338 } 339 } 340 } 341 509 342 } 510 343 -
trunk/Source/WebCore/platform/network/curl/CurlDownload.h
r217968 r218637 37 37 #endif 38 38 39 #include <curl/curl.h>39 #include "CurlManager.h" 40 40 41 41 namespace WebCore { 42 43 class CurlDownloadManager {44 public:45 CurlDownloadManager();46 ~CurlDownloadManager();47 48 bool add(CURL* curlHandle);49 bool remove(CURL* curlHandle);50 51 int getActiveDownloadCount() const;52 int getPendingDownloadCount() const;53 54 private:55 void startThreadIfNeeded();56 void stopThread();57 void stopThreadIfIdle();58 59 void updateHandleList();60 61 CURLM* getMultiHandle() const { return m_curlMultiHandle; }62 63 bool runThread() const { LockHolder locker(m_mutex); return m_runThread; }64 void setRunThread(bool runThread) { LockHolder locker(m_mutex); m_runThread = runThread; }65 66 bool addToCurl(CURL* curlHandle);67 bool removeFromCurl(CURL* curlHandle);68 69 static void downloadThread(void* data);70 71 RefPtr<Thread> m_thread;72 CURLM* m_curlMultiHandle { nullptr };73 Vector<CURL*> m_pendingHandleList;74 Vector<CURL*> m_activeHandleList;75 Vector<CURL*> m_removedHandleList;76 mutable Lock m_mutex;77 bool m_runThread { false };78 };79 42 80 43 class CurlDownloadListener { … … 86 49 }; 87 50 88 class CurlDownload : public ThreadSafeRefCounted<CurlDownload> {51 class CurlDownload : public ThreadSafeRefCounted<CurlDownload>, public CurlJob { 89 52 public: 90 53 CurlDownload(); … … 107 70 108 71 void setDestination(const String& destination) { m_destination = destination; } 72 73 virtual CurlJobAction handleCurlMsg(CURLMsg*); 109 74 110 75 private: … … 143 108 mutable Lock m_mutex; 144 109 CurlDownloadListener* m_listener { nullptr }; 145 146 static CurlDownloadManager m_downloadManager;147 148 friend class CurlDownloadManager;149 110 }; 150 111 -
trunk/Source/WebCore/platform/network/curl/ResourceHandleManager.cpp
r215173 r218637 43 43 #include "CredentialStorage.h" 44 44 #include "CurlCacheManager.h" 45 #include "CurlManager.h" 45 46 #include "HTTPHeaderNames.h" 46 47 #include "HTTPParsers.h" … … 88 89 const char* const errorDomainCurl = "CurlErrorDomain"; 89 90 90 URL getCurlEffectiveURL(CURL* handle)91 {92 const char* url;93 CURLcode err = curl_easy_getinfo(handle, CURLINFO_EFFECTIVE_URL, &url);94 if (CURLE_OK != err)95 return URL();96 return URL(URL(), url);97 }98 99 91 static const bool ignoreSSLErrors = getenv("WEBKIT_IGNORE_SSL_ERRORS"); 100 92 … … 152 144 } 153 145 154 static Lock* sharedResourceMutex(curl_lock_data data)155 {156 DEPRECATED_DEFINE_STATIC_LOCAL(Lock, cookieMutex, ());157 DEPRECATED_DEFINE_STATIC_LOCAL(Lock, dnsMutex, ());158 DEPRECATED_DEFINE_STATIC_LOCAL(Lock, shareMutex, ());159 160 switch (data) {161 case CURL_LOCK_DATA_COOKIE:162 return &cookieMutex;163 case CURL_LOCK_DATA_DNS:164 return &dnsMutex;165 case CURL_LOCK_DATA_SHARE:166 return &shareMutex;167 default:168 ASSERT_NOT_REACHED();169 return NULL;170 }171 }172 173 146 #if ENABLE(WEB_TIMING) 174 147 static void calculateWebTimingInformations(ResourceHandleInternal* d) … … 198 171 #endif 199 172 200 // libcurl does not implement its own thread synchronization primitives.201 // these two functions provide mutexes for cookies, and for the global DNS202 // cache.203 static void curl_lock_callback(CURL* /* handle */, curl_lock_data data, curl_lock_access /* access */, void* /* userPtr */)204 {205 if (Lock* mutex = sharedResourceMutex(data))206 mutex->lock();207 }208 209 static void curl_unlock_callback(CURL* /* handle */, curl_lock_data data, void* /* userPtr */)210 {211 if (Lock* mutex = sharedResourceMutex(data))212 mutex->unlock();213 }214 215 173 inline static bool isHttpInfo(int statusCode) 216 174 { … … 236 194 : m_downloadTimer(*this, &ResourceHandleManager::downloadTimerCallback) 237 195 , m_cookieJarFileName(cookieJarPath()) 238 , m_certificatePath 196 , m_certificatePath(certificatePath()) 239 197 , m_runningJobs(0) 240 198 #ifndef NDEBUG … … 242 200 #endif 243 201 { 244 curl_global_init(CURL_GLOBAL_ALL); 202 CURLSH* h = CurlManager::singleton().getCurlShareHandle(); 203 m_curlShareHandle = h; 245 204 m_curlMultiHandle = curl_multi_init(); 246 m_curlShareHandle = curl_share_init(); 247 curl_share_setopt(m_curlShareHandle, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE); 248 curl_share_setopt(m_curlShareHandle, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); 249 curl_share_setopt(m_curlShareHandle, CURLSHOPT_LOCKFUNC, curl_lock_callback); 250 curl_share_setopt(m_curlShareHandle, CURLSHOPT_UNLOCKFUNC, curl_unlock_callback); 205 251 206 252 207 initCookieSession(); … … 262 217 { 263 218 curl_multi_cleanup(m_curlMultiHandle); 264 curl_share_cleanup(m_curlShareHandle);265 219 if (m_cookieJarFileName) 266 220 fastFree(m_cookieJarFileName); 267 curl_global_cleanup();268 221 269 222 #ifndef NDEBUG … … 271 224 fclose(m_logFile); 272 225 #endif 273 }274 275 CURLSH* ResourceHandleManager::getCurlShareHandle() const276 {277 return m_curlShareHandle;278 226 } 279 227 … … 303 251 // Run the code here for local files to resolve the issue. 304 252 // TODO: See if there is a better approach for handling this. 305 URL url = getCurlEffectiveURL(handle);253 URL url = CurlUtils::getEffectiveURL(handle); 306 254 ASSERT(url.isValid()); 307 255 d->m_response.setURL(url); … … 414 362 return false; 415 363 416 URL url = getCurlEffectiveURL(h);364 URL url = CurlUtils::getEffectiveURL(h); 417 365 if (!url.isValid()) 418 366 return false; … … 503 451 d->m_response.setExpectedContentLength(static_cast<long long int>(contentLength)); 504 452 505 d->m_response.setURL( getCurlEffectiveURL(h));453 d->m_response.setURL(CurlUtils::getEffectiveURL(h)); 506 454 507 455 d->m_response.setHTTPStatusCode(httpCode); … … 710 658 } 711 659 } else { 712 URL url = getCurlEffectiveURL(d->m_handle);660 URL url = CurlUtils::getEffectiveURL(d->m_handle); 713 661 #ifndef NDEBUG 714 662 fprintf(stderr, "Curl ERROR for url='%s', error: '%s'\n", url.string().utf8().data(), curl_easy_strerror(msg->data.result)); -
trunk/Source/WebCore/platform/network/curl/ResourceHandleManager.h
r203250 r218637 58 58 void cancel(ResourceHandle*); 59 59 60 CURLSH* getCurlShareHandle() const;61 62 60 void setCookieJarFileName(const char* cookieJarFileName); 63 61 const char* getCookieJarFileName() const; … … 101 99 }; 102 100 103 URL getCurlEffectiveURL(CURL*);104 105 101 } 106 102
Note: See TracChangeset
for help on using the changeset viewer.