Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(419)

Side by Side Diff: Source/modules/fetch/Request.cpp

Issue 1088823002: [Fetch API] Follow a body setting spec change on Request constructor. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "config.h" 5 #include "config.h"
6 #include "modules/fetch/Request.h" 6 #include "modules/fetch/Request.h"
7 7
8 #include "bindings/core/v8/Dictionary.h" 8 #include "bindings/core/v8/Dictionary.h"
9 #include "core/dom/Document.h" 9 #include "core/dom/Document.h"
10 #include "core/dom/ExecutionContext.h" 10 #include "core/dom/ExecutionContext.h"
(...skipping 10 matching lines...) Expand all
21 21
22 namespace blink { 22 namespace blink {
23 23
24 FetchRequestData* createCopyOfFetchRequestDataForFetch(ExecutionContext* context , const FetchRequestData* original) 24 FetchRequestData* createCopyOfFetchRequestDataForFetch(ExecutionContext* context , const FetchRequestData* original)
25 { 25 {
26 FetchRequestData* request = FetchRequestData::create(); 26 FetchRequestData* request = FetchRequestData::create();
27 request->setURL(original->url()); 27 request->setURL(original->url());
28 request->setMethod(original->method()); 28 request->setMethod(original->method());
29 request->setHeaderList(original->headerList()->clone()); 29 request->setHeaderList(original->headerList()->clone());
30 request->setUnsafeRequestFlag(true); 30 request->setUnsafeRequestFlag(true);
31 request->setBlobDataHandle(original->blobDataHandle());
32 // FIXME: Set client. 31 // FIXME: Set client.
33 request->setOrigin(SecurityOrigin::create(context->url())); 32 request->setOrigin(SecurityOrigin::create(context->url()));
34 // FIXME: Set ForceOriginHeaderFlag. 33 // FIXME: Set ForceOriginHeaderFlag.
35 request->setSameOriginDataURLFlag(true); 34 request->setSameOriginDataURLFlag(true);
36 request->mutableReferrer()->setClient(); 35 request->mutableReferrer()->setClient();
37 request->setMode(original->mode()); 36 request->setMode(original->mode());
38 request->setCredentials(original->credentials()); 37 request->setCredentials(original->credentials());
39 // FIXME: Set cache mode. 38 // FIXME: Set cache mode.
39 // TODO(yhirano): Set redirect mode.
40 return request; 40 return request;
41 } 41 }
42 42
43 Request* Request::createRequestWithRequestOrString(ExecutionContext* context, Re quest* inputRequest, const String& inputString, const RequestInit& init, Excepti onState& exceptionState) 43 Request* Request::createRequestWithRequestOrString(ExecutionContext* context, Re quest* inputRequest, const String& inputString, const RequestInit& init, Excepti onState& exceptionState)
44 { 44 {
45 // "1. If input is a Request object, run these substeps:" 45 // "1. Let |temporaryBody| be null."
46 if (inputRequest) { 46 RefPtr<BlobDataHandle> temporaryBody;
47 // "1. If input's used flag is set, throw a TypeError." 47
48 // "2. If |input| is a Request object and |input|'s body is non-null, run
49 // these substeps:"
50 if (inputRequest && inputRequest->hasBody()) {
51 // "1. If |input|'s used flag is set, throw a TypeError."
52 // "2. Set |temporaryBody| to |input|'s body."
48 if (inputRequest->bodyUsed()) { 53 if (inputRequest->bodyUsed()) {
49 exceptionState.throwTypeError("Cannot construct a Request with a Req uest object that has already been used."); 54 exceptionState.throwTypeError("Cannot construct a Request with a Req uest object that has already been used.");
50 return 0; 55 return nullptr;
51 } 56 }
52 // "2. Set input's used flag." 57 if (inputRequest->isBodyConsumed()) {
53 inputRequest->lockBody(PassBody); 58 // Currently the only methods that can consume body data without
59 // setting 'body passed' flag consume entire body (e.g. text()).
60 // Thus we can set an empty blob to the new request instead of
61 // creating a draining stream.
62 // TODO(yhirano): Fix this once Request.body is introduced.
63 OwnPtr<BlobData> blobData = BlobData::create();
64 blobData->setContentType(inputRequest->blobDataHandle()->type());
65 temporaryBody = BlobDataHandle::create(blobData.release(), 0);
66 } else {
67 temporaryBody = inputRequest->m_request->blobDataHandle();
68 }
54 } 69 }
55 70
56 // "2. Let |request| be |input|'s associated request, if |input| is a 71 // "3. Let |request| be |input|'s request, if |input| is a Request object,
57 // Request object, and a new request otherwise." 72 // and a new request otherwise."
58 // "3. Set |request| to a new request whose url is |request|'s url, method 73 // "4. Set |request| to a new request whose url is |request|'s url, method
59 // is |request|'s method, header list is a copy of |request|'s header list, 74 // is |request|'s method, header list is a copy of |request|'s header list,
60 // unsafe request flag is set, body is |request|'s body, client is entry 75 // unsafe request flag is set, client is entry settings object, origin is
61 // settings object, origin is entry settings object's origin, force Origin 76 // entry settings object's origin, force Origin header flag is set,
62 // header flag is set, same-origin data URL flag is set, referrer is client, 77 // same-origin data URL flag is set, context is the empty string, mode is
63 // context is fetch, mode is |request|'s mode, credentials mode is 78 // |request|'s mode, credentials mode is |request|'s credentials mode,
64 // |request|'s credentials mode, and cache mode is |request|'s cache mode." 79 // cache mode is |request|'s cache mode, and redirect mode is request's
80 // redirect mode."
65 FetchRequestData* request = createCopyOfFetchRequestDataForFetch(context, in putRequest ? inputRequest->request() : FetchRequestData::create()); 81 FetchRequestData* request = createCopyOfFetchRequestDataForFetch(context, in putRequest ? inputRequest->request() : FetchRequestData::create());
66 82
67 if (inputRequest && inputRequest->blobDataHandle() && inputRequest->isBodyCo nsumed()) { 83 // "5. Let |fallbackMode| be null."
68 // Currently the only methods that can consume body data without 84 // "6. Let |fallbackCredentials| be null."
69 // setting 'body passed' flag consume entire body (e.g. text()). Thus 85 // "7. Let |fallbackCache| be null."
70 // we can set an empty blob to the new request instead of creating a 86 // "8. Let |fallbackRedirect| be null."
71 // draining stream.
72 // TODO(yhirano): Fix this once Request.body is introduced.
73 OwnPtr<BlobData> blobData = BlobData::create();
74 blobData->setContentType(inputRequest->blobDataHandle()->type());
75 request->setBlobDataHandle(BlobDataHandle::create(blobData.release(), 0) );
76 }
77
78 // "4. Let |fallbackMode| be null."
79 // "5. Let |fallbackCredentials| be null."
80 // "6. Let |fallbackCache| be null."
81 // We don't use fallback values. We set these flags directly in below. 87 // We don't use fallback values. We set these flags directly in below.
82 88
83 // "7. If |input| is a string, run these substeps:" 89 // "9. If |input| is a string, run these substeps:"
84 if (!inputRequest) { 90 if (!inputRequest) {
85 // "1. Let |parsedURL| be the result of parsing |input| with entry 91 // "1. Let |parsedURL| be the result of parsing |input| with entry
86 // settings object's API base URL." 92 // settings object's API base URL."
87 KURL parsedURL = context->completeURL(inputString); 93 KURL parsedURL = context->completeURL(inputString);
88 // "2. If |parsedURL| is failure, throw a TypeError." 94 // "2. If |parsedURL| is failure, throw a TypeError."
89 if (!parsedURL.isValid()) { 95 if (!parsedURL.isValid()) {
90 exceptionState.throwTypeError("Failed to parse URL from " + inputStr ing); 96 exceptionState.throwTypeError("Failed to parse URL from " + inputStr ing);
91 return 0; 97 return nullptr;
92 } 98 }
93 // "3. Set |request|'s url to |parsedURL|." 99 // TODO(yhirano): "3. If |parsedURL| includes credentials, throw a
100 // TypeError."
101 // "4. Set |request|'s url to |parsedURL|."
94 request->setURL(parsedURL); 102 request->setURL(parsedURL);
95 // "4. Set |fallbackMode| to CORS." 103 // "5. Set |fallbackMode| to CORS."
96 // "5. Set |fallbackCredentials| to omit." 104 // "6. Set |fallbackCredentials| to omit."
97 // "6. Set |fallbackCache| to default." 105 // "7. Set |fallbackCache| to default."
106 // "8. Set |fallbackRedirect| to follow."
98 // We don't use fallback values. We set these flags directly in below. 107 // We don't use fallback values. We set these flags directly in below.
99 } 108 }
100 109
101 // "8. Let |mode| be |init|'s mode member if it is present, and 110 // "10. Let |mode| be |init|'s mode member if it is present, and
102 // |fallbackMode| otherwise." 111 // |fallbackMode| otherwise."
103 // "9. If |mode| is non-null, set |request|'s mode to |mode|." 112 // "11. If |mode| is non-null, set |request|'s mode to |mode|."
104 if (init.mode == "same-origin") { 113 if (init.mode == "same-origin") {
105 request->setMode(WebURLRequest::FetchRequestModeSameOrigin); 114 request->setMode(WebURLRequest::FetchRequestModeSameOrigin);
106 } else if (init.mode == "no-cors") { 115 } else if (init.mode == "no-cors") {
107 request->setMode(WebURLRequest::FetchRequestModeNoCORS); 116 request->setMode(WebURLRequest::FetchRequestModeNoCORS);
108 } else if (init.mode == "cors") { 117 } else if (init.mode == "cors") {
109 request->setMode(WebURLRequest::FetchRequestModeCORS); 118 request->setMode(WebURLRequest::FetchRequestModeCORS);
110 } else { 119 } else {
111 if (!inputRequest) 120 if (!inputRequest)
112 request->setMode(WebURLRequest::FetchRequestModeCORS); 121 request->setMode(WebURLRequest::FetchRequestModeCORS);
113 } 122 }
114 123
115 // "10. Let |credentials| be |init|'s credentials member if it is present, 124 // "12. Let |credentials| be |init|'s credentials member if it is present,
116 // and |fallbackCredentials| otherwise." 125 // and |fallbackCredentials| otherwise."
117 // "11. If |credentials| is non-null, set |request|'s credentials mode to 126 // "13. If |credentials| is non-null, set |request|'s credentials mode to
118 // |credentials|. 127 // |credentials|.
119 if (init.credentials == "omit") { 128 if (init.credentials == "omit") {
120 request->setCredentials(WebURLRequest::FetchCredentialsModeOmit); 129 request->setCredentials(WebURLRequest::FetchCredentialsModeOmit);
121 } else if (init.credentials == "same-origin") { 130 } else if (init.credentials == "same-origin") {
122 request->setCredentials(WebURLRequest::FetchCredentialsModeSameOrigin); 131 request->setCredentials(WebURLRequest::FetchCredentialsModeSameOrigin);
123 } else if (init.credentials == "include") { 132 } else if (init.credentials == "include") {
124 request->setCredentials(WebURLRequest::FetchCredentialsModeInclude); 133 request->setCredentials(WebURLRequest::FetchCredentialsModeInclude);
125 } else { 134 } else {
126 if (!inputRequest) 135 if (!inputRequest)
127 request->setCredentials(WebURLRequest::FetchCredentialsModeOmit); 136 request->setCredentials(WebURLRequest::FetchCredentialsModeOmit);
128 } 137 }
129 138
130 // FIXME: "12. Let |cache| be |init|'s cache member if it is present, and 139 // FIXME: "14. Let |cache| be |init|'s cache member if it is present, and
131 // |fallbackCache| otherwise." 140 // |fallbackCache| otherwise."
132 // FIXME: "13. If |cache| is non-null, set |request|'s cache mode to 141 // FIXME: "15. If |cache| is non-null, set |request|'s cache mode to
133 // |cache|." 142 // |cache|."
143 // TODO(yhirano): "16. If |init|'s redirect member is present and its is
144 // manual, throw a TypeError."
145 // TODO(yhirano): "17. Let |redirect| be |init|'s redirect member if it is
146 // present, and |fallbackRedirect| otherwise."
147 // TODO(yhirano): "18 If |redirect| is non-null, set |request|'s redirect
148 // mode to |redirect|."
149 // TODO(yhirano): "19 If |request|'s redirect mode is manual, set it to
150 // follow."
134 151
135 // "14. If |init|'s method member is present, let |method| be it and run 152 // "20. If |init|'s method member is present, let |method| be it and run
136 // these substeps:" 153 // these substeps:"
137 if (!init.method.isNull()) { 154 if (!init.method.isNull()) {
138 // "1. If |method| is not a method or method is a forbidden method, 155 // "1. If |method| is not a method or method is a forbidden method,
139 // throw a TypeError." 156 // throw a TypeError."
140 if (!isValidHTTPToken(init.method)) { 157 if (!isValidHTTPToken(init.method)) {
141 exceptionState.throwTypeError("'" + init.method + "' is not a valid HTTP method."); 158 exceptionState.throwTypeError("'" + init.method + "' is not a valid HTTP method.");
142 return 0; 159 return nullptr;
143 } 160 }
144 if (FetchUtils::isForbiddenMethod(init.method)) { 161 if (FetchUtils::isForbiddenMethod(init.method)) {
145 exceptionState.throwTypeError("'" + init.method + "' HTTP method is unsupported."); 162 exceptionState.throwTypeError("'" + init.method + "' HTTP method is unsupported.");
146 return 0; 163 return nullptr;
147 } 164 }
148 // "2. Normalize |method|." 165 // "2. Normalize |method|."
149 // "3. Set |request|'s method to |method|." 166 // "3. Set |request|'s method to |method|."
150 request->setMethod(FetchUtils::normalizeMethod(AtomicString(init.method) )); 167 request->setMethod(FetchUtils::normalizeMethod(AtomicString(init.method) ));
151 } 168 }
152 // "15. Let |r| be a new Request object associated with |request|, and a new 169 // "21. Let |r| be a new Request object associated with |request| and a new
153 // Headers object." 170 // Headers object whose guard is request."
154 Request* r = Request::create(context, request); 171 Request* r = Request::create(context, request);
155 // "16. Let |headers| be a copy of |r|'s Headers object." 172 // "22. Let |headers| be a copy of |r|'s Headers object."
156 // "17. If |init|'s headers member is present, set |headers| to |init|'s 173 // "23. If |init|'s headers member is present, set |headers| to |init|'s
157 // headers member." 174 // headers member."
158 // We don't create a copy of r's Headers object when init's headers member 175 // We don't create a copy of r's Headers object when init's headers member
159 // is present. 176 // is present.
160 Headers* headers = 0; 177 Headers* headers = nullptr;
161 if (!init.headers && init.headersDictionary.isUndefinedOrNull()) { 178 if (!init.headers && init.headersDictionary.isUndefinedOrNull()) {
162 headers = r->headers()->clone(); 179 headers = r->headers()->clone();
163 } 180 }
164 // "18. Empty |r|'s request's header list." 181 // "24. Empty |r|'s request's header list."
165 r->clearHeaderList(); 182 r->clearHeaderList();
166 // "19. If |r|'s request's mode is no CORS, run these substeps: 183 // "25. If |r|'s request's mode is no CORS, run these substeps:
167 if (r->request()->mode() == WebURLRequest::FetchRequestModeNoCORS) { 184 if (r->request()->mode() == WebURLRequest::FetchRequestModeNoCORS) {
168 // "1. If |r|'s request's method is not a simple method, throw a 185 // "1. If |r|'s request's method is not a simple method, throw a
169 // TypeError." 186 // TypeError."
170 if (!FetchUtils::isSimpleMethod(r->request()->method())) { 187 if (!FetchUtils::isSimpleMethod(r->request()->method())) {
171 exceptionState.throwTypeError("'" + r->request()->method() + "' is u nsupported in no-cors mode."); 188 exceptionState.throwTypeError("'" + r->request()->method() + "' is u nsupported in no-cors mode.");
172 return 0; 189 return nullptr;
173 } 190 }
174 // "Set |r|'s Headers object's guard to |request-no-CORS|. 191 // "Set |r|'s Headers object's guard to |request-no-CORS|.
175 r->headers()->setGuard(Headers::RequestNoCORSGuard); 192 r->headers()->setGuard(Headers::RequestNoCORSGuard);
176 } 193 }
177 // "20. Fill |r|'s Headers object with |headers|. Rethrow any exceptions." 194 // "26. Fill |r|'s Headers object with |headers|. Rethrow any exceptions."
178 if (init.headers) { 195 if (init.headers) {
179 ASSERT(init.headersDictionary.isUndefinedOrNull()); 196 ASSERT(init.headersDictionary.isUndefinedOrNull());
180 r->headers()->fillWith(init.headers.get(), exceptionState); 197 r->headers()->fillWith(init.headers.get(), exceptionState);
181 } else if (!init.headersDictionary.isUndefinedOrNull()) { 198 } else if (!init.headersDictionary.isUndefinedOrNull()) {
182 r->headers()->fillWith(init.headersDictionary, exceptionState); 199 r->headers()->fillWith(init.headersDictionary, exceptionState);
183 } else { 200 } else {
184 ASSERT(headers); 201 ASSERT(headers);
185 r->headers()->fillWith(headers, exceptionState); 202 r->headers()->fillWith(headers, exceptionState);
186 } 203 }
187 if (exceptionState.hadException()) 204 if (exceptionState.hadException())
188 return 0; 205 return nullptr;
189 206
190 // "21. If |init|'s body member is present, run these substeps:" 207 // "27. If either |init|'s body member is present or |temporaryBody| is
208 // non-null, and |request|'s method is `GET` or `HEAD`, throw a TypeError.
209 if (init.bodyBlobHandle || temporaryBody) {
210 if (request->method() == "GET" || request->method() == "HEAD") {
211 exceptionState.throwTypeError("Request with GET/HEAD method cannot h ave body.");
212 return nullptr;
213 }
214 }
215
216 // "28. If |init|'s body member is present, run these substeps:"
191 if (init.bodyBlobHandle) { 217 if (init.bodyBlobHandle) {
192 // "1. If request's method is `GET` or `HEAD`, throw a TypeError." 218 // "1. Let |stream| and |Content-Type| be the result of extracting
193 // "2. Let |stream| and |Content-Type| be the result of extracting
194 // |init|'s body member." 219 // |init|'s body member."
195 // "3. Set |r|'s request's body to |stream|." 220 // "2. Set |temporaryBody| to |stream|.
196 // "4. If |Content-Type| is non-null and |r|'s request's header list 221 // "3. If |Content-Type| is non-null and |r|'s request's header list
197 // contains no header named `Content-Type`, append 222 // contains no header named `Content-Type`, append
198 // `Content-Type`/|Content-Type| to |r|'s Headers object. Rethrow any 223 // `Content-Type`/|Content-Type| to |r|'s Headers object. Rethrow any
199 // exception." 224 // exception."
200 if (request->method() == "GET" || request->method() == "HEAD") { 225 temporaryBody = init.bodyBlobHandle;
201 exceptionState.throwTypeError("Request with GET/HEAD method cannot h ave body.");
202 return 0;
203 }
204 r->setBodyBlobHandle(init.bodyBlobHandle);
205 if (!init.bodyBlobHandle->type().isEmpty() && !r->headers()->has("Conten t-Type", exceptionState)) { 226 if (!init.bodyBlobHandle->type().isEmpty() && !r->headers()->has("Conten t-Type", exceptionState)) {
206 r->headers()->append("Content-Type", init.bodyBlobHandle->type(), ex ceptionState); 227 r->headers()->append("Content-Type", init.bodyBlobHandle->type(), ex ceptionState);
207 } 228 }
208 if (exceptionState.hadException()) 229 if (exceptionState.hadException())
209 return 0; 230 return nullptr;
210 } 231 }
211 // "22. Set |r|'s MIME type to the result of extracting a MIME type from 232
233 // "29. Set |r|'s body to |temporaryBody|.
234 r->setBodyBlobHandle(temporaryBody.release());
235
236 // "30. Set |r|'s MIME type to the result of extracting a MIME type from
212 // |r|'s request's header list." 237 // |r|'s request's header list."
213 r->m_request->setMIMEType(r->m_request->headerList()->extractMIMEType()); 238 r->m_request->setMIMEType(r->m_request->headerList()->extractMIMEType());
214 239
215 // "23. Return |r|." 240 // "31. If |input| is a Request object and |input|'s body is non-null, run
241 // these substeps:"
242 if (inputRequest && inputRequest->hasBody()) {
243 // "1. Set |input|'s body to null."
244 inputRequest->setBodyBlobHandle(nullptr);
245 // "2. Set |input|'s used flag."
246 inputRequest->lockBody(PassBody);
247 }
248
249 // "32. Return |r|."
216 return r; 250 return r;
217 } 251 }
218 252
219 Request* Request::create(ExecutionContext* context, const RequestInfo& input, co nst Dictionary& init, ExceptionState& exceptionState) 253 Request* Request::create(ExecutionContext* context, const RequestInfo& input, co nst Dictionary& init, ExceptionState& exceptionState)
220 { 254 {
221 ASSERT(!input.isNull()); 255 ASSERT(!input.isNull());
222 if (input.isUSVString()) 256 if (input.isUSVString())
223 return create(context, input.getAsUSVString(), init, exceptionState); 257 return create(context, input.getAsUSVString(), init, exceptionState);
224 return create(context, input.getAsRequest(), init, exceptionState); 258 return create(context, input.getAsRequest(), init, exceptionState);
225 } 259 }
226 260
227 Request* Request::create(ExecutionContext* context, const String& input, Excepti onState& exceptionState) 261 Request* Request::create(ExecutionContext* context, const String& input, Excepti onState& exceptionState)
228 { 262 {
229 return create(context, input, Dictionary(), exceptionState); 263 return create(context, input, Dictionary(), exceptionState);
230 } 264 }
231 265
232 Request* Request::create(ExecutionContext* context, const String& input, const D ictionary& init, ExceptionState& exceptionState) 266 Request* Request::create(ExecutionContext* context, const String& input, const D ictionary& init, ExceptionState& exceptionState)
233 { 267 {
234 return createRequestWithRequestOrString(context, 0, input, RequestInit(conte xt, init, exceptionState), exceptionState); 268 return createRequestWithRequestOrString(context, nullptr, input, RequestInit (context, init, exceptionState), exceptionState);
235 } 269 }
236 270
237 Request* Request::create(ExecutionContext* context, Request* input, ExceptionSta te& exceptionState) 271 Request* Request::create(ExecutionContext* context, Request* input, ExceptionSta te& exceptionState)
238 { 272 {
239 return create(context, input, Dictionary(), exceptionState); 273 return create(context, input, Dictionary(), exceptionState);
240 } 274 }
241 275
242 Request* Request::create(ExecutionContext* context, Request* input, const Dictio nary& init, ExceptionState& exceptionState) 276 Request* Request::create(ExecutionContext* context, Request* input, const Dictio nary& init, ExceptionState& exceptionState)
243 { 277 {
244 return createRequestWithRequestOrString(context, input, String(), RequestIni t(context, init, exceptionState), exceptionState); 278 return createRequestWithRequestOrString(context, input, String(), RequestIni t(context, init, exceptionState), exceptionState);
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
494 } 528 }
495 529
496 DEFINE_TRACE(Request) 530 DEFINE_TRACE(Request)
497 { 531 {
498 Body::trace(visitor); 532 Body::trace(visitor);
499 visitor->trace(m_request); 533 visitor->trace(m_request);
500 visitor->trace(m_headers); 534 visitor->trace(m_headers);
501 } 535 }
502 536
503 } // namespace blink 537 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698