Diff
Modified: trunk/Source/WebCore/ChangeLog (222520 => 222521)
--- trunk/Source/WebCore/ChangeLog 2017-09-26 20:42:14 UTC (rev 222520)
+++ trunk/Source/WebCore/ChangeLog 2017-09-26 20:48:02 UTC (rev 222521)
@@ -1,3 +1,37 @@
+2017-09-26 Basuke Suzuki <[email protected]>
+
+ [Curl] Introduce CurlResponse to hold response information among threads.
+ https://bugs.webkit.org/show_bug.cgi?id=177496
+
+ 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):
+
2017-09-26 Chris Dumez <[email protected]>
Make StoredCredentials an enum class and rename its header
Modified: trunk/Source/WebCore/platform/network/curl/AuthenticationChallenge.h (222520 => 222521)
--- trunk/Source/WebCore/platform/network/curl/AuthenticationChallenge.h 2017-09-26 20:42:14 UTC (rev 222520)
+++ trunk/Source/WebCore/platform/network/curl/AuthenticationChallenge.h 2017-09-26 20:48:02 UTC (rev 222521)
@@ -31,6 +31,8 @@
namespace WebCore {
+class CurlResponse;
+
class AuthenticationChallenge final : public AuthenticationChallengeBase {
public:
AuthenticationChallenge()
@@ -42,12 +44,12 @@
{
}
- AuthenticationChallenge(uint16_t, long, unsigned, const ResourceResponse&, AuthenticationClient* = nullptr);
+ AuthenticationChallenge(const CurlResponse&, unsigned, const ResourceResponse&, AuthenticationClient* = nullptr);
AuthenticationClient* authenticationClient() const { return m_authenticationClient.get(); }
private:
ProtectionSpaceServerType protectionSpaceServerTypeFromURI(const URL&);
- ProtectionSpace protectionSpaceFromHandle(uint16_t, long, const ResourceResponse&);
+ ProtectionSpace protectionSpaceFromHandle(const CurlResponse&, const ResourceResponse&);
void removeLeadingAndTrailingQuotes(String&);
RefPtr<AuthenticationClient> m_authenticationClient;
Modified: trunk/Source/WebCore/platform/network/curl/AuthenticationChallengeCurl.cpp (222520 => 222521)
--- trunk/Source/WebCore/platform/network/curl/AuthenticationChallengeCurl.cpp 2017-09-26 20:42:14 UTC (rev 222520)
+++ trunk/Source/WebCore/platform/network/curl/AuthenticationChallengeCurl.cpp 2017-09-26 20:48:02 UTC (rev 222521)
@@ -29,12 +29,13 @@
#if USE(CURL)
#include "CurlContext.h"
+#include "CurlResponse.h"
#include "ResourceError.h"
namespace WebCore {
-AuthenticationChallenge::AuthenticationChallenge(uint16_t connectPort, long availableHttpAuth, unsigned previousFailureCount, const ResourceResponse& response, AuthenticationClient* client)
- : AuthenticationChallengeBase(protectionSpaceFromHandle(connectPort, availableHttpAuth, response), Credential(), previousFailureCount, response, ResourceError())
+AuthenticationChallenge::AuthenticationChallenge(const CurlResponse& curlResponse, unsigned previousFailureCount, const ResourceResponse& response, AuthenticationClient* client)
+ : AuthenticationChallengeBase(protectionSpaceFromHandle(curlResponse, response), Credential(), previousFailureCount, response, ResourceError())
, m_authenticationClient(client)
{
}
@@ -50,8 +51,11 @@
return ProtectionSpaceServerHTTP;
}
-ProtectionSpace AuthenticationChallenge::protectionSpaceFromHandle(uint16_t connectPort, long availableHttpAuth, const ResourceResponse& response)
+ProtectionSpace AuthenticationChallenge::protectionSpaceFromHandle(const CurlResponse& curlResponse, const ResourceResponse& response)
{
+ auto port = curlResponse.connectPort;
+ auto availableHttpAuth = curlResponse.availableHttpAuth;
+
ProtectionSpaceAuthenticationScheme scheme = ProtectionSpaceAuthenticationSchemeUnknown;
if (availableHttpAuth & CURLAUTH_BASIC)
scheme = ProtectionSpaceAuthenticationSchemeHTTPBasic;
@@ -72,7 +76,7 @@
removeLeadingAndTrailingQuotes(realm);
}
- return ProtectionSpace(response.url().host(), static_cast<int>(connectPort), protectionSpaceServerTypeFromURI(response.url()), realm, scheme);
+ return ProtectionSpace(response.url().host(), static_cast<int>(port), protectionSpaceServerTypeFromURI(response.url()), realm, scheme);
}
void AuthenticationChallenge::removeLeadingAndTrailingQuotes(String& value)
Modified: trunk/Source/WebCore/platform/network/curl/CurlContext.cpp (222520 => 222521)
--- trunk/Source/WebCore/platform/network/curl/CurlContext.cpp 2017-09-26 20:42:14 UTC (rev 222520)
+++ trunk/Source/WebCore/platform/network/curl/CurlContext.cpp 2017-09-26 20:48:02 UTC (rev 222521)
@@ -580,6 +580,19 @@
return responseCode;
}
+std::optional<long> CurlHandle::getHttpConnectCode()
+{
+ if (!m_handle)
+ return std::nullopt;
+
+ long httpConnectCode;
+ CURLcode errorCode = curl_easy_getinfo(m_handle, CURLINFO_HTTP_CONNECTCODE, &httpConnectCode);
+ if (errorCode != CURLE_OK)
+ return std::nullopt;
+
+ return httpConnectCode;
+}
+
std::optional<long long> CurlHandle::getContentLength()
{
if (!m_handle)
Modified: trunk/Source/WebCore/platform/network/curl/CurlContext.h (222520 => 222521)
--- trunk/Source/WebCore/platform/network/curl/CurlContext.h 2017-09-26 20:42:14 UTC (rev 222520)
+++ trunk/Source/WebCore/platform/network/curl/CurlContext.h 2017-09-26 20:48:02 UTC (rev 222521)
@@ -278,6 +278,7 @@
URL getEffectiveURL();
std::optional<uint16_t> getPrimaryPort();
std::optional<long> getResponseCode();
+ std::optional<long> getHttpConnectCode();
std::optional<long long> getContentLength();
std::optional<long> getHttpAuthAvail();
std::optional<NetworkLoadMetrics> getNetworkLoadMetrics();
Added: trunk/Source/WebCore/platform/network/curl/CurlResponse.h (0 => 222521)
--- trunk/Source/WebCore/platform/network/curl/CurlResponse.h (rev 0)
+++ trunk/Source/WebCore/platform/network/curl/CurlResponse.h 2017-09-26 20:48:02 UTC (rev 222521)
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "URL.h"
+
+namespace WebCore {
+
+class CurlResponse {
+public:
+ CurlResponse() = default;
+
+ CurlResponse isolatedCopy() const
+ {
+ CurlResponse copy;
+
+ copy.url = ""
+ copy.statusCode = statusCode;
+ copy.expectedContentLength = expectedContentLength;
+
+ for (auto header : headers)
+ copy.headers.append(header.isolatedCopy());
+
+ copy.connectPort = connectPort;
+ copy.availableHttpAuth = availableHttpAuth;
+
+ return copy;
+ }
+
+ URL url;
+ long statusCode { 0 };
+ long long expectedContentLength { 0 };
+ Vector<String> headers;
+
+ uint16_t connectPort { 0 };
+ long availableHttpAuth { 0 };
+};
+
+}
Modified: trunk/Source/WebCore/platform/network/curl/ResourceHandleCurlDelegate.cpp (222520 => 222521)
--- trunk/Source/WebCore/platform/network/curl/ResourceHandleCurlDelegate.cpp 2017-09-26 20:42:14 UTC (rev 222520)
+++ trunk/Source/WebCore/platform/network/curl/ResourceHandleCurlDelegate.cpp 2017-09-26 20:48:02 UTC (rev 222521)
@@ -317,20 +317,11 @@
}
}
-inline static bool isHttpInfo(int statusCode)
+void ResourceHandleCurlDelegate::didReceiveAllHeaders(const CurlResponse& receivedResponse)
{
- return 100 <= statusCode && statusCode < 200;
-}
-
-void ResourceHandleCurlDelegate::didReceiveAllHeaders(URL url, long httpCode, long long contentLength, uint16_t connectPort, long availableHttpAuth)
-{
ASSERT(isMainThread());
- response().setURL(url);
- response().setExpectedContentLength(contentLength);
- response().setHTTPStatusCode(httpCode);
- response().setMimeType(extractMIMETypeFromMediaType(response().httpHeaderField(HTTPHeaderName::ContentType)).convertToASCIILowercase());
- response().setTextEncodingName(extractCharsetFromMediaType(response().httpHeaderField(HTTPHeaderName::ContentType)));
+ m_handle->getInternal()->m_response = ResourceResponse(receivedResponse);
if (response().isMultipart()) {
String boundary;
@@ -356,13 +347,13 @@
return;
}
} else if (response().isUnauthorized()) {
- AuthenticationChallenge challenge(connectPort, availableHttpAuth, m_authFailureCount, response(), m_handle);
+ AuthenticationChallenge challenge(receivedResponse, m_authFailureCount, response(), m_handle);
m_handle->didReceiveAuthenticationChallenge(challenge);
m_authFailureCount++;
return;
}
- response().setResponseFired(true);
+ m_didNotifyResponse = true;
if (m_handle->client()) {
if (response().isNotModified()) {
@@ -383,7 +374,7 @@
{
ASSERT(isMainThread());
- if (!response().responseFired())
+ if (!m_didNotifyResponse)
handleLocalReceiveResponse();
if (m_multipartHandle)
@@ -409,7 +400,9 @@
// Determine the MIME type based on the path.
response().setMimeType(MIMETypeRegistry::getMIMETypeForPath(url));
- response().setResponseFired(true);
+
+ m_didNotifyResponse = true;
+
if (m_handle->client())
m_handle->client()->didReceiveResponse(m_handle, ResourceResponse(response()));
}
@@ -445,7 +438,7 @@
if (!m_handle)
return;
- if (!response().responseFired()) {
+ if (!m_didNotifyResponse) {
handleLocalReceiveResponse();
if (!m_handle)
return;
@@ -478,8 +471,8 @@
ASSERT(m_handle->client());
- int index = url.find(',');
- if (index == -1) {
+ auto index = url.find(',');
+ if (index == notFound) {
m_handle->client()->cannotShowURL(m_handle);
return;
}
@@ -671,6 +664,9 @@
*/
size_t ResourceHandleCurlDelegate::didReceiveHeader(String&& header)
{
+ static const auto emptyLineCRLF = "\r\n";
+ static const auto emptyLineLF = "\n";
+
if (!m_handle)
return 0;
@@ -677,69 +673,64 @@
if (m_defersLoading)
return 0;
- /*
- * a) We can finish and send the ResourceResponse
- * b) We will add the current header to the HTTPHeaderMap of the ResourceResponse
- *
- * The HTTP standard requires to use \r\n but for compatibility it recommends to
- * accept also \n.
- */
- if (header == AtomicString("\r\n") || header == AtomicString("\n")) {
- long httpCode = 0;
- if (auto code = m_curlHandle->getResponseCode())
- httpCode = *code;
+ size_t receiveBytes = header.length();
- if (!httpCode) {
- // Comes here when receiving 200 Connection Established. Just return.
- return header.length();
- }
+ // The HTTP standard requires to use \r\n but for compatibility it recommends to accept also \n.
+ // We will add the current header to the CurlResponse.headers
+ if ((header != emptyLineCRLF) && (header != emptyLineLF)) {
+ m_response.headers.append(WTFMove(header));
+ return receiveBytes;
+ }
- if (isHttpInfo(httpCode)) {
- // Just return when receiving http info, e.g. HTTP/1.1 100 Continue.
- // If not, the request might be cancelled, because the MIME type will be empty for this response.
- return header.length();
- }
+ // We can finish and send the ResourceResponse
+ long statusCode = 0;
+ if (auto code = m_curlHandle->getResponseCode())
+ statusCode = *code;
- URL url = ""
+ long httpConnectCode = 0;
+ if (auto code = m_curlHandle->getHttpConnectCode())
+ httpConnectCode = *code;
- long long contentLength = 0;
- if (auto length = m_curlHandle->getContentLength())
- contentLength = *length;
+ if ((100 <= statusCode) && (statusCode < 200)) {
+ // Just return when receiving http info, e.g. HTTP/1.1 100 Continue.
+ // If not, the request might be cancelled, because the MIME type will be empty for this response.
+ m_response = CurlResponse();
+ return receiveBytes;
+ }
- uint16_t connectPort = 0;
- if (auto port = m_curlHandle->getPrimaryPort())
- connectPort = *port;
+ if (!statusCode && (httpConnectCode == 200)) {
+ // Comes here when receiving 200 Connection Established. Just return.
+ m_response = CurlResponse();
+ return receiveBytes;
+ }
- long availableAuth = CURLAUTH_NONE;
- if (auto auth = m_curlHandle->getHttpAuthAvail())
- availableAuth = *auth;
+ // If the FOLLOWLOCATION option is enabled for the curl handle then
+ // curl will follow the redirections internally. Thus this header callback
+ // will be called more than one time with the line starting "HTTP" for one job.
- if (isMainThread())
- didReceiveAllHeaders(url, httpCode, contentLength, connectPort, availableAuth);
- else {
- callOnMainThread([protectedThis = makeRef(*this), copyUrl = url.isolatedCopy(), httpCode, contentLength, connectPort, availableAuth] {
- if (!protectedThis->m_handle)
- return;
- protectedThis->didReceiveAllHeaders(copyUrl, httpCode, contentLength, connectPort, availableAuth);
- });
- }
- } else {
- // If the FOLLOWLOCATION option is enabled for the curl handle then
- // curl will follow the redirections internally. Thus this header callback
- // will be called more than one time with the line starting "HTTP" for one job.
- if (isMainThread())
- response().appendHTTPHeaderField(header);
- else {
- callOnMainThread([protectedThis = makeRef(*this), copyHeader = header.isolatedCopy() ] {
- if (!protectedThis->m_handle)
- return;
+ m_response.url = ""
+ m_response.statusCode = statusCode;
- protectedThis->response().appendHTTPHeaderField(copyHeader);
- });
- }
+ if (auto length = m_curlHandle->getContentLength())
+ m_response.expectedContentLength = *length;
+
+ if (auto port = m_curlHandle->getPrimaryPort())
+ m_response.connectPort = *port;
+
+ if (auto auth = m_curlHandle->getHttpAuthAvail())
+ m_response.availableHttpAuth = *auth;
+
+ if (isMainThread())
+ didReceiveAllHeaders(m_response);
+ else {
+ callOnMainThread([protectedThis = makeRef(*this), response = m_response.isolatedCopy()] {
+ if (!protectedThis->m_handle)
+ return;
+ protectedThis->didReceiveAllHeaders(response);
+ });
}
- return header.length();
+ return receiveBytes;
}
// called with data after all headers have been processed via headerCallback
Modified: trunk/Source/WebCore/platform/network/curl/ResourceHandleCurlDelegate.h (222520 => 222521)
--- trunk/Source/WebCore/platform/network/curl/ResourceHandleCurlDelegate.h 2017-09-26 20:42:14 UTC (rev 222520)
+++ trunk/Source/WebCore/platform/network/curl/ResourceHandleCurlDelegate.h 2017-09-26 20:48:02 UTC (rev 222521)
@@ -30,6 +30,7 @@
#include "Credential.h"
#include "CurlJobManager.h"
+#include "CurlResponse.h"
#include "CurlSSLVerifier.h"
#include "FormDataStreamCurl.h"
#include "ResourceRequest.h"
@@ -77,7 +78,7 @@
void setupAuthentication();
- void didReceiveAllHeaders(URL, long httpCode, long long contentLength, uint16_t connectPort, long availableHttpAuth);
+ void didReceiveAllHeaders(const CurlResponse&);
void didReceiveContentData(Ref<SharedBuffer>&&);
void handleLocalReceiveResponse();
void prepareSendData(char*, size_t blockSize, size_t numberOfBlocks);
@@ -122,6 +123,8 @@
Vector<char> m_postBytes;
std::unique_ptr<CurlHandle> m_curlHandle;
CurlSSLVerifier m_sslVerifier;
+ CurlResponse m_response;
+ bool m_didNotifyResponse { false };
// Used by both threads.
bool m_isSyncRequest { false };
Condition m_workerThreadConditionVariable;
Modified: trunk/Source/WebCore/platform/network/curl/ResourceResponse.h (222520 => 222521)
--- trunk/Source/WebCore/platform/network/curl/ResourceResponse.h 2017-09-26 20:42:14 UTC (rev 222520)
+++ trunk/Source/WebCore/platform/network/curl/ResourceResponse.h 2017-09-26 20:48:02 UTC (rev 222521)
@@ -32,21 +32,21 @@
namespace WebCore {
+class CurlResponse;
+
class ResourceResponse : public ResourceResponseBase {
public:
ResourceResponse()
- : m_responseFired(false)
+ : ResourceResponseBase()
{
}
ResourceResponse(const URL& url, const String& mimeType, long long expectedLength, const String& textEncodingName)
- : ResourceResponseBase(url, mimeType, expectedLength, textEncodingName),
- m_responseFired(false)
+ : ResourceResponseBase(url, mimeType, expectedLength, textEncodingName)
{
}
- void setResponseFired(bool fired) { m_responseFired = fired; }
- bool responseFired() { return m_responseFired; }
+ ResourceResponse(const CurlResponse&);
void appendHTTPHeaderField(const String&);
@@ -66,8 +66,6 @@
String platformSuggestedFilename() const;
void setStatusLine(const String&);
-
- bool m_responseFired;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/network/curl/ResourceResponseCurl.cpp (222520 => 222521)
--- trunk/Source/WebCore/platform/network/curl/ResourceResponseCurl.cpp 2017-09-26 20:42:14 UTC (rev 222520)
+++ trunk/Source/WebCore/platform/network/curl/ResourceResponseCurl.cpp 2017-09-26 20:48:02 UTC (rev 222521)
@@ -28,6 +28,7 @@
#if USE(CURL)
#include "ResourceResponse.h"
+#include "CurlResponse.h"
#include "HTTPParsers.h"
namespace WebCore {
@@ -75,12 +76,24 @@
return false;
}
+ResourceResponse::ResourceResponse(const CurlResponse& response)
+ : ResourceResponseBase(response.url, "", response.expectedContentLength, "")
+{
+ setHTTPStatusCode(response.statusCode);
+
+ for (auto header : response.headers)
+ appendHTTPHeaderField(header);
+
+ setMimeType(extractMIMETypeFromMediaType(httpHeaderField(HTTPHeaderName::ContentType)).convertToASCIILowercase());
+ setTextEncodingName(extractCharsetFromMediaType(httpHeaderField(HTTPHeaderName::ContentType)));
+}
+
void ResourceResponse::appendHTTPHeaderField(const String& header)
{
- int splitPosistion = header.find(":");
+ auto splitPosistion = header.find(":");
if (splitPosistion != notFound) {
- String key = header.left(splitPosistion).stripWhiteSpace();
- String value = header.substring(splitPosistion + 1).stripWhiteSpace();
+ auto key = header.left(splitPosistion).stripWhiteSpace();
+ auto value = header.substring(splitPosistion + 1).stripWhiteSpace();
if (isAppendableHeader(key))
addHTTPHeaderField(key, value);
@@ -94,14 +107,14 @@
void ResourceResponse::setStatusLine(const String& header)
{
- String statusLine = header.stripWhiteSpace();
+ auto statusLine = header.stripWhiteSpace();
- int httpVersionEndPosition = statusLine.find(" ");
- int statusCodeEndPosition = notFound;
+ auto httpVersionEndPosition = statusLine.find(" ");
+ auto statusCodeEndPosition = notFound;
// Extract the http version
if (httpVersionEndPosition != notFound) {
- String httpVersion = statusLine.left(httpVersionEndPosition);
+ auto httpVersion = statusLine.left(httpVersionEndPosition);
setHTTPVersion(httpVersion.stripWhiteSpace());
statusLine = statusLine.substring(httpVersionEndPosition + 1).stripWhiteSpace();
@@ -110,7 +123,7 @@
// Extract the http status text
if (statusCodeEndPosition != notFound) {
- String statusText = statusLine.substring(statusCodeEndPosition + 1);
+ auto statusText = statusLine.substring(statusCodeEndPosition + 1);
setHTTPStatusText(statusText.stripWhiteSpace());
}
}