OLD | NEW |
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 "modules/fetch/Response.h" | 5 #include "modules/fetch/Response.h" |
6 | 6 |
7 #include "bindings/core/v8/Dictionary.h" | 7 #include "bindings/core/v8/Dictionary.h" |
8 #include "bindings/core/v8/ExceptionState.h" | 8 #include "bindings/core/v8/ExceptionState.h" |
9 #include "bindings/core/v8/ScriptState.h" | 9 #include "bindings/core/v8/ScriptState.h" |
10 #include "bindings/core/v8/V8ArrayBuffer.h" | 10 #include "bindings/core/v8/V8ArrayBuffer.h" |
(...skipping 16 matching lines...) Expand all Loading... |
27 #include "platform/RuntimeEnabledFeatures.h" | 27 #include "platform/RuntimeEnabledFeatures.h" |
28 #include "platform/network/EncodedFormData.h" | 28 #include "platform/network/EncodedFormData.h" |
29 #include "platform/network/HTTPHeaderMap.h" | 29 #include "platform/network/HTTPHeaderMap.h" |
30 #include "public/platform/modules/serviceworker/WebServiceWorkerResponse.h" | 30 #include "public/platform/modules/serviceworker/WebServiceWorkerResponse.h" |
31 #include "wtf/RefPtr.h" | 31 #include "wtf/RefPtr.h" |
32 | 32 |
33 namespace blink { | 33 namespace blink { |
34 | 34 |
35 namespace { | 35 namespace { |
36 | 36 |
37 FetchResponseData* createFetchResponseDataFromWebResponse(ExecutionContext* exec
utionContext, const WebServiceWorkerResponse& webResponse) | 37 FetchResponseData* createFetchResponseDataFromWebResponse(ScriptState* scriptSta
te, const WebServiceWorkerResponse& webResponse) |
38 { | 38 { |
39 FetchResponseData* response = nullptr; | 39 FetchResponseData* response = nullptr; |
40 if (webResponse.status() > 0) | 40 if (webResponse.status() > 0) |
41 response = FetchResponseData::create(); | 41 response = FetchResponseData::create(); |
42 else | 42 else |
43 response = FetchResponseData::createNetworkErrorResponse(); | 43 response = FetchResponseData::createNetworkErrorResponse(); |
44 | 44 |
45 response->setURL(webResponse.url()); | 45 response->setURL(webResponse.url()); |
46 response->setStatus(webResponse.status()); | 46 response->setStatus(webResponse.status()); |
47 response->setStatusMessage(webResponse.statusText()); | 47 response->setStatusMessage(webResponse.statusText()); |
48 response->setResponseTime(webResponse.responseTime()); | 48 response->setResponseTime(webResponse.responseTime()); |
49 response->setCacheStorageCacheName(webResponse.cacheStorageCacheName()); | 49 response->setCacheStorageCacheName(webResponse.cacheStorageCacheName()); |
50 | 50 |
51 for (HTTPHeaderMap::const_iterator i = webResponse.headers().begin(), end =
webResponse.headers().end(); i != end; ++i) { | 51 for (HTTPHeaderMap::const_iterator i = webResponse.headers().begin(), end =
webResponse.headers().end(); i != end; ++i) { |
52 response->headerList()->append(i->key, i->value); | 52 response->headerList()->append(i->key, i->value); |
53 } | 53 } |
54 | 54 |
55 response->replaceBodyStreamBuffer(new BodyStreamBuffer(FetchBlobDataConsumer
Handle::create(executionContext, webResponse.blobDataHandle()))); | 55 response->replaceBodyStreamBuffer(new BodyStreamBuffer(scriptState, FetchBlo
bDataConsumerHandle::create(scriptState->getExecutionContext(), webResponse.blob
DataHandle()))); |
56 | 56 |
57 // Filter the response according to |webResponse|'s ResponseType. | 57 // Filter the response according to |webResponse|'s ResponseType. |
58 switch (webResponse.responseType()) { | 58 switch (webResponse.responseType()) { |
59 case WebServiceWorkerResponseTypeBasic: | 59 case WebServiceWorkerResponseTypeBasic: |
60 response = response->createBasicFilteredResponse(); | 60 response = response->createBasicFilteredResponse(); |
61 break; | 61 break; |
62 case WebServiceWorkerResponseTypeCORS: | 62 case WebServiceWorkerResponseTypeCORS: |
63 response = response->createCORSFilteredResponse(); | 63 response = response->createCORSFilteredResponse(); |
64 break; | 64 break; |
65 case WebServiceWorkerResponseTypeOpaque: | 65 case WebServiceWorkerResponseTypeOpaque: |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 || (0x80 <= c && c <= 0xFF))) // obs-text | 102 || (0x80 <= c && c <= 0xFF))) // obs-text |
103 return false; | 103 return false; |
104 } | 104 } |
105 return true; | 105 return true; |
106 } | 106 } |
107 | 107 |
108 } // namespace | 108 } // namespace |
109 | 109 |
110 Response* Response::create(ScriptState* scriptState, ExceptionState& exceptionSt
ate) | 110 Response* Response::create(ScriptState* scriptState, ExceptionState& exceptionSt
ate) |
111 { | 111 { |
112 return create(scriptState->getExecutionContext(), nullptr, String(), Respons
eInit(), exceptionState); | 112 return create(scriptState, nullptr, String(), ResponseInit(), exceptionState
); |
113 } | 113 } |
114 | 114 |
115 Response* Response::create(ScriptState* scriptState, ScriptValue bodyValue, cons
t Dictionary& init, ExceptionState& exceptionState) | 115 Response* Response::create(ScriptState* scriptState, ScriptValue bodyValue, cons
t Dictionary& init, ExceptionState& exceptionState) |
116 { | 116 { |
117 v8::Local<v8::Value> body = bodyValue.v8Value(); | 117 v8::Local<v8::Value> body = bodyValue.v8Value(); |
118 ScriptValue reader; | 118 ScriptValue reader; |
119 v8::Isolate* isolate = scriptState->isolate(); | 119 v8::Isolate* isolate = scriptState->isolate(); |
120 ExecutionContext* executionContext = scriptState->getExecutionContext(); | 120 ExecutionContext* executionContext = scriptState->getExecutionContext(); |
121 | 121 |
122 OwnPtr<FetchDataConsumerHandle> bodyHandle; | 122 OwnPtr<FetchDataConsumerHandle> bodyHandle; |
(...skipping 26 matching lines...) Expand all Loading... |
149 bodyHandle = ReadableStreamDataConsumerHandle::create(scriptState, r
eader); | 149 bodyHandle = ReadableStreamDataConsumerHandle::create(scriptState, r
eader); |
150 } | 150 } |
151 } else { | 151 } else { |
152 String string = toUSVString(isolate, body, exceptionState); | 152 String string = toUSVString(isolate, body, exceptionState); |
153 if (exceptionState.hadException()) | 153 if (exceptionState.hadException()) |
154 return nullptr; | 154 return nullptr; |
155 bodyHandle = FetchFormDataConsumerHandle::create(string); | 155 bodyHandle = FetchFormDataConsumerHandle::create(string); |
156 contentType = "text/plain;charset=UTF-8"; | 156 contentType = "text/plain;charset=UTF-8"; |
157 } | 157 } |
158 // TODO(yhirano): Add the URLSearchParams case. | 158 // TODO(yhirano): Add the URLSearchParams case. |
159 Response* response = create(executionContext, bodyHandle.release(), contentT
ype, ResponseInit(init, exceptionState), exceptionState); | 159 Response* response = create(scriptState, bodyHandle.release(), contentType,
ResponseInit(init, exceptionState), exceptionState); |
160 if (!exceptionState.hadException() && !reader.isEmpty()) { | 160 if (!exceptionState.hadException() && !reader.isEmpty()) { |
161 // Add a hidden reference so that the weak persistent in the | 161 // Add a hidden reference so that the weak persistent in the |
162 // ReadableStreamDataConsumerHandle will be valid as long as the | 162 // ReadableStreamDataConsumerHandle will be valid as long as the |
163 // Response is valid. | 163 // Response is valid. |
164 v8::Local<v8::Value> wrapper = toV8(response, scriptState); | 164 v8::Local<v8::Value> wrapper = toV8(response, scriptState); |
165 if (wrapper.IsEmpty()) { | 165 if (wrapper.IsEmpty()) { |
166 exceptionState.throwTypeError("Cannot create a Response wrapper"); | 166 exceptionState.throwTypeError("Cannot create a Response wrapper"); |
167 return nullptr; | 167 return nullptr; |
168 } | 168 } |
169 ASSERT(wrapper->IsObject()); | 169 ASSERT(wrapper->IsObject()); |
170 V8HiddenValue::setHiddenValue(scriptState, wrapper.As<v8::Object>(), V8H
iddenValue::readableStreamReaderInResponse(scriptState->isolate()), reader.v8Val
ue()); | 170 V8HiddenValue::setHiddenValue(scriptState, wrapper.As<v8::Object>(), V8H
iddenValue::readableStreamReaderInResponse(scriptState->isolate()), reader.v8Val
ue()); |
171 } | 171 } |
172 return response; | 172 return response; |
173 } | 173 } |
174 | 174 |
175 Response* Response::create(ExecutionContext* context, PassOwnPtr<FetchDataConsum
erHandle> bodyHandle, const String& contentType, const ResponseInit& init, Excep
tionState& exceptionState) | 175 Response* Response::create(ScriptState* scriptState, PassOwnPtr<FetchDataConsume
rHandle> bodyHandle, const String& contentType, const ResponseInit& init, Except
ionState& exceptionState) |
176 { | 176 { |
177 unsigned short status = init.status; | 177 unsigned short status = init.status; |
178 | 178 |
179 // "1. If |init|'s status member is not in the range 200 to 599, inclusive,
throw a | 179 // "1. If |init|'s status member is not in the range 200 to 599, inclusive,
throw a |
180 // RangeError." | 180 // RangeError." |
181 if (status < 200 || 599 < status) { | 181 if (status < 200 || 599 < status) { |
182 exceptionState.throwRangeError(ExceptionMessages::indexOutsideRange<unsi
gned>("status", status, 200, ExceptionMessages::InclusiveBound, 599, ExceptionMe
ssages::InclusiveBound)); | 182 exceptionState.throwRangeError(ExceptionMessages::indexOutsideRange<unsi
gned>("status", status, 200, ExceptionMessages::InclusiveBound, 599, ExceptionMe
ssages::InclusiveBound)); |
183 return nullptr; | 183 return nullptr; |
184 } | 184 } |
185 | 185 |
186 // "2. If |init|'s statusText member does not match the Reason-Phrase | 186 // "2. If |init|'s statusText member does not match the Reason-Phrase |
187 // token production, throw a TypeError." | 187 // token production, throw a TypeError." |
188 if (!isValidReasonPhrase(init.statusText)) { | 188 if (!isValidReasonPhrase(init.statusText)) { |
189 exceptionState.throwTypeError("Invalid statusText"); | 189 exceptionState.throwTypeError("Invalid statusText"); |
190 return nullptr; | 190 return nullptr; |
191 } | 191 } |
192 | 192 |
193 // "3. Let |r| be a new Response object, associated with a new response, | 193 // "3. Let |r| be a new Response object, associated with a new response, |
194 // Headers object, and Body object." | 194 // Headers object, and Body object." |
195 Response* r = new Response(context); | 195 Response* r = new Response(scriptState->getExecutionContext()); |
196 | 196 |
197 // "4. Set |r|'s response's status to |init|'s status member." | 197 // "4. Set |r|'s response's status to |init|'s status member." |
198 r->m_response->setStatus(init.status); | 198 r->m_response->setStatus(init.status); |
199 | 199 |
200 // "5. Set |r|'s response's status message to |init|'s statusText member." | 200 // "5. Set |r|'s response's status message to |init|'s statusText member." |
201 r->m_response->setStatusMessage(AtomicString(init.statusText)); | 201 r->m_response->setStatusMessage(AtomicString(init.statusText)); |
202 | 202 |
203 // "6. If |init|'s headers member is present, run these substeps:" | 203 // "6. If |init|'s headers member is present, run these substeps:" |
204 if (init.headers) { | 204 if (init.headers) { |
205 // "1. Empty |r|'s response's header list." | 205 // "1. Empty |r|'s response's header list." |
(...skipping 23 matching lines...) Expand all Loading... |
229 // contains no header named `Content-Type`, append `Content-Type`/ | 229 // contains no header named `Content-Type`, append `Content-Type`/ |
230 // |Content-Type| to |r|'s response's header list." | 230 // |Content-Type| to |r|'s response's header list." |
231 // https://fetch.spec.whatwg.org/#concept-bodyinit-extract | 231 // https://fetch.spec.whatwg.org/#concept-bodyinit-extract |
232 // Step 3, Blob: | 232 // Step 3, Blob: |
233 // "If object's type attribute is not the empty byte sequence, set | 233 // "If object's type attribute is not the empty byte sequence, set |
234 // Content-Type to its value." | 234 // Content-Type to its value." |
235 if (isNullBodyStatus(status)) { | 235 if (isNullBodyStatus(status)) { |
236 exceptionState.throwTypeError("Response with null body status cannot
have body"); | 236 exceptionState.throwTypeError("Response with null body status cannot
have body"); |
237 return nullptr; | 237 return nullptr; |
238 } | 238 } |
239 r->m_response->replaceBodyStreamBuffer(new BodyStreamBuffer(bodyHandle))
; | 239 r->m_response->replaceBodyStreamBuffer(new BodyStreamBuffer(scriptState,
bodyHandle)); |
240 if (!contentType.isEmpty() && !r->m_response->headerList()->has("Content
-Type")) | 240 if (!contentType.isEmpty() && !r->m_response->headerList()->has("Content
-Type")) |
241 r->m_response->headerList()->append("Content-Type", contentType); | 241 r->m_response->headerList()->append("Content-Type", contentType); |
242 } | 242 } |
243 | 243 |
244 // "8. Set |r|'s MIME type to the result of extracting a MIME type | 244 // "8. Set |r|'s MIME type to the result of extracting a MIME type |
245 // from |r|'s response's header list." | 245 // from |r|'s response's header list." |
246 r->m_response->setMIMEType(r->m_response->headerList()->extractMIMEType()); | 246 r->m_response->setMIMEType(r->m_response->headerList()->extractMIMEType()); |
247 | 247 |
248 // "9. Return |r|." | 248 // "9. Return |r|." |
249 return r; | 249 return r; |
250 } | 250 } |
251 | 251 |
252 Response* Response::create(ExecutionContext* context, FetchResponseData* respons
e) | 252 Response* Response::create(ExecutionContext* context, FetchResponseData* respons
e) |
253 { | 253 { |
254 return new Response(context, response); | 254 return new Response(context, response); |
255 } | 255 } |
256 | 256 |
257 Response* Response::create(ExecutionContext* context, const WebServiceWorkerResp
onse& webResponse) | 257 Response* Response::create(ScriptState* scriptState, const WebServiceWorkerRespo
nse& webResponse) |
258 { | 258 { |
259 FetchResponseData* responseData = createFetchResponseDataFromWebResponse(con
text, webResponse); | 259 FetchResponseData* responseData = createFetchResponseDataFromWebResponse(scr
iptState, webResponse); |
260 return new Response(context, responseData); | 260 return new Response(scriptState->getExecutionContext(), responseData); |
261 } | 261 } |
262 | 262 |
263 Response* Response::error(ExecutionContext* context) | 263 Response* Response::error(ExecutionContext* context) |
264 { | 264 { |
265 FetchResponseData* responseData = FetchResponseData::createNetworkErrorRespo
nse(); | 265 FetchResponseData* responseData = FetchResponseData::createNetworkErrorRespo
nse(); |
266 Response* r = new Response(context, responseData); | 266 Response* r = new Response(context, responseData); |
267 r->m_headers->setGuard(Headers::ImmutableGuard); | 267 r->m_headers->setGuard(Headers::ImmutableGuard); |
268 return r; | 268 return r; |
269 } | 269 } |
270 | 270 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 // "The statusText attribute's getter must return response's status message.
" | 340 // "The statusText attribute's getter must return response's status message.
" |
341 return m_response->statusMessage(); | 341 return m_response->statusMessage(); |
342 } | 342 } |
343 | 343 |
344 Headers* Response::headers() const | 344 Headers* Response::headers() const |
345 { | 345 { |
346 // "The headers attribute's getter must return the associated Headers object
." | 346 // "The headers attribute's getter must return the associated Headers object
." |
347 return m_headers; | 347 return m_headers; |
348 } | 348 } |
349 | 349 |
350 Response* Response::clone(ExceptionState& exceptionState) | 350 Response* Response::clone(ScriptState* scriptState, ExceptionState& exceptionSta
te) |
351 { | 351 { |
352 if (isBodyLocked() || bodyUsed()) { | 352 if (isBodyLocked() || bodyUsed()) { |
353 exceptionState.throwTypeError("Response body is already used"); | 353 exceptionState.throwTypeError("Response body is already used"); |
354 return nullptr; | 354 return nullptr; |
355 } | 355 } |
356 | 356 |
357 FetchResponseData* response = m_response->clone(getExecutionContext()); | 357 FetchResponseData* response = m_response->clone(scriptState); |
358 Headers* headers = Headers::create(response->headerList()); | 358 Headers* headers = Headers::create(response->headerList()); |
359 headers->setGuard(m_headers->getGuard()); | 359 headers->setGuard(m_headers->getGuard()); |
360 return new Response(getExecutionContext(), response, headers); | 360 return new Response(getExecutionContext(), response, headers); |
361 } | 361 } |
362 | 362 |
363 bool Response::hasPendingActivity() const | 363 bool Response::hasPendingActivity() const |
364 { | 364 { |
365 if (!getExecutionContext() || getExecutionContext()->activeDOMObjectsAreStop
ped()) | 365 if (!getExecutionContext() || getExecutionContext()->activeDOMObjectsAreStop
ped()) |
366 return false; | 366 return false; |
367 if (!internalBodyBuffer()) | 367 if (!internalBodyBuffer()) |
368 return false; | 368 return false; |
369 if (internalBodyBuffer()->hasPendingActivity()) | 369 if (internalBodyBuffer()->hasPendingActivity()) |
370 return true; | 370 return true; |
371 return Body::hasPendingActivity(); | 371 return Body::hasPendingActivity(); |
372 } | 372 } |
373 | 373 |
374 void Response::stop() | 374 void Response::stop() |
375 { | 375 { |
376 if (m_response->internalBuffer()) | 376 if (m_response->internalBuffer()) |
377 m_response->internalBuffer()->stop(); | 377 m_response->internalBuffer()->stop(); |
378 } | 378 } |
379 | 379 |
380 void Response::populateWebServiceWorkerResponse(WebServiceWorkerResponse& respon
se) | 380 void Response::populateWebServiceWorkerResponse(WebServiceWorkerResponse& respon
se) |
381 { | 381 { |
382 m_response->populateWebServiceWorkerResponse(response); | 382 m_response->populateWebServiceWorkerResponse(response); |
383 } | 383 } |
384 | 384 |
385 Response::Response(ExecutionContext* context) | 385 Response::Response(ExecutionContext* context) : Response(context, FetchResponseD
ata::create()) {} |
386 : Body(context) | |
387 , m_response(FetchResponseData::create()) | |
388 , m_headers(Headers::create(m_response->headerList())) | |
389 { | |
390 m_headers->setGuard(Headers::ResponseGuard); | |
391 } | |
392 | 386 |
393 Response::Response(ExecutionContext* context, FetchResponseData* response) | 387 Response::Response(ExecutionContext* context, FetchResponseData* response) |
394 : Body(context) | 388 : Response(context, response, Headers::create(response->headerList())) |
395 , m_response(response) | |
396 , m_headers(Headers::create(m_response->headerList())) | |
397 { | 389 { |
398 m_headers->setGuard(Headers::ResponseGuard); | 390 m_headers->setGuard(Headers::ResponseGuard); |
399 } | 391 } |
400 | 392 |
401 Response::Response(ExecutionContext* context, FetchResponseData* response, Heade
rs* headers) | 393 Response::Response(ExecutionContext* context, FetchResponseData* response, Heade
rs* headers) |
402 : Body(context) , m_response(response) , m_headers(headers) {} | 394 : Body(context) |
| 395 , m_response(response) |
| 396 , m_headers(headers) |
| 397 { |
| 398 } |
403 | 399 |
404 bool Response::hasBody() const | 400 bool Response::hasBody() const |
405 { | 401 { |
406 return m_response->internalBuffer(); | 402 return m_response->internalBuffer(); |
407 } | 403 } |
408 | 404 |
409 bool Response::bodyUsed() | 405 bool Response::bodyUsed() |
410 { | 406 { |
411 return internalBodyBuffer() && internalBodyBuffer()->isStreamDisturbed(); | 407 return internalBodyBuffer() && internalBodyBuffer()->isStreamDisturbed(); |
412 } | 408 } |
413 | 409 |
414 String Response::mimeType() const | 410 String Response::mimeType() const |
415 { | 411 { |
416 return m_response->mimeType(); | 412 return m_response->mimeType(); |
417 } | 413 } |
418 | 414 |
419 String Response::internalMIMEType() const | 415 String Response::internalMIMEType() const |
420 { | 416 { |
421 return m_response->internalMIMEType(); | 417 return m_response->internalMIMEType(); |
422 } | 418 } |
423 | 419 |
424 DEFINE_TRACE(Response) | 420 DEFINE_TRACE(Response) |
425 { | 421 { |
426 Body::trace(visitor); | 422 Body::trace(visitor); |
427 visitor->trace(m_response); | 423 visitor->trace(m_response); |
428 visitor->trace(m_headers); | 424 visitor->trace(m_headers); |
429 } | 425 } |
430 | 426 |
431 } // namespace blink | 427 } // namespace blink |
OLD | NEW |