Index: Source/modules/fetch/Request.cpp |
diff --git a/Source/modules/fetch/Request.cpp b/Source/modules/fetch/Request.cpp |
index 82e6f5ad415045af0344498b0e441dcafa50d56b..9f7608476ce4b5d5db127958d8fbd62fb4967380 100644 |
--- a/Source/modules/fetch/Request.cpp |
+++ b/Source/modules/fetch/Request.cpp |
@@ -11,6 +11,8 @@ |
#include "core/fetch/FetchUtils.h" |
#include "core/fetch/ResourceLoaderOptions.h" |
#include "core/loader/ThreadableLoader.h" |
+#include "modules/fetch/BodyStreamBuffer.h" |
+#include "modules/fetch/FetchBlobDataConsumerHandle.h" |
#include "modules/fetch/FetchManager.h" |
#include "modules/fetch/RequestInit.h" |
#include "platform/network/HTTPParsers.h" |
@@ -47,7 +49,8 @@ FetchRequestData* createCopyOfFetchRequestDataForFetch(ScriptState* scriptState, |
Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Request* inputRequest, const String& inputString, const RequestInit& init, ExceptionState& exceptionState) |
{ |
// "1. Let |temporaryBody| be null." |
- RefPtr<BlobDataHandle> temporaryBody; |
+ Request* temporaryBodyRequest = nullptr; |
+ BodyStreamBuffer* temporaryBodyBuffer = nullptr; |
if (inputRequest) { |
// We check bodyUsed even when the body is null in spite of the |
@@ -67,18 +70,9 @@ Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Req |
exceptionState.throwTypeError("Cannot construct a Request with a Request object that has already been used."); |
return nullptr; |
} |
- if (inputRequest->isBodyConsumed()) { |
- // Currently the only methods that can consume body data without |
- // setting 'body passed' flag consume entire body (e.g. text()). |
- // Thus we can set an empty blob to the new request instead of |
- // creating a draining stream. |
- // TODO(yhirano): Fix this once Request.body is introduced. |
- OwnPtr<BlobData> blobData = BlobData::create(); |
- blobData->setContentType(inputRequest->blobDataHandle()->type()); |
- temporaryBody = BlobDataHandle::create(blobData.release(), 0); |
- } else { |
- temporaryBody = inputRequest->m_request->blobDataHandle(); |
- } |
+ // We call createDrainingStream() later and not here, because |
+ // createDrainingStream() has side effects on |inputRequest|'s body. |
+ temporaryBodyRequest = inputRequest; |
} |
// "3. Let |request| be |input|'s request, if |input| is a Request object, |
@@ -219,7 +213,7 @@ Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Req |
// "27. If either |init|'s body member is present or |temporaryBody| is |
// non-null, and |request|'s method is `GET` or `HEAD`, throw a TypeError. |
- if (init.bodyBlobHandle || temporaryBody) { |
+ if (init.bodyBlobHandle || temporaryBodyRequest) { |
if (request->method() == "GET" || request->method() == "HEAD") { |
exceptionState.throwTypeError("Request with GET/HEAD method cannot have body."); |
return nullptr; |
@@ -235,7 +229,8 @@ Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Req |
// contains no header named `Content-Type`, append |
// `Content-Type`/|Content-Type| to |r|'s Headers object. Rethrow any |
// exception." |
- temporaryBody = init.bodyBlobHandle; |
+ temporaryBodyBuffer = BodyStreamBuffer::create(FetchBlobDataConsumerHandle::create(scriptState->executionContext(), init.bodyBlobHandle)); |
+ temporaryBodyRequest = nullptr; |
if (!init.bodyBlobHandle->type().isEmpty() && !r->headers()->has("Content-Type", exceptionState)) { |
r->headers()->append("Content-Type", init.bodyBlobHandle->type(), exceptionState); |
} |
@@ -244,7 +239,10 @@ Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Req |
} |
// "29. Set |r|'s body to |temporaryBody|. |
- r->setBodyBlobHandle(temporaryBody.release()); |
+ if (temporaryBodyBuffer) |
+ r->setBuffer(temporaryBodyBuffer); |
+ else if (temporaryBodyRequest) |
+ r->setBuffer(temporaryBodyRequest->createDrainingStream()->leakBuffer()); |
// "30. Set |r|'s MIME type to the result of extracting a MIME type from |
// |r|'s request's header list." |
@@ -256,7 +254,7 @@ Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Req |
// spec. See https://github.com/whatwg/fetch/issues/61 for details. |
if (inputRequest) { |
// "1. Set |input|'s body to null." |
- inputRequest->setBodyBlobHandle(nullptr); |
+ inputRequest->setBuffer(nullptr); |
// "2. Set |input|'s used flag." |
inputRequest->lockBody(PassBody); |
} |
@@ -306,10 +304,15 @@ Request::Request(ExecutionContext* context, FetchRequestData* request) |
, m_headers(Headers::create(m_request->headerList())) |
{ |
m_headers->setGuard(Headers::RequestGuard); |
+ |
+ refreshBody(); |
} |
Request::Request(ExecutionContext* context, FetchRequestData* request, Headers* headers) |
- : Body(context) , m_request(request) , m_headers(headers) { } |
+ : Body(context) , m_request(request) , m_headers(headers) |
+{ |
+ refreshBody(); |
+} |
Request* Request::create(ExecutionContext* context, const WebServiceWorkerRequest& webRequest) |
{ |
@@ -320,10 +323,12 @@ Request* Request::create(ExecutionContext* context, const WebServiceWorkerReques |
Request::Request(ExecutionContext* context, const WebServiceWorkerRequest& webRequest) |
: Body(context) |
- , m_request(FetchRequestData::create(webRequest)) |
+ , m_request(FetchRequestData::create(context, webRequest)) |
, m_headers(Headers::create(m_request->headerList())) |
{ |
m_headers->setGuard(Headers::RequestGuard); |
+ |
+ refreshBody(); |
} |
String Request::method() const |
@@ -465,37 +470,39 @@ String Request::credentials() const |
return ""; |
} |
-Request* Request::clone(ExceptionState& exceptionState) const |
+Request* Request::clone(ExceptionState& exceptionState) |
{ |
if (bodyUsed()) { |
exceptionState.throwTypeError("Request body is already used"); |
return nullptr; |
} |
- FetchRequestData* request = m_request->clone(); |
- if (blobDataHandle() && isBodyConsumed()) { |
- // Currently the only methods that can consume body data without |
- // setting 'body passed' flag consume entire body (e.g. text()). Thus |
- // we can set an empty blob to the new request instead of creating a |
- // draining stream. |
- // TODO(yhirano): Fix this once Request.body is introduced. |
- OwnPtr<BlobData> blobData = BlobData::create(); |
- blobData->setContentType(blobDataHandle()->type()); |
- request->setBlobDataHandle(BlobDataHandle::create(blobData.release(), 0)); |
- } |
+ if (OwnPtr<DrainingBodyStreamBuffer> buffer = createDrainingStream()) |
+ m_request->setBuffer(buffer->leakBuffer()); |
+ FetchRequestData* request = m_request->clone(executionContext()); |
Headers* headers = Headers::create(request->headerList()); |
headers->setGuard(m_headers->guard()); |
Request* r = new Request(executionContext(), request, headers); |
r->suspendIfNeeded(); |
+ |
+ // Lock the old body and set |body| property to the new one. |
+ lockBody(); |
+ refreshBody(); |
return r; |
} |
FetchRequestData* Request::passRequestData() |
{ |
ASSERT(!bodyUsed()); |
+ |
+ if (OwnPtr<DrainingBodyStreamBuffer> buffer = createDrainingStream()) |
+ m_request->setBuffer(buffer->leakBuffer()); |
+ |
lockBody(PassBody); |
- return m_request->pass(); |
+ FetchRequestData* newRequestData = m_request->pass(executionContext()); |
+ refreshBody(); |
+ return newRequestData; |
} |
void Request::populateWebServiceWorkerRequest(WebServiceWorkerRequest& webRequest) const |
@@ -516,26 +523,20 @@ void Request::populateWebServiceWorkerRequest(WebServiceWorkerRequest& webReques |
// to plumb this information in to here. |
} |
-void Request::setBodyBlobHandle(PassRefPtr<BlobDataHandle> blobDataHandle) |
-{ |
- m_request->setBlobDataHandle(blobDataHandle); |
- setBody(m_request->blobDataHandle()); |
-} |
- |
-void Request::clearHeaderList() |
+void Request::setBuffer(BodyStreamBuffer* buffer) |
{ |
- m_request->headerList()->clearList(); |
+ m_request->setBuffer(buffer); |
+ refreshBody(); |
} |
-PassRefPtr<BlobDataHandle> Request::blobDataHandle() const |
+void Request::refreshBody() |
{ |
- return m_request->blobDataHandle(); |
+ setBody(m_request->buffer()); |
} |
-BodyStreamBuffer* Request::buffer() const |
+void Request::clearHeaderList() |
{ |
- // We don't support BodyStreamBuffer for Request yet. |
- return nullptr; |
+ m_request->headerList()->clearList(); |
} |
String Request::mimeType() const |