| Index: third_party/WebKit/Source/modules/fetch/Request.cpp
|
| diff --git a/third_party/WebKit/Source/modules/fetch/Request.cpp b/third_party/WebKit/Source/modules/fetch/Request.cpp
|
| index 6a13627398b72effb02e51e50ddc994485ad3f98..60f7fa7113464080674ef247a46eb99f58a0895d 100644
|
| --- a/third_party/WebKit/Source/modules/fetch/Request.cpp
|
| +++ b/third_party/WebKit/Source/modules/fetch/Request.cpp
|
| @@ -50,7 +50,6 @@ FetchRequestData* createCopyOfFetchRequestDataForFetch(ScriptState* scriptState,
|
|
|
| Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Request* inputRequest, const String& inputString, RequestInit& init, ExceptionState& exceptionState)
|
| {
|
| - // "1. Let |temporaryBody| be null."
|
| BodyStreamBuffer* temporaryBody = nullptr;
|
|
|
| if (inputRequest) {
|
| @@ -62,11 +61,11 @@ Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Req
|
| }
|
| }
|
|
|
| - // "2. If |input| is a Request object and |input|'s body is non-null, run
|
| - // these substeps:"
|
| + // - "If |input| is a Request object and it is disturbed, throw a
|
| + // TypeError."
|
| + // - "Let |temporaryBody| be |input|'s request's body if |input| is a
|
| + // Request object, and null otherwise."
|
| 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 nullptr;
|
| @@ -74,109 +73,132 @@ Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Req
|
| temporaryBody = inputRequest->bodyBuffer();
|
| }
|
|
|
| - // "3. Let |request| be |input|'s request, if |input| is a Request object,
|
| + // "Let |request| be |input|'s request, if |input| is a Request object,
|
| // and a new request otherwise."
|
| - // "4. Let origin be entry settings object's origin."
|
| +
|
| RefPtr<SecurityOrigin> origin = scriptState->executionContext()->securityOrigin();
|
|
|
| - // TODO(yhirano):
|
| - // "5. Let window be client."
|
| - // "6. If request's window is an environment settings object and its
|
| - // origin is same origin with origin, set window to request's window."
|
| - // "7. If init's window member is present and it is not null, throw a
|
| + // TODO(yhirano): Implement the following steps:
|
| + // - "Let |window| be client."
|
| + // - "If |request|'s window is an environment settings object and its
|
| + // origin is same origin with entry settings object's origin, set
|
| + // |window| to |request|'s window."
|
| + // - "If |init|'s window member is present and it is not null, throw a
|
| // TypeError."
|
| - // "8. If init's window member is present, set window to no-window."
|
| - // "9. Set |request| to a new request whose url is |request|'s current url,
|
| - // method is |request|'s method, header list is a copy of |request|'s header
|
| - // list, unsafe-request flag is set, client is entry settings object, window
|
| - // is window, origin is origin, force-Origin-header flag is set, same-origin
|
| - // data-URL flag is set, referrer is request's referrer, referrer policy is
|
| - // |request|'s referrer policy, context is the empty string, mode is
|
| - // |request|'s mode, credentials mode is |request|'s credentials mode, cache
|
| - // mode is |request|'s cache mode, redirect mode is |request|'s redirect
|
| - // mode, and integrity metadata is |request|'s integrity metadata."
|
| + // - "If |init|'s window member is present, set |window| to no-window."
|
| + //
|
| + // "Set |request| to a new request whose url is |request|'s current url,
|
| + // method is |request|'s method, header list is a copy of |request|'s
|
| + // header list, unsafe-request flag is set, client is entry settings object,
|
| + // window is |window|, origin is "client", omit-Origin-header flag is
|
| + // |request|'s omit-Origin-header flag, same-origin data-URL flag is set,
|
| + // referrer is |request|'s referrer, referrer policy is |request|'s
|
| + // referrer policy, destination is the empty string, mode is |request|'s
|
| + // mode, credentials mode is |request|'s credentials mode, cache mode is
|
| + // |request|'s cache mode, redirect mode is |request|'s redirect mode, and
|
| + // integrity metadata is |request|'s integrity metadata."
|
| FetchRequestData* request = createCopyOfFetchRequestDataForFetch(scriptState, inputRequest ? inputRequest->request() : FetchRequestData::create());
|
|
|
| - // "10. Let |fallbackMode| be null."
|
| - // "11. Let |fallbackCredentials| be null."
|
| - // "12. Let |baseURL| be entry settings object's API base URL."
|
| // We don't use fallback values. We set these flags directly in below.
|
| + // - "Let |fallbackMode| be null."
|
| + // - "Let |fallbackCredentials| be null."
|
| + // - "Let |baseURL| be entry settings object's API base URL."
|
|
|
| - // "13. If |input| is a string, run these substeps:"
|
| + // "If |input| is a string, run these substeps:"
|
| if (!inputRequest) {
|
| - // "1. Let |parsedURL| be the result of parsing |input| with |baseURL|."
|
| + // "Let |parsedURL| be the result of parsing |input| with |baseURL|."
|
| KURL parsedURL = scriptState->executionContext()->completeURL(inputString);
|
| - // "2. If |parsedURL| is failure, throw a TypeError."
|
| + // "If |parsedURL| is failure, throw a TypeError."
|
| if (!parsedURL.isValid()) {
|
| exceptionState.throwTypeError("Failed to parse URL from " + inputString);
|
| return nullptr;
|
| }
|
| - // TODO(yhirano): "3. If |parsedURL| includes credentials, throw a
|
| - // TypeError."
|
| - // "4. Set |request|'s url to |parsedURL|."
|
| + // TODO(yhirano): Implement the following substep:
|
| + // "If |parsedURL| includes credentials, throw a TypeError."
|
| + //
|
| + // "Set |request|'s url to |parsedURL| and replace |request|'s url list
|
| + // single URL with a copy of |parsedURL|."
|
| request->setURL(parsedURL);
|
| - // "5. Set |fallbackMode| to CORS."
|
| - // "6. Set |fallbackCredentials| to omit."
|
| +
|
| // We don't use fallback values. We set these flags directly in below.
|
| + // - "Set |fallbackMode| to "cors"."
|
| + // - "Set |fallbackCredentials| to "omit"."
|
| }
|
|
|
| - // "14. If any of |init|'s members are present, run these substeps:"
|
| + // "If any of |init|'s members are present, run these substeps:"
|
| if (init.areAnyMembersSet) {
|
| - // "1. If |request|'s |mode| is "navigate", throw a TypeError."
|
| + // "If |request|'s |mode| is "navigate", throw a TypeError."
|
| if (request->mode() == WebURLRequest::FetchRequestModeNavigate) {
|
| exceptionState.throwTypeError("Cannot construct a Request with a Request whose mode is 'navigate' and a non-empty RequestInit.");
|
| return nullptr;
|
| }
|
| - // "2. Unset |request|'s omit-Origin-header flag."
|
| - // "3. Set |request|'s referrer to "client"."
|
| - // "4. Set |request|'s referrer policy to the empty string."
|
| - // => RequestInit::RequestInit.
|
| +
|
| + // TODO(yhirano): Implement the following substep:
|
| + // "Unset |request|'s omit-Origin-header flag."
|
| +
|
| + // The substep "Set |request|'s referrer to "client"." is performed by
|
| + // the code below as follows:
|
| + // - |init.referrer.referrer| gets initialized by the RequestInit
|
| + // constructor to "about:client" when any of |options|'s members are
|
| + // present.
|
| + // - The code below does the equivalent as the step specified in the
|
| + // spec by processing the "about:client".
|
| +
|
| + // The substep "Set |request|'s referrer policy to the empty string."
|
| + // is also performed by the code below similarly.
|
| }
|
|
|
| - // 15. If |init|'s referrer member is present, run these substeps:
|
| - // Note that JS null and undefined are encoded as an empty string and thus
|
| - // a null string means referrer member is not set.
|
| - // 16. If |init|'s referrerPolicy member is present, set |request|'s
|
| - // referrer policy to it.
|
| - // areAnyMembersSet will be True, if any members in RequestInit are set and
|
| - // hence the referrer member
|
| + // The following if-clause performs the following two steps:
|
| + // - "If |init|'s referrer member is present, run these substeps:"
|
| + // - TODO(yhirano): Implement the following step:
|
| + // "If |init|'s referrerPolicy member is present, set |request|'s
|
| + // referrer policy to it."
|
| + //
|
| + // The condition "if any of |init|'s members are present"
|
| + // (areAnyMembersSet) is used for the if-clause instead of conditions
|
| + // indicating presence of each member as specified in the spec. This is to
|
| + // perform the substeps in the previous step together here.
|
| if (init.areAnyMembersSet) {
|
| - // 1. Let |referrer| be |init|'s referrer member.
|
| + // Nothing to do for the step "Let |referrer| be |init|'s referrer
|
| + // member."
|
| +
|
| if (init.referrer.referrer.isEmpty()) {
|
| - // 2. if |referrer| is the empty string, set |request|'s referrer to
|
| - // "no-referrer" and terminate these substeps.
|
| + // "If |referrer| is the empty string, set |request|'s referrer to
|
| + // "no-referrer" and terminate these substeps."
|
| request->setReferrerString(FetchRequestData::noReferrerString());
|
| } else {
|
| - // 3. Let |parsedReferrer| be the result of parsing |referrer| with
|
| - // |baseURL|.
|
| + // "Let |parsedReferrer| be the result of parsing |referrer| with
|
| + // |baseURL|."
|
| KURL parsedReferrer = scriptState->executionContext()->completeURL(init.referrer.referrer);
|
| if (!parsedReferrer.isValid()) {
|
| - // 4. If |parsedReferrer| is failure, throw a TypeError.
|
| + // "If |parsedReferrer| is failure, throw a TypeError."
|
| exceptionState.throwTypeError("Referrer '" + init.referrer.referrer + "' is not a valid URL.");
|
| return nullptr;
|
| }
|
| if (parsedReferrer.protocolIsAbout() && parsedReferrer.host().isEmpty() && parsedReferrer.path() == "client") {
|
| - // 5. If |parsedReferrer|'s non-relative flag is set, scheme is
|
| + // "If |parsedReferrer|'s non-relative flag is set, scheme is
|
| // "about", and path contains a single string "client", set
|
| - // request's referrer to "client" and terminate these substeps.
|
| + // request's referrer to "client" and terminate these
|
| + // substeps."
|
| request->setReferrerString(FetchRequestData::clientReferrerString());
|
| } else if (!origin->isSameSchemeHostPortAndSuborigin(SecurityOrigin::create(parsedReferrer).get())) {
|
| - // 6. If |parsedReferrer|'s origin is not same origin with
|
| - // |origin|, throw a TypeError.
|
| + // "If |parsedReferrer|'s origin is not same origin with
|
| + // |origin|, throw a TypeError."
|
| exceptionState.throwTypeError("The origin of '" + init.referrer.referrer + "' should be same as '" + origin->toString() + "'");
|
| return nullptr;
|
| } else {
|
| - // 7. Set |request|'s referrer to |parsedReferrer|.
|
| + // "Set |request|'s referrer to |parsedReferrer|."
|
| request->setReferrerString(AtomicString(parsedReferrer.string()));
|
| }
|
| }
|
| request->setReferrerPolicy(init.referrer.referrerPolicy);
|
| }
|
|
|
| - // "16. Let |mode| be |init|'s mode member if it is present, and
|
| - // |fallbackMode| otherwise."
|
| - // "17. If |mode| is "navigate", throw a TypeError.
|
| - // "18. If |mode| is non-null, set |request|'s mode to |mode|."
|
| + // The following code performs the following steps:
|
| + // - "Let |mode| be |init|'s mode member if it is present, and
|
| + // |fallbackMode| otherwise."
|
| + // - "If |mode| is "navigate", throw a TypeError."
|
| + // - "If |mode| is non-null, set |request|'s mode to |mode|."
|
| if (init.mode == "navigate") {
|
| exceptionState.throwTypeError("Cannot construct a Request with a RequestInit whose mode member is set as 'navigate'.");
|
| return nullptr;
|
| @@ -188,14 +210,16 @@ Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Req
|
| } else if (init.mode == "cors") {
|
| request->setMode(WebURLRequest::FetchRequestModeCORS);
|
| } else {
|
| + // |inputRequest| is directly checked here instead of setting and
|
| + // checking |fallbackMode| as specified in the spec.
|
| if (!inputRequest)
|
| request->setMode(WebURLRequest::FetchRequestModeCORS);
|
| }
|
|
|
| - // "19. Let |credentials| be |init|'s credentials member if it is present,
|
| - // and |fallbackCredentials| otherwise."
|
| - // "20. If |credentials| is non-null, set |request|'s credentials mode to
|
| - // |credentials|.
|
| + // "Let |credentials| be |init|'s credentials member if it is present, and
|
| + // |fallbackCredentials| otherwise."
|
| + // "If |credentials| is non-null, set |request|'s credentials mode to
|
| + // |credentials|."
|
| if (init.credentials == "omit") {
|
| request->setCredentials(WebURLRequest::FetchCredentialsModeOmit);
|
| } else if (init.credentials == "same-origin") {
|
| @@ -207,11 +231,12 @@ Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Req
|
| request->setCredentials(WebURLRequest::FetchCredentialsModeOmit);
|
| }
|
|
|
| - // TODO(yhirano): "21. If |init|'s cache member is present, set |request|'s
|
| - // cache mode to it."
|
| + // TODO(yhirano): Implement the following step:
|
| + // "If |init|'s cache member is present, set |request|'s cache mode to
|
| + // it."
|
|
|
| - // "22. If |init|'s redirect member is present, set |request|'s redirect
|
| - // mode to it."
|
| + // "If |init|'s redirect member is present, set |request|'s redirect mode
|
| + // to it."
|
| if (init.redirect == "follow") {
|
| request->setRedirect(WebURLRequest::FetchRedirectModeFollow);
|
| } else if (init.redirect == "error") {
|
| @@ -225,11 +250,11 @@ Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Req
|
| if (!init.integrity.isNull())
|
| request->setIntegrity(init.integrity);
|
|
|
| - // "24. If |init|'s method member is present, let |method| be it and run
|
| - // these substeps:"
|
| + // "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 |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 nullptr;
|
| @@ -238,42 +263,44 @@ Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Req
|
| exceptionState.throwTypeError("'" + init.method + "' HTTP method is unsupported.");
|
| return nullptr;
|
| }
|
| - // "2. Normalize |method|."
|
| - // "3. Set |request|'s method to |method|."
|
| + // "Normalize |method|."
|
| + // "Set |request|'s method to |method|."
|
| request->setMethod(FetchUtils::normalizeMethod(AtomicString(init.method)));
|
| }
|
| - // "25. Let |r| be a new Request object associated with |request| and a new
|
| - // Headers object whose guard is request."
|
| + // "Let |r| be a new Request object associated with |request| and a new
|
| + // Headers object whose guard is "request"."
|
| Request* r = Request::create(scriptState->executionContext(), request);
|
| - // "26. Let |headers| be a copy of |r|'s Headers object."
|
| - // "27. If |init|'s headers member is present, set |headers| to |init|'s
|
| - // headers member."
|
| + // Perform the following steps:
|
| + // - "Let |headers| be a copy of |r|'s Headers object."
|
| + // - "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 = nullptr;
|
| if (!init.headers && init.headersDictionary.isUndefinedOrNull()) {
|
| headers = r->headers()->clone();
|
| }
|
| - // "28. Empty |r|'s request's header list."
|
| + // "Empty |r|'s request's header list."
|
| r->m_request->headerList()->clearList();
|
| - // "29. If |r|'s request's mode is no CORS, run these substeps:
|
| + // "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
|
| + // "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 nullptr;
|
| }
|
| - // "2. If |request|'s integrity metadata is not the empty string, throw
|
| - // a TypeError."
|
| + // "If |request|'s integrity metadata is not the empty string, throw a
|
| + // TypeError."
|
| if (!request->integrity().isEmpty()) {
|
| exceptionState.throwTypeError("The integrity attribute is unsupported in no-cors mode.");
|
| return nullptr;
|
| }
|
| - // "3. Set |r|'s Headers object's guard to |request-no-CORS|.
|
| + // "Set |r|'s Headers object's guard to "request-no-cors"."
|
| r->headers()->setGuard(Headers::RequestNoCORSGuard);
|
| }
|
| - // "30. Fill |r|'s Headers object with |headers|. Rethrow any exceptions."
|
| + // "Fill |r|'s Headers object with |headers|. Rethrow any exceptions."
|
| if (init.headers) {
|
| ASSERT(init.headersDictionary.isUndefinedOrNull());
|
| r->headers()->fillWith(init.headers.get(), exceptionState);
|
| @@ -286,7 +313,7 @@ Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Req
|
| if (exceptionState.hadException())
|
| return nullptr;
|
|
|
| - // "31. If either |init|'s body member is present or |temporaryBody| is
|
| + // "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.body || temporaryBody) {
|
| if (request->method() == "GET" || request->method() == "HEAD") {
|
| @@ -295,15 +322,16 @@ Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Req
|
| }
|
| }
|
|
|
| - // "32. If |init|'s body member is present, run these substeps:"
|
| + // "If |init|'s body member is present, run these substeps:"
|
| if (init.body) {
|
| - // "1. Let |stream| and |Content-Type| be the result of extracting
|
| - // |init|'s body member."
|
| - // "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."
|
| + // Perform the following steps:
|
| + // - "Let |stream| and |Content-Type| be the result of extracting
|
| + // |init|'s body member."
|
| + // - "Set |temporaryBody| to |stream|.
|
| + // - "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."
|
| temporaryBody = new BodyStreamBuffer(init.body.release());
|
| if (!init.contentType.isEmpty() && !r->headers()->has("Content-Type", exceptionState)) {
|
| r->headers()->append("Content-Type", init.contentType, exceptionState);
|
| @@ -312,7 +340,7 @@ Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Req
|
| return nullptr;
|
| }
|
|
|
| - // "33. Set |r|'s body to |temporaryBody|.
|
| + // "Set |r|'s request's body to |temporaryBody|.
|
| if (temporaryBody)
|
| r->m_request->setBuffer(temporaryBody);
|
|
|
| @@ -332,22 +360,23 @@ Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Req
|
| r->setOpaque();
|
| }
|
|
|
| - // "34. Set |r|'s MIME type to the result of extracting a MIME type from
|
| - // |r|'s request's header list."
|
| + // "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());
|
|
|
| - // "35. If |input| is a Request object and |input|'s body is non-null, run
|
| - // these substeps:"
|
| + // "If |input| is a Request object and |input|'s request's body is
|
| + // non-null, run these substeps:"
|
| + //
|
| // We set bodyUsed even when the body is null in spite of the
|
| // spec. See https://github.com/whatwg/fetch/issues/61 for details.
|
| if (inputRequest) {
|
| - // "1. Set |input|'s body to null."
|
| + // "Set |input|'s body to an empty byte stream."
|
| inputRequest->m_request->setBuffer(nullptr);
|
| - // "2. Set |input|'s used flag."
|
| + // "Set |input|'s disturbed flag."
|
| inputRequest->setBodyPassed();
|
| }
|
|
|
| - // "36. Return |r|."
|
| + // "Return |r|."
|
| return r;
|
| }
|
|
|
|
|