[Fetch API] Implement data resolution for blob stored in Body
authoryouenn.fablet@crf.canon.fr <youenn.fablet@crf.canon.fr@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 14 Mar 2016 15:58:14 +0000 (15:58 +0000)
committeryouenn.fablet@crf.canon.fr <youenn.fablet@crf.canon.fr@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 14 Mar 2016 15:58:14 +0000 (15:58 +0000)
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:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@198133 268f45cc-cd09-0410-ab3c-d52691b4dbfc

19 files changed:
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-consume-expected.txt
LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-consume.html
LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-init-002-expected.txt
LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-consume-expected.txt
LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-consume.html
LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-init-002-expected.txt
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/Modules/fetch/FetchBody.cpp
Source/WebCore/Modules/fetch/FetchBody.h
Source/WebCore/Modules/fetch/FetchBodyOwner.cpp [new file with mode: 0644]
Source/WebCore/Modules/fetch/FetchBodyOwner.h
Source/WebCore/Modules/fetch/FetchLoader.cpp [new file with mode: 0644]
Source/WebCore/Modules/fetch/FetchLoader.h [new file with mode: 0644]
Source/WebCore/Modules/fetch/FetchLoaderClient.h [new file with mode: 0644]
Source/WebCore/Modules/fetch/FetchRequest.cpp
Source/WebCore/Modules/fetch/FetchResponse.cpp
Source/WebCore/WebCore.xcodeproj/project.pbxproj

index 5248dd5..d139a87 100644 (file)
@@ -1,5 +1,19 @@
 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
         https://bugs.webkit.org/show_bug.cgi?id=141157
 
index 96e7cec..b0f2fbf 100644 (file)
@@ -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"' 
index e365b72..269fe27 100644 (file)
@@ -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);
index ebc2aba..f40a9e5 100644 (file)
@@ -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"
index 0326d2d..d088a69 100644 (file)
@@ -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 
 
index 48d4bf9..50f51c4 100644 (file)
@@ -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);
index ab60ee1..4167d0f 100644 (file)
@@ -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 
index 978d40d..0f5a2d8 100644 (file)
@@ -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
index 4885d57..84e4898 100644 (file)
@@ -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.
index cc9b595..1efa197 100644 (file)
@@ -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));
@@ -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;
     };
 }
 
@@ -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);
@@ -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;
 }
 
index 012b304..965f805 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "Blob.h"
 #include "DOMFormData.h"
+#include "FetchLoader.h"
 #include "JSDOMPromise.h"
 
 namespace JSC {
@@ -43,7 +44,6 @@ class JSValue;
 namespace WebCore {
 
 class FetchBodyOwner;
-enum class FetchLoadingType;
 
 class FetchBody {
 public:
@@ -64,7 +64,8 @@ public:
     FetchBody() = default;
 
     void loadingFailed();
-    void loadedAsBlob(Blob&);
+    void loadedAsArrayBuffer(RefPtr<ArrayBuffer>&&);
+    void loadedAsText(ScriptExecutionContext&, String&&);
 
 private:
     enum class Type { None, Text, Blob, FormData };
@@ -85,8 +86,8 @@ private:
     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;
diff --git a/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp b/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp
new file mode 100644 (file)
index 0000000..a74a36d
--- /dev/null
@@ -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)
index 7206e6d..3a698ea 100644 (file)
 
 #include "ActiveDOMObject.h"
 #include "FetchBody.h"
+#include "FetchLoader.h"
+#include "FetchLoaderClient.h"
 
 namespace WebCore {
 
-enum class FetchLoadingType { Text, ArrayBuffer, Blob };
-
 class FetchBodyOwner : public RefCounted<FetchBodyOwner>, public ActiveDOMObject {
 public:
     FetchBodyOwner(ScriptExecutionContext&, FetchBody&&);
@@ -50,29 +50,41 @@ public:
     void json(DeferredWrapper&& promise) { m_body.json(*this, WTFMove(promise)); }
     void text(DeferredWrapper&& promise) { m_body.text(*this, WTFMove(promise)); }
 
-    void loadBlob(Blob&, FetchLoadingType);
+    void loadBlob(Blob&, FetchLoader::Type);
+
+    bool isActive() const { return !!m_blobLoader; }
+
+private:
+    // Blob loading routines
+    void loadedBlobAsText(String&&);
+    void loadedBlobAsArrayBuffer(RefPtr<ArrayBuffer>&& buffer) { m_body.loadedAsArrayBuffer(WTFMove(buffer)); }
+    void blobLoadingSucceeded() { finishBlobLoading(); }
+    void blobLoadingFailed();
+    void finishBlobLoading();
+
+    // ActiveDOMObject API
+    void stop() override;
+
+    struct BlobLoader final : FetchLoaderClient {
+        BlobLoader(FetchBodyOwner&);
+
+        // FetchLoaderClient API
+        void didFinishLoadingAsText(String&& text) final { owner.loadedBlobAsText(WTFMove(text)); }
+        void didFinishLoadingAsArrayBuffer(RefPtr<ArrayBuffer>&& buffer) final { owner.loadedBlobAsArrayBuffer(WTFMove(buffer)); }
+        void didReceiveResponse(const ResourceResponse&) final;
+        void didFail() final { owner.blobLoadingFailed(); };
+        void didSucceed() final { owner.blobLoadingSucceeded(); }
+
+        FetchBodyOwner& owner;
+        std::unique_ptr<FetchLoader> loader;
+    };
 
 protected:
     FetchBody m_body;
-};
 
-inline FetchBodyOwner::FetchBodyOwner(ScriptExecutionContext& context, FetchBody&& body)
-    : ActiveDOMObject(&context)
-    , m_body(WTFMove(body))
-{
-    suspendIfNeeded();
-}
-
-inline void FetchBodyOwner::loadBlob(Blob& blob, FetchLoadingType type)
-{
-    if (type == FetchLoadingType::Blob) {
-        // FIXME: Clone blob.
-        m_body.loadedAsBlob(blob);
-        return;
-    }
-    // FIXME: Implement blob loading.
-    m_body.loadingFailed();
-}
+private:
+    Optional<BlobLoader> m_blobLoader;
+};
 
 } // namespace WebCore
 
diff --git a/Source/WebCore/Modules/fetch/FetchLoader.cpp b/Source/WebCore/Modules/fetch/FetchLoader.cpp
new file mode 100644 (file)
index 0000000..30fccc7
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * 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 "FetchLoader.h"
+
+#if ENABLE(FETCH_API)
+
+#include "BlobURL.h"
+#include "FetchBody.h"
+#include "FetchLoaderClient.h"
+#include "ResourceRequest.h"
+#include "ScriptExecutionContext.h"
+#include "SharedBuffer.h"
+#include "TextResourceDecoder.h"
+#include "ThreadableBlobRegistry.h"
+#include "ThreadableLoader.h"
+
+namespace WebCore {
+
+bool FetchLoader::start(ScriptExecutionContext& context, Blob& blob)
+{
+    auto urlForReading = BlobURL::createPublicURL(context.securityOrigin());
+    if (urlForReading.isEmpty())
+        return false;
+    ThreadableBlobRegistry::registerBlobURL(context.securityOrigin(), urlForReading, blob.url());
+
+    ResourceRequest request(urlForReading);
+    request.setHTTPMethod("GET");
+
+    ThreadableLoaderOptions options;
+    options.setSendLoadCallbacks(SendCallbacks);
+    options.setSniffContent(DoNotSniffContent);
+    options.setDataBufferingPolicy(DoNotBufferData);
+    options.preflightPolicy = ConsiderPreflight;
+    options.setAllowCredentials(AllowStoredCredentials);
+    options.crossOriginRequestPolicy = DenyCrossOriginRequests;
+    options.contentSecurityPolicyEnforcement = ContentSecurityPolicyEnforcement::DoNotEnforce;
+
+    m_loader = ThreadableLoader::create(&context, this, request, options);
+    return true;
+}
+
+FetchLoader::FetchLoader(Type type, FetchLoaderClient& client)
+    : m_type(type)
+    , m_client(client)
+{
+}
+
+void FetchLoader::stop()
+{
+    if (m_loader) {
+        m_loader->cancel();
+        m_loader = nullptr;
+    }
+    m_data = nullptr;
+}
+
+void FetchLoader::didReceiveResponse(unsigned long, const ResourceResponse& response)
+{
+    m_client.didReceiveResponse(response);
+}
+
+// FIXME: We should make text and blob creation more efficient.
+// We might also want to merge this class with FileReaderLoader.
+void FetchLoader::didReceiveData(const char* value, int size)
+{
+    if (!m_data) {
+        m_data = SharedBuffer::create(value, size);
+        return;
+    }
+    m_data->append(value, size);
+}
+
+void FetchLoader::didFinishLoading(unsigned long, double)
+{
+    if (m_type == Type::ArrayBuffer)
+        m_client.didFinishLoadingAsArrayBuffer(m_data->createArrayBuffer());
+    else
+        m_client.didFinishLoadingAsText(TextResourceDecoder::create(ASCIILiteral("text/plain"), "UTF-8")->decodeAndFlush(m_data->data(), m_data->size()));
+    m_data = nullptr;
+
+    m_client.didSucceed();
+}
+
+void FetchLoader::didFail(const ResourceError&)
+{
+    m_client.didFail();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(FETCH_API)
diff --git a/Source/WebCore/Modules/fetch/FetchLoader.h b/Source/WebCore/Modules/fetch/FetchLoader.h
new file mode 100644 (file)
index 0000000..ef0a736
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#ifndef FetchLoader_h
+#define FetchLoader_h
+
+#if ENABLE(FETCH_API)
+
+#include "SharedBuffer.h"
+#include "ThreadableLoader.h"
+#include "ThreadableLoaderClient.h"
+
+namespace WebCore {
+
+class Blob;
+class FetchLoaderClient;
+class ScriptExecutionContext;
+
+class FetchLoader final : public ThreadableLoaderClient {
+public:
+    enum class Type { ArrayBuffer, Text };
+
+    FetchLoader(Type, FetchLoaderClient&);
+
+    bool start(ScriptExecutionContext&, Blob&);
+    void stop();
+
+private:
+    // ThreadableLoaderClient API.
+    void didReceiveResponse(unsigned long, const ResourceResponse&) final;
+    void didReceiveData(const char*, int) final;
+    void didFinishLoading(unsigned long, double) final;
+    void didFail(const ResourceError&) final;
+
+private:
+    Type m_type { Type::ArrayBuffer };
+    FetchLoaderClient& m_client;
+    RefPtr<ThreadableLoader> m_loader;
+    RefPtr<SharedBuffer> m_data;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(FETCH_API)
+
+#endif // FetchLoader_h
diff --git a/Source/WebCore/Modules/fetch/FetchLoaderClient.h b/Source/WebCore/Modules/fetch/FetchLoaderClient.h
new file mode 100644 (file)
index 0000000..dd35cbb
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+#ifndef FetchLoaderClient_h
+#define FetchLoaderClient_h
+
+#if ENABLE(FETCH_API)
+
+#include <wtf/Forward.h>
+
+namespace JSC {
+class ArrayBuffer;
+}
+
+namespace WebCore {
+
+class ResourceResponse;
+
+class FetchLoaderClient {
+public:
+    virtual ~FetchLoaderClient() { }
+
+    virtual void didReceiveResponse(const ResourceResponse&) { }
+
+    virtual void didFinishLoadingAsText(String&&) { }
+    virtual void didFinishLoadingAsArrayBuffer(RefPtr<JSC::ArrayBuffer>&&) { }
+
+    virtual void didSucceed() = 0;
+    virtual void didFail() = 0;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(FETCH_API)
+
+#endif // FetchLoaderClient_h
index 11b3d94..d6aea56 100644 (file)
@@ -453,7 +453,8 @@ const char* FetchRequest::activeDOMObjectName() const
 
 bool FetchRequest::canSuspendForDocumentSuspension() const
 {
-    return true;
+    // FIXME: We can probably do the same strategy as XHR.
+    return !isActive();
 }
 
 } // namespace WebCore
index ba8e8c3..351049c 100644 (file)
@@ -160,7 +160,8 @@ const char* FetchResponse::activeDOMObjectName() const
 
 bool FetchResponse::canSuspendForDocumentSuspension() const
 {
-    return true;
+    // FIXME: We can probably do the same strategy as XHR.
+    return !isActive();
 }
 
 } // namespace WebCore
index 4718ab2..4b17863 100644 (file)
                4138D3351244054800323D33 /* EventContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 4138D3331244054800323D33 /* EventContext.h */; };
                4138D3361244054800323D33 /* EventContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4138D3341244054800323D33 /* EventContext.cpp */; };
                413C2C341BC29A8F0075204C /* JSDOMConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 413C2C331BC29A7B0075204C /* JSDOMConstructor.h */; };
+               4147E2B71C89912C00A7E715 /* FetchLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4147E2B41C89912600A7E715 /* FetchLoader.cpp */; };
+               4147E2B81C89912F00A7E715 /* FetchBodyOwner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4147E2B31C89912600A7E715 /* FetchBodyOwner.cpp */; };
                415071571685067300C3C7B3 /* SelectorFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 415071551685067300C3C7B3 /* SelectorFilter.cpp */; };
                415071581685067300C3C7B3 /* SelectorFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 415071561685067300C3C7B3 /* SelectorFilter.h */; };
                4150F9F112B6E0E70008C860 /* SliderThumbElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 4150F9EF12B6E0E70008C860 /* SliderThumbElement.h */; };
                4138D3341244054800323D33 /* EventContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EventContext.cpp; sourceTree = "<group>"; };
                413C2C331BC29A7B0075204C /* JSDOMConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMConstructor.h; sourceTree = "<group>"; };
                4147E2B21C88337F00A7E715 /* FetchBodyOwner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FetchBodyOwner.h; sourceTree = "<group>"; };
+               4147E2B31C89912600A7E715 /* FetchBodyOwner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FetchBodyOwner.cpp; sourceTree = "<group>"; };
+               4147E2B41C89912600A7E715 /* FetchLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FetchLoader.cpp; sourceTree = "<group>"; };
+               4147E2B51C89912600A7E715 /* FetchLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FetchLoader.h; sourceTree = "<group>"; };
+               4147E2B61C89912600A7E715 /* FetchLoaderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FetchLoaderClient.h; sourceTree = "<group>"; };
                415071551685067300C3C7B3 /* SelectorFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SelectorFilter.cpp; sourceTree = "<group>"; };
                415071561685067300C3C7B3 /* SelectorFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectorFilter.h; sourceTree = "<group>"; };
                4150F9EF12B6E0E70008C860 /* SliderThumbElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SliderThumbElement.h; sourceTree = "<group>"; };
                                41F54F7D1C50C4F600338488 /* FetchBody.cpp */,
                                41F54F7E1C50C4F600338488 /* FetchBody.h */,
                                41F54F7F1C50C4F600338488 /* FetchBody.idl */,
+                               4147E2B31C89912600A7E715 /* FetchBodyOwner.cpp */,
                                4147E2B21C88337F00A7E715 /* FetchBodyOwner.h */,
                                41F54F821C50C4F600338488 /* FetchHeaders.cpp */,
                                41F54F831C50C4F600338488 /* FetchHeaders.h */,
                                41F54F841C50C4F600338488 /* FetchHeaders.idl */,
                                41F54F851C50C4F600338488 /* FetchHeaders.js */,
+                               4147E2B41C89912600A7E715 /* FetchLoader.cpp */,
+                               4147E2B51C89912600A7E715 /* FetchLoader.h */,
+                               4147E2B61C89912600A7E715 /* FetchLoaderClient.h */,
                                41F54F861C50C4F600338488 /* FetchOptions.h */,
                                41F54F871C50C4F600338488 /* FetchRequest.cpp */,
                                41F54F881C50C4F600338488 /* FetchRequest.h */,
                                07969DC117D14151007FF842 /* JSRTCStatsReport.cpp in Sources */,
                                07969DC317D14151007FF842 /* JSRTCStatsResponse.cpp in Sources */,
                                07DC5FD417D3EEE90099F890 /* JSRTCStatsResponseCustom.cpp in Sources */,
+                               4147E2B81C89912F00A7E715 /* FetchBodyOwner.cpp in Sources */,
                                5E2C436B1BCF071E0001E2BC /* JSRTCTrackEvent.cpp in Sources */,
                                BCEC01C20C274DDD009F4EC9 /* JSScreen.cpp in Sources */,
                                FDA15ECD12B03F61003A583A /* JSScriptProcessorNode.cpp in Sources */,
                                A77E1FEF14AACB6E005B7CB6 /* TreeScopeAdopter.cpp in Sources */,
                                854FE7380A2297BE0058D7AD /* TreeWalker.cpp in Sources */,
                                C375D7FD16639519006184AB /* TypeAhead.cpp in Sources */,
+                               4147E2B71C89912C00A7E715 /* FetchLoader.cpp in Sources */,
                                93309E19099E64920056E581 /* TypingCommand.cpp in Sources */,
                                85031B4D0A44EFC700F992E0 /* UIEvent.cpp in Sources */,
                                93354A3C0B24F8C9003F6DEA /* UIEventWithKeyState.cpp in Sources */,