Changeset 222521 in webkit


Ignore:
Timestamp:
Sep 26, 2017 1:48:02 PM (7 years ago)
Author:
commit-queue@webkit.org
Message:

[Curl] Introduce CurlResponse to hold response information among threads.
https://bugs.webkit.org/show_bug.cgi?id=177496

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

  • platform/network/curl/AuthenticationChallenge.h:
  • platform/network/curl/AuthenticationChallengeCurl.cpp:

(WebCore::AuthenticationChallenge::AuthenticationChallenge):
(WebCore::AuthenticationChallenge::protectionSpaceFromHandle):

  • platform/network/curl/CurlContext.cpp:

(WebCore::CurlHandle::getHttpConnectCode):

  • platform/network/curl/CurlContext.h:
  • platform/network/curl/CurlResponse.h: Added.

(WebCore::CurlResponse::isolatedCopy const):

  • platform/network/curl/ResourceHandleCurlDelegate.cpp:

(WebCore::ResourceHandleCurlDelegate::didReceiveAllHeaders):
(WebCore::ResourceHandleCurlDelegate::didReceiveContentData):
(WebCore::ResourceHandleCurlDelegate::handleLocalReceiveResponse):
(WebCore::ResourceHandleCurlDelegate::didFinish):
(WebCore::ResourceHandleCurlDelegate::handleDataURL):
(WebCore::ResourceHandleCurlDelegate::didReceiveHeader):
(WebCore::isHttpInfo): Deleted.

  • platform/network/curl/ResourceHandleCurlDelegate.h:
  • platform/network/curl/ResourceResponse.h:

(WebCore::ResourceResponse::ResourceResponse):
(WebCore::ResourceResponse::setResponseFired): Deleted.
(WebCore::ResourceResponse::responseFired): Deleted.

  • platform/network/curl/ResourceResponseCurl.cpp:

(WebCore::ResourceResponse::ResourceResponse):
(WebCore::ResourceResponse::appendHTTPHeaderField):
(WebCore::ResourceResponse::setStatusLine):

Location:
trunk/Source/WebCore
Files:
1 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r222519 r222521  
     12017-09-26  Basuke Suzuki  <Basuke.Suzuki@sony.com>
     2
     3        [Curl] Introduce CurlResponse to hold response information among threads.
     4        https://bugs.webkit.org/show_bug.cgi?id=177496
     5
     6        Reviewed by Alex Christensen.
     7
     8        * platform/network/curl/AuthenticationChallenge.h:
     9        * platform/network/curl/AuthenticationChallengeCurl.cpp:
     10        (WebCore::AuthenticationChallenge::AuthenticationChallenge):
     11        (WebCore::AuthenticationChallenge::protectionSpaceFromHandle):
     12        * platform/network/curl/CurlContext.cpp:
     13        (WebCore::CurlHandle::getHttpConnectCode):
     14        * platform/network/curl/CurlContext.h:
     15        * platform/network/curl/CurlResponse.h: Added.
     16        (WebCore::CurlResponse::isolatedCopy const):
     17        * platform/network/curl/ResourceHandleCurlDelegate.cpp:
     18        (WebCore::ResourceHandleCurlDelegate::didReceiveAllHeaders):
     19        (WebCore::ResourceHandleCurlDelegate::didReceiveContentData):
     20        (WebCore::ResourceHandleCurlDelegate::handleLocalReceiveResponse):
     21        (WebCore::ResourceHandleCurlDelegate::didFinish):
     22        (WebCore::ResourceHandleCurlDelegate::handleDataURL):
     23        (WebCore::ResourceHandleCurlDelegate::didReceiveHeader):
     24        (WebCore::isHttpInfo): Deleted.
     25        * platform/network/curl/ResourceHandleCurlDelegate.h:
     26        * platform/network/curl/ResourceResponse.h:
     27        (WebCore::ResourceResponse::ResourceResponse):
     28        (WebCore::ResourceResponse::setResponseFired): Deleted.
     29        (WebCore::ResourceResponse::responseFired): Deleted.
     30        * platform/network/curl/ResourceResponseCurl.cpp:
     31        (WebCore::ResourceResponse::ResourceResponse):
     32        (WebCore::ResourceResponse::appendHTTPHeaderField):
     33        (WebCore::ResourceResponse::setStatusLine):
     34
    1352017-09-26  Chris Dumez  <cdumez@apple.com>
    236
  • trunk/Source/WebCore/platform/network/curl/AuthenticationChallenge.h

    r222223 r222521  
    3232namespace WebCore {
    3333
     34class CurlResponse;
     35
    3436class AuthenticationChallenge final : public AuthenticationChallengeBase {
    3537public:
     
    4345    }
    4446
    45     AuthenticationChallenge(uint16_t, long, unsigned, const ResourceResponse&, AuthenticationClient* = nullptr);
     47    AuthenticationChallenge(const CurlResponse&, unsigned, const ResourceResponse&, AuthenticationClient* = nullptr);
    4648    AuthenticationClient* authenticationClient() const { return m_authenticationClient.get(); }
    4749
    4850private:
    4951    ProtectionSpaceServerType protectionSpaceServerTypeFromURI(const URL&);
    50     ProtectionSpace protectionSpaceFromHandle(uint16_t, long, const ResourceResponse&);
     52    ProtectionSpace protectionSpaceFromHandle(const CurlResponse&, const ResourceResponse&);
    5153    void removeLeadingAndTrailingQuotes(String&);
    5254
  • trunk/Source/WebCore/platform/network/curl/AuthenticationChallengeCurl.cpp

    r222223 r222521  
    3030
    3131#include "CurlContext.h"
     32#include "CurlResponse.h"
    3233#include "ResourceError.h"
    3334
    3435namespace WebCore {
    3536
    36 AuthenticationChallenge::AuthenticationChallenge(uint16_t connectPort, long availableHttpAuth, unsigned previousFailureCount, const ResourceResponse& response, AuthenticationClient* client)
    37     : AuthenticationChallengeBase(protectionSpaceFromHandle(connectPort, availableHttpAuth, response), Credential(), previousFailureCount, response, ResourceError())
     37AuthenticationChallenge::AuthenticationChallenge(const CurlResponse& curlResponse, unsigned previousFailureCount, const ResourceResponse& response, AuthenticationClient* client)
     38    : AuthenticationChallengeBase(protectionSpaceFromHandle(curlResponse, response), Credential(), previousFailureCount, response, ResourceError())
    3839    , m_authenticationClient(client)
    3940{
     
    5152}
    5253
    53 ProtectionSpace AuthenticationChallenge::protectionSpaceFromHandle(uint16_t connectPort, long availableHttpAuth, const ResourceResponse& response)
     54ProtectionSpace AuthenticationChallenge::protectionSpaceFromHandle(const CurlResponse& curlResponse, const ResourceResponse& response)
    5455{
     56    auto port = curlResponse.connectPort;
     57    auto availableHttpAuth = curlResponse.availableHttpAuth;
     58
    5559    ProtectionSpaceAuthenticationScheme scheme = ProtectionSpaceAuthenticationSchemeUnknown;
    5660    if (availableHttpAuth & CURLAUTH_BASIC)
     
    7377    }
    7478
    75     return ProtectionSpace(response.url().host(), static_cast<int>(connectPort), protectionSpaceServerTypeFromURI(response.url()), realm, scheme);
     79    return ProtectionSpace(response.url().host(), static_cast<int>(port), protectionSpaceServerTypeFromURI(response.url()), realm, scheme);
    7680}
    7781
  • trunk/Source/WebCore/platform/network/curl/CurlContext.cpp

    r222508 r222521  
    581581}
    582582
     583std::optional<long> CurlHandle::getHttpConnectCode()
     584{
     585    if (!m_handle)
     586        return std::nullopt;
     587
     588    long httpConnectCode;
     589    CURLcode errorCode = curl_easy_getinfo(m_handle, CURLINFO_HTTP_CONNECTCODE, &httpConnectCode);
     590    if (errorCode != CURLE_OK)
     591        return std::nullopt;
     592
     593    return httpConnectCode;
     594}
     595
    583596std::optional<long long> CurlHandle::getContentLength()
    584597{
  • trunk/Source/WebCore/platform/network/curl/CurlContext.h

    r222508 r222521  
    279279    std::optional<uint16_t> getPrimaryPort();
    280280    std::optional<long> getResponseCode();
     281    std::optional<long> getHttpConnectCode();
    281282    std::optional<long long> getContentLength();
    282283    std::optional<long> getHttpAuthAvail();
  • trunk/Source/WebCore/platform/network/curl/ResourceHandleCurlDelegate.cpp

    r222511 r222521  
    318318}
    319319
    320 inline static bool isHttpInfo(int statusCode)
    321 {
    322     return 100 <= statusCode && statusCode < 200;
    323 }
    324 
    325 void ResourceHandleCurlDelegate::didReceiveAllHeaders(URL url, long httpCode, long long contentLength, uint16_t connectPort, long availableHttpAuth)
     320void ResourceHandleCurlDelegate::didReceiveAllHeaders(const CurlResponse& receivedResponse)
    326321{
    327322    ASSERT(isMainThread());
    328323
    329     response().setURL(url);
    330     response().setExpectedContentLength(contentLength);
    331     response().setHTTPStatusCode(httpCode);
    332     response().setMimeType(extractMIMETypeFromMediaType(response().httpHeaderField(HTTPHeaderName::ContentType)).convertToASCIILowercase());
    333     response().setTextEncodingName(extractCharsetFromMediaType(response().httpHeaderField(HTTPHeaderName::ContentType)));
     324    m_handle->getInternal()->m_response = ResourceResponse(receivedResponse);
    334325
    335326    if (response().isMultipart()) {
     
    357348        }
    358349    } else if (response().isUnauthorized()) {
    359         AuthenticationChallenge challenge(connectPort, availableHttpAuth, m_authFailureCount, response(), m_handle);
     350        AuthenticationChallenge challenge(receivedResponse, m_authFailureCount, response(), m_handle);
    360351        m_handle->didReceiveAuthenticationChallenge(challenge);
    361352        m_authFailureCount++;
     
    363354    }
    364355
    365     response().setResponseFired(true);
     356    m_didNotifyResponse = true;
    366357
    367358    if (m_handle->client()) {
     
    384375    ASSERT(isMainThread());
    385376
    386     if (!response().responseFired())
     377    if (!m_didNotifyResponse)
    387378        handleLocalReceiveResponse();
    388379
     
    410401    // Determine the MIME type based on the path.
    411402    response().setMimeType(MIMETypeRegistry::getMIMETypeForPath(url));
    412     response().setResponseFired(true);
     403
     404    m_didNotifyResponse = true;
     405
    413406    if (m_handle->client())
    414407        m_handle->client()->didReceiveResponse(m_handle, ResourceResponse(response()));
     
    446439        return;
    447440
    448     if (!response().responseFired()) {
     441    if (!m_didNotifyResponse) {
    449442        handleLocalReceiveResponse();
    450443        if (!m_handle)
     
    479472    ASSERT(m_handle->client());
    480473
    481     int index = url.find(',');
    482     if (index == -1) {
     474    auto index = url.find(',');
     475    if (index == notFound) {
    483476        m_handle->client()->cannotShowURL(m_handle);
    484477        return;
     
    672665size_t ResourceHandleCurlDelegate::didReceiveHeader(String&& header)
    673666{
     667    static const auto emptyLineCRLF = "\r\n";
     668    static const auto emptyLineLF = "\n";
     669
    674670    if (!m_handle)
    675671        return 0;
     
    678674        return 0;
    679675
    680     /*
    681     * a) We can finish and send the ResourceResponse
    682     * b) We will add the current header to the HTTPHeaderMap of the ResourceResponse
    683     *
    684     * The HTTP standard requires to use \r\n but for compatibility it recommends to
    685     * accept also \n.
    686     */
    687     if (header == AtomicString("\r\n") || header == AtomicString("\n")) {
    688         long httpCode = 0;
    689         if (auto code = m_curlHandle->getResponseCode())
    690             httpCode = *code;
    691 
    692         if (!httpCode) {
    693             // Comes here when receiving 200 Connection Established. Just return.
    694             return header.length();
    695         }
    696 
    697         if (isHttpInfo(httpCode)) {
    698             // Just return when receiving http info, e.g. HTTP/1.1 100 Continue.
    699             // If not, the request might be cancelled, because the MIME type will be empty for this response.
    700             return header.length();
    701         }
    702 
    703         URL url = m_curlHandle->getEffectiveURL();
    704 
    705         long long contentLength = 0;
    706         if (auto length = m_curlHandle->getContentLength())
    707             contentLength = *length;
    708 
    709         uint16_t connectPort = 0;
    710         if (auto port = m_curlHandle->getPrimaryPort())
    711             connectPort = *port;
    712 
    713         long availableAuth = CURLAUTH_NONE;
    714         if (auto auth = m_curlHandle->getHttpAuthAvail())
    715             availableAuth = *auth;
    716 
    717         if (isMainThread())
    718             didReceiveAllHeaders(url, httpCode, contentLength, connectPort, availableAuth);
    719         else {
    720             callOnMainThread([protectedThis = makeRef(*this), copyUrl = url.isolatedCopy(), httpCode, contentLength, connectPort, availableAuth] {
    721                 if (!protectedThis->m_handle)
    722                     return;
    723                 protectedThis->didReceiveAllHeaders(copyUrl, httpCode, contentLength, connectPort, availableAuth);
    724             });
    725         }
    726     } else {
    727         // If the FOLLOWLOCATION option is enabled for the curl handle then
    728         // curl will follow the redirections internally. Thus this header callback
    729         // will be called more than one time with the line starting "HTTP" for one job.
    730         if (isMainThread())
    731             response().appendHTTPHeaderField(header);
    732         else {
    733             callOnMainThread([protectedThis = makeRef(*this), copyHeader = header.isolatedCopy() ] {
    734                 if (!protectedThis->m_handle)
    735                     return;
    736 
    737                 protectedThis->response().appendHTTPHeaderField(copyHeader);
    738             });
    739         }
    740     }
    741 
    742     return header.length();
     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;
    743734}
    744735
  • trunk/Source/WebCore/platform/network/curl/ResourceHandleCurlDelegate.h

    r222511 r222521  
    3131#include "Credential.h"
    3232#include "CurlJobManager.h"
     33#include "CurlResponse.h"
    3334#include "CurlSSLVerifier.h"
    3435#include "FormDataStreamCurl.h"
     
    7879    void setupAuthentication();
    7980
    80     void didReceiveAllHeaders(URL, long httpCode, long long contentLength, uint16_t connectPort, long availableHttpAuth);
     81    void didReceiveAllHeaders(const CurlResponse&);
    8182    void didReceiveContentData(Ref<SharedBuffer>&&);
    8283    void handleLocalReceiveResponse();
     
    123124    std::unique_ptr<CurlHandle> m_curlHandle;
    124125    CurlSSLVerifier m_sslVerifier;
     126    CurlResponse m_response;
     127    bool m_didNotifyResponse { false };
    125128    // Used by both threads.
    126129    bool m_isSyncRequest { false };
  • trunk/Source/WebCore/platform/network/curl/ResourceResponse.h

    r222068 r222521  
    3333namespace WebCore {
    3434
     35class CurlResponse;
     36
    3537class ResourceResponse : public ResourceResponseBase {
    3638public:
    3739    ResourceResponse()
    38         : m_responseFired(false)
     40        : ResourceResponseBase()
    3941    {
    4042    }
    4143
    4244    ResourceResponse(const URL& url, const String& mimeType, long long expectedLength, const String& textEncodingName)
    43         : ResourceResponseBase(url, mimeType, expectedLength, textEncodingName),
    44           m_responseFired(false)
     45        : ResourceResponseBase(url, mimeType, expectedLength, textEncodingName)
    4546    {
    4647    }
    4748
    48     void setResponseFired(bool fired) { m_responseFired = fired; }
    49     bool responseFired() { return m_responseFired; }
     49    ResourceResponse(const CurlResponse&);
    5050
    5151    void appendHTTPHeaderField(const String&);
     
    6767
    6868    void setStatusLine(const String&);
    69 
    70     bool m_responseFired;
    7169};
    7270
  • trunk/Source/WebCore/platform/network/curl/ResourceResponseCurl.cpp

    r222012 r222521  
    2929#include "ResourceResponse.h"
    3030
     31#include "CurlResponse.h"
    3132#include "HTTPParsers.h"
    3233
     
    7677}
    7778
     79ResourceResponse::ResourceResponse(const CurlResponse& response)
     80    : ResourceResponseBase(response.url, "", response.expectedContentLength, "")
     81{
     82    setHTTPStatusCode(response.statusCode);
     83
     84    for (auto header : response.headers)
     85        appendHTTPHeaderField(header);
     86
     87    setMimeType(extractMIMETypeFromMediaType(httpHeaderField(HTTPHeaderName::ContentType)).convertToASCIILowercase());
     88    setTextEncodingName(extractCharsetFromMediaType(httpHeaderField(HTTPHeaderName::ContentType)));
     89}
     90
    7891void ResourceResponse::appendHTTPHeaderField(const String& header)
    7992{
    80     int splitPosistion = header.find(":");
     93    auto splitPosistion = header.find(":");
    8194    if (splitPosistion != notFound) {
    82         String key = header.left(splitPosistion).stripWhiteSpace();
    83         String value = header.substring(splitPosistion + 1).stripWhiteSpace();
     95        auto key = header.left(splitPosistion).stripWhiteSpace();
     96        auto value = header.substring(splitPosistion + 1).stripWhiteSpace();
    8497
    8598        if (isAppendableHeader(key))
     
    95108void ResourceResponse::setStatusLine(const String& header)
    96109{
    97     String statusLine = header.stripWhiteSpace();
     110    auto statusLine = header.stripWhiteSpace();
    98111
    99     int httpVersionEndPosition = statusLine.find(" ");
    100     int statusCodeEndPosition = notFound;
     112    auto httpVersionEndPosition = statusLine.find(" ");
     113    auto statusCodeEndPosition = notFound;
    101114
    102115    // Extract the http version
    103116    if (httpVersionEndPosition != notFound) {
    104         String httpVersion = statusLine.left(httpVersionEndPosition);
     117        auto httpVersion = statusLine.left(httpVersionEndPosition);
    105118        setHTTPVersion(httpVersion.stripWhiteSpace());
    106119
     
    111124    // Extract the http status text
    112125    if (statusCodeEndPosition != notFound) {
    113         String statusText = statusLine.substring(statusCodeEndPosition + 1);
     126        auto statusText = statusLine.substring(statusCodeEndPosition + 1);
    114127        setHTTPStatusText(statusText.stripWhiteSpace());
    115128    }
Note: See TracChangeset for help on using the changeset viewer.