Diff
Modified: trunk/Source/WebCore/ChangeLog (151066 => 151067)
--- trunk/Source/WebCore/ChangeLog 2013-06-01 04:21:09 UTC (rev 151066)
+++ trunk/Source/WebCore/ChangeLog 2013-06-01 05:41:42 UTC (rev 151067)
@@ -1,3 +1,18 @@
+2013-05-31 [email protected] <[email protected]>
+
+ [Curl] Unable to download files.
+ https://bugs.webkit.org/show_bug.cgi?id=116150
+
+ Reviewed by Brent Fulgham.
+
+ Implemented basic download functionality for Curl.
+
+ * WebCore.vcproj/WebCore.vcproj: Added file.
+ * WebCore.vcxproj/WebCore.vcxproj: Added file.
+ * WebCore.vcxproj/WebCore.vcxproj.filters: Added file.
+ * platform/network/curl/CurlDownload.h: Added.
+ * platform/network/curl/CurlDownload.cpp: Added.
+
2013-05-31 Anders Carlsson <[email protected]>
Take the normal NSView code path when drawing into an inclusive layer
Modified: trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj (151066 => 151067)
--- trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj 2013-06-01 04:21:09 UTC (rev 151066)
+++ trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj 2013-06-01 05:41:42 UTC (rev 151067)
@@ -33721,6 +33721,42 @@
</FileConfiguration>
</File>
<File
+ RelativePath="..\platform\network\curl\CurlDownload.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug_All|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Production|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
RelativePath="..\platform\network\curl\DNSCurl.cpp"
>
<FileConfiguration
Modified: trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj (151066 => 151067)
--- trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj 2013-06-01 04:21:09 UTC (rev 151066)
+++ trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj 2013-06-01 05:41:42 UTC (rev 151067)
@@ -4700,6 +4700,12 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Production|Win32'">true</ExcludedFromBuild>
</ClCompile>
+ <ClCompile Include="..\platform\network\curl\CurlDownload.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DebugSuffix|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Production|Win32'">true</ExcludedFromBuild>
+ </ClCompile>
<ClCompile Include="..\platform\network\curl\DNSCurl.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DebugSuffix|Win32'">true</ExcludedFromBuild>
Modified: trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters (151066 => 151067)
--- trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters 2013-06-01 04:21:09 UTC (rev 151066)
+++ trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters 2013-06-01 05:41:42 UTC (rev 151067)
@@ -1953,6 +1953,9 @@
<ClCompile Include="..\platform\network\curl\CredentialStorageCurl.cpp">
<Filter>platform\network\curl</Filter>
</ClCompile>
+ <ClCompile Include="..\platform\network\curl\CurlDownload.cpp">
+ <Filter>platform\network\curl</Filter>
+ </ClCompile>
<ClCompile Include="..\platform\network\curl\DNSCurl.cpp">
<Filter>platform\network\curl</Filter>
</ClCompile>
Added: trunk/Source/WebCore/platform/network/curl/CurlDownload.cpp (0 => 151067)
--- trunk/Source/WebCore/platform/network/curl/CurlDownload.cpp (rev 0)
+++ trunk/Source/WebCore/platform/network/curl/CurlDownload.cpp 2013-06-01 05:41:42 UTC (rev 151067)
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, 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 COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CurlDownload.h"
+
+#include <WebCore/HTTPParsers.h>
+#include <WebCore/MainThreadTask.h>
+
+#include <wtf/MainThread.h>
+#include <wtf/text/CString.h>
+
+using namespace WebCore;
+
+template<> struct CrossThreadCopierBase<false, false, CurlDownload*> : public CrossThreadCopierPassThrough<CurlDownload*> {
+};
+
+// CurlDownloadManager -------------------------------------------------------------------
+
+CurlDownloadManager::CurlDownloadManager()
+: m_threadId(0)
+, m_curlMultiHandle(0)
+, m_activeDownloadCount(0)
+, m_runThread(false)
+{
+ 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)
+{
+ MutexLocker locker(m_mutex);
+
+ m_pendingHandleList.append(curlHandle);
+ startThreadIfNeeded();
+
+ return true;
+}
+
+bool CurlDownloadManager::remove(CURL* curlHandle)
+{
+ MutexLocker locker(m_mutex);
+
+ m_removedHandleList.append(curlHandle);
+
+ return true;
+}
+
+int CurlDownloadManager::getActiveDownloadCount() const
+{
+ return m_activeDownloadCount;
+}
+
+int CurlDownloadManager::getPendingDownloadCount() const
+{
+ MutexLocker locker(m_mutex);
+ return m_pendingHandleList.size();
+}
+
+void CurlDownloadManager::startThreadIfNeeded()
+{
+ if (!m_runThread) {
+ if (m_threadId)
+ waitForThreadCompletion(m_threadId);
+ m_runThread = true;
+ m_threadId = createThread(downloadThread, this, "downloadThread");
+ }
+}
+
+void CurlDownloadManager::stopThread()
+{
+ m_runThread = false;
+
+ if (m_threadId) {
+ waitForThreadCompletion(m_threadId);
+ m_threadId = 0;
+ }
+}
+
+void CurlDownloadManager::stopThreadIfIdle()
+{
+ MutexLocker locker(m_mutex);
+
+ if (!getActiveDownloadCount() && !getPendingDownloadCount())
+ setRunThread(false);
+}
+
+void CurlDownloadManager::updateHandleList()
+{
+ MutexLocker locker(m_mutex);
+
+ // Add pending curl easy handles to multi list
+ int size = m_pendingHandleList.size();
+ for (int i = 0; i < size; i++) {
+ CURLMcode retval = curl_multi_add_handle(m_curlMultiHandle, m_pendingHandleList[0]);
+
+ if (retval == CURLM_OK)
+ m_pendingHandleList.remove(0);
+ }
+
+ // Remove curl easy handles from multi list
+ size = m_removedHandleList.size();
+ for (int i = 0; i < size; i++) {
+ CURLMcode retval = curl_multi_remove_handle(m_curlMultiHandle, m_removedHandleList[0]);
+
+ if (retval == CURLM_OK)
+ m_removedHandleList.remove(0);
+ }
+}
+
+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);
+
+ while (curl_multi_perform(downloadManager->getMultiHandle(), &downloadManager->m_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);
+
+ if (msg->msg == CURLMSG_DONE) {
+ if (msg->data.result == CURLE_OK)
+ callOnMainThread<CurlDownload*, CurlDownload*>(CurlDownload::downloadFinishedCallback, download);
+ else
+ callOnMainThread<CurlDownload*, CurlDownload*>(CurlDownload::downloadFailedCallback, download);
+
+ curl_multi_remove_handle(downloadManager->getMultiHandle(), msg->easy_handle);
+ }
+
+ downloadManager->stopThreadIfIdle();
+ }
+}
+
+// CurlDownload --------------------------------------------------------------------------
+
+CurlDownloadManager CurlDownload::m_downloadManager;
+
+CurlDownload::CurlDownload()
+: m_curlHandle(0)
+, m_url(0)
+, m_tempHandle(invalidPlatformFileHandle)
+, m_deletesFileUponFailure(false)
+, m_listener(0)
+{
+}
+
+CurlDownload::~CurlDownload()
+{
+ MutexLocker locker(m_mutex);
+
+ if (m_curlHandle)
+ curl_easy_cleanup(m_curlHandle);
+
+ if (m_url)
+ fastFree(m_url);
+
+ closeFile();
+ moveFileToDestination();
+}
+
+void CurlDownload::init(CurlDownloadListener* listener, const KURL& url)
+{
+ if (!listener)
+ return;
+
+ MutexLocker locker(m_mutex);
+
+ m_curlHandle = curl_easy_init();
+
+ String urlStr = url.string();
+ m_url = fastStrDup(urlStr.latin1().data());
+
+ 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);
+
+ m_listener = listener;
+}
+
+bool CurlDownload::start()
+{
+ return m_downloadManager.add(m_curlHandle);
+}
+
+bool CurlDownload::cancel()
+{
+ return m_downloadManager.remove(m_curlHandle);
+}
+
+String CurlDownload::getTempPath() const
+{
+ MutexLocker locker(m_mutex);
+ return m_tempPath;
+}
+
+String CurlDownload::getUrl() const
+{
+ MutexLocker locker(m_mutex);
+ return String(m_url);
+}
+
+ResourceResponse CurlDownload::getResponse() const
+{
+ MutexLocker locker(m_mutex);
+ return m_response;
+}
+
+void CurlDownload::closeFile()
+{
+ MutexLocker locker(m_mutex);
+
+ if (m_tempHandle) {
+ WebCore::closeFile(m_tempHandle);
+ m_tempHandle = invalidPlatformFileHandle;
+ }
+}
+
+void CurlDownload::moveFileToDestination()
+{
+ if (m_destination.isEmpty())
+ return;
+
+ ::MoveFile(m_tempPath.charactersWithNullTermination(), m_destination.charactersWithNullTermination());
+}
+
+void CurlDownload::didReceiveHeader(const String& header)
+{
+ MutexLocker locker(m_mutex);
+
+ if (header == "\r\n" || header == "\n") {
+
+ long httpCode = 0;
+ CURLcode err = curl_easy_getinfo(m_curlHandle, CURLINFO_RESPONSE_CODE, &httpCode);
+
+ if (httpCode >= 200 && httpCode < 300) {
+ const char* url = ""
+ err = curl_easy_getinfo(m_curlHandle, CURLINFO_EFFECTIVE_URL, &url);
+ m_response.setURL(KURL(ParsedURLString, url));
+
+ m_response.setMimeType(extractMIMETypeFromMediaType(m_response.httpHeaderField("Content-Type")));
+ m_response.setTextEncodingName(extractCharsetFromMediaType(m_response.httpHeaderField("Content-Type")));
+ m_response.setSuggestedFilename(filenameFromHTTPContentDisposition(m_response.httpHeaderField("Content-Disposition")));
+
+ callOnMainThread<CurlDownload*, CurlDownload*>(receivedResponseCallback, this);
+ }
+ } else {
+ int splitPos = header.find(":");
+ if (splitPos != -1)
+ m_response.setHTTPHeaderField(header.left(splitPos), header.substring(splitPos+1).stripWhiteSpace());
+ }
+}
+
+void CurlDownload::didReceiveData(void* data, int size)
+{
+ MutexLocker locker(m_mutex);
+
+ callOnMainThread<CurlDownload*, CurlDownload*, int, int>(receivedDataCallback, this, size);
+
+ if (m_tempPath.isEmpty())
+ m_tempPath = openTemporaryFile("download", m_tempHandle);
+
+ if (m_tempHandle != invalidPlatformFileHandle) {
+ const char* fileData = static_cast<const char*>(data);
+ writeToFile(m_tempHandle, fileData, size);
+ }
+}
+
+void CurlDownload::didReceiveResponse()
+{
+ if (m_listener)
+ m_listener->didReceiveResponse();
+}
+
+void CurlDownload::didReceiveDataOfLength(int size)
+{
+ if (m_listener)
+ m_listener->didReceiveDataOfLength(size);
+}
+
+void CurlDownload::didFinish()
+{
+ closeFile();
+ moveFileToDestination();
+
+ if (m_listener)
+ m_listener->didFinish();
+}
+
+void CurlDownload::didFail()
+{
+ MutexLocker locker(m_mutex);
+
+ closeFile();
+
+ if (m_deletesFileUponFailure)
+ deleteFile(m_tempPath);
+
+ if (m_listener)
+ m_listener->didFail();
+}
+
+size_t CurlDownload::writeCallback(void* 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);
+
+ return totalSize;
+}
+
+size_t CurlDownload::headerCallback(char* ptr, size_t size, size_t nmemb, void* data)
+{
+ size_t totalSize = size * nmemb;
+ CurlDownload* download = reinterpret_cast<CurlDownload*>(data);
+
+ String header(static_cast<const char*>(ptr), totalSize);
+
+ if (download)
+ download->didReceiveHeader(header);
+
+ return totalSize;
+}
+
+void CurlDownload::downloadFinishedCallback(CurlDownload* download)
+{
+ if (download)
+ download->didFinish();
+}
+
+void CurlDownload::downloadFailedCallback(CurlDownload* download)
+{
+ if (download)
+ download->didFail();
+}
+
+void CurlDownload::receivedDataCallback(CurlDownload* download, int size)
+{
+ if (download)
+ download->didReceiveDataOfLength(size);
+}
+
+void CurlDownload::receivedResponseCallback(CurlDownload* download)
+{
+ if (download)
+ download->didReceiveResponse();
+}
Added: trunk/Source/WebCore/platform/network/curl/CurlDownload.h (0 => 151067)
--- trunk/Source/WebCore/platform/network/curl/CurlDownload.h (rev 0)
+++ trunk/Source/WebCore/platform/network/curl/CurlDownload.h 2013-06-01 05:41:42 UTC (rev 151067)
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, 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 COMPUTER, 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.
+ */
+
+#ifndef CurlDownload_h
+#define CurlDownload_h
+
+#include <WebCore/FileSystem.h>
+#include <WebCore/ResourceResponse.h>
+
+#if PLATFORM(WIN)
+#include <windows.h>
+#include <winsock2.h>
+#endif
+
+#include <curl/curl.h>
+
+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 { return m_runThread; }
+ void setRunThread(bool runThread) { m_runThread = runThread; }
+
+ static void downloadThread(void* data);
+
+ ThreadIdentifier m_threadId;
+ CURLM* m_curlMultiHandle;
+ int m_activeDownloadCount;
+ Vector<CURL*> m_pendingHandleList;
+ Vector<CURL*> m_removedHandleList;
+ mutable Mutex m_mutex;
+ bool m_runThread;
+};
+
+class CurlDownloadListener {
+public:
+ virtual void didReceiveResponse() { }
+ virtual void didReceiveDataOfLength(int size) { }
+ virtual void didFinish() { }
+ virtual void didFail() { }
+};
+
+class CurlDownload {
+public:
+ CurlDownload();
+ ~CurlDownload();
+
+ void init(CurlDownloadListener*, const WebCore::KURL&);
+ bool start();
+ bool cancel();
+
+ String getTempPath() const;
+ String getUrl() const;
+ WebCore::ResourceResponse getResponse() const;
+
+ bool deletesFileUponFailure() const { return m_deletesFileUponFailure; }
+ void setDeletesFileUponFailure(bool deletesFileUponFailure) { m_deletesFileUponFailure = deletesFileUponFailure; }
+
+ void setDestination(const String& destination) { m_destination = destination; }
+
+private:
+ void closeFile();
+ void moveFileToDestination();
+
+ // Called on download thread.
+ void didReceiveHeader(const String& header);
+ void didReceiveData(void* data, int size);
+
+ // Called on main thread.
+ void didReceiveResponse();
+ void didReceiveDataOfLength(int size);
+ void didFinish();
+ void didFail();
+
+ static size_t writeCallback(void* 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*);
+ static void downloadFailedCallback(CurlDownload*);
+ static void receivedDataCallback(CurlDownload*, int size);
+ static void receivedResponseCallback(CurlDownload*);
+
+ CURL* m_curlHandle;
+ char* m_url;
+ String m_tempPath;
+ String m_destination;
+ WebCore::PlatformFileHandle m_tempHandle;
+ WebCore::ResourceResponse m_response;
+ bool m_deletesFileUponFailure;
+ mutable Mutex m_mutex;
+ CurlDownloadListener *m_listener;
+
+ static CurlDownloadManager m_downloadManager;
+
+ friend class CurlDownloadManager;
+};
+
+#endif
Modified: trunk/Source/WebKit/win/ChangeLog (151066 => 151067)
--- trunk/Source/WebKit/win/ChangeLog 2013-06-01 04:21:09 UTC (rev 151066)
+++ trunk/Source/WebKit/win/ChangeLog 2013-06-01 05:41:42 UTC (rev 151067)
@@ -1,3 +1,26 @@
+2013-05-31 [email protected] <[email protected]>
+
+ [Curl] Unable to download files.
+ https://bugs.webkit.org/show_bug.cgi?id=116150
+
+ Reviewed by Brent Fulgham.
+
+ Implemented basic download functionality for Curl.
+
+ * WebDownload.h:
+ * WebDownloadCurl.cpp:
+ (WebDownload::init):
+ (WebDownload::start):
+ (WebDownload::cancel):
+ (WebDownload::deletesFileUponFailure):
+ (WebDownload::setDeletesFileUponFailure):
+ (WebDownload::setDestination):
+ (WebDownload::useCredential):
+ (WebDownload::didReceiveResponse):
+ (WebDownload::didReceiveDataOfLength):
+ (WebDownload::didFinish):
+ (WebDownload::didFail):
+
2013-05-29 Brent Fulgham <[email protected]>
[Windows] Be consistent with allocation/deallocation behavior
Modified: trunk/Source/WebKit/win/WebDownload.h (151066 => 151067)
--- trunk/Source/WebKit/win/WebDownload.h 2013-06-01 04:21:09 UTC (rev 151066)
+++ trunk/Source/WebKit/win/WebDownload.h 2013-06-01 05:41:42 UTC (rev 151067)
@@ -33,6 +33,8 @@
#if USE(CFNETWORK)
#include <CFNetwork/CFURLDownloadPriv.h>
+#elif USE(CURL)
+#include <WebCore/CurlDownload.h>
#endif
namespace WebCore {
@@ -42,7 +44,12 @@
class ResourceResponse;
}
-class WebDownload : public IWebDownload, public IWebURLAuthenticationChallengeSender
+class WebDownload
+: public IWebDownload
+, public IWebURLAuthenticationChallengeSender
+#if USE(CURL)
+, public CurlDownloadListener
+#endif
{
public:
static WebDownload* createInstance(const WebCore::KURL&, IWebDownloadDelegate*);
@@ -119,6 +126,11 @@
void didCreateDestination(CFURLRef);
void didFinish();
void didFail(CFErrorRef);
+#elif USE(CURL)
+ virtual void didReceiveResponse();
+ virtual void didReceiveDataOfLength(int size);
+ virtual void didFinish();
+ virtual void didFail();
#endif
protected:
@@ -128,6 +140,8 @@
WTF::String m_bundlePath;
#if USE(CFNETWORK)
RetainPtr<CFURLDownloadRef> m_download;
+#elif USE(CURL)
+ CurlDownload m_download;
#endif
COMPtr<IWebMutableURLRequest> m_request;
COMPtr<IWebDownloadDelegate> m_delegate;
Modified: trunk/Source/WebKit/win/WebDownloadCurl.cpp (151066 => 151067)
--- trunk/Source/WebKit/win/WebDownloadCurl.cpp 2013-06-01 04:21:09 UTC (rev 151066)
+++ trunk/Source/WebKit/win/WebDownloadCurl.cpp 2013-06-01 05:41:42 UTC (rev 151067)
@@ -62,7 +62,9 @@
void WebDownload::init(const KURL& url, IWebDownloadDelegate* delegate)
{
- notImplemented();
+ m_delegate = delegate;
+
+ m_download.init(this, url);
}
// IWebDownload -------------------------------------------------------------------
@@ -85,14 +87,21 @@
HRESULT STDMETHODCALLTYPE WebDownload::start()
{
- notImplemented();
- return E_FAIL;
+ if (!m_download.start())
+ return E_FAIL;
+
+ if (m_delegate)
+ m_delegate->didBegin(this);
+
+ return S_OK;
}
HRESULT STDMETHODCALLTYPE WebDownload::cancel()
{
- notImplemented();
- return E_FAIL;
+ if (!m_download.cancel())
+ return E_FAIL;
+
+ return S_OK;
}
HRESULT STDMETHODCALLTYPE WebDownload::cancelForResume()
@@ -104,23 +113,25 @@
HRESULT STDMETHODCALLTYPE WebDownload::deletesFileUponFailure(
/* [out, retval] */ BOOL* result)
{
- notImplemented();
- return E_FAIL;
+ *result = m_download.deletesFileUponFailure() ? TRUE : FALSE;
+ return S_OK;
}
HRESULT STDMETHODCALLTYPE WebDownload::setDeletesFileUponFailure(
/* [in] */ BOOL deletesFileUponFailure)
{
- notImplemented();
- return E_FAIL;
+ m_download.setDeletesFileUponFailure(deletesFileUponFailure);
+ return S_OK;
}
HRESULT STDMETHODCALLTYPE WebDownload::setDestination(
/* [in] */ BSTR path,
/* [in] */ BOOL allowOverwrite)
{
- notImplemented();
- return E_FAIL;
+ size_t len = wcslen(path);
+ m_destination = String(path, len);
+ m_download.setDestination(m_destination);
+ return S_OK;
}
// IWebURLAuthenticationChallengeSender -------------------------------------------------------------------
@@ -146,3 +157,44 @@
notImplemented();
return E_FAIL;
}
+
+void WebDownload::didReceiveResponse()
+{
+ COMPtr<WebDownload> protect = this;
+
+ if (m_delegate) {
+ ResourceResponse response = m_download.getResponse();
+ COMPtr<WebURLResponse> webResponse(AdoptCOM, WebURLResponse::createInstance(response));
+ m_delegate->didReceiveResponse(this, webResponse.get());
+
+ String suggestedFilename = response.suggestedFilename();
+ if (suggestedFilename.isEmpty())
+ suggestedFilename = pathGetFileName(response.url().string());
+ BString suggestedFilenameBSTR(suggestedFilename.characters(), suggestedFilename.length());
+ m_delegate->decideDestinationWithSuggestedFilename(this, suggestedFilenameBSTR);
+ }
+}
+
+void WebDownload::didReceiveDataOfLength(int size)
+{
+ COMPtr<WebDownload> protect = this;
+
+ if (m_delegate)
+ m_delegate->didReceiveDataOfLength(this, size);
+}
+
+void WebDownload::didFinish()
+{
+ COMPtr<WebDownload> protect = this;
+
+ if (m_delegate)
+ m_delegate->didFinish(this);
+}
+
+void WebDownload::didFail()
+{
+ COMPtr<WebDownload> protect = this;
+
+ if (m_delegate)
+ m_delegate->didFailWithError(this, 0);
+}