[Curl] Replace the implementation with NetworkLoadMetrics
[WebKit-https.git] / Source / WebCore / platform / network / curl / CurlContext.h
1 /*
2  * Copyright (C) 2013 Apple Inc.  All rights reserved.
3  * Copyright (C) 2017 Sony Interactive Entertainment Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #pragma once
28
29 #include "CookieJarCurl.h"
30 #include "URL.h"
31
32 #include <wtf/Lock.h>
33 #include <wtf/NeverDestroyed.h>
34 #include <wtf/Noncopyable.h>
35 #include <wtf/Threading.h>
36
37 #if OS(WINDOWS)
38 #include <windows.h>
39 #include <winsock2.h>
40 #endif
41
42 #include <curl/curl.h>
43
44 namespace WebCore {
45
46 enum class CurlProxyType {
47     Invalid = -1,
48     HTTP = CURLPROXY_HTTP,
49     Socks4 = CURLPROXY_SOCKS4,
50     Socks4A = CURLPROXY_SOCKS4A,
51     Socks5 = CURLPROXY_SOCKS5,
52     Socks5Hostname = CURLPROXY_SOCKS5_HOSTNAME
53 };
54
55 // CurlGlobal --------------------------------------------
56 // to make the initialization of libcurl happen before other initialization of CurlContext
57
58 class CurlGlobal {
59 protected:
60     CurlGlobal()
61     {
62         curl_global_init(CURL_GLOBAL_ALL);
63     }
64     
65     virtual ~CurlGlobal()
66     {
67         curl_global_cleanup();
68     }
69 };
70
71 // CurlShareHandle --------------------------------------------
72
73 class CurlShareHandle {
74     WTF_MAKE_NONCOPYABLE(CurlShareHandle);
75
76 public:
77     CurlShareHandle();
78     ~CurlShareHandle();
79
80     CURLSH* handle() const { return m_shareHandle; }
81
82 private:
83     static void lockCallback(CURL*, curl_lock_data, curl_lock_access, void*);
84     static void unlockCallback(CURL*, curl_lock_data, void*);
85     static Lock* mutexFor(curl_lock_data);
86
87     CURLSH* m_shareHandle { nullptr };
88 };
89
90 // CurlContext --------------------------------------------
91
92 class CurlContext : public CurlGlobal {
93     WTF_MAKE_NONCOPYABLE(CurlContext);
94
95 public:
96     struct ProxyInfo {
97         String host;
98         unsigned long port;
99         CurlProxyType type { CurlProxyType::Invalid };
100         String username;
101         String password;
102
103         const String url() const;
104     };
105
106     static const char* const errorDomain;
107
108     static CurlContext& singleton()
109     {
110         static CurlContext shared;
111         return shared;
112     }
113
114     virtual ~CurlContext();
115
116     const CurlShareHandle& shareHandle() { return m_shareHandle; }
117
118     // Cookie
119     const char* getCookieJarFileName() const { return m_cookieJarFileName.data(); }
120     void setCookieJarFileName(const char* cookieJarFileName) { m_cookieJarFileName = CString(cookieJarFileName); }
121     CookieJarCurl& cookieJar() { return *m_cookieJar; }
122
123     // Certificate
124     const char* getCertificatePath() const { return m_certificatePath.data(); }
125     bool shouldIgnoreSSLErrors() const { return m_ignoreSSLErrors; }
126
127     // Proxy
128     const ProxyInfo& proxyInfo() const { return m_proxy; }
129     void setProxyInfo(const ProxyInfo& info) { m_proxy = info;  }
130     void setProxyInfo(const String& host = emptyString(), unsigned long port = 0, CurlProxyType = CurlProxyType::HTTP, const String& username = emptyString(), const String& password = emptyString());
131
132 #ifndef NDEBUG
133     FILE* getLogFile() const { return m_logFile; }
134     bool isVerbose() const { return m_verbose; }
135 #endif
136
137 private:
138     ProxyInfo m_proxy;
139     CString m_cookieJarFileName;
140     CString m_certificatePath;
141     CurlShareHandle m_shareHandle;
142     std::unique_ptr<CookieJarCurl> m_cookieJar;
143     bool m_ignoreSSLErrors { false };
144
145     CurlContext();
146     void initCookieSession();
147
148
149 #ifndef NDEBUG
150     FILE* m_logFile { nullptr };
151     bool m_verbose { false };
152 #endif
153 };
154
155 // CurlMultiHandle --------------------------------------------
156
157 class CurlMultiHandle {
158     WTF_MAKE_NONCOPYABLE(CurlMultiHandle);
159
160 public:
161     CurlMultiHandle();
162     ~CurlMultiHandle();
163
164     CURLMcode addHandle(CURL*);
165     CURLMcode removeHandle(CURL*);
166
167     CURLMcode getFdSet(fd_set&, fd_set&, fd_set&, int&);
168     CURLMcode perform(int&);
169     CURLMsg* readInfo(int&);
170
171 private:
172     CURLM* m_multiHandle { nullptr };
173 };
174
175 // CurlSList -------------------------------------------------
176
177 class CurlSList {
178 public:
179     CurlSList() { }
180     ~CurlSList() { clear(); }
181
182     operator struct curl_slist** () { return &m_list; }
183
184     const struct curl_slist* head() const { return m_list; }
185     bool isEmpty() const { return !m_list; }
186     void clear()
187     {
188         if (m_list) {
189             curl_slist_free_all(m_list);
190             m_list = nullptr;
191         }
192     }
193
194     void append(const char* str) { m_list = curl_slist_append(m_list, str); }
195     void append(const String& str) { append(str.latin1().data()); }
196
197 private:
198     struct curl_slist* m_list { nullptr };
199 };
200
201 // CurlHandle -------------------------------------------------
202
203 class HTTPHeaderMap;
204 class NetworkLoadMetrics;
205
206 class CurlHandle {
207     WTF_MAKE_NONCOPYABLE(CurlHandle);
208
209 public:
210     enum VerifyPeer {
211         VerifyPeerDisable = 0L,
212         VerifyPeerEnable = 1L
213     };
214
215     enum VerifyHost {
216         VerifyHostLooseNameCheck = 0,
217         VerifyHostStrictNameCheck = 2
218     };
219
220     CurlHandle();
221     ~CurlHandle();
222
223     CURL* handle() const { return m_handle; }
224
225     void initialize();
226
227     CURLcode perform();
228     CURLcode pause(int);
229
230     CURLcode errorCode() const { return m_errorCode; }
231     void setErrorCode(CURLcode errorCode) { m_errorCode = errorCode; }
232
233     const String errorDescription() const;
234
235     void enableShareHandle();
236
237     void* privateData() const { return m_privateData; }
238     void setPrivateData(void* userData) { m_privateData = userData; }
239
240     void setUrl(const String&);
241     const char* url() const { return m_url; }
242
243     void appendRequestHeaders(const HTTPHeaderMap&);
244     void appendRequestHeader(const String&, const String&);
245     void appendRequestHeader(const String&);
246     void enableRequestHeaders();
247
248     void enableHttpGetRequest();
249     void enableHttpHeadRequest();
250     void enableHttpPostRequest();
251     void setPostFields(const char*, long);
252     void setPostFieldLarge(curl_off_t);
253     void enableHttpPutRequest();
254     void setInFileSizeLarge(curl_off_t);
255     void setHttpCustomRequest(const String&);
256
257     void enableAcceptEncoding();
258     void enableAllowedProtocols();
259
260     void enableFollowLocation();
261     void enableAutoReferer();
262
263     void enableHttpAuthentication(long);
264     void setHttpAuthUserPass(const String&, const String&);
265
266     void enableCAInfoIfExists();
267     void setSslVerifyPeer(VerifyPeer);
268     void setSslVerifyHost(VerifyHost);
269     void setSslCert(const char*);
270     void setSslCertType(const char*);
271     void setSslKeyPassword(const char*);
272     void setSslErrors(unsigned);
273     unsigned getSslErrors();
274
275     void enableCookieJarIfExists();
276     void setCookieList(const char*);
277     void fetchCookieList(CurlSList &cookies) const;
278
279     void enableProxyIfExists();
280
281     void enableTimeout();
282
283     // Callback function
284     void setHeaderCallbackFunction(curl_write_callback, void*);
285     void setWriteCallbackFunction(curl_write_callback, void*);
286     void setReadCallbackFunction(curl_read_callback, void*);
287     void setSslCtxCallbackFunction(curl_ssl_ctx_callback, void*);
288
289     // Status
290     URL getEffectiveURL();
291     std::optional<uint16_t> getPrimaryPort();
292     std::optional<long> getResponseCode();
293     std::optional<long long> getContentLenghtDownload();
294     std::optional<long> getHttpAuthAvail();
295     std::optional<NetworkLoadMetrics> getTimes();
296
297     static long long maxCurlOffT();
298
299 #ifndef NDEBUG
300     void enableVerboseIfUsed();
301     void enableStdErrIfUsed();
302 #endif
303
304 private:
305     void clearUrl();
306
307     static int expectedSizeOfCurlOffT();
308
309     CURL* m_handle { nullptr };
310     char m_errorBuffer[CURL_ERROR_SIZE] { };
311     CURLcode m_errorCode;
312     unsigned m_sslErrors { 0 };
313
314     char* m_url { nullptr };
315     void* m_privateData { nullptr };
316     CurlSList m_requestHeaders;
317 };
318
319 }