Move URL from WebCore to WTF
[WebKit-https.git] / Source / WebCore / platform / network / curl / CurlContext.h
index 59c05d2..e741038 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2013 Apple Inc.  All rights reserved.
- * Copyright (C) 2017 Sony Interactive Entertainment Inc.
+ * Copyright (C) 2018 Sony Interactive Entertainment Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #pragma once
 
-#include "CookieJarCurl.h"
+#include "CurlProxySettings.h"
 #include "CurlSSLHandle.h"
-#include "URL.h"
 
 #include <wtf/Lock.h>
 #include <wtf/NeverDestroyed.h>
 #include <wtf/Noncopyable.h>
+#include <wtf/Seconds.h>
 #include <wtf/Threading.h>
+#include <wtf/URL.h>
 
 #if OS(WINDOWS)
 #include <windows.h>
 
 namespace WebCore {
 
-enum class CurlProxyType {
-    Invalid = -1,
-    HTTP = CURLPROXY_HTTP,
-    Socks4 = CURLPROXY_SOCKS4,
-    Socks4A = CURLPROXY_SOCKS4A,
-    Socks5 = CURLPROXY_SOCKS5,
-    Socks5Hostname = CURLPROXY_SOCKS5_HOSTNAME
-};
+// Values taken from http://www.browserscope.org/ following
+// the rule "Do What Every Other Modern Browser Is Doing".
+const long CurlDefaultMaxConnects { -1 }; // -1 : Does not set CURLMOPT_MAXCONNECTS
+const long CurlDefaultMaxTotalConnections { 17 };
+const long CurlDefaultMaxHostConnections { 6 };
 
 // CurlGlobal --------------------------------------------
 // to make the initialization of libcurl happen before other initialization of CurlContext
@@ -83,42 +81,33 @@ public:
 private:
     static void lockCallback(CURL*, curl_lock_data, curl_lock_access, void*);
     static void unlockCallback(CURL*, curl_lock_data, void*);
-    static StaticLock* mutexFor(curl_lock_data);
+    static Lock* mutexFor(curl_lock_data);
 
     CURLSH* m_shareHandle { nullptr };
 };
 
 // CurlContext --------------------------------------------
 
+class CurlRequestScheduler;
+
 class CurlContext : public CurlGlobal {
     WTF_MAKE_NONCOPYABLE(CurlContext);
     friend NeverDestroyed<CurlContext>;
 public:
-    struct ProxyInfo {
-        String host;
-        unsigned long port;
-        CurlProxyType type { CurlProxyType::Invalid };
-        String username;
-        String password;
-
-        const String url() const;
-    };
-
-    static CurlContext& singleton();
+    WEBCORE_EXPORT static CurlContext& singleton();
 
     virtual ~CurlContext();
 
     const CurlShareHandle& shareHandle() { return m_shareHandle; }
 
-    // Cookie
-    const char* getCookieJarFileName() const { return m_cookieJarFileName.data(); }
-    void setCookieJarFileName(const char* cookieJarFileName) { m_cookieJarFileName = CString(cookieJarFileName); }
-    CookieJarCurl& cookieJar() { return *m_cookieJar; }
+    CurlRequestScheduler& scheduler() { return *m_scheduler; }
 
     // Proxy
-    const ProxyInfo& proxyInfo() const { return m_proxy; }
-    void setProxyInfo(const ProxyInfo& info) { m_proxy = info;  }
-    void setProxyInfo(const String& host = emptyString(), unsigned long port = 0, CurlProxyType = CurlProxyType::HTTP, const String& username = emptyString(), const String& password = emptyString());
+    const CurlProxySettings& proxySettings() const { return m_proxySettings; }
+    void setProxySettings(CurlProxySettings&& settings) { m_proxySettings = WTFMove(settings); }
+    void setProxyUserPass(const String& user, const String& password) { m_proxySettings.setUserPass(user, password); }
+    void setDefaultProxyAuthMethod() { m_proxySettings.setDefaultAuthMethod(); }
+    void setProxyAuthMethod(long authMethod) { m_proxySettings.setAuthMethod(authMethod); }
 
     // SSL
     CurlSSLHandle& sslHandle() { return m_sslHandle; }
@@ -126,20 +115,28 @@ public:
     // HTTP/2
     bool isHttp2Enabled() const;
 
+    // Timeout
+    Seconds dnsCacheTimeout() const { return m_dnsCacheTimeout; }
+    Seconds connectTimeout() const { return m_connectTimeout; }
+    Seconds defaultTimeoutInterval() const { return m_defaultTimeoutInterval; }
+
 #ifndef NDEBUG
     FILE* getLogFile() const { return m_logFile; }
     bool isVerbose() const { return m_verbose; }
 #endif
 
 private:
-    ProxyInfo m_proxy;
-    CString m_cookieJarFileName;
+    CurlContext();
+    void initShareHandle();
+
+    CurlProxySettings m_proxySettings;
     CurlShareHandle m_shareHandle;
-    std::unique_ptr<CookieJarCurl> m_cookieJar;
     CurlSSLHandle m_sslHandle;
+    std::unique_ptr<CurlRequestScheduler> m_scheduler;
 
-    CurlContext();
-    void initCookieSession();
+    Seconds m_dnsCacheTimeout { Seconds::fromMinutes(5) };
+    Seconds m_connectTimeout { 30.0 };
+    Seconds m_defaultTimeoutInterval { 60.0 };
 
 #ifndef NDEBUG
     FILE* m_logFile { nullptr };
@@ -156,6 +153,10 @@ public:
     CurlMultiHandle();
     ~CurlMultiHandle();
 
+    void setMaxConnects(long);
+    void setMaxTotalConnections(long);
+    void setMaxHostConnections(long);
+
     CURLMcode addHandle(CURL*);
     CURLMcode removeHandle(CURL*);
 
@@ -195,6 +196,8 @@ private:
 
 // CurlHandle -------------------------------------------------
 
+class CertificateInfo;
+class CurlSSLVerifier;
 class HTTPHeaderMap;
 class NetworkLoadMetrics;
 
@@ -216,8 +219,7 @@ public:
     virtual ~CurlHandle();
 
     CURL* handle() const { return m_handle; }
-
-    void initialize();
+    const URL& url() const { return m_url; }
 
     CURLcode perform();
     CURLcode pause(int);
@@ -227,6 +229,7 @@ public:
     void enableShareHandle();
 
     void setUrl(const URL&);
+    void enableSSLForHost(const String&);
 
     void appendRequestHeaders(const HTTPHeaderMap&);
     void appendRequestHeader(const String& name, const String& value);
@@ -243,11 +246,12 @@ public:
     void setInFileSizeLarge(curl_off_t);
     void setHttpCustomRequest(const String&);
 
+    void enableConnectionOnly();
+
     void enableAcceptEncoding();
     void enableAllowedProtocols();
 
-    void enableHttpAuthentication(long);
-    void setHttpAuthUserPass(const String&, const String&);
+    void setHttpAuthUserPass(const String&, const String&, long authType = CURLAUTH_ANY);
 
     void setCACertPath(const char*);
     void setSslVerifyPeer(VerifyPeer);
@@ -255,14 +259,13 @@ public:
     void setSslCert(const char*);
     void setSslCertType(const char*);
     void setSslKeyPassword(const char*);
-
-    void enableCookieJarIfExists();
-    void setCookieList(const char*);
-    void fetchCookieList(CurlSList &cookies) const;
+    void setSslCipherList(const char*);
 
     void enableProxyIfExists();
 
-    void enableTimeout();
+    void setDnsCacheTimeout(Seconds);
+    void setConnectTimeout(Seconds);
+    void setTimeout(Seconds);
 
     // Callback function
     void setHeaderCallbackFunction(curl_write_callback, void*);
@@ -271,13 +274,18 @@ public:
     void setSslCtxCallbackFunction(curl_ssl_ctx_callback, void*);
 
     // Status
-    std::optional<uint16_t> getPrimaryPort();
+    std::optional<String> getProxyUrl();
     std::optional<long> getResponseCode();
     std::optional<long> getHttpConnectCode();
     std::optional<long long> getContentLength();
     std::optional<long> getHttpAuthAvail();
+    std::optional<long> getProxyAuthAvail();
     std::optional<long> getHttpVersion();
-    std::optional<NetworkLoadMetrics> getNetworkLoadMetrics();
+    std::optional<NetworkLoadMetrics> getNetworkLoadMetrics(const WTF::Seconds& domainLookupStart);
+    void addExtraNetworkLoadMetrics(NetworkLoadMetrics&);
+
+    int sslErrors() const;
+    std::optional<CertificateInfo> certificateInfo() const;
 
     static long long maxCurlOffT();
 
@@ -290,10 +298,35 @@ private:
     void enableRequestHeaders();
     static int expectedSizeOfCurlOffT();
 
+    static CURLcode willSetupSslCtxCallback(CURL*, void* sslCtx, void* userData);
+    CURLcode willSetupSslCtx(void* sslCtx);
+
     CURL* m_handle { nullptr };
     char m_errorBuffer[CURL_ERROR_SIZE] { };
 
+    URL m_url;
     CurlSList m_requestHeaders;
+    std::unique_ptr<CurlSSLVerifier> m_sslVerifier;
+};
+
+class CurlSocketHandle : public CurlHandle {
+    WTF_MAKE_NONCOPYABLE(CurlSocketHandle);
+
+public:
+    struct WaitResult {
+        bool readable { false };
+        bool writable { false };
+    };
+
+    CurlSocketHandle(const URL&, Function<void(CURLcode)>&& errorHandler);
+
+    bool connect();
+    size_t send(const uint8_t*, size_t);
+    std::optional<size_t> receive(uint8_t*, size_t);
+    std::optional<WaitResult> wait(const Seconds& timeout, bool alsoWaitForWrite);
+
+private:
+    Function<void(CURLcode)> m_errorHandler;
 };
 
 } // namespace WebCore