| 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/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" |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 request->setCredentials(original->credentials()); | 43 request->setCredentials(original->credentials()); |
| 44 request->setRedirect(original->redirect()); | 44 request->setRedirect(original->redirect()); |
| 45 request->setIntegrity(original->integrity()); | 45 request->setIntegrity(original->integrity()); |
| 46 // FIXME: Set cache mode. | 46 // FIXME: Set cache mode. |
| 47 // TODO(yhirano): Set redirect mode. | 47 // TODO(yhirano): Set redirect mode. |
| 48 return request; | 48 return request; |
| 49 } | 49 } |
| 50 | 50 |
| 51 Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Req
uest* inputRequest, const String& inputString, RequestInit& init, ExceptionState
& exceptionState) | 51 Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Req
uest* inputRequest, const String& inputString, RequestInit& init, ExceptionState
& exceptionState) |
| 52 { | 52 { |
| 53 // "1. Let |temporaryBody| be null." | |
| 54 BodyStreamBuffer* temporaryBody = nullptr; | 53 BodyStreamBuffer* temporaryBody = nullptr; |
| 55 | 54 |
| 56 if (inputRequest) { | 55 if (inputRequest) { |
| 57 // 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 |
| 58 // spec. See https://github.com/whatwg/fetch/issues/61 for details. | 57 // spec. See https://github.com/whatwg/fetch/issues/61 for details. |
| 59 if (inputRequest->bodyUsed()) { | 58 if (inputRequest->bodyUsed()) { |
| 60 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."); |
| 61 return nullptr; | 60 return nullptr; |
| 62 } | 61 } |
| 63 } | 62 } |
| 64 | 63 |
| 65 // "2. If |input| is a Request object and |input|'s body is non-null, run | 64 // - "If |input| is a Request object and it is disturbed, throw a |
| 66 // these substeps:" | 65 // TypeError." |
| 66 // - "Let |temporaryBody| be |input|'s request's body if |input| is a |
| 67 // Request object, and null otherwise." |
| 67 if (inputRequest && inputRequest->hasBody()) { | 68 if (inputRequest && inputRequest->hasBody()) { |
| 68 // "1. If |input|'s used flag is set, throw a TypeError." | |
| 69 // "2. Set |temporaryBody| to |input|'s body." | |
| 70 if (inputRequest->bodyUsed()) { | 69 if (inputRequest->bodyUsed()) { |
| 71 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."); |
| 72 return nullptr; | 71 return nullptr; |
| 73 } | 72 } |
| 74 temporaryBody = inputRequest->bodyBuffer(); | 73 temporaryBody = inputRequest->bodyBuffer(); |
| 75 } | 74 } |
| 76 | 75 |
| 77 // "3. Let |request| be |input|'s request, if |input| is a Request object, | 76 // "Let |request| be |input|'s request, if |input| is a Request object, |
| 78 // and a new request otherwise." | 77 // and a new request otherwise." |
| 79 // "4. Let origin be entry settings object's origin." | 78 |
| 80 RefPtr<SecurityOrigin> origin = scriptState->executionContext()->securityOri
gin(); | 79 RefPtr<SecurityOrigin> origin = scriptState->executionContext()->securityOri
gin(); |
| 81 | 80 |
| 82 // TODO(yhirano): | 81 // TODO(yhirano): Implement the following steps: |
| 83 // "5. Let window be client." | 82 // - "Let |window| be client." |
| 84 // "6. If request's window is an environment settings object and its | 83 // - "If |request|'s window is an environment settings object and its |
| 85 // origin is same origin with origin, set window to request's window." | 84 // origin is same origin with entry settings object's origin, set |
| 86 // "7. If init's window member is present and it is not null, throw a | 85 // |window| to |request|'s window." |
| 86 // - "If |init|'s window member is present and it is not null, throw a |
| 87 // TypeError." | 87 // TypeError." |
| 88 // "8. If init's window member is present, set window to no-window." | 88 // - "If |init|'s window member is present, set |window| to no-window." |
| 89 // "9. Set |request| to a new request whose url is |request|'s current url, | 89 // |
| 90 // method is |request|'s method, header list is a copy of |request|'s header | 90 // "Set |request| to a new request whose url is |request|'s current url, |
| 91 // list, unsafe-request flag is set, client is entry settings object, window | 91 // method is |request|'s method, header list is a copy of |request|'s |
| 92 // is window, origin is origin, force-Origin-header flag is set, same-origin | 92 // header list, unsafe-request flag is set, client is entry settings object, |
| 93 // data-URL flag is set, referrer is request's referrer, referrer policy is | 93 // window is |window|, origin is "client", omit-Origin-header flag is |
| 94 // |request|'s referrer policy, context is the empty string, mode is | 94 // |request|'s omit-Origin-header flag, same-origin data-URL flag is set, |
| 95 // |request|'s mode, credentials mode is |request|'s credentials mode, cache | 95 // referrer is |request|'s referrer, referrer policy is |request|'s |
| 96 // mode is |request|'s cache mode, redirect mode is |request|'s redirect | 96 // referrer policy, destination is the empty string, mode is |request|'s |
| 97 // mode, and integrity metadata is |request|'s integrity metadata." | 97 // mode, credentials mode is |request|'s credentials mode, cache mode is |
| 98 // |request|'s cache mode, redirect mode is |request|'s redirect mode, and |
| 99 // integrity metadata is |request|'s integrity metadata." |
| 98 FetchRequestData* request = createCopyOfFetchRequestDataForFetch(scriptState
, inputRequest ? inputRequest->request() : FetchRequestData::create()); | 100 FetchRequestData* request = createCopyOfFetchRequestDataForFetch(scriptState
, inputRequest ? inputRequest->request() : FetchRequestData::create()); |
| 99 | 101 |
| 100 // "10. Let |fallbackMode| be null." | |
| 101 // "11. Let |fallbackCredentials| be null." | |
| 102 // "12. Let |baseURL| be entry settings object's API base URL." | |
| 103 // We don't use fallback values. We set these flags directly in below. | 102 // We don't use fallback values. We set these flags directly in below. |
| 103 // - "Let |fallbackMode| be null." |
| 104 // - "Let |fallbackCredentials| be null." |
| 105 // - "Let |baseURL| be entry settings object's API base URL." |
| 104 | 106 |
| 105 // "13. If |input| is a string, run these substeps:" | 107 // "If |input| is a string, run these substeps:" |
| 106 if (!inputRequest) { | 108 if (!inputRequest) { |
| 107 // "1. Let |parsedURL| be the result of parsing |input| with |baseURL|." | 109 // "Let |parsedURL| be the result of parsing |input| with |baseURL|." |
| 108 KURL parsedURL = scriptState->executionContext()->completeURL(inputStrin
g); | 110 KURL parsedURL = scriptState->executionContext()->completeURL(inputStrin
g); |
| 109 // "2. If |parsedURL| is failure, throw a TypeError." | 111 // "If |parsedURL| is failure, throw a TypeError." |
| 110 if (!parsedURL.isValid()) { | 112 if (!parsedURL.isValid()) { |
| 111 exceptionState.throwTypeError("Failed to parse URL from " + inputStr
ing); | 113 exceptionState.throwTypeError("Failed to parse URL from " + inputStr
ing); |
| 112 return nullptr; | 114 return nullptr; |
| 113 } | 115 } |
| 114 // TODO(yhirano): "3. If |parsedURL| includes credentials, throw a | 116 // TODO(yhirano): Implement the following substep: |
| 115 // TypeError." | 117 // "If |parsedURL| includes credentials, throw a TypeError." |
| 116 // "4. Set |request|'s url to |parsedURL|." | 118 // |
| 119 // "Set |request|'s url to |parsedURL| and replace |request|'s url list |
| 120 // single URL with a copy of |parsedURL|." |
| 117 request->setURL(parsedURL); | 121 request->setURL(parsedURL); |
| 118 // "5. Set |fallbackMode| to CORS." | 122 |
| 119 // "6. Set |fallbackCredentials| to omit." | |
| 120 // We don't use fallback values. We set these flags directly in below. | 123 // We don't use fallback values. We set these flags directly in below. |
| 124 // - "Set |fallbackMode| to "cors"." |
| 125 // - "Set |fallbackCredentials| to "omit"." |
| 121 } | 126 } |
| 122 | 127 |
| 123 // "14. If any of |init|'s members are present, run these substeps:" | 128 // "If any of |init|'s members are present, run these substeps:" |
| 124 if (init.areAnyMembersSet) { | 129 if (init.areAnyMembersSet) { |
| 125 // "1. If |request|'s |mode| is "navigate", throw a TypeError." | 130 // "If |request|'s |mode| is "navigate", throw a TypeError." |
| 126 if (request->mode() == WebURLRequest::FetchRequestModeNavigate) { | 131 if (request->mode() == WebURLRequest::FetchRequestModeNavigate) { |
| 127 exceptionState.throwTypeError("Cannot construct a Request with a Req
uest whose mode is 'navigate' and a non-empty RequestInit."); | 132 exceptionState.throwTypeError("Cannot construct a Request with a Req
uest whose mode is 'navigate' and a non-empty RequestInit."); |
| 128 return nullptr; | 133 return nullptr; |
| 129 } | 134 } |
| 130 // "2. Unset |request|'s omit-Origin-header flag." | 135 |
| 131 // "3. Set |request|'s referrer to "client"." | 136 // TODO(yhirano): Implement the following substep: |
| 132 // "4. Set |request|'s referrer policy to the empty string." | 137 // "Unset |request|'s omit-Origin-header flag." |
| 133 // => RequestInit::RequestInit. | 138 |
| 139 // The substep "Set |request|'s referrer to "client"." is performed by |
| 140 // the code below as follows: |
| 141 // - |init.referrer.referrer| gets initialized by the RequestInit |
| 142 // constructor to "about:client" when any of |options|'s members are |
| 143 // present. |
| 144 // - The code below does the equivalent as the step specified in the |
| 145 // spec by processing the "about:client". |
| 146 |
| 147 // The substep "Set |request|'s referrer policy to the empty string." |
| 148 // is also performed by the code below similarly. |
| 134 } | 149 } |
| 135 | 150 |
| 136 // 15. If |init|'s referrer member is present, run these substeps: | 151 // The following if-clause performs the following two steps: |
| 137 // Note that JS null and undefined are encoded as an empty string and thus | 152 // - "If |init|'s referrer member is present, run these substeps:" |
| 138 // a null string means referrer member is not set. | 153 // - TODO(yhirano): Implement the following step: |
| 139 // 16. If |init|'s referrerPolicy member is present, set |request|'s | 154 // "If |init|'s referrerPolicy member is present, set |request|'s |
| 140 // referrer policy to it. | 155 // referrer policy to it." |
| 141 // areAnyMembersSet will be True, if any members in RequestInit are set and | 156 // |
| 142 // hence the referrer member | 157 // The condition "if any of |init|'s members are present" |
| 158 // (areAnyMembersSet) is used for the if-clause instead of conditions |
| 159 // indicating presence of each member as specified in the spec. This is to |
| 160 // perform the substeps in the previous step together here. |
| 143 if (init.areAnyMembersSet) { | 161 if (init.areAnyMembersSet) { |
| 144 // 1. Let |referrer| be |init|'s referrer member. | 162 // Nothing to do for the step "Let |referrer| be |init|'s referrer |
| 163 // member." |
| 164 |
| 145 if (init.referrer.referrer.isEmpty()) { | 165 if (init.referrer.referrer.isEmpty()) { |
| 146 // 2. if |referrer| is the empty string, set |request|'s referrer to | 166 // "If |referrer| is the empty string, set |request|'s referrer to |
| 147 // "no-referrer" and terminate these substeps. | 167 // "no-referrer" and terminate these substeps." |
| 148 request->setReferrerString(FetchRequestData::noReferrerString()); | 168 request->setReferrerString(FetchRequestData::noReferrerString()); |
| 149 } else { | 169 } else { |
| 150 // 3. Let |parsedReferrer| be the result of parsing |referrer| with | 170 // "Let |parsedReferrer| be the result of parsing |referrer| with |
| 151 // |baseURL|. | 171 // |baseURL|." |
| 152 KURL parsedReferrer = scriptState->executionContext()->completeURL(i
nit.referrer.referrer); | 172 KURL parsedReferrer = scriptState->executionContext()->completeURL(i
nit.referrer.referrer); |
| 153 if (!parsedReferrer.isValid()) { | 173 if (!parsedReferrer.isValid()) { |
| 154 // 4. If |parsedReferrer| is failure, throw a TypeError. | 174 // "If |parsedReferrer| is failure, throw a TypeError." |
| 155 exceptionState.throwTypeError("Referrer '" + init.referrer.refer
rer + "' is not a valid URL."); | 175 exceptionState.throwTypeError("Referrer '" + init.referrer.refer
rer + "' is not a valid URL."); |
| 156 return nullptr; | 176 return nullptr; |
| 157 } | 177 } |
| 158 if (parsedReferrer.protocolIsAbout() && parsedReferrer.host().isEmpt
y() && parsedReferrer.path() == "client") { | 178 if (parsedReferrer.protocolIsAbout() && parsedReferrer.host().isEmpt
y() && parsedReferrer.path() == "client") { |
| 159 // 5. If |parsedReferrer|'s non-relative flag is set, scheme is | 179 // "If |parsedReferrer|'s non-relative flag is set, scheme is |
| 160 // "about", and path contains a single string "client", set | 180 // "about", and path contains a single string "client", set |
| 161 // request's referrer to "client" and terminate these substeps. | 181 // request's referrer to "client" and terminate these |
| 182 // substeps." |
| 162 request->setReferrerString(FetchRequestData::clientReferrerStrin
g()); | 183 request->setReferrerString(FetchRequestData::clientReferrerStrin
g()); |
| 163 } else if (!origin->isSameSchemeHostPortAndSuborigin(SecurityOrigin:
:create(parsedReferrer).get())) { | 184 } else if (!origin->isSameSchemeHostPortAndSuborigin(SecurityOrigin:
:create(parsedReferrer).get())) { |
| 164 // 6. If |parsedReferrer|'s origin is not same origin with | 185 // "If |parsedReferrer|'s origin is not same origin with |
| 165 // |origin|, throw a TypeError. | 186 // |origin|, throw a TypeError." |
| 166 exceptionState.throwTypeError("The origin of '" + init.referrer.
referrer + "' should be same as '" + origin->toString() + "'"); | 187 exceptionState.throwTypeError("The origin of '" + init.referrer.
referrer + "' should be same as '" + origin->toString() + "'"); |
| 167 return nullptr; | 188 return nullptr; |
| 168 } else { | 189 } else { |
| 169 // 7. Set |request|'s referrer to |parsedReferrer|. | 190 // "Set |request|'s referrer to |parsedReferrer|." |
| 170 request->setReferrerString(AtomicString(parsedReferrer.string())
); | 191 request->setReferrerString(AtomicString(parsedReferrer.string())
); |
| 171 } | 192 } |
| 172 } | 193 } |
| 173 request->setReferrerPolicy(init.referrer.referrerPolicy); | 194 request->setReferrerPolicy(init.referrer.referrerPolicy); |
| 174 } | 195 } |
| 175 | 196 |
| 176 // "16. Let |mode| be |init|'s mode member if it is present, and | 197 // The following code performs the following steps: |
| 177 // |fallbackMode| otherwise." | 198 // - "Let |mode| be |init|'s mode member if it is present, and |
| 178 // "17. If |mode| is "navigate", throw a TypeError. | 199 // |fallbackMode| otherwise." |
| 179 // "18. If |mode| is non-null, set |request|'s mode to |mode|." | 200 // - "If |mode| is "navigate", throw a TypeError." |
| 201 // - "If |mode| is non-null, set |request|'s mode to |mode|." |
| 180 if (init.mode == "navigate") { | 202 if (init.mode == "navigate") { |
| 181 exceptionState.throwTypeError("Cannot construct a Request with a Request
Init whose mode member is set as 'navigate'."); | 203 exceptionState.throwTypeError("Cannot construct a Request with a Request
Init whose mode member is set as 'navigate'."); |
| 182 return nullptr; | 204 return nullptr; |
| 183 } | 205 } |
| 184 if (init.mode == "same-origin") { | 206 if (init.mode == "same-origin") { |
| 185 request->setMode(WebURLRequest::FetchRequestModeSameOrigin); | 207 request->setMode(WebURLRequest::FetchRequestModeSameOrigin); |
| 186 } else if (init.mode == "no-cors") { | 208 } else if (init.mode == "no-cors") { |
| 187 request->setMode(WebURLRequest::FetchRequestModeNoCORS); | 209 request->setMode(WebURLRequest::FetchRequestModeNoCORS); |
| 188 } else if (init.mode == "cors") { | 210 } else if (init.mode == "cors") { |
| 189 request->setMode(WebURLRequest::FetchRequestModeCORS); | 211 request->setMode(WebURLRequest::FetchRequestModeCORS); |
| 190 } else { | 212 } else { |
| 213 // |inputRequest| is directly checked here instead of setting and |
| 214 // checking |fallbackMode| as specified in the spec. |
| 191 if (!inputRequest) | 215 if (!inputRequest) |
| 192 request->setMode(WebURLRequest::FetchRequestModeCORS); | 216 request->setMode(WebURLRequest::FetchRequestModeCORS); |
| 193 } | 217 } |
| 194 | 218 |
| 195 // "19. Let |credentials| be |init|'s credentials member if it is present, | 219 // "Let |credentials| be |init|'s credentials member if it is present, and |
| 196 // and |fallbackCredentials| otherwise." | 220 // |fallbackCredentials| otherwise." |
| 197 // "20. If |credentials| is non-null, set |request|'s credentials mode to | 221 // "If |credentials| is non-null, set |request|'s credentials mode to |
| 198 // |credentials|. | 222 // |credentials|." |
| 199 if (init.credentials == "omit") { | 223 if (init.credentials == "omit") { |
| 200 request->setCredentials(WebURLRequest::FetchCredentialsModeOmit); | 224 request->setCredentials(WebURLRequest::FetchCredentialsModeOmit); |
| 201 } else if (init.credentials == "same-origin") { | 225 } else if (init.credentials == "same-origin") { |
| 202 request->setCredentials(WebURLRequest::FetchCredentialsModeSameOrigin); | 226 request->setCredentials(WebURLRequest::FetchCredentialsModeSameOrigin); |
| 203 } else if (init.credentials == "include") { | 227 } else if (init.credentials == "include") { |
| 204 request->setCredentials(WebURLRequest::FetchCredentialsModeInclude); | 228 request->setCredentials(WebURLRequest::FetchCredentialsModeInclude); |
| 205 } else { | 229 } else { |
| 206 if (!inputRequest) | 230 if (!inputRequest) |
| 207 request->setCredentials(WebURLRequest::FetchCredentialsModeOmit); | 231 request->setCredentials(WebURLRequest::FetchCredentialsModeOmit); |
| 208 } | 232 } |
| 209 | 233 |
| 210 // TODO(yhirano): "21. If |init|'s cache member is present, set |request|'s | 234 // TODO(yhirano): Implement the following step: |
| 211 // cache mode to it." | 235 // "If |init|'s cache member is present, set |request|'s cache mode to |
| 236 // it." |
| 212 | 237 |
| 213 // "22. If |init|'s redirect member is present, set |request|'s redirect | 238 // "If |init|'s redirect member is present, set |request|'s redirect mode |
| 214 // mode to it." | 239 // to it." |
| 215 if (init.redirect == "follow") { | 240 if (init.redirect == "follow") { |
| 216 request->setRedirect(WebURLRequest::FetchRedirectModeFollow); | 241 request->setRedirect(WebURLRequest::FetchRedirectModeFollow); |
| 217 } else if (init.redirect == "error") { | 242 } else if (init.redirect == "error") { |
| 218 request->setRedirect(WebURLRequest::FetchRedirectModeError); | 243 request->setRedirect(WebURLRequest::FetchRedirectModeError); |
| 219 } else if (init.redirect == "manual") { | 244 } else if (init.redirect == "manual") { |
| 220 request->setRedirect(WebURLRequest::FetchRedirectModeManual); | 245 request->setRedirect(WebURLRequest::FetchRedirectModeManual); |
| 221 } | 246 } |
| 222 | 247 |
| 223 // "If |init|'s integrity member is present, set |request|'s | 248 // "If |init|'s integrity member is present, set |request|'s |
| 224 // integrity metadata to it." | 249 // integrity metadata to it." |
| 225 if (!init.integrity.isNull()) | 250 if (!init.integrity.isNull()) |
| 226 request->setIntegrity(init.integrity); | 251 request->setIntegrity(init.integrity); |
| 227 | 252 |
| 228 // "24. If |init|'s method member is present, let |method| be it and run | 253 // "If |init|'s method member is present, let |method| be it and run these |
| 229 // these substeps:" | 254 // substeps:" |
| 230 if (!init.method.isNull()) { | 255 if (!init.method.isNull()) { |
| 231 // "1. If |method| is not a method or method is a forbidden method, | 256 // "If |method| is not a method or method is a forbidden method, throw |
| 232 // throw a TypeError." | 257 // a TypeError." |
| 233 if (!isValidHTTPToken(init.method)) { | 258 if (!isValidHTTPToken(init.method)) { |
| 234 exceptionState.throwTypeError("'" + init.method + "' is not a valid
HTTP method."); | 259 exceptionState.throwTypeError("'" + init.method + "' is not a valid
HTTP method."); |
| 235 return nullptr; | 260 return nullptr; |
| 236 } | 261 } |
| 237 if (FetchUtils::isForbiddenMethod(init.method)) { | 262 if (FetchUtils::isForbiddenMethod(init.method)) { |
| 238 exceptionState.throwTypeError("'" + init.method + "' HTTP method is
unsupported."); | 263 exceptionState.throwTypeError("'" + init.method + "' HTTP method is
unsupported."); |
| 239 return nullptr; | 264 return nullptr; |
| 240 } | 265 } |
| 241 // "2. Normalize |method|." | 266 // "Normalize |method|." |
| 242 // "3. Set |request|'s method to |method|." | 267 // "Set |request|'s method to |method|." |
| 243 request->setMethod(FetchUtils::normalizeMethod(AtomicString(init.method)
)); | 268 request->setMethod(FetchUtils::normalizeMethod(AtomicString(init.method)
)); |
| 244 } | 269 } |
| 245 // "25. Let |r| be a new Request object associated with |request| and a new | 270 // "Let |r| be a new Request object associated with |request| and a new |
| 246 // Headers object whose guard is request." | 271 // Headers object whose guard is "request"." |
| 247 Request* r = Request::create(scriptState->executionContext(), request); | 272 Request* r = Request::create(scriptState->executionContext(), request); |
| 248 // "26. Let |headers| be a copy of |r|'s Headers object." | 273 // Perform the following steps: |
| 249 // "27. If |init|'s headers member is present, set |headers| to |init|'s | 274 // - "Let |headers| be a copy of |r|'s Headers object." |
| 250 // headers member." | 275 // - "If |init|'s headers member is present, set |headers| to |init|'s |
| 276 // headers member." |
| 277 // |
| 251 // We don't create a copy of r's Headers object when init's headers member | 278 // We don't create a copy of r's Headers object when init's headers member |
| 252 // is present. | 279 // is present. |
| 253 Headers* headers = nullptr; | 280 Headers* headers = nullptr; |
| 254 if (!init.headers && init.headersDictionary.isUndefinedOrNull()) { | 281 if (!init.headers && init.headersDictionary.isUndefinedOrNull()) { |
| 255 headers = r->headers()->clone(); | 282 headers = r->headers()->clone(); |
| 256 } | 283 } |
| 257 // "28. Empty |r|'s request's header list." | 284 // "Empty |r|'s request's header list." |
| 258 r->m_request->headerList()->clearList(); | 285 r->m_request->headerList()->clearList(); |
| 259 // "29. If |r|'s request's mode is no CORS, run these substeps: | 286 // "If |r|'s request's mode is "no-cors", run these substeps: |
| 260 if (r->request()->mode() == WebURLRequest::FetchRequestModeNoCORS) { | 287 if (r->request()->mode() == WebURLRequest::FetchRequestModeNoCORS) { |
| 261 // "1. If |r|'s request's method is not a simple method, throw a | 288 // "If |r|'s request's method is not a simple method, throw a |
| 262 // TypeError." | 289 // TypeError." |
| 263 if (!FetchUtils::isSimpleMethod(r->request()->method())) { | 290 if (!FetchUtils::isSimpleMethod(r->request()->method())) { |
| 264 exceptionState.throwTypeError("'" + r->request()->method() + "' is u
nsupported in no-cors mode."); | 291 exceptionState.throwTypeError("'" + r->request()->method() + "' is u
nsupported in no-cors mode."); |
| 265 return nullptr; | 292 return nullptr; |
| 266 } | 293 } |
| 267 // "2. If |request|'s integrity metadata is not the empty string, throw | 294 // "If |request|'s integrity metadata is not the empty string, throw a |
| 268 // a TypeError." | 295 // TypeError." |
| 269 if (!request->integrity().isEmpty()) { | 296 if (!request->integrity().isEmpty()) { |
| 270 exceptionState.throwTypeError("The integrity attribute is unsupporte
d in no-cors mode."); | 297 exceptionState.throwTypeError("The integrity attribute is unsupporte
d in no-cors mode."); |
| 271 return nullptr; | 298 return nullptr; |
| 272 } | 299 } |
| 273 // "3. Set |r|'s Headers object's guard to |request-no-CORS|. | 300 // "Set |r|'s Headers object's guard to "request-no-cors"." |
| 274 r->headers()->setGuard(Headers::RequestNoCORSGuard); | 301 r->headers()->setGuard(Headers::RequestNoCORSGuard); |
| 275 } | 302 } |
| 276 // "30. Fill |r|'s Headers object with |headers|. Rethrow any exceptions." | 303 // "Fill |r|'s Headers object with |headers|. Rethrow any exceptions." |
| 277 if (init.headers) { | 304 if (init.headers) { |
| 278 ASSERT(init.headersDictionary.isUndefinedOrNull()); | 305 ASSERT(init.headersDictionary.isUndefinedOrNull()); |
| 279 r->headers()->fillWith(init.headers.get(), exceptionState); | 306 r->headers()->fillWith(init.headers.get(), exceptionState); |
| 280 } else if (!init.headersDictionary.isUndefinedOrNull()) { | 307 } else if (!init.headersDictionary.isUndefinedOrNull()) { |
| 281 r->headers()->fillWith(init.headersDictionary, exceptionState); | 308 r->headers()->fillWith(init.headersDictionary, exceptionState); |
| 282 } else { | 309 } else { |
| 283 ASSERT(headers); | 310 ASSERT(headers); |
| 284 r->headers()->fillWith(headers, exceptionState); | 311 r->headers()->fillWith(headers, exceptionState); |
| 285 } | 312 } |
| 286 if (exceptionState.hadException()) | 313 if (exceptionState.hadException()) |
| 287 return nullptr; | 314 return nullptr; |
| 288 | 315 |
| 289 // "31. If either |init|'s body member is present or |temporaryBody| is | 316 // "If either |init|'s body member is present or |temporaryBody| is |
| 290 // non-null, and |request|'s method is `GET` or `HEAD`, throw a TypeError. | 317 // non-null, and |request|'s method is `GET` or `HEAD`, throw a TypeError. |
| 291 if (init.body || temporaryBody) { | 318 if (init.body || temporaryBody) { |
| 292 if (request->method() == "GET" || request->method() == "HEAD") { | 319 if (request->method() == "GET" || request->method() == "HEAD") { |
| 293 exceptionState.throwTypeError("Request with GET/HEAD method cannot h
ave body."); | 320 exceptionState.throwTypeError("Request with GET/HEAD method cannot h
ave body."); |
| 294 return nullptr; | 321 return nullptr; |
| 295 } | 322 } |
| 296 } | 323 } |
| 297 | 324 |
| 298 // "32. If |init|'s body member is present, run these substeps:" | 325 // "If |init|'s body member is present, run these substeps:" |
| 299 if (init.body) { | 326 if (init.body) { |
| 300 // "1. Let |stream| and |Content-Type| be the result of extracting | 327 // Perform the following steps: |
| 301 // |init|'s body member." | 328 // - "Let |stream| and |Content-Type| be the result of extracting |
| 302 // "2. Set |temporaryBody| to |stream|. | 329 // |init|'s body member." |
| 303 // "3. If |Content-Type| is non-null and |r|'s request's header list | 330 // - "Set |temporaryBody| to |stream|. |
| 304 // contains no header named `Content-Type`, append | 331 // - "If |Content-Type| is non-null and |r|'s request's header list |
| 305 // `Content-Type`/|Content-Type| to |r|'s Headers object. Rethrow any | 332 // contains no header named `Content-Type`, append |
| 306 // exception." | 333 // `Content-Type`/|Content-Type| to |r|'s Headers object. Rethrow any |
| 334 // exception." |
| 307 temporaryBody = new BodyStreamBuffer(init.body.release()); | 335 temporaryBody = new BodyStreamBuffer(init.body.release()); |
| 308 if (!init.contentType.isEmpty() && !r->headers()->has("Content-Type", ex
ceptionState)) { | 336 if (!init.contentType.isEmpty() && !r->headers()->has("Content-Type", ex
ceptionState)) { |
| 309 r->headers()->append("Content-Type", init.contentType, exceptionStat
e); | 337 r->headers()->append("Content-Type", init.contentType, exceptionStat
e); |
| 310 } | 338 } |
| 311 if (exceptionState.hadException()) | 339 if (exceptionState.hadException()) |
| 312 return nullptr; | 340 return nullptr; |
| 313 } | 341 } |
| 314 | 342 |
| 315 // "33. Set |r|'s body to |temporaryBody|. | 343 // "Set |r|'s request's body to |temporaryBody|. |
| 316 if (temporaryBody) | 344 if (temporaryBody) |
| 317 r->m_request->setBuffer(temporaryBody); | 345 r->m_request->setBuffer(temporaryBody); |
| 318 | 346 |
| 319 // https://w3c.github.io/webappsec-credential-management/#monkey-patching-fe
tch-3 | 347 // https://w3c.github.io/webappsec-credential-management/#monkey-patching-fe
tch-3 |
| 320 // "If |init|'s body member is a 'Credential' object:" | 348 // "If |init|'s body member is a 'Credential' object:" |
| 321 if (init.isCredentialRequest) { | 349 if (init.isCredentialRequest) { |
| 322 // "1. If |r|'s url is not the same as |r|'s client’s origin, throw a Ty
peError." | 350 // "1. If |r|'s url is not the same as |r|'s client’s origin, throw a Ty
peError." |
| 323 if (!origin->canRequest(r->url())) { | 351 if (!origin->canRequest(r->url())) { |
| 324 exceptionState.throwTypeError("Credentials may only be submitted to
same-origin endpoints."); | 352 exceptionState.throwTypeError("Credentials may only be submitted to
same-origin endpoints."); |
| 325 return nullptr; | 353 return nullptr; |
| 326 } | 354 } |
| 327 // "2. Set |r|'s redirect mode to "error"." | 355 // "2. Set |r|'s redirect mode to "error"." |
| 328 r->m_request->setRedirect(WebURLRequest::FetchRedirectModeError); | 356 r->m_request->setRedirect(WebURLRequest::FetchRedirectModeError); |
| 329 // "3. Set |r|'s skip-service-worker flag." | 357 // "3. Set |r|'s skip-service-worker flag." |
| 330 // TODO(mkwst): Set this flag. | 358 // TODO(mkwst): Set this flag. |
| 331 // "4. Set |r|'s opaque flag." | 359 // "4. Set |r|'s opaque flag." |
| 332 r->setOpaque(); | 360 r->setOpaque(); |
| 333 } | 361 } |
| 334 | 362 |
| 335 // "34. Set |r|'s MIME type to the result of extracting a MIME type from | 363 // "Set |r|'s MIME type to the result of extracting a MIME type from |r|'s |
| 336 // |r|'s request's header list." | 364 // request's header list." |
| 337 r->m_request->setMIMEType(r->m_request->headerList()->extractMIMEType()); | 365 r->m_request->setMIMEType(r->m_request->headerList()->extractMIMEType()); |
| 338 | 366 |
| 339 // "35. If |input| is a Request object and |input|'s body is non-null, run | 367 // "If |input| is a Request object and |input|'s request's body is |
| 340 // these substeps:" | 368 // non-null, run these substeps:" |
| 369 // |
| 341 // We set bodyUsed even when the body is null in spite of the | 370 // We set bodyUsed even when the body is null in spite of the |
| 342 // spec. See https://github.com/whatwg/fetch/issues/61 for details. | 371 // spec. See https://github.com/whatwg/fetch/issues/61 for details. |
| 343 if (inputRequest) { | 372 if (inputRequest) { |
| 344 // "1. Set |input|'s body to null." | 373 // "Set |input|'s body to an empty byte stream." |
| 345 inputRequest->m_request->setBuffer(nullptr); | 374 inputRequest->m_request->setBuffer(nullptr); |
| 346 // "2. Set |input|'s used flag." | 375 // "Set |input|'s disturbed flag." |
| 347 inputRequest->setBodyPassed(); | 376 inputRequest->setBodyPassed(); |
| 348 } | 377 } |
| 349 | 378 |
| 350 // "36. Return |r|." | 379 // "Return |r|." |
| 351 return r; | 380 return r; |
| 352 } | 381 } |
| 353 | 382 |
| 354 Request* Request::create(ScriptState* scriptState, const RequestInfo& input, con
st Dictionary& init, ExceptionState& exceptionState) | 383 Request* Request::create(ScriptState* scriptState, const RequestInfo& input, con
st Dictionary& init, ExceptionState& exceptionState) |
| 355 { | 384 { |
| 356 ASSERT(!input.isNull()); | 385 ASSERT(!input.isNull()); |
| 357 if (input.isUSVString()) | 386 if (input.isUSVString()) |
| 358 return create(scriptState, input.getAsUSVString(), init, exceptionState)
; | 387 return create(scriptState, input.getAsUSVString(), init, exceptionState)
; |
| 359 return create(scriptState, input.getAsRequest(), init, exceptionState); | 388 return create(scriptState, input.getAsRequest(), init, exceptionState); |
| 360 } | 389 } |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 619 } | 648 } |
| 620 | 649 |
| 621 DEFINE_TRACE(Request) | 650 DEFINE_TRACE(Request) |
| 622 { | 651 { |
| 623 Body::trace(visitor); | 652 Body::trace(visitor); |
| 624 visitor->trace(m_request); | 653 visitor->trace(m_request); |
| 625 visitor->trace(m_headers); | 654 visitor->trace(m_headers); |
| 626 } | 655 } |
| 627 | 656 |
| 628 } // namespace blink | 657 } // namespace blink |
| OLD | NEW |