 Chromium Code Reviews
 Chromium Code Reviews Issue 1192913007:
  Change BodyStreamBuffer to be FetchDataConsumerHandle-based and enable backpressure in Fetch API  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/blink.git@master
    
  
    Issue 1192913007:
  Change BodyStreamBuffer to be FetchDataConsumerHandle-based and enable backpressure in Fetch API  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/blink.git@master| Index: Source/modules/fetch/Request.cpp | 
| diff --git a/Source/modules/fetch/Request.cpp b/Source/modules/fetch/Request.cpp | 
| index 82e6f5ad415045af0344498b0e441dcafa50d56b..f9d28bacadf709c16988d60818c1c51c7770a0fe 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,7 @@ 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; | 
| + OwnPtr<DrainingBodyStreamBuffer> temporaryBody = nullptr; | 
| if (inputRequest) { | 
| // We check bodyUsed even when the body is null in spite of the | 
| @@ -67,18 +69,7 @@ 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(); | 
| - } | 
| + temporaryBody = inputRequest->createDrainingStream(); | 
| 
yhirano
2015/07/03 04:42:28
The spec intends to not mutate |inputRequest|'s bo
 
hiroshige
2015/07/05 07:30:25
Yes.
I modified the code to remove the side effect
 | 
| } | 
| // "3. Let |request| be |input|'s request, if |input| is a Request object, | 
| @@ -235,7 +226,7 @@ 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; | 
| + temporaryBody = DrainingBodyStreamBuffer::create(BodyStreamBuffer::create(FetchBlobDataConsumerHandle::create(scriptState->executionContext(), init.bodyBlobHandle)), nullptr); | 
| if (!init.bodyBlobHandle->type().isEmpty() && !r->headers()->has("Content-Type", exceptionState)) { | 
| r->headers()->append("Content-Type", init.bodyBlobHandle->type(), exceptionState); | 
| } | 
| @@ -244,7 +235,8 @@ Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Req | 
| } | 
| // "29. Set |r|'s body to |temporaryBody|. | 
| - r->setBodyBlobHandle(temporaryBody.release()); | 
| + if (temporaryBody) | 
| + r->setBuffer(temporaryBody->leak()); | 
| // "30. Set |r|'s MIME type to the result of extracting a MIME type from | 
| // |r|'s request's header list." | 
| @@ -256,7 +248,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 +298,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 +317,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 +464,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->leak()); | 
| + 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->leak()); | 
| + | 
| lockBody(PassBody); | 
| - return m_request->pass(); | 
| + FetchRequestData* newRequestData = m_request->pass(executionContext()); | 
| + refreshBody(); | 
| + return newRequestData; | 
| } | 
| void Request::populateWebServiceWorkerRequest(WebServiceWorkerRequest& webRequest) const | 
| @@ -516,26 +517,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 |