1/* 2 * Copyright (C) 2013 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#ifndef CurlDownload_h 27#define CurlDownload_h 28 29#include "FileSystem.h" 30#include "ResourceHandle.h" 31#include "ResourceResponse.h" 32#include <wtf/Threading.h> 33 34#if PLATFORM(WIN) 35#include <windows.h> 36#include <winsock2.h> 37#endif 38 39#include <curl/curl.h> 40 41namespace WebCore { 42 43class CurlDownloadManager { 44public: 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 54private: 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 { return m_runThread; } 64 void setRunThread(bool runThread) { m_runThread = runThread; } 65 66 bool addToCurl(CURL* curlHandle); 67 bool removeFromCurl(CURL* curlHandle); 68 69 static void downloadThread(void* data); 70 71 ThreadIdentifier m_threadId; 72 CURLM* m_curlMultiHandle; 73 Vector<CURL*> m_pendingHandleList; 74 Vector<CURL*> m_activeHandleList; 75 Vector<CURL*> m_removedHandleList; 76 mutable Mutex m_mutex; 77 bool m_runThread; 78}; 79 80class CurlDownloadListener { 81public: 82 virtual void didReceiveResponse() { } 83 virtual void didReceiveDataOfLength(int size) { } 84 virtual void didFinish() { } 85 virtual void didFail() { } 86}; 87 88class CurlDownload { 89public: 90 CurlDownload(); 91 ~CurlDownload(); 92 93 void init(CurlDownloadListener*, const WebCore::URL&); 94 void init(CurlDownloadListener*, ResourceHandle*, const ResourceRequest&, const ResourceResponse&); 95 96 bool start(); 97 bool cancel(); 98 99 String getTempPath() const; 100 String getUrl() const; 101 WebCore::ResourceResponse getResponse() const; 102 103 bool deletesFileUponFailure() const { return m_deletesFileUponFailure; } 104 void setDeletesFileUponFailure(bool deletesFileUponFailure) { m_deletesFileUponFailure = deletesFileUponFailure; } 105 106 void setDestination(const String& destination) { m_destination = destination; } 107 108private: 109 void closeFile(); 110 void moveFileToDestination(); 111 void writeDataToFile(const char* data, int size); 112 113 void addHeaders(const ResourceRequest&); 114 115 // Called on download thread. 116 void didReceiveHeader(const String& header); 117 void didReceiveData(void* data, int size); 118 119 // Called on main thread. 120 void didReceiveResponse(); 121 void didReceiveDataOfLength(int size); 122 void didFinish(); 123 void didFail(); 124 125 static size_t writeCallback(void* ptr, size_t, size_t nmemb, void* data); 126 static size_t headerCallback(char* ptr, size_t, size_t nmemb, void* data); 127 128 static void downloadFinishedCallback(CurlDownload*); 129 static void downloadFailedCallback(CurlDownload*); 130 static void receivedDataCallback(CurlDownload*, int size); 131 static void receivedResponseCallback(CurlDownload*); 132 133 CURL* m_curlHandle; 134 struct curl_slist* m_customHeaders; 135 char* m_url; 136 String m_tempPath; 137 String m_destination; 138 WebCore::PlatformFileHandle m_tempHandle; 139 WebCore::ResourceResponse m_response; 140 bool m_deletesFileUponFailure; 141 mutable Mutex m_mutex; 142 CurlDownloadListener *m_listener; 143 144 static CurlDownloadManager m_downloadManager; 145 146 friend class CurlDownloadManager; 147}; 148 149} 150 151#endif 152