| 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 "config.h" | 5 #include "config.h" | 
| 6 #include "modules/fetch/Response.h" | 6 #include "modules/fetch/Response.h" | 
| 7 | 7 | 
| 8 #include "bindings/core/v8/Dictionary.h" | 8 #include "bindings/core/v8/Dictionary.h" | 
| 9 #include "bindings/core/v8/ExceptionState.h" | 9 #include "bindings/core/v8/ExceptionState.h" | 
| 10 #include "core/dom/DOMArrayBuffer.h" | 10 #include "core/dom/DOMArrayBuffer.h" | 
| 11 #include "core/dom/DOMArrayBufferView.h" | 11 #include "core/dom/DOMArrayBufferView.h" | 
| 12 #include "core/fileapi/Blob.h" | 12 #include "core/fileapi/Blob.h" | 
| 13 #include "core/html/DOMFormData.h" | 13 #include "core/html/DOMFormData.h" | 
| 14 #include "modules/fetch/BodyStreamBuffer.h" | 14 #include "modules/fetch/BodyStreamBuffer.h" | 
| 15 #include "modules/fetch/FetchBlobDataConsumerHandle.h" | 15 #include "modules/fetch/FetchBlobDataConsumerHandle.h" | 
| 16 #include "modules/fetch/ResponseInit.h" | 16 #include "modules/fetch/ResponseInit.h" | 
| 17 #include "platform/network/FormData.h" | 17 #include "platform/network/FormData.h" | 
| 18 #include "platform/network/HTTPHeaderMap.h" | 18 #include "platform/network/HTTPHeaderMap.h" | 
| 19 #include "public/platform/WebServiceWorkerResponse.h" | 19 #include "public/platform/WebServiceWorkerResponse.h" | 
| 20 #include "wtf/RefPtr.h" | 20 #include "wtf/RefPtr.h" | 
| 21 | 21 | 
| 22 namespace blink { | 22 namespace blink { | 
| 23 | 23 | 
| 24 namespace { | 24 namespace { | 
| 25 | 25 | 
| 26 FetchResponseData* createFetchResponseDataFromWebResponse(ExecutionContext* exec
     utionContext, const WebServiceWorkerResponse& webResponse) | 26 FetchResponseData* createFetchResponseDataFromWebResponse(ExecutionContext* exec
     utionContext, const WebServiceWorkerResponse& webResponse) | 
| 27 { | 27 { | 
| 28     FetchResponseData* response = 0; | 28     FetchResponseData* response = nullptr; | 
| 29     if (webResponse.status() > 0) | 29     if (webResponse.status() > 0) | 
| 30         response = FetchResponseData::create(); | 30         response = FetchResponseData::create(); | 
| 31     else | 31     else | 
| 32         response = FetchResponseData::createNetworkErrorResponse(); | 32         response = FetchResponseData::createNetworkErrorResponse(); | 
| 33 | 33 | 
| 34     response->setURL(webResponse.url()); | 34     response->setURL(webResponse.url()); | 
| 35     response->setStatus(webResponse.status()); | 35     response->setStatus(webResponse.status()); | 
| 36     response->setStatusMessage(webResponse.statusText()); | 36     response->setStatusMessage(webResponse.statusText()); | 
| 37 | 37 | 
| 38     for (HTTPHeaderMap::const_iterator i = webResponse.headers().begin(), end = 
     webResponse.headers().end(); i != end; ++i) { | 38     for (HTTPHeaderMap::const_iterator i = webResponse.headers().begin(), end = 
     webResponse.headers().end(); i != end; ++i) { | 
| 39         response->headerList()->append(i->key, i->value); | 39         response->headerList()->append(i->key, i->value); | 
| 40     } | 40     } | 
| 41 | 41 | 
| 42     response->replaceBodyStreamBuffer(BodyStreamBuffer::create(FetchBlobDataCons
     umerHandle::create(executionContext, webResponse.blobDataHandle()))); | 42     response->replaceBodyStreamBuffer(new BodyStreamBuffer(FetchBlobDataConsumer
     Handle::create(executionContext, webResponse.blobDataHandle()))); | 
| 43 | 43 | 
| 44     // Filter the response according to |webResponse|'s ResponseType. | 44     // Filter the response according to |webResponse|'s ResponseType. | 
| 45     switch (webResponse.responseType()) { | 45     switch (webResponse.responseType()) { | 
| 46     case WebServiceWorkerResponseTypeBasic: | 46     case WebServiceWorkerResponseTypeBasic: | 
| 47         response = response->createBasicFilteredResponse(); | 47         response = response->createBasicFilteredResponse(); | 
| 48         break; | 48         break; | 
| 49     case WebServiceWorkerResponseTypeCORS: | 49     case WebServiceWorkerResponseTypeCORS: | 
| 50         response = response->createCORSFilteredResponse(); | 50         response = response->createCORSFilteredResponse(); | 
| 51         break; | 51         break; | 
| 52     case WebServiceWorkerResponseTypeOpaque: | 52     case WebServiceWorkerResponseTypeOpaque: | 
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 163     // "2. If |init|'s statusText member does not match the Reason-Phrase | 163     // "2. If |init|'s statusText member does not match the Reason-Phrase | 
| 164     // token production, throw a TypeError." | 164     // token production, throw a TypeError." | 
| 165     if (!isValidReasonPhrase(responseInit.statusText)) { | 165     if (!isValidReasonPhrase(responseInit.statusText)) { | 
| 166         exceptionState.throwTypeError("Invalid statusText"); | 166         exceptionState.throwTypeError("Invalid statusText"); | 
| 167         return 0; | 167         return 0; | 
| 168     } | 168     } | 
| 169 | 169 | 
| 170     // "3. Let |r| be a new Response object, associated with a new response, | 170     // "3. Let |r| be a new Response object, associated with a new response, | 
| 171     // Headers object, and Body object." | 171     // Headers object, and Body object." | 
| 172     Response* r = new Response(context); | 172     Response* r = new Response(context); | 
| 173     r->suspendIfNeeded(); |  | 
| 174 | 173 | 
| 175     // "4. Set |r|'s response's status to |init|'s status member." | 174     // "4. Set |r|'s response's status to |init|'s status member." | 
| 176     r->m_response->setStatus(responseInit.status); | 175     r->m_response->setStatus(responseInit.status); | 
| 177 | 176 | 
| 178     // "5. Set |r|'s response's status message to |init|'s statusText member." | 177     // "5. Set |r|'s response's status message to |init|'s statusText member." | 
| 179     r->m_response->setStatusMessage(AtomicString(responseInit.statusText)); | 178     r->m_response->setStatusMessage(AtomicString(responseInit.statusText)); | 
| 180 | 179 | 
| 181     // "6. If |init|'s headers member is present, run these substeps:" | 180     // "6. If |init|'s headers member is present, run these substeps:" | 
| 182     if (responseInit.headers) { | 181     if (responseInit.headers) { | 
| 183         // "1. Empty |r|'s response's header list." | 182         // "1. Empty |r|'s response's header list." | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
| 200     if (body) { | 199     if (body) { | 
| 201         // "1. Let |stream| and |Content-Type| be the result of extracting body.
     " | 200         // "1. Let |stream| and |Content-Type| be the result of extracting body.
     " | 
| 202         // "2. Set |r|'s response's body to |stream|." | 201         // "2. Set |r|'s response's body to |stream|." | 
| 203         // "3. If |Content-Type| is non-null and |r|'s response's header list | 202         // "3. If |Content-Type| is non-null and |r|'s response's header list | 
| 204         // contains no header named `Content-Type`, append `Content-Type`/ | 203         // contains no header named `Content-Type`, append `Content-Type`/ | 
| 205         // |Content-Type| to |r|'s response's header list." | 204         // |Content-Type| to |r|'s response's header list." | 
| 206         // https://fetch.spec.whatwg.org/#concept-bodyinit-extract | 205         // https://fetch.spec.whatwg.org/#concept-bodyinit-extract | 
| 207         // Step 3, Blob: | 206         // Step 3, Blob: | 
| 208         // "If object's type attribute is not the empty byte sequence, set | 207         // "If object's type attribute is not the empty byte sequence, set | 
| 209         // Content-Type to its value." | 208         // Content-Type to its value." | 
| 210         r->m_response->replaceBodyStreamBuffer(BodyStreamBuffer::create(FetchBlo
     bDataConsumerHandle::create(context, body->blobDataHandle()))); | 209         r->m_response->replaceBodyStreamBuffer(new BodyStreamBuffer(FetchBlobDat
     aConsumerHandle::create(context, body->blobDataHandle()))); | 
| 211         r->refreshBody(); |  | 
| 212         if (!body->type().isEmpty() && !r->m_response->headerList()->has("Conten
     t-Type")) | 210         if (!body->type().isEmpty() && !r->m_response->headerList()->has("Conten
     t-Type")) | 
| 213             r->m_response->headerList()->append("Content-Type", body->type()); | 211             r->m_response->headerList()->append("Content-Type", body->type()); | 
| 214     } | 212     } | 
| 215 | 213 | 
| 216     // "8. Set |r|'s MIME type to the result of extracting a MIME type | 214     // "8. Set |r|'s MIME type to the result of extracting a MIME type | 
| 217     // from |r|'s response's header list." | 215     // from |r|'s response's header list." | 
| 218     r->m_response->setMIMEType(r->m_response->headerList()->extractMIMEType()); | 216     r->m_response->setMIMEType(r->m_response->headerList()->extractMIMEType()); | 
| 219 | 217 | 
| 220     // "9. Return |r|." | 218     // "9. Return |r|." | 
| 221     return r; | 219     return r; | 
| 222 } | 220 } | 
| 223 | 221 | 
| 224 Response* Response::create(ExecutionContext* context, FetchResponseData* respons
     e) | 222 Response* Response::create(ExecutionContext* context, FetchResponseData* respons
     e) | 
| 225 { | 223 { | 
| 226     Response* r = new Response(context, response); | 224     return new Response(context, response); | 
| 227     r->suspendIfNeeded(); |  | 
| 228     return r; |  | 
| 229 } | 225 } | 
| 230 | 226 | 
| 231 Response* Response::create(ExecutionContext* context, const WebServiceWorkerResp
     onse& webResponse) | 227 Response* Response::create(ExecutionContext* context, const WebServiceWorkerResp
     onse& webResponse) | 
| 232 { | 228 { | 
| 233     FetchResponseData* responseData = createFetchResponseDataFromWebResponse(con
     text, webResponse); | 229     FetchResponseData* responseData = createFetchResponseDataFromWebResponse(con
     text, webResponse); | 
| 234     Response* r = new Response(context, responseData); | 230     return new Response(context, responseData); | 
| 235     r->suspendIfNeeded(); |  | 
| 236     return r; |  | 
| 237 } | 231 } | 
| 238 | 232 | 
| 239 Response* Response::error(ExecutionContext* context) | 233 Response* Response::error(ExecutionContext* context) | 
| 240 { | 234 { | 
| 241     FetchResponseData* responseData = FetchResponseData::createNetworkErrorRespo
     nse(); | 235     FetchResponseData* responseData = FetchResponseData::createNetworkErrorRespo
     nse(); | 
| 242     Response* r = new Response(context, responseData); | 236     Response* r = new Response(context, responseData); | 
| 243     r->m_headers->setGuard(Headers::ImmutableGuard); | 237     r->m_headers->setGuard(Headers::ImmutableGuard); | 
| 244     r->suspendIfNeeded(); |  | 
| 245     return r; | 238     return r; | 
| 246 } | 239 } | 
| 247 | 240 | 
| 248 Response* Response::redirect(ExecutionContext* context, const String& url, unsig
     ned short status, ExceptionState& exceptionState) | 241 Response* Response::redirect(ExecutionContext* context, const String& url, unsig
     ned short status, ExceptionState& exceptionState) | 
| 249 { | 242 { | 
| 250     KURL parsedURL = context->completeURL(url); | 243     KURL parsedURL = context->completeURL(url); | 
| 251     if (!parsedURL.isValid()) { | 244     if (!parsedURL.isValid()) { | 
| 252         exceptionState.throwTypeError("Failed to parse URL from " + url); | 245         exceptionState.throwTypeError("Failed to parse URL from " + url); | 
| 253         return nullptr; | 246         return nullptr; | 
| 254     } | 247     } | 
| 255 | 248 | 
| 256     if (status != 301 && status != 302 && status != 303 && status != 307 && stat
     us != 308) { | 249     if (status != 301 && status != 302 && status != 303 && status != 307 && stat
     us != 308) { | 
| 257         exceptionState.throwRangeError("Invalid status code"); | 250         exceptionState.throwRangeError("Invalid status code"); | 
| 258         return nullptr; | 251         return nullptr; | 
| 259     } | 252     } | 
| 260 | 253 | 
| 261     Response* r = new Response(context); | 254     Response* r = new Response(context); | 
| 262     r->suspendIfNeeded(); |  | 
| 263     r->m_headers->setGuard(Headers::ImmutableGuard); | 255     r->m_headers->setGuard(Headers::ImmutableGuard); | 
| 264     r->m_response->setStatus(status); | 256     r->m_response->setStatus(status); | 
| 265     r->m_response->headerList()->set("Location", parsedURL); | 257     r->m_response->headerList()->set("Location", parsedURL); | 
| 266 | 258 | 
| 267     return r; | 259     return r; | 
| 268 } | 260 } | 
| 269 | 261 | 
| 270 String Response::type() const | 262 String Response::type() const | 
| 271 { | 263 { | 
| 272     // "The type attribute's getter must return response's type." | 264     // "The type attribute's getter must return response's type." | 
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 323     return m_headers; | 315     return m_headers; | 
| 324 } | 316 } | 
| 325 | 317 | 
| 326 Response* Response::clone(ExceptionState& exceptionState) | 318 Response* Response::clone(ExceptionState& exceptionState) | 
| 327 { | 319 { | 
| 328     if (bodyUsed()) { | 320     if (bodyUsed()) { | 
| 329         exceptionState.throwTypeError("Response body is already used"); | 321         exceptionState.throwTypeError("Response body is already used"); | 
| 330         return nullptr; | 322         return nullptr; | 
| 331     } | 323     } | 
| 332 | 324 | 
| 333     if (OwnPtr<DrainingBodyStreamBuffer> buffer = createDrainingStream()) |  | 
| 334         m_response->replaceBodyStreamBuffer(buffer->leakBuffer()); |  | 
| 335 |  | 
| 336     FetchResponseData* response = m_response->clone(executionContext()); | 325     FetchResponseData* response = m_response->clone(executionContext()); | 
| 337     Headers* headers = Headers::create(response->headerList()); | 326     Headers* headers = Headers::create(response->headerList()); | 
| 338     headers->setGuard(m_headers->guard()); | 327     headers->setGuard(m_headers->guard()); | 
| 339     Response* r = new Response(executionContext(), response, headers); | 328     return new Response(executionContext(), response, headers); | 
| 340     r->suspendIfNeeded(); |  | 
| 341 |  | 
| 342     // Lock the old body and set |body| property to the new one. |  | 
| 343     lockBody(); |  | 
| 344     refreshBody(); |  | 
| 345 |  | 
| 346     return r; |  | 
| 347 } | 329 } | 
| 348 | 330 | 
| 349 bool Response::hasPendingActivity() const | 331 bool Response::hasPendingActivity() const | 
| 350 { | 332 { | 
| 351     if (!executionContext() || executionContext()->activeDOMObjectsAreStopped()) | 333     if (!executionContext() || executionContext()->activeDOMObjectsAreStopped()) | 
| 352         return false; | 334         return false; | 
| 353     if (m_isInternalDrained) | 335     if (internalBodyBuffer()->hasPendingActivity()) | 
| 354         return true; | 336         return true; | 
| 355     return Body::hasPendingActivity(); | 337     return Body::hasPendingActivity(); | 
| 356 } | 338 } | 
| 357 | 339 | 
| 358 void Response::populateWebServiceWorkerResponse(WebServiceWorkerResponse& respon
     se) | 340 void Response::populateWebServiceWorkerResponse(WebServiceWorkerResponse& respon
     se) | 
| 359 { | 341 { | 
| 360     m_response->populateWebServiceWorkerResponse(response); | 342     m_response->populateWebServiceWorkerResponse(response); | 
| 361 } | 343 } | 
| 362 | 344 | 
| 363 Response::Response(ExecutionContext* context) | 345 Response::Response(ExecutionContext* context) | 
| 364     : Body(context) | 346     : Body(context) | 
| 365     , m_response(FetchResponseData::create()) | 347     , m_response(FetchResponseData::create()) | 
| 366     , m_headers(Headers::create(m_response->headerList())) | 348     , m_headers(Headers::create(m_response->headerList())) | 
| 367     , m_isInternalDrained(false) |  | 
| 368 { | 349 { | 
| 369     m_headers->setGuard(Headers::ResponseGuard); | 350     m_headers->setGuard(Headers::ResponseGuard); | 
| 370 } | 351 } | 
| 371 | 352 | 
| 372 Response::Response(ExecutionContext* context, FetchResponseData* response) | 353 Response::Response(ExecutionContext* context, FetchResponseData* response) | 
| 373     : Body(context) | 354     : Body(context) | 
| 374     , m_response(response) | 355     , m_response(response) | 
| 375     , m_headers(Headers::create(m_response->headerList())) | 356     , m_headers(Headers::create(m_response->headerList())) | 
| 376     , m_isInternalDrained(false) |  | 
| 377 { | 357 { | 
| 378     m_headers->setGuard(Headers::ResponseGuard); | 358     m_headers->setGuard(Headers::ResponseGuard); | 
| 379 |  | 
| 380     refreshBody(); |  | 
| 381 } | 359 } | 
| 382 | 360 | 
| 383 Response::Response(ExecutionContext* context, FetchResponseData* response, Heade
     rs* headers) | 361 Response::Response(ExecutionContext* context, FetchResponseData* response, Heade
     rs* headers) | 
| 384     : Body(context) , m_response(response) , m_headers(headers), m_isInternalDra
     ined(false) | 362     : Body(context) , m_response(response) , m_headers(headers) {} | 
| 385 { |  | 
| 386     refreshBody(); |  | 
| 387 } |  | 
| 388 | 363 | 
| 389 bool Response::hasBody() const | 364 bool Response::hasBody() const | 
| 390 { | 365 { | 
| 391     return m_response->internalBuffer(); | 366     return m_response->internalBuffer()->hasBody(); | 
| 392 } |  | 
| 393 |  | 
| 394 void* Response::bufferForTest() const |  | 
| 395 { |  | 
| 396     return m_response->buffer(); |  | 
| 397 } | 367 } | 
| 398 | 368 | 
| 399 String Response::mimeType() const | 369 String Response::mimeType() const | 
| 400 { | 370 { | 
| 401     return m_response->mimeType(); | 371     return m_response->mimeType(); | 
| 402 } | 372 } | 
| 403 | 373 | 
| 404 void* Response::internalBufferForTest() const |  | 
| 405 { |  | 
| 406     return m_response->internalBuffer(); |  | 
| 407 } |  | 
| 408 |  | 
| 409 String Response::internalMIMEType() const | 374 String Response::internalMIMEType() const | 
| 410 { | 375 { | 
| 411     return m_response->internalMIMEType(); | 376     return m_response->internalMIMEType(); | 
| 412 } | 377 } | 
| 413 | 378 | 
| 414 PassOwnPtr<DrainingBodyStreamBuffer> Response::createInternalDrainingStream() |  | 
| 415 { |  | 
| 416     if (BodyStreamBuffer* buffer = m_response->internalBuffer()) { |  | 
| 417         if (buffer == m_response->buffer()) |  | 
| 418             return createDrainingStream(); |  | 
| 419         m_isInternalDrained = true; |  | 
| 420         return DrainingBodyStreamBuffer::create(buffer, this); |  | 
| 421     } |  | 
| 422     return nullptr; |  | 
| 423 } |  | 
| 424 |  | 
| 425 void Response::didFetchDataLoadFinishedFromDrainingStream() |  | 
| 426 { |  | 
| 427     ASSERT(m_isInternalDrained); |  | 
| 428     m_isInternalDrained = false; |  | 
| 429 } |  | 
| 430 |  | 
| 431 void Response::refreshBody() |  | 
| 432 { |  | 
| 433     setBody(m_response->buffer()); |  | 
| 434 } |  | 
| 435 |  | 
| 436 DEFINE_TRACE(Response) | 379 DEFINE_TRACE(Response) | 
| 437 { | 380 { | 
| 438     Body::trace(visitor); | 381     Body::trace(visitor); | 
| 439     visitor->trace(m_response); | 382     visitor->trace(m_response); | 
| 440     visitor->trace(m_headers); | 383     visitor->trace(m_headers); | 
| 441 } | 384 } | 
| 442 | 385 | 
| 443 } // namespace blink | 386 } // namespace blink | 
| OLD | NEW | 
|---|