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

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

Issue 1192913007: Change BodyStreamBuffer to be FetchDataConsumerHandle-based and enable backpressure in Fetch API (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: (temp) alternative to calling didGetReadable in sync. Created 5 years, 5 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"
11 #include "core/fetch/FetchUtils.h" 11 #include "core/fetch/FetchUtils.h"
12 #include "core/fetch/ResourceLoaderOptions.h" 12 #include "core/fetch/ResourceLoaderOptions.h"
13 #include "core/loader/ThreadableLoader.h" 13 #include "core/loader/ThreadableLoader.h"
14 #include "modules/fetch/BodyStreamBuffer.h"
15 #include "modules/fetch/FetchBlobDataConsumerHandle.h"
14 #include "modules/fetch/FetchManager.h" 16 #include "modules/fetch/FetchManager.h"
15 #include "modules/fetch/RequestInit.h" 17 #include "modules/fetch/RequestInit.h"
16 #include "platform/network/HTTPParsers.h" 18 #include "platform/network/HTTPParsers.h"
17 #include "platform/network/ResourceRequest.h" 19 #include "platform/network/ResourceRequest.h"
18 #include "platform/weborigin/Referrer.h" 20 #include "platform/weborigin/Referrer.h"
19 #include "public/platform/WebServiceWorkerRequest.h" 21 #include "public/platform/WebServiceWorkerRequest.h"
20 #include "public/platform/WebURLRequest.h" 22 #include "public/platform/WebURLRequest.h"
21 23
22 namespace blink { 24 namespace blink {
23 25
(...skipping 16 matching lines...) Expand all
40 request->setMode(original->mode()); 42 request->setMode(original->mode());
41 request->setCredentials(original->credentials()); 43 request->setCredentials(original->credentials());
42 // FIXME: Set cache mode. 44 // FIXME: Set cache mode.
43 // TODO(yhirano): Set redirect mode. 45 // TODO(yhirano): Set redirect mode.
44 return request; 46 return request;
45 } 47 }
46 48
47 Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Req uest* inputRequest, const String& inputString, const RequestInit& init, Exceptio nState& exceptionState) 49 Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Req uest* inputRequest, const String& inputString, const RequestInit& init, Exceptio nState& exceptionState)
48 { 50 {
49 // "1. Let |temporaryBody| be null." 51 // "1. Let |temporaryBody| be null."
50 RefPtr<BlobDataHandle> temporaryBody; 52 OwnPtr<DrainingBodyStreamBuffer> temporaryBody = nullptr;
51 53
52 if (inputRequest) { 54 if (inputRequest) {
53 // We check bodyUsed even when the body is null in spite of the 55 // We check bodyUsed even when the body is null in spite of the
54 // spec. See https://github.com/whatwg/fetch/issues/61 for details. 56 // spec. See https://github.com/whatwg/fetch/issues/61 for details.
55 if (inputRequest->bodyUsed()) { 57 if (inputRequest->bodyUsed()) {
56 exceptionState.throwTypeError("Cannot construct a Request with a Req uest object that has already been used."); 58 exceptionState.throwTypeError("Cannot construct a Request with a Req uest object that has already been used.");
57 return nullptr; 59 return nullptr;
58 } 60 }
59 } 61 }
60 62
61 // "2. If |input| is a Request object and |input|'s body is non-null, run 63 // "2. If |input| is a Request object and |input|'s body is non-null, run
62 // these substeps:" 64 // these substeps:"
63 if (inputRequest && inputRequest->hasBody()) { 65 if (inputRequest && inputRequest->hasBody()) {
64 // "1. If |input|'s used flag is set, throw a TypeError." 66 // "1. If |input|'s used flag is set, throw a TypeError."
65 // "2. Set |temporaryBody| to |input|'s body." 67 // "2. Set |temporaryBody| to |input|'s body."
66 if (inputRequest->bodyUsed()) { 68 if (inputRequest->bodyUsed()) {
67 exceptionState.throwTypeError("Cannot construct a Request with a Req uest object that has already been used."); 69 exceptionState.throwTypeError("Cannot construct a Request with a Req uest object that has already been used.");
68 return nullptr; 70 return nullptr;
69 } 71 }
70 if (inputRequest->isBodyConsumed()) { 72 temporaryBody = inputRequest->createDrainingStream();
yhirano 2015/07/03 04:42:28 The spec intends to not mutate |inputRequest|'s bo
hiroshige 2015/07/05 07:30:25 Yes. I modified the code to remove the side effect
71 // Currently the only methods that can consume body data without
72 // setting 'body passed' flag consume entire body (e.g. text()).
73 // Thus we can set an empty blob to the new request instead of
74 // creating a draining stream.
75 // TODO(yhirano): Fix this once Request.body is introduced.
76 OwnPtr<BlobData> blobData = BlobData::create();
77 blobData->setContentType(inputRequest->blobDataHandle()->type());
78 temporaryBody = BlobDataHandle::create(blobData.release(), 0);
79 } else {
80 temporaryBody = inputRequest->m_request->blobDataHandle();
81 }
82 } 73 }
83 74
84 // "3. Let |request| be |input|'s request, if |input| is a Request object, 75 // "3. Let |request| be |input|'s request, if |input| is a Request object,
85 // and a new request otherwise." 76 // and a new request otherwise."
86 // "4. Set |request| to a new request whose url is |request|'s url, method 77 // "4. Set |request| to a new request whose url is |request|'s url, method
87 // is |request|'s method, header list is a copy of |request|'s header list, 78 // is |request|'s method, header list is a copy of |request|'s header list,
88 // unsafe request flag is set, client is entry settings object, origin is 79 // unsafe request flag is set, client is entry settings object, origin is
89 // entry settings object's origin, force Origin header flag is set, 80 // entry settings object's origin, force Origin header flag is set,
90 // same-origin data URL flag is set, context is the empty string, mode is 81 // same-origin data URL flag is set, context is the empty string, mode is
91 // |request|'s mode, credentials mode is |request|'s credentials mode, 82 // |request|'s mode, credentials mode is |request|'s credentials mode,
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 219
229 // "28. If |init|'s body member is present, run these substeps:" 220 // "28. If |init|'s body member is present, run these substeps:"
230 if (init.bodyBlobHandle) { 221 if (init.bodyBlobHandle) {
231 // "1. Let |stream| and |Content-Type| be the result of extracting 222 // "1. Let |stream| and |Content-Type| be the result of extracting
232 // |init|'s body member." 223 // |init|'s body member."
233 // "2. Set |temporaryBody| to |stream|. 224 // "2. Set |temporaryBody| to |stream|.
234 // "3. If |Content-Type| is non-null and |r|'s request's header list 225 // "3. If |Content-Type| is non-null and |r|'s request's header list
235 // contains no header named `Content-Type`, append 226 // contains no header named `Content-Type`, append
236 // `Content-Type`/|Content-Type| to |r|'s Headers object. Rethrow any 227 // `Content-Type`/|Content-Type| to |r|'s Headers object. Rethrow any
237 // exception." 228 // exception."
238 temporaryBody = init.bodyBlobHandle; 229 temporaryBody = DrainingBodyStreamBuffer::create(BodyStreamBuffer::creat e(FetchBlobDataConsumerHandle::create(scriptState->executionContext(), init.body BlobHandle)), nullptr);
239 if (!init.bodyBlobHandle->type().isEmpty() && !r->headers()->has("Conten t-Type", exceptionState)) { 230 if (!init.bodyBlobHandle->type().isEmpty() && !r->headers()->has("Conten t-Type", exceptionState)) {
240 r->headers()->append("Content-Type", init.bodyBlobHandle->type(), ex ceptionState); 231 r->headers()->append("Content-Type", init.bodyBlobHandle->type(), ex ceptionState);
241 } 232 }
242 if (exceptionState.hadException()) 233 if (exceptionState.hadException())
243 return nullptr; 234 return nullptr;
244 } 235 }
245 236
246 // "29. Set |r|'s body to |temporaryBody|. 237 // "29. Set |r|'s body to |temporaryBody|.
247 r->setBodyBlobHandle(temporaryBody.release()); 238 if (temporaryBody)
239 r->setBuffer(temporaryBody->leak());
248 240
249 // "30. Set |r|'s MIME type to the result of extracting a MIME type from 241 // "30. Set |r|'s MIME type to the result of extracting a MIME type from
250 // |r|'s request's header list." 242 // |r|'s request's header list."
251 r->m_request->setMIMEType(r->m_request->headerList()->extractMIMEType()); 243 r->m_request->setMIMEType(r->m_request->headerList()->extractMIMEType());
252 244
253 // "31. If |input| is a Request object and |input|'s body is non-null, run 245 // "31. If |input| is a Request object and |input|'s body is non-null, run
254 // these substeps:" 246 // these substeps:"
255 // We set bodyUsed even when the body is null in spite of the 247 // We set bodyUsed even when the body is null in spite of the
256 // spec. See https://github.com/whatwg/fetch/issues/61 for details. 248 // spec. See https://github.com/whatwg/fetch/issues/61 for details.
257 if (inputRequest) { 249 if (inputRequest) {
258 // "1. Set |input|'s body to null." 250 // "1. Set |input|'s body to null."
259 inputRequest->setBodyBlobHandle(nullptr); 251 inputRequest->setBuffer(nullptr);
260 // "2. Set |input|'s used flag." 252 // "2. Set |input|'s used flag."
261 inputRequest->lockBody(PassBody); 253 inputRequest->lockBody(PassBody);
262 } 254 }
263 255
264 // "32. Return |r|." 256 // "32. Return |r|."
265 return r; 257 return r;
266 } 258 }
267 259
268 Request* Request::create(ScriptState* scriptState, const RequestInfo& input, con st Dictionary& init, ExceptionState& exceptionState) 260 Request* Request::create(ScriptState* scriptState, const RequestInfo& input, con st Dictionary& init, ExceptionState& exceptionState)
269 { 261 {
(...skipping 29 matching lines...) Expand all
299 r->suspendIfNeeded(); 291 r->suspendIfNeeded();
300 return r; 292 return r;
301 } 293 }
302 294
303 Request::Request(ExecutionContext* context, FetchRequestData* request) 295 Request::Request(ExecutionContext* context, FetchRequestData* request)
304 : Body(context) 296 : Body(context)
305 , m_request(request) 297 , m_request(request)
306 , m_headers(Headers::create(m_request->headerList())) 298 , m_headers(Headers::create(m_request->headerList()))
307 { 299 {
308 m_headers->setGuard(Headers::RequestGuard); 300 m_headers->setGuard(Headers::RequestGuard);
301
302 refreshBody();
309 } 303 }
310 304
311 Request::Request(ExecutionContext* context, FetchRequestData* request, Headers* headers) 305 Request::Request(ExecutionContext* context, FetchRequestData* request, Headers* headers)
312 : Body(context) , m_request(request) , m_headers(headers) { } 306 : Body(context) , m_request(request) , m_headers(headers)
307 {
308 refreshBody();
309 }
313 310
314 Request* Request::create(ExecutionContext* context, const WebServiceWorkerReques t& webRequest) 311 Request* Request::create(ExecutionContext* context, const WebServiceWorkerReques t& webRequest)
315 { 312 {
316 Request* r = new Request(context, webRequest); 313 Request* r = new Request(context, webRequest);
317 r->suspendIfNeeded(); 314 r->suspendIfNeeded();
318 return r; 315 return r;
319 } 316 }
320 317
321 Request::Request(ExecutionContext* context, const WebServiceWorkerRequest& webRe quest) 318 Request::Request(ExecutionContext* context, const WebServiceWorkerRequest& webRe quest)
322 : Body(context) 319 : Body(context)
323 , m_request(FetchRequestData::create(webRequest)) 320 , m_request(FetchRequestData::create(context, webRequest))
324 , m_headers(Headers::create(m_request->headerList())) 321 , m_headers(Headers::create(m_request->headerList()))
325 { 322 {
326 m_headers->setGuard(Headers::RequestGuard); 323 m_headers->setGuard(Headers::RequestGuard);
324
325 refreshBody();
327 } 326 }
328 327
329 String Request::method() const 328 String Request::method() const
330 { 329 {
331 // "The method attribute's getter must return request's method." 330 // "The method attribute's getter must return request's method."
332 return m_request->method(); 331 return m_request->method();
333 } 332 }
334 333
335 KURL Request::url() const 334 KURL Request::url() const
336 { 335 {
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
458 return "omit"; 457 return "omit";
459 case WebURLRequest::FetchCredentialsModeSameOrigin: 458 case WebURLRequest::FetchCredentialsModeSameOrigin:
460 return "same-origin"; 459 return "same-origin";
461 case WebURLRequest::FetchCredentialsModeInclude: 460 case WebURLRequest::FetchCredentialsModeInclude:
462 return "include"; 461 return "include";
463 } 462 }
464 ASSERT_NOT_REACHED(); 463 ASSERT_NOT_REACHED();
465 return ""; 464 return "";
466 } 465 }
467 466
468 Request* Request::clone(ExceptionState& exceptionState) const 467 Request* Request::clone(ExceptionState& exceptionState)
469 { 468 {
470 if (bodyUsed()) { 469 if (bodyUsed()) {
471 exceptionState.throwTypeError("Request body is already used"); 470 exceptionState.throwTypeError("Request body is already used");
472 return nullptr; 471 return nullptr;
473 } 472 }
474 473
475 FetchRequestData* request = m_request->clone(); 474 if (OwnPtr<DrainingBodyStreamBuffer> buffer = createDrainingStream())
476 if (blobDataHandle() && isBodyConsumed()) { 475 m_request->setBuffer(buffer->leak());
477 // Currently the only methods that can consume body data without
478 // setting 'body passed' flag consume entire body (e.g. text()). Thus
479 // we can set an empty blob to the new request instead of creating a
480 // draining stream.
481 // TODO(yhirano): Fix this once Request.body is introduced.
482 OwnPtr<BlobData> blobData = BlobData::create();
483 blobData->setContentType(blobDataHandle()->type());
484 request->setBlobDataHandle(BlobDataHandle::create(blobData.release(), 0) );
485 }
486 476
477 FetchRequestData* request = m_request->clone(executionContext());
487 Headers* headers = Headers::create(request->headerList()); 478 Headers* headers = Headers::create(request->headerList());
488 headers->setGuard(m_headers->guard()); 479 headers->setGuard(m_headers->guard());
489 Request* r = new Request(executionContext(), request, headers); 480 Request* r = new Request(executionContext(), request, headers);
490 r->suspendIfNeeded(); 481 r->suspendIfNeeded();
482
483 // Lock the old body and set |body| property to the new one.
484 lockBody();
485 refreshBody();
491 return r; 486 return r;
492 } 487 }
493 488
494 FetchRequestData* Request::passRequestData() 489 FetchRequestData* Request::passRequestData()
495 { 490 {
496 ASSERT(!bodyUsed()); 491 ASSERT(!bodyUsed());
492
493 if (OwnPtr<DrainingBodyStreamBuffer> buffer = createDrainingStream())
494 m_request->setBuffer(buffer->leak());
495
497 lockBody(PassBody); 496 lockBody(PassBody);
498 return m_request->pass(); 497 FetchRequestData* newRequestData = m_request->pass(executionContext());
498 refreshBody();
499 return newRequestData;
499 } 500 }
500 501
501 void Request::populateWebServiceWorkerRequest(WebServiceWorkerRequest& webReques t) const 502 void Request::populateWebServiceWorkerRequest(WebServiceWorkerRequest& webReques t) const
502 { 503 {
503 webRequest.setMethod(method()); 504 webRequest.setMethod(method());
504 webRequest.setRequestContext(m_request->context()); 505 webRequest.setRequestContext(m_request->context());
505 // This strips off the fragment part. 506 // This strips off the fragment part.
506 webRequest.setURL(url()); 507 webRequest.setURL(url());
507 508
508 const FetchHeaderList* headerList = m_headers->headerList(); 509 const FetchHeaderList* headerList = m_headers->headerList();
509 for (size_t i = 0, size = headerList->size(); i < size; ++i) { 510 for (size_t i = 0, size = headerList->size(); i < size; ++i) {
510 const FetchHeaderList::Header& header = headerList->entry(i); 511 const FetchHeaderList::Header& header = headerList->entry(i);
511 webRequest.appendHeader(header.first, header.second); 512 webRequest.appendHeader(header.first, header.second);
512 } 513 }
513 514
514 webRequest.setReferrer(m_request->referrer().referrer().referrer, static_cas t<WebReferrerPolicy>(m_request->referrer().referrer().referrerPolicy)); 515 webRequest.setReferrer(m_request->referrer().referrer().referrer, static_cas t<WebReferrerPolicy>(m_request->referrer().referrer().referrerPolicy));
515 // FIXME: How can we set isReload properly? What is the correct place to loa d it in to the Request object? We should investigate the right way 516 // FIXME: How can we set isReload properly? What is the correct place to loa d it in to the Request object? We should investigate the right way
516 // to plumb this information in to here. 517 // to plumb this information in to here.
517 } 518 }
518 519
519 void Request::setBodyBlobHandle(PassRefPtr<BlobDataHandle> blobDataHandle) 520 void Request::setBuffer(BodyStreamBuffer* buffer)
520 { 521 {
521 m_request->setBlobDataHandle(blobDataHandle); 522 m_request->setBuffer(buffer);
522 setBody(m_request->blobDataHandle()); 523 refreshBody();
524 }
525
526 void Request::refreshBody()
527 {
528 setBody(m_request->buffer());
523 } 529 }
524 530
525 void Request::clearHeaderList() 531 void Request::clearHeaderList()
526 { 532 {
527 m_request->headerList()->clearList(); 533 m_request->headerList()->clearList();
528 } 534 }
529 535
530 PassRefPtr<BlobDataHandle> Request::blobDataHandle() const
531 {
532 return m_request->blobDataHandle();
533 }
534
535 BodyStreamBuffer* Request::buffer() const
536 {
537 // We don't support BodyStreamBuffer for Request yet.
538 return nullptr;
539 }
540
541 String Request::mimeType() const 536 String Request::mimeType() const
542 { 537 {
543 return m_request->mimeType(); 538 return m_request->mimeType();
544 } 539 }
545 540
546 DEFINE_TRACE(Request) 541 DEFINE_TRACE(Request)
547 { 542 {
548 Body::trace(visitor); 543 Body::trace(visitor);
549 visitor->trace(m_request); 544 visitor->trace(m_request);
550 visitor->trace(m_headers); 545 visitor->trace(m_headers);
551 } 546 }
552 547
553 } // namespace blink 548 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698