Chromium Code Reviews| 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) |
| 386 : Body(context) | 386 : Response(context, FetchResponseData::create()) |
| 387 , m_response(FetchResponseData::create()) | |
| 388 , m_headers(Headers::create(m_response->headerList())) | |
| 389 { | 387 { |
| 390 m_headers->setGuard(Headers::ResponseGuard); | 388 m_headers->setGuard(Headers::ResponseGuard); |
|
tyoshino (SeeGerritForStatus)
2016/04/21 07:46:24
ditto
yhirano
2016/04/21 08:14:22
Done.
| |
| 391 } | 389 } |
| 392 | 390 |
| 393 Response::Response(ExecutionContext* context, FetchResponseData* response) | 391 Response::Response(ExecutionContext* context, FetchResponseData* response) |
| 394 : Body(context) | 392 : Response(context, response, Headers::create(response->headerList())) |
| 395 , m_response(response) | |
| 396 , m_headers(Headers::create(m_response->headerList())) | |
| 397 { | 393 { |
| 398 m_headers->setGuard(Headers::ResponseGuard); | 394 m_headers->setGuard(Headers::ResponseGuard); |
| 399 } | 395 } |
| 400 | 396 |
| 401 Response::Response(ExecutionContext* context, FetchResponseData* response, Heade rs* headers) | 397 Response::Response(ExecutionContext* context, FetchResponseData* response, Heade rs* headers) |
| 402 : Body(context) , m_response(response) , m_headers(headers) {} | 398 : Body(context) |
| 399 , m_response(response) | |
| 400 , m_headers(headers) | |
| 401 { | |
| 402 } | |
| 403 | 403 |
| 404 bool Response::hasBody() const | 404 bool Response::hasBody() const |
| 405 { | 405 { |
| 406 return m_response->internalBuffer(); | 406 return m_response->internalBuffer(); |
| 407 } | 407 } |
| 408 | 408 |
| 409 bool Response::bodyUsed() | 409 bool Response::bodyUsed() |
| 410 { | 410 { |
| 411 return internalBodyBuffer() && internalBodyBuffer()->isStreamDisturbed(); | 411 return internalBodyBuffer() && internalBodyBuffer()->isStreamDisturbed(); |
| 412 } | 412 } |
| 413 | 413 |
| 414 String Response::mimeType() const | 414 String Response::mimeType() const |
| 415 { | 415 { |
| 416 return m_response->mimeType(); | 416 return m_response->mimeType(); |
| 417 } | 417 } |
| 418 | 418 |
| 419 String Response::internalMIMEType() const | 419 String Response::internalMIMEType() const |
| 420 { | 420 { |
| 421 return m_response->internalMIMEType(); | 421 return m_response->internalMIMEType(); |
| 422 } | 422 } |
| 423 | 423 |
| 424 DEFINE_TRACE(Response) | 424 DEFINE_TRACE(Response) |
| 425 { | 425 { |
| 426 Body::trace(visitor); | 426 Body::trace(visitor); |
| 427 visitor->trace(m_response); | 427 visitor->trace(m_response); |
| 428 visitor->trace(m_headers); | 428 visitor->trace(m_headers); |
| 429 } | 429 } |
| 430 | 430 |
| 431 } // namespace blink | 431 } // namespace blink |
| OLD | NEW |