[Fetch API] Add basic loading of resources
authoryouenn.fablet@crf.canon.fr <youenn.fablet@crf.canon.fr@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 25 Mar 2016 14:19:31 +0000 (14:19 +0000)
committeryouenn.fablet@crf.canon.fr <youenn.fablet@crf.canon.fr@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 25 Mar 2016 14:19:31 +0000 (14:19 +0000)
https://bugs.webkit.org/show_bug.cgi?id=155637

Reviewed by Darin Adler.

LayoutTests/imported/w3c:

Rebasing test expectations.
Updating scheme-blob.js to ensure generated test names are stable run after run.

* web-platform-tests/fetch/api/basic/accept-header-expected.txt:
* web-platform-tests/fetch/api/basic/integrity-expected.txt:
* web-platform-tests/fetch/api/basic/mode-no-cors-expected.txt:
* web-platform-tests/fetch/api/basic/mode-same-origin-expected.txt:
* web-platform-tests/fetch/api/basic/request-forbidden-headers-expected.txt:
* web-platform-tests/fetch/api/basic/request-headers-expected.txt:
* web-platform-tests/fetch/api/basic/scheme-about-expected.txt:
* web-platform-tests/fetch/api/basic/scheme-blob-expected.txt:
* web-platform-tests/fetch/api/basic/scheme-blob-worker-expected.txt:
* web-platform-tests/fetch/api/basic/scheme-blob.js:
(checkFetchResponse): Deleted.
(checkKoUrl): Deleted.
* web-platform-tests/fetch/api/basic/scheme-data-expected.txt:
* web-platform-tests/fetch/api/basic/scheme-others-expected.txt:
* web-platform-tests/fetch/api/basic/stream-response-expected.txt:

Source/WebCore:

Adding support for basic fetch for Window (no support for Worker yet).
A FetchResponse object is created for every fetch task.
But it will only be exposed to JS at promise fulfillment time, i.e. once initial response headers are retrieved.

Updating Blob resource handle to add Content-Type and Content-Length header and notifying of error in case of erroneous HTTP method.

Fetch is limited to same origin requests currently due to some WPT tests that would timeout otherwise.

Tests: http/tests/fetch/closing-while-fetching.html
       http/tests/fetch/get-response-body-while-loading.html
Also covered by rebased tests.

* Modules/fetch/DOMWindowFetch.cpp: Creating a FetchResponse to start fetching.
(WebCore::DOMWindowFetch::fetch):
* Modules/fetch/DOMWindowFetch.h:
* Modules/fetch/FetchBody.cpp:
(WebCore::FetchBody::consume):
(WebCore::FetchBody::consumeArrayBuffer): Handling of body promises in case of data stored as a buffer.
(WebCore::FetchBody::consumeText): Passing the promise as a reference.
(WebCore::blobFromArrayBuffer): Helper routine.
(WebCore::FetchBody::fulfillTextPromise): Helper routine.
(WebCore::FetchBody::loadedAsArrayBuffer): Updated to handle storing of data as a buffer.
(WebCore::FetchBody::loadedAsText):
(WebCore::FetchBody::bodyForInternalRequest): Helper routine to generate the request body data to be sent as part of the fetch request.
(WebCore::FetchBody::extractFromText):
* Modules/fetch/FetchBody.h:
(WebCore::FetchBody::loadingBody):
(WebCore::FetchBody::FetchBody):
* Modules/fetch/FetchBodyOwner.cpp:
(WebCore::FetchBodyOwner::loadBlob): Updated to cope with the change that FetchLoader::start does not return a boolean anymore
but will directly call failure callbacks.
(WebCore::FetchBodyOwner::loadedBlobAsText): Moving it closer to other blob loading routines.
(WebCore::FetchBodyOwner::finishBlobLoading):
* Modules/fetch/FetchBodyOwner.h:
(WebCore::FetchBodyOwner::body):
(WebCore::FetchBodyOwner::loadedBlobAsArrayBuffer):
* Modules/fetch/FetchHeaders.cpp:
(WebCore::FetchHeaders::fill):
(WebCore::FetchHeaders::filterAndFill): Helper routine to fill headers from a HTTPHeaderMap after being filtered.
* Modules/fetch/FetchHeaders.h:
(WebCore::FetchHeaders::internalHeaders):
* Modules/fetch/FetchLoader.cpp:
(WebCore::FetchLoader::start):
(WebCore::FetchLoader::didFailRedirectCheck):
* Modules/fetch/FetchLoader.h:
* Modules/fetch/FetchRequest.cpp:
(WebCore::FetchRequest::internalRequest): Routine used to create the ResourceRequest transmitted to ThreadableLoader.
       * Modules/fetch/FetchRequest.h:
* Modules/fetch/FetchResponse.cpp:
(WebCore::FetchResponse::fetch): Start fetching by creating a FetchLoader based on passed request.
(WebCore::FetchResponse::BodyLoader::didSucceed): FetchLoader callback.
(WebCore::FetchResponse::BodyLoader::didFail): Ditto.
(WebCore::FetchResponse::BodyLoader::BodyLoader): Ditto.
(WebCore::FetchResponse::BodyLoader::didReceiveResponse): Ditto.
(WebCore::FetchResponse::BodyLoader::didFinishLoadingAsArrayBuffer): Ditto.
(WebCore::FetchResponse::BodyLoader::start): Starting fetch loader.
(WebCore::FetchResponse::BodyLoader::stop): Stopping fetch loader.
(WebCore::FetchResponse::stop): Stop loader if any.
* Modules/fetch/FetchResponse.h:
* platform/network/BlobResourceHandle.cpp:
(WebCore::BlobResourceHandle::doStart: Notifying the loader with an error if verb is not GET.
(WebCore::BlobResourceHandle::notifyResponseOnSuccess): Adding support for Content-Type and Content-Lenth headers.
(WebCore::BlobResourceHandle::createAsync): Removing GET verb check.

LayoutTests:

* TestExpectations: Removed flaky test expectations.
* http/tests/fetch/closing-while-fetching-expected.txt: Added.
* http/tests/fetch/closing-while-fetching.html: Added.
* http/tests/fetch/get-response-body-while-loading-expected.txt: Added.
* http/tests/fetch/get-response-body-while-loading.html: Added.
* http/tests/resources/download-json-with-delay.php: Added.
* platform/gtk/imported/w3c/web-platform-tests/fetch/api/basic/request-headers-expected.txt: Added.

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

38 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/http/tests/fetch/closing-while-fetching-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/fetch/closing-while-fetching.html [new file with mode: 0644]
LayoutTests/http/tests/fetch/get-response-body-while-loading-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/fetch/get-response-body-while-loading.html [new file with mode: 0644]
LayoutTests/http/tests/resources/download-json-with-delay.php [new file with mode: 0644]
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/accept-header-expected.txt
LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/integrity-expected.txt
LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/mode-no-cors-expected.txt
LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/mode-same-origin-expected.txt
LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/request-forbidden-headers-expected.txt
LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/request-headers-expected.txt
LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/scheme-about-expected.txt
LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/scheme-blob-expected.txt
LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/scheme-blob-worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/scheme-blob.js
LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/scheme-data-expected.txt
LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/scheme-others-expected.txt
LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/stream-response-expected.txt
LayoutTests/platform/gtk/imported/w3c/web-platform-tests/fetch/api/basic/request-headers-expected.txt [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Modules/fetch/DOMWindowFetch.cpp
Source/WebCore/Modules/fetch/DOMWindowFetch.h
Source/WebCore/Modules/fetch/FetchBody.cpp
Source/WebCore/Modules/fetch/FetchBody.h
Source/WebCore/Modules/fetch/FetchBodyOwner.cpp
Source/WebCore/Modules/fetch/FetchBodyOwner.h
Source/WebCore/Modules/fetch/FetchHeaders.cpp
Source/WebCore/Modules/fetch/FetchHeaders.h
Source/WebCore/Modules/fetch/FetchLoader.cpp
Source/WebCore/Modules/fetch/FetchLoader.h
Source/WebCore/Modules/fetch/FetchRequest.cpp
Source/WebCore/Modules/fetch/FetchRequest.h
Source/WebCore/Modules/fetch/FetchResponse.cpp
Source/WebCore/Modules/fetch/FetchResponse.h
Source/WebCore/platform/network/BlobResourceHandle.cpp

index c5f656c63203daccf9c59ca8c63f985b05078cab..96088fa2297a9a09aec5f85bac2d498ee393daaf 100644 (file)
@@ -1,3 +1,18 @@
+2016-03-25  Youenn Fablet  <youenn.fablet@crf.canon.fr>
+
+        [Fetch API] Add basic loading of resources
+        https://bugs.webkit.org/show_bug.cgi?id=155637
+
+        Reviewed by Darin Adler.
+
+        * TestExpectations: Removed flaky test expectations.
+        * http/tests/fetch/closing-while-fetching-expected.txt: Added.
+        * http/tests/fetch/closing-while-fetching.html: Added.
+        * http/tests/fetch/get-response-body-while-loading-expected.txt: Added.
+        * http/tests/fetch/get-response-body-while-loading.html: Added.
+        * http/tests/resources/download-json-with-delay.php: Added.
+        * platform/gtk/imported/w3c/web-platform-tests/fetch/api/basic/request-headers-expected.txt: Added.
+
 2016-03-25  Gyuyoung Kim  <gyuyoung.kim@webkit.org>
 
         Unreviewed EFL gardening.
index 7bc739f2f0eedd7d0d64d2de77054dabc90fad65..efec509a9d00f1a517f9fddd40c0ed4384d08455 100644 (file)
@@ -317,10 +317,6 @@ imported/w3c/web-platform-tests/XMLHttpRequest/send-redirect-bogus.htm [ Skip ]
 imported/w3c/web-platform-tests/XMLHttpRequest/send-redirect-to-cors.htm [ Skip ]
 imported/w3c/web-platform-tests/XMLHttpRequest/send-redirect-to-non-cors.htm [ Skip ]
 
-# Tests that are flaky as failing assertions print a new token generated for each test run.
-imported/w3c/web-platform-tests/fetch/api/basic/scheme-blob.html [ Failure ]
-imported/w3c/web-platform-tests/fetch/api/basic/scheme-blob-worker.html [ Failure ]
-
 # New W3C ref tests that are failing.
 webkit.org/b/148856 imported/w3c/web-platform-tests/html/semantics/embedded-content/the-video-element/video_initially_paused.html [ ImageOnlyFailure ]
 
diff --git a/LayoutTests/http/tests/fetch/closing-while-fetching-expected.txt b/LayoutTests/http/tests/fetch/closing-while-fetching-expected.txt
new file mode 100644 (file)
index 0000000..452b02c
--- /dev/null
@@ -0,0 +1,3 @@
+
+PASS Ensuring that fetch response body promise is not fulfilled when window is closed 
+
diff --git a/LayoutTests/http/tests/fetch/closing-while-fetching.html b/LayoutTests/http/tests/fetch/closing-while-fetching.html
new file mode 100644 (file)
index 0000000..d3278b5
--- /dev/null
@@ -0,0 +1,33 @@
+<!doctype html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>Fetch: retrieve response's body progressively</title>
+    <meta name="help" href="https://fetch.spec.whatwg.org/#main-fetch">
+    <meta name="help" href="https://fetch.spec.whatwg.org/#http-fetch">
+    <meta name="author" title="Canon Research France" href="https://www.crf.canon.fr">
+    <script src="/js-test-resources/testharness.js"></script>
+    <script src="/js-test-resources/testharnessreport.js"></script>
+  </head>
+  <body>
+    <script>
+        
+var test = async_test("Ensuring that fetch response body promise is not fulfilled when window is closed");
+test.step(function() {
+    var url = "/resources/download-json-with-delay.php?iteration=5&delay=1000";
+    fetch(url).then(test.step_func(function(response) {
+        assert_equals(response.status, 200);
+        response.text().then(test.step_func(function(buffer) {
+            assert_unreached();
+        }), test.step_func(function() {
+            assert_unreached();
+        }));
+        setTimeout(function() { test.done(); }, 100);
+    }), test.step_func(function() {
+        assert_unreached();
+    }));
+});
+
+    </script>
+  </body>
+</html>
diff --git a/LayoutTests/http/tests/fetch/get-response-body-while-loading-expected.txt b/LayoutTests/http/tests/fetch/get-response-body-while-loading-expected.txt
new file mode 100644 (file)
index 0000000..30b44fc
--- /dev/null
@@ -0,0 +1,6 @@
+
+PASS Testing calling Response.text() when still fetching data 
+PASS Testing calling Response.arrayBuffer() when still fetching data 
+PASS Testing calling Response.blob() when still fetching data 
+PASS Testing calling Response.json() when still fetching data 
+
diff --git a/LayoutTests/http/tests/fetch/get-response-body-while-loading.html b/LayoutTests/http/tests/fetch/get-response-body-while-loading.html
new file mode 100644 (file)
index 0000000..e936a78
--- /dev/null
@@ -0,0 +1,73 @@
+<!doctype html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>Fetch: retrieve response's body progressively</title>
+    <meta name="help" href="https://fetch.spec.whatwg.org/#main-fetch">
+    <meta name="help" href="https://fetch.spec.whatwg.org/#http-fetch">
+    <meta name="author" title="Canon Research France" href="https://www.crf.canon.fr">
+    <script src="/js-test-resources/testharness.js"></script>
+    <script src="/js-test-resources/testharnessreport.js"></script>
+  </head>
+  <body>
+    <script>
+
+promise_test(function() {
+    var url = "/resources/download-json-with-delay.php?iteration=5&delay=200";
+    var loadingFlag = false;
+    return fetch(url).then(function(response) {
+        assert_equals(response.status, 200);
+
+        setTimeout(function() { loadingFlag = true; }, 100);
+        return response.text().then(function(text) {
+            assert_true(loadingFlag, "ensuring that text() was called while loading is happening");
+            assert_true(text.indexOf("foobar") != -1, "text must contain foobar");
+        });
+    });
+}, "Testing calling Response.text() when still fetching data");
+
+promise_test(function() {
+    var url = "/resources/download-json-with-delay.php?iteration=5&delay=200";
+    var loadingFlag = false;
+    return fetch(url).then(function(response) {
+        assert_equals(response.status, 200);
+
+        setTimeout(function() { loadingFlag = true; }, 100);
+        return response.arrayBuffer().then(function(arrayBuffer) {
+            assert_true(arrayBuffer instanceof ArrayBuffer, "object must be an array buffer");
+            assert_true(loadingFlag, "ensuring that arrayBuffer() was called while loading is happening");
+        });
+    });
+}, "Testing calling Response.arrayBuffer() when still fetching data");
+
+promise_test(function() {
+    var url = "/resources/download-json-with-delay.php?iteration=5&delay=200";
+    var loadingFlag = false;
+    return fetch(url).then(function(response) {
+        assert_equals(response.status, 200);
+
+        setTimeout(function() { loadingFlag = true; }, 100);
+        return response.blob().then(function(blob) {
+            assert_true(blob instanceof Blob, "object must be a blob");
+            assert_true(loadingFlag, "ensuring that blob() was called while loading is happening");
+        });
+    });
+}, "Testing calling Response.blob() when still fetching data");
+
+promise_test(function() {
+    var url = "/resources/download-json-with-delay.php?iteration=5&delay=200";
+    var loadingFlag = false;
+    return fetch(url).then(function(response) {
+        assert_equals(response.status, 200);
+        
+        setTimeout(function() { loadingFlag = true; }, 100);
+        return response.json().then(function(object) {
+            assert_equals(object.constructor, Array);
+            assert_true(loadingFlag, "ensuring that json() was called while loading is happening");
+        });
+    });
+}, "Testing calling Response.json() when still fetching data");
+
+    </script>
+  </body>
+</html>
diff --git a/LayoutTests/http/tests/resources/download-json-with-delay.php b/LayoutTests/http/tests/resources/download-json-with-delay.php
new file mode 100644 (file)
index 0000000..d515850
--- /dev/null
@@ -0,0 +1,20 @@
+<?php
+header("Expires: Thu, 01 Dec 2003 16:00:00 GMT");
+header("Cache-Control: no-cache, no-store, must-revalidate");
+header("Pragma: no-cache");
+header("Content-Type: application/x-no-buffering-please");
+
+$iteration = $_GET['iteration'];
+$delay = $_GET['delay'];
+
+echo "[$iteration, $delay ";
+
+for ($i = 1; $i <= $iteration; ++$i) {
+    echo ", $i, \"foobar\"";
+    // Force content to be sent to the browser as is.
+    ob_flush();
+    flush();
+    usleep($delay * 1000);
+}
+echo "]";
+?>
index d16d8552202b388754876a9117a750c3164c8c13..77ef4afc4eaf0e6757eb22589bac9f60a0cb1fbd 100644 (file)
@@ -1,3 +1,29 @@
+2016-03-25  Youenn Fablet  <youenn.fablet@crf.canon.fr>
+
+        [Fetch API] Add basic loading of resources
+        https://bugs.webkit.org/show_bug.cgi?id=155637
+
+        Reviewed by Darin Adler.
+
+        Rebasing test expectations.
+        Updating scheme-blob.js to ensure generated test names are stable run after run.
+
+        * web-platform-tests/fetch/api/basic/accept-header-expected.txt:
+        * web-platform-tests/fetch/api/basic/integrity-expected.txt:
+        * web-platform-tests/fetch/api/basic/mode-no-cors-expected.txt:
+        * web-platform-tests/fetch/api/basic/mode-same-origin-expected.txt:
+        * web-platform-tests/fetch/api/basic/request-forbidden-headers-expected.txt:
+        * web-platform-tests/fetch/api/basic/request-headers-expected.txt:
+        * web-platform-tests/fetch/api/basic/scheme-about-expected.txt:
+        * web-platform-tests/fetch/api/basic/scheme-blob-expected.txt:
+        * web-platform-tests/fetch/api/basic/scheme-blob-worker-expected.txt:
+        * web-platform-tests/fetch/api/basic/scheme-blob.js:
+        (checkFetchResponse): Deleted.
+        (checkKoUrl): Deleted.
+        * web-platform-tests/fetch/api/basic/scheme-data-expected.txt:
+        * web-platform-tests/fetch/api/basic/scheme-others-expected.txt:
+        * web-platform-tests/fetch/api/basic/stream-response-expected.txt:
+
 2016-03-24  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r198627.
index 4cd5973340278ea1d7b14ea0c71a29dd7a254868..0dd43a208344ac1d1a59b4dd9f5757b1c37b6421 100644 (file)
@@ -1,3 +1,3 @@
 
-FAIL Request through fetch should have 'accept' header with value '*/*' promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
+PASS Request through fetch should have 'accept' header with value '*/*' 
 
index 42be0023948409643f939eba95399ac356ba7f95..c2dadd1f09b38804c1ccca459800b494cdc5b3db 100644 (file)
@@ -1,15 +1,15 @@
 
-FAIL Empty string integrity promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL SHA-256 integrity promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL SHA-384 integrity promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL SHA-512 integrity promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Invalid integrity assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Multiple integrities: valid stronger than invalid promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Multiple integrities: invalid stronger than valid assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Multiple integrities: invalid as strong as valid promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Multiple integrities: both are valid promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Multiple integrities: both are invalid assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL CORS empty integrity promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL CORS SHA-512 integrity promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL CORS invalid integrity assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
+PASS Empty string integrity 
+PASS SHA-256 integrity 
+PASS SHA-384 integrity 
+PASS SHA-512 integrity 
+FAIL Invalid integrity assert_unreached: Should have rejected. Reached unreachable code
+PASS Multiple integrities: valid stronger than invalid 
+FAIL Multiple integrities: invalid stronger than valid assert_unreached: Should have rejected. Reached unreachable code
+PASS Multiple integrities: invalid as strong as valid 
+PASS Multiple integrities: both are valid 
+FAIL Multiple integrities: both are invalid assert_unreached: Should have rejected. Reached unreachable code
+FAIL CORS empty integrity promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL CORS SHA-512 integrity promise_test: Unhandled rejection with value: object "TypeError: Type error"
+PASS CORS invalid integrity 
 
index d150a738c402270ec67cc77a68b671dfc870f3cd..47cbea743e88722c6d7076874f7945bb7dda27b2 100644 (file)
@@ -1,6 +1,6 @@
 
-FAIL Fetch ../resources/top.txt with no-cors mode promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Fetch http://localhost:8800/fetch/api/resources/top.txt with no-cors mode promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Fetch https://localhost:9443/fetch/api/resources/top.txt with no-cors mode promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Fetch http://www.localhost:8800/fetch/api/resources/top.txt with no-cors mode promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
+PASS Fetch ../resources/top.txt with no-cors mode 
+PASS Fetch http://localhost:8800/fetch/api/resources/top.txt with no-cors mode 
+FAIL Fetch https://localhost:9443/fetch/api/resources/top.txt with no-cors mode promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL Fetch http://www.localhost:8800/fetch/api/resources/top.txt with no-cors mode promise_test: Unhandled rejection with value: object "TypeError: Type error"
 
index 9ac98691ab0f8633ad1f2743779c82929b77f07c..9c3ae3004af8cb272b34d9151b83db5378326e1d 100644 (file)
@@ -1,6 +1,6 @@
 
-FAIL Fetch ../resources/top.txt with same-origin mode promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Fetch http://localhost:8800/fetch/api/resources/top.txt with same-origin mode promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Fetch https://localhost:9443/fetch/api/resources/top.txt with same-origin mode assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Fetch http://www.localhost:8800/fetch/api/resources/top.txt with same-origin mode assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
+PASS Fetch ../resources/top.txt with same-origin mode 
+PASS Fetch http://localhost:8800/fetch/api/resources/top.txt with same-origin mode 
+PASS Fetch https://localhost:9443/fetch/api/resources/top.txt with same-origin mode 
+PASS Fetch http://www.localhost:8800/fetch/api/resources/top.txt with same-origin mode 
 
index d5740d1b8d79b0060d29ff0decc56d922f6f1446..b42edf141fc289b182a8cacd992db5e838bc1dc6 100644 (file)
@@ -1,26 +1,26 @@
 
-FAIL Accept-Charset is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Accept-Encoding is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Access-Control-Request-Headers is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Access-Control-Request-Method is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Connection is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Content-Length is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Cookie is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Cookie2 is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Date is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL DNT is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Expect is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Host is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Keep-Alive is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Origin is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Referer is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL TE is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Trailer is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Transfer-Encoding is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Upgrade is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Via is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Proxy- is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Proxy-Test is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Sec- is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Sec-Test is a forbidden request header promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
+PASS Accept-Charset is a forbidden request header 
+PASS Accept-Encoding is a forbidden request header 
+PASS Access-Control-Request-Headers is a forbidden request header 
+PASS Access-Control-Request-Method is a forbidden request header 
+PASS Connection is a forbidden request header 
+PASS Content-Length is a forbidden request header 
+PASS Cookie is a forbidden request header 
+PASS Cookie2 is a forbidden request header 
+PASS Date is a forbidden request header 
+PASS DNT is a forbidden request header 
+PASS Expect is a forbidden request header 
+PASS Host is a forbidden request header 
+PASS Keep-Alive is a forbidden request header 
+PASS Origin is a forbidden request header 
+PASS Referer is a forbidden request header 
+PASS TE is a forbidden request header 
+PASS Trailer is a forbidden request header 
+PASS Transfer-Encoding is a forbidden request header 
+PASS Upgrade is a forbidden request header 
+PASS Via is a forbidden request header 
+PASS Proxy- is a forbidden request header 
+PASS Proxy-Test is a forbidden request header 
+PASS Sec- is a forbidden request header 
+PASS Sec-Test is a forbidden request header 
 
index 05e458005d7a53c68de86deab50b176b6dc5c49a..be0bbf71b1d67e816c5634bf928c429a87207763 100644 (file)
@@ -1,11 +1,11 @@
 
-FAIL Fetch with GET promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Fetch with HEAD promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Fetch with HEAD with body promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Fetch with PUT without body promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Fetch with PUT with body promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Fetch with POST without body promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Fetch with POST with body promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Fetch with Chicken promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Fetch with Chicken with body promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
+FAIL Fetch with GET assert_equals: Request has header origin: http://localhost:8800 expected (string) "http://localhost:8800" but got (object) null
+FAIL Fetch with HEAD assert_equals: Request has header origin: http://localhost:8800 expected (string) "http://localhost:8800" but got (object) null
+FAIL Fetch with HEAD with body promise_test: Unhandled rejection with value: object "TypeError: Type error"
+PASS Fetch with PUT without body 
+PASS Fetch with PUT with body 
+PASS Fetch with POST without body 
+PASS Fetch with POST with body 
+FAIL Fetch with Chicken assert_equals: Request has header content-length: null expected (object) null but got (string) "0"
+PASS Fetch with Chicken with body 
 
index 67ed49dcd3b8f1fff8f7db8a1e2bde417a0032d1..1fb886c505e389fb96e0dd134ed19f23191af047 100644 (file)
@@ -1,6 +1,6 @@
 
-FAIL Fetching about:blank is OK promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Fetching about:unicorn is OK promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Fetching about:invalid.com is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Fetching about:config is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
+FAIL Fetching about:blank is OK promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL Fetching about:unicorn is OK promise_test: Unhandled rejection with value: object "TypeError: Type error"
+PASS Fetching about:invalid.com is KO 
+PASS Fetching about:config is KO 
 
index ceb0135f0d612fdcc1147e827499891be6ba5ac2..6c4bc8ba0bd341513c7db9383b49a15f5fe1cbb3 100644 (file)
@@ -1,5 +1,5 @@
 
-FAIL Fetching blob:http://localhost:8800/4580501e-3c0f-4b03[...] is OK promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Fetching [GET] blob:http://www.localhost:8800/ is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Fetching [POST] blob:http://localhost:8800/ad829fe3-9045-4b29[...] is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
+PASS Regular Blob loading 
+PASS Loading an erroneous blob scheme URL 
+FAIL Loading a blob URL using POST assert_unreached: Should have rejected. Reached unreachable code
 
index dc0d2af0feaae5984fda7e39d83f644f56592ef6..4d1850da7849f5d3a67a07ecd7a54a1656b465ab 100644 (file)
@@ -1,5 +1,5 @@
 
-FAIL Fetching blob:http://localhost:8800/8807dca8-91bf-4414[...] is OK promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Fetching [GET] blob:http://www.localhost:8800/ is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Fetching [POST] blob:http://localhost:8800/41805be3-d8cc-490f[...] is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
+FAIL Regular Blob loading promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
+FAIL Loading an erroneous blob scheme URL assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
+FAIL Loading a blob URL using POST assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
 
index d9b804d4e58d2b7bf67bb7d136a3a46a0af9059b..ac9d35dfd0763a72bf324ee641d4d989ec76ee99 100644 (file)
@@ -4,9 +4,6 @@ if (this.document === undefined) {
 }
 
 function checkFetchResponse(url, data, mime, size, desc) {
-  if (!desc)
-    var cut = (url.length >= 45) ? "[...]" : "";
-    desc = "Fetching " + url.substring(0, 45) + cut + " is OK"
   promise_test(function(test) {
     size = size.toString();
     return fetch(url).then(function(resp) {
@@ -22,12 +19,9 @@ function checkFetchResponse(url, data, mime, size, desc) {
 }
 
 var blob = new Blob(["Blob's data"], { "type" : "text/plain" });
-checkFetchResponse(URL.createObjectURL(blob), "Blob's data", "text/plain",  blob.size);
+checkFetchResponse(URL.createObjectURL(blob), "Blob's data", "text/plain",  blob.size, "Regular Blob loading");
 
 function checkKoUrl(url, method, desc) {
-  if (!desc)
-    var cut = (url.length >= 45) ? "[...]" : "";
-    desc = "Fetching [" + method + "] " + url.substring(0, 45) + cut +  " is KO"
   promise_test(function(test) {
     var promise = fetch(url, {"method": method});
     return promise_rejects(test, new TypeError(), promise);
@@ -35,7 +29,7 @@ function checkKoUrl(url, method, desc) {
 }
 
 var blob2 = new Blob(["Blob's data"], { "type" : "text/plain" });
-checkKoUrl("blob:http://{{domains[www]}}:{{ports[http][0]}}/", "GET");
-checkKoUrl(URL.createObjectURL(blob2), "POST");
+checkKoUrl("blob:http://{{domains[www]}}:{{ports[http][0]}}/", "GET", "Loading an erroneous blob scheme URL");
+checkKoUrl(URL.createObjectURL(blob2), "POST", "Loading a blob URL using POST");
 
 done();
index 48f0aef7f114343fcf7fe7efc3e3573c3c3526e1..9b1e8b8496de53791ac99b5a80e37f2ad21fb142 100644 (file)
@@ -1,8 +1,8 @@
 
-FAIL Fetching data:,response%27s%20body is OK promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Fetching data:text/plain;base64,cmVzcG9uc2UncyBib[...] is OK promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Fetching data:image/png;base64,cmVzcG9uc2UncyBib2[...] is OK promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
-FAIL Fetching [GET] data:notAdataUrl.com is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Fetching [POST] data:,response%27s%20body is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Fetching [HEAD] data:,response%27s%20body is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
+FAIL Fetching data:,response%27s%20body is OK promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL Fetching data:text/plain;base64,cmVzcG9uc2UncyBib[...] is OK promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL Fetching data:image/png;base64,cmVzcG9uc2UncyBib2[...] is OK promise_test: Unhandled rejection with value: object "TypeError: Type error"
+PASS Fetching [GET] data:notAdataUrl.com is KO 
+PASS Fetching [POST] data:,response%27s%20body is KO 
+PASS Fetching [HEAD] data:,response%27s%20body is KO 
 
index c17442ec52104a38342302bcecf709cd6caae211..c1b695a5a6b5e844f4de37d7531ed6baaff6772b 100644 (file)
@@ -1,18 +1,18 @@
 
-FAIL Fetching aaa://localhost:8800/ is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Fetching cap://localhost:8800/ is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Fetching cid://localhost:8800/ is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Fetching dav://localhost:8800/ is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Fetching dict://localhost:8800/ is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Fetching dns://localhost:8800/ is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Fetching geo://localhost:8800/ is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Fetching im://localhost:8800/ is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Fetching imap://localhost:8800/ is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Fetching ipp://localhost:8800/ is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Fetching ldap://localhost:8800/ is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Fetching mailto://localhost:8800/ is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Fetching nfs://localhost:8800/ is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Fetching pop://localhost:8800/ is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Fetching rtsp://localhost:8800/ is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Fetching snmp://localhost:8800/ is KO assert_throws: function "function () { throw e }" threw "Fetch is not yet implemented" (undefined) expected object "TypeError" ("TypeError")
+PASS Fetching aaa://localhost:8800/ is KO 
+PASS Fetching cap://localhost:8800/ is KO 
+PASS Fetching cid://localhost:8800/ is KO 
+PASS Fetching dav://localhost:8800/ is KO 
+PASS Fetching dict://localhost:8800/ is KO 
+PASS Fetching dns://localhost:8800/ is KO 
+PASS Fetching geo://localhost:8800/ is KO 
+PASS Fetching im://localhost:8800/ is KO 
+PASS Fetching imap://localhost:8800/ is KO 
+PASS Fetching ipp://localhost:8800/ is KO 
+PASS Fetching ldap://localhost:8800/ is KO 
+PASS Fetching mailto://localhost:8800/ is KO 
+PASS Fetching nfs://localhost:8800/ is KO 
+PASS Fetching pop://localhost:8800/ is KO 
+PASS Fetching rtsp://localhost:8800/ is KO 
+PASS Fetching snmp://localhost:8800/ is KO 
 
index 118268f8c843219965a82d6f9cb70fb5df02bf87..d584d0103a6d37bf09b875ef3993dae3fea9f253 100644 (file)
@@ -1,3 +1,3 @@
 
-FAIL Stream response's body promise_test: Unhandled rejection with value: "Fetch is not yet implemented"
+FAIL Stream response's body assert_unreached: Body does not exist in response Reached unreachable code
 
diff --git a/LayoutTests/platform/gtk/imported/w3c/web-platform-tests/fetch/api/basic/request-headers-expected.txt b/LayoutTests/platform/gtk/imported/w3c/web-platform-tests/fetch/api/basic/request-headers-expected.txt
new file mode 100644 (file)
index 0000000..a005963
--- /dev/null
@@ -0,0 +1,11 @@
+
+FAIL Fetch with GET assert_equals: Request has header origin: http://localhost:8800 expected (string) "http://localhost:8800" but got (object) null
+FAIL Fetch with HEAD assert_equals: Request has header origin: http://localhost:8800 expected (string) "http://localhost:8800" but got (object) null
+FAIL Fetch with HEAD with body promise_test: Unhandled rejection with value: object "TypeError: Type error"
+PASS Fetch with PUT without body 
+PASS Fetch with PUT with body 
+PASS Fetch with POST without body 
+PASS Fetch with POST with body 
+PASS Fetch with Chicken 
+PASS Fetch with Chicken with body 
+
index 2192ea04d373aebdfe83b1754170db7b9a891b54..3a35154750c474e7804b47a9fed2a6f9435bebc2 100644 (file)
@@ -1,3 +1,74 @@
+2016-03-25  Youenn Fablet  <youenn.fablet@crf.canon.fr>
+
+        [Fetch API] Add basic loading of resources
+        https://bugs.webkit.org/show_bug.cgi?id=155637
+
+        Reviewed by Darin Adler.
+
+        Adding support for basic fetch for Window (no support for Worker yet).
+        A FetchResponse object is created for every fetch task.
+        But it will only be exposed to JS at promise fulfillment time, i.e. once initial response headers are retrieved.
+
+        Updating Blob resource handle to add Content-Type and Content-Length header and notifying of error in case of erroneous HTTP method.
+
+        Fetch is limited to same origin requests currently due to some WPT tests that would timeout otherwise.
+
+        Tests: http/tests/fetch/closing-while-fetching.html
+               http/tests/fetch/get-response-body-while-loading.html
+        Also covered by rebased tests.
+
+        * Modules/fetch/DOMWindowFetch.cpp: Creating a FetchResponse to start fetching.
+        (WebCore::DOMWindowFetch::fetch):
+        * Modules/fetch/DOMWindowFetch.h:
+        * Modules/fetch/FetchBody.cpp:
+        (WebCore::FetchBody::consume):
+        (WebCore::FetchBody::consumeArrayBuffer): Handling of body promises in case of data stored as a buffer.
+        (WebCore::FetchBody::consumeText): Passing the promise as a reference.
+        (WebCore::blobFromArrayBuffer): Helper routine.
+        (WebCore::FetchBody::fulfillTextPromise): Helper routine.
+        (WebCore::FetchBody::loadedAsArrayBuffer): Updated to handle storing of data as a buffer.
+        (WebCore::FetchBody::loadedAsText):
+        (WebCore::FetchBody::bodyForInternalRequest): Helper routine to generate the request body data to be sent as part of the fetch request.
+        (WebCore::FetchBody::extractFromText):
+        * Modules/fetch/FetchBody.h:
+        (WebCore::FetchBody::loadingBody):
+        (WebCore::FetchBody::FetchBody):
+        * Modules/fetch/FetchBodyOwner.cpp:
+        (WebCore::FetchBodyOwner::loadBlob): Updated to cope with the change that FetchLoader::start does not return a boolean anymore
+        but will directly call failure callbacks.
+        (WebCore::FetchBodyOwner::loadedBlobAsText): Moving it closer to other blob loading routines.
+        (WebCore::FetchBodyOwner::finishBlobLoading):
+        * Modules/fetch/FetchBodyOwner.h:
+        (WebCore::FetchBodyOwner::body):
+        (WebCore::FetchBodyOwner::loadedBlobAsArrayBuffer):
+        * Modules/fetch/FetchHeaders.cpp:
+        (WebCore::FetchHeaders::fill):
+        (WebCore::FetchHeaders::filterAndFill): Helper routine to fill headers from a HTTPHeaderMap after being filtered.
+        * Modules/fetch/FetchHeaders.h:
+        (WebCore::FetchHeaders::internalHeaders):
+        * Modules/fetch/FetchLoader.cpp:
+        (WebCore::FetchLoader::start):
+        (WebCore::FetchLoader::didFailRedirectCheck):
+        * Modules/fetch/FetchLoader.h:
+        * Modules/fetch/FetchRequest.cpp:
+        (WebCore::FetchRequest::internalRequest): Routine used to create the ResourceRequest transmitted to ThreadableLoader.
+       * Modules/fetch/FetchRequest.h:
+        * Modules/fetch/FetchResponse.cpp:
+        (WebCore::FetchResponse::fetch): Start fetching by creating a FetchLoader based on passed request.
+        (WebCore::FetchResponse::BodyLoader::didSucceed): FetchLoader callback.
+        (WebCore::FetchResponse::BodyLoader::didFail): Ditto.
+        (WebCore::FetchResponse::BodyLoader::BodyLoader): Ditto.
+        (WebCore::FetchResponse::BodyLoader::didReceiveResponse): Ditto.
+        (WebCore::FetchResponse::BodyLoader::didFinishLoadingAsArrayBuffer): Ditto.
+        (WebCore::FetchResponse::BodyLoader::start): Starting fetch loader.
+        (WebCore::FetchResponse::BodyLoader::stop): Stopping fetch loader.
+        (WebCore::FetchResponse::stop): Stop loader if any.
+        * Modules/fetch/FetchResponse.h:
+        * platform/network/BlobResourceHandle.cpp:
+        (WebCore::BlobResourceHandle::doStart: Notifying the loader with an error if verb is not GET.
+        (WebCore::BlobResourceHandle::notifyResponseOnSuccess): Adding support for Content-Type and Content-Lenth headers.
+        (WebCore::BlobResourceHandle::createAsync): Removing GET verb check.
+
 2016-03-25  Konstantin Tokarev  <annulen@yandex.ru>
 
         Removed leftovers of WCHAR_UNICODE code path after r162782.
index a4c83c3449328138d23051c2fe1205fa7cbd1a06..cb0d02b22752fd9a5720d790cab7e2585465a129 100644 (file)
 
 #if ENABLE(FETCH_API)
 
+#include "DOMWindow.h"
+#include "FetchRequest.h"
+#include "FetchResponse.h"
+
 namespace WebCore {
 
-void DOMWindowFetch::fetch(DOMWindow&, FetchRequest*, const Dictionary&, FetchPromise&& promise)
+void DOMWindowFetch::fetch(DOMWindow& window, FetchRequest* input, const Dictionary& dictionary, DeferredWrapper&& promise)
 {
-    promise.reject(ASCIILiteral("Fetch is not yet implemented"));
+    if (!window.scriptExecutionContext())
+        return;
+    ScriptExecutionContext& context = *window.scriptExecutionContext();
+
+    ExceptionCode ec = 0;
+    RefPtr<FetchRequest> fetchRequest = FetchRequest::create(context, input, dictionary, ec);
+    if (ec) {
+        promise.reject(ec);
+        return;
+    }
+    ASSERT(fetchRequest);
+    FetchResponse::fetch(context, *fetchRequest, WTFMove(promise));
 }
 
-void DOMWindowFetch::fetch(DOMWindow&, const String&, const Dictionary&, FetchPromise&& promise)
+void DOMWindowFetch::fetch(DOMWindow& window, const String& url, const Dictionary& dictionary, DeferredWrapper&& promise)
 {
-    promise.reject(ASCIILiteral("Fetch is not yet implemented"));
+    if (!window.scriptExecutionContext())
+        return;
+    ScriptExecutionContext& context = *window.scriptExecutionContext();
+    
+    ExceptionCode ec = 0;
+    RefPtr<FetchRequest> fetchRequest = FetchRequest::create(context, url, dictionary, ec);
+    if (ec) {
+        promise.reject(ec);
+        return;
+    }
+    ASSERT(fetchRequest);
+    FetchResponse::fetch(context, *fetchRequest, WTFMove(promise));
 }
 
 } // namespace WebCore
index 9fb155e28c50355a4725b452e5ef810c465092da..fe60f4025d821e5dfb655f0371e4d72cc67f3b66 100644 (file)
 
 #if ENABLE(FETCH_API)
 
-#include "JSDOMPromise.h"
+#include <wtf/Forward.h>
 
 namespace WebCore {
 
+class DOMWindow;
+class DeferredWrapper;
 class Dictionary;
 class FetchRequest;
-class FetchResponse;
 
 class DOMWindowFetch {
 public:
-    using FetchPromise = DOMPromise<RefPtr<FetchResponse>, String>;
-    static void fetch(DOMWindow&, FetchRequest*, const Dictionary&, FetchPromise&&);
-    static void fetch(DOMWindow&, const String&, const Dictionary&, FetchPromise&&);
+    static void fetch(DOMWindow&, FetchRequest*, const Dictionary&, DeferredWrapper&&);
+    static void fetch(DOMWindow&, const String&, const Dictionary&, DeferredWrapper&&);
 };
 
 } // namespace WebCore
index 1c0597e3190221e1c8c7b475a491d10adaf0973d..dacc2d810ab7b016f3c618dff82aa6fe6e6eddd7 100644 (file)
 #include "Dictionary.h"
 #include "ExceptionCode.h"
 #include "FetchBodyOwner.h"
+#include "FormData.h"
 #include "HTTPParsers.h"
 #include "JSBlob.h"
 #include "JSDOMFormData.h"
 
 namespace WebCore {
 
+static RefPtr<Blob> blobFromArrayBuffer(ArrayBuffer*, const String&);
+
 FetchBody::FetchBody(Ref<Blob>&& blob)
     : m_type(Type::Blob)
     , m_mimeType(blob->type())
@@ -155,20 +158,45 @@ void FetchBody::text(FetchBodyOwner& owner, DeferredWrapper&& promise)
 
 void FetchBody::consume(FetchBodyOwner& owner, Consumer::Type type, DeferredWrapper&& promise)
 {
+    if (m_type == Type::ArrayBuffer) {
+        consumeArrayBuffer(type, promise);
+        return;
+    }
     if (m_type == Type::Text) {
-        consumeText(type, WTFMove(promise));
+        consumeText(type, promise);
         return;
     }
     if (m_type == Type::Blob) {
         consumeBlob(owner, type, WTFMove(promise));
         return;
     }
+    if (m_type == Type::Loading) {
+        // FIXME: We should be able to change the loading type to text if consumer type is JSON or Text.
+        m_consumer = Consumer({type, WTFMove(promise)});
+        return;
+    }
 
     // FIXME: Support other types.
     promise.reject<ExceptionCode>(0);
 }
 
-void FetchBody::consumeText(Consumer::Type type, DeferredWrapper&& promise)
+void FetchBody::consumeArrayBuffer(Consumer::Type type, DeferredWrapper& promise)
+{
+    if (type == Consumer::Type::ArrayBuffer) {
+        fulfillPromiseWithArrayBuffer(promise, m_data.get());
+        return;
+    }
+    if (type == Consumer::Type::Blob) {
+        promise.resolve(blobFromArrayBuffer(m_data.get(), Blob::normalizedContentType(extractMIMETypeFromMediaType(m_mimeType))));
+        return;
+    }
+
+    ASSERT(type == Consumer::Type::Text || type == Consumer::Type::JSON);
+    // FIXME: Do we need TextResourceDecoder to create a String to decode UTF-8 data.
+    fulfillTextPromise(type, TextResourceDecoder::create(ASCIILiteral("text/plain"), "UTF-8")->decodeAndFlush(static_cast<const char*>(m_data->data()), m_data->byteLength()), promise);
+}
+
+void FetchBody::consumeText(Consumer::Type type, DeferredWrapper& promise)
 {
     ASSERT(type == Consumer::Type::ArrayBuffer || type == Consumer::Type::Blob);
 
@@ -214,6 +242,26 @@ Vector<char> FetchBody::extractFromText() const
     return value;
 }
 
+static inline RefPtr<Blob> blobFromArrayBuffer(ArrayBuffer* buffer, const String& contentType)
+{
+    if (!buffer)
+        return Blob::create(Vector<char>(), contentType);
+
+    // FIXME: We should try to move buffer to Blob without doing this copy.
+    Vector<char> value(buffer->byteLength());
+    memcpy(value.data(), buffer->data(), buffer->byteLength());
+    return Blob::create(WTFMove(value), contentType);
+}
+
+void FetchBody::fulfillTextPromise(FetchBody::Consumer::Type type, const String& text, DeferredWrapper& promise)
+{
+    ASSERT(type == Consumer::Type::Text || type == Consumer::Type::JSON);
+    if (type == FetchBody::Consumer::Type::Text)
+        promise.resolve(text);
+    else
+        fulfillPromiseWithJSON(promise, text);
+}
+
 void FetchBody::loadingFailed()
 {
     ASSERT(m_consumer);
@@ -223,16 +271,23 @@ void FetchBody::loadingFailed()
 
 void FetchBody::loadedAsArrayBuffer(RefPtr<ArrayBuffer>&& buffer)
 {
+    if (m_type == Type::Loading) {
+        m_type = Type::ArrayBuffer;
+        m_data = buffer;
+        if (m_consumer) {
+            consumeArrayBuffer(m_consumer->type, m_consumer->promise);
+            m_consumer = Nullopt;
+        }
+        return;
+    }
+
     ASSERT(m_consumer);
     ASSERT(m_consumer->type == Consumer::Type::Blob || m_consumer->type == Consumer::Type::ArrayBuffer);
     if (m_consumer->type == Consumer::Type::ArrayBuffer)
         fulfillPromiseWithArrayBuffer(m_consumer->promise, buffer.get());
     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->promise.resolve(blobFromArrayBuffer(buffer.get(), m_blob->type()));
     }
     m_consumer = Nullopt;
 }
@@ -241,13 +296,26 @@ void FetchBody::loadedAsText(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
-        fulfillPromiseWithJSON(m_consumer->promise, text);
+
+    fulfillTextPromise(m_consumer->type, text, m_consumer->promise);
     m_consumer = Nullopt;
 }
 
+RefPtr<FormData> FetchBody::bodyForInternalRequest() const
+{
+    if (m_type == Type::None)
+        return nullptr;
+    if (m_type == Type::Text)
+        return FormData::create(UTF8Encoding().encode(m_text, EntitiesForUnencodables));
+    if (m_type == Type::Blob) {
+        RefPtr<FormData> body = FormData::create();
+        body->appendBlob(m_blob->url());
+        return body;
+    }
+    ASSERT_NOT_REACHED();
+    return nullptr;
+}
+
 }
 
 #endif // ENABLE(FETCH_API)
index a5b3c06c8eee95b62dd0a04c4ff89d6a559edb31..f7ac6d71607077df736742512ad5c7af5264fbdd 100644 (file)
@@ -44,6 +44,7 @@ class JSValue;
 namespace WebCore {
 
 class FetchBodyOwner;
+class FormData;
 
 class FetchBody {
 public:
@@ -61,18 +62,22 @@ public:
 
     static FetchBody extract(JSC::ExecState&, JSC::JSValue);
     static FetchBody extractFromBody(FetchBody*);
+    static FetchBody loadingBody() { return { Type::Loading }; }
     FetchBody() = default;
 
     void loadingFailed();
     void loadedAsArrayBuffer(RefPtr<ArrayBuffer>&&);
     void loadedAsText(String&&);
 
+    RefPtr<FormData> bodyForInternalRequest() const;
+
 private:
-    enum class Type { None, Text, Blob, FormData };
+    enum class Type { None, ArrayBuffer, Loading, Text, Blob, FormData };
 
     FetchBody(Ref<Blob>&&);
     FetchBody(Ref<DOMFormData>&&);
     FetchBody(String&&);
+    FetchBody(Type type) : m_type(type) { }
 
     struct Consumer {
         enum class Type { Text, Blob, JSON, ArrayBuffer };
@@ -84,17 +89,21 @@ private:
 
     Vector<char> extractFromText() const;
     bool processIfEmptyOrDisturbed(Consumer::Type, DeferredWrapper&);
-    void consumeText(Consumer::Type, DeferredWrapper&&);
+    void consumeArrayBuffer(Consumer::Type, DeferredWrapper&);
+    void consumeText(Consumer::Type, DeferredWrapper&);
     void consumeBlob(FetchBodyOwner&, Consumer::Type, DeferredWrapper&&);
     static FetchLoader::Type loadingType(Consumer::Type);
+    static void fulfillTextPromise(FetchBody::Consumer::Type, const String&, DeferredWrapper&);
+    static void fulfillArrayBufferPromise(FetchBody::Consumer::Type, const String&, DeferredWrapper&);
 
-    Type m_type = Type::None;
+    Type m_type { Type::None };
     String m_mimeType;
-    bool m_isDisturbed = false;
+    bool m_isDisturbed { false };
 
     // FIXME: Add support for BufferSource and URLSearchParams.
     RefPtr<Blob> m_blob;
     RefPtr<DOMFormData> m_formData;
+    RefPtr<ArrayBuffer> m_data;
     String m_text;
 
     Optional<Consumer> m_consumer;
index 860ee3fa26202d332f9d870a7866a2a5c8b9c5b6..8290320694a1ce347a86f630bc7d24e1f35258f0 100644 (file)
@@ -59,17 +59,21 @@ void FetchBodyOwner::loadBlob(Blob& blob, FetchLoader::Type type)
     ASSERT(m_body.isDisturbed());
     ASSERT(!m_blobLoader);
 
+    if (!scriptExecutionContext()) {
+        m_body.loadingFailed();
+        return;
+    }
+
     m_blobLoader = { *this };
     m_blobLoader->loader = std::make_unique<FetchLoader>(type, *m_blobLoader);
 
+    m_blobLoader->loader->start(*scriptExecutionContext(), blob);
+    if (!m_blobLoader->loader->isStarted()) {
+        m_body.loadingFailed();
+        m_blobLoader = Nullopt;
+        return;
+    }
     setPendingActivity(this);
-    if (!scriptExecutionContext() || !m_blobLoader->loader->start(*scriptExecutionContext(), blob))
-        blobLoadingFailed();
-}
-
-void FetchBodyOwner::loadedBlobAsText(String&& text)
-{
-    m_body.loadedAsText(WTFMove(text));
 }
 
 void FetchBodyOwner::finishBlobLoading()
@@ -80,6 +84,11 @@ void FetchBodyOwner::finishBlobLoading()
     unsetPendingActivity(this);
 }
 
+void FetchBodyOwner::loadedBlobAsText(String&& text)
+{
+    m_body.loadedAsText(WTFMove(text));
+}
+
 void FetchBodyOwner::blobLoadingFailed()
 {
     m_body.loadingFailed();
@@ -97,6 +106,13 @@ void FetchBodyOwner::BlobLoader::didReceiveResponse(const ResourceResponse& resp
         didFail();
 }
 
+void FetchBodyOwner::BlobLoader::didFail()
+{
+    // didFail might be called within FetchLoader::start call.
+    if (loader->isStarted())
+        owner.blobLoadingFailed();
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(FETCH_API)
index 3a698ea93425f36daa253e413798dd75c25218d7..5f07d7a9e79d323581ac815f9ad4cab5ebcd7ed5 100644 (file)
@@ -54,6 +54,13 @@ public:
 
     bool isActive() const { return !!m_blobLoader; }
 
+protected:
+    const FetchBody& body() const { return m_body; }
+    FetchBody& body() { return m_body; }
+
+    // ActiveDOMObject API
+    void stop() override;
+
 private:
     // Blob loading routines
     void loadedBlobAsText(String&&);
@@ -62,9 +69,6 @@ private:
     void blobLoadingFailed();
     void finishBlobLoading();
 
-    // ActiveDOMObject API
-    void stop() override;
-
     struct BlobLoader final : FetchLoaderClient {
         BlobLoader(FetchBodyOwner&);
 
@@ -72,7 +76,7 @@ private:
         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 didFail() final;
         void didSucceed() final { owner.blobLoadingSucceeded(); }
 
         FetchBodyOwner& owner;
index 1669468411b2493661fd8d2e51d1ef9dbff78bfb..d84a5c464decc39b69a42ffacea44965ed00b9cf 100644 (file)
@@ -156,14 +156,19 @@ void FetchHeaders::set(const String& name, const String& value, ExceptionCode& e
 
 void FetchHeaders::fill(const FetchHeaders* headers)
 {
+    ASSERT(m_guard != Guard::Immutable);
+
     if (!headers)
         return;
 
-    ASSERT(m_guard != Guard::Immutable);
+    filterAndFill(headers->m_headers, m_guard);
+}
 
+void FetchHeaders::filterAndFill(const HTTPHeaderMap& headers, Guard guard)
+{
     ExceptionCode ec;
-    for (auto& header : headers->m_headers) {
-        if (canWriteHeader(header.key, header.value, m_guard, ec)) {
+    for (auto& header : headers) {
+        if (canWriteHeader(header.key, header.value, guard, ec)) {
             if (header.keyAsHTTPHeaderName)
                 m_headers.add(header.keyAsHTTPHeaderName.value(), header.value);
             else
index afc8cd2fba32a9edbb98690ea0e60560c5143544..c533227e38d210b2ea9bda2aa978db554f13d949 100644 (file)
@@ -64,6 +64,8 @@ public:
 
     void fill(const FetchHeaders*);
 
+    void filterAndFill(const HTTPHeaderMap&, Guard);
+
     String fastGet(HTTPHeaderName name) const { return m_headers.get(name); }
     void fastSet(HTTPHeaderName name, const String& value) { m_headers.set(name, value); }
 
@@ -79,6 +81,8 @@ public:
     };
     Iterator createIterator() { return Iterator(*this); }
 
+    const HTTPHeaderMap& internalHeaders() const { return m_headers; }
+
 private:
     FetchHeaders(Guard guard) : m_guard(guard) { }
     FetchHeaders(Guard guard, const HTTPHeaderMap& headers) : m_guard(guard), m_headers(headers) { }
index 834a7adf4fa7bab120a006218bcbb968c65984a6..a760baf6d85c2ce44ce89164c56d385f5455a392 100644 (file)
 #include "BlobURL.h"
 #include "FetchBody.h"
 #include "FetchLoaderClient.h"
+#include "FetchRequest.h"
 #include "ResourceRequest.h"
 #include "ScriptExecutionContext.h"
+#include "SecurityOrigin.h"
 #include "SharedBuffer.h"
 #include "TextResourceDecoder.h"
 #include "ThreadableBlobRegistry.h"
 
 namespace WebCore {
 
-bool FetchLoader::start(ScriptExecutionContext& context, Blob& blob)
+void FetchLoader::start(ScriptExecutionContext& context, Blob& blob)
 {
     auto urlForReading = BlobURL::createPublicURL(context.securityOrigin());
-    if (urlForReading.isEmpty())
-        return false;
+    if (urlForReading.isEmpty()) {
+        m_client.didFail();
+        return;
+    }
+
     ThreadableBlobRegistry::registerBlobURL(context.securityOrigin(), urlForReading, blob.url());
 
     ResourceRequest request(urlForReading);
@@ -63,7 +68,21 @@ bool FetchLoader::start(ScriptExecutionContext& context, Blob& blob)
     options.contentSecurityPolicyEnforcement = ContentSecurityPolicyEnforcement::DoNotEnforce;
 
     m_loader = ThreadableLoader::create(&context, this, request, options);
-    return true;
+}
+
+void FetchLoader::start(ScriptExecutionContext& context, const FetchRequest& request)
+{
+    // FIXME: Compute loading options according fetch options.
+    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.internalRequest(), options);
 }
 
 FetchLoader::FetchLoader(Type type, FetchLoaderClient& client)
@@ -113,6 +132,11 @@ void FetchLoader::didFail(const ResourceError&)
     m_client.didFail();
 }
 
+void FetchLoader::didFailRedirectCheck()
+{
+    m_client.didFail();
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(FETCH_API)
index ef0a736deb8868ca2bcbd51b1ff0e5722af486c8..8466fd757f33defc832a248fba345beba4e0b643 100644 (file)
@@ -39,6 +39,7 @@ namespace WebCore {
 
 class Blob;
 class FetchLoaderClient;
+class FetchRequest;
 class ScriptExecutionContext;
 
 class FetchLoader final : public ThreadableLoaderClient {
@@ -47,15 +48,18 @@ public:
 
     FetchLoader(Type, FetchLoaderClient&);
 
-    bool start(ScriptExecutionContext&, Blob&);
+    void start(ScriptExecutionContext&, const FetchRequest&);
+    void start(ScriptExecutionContext&, Blob&);
     void stop();
 
+    bool isStarted() const { return !!m_loader; }
 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;
+    void didFailRedirectCheck() final;
 
 private:
     Type m_type { Type::ArrayBuffer };
index d6aea5657005d304b8be9946688b184d0460631e..fdee688222ecf68c2c749845509032e117d31582 100644 (file)
@@ -435,6 +435,14 @@ String FetchRequest::redirect() const
     return String();
 }
 
+ResourceRequest FetchRequest::internalRequest() const
+{
+    ResourceRequest request = m_internalRequest.request;
+    request.setHTTPHeaderFields(m_headers->internalHeaders());
+    request.setHTTPBody(body().bodyForInternalRequest());
+    return request;
+}
+
 RefPtr<FetchRequest> FetchRequest::clone(ScriptExecutionContext& context, ExceptionCode& ec)
 {
     if (isDisturbed()) {
index 59c9b51489e8ef30e3f6eef9e0a2dfb1a2fc1499..8fdcaca98bc2282322b25f74d8a550cb400dbfc2 100644 (file)
@@ -72,6 +72,9 @@ public:
         String integrity;
     };
 
+    const FetchOptions& fetchOptions() const { return m_internalRequest.options; }
+    ResourceRequest internalRequest() const;
+
 private:
     FetchRequest(ScriptExecutionContext&, FetchBody&&, Ref<FetchHeaders>&&, InternalRequest&&);
 
index 351049c8e65db4981552a7451ae8f676f1bfcca2..34dc323c9b943a0645625644a9f0d50d24484ae9 100644 (file)
@@ -153,6 +153,82 @@ JSC::JSValue JSFetchResponse::body(JSC::ExecState&) const
     return JSC::jsNull();
 }
 
+void FetchResponse::fetch(ScriptExecutionContext& context, const FetchRequest& request, FetchPromise&& promise)
+{
+    Ref<FetchResponse> response = adoptRef(*new FetchResponse(context, Type::Basic, FetchBody::loadingBody(), FetchHeaders::create(FetchHeaders::Guard::Immutable), ResourceResponse()));
+
+    // Setting pending activity until BodyLoader didFail or didSucceed callback is called.
+    response->setPendingActivity(response.ptr());
+
+    response->m_bodyLoader = BodyLoader(response.get(), WTFMove(promise));
+    if (!response->m_bodyLoader->start(context, request))
+        response->m_bodyLoader = Nullopt;
+}
+
+void FetchResponse::BodyLoader::didSucceed()
+{
+    m_response.m_bodyLoader = Nullopt;
+    m_response.unsetPendingActivity(&m_response);
+}
+
+void FetchResponse::BodyLoader::didFail()
+{
+    if (m_promise)
+        std::exchange(m_promise, Nullopt)->reject(TypeError);
+
+    // Check whether didFail is called as part of FetchLoader::start.
+    if (m_loader->isStarted())
+        m_response.m_bodyLoader = Nullopt;
+
+    // FIXME: Handle the case of failing after didReceiveResponse is called.
+
+    m_response.unsetPendingActivity(&m_response);
+}
+
+FetchResponse::BodyLoader::BodyLoader(FetchResponse& response, FetchPromise&& promise)
+    : m_response(response)
+    , m_promise(WTFMove(promise))
+{
+}
+
+void FetchResponse::BodyLoader::didReceiveResponse(const ResourceResponse& resourceResponse)
+{
+    ASSERT(m_promise);
+
+    m_response.m_response = resourceResponse;
+    m_response.m_headers->filterAndFill(resourceResponse.httpHeaderFields(), FetchHeaders::Guard::Response);
+
+    std::exchange(m_promise, Nullopt)->resolve(&m_response);
+}
+
+void FetchResponse::BodyLoader::didFinishLoadingAsArrayBuffer(RefPtr<ArrayBuffer>&& buffer)
+{
+    m_response.body().loadedAsArrayBuffer(WTFMove(buffer));
+}
+
+bool FetchResponse::BodyLoader::start(ScriptExecutionContext& context, const FetchRequest& request)
+{
+    m_loader = std::make_unique<FetchLoader>(FetchLoader::Type::ArrayBuffer, *this);
+    m_loader->start(context, request);
+    return m_loader->isStarted();
+}
+
+void FetchResponse::BodyLoader::stop()
+{
+    if (m_loader)
+        m_loader->stop();
+}
+
+void FetchResponse::stop()
+{
+    FetchBodyOwner::stop();
+    if (m_bodyLoader) {
+        RefPtr<FetchResponse> protect(this);
+        m_bodyLoader->stop();
+        m_bodyLoader = Nullopt;
+    }
+}
+
 const char* FetchResponse::activeDOMObjectName() const
 {
     return "Response";
index 8afccb47bc4f1a7360762e7d13355e447945f1fb..9d09082ecfacf4eaa9de5b48cc7c1d21ba00c66a 100644 (file)
@@ -42,6 +42,7 @@ class ArrayBuffer;
 namespace WebCore {
 
 class Dictionary;
+class FetchRequest;
 
 typedef int ExceptionCode;
 
@@ -53,6 +54,9 @@ public:
     // FIXME: Binding generator should not require below method to handle optional status parameter.
     static RefPtr<FetchResponse> redirect(ScriptExecutionContext& context, const String& url, ExceptionCode& ec) { return redirect(context, url, 302, ec); }
 
+    using FetchPromise = DOMPromise<RefPtr<FetchResponse>, ExceptionCode>;
+    static void fetch(ScriptExecutionContext&, const FetchRequest&, FetchPromise&&);
+
     void initializeWith(const Dictionary&, ExceptionCode&);
 
     String type() const;
@@ -71,14 +75,35 @@ private:
     FetchResponse(ScriptExecutionContext&, Type, FetchBody&&, Ref<FetchHeaders>&&, ResourceResponse&&);
 
     // ActiveDOMObject API
+    void stop() final;
     const char* activeDOMObjectName() const final;
     bool canSuspendForDocumentSuspension() const final;
 
+    class BodyLoader final : public FetchLoaderClient {
+    public:
+        BodyLoader(FetchResponse&, FetchPromise&&);
+
+        bool start(ScriptExecutionContext&, const FetchRequest&);
+        void stop();
+
+    private:
+        // FetchLoaderClient API
+        void didSucceed() final;
+        void didFail() final;
+        void didReceiveResponse(const ResourceResponse&);
+        void didFinishLoadingAsArrayBuffer(RefPtr<ArrayBuffer>&&) final;
+
+        FetchResponse& m_response;
+        Optional<FetchPromise> m_promise;
+        std::unique_ptr<FetchLoader> m_loader;
+    };
+
     Type m_type;
     ResourceResponse m_response;
     Ref<FetchHeaders> m_headers;
     bool m_isLocked = false;
     bool m_isRedirected = false;
+    Optional<BodyLoader> m_bodyLoader;
 };
 
 } // namespace WebCore
index 41d009e30533d9acf8fe41f631dbcba2ddba8cf3..61f2334ade840d94e718282eda2f4b59cbee45aa 100644 (file)
@@ -136,10 +136,6 @@ void BlobResourceSynchronousLoader::didFail(ResourceHandle*, const ResourceError
 
 PassRefPtr<BlobResourceHandle> BlobResourceHandle::createAsync(BlobData* blobData, const ResourceRequest& request, ResourceHandleClient* client)
 {
-    // FIXME: Should probably call didFail() instead of blocking the load without explanation.
-    if (!equalLettersIgnoringASCIICase(request.httpMethod(), "get"))
-        return nullptr;
-
     return adoptRef(new BlobResourceHandle(blobData, request, client, true));
 }
 
@@ -207,6 +203,12 @@ void BlobResourceHandle::doStart()
     if (m_aborted || m_errorCode)
         return;
 
+    if (!equalLettersIgnoringASCIICase(firstRequest().httpMethod(), "get")) {
+        m_errorCode = methodNotAllowed;
+        notifyResponse();
+        return;
+    }
+
     // If the blob data is not found, fail now.
     if (!m_blobData) {
         m_errorCode = notFoundError;
@@ -578,6 +580,10 @@ void BlobResourceHandle::notifyResponseOnSuccess()
     ResourceResponse response(firstRequest().url(), m_blobData->contentType(), m_totalRemainingSize, String());
     response.setHTTPStatusCode(isRangeRequest ? httpPartialContent : httpOK);
     response.setHTTPStatusText(isRangeRequest ? httpPartialContentText : httpOKText);
+
+    response.setHTTPHeaderField(HTTPHeaderName::ContentType, m_blobData->contentType());
+    response.setHTTPHeaderField(HTTPHeaderName::ContentLength, String::number(m_totalRemainingSize));
+
     if (isRangeRequest)
         response.setHTTPHeaderField(HTTPHeaderName::ContentRange, ParsedContentRange(m_rangeOffset, m_rangeEnd, m_totalSize).headerValue());
     // FIXME: If a resource identified with a blob: URL is a File object, user agents must use that file's name attribute,