Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[Fetch API] Implement data resolution for blob stored in Body
https://bugs.webkit.org/show_bug.cgi?id=155359

Reviewed by Darin Adler.

LayoutTests/imported/w3c:

* web-platform-tests/fetch/api/request/request-consume-expected.txt:
* web-platform-tests/fetch/api/request/request-consume.html:
* web-platform-tests/fetch/api/request/request-init-002-expected.txt:
* web-platform-tests/fetch/api/response/response-consume-expected.txt:
* web-platform-tests/fetch/api/response/response-consume.html:
* web-platform-tests/fetch/api/response/response-init-002-expected.txt:

Source/WebCore:

Introducing FetchLoader as a wrapper around ThreadableLoader to load resources.
FetchLoader can retrieve data as text or array buffer. It only supports blob currently.

Introducing FetchLoaderClient interface and FetchBodyOwner::BlobLoader as specifc blob loader client.

Covered by existing rebased tests.

* CMakeLists.txt:
* Modules/fetch/FetchBody.cpp:
(WebCore::FetchBody::loadingType):
(WebCore::FetchBody::loadedAsArrayBuffer):
(WebCore::FetchBody::loadedAsText):
* Modules/fetch/FetchBody.h:
* Modules/fetch/FetchBodyOwner.cpp: Added.
(WebCore::FetchBodyOwner::FetchBodyOwner):
(WebCore::FetchBodyOwner::loadBlob):
(WebCore::FetchBodyOwner::finishBlobLoading):
(WebCore::FetchBodyOwner::blobLoadingFailed):
(WebCore::FetchBodyOwner::BlobLoader::didReceiveResponse):
* Modules/fetch/FetchBodyOwner.h:
(WebCore::FetchBodyOwner::loadedBlobAsText):
(WebCore::FetchBodyOwner::loadedBlobAsArrayBuffer):
(WebCore::FetchBodyOwner::blobLoadingSucceeded):
* Modules/fetch/FetchLoader.cpp: Added.
(WebCore::FetchLoader::start):
(WebCore::FetchLoader::FetchLoader):
(WebCore::FetchLoader::stop):
(WebCore::FetchLoader::didReceiveResponse):
(WebCore::FetchLoader::didReceiveData):
(WebCore::FetchLoader::didFinishLoading):
(WebCore::FetchLoader::didFail):
* Modules/fetch/FetchLoader.h: Added.
* Modules/fetch/FetchLoaderClient.h: Added.
(WebCore::FetchLoaderClient::~FetchLoaderClient):
(WebCore::FetchLoaderClient::didReceiveResponse):
(WebCore::FetchLoaderClient::didFinishLoadingAsText):
(WebCore::FetchLoaderClient::didFinishLoadingAsArrayBuffer):
* WebCore.xcodeproj/project.pbxproj:


Canonical link: https://commits.webkit.org/173550@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@198133 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
youennf committed Mar 14, 2016
1 parent 69a9c34 commit 56eb35d
Show file tree
Hide file tree
Showing 19 changed files with 512 additions and 47 deletions.
14 changes: 14 additions & 0 deletions LayoutTests/imported/w3c/ChangeLog
@@ -1,3 +1,17 @@
2016-03-14 Youenn Fablet <youenn.fablet@crf.canon.fr>

[Fetch API] Implement data resolution for blob stored in Body
https://bugs.webkit.org/show_bug.cgi?id=155359

Reviewed by Darin Adler.

* web-platform-tests/fetch/api/request/request-consume-expected.txt:
* web-platform-tests/fetch/api/request/request-consume.html:
* web-platform-tests/fetch/api/request/request-init-002-expected.txt:
* web-platform-tests/fetch/api/response/response-consume-expected.txt:
* web-platform-tests/fetch/api/response/response-consume.html:
* web-platform-tests/fetch/api/response/response-init-002-expected.txt:

2016-03-14 Youenn Fablet <youenn.fablet@crf.canon.fr>

Web platform test server should not try to launch servers on already bound sockets
Expand Down
Expand Up @@ -5,9 +5,9 @@ PASS Consume request's body as arrayBuffer
PASS Consume request's body as json
FAIL Consume request's body as formData promise_test: Unhandled rejection with value: undefined
PASS Consume blob response's body as blob
FAIL Consume blob response's body as text promise_test: Unhandled rejection with value: undefined
FAIL Consume blob response's body as json promise_test: Unhandled rejection with value: undefined
FAIL Consume blob response's body as arrayBuffer promise_test: Unhandled rejection with value: undefined
PASS Consume blob response's body as text
PASS Consume blob response's body as json
PASS Consume blob response's body as arrayBuffer
PASS Consume JSON from text: '"null"'
PASS Consume JSON from text: '"1"'
PASS Consume JSON from text: '"true"'
Expand Down
Expand Up @@ -79,7 +79,7 @@

var formData = new FormData();
formData.append("name", "value")
var textData = "This is response's body";
var textData = JSON.stringify("This is response's body");
var blob = new Blob([textData], { "type" : "text/plain" });

checkRequestBody(textData, "text", checkBodyText);
Expand Down
@@ -1,6 +1,6 @@

PASS Initialize Request with headers values
FAIL Initialize Request's body with application/octet-binary promise_test: Unhandled rejection with value: undefined
PASS Initialize Request's body with application/octet-binary
FAIL Initialize Request's body with multipart/form-data promise_test: Unhandled rejection with value: undefined
PASS Initialize Request's body with text/plain;charset=UTF-8
FAIL Initialize Request's body with application/x-www-form-urlencoded;charset=UTF-8 promise_test: Unhandled rejection with value: "URLSearchParams not supported"
Expand Down
Expand Up @@ -5,7 +5,7 @@ PASS Consume response's body as arrayBuffer
PASS Consume response's body as json
FAIL Consume response's body as formData promise_test: Unhandled rejection with value: undefined
PASS Consume blob response's body as blob
FAIL Consume blob response's body as text promise_test: Unhandled rejection with value: undefined
FAIL Consume blob response's body as json promise_test: Unhandled rejection with value: undefined
FAIL Consume blob response's body as arrayBuffer promise_test: Unhandled rejection with value: undefined
PASS Consume blob response's body as text
PASS Consume blob response's body as json
PASS Consume blob response's body as arrayBuffer

Expand Up @@ -79,7 +79,7 @@

var formData = new FormData();
formData.append("name", "value");
var textData = "This is response's body";
var textData = JSON.stringify("This is response's body");
var blob = new Blob([textData], { "type" : "text/plain" });

checkResponseBody(textData, "text", checkBodyText);
Expand Down
@@ -1,6 +1,6 @@

PASS Initialize Response with headers values
FAIL Initialize Response's body with application/octet-binary promise_test: Unhandled rejection with value: undefined
PASS Initialize Response's body with application/octet-binary
FAIL Initialize Response's body with multipart/form-data promise_test: Unhandled rejection with value: undefined
FAIL Initialize Response's body with application/x-www-form-urlencoded;charset=UTF-8 assert_true: Content-Type header should be "application/x-www-form-urlencoded;charset=UTF-8" expected true got false
PASS Initialize Response's body with text/plain;charset=UTF-8
Expand Down
2 changes: 2 additions & 0 deletions Source/WebCore/CMakeLists.txt
Expand Up @@ -816,7 +816,9 @@ set(WebCore_SOURCES

Modules/fetch/DOMWindowFetch.cpp
Modules/fetch/FetchBody.cpp
Modules/fetch/FetchBodyOwner.cpp
Modules/fetch/FetchHeaders.cpp
Modules/fetch/FetchLoader.cpp
Modules/fetch/FetchRequest.cpp
Modules/fetch/FetchResponse.cpp
Modules/fetch/WorkerGlobalScopeFetch.cpp
Expand Down
46 changes: 46 additions & 0 deletions Source/WebCore/ChangeLog
@@ -1,3 +1,49 @@
2016-03-14 Youenn Fablet <youenn.fablet@crf.canon.fr>

[Fetch API] Implement data resolution for blob stored in Body
https://bugs.webkit.org/show_bug.cgi?id=155359

Reviewed by Darin Adler.

Introducing FetchLoader as a wrapper around ThreadableLoader to load resources.
FetchLoader can retrieve data as text or array buffer. It only supports blob currently.

Introducing FetchLoaderClient interface and FetchBodyOwner::BlobLoader as specifc blob loader client.

Covered by existing rebased tests.

* CMakeLists.txt:
* Modules/fetch/FetchBody.cpp:
(WebCore::FetchBody::loadingType):
(WebCore::FetchBody::loadedAsArrayBuffer):
(WebCore::FetchBody::loadedAsText):
* Modules/fetch/FetchBody.h:
* Modules/fetch/FetchBodyOwner.cpp: Added.
(WebCore::FetchBodyOwner::FetchBodyOwner):
(WebCore::FetchBodyOwner::loadBlob):
(WebCore::FetchBodyOwner::finishBlobLoading):
(WebCore::FetchBodyOwner::blobLoadingFailed):
(WebCore::FetchBodyOwner::BlobLoader::didReceiveResponse):
* Modules/fetch/FetchBodyOwner.h:
(WebCore::FetchBodyOwner::loadedBlobAsText):
(WebCore::FetchBodyOwner::loadedBlobAsArrayBuffer):
(WebCore::FetchBodyOwner::blobLoadingSucceeded):
* Modules/fetch/FetchLoader.cpp: Added.
(WebCore::FetchLoader::start):
(WebCore::FetchLoader::FetchLoader):
(WebCore::FetchLoader::stop):
(WebCore::FetchLoader::didReceiveResponse):
(WebCore::FetchLoader::didReceiveData):
(WebCore::FetchLoader::didFinishLoading):
(WebCore::FetchLoader::didFail):
* Modules/fetch/FetchLoader.h: Added.
* Modules/fetch/FetchLoaderClient.h: Added.
(WebCore::FetchLoaderClient::~FetchLoaderClient):
(WebCore::FetchLoaderClient::didReceiveResponse):
(WebCore::FetchLoaderClient::didFinishLoadingAsText):
(WebCore::FetchLoaderClient::didFinishLoadingAsArrayBuffer):
* WebCore.xcodeproj/project.pbxproj:

2016-03-14 Frederic Wang <fwang@igalia.com>

Make MathML colspan/rowspan consistent with HTML table cells.
Expand Down
42 changes: 32 additions & 10 deletions Source/WebCore/Modules/fetch/FetchBody.cpp
Expand Up @@ -135,8 +135,11 @@ void FetchBody::json(FetchBodyOwner& owner, DeferredWrapper&& promise)
if (processIfEmptyOrDisturbed(Consumer::Type::JSON, promise))
return;

if (!owner.scriptExecutionContext())
return;

if (m_type == Type::Text) {
resolveAsJSON(owner.scriptExecutionContext(), m_text, WTFMove(promise));
resolveAsJSON(*owner.scriptExecutionContext(), m_text, WTFMove(promise));
return;
}
consume(owner, Consumer::Type::JSON, WTFMove(promise));
Expand Down Expand Up @@ -182,19 +185,18 @@ void FetchBody::consumeText(Consumer::Type type, DeferredWrapper&& promise)
promise.resolve<RefPtr<Blob>>(Blob::create(extractFromText(), contentType));
}

FetchLoadingType FetchBody::loadingType(Consumer::Type type)
FetchLoader::Type FetchBody::loadingType(Consumer::Type type)
{
switch (type) {
case Consumer::Type::JSON:
case Consumer::Type::Text:
return FetchLoadingType::Text;
return FetchLoader::Type::Text;
case Consumer::Type::Blob:
return FetchLoadingType::Blob;
case Consumer::Type::ArrayBuffer:
return FetchLoadingType::ArrayBuffer;
return FetchLoader::Type::ArrayBuffer;
default:
ASSERT_NOT_REACHED();
return FetchLoadingType::ArrayBuffer;
return FetchLoader::Type::ArrayBuffer;
};
}

Expand All @@ -206,9 +208,9 @@ void FetchBody::consumeBlob(FetchBodyOwner& owner, Consumer::Type type, Deferred
owner.loadBlob(*m_blob, loadingType(type));
}

void FetchBody::resolveAsJSON(ScriptExecutionContext* context, const String& data, DeferredWrapper&& promise)
void FetchBody::resolveAsJSON(ScriptExecutionContext& context, const String& data, DeferredWrapper&& promise)
{
DOMRequestState state(context);
DOMRequestState state(&context);
JSC::JSValue value = JSC::JSONParse(state.exec(), data);
if (!value)
promise.reject<ExceptionCode>(SYNTAX_ERR);
Expand All @@ -233,10 +235,30 @@ void FetchBody::loadingFailed()
m_consumer = Nullopt;
}

void FetchBody::loadedAsBlob(Blob& blob)
void FetchBody::loadedAsArrayBuffer(RefPtr<ArrayBuffer>&& buffer)
{
ASSERT(m_consumer);
m_consumer->promise.resolve(&blob);
ASSERT(m_consumer->type == Consumer::Type::Blob || m_consumer->type == Consumer::Type::ArrayBuffer);
if (m_consumer->type == Consumer::Type::ArrayBuffer)
m_consumer->promise.resolve(buffer);
else {
ASSERT(m_blob);
Vector<char> data;
data.reserveCapacity(buffer->byteLength());
data.append(static_cast<const char*>(buffer->data()), buffer->byteLength());
m_consumer->promise.resolve<RefPtr<Blob>>(Blob::create(WTFMove(data), m_blob->type()));
}
m_consumer = Nullopt;
}

void FetchBody::loadedAsText(ScriptExecutionContext& context, String&& text)
{
ASSERT(m_consumer);
ASSERT(m_consumer->type == Consumer::Type::Text || m_consumer->type == Consumer::Type::JSON);
if (m_consumer->type == Consumer::Type::Text)
m_consumer->promise.resolve(text);
else
resolveAsJSON(context, text, WTFMove(m_consumer->promise));
m_consumer = Nullopt;
}

Expand Down
9 changes: 5 additions & 4 deletions Source/WebCore/Modules/fetch/FetchBody.h
Expand Up @@ -33,6 +33,7 @@

#include "Blob.h"
#include "DOMFormData.h"
#include "FetchLoader.h"
#include "JSDOMPromise.h"

namespace JSC {
Expand All @@ -43,7 +44,6 @@ class JSValue;
namespace WebCore {

class FetchBodyOwner;
enum class FetchLoadingType;

class FetchBody {
public:
Expand All @@ -64,7 +64,8 @@ class FetchBody {
FetchBody() = default;

void loadingFailed();
void loadedAsBlob(Blob&);
void loadedAsArrayBuffer(RefPtr<ArrayBuffer>&&);
void loadedAsText(ScriptExecutionContext&, String&&);

private:
enum class Type { None, Text, Blob, FormData };
Expand All @@ -85,8 +86,8 @@ class FetchBody {
bool processIfEmptyOrDisturbed(Consumer::Type, DeferredWrapper&);
void consumeText(Consumer::Type, DeferredWrapper&&);
void consumeBlob(FetchBodyOwner&, Consumer::Type, DeferredWrapper&&);
void resolveAsJSON(ScriptExecutionContext*, const String&, DeferredWrapper&&);
static FetchLoadingType loadingType(Consumer::Type);
void resolveAsJSON(ScriptExecutionContext&, const String&, DeferredWrapper&&);
static FetchLoader::Type loadingType(Consumer::Type);

Type m_type = Type::None;
String m_mimeType;
Expand Down
104 changes: 104 additions & 0 deletions Source/WebCore/Modules/fetch/FetchBodyOwner.cpp
@@ -0,0 +1,104 @@
/*
* Copyright (C) 2016 Canon Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions
* are required to be 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.
* 3. Neither the name of Canon Inc. nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY CANON 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 CANON INC. AND 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.
*/

#include "config.h"
#include "FetchBodyOwner.h"

#if ENABLE(FETCH_API)

#include "FetchLoader.h"
#include "ResourceResponse.h"

namespace WebCore {

FetchBodyOwner::FetchBodyOwner(ScriptExecutionContext& context, FetchBody&& body)
: ActiveDOMObject(&context)
, m_body(WTFMove(body))
{
suspendIfNeeded();
}

void FetchBodyOwner::stop()
{
if (m_blobLoader) {
if (m_blobLoader->loader)
m_blobLoader->loader->stop();
finishBlobLoading();
}
ASSERT(!m_blobLoader);
}

void FetchBodyOwner::loadBlob(Blob& blob, FetchLoader::Type type)
{
// Can only be called once for a body instance.
ASSERT(m_body.isDisturbed());
ASSERT(!m_blobLoader);

m_blobLoader = { *this };
m_blobLoader->loader = std::make_unique<FetchLoader>(type, *m_blobLoader);

setPendingActivity(this);
if (!scriptExecutionContext() || !m_blobLoader->loader->start(*scriptExecutionContext(), blob))
blobLoadingFailed();
}

void FetchBodyOwner::loadedBlobAsText(String&& text)
{
ASSERT(*scriptExecutionContext());

m_body.loadedAsText(*scriptExecutionContext(), WTFMove(text));
}

void FetchBodyOwner::finishBlobLoading()
{
ASSERT(m_blobLoader);

m_blobLoader = Nullopt;
unsetPendingActivity(this);
}

void FetchBodyOwner::blobLoadingFailed()
{
m_body.loadingFailed();
finishBlobLoading();
}

FetchBodyOwner::BlobLoader::BlobLoader(FetchBodyOwner& owner)
: owner(owner)
{
}

void FetchBodyOwner::BlobLoader::didReceiveResponse(const ResourceResponse& response)
{
if (response.httpStatusCode() != 200)
didFail();
}

} // namespace WebCore

#endif // ENABLE(FETCH_API)

0 comments on commit 56eb35d

Please sign in to comment.