Changeset 222756 in webkit


Ignore:
Timestamp:
Oct 2, 2017 4:34:18 PM (7 years ago)
Author:
commit-queue@webkit.org
Message:

[Curl] Implement missing async method in RecourceHandle and make it actually async
https://bugs.webkit.org/show_bug.cgi?id=173964

Patch by Basuke Suzuki <Basuke Suzuki> on 2017-10-02
Reviewed by Alex Christensen.

  • platform/network/ResourceHandle.cpp:

(WebCore::ResourceHandle::continueWillSendRequest): Deleted.
(WebCore::ResourceHandle::continueDidReceiveResponse): Deleted.
(WebCore::ResourceHandle::continueCanAuthenticateAgainstProtectionSpace): Deleted.

  • platform/network/curl/CurlRequest.cpp:

(WebCore::CurlRequest::start):
(WebCore::CurlRequest::cancel):
(WebCore::CurlRequest::suspend):
(WebCore::CurlRequest::resume):
(WebCore::CurlRequest::didReceiveHeader):
(WebCore::CurlRequest::didReceiveData):
(WebCore::CurlRequest::didCompleteTransfer):
(WebCore::CurlRequest::didCancelTransfer):
(WebCore::CurlRequest::finalizeTransfer):
(WebCore::CurlRequest::invokeDidReceiveResponseForFile):
(WebCore::CurlRequest::invokeDidReceiveResponse):
(WebCore::CurlRequest::completeDidReceiveResponse):
(WebCore::CurlRequest::setRequestPaused):
(WebCore::CurlRequest::setCallbackPaused):
(WebCore::CurlRequest::pausedStatusChanged):
(WebCore::CurlRequest::setPaused): Deleted.

  • platform/network/curl/CurlRequest.h:

(WebCore::CurlRequest::needToInvokeDidReceiveResponse const):
(WebCore::CurlRequest::isPaused const):

  • platform/network/curl/ResourceHandleCurl.cpp:

(WebCore::ResourceHandle::receivedRequestToContinueWithoutCredential):
(WebCore::ResourceHandle::continueDidReceiveResponse):
(WebCore::ResourceHandle::platformContinueSynchronousDidReceiveResponse):

  • platform/network/curl/ResourceHandleCurlDelegate.cpp:

(WebCore::ResourceHandleCurlDelegate::curlDidReceiveResponse):
(WebCore::ResourceHandleCurlDelegate::continueDidReceiveResponse):
(WebCore::ResourceHandleCurlDelegate::platformContinueSynchronousDidReceiveResponse):
(WebCore::ResourceHandleCurlDelegate::continueAfterDidReceiveResponse):
(WebCore::ResourceHandleCurlDelegate::shouldRedirectAsGET):

  • platform/network/curl/ResourceHandleCurlDelegate.h:
  • platform/network/curl/ResourceResponseCurl.cpp:

(WebCore::ResourceResponse::shouldRedirect):
(WebCore::ResourceResponse::isMovedPermanently const):
(WebCore::ResourceResponse::isFound const):
(WebCore::ResourceResponse::isSeeOther const):
(WebCore::ResourceResponse::isNotModified const):
(WebCore::ResourceResponse::isUnauthorized const):

Location:
trunk/Source/WebCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r222746 r222756  
     12017-10-02  Basuke Suzuki  <Basuke.Suzuki@sony.com>
     2
     3        [Curl] Implement missing async method in RecourceHandle and make it actually async
     4        https://bugs.webkit.org/show_bug.cgi?id=173964
     5
     6        Reviewed by Alex Christensen.
     7
     8        * platform/network/ResourceHandle.cpp:
     9        (WebCore::ResourceHandle::continueWillSendRequest): Deleted.
     10        (WebCore::ResourceHandle::continueDidReceiveResponse): Deleted.
     11        (WebCore::ResourceHandle::continueCanAuthenticateAgainstProtectionSpace): Deleted.
     12        * platform/network/curl/CurlRequest.cpp:
     13        (WebCore::CurlRequest::start):
     14        (WebCore::CurlRequest::cancel):
     15        (WebCore::CurlRequest::suspend):
     16        (WebCore::CurlRequest::resume):
     17        (WebCore::CurlRequest::didReceiveHeader):
     18        (WebCore::CurlRequest::didReceiveData):
     19        (WebCore::CurlRequest::didCompleteTransfer):
     20        (WebCore::CurlRequest::didCancelTransfer):
     21        (WebCore::CurlRequest::finalizeTransfer):
     22        (WebCore::CurlRequest::invokeDidReceiveResponseForFile):
     23        (WebCore::CurlRequest::invokeDidReceiveResponse):
     24        (WebCore::CurlRequest::completeDidReceiveResponse):
     25        (WebCore::CurlRequest::setRequestPaused):
     26        (WebCore::CurlRequest::setCallbackPaused):
     27        (WebCore::CurlRequest::pausedStatusChanged):
     28        (WebCore::CurlRequest::setPaused): Deleted.
     29        * platform/network/curl/CurlRequest.h:
     30        (WebCore::CurlRequest::needToInvokeDidReceiveResponse const):
     31        (WebCore::CurlRequest::isPaused const):
     32        * platform/network/curl/ResourceHandleCurl.cpp:
     33        (WebCore::ResourceHandle::receivedRequestToContinueWithoutCredential):
     34        (WebCore::ResourceHandle::continueDidReceiveResponse):
     35        (WebCore::ResourceHandle::platformContinueSynchronousDidReceiveResponse):
     36        * platform/network/curl/ResourceHandleCurlDelegate.cpp:
     37        (WebCore::ResourceHandleCurlDelegate::curlDidReceiveResponse):
     38        (WebCore::ResourceHandleCurlDelegate::continueDidReceiveResponse):
     39        (WebCore::ResourceHandleCurlDelegate::platformContinueSynchronousDidReceiveResponse):
     40        (WebCore::ResourceHandleCurlDelegate::continueAfterDidReceiveResponse):
     41        (WebCore::ResourceHandleCurlDelegate::shouldRedirectAsGET):
     42        * platform/network/curl/ResourceHandleCurlDelegate.h:
     43        * platform/network/curl/ResourceResponseCurl.cpp:
     44        (WebCore::ResourceResponse::shouldRedirect):
     45        (WebCore::ResourceResponse::isMovedPermanently const):
     46        (WebCore::ResourceResponse::isFound const):
     47        (WebCore::ResourceResponse::isSeeOther const):
     48        (WebCore::ResourceResponse::isNotModified const):
     49        (WebCore::ResourceResponse::isUnauthorized const):
     50
    1512017-10-02  Ryosuke Niwa  <rniwa@webkit.org>
    252
  • trunk/Source/WebCore/platform/network/ResourceHandle.cpp

    r222728 r222756  
    171171}
    172172
    173 #if !PLATFORM(COCOA) && !USE(CFURLCONNECTION) && !USE(SOUP) && !USE(CURL)
    174 // ResourceHandle never uses async client calls on these platforms yet.
    175 void ResourceHandle::continueWillSendRequest(ResourceRequest&&)
    176 {
    177     notImplemented();
    178 }
    179 
    180 void ResourceHandle::continueDidReceiveResponse()
    181 {
    182     notImplemented();
    183 }
    184 
    185 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
    186 void ResourceHandle::continueCanAuthenticateAgainstProtectionSpace(bool)
    187 {
    188     notImplemented();
    189 }
    190 #endif
    191 #endif
    192 
    193 #if !USE(SOUP)
     173#if !USE(SOUP) && !USE(CURL)
    194174void ResourceHandle::platformContinueSynchronousDidReceiveResponse()
    195175{
  • trunk/Source/WebCore/platform/network/curl/CurlRequest.cpp

    r222730 r222756  
    5757void CurlRequest::start(bool isSyncRequest)
    5858{
     59    // The pausing of transfer does not work with protocols, like file://.
     60    // Therefore, PAUSE can not be done in didReceiveData().
     61    // It means that the same logic as http:// can not be used.
     62    // In the file scheme, invokeDidReceiveResponse() is done first.
     63    // Then StartWithJobManager is called with completeDidReceiveResponse and start transfer with libcurl.
     64
     65    // http : didReceiveHeader => didReceiveData[PAUSE] => invokeDidReceiveResponse => (MainThread)curlDidReceiveResponse => completeDidReceiveResponse[RESUME] => didReceiveData
     66    // file : invokeDidReceiveResponseForFile => (MainThread)curlDidReceiveResponse => completeDidReceiveResponse => didReceiveData
     67
    5968    ASSERT(isMainThread());
    6069
     
    6776        if (url.isLocalFile())
    6877            invokeDidReceiveResponseForFile(url);
    69 
    70         startWithJobManager();
     78        else
     79            startWithJobManager();
    7180    } else {
    7281        // For synchronous, does not use CurlJobManager. Curl processes runs on main thread.
     
    102111        CurlJobManager::singleton().cancel(this);
    103112
    104     setPaused(false);
     113    setRequestPaused(false);
     114    setCallbackPaused(false);
    105115}
    106116
     
    109119    ASSERT(isMainThread());
    110120
    111     setPaused(true);
     121    setRequestPaused(true);
    112122}
    113123
     
    116126    ASSERT(isMainThread());
    117127
    118     setPaused(false);
     128    setRequestPaused(false);
    119129}
    120130
     
    289299        m_networkLoadMetrics = *metrics;
    290300
    291     invokeDidReceiveResponse();
     301    // Response will send at didReceiveData() or didCompleteTransfer()
     302    // to receive continueDidRceiveResponse() for asynchronously.
    292303
    293304    return receiveBytes;
     
    300311    if (m_cancelled)
    301312        return 0;
     313
     314    if (needToInvokeDidReceiveResponse()) {
     315        if (!m_isSyncRequest) {
     316            // For asynchronous, pause until completeDidReceiveResponse() is called.
     317            setCallbackPaused(true);
     318            invokeDidReceiveResponse(Action::ReceiveData);
     319            return CURL_WRITEFUNC_PAUSE;
     320        }
     321
     322        // For synchronous, completeDidReceiveResponse() is called in invokeDidReceiveResponse().
     323        // In this case, pause is unnecessary.
     324        invokeDidReceiveResponse(Action::None);
     325    }
    302326
    303327    auto receiveBytes = buffer->size();
     
    321345
    322346    if (result == CURLE_OK) {
    323         if (auto metrics = m_curlHandle->getNetworkLoadMetrics())
    324             m_networkLoadMetrics = *metrics;
    325 
    326         callDelegate([this](CurlRequestDelegate* delegate) {
    327             if (delegate)
    328                 delegate->curlDidComplete();
    329         });
     347        if (needToInvokeDidReceiveResponse()) {
     348            // Processing of didReceiveResponse() has not been completed. (For example, HEAD method)
     349            // When completeDidReceiveResponse() is called, didCompleteTransfer() will be called again.
     350
     351            m_finishedResultCode = result;
     352            invokeDidReceiveResponse(Action::FinishTransfer);
     353        } else {
     354            if (auto metrics = m_curlHandle->getNetworkLoadMetrics())
     355                m_networkLoadMetrics = *metrics;
     356
     357            finalizeTransfer();
     358            callDelegate([this](CurlRequestDelegate* delegate) {
     359                if (delegate)
     360                    delegate->curlDidComplete();
     361            });
     362        }
    330363    } else {
    331364        auto resourceError = ResourceError::httpError(result, m_request.url());
     
    333366            resourceError.setSslErrors(m_sslVerifier.sslErrors());
    334367
     368        finalizeTransfer();
    335369        callDelegate([this, error = resourceError.isolatedCopy()](CurlRequestDelegate* delegate) {
    336370            if (delegate)
     
    338372        });
    339373    }
    340 
    341     m_formDataStream = nullptr;
    342     m_curlHandle = nullptr;
    343374}
    344375
    345376void CurlRequest::didCancelTransfer()
     377{
     378    finalizeTransfer();
     379}
     380
     381void CurlRequest::finalizeTransfer()
    346382{
    347383    m_formDataStream = nullptr;
     
    455491        // DidReceiveResponse must not be called immediately
    456492        CurlJobManager::singleton().callOnJobThread([protectedThis = makeRef(*this)]() {
    457             protectedThis->invokeDidReceiveResponse();
     493            protectedThis->invokeDidReceiveResponse(Action::StartTransfer);
    458494        });
    459     } else
    460         invokeDidReceiveResponse();
    461 }
    462 
    463 void CurlRequest::invokeDidReceiveResponse()
    464 {
     495    } else {
     496        // For synchronous, completeDidReceiveResponse() is called in platformContinueSynchronousDidReceiveResponse().
     497        invokeDidReceiveResponse(Action::None);
     498    }
     499}
     500
     501void CurlRequest::invokeDidReceiveResponse(Action behaviorAfterInvoke)
     502{
     503    ASSERT(!m_didNotifyResponse);
     504
     505    m_didNotifyResponse = true;
     506    m_actionAfterInvoke = behaviorAfterInvoke;
     507
    465508    callDelegate([this, response = m_response.isolatedCopy()](CurlRequestDelegate* delegate) {
    466509        if (delegate)
     
    469512}
    470513
    471 void CurlRequest::setPaused(bool paused)
    472 {
     514void CurlRequest::completeDidReceiveResponse()
     515{
     516    ASSERT(isMainThread());
     517    ASSERT(m_didNotifyResponse);
     518    ASSERT(!m_didReturnFromNotify);
     519
    473520    if (m_cancelled)
    474521        return;
    475522
    476     if (paused == m_isPaused)
    477         return;
    478 
    479     m_isPaused = paused;
    480 
    481     if (!m_curlHandle)
     523    m_didReturnFromNotify = true;
     524
     525    if (m_actionAfterInvoke == Action::ReceiveData) {
     526        // Resume transfer
     527        setCallbackPaused(false);
     528    } else if (m_actionAfterInvoke == Action::StartTransfer) {
     529        // Start transfer for file scheme
     530        startWithJobManager();
     531    } else if (m_actionAfterInvoke == Action::FinishTransfer) {
     532        // Keep the calling thread of didCompleteTransfer()
     533        if (!m_isSyncRequest) {
     534            CurlJobManager::singleton().callOnJobThread([protectedThis = makeRef(*this), finishedResultCode = m_finishedResultCode]() {
     535                protectedThis->didCompleteTransfer(finishedResultCode);
     536            });
     537        } else
     538            didCompleteTransfer(m_finishedResultCode);
     539    }
     540}
     541
     542void CurlRequest::setRequestPaused(bool paused)
     543{
     544    auto wasPaused = isPaused();
     545
     546    m_isPausedOfRequest = paused;
     547
     548    if (isPaused() == wasPaused)
     549        return;
     550
     551    pausedStatusChanged();
     552}
     553
     554void CurlRequest::setCallbackPaused(bool paused)
     555{
     556    auto wasPaused = isPaused();
     557
     558    m_isPausedOfCallback = paused;
     559
     560    if (isPaused() == wasPaused)
     561        return;
     562
     563    // In this case, PAUSE will be executed within didReceiveData(). Change pause state and return.
     564    if (paused)
     565        return;
     566
     567    pausedStatusChanged();
     568}
     569
     570void CurlRequest::pausedStatusChanged()
     571{
     572    if (m_cancelled || !m_curlHandle)
    482573        return;
    483574
    484575    if (!m_isSyncRequest && isMainThread()) {
    485         CurlJobManager::singleton().callOnJobThread([protectedThis = makeRef(*this), paused = m_isPaused]() {
     576        CurlJobManager::singleton().callOnJobThread([protectedThis = makeRef(*this), paused = isPaused()]() {
    486577            if (protectedThis->m_cancelled)
    487578                return;
     
    494585        });
    495586    } else {
    496         auto error = m_curlHandle->pause(m_isPaused ? CURLPAUSE_ALL : CURLPAUSE_CONT);
    497         if ((error != CURLE_OK) && !m_isPaused)
     587        auto error = m_curlHandle->pause(isPaused() ? CURLPAUSE_ALL : CURLPAUSE_CONT);
     588        if ((error != CURLE_OK) && !isPaused())
    498589            cancel();
    499590    }
  • trunk/Source/WebCore/platform/network/curl/CurlRequest.h

    r222665 r222756  
    5757    bool isSyncRequest() { return m_isSyncRequest; }
    5858
     59    // Processing for DidReceiveResponse
     60    void completeDidReceiveResponse();
     61
    5962    NetworkLoadMetrics getNetworkLoadMetrics() { return m_networkLoadMetrics.isolatedCopy(); }
    6063
    6164private:
     65    enum class Action {
     66        None,
     67        ReceiveData,
     68        StartTransfer,
     69        FinishTransfer
     70    };
     71
    6272    void retain() override { ref(); }
    6373    void release() override { deref(); }
     
    7787    void didCompleteTransfer(CURLcode) override;
    7888    void didCancelTransfer() override;
     89    void finalizeTransfer();
    7990
    8091    // For POST and PUT method
     
    8495    void setupFormData(ResourceRequest&, bool);
    8596
    86     // Processing for DidResourceResponse
     97    // Processing for DidReceiveResponse
     98    bool needToInvokeDidReceiveResponse() const { return !m_didNotifyResponse || !m_didReturnFromNotify; }
    8799    void invokeDidReceiveResponseForFile(URL&);
    88     void invokeDidReceiveResponse();
    89     void setPaused(bool);
     100    void invokeDidReceiveResponse(Action);
     101    void setRequestPaused(bool);
     102    void setCallbackPaused(bool);
     103    void pausedStatusChanged();
     104    bool isPaused() const { return m_isPausedOfRequest || m_isPausedOfCallback; };
    90105
    91106    // Callback functions for curl
     
    112127    CurlResponse m_response;
    113128
    114     bool m_isPaused { false };
     129    bool m_didNotifyResponse { false };
     130    bool m_didReturnFromNotify { false };
     131    Action m_actionAfterInvoke { Action::None };
     132    CURLcode m_finishedResultCode { CURLE_OK };
     133
     134    bool m_isPausedOfRequest { false };
     135    bool m_isPausedOfCallback { false };
    115136
    116137    NetworkLoadMetrics m_networkLoadMetrics;
  • trunk/Source/WebCore/platform/network/curl/ResourceHandleCurl.cpp

    r222728 r222756  
    214214        return;
    215215
    216     if (d->m_delegate)
    217         d->m_delegate->setAuthentication("", "");
    218 
    219216    clearAuthentication();
     217
     218    auto protectedThis = makeRef(*this);
     219    didReceiveResponse(ResourceResponse(d->m_response));
    220220}
    221221
     
    260260void ResourceHandle::continueDidReceiveResponse()
    261261{
    262     notImplemented();
     262    ASSERT(isMainThread());
     263
     264    if (d->m_delegate)
     265        d->m_delegate->continueDidReceiveResponse();
     266}
     267
     268void ResourceHandle::platformContinueSynchronousDidReceiveResponse()
     269{
     270    ASSERT(isMainThread());
     271
     272    if (d->m_delegate)
     273        d->m_delegate->platformContinueSynchronousDidReceiveResponse();
    263274}
    264275
  • trunk/Source/WebCore/platform/network/curl/ResourceHandleCurlDelegate.cpp

    r222728 r222756  
    228228
    229229        CurlCacheManager::getInstance().didReceiveResponse(*m_handle, response());
    230         m_handle->client()->didReceiveResponse(m_handle, ResourceResponse(response()));
     230
     231        auto protectedThis = makeRef(*m_handle);
     232        m_handle->didReceiveResponse(ResourceResponse(response()));
    231233    }
    232234}
     
    277279}
    278280
     281void ResourceHandleCurlDelegate::continueDidReceiveResponse()
     282{
     283    ASSERT(isMainThread());
     284
     285    continueAfterDidReceiveResponse();
     286}
     287
     288void ResourceHandleCurlDelegate::platformContinueSynchronousDidReceiveResponse()
     289{
     290    ASSERT(isMainThread());
     291
     292    continueAfterDidReceiveResponse();
     293}
     294
     295void ResourceHandleCurlDelegate::continueAfterDidReceiveResponse()
     296{
     297    ASSERT(isMainThread());
     298
     299    // continueDidReceiveResponse might cancel the load.
     300    if (cancelledOrClientless() || !m_curlRequest)
     301        return;
     302
     303    m_curlRequest->completeDidReceiveResponse();
     304}
     305
    279306bool ResourceHandleCurlDelegate::shouldRedirectAsGET(const ResourceRequest& request, bool crossOrigin)
    280307{
    281     if ((request.httpMethod() == "GET") || (request.httpMethod() == "HEAD"))
     308    if (request.httpMethod() == "GET" || request.httpMethod() == "HEAD")
    282309        return false;
    283310
  • trunk/Source/WebCore/platform/network/curl/ResourceHandleCurlDelegate.h

    r222728 r222756  
    5656    void dispatchSynchronousJob();
    5757
     58    void continueDidReceiveResponse();
     59    void platformContinueSynchronousDidReceiveResponse();
     60
    5861    void continueWillSendRequest(ResourceRequest&&);
    5962
     
    7174    void curlDidComplete() override;
    7275    void curlDidFailWithError(const ResourceError&) override;
     76
     77    void continueAfterDidReceiveResponse();
    7378
    7479    bool shouldRedirectAsGET(const ResourceRequest&, bool crossOrigin);
  • trunk/Source/WebCore/platform/network/curl/ResourceResponseCurl.cpp

    r222728 r222756  
    137137{
    138138    auto statusCode = httpStatusCode();
    139     if ((statusCode < 300) || (400 <= statusCode))
     139    if (statusCode < 300 || 400 <= statusCode)
    140140        return false;
    141141
     
    152152bool ResourceResponse::isMovedPermanently() const
    153153{
    154     return (httpStatusCode() == 301);
     154    return httpStatusCode() == 301;
    155155}
    156156
    157157bool ResourceResponse::isFound() const
    158158{
    159     return (httpStatusCode() == 302);
     159    return httpStatusCode() == 302;
    160160}
    161161
    162162bool ResourceResponse::isSeeOther() const
    163163{
    164     return (httpStatusCode() == 303);
     164    return httpStatusCode() == 303;
    165165}
    166166
    167167bool ResourceResponse::isNotModified() const
    168168{
    169     return (httpStatusCode() == 304);
     169    return httpStatusCode() == 304;
    170170}
    171171
    172172bool ResourceResponse::isUnauthorized() const
    173173{
    174     return (httpStatusCode() == 401);
     174    return httpStatusCode() == 401;
    175175}
    176176
Note: See TracChangeset for help on using the changeset viewer.