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

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: Rebase. 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
« no previous file with comments | « Source/modules/fetch/Request.h ('k') | Source/modules/fetch/Response.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 Request* temporaryBodyRequest = nullptr;
53 BodyStreamBuffer* temporaryBodyBuffer = nullptr;
51 54
52 if (inputRequest) { 55 if (inputRequest) {
53 // We check bodyUsed even when the body is null in spite of the 56 // 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. 57 // spec. See https://github.com/whatwg/fetch/issues/61 for details.
55 if (inputRequest->bodyUsed()) { 58 if (inputRequest->bodyUsed()) {
56 exceptionState.throwTypeError("Cannot construct a Request with a Req uest object that has already been used."); 59 exceptionState.throwTypeError("Cannot construct a Request with a Req uest object that has already been used.");
57 return nullptr; 60 return nullptr;
58 } 61 }
59 } 62 }
60 63
61 // "2. If |input| is a Request object and |input|'s body is non-null, run 64 // "2. If |input| is a Request object and |input|'s body is non-null, run
62 // these substeps:" 65 // these substeps:"
63 if (inputRequest && inputRequest->hasBody()) { 66 if (inputRequest && inputRequest->hasBody()) {
64 // "1. If |input|'s used flag is set, throw a TypeError." 67 // "1. If |input|'s used flag is set, throw a TypeError."
65 // "2. Set |temporaryBody| to |input|'s body." 68 // "2. Set |temporaryBody| to |input|'s body."
66 if (inputRequest->bodyUsed()) { 69 if (inputRequest->bodyUsed()) {
67 exceptionState.throwTypeError("Cannot construct a Request with a Req uest object that has already been used."); 70 exceptionState.throwTypeError("Cannot construct a Request with a Req uest object that has already been used.");
68 return nullptr; 71 return nullptr;
69 } 72 }
70 if (inputRequest->isBodyConsumed()) { 73 // We call createDrainingStream() later and not here, because
71 // Currently the only methods that can consume body data without 74 // createDrainingStream() has side effects on |inputRequest|'s body.
72 // setting 'body passed' flag consume entire body (e.g. text()). 75 temporaryBodyRequest = inputRequest;
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 } 76 }
83 77
84 // "3. Let |request| be |input|'s request, if |input| is a Request object, 78 // "3. Let |request| be |input|'s request, if |input| is a Request object,
85 // and a new request otherwise." 79 // and a new request otherwise."
86 // "4. Set |request| to a new request whose url is |request|'s url, method 80 // "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, 81 // 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 82 // unsafe request flag is set, client is entry settings object, origin is
89 // entry settings object's origin, force Origin header flag is set, 83 // 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 84 // 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, 85 // |request|'s mode, credentials mode is |request|'s credentials mode,
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 r->headers()->fillWith(init.headersDictionary, exceptionState); 206 r->headers()->fillWith(init.headersDictionary, exceptionState);
213 } else { 207 } else {
214 ASSERT(headers); 208 ASSERT(headers);
215 r->headers()->fillWith(headers, exceptionState); 209 r->headers()->fillWith(headers, exceptionState);
216 } 210 }
217 if (exceptionState.hadException()) 211 if (exceptionState.hadException())
218 return nullptr; 212 return nullptr;
219 213
220 // "27. If either |init|'s body member is present or |temporaryBody| is 214 // "27. If either |init|'s body member is present or |temporaryBody| is
221 // non-null, and |request|'s method is `GET` or `HEAD`, throw a TypeError. 215 // non-null, and |request|'s method is `GET` or `HEAD`, throw a TypeError.
222 if (init.bodyBlobHandle || temporaryBody) { 216 if (init.bodyBlobHandle || temporaryBodyRequest) {
223 if (request->method() == "GET" || request->method() == "HEAD") { 217 if (request->method() == "GET" || request->method() == "HEAD") {
224 exceptionState.throwTypeError("Request with GET/HEAD method cannot h ave body."); 218 exceptionState.throwTypeError("Request with GET/HEAD method cannot h ave body.");
225 return nullptr; 219 return nullptr;
226 } 220 }
227 } 221 }
228 222
229 // "28. If |init|'s body member is present, run these substeps:" 223 // "28. If |init|'s body member is present, run these substeps:"
230 if (init.bodyBlobHandle) { 224 if (init.bodyBlobHandle) {
231 // "1. Let |stream| and |Content-Type| be the result of extracting 225 // "1. Let |stream| and |Content-Type| be the result of extracting
232 // |init|'s body member." 226 // |init|'s body member."
233 // "2. Set |temporaryBody| to |stream|. 227 // "2. Set |temporaryBody| to |stream|.
234 // "3. If |Content-Type| is non-null and |r|'s request's header list 228 // "3. If |Content-Type| is non-null and |r|'s request's header list
235 // contains no header named `Content-Type`, append 229 // contains no header named `Content-Type`, append
236 // `Content-Type`/|Content-Type| to |r|'s Headers object. Rethrow any 230 // `Content-Type`/|Content-Type| to |r|'s Headers object. Rethrow any
237 // exception." 231 // exception."
238 temporaryBody = init.bodyBlobHandle; 232 temporaryBodyBuffer = BodyStreamBuffer::create(FetchBlobDataConsumerHand le::create(scriptState->executionContext(), init.bodyBlobHandle));
233 temporaryBodyRequest = nullptr;
239 if (!init.bodyBlobHandle->type().isEmpty() && !r->headers()->has("Conten t-Type", exceptionState)) { 234 if (!init.bodyBlobHandle->type().isEmpty() && !r->headers()->has("Conten t-Type", exceptionState)) {
240 r->headers()->append("Content-Type", init.bodyBlobHandle->type(), ex ceptionState); 235 r->headers()->append("Content-Type", init.bodyBlobHandle->type(), ex ceptionState);
241 } 236 }
242 if (exceptionState.hadException()) 237 if (exceptionState.hadException())
243 return nullptr; 238 return nullptr;
244 } 239 }
245 240
246 // "29. Set |r|'s body to |temporaryBody|. 241 // "29. Set |r|'s body to |temporaryBody|.
247 r->setBodyBlobHandle(temporaryBody.release()); 242 if (temporaryBodyBuffer)
243 r->setBuffer(temporaryBodyBuffer);
244 else if (temporaryBodyRequest)
245 r->setBuffer(temporaryBodyRequest->createDrainingStream()->leakBuffer()) ;
248 246
249 // "30. Set |r|'s MIME type to the result of extracting a MIME type from 247 // "30. Set |r|'s MIME type to the result of extracting a MIME type from
250 // |r|'s request's header list." 248 // |r|'s request's header list."
251 r->m_request->setMIMEType(r->m_request->headerList()->extractMIMEType()); 249 r->m_request->setMIMEType(r->m_request->headerList()->extractMIMEType());
252 250
253 // "31. If |input| is a Request object and |input|'s body is non-null, run 251 // "31. If |input| is a Request object and |input|'s body is non-null, run
254 // these substeps:" 252 // these substeps:"
255 // We set bodyUsed even when the body is null in spite of the 253 // 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. 254 // spec. See https://github.com/whatwg/fetch/issues/61 for details.
257 if (inputRequest) { 255 if (inputRequest) {
258 // "1. Set |input|'s body to null." 256 // "1. Set |input|'s body to null."
259 inputRequest->setBodyBlobHandle(nullptr); 257 inputRequest->setBuffer(nullptr);
260 // "2. Set |input|'s used flag." 258 // "2. Set |input|'s used flag."
261 inputRequest->lockBody(PassBody); 259 inputRequest->lockBody(PassBody);
262 } 260 }
263 261
264 // "32. Return |r|." 262 // "32. Return |r|."
265 return r; 263 return r;
266 } 264 }
267 265
268 Request* Request::create(ScriptState* scriptState, const RequestInfo& input, con st Dictionary& init, ExceptionState& exceptionState) 266 Request* Request::create(ScriptState* scriptState, const RequestInfo& input, con st Dictionary& init, ExceptionState& exceptionState)
269 { 267 {
(...skipping 29 matching lines...) Expand all
299 r->suspendIfNeeded(); 297 r->suspendIfNeeded();
300 return r; 298 return r;
301 } 299 }
302 300
303 Request::Request(ExecutionContext* context, FetchRequestData* request) 301 Request::Request(ExecutionContext* context, FetchRequestData* request)
304 : Body(context) 302 : Body(context)
305 , m_request(request) 303 , m_request(request)
306 , m_headers(Headers::create(m_request->headerList())) 304 , m_headers(Headers::create(m_request->headerList()))
307 { 305 {
308 m_headers->setGuard(Headers::RequestGuard); 306 m_headers->setGuard(Headers::RequestGuard);
307
308 refreshBody();
309 } 309 }
310 310
311 Request::Request(ExecutionContext* context, FetchRequestData* request, Headers* headers) 311 Request::Request(ExecutionContext* context, FetchRequestData* request, Headers* headers)
312 : Body(context) , m_request(request) , m_headers(headers) { } 312 : Body(context) , m_request(request) , m_headers(headers)
313 {
314 refreshBody();
315 }
313 316
314 Request* Request::create(ExecutionContext* context, const WebServiceWorkerReques t& webRequest) 317 Request* Request::create(ExecutionContext* context, const WebServiceWorkerReques t& webRequest)
315 { 318 {
316 Request* r = new Request(context, webRequest); 319 Request* r = new Request(context, webRequest);
317 r->suspendIfNeeded(); 320 r->suspendIfNeeded();
318 return r; 321 return r;
319 } 322 }
320 323
321 Request::Request(ExecutionContext* context, const WebServiceWorkerRequest& webRe quest) 324 Request::Request(ExecutionContext* context, const WebServiceWorkerRequest& webRe quest)
322 : Body(context) 325 : Body(context)
323 , m_request(FetchRequestData::create(webRequest)) 326 , m_request(FetchRequestData::create(context, webRequest))
324 , m_headers(Headers::create(m_request->headerList())) 327 , m_headers(Headers::create(m_request->headerList()))
325 { 328 {
326 m_headers->setGuard(Headers::RequestGuard); 329 m_headers->setGuard(Headers::RequestGuard);
330
331 refreshBody();
327 } 332 }
328 333
329 String Request::method() const 334 String Request::method() const
330 { 335 {
331 // "The method attribute's getter must return request's method." 336 // "The method attribute's getter must return request's method."
332 return m_request->method(); 337 return m_request->method();
333 } 338 }
334 339
335 KURL Request::url() const 340 KURL Request::url() const
336 { 341 {
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
458 return "omit"; 463 return "omit";
459 case WebURLRequest::FetchCredentialsModeSameOrigin: 464 case WebURLRequest::FetchCredentialsModeSameOrigin:
460 return "same-origin"; 465 return "same-origin";
461 case WebURLRequest::FetchCredentialsModeInclude: 466 case WebURLRequest::FetchCredentialsModeInclude:
462 return "include"; 467 return "include";
463 } 468 }
464 ASSERT_NOT_REACHED(); 469 ASSERT_NOT_REACHED();
465 return ""; 470 return "";
466 } 471 }
467 472
468 Request* Request::clone(ExceptionState& exceptionState) const 473 Request* Request::clone(ExceptionState& exceptionState)
469 { 474 {
470 if (bodyUsed()) { 475 if (bodyUsed()) {
471 exceptionState.throwTypeError("Request body is already used"); 476 exceptionState.throwTypeError("Request body is already used");
472 return nullptr; 477 return nullptr;
473 } 478 }
474 479
475 FetchRequestData* request = m_request->clone(); 480 if (OwnPtr<DrainingBodyStreamBuffer> buffer = createDrainingStream())
476 if (blobDataHandle() && isBodyConsumed()) { 481 m_request->setBuffer(buffer->leakBuffer());
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 482
483 FetchRequestData* request = m_request->clone(executionContext());
487 Headers* headers = Headers::create(request->headerList()); 484 Headers* headers = Headers::create(request->headerList());
488 headers->setGuard(m_headers->guard()); 485 headers->setGuard(m_headers->guard());
489 Request* r = new Request(executionContext(), request, headers); 486 Request* r = new Request(executionContext(), request, headers);
490 r->suspendIfNeeded(); 487 r->suspendIfNeeded();
488
489 // Lock the old body and set |body| property to the new one.
490 lockBody();
491 refreshBody();
491 return r; 492 return r;
492 } 493 }
493 494
494 FetchRequestData* Request::passRequestData() 495 FetchRequestData* Request::passRequestData()
495 { 496 {
496 ASSERT(!bodyUsed()); 497 ASSERT(!bodyUsed());
498
499 if (OwnPtr<DrainingBodyStreamBuffer> buffer = createDrainingStream())
500 m_request->setBuffer(buffer->leakBuffer());
501
497 lockBody(PassBody); 502 lockBody(PassBody);
498 return m_request->pass(); 503 FetchRequestData* newRequestData = m_request->pass(executionContext());
504 refreshBody();
505 return newRequestData;
499 } 506 }
500 507
501 void Request::populateWebServiceWorkerRequest(WebServiceWorkerRequest& webReques t) const 508 void Request::populateWebServiceWorkerRequest(WebServiceWorkerRequest& webReques t) const
502 { 509 {
503 webRequest.setMethod(method()); 510 webRequest.setMethod(method());
504 webRequest.setRequestContext(m_request->context()); 511 webRequest.setRequestContext(m_request->context());
505 // This strips off the fragment part. 512 // This strips off the fragment part.
506 webRequest.setURL(url()); 513 webRequest.setURL(url());
507 514
508 const FetchHeaderList* headerList = m_headers->headerList(); 515 const FetchHeaderList* headerList = m_headers->headerList();
509 for (size_t i = 0, size = headerList->size(); i < size; ++i) { 516 for (size_t i = 0, size = headerList->size(); i < size; ++i) {
510 const FetchHeaderList::Header& header = headerList->entry(i); 517 const FetchHeaderList::Header& header = headerList->entry(i);
511 webRequest.appendHeader(header.first, header.second); 518 webRequest.appendHeader(header.first, header.second);
512 } 519 }
513 520
514 webRequest.setReferrer(m_request->referrer().referrer().referrer, static_cas t<WebReferrerPolicy>(m_request->referrer().referrer().referrerPolicy)); 521 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 522 // 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. 523 // to plumb this information in to here.
517 } 524 }
518 525
519 void Request::setBodyBlobHandle(PassRefPtr<BlobDataHandle> blobDataHandle) 526 void Request::setBuffer(BodyStreamBuffer* buffer)
520 { 527 {
521 m_request->setBlobDataHandle(blobDataHandle); 528 m_request->setBuffer(buffer);
522 setBody(m_request->blobDataHandle()); 529 refreshBody();
530 }
531
532 void Request::refreshBody()
533 {
534 setBody(m_request->buffer());
523 } 535 }
524 536
525 void Request::clearHeaderList() 537 void Request::clearHeaderList()
526 { 538 {
527 m_request->headerList()->clearList(); 539 m_request->headerList()->clearList();
528 } 540 }
529 541
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 542 String Request::mimeType() const
542 { 543 {
543 return m_request->mimeType(); 544 return m_request->mimeType();
544 } 545 }
545 546
546 DEFINE_TRACE(Request) 547 DEFINE_TRACE(Request)
547 { 548 {
548 Body::trace(visitor); 549 Body::trace(visitor);
549 visitor->trace(m_request); 550 visitor->trace(m_request);
550 visitor->trace(m_headers); 551 visitor->trace(m_headers);
551 } 552 }
552 553
553 } // namespace blink 554 } // namespace blink
OLDNEW
« no previous file with comments | « Source/modules/fetch/Request.h ('k') | Source/modules/fetch/Response.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698