| Differences between
and this patch
- a/Source/WebCore/ChangeLog +31 lines
Lines 1-3 a/Source/WebCore/ChangeLog_sec1
1
2016-08-27  Youenn Fablet  <youenn@apple.com>
2
3
        [Fetch API] Blob type should be set from Response/Request contentType header
4
        https://bugs.webkit.org/show_bug.cgi?id=161228
5
6
        Reviewed by Alex Christensen.
7
8
        Covered by updated tests.
9
10
        Renaming FetchBody::m_mimeType to m_contentType since that better relates to Content-Type header.
11
        Updated FetchRequest and FetchResponse to set m_contentType according request/response headers.
12
        Handled the case of a Request created from JS, a Response created from JS and a Response created internally to
13
        be used as resolve value in the fetch promise.
14
15
        In case Content-Type is set but is empty, its empty value should be used for blob type.
16
        Updated contentType checks to use isNull in lieu of isEmpty.
17
18
        * Modules/fetch/FetchBody.cpp:
19
        (WebCore::FetchBody::updateContentType): Routine to synchronize headers with m_contentType.
20
        (WebCore::FetchBody::FetchBody): Renamed m_mimeType to m_contentType.
21
        (WebCore::FetchBody::blob): Ditto.
22
        * Modules/fetch/FetchBody.h: Ditto.
23
        (WebCore::FetchBody::contentType):
24
        (WebCore::FetchBody::setMimeType): Deleted.
25
        (WebCore::FetchBody::mimeType): Deleted.
26
        * Modules/fetch/FetchRequest.cpp:
27
        (WebCore::FetchRequest::setBody): set FetchBody::m_contentType according HTTP headers.
28
        * Modules/fetch/FetchResponse.cpp:
29
        (WebCore::FetchResponse::initializeWith): Ditto.
30
        (WebCore::FetchResponse::BodyLoader::didReceiveResponse): Ditto.
31
1
2016-08-26  Alex Christensen  <achristensen@webkit.org>
32
2016-08-26  Alex Christensen  <achristensen@webkit.org>
2
33
3
        Fix Windows build after r205065.
34
        Fix Windows build after r205065.
- a/Source/WebCore/Modules/fetch/FetchBody.cpp -4 / +16 lines
Lines 34-39 a/Source/WebCore/Modules/fetch/FetchBody.cpp_sec1
34
#include "DOMRequestState.h"
34
#include "DOMRequestState.h"
35
#include "Dictionary.h"
35
#include "Dictionary.h"
36
#include "FetchBodyOwner.h"
36
#include "FetchBodyOwner.h"
37
#include "FetchHeaders.h"
37
#include "FetchResponseSource.h"
38
#include "FetchResponseSource.h"
38
#include "FormData.h"
39
#include "FormData.h"
39
#include "HTTPParsers.h"
40
#include "HTTPParsers.h"
Lines 46-59 namespace WebCore { a/Source/WebCore/Modules/fetch/FetchBody.cpp_sec2
46
47
47
FetchBody::FetchBody(Ref<Blob>&& blob)
48
FetchBody::FetchBody(Ref<Blob>&& blob)
48
    : m_type(Type::Blob)
49
    : m_type(Type::Blob)
49
    , m_mimeType(blob->type())
50
    , m_contentType(blob->type())
50
    , m_blob(WTFMove(blob))
51
    , m_blob(WTFMove(blob))
51
{
52
{
52
}
53
}
53
54
54
FetchBody::FetchBody(Ref<DOMFormData>&& formData)
55
FetchBody::FetchBody(Ref<DOMFormData>&& formData)
55
    : m_type(Type::FormData)
56
    : m_type(Type::FormData)
56
    , m_mimeType(ASCIILiteral("multipart/form-data"))
57
    , m_contentType(ASCIILiteral("multipart/form-data"))
57
    , m_formData(WTFMove(formData))
58
    , m_formData(WTFMove(formData))
58
{
59
{
59
    // FIXME: Handle the boundary parameter of multipart/form-data MIME type.
60
    // FIXME: Handle the boundary parameter of multipart/form-data MIME type.
Lines 61-67 FetchBody::FetchBody(Ref<DOMFormData>&& formData) a/Source/WebCore/Modules/fetch/FetchBody.cpp_sec3
61
62
62
FetchBody::FetchBody(String&& text)
63
FetchBody::FetchBody(String&& text)
63
    : m_type(Type::Text)
64
    : m_type(Type::Text)
64
    , m_mimeType(ASCIILiteral("text/plain;charset=UTF-8"))
65
    , m_contentType(ASCIILiteral("text/plain;charset=UTF-8"))
65
    , m_text(WTFMove(text))
66
    , m_text(WTFMove(text))
66
{
67
{
67
}
68
}
Lines 88-93 FetchBody FetchBody::extractFromBody(FetchBody* body) a/Source/WebCore/Modules/fetch/FetchBody.cpp_sec4
88
    return FetchBody(WTFMove(*body));
89
    return FetchBody(WTFMove(*body));
89
}
90
}
90
91
92
void FetchBody::updateContentType(FetchHeaders& headers)
93
{
94
    String contentType = headers.fastGet(HTTPHeaderName::ContentType);
95
    if (!contentType.isNull()) {
96
        m_contentType = contentType;
97
        return;
98
    }
99
    if (!m_contentType.isNull())
100
        headers.fastSet(HTTPHeaderName::ContentType, m_contentType);
101
}
102
91
void FetchBody::arrayBuffer(FetchBodyOwner& owner, DeferredWrapper&& promise)
103
void FetchBody::arrayBuffer(FetchBodyOwner& owner, DeferredWrapper&& promise)
92
{
104
{
93
    ASSERT(m_type != Type::None);
105
    ASSERT(m_type != Type::None);
Lines 99-105 void FetchBody::blob(FetchBodyOwner& owner, DeferredWrapper&& promise) a/Source/WebCore/Modules/fetch/FetchBody.cpp_sec5
99
{
111
{
100
    ASSERT(m_type != Type::None);
112
    ASSERT(m_type != Type::None);
101
    m_consumer.setType(FetchBodyConsumer::Type::Blob);
113
    m_consumer.setType(FetchBodyConsumer::Type::Blob);
102
    m_consumer.setContentType(Blob::normalizedContentType(extractMIMETypeFromMediaType(m_mimeType)));
114
    m_consumer.setContentType(Blob::normalizedContentType(extractMIMETypeFromMediaType(m_contentType)));
103
    consume(owner, WTFMove(promise));
115
    consume(owner, WTFMove(promise));
104
}
116
}
105
117
- a/Source/WebCore/Modules/fetch/FetchBody.h -3 / +5 lines
Lines 45-50 class JSValue; a/Source/WebCore/Modules/fetch/FetchBody.h_sec1
45
namespace WebCore {
45
namespace WebCore {
46
46
47
class FetchBodyOwner;
47
class FetchBodyOwner;
48
class FetchHeaders;
48
class FetchResponseSource;
49
class FetchResponseSource;
49
class FormData;
50
class FormData;
50
51
Lines 62-69 public: a/Source/WebCore/Modules/fetch/FetchBody.h_sec2
62
63
63
    bool isEmpty() const { return m_type == Type::None; }
64
    bool isEmpty() const { return m_type == Type::None; }
64
65
65
    void setMimeType(const String& mimeType) { m_mimeType = mimeType; }
66
    void updateContentType(FetchHeaders&);
66
    String mimeType() const { return m_mimeType; }
67
    void setContentType(const String& contentType) { m_contentType = contentType; }
68
    String contentType() const { return m_contentType; }
67
69
68
    static FetchBody extract(JSC::ExecState&, JSC::JSValue);
70
    static FetchBody extract(JSC::ExecState&, JSC::JSValue);
69
    static FetchBody extractFromBody(FetchBody*);
71
    static FetchBody extractFromBody(FetchBody*);
Lines 96-102 private: a/Source/WebCore/Modules/fetch/FetchBody.h_sec3
96
    void consumeBlob(FetchBodyOwner&, DeferredWrapper&&);
98
    void consumeBlob(FetchBodyOwner&, DeferredWrapper&&);
97
99
98
    Type m_type { Type::None };
100
    Type m_type { Type::None };
99
    String m_mimeType;
101
    String m_contentType;
100
102
101
    // FIXME: Add support for BufferSource and URLSearchParams.
103
    // FIXME: Add support for BufferSource and URLSearchParams.
102
    RefPtr<Blob> m_blob;
104
    RefPtr<Blob> m_blob;
- a/Source/WebCore/Modules/fetch/FetchRequest.cpp -6 / +2 lines
Lines 268-279 void FetchRequest::setBody(JSC::ExecState& execState, JSC::JSValue body, FetchRe a/Source/WebCore/Modules/fetch/FetchRequest.cpp_sec1
268
        request->setDisturbed();
268
        request->setDisturbed();
269
    }
269
    }
270
270
271
    String type = m_headers->fastGet(HTTPHeaderName::ContentType);
271
    m_body.updateContentType(m_headers);
272
    if (!body.isUndefined() && type.isEmpty() && !m_body.mimeType().isEmpty()) {
272
273
        type = m_body.mimeType();
274
        m_headers->fastSet(HTTPHeaderName::ContentType, type);
275
    }
276
    m_body.setMimeType(type);
277
    if (!validateBodyAndMethod(m_body, m_internalRequest))
273
    if (!validateBodyAndMethod(m_body, m_internalRequest))
278
        ec = TypeError;
274
        ec = TypeError;
279
}
275
}
- a/Source/WebCore/Modules/fetch/FetchResponse.cpp -2 / +2 lines
Lines 83-90 void FetchResponse::setStatus(int status, const String& statusText, ExceptionCod a/Source/WebCore/Modules/fetch/FetchResponse.cpp_sec1
83
void FetchResponse::initializeWith(JSC::ExecState& execState, JSC::JSValue body)
83
void FetchResponse::initializeWith(JSC::ExecState& execState, JSC::JSValue body)
84
{
84
{
85
    m_body = FetchBody::extract(execState, body);
85
    m_body = FetchBody::extract(execState, body);
86
    if (m_headers->fastGet(HTTPHeaderName::ContentType).isEmpty() && !m_body.mimeType().isEmpty())
86
    m_body.updateContentType(m_headers);
87
        m_headers->fastSet(HTTPHeaderName::ContentType, m_body.mimeType());
88
}
87
}
89
88
90
FetchResponse::FetchResponse(ScriptExecutionContext& context, FetchBody&& body, Ref<FetchHeaders>&& headers, ResourceResponse&& response)
89
FetchResponse::FetchResponse(ScriptExecutionContext& context, FetchBody&& body, Ref<FetchHeaders>&& headers, ResourceResponse&& response)
Lines 176-181 void FetchResponse::BodyLoader::didReceiveResponse(const ResourceResponse& resou a/Source/WebCore/Modules/fetch/FetchResponse.cpp_sec2
176
175
177
    m_response.m_response = resourceResponse;
176
    m_response.m_response = resourceResponse;
178
    m_response.m_headers->filterAndFill(resourceResponse.httpHeaderFields(), FetchHeaders::Guard::Response);
177
    m_response.m_headers->filterAndFill(resourceResponse.httpHeaderFields(), FetchHeaders::Guard::Response);
178
    m_response.m_body.setContentType(m_response.m_headers->fastGet(HTTPHeaderName::ContentType));
179
179
180
    std::exchange(m_promise, Nullopt)->resolve(m_response);
180
    std::exchange(m_promise, Nullopt)->resolve(m_response);
181
}
181
}
- a/LayoutTests/imported/w3c/ChangeLog +15 lines
Lines 1-3 a/LayoutTests/imported/w3c/ChangeLog_sec1
1
2016-08-27  Youenn Fablet  <youenn@apple.com>
2
3
        [Fetch API] Blob type should be set from Response/Request contentType header
4
        https://bugs.webkit.org/show_bug.cgi?id=161228
5
6
        Reviewed by Alex Christensen.
7
8
        * web-platform-tests/fetch/api/request/request-consume.html:
9
        * web-platform-tests/fetch/api/request/request-headers-expected.txt:
10
        * web-platform-tests/fetch/api/request/request-headers.html:
11
        * web-platform-tests/fetch/api/response/response-consume-expected.txt:
12
        * web-platform-tests/fetch/api/response/response-consume.html:
13
        * web-platform-tests/fetch/api/response/response-init-002-expected.txt:
14
        * web-platform-tests/fetch/api/response/response-init-002.html:
15
1
2016-08-26  Andreas Kling  <akling@apple.com>
16
2016-08-26  Andreas Kling  <akling@apple.com>
2
17
3
        The :enabled/:disabled selectors should only match elements that can be disabled.
18
        The :enabled/:disabled selectors should only match elements that can be disabled.
- a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-consume.html -3 / +6 lines
Lines 19-26 a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-consume.html_sec1
19
      });
19
      });
20
    }
20
    }
21
21
22
    function checkBodyBlob(request, expectedBody) {
22
    function checkBodyBlob(request, expectedBody, checkContentType) {
23
      return request.blob().then(function(bodyAsBlob) {
23
      return request.blob().then(function(bodyAsBlob) {
24
        if (checkContentType)
25
          assert_equals(bodyAsBlob.type, "text/plain", "Blob body type should be computed from the request Content-Type");
26
24
        var promise = new Promise(function (resolve, reject) {
27
        var promise = new Promise(function (resolve, reject) {
25
          var reader = new FileReader();
28
          var reader = new FileReader();
26
          reader.onload = function(evt) {
29
          reader.onload = function(evt) {
Lines 62-68 a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-consume.html_sec2
62
65
63
    function checkRequestBody(body, bodyType, checkFunction) {
66
    function checkRequestBody(body, bodyType, checkFunction) {
64
      promise_test(function(test) {
67
      promise_test(function(test) {
65
        var request = new Request("", {"method": "POST", "body": body });
68
        var request = new Request("", {"method": "POST", "body": body, "headers": [["Content-Type", "text/PLAIN"]] });
66
        assert_false(request.bodyUsed, "bodyUsed is false at init");
69
        assert_false(request.bodyUsed, "bodyUsed is false at init");
67
        return checkFunction(request, body);
70
        return checkFunction(request, body);
68
      }, "Consume request's body as " + bodyType);
71
      }, "Consume request's body as " + bodyType);
Lines 74-80 a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-consume.html_sec3
74
    var blob = new Blob([textData], { "type" : "text/plain" });
77
    var blob = new Blob([textData], { "type" : "text/plain" });
75
78
76
    checkRequestBody(textData, "text", checkBodyText);
79
    checkRequestBody(textData, "text", checkBodyText);
77
    checkRequestBody(textData, "blob", checkBodyBlob);
80
    checkRequestBody(textData, "blob", function(request, body) { checkBodyBlob(request, body, true); });
78
    checkRequestBody(textData, "arrayBuffer", checkBodyArrayBuffer);
81
    checkRequestBody(textData, "arrayBuffer", checkBodyArrayBuffer);
79
    checkRequestBody(textData, "json", checkBodyJSON);
82
    checkRequestBody(textData, "json", checkBodyJSON);
80
    checkRequestBody(formData, "formData", checkBodyFormData);
83
    checkRequestBody(formData, "formData", checkBodyFormData);
- a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-headers-expected.txt +1 lines
Lines 54-57 PASS Request should not get its content-type from the init request if init heade a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-headers-expected.txt_sec1
54
PASS Request should get its content-type from the body if none is provided 
54
PASS Request should get its content-type from the body if none is provided 
55
PASS Request should get its content-type from init headers if one is provided 
55
PASS Request should get its content-type from init headers if one is provided 
56
PASS Testing request header creations with various objects 
56
PASS Testing request header creations with various objects 
57
PASS Testing empty Request Content-Type header 
57
58
- a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-headers.html +7 lines
Lines 161-166 a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-headers.html_sec1
161
        assert_equals(request3.headers.get("hello"), "worldOOH");
161
        assert_equals(request3.headers.get("hello"), "worldOOH");
162
      }, "Testing request header creations with various objects");
162
      }, "Testing request header creations with various objects");
163
163
164
      promise_test(function(test) {
165
        var request = new Request("", {"headers" : [["Content-Type", ""]], "body" : "this is my plate", "method" : "POST"});
166
        return request.blob().then(function(blob) {
167
          assert_equals(blob.type, "", "Blob type should be the empty string");
168
        });
169
      }, "Testing empty Request Content-Type header");
170
164
    </script>
171
    </script>
165
  </body>
172
  </body>
166
</html>
173
</html>
- a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-consume-expected.txt +3 lines
Lines 12-15 PASS Consume stream response's body as blob a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-consume-expected.txt_sec1
12
PASS Consume stream response's body as text 
12
PASS Consume stream response's body as text 
13
PASS Consume stream response's body as json 
13
PASS Consume stream response's body as json 
14
PASS Consume stream response's body as arrayBuffer 
14
PASS Consume stream response's body as arrayBuffer 
15
PASS Consume fetched response's body as blob 
16
PASS Consume fetched response's body as text 
17
PASS Consume fetched response's body as arrayBuffer 
15
18
- a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-consume.html -3 / +18 lines
Lines 19-26 a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-consume.html_sec1
19
      });
19
      });
20
    }
20
    }
21
21
22
    function checkBodyBlob(response, expectedBody) {
22
    function checkBodyBlob(response, expectedBody, checkContentType) {
23
      return response.blob().then(function(bodyAsBlob) {
23
      return response.blob().then(function(bodyAsBlob) {
24
        if (checkContentType)
25
          assert_equals(bodyAsBlob.type, "text/plain", "Blob body type should be computed from the response Content-Type");
26
24
        var promise = new Promise( function (resolve, reject) {
27
        var promise = new Promise( function (resolve, reject) {
25
          var reader = new FileReader();
28
          var reader = new FileReader();
26
          reader.onload = function(evt) {
29
          reader.onload = function(evt) {
Lines 62-68 a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-consume.html_sec2
62
65
63
    function checkResponseBody(body, bodyType, checkFunction) {
66
    function checkResponseBody(body, bodyType, checkFunction) {
64
      promise_test(function(test) {
67
      promise_test(function(test) {
65
        var response = new Response(body);
68
        var response = new Response(body, { "headers": [["Content-Type", "text/PLAIN"]] });
66
        assert_false(response.bodyUsed, "bodyUsed is false at init");
69
        assert_false(response.bodyUsed, "bodyUsed is false at init");
67
        return checkFunction(response, body);
70
        return checkFunction(response, body);
68
      }, "Consume response's body as " + bodyType);
71
      }, "Consume response's body as " + bodyType);
Lines 74-80 a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-consume.html_sec3
74
    var blob = new Blob([textData], { "type" : "text/plain" });
77
    var blob = new Blob([textData], { "type" : "text/plain" });
75
78
76
    checkResponseBody(textData, "text", checkBodyText);
79
    checkResponseBody(textData, "text", checkBodyText);
77
    checkResponseBody(textData, "blob", checkBodyBlob);
80
    checkResponseBody(textData, "blob", function(response, body) { checkBodyBlob(response, body, true); });
78
    checkResponseBody(textData, "arrayBuffer", checkBodyArrayBuffer);
81
    checkResponseBody(textData, "arrayBuffer", checkBodyArrayBuffer);
79
    checkResponseBody(textData, "json", checkBodyJSON);
82
    checkResponseBody(textData, "json", checkBodyJSON);
80
    checkResponseBody(formData, "formData", checkBodyFormData);
83
    checkResponseBody(formData, "formData", checkBodyFormData);
Lines 111-116 a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-consume.html_sec4
111
    checkReadableStreamResponseBody(textData, "json", checkBodyJSON);
114
    checkReadableStreamResponseBody(textData, "json", checkBodyJSON);
112
    checkReadableStreamResponseBody(textData, "arrayBuffer", checkBodyArrayBuffer);
115
    checkReadableStreamResponseBody(textData, "arrayBuffer", checkBodyArrayBuffer);
113
116
117
    function checkFetchedResponseBody(bodyType, checkFunction) {
118
      return promise_test(function(test) {
119
        return fetch("../resources/top.txt").then(function(response) {
120
          assert_false(response.bodyUsed, "bodyUsed is false at init");
121
          return checkFunction(response, "top");
122
        });
123
      }, "Consume fetched response's body as " + bodyType);
124
    }
125
    checkFetchedResponseBody("blob", checkBodyBlob);
126
    checkFetchedResponseBody("text", checkBodyText);
127
    checkFetchedResponseBody("arrayBuffer", checkBodyArrayBuffer);
128
114
    </script>
129
    </script>
115
  </body>
130
  </body>
116
</html>
131
</html>
- a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-init-002-expected.txt +1 lines
Lines 5-8 FAIL Initialize Response's body with multipart/form-data promise_test: Unhandled a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-init-002-expected.txt_sec1
5
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
5
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
6
PASS Initialize Response's body with text/plain;charset=UTF-8 
6
PASS Initialize Response's body with text/plain;charset=UTF-8 
7
PASS Read Response's body as readableStream 
7
PASS Read Response's body as readableStream 
8
PASS Testing empty Response Content-Type header 
8
9
- a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-init-002.html +8 lines
Lines 57-62 a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-init-002.html_sec1
57
        var response = new Response(body);
57
        var response = new Response(body);
58
        return validateStreamFromString(response.body.getReader(), body);
58
        return validateStreamFromString(response.body.getReader(), body);
59
      }, "Read Response's body as readableStream");
59
      }, "Read Response's body as readableStream");
60
61
      promise_test(function(test) {
62
        var response = new Response("This is my fork", {"headers" : [["Content-Type", ""]]});
63
        return response.blob().then(function(blob) {
64
          assert_equals(blob.type, "", "Blob type should be the empty string");
65
        });
66
      }, "Testing empty Response Content-Type header");
67
60
    </script>
68
    </script>
61
  </body>
69
  </body>
62
</html>
70
</html>

Return to Bug 161228