| Index: Source/modules/fetch/Request.cpp
|
| diff --git a/Source/modules/fetch/Request.cpp b/Source/modules/fetch/Request.cpp
|
| index af5c233853618bd09bcbf419ab42ad59049365c9..806a2961a06fb6eaa2882d1e18ccee85272c1bfd 100644
|
| --- a/Source/modules/fetch/Request.cpp
|
| +++ b/Source/modules/fetch/Request.cpp
|
| @@ -28,7 +28,6 @@ FetchRequestData* createCopyOfFetchRequestDataForFetch(ExecutionContext* context
|
| request->setMethod(original->method());
|
| request->setHeaderList(original->headerList()->clone());
|
| request->setUnsafeRequestFlag(true);
|
| - request->setBlobDataHandle(original->blobDataHandle());
|
| // FIXME: Set client.
|
| request->setOrigin(SecurityOrigin::create(context->url()));
|
| // FIXME: Set ForceOriginHeaderFlag.
|
| @@ -37,50 +36,57 @@ FetchRequestData* createCopyOfFetchRequestDataForFetch(ExecutionContext* context
|
| request->setMode(original->mode());
|
| request->setCredentials(original->credentials());
|
| // FIXME: Set cache mode.
|
| + // TODO(yhirano): Set redirect mode.
|
| return request;
|
| }
|
|
|
| Request* Request::createRequestWithRequestOrString(ExecutionContext* context, Request* inputRequest, const String& inputString, const RequestInit& init, ExceptionState& exceptionState)
|
| {
|
| - // "1. If input is a Request object, run these substeps:"
|
| - if (inputRequest) {
|
| - // "1. If input's used flag is set, throw a TypeError."
|
| + // "1. Let |temporaryBody| be null."
|
| + RefPtr<BlobDataHandle> temporaryBody;
|
| +
|
| + // "2. If |input| is a Request object and |input|'s body is non-null, run
|
| + // these substeps:"
|
| + if (inputRequest && inputRequest->hasBody()) {
|
| + // "1. If |input|'s used flag is set, throw a TypeError."
|
| + // "2. Set |temporaryBody| to |input|'s body."
|
| if (inputRequest->bodyUsed()) {
|
| exceptionState.throwTypeError("Cannot construct a Request with a Request object that has already been used.");
|
| - return 0;
|
| + return nullptr;
|
| + }
|
| + if (inputRequest->isBodyConsumed()) {
|
| + // Currently the only methods that can consume body data without
|
| + // setting 'body passed' flag consume entire body (e.g. text()).
|
| + // Thus we can set an empty blob to the new request instead of
|
| + // creating a draining stream.
|
| + // TODO(yhirano): Fix this once Request.body is introduced.
|
| + OwnPtr<BlobData> blobData = BlobData::create();
|
| + blobData->setContentType(inputRequest->blobDataHandle()->type());
|
| + temporaryBody = BlobDataHandle::create(blobData.release(), 0);
|
| + } else {
|
| + temporaryBody = inputRequest->m_request->blobDataHandle();
|
| }
|
| - // "2. Set input's used flag."
|
| - inputRequest->lockBody(PassBody);
|
| }
|
|
|
| - // "2. Let |request| be |input|'s associated request, if |input| is a
|
| - // Request object, and a new request otherwise."
|
| - // "3. Set |request| to a new request whose url is |request|'s url, method
|
| + // "3. Let |request| be |input|'s request, if |input| is a Request object,
|
| + // and a new request otherwise."
|
| + // "4. Set |request| to a new request whose url is |request|'s url, method
|
| // is |request|'s method, header list is a copy of |request|'s header list,
|
| - // unsafe request flag is set, body is |request|'s body, client is entry
|
| - // settings object, origin is entry settings object's origin, force Origin
|
| - // header flag is set, same-origin data URL flag is set, referrer is client,
|
| - // context is fetch, mode is |request|'s mode, credentials mode is
|
| - // |request|'s credentials mode, and cache mode is |request|'s cache mode."
|
| + // unsafe request flag is set, client is entry settings object, origin is
|
| + // entry settings object's origin, force Origin header flag is set,
|
| + // same-origin data URL flag is set, context is the empty string, mode is
|
| + // |request|'s mode, credentials mode is |request|'s credentials mode,
|
| + // cache mode is |request|'s cache mode, and redirect mode is request's
|
| + // redirect mode."
|
| FetchRequestData* request = createCopyOfFetchRequestDataForFetch(context, inputRequest ? inputRequest->request() : FetchRequestData::create());
|
|
|
| - if (inputRequest && inputRequest->blobDataHandle() && inputRequest->isBodyConsumed()) {
|
| - // Currently the only methods that can consume body data without
|
| - // setting 'body passed' flag consume entire body (e.g. text()). Thus
|
| - // we can set an empty blob to the new request instead of creating a
|
| - // draining stream.
|
| - // TODO(yhirano): Fix this once Request.body is introduced.
|
| - OwnPtr<BlobData> blobData = BlobData::create();
|
| - blobData->setContentType(inputRequest->blobDataHandle()->type());
|
| - request->setBlobDataHandle(BlobDataHandle::create(blobData.release(), 0));
|
| - }
|
| -
|
| - // "4. Let |fallbackMode| be null."
|
| - // "5. Let |fallbackCredentials| be null."
|
| - // "6. Let |fallbackCache| be null."
|
| + // "5. Let |fallbackMode| be null."
|
| + // "6. Let |fallbackCredentials| be null."
|
| + // "7. Let |fallbackCache| be null."
|
| + // "8. Let |fallbackRedirect| be null."
|
| // We don't use fallback values. We set these flags directly in below.
|
|
|
| - // "7. If |input| is a string, run these substeps:"
|
| + // "9. If |input| is a string, run these substeps:"
|
| if (!inputRequest) {
|
| // "1. Let |parsedURL| be the result of parsing |input| with entry
|
| // settings object's API base URL."
|
| @@ -88,19 +94,22 @@ Request* Request::createRequestWithRequestOrString(ExecutionContext* context, Re
|
| // "2. If |parsedURL| is failure, throw a TypeError."
|
| if (!parsedURL.isValid()) {
|
| exceptionState.throwTypeError("Failed to parse URL from " + inputString);
|
| - return 0;
|
| + return nullptr;
|
| }
|
| - // "3. Set |request|'s url to |parsedURL|."
|
| + // TODO(yhirano): "3. If |parsedURL| includes credentials, throw a
|
| + // TypeError."
|
| + // "4. Set |request|'s url to |parsedURL|."
|
| request->setURL(parsedURL);
|
| - // "4. Set |fallbackMode| to CORS."
|
| - // "5. Set |fallbackCredentials| to omit."
|
| - // "6. Set |fallbackCache| to default."
|
| + // "5. Set |fallbackMode| to CORS."
|
| + // "6. Set |fallbackCredentials| to omit."
|
| + // "7. Set |fallbackCache| to default."
|
| + // "8. Set |fallbackRedirect| to follow."
|
| // We don't use fallback values. We set these flags directly in below.
|
| }
|
|
|
| - // "8. Let |mode| be |init|'s mode member if it is present, and
|
| + // "10. Let |mode| be |init|'s mode member if it is present, and
|
| // |fallbackMode| otherwise."
|
| - // "9. If |mode| is non-null, set |request|'s mode to |mode|."
|
| + // "11. If |mode| is non-null, set |request|'s mode to |mode|."
|
| if (init.mode == "same-origin") {
|
| request->setMode(WebURLRequest::FetchRequestModeSameOrigin);
|
| } else if (init.mode == "no-cors") {
|
| @@ -112,9 +121,9 @@ Request* Request::createRequestWithRequestOrString(ExecutionContext* context, Re
|
| request->setMode(WebURLRequest::FetchRequestModeCORS);
|
| }
|
|
|
| - // "10. Let |credentials| be |init|'s credentials member if it is present,
|
| + // "12. Let |credentials| be |init|'s credentials member if it is present,
|
| // and |fallbackCredentials| otherwise."
|
| - // "11. If |credentials| is non-null, set |request|'s credentials mode to
|
| + // "13. If |credentials| is non-null, set |request|'s credentials mode to
|
| // |credentials|.
|
| if (init.credentials == "omit") {
|
| request->setCredentials(WebURLRequest::FetchCredentialsModeOmit);
|
| @@ -127,54 +136,62 @@ Request* Request::createRequestWithRequestOrString(ExecutionContext* context, Re
|
| request->setCredentials(WebURLRequest::FetchCredentialsModeOmit);
|
| }
|
|
|
| - // FIXME: "12. Let |cache| be |init|'s cache member if it is present, and
|
| + // FIXME: "14. Let |cache| be |init|'s cache member if it is present, and
|
| // |fallbackCache| otherwise."
|
| - // FIXME: "13. If |cache| is non-null, set |request|'s cache mode to
|
| + // FIXME: "15. If |cache| is non-null, set |request|'s cache mode to
|
| // |cache|."
|
| -
|
| - // "14. If |init|'s method member is present, let |method| be it and run
|
| + // TODO(yhirano): "16. If |init|'s redirect member is present and its is
|
| + // manual, throw a TypeError."
|
| + // TODO(yhirano): "17. Let |redirect| be |init|'s redirect member if it is
|
| + // present, and |fallbackRedirect| otherwise."
|
| + // TODO(yhirano): "18 If |redirect| is non-null, set |request|'s redirect
|
| + // mode to |redirect|."
|
| + // TODO(yhirano): "19 If |request|'s redirect mode is manual, set it to
|
| + // follow."
|
| +
|
| + // "20. If |init|'s method member is present, let |method| be it and run
|
| // these substeps:"
|
| if (!init.method.isNull()) {
|
| // "1. If |method| is not a method or method is a forbidden method,
|
| // throw a TypeError."
|
| if (!isValidHTTPToken(init.method)) {
|
| exceptionState.throwTypeError("'" + init.method + "' is not a valid HTTP method.");
|
| - return 0;
|
| + return nullptr;
|
| }
|
| if (FetchUtils::isForbiddenMethod(init.method)) {
|
| exceptionState.throwTypeError("'" + init.method + "' HTTP method is unsupported.");
|
| - return 0;
|
| + return nullptr;
|
| }
|
| // "2. Normalize |method|."
|
| // "3. Set |request|'s method to |method|."
|
| request->setMethod(FetchUtils::normalizeMethod(AtomicString(init.method)));
|
| }
|
| - // "15. Let |r| be a new Request object associated with |request|, and a new
|
| - // Headers object."
|
| + // "21. Let |r| be a new Request object associated with |request| and a new
|
| + // Headers object whose guard is request."
|
| Request* r = Request::create(context, request);
|
| - // "16. Let |headers| be a copy of |r|'s Headers object."
|
| - // "17. If |init|'s headers member is present, set |headers| to |init|'s
|
| + // "22. Let |headers| be a copy of |r|'s Headers object."
|
| + // "23. If |init|'s headers member is present, set |headers| to |init|'s
|
| // headers member."
|
| // We don't create a copy of r's Headers object when init's headers member
|
| // is present.
|
| - Headers* headers = 0;
|
| + Headers* headers = nullptr;
|
| if (!init.headers && init.headersDictionary.isUndefinedOrNull()) {
|
| headers = r->headers()->clone();
|
| }
|
| - // "18. Empty |r|'s request's header list."
|
| + // "24. Empty |r|'s request's header list."
|
| r->clearHeaderList();
|
| - // "19. If |r|'s request's mode is no CORS, run these substeps:
|
| + // "25. If |r|'s request's mode is no CORS, run these substeps:
|
| if (r->request()->mode() == WebURLRequest::FetchRequestModeNoCORS) {
|
| // "1. If |r|'s request's method is not a simple method, throw a
|
| // TypeError."
|
| if (!FetchUtils::isSimpleMethod(r->request()->method())) {
|
| exceptionState.throwTypeError("'" + r->request()->method() + "' is unsupported in no-cors mode.");
|
| - return 0;
|
| + return nullptr;
|
| }
|
| // "Set |r|'s Headers object's guard to |request-no-CORS|.
|
| r->headers()->setGuard(Headers::RequestNoCORSGuard);
|
| }
|
| - // "20. Fill |r|'s Headers object with |headers|. Rethrow any exceptions."
|
| + // "26. Fill |r|'s Headers object with |headers|. Rethrow any exceptions."
|
| if (init.headers) {
|
| ASSERT(init.headersDictionary.isUndefinedOrNull());
|
| r->headers()->fillWith(init.headers.get(), exceptionState);
|
| @@ -185,34 +202,51 @@ Request* Request::createRequestWithRequestOrString(ExecutionContext* context, Re
|
| r->headers()->fillWith(headers, exceptionState);
|
| }
|
| if (exceptionState.hadException())
|
| - return 0;
|
| + return nullptr;
|
| +
|
| + // "27. If either |init|'s body member is present or |temporaryBody| is
|
| + // non-null, and |request|'s method is `GET` or `HEAD`, throw a TypeError.
|
| + if (init.bodyBlobHandle || temporaryBody) {
|
| + if (request->method() == "GET" || request->method() == "HEAD") {
|
| + exceptionState.throwTypeError("Request with GET/HEAD method cannot have body.");
|
| + return nullptr;
|
| + }
|
| + }
|
|
|
| - // "21. If |init|'s body member is present, run these substeps:"
|
| + // "28. If |init|'s body member is present, run these substeps:"
|
| if (init.bodyBlobHandle) {
|
| - // "1. If request's method is `GET` or `HEAD`, throw a TypeError."
|
| - // "2. Let |stream| and |Content-Type| be the result of extracting
|
| + // "1. Let |stream| and |Content-Type| be the result of extracting
|
| // |init|'s body member."
|
| - // "3. Set |r|'s request's body to |stream|."
|
| - // "4. If |Content-Type| is non-null and |r|'s request's header list
|
| + // "2. Set |temporaryBody| to |stream|.
|
| + // "3. If |Content-Type| is non-null and |r|'s request's header list
|
| // contains no header named `Content-Type`, append
|
| // `Content-Type`/|Content-Type| to |r|'s Headers object. Rethrow any
|
| // exception."
|
| - if (request->method() == "GET" || request->method() == "HEAD") {
|
| - exceptionState.throwTypeError("Request with GET/HEAD method cannot have body.");
|
| - return 0;
|
| - }
|
| - r->setBodyBlobHandle(init.bodyBlobHandle);
|
| + temporaryBody = init.bodyBlobHandle;
|
| if (!init.bodyBlobHandle->type().isEmpty() && !r->headers()->has("Content-Type", exceptionState)) {
|
| r->headers()->append("Content-Type", init.bodyBlobHandle->type(), exceptionState);
|
| }
|
| if (exceptionState.hadException())
|
| - return 0;
|
| + return nullptr;
|
| }
|
| - // "22. Set |r|'s MIME type to the result of extracting a MIME type from
|
| +
|
| + // "29. Set |r|'s body to |temporaryBody|.
|
| + r->setBodyBlobHandle(temporaryBody.release());
|
| +
|
| + // "30. Set |r|'s MIME type to the result of extracting a MIME type from
|
| // |r|'s request's header list."
|
| r->m_request->setMIMEType(r->m_request->headerList()->extractMIMEType());
|
|
|
| - // "23. Return |r|."
|
| + // "31. If |input| is a Request object and |input|'s body is non-null, run
|
| + // these substeps:"
|
| + if (inputRequest && inputRequest->hasBody()) {
|
| + // "1. Set |input|'s body to null."
|
| + inputRequest->setBodyBlobHandle(nullptr);
|
| + // "2. Set |input|'s used flag."
|
| + inputRequest->lockBody(PassBody);
|
| + }
|
| +
|
| + // "32. Return |r|."
|
| return r;
|
| }
|
|
|
| @@ -231,7 +265,7 @@ Request* Request::create(ExecutionContext* context, const String& input, Excepti
|
|
|
| Request* Request::create(ExecutionContext* context, const String& input, const Dictionary& init, ExceptionState& exceptionState)
|
| {
|
| - return createRequestWithRequestOrString(context, 0, input, RequestInit(context, init, exceptionState), exceptionState);
|
| + return createRequestWithRequestOrString(context, nullptr, input, RequestInit(context, init, exceptionState), exceptionState);
|
| }
|
|
|
| Request* Request::create(ExecutionContext* context, Request* input, ExceptionState& exceptionState)
|
|
|