Changeset 222665 in webkit


Ignore:
Timestamp:
Sep 29, 2017 2:19:32 PM (6 years ago)
Author:
commit-queue@webkit.org
Message:

[Curl] Extract a features to manage HTTP communication from ResourceHandle
https://bugs.webkit.org/show_bug.cgi?id=175148

Patch by Basuke Suzuki <Basuke Suzuki> on 2017-09-29
Reviewed by Alex Christensen.

  • platform/Curl.cmake:
  • platform/network/curl/CurlRequest.cpp: Added.

(WebCore::CurlRequest::CurlRequest):
(WebCore::CurlRequest::setUserPass):
(WebCore::CurlRequest::start):
(WebCore::CurlRequest::startWithJobManager):
(WebCore::CurlRequest::cancel):
(WebCore::CurlRequest::suspend):
(WebCore::CurlRequest::resume):
(WebCore::CurlRequest::callDelegate):
(WebCore::CurlRequest::setupTransfer):
(WebCore::CurlRequest::willSetupSslCtx):
(WebCore::CurlRequest::willSendData):
(WebCore::CurlRequest::didReceiveHeader):
(WebCore::CurlRequest::didReceiveData):
(WebCore::CurlRequest::didCompleteTransfer):
(WebCore::CurlRequest::didCancelTransfer):
(WebCore::CurlRequest::resolveBlobReferences):
(WebCore::CurlRequest::setupPUT):
(WebCore::CurlRequest::setupPOST):
(WebCore::CurlRequest::setupFormData):
(WebCore::CurlRequest::invokeDidReceiveResponseForFile):
(WebCore::CurlRequest::invokeDidReceiveResponse):
(WebCore::CurlRequest::setPaused):
(WebCore::CurlRequest::willSetupSslCtxCallback):
(WebCore::CurlRequest::willSendDataCallback):
(WebCore::CurlRequest::didReceiveHeaderCallback):
(WebCore::CurlRequest::didReceiveDataCallback):

  • platform/network/curl/CurlRequest.h: Added.

(WebCore::CurlRequest::~CurlRequest):
(WebCore::CurlRequest::setDelegate):
(WebCore::CurlRequest::isSyncRequest):
(WebCore::CurlRequest::getNetworkLoadMetrics):

  • platform/network/curl/CurlRequestDelegate.h: Added.
  • platform/network/curl/ResourceHandleCurl.cpp:

(WebCore::ResourceHandle::cancel):
(WebCore::ResourceHandle::platformSetDefersLoading):
(WebCore::ResourceHandle::didReceiveAuthenticationChallenge):
(WebCore::ResourceHandle::receivedCredential):
(WebCore::ResourceHandle::receivedRequestToContinueWithoutCredential):
(WebCore::ResourceHandle::receivedCancellation):

  • platform/network/curl/ResourceHandleCurlDelegate.cpp:

(WebCore::ResourceHandleCurlDelegate::ResourceHandleCurlDelegate):
(WebCore::ResourceHandleCurlDelegate::~ResourceHandleCurlDelegate):
(WebCore::ResourceHandleCurlDelegate::start):
(WebCore::ResourceHandleCurlDelegate::cancel):
(WebCore::ResourceHandleCurlDelegate::setDefersLoading):
(WebCore::ResourceHandleCurlDelegate::setAuthentication):
(WebCore::ResourceHandleCurlDelegate::dispatchSynchronousJob):
(WebCore::ResourceHandleCurlDelegate::createCurlRequest):
(WebCore::ResourceHandleCurlDelegate::cancelledOrClientless):
(WebCore::ResourceHandleCurlDelegate::curlDidReceiveResponse):
(WebCore::ResourceHandleCurlDelegate::curlDidReceiveBuffer):
(WebCore::ResourceHandleCurlDelegate::curlDidComplete):
(WebCore::ResourceHandleCurlDelegate::curlDidFailWithError):
(WebCore::ResourceHandleCurlDelegate::response):
(WebCore::ResourceHandleCurlDelegate::getCredential):
(WebCore::ResourceHandleCurlDelegate::retain): Deleted.
(WebCore::ResourceHandleCurlDelegate::release): Deleted.
(WebCore::ResourceHandleCurlDelegate::setupTransfer): Deleted.
(WebCore::ResourceHandleCurlDelegate::didCompleteTransfer): Deleted.
(WebCore::ResourceHandleCurlDelegate::didCancelTransfer): Deleted.
(WebCore::ResourceHandleCurlDelegate::setupAuthentication): Deleted.
(WebCore::ResourceHandleCurlDelegate::didReceiveAllHeaders): Deleted.
(WebCore::ResourceHandleCurlDelegate::didReceiveContentData): Deleted.
(WebCore::ResourceHandleCurlDelegate::handleLocalReceiveResponse): Deleted.
(WebCore::ResourceHandleCurlDelegate::prepareSendData): Deleted.
(WebCore::ResourceHandleCurlDelegate::didFinish): Deleted.
(WebCore::ResourceHandleCurlDelegate::didFail): Deleted.
(WebCore::ResourceHandleCurlDelegate::setupPOST): Deleted.
(WebCore::ResourceHandleCurlDelegate::setupPUT): Deleted.
(WebCore::ResourceHandleCurlDelegate::getFormElementsCount): Deleted.
(WebCore::ResourceHandleCurlDelegate::setupFormData): Deleted.
(WebCore::ResourceHandleCurlDelegate::applyAuthentication): Deleted.
(WebCore::ResourceHandleCurlDelegate::getNetworkLoadMetrics): Deleted.
(WebCore::ResourceHandleCurlDelegate::willSetupSslCtx): Deleted.
(WebCore::ResourceHandleCurlDelegate::didReceiveHeader): Deleted.
(WebCore::ResourceHandleCurlDelegate::didReceiveData): Deleted.
(WebCore::ResourceHandleCurlDelegate::willSendData): Deleted.
(WebCore::ResourceHandleCurlDelegate::willSetupSslCtxCallback): Deleted.
(WebCore::ResourceHandleCurlDelegate::didReceiveHeaderCallback): Deleted.
(WebCore::ResourceHandleCurlDelegate::didReceiveDataCallback): Deleted.
(WebCore::ResourceHandleCurlDelegate::willSendDataCallback): Deleted.

  • platform/network/curl/ResourceHandleCurlDelegate.h:
Location:
trunk/Source/WebCore
Files:
3 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r222664 r222665  
     12017-09-29  Basuke Suzuki  <Basuke.Suzuki@sony.com>
     2
     3        [Curl] Extract a features to manage HTTP communication from ResourceHandle
     4        https://bugs.webkit.org/show_bug.cgi?id=175148
     5
     6        Reviewed by Alex Christensen.
     7
     8        * platform/Curl.cmake:
     9        * platform/network/curl/CurlRequest.cpp: Added.
     10        (WebCore::CurlRequest::CurlRequest):
     11        (WebCore::CurlRequest::setUserPass):
     12        (WebCore::CurlRequest::start):
     13        (WebCore::CurlRequest::startWithJobManager):
     14        (WebCore::CurlRequest::cancel):
     15        (WebCore::CurlRequest::suspend):
     16        (WebCore::CurlRequest::resume):
     17        (WebCore::CurlRequest::callDelegate):
     18        (WebCore::CurlRequest::setupTransfer):
     19        (WebCore::CurlRequest::willSetupSslCtx):
     20        (WebCore::CurlRequest::willSendData):
     21        (WebCore::CurlRequest::didReceiveHeader):
     22        (WebCore::CurlRequest::didReceiveData):
     23        (WebCore::CurlRequest::didCompleteTransfer):
     24        (WebCore::CurlRequest::didCancelTransfer):
     25        (WebCore::CurlRequest::resolveBlobReferences):
     26        (WebCore::CurlRequest::setupPUT):
     27        (WebCore::CurlRequest::setupPOST):
     28        (WebCore::CurlRequest::setupFormData):
     29        (WebCore::CurlRequest::invokeDidReceiveResponseForFile):
     30        (WebCore::CurlRequest::invokeDidReceiveResponse):
     31        (WebCore::CurlRequest::setPaused):
     32        (WebCore::CurlRequest::willSetupSslCtxCallback):
     33        (WebCore::CurlRequest::willSendDataCallback):
     34        (WebCore::CurlRequest::didReceiveHeaderCallback):
     35        (WebCore::CurlRequest::didReceiveDataCallback):
     36        * platform/network/curl/CurlRequest.h: Added.
     37        (WebCore::CurlRequest::~CurlRequest):
     38        (WebCore::CurlRequest::setDelegate):
     39        (WebCore::CurlRequest::isSyncRequest):
     40        (WebCore::CurlRequest::getNetworkLoadMetrics):
     41        * platform/network/curl/CurlRequestDelegate.h: Added.
     42        * platform/network/curl/ResourceHandleCurl.cpp:
     43        (WebCore::ResourceHandle::cancel):
     44        (WebCore::ResourceHandle::platformSetDefersLoading):
     45        (WebCore::ResourceHandle::didReceiveAuthenticationChallenge):
     46        (WebCore::ResourceHandle::receivedCredential):
     47        (WebCore::ResourceHandle::receivedRequestToContinueWithoutCredential):
     48        (WebCore::ResourceHandle::receivedCancellation):
     49        * platform/network/curl/ResourceHandleCurlDelegate.cpp:
     50        (WebCore::ResourceHandleCurlDelegate::ResourceHandleCurlDelegate):
     51        (WebCore::ResourceHandleCurlDelegate::~ResourceHandleCurlDelegate):
     52        (WebCore::ResourceHandleCurlDelegate::start):
     53        (WebCore::ResourceHandleCurlDelegate::cancel):
     54        (WebCore::ResourceHandleCurlDelegate::setDefersLoading):
     55        (WebCore::ResourceHandleCurlDelegate::setAuthentication):
     56        (WebCore::ResourceHandleCurlDelegate::dispatchSynchronousJob):
     57        (WebCore::ResourceHandleCurlDelegate::createCurlRequest):
     58        (WebCore::ResourceHandleCurlDelegate::cancelledOrClientless):
     59        (WebCore::ResourceHandleCurlDelegate::curlDidReceiveResponse):
     60        (WebCore::ResourceHandleCurlDelegate::curlDidReceiveBuffer):
     61        (WebCore::ResourceHandleCurlDelegate::curlDidComplete):
     62        (WebCore::ResourceHandleCurlDelegate::curlDidFailWithError):
     63        (WebCore::ResourceHandleCurlDelegate::response):
     64        (WebCore::ResourceHandleCurlDelegate::getCredential):
     65        (WebCore::ResourceHandleCurlDelegate::retain): Deleted.
     66        (WebCore::ResourceHandleCurlDelegate::release): Deleted.
     67        (WebCore::ResourceHandleCurlDelegate::setupTransfer): Deleted.
     68        (WebCore::ResourceHandleCurlDelegate::didCompleteTransfer): Deleted.
     69        (WebCore::ResourceHandleCurlDelegate::didCancelTransfer): Deleted.
     70        (WebCore::ResourceHandleCurlDelegate::setupAuthentication): Deleted.
     71        (WebCore::ResourceHandleCurlDelegate::didReceiveAllHeaders): Deleted.
     72        (WebCore::ResourceHandleCurlDelegate::didReceiveContentData): Deleted.
     73        (WebCore::ResourceHandleCurlDelegate::handleLocalReceiveResponse): Deleted.
     74        (WebCore::ResourceHandleCurlDelegate::prepareSendData): Deleted.
     75        (WebCore::ResourceHandleCurlDelegate::didFinish): Deleted.
     76        (WebCore::ResourceHandleCurlDelegate::didFail): Deleted.
     77        (WebCore::ResourceHandleCurlDelegate::setupPOST): Deleted.
     78        (WebCore::ResourceHandleCurlDelegate::setupPUT): Deleted.
     79        (WebCore::ResourceHandleCurlDelegate::getFormElementsCount): Deleted.
     80        (WebCore::ResourceHandleCurlDelegate::setupFormData): Deleted.
     81        (WebCore::ResourceHandleCurlDelegate::applyAuthentication): Deleted.
     82        (WebCore::ResourceHandleCurlDelegate::getNetworkLoadMetrics): Deleted.
     83        (WebCore::ResourceHandleCurlDelegate::willSetupSslCtx): Deleted.
     84        (WebCore::ResourceHandleCurlDelegate::didReceiveHeader): Deleted.
     85        (WebCore::ResourceHandleCurlDelegate::didReceiveData): Deleted.
     86        (WebCore::ResourceHandleCurlDelegate::willSendData): Deleted.
     87        (WebCore::ResourceHandleCurlDelegate::willSetupSslCtxCallback): Deleted.
     88        (WebCore::ResourceHandleCurlDelegate::didReceiveHeaderCallback): Deleted.
     89        (WebCore::ResourceHandleCurlDelegate::didReceiveDataCallback): Deleted.
     90        (WebCore::ResourceHandleCurlDelegate::willSendDataCallback): Deleted.
     91        * platform/network/curl/ResourceHandleCurlDelegate.h:
     92
    1932017-09-29  Chris Dumez  <cdumez@apple.com>
    294
  • trunk/Source/WebCore/platform/Curl.cmake

    r222223 r222665  
    1212    platform/network/curl/CurlDownload.cpp
    1313    platform/network/curl/CurlJobManager.cpp
     14    platform/network/curl/CurlRequest.cpp
    1415    platform/network/curl/CurlSSLHandle.cpp
    1516    platform/network/curl/CurlSSLVerifier.cpp
  • trunk/Source/WebCore/platform/network/curl/ResourceHandleCurl.cpp

    r222467 r222665  
    3333#if USE(CURL)
    3434
    35 #include "CachedResourceLoader.h"
    3635#include "CredentialStorage.h"
    37 #include "CurlCacheManager.h"
    3836#include "CurlContext.h"
    39 #include "CurlJobManager.h"
    40 #include "CurlSSLHandle.h"
    4137#include "FileSystem.h"
    4238#include "Logging.h"
    43 #include "MIMETypeRegistry.h"
    44 #include "NetworkingContext.h"
    4539#include "ResourceHandleInternal.h"
    4640#include "SynchronousLoaderClient.h"
    47 #include <wtf/text/Base64.h>
    4841
    4942namespace WebCore {
     
    7972void ResourceHandle::cancel()
    8073{
    81     d->m_delegate->cancel();
     74    if (d->m_delegate)
     75        d->m_delegate->cancel();
    8276}
    8377
     
    115109    ASSERT(isMainThread());
    116110
    117     d->m_delegate->setDefersLoading(defers);
     111    if (d->m_delegate)
     112        d->m_delegate->setDefersLoading(defers);
    118113}
    119114
     
    137132        CredentialStorage::defaultCredentialStorage().set(partition, credential, challenge.protectionSpace(), urlToStore);
    138133       
    139         d->m_delegate->setAuthentication(credential.user(), credential.password());
     134        if (d->m_delegate)
     135            d->m_delegate->setAuthentication(credential.user(), credential.password());
    140136
    141137        d->m_user = String();
     
    162158                }
    163159
    164                 d->m_delegate->setAuthentication(credential.user(), credential.password());
     160                if (d->m_delegate)
     161                    d->m_delegate->setAuthentication(credential.user(), credential.password());
    165162                return;
    166163            }
     
    169166
    170167    d->m_currentWebChallenge = challenge;
    171    
    172     if (client())
     168
     169    if (client()) {
     170        auto protectedThis = makeRef(*this);
    173171        client()->didReceiveAuthenticationChallenge(this, d->m_currentWebChallenge);
     172    }
    174173}
    175174
     
    195194    }
    196195
    197     d->m_delegate->setAuthentication(credential.user(), credential.password());
     196    if (d->m_delegate)
     197        d->m_delegate->setAuthentication(credential.user(), credential.password());
     198
    198199    clearAuthentication();
    199200}
     
    206207        return;
    207208
    208     d->m_delegate->setAuthentication("", "");
     209    if (d->m_delegate)
     210        d->m_delegate->setAuthentication("", "");
     211
    209212    clearAuthentication();
    210213}
     
    217220        return;
    218221
    219     if (client())
     222    if (client()) {
     223        auto protectedThis = makeRef(*this);
    220224        client()->receivedCancellation(this, challenge);
     225    }
    221226}
    222227
  • trunk/Source/WebCore/platform/network/curl/ResourceHandleCurlDelegate.cpp

    r222521 r222665  
    3333#if USE(CURL)
    3434
     35#include "AuthenticationChallenge.h"
    3536#include "CredentialStorage.h"
    3637#include "CurlCacheManager.h"
     38#include "CurlRequest.h"
    3739#include "HTTPParsers.h"
    38 #include "MIMETypeRegistry.h"
    3940#include "MultipartHandle.h"
    40 #include "ResourceHandle.h"
    4141#include "ResourceHandleInternal.h"
    4242#include "SharedBuffer.h"
    4343#include "TextEncoding.h"
    44 #include "URL.h"
    45 #include <wtf/MainThread.h>
    4644#include <wtf/text/Base64.h>
    4745
     
    5149    : m_handle(handle)
    5250    , m_firstRequest(handle->firstRequest().isolatedCopy())
    53     , m_customHTTPHeaderFields(m_firstRequest.httpHeaderFields().isolatedCopy())
     51    , m_currentRequest(handle->firstRequest().isolatedCopy())
    5452    , m_shouldUseCredentialStorage(handle->shouldUseCredentialStorage())
    5553    , m_user(handle->getInternal()->m_user.isolatedCopy())
     
    5856    , m_defersLoading(handle->getInternal()->m_defersLoading)
    5957{
    60     const URL& url = m_firstRequest.url();
    61 
    62     if (m_customHTTPHeaderFields.size()) {
    63         auto& cache = CurlCacheManager::getInstance();
    64         bool hasCacheHeaders = m_customHTTPHeaderFields.contains(HTTPHeaderName::IfModifiedSince) || m_customHTTPHeaderFields.contains(HTTPHeaderName::IfNoneMatch);
    65         if (!hasCacheHeaders && cache.isCached(url)) {
    66             cache.addCacheEntryClient(url, m_handle);
    67             // append additional cache information
    68             for (auto entry : cache.requestHeaders(url))
    69                 m_customHTTPHeaderFields.set(entry.key, entry.value);
    70             m_addedCacheValidationHeaders = true;
    71         }
    72     }
    73 
    74     setupAuthentication();
     58
    7559}
    7660
    7761ResourceHandleCurlDelegate::~ResourceHandleCurlDelegate()
    7862{
     63    if (m_curlRequest)
     64        m_curlRequest->setDelegate(nullptr);
    7965}
    8066
     
    8975}
    9076
    91 void ResourceHandleCurlDelegate::start(bool isSyncRequest)
    92 {
    93     m_isSyncRequest = isSyncRequest;
    94 
    95     if (!m_isSyncRequest) {
    96         // For asynchronous, use CurlJobManager. Curl processes runs on sub thread.
    97         CurlJobManager::singleton().add(this);
    98     } else {
    99         // For synchronous, does not use CurlJobManager. Curl processes runs on main thread.
    100         retain();
    101         setupTransfer();
    102 
    103         // curl_easy_perform blocks until the transfer is finished.
    104         CURLcode resultCode = m_curlHandle->perform();
    105         didCompleteTransfer(resultCode);
    106         release();
    107     }
     77bool ResourceHandleCurlDelegate::start()
     78{
     79    ASSERT(isMainThread());
     80
     81    auto credential = getCredential(m_currentRequest, false);
     82
     83    m_curlRequest = createCurlRequest(m_currentRequest);
     84    m_curlRequest->setUserPass(credential.first, credential.second);
     85    m_curlRequest->start();
     86
     87    return true;
    10888}
    10989
    11090void ResourceHandleCurlDelegate::cancel()
    11191{
     92    ASSERT(isMainThread());
     93
    11294    releaseHandle();
    11395
    114     if (!m_isSyncRequest)
    115         CurlJobManager::singleton().cancel(this);
     96    if (!m_curlRequest)
     97        m_curlRequest->cancel();
    11698}
    11799
    118100void ResourceHandleCurlDelegate::setDefersLoading(bool defers)
    119101{
     102    ASSERT(isMainThread());
     103
    120104    if (defers == m_defersLoading)
    121105        return;
     
    123107    m_defersLoading = defers;
    124108
    125     auto action = [protectedThis = makeRef(*this)]() {
    126         if (!protectedThis->m_curlHandle)
    127             return;
    128 
    129         if (protectedThis->m_defersLoading) {
    130             CURLcode error = protectedThis->m_curlHandle->pause(CURLPAUSE_ALL);
    131             // If we could not defer the handle, so don't do it.
    132             if (error != CURLE_OK)
    133                 return;
    134         } else {
    135             CURLcode error = protectedThis->m_curlHandle->pause(CURLPAUSE_CONT);
    136             if (error != CURLE_OK) {
    137                 // Restarting the handle has failed so just cancel it.
    138                 protectedThis->m_handle->cancel();
    139             }
    140         }
    141     };
    142 
    143     CurlJobManager::singleton().callOnJobThread(WTFMove(action));
    144 }
    145 
    146 void ResourceHandleCurlDelegate::setAuthentication(const String& user, const String& pass)
    147 {
    148     auto action = [protectedThis = makeRef(*this), user = user.isolatedCopy(), pass = pass.isolatedCopy()]() {
    149         protectedThis->m_user = user;
    150         protectedThis->m_pass = pass;
    151         if (protectedThis->m_curlHandle)
    152             protectedThis->m_curlHandle->setHttpAuthUserPass(user, pass);
    153     };
    154 
    155     CurlJobManager::singleton().callOnJobThread(WTFMove(action));
     109    if (!m_curlRequest)
     110        return;
     111
     112    if (m_defersLoading)
     113        m_curlRequest->suspend();
     114    else
     115        m_curlRequest->resume();
     116}
     117
     118void ResourceHandleCurlDelegate::setAuthentication(const String& user, const String& password)
     119{
     120    ASSERT(isMainThread());
     121
     122    if (!m_curlRequest)
     123        return;
     124
     125    bool isSyncRequest = m_curlRequest->isSyncRequest();
     126    m_curlRequest->cancel();
     127    m_curlRequest->setDelegate(nullptr);
     128
     129    m_curlRequest = createCurlRequest(m_currentRequest);
     130    m_curlRequest->setUserPass(user, password);
     131    m_curlRequest->start(isSyncRequest);
    156132}
    157133
    158134void ResourceHandleCurlDelegate::dispatchSynchronousJob()
    159135{
    160     if (m_firstRequest.url().protocolIsData()) {
     136    if (m_currentRequest.url().protocolIsData()) {
    161137        handleDataURL();
    162138        return;
     
    168144    m_defersLoading = false;
    169145
    170     start(true);
    171 }
    172 
    173 void ResourceHandleCurlDelegate::retain()
    174 {
    175     ref();
    176 }
    177 
    178 void ResourceHandleCurlDelegate::release()
    179 {
    180     deref();
    181 }
    182 
    183 CURL* ResourceHandleCurlDelegate::setupTransfer()
    184 {
    185     m_curlHandle = std::make_unique<CurlHandle>();
    186     m_curlHandle->initialize();
    187 
    188     if (m_defersLoading) {
    189         CURLcode error = m_curlHandle->pause(CURLPAUSE_ALL);
    190         // If we did not pause the handle, we would ASSERT in the
    191         // header callback. So just assert here.
    192         ASSERT_UNUSED(error, error == CURLE_OK);
    193     }
    194 
    195 #ifndef NDEBUG
    196     m_curlHandle->enableVerboseIfUsed();
    197     m_curlHandle->enableStdErrIfUsed();
    198 #endif
    199 
    200     auto& sslHandle = CurlContext::singleton().sslHandle();
    201 
    202     m_curlHandle->setSslVerifyPeer(CurlHandle::VerifyPeer::Enable);
    203     m_curlHandle->setSslVerifyHost(CurlHandle::VerifyHost::StrictNameCheck);
    204     m_curlHandle->setWriteCallbackFunction(didReceiveDataCallback, this);
    205     m_curlHandle->setHeaderCallbackFunction(didReceiveHeaderCallback, this);
    206     m_curlHandle->enableAutoReferer();
    207     m_curlHandle->enableFollowLocation();
    208     m_curlHandle->enableHttpAuthentication(CURLAUTH_ANY);
    209     m_curlHandle->enableShareHandle();
    210     m_curlHandle->enableTimeout();
    211     m_curlHandle->enableAllowedProtocols();
    212 
    213     auto sslClientCertificate = sslHandle.getSSLClientCertificate(m_firstRequest.url().host());
    214     if (sslClientCertificate) {
    215         m_curlHandle->setSslCert(sslClientCertificate->first.utf8().data());
    216         m_curlHandle->setSslCertType("P12");
    217         m_curlHandle->setSslKeyPassword(sslClientCertificate->second.utf8().data());
    218     }
    219 
    220     if (sslHandle.shouldIgnoreSSLErrors())
    221         m_curlHandle->setSslVerifyPeer(CurlHandle::VerifyPeer::Disable);
    222     else
    223         m_curlHandle->setSslCtxCallbackFunction(willSetupSslCtxCallback, this);
    224 
    225     m_curlHandle->setCACertPath(sslHandle.getCACertPath());
    226 
    227     m_curlHandle->enableAcceptEncoding();
    228     m_curlHandle->setUrl(m_firstRequest.url());
    229     m_curlHandle->enableCookieJarIfExists();
    230 
    231     if (m_customHTTPHeaderFields.size())
    232         m_curlHandle->appendRequestHeaders(m_customHTTPHeaderFields);
    233 
    234     String method = m_firstRequest.httpMethod();
    235     if ("GET" == method)
    236         m_curlHandle->enableHttpGetRequest();
    237     else if ("POST" == method)
    238         setupPOST();
    239     else if ("PUT" == method)
    240         setupPUT();
    241     else if ("HEAD" == method)
    242         m_curlHandle->enableHttpHeadRequest();
    243     else {
    244         m_curlHandle->setHttpCustomRequest(method);
    245         setupPUT();
    246     }
    247 
    248     applyAuthentication();
    249 
    250     m_curlHandle->enableProxyIfExists();
    251 
    252     return m_curlHandle->handle();
    253 }
    254 
    255 void ResourceHandleCurlDelegate::didCompleteTransfer(CURLcode result)
    256 {
    257     if (result == CURLE_OK) {
    258         NetworkLoadMetrics networkLoadMetrics = getNetworkLoadMetrics();
    259 
    260         if (isMainThread())
    261             didFinish(networkLoadMetrics);
    262         else {
    263             callOnMainThread([protectedThis = makeRef(*this), metrics = networkLoadMetrics.isolatedCopy()] {
    264                 if (!protectedThis->m_handle)
    265                     return;
    266                 protectedThis->didFinish(metrics);
    267             });
    268         }
    269     } else {
    270         ResourceError resourceError = ResourceError::httpError(result, m_firstRequest.url());
    271         if (m_sslVerifier.sslErrors())
    272             resourceError.setSslErrors(m_sslVerifier.sslErrors());
    273 
    274         if (isMainThread())
    275             didFail(resourceError);
    276         else {
    277             callOnMainThread([protectedThis = makeRef(*this), error = resourceError.isolatedCopy()] {
    278                 if (!protectedThis->m_handle)
    279                     return;
    280                 protectedThis->didFail(error);
    281             });
    282         }
    283     }
    284 
    285     m_formDataStream = nullptr;
    286     m_curlHandle = nullptr;
    287 }
    288 
    289 void ResourceHandleCurlDelegate::didCancelTransfer()
    290 {
    291     m_formDataStream = nullptr;
    292     m_curlHandle = nullptr;
    293 }
    294 
    295 ResourceResponse& ResourceHandleCurlDelegate::response()
    296 {
    297     return m_handle->getInternal()->m_response;
    298 }
    299 
    300 void ResourceHandleCurlDelegate::setupAuthentication()
    301 {
    302     // m_user/m_pass are credentials given manually, for instance, by the arguments passed to XMLHttpRequest.open().
    303     String partition = m_firstRequest.cachePartition();
    304 
    305     if (m_shouldUseCredentialStorage) {
    306         if (m_user.isEmpty() && m_pass.isEmpty()) {
    307             // <rdar://problem/7174050> - For URLs that match the paths of those previously challenged for HTTP Basic authentication,
    308             // try and reuse the credential preemptively, as allowed by RFC 2617.
    309             m_initialCredential = CredentialStorage::defaultCredentialStorage().get(partition, m_firstRequest.url());
    310         } else {
    311             // If there is already a protection space known for the URL, update stored credentials
    312             // before sending a request. This makes it possible to implement logout by sending an
    313             // XMLHttpRequest with known incorrect credentials, and aborting it immediately (so that
    314             // an authentication dialog doesn't pop up).
    315             CredentialStorage::defaultCredentialStorage().set(partition, Credential(m_user, m_pass, CredentialPersistenceNone), m_firstRequest.url());
    316         }
    317     }
    318 }
    319 
    320 void ResourceHandleCurlDelegate::didReceiveAllHeaders(const CurlResponse& receivedResponse)
    321 {
    322     ASSERT(isMainThread());
     146    m_curlRequest = createCurlRequest(m_currentRequest);
     147    m_curlRequest->start(true);
     148}
     149
     150RefPtr<CurlRequest> ResourceHandleCurlDelegate::createCurlRequest(ResourceRequest& request)
     151{
     152    ASSERT(isMainThread());
     153
     154    // CurlCache : append additional cache information
     155    m_addedCacheValidationHeaders = false;
     156
     157    bool hasCacheHeaders = request.httpHeaderFields().contains(HTTPHeaderName::IfModifiedSince) || request.httpHeaderFields().contains(HTTPHeaderName::IfNoneMatch);
     158    if (!hasCacheHeaders) {
     159        auto& cache = CurlCacheManager::getInstance();
     160        URL cacheUrl = request.url();
     161        cacheUrl.removeFragmentIdentifier();
     162
     163        if (cache.isCached(cacheUrl)) {
     164            cache.addCacheEntryClient(cacheUrl, m_handle);
     165
     166            for (auto entry : cache.requestHeaders(cacheUrl))
     167                request.addHTTPHeaderField(entry.key, entry.value);
     168
     169            m_addedCacheValidationHeaders = true;
     170        }
     171    }
     172
     173    return adoptRef(new CurlRequest(request, this, m_defersLoading));
     174}
     175
     176bool ResourceHandleCurlDelegate::cancelledOrClientless()
     177{
     178    if (!m_handle)
     179        return true;
     180
     181    return !m_handle->client();
     182}
     183
     184void ResourceHandleCurlDelegate::curlDidReceiveResponse(const CurlResponse& receivedResponse)
     185{
     186    ASSERT(isMainThread());
     187    ASSERT(!m_defersLoading);
     188
     189    if (cancelledOrClientless())
     190        return;
    323191
    324192    m_handle->getInternal()->m_response = ResourceResponse(receivedResponse);
     193
     194    if (m_curlRequest)
     195        m_handle->getInternal()->m_response.setDeprecatedNetworkLoadMetrics(m_curlRequest->getNetworkLoadMetrics());
    325196
    326197    if (response().isMultipart()) {
     
    347218            return;
    348219        }
    349     } else if (response().isUnauthorized()) {
     220    }
     221
     222    if (response().isUnauthorized()) {
    350223        AuthenticationChallenge challenge(receivedResponse, m_authFailureCount, response(), m_handle);
    351224        m_handle->didReceiveAuthenticationChallenge(challenge);
     
    354227    }
    355228
    356     m_didNotifyResponse = true;
    357 
    358229    if (m_handle->client()) {
    359230        if (response().isNotModified()) {
    360             const String& url = m_firstRequest.url().string();
    361             if (CurlCacheManager::getInstance().getCachedResponse(url, response())) {
     231            URL cacheUrl = m_currentRequest.url();
     232            cacheUrl.removeFragmentIdentifier();
     233
     234            if (CurlCacheManager::getInstance().getCachedResponse(cacheUrl, response())) {
    362235                if (m_addedCacheValidationHeaders) {
    363236                    response().setHTTPStatusCode(200);
     
    366239            }
    367240        }
     241
    368242        CurlCacheManager::getInstance().didReceiveResponse(*m_handle, response());
    369243        m_handle->client()->didReceiveResponse(m_handle, ResourceResponse(response()));
     
    371245}
    372246
    373 void ResourceHandleCurlDelegate::didReceiveContentData(Ref<SharedBuffer>&& buffer)
    374 {
    375     ASSERT(isMainThread());
    376 
    377     if (!m_didNotifyResponse)
    378         handleLocalReceiveResponse();
     247void ResourceHandleCurlDelegate::curlDidReceiveBuffer(Ref<SharedBuffer>&& buffer)
     248{
     249    ASSERT(isMainThread());
     250
     251    if (cancelledOrClientless())
     252        return;
    379253
    380254    if (m_multipartHandle)
     
    386260}
    387261
    388 void ResourceHandleCurlDelegate::handleLocalReceiveResponse()
    389 {
    390     ASSERT(isMainThread());
    391 
    392     // since the code in headerCallback will not have run for local files
    393     // the code to set the URL and fire didReceiveResponse is never run,
    394     // which means the ResourceLoader's response does not contain the URL.
    395     // Run the code here for local files to resolve the issue.
    396     // TODO: See if there is a better approach for handling this.
    397     URL url = m_curlHandle->getEffectiveURL();
    398     ASSERT(url.isValid());
    399     response().setURL(url);
    400 
    401     // Determine the MIME type based on the path.
    402     response().setMimeType(MIMETypeRegistry::getMIMETypeForPath(url));
    403 
    404     m_didNotifyResponse = true;
    405 
    406     if (m_handle->client())
    407         m_handle->client()->didReceiveResponse(m_handle, ResourceResponse(response()));
    408 }
    409 
    410 void ResourceHandleCurlDelegate::prepareSendData(char* buffer, size_t blockSize, size_t numberOfBlocks)
    411 {
    412     ASSERT(isMainThread());
    413     ASSERT(!m_sendBytes);
    414 
    415     std::unique_lock<Lock> lock(m_workerThreadMutex);
    416 
    417     if (!m_formDataStream || !m_formDataStream->hasMoreElements()) {
    418         m_workerThreadConditionVariable.notifyOne();
    419         return;
    420     }
    421 
    422     size_t size = m_formDataStream->read(buffer, blockSize, numberOfBlocks);
    423     if (!size) {
    424         // Something went wrong so cancel the job.
    425         m_handle->cancel();
    426         m_workerThreadConditionVariable.notifyOne();
    427         return;
    428     }
    429 
    430     m_sendBytes = size;
    431     m_workerThreadConditionVariable.notifyOne();
    432 }
    433 
    434 void ResourceHandleCurlDelegate::didFinish(NetworkLoadMetrics networkLoadMetrics)
    435 {
    436     response().setDeprecatedNetworkLoadMetrics(networkLoadMetrics);
    437 
    438     if (!m_handle)
    439         return;
    440 
    441     if (!m_didNotifyResponse) {
    442         handleLocalReceiveResponse();
    443         if (!m_handle)
    444             return;
    445     }
     262void ResourceHandleCurlDelegate::curlDidComplete()
     263{
     264    ASSERT(isMainThread());
     265
     266    if (cancelledOrClientless())
     267        return;
     268
     269    if (m_curlRequest)
     270        m_handle->getInternal()->m_response.setDeprecatedNetworkLoadMetrics(m_curlRequest->getNetworkLoadMetrics());
    446271
    447272    if (m_multipartHandle)
     
    454279}
    455280
    456 void ResourceHandleCurlDelegate::didFail(const ResourceError& resourceError)
    457 {
    458     if (!m_handle)
    459         return;
    460 
    461     if (m_handle->client()) {
    462         CurlCacheManager::getInstance().didFail(*m_handle);
    463         m_handle->client()->didFail(m_handle, resourceError);
    464     }
     281void ResourceHandleCurlDelegate::curlDidFailWithError(const ResourceError& resourceError)
     282{
     283    ASSERT(isMainThread());
     284
     285    if (cancelledOrClientless())
     286        return;
     287
     288    CurlCacheManager::getInstance().didFail(*m_handle);
     289    m_handle->client()->didFail(m_handle, resourceError);
     290}
     291
     292ResourceResponse& ResourceHandleCurlDelegate::response()
     293{
     294    return m_handle->getInternal()->m_response;
    465295}
    466296
     
    527357}
    528358
    529 void ResourceHandleCurlDelegate::setupPOST()
    530 {
    531     m_curlHandle->enableHttpPostRequest();
    532 
    533     size_t numElements = getFormElementsCount();
    534     if (!numElements)
    535         return;
    536 
    537     // Do not stream for simple POST data
    538     if (numElements == 1) {
    539         m_postBytes = m_firstRequest.httpBody()->flatten();
    540         if (m_postBytes.size())
    541             m_curlHandle->setPostFields(m_postBytes.data(), m_postBytes.size());
    542         return;
    543     }
    544 
    545     setupFormData(true);
    546 }
    547 
    548 void ResourceHandleCurlDelegate::setupPUT()
    549 {
    550     m_curlHandle->enableHttpPutRequest();
    551 
    552     // Disable the Expect: 100 continue header
    553     m_curlHandle->removeRequestHeader("Expect");
    554 
    555     size_t numElements = getFormElementsCount();
    556     if (!numElements)
    557         return;
    558 
    559     setupFormData(false);
    560 }
    561 
    562 size_t ResourceHandleCurlDelegate::getFormElementsCount()
    563 {
    564     RefPtr<FormData> formData = m_firstRequest.httpBody();
    565     if (!formData)
    566         return 0;
    567 
    568     // Resolve the blob elements so the formData can correctly report it's size.
    569     formData = formData->resolveBlobReferences();
    570     size_t size = formData->elements().size();
    571     m_firstRequest.setHTTPBody(WTFMove(formData));
    572     return size;
    573 }
    574 
    575 void ResourceHandleCurlDelegate::setupFormData(bool isPostRequest)
    576 {
    577     Vector<FormDataElement> elements = m_firstRequest.httpBody()->elements();
    578     size_t numElements = elements.size();
    579 
    580     static const long long maxCurlOffT = m_curlHandle->maxCurlOffT();
    581 
    582     // Obtain the total size of the form data
    583     curl_off_t size = 0;
    584     bool chunkedTransfer = false;
    585     for (size_t i = 0; i < numElements; i++) {
    586         FormDataElement element = elements[i];
    587         if (element.m_type == FormDataElement::Type::EncodedFile) {
    588             long long fileSizeResult;
    589             if (getFileSize(element.m_filename, fileSizeResult)) {
    590                 if (fileSizeResult > maxCurlOffT) {
    591                     // File size is too big for specifying it to cURL
    592                     chunkedTransfer = true;
    593                     break;
    594                 }
    595                 size += fileSizeResult;
    596             } else {
    597                 chunkedTransfer = true;
    598                 break;
    599             }
    600         } else
    601             size += elements[i].m_data.size();
    602     }
    603 
    604     // cURL guesses that we want chunked encoding as long as we specify the header
    605     if (chunkedTransfer)
    606         m_curlHandle->appendRequestHeader("Transfer-Encoding: chunked");
    607     else {
    608         if (isPostRequest)
    609             m_curlHandle->setPostFieldLarge(size);
    610         else
    611             m_curlHandle->setInFileSizeLarge(size);
    612     }
    613 
    614     m_formDataStream = std::make_unique<FormDataStream>();
    615     m_formDataStream->setHTTPBody(m_firstRequest.httpBody());
    616 
    617     m_curlHandle->setReadCallbackFunction(willSendDataCallback, this);
    618 }
    619 
    620 void ResourceHandleCurlDelegate::applyAuthentication()
    621 {
     359std::pair<String, String> ResourceHandleCurlDelegate::getCredential(ResourceRequest& request, bool redirect)
     360{
     361    // m_user/m_pass are credentials given manually, for instance, by the arguments passed to XMLHttpRequest.open().
     362    String partition = request.cachePartition();
     363
     364    if (m_shouldUseCredentialStorage) {
     365        if (m_user.isEmpty() && m_pass.isEmpty()) {
     366            // <rdar://problem/7174050> - For URLs that match the paths of those previously challenged for HTTP Basic authentication,
     367            // try and reuse the credential preemptively, as allowed by RFC 2617.
     368            m_initialCredential = CredentialStorage::defaultCredentialStorage().get(partition, request.url());
     369        } else if (!redirect) {
     370            // If there is already a protection space known for the URL, update stored credentials
     371            // before sending a request. This makes it possible to implement logout by sending an
     372            // XMLHttpRequest with known incorrect credentials, and aborting it immediately (so that
     373            // an authentication dialog doesn't pop up).
     374            CredentialStorage::defaultCredentialStorage().set(partition, Credential(m_user, m_pass, CredentialPersistenceNone), request.url());
     375        }
     376    }
     377
    622378    String user = m_user;
    623379    String password = m_pass;
     
    626382        user = m_initialCredential.user();
    627383        password = m_initialCredential.password();
    628         m_curlHandle->enableHttpAuthentication(CURLAUTH_BASIC);
    629     }
    630 
    631     // It seems we need to set CURLOPT_USERPWD even if username and password is empty.
    632     // Otherwise cURL will not automatically continue with a new request after a 401 response.
    633 
    634     // curl CURLOPT_USERPWD expects username:password
    635     m_curlHandle->setHttpAuthUserPass(user, password);
    636 }
    637 
    638 NetworkLoadMetrics ResourceHandleCurlDelegate::getNetworkLoadMetrics()
    639 {
    640     NetworkLoadMetrics networkLoadMetrics;
    641     if (auto metrics = m_curlHandle->getNetworkLoadMetrics())
    642         networkLoadMetrics = *metrics;
    643 
    644     return networkLoadMetrics;
    645 }
    646 
    647 CURLcode ResourceHandleCurlDelegate::willSetupSslCtx(void* sslCtx)
    648 {
    649     m_sslVerifier.setCurlHandle(m_curlHandle.get());
    650     m_sslVerifier.setHostName(m_firstRequest.url().host());
    651     m_sslVerifier.setSslCtx(sslCtx);
    652 
    653     return CURLE_OK;
    654 }
    655 
    656 /*
    657 * This is being called for each HTTP header in the response. This includes '\r\n'
    658 * for the last line of the header.
    659 *
    660 * We will add each HTTP Header to the ResourceResponse and on the termination
    661 * of the header (\r\n) we will parse Content-Type and Content-Disposition and
    662 * update the ResourceResponse and then send it away.
    663 *
    664 */
    665 size_t ResourceHandleCurlDelegate::didReceiveHeader(String&& header)
    666 {
    667     static const auto emptyLineCRLF = "\r\n";
    668     static const auto emptyLineLF = "\n";
    669 
    670     if (!m_handle)
    671         return 0;
    672 
    673     if (m_defersLoading)
    674         return 0;
    675 
    676     size_t receiveBytes = header.length();
    677 
    678     // The HTTP standard requires to use \r\n but for compatibility it recommends to accept also \n.
    679     // We will add the current header to the CurlResponse.headers
    680     if ((header != emptyLineCRLF) && (header != emptyLineLF)) {
    681         m_response.headers.append(WTFMove(header));
    682         return receiveBytes;
    683     }
    684 
    685     // We can finish and send the ResourceResponse
    686     long statusCode = 0;
    687     if (auto code = m_curlHandle->getResponseCode())
    688         statusCode = *code;
    689 
    690     long httpConnectCode = 0;
    691     if (auto code = m_curlHandle->getHttpConnectCode())
    692         httpConnectCode = *code;
    693 
    694     if ((100 <= statusCode) && (statusCode < 200)) {
    695         // Just return when receiving http info, e.g. HTTP/1.1 100 Continue.
    696         // If not, the request might be cancelled, because the MIME type will be empty for this response.
    697         m_response = CurlResponse();
    698         return receiveBytes;
    699     }
    700 
    701     if (!statusCode && (httpConnectCode == 200)) {
    702         // Comes here when receiving 200 Connection Established. Just return.
    703         m_response = CurlResponse();
    704         return receiveBytes;
    705     }
    706 
    707     // If the FOLLOWLOCATION option is enabled for the curl handle then
    708     // curl will follow the redirections internally. Thus this header callback
    709     // will be called more than one time with the line starting "HTTP" for one job.
    710 
    711     m_response.url = m_curlHandle->getEffectiveURL();
    712     m_response.statusCode = statusCode;
    713 
    714     if (auto length = m_curlHandle->getContentLength())
    715         m_response.expectedContentLength = *length;
    716 
    717     if (auto port = m_curlHandle->getPrimaryPort())
    718         m_response.connectPort = *port;
    719 
    720     if (auto auth = m_curlHandle->getHttpAuthAvail())
    721         m_response.availableHttpAuth = *auth;
    722 
    723     if (isMainThread())
    724         didReceiveAllHeaders(m_response);
    725     else {
    726         callOnMainThread([protectedThis = makeRef(*this), response = m_response.isolatedCopy()] {
    727             if (!protectedThis->m_handle)
    728                 return;
    729             protectedThis->didReceiveAllHeaders(response);
    730         });
    731     }
    732 
    733     return receiveBytes;
    734 }
    735 
    736 // called with data after all headers have been processed via headerCallback
    737 size_t ResourceHandleCurlDelegate::didReceiveData(Ref<SharedBuffer>&& buffer)
    738 {
    739     if (!m_handle)
    740         return 0;
    741 
    742     if (m_defersLoading)
    743         return 0;
    744 
    745     size_t receiveBytes = buffer->size();
    746 
    747     // this shouldn't be necessary but apparently is. CURL writes the data
    748     // of html page even if it is a redirect that was handled internally
    749     // can be observed e.g. on gmail.com
    750     if (auto httpCode = m_curlHandle->getResponseCode()) {
    751         if (*httpCode >= 300 && *httpCode < 400)
    752             return receiveBytes;
    753     }
    754 
    755     if (receiveBytes) {
    756         if (isMainThread())
    757             didReceiveContentData(WTFMove(buffer));
    758         else {
    759             callOnMainThread([protectedThis = makeRef(*this), buf = WTFMove(buffer)]() mutable {
    760                 if (!protectedThis->m_handle)
    761                     return;
    762                 protectedThis->didReceiveContentData(WTFMove(buf));
    763             });
    764         }
    765     }
    766 
    767     return receiveBytes;
    768 }
    769 
    770 /* This is called to obtain HTTP POST or PUT data.
    771 Iterate through FormData elements and upload files.
    772 Carefully respect the given buffer blockSize and fill the rest of the data at the next calls.
    773 */
    774 size_t ResourceHandleCurlDelegate::willSendData(char* buffer, size_t blockSize, size_t numberOfBlocks)
    775 {
    776     ASSERT(!isMainThread());
    777 
    778     if (!m_handle)
    779         return 0;
    780 
    781     if (m_defersLoading)
    782         return 0;
    783 
    784     if (!blockSize || !numberOfBlocks)
    785         return 0;
    786 
    787     {
    788         std::unique_lock<Lock> lock(m_workerThreadMutex);
    789 
    790         m_sendBytes = 0;
    791 
    792         if (isMainThread())
    793             prepareSendData(buffer, blockSize, numberOfBlocks);
    794         else {
    795             callOnMainThread([protectedThis = makeRef(*this), buffer, blockSize, numberOfBlocks] {
    796                 if (!protectedThis->m_handle)
    797                     return;
    798                 protectedThis->prepareSendData(buffer, blockSize, numberOfBlocks);
    799             });
    800 
    801             m_workerThreadConditionVariable.wait(lock, [this] {
    802                 return m_sendBytes;
    803             });
    804         }
    805     }
    806 
    807     return m_sendBytes;
    808 }
    809 
    810 CURLcode ResourceHandleCurlDelegate::willSetupSslCtxCallback(CURL*, void* sslCtx, void* userData)
    811 {
    812     return static_cast<ResourceHandleCurlDelegate*>(userData)->willSetupSslCtx(sslCtx);
    813 }
    814 
    815 size_t ResourceHandleCurlDelegate::didReceiveHeaderCallback(char* ptr, size_t blockSize, size_t numberOfBlocks, void* data)
    816 {
    817     return static_cast<ResourceHandleCurlDelegate*>(const_cast<void*>(data))->didReceiveHeader(String(static_cast<const char*>(ptr), blockSize * numberOfBlocks));
    818 }
    819 
    820 size_t ResourceHandleCurlDelegate::didReceiveDataCallback(char* ptr, size_t blockSize, size_t numberOfBlocks, void* data)
    821 {
    822     return static_cast<ResourceHandleCurlDelegate*>(const_cast<void*>(data))->didReceiveData(SharedBuffer::create(ptr, blockSize * numberOfBlocks));
    823 }
    824 
    825 size_t ResourceHandleCurlDelegate::willSendDataCallback(char* ptr, size_t blockSize, size_t numberOfBlocks, void* data)
    826 {
    827     return static_cast<ResourceHandleCurlDelegate*>(const_cast<void*>(data))->willSendData(ptr, blockSize, numberOfBlocks);
     384    }
     385
     386    if (user.isEmpty() && password.isEmpty())
     387        return std::pair<String, String>("", "");
     388
     389    return std::pair<String, String>(user, password);
    828390}
    829391
  • trunk/Source/WebCore/platform/network/curl/ResourceHandleCurlDelegate.h

    r222521 r222665  
    3030
    3131#include "Credential.h"
    32 #include "CurlJobManager.h"
    33 #include "CurlResponse.h"
    34 #include "CurlSSLVerifier.h"
    35 #include "FormDataStreamCurl.h"
     32#include "CurlRequestDelegate.h"
    3633#include "ResourceRequest.h"
    37 #include "ResourceResponse.h"
    38 #include <wtf/Condition.h>
    39 #include <wtf/ThreadSafeRefCounted.h>
    4034
    4135namespace WebCore {
    4236
     37class CurlRequest;
    4338class MultipartHandle;
    44 class ProtectionSpace;
    45 class ResourceError;
    4639class ResourceHandle;
    47 class SharedBuffer;
     40class ResourceResponse;
    4841
    49 class ResourceHandleCurlDelegate final : public ThreadSafeRefCounted<ResourceHandleCurlDelegate>, public CurlJobClient {
     42class ResourceHandleCurlDelegate final : public ThreadSafeRefCounted<ResourceHandleCurlDelegate>, public CurlRequestDelegate {
    5043public:
    5144    ResourceHandleCurlDelegate(ResourceHandle*);
     
    5548    void releaseHandle();
    5649
    57     bool start() { start(false); return true; }
     50    bool start();
    5851    void cancel();
    5952
     
    6457
    6558private:
    66     void retain() override;
    67     void release() override;
    68 
    69     CURL* handle() override { return m_curlHandle ? m_curlHandle->handle() : nullptr; }
    70     CURL* setupTransfer() override;
    71     void didCompleteTransfer(CURLcode) override;
    72     void didCancelTransfer() override;
    73 
    7459    // Called from main thread.
    7560    ResourceResponse& response();
    7661
    77     void start(bool isSyncRequest);
     62    std::pair<String, String> getCredential(ResourceRequest&, bool);
    7863
    79     void setupAuthentication();
     64    bool cancelledOrClientless();
    8065
    81     void didReceiveAllHeaders(const CurlResponse&);
    82     void didReceiveContentData(Ref<SharedBuffer>&&);
    83     void handleLocalReceiveResponse();
    84     void prepareSendData(char*, size_t blockSize, size_t numberOfBlocks);
    85 
    86     void didFinish(NetworkLoadMetrics);
    87     void didFail(const ResourceError&);
     66    RefPtr<CurlRequest> createCurlRequest(ResourceRequest&);
     67    void curlDidReceiveResponse(const CurlResponse&) override;
     68    void curlDidReceiveBuffer(Ref<SharedBuffer>&&) override;
     69    void curlDidComplete() override;
     70    void curlDidFailWithError(const ResourceError&) override;
    8871
    8972    void handleDataURL();
    9073
    91     // Called from worker thread.
    92     void setupPOST();
    93     void setupPUT();
    94     size_t getFormElementsCount();
    95     void setupFormData(bool);
    96     void applyAuthentication();
    97     NetworkLoadMetrics getNetworkLoadMetrics();
    98 
    99     CURLcode willSetupSslCtx(void*);
    100     size_t didReceiveHeader(String&&);
    101     size_t didReceiveData(Ref<SharedBuffer>&&);
    102     size_t willSendData(char*, size_t blockSize, size_t numberOfBlocks);
    103 
    104     static CURLcode willSetupSslCtxCallback(CURL*, void*, void*);
    105     static size_t didReceiveHeaderCallback(char*, size_t blockSize, size_t numberOfBlocks, void*);
    106     static size_t didReceiveDataCallback(char*, size_t blockSize, size_t numberOfBlocks, void*);
    107     static size_t willSendDataCallback(char*, size_t blockSize, size_t numberOfBlocks, void*);
    108 
    10974    // Used by main thread.
    11075    ResourceHandle* m_handle;
    111     std::unique_ptr<FormDataStream> m_formDataStream;
    11276    std::unique_ptr<MultipartHandle> m_multipartHandle;
    113     unsigned short m_authFailureCount { 0 };
     77    unsigned m_authFailureCount { 0 };
    11478    // Used by worker thread.
    11579    ResourceRequest m_firstRequest;
    116     HTTPHeaderMap m_customHTTPHeaderFields;
     80    ResourceRequest m_currentRequest;
    11781    bool m_shouldUseCredentialStorage;
    11882    String m_user;
     
    12185    bool m_defersLoading;
    12286    bool m_addedCacheValidationHeaders { false };
    123     Vector<char> m_postBytes;
    124     std::unique_ptr<CurlHandle> m_curlHandle;
    125     CurlSSLVerifier m_sslVerifier;
    126     CurlResponse m_response;
    127     bool m_didNotifyResponse { false };
    128     // Used by both threads.
    129     bool m_isSyncRequest { false };
    130     Condition m_workerThreadConditionVariable;
    131     Lock m_workerThreadMutex;
    132     size_t m_sendBytes { 0 };
     87    RefPtr<CurlRequest> m_curlRequest;
    13388};
    13489
Note: See TracChangeset for help on using the changeset viewer.